[ignition-math4] 01/04: Imported Upstream version 4.0.0~pre2

Jose Luis Rivero jrivero-guest at moszumanska.debian.org
Mon Nov 20 19:51:21 UTC 2017


This is an automated email from the git hooks/post-receive script.

jrivero-guest pushed a commit to branch master
in repository ignition-math4.

commit 5b753089b763f77f3ea440b2e5de13df6a387d49
Author: Jose Luis Rivero <jrivero at osrfoundation.org>
Date:   Mon Nov 20 15:55:53 2017 +0000

    Imported Upstream version 4.0.0~pre2
---
 .hg_archival.txt                                   |    6 +
 AUTHORS                                            |    1 +
 CMakeLists.txt                                     |   37 +
 COPYING                                            |  178 +
 Changelog.md                                       |  185 +
 LICENSE                                            |   15 +
 Migration.md                                       |  139 +
 NEWS                                               |    1 +
 README.md                                          |   50 +
 bitbucket-pipelines.yml                            |   24 +
 configure.bat                                      |   23 +
 doc/CMakeLists.txt                                 |   14 +
 doc/footer.html                                    |    1 +
 doc/header.html                                    |   67 +
 doc/ignition.in                                    | 2306 ++++++++
 doc/ignition_logo.svg                              |  249 +
 doc/mainpage.html                                  |   17 +
 doc/style.css                                      |  107 +
 examples/CMakeLists.txt                            |   13 +
 examples/graph_example.cc                          |   90 +
 examples/triangle_example.cc                       |   80 +
 examples/vector2_example.cc                        |   66 +
 include/CMakeLists.txt                             |    1 +
 include/ignition/CMakeLists.txt                    |    1 +
 include/ignition/math/Angle.hh                     |  203 +
 include/ignition/math/Box.hh                       |  236 +
 include/ignition/math/CMakeLists.txt               |    2 +
 include/ignition/math/Color.hh                     |  318 ++
 include/ignition/math/Filter.hh                    |  247 +
 include/ignition/math/Frustum.hh                   |  181 +
 include/ignition/math/Helpers.hh                   |  770 +++
 include/ignition/math/Inertial.hh                  |  244 +
 include/ignition/math/Kmeans.hh                    |   85 +
 include/ignition/math/Line2.hh                     |  315 ++
 include/ignition/math/Line3.hh                     |  388 ++
 include/ignition/math/MassMatrix3.hh               |  906 ++++
 include/ignition/math/MassMatrix3.ipynb            |  134 +
 include/ignition/math/Matrix3.hh                   |  544 ++
 include/ignition/math/Matrix4.hh                   |  890 ++++
 include/ignition/math/OrientedBox.hh               |  187 +
 include/ignition/math/PID.hh                       |  228 +
 include/ignition/math/Plane.hh                     |  231 +
 include/ignition/math/Pose3.hh                     |  411 ++
 include/ignition/math/Quaternion.hh                | 1083 ++++
 include/ignition/math/Rand.hh                      |   86 +
 include/ignition/math/RotationSpline.hh            |  121 +
 include/ignition/math/SemanticVersion.hh           |  159 +
 include/ignition/math/SignalStats.hh               |  258 +
 include/ignition/math/SphericalCoordinates.hh      |  232 +
 include/ignition/math/Spline.hh                    |  261 +
 include/ignition/math/Temperature.hh               |  375 ++
 include/ignition/math/Triangle.hh                  |  242 +
 include/ignition/math/Triangle3.hh                 |  278 +
 include/ignition/math/Vector2.hh                   |  478 ++
 include/ignition/math/Vector3.hh                   |  757 +++
 include/ignition/math/Vector3Stats.hh              |  107 +
 include/ignition/math/Vector4.hh                   |  589 ++
 include/ignition/math/config.hh.in                 |   15 +
 include/ignition/math/graph/Edge.hh                |  337 ++
 include/ignition/math/graph/Graph.hh               |  763 +++
 include/ignition/math/graph/GraphAlgorithms.hh     |  323 ++
 include/ignition/math/graph/Vertex.hh              |  140 +
 include/ignition/math/math.hh.in                   |    3 +
 src/Angle.cc                                       |  173 +
 src/Angle_TEST.cc                                  |  119 +
 src/Box.cc                                         |  296 ++
 src/BoxPrivate.hh                                  |   38 +
 src/Box_TEST.cc                                    |  567 ++
 src/CMakeLists.txt                                 |   20 +
 src/Color.cc                                       |  583 ++
 src/Color_TEST.cc                                  |  379 ++
 src/Filter_TEST.cc                                 |  105 +
 src/Frustum.cc                                     |  254 +
 src/FrustumPrivate.hh                              |   78 +
 src/Frustum_TEST.cc                                |  472 ++
 src/Helpers.cc                                     |   47 +
 src/Helpers_TEST.cc                                |  517 ++
 src/Inertial_TEST.cc                               |  527 ++
 src/Kmeans.cc                                      |  172 +
 src/KmeansPrivate.hh                               |   51 +
 src/Kmeans_TEST.cc                                 |  142 +
 src/Line2_TEST.cc                                  |  268 +
 src/Line3_TEST.cc                                  |  293 +
 src/MassMatrix3_TEST.cc                            |  858 +++
 src/Matrix3_TEST.cc                                |  400 ++
 src/Matrix4_TEST.cc                                |  656 +++
 src/OrientedBox_TEST.cc                            |  335 ++
 src/PID.cc                                         |  243 +
 src/PID_TEST.cc                                    |  402 ++
 src/Plane_TEST.cc                                  |  147 +
 src/Pose_TEST.cc                                   |  157 +
 src/Quaternion_TEST.cc                             |  568 ++
 src/Rand.cc                                        |   92 +
 src/Rand_TEST.cc                                   |   79 +
 src/RotationSpline.cc                              |  211 +
 src/RotationSplinePrivate.cc                       |   26 +
 src/RotationSplinePrivate.hh                       |   46 +
 src/RotationSpline_TEST.cc                         |  100 +
 src/SemanticVersion.cc                             |  294 +
 src/SemanticVersion_TEST.cc                        |  217 +
 src/SignalStats.cc                                 |  359 ++
 src/SignalStatsPrivate.hh                          |   77 +
 src/SignalStats_TEST.cc                            |  641 +++
 src/SphericalCoordinates.cc                        |  557 ++
 src/SphericalCoordinates_TEST.cc                   |  385 ++
 src/Spline.cc                                      |  385 ++
 src/SplinePrivate.cc                               |  156 +
 src/SplinePrivate.hh                               |  207 +
 src/Spline_TEST.cc                                 |  179 +
 src/Temperature.cc                                 |  325 ++
 src/Temperature_TEST.cc                            |  178 +
 src/Triangle3_TEST.cc                              |  261 +
 src/Triangle_TEST.cc                               |  194 +
 src/Vector2_TEST.cc                                |  304 ++
 src/Vector3Stats.cc                                |  121 +
 src/Vector3StatsPrivate.hh                         |   44 +
 src/Vector3Stats_TEST.cc                           |  189 +
 src/Vector3_TEST.cc                                |  418 ++
 src/Vector4_TEST.cc                                |  314 ++
 src/graph/CMakeLists.txt                           |    7 +
 src/graph/Edge_TEST.cc                             |  225 +
 src/graph/GraphAlgorithms_TEST.cc                  |  312 ++
 src/graph/GraphDirected_TEST.cc                    |  500 ++
 src/graph/GraphUndirected_TEST.cc                  |  534 ++
 src/graph/Graph_TEST.cc                            |  435 ++
 src/graph/Vertex_TEST.cc                           |   69 +
 test/CMakeLists.txt                                |   22 +
 test/gtest/cmake/internal_utils.cmake              |  227 +
 test/gtest/gtest-1.7.0.diff                        |   44 +
 test/gtest/include/gtest/gtest-death-test.h        |  294 +
 test/gtest/include/gtest/gtest-message.h           |  250 +
 test/gtest/include/gtest/gtest-param-test.h        | 1421 +++++
 test/gtest/include/gtest/gtest-param-test.h.pump   |  487 ++
 test/gtest/include/gtest/gtest-printers.h          |  858 +++
 test/gtest/include/gtest/gtest-spi.h               |  232 +
 test/gtest/include/gtest/gtest-test-part.h         |  179 +
 test/gtest/include/gtest/gtest-typed-test.h        |  263 +
 test/gtest/include/gtest/gtest.h                   | 2291 ++++++++
 test/gtest/include/gtest/gtest_pred_impl.h         |  358 ++
 test/gtest/include/gtest/gtest_prod.h              |   58 +
 .../gtest/internal/gtest-death-test-internal.h     |  319 ++
 test/gtest/include/gtest/internal/gtest-filepath.h |  206 +
 test/gtest/include/gtest/internal/gtest-internal.h | 1158 ++++
 .../include/gtest/internal/gtest-linked_ptr.h      |  233 +
 .../gtest/internal/gtest-param-util-generated.h    | 5143 ++++++++++++++++++
 .../internal/gtest-param-util-generated.h.pump     |  301 ++
 .../include/gtest/internal/gtest-param-util.h      |  619 +++
 test/gtest/include/gtest/internal/gtest-port.h     | 1950 +++++++
 test/gtest/include/gtest/internal/gtest-string.h   |  167 +
 test/gtest/include/gtest/internal/gtest-tuple.h    | 1012 ++++
 .../include/gtest/internal/gtest-tuple.h.pump      |  339 ++
 .../gtest/include/gtest/internal/gtest-type-util.h | 3331 ++++++++++++
 .../include/gtest/internal/gtest-type-util.h.pump  |  297 ++
 test/gtest/src/gtest-all.cc                        |   48 +
 test/gtest/src/gtest-death-test.cc                 | 1344 +++++
 test/gtest/src/gtest-filepath.cc                   |  382 ++
 test/gtest/src/gtest-internal-inl.h                | 1218 +++++
 test/gtest/src/gtest-port.cc                       |  805 +++
 test/gtest/src/gtest-printers.cc                   |  363 ++
 test/gtest/src/gtest-test-part.cc                  |  110 +
 test/gtest/src/gtest-typed-test.cc                 |  110 +
 test/gtest/src/gtest.cc                            | 5019 +++++++++++++++++
 test/gtest/src/gtest_main.cc                       |   38 +
 test/integration/CMakeLists.txt                    |    8 +
 test/performance/CMakeLists.txt                    |    8 +
 test/regression/CMakeLists.txt                     |    8 +
 test/test_config.h.in                              |    1 +
 tools/check_test_ran.py                            |   79 +
 tools/code_check.sh                                |  150 +
 tools/cppcheck_rules/header_guard.rule             |   10 +
 tools/cppcheck_rules/namespace_AZ.rule             |    9 +
 tools/cpplint.py                                   | 5622 ++++++++++++++++++++
 172 files changed, 71497 insertions(+)

diff --git a/.hg_archival.txt b/.hg_archival.txt
new file mode 100644
index 0000000..77fd3c2
--- /dev/null
+++ b/.hg_archival.txt
@@ -0,0 +1,6 @@
+repo: e97318167882c5edd21067dd86576efadebd68ed
+node: 3e9ea893e1e4b477e8eb77e40d7a020f3f1b5527
+branch: ign-math4
+latesttag: ignition-math4_4.0.0~pre1
+latesttagdistance: 3
+changessincelatesttag: 59
diff --git a/AUTHORS b/AUTHORS
new file mode 100644
index 0000000..65032b7
--- /dev/null
+++ b/AUTHORS
@@ -0,0 +1 @@
+OSRFoundation
diff --git a/CMakeLists.txt b/CMakeLists.txt
new file mode 100644
index 0000000..bb99ea8
--- /dev/null
+++ b/CMakeLists.txt
@@ -0,0 +1,37 @@
+cmake_minimum_required(VERSION 3.5.1 FATAL_ERROR)
+
+#============================================================================
+# Find ignition-cmake
+#============================================================================
+# If you get an error at this line, you need to install ignition-cmake
+find_package(ignition-cmake0 REQUIRED)
+
+#============================================================================
+# Set up the project
+#============================================================================
+ign_configure_project(math 4.0.0 VERSION_SUFFIX pre2)
+
+
+#============================================================================
+# Set project-specific options
+#============================================================================
+
+# ignition-math currently has no options that are unique to it
+
+
+#============================================================================
+# Search for project-specific dependencies
+#============================================================================
+
+# ignition-math currently has no dependencies that are unique to it
+
+#============================================================================
+# Configure the build
+#============================================================================
+ign_configure_build(QUIT_IF_BUILD_ERRORS)
+
+
+#============================================================================
+# Create package information
+#============================================================================
+ign_create_packages()
diff --git a/COPYING b/COPYING
new file mode 100644
index 0000000..4909afd
--- /dev/null
+++ b/COPYING
@@ -0,0 +1,178 @@
+                                 Apache License
+                           Version 2.0, January 2004
+                        http://www.apache.org/licenses/
+
+   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+   1. Definitions.
+
+      "License" shall mean the terms and conditions for use, reproduction,
+      and distribution as defined by Sections 1 through 9 of this document.
+
+      "Licensor" shall mean the copyright owner or entity authorized by
+      the copyright owner that is granting the License.
+
+      "Legal Entity" shall mean the union of the acting entity and all
+      other entities that control, are controlled by, or are under common
+      control with that entity. For the purposes of this definition,
+      "control" means (i) the power, direct or indirect, to cause the
+      direction or management of such entity, whether by contract or
+      otherwise, or (ii) ownership of fifty percent (50%) or more of the
+      outstanding shares, or (iii) beneficial ownership of such entity.
+
+      "You" (or "Your") shall mean an individual or Legal Entity
+      exercising permissions granted by this License.
+
+      "Source" form shall mean the preferred form for making modifications,
+      including but not limited to software source code, documentation
+      source, and configuration files.
+
+      "Object" form shall mean any form resulting from mechanical
+      transformation or translation of a Source form, including but
+      not limited to compiled object code, generated documentation,
+      and conversions to other media types.
+
+      "Work" shall mean the work of authorship, whether in Source or
+      Object form, made available under the License, as indicated by a
+      copyright notice that is included in or attached to the work
+      (an example is provided in the Appendix below).
+
+      "Derivative Works" shall mean any work, whether in Source or Object
+      form, that is based on (or derived from) the Work and for which the
+      editorial revisions, annotations, elaborations, or other modifications
+      represent, as a whole, an original work of authorship. For the purposes
+      of this License, Derivative Works shall not include works that remain
+      separable from, or merely link (or bind by name) to the interfaces of,
+      the Work and Derivative Works thereof.
+
+      "Contribution" shall mean any work of authorship, including
+      the original version of the Work and any modifications or additions
+      to that Work or Derivative Works thereof, that is intentionally
+      submitted to Licensor for inclusion in the Work by the copyright owner
+      or by an individual or Legal Entity authorized to submit on behalf of
+      the copyright owner. For the purposes of this definition, "submitted"
+      means any form of electronic, verbal, or written communication sent
+      to the Licensor or its representatives, including but not limited to
+      communication on electronic mailing lists, source code control systems,
+      and issue tracking systems that are managed by, or on behalf of, the
+      Licensor for the purpose of discussing and improving the Work, but
+      excluding communication that is conspicuously marked or otherwise
+      designated in writing by the copyright owner as "Not a Contribution."
+
+      "Contributor" shall mean Licensor and any individual or Legal Entity
+      on behalf of whom a Contribution has been received by Licensor and
+      subsequently incorporated within the Work.
+
+   2. Grant of Copyright License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      copyright license to reproduce, prepare Derivative Works of,
+      publicly display, publicly perform, sublicense, and distribute the
+      Work and such Derivative Works in Source or Object form.
+
+   3. Grant of Patent License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      (except as stated in this section) patent license to make, have made,
+      use, offer to sell, sell, import, and otherwise transfer the Work,
+      where such license applies only to those patent claims licensable
+      by such Contributor that are necessarily infringed by their
+      Contribution(s) alone or by combination of their Contribution(s)
+      with the Work to which such Contribution(s) was submitted. If You
+      institute patent litigation against any entity (including a
+      cross-claim or counterclaim in a lawsuit) alleging that the Work
+      or a Contribution incorporated within the Work constitutes direct
+      or contributory patent infringement, then any patent licenses
+      granted to You under this License for that Work shall terminate
+      as of the date such litigation is filed.
+
+   4. Redistribution. You may reproduce and distribute copies of the
+      Work or Derivative Works thereof in any medium, with or without
+      modifications, and in Source or Object form, provided that You
+      meet the following conditions:
+
+      (a) You must give any other recipients of the Work or
+          Derivative Works a copy of this License; and
+
+      (b) You must cause any modified files to carry prominent notices
+          stating that You changed the files; and
+
+      (c) You must retain, in the Source form of any Derivative Works
+          that You distribute, all copyright, patent, trademark, and
+          attribution notices from the Source form of the Work,
+          excluding those notices that do not pertain to any part of
+          the Derivative Works; and
+
+      (d) If the Work includes a "NOTICE" text file as part of its
+          distribution, then any Derivative Works that You distribute must
+          include a readable copy of the attribution notices contained
+          within such NOTICE file, excluding those notices that do not
+          pertain to any part of the Derivative Works, in at least one
+          of the following places: within a NOTICE text file distributed
+          as part of the Derivative Works; within the Source form or
+          documentation, if provided along with the Derivative Works; or,
+          within a display generated by the Derivative Works, if and
+          wherever such third-party notices normally appear. The contents
+          of the NOTICE file are for informational purposes only and
+          do not modify the License. You may add Your own attribution
+          notices within Derivative Works that You distribute, alongside
+          or as an addendum to the NOTICE text from the Work, provided
+          that such additional attribution notices cannot be construed
+          as modifying the License.
+
+      You may add Your own copyright statement to Your modifications and
+      may provide additional or different license terms and conditions
+      for use, reproduction, or distribution of Your modifications, or
+      for any such Derivative Works as a whole, provided Your use,
+      reproduction, and distribution of the Work otherwise complies with
+      the conditions stated in this License.
+
+   5. Submission of Contributions. Unless You explicitly state otherwise,
+      any Contribution intentionally submitted for inclusion in the Work
+      by You to the Licensor shall be under the terms and conditions of
+      this License, without any additional terms or conditions.
+      Notwithstanding the above, nothing herein shall supersede or modify
+      the terms of any separate license agreement you may have executed
+      with Licensor regarding such Contributions.
+
+   6. Trademarks. This License does not grant permission to use the trade
+      names, trademarks, service marks, or product names of the Licensor,
+      except as required for reasonable and customary use in describing the
+      origin of the Work and reproducing the content of the NOTICE file.
+
+   7. Disclaimer of Warranty. Unless required by applicable law or
+      agreed to in writing, Licensor provides the Work (and each
+      Contributor provides its Contributions) on an "AS IS" BASIS,
+      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+      implied, including, without limitation, any warranties or conditions
+      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+      PARTICULAR PURPOSE. You are solely responsible for determining the
+      appropriateness of using or redistributing the Work and assume any
+      risks associated with Your exercise of permissions under this License.
+
+   8. Limitation of Liability. In no event and under no legal theory,
+      whether in tort (including negligence), contract, or otherwise,
+      unless required by applicable law (such as deliberate and grossly
+      negligent acts) or agreed to in writing, shall any Contributor be
+      liable to You for damages, including any direct, indirect, special,
+      incidental, or consequential damages of any character arising as a
+      result of this License or out of the use or inability to use the
+      Work (including but not limited to damages for loss of goodwill,
+      work stoppage, computer failure or malfunction, or any and all
+      other commercial damages or losses), even if such Contributor
+      has been advised of the possibility of such damages.
+
+   9. Accepting Warranty or Additional Liability. While redistributing
+      the Work or Derivative Works thereof, You may choose to offer,
+      and charge a fee for, acceptance of support, warranty, indemnity,
+      or other liability obligations and/or rights consistent with this
+      License. However, in accepting such obligations, You may act only
+      on Your own behalf and on Your sole responsibility, not on behalf
+      of any other Contributor, and only if You agree to indemnify,
+      defend, and hold each Contributor harmless for any liability
+      incurred by, or claims asserted against, such Contributor by reason
+      of your accepting any such warranty or additional liability.
+
+   END OF TERMS AND CONDITIONS
+
+
diff --git a/Changelog.md b/Changelog.md
new file mode 100644
index 0000000..f75a6b3
--- /dev/null
+++ b/Changelog.md
@@ -0,0 +1,185 @@
+## Ignition Math 4.x
+
+### Ignition Math 4.x.x
+
+1. Use ignition-cmake to simplify build scripts
+    * [Pull request 200](https://bitbucket.org/ignitionrobotics/ign-math/pull-requests/200)
+
+1. Make constructor SemanticVersion(string) explicit
+    * [Pull request 203](https://bitbucket.org/ignitionrobotics/ign-math/pull-requests/203)
+
+1. Switch to C++14
+    * [Pull request 180](https://bitbucket.org/ignitionrobotics/ign-math/pull-requests/180)
+
+1. Improved the performance of `graph::InDegree()` and `graph::IncidentsTo()`.
+    * [Pull request 188](https://bitbucket.org/ignitionrobotics/ign-math/pull-requests/188)
+    * [Issue 79](https://bitbucket.org/ignitionrobotics/ign-math/issues/79)
+
+1. Removed the box 'extent' field. The default constructor now sets a box's
+   corners to extrema in order to indicate an uninitialized box.
+    * [Pull request 172](https://bitbucket.org/ignitionrobotics/ign-math/pull-requests/172)
+    * [Issue 72](https://bitbucket.org/ignitionrobotics/ign-math/issues/72)
+    * [Issue 53](https://bitbucket.org/ignitionrobotics/ign-math/issues/53)
+
+1. Added graph utilites:
+    1. Added a Vertex class:
+        * [Pull request 170](https://bitbucket.org/ignitionrobotics/ign-math/pull-request/170)
+    1. Added an Edge class:
+        * [Pull request 174](https://bitbucket.org/ignitionrobotics/ign-math/pull-request/174)
+    1. Added a Graph class:
+        * [Pull request 175](https://bitbucket.org/ignitionrobotics/ign-math/pull-request/175)
+    1. Added a GraphAlgorithms class:
+        * [Pull request 177](https://bitbucket.org/ignitionrobotics/ign-math/pull-request/177)
+    1. Added a function to calculate connected components in undirected
+       graphs:
+         * [Pull request 190](https://bitbucket.org/ignitionrobotics/ign-math/pull-request/190)
+
+## Ignition Math 3.x
+
+### Ignition Math 3.x.x
+
+1. Create consistent bracket operators across all Vector# types
+    * [Pull request 181](https://bitbucket.org/ignitionrobotics/ign-math/pull-requests/181)
+
+### Ignition Math 3.2.0 (2017-05-15)
+
+1. Construct on first use in Rand class
+    * [Pull request 165](https://bitbucket.org/ignitionrobotics/ign-math/pull-request/165)
+
+1. Extended Spline API: derivative interpolation, arc length calculation
+   and tangent forcing.
+    * [Pull request 162](https://bitbucket.org/ignitionrobotics/ign-math/pull-requests/162)
+
+### Ignition Math 3.1.0 (2017-04-11)
+
+1. Added signum functions to Helpers.hh.
+    * Contribution from Martin Pecka
+    * [Pull request 153](https://bitbucket.org/ignitionrobotics/ign-math/pull-request/153)
+
+### Ignition Math 3.0.0 (2017-01-05)
+
+1. Deprecate many IGN_* macros in favor of static const variables in Helpers.hh
+    * [Pull request 138](https://bitbucket.org/ignitionrobotics/ign-math/pull-request/138)
+    * [Pull request 137](https://bitbucket.org/ignitionrobotics/ign-math/pull-request/137)
+
+1. Removed exceptions. Return values should be evaluated to determine if
+   errors have occured.
+    * [Pull request 132](https://bitbucket.org/ignitionrobotics/ign-math/pull-request/132)
+
+1. Added `operator=(const Quaternion<T> &_q)` to `Matrix3`.
+    * [Pull request 111](https://bitbucket.org/ignitionrobotics/ign-math/pull-request/111)
+
+1. Fix xenial cppcheck
+    * [Pull request xxx](https://bitbucket.org/ignitionrobotics/ign-math/pull-request/xxx)
+
+1. Require cmake 2.8.12
+    * [Pull request 76](https://bitbucket.org/ignitionrobotics/ign-math/pull-request/76)
+
+1. Migrate to relocatable CMake package.
+   Contribution from Silvio Traversaro.
+    * [Pull request 67](https://bitbucket.org/ignitionrobotics/ign-math/pull-request/67)
+
+1. Fix logic of installation of CMake configuration files in Windows.
+   Contribution from Silvio Traversaro.
+    * [Pull request 63](https://bitbucket.org/ignitionrobotics/ign-math/pull-request/63)
+
+## Ignition Math 2.x
+
+### Ignition Math 2.8
+
+### Ignition Math 2.8.0
+
+1. Added Color
+    * [Pull request 150](https://bitbucket.org/ignitionrobotics/ign-math/pull-request/150)
+
+1. Added OrientedBox
+    * [Pull request 146](https://bitbucket.org/ignitionrobotics/ign-math/pull-request/146)
+
+1. Added an assignment operator to the Frustum class.
+    * [Pull request 144](https://bitbucket.org/ignitionrobotics/ign-math/pull-request/144)
+
+### Ignition Math 2.7
+
+### Ignition Math 2.7.0
+
+1. Add static const variables as alternative to macros in Helpers.hh
+    * [Pull request 137](https://bitbucket.org/ignitionrobotics/ign-math/pull-request/137)
+
+1. Add new methods for floating numbers: lessOrEqual and greaterOrEqual
+    * [Pull request 134](https://bitbucket.org/ignitionrobotics/ign-math/pull-request/134)
+
+### Ignition Math 2.6
+
+### Ignition Math 2.6.0
+
+1. Added copy constructor, equality operators and assignment operators to
+    SphericalCoordinates class.
+    * [Pull request 131](https://bitbucket.org/ignitionrobotics/ign-math/pull-request/131)
+
+1. Fix Euler angle conversion of quaternions near singularities
+    * [Pull request 129](https://bitbucket.org/ignitionrobotics/ign-math/pull-request/129)
+
+1. Backport triangle3, helper functions, equality helper to work with 387 fp unit
+   (Contribution from Rich Mattes).
+    * [Pull request 125](https://bitbucket.org/ignitionrobotics/ign-math/pull-request/125)
+    * [Pull request 58](https://bitbucket.org/ignitionrobotics/ign-math/pull-request/58)
+    * [Pull request 56](https://bitbucket.org/ignitionrobotics/ign-math/pull-request/56)
+
+1. Added Matrix4<T>::LookAt
+    * [Pull request 124](https://bitbucket.org/ignitionrobotics/ign-math/pull-request/124)
+
+1. Set Inertial Rotations
+    * [Pull request 121](https://bitbucket.org/ignitionrobotics/ign-math/pull-request/121)
+
+1. Added SemanticVersion class
+    * [Pull request 120](https://bitbucket.org/ignitionrobotics/ign-math/pull-request/120)
+
+### Ignition Math 2.5
+
+### Ignition Math 2.5.0
+
+1. Added PID class
+    * [Pull request 117](https://bitbucket.org/ignitionrobotics/ign-math/pull-request/117)
+
+1. Added SphericalCoordinate class
+    * [Pull request 108](https://bitbucket.org/ignitionrobotics/ign-math/pull-request/108)
+
+### Ignition Math 2.4
+
+#### Ignition Math 2.4.1
+
+1. Combine inertial properties of different objects, returning the equivalent
+   inertial properties as if the objects were welded together.
+    * [Pull request 115](https://bitbucket.org/ignitionrobotics/ign-math/pull-request/115)
+
+#### Ignition Math 2.4.0
+
+1. New MassMatrix3 class
+    * [Pull request 112](https://bitbucket.org/ignitionrobotics/ign-math/pull-request/112)
+1. MassMatrix3 helper functions
+    * [Pull request 110](https://bitbucket.org/ignitionrobotics/ign-math/pull-request/110)
+1. Added Temperature class
+    * A contribution from Shintaro Noda
+    * [Pull request 113](https://bitbucket.org/ignitionrobotics/ign-math/pull-request/113)
+
+### Ignition Math 2.3.0
+
+1. Added simple volumes formulas
+    * [Pull request 84](https://bitbucket.org/ignitionrobotics/ign-math/pull-request/84)
+1. Add Length and SquaredLength for Vector2 with test
+    * [Pull request 73](https://bitbucket.org/ignitionrobotics/ign-math/pull-request/73)
+1. Add Equal function with numerical tolerance argument
+    * [Pull request 75](https://bitbucket.org/ignitionrobotics/ign-math/pull-request/75)
+1. First part of MassMatrix3 class, mostly accessors and modifiers
+    * [Pull request 77](https://bitbucket.org/ignitionrobotics/ign-math/pull-request/77)
+1. Add Transpose methods for Matrix3,4 with test
+    * [Pull request 74](https://bitbucket.org/ignitionrobotics/ign-math/pull-request/74)
+1. Multiplication improvements for Vector/Matrix classes
+    * [Pull request 69](https://bitbucket.org/ignitionrobotics/ign-math/pull-request/69)
+1. Scalar +,- operators for Vector[234]
+    * [Pull request 71](https://bitbucket.org/ignitionrobotics/ign-math/pull-request/71)
+1. Add Determinant method for Matrix[34]
+    * [Pull request 72](https://bitbucket.org/ignitionrobotics/ign-math/pull-requests/72)
+1. Fixes for compiling and running tests on Windows 7/Visual Studio 2013
+   Contribution from Silvio Traversaro.
+    * [Pull request 62](https://bitbucket.org/ignitionrobotics/ign-math/pull-request/62)
diff --git a/LICENSE b/LICENSE
new file mode 100644
index 0000000..bd33c43
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,15 @@
+Software License Agreement (Apache License)
+
+Copyright 2012 Open Source Robotics Foundation
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
diff --git a/Migration.md b/Migration.md
new file mode 100644
index 0000000..080663f
--- /dev/null
+++ b/Migration.md
@@ -0,0 +1,139 @@
+# Note on deprecations
+A tick-tock release cycle allows easy migration to new software versions.
+Obsolete code is marked as deprecated for one major release.
+Deprecated code produces compile-time warnings. These warning serve as
+notification to users that their code should be upgraded. The next major
+release will remove the deprecated code.
+
+## Ignition Math 3.X to 4.X
+
+### Added dependencies
+
+1. **ignition-cmake**
+    + Ignition-math now has a build dependency on ignition-cmake, which
+      allows cmake scripts to be shared across all the ignition packages.
+
+### Modifications
+
+1. **Box.hh**
+    + Boxes generated with the default constructor do not intersect any other
+    boxes or contain any points (previously they contained the origin).
+
+1. **SemanticVersion.hh**
+    + The SemanticVersion(const std::string &) constructor is now explicit.
+
+## Ignition Math 2.X to 3.X
+
+### Modifications
+
+1. **RotationSpline.hh**
+    + The `UpdatePoint` function now returns a boolean value.
+
+1. **Spline.hh**
+    + The `UpdatePoint` function now returns a boolean value.
+
+### Deprecations
+
+1. **Matrix4.hh**
+    + ***Deprecation:*** public: Vector3<T> TransformAffine(const Vector3<T>
+        &_v) const
+    + ***Replacement:*** public: bool TransformAffine(const Vector3<T>
+        &_v,Vector3<T> &_result) const
+
+1. **Helpers.hh**
+    + ***Deprecation:*** IGN_DBL_MAX
+    + ***Replacement:*** ignition::math::MAX_D
+
+    + ***Deprecation:*** IGN_DBL_MIN
+    + ***Replacement:*** ignition::math::MIN_D
+
+    + ***Deprecation:*** IGN_DBL_LOW
+    + ***Replacement:*** ignition::math::LOW_D
+
+    + ***Deprecation:*** IGN_DBL_INF
+    + ***Replacement:*** ignition::math::INF_D
+
+    + ***Deprecation:*** IGN_FLT_MAX
+    + ***Replacement:*** ignition::math::MAX_F
+
+    + ***Deprecation:*** IGN_FLT_MIN
+    + ***Replacement:*** ignition::math::MIN_F
+
+    + ***Deprecation:*** IGN_FLT_LOW
+    + ***Replacement:*** ignition::math::LOW_F
+
+    + ***Deprecation:*** IGN_FLT_INF
+    + ***Replacement:*** ignition::math::INF_F
+
+    + ***Deprecation:*** IGN_UI16_MAX
+    + ***Replacement:*** ignition::math::MAX_UI16
+
+    + ***Deprecation:*** IGN_UI16_MIN
+    + ***Replacement:*** ignition::math::MIN_UI16
+
+    + ***Deprecation:*** IGN_UI16_LOW
+    + ***Replacement:*** ignition::math::LOW_UI16
+
+    + ***Deprecation:*** IGN_UI16_INF
+    + ***Replacement:*** ignition::math::INF_UI16
+
+    + ***Deprecation:*** IGN_I16_MAX
+    + ***Replacement:*** ignition::math::MAX_I16
+
+    + ***Deprecation:*** IGN_I16_MIN
+    + ***Replacement:*** ignition::math::MIN_I16
+
+    + ***Deprecation:*** IGN_I16_LOW
+    + ***Replacement:*** ignition::math::LOW_I16
+
+    + ***Deprecation:*** IGN_I16_INF
+    + ***Replacement:*** ignition::math::INF_I16
+
+    + ***Deprecation:*** IGN_UI32_MAX
+    + ***Replacement:*** ignition::math::MAX_UI32
+
+    + ***Deprecation:*** IGN_UI32_MIN
+    + ***Replacement:*** ignition::math::MIN_UI32
+
+    + ***Deprecation:*** IGN_UI32_LOW
+    + ***Replacement:*** ignition::math::LOW_UI32
+
+    + ***Deprecation:*** IGN_UI32_INF
+    + ***Replacement:*** ignition::math::INF_UI32
+
+    + ***Deprecation:*** IGN_I32_MAX
+    + ***Replacement:*** ignition::math::MAX_I32
+
+    + ***Deprecation:*** IGN_I32_MIN
+    + ***Replacement:*** ignition::math::MIN_I32
+
+    + ***Deprecation:*** IGN_I32_LOW
+    + ***Replacement:*** ignition::math::LOW_I32
+
+    + ***Deprecation:*** IGN_I32_INF
+    + ***Replacement:*** ignition::math::INF_I32
+
+    + ***Deprecation:*** IGN_UI64_MAX
+    + ***Replacement:*** ignition::math::MAX_UI64
+
+    + ***Deprecation:*** IGN_UI64_MIN
+    + ***Replacement:*** ignition::math::MIN_UI64
+
+    + ***Deprecation:*** IGN_UI64_LOW
+    + ***Replacement:*** ignition::math::LOW_UI64
+
+    + ***Deprecation:*** IGN_UI64_INF
+    + ***Replacement:*** ignition::math::INF_UI64
+
+    + ***Deprecation:*** IGN_I64_MAX
+    + ***Replacement:*** ignition::math::MAX_I64
+
+    + ***Deprecation:*** IGN_I64_MIN
+    + ***Replacement:*** ignition::math::MIN_I64
+
+    + ***Deprecation:*** IGN_I64_LOW
+    + ***Replacement:*** ignition::math::LOW_I64
+
+    + ***Deprecation:*** IGN_I64_INF
+    + ***Replacement:*** ignition::math::INF_I64
+
diff --git a/NEWS b/NEWS
new file mode 100644
index 0000000..6b7be6e
--- /dev/null
+++ b/NEWS
@@ -0,0 +1 @@
+http://ignition_robotics.org
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..a4d7415
--- /dev/null
+++ b/README.md
@@ -0,0 +1,50 @@
+# Ignition Math
+
+
+**Math classes and functions for robot applications.**
+
+Ignition Math is a component in the Ignition framework, a set of libraries
+designed to rapidly develop robot applications. The library defines math
+classes and functions used in other Ignition libraries and programs.
+
+  [http://ignitionrobotics.org](http://ignitionrobotics.org)
+
+## Continuous integration
+
+This project uses [appveyor](https://ci.appveyor.com/project/scpeters/ign-math/history)
+for testing on Windows.
+It has the following build status:
+![appveyor badge](https://ci.appveyor.com/api/projects/status/bitbucket/ignitionrobotics/ign-math?svg=true)
+
+This project also uses [bitbucket pipelines](https://bitbucket.org/ignitionrobotics/ign-math/addon/pipelines/home#!/)
+for testing with Linux.
+
+Test coverage reports are available at Codecov:
+
+[![codecov](https://codecov.io/bb/ignitionrobotics/ign-math/branch/master/graph/badge.svg)](https://codecov.io/bb/ignitionrobotics/ign-math)
+
+## Required Dependencies
+
+    brew install ignition-cmake
+
+## Optional Dependencies
+
+    sudo apt-get install doxygen
+    brew install doxygen
+
+## Installation
+
+Standard installation can be performed in UNIX systems using the following
+steps:
+
+ - mkdir build/
+ - cd build/
+ - cmake ..
+ - sudo make install
+
+## Uninstallation
+
+To uninstall the software installed with the previous steps:
+
+ - cd build/
+ - sudo make uninstall
diff --git a/bitbucket-pipelines.yml b/bitbucket-pipelines.yml
new file mode 100644
index 0000000..0979a22
--- /dev/null
+++ b/bitbucket-pipelines.yml
@@ -0,0 +1,24 @@
+image: ubuntu:xenial
+
+pipelines:
+  default:
+    - step:
+        script:
+          - apt-get update
+          - apt-get -y install cmake build-essential lcov curl mercurial
+          - gcc -v
+          - g++ -v
+          # Ignition cmake
+          - echo "deb http://packages.osrfoundation.org/gazebo/ubuntu-prerelease xenial main" > /etc/apt/sources.list.d/gazebo-prerelease.list
+          - apt-key adv --keyserver hkp://p80.pool.sks-keyservers.net:80 --recv-keys D2486D2DD83DB69272AFE98867170598AF249743
+          - apt-get update
+          - apt-get -y install
+            libignition-cmake-dev
+          # Ignition math
+          - mkdir build
+          - cd build
+          - cmake .. -DCMAKE_BUILD_TYPE=coverage
+          - make
+          - make test
+          - make coverage
+          - bash <(curl -s https://codecov.io/bash)
diff --git a/configure.bat b/configure.bat
new file mode 100644
index 0000000..625cc06
--- /dev/null
+++ b/configure.bat
@@ -0,0 +1,23 @@
+
+:: NOTE: This script is only meant to be used as part of the ignition developers' CI system
+:: Users and developers should build and install this library using cmake and Visual Studio
+
+:: Install dependencies
+call %win_lib% :install_ign_project ign-cmake default
+
+:: Set configuration variables
+ at set build_type=Release
+ at if not "%1"=="" set build_type=%1
+ at echo Configuring for build type %build_type%
+
+:: Go to the directory that this configure.bat file exists in
+cd /d %~dp0
+
+:: Create a build directory and configure
+md build
+cd build
+cmake .. -G "NMake Makefiles" -DCMAKE_INSTALL_PREFIX="%WORKSPACE_INSTALL_DIR%" -DCMAKE_BUILD_TYPE="%build_type%" -DBUILD_TESTING:BOOL=False
+:: Note: We disable testing by default. If the intention is for the CI to build and test
+:: this project, then the CI script will turn it back on.
+
+:: If the caller wants to build and/or install, they should do so after calling this script
diff --git a/doc/CMakeLists.txt b/doc/CMakeLists.txt
new file mode 100644
index 0000000..36e4496
--- /dev/null
+++ b/doc/CMakeLists.txt
@@ -0,0 +1,14 @@
+find_package(Doxygen)
+
+if (DOXYGEN_FOUND)
+  configure_file(${CMAKE_SOURCE_DIR}/doc/ignition.in
+                 ${CMAKE_BINARY_DIR}/ignition.dox @ONLY)
+
+  add_custom_target(doc
+    # Generate the API documentation
+    ${DOXYGEN_EXECUTABLE} ${CMAKE_BINARY_DIR}/ignition.dox
+    WORKING_DIRECTORY ${CMAKE_BINARY_DIR}
+    COMMAND cp ${CMAKE_SOURCE_DIR}/doc/ignition_logo.svg
+            ${CMAKE_BINARY_DIR}/doxygen/html
+    COMMENT "Generating API documentation with Doxygen" VERBATIM)
+endif()
diff --git a/doc/footer.html b/doc/footer.html
new file mode 100644
index 0000000..71d71c4
--- /dev/null
+++ b/doc/footer.html
@@ -0,0 +1 @@
+<!--</td></tr></table>-->
diff --git a/doc/header.html b/doc/header.html
new file mode 100644
index 0000000..55ace60
--- /dev/null
+++ b/doc/header.html
@@ -0,0 +1,67 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<html>
+  <head>
+    <meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8">
+    <meta http-equiv="X-UA-Compatible" content="IE=9"/>
+    <meta name="keywords" content="Ingition: Math">
+    <title>Ignition: $title</title>
+    <link href="tabs.css" rel="stylesheet" type="text/css">
+    <script type="text/javascript" src="jquery.js"></script>
+    <script type="text/javascript" src="dynsections.js"></script>
+    <link href="search/search.css" rel="stylesheet" type="text/css">
+    <script type="text/javascript" src="search/search.js"></script>
+    <script type="text/javascript">
+        $(document).ready(function() { searchBox.OnSelectItem(0); });
+    </script>
+
+    <link href="doxygen.css" rel="stylesheet" type="text/css">
+    <!--<link href="tabs.css" rel="stylesheet" type="text/css">-->
+    <link href="style.css" rel="stylesheet" type="text/css">
+  </head>
+
+<body>
+  <div class="leftbar"> 
+    <h2 style="text-align:center;">
+      <a href="index.html"><img src="ignition_logo.svg" width="180px"/></a>
+    </h2>
+
+    <div class="menu">
+      <dl>
+        <dt>API</dt>
+        <dd><a href="classes.html">Class List</a></dd>
+        <dd><a href="hierarchy.html">Class Hierarchy</a></dd>
+        <dd><a href="globals.html">Globals</a></dd>
+        <dd><a href="namespacemembers.html">Namespace Members</a></dd>
+        <dd><a href="files.html">Files</a></dd>
+      </dl>
+    </div>
+    <div class="menu">
+      <dl>
+        <dt>Links</dt>
+        <dd><a href="http://ignitionrobotics.org">Ignition Website</a></dd>
+        <dd><a href="https://bitbucket.org/ignitionrobotics/ign-math/issues/new">Report Documentation Issues</a></dd>
+      </dl>
+    </div>
+
+    <div id="MSearchBox" class="MSearchBoxInactive">
+      <span>
+        <img id="MSearchSelect" src="search/mag_sel.png"
+        onmouseover="return searchBox.OnSearchSelectShow()"
+        onmouseout="return searchBox.OnSearchSelectHide()"
+        alt=""/>
+        <input type="text" id="MSearchField" value="Search" accesskey="S"
+        onfocus="searchBox.OnSearchFieldFocus(true)" 
+        onblur="searchBox.OnSearchFieldFocus(false)" 
+        onkeyup="searchBox.OnSearchFieldChange(event)"/>
+      </span>
+    </div> <!-- End MSearchBox -->
+
+    <div id="MSearchResultsWindow" style="position: static; display: block; border: none; background-color: #ffffff; width: 18em;">
+      <iframe src="javascript:void(0)" frameborder="0" 
+              name="MSearchResults"
+              style="height: 500px; width: 18em; display: block; text-wrap: unrestricted">
+      </iframe>
+    </div>
+  </div>
+
+  <div id="top">
diff --git a/doc/ignition.in b/doc/ignition.in
new file mode 100644
index 0000000..32cb4bd
--- /dev/null
+++ b/doc/ignition.in
@@ -0,0 +1,2306 @@
+# Doxyfile 1.8.6
+
+# This file describes the settings to be used by the documentation system
+# doxygen (www.doxygen.org) for a project.
+#
+# All text after a double hash (##) is considered a comment and is placed in
+# front of the TAG it is preceding.
+#
+# All text after a single hash (#) is considered a comment and will be ignored.
+# The format is:
+# TAG = value [value, ...]
+# For lists, items can also be appended using:
+# TAG += value [value, ...]
+# Values that contain spaces should be placed between quotes (\" \").
+
+#---------------------------------------------------------------------------
+# Project related configuration options
+#---------------------------------------------------------------------------
+
+# This tag specifies the encoding used for all characters in the config file
+# that follow. The default is UTF-8 which is also the encoding used for all text
+# before the first occurrence of this tag. Doxygen uses libiconv (or the iconv
+# built into libc) for the transcoding. See http://www.gnu.org/software/libiconv
+# for the list of possible encodings.
+# The default value is: UTF-8.
+
+DOXYFILE_ENCODING      = UTF-8
+
+# The PROJECT_NAME tag is a single word (or a sequence of words surrounded by
+# double-quotes, unless you are using Doxywizard) that should identify the
+# project for which the documentation is generated. This name is used in the
+# title of most generated pages and in a few other places.
+# The default value is: My Project.
+
+PROJECT_NAME           = IgnitionMath
+
+# The PROJECT_NUMBER tag can be used to enter a project or revision number. This
+# could be handy for archiving the generated documentation or if some version
+# control system is used.
+
+PROJECT_NUMBER         = @PROJECT_VERSION_FULL@
+
+# Using the PROJECT_BRIEF tag one can provide an optional one line description
+# for a project that appears at the top of each page and should give viewer a
+# quick idea about the purpose of the project. Keep the description short.
+
+PROJECT_BRIEF          =
+
+# With the PROJECT_LOGO tag one can specify an logo or icon that is included in
+# the documentation. The maximum height of the logo should not exceed 55 pixels
+# and the maximum width should not exceed 200 pixels. Doxygen will copy the logo
+# to the output directory.
+
+PROJECT_LOGO           =
+
+# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) path
+# into which the generated documentation will be written. If a relative path is
+# entered, it will be relative to the location where doxygen was started. If
+# left blank the current directory will be used.
+
+OUTPUT_DIRECTORY       = doxygen
+
+# If the CREATE_SUBDIRS tag is set to YES, then doxygen will create 4096 sub-
+# directories (in 2 levels) under the output directory of each output format and
+# will distribute the generated files over these directories. Enabling this
+# option can be useful when feeding doxygen a huge amount of source files, where
+# putting all generated files in the same directory would otherwise causes
+# performance problems for the file system.
+# The default value is: NO.
+
+CREATE_SUBDIRS         = NO
+
+# The OUTPUT_LANGUAGE tag is used to specify the language in which all
+# documentation generated by doxygen is written. Doxygen will use this
+# information to generate all constant output in the proper language.
+# Possible values are: Afrikaans, Arabic, Armenian, Brazilian, Catalan, Chinese,
+# Chinese-Traditional, Croatian, Czech, Danish, Dutch, English (United States),
+# Esperanto, Farsi (Persian), Finnish, French, German, Greek, Hungarian,
+# Indonesian, Italian, Japanese, Japanese-en (Japanese with English messages),
+# Korean, Korean-en (Korean with English messages), Latvian, Lithuanian,
+# Macedonian, Norwegian, Persian (Farsi), Polish, Portuguese, Romanian, Russian,
+# Serbian, Serbian-Cyrillic, Slovak, Slovene, Spanish, Swedish, Turkish,
+# Ukrainian and Vietnamese.
+# The default value is: English.
+
+OUTPUT_LANGUAGE        = English
+
+# If the BRIEF_MEMBER_DESC tag is set to YES doxygen will include brief member
+# descriptions after the members that are listed in the file and class
+# documentation (similar to Javadoc). Set to NO to disable this.
+# The default value is: YES.
+
+BRIEF_MEMBER_DESC      = YES
+
+# If the REPEAT_BRIEF tag is set to YES doxygen will prepend the brief
+# description of a member or function before the detailed description
+#
+# Note: If both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the
+# brief descriptions will be completely suppressed.
+# The default value is: YES.
+
+REPEAT_BRIEF           = YES
+
+# This tag implements a quasi-intelligent brief description abbreviator that is
+# used to form the text in various listings. Each string in this list, if found
+# as the leading text of the brief description, will be stripped from the text
+# and the result, after processing the whole list, is used as the annotated
+# text. Otherwise, the brief description is used as-is. If left blank, the
+# following values are used ($name is automatically replaced with the name of
+# the entity):The $name class, The $name widget, The $name file, is, provides,
+# specifies, contains, represents, a, an and the.
+
+ABBREVIATE_BRIEF       =
+
+# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then
+# doxygen will generate a detailed section even if there is only a brief
+# description.
+# The default value is: NO.
+
+ALWAYS_DETAILED_SEC    = YES
+
+# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all
+# inherited members of a class in the documentation of that class as if those
+# members were ordinary class members. Constructors, destructors and assignment
+# operators of the base classes will not be shown.
+# The default value is: NO.
+
+INLINE_INHERITED_MEMB  = NO
+
+# If the FULL_PATH_NAMES tag is set to YES doxygen will prepend the full path
+# before files name in the file list and in the header files. If set to NO the
+# shortest path that makes the file name unique will be used
+# The default value is: YES.
+
+FULL_PATH_NAMES        = NO
+
+# The STRIP_FROM_PATH tag can be used to strip a user-defined part of the path.
+# Stripping is only done if one of the specified strings matches the left-hand
+# part of the path. The tag can be used to show relative paths in the file list.
+# If left blank the directory from which doxygen is run is used as the path to
+# strip.
+#
+# Note that you can specify absolute paths here, but also relative paths, which
+# will be relative from the directory where doxygen is started.
+# This tag requires that the tag FULL_PATH_NAMES is set to YES.
+
+STRIP_FROM_PATH        =
+
+# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of the
+# path mentioned in the documentation of a class, which tells the reader which
+# header file to include in order to use a class. If left blank only the name of
+# the header file containing the class definition is used. Otherwise one should
+# specify the list of include paths that are normally passed to the compiler
+# using the -I flag.
+
+STRIP_FROM_INC_PATH    =
+
+# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter (but
+# less readable) file names. This can be useful is your file systems doesn't
+# support long names like on DOS, Mac, or CD-ROM.
+# The default value is: NO.
+
+SHORT_NAMES            = NO
+
+# If the JAVADOC_AUTOBRIEF tag is set to YES then doxygen will interpret the
+# first line (until the first dot) of a Javadoc-style comment as the brief
+# description. If set to NO, the Javadoc-style will behave just like regular Qt-
+# style comments (thus requiring an explicit @brief command for a brief
+# description.)
+# The default value is: NO.
+
+JAVADOC_AUTOBRIEF      = YES
+
+# If the QT_AUTOBRIEF tag is set to YES then doxygen will interpret the first
+# line (until the first dot) of a Qt-style comment as the brief description. If
+# set to NO, the Qt-style will behave just like regular Qt-style comments (thus
+# requiring an explicit \brief command for a brief description.)
+# The default value is: NO.
+
+QT_AUTOBRIEF           = NO
+
+# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make doxygen treat a
+# multi-line C++ special comment block (i.e. a block of //! or /// comments) as
+# a brief description. This used to be the default behavior. The new default is
+# to treat a multi-line C++ comment block as a detailed description. Set this
+# tag to YES if you prefer the old behavior instead.
+#
+# Note that setting this tag to YES also means that rational rose comments are
+# not recognized any more.
+# The default value is: NO.
+
+MULTILINE_CPP_IS_BRIEF = NO
+
+# If the INHERIT_DOCS tag is set to YES then an undocumented member inherits the
+# documentation from any documented member that it re-implements.
+# The default value is: YES.
+
+INHERIT_DOCS           = YES
+
+# If the SEPARATE_MEMBER_PAGES tag is set to YES, then doxygen will produce a
+# new page for each member. If set to NO, the documentation of a member will be
+# part of the file/class/namespace that contains it.
+# The default value is: NO.
+
+SEPARATE_MEMBER_PAGES  = NO
+
+# The TAB_SIZE tag can be used to set the number of spaces in a tab. Doxygen
+# uses this value to replace tabs by spaces in code fragments.
+# Minimum value: 1, maximum value: 16, default value: 4.
+
+TAB_SIZE               = 4
+
+# This tag can be used to specify a number of aliases that act as commands in
+# the documentation. An alias has the form:
+# name=value
+# For example adding
+# "sideeffect=@par Side Effects:\n"
+# will allow you to put the command \sideeffect (or @sideeffect) in the
+# documentation, which will result in a user-defined paragraph with heading
+# "Side Effects:". You can put \n's in the value part of an alias to insert
+# newlines.
+
+ALIASES                =
+
+# This tag can be used to specify a number of word-keyword mappings (TCL only).
+# A mapping has the form "name=value". For example adding "class=itcl::class"
+# will allow you to use the command class in the itcl::class meaning.
+
+TCL_SUBST              =
+
+# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C sources
+# only. Doxygen will then generate output that is more tailored for C. For
+# instance, some of the names that are used will be different. The list of all
+# members will be omitted, etc.
+# The default value is: NO.
+
+OPTIMIZE_OUTPUT_FOR_C  = NO
+
+# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java or
+# Python sources only. Doxygen will then generate output that is more tailored
+# for that language. For instance, namespaces will be presented as packages,
+# qualified scopes will look different, etc.
+# The default value is: NO.
+
+OPTIMIZE_OUTPUT_JAVA   = NO
+
+# Set the OPTIMIZE_FOR_FORTRAN tag to YES if your project consists of Fortran
+# sources. Doxygen will then generate output that is tailored for Fortran.
+# The default value is: NO.
+
+OPTIMIZE_FOR_FORTRAN   = NO
+
+# Set the OPTIMIZE_OUTPUT_VHDL tag to YES if your project consists of VHDL
+# sources. Doxygen will then generate output that is tailored for VHDL.
+# The default value is: NO.
+
+OPTIMIZE_OUTPUT_VHDL   = NO
+
+# Doxygen selects the parser to use depending on the extension of the files it
+# parses. With this tag you can assign which parser to use for a given
+# extension. Doxygen has a built-in mapping, but you can override or extend it
+# using this tag. The format is ext=language, where ext is a file extension, and
+# language is one of the parsers supported by doxygen: IDL, Java, Javascript,
+# C#, C, C++, D, PHP, Objective-C, Python, Fortran, VHDL. For instance to make
+# doxygen treat .inc files as Fortran files (default is PHP), and .f files as C
+# (default is Fortran), use: inc=Fortran f=C.
+#
+# Note For files without extension you can use no_extension as a placeholder.
+#
+# Note that for custom extensions you also need to set FILE_PATTERNS otherwise
+# the files are not read by doxygen.
+
+EXTENSION_MAPPING      =
+
+# If the MARKDOWN_SUPPORT tag is enabled then doxygen pre-processes all comments
+# according to the Markdown format, which allows for more readable
+# documentation. See http://daringfireball.net/projects/markdown/ for details.
+# The output of markdown processing is further processed by doxygen, so you can
+# mix doxygen, HTML, and XML commands with Markdown formatting. Disable only in
+# case of backward compatibilities issues.
+# The default value is: YES.
+
+MARKDOWN_SUPPORT       = YES
+
+# When enabled doxygen tries to link words that correspond to documented
+# classes, or namespaces to their corresponding documentation. Such a link can
+# be prevented in individual cases by by putting a % sign in front of the word
+# or globally by setting AUTOLINK_SUPPORT to NO.
+# The default value is: YES.
+
+AUTOLINK_SUPPORT       = YES
+
+# If you use STL classes (i.e. std::string, std::vector, etc.) but do not want
+# to include (a tag file for) the STL sources as input, then you should set this
+# tag to YES in order to let doxygen match functions declarations and
+# definitions whose arguments contain STL classes (e.g. func(std::string);
+# versus func(std::string) {}). This also make the inheritance and collaboration
+# diagrams that involve STL classes more complete and accurate.
+# The default value is: NO.
+
+BUILTIN_STL_SUPPORT    = YES
+
+# If you use Microsoft's C++/CLI language, you should set this option to YES to
+# enable parsing support.
+# The default value is: NO.
+
+CPP_CLI_SUPPORT        = NO
+
+# Set the SIP_SUPPORT tag to YES if your project consists of sip (see:
+# http://www.riverbankcomputing.co.uk/software/sip/intro) sources only. Doxygen
+# will parse them like normal C++ but will assume all classes use public instead
+# of private inheritance when no explicit protection keyword is present.
+# The default value is: NO.
+
+SIP_SUPPORT            = NO
+
+# For Microsoft's IDL there are propget and propput attributes to indicate
+# getter and setter methods for a property. Setting this option to YES will make
+# doxygen to replace the get and set methods by a property in the documentation.
+# This will only work if the methods are indeed getting or setting a simple
+# type. If this is not the case, or you want to show the methods anyway, you
+# should set this option to NO.
+# The default value is: YES.
+
+IDL_PROPERTY_SUPPORT   = YES
+
+# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC
+# tag is set to YES, then doxygen will reuse the documentation of the first
+# member in the group (if any) for the other members of the group. By default
+# all members of a group must be documented explicitly.
+# The default value is: NO.
+
+DISTRIBUTE_GROUP_DOC   = YES
+
+# Set the SUBGROUPING tag to YES to allow class member groups of the same type
+# (for instance a group of public functions) to be put as a subgroup of that
+# type (e.g. under the Public Functions section). Set it to NO to prevent
+# subgrouping. Alternatively, this can be done per class using the
+# \nosubgrouping command.
+# The default value is: YES.
+
+SUBGROUPING            = YES
+
+# When the INLINE_GROUPED_CLASSES tag is set to YES, classes, structs and unions
+# are shown inside the group in which they are included (e.g. using \ingroup)
+# instead of on a separate page (for HTML and Man pages) or section (for LaTeX
+# and RTF).
+#
+# Note that this feature does not work in combination with
+# SEPARATE_MEMBER_PAGES.
+# The default value is: NO.
+
+INLINE_GROUPED_CLASSES = NO
+
+# When the INLINE_SIMPLE_STRUCTS tag is set to YES, structs, classes, and unions
+# with only public data fields or simple typedef fields will be shown inline in
+# the documentation of the scope in which they are defined (i.e. file,
+# namespace, or group documentation), provided this scope is documented. If set
+# to NO, structs, classes, and unions are shown on a separate page (for HTML and
+# Man pages) or section (for LaTeX and RTF).
+# The default value is: NO.
+
+INLINE_SIMPLE_STRUCTS  = NO
+
+# When TYPEDEF_HIDES_STRUCT tag is enabled, a typedef of a struct, union, or
+# enum is documented as struct, union, or enum with the name of the typedef. So
+# typedef struct TypeS {} TypeT, will appear in the documentation as a struct
+# with name TypeT. When disabled the typedef will appear as a member of a file,
+# namespace, or class. And the struct will be named TypeS. This can typically be
+# useful for C code in case the coding convention dictates that all compound
+# types are typedef'ed and only the typedef is referenced, never the tag name.
+# The default value is: NO.
+
+TYPEDEF_HIDES_STRUCT   = NO
+
+# The size of the symbol lookup cache can be set using LOOKUP_CACHE_SIZE. This
+# cache is used to resolve symbols given their name and scope. Since this can be
+# an expensive process and often the same symbol appears multiple times in the
+# code, doxygen keeps a cache of pre-resolved symbols. If the cache is too small
+# doxygen will become slower. If the cache is too large, memory is wasted. The
+# cache size is given by this formula: 2^(16+LOOKUP_CACHE_SIZE). The valid range
+# is 0..9, the default is 0, corresponding to a cache size of 2^16=65536
+# symbols. At the end of a run doxygen will report the cache usage and suggest
+# the optimal cache size from a speed point of view.
+# Minimum value: 0, maximum value: 9, default value: 0.
+
+LOOKUP_CACHE_SIZE      = 0
+
+#---------------------------------------------------------------------------
+# Build related configuration options
+#---------------------------------------------------------------------------
+
+# If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in
+# documentation are documented, even if no documentation was available. Private
+# class members and static file members will be hidden unless the
+# EXTRACT_PRIVATE respectively EXTRACT_STATIC tags are set to YES.
+# Note: This will also disable the warnings about undocumented members that are
+# normally produced when WARNINGS is set to YES.
+# The default value is: NO.
+
+EXTRACT_ALL            = YES
+
+# If the EXTRACT_PRIVATE tag is set to YES all private members of a class will
+# be included in the documentation.
+# The default value is: NO.
+
+EXTRACT_PRIVATE        = NO
+
+# If the EXTRACT_PACKAGE tag is set to YES all members with package or internal
+# scope will be included in the documentation.
+# The default value is: NO.
+
+EXTRACT_PACKAGE        = NO
+
+# If the EXTRACT_STATIC tag is set to YES all static members of a file will be
+# included in the documentation.
+# The default value is: NO.
+
+EXTRACT_STATIC         = YES
+
+# If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs) defined
+# locally in source files will be included in the documentation. If set to NO
+# only classes defined in header files are included. Does not have any effect
+# for Java sources.
+# The default value is: YES.
+
+EXTRACT_LOCAL_CLASSES  = NO
+
+# This flag is only useful for Objective-C code. When set to YES local methods,
+# which are defined in the implementation section but not in the interface are
+# included in the documentation. If set to NO only methods in the interface are
+# included.
+# The default value is: NO.
+
+EXTRACT_LOCAL_METHODS  = NO
+
+# If this flag is set to YES, the members of anonymous namespaces will be
+# extracted and appear in the documentation as a namespace called
+# 'anonymous_namespace{file}', where file will be replaced with the base name of
+# the file that contains the anonymous namespace. By default anonymous namespace
+# are hidden.
+# The default value is: NO.
+
+EXTRACT_ANON_NSPACES   = YES
+
+# If the HIDE_UNDOC_MEMBERS tag is set to YES, doxygen will hide all
+# undocumented members inside documented classes or files. If set to NO these
+# members will be included in the various overviews, but no documentation
+# section is generated. This option has no effect if EXTRACT_ALL is enabled.
+# The default value is: NO.
+
+HIDE_UNDOC_MEMBERS     = NO
+
+# If the HIDE_UNDOC_CLASSES tag is set to YES, doxygen will hide all
+# undocumented classes that are normally visible in the class hierarchy. If set
+# to NO these classes will be included in the various overviews. This option has
+# no effect if EXTRACT_ALL is enabled.
+# The default value is: NO.
+
+HIDE_UNDOC_CLASSES     = NO
+
+# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, doxygen will hide all friend
+# (class|struct|union) declarations. If set to NO these declarations will be
+# included in the documentation.
+# The default value is: NO.
+
+HIDE_FRIEND_COMPOUNDS  = YES
+
+# If the HIDE_IN_BODY_DOCS tag is set to YES, doxygen will hide any
+# documentation blocks found inside the body of a function. If set to NO these
+# blocks will be appended to the function's detailed documentation block.
+# The default value is: NO.
+
+HIDE_IN_BODY_DOCS      = NO
+
+# The INTERNAL_DOCS tag determines if documentation that is typed after a
+# \internal command is included. If the tag is set to NO then the documentation
+# will be excluded. Set it to YES to include the internal documentation.
+# The default value is: NO.
+
+INTERNAL_DOCS          = NO
+
+# If the CASE_SENSE_NAMES tag is set to NO then doxygen will only generate file
+# names in lower-case letters. If set to YES upper-case letters are also
+# allowed. This is useful if you have classes or files whose names only differ
+# in case and if your file system supports case sensitive file names. Windows
+# and Mac users are advised to set this option to NO.
+# The default value is: system dependent.
+
+CASE_SENSE_NAMES       = YES
+
+# If the HIDE_SCOPE_NAMES tag is set to NO then doxygen will show members with
+# their full class and namespace scopes in the documentation. If set to YES the
+# scope will be hidden.
+# The default value is: NO.
+
+HIDE_SCOPE_NAMES       = NO
+
+# If the SHOW_INCLUDE_FILES tag is set to YES then doxygen will put a list of
+# the files that are included by a file in the documentation of that file.
+# The default value is: YES.
+
+SHOW_INCLUDE_FILES     = YES
+
+# If the SHOW_GROUPED_MEMB_INC tag is set to YES then Doxygen will add for each
+# grouped member an include statement to the documentation, telling the reader
+# which file to include in order to use the member.
+# The default value is: NO.
+
+SHOW_GROUPED_MEMB_INC  = NO
+
+# If the FORCE_LOCAL_INCLUDES tag is set to YES then doxygen will list include
+# files with double quotes in the documentation rather than with sharp brackets.
+# The default value is: NO.
+
+FORCE_LOCAL_INCLUDES   = NO
+
+# If the INLINE_INFO tag is set to YES then a tag [inline] is inserted in the
+# documentation for inline members.
+# The default value is: YES.
+
+INLINE_INFO            = YES
+
+# If the SORT_MEMBER_DOCS tag is set to YES then doxygen will sort the
+# (detailed) documentation of file and class members alphabetically by member
+# name. If set to NO the members will appear in declaration order.
+# The default value is: YES.
+
+SORT_MEMBER_DOCS       = YES
+
+# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the brief
+# descriptions of file, namespace and class members alphabetically by member
+# name. If set to NO the members will appear in declaration order. Note that
+# this will also influence the order of the classes in the class list.
+# The default value is: NO.
+
+SORT_BRIEF_DOCS        = YES
+
+# If the SORT_MEMBERS_CTORS_1ST tag is set to YES then doxygen will sort the
+# (brief and detailed) documentation of class members so that constructors and
+# destructors are listed first. If set to NO the constructors will appear in the
+# respective orders defined by SORT_BRIEF_DOCS and SORT_MEMBER_DOCS.
+# Note: If SORT_BRIEF_DOCS is set to NO this option is ignored for sorting brief
+# member documentation.
+# Note: If SORT_MEMBER_DOCS is set to NO this option is ignored for sorting
+# detailed member documentation.
+# The default value is: NO.
+
+SORT_MEMBERS_CTORS_1ST = YES
+
+# If the SORT_GROUP_NAMES tag is set to YES then doxygen will sort the hierarchy
+# of group names into alphabetical order. If set to NO the group names will
+# appear in their defined order.
+# The default value is: NO.
+
+SORT_GROUP_NAMES       = NO
+
+# If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be sorted by
+# fully-qualified names, including namespaces. If set to NO, the class list will
+# be sorted only by class name, not including the namespace part.
+# Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES.
+# Note: This option applies only to the class list, not to the alphabetical
+# list.
+# The default value is: NO.
+
+SORT_BY_SCOPE_NAME     = NO
+
+# If the STRICT_PROTO_MATCHING option is enabled and doxygen fails to do proper
+# type resolution of all parameters of a function it will reject a match between
+# the prototype and the implementation of a member function even if there is
+# only one candidate or it is obvious which candidate to choose by doing a
+# simple string match. By disabling STRICT_PROTO_MATCHING doxygen will still
+# accept a match between prototype and implementation in such cases.
+# The default value is: NO.
+
+STRICT_PROTO_MATCHING  = NO
+
+# The GENERATE_TODOLIST tag can be used to enable ( YES) or disable ( NO) the
+# todo list. This list is created by putting \todo commands in the
+# documentation.
+# The default value is: YES.
+
+GENERATE_TODOLIST      = YES
+
+# The GENERATE_TESTLIST tag can be used to enable ( YES) or disable ( NO) the
+# test list. This list is created by putting \test commands in the
+# documentation.
+# The default value is: YES.
+
+GENERATE_TESTLIST      = YES
+
+# The GENERATE_BUGLIST tag can be used to enable ( YES) or disable ( NO) the bug
+# list. This list is created by putting \bug commands in the documentation.
+# The default value is: YES.
+
+GENERATE_BUGLIST       = YES
+
+# The GENERATE_DEPRECATEDLIST tag can be used to enable ( YES) or disable ( NO)
+# the deprecated list. This list is created by putting \deprecated commands in
+# the documentation.
+# The default value is: YES.
+
+GENERATE_DEPRECATEDLIST= YES
+
+# The ENABLED_SECTIONS tag can be used to enable conditional documentation
+# sections, marked by \if <section_label> ... \endif and \cond <section_label>
+# ... \endcond blocks.
+
+ENABLED_SECTIONS       =
+
+# The MAX_INITIALIZER_LINES tag determines the maximum number of lines that the
+# initial value of a variable or macro / define can have for it to appear in the
+# documentation. If the initializer consists of more lines than specified here
+# it will be hidden. Use a value of 0 to hide initializers completely. The
+# appearance of the value of individual variables and macros / defines can be
+# controlled using \showinitializer or \hideinitializer command in the
+# documentation regardless of this setting.
+# Minimum value: 0, maximum value: 10000, default value: 30.
+
+MAX_INITIALIZER_LINES  = 30
+
+# Set the SHOW_USED_FILES tag to NO to disable the list of files generated at
+# the bottom of the documentation of classes and structs. If set to YES the list
+# will mention the files that were used to generate the documentation.
+# The default value is: YES.
+
+SHOW_USED_FILES        = YES
+
+# Set the SHOW_FILES tag to NO to disable the generation of the Files page. This
+# will remove the Files entry from the Quick Index and from the Folder Tree View
+# (if specified).
+# The default value is: YES.
+
+SHOW_FILES             = YES
+
+# Set the SHOW_NAMESPACES tag to NO to disable the generation of the Namespaces
+# page. This will remove the Namespaces entry from the Quick Index and from the
+# Folder Tree View (if specified).
+# The default value is: YES.
+
+SHOW_NAMESPACES        = YES
+
+# The FILE_VERSION_FILTER tag can be used to specify a program or script that
+# doxygen should invoke to get the current version for each file (typically from
+# the version control system). Doxygen will invoke the program by executing (via
+# popen()) the command command input-file, where command is the value of the
+# FILE_VERSION_FILTER tag, and input-file is the name of an input file provided
+# by doxygen. Whatever the program writes to standard output is used as the file
+# version. For an example see the documentation.
+
+FILE_VERSION_FILTER    =
+
+# The LAYOUT_FILE tag can be used to specify a layout file which will be parsed
+# by doxygen. The layout file controls the global structure of the generated
+# output files in an output format independent way. To create the layout file
+# that represents doxygen's defaults, run doxygen with the -l option. You can
+# optionally specify a file name after the option, if omitted DoxygenLayout.xml
+# will be used as the name of the layout file.
+#
+# Note that if you run doxygen from a directory containing a file called
+# DoxygenLayout.xml, doxygen will parse it automatically even if the LAYOUT_FILE
+# tag is left empty.
+
+LAYOUT_FILE            =
+
+# The CITE_BIB_FILES tag can be used to specify one or more bib files containing
+# the reference definitions. This must be a list of .bib files. The .bib
+# extension is automatically appended if omitted. This requires the bibtex tool
+# to be installed. See also http://en.wikipedia.org/wiki/BibTeX for more info.
+# For LaTeX the style of the bibliography can be controlled using
+# LATEX_BIB_STYLE. To use this feature you need bibtex and perl available in the
+# search path. Do not use file names with spaces, bibtex cannot handle them. See
+# also \cite for info how to create references.
+
+CITE_BIB_FILES         =
+
+#---------------------------------------------------------------------------
+# Configuration options related to warning and progress messages
+#---------------------------------------------------------------------------
+
+# The QUIET tag can be used to turn on/off the messages that are generated to
+# standard output by doxygen. If QUIET is set to YES this implies that the
+# messages are off.
+# The default value is: NO.
+
+QUIET                  = NO
+
+# The WARNINGS tag can be used to turn on/off the warning messages that are
+# generated to standard error ( stderr) by doxygen. If WARNINGS is set to YES
+# this implies that the warnings are on.
+#
+# Tip: Turn warnings on while writing the documentation.
+# The default value is: YES.
+
+WARNINGS               = YES
+
+# If the WARN_IF_UNDOCUMENTED tag is set to YES, then doxygen will generate
+# warnings for undocumented members. If EXTRACT_ALL is set to YES then this flag
+# will automatically be disabled.
+# The default value is: YES.
+
+WARN_IF_UNDOCUMENTED   = YES
+
+# If the WARN_IF_DOC_ERROR tag is set to YES, doxygen will generate warnings for
+# potential errors in the documentation, such as not documenting some parameters
+# in a documented function, or documenting parameters that don't exist or using
+# markup commands wrongly.
+# The default value is: YES.
+
+WARN_IF_DOC_ERROR      = YES
+
+# This WARN_NO_PARAMDOC option can be enabled to get warnings for functions that
+# are documented, but have no documentation for their parameters or return
+# value. If set to NO doxygen will only warn about wrong or incomplete parameter
+# documentation, but not about the absence of documentation.
+# The default value is: NO.
+
+WARN_NO_PARAMDOC       = NO
+
+# The WARN_FORMAT tag determines the format of the warning messages that doxygen
+# can produce. The string should contain the $file, $line, and $text tags, which
+# will be replaced by the file and line number from which the warning originated
+# and the warning text. Optionally the format may contain $version, which will
+# be replaced by the version of the file (if it could be obtained via
+# FILE_VERSION_FILTER)
+# The default value is: $file:$line: $text.
+
+WARN_FORMAT            = "$file:$line: $text"
+
+# The WARN_LOGFILE tag can be used to specify a file to which warning and error
+# messages should be written. If left blank the output is written to standard
+# error (stderr).
+
+WARN_LOGFILE           = /tmp/ignition-math_dox.warn
+
+#---------------------------------------------------------------------------
+# Configuration options related to the input files
+#---------------------------------------------------------------------------
+
+# The INPUT tag is used to specify the files and/or directories that contain
+# documented source files. You may enter file names like myfile.cpp or
+# directories like /usr/src/myproject. Separate the files or directories with
+# spaces.
+# Note: If this tag is empty the current directory is searched.
+
+INPUT                  = @CMAKE_SOURCE_DIR@/doc/mainpage.html \
+                         @CMAKE_SOURCE_DIR@/include/ignition/math
+
+# This tag can be used to specify the character encoding of the source files
+# that doxygen parses. Internally doxygen uses the UTF-8 encoding. Doxygen uses
+# libiconv (or the iconv built into libc) for the transcoding. See the libiconv
+# documentation (see: http://www.gnu.org/software/libiconv) for the list of
+# possible encodings.
+# The default value is: UTF-8.
+
+INPUT_ENCODING         = UTF-8
+
+# If the value of the INPUT tag contains directories, you can use the
+# FILE_PATTERNS tag to specify one or more wildcard patterns (like *.cpp and
+# *.h) to filter out the source-files in the directories. If left blank the
+# following patterns are tested:*.c, *.cc, *.cxx, *.cpp, *.c++, *.java, *.ii,
+# *.ixx, *.ipp, *.i++, *.inl, *.idl, *.ddl, *.odl, *.h, *.hh, *.hxx, *.hpp,
+# *.h++, *.cs, *.d, *.php, *.php4, *.php5, *.phtml, *.inc, *.m, *.markdown,
+# *.md, *.mm, *.dox, *.py, *.f90, *.f, *.for, *.tcl, *.vhd, *.vhdl, *.ucf,
+# *.qsf, *.as and *.js.
+
+FILE_PATTERNS          = *.hh \
+                         *.h
+
+# The RECURSIVE tag can be used to specify whether or not subdirectories should
+# be searched for input files as well.
+# The default value is: NO.
+
+RECURSIVE              = YES
+
+# The EXCLUDE tag can be used to specify files and/or directories that should be
+# excluded from the INPUT source files. This way you can easily exclude a
+# subdirectory from a directory tree whose root is specified with the INPUT tag.
+#
+# Note that relative paths are relative to the directory from which doxygen is
+# run.
+
+EXCLUDE                =
+
+# The EXCLUDE_SYMLINKS tag can be used to select whether or not files or
+# directories that are symbolic links (a Unix file system feature) are excluded
+# from the input.
+# The default value is: NO.
+
+EXCLUDE_SYMLINKS       = NO
+
+# If the value of the INPUT tag contains directories, you can use the
+# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude
+# certain files from those directories.
+#
+# Note that the wildcards are matched against the file with absolute path, so to
+# exclude all test directories for example use the pattern */test/*
+
+EXCLUDE_PATTERNS       =
+
+# The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names
+# (namespaces, classes, functions, etc.) that should be excluded from the
+# output. The symbol name can be a fully qualified name, a word, or if the
+# wildcard * is used, a substring. Examples: ANamespace, AClass,
+# AClass::ANamespace, ANamespace::*Test
+#
+# Note that the wildcards are matched against the file with absolute path, so to
+# exclude all test directories use the pattern */test/*
+
+EXCLUDE_SYMBOLS        =
+
+# The EXAMPLE_PATH tag can be used to specify one or more files or directories
+# that contain example code fragments that are included (see the \include
+# command).
+
+EXAMPLE_PATH           = examples
+
+# If the value of the EXAMPLE_PATH tag contains directories, you can use the
+# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp and
+# *.h) to filter out the source-files in the directories. If left blank all
+# files are included.
+
+EXAMPLE_PATTERNS       = *.cc \
+                         *.hh
+
+# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be
+# searched for input files to be used with the \include or \dontinclude commands
+# irrespective of the value of the RECURSIVE tag.
+# The default value is: NO.
+
+EXAMPLE_RECURSIVE      = YES
+
+# The IMAGE_PATH tag can be used to specify one or more files or directories
+# that contain images that are to be included in the documentation (see the
+# \image command).
+
+IMAGE_PATH             =
+
+# The INPUT_FILTER tag can be used to specify a program that doxygen should
+# invoke to filter for each input file. Doxygen will invoke the filter program
+# by executing (via popen()) the command:
+#
+# <filter> <input-file>
+#
+# where <filter> is the value of the INPUT_FILTER tag, and <input-file> is the
+# name of an input file. Doxygen will then use the output that the filter
+# program writes to standard output. If FILTER_PATTERNS is specified, this tag
+# will be ignored.
+#
+# Note that the filter must not add or remove lines; it is applied before the
+# code is scanned, but not when the output code is generated. If lines are added
+# or removed, the anchors will not be placed correctly.
+
+INPUT_FILTER           =
+
+# The FILTER_PATTERNS tag can be used to specify filters on a per file pattern
+# basis. Doxygen will compare the file name with each pattern and apply the
+# filter if there is a match. The filters are a list of the form: pattern=filter
+# (like *.cpp=my_cpp_filter). See INPUT_FILTER for further information on how
+# filters are used. If the FILTER_PATTERNS tag is empty or if none of the
+# patterns match the file name, INPUT_FILTER is applied.
+
+FILTER_PATTERNS        =
+
+# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using
+# INPUT_FILTER ) will also be used to filter the input files that are used for
+# producing the source files to browse (i.e. when SOURCE_BROWSER is set to YES).
+# The default value is: NO.
+
+FILTER_SOURCE_FILES    = NO
+
+# The FILTER_SOURCE_PATTERNS tag can be used to specify source filters per file
+# pattern. A pattern will override the setting for FILTER_PATTERN (if any) and
+# it is also possible to disable source filtering for a specific pattern using
+# *.ext= (so without naming a filter).
+# This tag requires that the tag FILTER_SOURCE_FILES is set to YES.
+
+FILTER_SOURCE_PATTERNS =
+
+# If the USE_MDFILE_AS_MAINPAGE tag refers to the name of a markdown file that
+# is part of the input, its contents will be placed on the main page
+# (index.html). This can be useful if you have a project on for instance GitHub
+# and want to reuse the introduction page also for the doxygen output.
+
+USE_MDFILE_AS_MAINPAGE =
+
+#---------------------------------------------------------------------------
+# Configuration options related to source browsing
+#---------------------------------------------------------------------------
+
+# If the SOURCE_BROWSER tag is set to YES then a list of source files will be
+# generated. Documented entities will be cross-referenced with these sources.
+#
+# Note: To get rid of all source code in the generated output, make sure that
+# also VERBATIM_HEADERS is set to NO.
+# The default value is: NO.
+
+SOURCE_BROWSER         = NO
+
+# Setting the INLINE_SOURCES tag to YES will include the body of functions,
+# classes and enums directly into the documentation.
+# The default value is: NO.
+
+INLINE_SOURCES         = NO
+
+# Setting the STRIP_CODE_COMMENTS tag to YES will instruct doxygen to hide any
+# special comment blocks from generated source code fragments. Normal C, C++ and
+# Fortran comments will always remain visible.
+# The default value is: YES.
+
+STRIP_CODE_COMMENTS    = YES
+
+# If the REFERENCED_BY_RELATION tag is set to YES then for each documented
+# function all documented functions referencing it will be listed.
+# The default value is: NO.
+
+REFERENCED_BY_RELATION = YES
+
+# If the REFERENCES_RELATION tag is set to YES then for each documented function
+# all documented entities called/used by that function will be listed.
+# The default value is: NO.
+
+REFERENCES_RELATION    = YES
+
+# If the REFERENCES_LINK_SOURCE tag is set to YES and SOURCE_BROWSER tag is set
+# to YES, then the hyperlinks from functions in REFERENCES_RELATION and
+# REFERENCED_BY_RELATION lists will link to the source code. Otherwise they will
+# link to the documentation.
+# The default value is: YES.
+
+REFERENCES_LINK_SOURCE = YES
+
+# If SOURCE_TOOLTIPS is enabled (the default) then hovering a hyperlink in the
+# source code will show a tooltip with additional information such as prototype,
+# brief description and links to the definition and documentation. Since this
+# will make the HTML file larger and loading of large files a bit slower, you
+# can opt to disable this feature.
+# The default value is: YES.
+# This tag requires that the tag SOURCE_BROWSER is set to YES.
+
+SOURCE_TOOLTIPS        = YES
+
+# If the USE_HTAGS tag is set to YES then the references to source code will
+# point to the HTML generated by the htags(1) tool instead of doxygen built-in
+# source browser. The htags tool is part of GNU's global source tagging system
+# (see http://www.gnu.org/software/global/global.html). You will need version
+# 4.8.6 or higher.
+#
+# To use it do the following:
+# - Install the latest version of global
+# - Enable SOURCE_BROWSER and USE_HTAGS in the config file
+# - Make sure the INPUT points to the root of the source tree
+# - Run doxygen as normal
+#
+# Doxygen will invoke htags (and that will in turn invoke gtags), so these
+# tools must be available from the command line (i.e. in the search path).
+#
+# The result: instead of the source browser generated by doxygen, the links to
+# source code will now point to the output of htags.
+# The default value is: NO.
+# This tag requires that the tag SOURCE_BROWSER is set to YES.
+
+USE_HTAGS              = NO
+
+# If the VERBATIM_HEADERS tag is set the YES then doxygen will generate a
+# verbatim copy of the header file for each class for which an include is
+# specified. Set to NO to disable this.
+# See also: Section \class.
+# The default value is: YES.
+
+VERBATIM_HEADERS       = YES
+
+#---------------------------------------------------------------------------
+# Configuration options related to the alphabetical class index
+#---------------------------------------------------------------------------
+
+# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index of all
+# compounds will be generated. Enable this if the project contains a lot of
+# classes, structs, unions or interfaces.
+# The default value is: YES.
+
+ALPHABETICAL_INDEX     = YES
+
+# The COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns in
+# which the alphabetical index list will be split.
+# Minimum value: 1, maximum value: 20, default value: 5.
+# This tag requires that the tag ALPHABETICAL_INDEX is set to YES.
+
+COLS_IN_ALPHA_INDEX    = 3
+
+# In case all classes in a project start with a common prefix, all classes will
+# be put under the same header in the alphabetical index. The IGNORE_PREFIX tag
+# can be used to specify a prefix (or a list of prefixes) that should be ignored
+# while generating the index headers.
+# This tag requires that the tag ALPHABETICAL_INDEX is set to YES.
+
+IGNORE_PREFIX          =
+
+#---------------------------------------------------------------------------
+# Configuration options related to the HTML output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_HTML tag is set to YES doxygen will generate HTML output
+# The default value is: YES.
+
+GENERATE_HTML          = YES
+
+# The HTML_OUTPUT tag is used to specify where the HTML docs will be put. If a
+# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of
+# it.
+# The default directory is: html.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_OUTPUT            = html
+
+# The HTML_FILE_EXTENSION tag can be used to specify the file extension for each
+# generated HTML page (for example: .htm, .php, .asp).
+# The default value is: .html.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_FILE_EXTENSION    = .html
+
+# The HTML_HEADER tag can be used to specify a user-defined HTML header file for
+# each generated HTML page. If the tag is left blank doxygen will generate a
+# standard header.
+#
+# To get valid HTML the header file that includes any scripts and style sheets
+# that doxygen needs, which is dependent on the configuration options used (e.g.
+# the setting GENERATE_TREEVIEW). It is highly recommended to start with a
+# default header using
+# doxygen -w html new_header.html new_footer.html new_stylesheet.css
+# YourConfigFile
+# and then modify the file new_header.html. See also section "Doxygen usage"
+# for information on how to generate the default header that doxygen normally
+# uses.
+# Note: The header is subject to change so you typically have to regenerate the
+# default header when upgrading to a newer version of doxygen. For a description
+# of the possible markers and block names see the documentation.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_HEADER            = "@CMAKE_SOURCE_DIR@/doc/header.html"
+
+# The HTML_FOOTER tag can be used to specify a user-defined HTML footer for each
+# generated HTML page. If the tag is left blank doxygen will generate a standard
+# footer. See HTML_HEADER for more information on how to generate a default
+# footer and what special commands can be used inside the footer. See also
+# section "Doxygen usage" for information on how to generate the default footer
+# that doxygen normally uses.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_FOOTER            = "@CMAKE_SOURCE_DIR@/doc/footer.html"
+
+# The HTML_STYLESHEET tag can be used to specify a user-defined cascading style
+# sheet that is used by each HTML page. It can be used to fine-tune the look of
+# the HTML output. If left blank doxygen will generate a default style sheet.
+# See also section "Doxygen usage" for information on how to generate the style
+# sheet that doxygen normally uses.
+# Note: It is recommended to use HTML_EXTRA_STYLESHEET instead of this tag, as
+# it is more robust and this tag (HTML_STYLESHEET) will in the future become
+# obsolete.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_STYLESHEET        =
+
+# The HTML_EXTRA_STYLESHEET tag can be used to specify an additional user-
+# defined cascading style sheet that is included after the standard style sheets
+# created by doxygen. Using this option one can overrule certain style aspects.
+# This is preferred over using HTML_STYLESHEET since it does not replace the
+# standard style sheet and is therefor more robust against future updates.
+# Doxygen will copy the style sheet file to the output directory. For an example
+# see the documentation.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_EXTRA_STYLESHEET  = "@CMAKE_SOURCE_DIR@/doc/style.css"
+
+# The HTML_EXTRA_FILES tag can be used to specify one or more extra images or
+# other source files which should be copied to the HTML output directory. Note
+# that these files will be copied to the base HTML output directory. Use the
+# $relpath^ marker in the HTML_HEADER and/or HTML_FOOTER files to load these
+# files. In the HTML_STYLESHEET file, use the file name only. Also note that the
+# files will be copied as-is; there are no commands or markers available.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_EXTRA_FILES       =
+
+# The HTML_COLORSTYLE_HUE tag controls the color of the HTML output. Doxygen
+# will adjust the colors in the stylesheet and background images according to
+# this color. Hue is specified as an angle on a colorwheel, see
+# http://en.wikipedia.org/wiki/Hue for more information. For instance the value
+# 0 represents red, 60 is yellow, 120 is green, 180 is cyan, 240 is blue, 300
+# purple, and 360 is red again.
+# Minimum value: 0, maximum value: 359, default value: 220.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_COLORSTYLE_HUE    = 13
+
+# The HTML_COLORSTYLE_SAT tag controls the purity (or saturation) of the colors
+# in the HTML output. For a value of 0 the output will use grayscales only. A
+# value of 255 will produce the most vivid colors.
+# Minimum value: 0, maximum value: 255, default value: 100.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_COLORSTYLE_SAT    = 76
+
+# The HTML_COLORSTYLE_GAMMA tag controls the gamma correction applied to the
+# luminance component of the colors in the HTML output. Values below 100
+# gradually make the output lighter, whereas values above 100 make the output
+# darker. The value divided by 100 is the actual gamma applied, so 80 represents
+# a gamma of 0.8, The value 220 represents a gamma of 2.2, and 100 does not
+# change the gamma.
+# Minimum value: 40, maximum value: 240, default value: 80.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_COLORSTYLE_GAMMA  = 80
+
+# If the HTML_TIMESTAMP tag is set to YES then the footer of each generated HTML
+# page will contain the date and time when the page was generated. Setting this
+# to NO can help when comparing the output of multiple runs.
+# The default value is: YES.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_TIMESTAMP         = YES
+
+# If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML
+# documentation will contain sections that can be hidden and shown after the
+# page has loaded.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_DYNAMIC_SECTIONS  = NO
+
+# With HTML_INDEX_NUM_ENTRIES one can control the preferred number of entries
+# shown in the various tree structured indices initially; the user can expand
+# and collapse entries dynamically later on. Doxygen will expand the tree to
+# such a level that at most the specified number of entries are visible (unless
+# a fully collapsed tree already exceeds this amount). So setting the number of
+# entries 1 will produce a full collapsed tree by default. 0 is a special value
+# representing an infinite number of entries and will result in a full expanded
+# tree by default.
+# Minimum value: 0, maximum value: 9999, default value: 100.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_INDEX_NUM_ENTRIES = 100
+
+# If the GENERATE_DOCSET tag is set to YES, additional index files will be
+# generated that can be used as input for Apple's Xcode 3 integrated development
+# environment (see: http://developer.apple.com/tools/xcode/), introduced with
+# OSX 10.5 (Leopard). To create a documentation set, doxygen will generate a
+# Makefile in the HTML output directory. Running make will produce the docset in
+# that directory and running make install will install the docset in
+# ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find it at
+# startup. See http://developer.apple.com/tools/creatingdocsetswithdoxygen.html
+# for more information.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+GENERATE_DOCSET        = NO
+
+# This tag determines the name of the docset feed. A documentation feed provides
+# an umbrella under which multiple documentation sets from a single provider
+# (such as a company or product suite) can be grouped.
+# The default value is: Doxygen generated docs.
+# This tag requires that the tag GENERATE_DOCSET is set to YES.
+
+DOCSET_FEEDNAME        = "Gazebo API Documentation"
+
+# This tag specifies a string that should uniquely identify the documentation
+# set bundle. This should be a reverse domain-name style string, e.g.
+# com.mycompany.MyDocSet. Doxygen will append .docset to the name.
+# The default value is: org.doxygen.Project.
+# This tag requires that the tag GENERATE_DOCSET is set to YES.
+
+DOCSET_BUNDLE_ID       = org.doxygen.Project
+
+# The DOCSET_PUBLISHER_ID tag specifies a string that should uniquely identify
+# the documentation publisher. This should be a reverse domain-name style
+# string, e.g. com.mycompany.MyDocSet.documentation.
+# The default value is: org.doxygen.Publisher.
+# This tag requires that the tag GENERATE_DOCSET is set to YES.
+
+DOCSET_PUBLISHER_ID    = org.doxygen.Publisher
+
+# The DOCSET_PUBLISHER_NAME tag identifies the documentation publisher.
+# The default value is: Publisher.
+# This tag requires that the tag GENERATE_DOCSET is set to YES.
+
+DOCSET_PUBLISHER_NAME  = Publisher
+
+# If the GENERATE_HTMLHELP tag is set to YES then doxygen generates three
+# additional HTML index files: index.hhp, index.hhc, and index.hhk. The
+# index.hhp is a project file that can be read by Microsoft's HTML Help Workshop
+# (see: http://www.microsoft.com/en-us/download/details.aspx?id=21138) on
+# Windows.
+#
+# The HTML Help Workshop contains a compiler that can convert all HTML output
+# generated by doxygen into a single compiled HTML file (.chm). Compiled HTML
+# files are now used as the Windows 98 help format, and will replace the old
+# Windows help format (.hlp) on all Windows platforms in the future. Compressed
+# HTML files also contain an index, a table of contents, and you can search for
+# words in the documentation. The HTML workshop also contains a viewer for
+# compressed HTML files.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+GENERATE_HTMLHELP      = NO
+
+# The CHM_FILE tag can be used to specify the file name of the resulting .chm
+# file. You can add a path in front of the file if the result should not be
+# written to the html output directory.
+# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
+
+CHM_FILE               =
+
+# The HHC_LOCATION tag can be used to specify the location (absolute path
+# including file name) of the HTML help compiler ( hhc.exe). If non-empty
+# doxygen will try to run the HTML help compiler on the generated index.hhp.
+# The file has to be specified with full path.
+# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
+
+HHC_LOCATION           =
+
+# The GENERATE_CHI flag controls if a separate .chi index file is generated (
+# YES) or that it should be included in the master .chm file ( NO).
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
+
+GENERATE_CHI           = NO
+
+# The CHM_INDEX_ENCODING is used to encode HtmlHelp index ( hhk), content ( hhc)
+# and project file content.
+# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
+
+CHM_INDEX_ENCODING     =
+
+# The BINARY_TOC flag controls whether a binary table of contents is generated (
+# YES) or a normal table of contents ( NO) in the .chm file.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
+
+BINARY_TOC             = NO
+
+# The TOC_EXPAND flag can be set to YES to add extra items for group members to
+# the table of contents of the HTML help documentation and to the tree view.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
+
+TOC_EXPAND             = NO
+
+# If the GENERATE_QHP tag is set to YES and both QHP_NAMESPACE and
+# QHP_VIRTUAL_FOLDER are set, an additional index file will be generated that
+# can be used as input for Qt's qhelpgenerator to generate a Qt Compressed Help
+# (.qch) of the generated HTML documentation.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+GENERATE_QHP           = NO
+
+# If the QHG_LOCATION tag is specified, the QCH_FILE tag can be used to specify
+# the file name of the resulting .qch file. The path specified is relative to
+# the HTML output folder.
+# This tag requires that the tag GENERATE_QHP is set to YES.
+
+QCH_FILE               =
+
+# The QHP_NAMESPACE tag specifies the namespace to use when generating Qt Help
+# Project output. For more information please see Qt Help Project / Namespace
+# (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#namespace).
+# The default value is: org.doxygen.Project.
+# This tag requires that the tag GENERATE_QHP is set to YES.
+
+QHP_NAMESPACE          = org.doxygen.Project
+
+# The QHP_VIRTUAL_FOLDER tag specifies the namespace to use when generating Qt
+# Help Project output. For more information please see Qt Help Project / Virtual
+# Folders (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#virtual-
+# folders).
+# The default value is: doc.
+# This tag requires that the tag GENERATE_QHP is set to YES.
+
+QHP_VIRTUAL_FOLDER     = doc
+
+# If the QHP_CUST_FILTER_NAME tag is set, it specifies the name of a custom
+# filter to add. For more information please see Qt Help Project / Custom
+# Filters (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#custom-
+# filters).
+# This tag requires that the tag GENERATE_QHP is set to YES.
+
+QHP_CUST_FILTER_NAME   =
+
+# The QHP_CUST_FILTER_ATTRS tag specifies the list of the attributes of the
+# custom filter to add. For more information please see Qt Help Project / Custom
+# Filters (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#custom-
+# filters).
+# This tag requires that the tag GENERATE_QHP is set to YES.
+
+QHP_CUST_FILTER_ATTRS  =
+
+# The QHP_SECT_FILTER_ATTRS tag specifies the list of the attributes this
+# project's filter section matches. Qt Help Project / Filter Attributes (see:
+# http://qt-project.org/doc/qt-4.8/qthelpproject.html#filter-attributes).
+# This tag requires that the tag GENERATE_QHP is set to YES.
+
+QHP_SECT_FILTER_ATTRS  =
+
+# The QHG_LOCATION tag can be used to specify the location of Qt's
+# qhelpgenerator. If non-empty doxygen will try to run qhelpgenerator on the
+# generated .qhp file.
+# This tag requires that the tag GENERATE_QHP is set to YES.
+
+QHG_LOCATION           =
+
+# If the GENERATE_ECLIPSEHELP tag is set to YES, additional index files will be
+# generated, together with the HTML files, they form an Eclipse help plugin. To
+# install this plugin and make it available under the help contents menu in
+# Eclipse, the contents of the directory containing the HTML and XML files needs
+# to be copied into the plugins directory of eclipse. The name of the directory
+# within the plugins directory should be the same as the ECLIPSE_DOC_ID value.
+# After copying Eclipse needs to be restarted before the help appears.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+GENERATE_ECLIPSEHELP   = NO
+
+# A unique identifier for the Eclipse help plugin. When installing the plugin
+# the directory name containing the HTML and XML files should also have this
+# name. Each documentation set should have its own identifier.
+# The default value is: org.doxygen.Project.
+# This tag requires that the tag GENERATE_ECLIPSEHELP is set to YES.
+
+ECLIPSE_DOC_ID         = org.doxygen.Project
+
+# If you want full control over the layout of the generated HTML pages it might
+# be necessary to disable the index and replace it with your own. The
+# DISABLE_INDEX tag can be used to turn on/off the condensed index (tabs) at top
+# of each HTML page. A value of NO enables the index and the value YES disables
+# it. Since the tabs in the index contain the same information as the navigation
+# tree, you can set this option to YES if you also set GENERATE_TREEVIEW to YES.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+DISABLE_INDEX          = YES
+
+# The GENERATE_TREEVIEW tag is used to specify whether a tree-like index
+# structure should be generated to display hierarchical information. If the tag
+# value is set to YES, a side panel will be generated containing a tree-like
+# index structure (just like the one that is generated for HTML Help). For this
+# to work a browser that supports JavaScript, DHTML, CSS and frames is required
+# (i.e. any modern browser). Windows users are probably better off using the
+# HTML help feature. Via custom stylesheets (see HTML_EXTRA_STYLESHEET) one can
+# further fine-tune the look of the index. As an example, the default style
+# sheet generated by doxygen has an example that shows how to put an image at
+# the root of the tree instead of the PROJECT_NAME. Since the tree basically has
+# the same information as the tab index, you could consider setting
+# DISABLE_INDEX to YES when enabling this option.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+GENERATE_TREEVIEW      = NO
+
+# The ENUM_VALUES_PER_LINE tag can be used to set the number of enum values that
+# doxygen will group on one line in the generated HTML documentation.
+#
+# Note that a value of 0 will completely suppress the enum values from appearing
+# in the overview section.
+# Minimum value: 0, maximum value: 20, default value: 4.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+ENUM_VALUES_PER_LINE   = 4
+
+# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be used
+# to set the initial width (in pixels) of the frame in which the tree is shown.
+# Minimum value: 0, maximum value: 1500, default value: 250.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+TREEVIEW_WIDTH         = 250
+
+# When the EXT_LINKS_IN_WINDOW option is set to YES doxygen will open links to
+# external symbols imported via tag files in a separate window.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+EXT_LINKS_IN_WINDOW    = NO
+
+# Use this tag to change the font size of LaTeX formulas included as images in
+# the HTML documentation. When you change the font size after a successful
+# doxygen run you need to manually remove any form_*.png images from the HTML
+# output directory to force them to be regenerated.
+# Minimum value: 8, maximum value: 50, default value: 10.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+FORMULA_FONTSIZE       = 10
+
+# Use the FORMULA_TRANPARENT tag to determine whether or not the images
+# generated for formulas are transparent PNGs. Transparent PNGs are not
+# supported properly for IE 6.0, but are supported on all modern browsers.
+#
+# Note that when changing this option you need to delete any form_*.png files in
+# the HTML output directory before the changes have effect.
+# The default value is: YES.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+FORMULA_TRANSPARENT    = YES
+
+# Enable the USE_MATHJAX option to render LaTeX formulas using MathJax (see
+# http://www.mathjax.org) which uses client side Javascript for the rendering
+# instead of using prerendered bitmaps. Use this if you do not have LaTeX
+# installed or if you want to formulas look prettier in the HTML output. When
+# enabled you may also need to install MathJax separately and configure the path
+# to it using the MATHJAX_RELPATH option.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+USE_MATHJAX            = NO
+
+# When MathJax is enabled you can set the default output format to be used for
+# the MathJax output. See the MathJax site (see:
+# http://docs.mathjax.org/en/latest/output.html) for more details.
+# Possible values are: HTML-CSS (which is slower, but has the best
+# compatibility), NativeMML (i.e. MathML) and SVG.
+# The default value is: HTML-CSS.
+# This tag requires that the tag USE_MATHJAX is set to YES.
+
+MATHJAX_FORMAT         = HTML-CSS
+
+# When MathJax is enabled you need to specify the location relative to the HTML
+# output directory using the MATHJAX_RELPATH option. The destination directory
+# should contain the MathJax.js script. For instance, if the mathjax directory
+# is located at the same level as the HTML output directory, then
+# MATHJAX_RELPATH should be ../mathjax. The default value points to the MathJax
+# Content Delivery Network so you can quickly see the result without installing
+# MathJax. However, it is strongly recommended to install a local copy of
+# MathJax from http://www.mathjax.org before deployment.
+# The default value is: http://cdn.mathjax.org/mathjax/latest.
+# This tag requires that the tag USE_MATHJAX is set to YES.
+
+MATHJAX_RELPATH        = http://cdn.mathjax.org/mathjax/latest
+
+# The MATHJAX_EXTENSIONS tag can be used to specify one or more MathJax
+# extension names that should be enabled during MathJax rendering. For example
+# MATHJAX_EXTENSIONS = TeX/AMSmath TeX/AMSsymbols
+# This tag requires that the tag USE_MATHJAX is set to YES.
+
+MATHJAX_EXTENSIONS     =
+
+# The MATHJAX_CODEFILE tag can be used to specify a file with javascript pieces
+# of code that will be used on startup of the MathJax code. See the MathJax site
+# (see: http://docs.mathjax.org/en/latest/output.html) for more details. For an
+# example see the documentation.
+# This tag requires that the tag USE_MATHJAX is set to YES.
+
+MATHJAX_CODEFILE       =
+
+# When the SEARCHENGINE tag is enabled doxygen will generate a search box for
+# the HTML output. The underlying search engine uses javascript and DHTML and
+# should work on any modern browser. Note that when using HTML help
+# (GENERATE_HTMLHELP), Qt help (GENERATE_QHP), or docsets (GENERATE_DOCSET)
+# there is already a search function so this one should typically be disabled.
+# For large projects the javascript based search engine can be slow, then
+# enabling SERVER_BASED_SEARCH may provide a better solution. It is possible to
+# search using the keyboard; to jump to the search box use <access key> + S
+# (what the <access key> is depends on the OS and browser, but it is typically
+# <CTRL>, <ALT>/<option>, or both). Inside the search box use the <cursor down
+# key> to jump into the search results window, the results can be navigated
+# using the <cursor keys>. Press <Enter> to select an item or <escape> to cancel
+# the search. The filter options can be selected when the cursor is inside the
+# search box by pressing <Shift>+<cursor down>. Also here use the <cursor keys>
+# to select a filter and <Enter> or <escape> to activate or cancel the filter
+# option.
+# The default value is: YES.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+SEARCHENGINE           = YES
+
+# When the SERVER_BASED_SEARCH tag is enabled the search engine will be
+# implemented using a web server instead of a web client using Javascript. There
+# are two flavours of web server based searching depending on the
+# EXTERNAL_SEARCH setting. When disabled, doxygen will generate a PHP script for
+# searching and an index file used by the script. When EXTERNAL_SEARCH is
+# enabled the indexing and searching needs to be provided by external tools. See
+# the section "External Indexing and Searching" for details.
+# The default value is: NO.
+# This tag requires that the tag SEARCHENGINE is set to YES.
+
+SERVER_BASED_SEARCH    = NO
+
+# When EXTERNAL_SEARCH tag is enabled doxygen will no longer generate the PHP
+# script for searching. Instead the search results are written to an XML file
+# which needs to be processed by an external indexer. Doxygen will invoke an
+# external search engine pointed to by the SEARCHENGINE_URL option to obtain the
+# search results.
+#
+# Doxygen ships with an example indexer ( doxyindexer) and search engine
+# (doxysearch.cgi) which are based on the open source search engine library
+# Xapian (see: http://xapian.org/).
+#
+# See the section "External Indexing and Searching" for details.
+# The default value is: NO.
+# This tag requires that the tag SEARCHENGINE is set to YES.
+
+EXTERNAL_SEARCH        = NO
+
+# The SEARCHENGINE_URL should point to a search engine hosted by a web server
+# which will return the search results when EXTERNAL_SEARCH is enabled.
+#
+# Doxygen ships with an example indexer ( doxyindexer) and search engine
+# (doxysearch.cgi) which are based on the open source search engine library
+# Xapian (see: http://xapian.org/). See the section "External Indexing and
+# Searching" for details.
+# This tag requires that the tag SEARCHENGINE is set to YES.
+
+SEARCHENGINE_URL       =
+
+# When SERVER_BASED_SEARCH and EXTERNAL_SEARCH are both enabled the unindexed
+# search data is written to a file for indexing by an external tool. With the
+# SEARCHDATA_FILE tag the name of this file can be specified.
+# The default file is: searchdata.xml.
+# This tag requires that the tag SEARCHENGINE is set to YES.
+
+SEARCHDATA_FILE        = searchdata.xml
+
+# When SERVER_BASED_SEARCH and EXTERNAL_SEARCH are both enabled the
+# EXTERNAL_SEARCH_ID tag can be used as an identifier for the project. This is
+# useful in combination with EXTRA_SEARCH_MAPPINGS to search through multiple
+# projects and redirect the results back to the right project.
+# This tag requires that the tag SEARCHENGINE is set to YES.
+
+EXTERNAL_SEARCH_ID     =
+
+# The EXTRA_SEARCH_MAPPINGS tag can be used to enable searching through doxygen
+# projects other than the one defined by this configuration file, but that are
+# all added to the same external search index. Each project needs to have a
+# unique id set via EXTERNAL_SEARCH_ID. The search mapping then maps the id of
+# to a relative location where the documentation can be found. The format is:
+# EXTRA_SEARCH_MAPPINGS = tagname1=loc1 tagname2=loc2 ...
+# This tag requires that the tag SEARCHENGINE is set to YES.
+
+EXTRA_SEARCH_MAPPINGS  =
+
+#---------------------------------------------------------------------------
+# Configuration options related to the LaTeX output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_LATEX tag is set to YES doxygen will generate LaTeX output.
+# The default value is: YES.
+
+GENERATE_LATEX         = NO
+
+# The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put. If a
+# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of
+# it.
+# The default directory is: latex.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_OUTPUT           = latex
+
+# The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be
+# invoked.
+#
+# Note that when enabling USE_PDFLATEX this option is only used for generating
+# bitmaps for formulas in the HTML output, but not in the Makefile that is
+# written to the output directory.
+# The default file is: latex.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_CMD_NAME         = latex
+
+# The MAKEINDEX_CMD_NAME tag can be used to specify the command name to generate
+# index for LaTeX.
+# The default file is: makeindex.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+MAKEINDEX_CMD_NAME     = makeindex
+
+# If the COMPACT_LATEX tag is set to YES doxygen generates more compact LaTeX
+# documents. This may be useful for small projects and may help to save some
+# trees in general.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+COMPACT_LATEX          = NO
+
+# The PAPER_TYPE tag can be used to set the paper type that is used by the
+# printer.
+# Possible values are: a4 (210 x 297 mm), letter (8.5 x 11 inches), legal (8.5 x
+# 14 inches) and executive (7.25 x 10.5 inches).
+# The default value is: a4.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+PAPER_TYPE             = letter
+
+# The EXTRA_PACKAGES tag can be used to specify one or more LaTeX package names
+# that should be included in the LaTeX output. To get the times font for
+# instance you can specify
+# EXTRA_PACKAGES=times
+# If left blank no extra packages will be included.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+EXTRA_PACKAGES         =
+
+# The LATEX_HEADER tag can be used to specify a personal LaTeX header for the
+# generated LaTeX document. The header should contain everything until the first
+# chapter. If it is left blank doxygen will generate a standard header. See
+# section "Doxygen usage" for information on how to let doxygen write the
+# default header to a separate file.
+#
+# Note: Only use a user-defined header if you know what you are doing! The
+# following commands have a special meaning inside the header: $title,
+# $datetime, $date, $doxygenversion, $projectname, $projectnumber. Doxygen will
+# replace them by respectively the title of the page, the current date and time,
+# only the current date, the version number of doxygen, the project name (see
+# PROJECT_NAME), or the project number (see PROJECT_NUMBER).
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_HEADER           =
+
+# The LATEX_FOOTER tag can be used to specify a personal LaTeX footer for the
+# generated LaTeX document. The footer should contain everything after the last
+# chapter. If it is left blank doxygen will generate a standard footer.
+#
+# Note: Only use a user-defined footer if you know what you are doing!
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_FOOTER           =
+
+# The LATEX_EXTRA_FILES tag can be used to specify one or more extra images or
+# other source files which should be copied to the LATEX_OUTPUT output
+# directory. Note that the files will be copied as-is; there are no commands or
+# markers available.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_EXTRA_FILES      =
+
+# If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated is
+# prepared for conversion to PDF (using ps2pdf or pdflatex). The PDF file will
+# contain links (just like the HTML output) instead of page references. This
+# makes the output suitable for online browsing using a PDF viewer.
+# The default value is: YES.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+PDF_HYPERLINKS         = NO
+
+# If the LATEX_PDFLATEX tag is set to YES, doxygen will use pdflatex to generate
+# the PDF file directly from the LaTeX files. Set this option to YES to get a
+# higher quality PDF documentation.
+# The default value is: YES.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+USE_PDFLATEX           = YES
+
+# If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \batchmode
+# command to the generated LaTeX files. This will instruct LaTeX to keep running
+# if errors occur, instead of asking the user for help. This option is also used
+# when generating formulas in HTML.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_BATCHMODE        = NO
+
+# If the LATEX_HIDE_INDICES tag is set to YES then doxygen will not include the
+# index chapters (such as File Index, Compound Index, etc.) in the output.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_HIDE_INDICES     = NO
+
+# If the LATEX_SOURCE_CODE tag is set to YES then doxygen will include source
+# code with syntax highlighting in the LaTeX output.
+#
+# Note that which sources are shown also depends on other settings such as
+# SOURCE_BROWSER.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_SOURCE_CODE      = NO
+
+# The LATEX_BIB_STYLE tag can be used to specify the style to use for the
+# bibliography, e.g. plainnat, or ieeetr. See
+# http://en.wikipedia.org/wiki/BibTeX and \cite for more info.
+# The default value is: plain.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_BIB_STYLE        = plain
+
+#---------------------------------------------------------------------------
+# Configuration options related to the RTF output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_RTF tag is set to YES doxygen will generate RTF output. The
+# RTF output is optimized for Word 97 and may not look too pretty with other RTF
+# readers/editors.
+# The default value is: NO.
+
+GENERATE_RTF           = NO
+
+# The RTF_OUTPUT tag is used to specify where the RTF docs will be put. If a
+# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of
+# it.
+# The default directory is: rtf.
+# This tag requires that the tag GENERATE_RTF is set to YES.
+
+RTF_OUTPUT             = rtf
+
+# If the COMPACT_RTF tag is set to YES doxygen generates more compact RTF
+# documents. This may be useful for small projects and may help to save some
+# trees in general.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_RTF is set to YES.
+
+COMPACT_RTF            = NO
+
+# If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated will
+# contain hyperlink fields. The RTF file will contain links (just like the HTML
+# output) instead of page references. This makes the output suitable for online
+# browsing using Word or some other Word compatible readers that support those
+# fields.
+#
+# Note: WordPad (write) and others do not support links.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_RTF is set to YES.
+
+RTF_HYPERLINKS         = NO
+
+# Load stylesheet definitions from file. Syntax is similar to doxygen's config
+# file, i.e. a series of assignments. You only have to provide replacements,
+# missing definitions are set to their default value.
+#
+# See also section "Doxygen usage" for information on how to generate the
+# default style sheet that doxygen normally uses.
+# This tag requires that the tag GENERATE_RTF is set to YES.
+
+RTF_STYLESHEET_FILE    =
+
+# Set optional variables used in the generation of an RTF document. Syntax is
+# similar to doxygen's config file. A template extensions file can be generated
+# using doxygen -e rtf extensionFile.
+# This tag requires that the tag GENERATE_RTF is set to YES.
+
+RTF_EXTENSIONS_FILE    =
+
+#---------------------------------------------------------------------------
+# Configuration options related to the man page output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_MAN tag is set to YES doxygen will generate man pages for
+# classes and files.
+# The default value is: NO.
+
+GENERATE_MAN           = NO
+
+# The MAN_OUTPUT tag is used to specify where the man pages will be put. If a
+# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of
+# it. A directory man3 will be created inside the directory specified by
+# MAN_OUTPUT.
+# The default directory is: man.
+# This tag requires that the tag GENERATE_MAN is set to YES.
+
+MAN_OUTPUT             = man
+
+# The MAN_EXTENSION tag determines the extension that is added to the generated
+# man pages. In case the manual section does not start with a number, the number
+# 3 is prepended. The dot (.) at the beginning of the MAN_EXTENSION tag is
+# optional.
+# The default value is: .3.
+# This tag requires that the tag GENERATE_MAN is set to YES.
+
+MAN_EXTENSION          = .3
+
+# If the MAN_LINKS tag is set to YES and doxygen generates man output, then it
+# will generate one additional man file for each entity documented in the real
+# man page(s). These additional files only source the real man page, but without
+# them the man command would be unable to find the correct page.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_MAN is set to YES.
+
+MAN_LINKS              = NO
+
+#---------------------------------------------------------------------------
+# Configuration options related to the XML output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_XML tag is set to YES doxygen will generate an XML file that
+# captures the structure of the code including all documentation.
+# The default value is: NO.
+
+GENERATE_XML           = NO
+
+# The XML_OUTPUT tag is used to specify where the XML pages will be put. If a
+# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of
+# it.
+# The default directory is: xml.
+# This tag requires that the tag GENERATE_XML is set to YES.
+
+XML_OUTPUT             = xml
+
+# The XML_SCHEMA tag can be used to specify a XML schema, which can be used by a
+# validating XML parser to check the syntax of the XML files.
+# This tag requires that the tag GENERATE_XML is set to YES.
+
+XML_SCHEMA             =
+
+# The XML_DTD tag can be used to specify a XML DTD, which can be used by a
+# validating XML parser to check the syntax of the XML files.
+# This tag requires that the tag GENERATE_XML is set to YES.
+
+XML_DTD                =
+
+# If the XML_PROGRAMLISTING tag is set to YES doxygen will dump the program
+# listings (including syntax highlighting and cross-referencing information) to
+# the XML output. Note that enabling this will significantly increase the size
+# of the XML output.
+# The default value is: YES.
+# This tag requires that the tag GENERATE_XML is set to YES.
+
+XML_PROGRAMLISTING     = YES
+
+#---------------------------------------------------------------------------
+# Configuration options related to the DOCBOOK output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_DOCBOOK tag is set to YES doxygen will generate Docbook files
+# that can be used to generate PDF.
+# The default value is: NO.
+
+GENERATE_DOCBOOK       = NO
+
+# The DOCBOOK_OUTPUT tag is used to specify where the Docbook pages will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be put in
+# front of it.
+# The default directory is: docbook.
+# This tag requires that the tag GENERATE_DOCBOOK is set to YES.
+
+DOCBOOK_OUTPUT         = docbook
+
+#---------------------------------------------------------------------------
+# Configuration options for the AutoGen Definitions output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_AUTOGEN_DEF tag is set to YES doxygen will generate an AutoGen
+# Definitions (see http://autogen.sf.net) file that captures the structure of
+# the code including all documentation. Note that this feature is still
+# experimental and incomplete at the moment.
+# The default value is: NO.
+
+GENERATE_AUTOGEN_DEF   = NO
+
+#---------------------------------------------------------------------------
+# Configuration options related to the Perl module output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_PERLMOD tag is set to YES doxygen will generate a Perl module
+# file that captures the structure of the code including all documentation.
+#
+# Note that this feature is still experimental and incomplete at the moment.
+# The default value is: NO.
+
+GENERATE_PERLMOD       = NO
+
+# If the PERLMOD_LATEX tag is set to YES doxygen will generate the necessary
+# Makefile rules, Perl scripts and LaTeX code to be able to generate PDF and DVI
+# output from the Perl module output.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_PERLMOD is set to YES.
+
+PERLMOD_LATEX          = NO
+
+# If the PERLMOD_PRETTY tag is set to YES the Perl module output will be nicely
+# formatted so it can be parsed by a human reader. This is useful if you want to
+# understand what is going on. On the other hand, if this tag is set to NO the
+# size of the Perl module output will be much smaller and Perl will parse it
+# just the same.
+# The default value is: YES.
+# This tag requires that the tag GENERATE_PERLMOD is set to YES.
+
+PERLMOD_PRETTY         = YES
+
+# The names of the make variables in the generated doxyrules.make file are
+# prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX. This is useful
+# so different doxyrules.make files included by the same Makefile don't
+# overwrite each other's variables.
+# This tag requires that the tag GENERATE_PERLMOD is set to YES.
+
+PERLMOD_MAKEVAR_PREFIX =
+
+#---------------------------------------------------------------------------
+# Configuration options related to the preprocessor
+#---------------------------------------------------------------------------
+
+# If the ENABLE_PREPROCESSING tag is set to YES doxygen will evaluate all
+# C-preprocessor directives found in the sources and include files.
+# The default value is: YES.
+
+ENABLE_PREPROCESSING   = YES
+
+# If the MACRO_EXPANSION tag is set to YES doxygen will expand all macro names
+# in the source code. If set to NO only conditional compilation will be
+# performed. Macro expansion can be done in a controlled way by setting
+# EXPAND_ONLY_PREDEF to YES.
+# The default value is: NO.
+# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
+
+MACRO_EXPANSION        = YES
+
+# If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES then
+# the macro expansion is limited to the macros specified with the PREDEFINED and
+# EXPAND_AS_DEFINED tags.
+# The default value is: NO.
+# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
+
+EXPAND_ONLY_PREDEF     = NO
+
+# If the SEARCH_INCLUDES tag is set to YES the includes files in the
+# INCLUDE_PATH will be searched if a #include is found.
+# The default value is: YES.
+# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
+
+SEARCH_INCLUDES        = YES
+
+# The INCLUDE_PATH tag can be used to specify one or more directories that
+# contain include files that are not input files but should be processed by the
+# preprocessor.
+# This tag requires that the tag SEARCH_INCLUDES is set to YES.
+
+INCLUDE_PATH           = .
+
+# You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard
+# patterns (like *.h and *.hpp) to filter out the header-files in the
+# directories. If left blank, the patterns specified with FILE_PATTERNS will be
+# used.
+# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
+
+INCLUDE_FILE_PATTERNS  =
+
+# The PREDEFINED tag can be used to specify one or more macro names that are
+# defined before the preprocessor is started (similar to the -D option of e.g.
+# gcc). The argument of the tag is a list of macros of the form: name or
+# name=definition (no spaces). If the definition and the "=" are omitted, "=1"
+# is assumed. To prevent a macro definition from being undefined via #undef or
+# recursively expanded use the := operator instead of the = operator.
+# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
+
+PREDEFINED             =
+
+# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then this
+# tag can be used to specify a list of macro names that should be expanded. The
+# macro definition that is found in the sources will be used. Use the PREDEFINED
+# tag if you want to use a different macro definition that overrules the
+# definition found in the source code.
+# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
+
+EXPAND_AS_DEFINED      =
+
+# If the SKIP_FUNCTION_MACROS tag is set to YES then doxygen's preprocessor will
+# remove all refrences to function-like macros that are alone on a line, have an
+# all uppercase name, and do not end with a semicolon. Such function macros are
+# typically used for boiler-plate code, and will confuse the parser if not
+# removed.
+# The default value is: YES.
+# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
+
+SKIP_FUNCTION_MACROS   = NO
+
+#---------------------------------------------------------------------------
+# Configuration options related to external references
+#---------------------------------------------------------------------------
+
+# The TAGFILES tag can be used to specify one or more tag files. For each tag
+# file the location of the external documentation should be added. The format of
+# a tag file without this location is as follows:
+# TAGFILES = file1 file2 ...
+# Adding location for the tag files is done as follows:
+# TAGFILES = file1=loc1 "file2 = loc2" ...
+# where loc1 and loc2 can be relative or absolute paths or URLs. See the
+# section "Linking to external documentation" for more information about the use
+# of tag files.
+# Note: Each tag file must have an unique name (where the name does NOT include
+# the path). If a tag file is not located in the directory in which doxygen is
+# run, you must also specify the path to the tagfile here.
+
+TAGFILES               =
+
+# When a file name is specified after GENERATE_TAGFILE, doxygen will create a
+# tag file that is based on the input files it reads. See section "Linking to
+# external documentation" for more information about the usage of tag files.
+
+GENERATE_TAGFILE       =
+
+# If the ALLEXTERNALS tag is set to YES all external class will be listed in the
+# class index. If set to NO only the inherited external classes will be listed.
+# The default value is: NO.
+
+ALLEXTERNALS           = NO
+
+# If the EXTERNAL_GROUPS tag is set to YES all external groups will be listed in
+# the modules index. If set to NO, only the current project's groups will be
+# listed.
+# The default value is: YES.
+
+EXTERNAL_GROUPS        = NO
+
+# If the EXTERNAL_PAGES tag is set to YES all external pages will be listed in
+# the related pages index. If set to NO, only the current project's pages will
+# be listed.
+# The default value is: YES.
+
+EXTERNAL_PAGES         = YES
+
+# The PERL_PATH should be the absolute path and name of the perl script
+# interpreter (i.e. the result of 'which perl').
+# The default file (with absolute path) is: /usr/bin/perl.
+
+PERL_PATH              = /usr/bin/perl
+
+#---------------------------------------------------------------------------
+# Configuration options related to the dot tool
+#---------------------------------------------------------------------------
+
+# If the CLASS_DIAGRAMS tag is set to YES doxygen will generate a class diagram
+# (in HTML and LaTeX) for classes with base or super classes. Setting the tag to
+# NO turns the diagrams off. Note that this option also works with HAVE_DOT
+# disabled, but it is recommended to install and use dot, since it yields more
+# powerful graphs.
+# The default value is: YES.
+
+CLASS_DIAGRAMS         = YES
+
+# You can define message sequence charts within doxygen comments using the \msc
+# command. Doxygen will then run the mscgen tool (see:
+# http://www.mcternan.me.uk/mscgen/)) to produce the chart and insert it in the
+# documentation. The MSCGEN_PATH tag allows you to specify the directory where
+# the mscgen tool resides. If left empty the tool is assumed to be found in the
+# default search path.
+
+MSCGEN_PATH            =
+
+# You can include diagrams made with dia in doxygen documentation. Doxygen will
+# then run dia to produce the diagram and insert it in the documentation. The
+# DIA_PATH tag allows you to specify the directory where the dia binary resides.
+# If left empty dia is assumed to be found in the default search path.
+
+DIA_PATH               =
+
+# If set to YES, the inheritance and collaboration graphs will hide inheritance
+# and usage relations if the target is undocumented or is not a class.
+# The default value is: YES.
+
+HIDE_UNDOC_RELATIONS   = YES
+
+# If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is
+# available from the path. This tool is part of Graphviz (see:
+# http://www.graphviz.org/), a graph visualization toolkit from AT&T and Lucent
+# Bell Labs. The other options in this section have no effect if this option is
+# set to NO
+# The default value is: NO.
+
+HAVE_DOT               = YES
+
+# The DOT_NUM_THREADS specifies the number of dot invocations doxygen is allowed
+# to run in parallel. When set to 0 doxygen will base this on the number of
+# processors available in the system. You can set it explicitly to a value
+# larger than 0 to get control over the balance between CPU load and processing
+# speed.
+# Minimum value: 0, maximum value: 32, default value: 0.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_NUM_THREADS        = 0
+
+# When you want a differently looking font n the dot files that doxygen
+# generates you can specify the font name using DOT_FONTNAME. You need to make
+# sure dot is able to find the font, which can be done by putting it in a
+# standard location or by setting the DOTFONTPATH environment variable or by
+# setting DOT_FONTPATH to the directory containing the font.
+# The default value is: Helvetica.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_FONTNAME           = FreeSans.ttf
+
+# The DOT_FONTSIZE tag can be used to set the size (in points) of the font of
+# dot graphs.
+# Minimum value: 4, maximum value: 24, default value: 10.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_FONTSIZE           = 10
+
+# By default doxygen will tell dot to use the default font as specified with
+# DOT_FONTNAME. If you specify a different font using DOT_FONTNAME you can set
+# the path where dot can find it using this tag.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_FONTPATH           =
+
+# If the CLASS_GRAPH tag is set to YES then doxygen will generate a graph for
+# each documented class showing the direct and indirect inheritance relations.
+# Setting this tag to YES will force the CLASS_DIAGRAMS tag to NO.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+CLASS_GRAPH            = YES
+
+# If the COLLABORATION_GRAPH tag is set to YES then doxygen will generate a
+# graph for each documented class showing the direct and indirect implementation
+# dependencies (inheritance, containment, and class references variables) of the
+# class with other documented classes.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+COLLABORATION_GRAPH    = NO
+
+# If the GROUP_GRAPHS tag is set to YES then doxygen will generate a graph for
+# groups, showing the direct groups dependencies.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+GROUP_GRAPHS           = YES
+
+# If the UML_LOOK tag is set to YES doxygen will generate inheritance and
+# collaboration diagrams in a style similar to the OMG's Unified Modeling
+# Language.
+# The default value is: NO.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+UML_LOOK               = NO
+
+# If the UML_LOOK tag is enabled, the fields and methods are shown inside the
+# class node. If there are many fields or methods and many nodes the graph may
+# become too big to be useful. The UML_LIMIT_NUM_FIELDS threshold limits the
+# number of items for each type to make the size more manageable. Set this to 0
+# for no limit. Note that the threshold may be exceeded by 50% before the limit
+# is enforced. So when you set the threshold to 10, up to 15 fields may appear,
+# but if the number exceeds 15, the total amount of fields shown is limited to
+# 10.
+# Minimum value: 0, maximum value: 100, default value: 10.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+UML_LIMIT_NUM_FIELDS   = 10
+
+# If the TEMPLATE_RELATIONS tag is set to YES then the inheritance and
+# collaboration graphs will show the relations between templates and their
+# instances.
+# The default value is: NO.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+TEMPLATE_RELATIONS     = NO
+
+# If the INCLUDE_GRAPH, ENABLE_PREPROCESSING and SEARCH_INCLUDES tags are set to
+# YES then doxygen will generate a graph for each documented file showing the
+# direct and indirect include dependencies of the file with other documented
+# files.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+INCLUDE_GRAPH          = YES
+
+# If the INCLUDED_BY_GRAPH, ENABLE_PREPROCESSING and SEARCH_INCLUDES tags are
+# set to YES then doxygen will generate a graph for each documented file showing
+# the direct and indirect include dependencies of the file with other documented
+# files.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+INCLUDED_BY_GRAPH      = YES
+
+# If the CALL_GRAPH tag is set to YES then doxygen will generate a call
+# dependency graph for every global function or class method.
+#
+# Note that enabling this option will significantly increase the time of a run.
+# So in most cases it will be better to enable call graphs for selected
+# functions only using the \callgraph command.
+# The default value is: NO.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+CALL_GRAPH             = NO
+
+# If the CALLER_GRAPH tag is set to YES then doxygen will generate a caller
+# dependency graph for every global function or class method.
+#
+# Note that enabling this option will significantly increase the time of a run.
+# So in most cases it will be better to enable caller graphs for selected
+# functions only using the \callergraph command.
+# The default value is: NO.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+CALLER_GRAPH           = NO
+
+# If the GRAPHICAL_HIERARCHY tag is set to YES then doxygen will graphical
+# hierarchy of all classes instead of a textual one.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+GRAPHICAL_HIERARCHY    = YES
+
+# If the DIRECTORY_GRAPH tag is set to YES then doxygen will show the
+# dependencies a directory has on other directories in a graphical way. The
+# dependency relations are determined by the #include relations between the
+# files in the directories.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DIRECTORY_GRAPH        = YES
+
+# The DOT_IMAGE_FORMAT tag can be used to set the image format of the images
+# generated by dot.
+# Note: If you choose svg you need to set HTML_FILE_EXTENSION to xhtml in order
+# to make the SVG files visible in IE 9+ (other browsers do not have this
+# requirement).
+# Possible values are: png, jpg, gif and svg.
+# The default value is: png.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_IMAGE_FORMAT       = svg
+
+# If DOT_IMAGE_FORMAT is set to svg, then this option can be set to YES to
+# enable generation of interactive SVG images that allow zooming and panning.
+#
+# Note that this requires a modern browser other than Internet Explorer. Tested
+# and working are Firefox, Chrome, Safari, and Opera.
+# Note: For IE 9+ you need to set HTML_FILE_EXTENSION to xhtml in order to make
+# the SVG files visible. Older versions of IE do not have SVG support.
+# The default value is: NO.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+INTERACTIVE_SVG        = NO
+
+# The DOT_PATH tag can be used to specify the path where the dot tool can be
+# found. If left blank, it is assumed the dot tool can be found in the path.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_PATH               =
+
+# The DOTFILE_DIRS tag can be used to specify one or more directories that
+# contain dot files that are included in the documentation (see the \dotfile
+# command).
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOTFILE_DIRS           =
+
+# The MSCFILE_DIRS tag can be used to specify one or more directories that
+# contain msc files that are included in the documentation (see the \mscfile
+# command).
+
+MSCFILE_DIRS           =
+
+# The DIAFILE_DIRS tag can be used to specify one or more directories that
+# contain dia files that are included in the documentation (see the \diafile
+# command).
+
+DIAFILE_DIRS           =
+
+# The DOT_GRAPH_MAX_NODES tag can be used to set the maximum number of nodes
+# that will be shown in the graph. If the number of nodes in a graph becomes
+# larger than this value, doxygen will truncate the graph, which is visualized
+# by representing a node as a red box. Note that doxygen if the number of direct
+# children of the root node in a graph is already larger than
+# DOT_GRAPH_MAX_NODES then the graph will not be shown at all. Also note that
+# the size of a graph can be further restricted by MAX_DOT_GRAPH_DEPTH.
+# Minimum value: 0, maximum value: 10000, default value: 50.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_GRAPH_MAX_NODES    = 50
+
+# The MAX_DOT_GRAPH_DEPTH tag can be used to set the maximum depth of the graphs
+# generated by dot. A depth value of 3 means that only nodes reachable from the
+# root by following a path via at most 3 edges will be shown. Nodes that lay
+# further from the root node will be omitted. Note that setting this option to 1
+# or 2 may greatly reduce the computation time needed for large code bases. Also
+# note that the size of a graph can be further restricted by
+# DOT_GRAPH_MAX_NODES. Using a depth of 0 means no depth restriction.
+# Minimum value: 0, maximum value: 1000, default value: 0.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+MAX_DOT_GRAPH_DEPTH    = 0
+
+# Set the DOT_TRANSPARENT tag to YES to generate images with a transparent
+# background. This is disabled by default, because dot on Windows does not seem
+# to support this out of the box.
+#
+# Warning: Depending on the platform used, enabling this option may lead to
+# badly anti-aliased labels on the edges of a graph (i.e. they become hard to
+# read).
+# The default value is: NO.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_TRANSPARENT        = NO
+
+# Set the DOT_MULTI_TARGETS tag to YES allow dot to generate multiple output
+# files in one run (i.e. multiple -o and -T options on the command line). This
+# makes dot run faster, but since only newer versions of dot (>1.8.10) support
+# this, this feature is disabled by default.
+# The default value is: NO.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_MULTI_TARGETS      = NO
+
+# If the GENERATE_LEGEND tag is set to YES doxygen will generate a legend page
+# explaining the meaning of the various boxes and arrows in the dot generated
+# graphs.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+GENERATE_LEGEND        = YES
+
+# If the DOT_CLEANUP tag is set to YES doxygen will remove the intermediate dot
+# files that are used to generate the various graphs.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_CLEANUP            = YES
diff --git a/doc/ignition_logo.svg b/doc/ignition_logo.svg
new file mode 100644
index 0000000..6fbbc8d
--- /dev/null
+++ b/doc/ignition_logo.svg
@@ -0,0 +1,249 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+   xmlns:dc="http://purl.org/dc/elements/1.1/"
+   xmlns:cc="http://creativecommons.org/ns#"
+   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+   xmlns:svg="http://www.w3.org/2000/svg"
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+   width="473.20953"
+   height="338.49789"
+   id="svg3097"
+   version="1.1"
+   inkscape:version="0.48.4 r9939"
+   sodipodi:docname="ignition_logo.svg">
+  <defs
+     id="defs3099" />
+  <sodipodi:namedview
+     id="base"
+     pagecolor="#ffffff"
+     bordercolor="#666666"
+     borderopacity="1.0"
+     inkscape:pageopacity="0.0"
+     inkscape:pageshadow="2"
+     inkscape:zoom="0.7"
+     inkscape:cx="-8.01737"
+     inkscape:cy="108.51396"
+     inkscape:document-units="px"
+     inkscape:current-layer="layer1"
+     showgrid="false"
+     fit-margin-top="0"
+     fit-margin-left="0"
+     fit-margin-right="0"
+     fit-margin-bottom="0"
+     inkscape:window-width="1350"
+     inkscape:window-height="857"
+     inkscape:window-x="457"
+     inkscape:window-y="89"
+     inkscape:window-maximized="0" />
+  <metadata
+     id="metadata3102">
+    <rdf:RDF>
+      <cc:Work
+         rdf:about="">
+        <dc:format>image/svg+xml</dc:format>
+        <dc:type
+           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+        <dc:title />
+      </cc:Work>
+    </rdf:RDF>
+  </metadata>
+  <g
+     inkscape:label="Layer 1"
+     inkscape:groupmode="layer"
+     id="layer1"
+     transform="translate(-159.66847,-323.82846)">
+    <g
+       id="g44"
+       transform="matrix(1.25,0,0,-1.25,389.76025,331.23471)">
+      <path
+         d="m 0,0 c 0,-3.272 2.927,-5.924 6.534,-5.924 3.61,0 6.535,2.652 6.535,5.924 0,3.272 -2.925,5.925 -6.535,5.925 C 2.927,5.925 0,3.272 0,0"
+         style="fill:#f1623b;fill-opacity:1;fill-rule:nonzero;stroke:none"
+         id="path46"
+         inkscape:connector-curvature="0" />
+    </g>
+    <g
+       id="g48"
+       transform="matrix(1.25,0,0,-1.25,369.82862,394.56733)">
+      <path
+         d="m 0,0 c 0,-5.404 -4.833,-9.788 -10.797,-9.788 -5.962,0 -10.798,4.384 -10.798,9.788 0,1.761 0.513,3.412 1.412,4.84 1.86,2.956 5.366,4.949 9.386,4.949 C -4.833,9.789 0,5.406 0,0"
+         style="fill:#f1623b;fill-opacity:1;fill-rule:nonzero;stroke:none"
+         id="path50"
+         inkscape:connector-curvature="0" />
+    </g>
+    <g
+       id="g52"
+       transform="matrix(1.25,0,0,-1.25,337.86512,375.95645)">
+      <path
+         d="m 0,0 c 0,-2.816 -2.52,-5.1 -5.626,-5.1 -3.108,0 -5.626,2.284 -5.626,5.1 0,2.816 2.518,5.101 5.626,5.101 C -2.52,5.101 0,2.816 0,0"
+         style="fill:#f1623b;fill-opacity:1;fill-rule:nonzero;stroke:none"
+         id="path54"
+         inkscape:connector-curvature="0" />
+    </g>
+    <path
+       d="m 334.872,370.83683 -7.95625,0 0,-15.96875 7.95625,0 0,15.96875 z"
+       style="fill:#f1623b;fill-opacity:1;fill-rule:nonzero;stroke:none"
+       id="path56"
+       inkscape:connector-curvature="0" />
+    <g
+       id="g58"
+       transform="matrix(1.25,0,0,-1.25,349.28362,389.69421)">
+      <path
+         d="M 0,0 -4.691,-3.898 -15.124,6.425 -10.433,10.321 0,0 z"
+         style="fill:#f1623b;fill-opacity:1;fill-rule:nonzero;stroke:none"
+         id="path60"
+         inkscape:connector-curvature="0" />
+    </g>
+    <g
+       id="g62"
+       transform="matrix(1.25,0,0,-1.25,324.0755,339.67108)">
+      <path
+         d="m 0,0 c 0,0 0.454,-6.8 5.455,-6.8 5.001,0 5.228,5.358 5.228,5.358 0,0 7.954,-11.538 -5.228,-11.538 C -7.729,-12.98 0,0 0,0"
+         style="fill:#f1623b;fill-opacity:1;fill-rule:nonzero;stroke:none"
+         id="path64"
+         inkscape:connector-curvature="0" />
+    </g>
+    <g
+       id="g66"
+       transform="matrix(1.25,0,0,-1.25,422.71925,394.56733)">
+      <path
+         d="m 0,0 c 0,-5.404 4.833,-9.788 10.794,-9.788 5.965,0 10.799,4.384 10.799,9.788 0,1.761 -0.512,3.412 -1.409,4.84 -1.861,2.956 -5.368,4.949 -9.39,4.949 C 4.833,9.789 0,5.406 0,0"
+         style="fill:#f1623b;fill-opacity:1;fill-rule:nonzero;stroke:none"
+         id="path68"
+         inkscape:connector-curvature="0" />
+    </g>
+    <g
+       id="g70"
+       transform="matrix(1.25,0,0,-1.25,454.68275,375.95645)">
+      <path
+         d="m 0,0 c 0,-2.816 2.52,-5.1 5.626,-5.1 3.107,0 5.628,2.284 5.628,5.1 0,2.816 -2.521,5.101 -5.628,5.101 C 2.52,5.101 0,2.816 0,0"
+         style="fill:#f1623b;fill-opacity:1;fill-rule:nonzero;stroke:none"
+         id="path72"
+         inkscape:connector-curvature="0" />
+    </g>
+    <path
+       d="m 457.67575,370.83683 7.9575,0 0,-15.96875 -7.9575,0 0,15.96875 z"
+       style="fill:#f1623b;fill-opacity:1;fill-rule:nonzero;stroke:none"
+       id="path74"
+       inkscape:connector-curvature="0" />
+    <g
+       id="g76"
+       transform="matrix(1.25,0,0,-1.25,443.26312,389.69421)">
+      <path
+         d="M 0,0 4.692,-3.898 15.124,6.425 10.432,10.321 0,0 z"
+         style="fill:#f1623b;fill-opacity:1;fill-rule:nonzero;stroke:none"
+         id="path78"
+         inkscape:connector-curvature="0" />
+    </g>
+    <g
+       id="g80"
+       transform="matrix(1.25,0,0,-1.25,468.47125,339.67108)">
+      <path
+         d="m 0,0 c 0,0 -0.452,-6.8 -5.454,-6.8 -4.999,0 -5.23,5.358 -5.23,5.358 0,0 -7.953,-11.538 5.23,-11.538 C 7.728,-12.98 0,0 0,0"
+         style="fill:#f1623b;fill-opacity:1;fill-rule:nonzero;stroke:none"
+         id="path82"
+         inkscape:connector-curvature="0" />
+    </g>
+    <path
+       d="m 422.7195,379.30433 -52.28125,0 0,-14.42375 52.28125,0 0,14.42375 z m -21.455,-35.80125 0,-6.76125 c 0,-1.81625 -1.62,-3.285 -3.62125,-3.285 -2.00125,0 -3.6225,1.46875 -3.6225,3.285 l 0,6.585 c -20.4625,1.18125 -36.6525,16.37 -36.6525,34.94875 l 0,46.6225 c 0,10.23875 9.1575,12.105 20.4575,12.105 l 37.505,0 c 11.29875,0 20.4575,-1.86625 20.4575,-12.105 l 0,-46.6225 c 0,-17.93 -15.0825,-32.70125 -34.52375,-34.7725"
+       style="fill:#f1623b;fill-opacity:1;fill-rule:nonzero;stroke:none"
+       id="path84"
+       inkscape:connector-curvature="0" />
+    <g
+       id="g86"
+       transform="matrix(1.25,0,0,-1.25,378.879,495.55483)">
+      <path
+         d="m 0,0 c 0,0 1.215,6.836 3.784,6.836 0.135,-6.393 8.377,-10.801 6.187,-21.166 19.458,7.497 20.304,31.971 20.304,31.971 0,0 -0.117,-0.883 4.259,-5.733 7.786,20.727 -10.451,29.928 -10.451,29.928 l -1.348,0.003 C 23.916,40.416 28.458,33.285 15.008,19.623 9.585,25.687 0.048,33.539 5.561,41.89 4.985,41.89 4.394,41.893 3.784,41.893 -20.647,23.148 0,0 0,0"
+         style="fill:#f1623b;fill-opacity:1;fill-rule:nonzero;stroke:none"
+         id="path88"
+         inkscape:connector-curvature="0" />
+    </g>
+    <g
+       id="g90"
+       transform="matrix(1.25,0,0,-1.25,207.40347,592.96504)">
+      <path
+         d="m 0,0 -36.232,0 c -1.087,0 -1.956,0.869 -1.956,2.028 l 0,3.986 c 0,1.16 0.869,2.029 1.956,2.029 l 14.13,0 0,40.29 -6.086,0 c -1.087,0 -1.957,0.87 -1.957,1.957 l 0,4.058 c 0,1.159 0.87,2.028 1.957,2.028 l 20.145,0 c 1.159,0 2.028,-0.869 2.028,-2.028 l 0,-4.058 c 0,-1.087 -0.869,-1.957 -2.028,-1.957 l -6.015,0 0,-40.29 14.058,0 c 1.159,0 2.029,-0.869 2.029,-2.029 l 0,-3.986 C 2.029,0.869 1.159,0 0,0"
+         style="fill:#606163;fill-opacity:1;fill-rule:nonzero;stroke:none"
+         id="path92"
+         inkscape:connector-curvature="0" />
+    </g>
+    <g
+       id="g94"
+       transform="matrix(1.25,0,0,-1.25,260.3051,552.74779)">
+      <path
+         d="m 0,0 -16.087,0 c -4.42,0 -8.043,-3.623 -8.043,-8.044 l 0,-8.044 c 0,-4.42 3.623,-8.043 8.043,-8.043 L 0,-24.131 0,0 z m -8.043,-48.262 -22.174,0 c -1.087,0 -1.957,0.87 -1.957,2.03 l 0,3.986 c 0,1.158 0.87,2.028 1.957,2.028 l 22.174,0 c 4.42,0 8.043,3.623 8.043,8.044 l -16.087,0 c -8.841,0 -16.087,7.246 -16.087,16.086 l 0,8.044 c 0,8.913 7.246,16.16 16.087,16.16 l 22.102,0 c 1.159,0 2.028,-0.942 2.028,-2.03 l 0,-38.26 c 0,-8.842 -7.246,-16.088 -16.086,-16.088"
+         style="fill:#606163;fill-opacity:1;fill-rule:nonzero;stroke:none"
+         id="path96"
+         inkscape:connector-curvature="0" />
+    </g>
+    <g
+       id="g98"
+       transform="matrix(1.25,0,0,-1.25,328.24334,592.96504)">
+      <path
+         d="m 0,0 -3.985,0 c -1.161,0 -2.03,0.869 -2.03,2.028 l 0,22.102 c 0,4.421 -3.623,8.044 -8.043,8.044 l -16.087,0 0,-30.146 C -30.145,0.869 -31.087,0 -32.174,0 l -4.058,0 c -1.087,0 -1.956,0.869 -1.956,2.028 l 0,36.232 c 0,1.088 0.869,2.03 1.956,2.03 l 22.174,0 c 8.84,0 16.086,-7.247 16.086,-16.16 l 0,-22.102 C 2.028,0.869 1.159,0 0,0"
+         style="fill:#606163;fill-opacity:1;fill-rule:nonzero;stroke:none"
+         id="path100"
+         inkscape:connector-curvature="0" />
+    </g>
+    <g
+       id="g102"
+       transform="matrix(1.25,0,0,-1.25,368.55463,532.54879)">
+      <path
+         d="m 0,0 -3.986,0 c -1.159,0 -2.029,0.87 -2.029,1.957 l 0,4.058 c 0,1.159 0.87,2.028 2.029,2.028 l 3.986,0 c 1.159,0 2.029,-0.869 2.029,-2.028 l 0,-4.058 C 2.029,0.87 1.159,0 0,0 m 16.087,-48.333 -36.232,0 c -1.087,0 -1.957,0.869 -1.957,2.028 l 0,3.986 c 0,1.16 0.87,2.029 1.957,2.029 l 14.13,0 0,24.131 -6.087,0 c -1.086,0 -1.957,0.942 -1.957,2.029 l 0,4.057 c 0,1.088 0.871,2.03 1.957,2.03 l 12.102,0 c 1.159,0 2.029,-0.942 2.029,-2.03 l 0,-30.217 14.058,0 c 1.159,0 2.028,-0.869 2 [...]
+         style="fill:#606163;fill-opacity:1;fill-rule:nonzero;stroke:none"
+         id="path104"
+         inkscape:connector-curvature="0" />
+    </g>
+    <g
+       id="g106"
+       transform="matrix(1.25,0,0,-1.25,449.08313,592.96504)">
+      <path
+         d="m 0,0 -6.015,0 c -8.839,0 -16.087,7.246 -16.087,16.086 l 0,16.088 -14.129,0 c -1.088,0 -1.957,0.942 -1.957,2.029 l 0,4.057 c 0,1.088 0.869,2.03 1.957,2.03 l 14.129,0 0,14.058 c 0,1.159 0.871,2.028 2.029,2.028 l 3.986,0 c 1.159,0 2.029,-0.869 2.029,-2.028 l 0,-14.058 14.058,0 c 1.159,0 2.028,-0.942 2.028,-2.03 l 0,-4.057 C 2.028,33.116 1.159,32.174 0,32.174 l -14.058,0 0,-16.088 c 0,-4.42 3.623,-8.043 8.043,-8.043 l 6.015,0 c 1.159,0 2.028,-0.869 2.028,-2.029 l 0,-3.986 C 2.02 [...]
+         style="fill:#606163;fill-opacity:1;fill-rule:nonzero;stroke:none"
+         id="path108"
+         inkscape:connector-curvature="0" />
+    </g>
+    <g
+       id="g110"
+       transform="matrix(1.25,0,0,-1.25,489.39443,532.54879)">
+      <path
+         d="m 0,0 -3.986,0 c -1.159,0 -2.029,0.87 -2.029,1.957 l 0,4.058 c 0,1.159 0.87,2.028 2.029,2.028 l 3.986,0 c 1.159,0 2.029,-0.869 2.029,-2.028 l 0,-4.058 C 2.029,0.87 1.159,0 0,0 m 16.087,-48.333 -36.232,0 c -1.087,0 -1.957,0.869 -1.957,2.028 l 0,3.986 c 0,1.16 0.87,2.029 1.957,2.029 l 14.13,0 0,24.131 -6.087,0 c -1.086,0 -1.957,0.942 -1.957,2.029 l 0,4.057 c 0,1.088 0.871,2.03 1.957,2.03 l 12.102,0 c 1.159,0 2.029,-0.942 2.029,-2.03 l 0,-30.217 14.058,0 c 1.159,0 2.028,-0.869 2 [...]
+         style="fill:#606163;fill-opacity:1;fill-rule:nonzero;stroke:none"
+         id="path112"
+         inkscape:connector-curvature="0" />
+    </g>
+    <g
+       id="g114"
+       transform="matrix(1.25,0,0,-1.25,562.40473,562.80266)">
+      <path
+         d="m 0,0 c 0,4.421 -3.623,8.044 -8.043,8.044 l -8.044,0 c -4.421,0 -8.044,-3.623 -8.044,-8.044 l 0,-8.044 c 0,-4.42 3.623,-8.043 8.044,-8.043 l 8.044,0 c 4.42,0 8.043,3.623 8.043,8.043 L 0,0 z m -8.043,-24.13 -8.044,0 c -8.841,0 -16.087,7.246 -16.087,16.086 l 0,8.044 c 0,8.913 7.246,16.16 16.087,16.16 l 8.044,0 C 0.797,16.16 8.043,8.913 8.043,0 l 0,-8.044 c 0,-8.84 -7.246,-16.086 -16.086,-16.086"
+         style="fill:#606163;fill-opacity:1;fill-rule:nonzero;stroke:none"
+         id="path116"
+         inkscape:connector-curvature="0" />
+    </g>
+    <g
+       id="g118"
+       transform="matrix(1.25,0,0,-1.25,630.34173,592.96504)">
+      <path
+         d="m 0,0 -3.984,0 c -1.161,0 -2.03,0.869 -2.03,2.028 l 0,22.102 c 0,4.421 -3.623,8.044 -8.043,8.044 l -16.088,0 0,-30.146 C -30.145,0.869 -31.086,0 -32.174,0 l -4.056,0 c -1.088,0 -1.958,0.869 -1.958,2.028 l 0,36.232 c 0,1.088 0.87,2.03 1.958,2.03 l 22.173,0 c 8.84,0 16.086,-7.247 16.086,-16.16 l 0,-22.102 C 2.029,0.869 1.16,0 0,0"
+         style="fill:#606163;fill-opacity:1;fill-rule:nonzero;stroke:none"
+         id="path120"
+         inkscape:connector-curvature="0" />
+    </g>
+    <text
+       xml:space="preserve"
+       style="font-size:40px;font-style:normal;font-weight:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans"
+       x="516.81549"
+       y="661.64667"
+       id="text3104"
+       sodipodi:linespacing="125%"><tspan
+         sodipodi:role="line"
+         id="tspan3106"
+         x="516.81549"
+         y="661.64667"
+         style="font-size:48px;fill:#666666">Math</tspan></text>
+  </g>
+</svg>
diff --git a/doc/mainpage.html b/doc/mainpage.html
new file mode 100644
index 0000000..48053a4
--- /dev/null
+++ b/doc/mainpage.html
@@ -0,0 +1,17 @@
+/** \mainpage Ignition: Math API Reference
+
+Welcome to the Ingition Math library API.  Should you find problems with this documentation - typos, unclear phrases,
+or insufficient detail - please create a <a
+  href="https://bitbucket.org/osrf/ignition-math/issues/new">new bitbucket issue</a>.
+Include sufficient detail to quickly locate the problematic documentation.
+
+<dl>
+  <dt>API</dt>
+  <dd><a href="classes.html">Class List</a>- Index of all classes in Ignition Math, organized alphabetically</dd><br/>
+  <dd><a href="hierarchy.html">Class Hierarchy</a> - Heirarchical class structure.</dd><br/>
+  <dd><a href="globals.html">Globals</a> - Global defines and variables.</dd><br/>
+  <dd><a href="namespacemembers.html">Namespace Members</a> - Functions and other goodies in the igntion::math namesapce</dd><br/>
+  <dd><a href="files.html">Files</a> - A list of all the files.</dd><br/>
+</dl>
+
+*/
diff --git a/doc/style.css b/doc/style.css
new file mode 100644
index 0000000..43449be
--- /dev/null
+++ b/doc/style.css
@@ -0,0 +1,107 @@
+body, table, div, p, dl {
+  font-family: arial, verdana, sans, sans-serif;
+  background-color: #FFF;
+	font-size: 12px;
+  margin: 0;
+  padding 0;
+}
+
+div#top {
+  margin: 0 0 0 20em;
+}
+div.header {
+	margin-left: 20em;
+}
+
+div.contents {
+	margin-top: 0px;
+	margin-left: 20em;
+	margin-right: 10px;
+}
+
+.floatright 
+{ 
+  float: right; 
+  margin: 0 0 1em 1em; 
+}
+
+.timestamp { 
+  text-align:right; 
+  background-color: #DDD; 
+  font-size:75%;
+}
+
+
+div.leftbar
+{
+  text-align:left;
+  float: left;
+  border-right: 1px solid #dddddd;
+  width: 18em;
+  margin: 0 0 0 0;
+  padding: 4 4 4 4;
+  background-color: #ffffff;
+  position: fixed;
+  height: 100%;
+}
+
+div.menu {
+  #display:block;
+  background:#ffffff;
+  font-size: 90%;
+  /*border-top: 2px solid #000000;
+   *   border-bottom: 2px solid #000000;
+   *   */
+  margin: 0 0 10px 0;
+}
+
+div.menu dl {
+  margin-top: 0px;
+  margin-bottom: 5px;
+}
+
+div.menu dt {
+  font-weight:bold;
+  padding:0 4px 4px 4px;
+  font-size: 110%;
+  text-align: left;
+  text-decoration:none;
+}
+
+div.menu dd {
+  font-weight: bold;
+  margin-left: 0px;
+  padding-left: 20px;
+  padding-bottom: 2px;
+  font-size: 100%;
+}
+
+
+div.leftbar img {
+  border:0;
+}
+
+div.submenu dd {
+  font-size: 70%;
+  margin-left: 8px;
+  padding-left: 10px;
+  padding-bottom: 3px;
+}
+
+div.submenu dd .secondline {
+  margin-left: 12px;
+}
+
+#MSearchBox
+{
+  border: 1px solid black;
+  position: static;
+  margin: 10px;
+  display: block;
+  height: 20px;
+}
+
+#MSearchField
+{
+  background:none;
+}
diff --git a/examples/CMakeLists.txt b/examples/CMakeLists.txt
new file mode 100644
index 0000000..538b32c
--- /dev/null
+++ b/examples/CMakeLists.txt
@@ -0,0 +1,13 @@
+cmake_minimum_required(VERSION 3.5 FATAL_ERROR)
+
+# Find the Ignition-Math library
+find_package(ignition-math4 REQUIRED)
+
+add_executable(vector2_example vector2_example.cc)
+target_link_libraries(vector2_example ${IGNITION-MATH_LIBRARIES})
+
+add_executable(triangle_example triangle_example.cc)
+target_link_libraries(triangle_example ${IGNITION-MATH_LIBRARIES})
+
+add_executable(graph_example graph_example.cc)
+target_link_libraries(graph_example ${IGNITION-MATH_LIBRARIES})
diff --git a/examples/graph_example.cc b/examples/graph_example.cc
new file mode 100644
index 0000000..a30788d
--- /dev/null
+++ b/examples/graph_example.cc
@@ -0,0 +1,90 @@
+/*
+ * Copyright (C) 2017 Open Source Robotics Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+*/
+
+#include <iostream>
+#include <ignition/math.hh>
+
+int main(int argc, char **argv)
+{
+  // Create a directed graph that is capable of storing integer data in the
+  // vertices and double data on the edges.
+  ignition::math::graph::DirectedGraph<int, double> graph(
+    // Create the vertices, with default data and vertex ids.
+    {
+      {"vertex1"}, {"vertex2"}, {"vertex3"}
+    },
+    // Create the edges, with default data and weight values.
+    {
+      // Edge from vertex 0 to vertex 1. Each number refers to a vertex id.
+      // Vertex ids start from zero.
+      {{0, 1}}, {{1, 2}}
+    });
+
+  // Output in DOT graph format.
+  std::cout << "Graph with default vertex Ids and data, "
+            << "and default edge data.\n"
+            << graph << std::endl;
+
+  // You can assign data to vertices.
+  ignition::math::graph::DirectedGraph<int, double> graph2(
+    // Create the vertices, with custom data and default vertex ids.
+    {
+      {"vertex1", 1}, {"vertex2", 2}, {"vertex3", 10}
+    },
+    // Create the edges, with default data and weight values.
+    {
+      // Edge from vertex 0 to vertex 1. Each number refers to a vertex id
+      // specified above.
+      {{0, 2}}, {{1, 2}}
+    });
+
+  // Output in DOT graph format.
+  std::cout << "Graph with default vertex Ids and custom vertex data, "
+            << "and default edge data.\n"
+            << graph2 << std::endl;
+
+  // It's also possible to specify vertex ids.
+  ignition::math::graph::DirectedGraph<int, double> graph3(
+    // Create the vertices with custom data and vertex ids.
+    {
+      {"vertex1", 1, 2}, {"vertex2", 2, 3}, {"vertex3", 10, 4}
+    },
+    // Create the edges, with custom data and default weight values.
+    {
+      {{2, 3}, 6.3}, {{3, 4}, 4.2}
+    });
+
+  // Output in DOT graph format.
+  std::cout << "Graph with custom vertex Ids and data, and custom edge data.\n"
+            << graph3 << std::endl;
+
+  // Finally, you can also assign weights to the edges.
+  ignition::math::graph::DirectedGraph<int, double> graph4(
+    // Create the vertices with custom data and vertex ids.
+    {
+      {"vertex1", 1, 2}, {"vertex2", 2, 3}, {"vertex3", 10, 4}
+    },
+    // Create the edges, with custom data and default weight values.
+    {
+      {{2, 3}, 6.3, 1.1}, {{3, 4}, 4.2, 2.3}
+    });
+
+  // Output in DOT graph format.
+  std::cout << "Graph with custom vertex Ids and data, "
+            << "and custom edge data and weights.\n"
+            << graph4 << std::endl;
+}
diff --git a/examples/triangle_example.cc b/examples/triangle_example.cc
new file mode 100644
index 0000000..ab92d89
--- /dev/null
+++ b/examples/triangle_example.cc
@@ -0,0 +1,80 @@
+/*
+ * Copyright (C) 2012 Open Source Robotics Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+*/
+
+#include <iostream>
+#include <ignition/math.hh>
+
+int main(int argc, char **argv)
+{
+  // Create a triangle with the following vertices:
+  // 1: x = -1, y = 0
+  // 2: x = 0, y = 1
+  // 3: x = 1, y = 0
+  ignition::math::Triangled tri(
+      ignition::math::Vector2d(-1, 0),
+      ignition::math::Vector2d(0, 1),
+      ignition::math::Vector2d(1, 0));
+
+  // The individual vertices are accessible through the [] operator
+  std::cout << "Vertex 1: " << tri[0] << "\n"
+            << "Vertex 2: " << tri[1] << "\n"
+            << "Vertex 3: " << tri[2] << "\n";
+
+  // Each side of the triangle is also accessible via the Side function
+  std::cout << "Side 1: " << tri.Side(0) << "\n"
+            << "Side 2: " << tri.Side(1) << "\n"
+            << "Side 3: " << tri.Side(2) << "\n";
+
+  // It's also possible to set each vertex individually.
+  tri.Set(0, ignition::math::Vector2d(-10, 0));
+  tri.Set(1, ignition::math::Vector2d(0, 20));
+  tri.Set(2, ignition::math::Vector2d(10, 2));
+
+  // Or set all the vertices at once.
+  tri.Set(ignition::math::Vector2d(-1, 0),
+          ignition::math::Vector2d(0, 1),
+          ignition::math::Vector2d(1, 0));
+
+  // You can get the perimeter length and area of the triangle
+  std::cout << "Perimeter=" << tri.Perimeter()
+            << " Area=" << tri.Area() << "\n";
+
+  // The Contains functions check if a line or point is inside the triangle
+  if (tri.Contains(ignition::math::Vector2d(0, 0.5)))
+    std::cout << "Triangle contains the point 0, 0.5\n";
+  else
+    std::cout << "Triangle does not contain the point 0, 0.5\n";
+
+  // The Intersect function check if a line segment intersects the triangle.
+  // It also returns the points of intersection
+  ignition::math::Vector2d pt1, pt2;
+  if (tri.Intersects(ignition::math::Line2d(-2, 0.5, 2, 0.5), pt1, pt2))
+  {
+    std::cout << "A line from (-2, 0.5) to (2, 0.5) intersects "
+              << "the triangle at the\nfollowing points:\n"
+              << "\t Pt1=" << pt1 << "\n"
+              << "\t Pt2=" << pt2 << "\n";
+  }
+  else
+  {
+    std::cout << "A line from (-2, 0.5) to (2, 0.5) does not intersect "
+              << "the triangle\n";
+  }
+
+  // There are more functions in Triangle. Take a look at the API;
+  // http://ignitionrobotics.org/libraries/ign_mat/api
+}
diff --git a/examples/vector2_example.cc b/examples/vector2_example.cc
new file mode 100644
index 0000000..9d16441
--- /dev/null
+++ b/examples/vector2_example.cc
@@ -0,0 +1,66 @@
+/*
+ * Copyright (C) 2012 Open Source Robotics Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+*/
+
+#include <iostream>
+#include <ignition/math.hh>
+
+int main(int argc, char **argv)
+{
+  // Create a Vector2 called vec2 of doubles using the typedef Vector2d.
+  // The initial x any y values are zero.\n\n";
+  ignition::math::Vector2d vec2;
+
+  // The x and y component of vec2 can be set at anytime.
+  vec2.Set(2.0, 4.0);
+
+  // The Vector2 class is a template, so you can also create a Vector2 using
+  // ignition::math::Vector2<double>
+  ignition::math::Vector2<double> vec2a;
+
+  vec2a.Set(1.0, 2.0);
+
+  // It's also possible to set initial values. This time we are using
+  // a Vector2 of floats
+  ignition::math::Vector2f vec2b(1.2f, 3.4f);
+
+  // We can output the contents of each vector using std::cout
+  std::cout << "Vec2: " << vec2 << "\n"
+            << "Vec2a: " << vec2a << "\n"
+            << "Vec2b: " << vec2b << "\n";
+
+  // You can also get access to each component in the vector using the
+  // X(), Y() accessors or the [] operator.
+  std::cout << "Vec2: x=" << vec2.X() << " y=" << vec2.Y() << "\n";
+  std::cout << "Vec2a: x=" << vec2a[0] << " y=" << vec2a[1] << "\n";
+  std::cout << "Vec2b: x=" << vec2b.X() << " y=" << vec2b[1] << "\n";
+
+  // The [] operator is clamped to the range [0, 1]
+  std::cout << vec2[3] << std::endl;
+
+  // The Vector2 class overloads many common operators
+  std::cout << vec2 * vec2a << "\n"
+            << vec2 + vec2a << "\n"
+            << vec2 - vec2a << "\n"
+            << vec2 / vec2a << "\n";
+
+  // There are also many useful function such as finding the distance
+  // between two vectors
+  std::cout << vec2.Distance(vec2a) << std::endl;
+
+  // There are more functions in Vector2. Take a look at the API;
+  // http://ignitionrobotics.org/libraries/ign_mat/api
+}
diff --git a/include/CMakeLists.txt b/include/CMakeLists.txt
new file mode 100644
index 0000000..25ec897
--- /dev/null
+++ b/include/CMakeLists.txt
@@ -0,0 +1 @@
+add_subdirectory(ignition)
diff --git a/include/ignition/CMakeLists.txt b/include/ignition/CMakeLists.txt
new file mode 100644
index 0000000..2767b4e
--- /dev/null
+++ b/include/ignition/CMakeLists.txt
@@ -0,0 +1 @@
+add_subdirectory(math)
diff --git a/include/ignition/math/Angle.hh b/include/ignition/math/Angle.hh
new file mode 100644
index 0000000..3a8bfb2
--- /dev/null
+++ b/include/ignition/math/Angle.hh
@@ -0,0 +1,203 @@
+/*
+ * Copyright (C) 2012 Open Source Robotics Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+*/
+#ifndef IGNITION_MATH_ANGLE_HH_
+#define IGNITION_MATH_ANGLE_HH_
+
+#include <iostream>
+#include <ignition/math/Helpers.hh>
+
+/// \brief Macro that converts radians to degrees
+/// \param[in] radians
+/// \return degrees
+#define IGN_RTOD(r) ((r) * 180 / IGN_PI)
+
+/// \brief Converts degrees to radians
+/// \param[in] degrees
+/// \return radians
+#define IGN_DTOR(d) ((d) * IGN_PI / 180)
+
+/// \brief Macro that normalizes an angle in the range -Pi to Pi
+/// \param[in] angle
+/// \return the angle, in range
+#define IGN_NORMALIZE(a) (atan2(sin(a), cos(a)))
+
+namespace ignition
+{
+  namespace math
+  {
+    /// \class Angle Angle.hh ignition/math/Angle.hh
+    /// \brief An angle and related functions.
+    class IGNITION_MATH_VISIBLE Angle
+    {
+      /// \brief math::Angle(0)
+      public: static const Angle Zero;
+
+      /// \brief math::Angle(IGN_PI)
+      public: static const Angle Pi;
+
+      /// \brief math::Angle(IGN_PI * 0.5)
+      public: static const Angle HalfPi;
+
+      /// \brief math::Angle(IGN_PI * 2)
+      public: static const Angle TwoPi;
+
+      /// \brief Constructor
+      public: Angle();
+
+      /// \brief Conversion Constructor
+      /// \param[in] _radian Radians
+      // cppcheck-suppress noExplicitConstructor
+      public: Angle(const double _radian);
+
+      /// \brief Copy constructor
+      /// \param[in] _angle Angle to copy
+      public: Angle(const Angle &_angle);
+
+      /// \brief Destructor
+      public: virtual ~Angle();
+
+      /// \brief Set the value from an angle in radians
+      /// \param[in] _radian Radian value
+      public: void Radian(double _radian);
+
+      /// \brief Set the value from an angle in degrees
+      /// \param[in] _degree Degree value
+      public: void Degree(double _degree);
+
+      /// \brief Get the angle in radians
+      /// \return double containing the angle's radian value
+      public: double Radian() const;
+
+      /// \brief Get the angle in degrees
+      /// \return double containing the angle's degree value
+      public: double Degree() const;
+
+      /// \brief Normalize the angle in the range -Pi to Pi
+      public: void Normalize();
+
+      /// \brief Return the angle's radian value
+      /// \return double containing the angle's radian value
+      public: double operator()() const;
+
+      /// \brief Dereference operator
+      /// \return Double containing the angle's radian value
+      public: inline double operator*() const
+              {
+                return value;
+              }
+
+      /// \brief Substraction, result = this - _angle
+      /// \param[in] _angle Angle for substraction
+      /// \return the new angle
+      public: Angle operator-(const Angle &_angle) const;
+
+      /// \brief Addition operator, result = this + _angle
+      /// \param[in] _angle Angle for addition
+      /// \return the new angle
+      public: Angle operator+(const Angle &_angle) const;
+
+      /// \brief Multiplication operator, result = this * _angle
+      /// \param[in] _angle Angle for multiplication
+      /// \return the new angle
+      public: Angle operator*(const Angle &_angle) const;
+
+      /// \brief Division, result = this / _angle
+      /// \param[in] _angle Angle for division
+      /// \return the new angle
+      public: Angle operator/(const Angle &_angle) const;
+
+      /// \brief Subtraction set, this = this - _angle
+      /// \param[in] _angle Angle for subtraction
+      /// \return angle
+      public: Angle operator-=(const Angle &_angle);
+
+      /// \brief Addition set, this = this + _angle
+      /// \param[in] _angle Angle for addition
+      /// \return angle
+      public: Angle operator+=(const Angle &_angle);
+
+      /// \brief Multiplication set, this = this * _angle
+      /// \param[in] _angle Angle for multiplication
+      /// \return angle
+      public: Angle operator*=(const Angle &_angle);
+
+      /// \brief Division set, this = this / _angle
+      /// \param[in] _angle Angle for division
+      /// \return angle
+      public: Angle operator/=(const Angle &_angle);
+
+      /// \brief Equality operator, result = this == _angle
+      /// \param[in] _angle Angle to check for equality
+      /// \return true if this == _angle
+      public: bool operator==(const Angle &_angle) const;
+
+      /// \brief Inequality
+      /// \param[in] _angle Angle to check for inequality
+      /// \return true if this != _angle
+      public: bool operator!=(const Angle &_angle) const;
+
+      /// \brief Less than operator
+      /// \param[in] _angle Angle to check
+      /// \return true if this < _angle
+      public: bool operator<(const Angle &_angle) const;
+
+      /// \brief Less or equal operator
+      /// \param[in] _angle Angle to check
+      /// \return true if this <= _angle
+      public: bool operator<=(const Angle &_angle) const;
+
+      /// \brief Greater than operator
+      /// \param[in] _angle Angle to check
+      /// \return true if this > _angle
+      public: bool operator>(const Angle &_angle) const;
+
+      /// \brief Greater or equal operator
+      /// \param[in] _angle Angle to check
+      /// \return true if this >= _angle
+      public: bool operator>=(const Angle &_angle) const;
+
+      /// \brief Stream insertion operator. Outputs in degrees
+      /// \param[in] _out output stream
+      /// \param[in] _a angle to output
+      /// \return The output stream
+      public: friend std::ostream &operator<<(std::ostream &_out,
+                                              const ignition::math::Angle &_a)
+      {
+        _out << _a.Radian();
+        return _out;
+      }
+
+      /// \brief Stream extraction operator. Assumes input is in radians
+      /// \param in input stream
+      /// \param pt angle to read value into
+      /// \return The input stream
+      public: friend std::istream &operator>>(std::istream &_in,
+                                              ignition::math::Angle &_a)
+      {
+        // Skip white spaces
+        _in.setf(std::ios_base::skipws);
+        _in >> _a.value;
+        return _in;
+      }
+
+      /// The angle in radians
+      private: double value;
+    };
+  }
+}
+
+#endif
diff --git a/include/ignition/math/Box.hh b/include/ignition/math/Box.hh
new file mode 100644
index 0000000..327c31a
--- /dev/null
+++ b/include/ignition/math/Box.hh
@@ -0,0 +1,236 @@
+/*
+ * Copyright (C) 2012 Open Source Robotics Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+*/
+#ifndef IGNITION_MATH_BOX_HH_
+#define IGNITION_MATH_BOX_HH_
+
+#include <iostream>
+#include <tuple>
+#include <ignition/math/Helpers.hh>
+#include <ignition/math/Vector3.hh>
+#include <ignition/math/Line3.hh>
+
+namespace ignition
+{
+  namespace math
+  {
+    // Forward declaration of private data
+    class BoxPrivate;
+
+    /// \class Box Box.hh ignition/math/Box.hh
+    /// \brief Mathematical representation of a box and related functions.
+    class IGNITION_MATH_VISIBLE Box
+    {
+      /// \brief Default constructor. This constructor will set the box's
+      /// minimum and maximum corners to the highest (max) and lowest
+      /// floating point values available to indicate that it is uninitialized.
+      /// The default box does not intersect any other boxes or contain any
+      /// points since it has no extent. Its center is the origin and its side
+      /// lengths are 0.
+      public: Box();
+
+      /// \brief Constructor. This constructor will compute the box's
+      /// minimum and maximum corners based on the two arguments.
+      /// \param[in] _vec1 One corner of the box
+      /// \param[in] _vec2 Another corner of the box
+      public: Box(const Vector3d &_vec1, const Vector3d &_vec2);
+
+      /// \brief Constructor. This constructor will compute the box's
+      /// minimum and maximum corners based on the arguments.
+      /// \param[in] _vec1X One corner's X position
+      /// \param[in] _vec1Y One corner's Y position
+      /// \param[in] _vec1Z One corner's Z position
+      /// \param[in] _vec2X Other corner's X position
+      /// \param[in] _vec2Y Other corner's Y position
+      /// \param[in] _vec2Z Other corner's Z position
+      public: Box(double _vec1X, double _vec1Y, double _vec1Z,
+                  double _vec2X, double _vec2Y, double _vec2Z);
+
+      /// \brief Copy Constructor
+      /// \param[in]  _b Box to copy
+      public: Box(const Box &_b);
+
+      /// \brief Destructor
+      public: virtual ~Box();
+
+      /// \brief Get the length along the x dimension
+      /// \return Double value of the length in the x dimension
+      public: double XLength() const;
+
+      /// \brief Get the length along the y dimension
+      /// \return Double value of the length in the y dimension
+      public: double YLength() const;
+
+      /// \brief Get the length along the z dimension
+      /// \return Double value of the length in the z dimension
+      public: double ZLength() const;
+
+      /// \brief Get the size of the box
+      /// \return Size of the box
+      public: math::Vector3d Size() const;
+
+      /// \brief Get the box center
+      /// \return The center position of the box
+      public: math::Vector3d Center() const;
+
+      /// \brief Merge a box with this box
+      /// \param[in]  _box Box to add to this box
+      public: void Merge(const Box &_box);
+
+      /// \brief Assignment operator. Set this box to the parameter
+      /// \param[in]  _b Box to copy
+      /// \return The new box.
+      public: Box &operator=(const Box &_b);
+
+      /// \brief Addition operator. result = this + _b
+      /// \param[in] _b Box to add
+      /// \return The new box
+      public: Box operator+(const Box &_b) const;
+
+      /// \brief Addition set operator. this = this + _b
+      /// \param[in] _b Box to add
+      /// \return This new box
+      public: const Box &operator+=(const Box &_b);
+
+      /// \brief Equality test operator
+      /// \param[in] _b Box to test
+      /// \return True if equal
+      public: bool operator==(const Box &_b) const;
+
+      /// \brief Inequality test operator
+      /// \param[in] _b Box to test
+      /// \return True if not equal
+      public: bool operator!=(const Box &_b) const;
+
+      /// \brief Subtract a vector from the min and max values
+      /// \param _v The vector to use during subtraction
+      /// \return The new box
+      public: Box operator-(const Vector3d &_v);
+
+      /// \brief Output operator
+      /// \param[in] _out Output stream
+      /// \param[in] _b Box to output to the stream
+      /// \return The stream
+      public: friend std::ostream &operator<<(std::ostream &_out,
+                                              const ignition::math::Box &_b)
+      {
+        _out << "Min[" << _b.Min() << "] Max[" << _b.Max() << "]";
+        return _out;
+      }
+
+      /// \brief Get the minimum corner.
+      /// \return The Vector3d that is the minimum corner of the box.
+      public: const Vector3d &Min() const;
+
+      /// \brief Get the maximum corner.
+      /// \return The Vector3d that is the maximum corner of the box.
+      public: const Vector3d &Max() const;
+
+      /// \brief Get a mutable version of the minimum corner.
+      /// \return The Vector3d that is the minimum corner of the box.
+      public: Vector3d &Min();
+
+      /// \brief Get a mutable version of the maximum corner.
+      /// \return The Vector3d that is the maximum corner of the box.
+      public: Vector3d &Max();
+
+      /// \brief Test box intersection. This test will only work if
+      /// both box's minimum corner is less than or equal to their
+      /// maximum corner.
+      /// \param[in] _box Box to check for intersection with this box.
+      /// \return True if this box intersects _box.
+      public: bool Intersects(const Box &_box) const;
+
+      /// \brief Check if a point lies inside the box.
+      /// \param[in] _p Point to check.
+      /// \return True if the point is inside the box.
+      public: bool Contains(const Vector3d &_p) const;
+
+      /// \brief Check if a ray (origin, direction) intersects the box.
+      /// \param[in] _origin Origin of the ray.
+      /// \param[in] _dir Direction of the ray. This ray will be normalized.
+      /// \param[in] _min Minimum allowed distance.
+      /// \param[in] _max Maximum allowed distance.
+      /// \return A boolean
+      public: bool IntersectCheck(const Vector3d &_origin, const Vector3d &_dir,
+                  const double _min, const double _max) const;
+
+      /// \brief Check if a ray (origin, direction) intersects the box.
+      /// \param[in] _origin Origin of the ray.
+      /// \param[in] _dir Direction of the ray. This ray will be normalized.
+      /// \param[in] _min Minimum allowed distance.
+      /// \param[in] _max Maximum allowed distance.
+      /// \return A boolean and double tuple. The boolean value is true
+      /// if the line intersects the box.
+      ///
+      /// The double is the distance from
+      /// the ray's start  to the closest intersection point on the box,
+      /// minus the _min distance. For example, if _min == 0.5 and the
+      /// intersection happens at a distance of 2.0 from _origin then returned
+      /// distance is 1.5.
+      ///
+      /// The double value is zero when the boolean value is false.
+      public: std::tuple<bool, double> IntersectDist(
+                  const Vector3d &_origin, const Vector3d &_dir,
+                  const double _min, const double _max) const;
+
+      /// \brief Check if a ray (origin, direction) intersects the box.
+      /// \param[in] _origin Origin of the ray.
+      /// \param[in] _dir Direction of the ray. This ray will be normalized.
+      /// \param[in] _min Minimum allowed distance.
+      /// \param[in] _max Maximum allowed distance.
+      /// \return A boolean, double, Vector3d tuple. The boolean value is true
+      /// if the line intersects the box.
+      ///
+      /// The double is the distance from the ray's start to the closest
+      /// intersection point on the box,
+      /// minus the _min distance. For example, if _min == 0.5 and the
+      /// intersection happens at a distance of 2.0 from _origin then returned
+      /// distance is 1.5.
+      /// The double value is zero when the boolean value is false. The
+      ///
+      /// Vector3d is the intersection point on the box. The Vector3d value
+      /// is zero if the boolean value is false.
+      public: std::tuple<bool, double, Vector3d> Intersect(
+                  const Vector3d &_origin, const Vector3d &_dir,
+                  const double _min, const double _max) const;
+
+      /// \brief Check if a line intersects the box.
+      /// \param[in] _line The line to check against this box.
+      /// \return A boolean, double, Vector3d tuple. The boolean value is true
+      /// if the line intersects the box. The double is the distance from
+      /// the line's start to the closest intersection point on the box.
+      /// The double value is zero when the boolean value is false. The
+      /// Vector3d is the intersection point on the box. The Vector3d value
+      /// is zero if the boolean value is false.
+      public: std::tuple<bool, double, Vector3d> Intersect(
+                  const Line3d &_line) const;
+
+      /// \brief Clip a line to a dimension of the box.
+      /// This is a helper function to Intersects
+      /// \param[in] _d Dimension of the box(0, 1, or 2).
+      /// \param[in] _line Line to clip
+      /// \param[in,out] _low Close distance
+      /// \param[in,out] _high Far distance
+      private: bool ClipLine(const int _d, const Line3d &_line,
+                   double &_low, double &_high) const;
+
+      /// \brief Private data pointer
+      private: BoxPrivate *dataPtr;
+    };
+  }
+}
+#endif
diff --git a/include/ignition/math/CMakeLists.txt b/include/ignition/math/CMakeLists.txt
new file mode 100644
index 0000000..5ff7092
--- /dev/null
+++ b/include/ignition/math/CMakeLists.txt
@@ -0,0 +1,2 @@
+
+ign_install_all_headers(ADDITIONAL_DIRS graph)
diff --git a/include/ignition/math/Color.hh b/include/ignition/math/Color.hh
new file mode 100644
index 0000000..cb07d7a
--- /dev/null
+++ b/include/ignition/math/Color.hh
@@ -0,0 +1,318 @@
+/*
+ * Copyright (C) 2017 Open Source Robotics Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+*/
+#ifndef IGNITION_MATH_COLOR_HH_
+#define IGNITION_MATH_COLOR_HH_
+
+#include <iostream>
+
+#include <ignition/math/Helpers.hh>
+#include <ignition/math/Vector3.hh>
+
+namespace ignition
+{
+  namespace math
+  {
+    /// \class Color Color.hh ignition/math/Color.hh
+    /// \brief Defines a color using a red (R), green (G), blue (B), and alpha
+    /// (A) component. Each color component is in the range [0..1].
+    class IGNITION_MATH_VISIBLE Color
+    {
+      /// \brief (1, 1, 1)
+      public: static const Color White;
+      /// \brief (0, 0, 0)
+      public: static const Color Black;
+      /// \brief (1, 0, 0)
+      public: static const Color Red;
+      /// \brief (0, 1, 0)
+      public: static const Color Green;
+      /// \brief (0, 0, 1)
+      public: static const Color Blue;
+      /// \brief (1, 1, 0)
+      public: static const Color Yellow;
+      /// \brief (1, 0, 1)
+      public: static const Color Magenta;
+      /// \brief (0, 1, 1)
+      public: static const Color Cyan;
+
+      /// \def RGBA
+      /// \brief A RGBA packed value as an unsigned int
+      public: typedef unsigned int RGBA;
+
+      /// \def BGRA
+      /// \brief A BGRA packed value as an unsigned int
+      public: typedef unsigned int BGRA;
+
+      /// \def ARGB
+      /// \brief A ARGB packed value as an unsigned int
+      public: typedef unsigned int ARGB;
+
+      /// \def ABGR
+      /// \brief A ABGR packed value as an unsigned int
+      public: typedef unsigned int ABGR;
+
+      /// \brief Constructor
+      public: Color();
+
+      /// \brief Constructor
+      /// \param[in] _r Red value (range 0 to 1)
+      /// \param[in] _g Green value (range 0 to 1
+      /// \param[in] _b Blue value (range 0 to 1
+      /// \param[in] _a Alpha value (0=transparent, 1=opaque)
+      public: Color(const float _r, const float _g, const float _b,
+                  const float _a = 1.0);
+
+      /// \brief Copy Constructor
+      /// \param[in] _clr Color to copy
+      public: Color(const Color &_clr);
+
+      /// \brief Destructor
+      public: virtual ~Color();
+
+      /// \brief Reset the color to default values to red=0, green=0,
+      /// blue=0, alpha=1.
+      public: void Reset();
+
+      /// \brief Set the contents of the vector
+      /// \param[in] _r Red value (range 0 to 1)
+      /// \param[in] _g Green value (range 0 to 1)
+      /// \param[in] _b Blue value (range 0 to 1)
+      /// \param[in] _a Alpha value (0=transparent, 1=opaque)
+      public: void Set(const float _r = 1, const float _g = 1,
+                  const float _b = 1, const float _a = 1);
+
+      /// \brief Get the color in HSV colorspace
+      /// \return HSV values in a Vector3f format. A vector3f containing
+      /// {NAN_F, NAN_F, NAN_F} is returned on error.
+      public: Vector3f HSV() const;
+
+      /// \brief Set a color based on HSV values
+      /// \param[in] _h Hue(0..360)
+      /// \param[in] _s Saturation(0..1)
+      /// \param[in] _v Value(0..1)
+      public: void SetFromHSV(const float _h, const float _s, const float _v);
+
+      /// \brief Get the color in YUV colorspace
+      /// \return the YUV  color
+      public: Vector3f YUV() const;
+
+      /// \brief Set from yuv
+      /// \param[in] _y value
+      /// \param[in] _u value
+      /// \param[in] _v value
+      public: void SetFromYUV(const float _y, const float _u, const float _v);
+
+      /// \brief Equal operator
+      /// \param[in] _pt Color to copy
+      /// \return Reference to this color
+      public: Color &operator=(const Color &_pt);
+
+      /// \brief Array index operator
+      /// \param[in] _index Color component index(0=red, 1=green, 2=blue)
+      /// \return r, g, b, or a when _index is 0, 1, 2 or 3. A NAN_F value is
+      /// returned if the _index is invalid
+      public: float operator[](const unsigned int _index);
+
+      /// \brief Get as uint32 RGBA packed value
+      /// \return the color
+      public: RGBA AsRGBA() const;
+
+      /// \brief Get as uint32 BGRA packed value
+      /// \return the color
+      public: BGRA AsBGRA() const;
+
+      /// \brief Get as uint32 ARGB packed value
+      /// \return the color
+      public: ARGB AsARGB() const;
+
+      /// \brief Get as uint32 ABGR packed value
+      /// \return the color
+      public: ABGR AsABGR() const;
+
+      /// \brief Set from uint32 RGBA packed value
+      /// \param[in] _v the new color
+      public: void SetFromRGBA(const RGBA _v);
+
+      /// \brief Set from uint32 BGRA packed value
+      /// \param[in] _v the new color
+      public: void SetFromBGRA(const BGRA _v);
+
+      /// \brief Set from uint32 ARGB packed value
+      /// \param[in] _v the new color
+      public: void SetFromARGB(const ARGB _v);
+
+      /// \brief Set from uint32 ABGR packed value
+      /// \param[in] _v the new color
+      public: void SetFromABGR(const ABGR _v);
+
+      /// \brief Addition operator (this + _pt)
+      /// \param[in] _pt Color to add
+      /// \return The resulting color
+      public: Color operator+(const Color &_pt) const;
+
+      /// \brief Add _v to all color components
+      /// \param[in] _v Value to add to each color component
+      /// \return The resulting color
+      public: Color operator+(const float &_v) const;
+
+      /// \brief Addition equal operator
+      /// \param[in] _pt Color to add
+      /// \return The resulting color
+      public: const Color &operator+=(const Color &_pt);
+
+      /// \brief Subtraction operator
+      /// \param[in] _pt The color to substract
+      /// \return The resulting color
+      public: Color operator-(const Color &_pt) const;
+
+      /// \brief Subtract _v from all color components
+      /// \param[in] _v Value to subtract
+      /// \return The resulting color
+      public: Color operator-(const float &_v) const;
+
+      /// \brief Subtraction equal operator
+      /// \param[in] _pt Color to subtract
+      /// \return The resulting color
+      public: const Color &operator-=(const Color &_pt);
+
+      /// \brief Division operator
+      /// \param[in] _pt Color to divide by
+      /// \return The resulting color
+      public: const Color operator/(const Color &_pt) const;
+
+      /// \brief Divide all color component by _v
+      /// \param[in] _v The value to divide by
+      /// \return The resulting color
+      public: const Color operator/(const float &_v) const;
+
+      /// \brief Division equal operator
+      /// \param[in] _pt Color to divide by
+      /// \return The resulting color
+      public: const Color &operator/=(const Color &_pt);
+
+      /// \brief Multiplication operator
+      /// \param[in] _pt The color to muliply by
+      /// \return The resulting color
+      public: const Color operator*(const Color &_pt) const;
+
+      /// \brief Multiply all color components by _v
+      /// \param[in] _v The value to multiply by
+      /// \return The resulting color
+      public: const Color operator*(const float &_v) const;
+
+      /// \brief Multiplication equal operator
+      /// \param[in] _pt The color to muliply by
+      /// \return The resulting color
+      public: const Color &operator*=(const Color &_pt);
+
+      /// \brief Equality operator
+      /// \param[in] _pt The color to check for equality
+      /// \return True if the this color equals _pt
+      public: bool operator==(const Color &_pt) const;
+
+      /// \brief Inequality operator
+      /// \param[in] _pt The color to check for inequality
+      /// \return True if the this color does not equal _pt
+      public: bool operator!=(const Color &_pt) const;
+
+      /// \brief Clamp the color values to valid ranges
+      private: void Clamp();
+
+      /// \brief Stream insertion operator
+      /// \param[in] _out the output stream
+      /// \param[in] _pt the color
+      /// \return the output stream
+      public: friend std::ostream &operator<<(std::ostream &_out,
+                                              const Color &_pt)
+      {
+        _out << _pt.r << " " << _pt.g << " " << _pt.b << " " << _pt.a;
+        return _out;
+      }
+
+      /// \brief Stream insertion operator
+      /// \param[in] _in the input stream
+      /// \param[in] _pt
+      public: friend std::istream &operator>> (std::istream &_in, Color &_pt)
+      {
+        // Skip white spaces
+        _in.setf(std::ios_base::skipws);
+        _in >> _pt.r >> _pt.g >> _pt.b >> _pt.a;
+        return _in;
+      }
+
+      /// \brief Get the red value
+      /// \return The red value
+      public: float R() const;
+
+      /// \brief Get the green value
+      /// \return The green value
+      public: float G() const;
+
+      /// \brief Get the blue value
+      /// \return The blue value
+      public: float B() const;
+
+      /// \brief Get the alpha value
+      /// \return The alpha value
+      public: float A() const;
+
+      /// \brief Get a mutable reference to the red value
+      /// \return The red value
+      public: float &R();
+
+      /// \brief Get a mutable reference to the green value
+      /// \return The green value
+      public: float &G();
+
+      /// \brief Get a mutable reference to the blue value
+      /// \return The blue value
+      public: float &B();
+
+      /// \brief Get a mutable reference to the alpha value
+      /// \return The alpha value
+      public: float &A();
+
+      /// \brief Set the red value
+      /// \param _r New red value
+      public: void R(const float _r);
+
+      /// \brief Set the green value
+      /// \param _r New green value
+      public: void G(const float _g);
+
+      /// \brief Set the blue value
+      /// \param _r New blue value
+      public: void B(const float _b);
+
+      /// \brief Set the alpha value
+      /// \param _r New alpha value
+      public: void A(const float _a);
+
+      /// \brief Red value
+      private: float r = 0;
+
+      /// \brief Green value
+      private: float g = 0;
+
+      /// \brief Blue value
+      private: float b = 0;
+
+      /// \brief Alpha value
+      private: float a = 1;
+    };
+  }
+}
+#endif
diff --git a/include/ignition/math/Filter.hh b/include/ignition/math/Filter.hh
new file mode 100644
index 0000000..dfe9ab3
--- /dev/null
+++ b/include/ignition/math/Filter.hh
@@ -0,0 +1,247 @@
+/*
+ * Copyright (C) 2014 Open Source Robotics Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+*/
+#ifndef IGNITION_MATH_FILTER_HH_
+#define IGNITION_MATH_FILTER_HH_
+
+#include <ignition/math/Helpers.hh>
+#include <ignition/math/Vector3.hh>
+#include <ignition/math/Quaternion.hh>
+
+namespace ignition
+{
+  namespace math
+  {
+    /// \class Filter Filter.hh ignition/math/Filter.hh
+    /// \brief Filter base class
+    template <class T>
+    class Filter
+    {
+      /// \brief Destructor.
+      public: virtual ~Filter() {}
+
+      /// \brief Set the output of the filter.
+      /// \param[in] _val New value.
+      public: virtual void Set(const T &_val)
+      {
+        y0 = _val;
+      }
+
+      /// \brief Set the cutoff frequency and sample rate.
+      /// \param[in] _fc Cutoff frequency.
+      /// \param[in] _fs Sample rate.
+      public: virtual void Fc(double _fc, double _fs) = 0;
+
+      /// \brief Get the output of the filter.
+      /// \return Filter's output.
+      public: virtual const T &Value() const
+      {
+        return y0;
+      }
+
+      /// \brief Output.
+      protected: T y0{};
+    };
+
+    /// \class OnePole Filter.hh ignition/math/Filter.hh
+    /// \brief A one-pole DSP filter.
+    /// \sa http://www.earlevel.com/main/2012/12/15/a-one-pole-filter/
+    template <class T>
+    class OnePole : public Filter<T>
+    {
+      /// \brief Constructor.
+      public: OnePole() = default;
+
+      /// \brief Constructor.
+      /// \param[in] _fc Cutoff frequency.
+      /// \param[in] _fs Sample rate.
+      public: OnePole(double _fc, double _fs)
+      {
+        this->Fc(_fc, _fs);
+      }
+
+      // Documentation Inherited.
+      public: virtual void Fc(double _fc, double _fs)
+      {
+        b1 = exp(-2.0 * IGN_PI * _fc / _fs);
+        a0 = 1.0 - b1;
+      }
+
+      /// \brief Update the filter's output.
+      /// \paran[in] _x Input value.
+      /// \return The filter's current output.
+      public: const T& Process(const T &_x)
+      {
+        this->y0 = a0 * _x + b1 * this->y0;
+        return this->y0;
+      }
+
+      /// \brief Input gain control.
+      protected: double a0 = 0;
+
+      /// \brief Gain of the feedback.
+      protected: double b1 = 0;
+    };
+
+    /// \class OnePoleQuaternion Filter.hh ignition/math/Filter.hh
+    /// \brief One-pole quaternion filter.
+    class OnePoleQuaternion : public OnePole<math::Quaterniond>
+    {
+      /// \brief Constructor.
+      public: OnePoleQuaternion()
+      {
+        this->Set(math::Quaterniond(1, 0, 0, 0));
+      }
+
+      /// \brief Constructor.
+      /// \param[in] _fc Cutoff frequency.
+      /// \param[in] _fs Sample rate.
+      public: OnePoleQuaternion(double _fc, double _fs)
+        : OnePole<math::Quaterniond>(_fc, _fs)
+      {
+        this->Set(math::Quaterniond(1, 0, 0, 0));
+      }
+
+      /// \brief Update the filter's output.
+      /// \paran[in] _x Input value.
+      /// \return The filter's current output.
+      public: const math::Quaterniond& Process(
+                  const math::Quaterniond &_x)
+      {
+        y0 = math::Quaterniond::Slerp(a0, y0, _x);
+        return y0;
+      }
+    };
+
+    /// \class OnePoleVector3 Filter.hh ignition/math/Filter.hh
+    /// \brief One-pole vector3 filter.
+    class OnePoleVector3 : public OnePole<math::Vector3d>
+    {
+      /// \brief Constructor.
+      public: OnePoleVector3()
+      {
+        this->Set(math::Vector3d(0, 0, 0));
+      }
+
+      /// \brief Constructor.
+      /// \param[in] _fc Cutoff frequency.
+      /// \param[in] _fs Sample rate.
+      public: OnePoleVector3(double _fc, double _fs)
+        : OnePole<math::Vector3d>(_fc, _fs)
+      {
+        this->Set(math::Vector3d(0, 0, 0));
+      }
+    };
+
+    /// \class BiQuad Filter.hh ignition/math/Filter.hh
+    /// \brief Bi-quad filter base class.
+    /// \sa http://www.earlevel.com/main/2003/03/02/the-bilinear-z-transform/
+    template <class T>
+    class BiQuad : public Filter<T>
+    {
+      /// \brief Constructor.
+      public: BiQuad() = default;
+
+      /// \brief Constructor.
+      /// \param[in] _fc Cutoff frequency.
+      /// \param[in] _fs Sample rate.
+      public: BiQuad(double _fc, double _fs)
+      {
+        this->Fc(_fc, _fs);
+      }
+
+      // Documentation Inherited.
+      public: void Fc(double _fc, double _fs)
+      {
+        this->Fc(_fc, _fs, 0.5);
+      }
+
+      /// \brief Set the cutoff frequency, sample rate and Q coefficient.
+      /// \param[in] _fc Cutoff frequency.
+      /// \param[in] _fs Sample rate.
+      /// \param[in] _q Q coefficient.
+      public: void Fc(double _fc, double _fs, double _q)
+      {
+        double k = tan(IGN_PI * _fc / _fs);
+        double kQuadDenom = k * k + k / _q + 1.0;
+        this->a0 = k * k/ kQuadDenom;
+        this->a1 = 2 * this->a0;
+        this->a2 = this->a0;
+        this->b0 = 1.0;
+        this->b1 = 2 * (k * k - 1.0) / kQuadDenom;
+        this->b2 = (k * k - k / _q + 1.0) / kQuadDenom;
+      }
+
+      /// \brief Set the current filter's output.
+      /// \param[in] _val New filter's output.
+      public: virtual void Set(const T &_val)
+      {
+        this->y0 = this->y1 = this->y2 = this->x1 = this->x2 = _val;
+      }
+
+      /// \brief Update the filter's output.
+      /// \param[in] _x Input value.
+      /// \return The filter's current output.
+      public: virtual const T& Process(const T &_x)
+      {
+        this->y0 = this->a0 * _x +
+                   this->a1 * this->x1 +
+                   this->a2 * this->x2 -
+                   this->b1 * this->y1 -
+                   this->b2 * this->y2;
+
+        this->x2 = this->x1;
+        this->x1 = _x;
+        this->y2 = this->y1;
+        this->y1 = this->y0;
+        return this->y0;
+      }
+
+      /// \brief Input gain control coefficients.
+      protected: double a0 = 0,
+                        a1 = 0,
+                        a2 = 0,
+                        b0 = 0,
+                        b1 = 0,
+                        b2 = 0;
+
+      /// \brief Gain of the feedback coefficients.
+      protected: T x1{}, x2{}, y1{}, y2{};
+    };
+
+    /// \class BiQuadVector3 Filter.hh ignition/math/Filter.hh
+    /// \brief BiQuad vector3 filter
+    class BiQuadVector3 : public BiQuad<math::Vector3d>
+    {
+      /// \brief Constructor.
+      public: BiQuadVector3()
+      {
+        this->Set(math::Vector3d(0, 0, 0));
+      }
+
+      /// \brief Constructor.
+      /// \param[in] _fc Cutoff frequency.
+      /// \param[in] _fs Sample rate.
+      public: BiQuadVector3(double _fc, double _fs)
+        : BiQuad<math::Vector3d>(_fc, _fs)
+      {
+        this->Set(math::Vector3d(0, 0, 0));
+      }
+    };
+  }
+}
+
+#endif
diff --git a/include/ignition/math/Frustum.hh b/include/ignition/math/Frustum.hh
new file mode 100644
index 0000000..04aa88b
--- /dev/null
+++ b/include/ignition/math/Frustum.hh
@@ -0,0 +1,181 @@
+/*
+ * Copyright (C) 2015 Open Source Robotics Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+*/
+#ifndef IGNITION_MATH_FRUSTUM_HH_
+#define IGNITION_MATH_FRUSTUM_HH_
+
+#include <ignition/math/Plane.hh>
+#include <ignition/math/Angle.hh>
+#include <ignition/math/Pose3.hh>
+
+namespace ignition
+{
+  namespace math
+  {
+    // Forward declaration of private data
+    class FrustumPrivate;
+
+    /// \brief Mathematical representation of a frustum and related functions.
+    /// This is also known as a view frustum.
+    class IGNITION_MATH_VISIBLE Frustum
+    {
+      /// \brief Planes that define the boundaries of the frustum.
+      public: enum FrustumPlane
+      {
+        /// \brief Near plane
+        FRUSTUM_PLANE_NEAR   = 0,
+
+        /// \brief Far plane
+        FRUSTUM_PLANE_FAR    = 1,
+
+        /// \brief Left plane
+        FRUSTUM_PLANE_LEFT   = 2,
+
+        /// \brief Right plane
+        FRUSTUM_PLANE_RIGHT  = 3,
+
+        /// \brief Top plane
+        FRUSTUM_PLANE_TOP    = 4,
+
+        /// \brief Bottom plane
+        FRUSTUM_PLANE_BOTTOM = 5
+      };
+
+      /// \brief Default constructor. With the following default values:
+      ///
+      /// * near: 0.0
+      /// * far: 1.0
+      /// * fov: 0.78539 radians (45 degrees)
+      /// * aspect ratio: 1.0
+      /// * pose: Pose3d::Zero
+      public: Frustum();
+
+      /// \brief Constructor
+      /// \param[in] _near Near plane distance. This is the distance from
+      /// the frustum's vertex to the closest plane
+      /// \param[in] _far Far plane distance. This is the distance from the
+      /// frustum's vertex to the farthest plane.
+      /// \param[in] _fov Field of view. The field of view is the
+      /// angle between the frustum's vertex and the edges of the near or far
+      /// plane. This value represents the horizontal angle.
+      /// \param[in] _aspectRatio The aspect ratio, which is the width divided
+      /// by height of the near or far planes.
+      /// \param[in] _pose Pose of the frustum, which is the vertex (top of
+      /// the pyramid).
+      public: Frustum(const double _near,
+                      const double _far,
+                      const math::Angle &_fov,
+                      const double _aspectRatio,
+                      const math::Pose3d &_pose = math::Pose3d::Zero);
+
+      /// \brief Copy Constructor
+      /// \param[in] _p Frustum to copy.
+      public: Frustum(const Frustum &_p);
+
+      /// \brief Destructor
+      public: virtual ~Frustum();
+
+      /// \brief Get the near distance. This is the distance from the
+      /// frustum's vertex to the closest plane.
+      /// \return Near distance.
+      /// \sa SetNear
+      public: double Near() const;
+
+      /// \brief Set the near distance. This is the distance from the
+      /// frustum's vertex to the closest plane.
+      /// \param[in] _near Near distance.
+      /// \sa Near
+      public: void SetNear(const double _near);
+
+      /// \brief Get the far distance. This is the distance from the
+      /// frustum's vertex to the farthest plane.
+      /// \return Far distance.
+      /// \sa SetFar
+      public: double Far() const;
+
+      /// \brief Set the far distance. This is the distance from the
+      /// frustum's vertex to the farthest plane.
+      /// \param[in] _far Far distance.
+      /// \sa Far
+      public: void SetFar(const double _far);
+
+      /// \brief Get the horizontal field of view. The field of view is the
+      /// angle between the frustum's vertex and the edges of the near or far
+      /// plane. This value represents the horizontal angle.
+      /// \return The field of view.
+      /// \sa SetFOV
+      public: math::Angle FOV() const;
+
+      /// \brief Set the horizontal field of view. The field of view is the
+      /// angle between the frustum's vertex and the edges of the near or far
+      /// plane. This value represents the horizontal angle.
+      /// \param[in] _fov The field of view.
+      /// \sa FOV
+      public: void SetFOV(const math::Angle &_fov);
+
+      /// \brief Get the aspect ratio, which is the width divided by height
+      /// of the near or far planes.
+      /// \return The frustum's aspect ratio.
+      /// \sa SetAspectRatio
+      public: double AspectRatio() const;
+
+      /// \brief Set the aspect ratio, which is the width divided by height
+      /// of the near or far planes.
+      /// \param[in] _aspectRatio The frustum's aspect ratio.
+      /// \sa AspectRatio
+      public: void SetAspectRatio(const double _aspectRatio);
+
+      /// \brief Get a plane of the frustum.
+      /// \param[in] _plane The plane to return.
+      /// \return Plane of the frustum.
+      public: Planed Plane(const FrustumPlane _plane) const;
+
+      /// \brief Check if a box lies inside the pyramid frustum.
+      /// \param[in] _b Box to check.
+      /// \return True if the box is inside the pyramid frustum.
+      public: bool Contains(const Box &_b) const;
+
+      /// \brief Check if a point lies inside the pyramid frustum.
+      /// \param[in] _p Point to check.
+      /// \return True if the point is inside the pyramid frustum.
+      public: bool Contains(const Vector3d &_p) const;
+
+      /// \brief Get the pose of the frustum
+      /// \return Pose of the frustum
+      /// \sa SetPose
+      public: Pose3d Pose() const;
+
+      /// \brief Set the pose of the frustum
+      /// \param[in] _pose Pose of the frustum, top vertex.
+      /// \sa Pose
+      public: void SetPose(const Pose3d &_pose);
+
+      /// \brief Assignment operator. Set this frustum to the parameter.
+      /// \param[in]  _b Frustum to copy
+      /// \return The new frustum.
+      public: Frustum &operator=(const Frustum &_f);
+
+      /// \brief Compute the planes of the frustum. This is called whenever
+      /// a property of the frustum is changed.
+      private: void ComputePlanes();
+
+      /// \internal
+      /// \brief Private data pointer
+      private: FrustumPrivate *dataPtr;
+    };
+  }
+}
+#endif
diff --git a/include/ignition/math/Helpers.hh b/include/ignition/math/Helpers.hh
new file mode 100644
index 0000000..fb4eecd
--- /dev/null
+++ b/include/ignition/math/Helpers.hh
@@ -0,0 +1,770 @@
+/*
+ * Copyright (C) 2012 Open Source Robotics Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+*/
+#ifndef IGNITION_MATH_FUNCTIONS_HH_
+#define IGNITION_MATH_FUNCTIONS_HH_
+
+#include <cmath>
+#include <algorithm>
+#include <limits>
+#include <string>
+#include <iostream>
+#include <vector>
+#include <tuple>
+#include <cstdint>
+
+#include "ignition/math/Export.hh"
+
+/// \brief Double maximum value. This value will be similar to 1.79769e+308
+/// \deprecated Use static const value instead.
+#define IGN_DBL_MAX ignition::math::DPRCT_MAX_D
+
+/// \brief Double min value. This value will be similar to 2.22507e-308
+/// \deprecated Use static const value instead.
+#define IGN_DBL_MIN ignition::math::DPRCT_MIN_D
+
+/// \brief Double low value, equivalent to -IGN_DBL_MAX
+/// \deprecated Use static const value instead.
+#define IGN_DBL_LOW ignition::math::DPRCT_LOW_D
+
+/// \brief Double positive infinite value
+/// \deprecated Use static const value instead.
+#define IGN_DBL_INF ignition::math::DPRCT_INF_D
+
+/// \brief Float maximum value. This value will be similar to 3.40282e+38
+/// \deprecated Use static const value instead.
+#define IGN_FLT_MAX ignition::math::DPRCT_MAX_F
+
+/// \brief Float minimum value. This value will be similar to 1.17549e-38
+/// \deprecated Use static const value instead.
+#define IGN_FLT_MIN ignition::math::DPRCT_MIN_F
+
+/// \brief Float lowest value, equivalent to -IGN_FLT_MAX
+/// \deprecated Use static const value instead.
+#define IGN_FLT_LOW ignition::math::DPRCT_LOW_F
+
+/// \brief Float positive infinite value
+/// \deprecated Use static const value instead.
+#define IGN_FLT_INF ignition::math::DPRCT_INF_F
+
+/// \brief 16bit unsigned integer maximum value
+/// \deprecated Use static const value instead.
+#define IGN_UINT16_MAX ignition::math::DPRCT_MAX_UI16
+
+/// \brief 16bit unsigned integer minimum value
+/// \deprecated Use static const value instead.
+#define IGN_UINT16_MIN ignition::math::DPRCT_MIN_UI16
+
+/// \brief 16bit unsigned integer lowest value. This is equivalent to
+/// IGN_UINT16_MIN, and is defined here for completeness.
+/// \deprecated Use static const value instead.
+#define IGN_UINT16_LOW ignition::math::DPRCT_LOW_UI16
+
+/// \brief 16-bit unsigned integer positive infinite value
+/// \deprecated Use static const value instead.
+#define IGN_UINT16_INF ignition::math::DPRCT_INF_UI16
+
+/// \brief 16bit integer maximum value
+/// \deprecated Use static const value instead.
+#define IGN_INT16_MAX ignition::math::DPRCT_MAX_I16
+
+/// \brief 16bit integer minimum value
+/// \deprecated Use static const value instead.
+#define IGN_INT16_MIN ignition::math::DPRCT_MIN_I16
+
+/// \brief 16bit integer lowest value. This is equivalent to IGN_INT16_MIN,
+/// and is defined here for completeness.
+/// \deprecated Use static const value instead.
+#define IGN_INT16_LOW ignition::math::DPRCT_LOW_I16
+
+/// \brief 16-bit integer positive infinite value
+/// \deprecated Use static const value instead.
+#define IGN_INT16_INF ignition::math::DPRCT_INF_I16
+
+/// \brief 32bit unsigned integer maximum value
+/// \deprecated Use static const value instead.
+#define IGN_UINT32_MAX ignition::math::DPRCT_MAX_UI32
+
+/// \brief 32bit unsigned integer minimum value
+/// \deprecated Use static const value instead.
+#define IGN_UINT32_MIN ignition::math::DPRCT_MIN_UI32
+
+/// \brief 32bit unsigned integer lowest value. This is equivalent to
+/// IGN_UINT32_MIN, and is defined here for completeness.
+/// \deprecated Use static const value instead.
+#define IGN_UINT32_LOW ignition::math::DPRCT_LOW_UI32
+
+/// \brief 32-bit unsigned integer positive infinite value
+/// \deprecated Use static const value instead.
+#define IGN_UINT32_INF ignition::math::DPRCT_INF_UI32
+
+/// \brief 32bit integer maximum value
+/// \deprecated Use static const value instead.
+#define IGN_INT32_MAX ignition::math::DPRCT_MAX_I32
+
+/// \brief 32bit integer minimum value
+/// \deprecated Use static const value instead.
+#define IGN_INT32_MIN ignition::math::DPRCT_MIN_I32
+
+/// \brief 32bit integer minimum value. This is equivalent to IGN_INT32_MIN,
+/// and is defined here for completeness.
+/// \deprecated Use static const value instead.
+#define IGN_INT32_LOW ignition::math::DPRCT_LOW_I32
+
+/// \brief 32-bit integer positive infinite value
+/// \deprecated Use static const value instead.
+#define IGN_INT32_INF ignition::math::DPRCT_INF_I32
+
+/// \brief 64bit unsigned integer maximum value
+/// \deprecated Use static const value instead.
+#define IGN_UINT64_MAX ignition::math::DPRCT_MAX_UI64
+
+/// \brief 64bit unsigned integer minimum value
+/// \deprecated Use static const value instead.
+#define IGN_UINT64_MIN ignition::math::DPRCT_MIN_UI64
+
+/// \brief 64bit unsigned integer lowest value. This is equivalent to
+/// IGN_UINT64_MIN, and is defined here for completeness.
+/// \deprecated Use static const value instead.
+#define IGN_UINT64_LOW ignition::math::DPRCT_LOW_UI64
+
+/// \brief 64-bit unsigned integer positive infinite value
+/// \deprecated Use static const value instead.
+#define IGN_UINT64_INF ignition::math::DPRCT_INF_UI64
+
+/// \brief 64bit integer maximum value
+/// \deprecated Use static const value instead.
+#define IGN_INT64_MAX ignition::math::DPRCT_MAX_I64
+
+/// \brief 64bit integer minimum value
+/// \deprecated Use static const value instead.
+#define IGN_INT64_MIN ignition::math::DPRCT_MIN_I64
+
+/// \brief 64bit integer lowest value. This is equivalent to IGN_INT64_MIN,
+/// and is defined here for completeness.
+/// \deprecated Use static const value instead.
+#define IGN_INT64_LOW ignition::math::DPRCT_LOW_I64
+
+/// \brief 64-bit integer positive infinite value
+/// \deprecated Use static const value instead.
+#define IGN_INT64_INF ignition::math::DPRCT_INF_I64
+
+/// \brief Define IGN_PI, IGN_PI_2, and IGN_PI_4.
+/// This was put here for Windows support.
+#ifdef M_PI
+#define IGN_PI M_PI
+#define IGN_PI_2 M_PI_2
+#define IGN_PI_4 M_PI_4
+#define IGN_SQRT2 M_SQRT2
+#else
+#define IGN_PI   3.14159265358979323846
+#define IGN_PI_2 1.57079632679489661923
+#define IGN_PI_4 0.78539816339744830962
+#define IGN_SQRT2 1.41421356237309504880
+#endif
+
+/// \brief Define IGN_FP_VOLATILE for FP equality comparisons
+/// Use volatile parameters when checking floating point equality on
+/// the 387 math coprocessor to work around bugs from the 387 extra precision
+#if defined __FLT_EVAL_METHOD__  &&  __FLT_EVAL_METHOD__ == 2
+#define IGN_FP_VOLATILE volatile
+#else
+#define IGN_FP_VOLATILE
+#endif
+
+/// \brief Compute sphere volume
+/// \param[in] _radius Sphere radius
+#define IGN_SPHERE_VOLUME(_radius) (4.0*IGN_PI*std::pow(_radius, 3)/3.0)
+
+/// \brief Compute cylinder volume
+/// \param[in] _r Cylinder base radius
+/// \param[in] _l Cylinder length
+#define IGN_CYLINDER_VOLUME(_r, _l) (_l * IGN_PI * std::pow(_r, 2))
+
+/// \brief Compute box volume
+/// \param[in] _x X length
+/// \param[in] _y Y length
+/// \param[in] _z Z length
+#define IGN_BOX_VOLUME(_x, _y, _z) (_x *_y * _z)
+
+/// \brief Compute box volume from a vector
+/// \param[in] _v Vector3d that contains the box's dimensions.
+#define IGN_BOX_VOLUME_V(_v) (_v.X() *_v.Y() * _v.Z())
+
+namespace ignition
+{
+  /// \brief Math classes and function useful in robot applications.
+  namespace math
+  {
+    /// \brief size_t type with a value of 0
+    static const size_t IGN_ZERO_SIZE_T  = 0u;
+
+    /// \brief size_t type with a value of 1
+    static const size_t IGN_ONE_SIZE_T   = 1u;
+
+    /// \brief size_t type with a value of 2
+    static const size_t IGN_TWO_SIZE_T   = 2u;
+
+    /// \brief size_t type with a value of 3
+    static const size_t IGN_THREE_SIZE_T = 3u;
+
+    /// \brief size_t type with a value of 4
+    static const size_t IGN_FOUR_SIZE_T  = 4u;
+
+    /// \brief size_t type with a value of 5
+    static const size_t IGN_FIVE_SIZE_T  = 5u;
+
+    /// \brief size_t type with a value of 6
+    static const size_t IGN_SIX_SIZE_T   = 6u;
+
+    /// \brief size_t type with a value of 7
+    static const size_t IGN_SEVEN_SIZE_T = 7u;
+
+    /// \brief size_t type with a value of 8
+    static const size_t IGN_EIGHT_SIZE_T = 8u;
+
+    /// \brief size_t type with a value of 9
+    static const size_t IGN_NINE_SIZE_T  = 9u;
+
+    /// \brief Double maximum value. This value will be similar to 1.79769e+308
+    static const double MAX_D = std::numeric_limits<double>::max();
+
+    /// \brief Double min value. This value will be similar to 2.22507e-308
+    static const double MIN_D = std::numeric_limits<double>::min();
+
+    /// \brief Double low value, equivalent to -MAX_D
+    static const double LOW_D = std::numeric_limits<double>::lowest();
+
+    /// \brief Double positive infinite value
+    static const double INF_D = std::numeric_limits<double>::infinity();
+
+    /// \brief Returns the representation of a quiet not a number (NAN)
+    static const double NAN_D = std::numeric_limits<double>::quiet_NaN();
+
+    /// \brief Float maximum value. This value will be similar to 3.40282e+38
+    static const float MAX_F = std::numeric_limits<float>::max();
+
+    /// \brief Float minimum value. This value will be similar to 1.17549e-38
+    static const float MIN_F = std::numeric_limits<float>::min();
+
+    /// \brief Float low value, equivalent to -MAX_F
+    static const float LOW_F = std::numeric_limits<float>::lowest();
+
+    /// \brief float positive infinite value
+    static const float INF_F = std::numeric_limits<float>::infinity();
+
+    /// \brief Returns the representation of a quiet not a number (NAN)
+    static const float NAN_F = std::numeric_limits<float>::quiet_NaN();
+
+    /// \brief 16bit unsigned integer maximum value
+    static const uint16_t MAX_UI16 = std::numeric_limits<uint16_t>::max();
+
+    /// \brief 16bit unsigned integer minimum value
+    static const uint16_t MIN_UI16 = std::numeric_limits<uint16_t>::min();
+
+    /// \brief 16bit unsigned integer lowest value. This is equivalent to
+    /// IGN_UINT16_MIN, and is defined here for completeness.
+    static const uint16_t LOW_UI16 = std::numeric_limits<uint16_t>::lowest();
+
+    /// \brief 16-bit unsigned integer positive infinite value
+    static const uint16_t INF_UI16 = std::numeric_limits<uint16_t>::infinity();
+
+    /// \brief 16bit unsigned integer maximum value
+    static const int16_t MAX_I16 = std::numeric_limits<int16_t>::max();
+
+    /// \brief 16bit unsigned integer minimum value
+    static const int16_t MIN_I16 = std::numeric_limits<int16_t>::min();
+
+    /// \brief 16bit unsigned integer lowest value. This is equivalent to
+    /// IGN_INT16_MIN, and is defined here for completeness.
+    static const int16_t LOW_I16 = std::numeric_limits<int16_t>::lowest();
+
+    /// \brief 16-bit unsigned integer positive infinite value
+    static const int16_t INF_I16 = std::numeric_limits<int16_t>::infinity();
+
+    /// \brief 32bit unsigned integer maximum value
+    static const uint32_t MAX_UI32 = std::numeric_limits<uint32_t>::max();
+
+    /// \brief 32bit unsigned integer minimum value
+    static const uint32_t MIN_UI32 = std::numeric_limits<uint32_t>::min();
+
+    /// \brief 32bit unsigned integer lowest value. This is equivalent to
+    /// IGN_UINT32_MIN, and is defined here for completeness.
+    static const uint32_t LOW_UI32 = std::numeric_limits<uint32_t>::lowest();
+
+    /// \brief 32-bit unsigned integer positive infinite value
+    static const uint32_t INF_UI32 = std::numeric_limits<uint32_t>::infinity();
+
+    /// \brief 32bit unsigned integer maximum value
+    static const int32_t MAX_I32 = std::numeric_limits<int32_t>::max();
+
+    /// \brief 32bit unsigned integer minimum value
+    static const int32_t MIN_I32 = std::numeric_limits<int32_t>::min();
+
+    /// \brief 32bit unsigned integer lowest value. This is equivalent to
+    /// IGN_INT32_MIN, and is defined here for completeness.
+    static const int32_t LOW_I32 = std::numeric_limits<int32_t>::lowest();
+
+    /// \brief 32-bit unsigned integer positive infinite value
+    static const int32_t INF_I32 = std::numeric_limits<int32_t>::infinity();
+
+    /// \brief 64bit unsigned integer maximum value
+    static const uint64_t MAX_UI64 = std::numeric_limits<uint64_t>::max();
+
+    /// \brief 64bit unsigned integer minimum value
+    static const uint64_t MIN_UI64 = std::numeric_limits<uint64_t>::min();
+
+    /// \brief 64bit unsigned integer lowest value. This is equivalent to
+    /// IGN_UINT64_MIN, and is defined here for completeness.
+    static const uint64_t LOW_UI64 = std::numeric_limits<uint64_t>::lowest();
+
+    /// \brief 64-bit unsigned integer positive infinite value
+    static const uint64_t INF_UI64 = std::numeric_limits<uint64_t>::infinity();
+
+    /// \brief 64bit unsigned integer maximum value
+    static const int64_t MAX_I64 = std::numeric_limits<int64_t>::max();
+
+    /// \brief 64bit unsigned integer minimum value
+    static const int64_t MIN_I64 = std::numeric_limits<int64_t>::min();
+
+    /// \brief 64bit unsigned integer lowest value. This is equivalent to
+    /// IGN_INT64_MIN, and is defined here for completeness.
+    static const int64_t LOW_I64 = std::numeric_limits<int64_t>::lowest();
+
+    /// \brief 64-bit unsigned integer positive infinite value
+    static const int64_t INF_I64 = std::numeric_limits<int64_t>::infinity();
+
+    /// \brief Returns the representation of a quiet not a number (NAN)
+    static const int NAN_I = std::numeric_limits<int>::quiet_NaN();
+
+    // variables created to deprecate macros in this file
+    static const double IGN_DEPRECATED(2) DPRCT_MAX_D = MAX_D;
+    static const double IGN_DEPRECATED(2) DPRCT_MIN_D = MIN_D;
+    static const double IGN_DEPRECATED(2) DPRCT_LOW_D = LOW_D;
+    static const double IGN_DEPRECATED(2) DPRCT_INF_D = INF_D;
+    static const float IGN_DEPRECATED(2) DPRCT_MAX_F = MAX_F;
+    static const float IGN_DEPRECATED(2) DPRCT_MIN_F = MIN_F;
+    static const float IGN_DEPRECATED(2) DPRCT_LOW_F = LOW_F;
+    static const float IGN_DEPRECATED(2) DPRCT_INF_F = INF_F;
+    static const uint16_t IGN_DEPRECATED(2) DPRCT_MAX_UI16 = MAX_UI16;
+    static const uint16_t IGN_DEPRECATED(2) DPRCT_MIN_UI16 = MIN_UI16;
+    static const uint16_t IGN_DEPRECATED(2) DPRCT_LOW_UI16 = LOW_UI16;
+    static const uint16_t IGN_DEPRECATED(2) DPRCT_INF_UI16 = INF_UI16;
+    static const int16_t IGN_DEPRECATED(2) DPRCT_MAX_I16 = MAX_I16;
+    static const int16_t IGN_DEPRECATED(2) DPRCT_MIN_I16 = MIN_I16;
+    static const int16_t IGN_DEPRECATED(2) DPRCT_LOW_I16 = LOW_I16;
+    static const int16_t IGN_DEPRECATED(2) DPRCT_INF_I16 = INF_I16;
+    static const uint32_t IGN_DEPRECATED(2) DPRCT_MAX_UI32 = MAX_UI32;
+    static const uint32_t IGN_DEPRECATED(2) DPRCT_MIN_UI32 = MIN_UI32;
+    static const uint32_t IGN_DEPRECATED(2) DPRCT_LOW_UI32 = LOW_UI32;
+    static const uint32_t IGN_DEPRECATED(2) DPRCT_INF_UI32 = INF_UI32;
+    static const int32_t IGN_DEPRECATED(2) DPRCT_MAX_I32 = MAX_I32;
+    static const int32_t IGN_DEPRECATED(2) DPRCT_MIN_I32 = MIN_I32;
+    static const int32_t IGN_DEPRECATED(2) DPRCT_LOW_I32 = LOW_I32;
+    static const int32_t IGN_DEPRECATED(2) DPRCT_INF_I32 = INF_I32;
+    static const uint64_t IGN_DEPRECATED(2) DPRCT_MAX_UI64 = MAX_UI64;
+    static const uint64_t IGN_DEPRECATED(2) DPRCT_MIN_UI64 = MIN_UI64;
+    static const uint64_t IGN_DEPRECATED(2) DPRCT_LOW_UI64 = LOW_UI64;
+    static const uint64_t IGN_DEPRECATED(2) DPRCT_INF_UI64 = INF_UI64;
+    static const int64_t IGN_DEPRECATED(2) DPRCT_MAX_I64 = MAX_I64;
+    static const int64_t IGN_DEPRECATED(2) DPRCT_MIN_I64 = MIN_I64;
+    static const int64_t IGN_DEPRECATED(2) DPRCT_LOW_I64 = LOW_I64;
+    static const int64_t IGN_DEPRECATED(2) DPRCT_INF_I64 = INF_I64;
+
+    /// \brief Simple clamping function
+    /// \param[in] _v value
+    /// \param[in] _min minimum
+    /// \param[in] _max maximum
+    template<typename T>
+    inline T clamp(T _v, T _min, T _max)
+    {
+      return std::max(std::min(_v, _max), _min);
+    }
+
+    /// \brief check if a float is NaN
+    /// \param[in] _v the value
+    /// \return true if _v is not a number, false otherwise
+    inline bool isnan(float _v)
+    {
+      return (std::isnan)(_v);
+    }
+
+    /// \brief check if a double is NaN
+    /// \param[in] _v the value
+    /// \return true if _v is not a number, false otherwise
+    inline bool isnan(double _v)
+    {
+      return (std::isnan)(_v);
+    }
+
+    /// \brief Fix a nan value.
+    /// \param[in] _v Value to correct.
+    /// \return 0 if _v is NaN, _v otherwise.
+    inline float fixnan(float _v)
+    {
+      return isnan(_v) || std::isinf(_v) ? 0.0f : _v;
+    }
+
+    /// \brief Fix a nan value.
+    /// \param[in] _v Value to correct.
+    /// \return 0 if _v is NaN, _v otherwise.
+    inline double fixnan(double _v)
+    {
+      return isnan(_v) || std::isinf(_v) ? 0.0 : _v;
+    }
+
+    /// \brief Check if parameter is even.
+    /// \param[in] _v Value to check.
+    /// \return True if _v is even.
+    inline bool isEven(const int _v)
+    {
+      return !(_v % 2);
+    }
+
+    /// \brief Check if parameter is even.
+    /// \param[in] _v Value to check.
+    /// \return True if _v is even.
+    inline bool isEven(const unsigned int _v)
+    {
+      return !(_v % 2);
+    }
+
+    /// \brief Check if parameter is odd.
+    /// \param[in] _v Value to check.
+    /// \return True if _v is odd.
+    inline bool isOdd(const int _v)
+    {
+      return (_v % 2) != 0;
+    }
+
+    /// \brief Check if parameter is odd.
+    /// \param[in] _v Value to check.
+    /// \return True if _v is odd.
+    inline bool isOdd(const unsigned int _v)
+    {
+      return (_v % 2) != 0;
+    }
+
+    /// \brief The signum function.
+    ///
+    /// Returns 0 for zero values, -1 for negative values,
+    /// +1 for positive values.
+    /// \param[in] _value The value.
+    /// \return The signum of the value.
+    template<typename T>
+    inline int sgn(T _value)
+    {
+      return (T(0) < _value) - (_value < T(0));
+    }
+
+    /// \brief The signum function.
+    ///
+    /// Returns 0 for zero values, -1 for negative values,
+    /// +1 for positive values.
+    /// \param[in] _value The value.
+    /// \return The signum of the value.
+    template<typename T>
+    inline int signum(T _value)
+    {
+      return sgn(_value);
+    }
+
+    /// \brief get mean of vector of values
+    /// \param[in] _values the vector of values
+    /// \return the mean
+    template<typename T>
+    inline T mean(const std::vector<T> &_values)
+    {
+      T sum = 0;
+      for (unsigned int i = 0; i < _values.size(); ++i)
+        sum += _values[i];
+      return sum / _values.size();
+    }
+
+    /// \brief get variance of vector of values
+    /// \param[in] _values the vector of values
+    /// \return the squared deviation
+    template<typename T>
+    inline T variance(const std::vector<T> &_values)
+    {
+      T avg = mean<T>(_values);
+
+      T sum = 0;
+      for (unsigned int i = 0; i < _values.size(); ++i)
+        sum += (_values[i] - avg) * (_values[i] - avg);
+      return sum / _values.size();
+    }
+
+    /// \brief get the maximum value of vector of values
+    /// \param[in] _values the vector of values
+    /// \return maximum
+    template<typename T>
+    inline T max(const std::vector<T> &_values)
+    {
+      T max = std::numeric_limits<T>::min();
+      for (unsigned int i = 0; i < _values.size(); ++i)
+        if (_values[i] > max)
+          max = _values[i];
+      return max;
+    }
+
+    /// \brief get the minimum value of vector of values
+    /// \param[in] _values the vector of values
+    /// \return minimum
+    template<typename T>
+    inline T min(const std::vector<T> &_values)
+    {
+      T min = std::numeric_limits<T>::max();
+      for (unsigned int i = 0; i < _values.size(); ++i)
+        if (_values[i] < min)
+          min = _values[i];
+      return min;
+    }
+
+    /// \brief check if two values are equal, within a tolerance
+    /// \param[in] _a the first value
+    /// \param[in] _b the second value
+    /// \param[in] _epsilon the tolerance
+    template<typename T>
+    inline bool equal(const T &_a, const T &_b,
+                      const T &_epsilon = T(1e-6))
+    {
+      IGN_FP_VOLATILE T diff = std::abs(_a - _b);
+      return diff <= _epsilon;
+    }
+
+    /// \brief inequality test, within a tolerance
+    /// \param[in] _a the first value
+    /// \param[in] _b the second value
+    /// \param[in] _epsilon the tolerance
+    template<typename T>
+    inline bool lessOrNearEqual(const T &_a, const T &_b,
+                            const T &_epsilon = 1e-6)
+    {
+      return _a < _b + _epsilon;
+    }
+
+    /// \brief inequality test, within a tolerance
+    /// \param[in] _a the first value
+    /// \param[in] _b the second value
+    /// \param[in] _epsilon the tolerance
+    template<typename T>
+    inline bool greaterOrNearEqual(const T &_a, const T &_b,
+                               const T &_epsilon = 1e-6)
+    {
+      return _a > _b - _epsilon;
+    }
+
+    /// \brief get value at a specified precision
+    /// \param[in] _a the number
+    /// \param[in] _precision the precision
+    /// \return the value for the specified precision
+    template<typename T>
+    inline T precision(const T &_a, const unsigned int &_precision)
+    {
+      auto p = std::pow(10, _precision);
+      return static_cast<T>(std::round(_a * p) / p);
+    }
+
+    /// \brief Sort two numbers, such that _a <= _b
+    /// \param[out] _a the first number
+    /// \param[out] _b the second number
+    template<typename T>
+    inline void sort2(T &_a, T &_b)
+    {
+      using std::swap;
+      if (_b < _a)
+        swap(_a, _b);
+    }
+
+    /// \brief Sort three numbers, such that _a <= _b <= _c
+    /// \param[out] _a the first number
+    /// \param[out] _b the second number
+    /// \param[out] _c the third number
+    template<typename T>
+    inline void sort3(T &_a, T &_b, T &_c)
+    {
+      // _a <= _b
+      sort2(_a, _b);
+      // _a <= _c, _b <= _c
+      sort2(_b, _c);
+      // _a <= _b <= _c
+      sort2(_a, _b);
+    }
+
+    /// \brief Is this a power of 2?
+    /// \param[in] _x the number
+    /// \return true if _x is a power of 2, false otherwise
+    inline bool isPowerOfTwo(unsigned int _x)
+    {
+      return ((_x != 0) && ((_x & (~_x + 1)) == _x));
+    }
+
+    /// \brief Get the smallest power of two that is greater or equal to
+    /// a given value
+    /// \param[in] _x the number
+    /// \return the same value if _x is already a power of two. Otherwise,
+    /// it returns the smallest power of two that is greater than _x
+    inline unsigned int roundUpPowerOfTwo(unsigned int _x)
+    {
+      if (_x == 0)
+        return 1;
+
+      if (isPowerOfTwo(_x))
+        return _x;
+
+      while (_x & (_x - 1))
+        _x = _x & (_x - 1);
+
+      _x = _x << 1;
+
+      return _x;
+    }
+
+    /// \brief parse string into an integer
+    /// \param[in] _input the string
+    /// \return an integer, 0 or 0 and a message in the error stream
+    inline int parseInt(const std::string &_input)
+    {
+      const char *p = _input.c_str();
+      if (!*p || *p == '?')
+        return NAN_I;
+
+      int s = 1;
+      while (*p == ' ')
+        p++;
+
+      if (*p == '-')
+      {
+        s = -1;
+        p++;
+      }
+
+      int acc = 0;
+      while (*p >= '0' && *p <= '9')
+        acc = acc * 10 + *p++ - '0';
+
+      if (*p)
+      {
+        std::cerr << "Invalid int numeric format[" << _input << "]\n";
+        return NAN_I;
+      }
+
+      return s * acc;
+    }
+
+    /// \brief parse string into float
+    /// \param _input the string
+    /// \return a floating point number (can be NaN) or 0 with a message in the
+    /// error stream
+    inline double parseFloat(const std::string &_input)
+    {
+      const char *p = _input.c_str();
+      if (!*p || *p == '?')
+        return NAN_D;
+      int s = 1;
+      while (*p == ' ')
+        p++;
+
+      if (*p == '-')
+      {
+        s = -1;
+        p++;
+      }
+
+      double acc = 0;
+      while (*p >= '0' && *p <= '9')
+        acc = acc * 10 + *p++ - '0';
+
+      if (*p == '.')
+      {
+        double k = 0.1;
+        p++;
+        while (*p >= '0' && *p <= '9')
+        {
+          acc += (*p++ - '0') * k;
+          k *= 0.1;
+        }
+      }
+      if (*p == 'e')
+      {
+        int es = 1;
+        int f = 0;
+        p++;
+        if (*p == '-')
+        {
+          es = -1;
+          p++;
+        }
+        else if (*p == '+')
+        {
+          es = 1;
+          p++;
+        }
+        while (*p >= '0' && *p <= '9')
+          f = f * 10 + *p++ - '0';
+
+        acc *= pow(10, f*es);
+      }
+
+      if (*p)
+      {
+        std::cerr << "Invalid double numeric format[" << _input << "]\n";
+        return NAN_D;
+      }
+      return s * acc;
+    }
+
+
+    // Degrade precision on Windows, which cannot handle 'long double'
+    // values properly. See the implementation of Unpair.
+#ifdef _MSC_VER
+    using PairInput = uint16_t;
+    using PairOutput = uint32_t;
+#else
+    using PairInput = uint32_t;
+    using PairOutput = uint64_t;
+#endif
+
+    /// \brief A pairing function that maps two values to a unique third
+    /// value. This is an implement of Szudzik's function.
+    /// \param[in] _a First value, must be a non-negative integer. On
+    /// Windows this value is uint16_t. On Linux/OSX this value is uint32_t.
+    /// \param[in] _b Second value, must be a non-negative integer. On
+    /// Windows this value is uint16_t. On Linux/OSX this value is uint32_t.
+    /// \return A unique non-negative integer value. On Windows the return
+    /// value is uint32_t. On Linux/OSX the return value is uint64_t
+    /// \sa Unpair
+    PairOutput IGNITION_MATH_VISIBLE Pair(
+        const PairInput _a, const PairInput _b);
+
+    /// \brief The reverse of the Pair function. Accepts a key, produced
+    /// from the Pair function, and returns a tuple consisting of the two
+    /// non-negative integer values used to create the _key.
+    /// \param[in] _key A non-negative integer generated from the Pair
+    /// function. On Windows this value is uint32_t. On Linux/OSX, this
+    /// value is uint64_t.
+    /// \return A tuple that consists of the two non-negative integers that
+    /// will generate _key when used with the Pair function. On Windows the
+    /// tuple contains two uint16_t values. On Linux/OSX the tuple contains
+    /// two uint32_t values.
+    /// \sa Pair
+    std::tuple<PairInput, PairInput> IGNITION_MATH_VISIBLE Unpair(
+        const PairOutput _key);
+  }
+}
+
+#endif
diff --git a/include/ignition/math/Inertial.hh b/include/ignition/math/Inertial.hh
new file mode 100644
index 0000000..d2ee498
--- /dev/null
+++ b/include/ignition/math/Inertial.hh
@@ -0,0 +1,244 @@
+/*
+ * Copyright (C) 2016 Open Source Robotics Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+*/
+#ifndef IGNITION_MATH_INERTIAL_HH_
+#define IGNITION_MATH_INERTIAL_HH_
+
+#include "ignition/math/MassMatrix3.hh"
+#include "ignition/math/Pose3.hh"
+
+namespace ignition
+{
+  namespace math
+  {
+    /// \class Inertial Inertial.hh ignition/math/Inertial.hh
+    /// \brief A class for inertial information about a rigid body
+    /// consisting of the scalar mass, a 3x3 symmetric moment
+    /// of inertia matrix, and center of mass reference frame pose.
+    template<typename T>
+    class Inertial
+    {
+      /// \brief Default Constructor
+      public: Inertial()
+      {}
+
+      /// \brief Constructor.
+      /// \param[in] _massMatrix Mass and inertia matrix.
+      /// \param[in] _pose Pose of center of mass reference frame.
+      public: Inertial(const MassMatrix3<T> &_massMatrix,
+                       const Pose3<T> &_pose)
+      : massMatrix(_massMatrix), pose(_pose)
+      {}
+
+      /// \brief Copy constructor.
+      /// \param[in] _inertial Inertial element to copy
+      public: Inertial(const Inertial<T> &_inertial)
+      : massMatrix(_inertial.MassMatrix()), pose(_inertial.Pose())
+      {}
+
+      /// \brief Destructor.
+      public: virtual ~Inertial() {}
+
+      /// \brief Set the mass and inertia matrix.
+      /// \param[in] _m New MassMatrix3 object.
+      /// \return True if the MassMatrix3 is valid.
+      public: bool SetMassMatrix(const MassMatrix3<T> &_m)
+      {
+        this->massMatrix = _m;
+        return this->massMatrix.IsValid();
+      }
+
+      /// \brief Get the mass and inertia matrix.
+      /// \return The MassMatrix3 object.
+      public: const MassMatrix3<T> &MassMatrix() const
+      {
+        return this->massMatrix;
+      }
+
+      /// \brief Set the pose of center of mass reference frame.
+      /// \param[in] _pose New pose.
+      /// \return True if the MassMatrix3 is valid.
+      public: bool SetPose(const Pose3<T> &_pose)
+      {
+        this->pose = _pose;
+        return this->massMatrix.IsValid();
+      }
+
+      /// \brief Get the pose of center of mass reference frame.
+      /// \return The pose of center of mass reference frame.
+      public: const Pose3<T> &Pose() const
+      {
+        return this->pose;
+      }
+
+      /// \brief Get the moment of inertia matrix expressed in the
+      /// base coordinate frame.
+      /// \return Rotated moment of inertia matrix.
+      public: Matrix3<T> MOI() const
+      {
+        auto R = Matrix3<T>(this->pose.Rot());
+        return R * this->massMatrix.MOI() * R.Transposed();
+      }
+
+      /// \brief Set the inertial pose rotation without affecting the
+      /// MOI in the base coordinate frame.
+      /// \param[in] _q New rotation for inertial pose.
+      /// \return True if the MassMatrix3 is valid.
+      public: bool SetInertialRotation(const Quaternion<T> &_q)
+      {
+        auto moi = this->MOI();
+        this->pose.Rot() = _q;
+        auto R = Matrix3<T>(_q);
+        return this->massMatrix.MOI(R.Transposed() * moi * R);
+      }
+
+      /// \brief Set the MassMatrix rotation (eigenvectors of inertia matrix)
+      /// without affecting the MOI in the base coordinate frame.
+      /// Note that symmetries in inertia matrix may prevent the output of
+      /// MassMatrix3::PrincipalAxesOffset to match this function's input _q,
+      /// but it is guaranteed that the MOI in the base frame will not change.
+      /// A negative value of _tol (such as -1e-6) can be passed to ensure
+      /// that diagonal values are always sorted.
+      /// \param[in] _q New rotation.
+      /// \param[in] _tol Relative tolerance given by absolute value
+      /// of _tol. This is passed to the MassMatrix3
+      /// PrincipalMoments and PrincipalAxesOffset functions.
+      /// \return True if the MassMatrix3 is valid.
+      public: bool SetMassMatrixRotation(const Quaternion<T> &_q,
+                                         const T _tol = 1e-6)
+      {
+        this->pose.Rot() *= this->MassMatrix().PrincipalAxesOffset(_tol) *
+                            _q.Inverse();
+        const auto moments = this->MassMatrix().PrincipalMoments(_tol);
+        const auto diag = Matrix3<T>(
+            moments[0], 0, 0,
+            0, moments[1], 0,
+            0, 0, moments[2]);
+        const auto R = Matrix3<T>(_q);
+        return this->massMatrix.MOI(R * diag * R.Transposed());
+      }
+
+      /// \brief Equal operator.
+      /// \param[in] _inertial Inertial to copy.
+      /// \return Reference to this object.
+      public: Inertial &operator=(const Inertial<T> &_inertial)
+      {
+        this->massMatrix = _inertial.MassMatrix();
+        this->pose = _inertial.Pose();
+
+        return *this;
+      }
+
+      /// \brief Equality comparison operator.
+      /// \param[in] _inertial Inertial to copy.
+      /// \return true if each component is equal within a default tolerance,
+      /// false otherwise
+      public: bool operator==(const Inertial<T> &_inertial) const
+      {
+        return (this->pose == _inertial.Pose()) &&
+               (this->massMatrix == _inertial.MassMatrix());
+      }
+
+      /// \brief Inequality test operator
+      /// \param[in] _inertial Inertial<T> to test
+      /// \return True if not equal (using the default tolerance of 1e-6)
+      public: bool operator!=(const Inertial<T> &_inertial) const
+      {
+        return !(*this == _inertial);
+      }
+
+      /// \brief Adds inertial properties to current object.
+      /// The mass, center of mass location, and inertia matrix are updated
+      /// as long as the total mass is positive.
+      /// \param[in] _inertial Inertial to add.
+      /// \return Reference to this object.
+      public: Inertial<T> &operator+=(const Inertial<T> &_inertial)
+      {
+        T m1 = this->massMatrix.Mass();
+        T m2 = _inertial.MassMatrix().Mass();
+
+        // Total mass
+        T mass = m1 + m2;
+
+        // Only continue if total mass is positive
+        if (mass <= 0)
+        {
+          return *this;
+        }
+
+        auto com1 = this->Pose().Pos();
+        auto com2 = _inertial.Pose().Pos();
+        // New center of mass location in base frame
+        auto com = (m1*com1 + m2*com2) / mass;
+
+        // Components of new moment of inertia matrix
+        Vector3<T> ixxyyzz;
+        Vector3<T> ixyxzyz;
+        // First add matrices in base frame
+        {
+          auto moi = this->MOI() + _inertial.MOI();
+          ixxyyzz = Vector3<T>(moi(0, 0), moi(1, 1), moi(2, 2));
+          ixyxzyz = Vector3<T>(moi(0, 1), moi(0, 2), moi(1, 2));
+        }
+        // Then account for parallel axis theorem
+        {
+          auto dc = com1 - com;
+          ixxyyzz.X() += m1 * (std::pow(dc[1], 2) + std::pow(dc[2], 2));
+          ixxyyzz.Y() += m1 * (std::pow(dc[2], 2) + std::pow(dc[0], 2));
+          ixxyyzz.Z() += m1 * (std::pow(dc[0], 2) + std::pow(dc[1], 2));
+          ixxyyzz.X() -= m1 * dc[0] * dc[1];
+          ixxyyzz.Y() -= m1 * dc[0] * dc[2];
+          ixxyyzz.Z() -= m1 * dc[1] * dc[2];
+        }
+        {
+          auto dc = com2 - com;
+          ixxyyzz.X() += m2 * (std::pow(dc[1], 2) + std::pow(dc[2], 2));
+          ixxyyzz.Y() += m2 * (std::pow(dc[2], 2) + std::pow(dc[0], 2));
+          ixxyyzz.Z() += m2 * (std::pow(dc[0], 2) + std::pow(dc[1], 2));
+          ixxyyzz.X() -= m2 * dc[0] * dc[1];
+          ixxyyzz.Y() -= m2 * dc[0] * dc[2];
+          ixxyyzz.Z() -= m2 * dc[1] * dc[2];
+        }
+        this->massMatrix = MassMatrix3<T>(mass, ixxyyzz, ixyxzyz);
+        this->pose = Pose3<T>(com, Quaternion<T>::Identity);
+
+        return *this;
+      }
+
+      /// \brief Adds inertial properties to current object.
+      /// The mass, center of mass location, and inertia matrix are updated
+      /// as long as the total mass is positive.
+      /// \param[in] _inertial Inertial to add.
+      /// \return Sum of inertials as new object.
+      public: const Inertial<T> operator+(const Inertial<T> &_inertial) const
+      {
+        return Inertial<T>(*this) += _inertial;
+      }
+
+      /// \brief Mass and inertia matrix of the object expressed in the
+      /// center of mass reference frame.
+      private: MassMatrix3<T> massMatrix;
+
+      /// \brief Pose offset of center of mass reference frame relative
+      /// to a base frame.
+      private: Pose3<T> pose;
+    };
+
+    typedef Inertial<double> Inertiald;
+    typedef Inertial<float> Inertialf;
+  }
+}
+#endif
diff --git a/include/ignition/math/Kmeans.hh b/include/ignition/math/Kmeans.hh
new file mode 100644
index 0000000..17ff01c
--- /dev/null
+++ b/include/ignition/math/Kmeans.hh
@@ -0,0 +1,85 @@
+/*
+ * Copyright (C) 2014 Open Source Robotics Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+*/
+#ifndef IGNITION_MATH_KMEANS_HH_
+#define IGNITION_MATH_KMEANS_HH_
+
+#include <vector>
+#include <ignition/math/Vector3.hh>
+#include <ignition/math/Helpers.hh>
+
+namespace ignition
+{
+  namespace math
+  {
+    // Forward declare private data
+    class KmeansPrivate;
+
+    /// \class Kmeans Kmeans.hh math/gzmath.hh
+    /// \brief K-Means clustering algorithm. Given a set of observations,
+    /// k-means partitions the observations into k sets so as to minimize the
+    /// within-cluster sum of squares.
+    /// Description based on http://en.wikipedia.org/wiki/K-means_clustering.
+    class IGNITION_MATH_VISIBLE Kmeans
+    {
+      /// \brief constructor
+      /// \param[in] _obs Set of observations to cluster.
+      public: explicit Kmeans(const std::vector<Vector3d> &_obs);
+
+      /// \brief Destructor.
+      public: virtual ~Kmeans();
+
+      /// \brief Get the observations to cluster.
+      /// \return The vector of observations.
+      public: std::vector<Vector3d> Observations() const;
+
+      /// \brief Set the observations to cluster.
+      /// \param[in] _obs The new vector of observations.
+      /// \return True if the vector is not empty or false otherwise.
+      public: bool Observations(const std::vector<Vector3d> &_obs);
+
+      /// \brief Add observations to the cluster.
+      /// \param[in] _obs Vector of observations.
+      /// \return True if the _obs vector is not empty or false otherwise.
+      public: bool AppendObservations(const std::vector<Vector3d> &_obs);
+
+      /// \brief Executes the k-means algorithm.
+      /// \param[in] _k Number of partitions to cluster.
+      /// \param[out] _centroids Vector of centroids. Each element contains the
+      /// centroid of one cluster.
+      /// \param[out] _labels Vector of labels. The size of this vector is
+      /// equals to the number of observations. Each element represents the
+      /// cluster to which observation belongs.
+      /// \return True when the operation succeed or false otherwise. The
+      /// operation will fail if the number of observations is not positive,
+      /// if the number of clusters is non positive, or if the number of
+      /// clusters if greater than the number of observations.
+      public: bool Cluster(int _k,
+                           std::vector<Vector3d> &_centroids,
+                           std::vector<unsigned int> &_labels);
+
+      /// \brief Given an observation, it returns the closest centroid to it.
+      /// \param[in] _p Point to check.
+      /// \return The index of the closest centroid to the point _p.
+      private: unsigned int ClosestCentroid(const Vector3d &_p) const;
+
+      /// \brief Private data pointer
+      private: KmeansPrivate *dataPtr;
+    };
+  }
+}
+
+#endif
diff --git a/include/ignition/math/Line2.hh b/include/ignition/math/Line2.hh
new file mode 100644
index 0000000..2ef886b
--- /dev/null
+++ b/include/ignition/math/Line2.hh
@@ -0,0 +1,315 @@
+/*
+ * Copyright (C) 2014 Open Source Robotics Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+*/
+#ifndef IGNITION_MATH_LINE2_HH_
+#define IGNITION_MATH_LINE2_HH_
+
+#include <algorithm>
+#include <ignition/math/Vector2.hh>
+
+namespace ignition
+{
+  namespace math
+  {
+    /// \class Line2 Line2.hh ignition/math/Line2.hh
+    /// \brief A two dimensional line segment. The line is defined by a
+    /// start and end point.
+    template<typename T>
+    class Line2
+    {
+      /// \brief Constructor.
+      /// \param[in] _ptA Start point of the line segment
+      /// \param[in] _ptB End point of the line segment
+      public: Line2(const math::Vector2<T> &_ptA, const math::Vector2<T> &_ptB)
+      {
+        this->Set(_ptA, _ptB);
+      }
+
+      /// \brief Constructor.
+      /// \param[in] _x1 X coordinate of the start point.
+      /// \param[in] _y1 Y coordinate of the start point.
+      /// \param[in] _x2 X coordinate of the end point.
+      /// \param[in] _y2 Y coordinate of the end point.
+      public: Line2(double _x1, double _y1, double _x2, double _y2)
+      {
+        this->Set(_x1, _y1, _x2, _y2);
+      }
+
+      /// \brief Set the start and end point of the line segment
+      /// \param[in] _ptA Start point of the line segment
+      /// \param[in] _ptB End point of the line segment
+      public: void Set(const math::Vector2<T> &_ptA,
+                       const math::Vector2<T> &_ptB)
+      {
+        this->pts[0] = _ptA;
+        this->pts[1] = _ptB;
+      }
+
+      /// \brief Set the start and end point of the line segment
+      /// \param[in] _x1 X coordinate of the start point.
+      /// \param[in] _y1 Y coordinate of the start point.
+      /// \param[in] _x2 X coordinate of the end point.
+      /// \param[in] _y2 Y coordinate of the end point.
+      public: void Set(double _x1, double _y1, double _x2, double _y2)
+      {
+        this->pts[0].Set(_x1, _y1);
+        this->pts[1].Set(_x2, _y2);
+      }
+
+      /// \brief Return the cross product of this line and the given line.
+      /// Give 'a' as this line and 'b' as given line, the equation is:
+      /// (a.start.x - a.end.x) * (b.start.y - b.end.y) -
+      /// (a.start.y - a.end.y) * (b.start.x - b.end.x)
+      /// \param[in] _line Line for the cross product computation.
+      /// \return Return the cross product of this line and the given line.
+      public: double CrossProduct(const Line2<T> &_line) const
+      {
+        return (this->pts[0].X() - this->pts[1].X()) *
+               (_line[0].Y() -_line[1].Y()) -
+               (this->pts[0].Y() - this->pts[1].Y()) *
+               (_line[0].X() - _line[1].X());
+      }
+
+      /// \brief Return the cross product of this line and the given point.
+      /// Given 'a' and 'b' as the start and end points, the equation is:
+      //  (_pt.y - a.y) * (b.x - a.x) - (_pt.x - a.x) * (b.y - a.y)
+      /// \param[in] _pt Point for the cross product computation.
+      /// \return Return the cross product of this line and the given point.
+      public: double CrossProduct(const Vector2<T> &_pt) const
+      {
+        return (_pt.Y() - this->pts[0].Y()) *
+               (this->pts[1].X() - this->pts[0].X()) -
+               (_pt.X() - this->pts[0].X()) *
+               (this->pts[1].Y() - this->pts[0].Y());
+      }
+
+      /// \brief Check if the given point is collinear with this line.
+      /// \param[in] _pt The point to check.
+      /// \param[in] _epsilon The error bounds within which the collinear
+      /// check will return true.
+      /// \return Return true if the point is collinear with this line, false
+      /// otherwise.
+      public: bool Collinear(const math::Vector2<T> &_pt,
+                             double _epsilon = 1e-6) const
+      {
+        return math::equal(this->CrossProduct(_pt),
+            static_cast<T>(0), _epsilon);
+      }
+
+      /// \brief Check if the given line is parallel with this line.
+      /// \param[in] _line The line to check.
+      /// \param[in] _epsilon The error bounds within which the parallel
+      /// check will return true.
+      /// \return Return true if the line is parallel with this line, false
+      /// otherwise. Return true if either line is a point (line with zero
+      /// length).
+      public: bool Parallel(const math::Line2<T> &_line,
+                            double _epsilon = 1e-6) const
+      {
+        return math::equal(this->CrossProduct(_line),
+            static_cast<T>(0), _epsilon);
+      }
+
+      /// \brief Check if the given line is collinear with this line. This
+      /// is the AND of Parallel and Intersect.
+      /// \param[in] _line The line to check.
+      /// \param[in] _epsilon The error bounds within which the collinear
+      /// check will return true.
+      /// \return Return true if the line is collinear with this line, false
+      /// otherwise.
+      public: bool Collinear(const math::Line2<T> &_line,
+                             double _epsilon = 1e-6) const
+      {
+        return this->Parallel(_line, _epsilon) &&
+               this->Intersect(_line, _epsilon);
+      }
+
+      /// \brief Return whether the given point is on this line segment.
+      /// \param[in] _pt Point to check.
+      /// \param[in] _epsilon The error bounds within which the OnSegment
+      /// check will return true.
+      /// \return True if the point is on the segement.
+      public: bool OnSegment(const math::Vector2<T> &_pt,
+                             double _epsilon = 1e-6) const
+      {
+        return this->Collinear(_pt, _epsilon) && this->Within(_pt, _epsilon);
+      }
+
+      /// \brief Check if the given point is between the start and end
+      /// points of the line segment. This does not imply that the point is
+      /// on the segment.
+      /// \param[in] _pt Point to check.
+      /// \param[in] _epsilon The error bounds within which the within
+      /// check will return true.
+      /// \return True if the point is on the segement.
+      public: bool Within(const math::Vector2<T> &_pt,
+                          double _epsilon = 1e-6) const
+      {
+        return _pt.X() <= std::max(this->pts[0].X(),
+                                   this->pts[1].X()) + _epsilon &&
+               _pt.X() >= std::min(this->pts[0].X(),
+                                   this->pts[1].X()) - _epsilon &&
+               _pt.Y() <= std::max(this->pts[0].Y(),
+                                   this->pts[1].Y()) + _epsilon &&
+               _pt.Y() >= std::min(this->pts[0].Y(),
+                                   this->pts[1].Y()) - _epsilon;
+      }
+
+      /// \brief Check if this line intersects the given line segment.
+      /// \param[in] _line The line to check for intersection.
+      /// \param[in] _epsilon The error bounds within which the intersection
+      /// check will return true.
+      /// \return True if an intersection was found.
+      public: bool Intersect(const Line2<T> &_line,
+                             double _epsilon = 1e-6) const
+      {
+        static math::Vector2<T> ignore;
+        return this->Intersect(_line, ignore, _epsilon);
+      }
+
+      /// \brief Check if this line intersects the given line segment. The
+      /// point of intersection is returned in the _result parameter.
+      /// \param[in] _line The line to check for intersection.
+      /// \param[out] _pt The point of intersection. This value is only
+      /// valid if the return value is true.
+      /// \param[in] _epsilon The error bounds within which the intersection
+      /// check will return true.
+      /// \return True if an intersection was found.
+      public: bool Intersect(const Line2<T> &_line, math::Vector2<T> &_pt,
+                             double _epsilon = 1e-6) const
+      {
+        double d = this->CrossProduct(_line);
+
+        // d is zero if the two line are collinear. Must check special
+        // cases.
+        if (math::equal(d, 0.0, _epsilon))
+        {
+          // Check if _line's starting point is on the line.
+          if (this->Within(_line[0], _epsilon))
+          {
+            _pt = _line[0];
+            return true;
+          }
+          // Check if _line's ending point is on the line.
+          else if (this->Within(_line[1], _epsilon))
+          {
+            _pt = _line[1];
+            return true;
+          }
+          // Other wise return false.
+          else
+            return false;
+        }
+
+        _pt.X((_line[0].X() - _line[1].X()) *
+              (this->pts[0].X() * this->pts[1].Y() -
+               this->pts[0].Y() * this->pts[1].X()) -
+              (this->pts[0].X() - this->pts[1].X()) *
+              (_line[0].X() * _line[1].Y() - _line[0].Y() * _line[1].X()));
+
+        _pt.Y((_line[0].Y() - _line[1].Y()) *
+              (this->pts[0].X() * this->pts[1].Y() -
+               this->pts[0].Y() * this->pts[1].X()) -
+              (this->pts[0].Y() - this->pts[1].Y()) *
+              (_line[0].X() * _line[1].Y() - _line[0].Y() * _line[1].X()));
+
+        _pt /= d;
+
+        if (_pt.X() < std::min(this->pts[0].X(), this->pts[1].X()) ||
+            _pt.X() > std::max(this->pts[0].X(), this->pts[1].X()) ||
+            _pt.X() < std::min(_line[0].X(), _line[1].X()) ||
+            _pt.X() > std::max(_line[0].X(), _line[1].X()))
+        {
+          return false;
+        }
+
+        if (_pt.Y() < std::min(this->pts[0].Y(), this->pts[1].Y()) ||
+            _pt.Y() > std::max(this->pts[0].Y(), this->pts[1].Y()) ||
+            _pt.Y() < std::min(_line[0].Y(), _line[1].Y()) ||
+            _pt.Y() > std::max(_line[0].Y(), _line[1].Y()))
+        {
+          return false;
+        }
+
+        return true;
+      }
+
+      /// \brief Get the length of the line
+      /// \return The length of the line.
+      public: T Length() const
+      {
+        return sqrt((this->pts[0].X() - this->pts[1].X()) *
+                    (this->pts[0].X() - this->pts[1].X()) +
+                    (this->pts[0].Y() - this->pts[1].Y()) *
+                    (this->pts[0].Y() - this->pts[1].Y()));
+      }
+
+      /// \brief Get the slope of the line
+      /// \return The slope of the line, NAN_D if the line is vertical.
+      public: double Slope() const
+      {
+        if (math::equal(this->pts[1].X(), this->pts[0].X()))
+          return NAN_D;
+
+        return (this->pts[1].Y() - this->pts[0].Y()) /
+               static_cast<double>(this->pts[1].X() - this->pts[0].X());
+      }
+
+      /// \brief Equality operator.
+      /// \param[in] _line Line to compare for equality.
+      /// \return True if the given line is equal to this line
+      public: bool operator==(const Line2<T> &_line) const
+      {
+        return this->pts[0] == _line[0] && this->pts[1] == _line[1];
+      }
+
+      /// \brief Inequality operator.
+      /// \param[in] _line Line to compare for inequality.
+      /// \return True if the given line is not to this line
+      public: bool operator!=(const Line2<T> &_line) const
+      {
+        return !(*this == _line);
+      }
+
+      /// \brief Get the start or end point.
+      /// \param[in] _index 0 = start point, 1 = end point. The _index
+      /// is clamped to the range [0, 1]
+      public: math::Vector2<T> operator[](size_t _index) const
+      {
+        return this->pts[clamp(_index, IGN_ZERO_SIZE_T, IGN_ONE_SIZE_T)];
+      }
+
+      /// \brief Stream extraction operator
+      /// \param[in] _out output stream
+      /// \param[in] _pt Line2 to output
+      /// \return The stream
+      public: friend std::ostream &operator<<(
+                  std::ostream &_out, const Line2<T> &_line)
+      {
+        _out << _line[0] << " " << _line[1];
+        return _out;
+      }
+
+      private: math::Vector2<T> pts[2];
+    };
+
+
+    typedef Line2<int> Line2i;
+    typedef Line2<double> Line2d;
+    typedef Line2<float> Line2f;
+  }
+}
+#endif
diff --git a/include/ignition/math/Line3.hh b/include/ignition/math/Line3.hh
new file mode 100644
index 0000000..14b2bd8
--- /dev/null
+++ b/include/ignition/math/Line3.hh
@@ -0,0 +1,388 @@
+/*
+ * Copyright (C) 2015 Open Source Robotics Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+*/
+#ifndef IGNITION_MATH_LINE3_HH_
+#define IGNITION_MATH_LINE3_HH_
+
+#include <algorithm>
+#include <ignition/math/Vector3.hh>
+
+namespace ignition
+{
+  namespace math
+  {
+    /// \class Line3 Line3.hh ignition/math/Line3.hh
+    /// \brief A three dimensional line segment. The line is defined by a
+    /// start and end point.
+    template<typename T>
+    class Line3
+    {
+      /// \brief Line Constructor
+      public: Line3() = default;
+
+      /// \brief Copy constructor
+      /// \param[in] _line a line object
+      public: Line3(const Line3<T> &_line)
+      {
+        this->pts[0] = _line[0];
+        this->pts[1] = _line[1];
+      }
+
+      /// \brief Constructor.
+      /// \param[in] _ptA Start point of the line segment
+      /// \param[in] _ptB End point of the line segment
+      public: Line3(const math::Vector3<T> &_ptA, const math::Vector3<T> &_ptB)
+      {
+        this->Set(_ptA, _ptB);
+      }
+
+      /// \brief 2D Constructor where Z coordinates are 0
+      /// \param[in] _x1 X coordinate of the start point.
+      /// \param[in] _y1 Y coordinate of the start point.
+      /// \param[in] _x2 X coordinate of the end point.
+      /// \param[in] _y2 Y coordinate of the end point.
+      public: Line3(const double _x1, const double _y1,
+        const double _x2, const double _y2)
+      {
+        this->Set(_x1, _y1, _x2, _y2);
+      }
+
+      /// \brief Constructor.
+      /// \param[in] _x1 X coordinate of the start point.
+      /// \param[in] _y1 Y coordinate of the start point.
+      /// \param[in] _z1 Z coordinate of the start point.
+      /// \param[in] _x2 X coordinate of the end point.
+      /// \param[in] _y2 Y coordinate of the end point.
+      /// \param[in] _z2 Z coordinate of the end point.
+      public: Line3(const double _x1, const double _y1,
+        const double _z1, const double _x2,
+        const double _y2, const double _z2)
+      {
+        this->Set(_x1, _y1, _z1, _x2, _y2, _z2);
+      }
+
+      /// \brief Set the start and end point of the line segment
+      /// \param[in] _ptA Start point of the line segment
+      /// \param[in] _ptB End point of the line segment
+      public: void Set(const math::Vector3<T> &_ptA,
+                       const math::Vector3<T> &_ptB)
+      {
+        this->pts[0] = _ptA;
+        this->pts[1] = _ptB;
+      }
+
+      /// \brief Set the start point of the line segment
+      /// \param[in] _ptA Start point of the line segment
+      public: void SetA(const math::Vector3<T> &_ptA)
+      {
+        this->pts[0] = _ptA;
+      }
+
+      /// \brief Set the end point of the line segment
+      /// \param[in] _ptB End point of the line segment
+      public: void SetB(const math::Vector3<T> &_ptB)
+      {
+        this->pts[1] = _ptB;
+      }
+
+      /// \brief Set the start and end point of the line segment, assuming that
+      /// both points have the same height.
+      /// \param[in] _x1 X coordinate of the start point.
+      /// \param[in] _y1 Y coordinate of the start point.
+      /// \param[in] _x2 X coordinate of the end point.
+      /// \param[in] _y2 Y coordinate of the end point.
+      /// \param[in] _z Z coordinate of both points,
+      /// by default _z is set to 0.
+      public: void Set(const double _x1, const double _y1,
+        const double _x2, const double _y2,
+        const double _z = 0)
+      {
+        this->pts[0].Set(_x1, _y1, _z);
+        this->pts[1].Set(_x2, _y2, _z);
+      }
+
+      /// \brief Set the start and end point of the line segment
+      /// \param[in] _x1 X coordinate of the start point.
+      /// \param[in] _y1 Y coordinate of the start point.
+      /// \param[in] _z1 Z coordinate of the start point.
+      /// \param[in] _x2 X coordinate of the end point.
+      /// \param[in] _y2 Y coordinate of the end point.
+      /// \param[in] _z2 Z coordinate of the end point.
+      public: void Set(const double _x1, const double _y1,
+        const double _z1, const double _x2,
+        const double _y2, const double _z2)
+      {
+        this->pts[0].Set(_x1, _y1, _z1);
+        this->pts[1].Set(_x2, _y2, _z2);
+      }
+
+      /// \brief Get the direction of the line
+      /// \return The direction vector
+      public: math::Vector3<T> Direction() const
+      {
+        return (this->pts[1] - this->pts[0]).Normalize();
+      }
+
+      /// \brief Get the length of the line
+      /// \return The length of the line.
+      public: T Length() const
+      {
+        return this->pts[0].Distance(this->pts[1]);
+      }
+
+      /// \brief Get the shortest line between this line and the
+      /// provided line.
+      ///
+      /// In the case when the two lines are parallel, we choose the first
+      /// point of this line and the closest point in the provided line.
+      /// \param[in] _line Line to compare against this.
+      /// \param[out] _result The shortest line between _line and this.
+      /// \return True if a solution was found. False if a solution is not
+      /// possible.
+      public: bool Distance(const Line3<T> &_line, Line3<T> &_result,
+                            const double _epsilon = 1e-6) const
+      {
+        Vector3<T> p13 = this->pts[0] - _line[0];
+        Vector3<T> p43 = _line[1] - _line[0];
+
+        if (std::abs(p43.X()) < _epsilon && std::abs(p43.Y()) < _epsilon &&
+            std::abs(p43.Z()) < _epsilon)
+        {
+          return false;
+        }
+
+        Vector3<T> p21 = this->pts[1] - this->pts[0];
+
+        if (std::abs(p21.X()) < _epsilon && std::abs(p21.Y()) < _epsilon &&
+            std::abs(p21.Z()) < _epsilon)
+        {
+          return false;
+        }
+
+        double d1343 = p13.Dot(p43);
+        double d4321 = p43.Dot(p21);
+        double d1321 = p13.Dot(p21);
+        double d4343 = p43.Dot(p43);
+        double d2121 = p21.Dot(p21);
+
+        double denom = d2121 * d4343 - d4321 * d4321;
+
+        // In this case, we choose the first point in this line,
+        // and the closest point in the provided line.
+        if (std::abs(denom) < _epsilon)
+        {
+          double d1 = this->pts[0].Distance(_line[0]);
+          double d2 = this->pts[0].Distance(_line[1]);
+
+          double d3 = this->pts[1].Distance(_line[0]);
+          double d4 = this->pts[1].Distance(_line[1]);
+
+          if (d1 <= d2 && d1 <= d3 && d1 <= d4)
+          {
+            _result.SetA(this->pts[0]);
+            _result.SetB(_line[0]);
+          }
+          else if (d2 <= d3 && d2 <= d4)
+          {
+            _result.SetA(this->pts[0]);
+            _result.SetB(_line[1]);
+          }
+          else if (d3 <= d4)
+          {
+            _result.SetA(this->pts[1]);
+            _result.SetB(_line[0]);
+          }
+          else
+          {
+            _result.SetA(this->pts[1]);
+            _result.SetB(_line[1]);
+          }
+
+          return true;
+        }
+
+        double numer = d1343 * d4321 - d1321 * d4343;
+
+        double mua = clamp(numer / denom, 0.0, 1.0);
+        double mub = clamp((d1343 + d4321 * mua) / d4343, 0.0, 1.0);
+
+        _result.Set(this->pts[0] + (p21 * mua), _line[0] + (p43 * mub));
+
+        return true;
+      }
+
+      /// \brief Check if this line intersects the given line segment.
+      /// \param[in] _line The line to check for intersection.
+      /// \param[in] _epsilon The error bounds within which the intersection
+      /// check will return true.
+      /// \return True if an intersection was found.
+      public: bool Intersect(const Line3<T> &_line,
+                             double _epsilon = 1e-6) const
+      {
+        static math::Vector3<T> ignore;
+        return this->Intersect(_line, ignore, _epsilon);
+      }
+
+      /// \brief Test if this line and the given line are coplanar.
+      /// \param[in] _line Line to check against.
+      /// \param[in] _epsilon The error bounds within which the
+      /// check will return true.
+      /// \return True if the two lines are coplanar.
+      public: bool Coplanar(const Line3<T> &_line,
+                            const double _epsilon = 1e-6) const
+      {
+        return std::abs((_line[0] - this->pts[0]).Dot(
+              (this->pts[1] - this->pts[0]).Cross(_line[1] - _line[0])))
+          <= _epsilon;
+      }
+
+      /// \brief Test if this line and the given line are parallel.
+      /// \param[in] _line Line to check against.
+      /// \param[in] _epsilon The error bounds within which the
+      /// check will return true.
+      /// \return True if the two lines are parallel.
+      public: bool Parallel(const Line3<T> &_line,
+                            const double _epsilon = 1e-6) const
+      {
+        return (this->pts[1] - this->pts[0]).Cross(
+            _line[1] - _line[0]).Length() <= _epsilon;
+      }
+
+      /// \brief Check if this line intersects the given line segment. The
+      /// point of intersection is returned in the _pt parameter.
+      /// \param[in] _line The line to check for intersection.
+      /// \param[out] _pt The point of intersection. This value is only
+      /// valid if the return value is true.
+      /// \param[in] _epsilon The error bounds within which the intersection
+      /// check will return true.
+      /// \return True if an intersection was found.
+      public: bool Intersect(const Line3<T> &_line, math::Vector3<T> &_pt,
+                             double _epsilon = 1e-6) const
+      {
+        // Handle special case when lines are parallel
+        if (this->Parallel(_line, _epsilon))
+        {
+          // Check if _line's starting point is on the line.
+          if (this->Within(_line[0], _epsilon))
+          {
+            _pt = _line[0];
+            return true;
+          }
+          // Check if _line's ending point is on the line.
+          else if (this->Within(_line[1], _epsilon))
+          {
+            _pt = _line[1];
+            return true;
+          }
+          // Otherwise return false.
+          else
+            return false;
+        }
+
+        // Get the line that is the shortest distance between this and _line
+        math::Line3<T> distLine;
+        this->Distance(_line, distLine, _epsilon);
+
+        // If the length of the line is less than epsilon, then they
+        // intersect.
+        if (distLine.Length() < _epsilon)
+        {
+          _pt = distLine[0];
+          return true;
+        }
+
+        return false;
+      }
+
+      /// \brief Check if the given point is between the start and end
+      /// points of the line segment.
+      /// \param[in] _pt Point to check.
+      /// \param[in] _epsilon The error bounds within which the within
+      /// check will return true.
+      /// \return True if the point is on the segement.
+      public: bool Within(const math::Vector3<T> &_pt,
+                          double _epsilon = 1e-6) const
+      {
+        return _pt.X() <= std::max(this->pts[0].X(),
+                                   this->pts[1].X()) + _epsilon &&
+               _pt.X() >= std::min(this->pts[0].X(),
+                                   this->pts[1].X()) - _epsilon &&
+               _pt.Y() <= std::max(this->pts[0].Y(),
+                                   this->pts[1].Y()) + _epsilon &&
+               _pt.Y() >= std::min(this->pts[0].Y(),
+                                   this->pts[1].Y()) - _epsilon &&
+               _pt.Z() <= std::max(this->pts[0].Z(),
+                                   this->pts[1].Z()) + _epsilon &&
+               _pt.Z() >= std::min(this->pts[0].Z(),
+                                   this->pts[1].Z()) - _epsilon;
+      }
+
+      /// \brief Equality operator.
+      /// \param[in] _line Line to compare for equality.
+      /// \return True if the given line is equal to this line
+      public: bool operator==(const Line3<T> &_line) const
+      {
+        return this->pts[0] == _line[0] && this->pts[1] == _line[1];
+      }
+
+      /// \brief Inequality operator.
+      /// \param[in] _line Line to compare for inequality.
+      /// \return True if the given line is not to this line
+      public: bool operator!=(const Line3<T> &_line) const
+      {
+        return !(*this == _line);
+      }
+
+      /// \brief Get the start or end point.
+      /// \param[in] _index 0 = start point, 1 = end point. The _index
+      /// parameter is clamped to the range [0, 1].
+      public: math::Vector3<T> operator[](const size_t _index) const
+      {
+        return this->pts[clamp(_index, IGN_ZERO_SIZE_T, IGN_ONE_SIZE_T)];
+      }
+
+      /// \brief Stream extraction operator
+      /// \param[in] _out output stream
+      /// \param[in] _line Line3 to output
+      /// \return The stream
+      public: friend std::ostream &operator<<(
+                  std::ostream &_out, const Line3<T> &_line)
+      {
+        _out << _line[0] << " " << _line[1];
+        return _out;
+      }
+
+      /// \brief Assignment operator
+      /// \param[in] _line a new value
+      /// \return this
+      public: Line3 &operator=(const Line3<T> &_line)
+      {
+        this->pts[0] = _line[0];
+        this->pts[1] = _line[1];
+
+        return *this;
+      }
+
+      /// \brief Vector for storing the start and end points of the line
+      private: math::Vector3<T> pts[2];
+    };
+
+    typedef Line3<int> Line3i;
+    typedef Line3<double> Line3d;
+    typedef Line3<float> Line3f;
+  }
+}
+#endif
diff --git a/include/ignition/math/MassMatrix3.hh b/include/ignition/math/MassMatrix3.hh
new file mode 100644
index 0000000..7b7b5f0
--- /dev/null
+++ b/include/ignition/math/MassMatrix3.hh
@@ -0,0 +1,906 @@
+/*
+ * Copyright (C) 2015 Open Source Robotics Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+*/
+#ifndef IGNITION_MATH_MASSMATRIX3_HH_
+#define IGNITION_MATH_MASSMATRIX3_HH_
+
+#include <algorithm>
+#include <string>
+#include <vector>
+
+#include "ignition/math/Helpers.hh"
+#include "ignition/math/Quaternion.hh"
+#include "ignition/math/Vector2.hh"
+#include "ignition/math/Vector3.hh"
+#include "ignition/math/Matrix3.hh"
+
+namespace ignition
+{
+  namespace math
+  {
+    /// \class MassMatrix3 MassMatrix3.hh ignition/math/MassMatrix3.hh
+    /// \brief A class for inertial information about a rigid body
+    /// consisting of the scalar mass and a 3x3 symmetric moment
+    /// of inertia matrix stored as two Vector3's.
+    template<typename T>
+    class MassMatrix3
+    {
+      /// \brief Default Constructor
+      public: MassMatrix3() : mass(0)
+      {}
+
+      /// \brief Constructor.
+      /// \param[in] _mass Mass value in kg if using metric.
+      /// \param[in] _ixxyyzz Diagonal moments of inertia.
+      /// \param[in] _ixyxzyz Off-diagonal moments of inertia
+      public: MassMatrix3(const T &_mass,
+                          const Vector3<T> &_ixxyyzz,
+                          const Vector3<T> &_ixyxzyz)
+      : mass(_mass), Ixxyyzz(_ixxyyzz), Ixyxzyz(_ixyxzyz)
+      {}
+
+      /// \brief Copy constructor.
+      /// \param[in] _massMatrix MassMatrix3 element to copy
+      public: MassMatrix3(const MassMatrix3<T> &_m)
+      : mass(_m.Mass()), Ixxyyzz(_m.DiagonalMoments()),
+        Ixyxzyz(_m.OffDiagonalMoments())
+      {}
+
+      /// \brief Destructor.
+      public: virtual ~MassMatrix3() {}
+
+      /// \brief Set the mass.
+      /// \param[in] _m New mass value.
+      /// \return True if the MassMatrix3 is valid.
+      public: bool Mass(const T &_m)
+      {
+        this->mass = _m;
+        return this->IsValid();
+      }
+
+      /// \brief Get the mass
+      /// \return The mass value
+      public: T Mass() const
+      {
+        return this->mass;
+      }
+
+      /// \brief Set the moment of inertia matrix.
+      /// \param[in] _ixx X second moment of inertia (MOI) about x axis.
+      /// \param[in] _iyy Y second moment of inertia about y axis.
+      /// \param[in] _izz Z second moment of inertia about z axis.
+      /// \param[in] _ixy XY inertia.
+      /// \param[in] _ixz XZ inertia.
+      /// \param[in] _iyz YZ inertia.
+      /// \return True if the MassMatrix3 is valid.
+      public: bool InertiaMatrix(const T &_ixx, const T &_iyy, const T &_izz,
+                                 const T &_ixy, const T &_ixz, const T &_iyz)
+      {
+        this->Ixxyyzz.Set(_ixx, _iyy, _izz);
+        this->Ixyxzyz.Set(_ixy, _ixz, _iyz);
+        return this->IsValid();
+      }
+
+      /// \brief Get the diagonal moments of inertia (Ixx, Iyy, Izz).
+      /// \return The diagonal moments.
+      public: Vector3<T> DiagonalMoments() const
+      {
+        return this->Ixxyyzz;
+      }
+
+      /// \brief Get the off-diagonal moments of inertia (Ixy, Ixz, Iyz).
+      /// \return The off-diagonal moments of inertia.
+      public: Vector3<T> OffDiagonalMoments() const
+      {
+        return this->Ixyxzyz;
+      }
+
+      /// \brief Set the diagonal moments of inertia (Ixx, Iyy, Izz).
+      /// \param[in] _ixxyyzz diagonal moments of inertia
+      /// \return True if the MassMatrix3 is valid.
+      public: bool DiagonalMoments(const Vector3<T> &_ixxyyzz)
+      {
+        this->Ixxyyzz = _ixxyyzz;
+        return this->IsValid();
+      }
+
+      /// \brief Set the off-diagonal moments of inertia (Ixy, Ixz, Iyz).
+      /// \param[in] _ixyxzyz off-diagonal moments of inertia
+      /// \return True if the MassMatrix3 is valid.
+      public: bool OffDiagonalMoments(const Vector3<T> &_ixyxzyz)
+      {
+        this->Ixyxzyz = _ixyxzyz;
+        return this->IsValid();
+      }
+
+      /// \brief Get IXX
+      /// \return IXX value
+      public: T IXX() const
+      {
+        return this->Ixxyyzz[0];
+      }
+
+      /// \brief Get IYY
+      /// \return IYY value
+      public: T IYY() const
+      {
+        return this->Ixxyyzz[1];
+      }
+
+      /// \brief Get IZZ
+      /// \return IZZ value
+      public: T IZZ() const
+      {
+        return this->Ixxyyzz[2];
+      }
+
+      /// \brief Get IXY
+      /// \return IXY value
+      public: T IXY() const
+      {
+        return this->Ixyxzyz[0];
+      }
+
+      /// \brief Get IXZ
+      /// \return IXZ value
+      public: T IXZ() const
+      {
+        return this->Ixyxzyz[1];
+      }
+
+      /// \brief Get IYZ
+      /// \return IYZ value
+      public: T IYZ() const
+      {
+        return this->Ixyxzyz[2];
+      }
+
+      /// \brief Set IXX
+      /// \param[in] _v IXX value
+      /// \return True if the MassMatrix3 is valid.
+      public: bool IXX(const T &_v)
+      {
+        this->Ixxyyzz.X(_v);
+        return this->IsValid();
+      }
+
+      /// \brief Set IYY
+      /// \param[in] _v IYY value
+      /// \return True if the MassMatrix3 is valid.
+      public: bool IYY(const T &_v)
+      {
+        this->Ixxyyzz.Y(_v);
+        return this->IsValid();
+      }
+
+      /// \brief Set IZZ
+      /// \param[in] _v IZZ value
+      /// \return True if the MassMatrix3 is valid.
+      public: bool IZZ(const T &_v)
+      {
+        this->Ixxyyzz.Z(_v);
+        return this->IsValid();
+      }
+
+      /// \brief Set IXY
+      /// \param[in] _v IXY value
+      /// \return True if the MassMatrix3 is valid.
+      public: bool IXY(const T &_v)
+      {
+        this->Ixyxzyz.X(_v);
+        return this->IsValid();
+      }
+
+      /// \brief Set IXZ
+      /// \param[in] _v IXZ value
+      /// \return True if the MassMatrix3 is valid.
+      public: bool IXZ(const T &_v)
+      {
+        this->Ixyxzyz.Y(_v);
+        return this->IsValid();
+      }
+
+      /// \brief Set IYZ
+      /// \param[in] _v IYZ value
+      /// \return True if the MassMatrix3 is valid.
+      public: bool IYZ(const T &_v)
+      {
+        this->Ixyxzyz.Z(_v);
+        return this->IsValid();
+      }
+
+      /// \brief returns Moments of Inertia as a Matrix3
+      /// \return Moments of Inertia as a Matrix3
+      public: Matrix3<T> MOI() const
+      {
+        return Matrix3<T>(
+          this->Ixxyyzz[0], this->Ixyxzyz[0], this->Ixyxzyz[1],
+          this->Ixyxzyz[0], this->Ixxyyzz[1], this->Ixyxzyz[2],
+          this->Ixyxzyz[1], this->Ixyxzyz[2], this->Ixxyyzz[2]);
+      }
+
+      /// \brief Sets Moments of Inertia (MOI) from a Matrix3.
+      /// Symmetric component of input matrix is used by averaging
+      /// off-axis terms.
+      /// \param[in] Moments of Inertia as a Matrix3
+      /// \return True if the MassMatrix3 is valid.
+      public: bool MOI(const Matrix3<T> &_moi)
+      {
+        this->Ixxyyzz.Set(_moi(0, 0), _moi(1, 1), _moi(2, 2));
+        this->Ixyxzyz.Set(
+          0.5*(_moi(0, 1) + _moi(1, 0)),
+          0.5*(_moi(0, 2) + _moi(2, 0)),
+          0.5*(_moi(1, 2) + _moi(2, 1)));
+        return this->IsValid();
+      }
+
+      /// \brief Equal operator.
+      /// \param[in] _massMatrix MassMatrix3 to copy.
+      /// \return Reference to this object.
+      public: MassMatrix3 &operator=(const MassMatrix3<T> &_massMatrix)
+      {
+        this->mass = _massMatrix.Mass();
+        this->Ixxyyzz = _massMatrix.DiagonalMoments();
+        this->Ixyxzyz = _massMatrix.OffDiagonalMoments();
+
+        return *this;
+      }
+
+      /// \brief Equality comparison operator.
+      /// \param[in] _m MassMatrix3 to copy.
+      /// \return true if each component is equal within a default tolerance,
+      /// false otherwise
+      public: bool operator==(const MassMatrix3<T> &_m) const
+      {
+        return equal<T>(this->mass, _m.Mass()) &&
+               (this->Ixxyyzz == _m.DiagonalMoments()) &&
+               (this->Ixyxzyz == _m.OffDiagonalMoments());
+      }
+
+      /// \brief Inequality test operator
+      /// \param[in] _m MassMatrix3<T> to test
+      /// \return True if not equal (using the default tolerance of 1e-6)
+      public: bool operator!=(const MassMatrix3<T> &_m) const
+      {
+        return !(*this == _m);
+      }
+
+      /// \brief Verify that inertia values are positive definite
+      /// \return True if mass is positive and moment of inertia matrix
+      /// is positive definite.
+      public: bool IsPositive() const
+      {
+        // Check if mass and determinants of all upper left submatrices
+        // of moment of inertia matrix are positive
+        return (this->mass > 0) &&
+               (this->IXX() > 0) &&
+               (this->IXX()*this->IYY() - std::pow(this->IXY(), 2) > 0) &&
+               (this->MOI().Determinant() > 0);
+      }
+
+      /// \brief Verify that inertia values are positive definite
+      /// and satisfy the triangle inequality.
+      /// \return True if IsPositive and moment of inertia satisfies
+      /// the triangle inequality.
+      public: bool IsValid() const
+      {
+        return this->IsPositive() && ValidMoments(this->PrincipalMoments());
+      }
+
+      /// \brief Verify that principal moments are positive
+      /// and satisfy the triangle inequality.
+      /// \param[in] _moments Principal moments of inertia.
+      /// \return True if moments of inertia are positive
+      /// and satisfy the triangle inequality.
+      public: static bool ValidMoments(const Vector3<T> &_moments)
+      {
+        return _moments[0] > 0 &&
+               _moments[1] > 0 &&
+               _moments[2] > 0 &&
+               _moments[0] + _moments[1] > _moments[2] &&
+               _moments[1] + _moments[2] > _moments[0] &&
+               _moments[2] + _moments[0] > _moments[1];
+      }
+
+      /// \brief Compute principal moments of inertia,
+      /// which are the eigenvalues of the moment of inertia matrix.
+      /// \param[in] _tol Relative tolerance given by absolute value
+      /// of _tol.
+      /// Negative values of _tol are interpreted as a flag that
+      /// causes principal moments to always be sorted from smallest
+      /// to largest.
+      /// \return Principal moments of inertia.
+      /// If the matrix is already diagonal and _tol is positive,
+      /// they are returned in the existing order.
+      /// Otherwise, the moments are sorted from smallest to largest.
+      public: Vector3<T> PrincipalMoments(const T _tol = 1e-6) const
+      {
+        // Compute tolerance relative to maximum value of inertia diagonal
+        T tol = _tol * this->Ixxyyzz.Max();
+        if (this->Ixyxzyz.Equal(Vector3<T>::Zero, tol))
+        {
+          // Matrix is already diagonalized, return diagonal moments
+          return this->Ixxyyzz;
+        }
+
+        // Algorithm based on http://arxiv.org/abs/1306.6291v4
+        // A Method for Fast Diagonalization of a 2x2 or 3x3 Real Symmetric
+        // Matrix, by Maarten Kronenburg
+        Vector3<T> Id(this->Ixxyyzz);
+        Vector3<T> Ip(this->Ixyxzyz);
+        // b = Ixx + Iyy + Izz
+        T b = Id.Sum();
+        // c = Ixx*Iyy - Ixy^2  +  Ixx*Izz - Ixz^2  +  Iyy*Izz - Iyz^2
+        T c = Id[0]*Id[1] - std::pow(Ip[0], 2)
+            + Id[0]*Id[2] - std::pow(Ip[1], 2)
+            + Id[1]*Id[2] - std::pow(Ip[2], 2);
+        // d = Ixx*Iyz^2 + Iyy*Ixz^2 + Izz*Ixy^2 - Ixx*Iyy*Izz - 2*Ixy*Ixz*Iyz
+        T d = Id[0]*std::pow(Ip[2], 2)
+            + Id[1]*std::pow(Ip[1], 2)
+            + Id[2]*std::pow(Ip[0], 2)
+            - Id[0]*Id[1]*Id[2]
+            - 2*Ip[0]*Ip[1]*Ip[2];
+        // p = b^2 - 3c
+        T p = std::pow(b, 2) - 3*c;
+
+        // At this point, it is important to check that p is not close
+        //  to zero, since its inverse is used to compute delta.
+        // In equation 4.7, p is expressed as a sum of squares
+        //  that is only zero if the matrix is diagonal
+        //  with identical principal moments.
+        // This check has no test coverage, since this function returns
+        //  immediately if a diagonal matrix is detected.
+        if (p < std::pow(tol, 2))
+          return b / 3.0 * Vector3<T>::One;
+
+        // q = 2b^3 - 9bc - 27d
+        T q = 2*std::pow(b, 3) - 9*b*c - 27*d;
+
+        // delta = acos(q / (2 * p^(1.5)))
+        // additionally clamp the argument to [-1,1]
+        T delta = acos(clamp<T>(0.5 * q / std::pow(p, 1.5), -1, 1));
+
+        // sort the moments from smallest to largest
+        T moment0 = (b + 2*sqrt(p) * cos(delta / 3.0)) / 3.0;
+        T moment1 = (b + 2*sqrt(p) * cos((delta + 2*IGN_PI)/3.0)) / 3.0;
+        T moment2 = (b + 2*sqrt(p) * cos((delta - 2*IGN_PI)/3.0)) / 3.0;
+        sort3(moment0, moment1, moment2);
+        return Vector3<T>(moment0, moment1, moment2);
+      }
+
+      /// \brief Compute rotational offset of principal axes.
+      /// \param[in] _tol Relative tolerance given by absolute value
+      /// of _tol.
+      /// Negative values of _tol are interpreted as a flag that
+      /// causes principal moments to always be sorted from smallest
+      /// to largest.
+      /// \return Quaternion representing rotational offset of principal axes.
+      /// With a rotation matrix constructed from this quaternion R(q)
+      /// and a diagonal matrix L with principal moments on the diagonal,
+      /// the original moment of inertia matrix MOI can be reconstructed
+      /// with MOI = R(q).Transpose() * L * R(q)
+      public: Quaternion<T> PrincipalAxesOffset(const T _tol = 1e-6) const
+      {
+        // Compute tolerance relative to maximum value of inertia diagonal
+        T tol = _tol * this->Ixxyyzz.Max();
+        Vector3<T> moments = this->PrincipalMoments(tol);
+        if (moments.Equal(this->Ixxyyzz, tol) ||
+            (math::equal<T>(moments[0], moments[1], std::abs(tol)) &&
+             math::equal<T>(moments[0], moments[2], std::abs(tol))))
+        {
+          // matrix is already aligned with principal axes
+          // or all three moments are approximately equal
+          // return identity rotation
+          return Quaternion<T>::Identity;
+        }
+
+        // Algorithm based on http://arxiv.org/abs/1306.6291v4
+        // A Method for Fast Diagonalization of a 2x2 or 3x3 Real Symmetric
+        // Matrix, by Maarten Kronenburg
+        // A real, symmetric matrix can be diagonalized by an orthogonal matrix
+        // (due to the finite-dimensional spectral theorem
+        // https://en.wikipedia.org/wiki/Spectral_theorem
+        // #Hermitian_maps_and_Hermitian_matrices ),
+        // and another name for orthogonal matrix is rotation matrix.
+        // Section 5 of the paper shows how to compute Euler angles
+        // phi1, phi2, and phi3 that map to a rotation matrix.
+        // In some cases, there are multiple possible values for a given angle,
+        // such as phi1, that are denoted as phi11, phi12, phi11a, phi12a, etc.
+        // Similar variable names are used to the paper so that the paper
+        // can be used as an additional reference.
+
+        // f1, f2 defined in equations 5.5, 5.6
+        Vector2<T> f1(this->Ixyxzyz[0], -this->Ixyxzyz[1]);
+        Vector2<T> f2(this->Ixxyyzz[1] - this->Ixxyyzz[2],
+                   -2*this->Ixyxzyz[2]);
+
+        // Check if two moments are equal, since different equations are used
+        // The moments vector is already sorted, so just check adjacent values.
+        Vector2<T> momentsDiff(moments[0] - moments[1],
+                               moments[1] - moments[2]);
+
+        // index of unequal moment
+        int unequalMoment = -1;
+        if (equal<T>(momentsDiff[0], 0, std::abs(tol)))
+          unequalMoment = 2;
+        else if (equal<T>(momentsDiff[1], 0, std::abs(tol)))
+          unequalMoment = 0;
+
+        if (unequalMoment >= 0)
+        {
+          // moments[1] is the repeated value
+          // it is not equal to moments[unequalMoment]
+          // momentsDiff3 = lambda - lambda3
+          T momentsDiff3 = moments[1] - moments[unequalMoment];
+          // eq 5.21:
+          // s = cos(phi2)^2 = (A_11 - lambda3) / (lambda - lambda3)
+          // s >= 0 since A_11 is in range [lambda, lambda3]
+          T s = (this->Ixxyyzz[0] - moments[unequalMoment]) / momentsDiff3;
+          // set phi3 to zero for repeated moments (eq 5.23)
+          T phi3 = 0;
+          // phi2 = +- acos(sqrt(s))
+          // start with just the positive value
+          // also clamp the acos argument to prevent NaN's
+          T phi2 = acos(clamp<T>(ClampedSqrt(s), -1, 1));
+
+          // The paper defines variables phi11 and phi12
+          // which are candidate values of angle phi1.
+          // phi12 is straightforward to compute as a function of f2 and g2.
+          // eq 5.25:
+          Vector2<T> g2(momentsDiff3 * s, 0);
+          // combining eq 5.12 and 5.14, and subtracting psi2
+          // instead of multiplying by its rotation matrix:
+          math::Angle phi12(0.5*(Angle2(g2, tol) - Angle2(f2, tol)));
+          phi12.Normalize();
+
+          // The paragraph prior to equation 5.16 describes how to choose
+          // the candidate value of phi1 based on the length
+          // of the f1 and f2 vectors.
+          // * When |f1| != 0 and |f2| != 0, then one should choose the
+          //   value of phi2 so that phi11 = phi12
+          // * When |f1| == 0 and f2 != 0, then phi1 = phi12
+          //   phi11 can be ignored, and either sign of phi2 can be used
+          // * The case of |f2| == 0 can be ignored at this point in the code
+          //   since having a repeated moment when |f2| == 0 implies that
+          //   the matrix is diagonal. But this function returns a unit
+          //   quaternion for diagonal matrices, so we can assume |f2| != 0
+          //   See MassMatrix3.ipynb for a more complete discussion.
+          //
+          // Since |f2| != 0, we only need to consider |f1|
+          // * |f1| == 0: phi1 = phi12
+          // * |f1| != 0: choose phi2 so that phi11 == phi12
+          // In either case, phi1 = phi12,
+          // and the sign of phi2 must be chosen to make phi11 == phi12
+          T phi1 = phi12.Radian();
+
+          bool f1small = f1.SquaredLength() < std::pow(tol, 2);
+          if (!f1small)
+          {
+            // a: phi2 > 0
+            // eq. 5.24
+            Vector2<T> g1a(0, 0.5*momentsDiff3 * sin(2*phi2));
+            // combining eq 5.11 and 5.13, and subtracting psi1
+            // instead of multiplying by its rotation matrix:
+            math::Angle phi11a(Angle2(g1a, tol) - Angle2(f1, tol));
+            phi11a.Normalize();
+
+            // b: phi2 < 0
+            // eq. 5.24
+            Vector2<T> g1b(0, 0.5*momentsDiff3 * sin(-2*phi2));
+            // combining eq 5.11 and 5.13, and subtracting psi1
+            // instead of multiplying by its rotation matrix:
+            math::Angle phi11b(Angle2(g1b, tol) - Angle2(f1, tol));
+            phi11b.Normalize();
+
+            // choose sign of phi2
+            // based on whether phi11a or phi11b is closer to phi12
+            // use sin and cos to account for angle wrapping
+            T erra = std::pow(sin(phi1) - sin(phi11a.Radian()), 2)
+                   + std::pow(cos(phi1) - cos(phi11a.Radian()), 2);
+            T errb = std::pow(sin(phi1) - sin(phi11b.Radian()), 2)
+                   + std::pow(cos(phi1) - cos(phi11b.Radian()), 2);
+            if (errb < erra)
+            {
+              phi2 *= -1;
+            }
+          }
+
+          // I determined these arguments using trial and error
+          Quaternion<T> result = Quaternion<T>(-phi1, -phi2, -phi3).Inverse();
+
+          // Previous equations assume repeated moments are at the beginning
+          // of the moments vector (moments[0] == moments[1]).
+          // We have the vectors sorted by size, so it's possible that the
+          // repeated moments are at the end (moments[1] == moments[2]).
+          // In this case (unequalMoment == 0), we apply an extra
+          // rotation that exchanges moment[0] and moment[2]
+          // Rotation matrix = [ 0  0  1]
+          //                   [ 0  1  0]
+          //                   [-1  0  0]
+          // That is equivalent to a 90 degree pitch
+          if (unequalMoment == 0)
+            result *= Quaternion<T>(0, IGN_PI_2, 0);
+
+          return result;
+        }
+
+        // No repeated principal moments
+        // eq 5.1:
+        T v = (std::pow(this->Ixyxzyz[0], 2) + std::pow(this->Ixyxzyz[1], 2)
+              +(this->Ixxyyzz[0] - moments[2])
+              *(this->Ixxyyzz[0] + moments[2] - moments[0] - moments[1]))
+            / ((moments[1] - moments[2]) * (moments[2] - moments[0]));
+        // value of w depends on v
+        T w;
+        if (v < std::abs(tol))
+        {
+          // first sentence after eq 5.4:
+          // "In the case that v = 0, then w = 1."
+          w = 1;
+        }
+        else
+        {
+          // eq 5.2:
+          w = (this->Ixxyyzz[0] - moments[2] + (moments[2] - moments[1])*v)
+              / ((moments[0] - moments[1]) * v);
+        }
+        // initialize values of angle phi1, phi2, phi3
+        T phi1 = 0;
+        // eq 5.3: start with positive value
+        T phi2 = acos(clamp<T>(ClampedSqrt(v), -1, 1));
+        // eq 5.4: start with positive value
+        T phi3 = acos(clamp<T>(ClampedSqrt(w), -1, 1));
+
+        // compute g1, g2 for phi2,phi3 >= 0
+        // equations 5.7, 5.8
+        Vector2<T> g1(
+          0.5* (moments[0]-moments[1])*ClampedSqrt(v)*sin(2*phi3),
+          0.5*((moments[0]-moments[1])*w + moments[1]-moments[2])*sin(2*phi2));
+        Vector2<T> g2(
+          (moments[0]-moments[1])*(1 + (v-2)*w) + (moments[1]-moments[2])*v,
+          (moments[0]-moments[1])*sin(phi2)*sin(2*phi3));
+
+        // The paragraph prior to equation 5.16 describes how to choose
+        // the candidate value of phi1 based on the length
+        // of the f1 and f2 vectors.
+        // * The case of |f1| == |f2| == 0 implies a repeated moment,
+        //   which should not be possible at this point in the code
+        // * When |f1| != 0 and |f2| != 0, then one should choose the
+        //   value of phi2 so that phi11 = phi12
+        // * When |f1| == 0 and f2 != 0, then phi1 = phi12
+        //   phi11 can be ignored, and either sign of phi2, phi3 can be used
+        // * When |f2| == 0 and f1 != 0, then phi1 = phi11
+        //   phi12 can be ignored, and either sign of phi2, phi3 can be used
+        bool f1small = f1.SquaredLength() < std::pow(tol, 2);
+        bool f2small = f2.SquaredLength() < std::pow(tol, 2);
+        if (f1small && f2small)
+        {
+          // this should never happen
+          // f1small && f2small implies a repeated moment
+          // return invalid quaternion
+          /// \todo Use a mock class to test this line
+          return Quaternion<T>::Zero;
+        }
+        else if (f1small)
+        {
+          // use phi12 (equations 5.12, 5.14)
+          math::Angle phi12(0.5*(Angle2(g2, tol) - Angle2(f2, tol)));
+          phi12.Normalize();
+          phi1 = phi12.Radian();
+        }
+        else if (f2small)
+        {
+          // use phi11 (equations 5.11, 5.13)
+          math::Angle phi11(Angle2(g1, tol) - Angle2(f1, tol));
+          phi11.Normalize();
+          phi1 = phi11.Radian();
+        }
+        else
+        {
+          // check for when phi11 == phi12
+          // eqs 5.11, 5.13:
+          math::Angle phi11(Angle2(g1, tol) - Angle2(f1, tol));
+          phi11.Normalize();
+          // eqs 5.12, 5.14:
+          math::Angle phi12(0.5*(Angle2(g2, tol) - Angle2(f2, tol)));
+          phi12.Normalize();
+          T err  = std::pow(sin(phi11.Radian()) - sin(phi12.Radian()), 2)
+                 + std::pow(cos(phi11.Radian()) - cos(phi12.Radian()), 2);
+          phi1 = phi11.Radian();
+          math::Vector2<T> signsPhi23(1, 1);
+          // case a: phi2 <= 0
+          {
+            Vector2<T> g1a = Vector2<T>(1, -1) * g1;
+            Vector2<T> g2a = Vector2<T>(1, -1) * g2;
+            math::Angle phi11a(Angle2(g1a, tol) - Angle2(f1, tol));
+            math::Angle phi12a(0.5*(Angle2(g2a, tol) - Angle2(f2, tol)));
+            phi11a.Normalize();
+            phi12a.Normalize();
+            T erra = std::pow(sin(phi11a.Radian()) - sin(phi12a.Radian()), 2)
+                   + std::pow(cos(phi11a.Radian()) - cos(phi12a.Radian()), 2);
+            if (erra < err)
+            {
+              err = erra;
+              phi1 = phi11a.Radian();
+              signsPhi23.Set(-1, 1);
+            }
+          }
+          // case b: phi3 <= 0
+          {
+            Vector2<T> g1b = Vector2<T>(-1, 1) * g1;
+            Vector2<T> g2b = Vector2<T>(1, -1) * g2;
+            math::Angle phi11b(Angle2(g1b, tol) - Angle2(f1, tol));
+            math::Angle phi12b(0.5*(Angle2(g2b, tol) - Angle2(f2, tol)));
+            phi11b.Normalize();
+            phi12b.Normalize();
+            T errb = std::pow(sin(phi11b.Radian()) - sin(phi12b.Radian()), 2)
+                   + std::pow(cos(phi11b.Radian()) - cos(phi12b.Radian()), 2);
+            if (errb < err)
+            {
+              err = errb;
+              phi1 = phi11b.Radian();
+              signsPhi23.Set(1, -1);
+            }
+          }
+          // case c: phi2,phi3 <= 0
+          {
+            Vector2<T> g1c = Vector2<T>(-1, -1) * g1;
+            Vector2<T> g2c = g2;
+            math::Angle phi11c(Angle2(g1c, tol) - Angle2(f1, tol));
+            math::Angle phi12c(0.5*(Angle2(g2c, tol) - Angle2(f2, tol)));
+            phi11c.Normalize();
+            phi12c.Normalize();
+            T errc = std::pow(sin(phi11c.Radian()) - sin(phi12c.Radian()), 2)
+                   + std::pow(cos(phi11c.Radian()) - cos(phi12c.Radian()), 2);
+            if (errc < err)
+            {
+              err = errc;
+              phi1 = phi11c.Radian();
+              signsPhi23.Set(-1, -1);
+            }
+          }
+
+          // apply sign changes
+          phi2 *= signsPhi23[0];
+          phi3 *= signsPhi23[1];
+        }
+
+        // I determined these arguments using trial and error
+        return Quaternion<T>(-phi1, -phi2, -phi3).Inverse();
+      }
+
+      /// \brief Get dimensions and rotation offset of uniform box
+      /// with equivalent mass and moment of inertia.
+      /// To compute this, the Matrix3 is diagonalized.
+      /// The eigenvalues on the diagonal and the rotation offset
+      /// of the principal axes are returned.
+      /// \param[in] _size Dimensions of box aligned with principal axes.
+      /// \param[in] _rot Rotational offset of principal axes.
+      /// \param[in] _tol Relative tolerance.
+      /// \return True if box properties were computed successfully.
+      public: bool EquivalentBox(Vector3<T> &_size,
+                                 Quaternion<T> &_rot,
+                                 const T _tol = 1e-6) const
+      {
+        if (!this->IsPositive())
+        {
+          // inertia is not positive, cannot compute equivalent box
+          return false;
+        }
+
+        Vector3<T> moments = this->PrincipalMoments(_tol);
+        if (!ValidMoments(moments))
+        {
+          // principal moments don't satisfy the triangle identity
+          return false;
+        }
+
+        // The reason for checking that the principal moments satisfy
+        // the triangle inequality
+        // I1 + I2 - I3 >= 0
+        // is to ensure that the arguments to sqrt in these equations
+        // are positive and the box size is real.
+        _size.X(sqrt(6*(moments.Y() + moments.Z() - moments.X()) / this->mass));
+        _size.Y(sqrt(6*(moments.Z() + moments.X() - moments.Y()) / this->mass));
+        _size.Z(sqrt(6*(moments.X() + moments.Y() - moments.Z()) / this->mass));
+
+        _rot = this->PrincipalAxesOffset(_tol);
+
+        if (_rot == Quaternion<T>::Zero)
+        {
+          // _rot is an invalid quaternion
+          /// \todo Use a mock class to test this line
+          return false;
+        }
+
+        return true;
+      }
+
+      /// \brief Set inertial properties based on mass and equivalent box.
+      /// \param[in] _mass Mass to set.
+      /// \param[in] _size Size of equivalent box.
+      /// \param[in] _rot Rotational offset of equivalent box.
+      /// \return True if inertial properties were set successfully.
+      public: bool SetFromBox(const T _mass,
+                              const Vector3<T> &_size,
+                            const Quaternion<T> &_rot = Quaternion<T>::Identity)
+      {
+        // Check that _mass and _size are strictly positive
+        // and that quatenion is valid
+        if (_mass <= 0 || _size.Min() <= 0 || _rot == Quaternion<T>::Zero)
+        {
+          return false;
+        }
+        this->Mass(_mass);
+        return this->SetFromBox(_size, _rot);
+      }
+
+      /// \brief Set inertial properties based on equivalent box
+      /// using the current mass value.
+      /// \param[in] _size Size of equivalent box.
+      /// \param[in] _rot Rotational offset of equivalent box.
+      /// \return True if inertial properties were set successfully.
+      public: bool SetFromBox(const Vector3<T> &_size,
+                            const Quaternion<T> &_rot = Quaternion<T>::Identity)
+      {
+        // Check that _mass and _size are strictly positive
+        // and that quatenion is valid
+        if (this->Mass() <= 0 || _size.Min() <= 0 ||
+            _rot == Quaternion<T>::Zero)
+        {
+          return false;
+        }
+
+        // Diagonal matrix L with principal moments
+        Matrix3<T> L;
+        T x2 = std::pow(_size.X(), 2);
+        T y2 = std::pow(_size.Y(), 2);
+        T z2 = std::pow(_size.Z(), 2);
+        L(0, 0) = this->mass / 12.0 * (y2 + z2);
+        L(1, 1) = this->mass / 12.0 * (z2 + x2);
+        L(2, 2) = this->mass / 12.0 * (x2 + y2);
+        Matrix3<T> R(_rot);
+        return this->MOI(R * L * R.Transposed());
+      }
+
+      /// \brief Set inertial properties based on mass and equivalent cylinder
+      /// aligned with Z axis.
+      /// \param[in] _mass Mass to set.
+      /// \param[in] _length Length of cylinder along Z axis.
+      /// \param[in] _radius Radius of cylinder.
+      /// \param[in] _rot Rotational offset of equivalent cylinder.
+      /// \return True if inertial properties were set successfully.
+      public: bool SetFromCylinderZ(const T _mass,
+                                    const T _length,
+                                    const T _radius,
+                            const Quaternion<T> &_rot = Quaternion<T>::Identity)
+      {
+        // Check that _mass, _radius and _length are strictly positive
+        // and that quatenion is valid
+        if (_mass <= 0 || _length <= 0 || _radius <= 0 ||
+            _rot == Quaternion<T>::Zero)
+        {
+          return false;
+        }
+        this->Mass(_mass);
+        return this->SetFromCylinderZ(_length, _radius, _rot);
+      }
+
+      /// \brief Set inertial properties based on equivalent cylinder
+      /// aligned with Z axis using the current mass value.
+      /// \param[in] _length Length of cylinder along Z axis.
+      /// \param[in] _radius Radius of cylinder.
+      /// \param[in] _rot Rotational offset of equivalent cylinder.
+      /// \return True if inertial properties were set successfully.
+      public: bool SetFromCylinderZ(const T _length,
+                                    const T _radius,
+                                    const Quaternion<T> &_rot)
+      {
+        // Check that _mass and _size are strictly positive
+        // and that quatenion is valid
+        if (this->Mass() <= 0 || _length <= 0 || _radius <= 0 ||
+            _rot == Quaternion<T>::Zero)
+        {
+          return false;
+        }
+
+        // Diagonal matrix L with principal moments
+        T radius2 = std::pow(_radius, 2);
+        Matrix3<T> L;
+        L(0, 0) = this->mass / 12.0 * (3*radius2 + std::pow(_length, 2));
+        L(1, 1) = L(0, 0);
+        L(2, 2) = this->mass / 2.0 * radius2;
+        Matrix3<T> R(_rot);
+        return this->MOI(R * L * R.Transposed());
+      }
+
+      /// \brief Set inertial properties based on mass and equivalent sphere.
+      /// \param[in] _mass Mass to set.
+      /// \param[in] _radius Radius of equivalent, uniform sphere.
+      /// \return True if inertial properties were set successfully.
+      public: bool SetFromSphere(const T _mass, const T _radius)
+      {
+        // Check that _mass and _radius are strictly positive
+        if (_mass <= 0 || _radius <= 0)
+        {
+          return false;
+        }
+        this->Mass(_mass);
+        return this->SetFromSphere(_radius);
+      }
+
+      /// \brief Set inertial properties based on equivalent sphere
+      /// using the current mass value.
+      /// \param[in] _radius Radius of equivalent, uniform sphere.
+      /// \return True if inertial properties were set successfully.
+      public: bool SetFromSphere(const T _radius)
+      {
+        // Check that _mass and _radius are strictly positive
+        if (this->Mass() <= 0 || _radius <= 0)
+        {
+          return false;
+        }
+
+        // Diagonal matrix L with principal moments
+        T radius2 = std::pow(_radius, 2);
+        Matrix3<T> L;
+        L(0, 0) = 0.4 * this->mass * radius2;
+        L(1, 1) = 0.4 * this->mass * radius2;
+        L(2, 2) = 0.4 * this->mass * radius2;
+        return this->MOI(L);
+      }
+
+      /// \brief Square root of positive numbers, otherwise zero.
+      /// \param[in] _x Number to be square rooted.
+      /// \return sqrt(_x) if _x > 0, otherwise 0
+      private: static inline T ClampedSqrt(const T &_x)
+      {
+        if (_x <= 0)
+          return 0;
+        return sqrt(_x);
+      }
+
+      /// \brief Angle formed by direction of a Vector2.
+      /// \param[in] _v Vector whose direction is to be computed.
+      /// \param[in] _eps Minimum length of vector required for computing angle.
+      /// \return Angle formed between vector and X axis,
+      /// or zero if vector has length less than 1e-6.
+      private: static T Angle2(const Vector2<T> &_v, const T _eps = 1e-6)
+      {
+        if (_v.SquaredLength() < std::pow(_eps, 2))
+          return 0;
+        return atan2(_v[1], _v[0]);
+      }
+
+      /// \brief Mass of the object. Default is 0.0.
+      private: T mass;
+
+      /// \brief Principal moments of inertia. Default is (0.0 0.0 0.0)
+      /// These Moments of Inertia are specified in the local frame.
+      /// Where Ixxyyzz.x is Ixx, Ixxyyzz.y is Iyy and Ixxyyzz.z is Izz.
+      private: Vector3<T> Ixxyyzz;
+
+      /// \brief Product moments of inertia. Default is (0.0 0.0 0.0)
+      /// These MOI off-diagonals are specified in the local frame.
+      /// Where Ixyxzyz.x is Ixy, Ixyxzyz.y is Ixz and Ixyxzyz.z is Iyz.
+      private: Vector3<T> Ixyxzyz;
+    };
+
+    typedef MassMatrix3<double> MassMatrix3d;
+    typedef MassMatrix3<float> MassMatrix3f;
+  }
+}
+#endif
diff --git a/include/ignition/math/MassMatrix3.ipynb b/include/ignition/math/MassMatrix3.ipynb
new file mode 100644
index 0000000..0e94e96
--- /dev/null
+++ b/include/ignition/math/MassMatrix3.ipynb
@@ -0,0 +1,134 @@
+{
+ "metadata": {
+  "name": "",
+  "signature": "sha256:806f7b6e2812a7f1e8ff67e708d852d06c6ed452860f8c9bb02bb4ff9ea5fdbf"
+ },
+ "nbformat": 3,
+ "nbformat_minor": 0,
+ "worksheets": [
+  {
+   "cells": [
+    {
+     "cell_type": "markdown",
+     "metadata": {},
+     "source": [
+      "# Diagonalization of 3x3 symmetric matrix\n",
+      "\n",
+      "The `MassMatrix3` class uses an algorithm described in [A Method for Fast Diagonalization of a 2x2 or 3x3 Real Symmetric Matrix](http://arxiv.org/abs/1306.6291v4) by M.J. Kronenburg. This document proves that when a matrix $\\textbf{A}$ has a repeated eigenvalue and the vector $\\textbf{f}_2$ has length 0, then $\\textbf{A}$ is a diagonal matrix.\n",
+      "\n",
+      "The symmetric 3x3 matrix $\\textbf{A}$ has diagonal elements $A_{11}$, $A_{22}$, and $A_{33}$ and off-diagonal terms $A_{12}$, $A_{13}$, and $A_{23}$. The vector $\\textbf{f}_2$ is defined in (5.6) as\n",
+      "\n",
+      "$\\textbf{f}_2 = [A_{22} - A_{33}, -2A_{23}]^T$\n",
+      "\n",
+      "When $\\textbf{f}_2$ has length zero, the following are true:\n",
+      "\n",
+      "$A_{22} = A_{33} = A$\n",
+      "\n",
+      "$A_{23} = 0$\n",
+      "\n",
+      "In Section 4, conditions are given for which a matrix will have at least 1 repeated eigenvalue $\\lambda$ based on the coefficients of its characteristic equation:\n",
+      "\n",
+      "$\\lambda^3 - b \\lambda^2 + c \\lambda + d = 0$\n",
+      "\n",
+      "With $p = b^2 - 3c$ and $q = 2b^3 - 9bc - 27d$, there is at least one repeated eigenvalue when $q^2 = 4p^3$\n",
+      "\n",
+      "These conditions are manipulated symbolically below:"
+     ]
+    },
+    {
+     "cell_type": "code",
+     "collapsed": false,
+     "input": [
+      "from sympy import *"
+     ],
+     "language": "python",
+     "metadata": {},
+     "outputs": []
+    },
+    {
+     "cell_type": "code",
+     "collapsed": false,
+     "input": [
+      "# Identify condition in which there is a repeated eigenvalue (Q^2 - 4P^3 = 0)\n",
+      "B, C, D, P, Q = symbols('B C D P Q')\n",
+      "P = B**2 - 3*C\n",
+      "Q = 2*B**3 - 9*B*C - 27*D\n",
+      "simplify(expand(Q**2 - 4*P**3))"
+     ],
+     "language": "python",
+     "metadata": {},
+     "outputs": [
+      {
+       "metadata": {},
+       "output_type": "pyout",
+       "prompt_number": 13,
+       "text": [
+        "-108*B**3*D - 27*B**2*C**2 + 486*B*C*D + 108*C**3 + 729*D**2"
+       ]
+      }
+     ],
+     "prompt_number": 13
+    },
+    {
+     "cell_type": "markdown",
+     "metadata": {},
+     "source": [
+      "First the condition in which there is a repeated eigen value ($q^2 = 4p^3$) is expressed in terms of $b$, $c$, and $d$ and simplified to:\n",
+      "\n",
+      "$-108b^3d - 27b^2c^2 + 486bcd + 108c^3 + 729d^2 = 0$"
+     ]
+    },
+    {
+     "cell_type": "code",
+     "collapsed": false,
+     "input": [
+      "# Expand expression for which there is a repeated eigenvalue\n",
+      "A11, A12, A13, A = symbols('A11 A12 A13 A')\n",
+      "b, c, d = symbols('b c d')\n",
+      "b = A11 + 2*A\n",
+      "c = A11*A + A11*A + A**2 - A12**2 - A13**2\n",
+      "d = A*A13**2 + A*A12**2 - A11*A**2\n",
+      "factor(simplify(-108*b**3*d - 27*b**2*c**2 + 486*b*c*d + 108*c**3 + 729*d**2))"
+     ],
+     "language": "python",
+     "metadata": {},
+     "outputs": [
+      {
+       "metadata": {},
+       "output_type": "pyout",
+       "prompt_number": 16,
+       "text": [
+        "-27*(A12**2 + A13**2)**2*(A**2 - 2*A*A11 + A11**2 + 4*A12**2 + 4*A13**2)"
+       ]
+      }
+     ],
+     "prompt_number": 16
+    },
+    {
+     "cell_type": "markdown",
+     "metadata": {},
+     "source": [
+      "This condition is then expressed in terms of $A11$, $A$, $A12$, and $A13$ corresponding to $\\textbf{f}_2 = 0$.\n",
+      "After simplification and factoring, there are 2 cases for which the expression is equal to zero:\n",
+      "\n",
+      "$A_{12}^2 + A_{13}^2 = 0$\n",
+      "\n",
+      "$4A_{12}^2 + 4A_{13}^2 + (A - A_{11})^2 = 0$\n",
+      "\n",
+      "In both cases, $A_{12} = A_{13} = 0$ is a pre-requisite. Since $A_{23} = 0$ was already assumed, this implies that\n",
+      "the matrix must be diagonal if it has any repeated eigenvalues and $\\textbf{f}_2 = 0$."
+     ]
+    },
+    {
+     "cell_type": "code",
+     "collapsed": false,
+     "input": [],
+     "language": "python",
+     "metadata": {},
+     "outputs": []
+    }
+   ],
+   "metadata": {}
+  }
+ ]
+}
\ No newline at end of file
diff --git a/include/ignition/math/Matrix3.hh b/include/ignition/math/Matrix3.hh
new file mode 100644
index 0000000..7fd2704
--- /dev/null
+++ b/include/ignition/math/Matrix3.hh
@@ -0,0 +1,544 @@
+/*
+ * Copyright (C) 2012 Open Source Robotics Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+*/
+#ifndef IGNITION_MATH_MATRIX3_HH_
+#define IGNITION_MATH_MATRIX3_HH_
+
+#include <algorithm>
+#include <cstring>
+#include <ignition/math/Helpers.hh>
+#include <ignition/math/Vector3.hh>
+#include <ignition/math/Quaternion.hh>
+
+namespace ignition
+{
+  namespace math
+  {
+    template <typename T> class Quaternion;
+
+    /// \class Matrix3 Matrix3.hh ignition/math/Matrix3.hh
+    /// \brief A 3x3 matrix class
+    template<typename T>
+    class Matrix3
+    {
+      /// \brief Identity matrix
+      public: static const Matrix3<T> Identity;
+
+      /// \brief Zero matrix
+      public: static const Matrix3<T> Zero;
+
+      /// \brief Constructor
+      public: Matrix3()
+      {
+        std::memset(this->data, 0, sizeof(this->data[0][0])*9);
+      }
+
+      /// \brief Copy constructor
+      /// \param _m Matrix to copy
+      public: Matrix3(const Matrix3<T> &_m)
+      {
+        std::memcpy(this->data, _m.data, sizeof(this->data[0][0])*9);
+      }
+
+      /// \brief Constructor
+      /// \param[in] _v00 Row 0, Col 0 value
+      /// \param[in] _v01 Row 0, Col 1 value
+      /// \param[in] _v02 Row 0, Col 2 value
+      /// \param[in] _v10 Row 1, Col 0 value
+      /// \param[in] _v11 Row 1, Col 1 value
+      /// \param[in] _v12 Row 1, Col 2 value
+      /// \param[in] _v20 Row 2, Col 0 value
+      /// \param[in] _v21 Row 2, Col 1 value
+      /// \param[in] _v22 Row 2, Col 2 value
+      public: Matrix3(T _v00, T _v01, T _v02,
+                      T _v10, T _v11, T _v12,
+                      T _v20, T _v21, T _v22)
+      {
+        this->data[0][0] = _v00;
+        this->data[0][1] = _v01;
+        this->data[0][2] = _v02;
+        this->data[1][0] = _v10;
+        this->data[1][1] = _v11;
+        this->data[1][2] = _v12;
+        this->data[2][0] = _v20;
+        this->data[2][1] = _v21;
+        this->data[2][2] = _v22;
+      }
+
+      /// \brief Construct Matrix3 from a quaternion.
+      /// \param[in] _q Quaternion.
+      public: explicit Matrix3(const Quaternion<T> &_q)
+      {
+        Quaternion<T> qt = _q;
+        qt.Normalize();
+        this->Set(1 - 2*qt.Y()*qt.Y() - 2 *qt.Z()*qt.Z(),
+                  2 * qt.X()*qt.Y() - 2*qt.Z()*qt.W(),
+                  2 * qt.X() * qt.Z() + 2 * qt.Y() * qt.W(),
+                  2 * qt.X() * qt.Y() + 2 * qt.Z() * qt.W(),
+                  1 - 2*qt.X()*qt.X() - 2 * qt.Z()*qt.Z(),
+                  2 * qt.Y() * qt.Z() - 2 * qt.X() * qt.W(),
+                  2 * qt.X() * qt.Z() - 2 * qt.Y() * qt.W(),
+                  2 * qt.Y() * qt.Z() + 2 * qt.X() * qt.W(),
+                  1 - 2 * qt.X()*qt.X() - 2 * qt.Y()*qt.Y());
+      }
+
+      /// \brief Desctructor
+      public: virtual ~Matrix3() {}
+
+      /// \brief Set values
+      /// \param[in] _v00 Row 0, Col 0 value
+      /// \param[in] _v01 Row 0, Col 1 value
+      /// \param[in] _v02 Row 0, Col 2 value
+      /// \param[in] _v10 Row 1, Col 0 value
+      /// \param[in] _v11 Row 1, Col 1 value
+      /// \param[in] _v12 Row 1, Col 2 value
+      /// \param[in] _v20 Row 2, Col 0 value
+      /// \param[in] _v21 Row 2, Col 1 value
+      /// \param[in] _v22 Row 2, Col 2 value
+      public: void Set(T _v00, T _v01, T _v02,
+                       T _v10, T _v11, T _v12,
+                       T _v20, T _v21, T _v22)
+      {
+        this->data[0][0] = _v00;
+        this->data[0][1] = _v01;
+        this->data[0][2] = _v02;
+        this->data[1][0] = _v10;
+        this->data[1][1] = _v11;
+        this->data[1][2] = _v12;
+        this->data[2][0] = _v20;
+        this->data[2][1] = _v21;
+        this->data[2][2] = _v22;
+      }
+
+      /// \brief Set the matrix from three axis (1 per column)
+      /// \param[in] _xAxis The x axis
+      /// \param[in] _yAxis The y axis
+      /// \param[in] _zAxis The z axis
+      public: void Axes(const Vector3<T> &_xAxis,
+                        const Vector3<T> &_yAxis,
+                        const Vector3<T> &_zAxis)
+      {
+        this->Col(0, _xAxis);
+        this->Col(1, _yAxis);
+        this->Col(2, _zAxis);
+      }
+
+      /// \brief Set the matrix from an axis and angle
+      /// \param[in] _axis the axis
+      /// \param[in] _angle ccw rotation around the axis in radians
+      public: void Axis(const Vector3<T> &_axis, T _angle)
+      {
+        T c = cos(_angle);
+        T s = sin(_angle);
+        T C = 1-c;
+
+        this->data[0][0] = _axis.X()*_axis.X()*C + c;
+        this->data[0][1] = _axis.X()*_axis.Y()*C - _axis.Z()*s;
+        this->data[0][2] = _axis.X()*_axis.Z()*C + _axis.Y()*s;
+
+        this->data[1][0] = _axis.Y()*_axis.X()*C + _axis.Z()*s;
+        this->data[1][1] = _axis.Y()*_axis.Y()*C + c;
+        this->data[1][2] = _axis.Y()*_axis.Z()*C - _axis.X()*s;
+
+        this->data[2][0] = _axis.Z()*_axis.X()*C - _axis.Y()*s;
+        this->data[2][1] = _axis.Z()*_axis.Y()*C + _axis.X()*s;
+        this->data[2][2] = _axis.Z()*_axis.Z()*C + c;
+      }
+
+      /// \brief Set the matrix to represent rotation from
+      /// vector _v1 to vector _v2, so that
+      /// _v2.Normalize() == this * _v1.Normalize() holds.
+      ///
+      /// \param[in] _v1 The first vector
+      /// \param[in] _v2 The second vector
+      public: void From2Axes(const Vector3<T> &_v1, const Vector3<T> &_v2)
+      {
+        const T _v1LengthSquared = _v1.SquaredLength();
+        if (_v1LengthSquared <= 0.0)
+        {
+          // zero vector - we can't handle this
+          this->Set(1, 0, 0, 0, 1, 0, 0, 0, 1);
+          return;
+        }
+
+        const T _v2LengthSquared = _v2.SquaredLength();
+        if (_v2LengthSquared <= 0.0)
+        {
+          // zero vector - we can't handle this
+          this->Set(1, 0, 0, 0, 1, 0, 0, 0, 1);
+          return;
+        }
+
+        const T dot = _v1.Dot(_v2) / sqrt(_v1LengthSquared * _v2LengthSquared);
+        if (fabs(dot - 1.0) <= 1e-6)
+        {
+          // the vectors are parallel
+          this->Set(1, 0, 0, 0, 1, 0, 0, 0, 1);
+          return;
+        }
+        else if (fabs(dot + 1.0) <= 1e-6)
+        {
+          // the vectors are opposite
+          this->Set(-1, 0, 0, 0, -1, 0, 0, 0, -1);
+          return;
+        }
+
+        const Vector3<T> cross = _v1.Cross(_v2).Normalize();
+
+        this->Axis(cross, acos(dot));
+      }
+
+      /// \brief Set a column.
+      /// \param[in] _c The colum index [0, 1, 2]. _col is clamped to the
+      /// range [0, 2].
+      /// \param[in] _v The value to set in each row of the column.
+      public: void Col(unsigned int _c, const Vector3<T> &_v)
+      {
+        unsigned int c = clamp(_c, 0u, 2u);
+
+        this->data[0][c] = _v.X();
+        this->data[1][c] = _v.Y();
+        this->data[2][c] = _v.Z();
+      }
+
+      /// \brief Equal operator. this = _mat
+      /// \param _mat Incoming matrix
+      /// \return itself
+      public: Matrix3<T> &operator=(const Matrix3<T> &_mat)
+      {
+        memcpy(this->data, _mat.data, sizeof(this->data[0][0])*9);
+        return *this;
+      }
+
+      /// \brief returns the element wise difference of two matrices
+      public: Matrix3<T> operator-(const Matrix3<T> &_m) const
+      {
+        return Matrix3<T>(
+            this->data[0][0] - _m(0, 0),
+            this->data[0][1] - _m(0, 1),
+            this->data[0][2] - _m(0, 2),
+            this->data[1][0] - _m(1, 0),
+            this->data[1][1] - _m(1, 1),
+            this->data[1][2] - _m(1, 2),
+            this->data[2][0] - _m(2, 0),
+            this->data[2][1] - _m(2, 1),
+            this->data[2][2] - _m(2, 2));
+      }
+
+      /// \brief returns the element wise sum of two matrices
+      public: Matrix3<T> operator+(const Matrix3<T> &_m) const
+      {
+        return Matrix3<T>(
+            this->data[0][0]+_m(0, 0),
+            this->data[0][1]+_m(0, 1),
+            this->data[0][2]+_m(0, 2),
+            this->data[1][0]+_m(1, 0),
+            this->data[1][1]+_m(1, 1),
+            this->data[1][2]+_m(1, 2),
+            this->data[2][0]+_m(2, 0),
+            this->data[2][1]+_m(2, 1),
+            this->data[2][2]+_m(2, 2));
+      }
+
+      /// \brief returns the element wise scalar multiplication
+      public: Matrix3<T> operator*(const T &_s) const
+      {
+        return Matrix3<T>(
+          _s * this->data[0][0], _s * this->data[0][1], _s * this->data[0][2],
+          _s * this->data[1][0], _s * this->data[1][1], _s * this->data[1][2],
+          _s * this->data[2][0], _s * this->data[2][1], _s * this->data[2][2]);
+      }
+
+      /// \brief Matrix multiplication operator
+      /// \param[in] _m Matrix3<T> to multiply
+      /// \return product of this * _m
+      public: Matrix3<T> operator*(const Matrix3<T> &_m) const
+      {
+        return Matrix3<T>(
+            // first row
+            this->data[0][0]*_m(0, 0)+
+            this->data[0][1]*_m(1, 0)+
+            this->data[0][2]*_m(2, 0),
+
+            this->data[0][0]*_m(0, 1)+
+            this->data[0][1]*_m(1, 1)+
+            this->data[0][2]*_m(2, 1),
+
+            this->data[0][0]*_m(0, 2)+
+            this->data[0][1]*_m(1, 2)+
+            this->data[0][2]*_m(2, 2),
+
+            // second row
+            this->data[1][0]*_m(0, 0)+
+            this->data[1][1]*_m(1, 0)+
+            this->data[1][2]*_m(2, 0),
+
+            this->data[1][0]*_m(0, 1)+
+            this->data[1][1]*_m(1, 1)+
+            this->data[1][2]*_m(2, 1),
+
+            this->data[1][0]*_m(0, 2)+
+            this->data[1][1]*_m(1, 2)+
+            this->data[1][2]*_m(2, 2),
+
+            // third row
+            this->data[2][0]*_m(0, 0)+
+            this->data[2][1]*_m(1, 0)+
+            this->data[2][2]*_m(2, 0),
+
+            this->data[2][0]*_m(0, 1)+
+            this->data[2][1]*_m(1, 1)+
+            this->data[2][2]*_m(2, 1),
+
+            this->data[2][0]*_m(0, 2)+
+            this->data[2][1]*_m(1, 2)+
+            this->data[2][2]*_m(2, 2));
+      }
+
+      /// \brief Multiplication operator with Vector3 on the right
+      /// treated like a column vector.
+      /// \param _vec Vector3
+      /// \return Resulting vector from multiplication
+      public: Vector3<T> operator*(const Vector3<T> &_vec) const
+      {
+        return Vector3<T>(
+            this->data[0][0]*_vec.X() + this->data[0][1]*_vec.Y() +
+            this->data[0][2]*_vec.Z(),
+            this->data[1][0]*_vec.X() + this->data[1][1]*_vec.Y() +
+            this->data[1][2]*_vec.Z(),
+            this->data[2][0]*_vec.X() + this->data[2][1]*_vec.Y() +
+            this->data[2][2]*_vec.Z());
+      }
+
+      /// \brief Matrix multiplication operator for scaling.
+      /// \param[in] _s Scaling factor.
+      /// \param[in] _m Input matrix.
+      /// \return A scaled matrix.
+      public: friend inline Matrix3<T> operator*(T _s, const Matrix3<T> &_m)
+      {
+        return _m * _s;
+      }
+
+      /// \brief Matrix left multiplication operator for Vector3.
+      /// Treats the Vector3 like a row vector multiplying the matrix
+      /// from the left.
+      /// \param[in] _v Input vector.
+      /// \param[in] _m Input matrix.
+      /// \return The product vector.
+      public: friend inline Vector3<T> operator*(const Vector3<T> &_v,
+                                                 const Matrix3<T> &_m)
+      {
+        return Vector3<T>(
+            _m(0, 0)*_v.X() + _m(1, 0)*_v.Y() + _m(2, 0)*_v.Z(),
+            _m(0, 1)*_v.X() + _m(1, 1)*_v.Y() + _m(2, 1)*_v.Z(),
+            _m(0, 2)*_v.X() + _m(1, 2)*_v.Y() + _m(2, 2)*_v.Z());
+      }
+
+      /// \brief Equality test with tolerance.
+      /// \param[in] _m the matrix to compare to
+      /// \param[in] _tol equality tolerance.
+      /// \return true if the elements of the matrices are equal within
+      /// the tolerence specified by _tol.
+      public: bool Equal(const Matrix3 &_m, const T &_tol) const
+      {
+        return equal<T>(this->data[0][0], _m(0, 0), _tol)
+            && equal<T>(this->data[0][1], _m(0, 1), _tol)
+            && equal<T>(this->data[0][2], _m(0, 2), _tol)
+            && equal<T>(this->data[1][0], _m(1, 0), _tol)
+            && equal<T>(this->data[1][1], _m(1, 1), _tol)
+            && equal<T>(this->data[1][2], _m(1, 2), _tol)
+            && equal<T>(this->data[2][0], _m(2, 0), _tol)
+            && equal<T>(this->data[2][1], _m(2, 1), _tol)
+            && equal<T>(this->data[2][2], _m(2, 2), _tol);
+      }
+
+      /// \brief Equality test operator
+      /// \param[in] _m Matrix3<T> to test
+      /// \return True if equal (using the default tolerance of 1e-6)
+      public: bool operator==(const Matrix3<T> &_m) const
+      {
+        return this->Equal(_m, static_cast<T>(1e-6));
+      }
+
+      /// \brief Set the matrix3 from a quaternion
+      /// \param[in] _q Quaternion to set the matrix3 from.
+      /// \return Reference to the new matrix3 object.
+      public: Matrix3<T> &operator=(const Quaternion<T> &_q)
+      {
+        return *this = Matrix3<T>(_q);
+      }
+
+      /// \brief Inequality test operator
+      /// \param[in] _m Matrix3<T> to test
+      /// \return True if not equal (using the default tolerance of 1e-6)
+      public: bool operator!=(const Matrix3<T> &_m) const
+      {
+        return !(*this == _m);
+      }
+
+      /// \brief Array subscript operator
+      /// \param[in] _row row index. _row is clamped to the range [0,2]
+      /// \param[in] _col column index. _col is clamped to the range [0,2]
+      /// \return a pointer to the row
+      public: inline const T &operator()(size_t _row, size_t _col) const
+      {
+        return this->data[clamp(_row, IGN_ZERO_SIZE_T, IGN_TWO_SIZE_T)]
+                         [clamp(_col, IGN_ZERO_SIZE_T, IGN_TWO_SIZE_T)];
+      }
+
+      /// \brief Array subscript operator
+      /// \param[in] _row row index. _row is clamped to the range [0,2]
+      /// \param[in] _col column index. _col is clamped to the range [0,2]
+      /// \return a pointer to the row
+      public: inline T &operator()(size_t _row, size_t _col)
+      {
+        return this->data[clamp(_row, IGN_ZERO_SIZE_T, IGN_TWO_SIZE_T)]
+                         [clamp(_col, IGN_ZERO_SIZE_T, IGN_TWO_SIZE_T)];
+      }
+
+      /// \brief Return the determinant of the matrix
+      /// \return Determinant of this matrix.
+      public: T Determinant() const
+      {
+        T t0 = this->data[2][2]*this->data[1][1]
+             - this->data[2][1]*this->data[1][2];
+
+        T t1 = -(this->data[2][2]*this->data[1][0]
+                -this->data[2][0]*this->data[1][2]);
+
+        T t2 = this->data[2][1]*this->data[1][0]
+             - this->data[2][0]*this->data[1][1];
+
+        return t0 * this->data[0][0]
+             + t1 * this->data[0][1]
+             + t2 * this->data[0][2];
+      }
+
+      /// \brief Return the inverse matrix
+      /// \return Inverse of this matrix.
+      public: Matrix3<T> Inverse() const
+      {
+        T t0 = this->data[2][2]*this->data[1][1] -
+                    this->data[2][1]*this->data[1][2];
+
+        T t1 = -(this->data[2][2]*this->data[1][0] -
+                      this->data[2][0]*this->data[1][2]);
+
+        T t2 = this->data[2][1]*this->data[1][0] -
+                    this->data[2][0]*this->data[1][1];
+
+        T invDet = 1.0 / (t0 * this->data[0][0] +
+                               t1 * this->data[0][1] +
+                               t2 * this->data[0][2]);
+
+        return invDet * Matrix3<T>(
+          t0,
+          - (this->data[2][2] * this->data[0][1] -
+             this->data[2][1] * this->data[0][2]),
+          + (this->data[1][2] * this->data[0][1] -
+             this->data[1][1] * this->data[0][2]),
+          t1,
+          + (this->data[2][2] * this->data[0][0] -
+             this->data[2][0] * this->data[0][2]),
+          - (this->data[1][2] * this->data[0][0] -
+             this->data[1][0] * this->data[0][2]),
+          t2,
+          - (this->data[2][1] * this->data[0][0] -
+             this->data[2][0] * this->data[0][1]),
+          + (this->data[1][1] * this->data[0][0] -
+             this->data[1][0] * this->data[0][1]));
+      }
+
+      /// \brief Transpose this matrix.
+      public: void Transpose()
+      {
+        std::swap(this->data[0][1], this->data[1][0]);
+        std::swap(this->data[0][2], this->data[2][0]);
+        std::swap(this->data[1][2], this->data[2][1]);
+      }
+
+      /// \brief Return the transpose of this matrix
+      /// \return Transpose of this matrix.
+      public: Matrix3<T> Transposed() const
+      {
+        return Matrix3<T>(
+          this->data[0][0], this->data[1][0], this->data[2][0],
+          this->data[0][1], this->data[1][1], this->data[2][1],
+          this->data[0][2], this->data[1][2], this->data[2][2]);
+      }
+
+      /// \brief Stream insertion operator
+      /// \param[in] _out Output stream
+      /// \param[in] _m Matrix to output
+      /// \return the stream
+      public: friend std::ostream &operator<<(
+                  std::ostream &_out, const ignition::math::Matrix3<T> &_m)
+      {
+        _out << precision(_m(0, 0), 6) << " "
+             << precision(_m(0, 1), 6) << " "
+             << precision(_m(0, 2), 6) << " "
+             << precision(_m(1, 0), 6) << " "
+             << precision(_m(1, 1), 6) << " "
+             << precision(_m(1, 2), 6) << " "
+             << precision(_m(2, 0), 6) << " "
+             << precision(_m(2, 1), 6) << " "
+             << precision(_m(2, 2), 6);
+
+        return _out;
+      }
+      /// \brief Stream extraction operator
+      /// \param _in input stream
+      /// \param _pt Matrix3 to read values into
+      /// \return the stream
+      public: friend std::istream &operator>>(
+                  std::istream &_in, ignition::math::Matrix3<T> &_m)
+      {
+        // Skip white spaces
+        _in.setf(std::ios_base::skipws);
+        T d[9];
+        _in >> d[0] >> d[1] >> d[2]
+            >> d[3] >> d[4] >> d[5]
+            >> d[6] >> d[7] >> d[8];
+
+        _m.Set(d[0], d[1], d[2],
+               d[3], d[4], d[5],
+               d[6], d[7], d[8]);
+        return _in;
+      }
+
+      /// \brief the 3x3 matrix
+      private: T data[3][3];
+    };
+
+    template<typename T>
+    const Matrix3<T> Matrix3<T>::Identity(
+        1, 0, 0,
+        0, 1, 0,
+        0, 0, 1);
+
+    template<typename T>
+    const Matrix3<T> Matrix3<T>::Zero(
+        0, 0, 0,
+        0, 0, 0,
+        0, 0, 0);
+
+    typedef Matrix3<int> Matrix3i;
+    typedef Matrix3<double> Matrix3d;
+    typedef Matrix3<float> Matrix3f;
+  }
+}
+
+#endif
diff --git a/include/ignition/math/Matrix4.hh b/include/ignition/math/Matrix4.hh
new file mode 100644
index 0000000..2784954
--- /dev/null
+++ b/include/ignition/math/Matrix4.hh
@@ -0,0 +1,890 @@
+/*
+ * Copyright (C) 2012 Open Source Robotics Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+*/
+#ifndef IGNITION_MATH_MATRIX4_HH_
+#define IGNITION_MATH_MATRIX4_HH_
+
+#include <algorithm>
+#include <ignition/math/Helpers.hh>
+#include <ignition/math/Matrix3.hh>
+#include <ignition/math/Vector3.hh>
+#include <ignition/math/Pose3.hh>
+
+namespace ignition
+{
+  namespace math
+  {
+    /// \class Matrix4 Matrix4.hh ignition/math/Matrix4.hh
+    /// \brief A 4x4 matrix class
+    template<typename T>
+    class Matrix4
+    {
+      /// \brief Identity matrix
+      public: static const Matrix4<T> Identity;
+
+      /// \brief Zero matrix
+      public: static const Matrix4<T> Zero;
+
+      /// \brief Constructor
+      public: Matrix4()
+      {
+        memset(this->data, 0, sizeof(this->data[0][0])*16);
+      }
+
+      /// \brief Copy constructor
+      /// \param _m Matrix to copy
+      public: Matrix4(const Matrix4<T> &_m)
+      {
+        memcpy(this->data, _m.data, sizeof(this->data[0][0])*16);
+      }
+
+      /// \brief Constructor
+      /// \param[in] _v00 Row 0, Col 0 value
+      /// \param[in] _v01 Row 0, Col 1 value
+      /// \param[in] _v02 Row 0, Col 2 value
+      /// \param[in] _v03 Row 0, Col 3 value
+      /// \param[in] _v10 Row 1, Col 0 value
+      /// \param[in] _v11 Row 1, Col 1 value
+      /// \param[in] _v12 Row 1, Col 2 value
+      /// \param[in] _v13 Row 1, Col 3 value
+      /// \param[in] _v20 Row 2, Col 0 value
+      /// \param[in] _v21 Row 2, Col 1 value
+      /// \param[in] _v22 Row 2, Col 2 value
+      /// \param[in] _v23 Row 2, Col 3 value
+      /// \param[in] _v30 Row 3, Col 0 value
+      /// \param[in] _v31 Row 3, Col 1 value
+      /// \param[in] _v32 Row 3, Col 2 value
+      /// \param[in] _v33 Row 3, Col 3 value
+      public: Matrix4(T _v00, T _v01, T _v02, T _v03,
+                      T _v10, T _v11, T _v12, T _v13,
+                      T _v20, T _v21, T _v22, T _v23,
+                      T _v30, T _v31, T _v32, T _v33)
+      {
+        this->Set(_v00, _v01, _v02, _v03,
+                  _v10, _v11, _v12, _v13,
+                  _v20, _v21, _v22, _v23,
+                  _v30, _v31, _v32, _v33);
+      }
+
+      /// \brief Construct Matrix4 from a quaternion.
+      /// \param[in] _q Quaternion.
+      public: explicit Matrix4(const Quaternion<T> &_q)
+      {
+        Quaternion<T> qt = _q;
+        qt.Normalize();
+        this->Set(1 - 2*qt.Y()*qt.Y() - 2 *qt.Z()*qt.Z(),
+                  2 * qt.X()*qt.Y() - 2*qt.Z()*qt.W(),
+                  2 * qt.X() * qt.Z() + 2 * qt.Y() * qt.W(),
+                  0,
+
+                  2 * qt.X() * qt.Y() + 2 * qt.Z() * qt.W(),
+                  1 - 2*qt.X()*qt.X() - 2 * qt.Z()*qt.Z(),
+                  2 * qt.Y() * qt.Z() - 2 * qt.X() * qt.W(),
+                  0,
+
+                  2 * qt.X() * qt.Z() - 2 * qt.Y() * qt.W(),
+                  2 * qt.Y() * qt.Z() + 2 * qt.X() * qt.W(),
+                  1 - 2 * qt.X()*qt.X() - 2 * qt.Y()*qt.Y(),
+                  0,
+
+                  0, 0, 0, 1);
+      }
+
+      /// \brief Construct Matrix4 from a math::Pose3
+      /// \param[in] _pose Pose.
+      public: explicit Matrix4(const Pose3<T> &_pose) : Matrix4(_pose.Rot())
+      {
+        this->Translate(_pose.Pos());
+      }
+
+      /// \brief Destructor
+      public: virtual ~Matrix4() {}
+
+      /// \brief Change the values
+      /// \param[in] _v00 Row 0, Col 0 value
+      /// \param[in] _v01 Row 0, Col 1 value
+      /// \param[in] _v02 Row 0, Col 2 value
+      /// \param[in] _v03 Row 0, Col 3 value
+      /// \param[in] _v10 Row 1, Col 0 value
+      /// \param[in] _v11 Row 1, Col 1 value
+      /// \param[in] _v12 Row 1, Col 2 value
+      /// \param[in] _v13 Row 1, Col 3 value
+      /// \param[in] _v20 Row 2, Col 0 value
+      /// \param[in] _v21 Row 2, Col 1 value
+      /// \param[in] _v22 Row 2, Col 2 value
+      /// \param[in] _v23 Row 2, Col 3 value
+      /// \param[in] _v30 Row 3, Col 0 value
+      /// \param[in] _v31 Row 3, Col 1 value
+      /// \param[in] _v32 Row 3, Col 2 value
+      /// \param[in] _v33 Row 3, Col 3 value
+      public: void Set(
+            T _v00, T _v01, T _v02, T _v03,
+            T _v10, T _v11, T _v12, T _v13,
+            T _v20, T _v21, T _v22, T _v23,
+            T _v30, T _v31, T _v32, T _v33)
+      {
+        this->data[0][0] = _v00;
+        this->data[0][1] = _v01;
+        this->data[0][2] = _v02;
+        this->data[0][3] = _v03;
+
+        this->data[1][0] = _v10;
+        this->data[1][1] = _v11;
+        this->data[1][2] = _v12;
+        this->data[1][3] = _v13;
+
+        this->data[2][0] = _v20;
+        this->data[2][1] = _v21;
+        this->data[2][2] = _v22;
+        this->data[2][3] = _v23;
+
+        this->data[3][0] = _v30;
+        this->data[3][1] = _v31;
+        this->data[3][2] = _v32;
+        this->data[3][3] = _v33;
+      }
+
+      /// \brief Set the upper-left 3x3 matrix from an axis and angle
+      /// \param[in] _axis the axis
+      /// \param[in] _angle ccw rotation around the axis in radians
+      public: void Axis(const Vector3<T> &_axis, T _angle)
+      {
+        T c = cos(_angle);
+        T s = sin(_angle);
+        T C = 1-c;
+
+        this->data[0][0] = _axis.X()*_axis.X()*C + c;
+        this->data[0][1] = _axis.X()*_axis.Y()*C - _axis.Z()*s;
+        this->data[0][2] = _axis.X()*_axis.Z()*C + _axis.Y()*s;
+
+        this->data[1][0] = _axis.Y()*_axis.X()*C + _axis.Z()*s;
+        this->data[1][1] = _axis.Y()*_axis.Y()*C + c;
+        this->data[1][2] = _axis.Y()*_axis.Z()*C - _axis.X()*s;
+
+        this->data[2][0] = _axis.Z()*_axis.X()*C - _axis.Y()*s;
+        this->data[2][1] = _axis.Z()*_axis.Y()*C + _axis.X()*s;
+        this->data[2][2] = _axis.Z()*_axis.Z()*C + c;
+      }
+
+      /// \brief Set the translational values [ (0, 3) (1, 3) (2, 3) ]
+      /// \param[in] _t Values to set
+      public: void Translate(const Vector3<T> &_t)
+      {
+        this->data[0][3] = _t.X();
+        this->data[1][3] = _t.Y();
+        this->data[2][3] = _t.Z();
+      }
+
+      /// \brief Set the translational values [ (0, 3) (1, 3) (2, 3) ]
+      /// \param[in] _x X translation value.
+      /// \param[in] _y Y translation value.
+      /// \param[in] _z Z translation value.
+      public: void Translate(T _x, T _y, T _z)
+      {
+        this->data[0][3] = _x;
+        this->data[1][3] = _y;
+        this->data[2][3] = _z;
+      }
+
+      /// \brief Get the translational values as a Vector3
+      /// \return x,y,z translation values
+      public: Vector3<T> Translation() const
+      {
+        return Vector3<T>(this->data[0][3], this->data[1][3], this->data[2][3]);
+      }
+
+      /// \brief Get the scale values as a Vector3<T>
+      /// \return x,y,z scale values
+      public: Vector3<T> Scale() const
+      {
+        return Vector3<T>(this->data[0][0], this->data[1][1], this->data[2][2]);
+      }
+
+      /// \brief Get the rotation as a quaternion
+      /// \return the rotation
+      public: Quaternion<T> Rotation() const
+      {
+        Quaternion<T> q;
+        /// algorithm from Ogre::Quaternion<T> source, which in turn is based on
+        /// Ken Shoemake's article "Quaternion<T> Calculus and Fast Animation".
+        T trace = this->data[0][0] + this->data[1][1] + this->data[2][2];
+        T root;
+        if (trace > 0)
+        {
+          root = sqrt(trace + 1.0);
+          q.W(root / 2.0);
+          root = 1.0 / (2.0 * root);
+          q.X((this->data[2][1] - this->data[1][2]) * root);
+          q.Y((this->data[0][2] - this->data[2][0]) * root);
+          q.Z((this->data[1][0] - this->data[0][1]) * root);
+        }
+        else
+        {
+          static unsigned int s_iNext[3] = {1, 2, 0};
+          unsigned int i = 0;
+          if (this->data[1][1] > this->data[0][0])
+            i = 1;
+          if (this->data[2][2] > this->data[i][i])
+            i = 2;
+          unsigned int j = s_iNext[i];
+          unsigned int k = s_iNext[j];
+
+          root = sqrt(this->data[i][i] - this->data[j][j] -
+                      this->data[k][k] + 1.0);
+
+          T a, b, c;
+          a = root / 2.0;
+          root = 1.0 / (2.0 * root);
+          b = (this->data[j][i] + this->data[i][j]) * root;
+          c = (this->data[k][i] + this->data[i][k]) * root;
+
+          switch (i)
+          {
+            default:
+            case 0: q.X(a); break;
+            case 1: q.Y(a); break;
+            case 2: q.Z(a); break;
+          };
+          switch (j)
+          {
+            default:
+            case 0: q.X(b); break;
+            case 1: q.Y(b); break;
+            case 2: q.Z(b); break;
+          };
+          switch (k)
+          {
+            default:
+            case 0: q.X(c); break;
+            case 1: q.Y(c); break;
+            case 2: q.Z(c); break;
+          };
+
+          q.W((this->data[k][j] - this->data[j][k]) * root);
+        }
+
+        return q;
+      }
+
+      /// \brief Get the rotation as a Euler angles
+      /// \param[in] _firstSolution True to get the first Euler solution,
+      /// false to get the second.
+      /// \return the rotation
+      public: Vector3<T> EulerRotation(bool _firstSolution) const
+      {
+        Vector3<T> euler;
+        Vector3<T> euler2;
+
+        T m31 = this->data[2][0];
+        T m11 = this->data[0][0];
+        T m12 = this->data[0][1];
+        T m13 = this->data[0][2];
+        T m32 = this->data[2][1];
+        T m33 = this->data[2][2];
+        T m21 = this->data[1][0];
+
+        if (std::abs(m31) >= 1.0)
+        {
+          euler.Z(0.0);
+          euler2.Z(0.0);
+
+          if (m31 < 0.0)
+          {
+            euler.Y(IGN_PI / 2.0);
+            euler2.Y(IGN_PI / 2.0);
+            euler.X(atan2(m12, m13));
+            euler2.X(atan2(m12, m13));
+          }
+          else
+          {
+            euler.Y(-IGN_PI / 2.0);
+            euler2.Y(-IGN_PI / 2.0);
+            euler.X(atan2(-m12, -m13));
+            euler2.X(atan2(-m12, -m13));
+          }
+        }
+        else
+        {
+          euler.Y(-asin(m31));
+          euler2.Y(IGN_PI - euler.Y());
+
+          euler.X(atan2(m32 / cos(euler.Y()), m33 / cos(euler.Y())));
+          euler2.X(atan2(m32 / cos(euler2.Y()), m33 / cos(euler2.Y())));
+
+          euler.Z(atan2(m21 / cos(euler.Y()), m11 / cos(euler.Y())));
+          euler2.Z(atan2(m21 / cos(euler2.Y()), m11 / cos(euler2.Y())));
+        }
+
+        if (_firstSolution)
+          return euler;
+        else
+          return euler2;
+      }
+
+      /// \brief Get the transformation as math::Pose
+      /// \return the pose
+      public: Pose3<T> Pose() const
+      {
+        return Pose3<T>(this->Translation(), this->Rotation());
+      }
+
+      /// \brief Set the scale
+      /// \param[in] _s scale
+      public: void Scale(const Vector3<T> &_s)
+      {
+        this->data[0][0] = _s.X();
+        this->data[1][1] = _s.Y();
+        this->data[2][2] = _s.Z();
+        this->data[3][3] = 1.0;
+      }
+
+      /// \brief Set the scale
+      /// \param[in] _x X scale value.
+      /// \param[in] _y Y scale value.
+      /// \param[in] _z Z scale value.
+      public: void Scale(T _x, T _y, T _z)
+      {
+        this->data[0][0] = _x;
+        this->data[1][1] = _y;
+        this->data[2][2] = _z;
+        this->data[3][3] = 1.0;
+      }
+
+      /// \brief Return true if the matrix is affine
+      /// \return true if the matrix is affine, false otherwise
+      public: bool IsAffine() const
+      {
+        return equal(this->data[3][0], static_cast<T>(0)) &&
+          equal(this->data[3][1], static_cast<T>(0)) &&
+          equal(this->data[3][2], static_cast<T>(0)) &&
+          equal(this->data[3][3], static_cast<T>(1));
+      }
+
+      /// \brief Perform an affine transformation
+      /// \param[in] _v Vector3 value for the transformation
+      /// \return The result of the transformation. A default constructed
+      /// Vector3<T> is returned if this matrix is not affine.
+      /// \deprecated Use bool TransformAffine(const Vector3<T> &_v,
+      /// Vector3<T> &_result) const;
+      public: Vector3<T> TransformAffine(const Vector3<T> &_v) const
+#ifndef _WIN32
+      IGN_DEPRECATED(3.0)
+#endif
+      {
+        if (this->IsAffine())
+        {
+          return Vector3<T>(this->data[0][0]*_v.X() + this->data[0][1]*_v.Y() +
+                            this->data[0][2]*_v.Z() + this->data[0][3],
+                            this->data[1][0]*_v.X() + this->data[1][1]*_v.Y() +
+                            this->data[1][2]*_v.Z() + this->data[1][3],
+                            this->data[2][0]*_v.X() + this->data[2][1]*_v.Y() +
+                            this->data[2][2]*_v.Z() + this->data[2][3]);
+        }
+        else
+        {
+          return Vector3<T>();
+        }
+      }
+
+      /// \brief Perform an affine transformation
+      /// \param[in] _v Vector3 value for the transformation
+      /// \param[out] _result  The result of the transformation. _result is
+      /// not changed if this matrix is not affine.
+      /// \return True if this matrix is affine, false otherwise.
+      public: bool TransformAffine(const Vector3<T> &_v,
+                                   Vector3<T> &_result) const
+      {
+        if (!this->IsAffine())
+          return false;
+
+        _result.Set(this->data[0][0]*_v.X() + this->data[0][1]*_v.Y() +
+                    this->data[0][2]*_v.Z() + this->data[0][3],
+                    this->data[1][0]*_v.X() + this->data[1][1]*_v.Y() +
+                    this->data[1][2]*_v.Z() + this->data[1][3],
+                    this->data[2][0]*_v.X() + this->data[2][1]*_v.Y() +
+                    this->data[2][2]*_v.Z() + this->data[2][3]);
+        return true;
+      }
+
+      /// \brief Return the determinant of the matrix
+      /// \return Determinant of this matrix.
+      public: T Determinant() const
+      {
+        T v0, v1, v2, v3, v4, v5, t00, t10, t20, t30;
+
+        v0 = this->data[2][0]*this->data[3][1]
+           - this->data[2][1]*this->data[3][0];
+        v1 = this->data[2][0]*this->data[3][2]
+           - this->data[2][2]*this->data[3][0];
+        v2 = this->data[2][0]*this->data[3][3]
+           - this->data[2][3]*this->data[3][0];
+        v3 = this->data[2][1]*this->data[3][2]
+           - this->data[2][2]*this->data[3][1];
+        v4 = this->data[2][1]*this->data[3][3]
+           - this->data[2][3]*this->data[3][1];
+        v5 = this->data[2][2]*this->data[3][3]
+           - this->data[2][3]*this->data[3][2];
+
+        t00 =  v5*this->data[1][1] - v4*this->data[1][2] + v3*this->data[1][3];
+        t10 = -v5*this->data[1][0] + v2*this->data[1][2] - v1*this->data[1][3];
+        t20 =  v4*this->data[1][0] - v2*this->data[1][1] + v0*this->data[1][3];
+        t30 = -v3*this->data[1][0] + v1*this->data[1][1] - v0*this->data[1][2];
+
+        return t00 * this->data[0][0]
+             + t10 * this->data[0][1]
+             + t20 * this->data[0][2]
+             + t30 * this->data[0][3];
+      }
+
+      /// \brief Return the inverse matrix.
+      /// This is a non-destructive operation.
+      /// \return Inverse of this matrix.
+      public: Matrix4<T> Inverse() const
+      {
+        T v0, v1, v2, v3, v4, v5, t00, t10, t20, t30;
+        Matrix4<T> r;
+
+        v0 = this->data[2][0]*this->data[3][1] -
+          this->data[2][1]*this->data[3][0];
+        v1 = this->data[2][0]*this->data[3][2] -
+          this->data[2][2]*this->data[3][0];
+        v2 = this->data[2][0]*this->data[3][3] -
+          this->data[2][3]*this->data[3][0];
+        v3 = this->data[2][1]*this->data[3][2] -
+          this->data[2][2]*this->data[3][1];
+        v4 = this->data[2][1]*this->data[3][3] -
+          this->data[2][3]*this->data[3][1];
+        v5 = this->data[2][2]*this->data[3][3] -
+          this->data[2][3]*this->data[3][2];
+
+        t00 = +(v5*this->data[1][1] -
+            v4*this->data[1][2] + v3*this->data[1][3]);
+        t10 = -(v5*this->data[1][0] -
+            v2*this->data[1][2] + v1*this->data[1][3]);
+        t20 = +(v4*this->data[1][0] -
+            v2*this->data[1][1] + v0*this->data[1][3]);
+        t30 = -(v3*this->data[1][0] -
+            v1*this->data[1][1] + v0*this->data[1][2]);
+
+        T invDet = 1 / (t00 * this->data[0][0] + t10 * this->data[0][1] +
+            t20 * this->data[0][2] + t30 * this->data[0][3]);
+
+        r(0, 0) = t00 * invDet;
+        r(1, 0) = t10 * invDet;
+        r(2, 0) = t20 * invDet;
+        r(3, 0) = t30 * invDet;
+
+        r(0, 1) = -(v5*this->data[0][1] -
+            v4*this->data[0][2] + v3*this->data[0][3]) * invDet;
+        r(1, 1) = +(v5*this->data[0][0] -
+            v2*this->data[0][2] + v1*this->data[0][3]) * invDet;
+        r(2, 1) = -(v4*this->data[0][0] -
+            v2*this->data[0][1] + v0*this->data[0][3]) * invDet;
+        r(3, 1) = +(v3*this->data[0][0] -
+            v1*this->data[0][1] + v0*this->data[0][2]) * invDet;
+
+        v0 = this->data[1][0]*this->data[3][1] -
+          this->data[1][1]*this->data[3][0];
+        v1 = this->data[1][0]*this->data[3][2] -
+          this->data[1][2]*this->data[3][0];
+        v2 = this->data[1][0]*this->data[3][3] -
+          this->data[1][3]*this->data[3][0];
+        v3 = this->data[1][1]*this->data[3][2] -
+          this->data[1][2]*this->data[3][1];
+        v4 = this->data[1][1]*this->data[3][3] -
+          this->data[1][3]*this->data[3][1];
+        v5 = this->data[1][2]*this->data[3][3] -
+          this->data[1][3]*this->data[3][2];
+
+        r(0, 2) = +(v5*this->data[0][1] -
+            v4*this->data[0][2] + v3*this->data[0][3]) * invDet;
+        r(1, 2) = -(v5*this->data[0][0] -
+            v2*this->data[0][2] + v1*this->data[0][3]) * invDet;
+        r(2, 2) = +(v4*this->data[0][0] -
+            v2*this->data[0][1] + v0*this->data[0][3]) * invDet;
+        r(3, 2) = -(v3*this->data[0][0] -
+            v1*this->data[0][1] + v0*this->data[0][2]) * invDet;
+
+        v0 = this->data[2][1]*this->data[1][0] -
+          this->data[2][0]*this->data[1][1];
+        v1 = this->data[2][2]*this->data[1][0] -
+          this->data[2][0]*this->data[1][2];
+        v2 = this->data[2][3]*this->data[1][0] -
+          this->data[2][0]*this->data[1][3];
+        v3 = this->data[2][2]*this->data[1][1] -
+          this->data[2][1]*this->data[1][2];
+        v4 = this->data[2][3]*this->data[1][1] -
+          this->data[2][1]*this->data[1][3];
+        v5 = this->data[2][3]*this->data[1][2] -
+          this->data[2][2]*this->data[1][3];
+
+        r(0, 3) = -(v5*this->data[0][1] -
+            v4*this->data[0][2] + v3*this->data[0][3]) * invDet;
+        r(1, 3) = +(v5*this->data[0][0] -
+            v2*this->data[0][2] + v1*this->data[0][3]) * invDet;
+        r(2, 3) = -(v4*this->data[0][0] -
+            v2*this->data[0][1] + v0*this->data[0][3]) * invDet;
+        r(3, 3) = +(v3*this->data[0][0] -
+            v1*this->data[0][1] + v0*this->data[0][2]) * invDet;
+
+        return r;
+      }
+
+      /// \brief Transpose this matrix.
+      public: void Transpose()
+      {
+        std::swap(this->data[0][1], this->data[1][0]);
+        std::swap(this->data[0][2], this->data[2][0]);
+        std::swap(this->data[0][3], this->data[3][0]);
+        std::swap(this->data[1][2], this->data[2][1]);
+        std::swap(this->data[1][3], this->data[3][1]);
+        std::swap(this->data[2][3], this->data[3][2]);
+      }
+
+      /// \brief Return the transpose of this matrix
+      /// \return Transpose of this matrix.
+      public: Matrix4<T> Transposed() const
+      {
+        return Matrix4<T>(
+        this->data[0][0], this->data[1][0], this->data[2][0], this->data[3][0],
+        this->data[0][1], this->data[1][1], this->data[2][1], this->data[3][1],
+        this->data[0][2], this->data[1][2], this->data[2][2], this->data[3][2],
+        this->data[0][3], this->data[1][3], this->data[2][3], this->data[3][3]);
+      }
+
+      /// \brief Equal operator. this = _mat
+      /// \param _mat Incoming matrix
+      /// \return itself
+      public: Matrix4<T> &operator=(const Matrix4<T> &_mat)
+      {
+        memcpy(this->data, _mat.data, sizeof(this->data[0][0])*16);
+        return *this;
+      }
+
+      /// \brief Equal operator for 3x3 matrix
+      /// \param _mat Incoming matrix
+      /// \return itself
+      public: const Matrix4<T> &operator=(const Matrix3<T> &_mat)
+      {
+        this->data[0][0] = _mat(0, 0);
+        this->data[0][1] = _mat(0, 1);
+        this->data[0][2] = _mat(0, 2);
+
+        this->data[1][0] = _mat(1, 0);
+        this->data[1][1] = _mat(1, 1);
+        this->data[1][2] = _mat(1, 2);
+
+        this->data[2][0] = _mat(2, 0);
+        this->data[2][1] = _mat(2, 1);
+        this->data[2][2] = _mat(2, 2);
+
+        return *this;
+      }
+
+      /// \brief Multiplication operator
+      /// \param _mat Incoming matrix
+      /// \return This matrix * _mat
+      public: Matrix4<T> operator*(const Matrix4<T> &_m2) const
+      {
+        return Matrix4<T>(
+          this->data[0][0] * _m2(0, 0) +
+          this->data[0][1] * _m2(1, 0) +
+          this->data[0][2] * _m2(2, 0) +
+          this->data[0][3] * _m2(3, 0),
+
+          this->data[0][0] * _m2(0, 1) +
+          this->data[0][1] * _m2(1, 1) +
+          this->data[0][2] * _m2(2, 1) +
+          this->data[0][3] * _m2(3, 1),
+
+          this->data[0][0] * _m2(0, 2) +
+          this->data[0][1] * _m2(1, 2) +
+          this->data[0][2] * _m2(2, 2) +
+          this->data[0][3] * _m2(3, 2),
+
+          this->data[0][0] * _m2(0, 3) +
+          this->data[0][1] * _m2(1, 3) +
+          this->data[0][2] * _m2(2, 3) +
+          this->data[0][3] * _m2(3, 3),
+
+          this->data[1][0] * _m2(0, 0) +
+          this->data[1][1] * _m2(1, 0) +
+          this->data[1][2] * _m2(2, 0) +
+          this->data[1][3] * _m2(3, 0),
+
+          this->data[1][0] * _m2(0, 1) +
+          this->data[1][1] * _m2(1, 1) +
+          this->data[1][2] * _m2(2, 1) +
+          this->data[1][3] * _m2(3, 1),
+
+          this->data[1][0] * _m2(0, 2) +
+          this->data[1][1] * _m2(1, 2) +
+          this->data[1][2] * _m2(2, 2) +
+          this->data[1][3] * _m2(3, 2),
+
+          this->data[1][0] * _m2(0, 3) +
+          this->data[1][1] * _m2(1, 3) +
+          this->data[1][2] * _m2(2, 3) +
+          this->data[1][3] * _m2(3, 3),
+
+          this->data[2][0] * _m2(0, 0) +
+          this->data[2][1] * _m2(1, 0) +
+          this->data[2][2] * _m2(2, 0) +
+          this->data[2][3] * _m2(3, 0),
+
+          this->data[2][0] * _m2(0, 1) +
+          this->data[2][1] * _m2(1, 1) +
+          this->data[2][2] * _m2(2, 1) +
+          this->data[2][3] * _m2(3, 1),
+
+          this->data[2][0] * _m2(0, 2) +
+          this->data[2][1] * _m2(1, 2) +
+          this->data[2][2] * _m2(2, 2) +
+          this->data[2][3] * _m2(3, 2),
+
+          this->data[2][0] * _m2(0, 3) +
+          this->data[2][1] * _m2(1, 3) +
+          this->data[2][2] * _m2(2, 3) +
+          this->data[2][3] * _m2(3, 3),
+
+          this->data[3][0] * _m2(0, 0) +
+          this->data[3][1] * _m2(1, 0) +
+          this->data[3][2] * _m2(2, 0) +
+          this->data[3][3] * _m2(3, 0),
+
+          this->data[3][0] * _m2(0, 1) +
+          this->data[3][1] * _m2(1, 1) +
+          this->data[3][2] * _m2(2, 1) +
+          this->data[3][3] * _m2(3, 1),
+
+          this->data[3][0] * _m2(0, 2) +
+          this->data[3][1] * _m2(1, 2) +
+          this->data[3][2] * _m2(2, 2) +
+          this->data[3][3] * _m2(3, 2),
+
+          this->data[3][0] * _m2(0, 3) +
+          this->data[3][1] * _m2(1, 3) +
+          this->data[3][2] * _m2(2, 3) +
+          this->data[3][3] * _m2(3, 3));
+      }
+
+      /// \brief Multiplication operator
+      /// \param _vec Vector3
+      /// \return Resulting vector from multiplication
+      public: Vector3<T> operator*(const Vector3<T> &_vec) const
+      {
+        return Vector3<T>(
+            this->data[0][0]*_vec.X() + this->data[0][1]*_vec.Y() +
+            this->data[0][2]*_vec.Z() + this->data[0][3],
+            this->data[1][0]*_vec.X() + this->data[1][1]*_vec.Y() +
+            this->data[1][2]*_vec.Z() + this->data[1][3],
+            this->data[2][0]*_vec.X() + this->data[2][1]*_vec.Y() +
+            this->data[2][2]*_vec.Z() + this->data[2][3]);
+      }
+
+      /// \brief Get the value at the specified row, column index
+      /// \param[in] _col The column index. Index values are clamped to a
+      /// range of [0, 3].
+      /// \param[in] _row the row index. Index values are clamped to a
+      /// range of [0, 3].
+      /// \return The value at the specified index
+      public: inline const T &operator()(const size_t _row,
+                  const size_t _col) const
+      {
+        return this->data[clamp(_row, IGN_ZERO_SIZE_T, IGN_THREE_SIZE_T)][
+                          clamp(_col, IGN_ZERO_SIZE_T, IGN_THREE_SIZE_T)];
+      }
+
+      /// \brief Get a mutable version the value at the specified row,
+      /// column index
+      /// \param[in] _col The column index. Index values are clamped to a
+      /// range of [0, 3].
+      /// \param[in] _row the row index. Index values are clamped to a
+      /// range of [0, 3].
+      /// \return The value at the specified index
+      public: inline T &operator()(const size_t _row, const size_t _col)
+      {
+        return this->data[clamp(_row, IGN_ZERO_SIZE_T, IGN_THREE_SIZE_T)]
+                         [clamp(_col, IGN_ZERO_SIZE_T, IGN_THREE_SIZE_T)];
+      }
+
+      /// \brief Equality test with tolerance.
+      /// \param[in] _m the matrix to compare to
+      /// \param[in] _tol equality tolerance.
+      /// \return true if the elements of the matrices are equal within
+      /// the tolerence specified by _tol.
+      public: bool Equal(const Matrix4 &_m, const T &_tol) const
+      {
+        return equal<T>(this->data[0][0], _m(0, 0), _tol)
+            && equal<T>(this->data[0][1], _m(0, 1), _tol)
+            && equal<T>(this->data[0][2], _m(0, 2), _tol)
+            && equal<T>(this->data[0][3], _m(0, 3), _tol)
+            && equal<T>(this->data[1][0], _m(1, 0), _tol)
+            && equal<T>(this->data[1][1], _m(1, 1), _tol)
+            && equal<T>(this->data[1][2], _m(1, 2), _tol)
+            && equal<T>(this->data[1][3], _m(1, 3), _tol)
+            && equal<T>(this->data[2][0], _m(2, 0), _tol)
+            && equal<T>(this->data[2][1], _m(2, 1), _tol)
+            && equal<T>(this->data[2][2], _m(2, 2), _tol)
+            && equal<T>(this->data[2][3], _m(2, 3), _tol)
+            && equal<T>(this->data[3][0], _m(3, 0), _tol)
+            && equal<T>(this->data[3][1], _m(3, 1), _tol)
+            && equal<T>(this->data[3][2], _m(3, 2), _tol)
+            && equal<T>(this->data[3][3], _m(3, 3), _tol);
+      }
+
+      /// \brief Equality operator
+      /// \param[in] _m Matrix3 to test
+      /// \return true if the 2 matrices are equal (using the tolerance 1e-6),
+      ///  false otherwise
+      public: bool operator==(const Matrix4<T> &_m) const
+      {
+        return this->Equal(_m, static_cast<T>(1e-6));
+      }
+
+      /// \brief Inequality test operator
+      /// \param[in] _m Matrix4<T> to test
+      /// \return True if not equal (using the default tolerance of 1e-6)
+      public: bool operator!=(const Matrix4<T> &_m) const
+      {
+        return !(*this == _m);
+      }
+
+      /// \brief Stream insertion operator
+      /// \param _out output stream
+      /// \param _m Matrix to output
+      /// \return the stream
+      public: friend std::ostream &operator<<(
+                  std::ostream &_out, const ignition::math::Matrix4<T> &_m)
+      {
+        _out << precision(_m(0, 0), 6) << " "
+             << precision(_m(0, 1), 6) << " "
+             << precision(_m(0, 2), 6) << " "
+             << precision(_m(0, 3), 6) << " "
+             << precision(_m(1, 0), 6) << " "
+             << precision(_m(1, 1), 6) << " "
+             << precision(_m(1, 2), 6) << " "
+             << precision(_m(1, 3), 6) << " "
+             << precision(_m(2, 0), 6) << " "
+             << precision(_m(2, 1), 6) << " "
+             << precision(_m(2, 2), 6) << " "
+             << precision(_m(2, 3), 6) << " "
+             << precision(_m(3, 0), 6) << " "
+             << precision(_m(3, 1), 6) << " "
+             << precision(_m(3, 2), 6) << " "
+             << precision(_m(3, 3), 6);
+
+        return _out;
+      }
+
+      /// \brief Stream extraction operator
+      /// \param _in input stream
+      /// \param _pt Matrix4<T> to read values into
+      /// \return the stream
+      public: friend std::istream &operator>>(
+                  std::istream &_in, ignition::math::Matrix4<T> &_m)
+      {
+        // Skip white spaces
+        _in.setf(std::ios_base::skipws);
+        T d[16];
+        _in >> d[0] >> d[1] >> d[2] >> d[3]
+            >> d[4] >> d[5] >> d[6] >> d[7]
+            >> d[8] >> d[9] >> d[10] >> d[11]
+            >> d[12] >> d[13] >> d[14] >> d[15];
+
+        _m.Set(d[0], d[1], d[2], d[3],
+               d[4], d[5], d[6], d[7],
+               d[8], d[9], d[10], d[11],
+               d[12], d[13], d[14], d[15]);
+        return _in;
+      }
+
+      /// \brief Get transform which translates to _eye and rotates the X axis
+      /// so it faces the _target. The rotation is such that Z axis is in the
+      /// _up direction, if possible. The coordinate system is right-handed,
+      /// \param[in] _eye Coordinate frame translation.
+      /// \param[in] _target Point which the X axis should face. If _target is
+      /// equal to _eye, the X axis won't be rotated.
+      /// \param[in] _up Direction in which the Z axis should point. If _up is
+      /// zero or parallel to X, it will be set to +Z.
+      /// \return Transformation matrix.
+      public: static Matrix4<T> LookAt(const Vector3<T> &_eye,
+          const Vector3<T> &_target, const Vector3<T> &_up = Vector3<T>::UnitZ)
+      {
+        // Most important constraint: direction to point X axis at
+        auto front = _target - _eye;
+
+        // Case when _eye == _target
+        if (front == Vector3<T>::Zero)
+          front = Vector3<T>::UnitX;
+        front.Normalize();
+
+        // Desired direction to point Z axis at
+        auto up = _up;
+
+        // Case when _up == Zero
+        if (up == Vector3<T>::Zero)
+          up = Vector3<T>::UnitZ;
+        else
+          up.Normalize();
+
+        // Case when _up is parallel to X
+        if (up.Cross(Vector3<T>::UnitX) == Vector3<T>::Zero)
+          up = Vector3<T>::UnitZ;
+
+        // Find direction to point Y axis at
+        auto left = up.Cross(front);
+
+        // Case when front is parallel to up
+        if (left == Vector3<T>::Zero)
+          left = Vector3<T>::UnitY;
+        else
+          left.Normalize();
+
+        // Fix up direction so it's perpendicular to XY
+        up = (front.Cross(left)).Normalize();
+
+        return Matrix4<T>(
+            front.X(), left.X(), up.X(), _eye.X(),
+            front.Y(), left.Y(), up.Y(), _eye.Y(),
+            front.Z(), left.Z(), up.Z(), _eye.Z(),
+                  0,      0,         0,        1);
+      }
+
+      /// \brief The 4x4 matrix
+      private: T data[4][4];
+    };
+
+    template<typename T>
+    const Matrix4<T> Matrix4<T>::Identity(
+        1, 0, 0, 0,
+        0, 1, 0, 0,
+        0, 0, 1, 0,
+        0, 0, 0, 1);
+
+    template<typename T>
+    const Matrix4<T> Matrix4<T>::Zero(
+        0, 0, 0, 0,
+        0, 0, 0, 0,
+        0, 0, 0, 0,
+        0, 0, 0, 0);
+
+    typedef Matrix4<int> Matrix4i;
+    typedef Matrix4<double> Matrix4d;
+    typedef Matrix4<float> Matrix4f;
+  }
+}
+#endif
diff --git a/include/ignition/math/OrientedBox.hh b/include/ignition/math/OrientedBox.hh
new file mode 100644
index 0000000..083eb41
--- /dev/null
+++ b/include/ignition/math/OrientedBox.hh
@@ -0,0 +1,187 @@
+/*
+ * Copyright (C) 2017 Open Source Robotics Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+*/
+#ifndef IGNITION_MATH_ORIENTEDBOX_HH_
+#define IGNITION_MATH_ORIENTEDBOX_HH_
+
+#include <iostream>
+#include <ignition/math/Helpers.hh>
+#include <ignition/math/Matrix4.hh>
+#include <ignition/math/Pose3.hh>
+#include <ignition/math/Vector3.hh>
+
+namespace ignition
+{
+  namespace math
+  {
+    /// \brief Mathematical representation of a box which can be arbitrarily
+    /// positioned and rotated.
+    template<typename T>
+    class OrientedBox
+    {
+      /// \brief Default constructor
+      public: OrientedBox() : size(Vector3<T>::Zero), pose(Pose3<T>::Zero)
+      {
+      }
+
+      /// \brief Constructor which takes size and pose.
+      /// \param[in] _size Box size, in its own coordinate frame. Its absolute
+      /// value will be taken, so the size is non-negative.
+      /// \param[in] _pose Box pose.
+      public: OrientedBox(const Vector3<T> &_size, const Pose3<T> &_pose)
+          : size(_size), pose(_pose)
+      {
+        // Enforce non-negative size
+        this->size = this->size.Abs();
+      }
+
+      /// \brief Constructor which takes only the size.
+      /// \param[in] _size Box size, in its own coordinate frame. Its absolute
+      /// value will be taken, so the size is non-negative.
+      public: explicit OrientedBox(const Vector3<T> &_size)
+          : size(_size), pose(Pose3<T>::Zero)
+      {
+        // Enforce non-negative size
+        this->size = this->size.Abs();
+      }
+
+      /// \brief Copy constructor.
+      /// \param[in] _b OrientedBox to copy.
+      public: OrientedBox(const OrientedBox<T> &_b)
+          : size(_b.size), pose(_b.pose)
+      {
+      }
+
+      /// \brief Destructor
+      public: virtual ~OrientedBox()
+      {
+      }
+
+      /// \brief Get the length along the x dimension
+      /// \return Value of the length in the x dimension
+      public: T XLength() const
+      {
+        return this->size.X();
+      }
+
+      /// \brief Get the length along the y dimension
+      /// \return Value of the length in the y dimension
+      public: T YLength() const
+      {
+        return this->size.Y();
+      }
+
+      /// \brief Get the length along the z dimension
+      /// \return Value of the length in the z dimension
+      public: T ZLength() const
+      {
+        return this->size.Z();
+      }
+
+      /// \brief Get the size of the box
+      /// \return Size of the box
+      public: const Vector3<T> &Size() const
+      {
+        return this->size;
+      }
+
+      /// \brief Get the box pose, which is the pose of its center.
+      /// \return The pose of the box.
+      public: const Pose3<T> &Pose() const
+      {
+        return this->pose;
+      }
+
+      /// \brief Set the box size.
+      /// \param[in] _size Box size, in its own coordinate frame. Its absolute
+      /// value will be taken, so the size is non-negative.
+      public: void Size(Vector3<T> &_size)
+      {
+        // Enforce non-negative size
+        this->size = _size.Abs();
+      }
+
+      /// \brief Set the box pose.
+      /// \param[in] _pose Box pose.
+      public: void Pose(Pose3<T> &_pose)
+      {
+        this->pose = _pose;
+      }
+
+      /// \brief Assignment operator. Set this box to the parameter
+      /// \param[in]  _b OrientedBox to copy
+      /// \return The new box.
+      public: OrientedBox &operator=(const OrientedBox<T> &_b)
+      {
+        this->size = _b.size;
+        this->pose = _b.pose;
+        return *this;
+      }
+
+      /// \brief Equality test operator
+      /// \param[in] _b OrientedBox to test
+      /// \return True if equal
+      public: bool operator==(const OrientedBox<T> &_b) const
+      {
+        return this->size == _b.size && this->pose == _b.pose;
+      }
+
+      /// \brief Inequality test operator
+      /// \param[in] _b OrientedBox to test
+      /// \return True if not equal
+      public: bool operator!=(const OrientedBox<T> &_b) const
+      {
+        return this->size != _b.size || this->pose != _b.pose;
+      }
+
+      /// \brief Output operator
+      /// \param[in] _out Output stream
+      /// \param[in] _b OrientedBox to output to the stream
+      /// \return The stream
+      public: friend std::ostream &operator<<(std::ostream &_out,
+                                              const OrientedBox<T> &_b)
+      {
+        _out << "Size[" << _b.Size() << "] Pose[" << _b.Pose() << "]";
+        return _out;
+      }
+
+      /// \brief Check if a point lies inside the box.
+      /// \param[in] _p Point to check.
+      /// \return True if the point is inside the box.
+      public: bool Contains(const Vector3d &_p) const
+      {
+        // Move point to box frame
+        auto t = Matrix4<T>(this->pose).Inverse();
+        auto p = t *_p;
+
+        return p.X() >= -this->size.X()*0.5 && p.X() <= this->size.X()*0.5 &&
+               p.Y() >= -this->size.Y()*0.5 && p.Y() <= this->size.Y()*0.5 &&
+               p.Z() >= -this->size.Z()*0.5 && p.Z() <= this->size.Z()*0.5;
+      }
+
+      /// \brief The size of the box in its local frame.
+      private: Vector3<T> size;
+
+      /// \brief The pose of the center of the box.
+      private: Pose3<T> pose;
+    };
+
+    typedef OrientedBox<int> OrientedBoxi;
+    typedef OrientedBox<double> OrientedBoxd;
+    typedef OrientedBox<float> OrientedBoxf;
+  }
+}
+#endif
diff --git a/include/ignition/math/PID.hh b/include/ignition/math/PID.hh
new file mode 100644
index 0000000..0587a62
--- /dev/null
+++ b/include/ignition/math/PID.hh
@@ -0,0 +1,228 @@
+/*
+ * Copyright (C) 2016 Open Source Robotics Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+*/
+#ifndef IGNITION_MATH_PID_HH_
+#define IGNITION_MATH_PID_HH_
+
+#include <chrono>
+#include <ignition/math/Helpers.hh>
+
+namespace ignition
+{
+  namespace math
+  {
+    /// \class PID PID.hh ignition/math/PID.hh
+    /// \brief Generic PID controller class.
+    /// Generic proportional-integral-derivative controller class that
+    /// keeps track of PID-error states and control inputs given
+    /// the state of a system and a user specified target state.
+    /// It includes a user-adjustable command offset term (feed-forward).
+    class IGNITION_MATH_VISIBLE PID
+    {
+      /// \brief Constructor, zeros out Pid values when created and
+      /// initialize Pid-gains and integral term limits:[iMax:iMin]-[I1:I2].
+      ///
+      /// Disable command clamping by setting _cmdMin to a value larger
+      /// than _cmdMax. Command clamping is disabled by default.
+      ///
+      /// Disable integral clamping by setting _iMin to a value larger
+      /// than _iMax. Integral clamping is disabled by default.
+      ///
+      /// \param[in] _p  The proportional gain.
+      /// \param[in] _i  The integral gain.
+      /// \param[in] _d  The derivative gain.
+      /// \param[in] _imax The integral upper limit.
+      /// \param[in] _imin The integral lower limit.
+      /// \param[in] _cmdMax Output max value.
+      /// \param[in] _cmdMin Output min value.
+      /// \param[in] _cmdOffset Command offset (feed-forward).
+      public: PID(const double _p = 0.0,
+                  const double _i = 0.0,
+                  const double _d = 0.0,
+                  const double _imax = -1.0,
+                  const double _imin = 0.0,
+                  const double _cmdMax = -1.0,
+                  const double _cmdMin = 0.0,
+                  const double _cmdOffset = 0.0);
+
+      /// \brief Destructor
+      public: ~PID() = default;
+
+      /// \brief Initialize PID-gains and integral term
+      ///        limits:[iMax:iMin]-[I1:I2].
+      ///
+      /// Disable command clamping by setting _cmdMin to a value larger
+      /// than _cmdMax. Command clamping is disabled by default.
+      ///
+      /// Disable integral clamping by setting _iMin to a value larger
+      /// than _iMax. Integral clamping is disabled by default.
+      ///
+      /// \param[in] _p  The proportional gain.
+      /// \param[in] _i  The integral gain.
+      /// \param[in] _d  The derivative gain.
+      /// \param[in] _imax The integral upper limit.
+      /// \param[in] _imin The integral lower limit.
+      /// \param[in] _cmdMax Output max value.
+      /// \param[in] _cmdMin Output min value.
+      /// \param[in] _cmdOffset Command offset (feed-forward).
+      public: void Init(const double _p = 0.0,
+                        const double _i = 0.0,
+                        const double _d = 0.0,
+                        const double _imax = -1.0,
+                        const double _imin = 0.0,
+                        const double _cmdMax = -1.0,
+                        const double _cmdMin = 0.0,
+                        const double _cmdOffset = 0.0);
+
+      /// \brief Set the proportional Gain.
+      /// \param[in] _p proportional gain value
+      public: void SetPGain(const double _p);
+
+      /// \brief Set the integral Gain.
+      /// \param[in] _i integral gain value
+      public: void SetIGain(const double _i);
+
+      /// \brief Set the derivtive Gain.
+      /// \param[in] _d derivative gain value
+      public: void SetDGain(const double _d);
+
+      /// \brief Set the integral upper limit.
+      /// \param[in] _i integral upper limit value
+      public: void SetIMax(const double _i);
+
+      /// \brief Set the integral lower limit.
+      /// \param[in] _i integral lower limit value
+      public: void SetIMin(const double _i);
+
+      /// \brief Set the maximum value for the command.
+      /// \param[in] _c The maximum value
+      public: void SetCmdMax(const double _c);
+
+      /// \brief Set the minimum value for the command.
+      /// \param[in] _c The minimum value
+      public: void SetCmdMin(const double _c);
+
+      /// \brief Set the offset value for the command,
+      /// which is added to the result of the PID controller.
+      /// \param[in] _c The offset value
+      public: void SetCmdOffset(const double _c);
+
+      /// \brief Get the proportional Gain.
+      /// \return The proportional gain value
+      public: double PGain() const;
+
+      /// \brief Get the integral Gain.
+      /// \return The integral gain value
+      public: double IGain() const;
+
+      /// \brief Get the derivative Gain.
+      /// \return The derivative gain value
+      public: double DGain() const;
+
+      /// \brief Get the integral upper limit.
+      /// \return The integral upper limit value
+      public: double IMax() const;
+
+      /// \brief Get the integral lower limit.
+      /// \return The integral lower limit value
+      public: double IMin() const;
+
+      /// \brief Get the maximum value for the command.
+      /// \return The maximum value
+      public: double CmdMax() const;
+
+      /// \brief Get the maximum value for the command.
+      /// \return The maximum value
+      public: double CmdMin() const;
+
+      /// \brief Get the offset value for the command.
+      /// \return The offset value
+      public: double CmdOffset() const;
+
+      /// \brief Update the Pid loop with nonuniform time step size.
+      /// \param[in] _error  Error since last call (p_state - p_target).
+      /// \param[in] _dt Change in time since last update call.
+      /// Normally, this is called at every time step,
+      /// The return value is an updated command to be passed
+      /// to the object being controlled.
+      /// \return the command value
+      public: double Update(const double _error,
+                            const std::chrono::duration<double> &_dt);
+
+      /// \brief Set current target command for this PID controller.
+      /// \param[in] _cmd New command
+      public: void SetCmd(const double _cmd);
+
+      /// \brief Return current command for this PID controller.
+      /// \return the command value
+      public: double Cmd() const;
+
+      /// \brief Return PID error terms for the controller.
+      /// \param[in] _pe  The proportional error.
+      /// \param[in] _ie  The integral of gain times error.
+      /// \param[in] _de  The derivative error.
+      public: void Errors(double &_pe, double &_ie, double &_de) const;
+
+      /// \brief Assignment operator
+      /// \param[in] _p a reference to a PID to assign values from
+      /// \return reference to this instance
+      public: PID &operator=(const PID &_p);
+
+      /// \brief Reset the errors and command.
+      public: void Reset();
+
+      /// \brief Error at a previous step.
+      private: double pErrLast = 0.0;
+
+      /// \brief Current error.
+      private: double pErr = 0.0;
+
+      /// \brief Integral of gain times error.
+      private: double iErr = 0.0;
+
+      /// \brief Derivative error.
+      private: double dErr = 0.0;
+
+      /// \brief Gain for proportional control.
+      private: double pGain;
+
+      /// \brief Gain for integral control.
+      private: double iGain = 0.0;
+
+      /// \brief Gain for derivative control.
+      private: double dGain = 0.0;
+
+      /// \brief Maximum clamping value for integral term.
+      private: double iMax = -1.0;
+
+      /// \brief Minim clamping value for integral term.
+      private: double iMin = 0.0;
+
+      /// \brief Command value.
+      private: double cmd = 0.0;
+
+      /// \brief Max command clamping value.
+      private: double cmdMax = -1.0;
+
+      /// \brief Min command clamping value.
+      private: double cmdMin = 0.0;
+
+      /// \brief Command offset.
+      private: double cmdOffset = 0.0;
+    };
+  }
+}
+#endif
diff --git a/include/ignition/math/Plane.hh b/include/ignition/math/Plane.hh
new file mode 100644
index 0000000..27b8f59
--- /dev/null
+++ b/include/ignition/math/Plane.hh
@@ -0,0 +1,231 @@
+/*
+ * Copyright (C) 2012 Open Source Robotics Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+*/
+#ifndef IGNITION_MATH_PLANE_HH_
+#define IGNITION_MATH_PLANE_HH_
+
+#include <ignition/math/Box.hh>
+#include <ignition/math/Vector3.hh>
+#include <ignition/math/Vector2.hh>
+
+namespace ignition
+{
+  namespace math
+  {
+    /// \class Plane Plane.hh ignition/math/Plane.hh
+    /// \brief A plane and related functions.
+    template<typename T>
+    class Plane
+    {
+      /// \brief Enum used to indicate a side of the plane, no side, or both
+      /// sides for entities on the plane.
+      /// \sa Side
+      public: enum PlaneSide
+      {
+        /// \brief Negative side of the plane. This is the side that is
+        /// opposite the normal.
+        NEGATIVE_SIDE = 0,
+
+        /// \brief Positive side of the plane. This is the side that has the
+        /// normal vector.
+        POSITIVE_SIDE = 1,
+
+        /// \brief On the plane.
+        NO_SIDE = 2,
+
+        /// \brief On both sides of the plane.
+        BOTH_SIDE = 3
+      };
+
+      /// \brief Constructor
+      public: Plane()
+      : d(0.0)
+      {
+      }
+
+      /// \brief Constructor from a normal and a distance
+      /// \param[in] _normal The plane normal
+      /// \param[in] _offset Offset along the normal
+      public: Plane(const Vector3<T> &_normal, T _offset = 0.0)
+      : normal(_normal), d(_offset)
+      {
+      }
+
+      /// \brief Constructor
+      /// \param[in] _normal The plane normal
+      /// \param[in] _size Size of the plane
+      /// \param[in] _offset Offset along the normal
+      public: Plane(const Vector3<T> &_normal, const Vector2<T> &_size,
+                    T _offset)
+      {
+        this->Set(_normal, _size, _offset);
+      }
+
+      /// \brief Destructor
+      public: virtual ~Plane() {}
+
+      /// \brief Set the plane
+      /// \param[in] _normal The plane normal
+      /// \param[in] _offset Offset along the normal
+      public: void Set(const Vector3<T> &_normal, T _offset)
+      {
+        this->normal = _normal;
+        this->d = _offset;
+      }
+
+      /// \brief Set the plane
+      /// \param[in] _normal The plane normal
+      /// \param[in] _size Size of the plane
+      /// \param[in] _offset Offset along the normal
+      public: void Set(const Vector3<T> &_normal, const Vector2<T> &_size,
+                       T _offset)
+      {
+        this->normal = _normal;
+        this->size = _size;
+        this->d = _offset;
+      }
+
+      /// \brief The distance to the plane from the given point. The
+      /// distance can be negative, which indicates the point is on the
+      /// negative side of the plane.
+      /// \param[in] _point 3D point to calculate distance from.
+      /// \return Distance from the point to the plane.
+      /// \sa Side
+      public: T Distance(const Vector3<T> &_point) const
+      {
+        return this->normal.Dot(_point) - this->d;
+      }
+
+      /// \brief The side of the plane a point is on.
+      /// \param[in] _point The 3D point to check.
+      /// \return Plane::NEGATIVE_SIDE if the distance from the point to the
+      /// plane is negative, Plane::POSITIVE_SIDE if the distance from the
+      /// point to the plane is positive, or Plane::NO_SIDE if the
+      /// point is on the plane.
+      public: PlaneSide Side(const Vector3<T> &_point) const
+      {
+        T dist = this->Distance(_point);
+
+        if (dist < 0.0)
+          return NEGATIVE_SIDE;
+
+        if (dist > 0.0)
+          return POSITIVE_SIDE;
+
+        return NO_SIDE;
+      }
+
+      /// \brief The side of the plane a box is on.
+      /// \param[in] _box The 3D box to check.
+      /// \return Plane::NEGATIVE_SIDE if the distance from the box to the
+      /// plane is negative, Plane::POSITIVE_SIDE if the distance from the
+      /// box to the plane is positive, or Plane::BOTH_SIDE if the
+      /// box is on the plane.
+      public: PlaneSide Side(const math::Box &_box) const
+      {
+        double dist = this->Distance(_box.Center());
+        double maxAbsDist = this->normal.AbsDot(_box.Size()/2.0);
+
+        if (dist < -maxAbsDist)
+          return NEGATIVE_SIDE;
+
+        if (dist > maxAbsDist)
+          return POSITIVE_SIDE;
+
+        return BOTH_SIDE;
+      }
+
+      /// \brief Get distance to the plane give an origin and direction
+      /// \param[in] _origin the origin
+      /// \param[in] _dir a direction
+      /// \return the shortest distance
+      public: T Distance(const Vector3<T> &_origin,
+                         const Vector3<T> &_dir) const
+      {
+        T denom = this->normal.Dot(_dir);
+
+        if (std::abs(denom) < 1e-3)
+        {
+          // parallel
+          return 0;
+        }
+        else
+        {
+          T nom = _origin.Dot(this->normal) - this->d;
+          T t = -(nom/denom);
+          return t;
+        }
+      }
+
+      /// \brief Get the plane size
+      public: inline const Vector2<T> &Size() const
+      {
+        return this->size;
+      }
+
+      /// \brief Get the plane size
+      public: inline Vector2<T> &Size()
+      {
+        return this->size;
+      }
+
+      /// \brief Get the plane offset
+      public: inline const Vector3<T> &Normal() const
+      {
+        return this->normal;
+      }
+
+      /// \brief Get the plane offset
+      public: inline Vector3<T> &Normal()
+      {
+        return this->normal;
+      }
+
+      /// \brief Get the plane offset
+      public: inline T Offset() const
+      {
+        return this->d;
+      }
+
+      /// \brief Equal operator
+      /// \param _p another plane
+      /// \return itself
+      public: Plane<T> &operator=(const Plane<T> &_p)
+      {
+        this->normal = _p.normal;
+        this->size = _p.size;
+        this->d = _p.d;
+
+        return *this;
+      }
+
+      /// \brief Plane normal
+      private: Vector3<T> normal;
+
+      /// \brief Plane size
+      private: Vector2<T> size;
+
+      /// \brief Plane offset
+      private: T d;
+    };
+
+    typedef Plane<int> Planei;
+    typedef Plane<double> Planed;
+    typedef Plane<float> Planef;
+  }
+}
+
+#endif
diff --git a/include/ignition/math/Pose3.hh b/include/ignition/math/Pose3.hh
new file mode 100644
index 0000000..31981ff
--- /dev/null
+++ b/include/ignition/math/Pose3.hh
@@ -0,0 +1,411 @@
+/*
+ * Copyright (C) 2012 Open Source Robotics Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+*/
+#ifndef IGNITION_MATH_POSE_HH_
+#define IGNITION_MATH_POSE_HH_
+
+#include <ignition/math/Quaternion.hh>
+#include <ignition/math/Vector3.hh>
+
+namespace ignition
+{
+  namespace math
+  {
+    /// \class Pose3 Pose3.hh ignition/math/Pose3.hh
+    /// \brief Encapsulates a position and rotation in three space
+    template<typename T>
+    class Pose3
+    {
+      /// \brief math::Pose3<T>(0, 0, 0, 0, 0, 0)
+      public: static const Pose3<T> Zero;
+
+      /// \brief Default constructors
+      public: Pose3() : p(0, 0, 0), q(1, 0, 0, 0)
+      {
+      }
+
+      /// \brief Constructor
+      /// \param[in] _pos A position
+      /// \param[in] _rot A rotation
+      public: Pose3(const Vector3<T> &_pos, const Quaternion<T> &_rot)
+      : p(_pos), q(_rot)
+      {
+      }
+
+      /// \brief Constructor
+      /// \param[in] _x x position in meters.
+      /// \param[in] _y y position in meters.
+      /// \param[in] _z z position in meters.
+      /// \param[in] _roll Roll (rotation about X-axis) in radians.
+      /// \param[in] _pitch Pitch (rotation about y-axis) in radians.
+      /// \param[in] _yaw Yaw (rotation about z-axis) in radians.
+      public: Pose3(T _x, T _y, T _z, T _roll, T _pitch, T _yaw)
+      : p(_x, _y, _z), q(_roll, _pitch, _yaw)
+      {
+      }
+
+      /// \brief Constructor
+      /// \param[in] _x x position in meters.
+      /// \param[in] _y y position in meters.
+      /// \param[in] _z z position in meters.
+      /// \param[in] _qw Quaternion w value.
+      /// \param[in] _qx Quaternion x value.
+      /// \param[in] _qy Quaternion y value.
+      /// \param[in] _qz Quaternion z value.
+      public: Pose3(T _x, T _y, T _z, T _qw, T _qx, T _qy, T _qz)
+      : p(_x, _y, _z), q(_qw, _qx, _qy, _qz)
+      {
+      }
+
+      /// \brief Copy constructor
+      /// \param[in] _pose Pose3<T> to copy
+      public: Pose3(const Pose3<T> &_pose)
+      : p(_pose.p), q(_pose.q)
+      {
+      }
+
+      /// \brief Destructor
+      public: virtual ~Pose3()
+      {
+      }
+
+      /// \brief Set the pose from a Vector3 and a Quaternion<T>
+      /// \param[in] _pos The position.
+      /// \param[in] _rot The rotation.
+      public: void Set(const Vector3<T> &_pos, const Quaternion<T> &_rot)
+      {
+        this->p = _pos;
+        this->q = _rot;
+      }
+
+      /// \brief Set the pose from  pos and rpy vectors
+      /// \param[in] _pos The position.
+      /// \param[in] _rpy The rotation expressed as Euler angles.
+      public: void Set(const Vector3<T> &_pos, const Vector3<T> &_rpy)
+      {
+        this->p = _pos;
+        this->q.Euler(_rpy);
+      }
+
+      /// \brief Set the pose from a six tuple.
+      /// \param[in] _x x position in meters.
+      /// \param[in] _y y position in meters.
+      /// \param[in] _z z position in meters.
+      /// \param[in] _roll Roll (rotation about X-axis) in radians.
+      /// \param[in] _pitch Pitch (rotation about y-axis) in radians.
+      /// \param[in] _yaw Pitch (rotation about z-axis) in radians.
+      public: void Set(T _x, T _y, T _z, T _roll, T _pitch, T _yaw)
+      {
+        this->p.Set(_x, _y, _z);
+        this->q.Euler(math::Vector3<T>(_roll, _pitch, _yaw));
+      }
+
+      /// \brief See if a pose is finite (e.g., not nan)
+      public: bool IsFinite() const
+      {
+        return this->p.IsFinite() && this->q.IsFinite();
+      }
+
+      /// \brief Fix any nan values
+      public: inline void Correct()
+      {
+        this->p.Correct();
+        this->q.Correct();
+      }
+
+      /// \brief Get the inverse of this pose
+      /// \return the inverse pose
+      public: Pose3<T> Inverse() const
+      {
+        Quaternion<T> inv = this->q.Inverse();
+        return Pose3<T>(inv * (this->p*-1), inv);
+      }
+
+      /// \brief Addition operator
+      /// A is the transform from O to P specified in frame O
+      /// B is the transform from P to Q specified in frame P
+      /// then, B + A is the transform from O to Q specified in frame O
+      /// \param[in] _pose Pose3<T> to add to this pose
+      /// \return The resulting pose
+      public: Pose3<T> operator+(const Pose3<T> &_pose) const
+      {
+        Pose3<T> result;
+
+        result.p = this->CoordPositionAdd(_pose);
+        result.q = this->CoordRotationAdd(_pose.q);
+
+        return result;
+      }
+
+      /// \brief Add-Equals operator
+      /// \param[in] _pose Pose3<T> to add to this pose
+      /// \return The resulting pose
+      public: const Pose3<T> &operator+=(const Pose3<T> &_pose)
+      {
+        this->p = this->CoordPositionAdd(_pose);
+        this->q = this->CoordRotationAdd(_pose.q);
+
+        return *this;
+      }
+
+      /// \brief Negation operator
+      /// A is the transform from O to P in frame O
+      /// then -A is transform from P to O specified in frame P
+      /// \return The resulting pose
+      public: inline Pose3<T> operator-() const
+      {
+        return Pose3<T>() - *this;
+      }
+
+      /// \brief Subtraction operator
+      /// A is the transform from O to P in frame O
+      /// B is the transform from O to Q in frame O
+      /// B - A is the transform from P to Q in frame P
+      /// \param[in] _pose Pose3<T> to subtract from this one
+      /// \return The resulting pose
+      public: inline Pose3<T> operator-(const Pose3<T> &_pose) const
+      {
+        return Pose3<T>(this->CoordPositionSub(_pose),
+          this->CoordRotationSub(_pose.q));
+      }
+
+      /// \brief Subtraction operator
+      /// \param[in] _pose Pose3<T> to subtract from this one
+      /// \return The resulting pose
+      public: const Pose3<T> &operator-=(const Pose3<T> &_pose)
+      {
+        this->p = this->CoordPositionSub(_pose);
+        this->q = this->CoordRotationSub(_pose.q);
+
+        return *this;
+      }
+
+      /// \brief Equality operator
+      /// \param[in] _pose Pose3<T> for comparison
+      /// \return True if equal
+      public: bool operator==(const Pose3<T> &_pose) const
+      {
+        return this->p == _pose.p && this->q == _pose.q;
+      }
+
+      /// \brief Inequality operator
+      /// \param[in] _pose Pose3<T> for comparison
+      /// \return True if not equal
+      public: bool operator!=(const Pose3<T> &_pose) const
+      {
+        return this->p != _pose.p || this->q != _pose.q;
+      }
+
+      /// \brief Multiplication operator
+      /// \param[in] _pose the other pose
+      /// \return itself
+      public: Pose3<T> operator*(const Pose3<T> &_pose) const
+      {
+        return Pose3<T>(this->CoordPositionAdd(_pose),  _pose.q * this->q);
+      }
+
+      /// \brief Equal operator
+      /// \param[in] _pose Pose3<T> to copy
+      public: Pose3<T> &operator=(const Pose3<T> &_pose)
+      {
+        this->p = _pose.p;
+        this->q = _pose.q;
+        return *this;
+      }
+
+      /// \brief Add one point to a vector: result = this + pos
+      /// \param[in] _pos Position to add to this pose
+      /// \return the resulting position
+      public: Vector3<T> CoordPositionAdd(const Vector3<T> &_pos) const
+      {
+        Quaternion<T> tmp(0.0, _pos.X(), _pos.Y(), _pos.Z());
+
+        // result = pose.q + pose.q * this->p * pose.q!
+        tmp = this->q * (tmp * this->q.Inverse());
+
+        return Vector3<T>(this->p.X() + tmp.X(),
+                          this->p.Y() + tmp.Y(),
+                          this->p.Z() + tmp.Z());
+      }
+
+      /// \brief Add one point to another: result = this + pose
+      /// \param[in] _pose The Pose3<T> to add
+      /// \return The resulting position
+      public: Vector3<T> CoordPositionAdd(const Pose3<T> &_pose) const
+      {
+        Quaternion<T> tmp(static_cast<T>(0),
+            this->p.X(), this->p.Y(), this->p.Z());
+
+        // result = _pose.q + _pose.q * this->p * _pose.q!
+        tmp = _pose.q * (tmp * _pose.q.Inverse());
+
+        return Vector3<T>(_pose.p.X() + tmp.X(),
+                          _pose.p.Y() + tmp.Y(),
+                          _pose.p.Z() + tmp.Z());
+      }
+
+      /// \brief Subtract one position from another: result = this - pose
+      /// \param[in] _pose Pose3<T> to subtract
+      /// \return The resulting position
+      public: inline Vector3<T> CoordPositionSub(const Pose3<T> &_pose) const
+      {
+        Quaternion<T> tmp(0,
+            this->p.X() - _pose.p.X(),
+            this->p.Y() - _pose.p.Y(),
+            this->p.Z() - _pose.p.Z());
+
+        tmp = _pose.q.Inverse() * (tmp * _pose.q);
+        return Vector3<T>(tmp.X(), tmp.Y(), tmp.Z());
+      }
+
+      /// \brief Add one rotation to another: result =  this->q + rot
+      /// \param[in] _rot Rotation to add
+      /// \return The resulting rotation
+      public: Quaternion<T> CoordRotationAdd(const Quaternion<T> &_rot) const
+      {
+        return Quaternion<T>(_rot * this->q);
+      }
+
+      /// \brief Subtract one rotation from another: result = this->q - rot
+      /// \param[in] _rot The rotation to subtract
+      /// \return The resulting rotation
+      public: inline Quaternion<T> CoordRotationSub(
+                  const Quaternion<T> &_rot) const
+      {
+        Quaternion<T> result(_rot.Inverse() * this->q);
+        result.Normalize();
+        return result;
+      }
+
+      /// \brief Find the inverse of a pose; i.e., if b = this + a, given b and
+      /// this, find a
+      /// \param[in] _b the other pose
+      public: Pose3<T> CoordPoseSolve(const Pose3<T> &_b) const
+      {
+        Quaternion<T> qt;
+        Pose3<T> a;
+
+        a.q = this->q.Inverse() * _b.q;
+        qt = a.q * Quaternion<T>(0, this->p.X(), this->p.Y(), this->p.Z());
+        qt = qt * a.q.Inverse();
+        a.p = _b.p - Vector3<T>(qt.X(), qt.Y(), qt.Z());
+
+        return a;
+      }
+
+      /// \brief Reset the pose
+      public: void Reset()
+      {
+        // set the position to zero
+        this->p.Set();
+        this->q = Quaterniond::Identity;
+      }
+
+      /// \brief Rotate vector part of a pose about the origin
+      /// \param[in] _rot rotation
+      /// \return the rotated pose
+      public: Pose3<T> RotatePositionAboutOrigin(const Quaternion<T> &_q) const
+      {
+        Pose3<T> a = *this;
+        a.p.X((1.0 - 2.0*_q.Y()*_q.Y() - 2.0*_q.Z()*_q.Z()) * this->p.X()
+                +(2.0*(_q.X()*_q.Y()+_q.W()*_q.Z())) * this->p.Y()
+                +(2.0*(_q.X()*_q.Z()-_q.W()*_q.Y())) * this->p.Z());
+        a.p.Y((2.0*(_q.X()*_q.Y()-_q.W()*_q.Z())) * this->p.X()
+                +(1.0 - 2.0*_q.X()*_q.X() - 2.0*_q.Z()*_q.Z()) * this->p.Y()
+                +(2.0*(_q.Y()*_q.Z()+_q.W()*_q.X())) * this->p.Z());
+        a.p.Z((2.0*(_q.X()*_q.Z()+_q.W()*_q.Y())) * this->p.X()
+                +(2.0*(_q.Y()*_q.Z()-_q.W()*_q.X())) * this->p.Y()
+                +(1.0 - 2.0*_q.X()*_q.X() - 2.0*_q.Y()*_q.Y()) * this->p.Z());
+        return a;
+      }
+
+      /// \brief Round all values to _precision decimal places
+      /// \param[in] _precision
+      public: void Round(int _precision)
+      {
+        this->q.Round(_precision);
+        this->p.Round(_precision);
+      }
+
+      /// \brief Get the position.
+      /// \return Origin of the pose.
+      public: inline const Vector3<T> &Pos() const
+      {
+        return this->p;
+      }
+
+      /// \brief Get a mutable reference to the position.
+      /// \return Origin of the pose.
+      public: inline Vector3<T> &Pos()
+      {
+        return this->p;
+      }
+
+      /// \brief Get the rotation.
+      /// \return Quaternion representation of the rotation.
+      public: inline const Quaternion<T> &Rot() const
+      {
+        return this->q;
+      }
+
+      /// \brief Get a mutuable reference to the rotation.
+      /// \return Quaternion representation of the rotation.
+      public: inline Quaternion<T> &Rot()
+      {
+        return this->q;
+      }
+
+      /// \brief Stream insertion operator
+      /// \param[in] _out output stream
+      /// \param[in] _pose pose to output
+      /// \return the stream
+      public: friend std::ostream &operator<<(
+                  std::ostream &_out, const ignition::math::Pose3<T> &_pose)
+      {
+        _out << _pose.Pos() << " " << _pose.Rot();
+        return _out;
+      }
+
+      /// \brief Stream extraction operator
+      /// \param[in] _in the input stream
+      /// \param[in] _pose the pose
+      /// \return the stream
+      public: friend std::istream &operator>>(
+                  std::istream &_in, ignition::math::Pose3<T> &_pose)
+      {
+        // Skip white spaces
+        _in.setf(std::ios_base::skipws);
+        Vector3<T> pos;
+        Quaternion<T> rot;
+        _in >> pos >> rot;
+        _pose.Set(pos, rot);
+        return _in;
+      }
+
+      /// \brief The position
+      private: Vector3<T> p;
+
+      /// \brief The rotation
+      private: Quaternion<T> q;
+    };
+    template<typename T> const Pose3<T> Pose3<T>::Zero(0, 0, 0, 0, 0, 0);
+
+    typedef Pose3<int> Pose3i;
+    typedef Pose3<double> Pose3d;
+    typedef Pose3<float> Pose3f;
+  }
+}
+#endif
diff --git a/include/ignition/math/Quaternion.hh b/include/ignition/math/Quaternion.hh
new file mode 100644
index 0000000..a810561
--- /dev/null
+++ b/include/ignition/math/Quaternion.hh
@@ -0,0 +1,1083 @@
+/*
+ * Copyright (C) 2012 Open Source Robotics Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+*/
+#ifndef IGNITION_MATH_QUATERNION_HH_
+#define IGNITION_MATH_QUATERNION_HH_
+
+#include <ignition/math/Helpers.hh>
+#include <ignition/math/Angle.hh>
+#include <ignition/math/Vector3.hh>
+#include <ignition/math/Matrix3.hh>
+
+namespace ignition
+{
+  namespace math
+  {
+    template <typename T> class Matrix3;
+
+    /// \class Quaternion Quaternion.hh ignition/math/Quaternion.hh
+    /// \brief A quaternion class
+    template<typename T>
+    class Quaternion
+    {
+      /// \brief math::Quaternion(1, 0, 0, 0)
+      public: static const Quaternion Identity;
+
+      /// \brief math::Quaternion(0, 0, 0, 0)
+      public: static const Quaternion Zero;
+
+      /// \brief Default Constructor
+      public: Quaternion()
+      : qw(1), qx(0), qy(0), qz(0)
+      {
+        // quaternion not normalized, because that breaks
+        // Pose::CoordPositionAdd(...)
+      }
+
+      /// \brief Constructor
+      /// \param[in] _w W param
+      /// \param[in] _x X param
+      /// \param[in] _y Y param
+      /// \param[in] _z Z param
+      public: Quaternion(const T &_w, const T &_x, const T &_y, const T &_z)
+      : qw(_w), qx(_x), qy(_y), qz(_z)
+      {}
+
+      /// \brief Constructor from Euler angles in radians
+      /// \param[in] _roll  roll
+      /// \param[in] _pitch pitch
+      /// \param[in] _yaw   yaw
+      public: Quaternion(const T &_roll, const T &_pitch, const T &_yaw)
+      {
+        this->Euler(Vector3<T>(_roll, _pitch, _yaw));
+      }
+
+      /// \brief Constructor from axis angle
+      /// \param[in] _axis the rotation axis
+      /// \param[in] _angle the rotation angle in radians
+      public: Quaternion(const Vector3<T> &_axis, const T &_angle)
+      {
+        this->Axis(_axis, _angle);
+      }
+
+      /// \brief Constructor
+      /// \param[in] _rpy euler angles
+      public: explicit Quaternion(const Vector3<T> &_rpy)
+      {
+        this->Euler(_rpy);
+      }
+
+      /// \brief Construct from rotation matrix.
+      /// \param[in] _mat rotation matrix (must be orthogonal, the function
+      ///                 doesn't check it)
+      public: explicit Quaternion(const Matrix3<T> &_mat)
+      {
+        this->Matrix(_mat);
+      }
+
+      /// \brief Copy constructor
+      /// \param[in] _qt Quaternion<T> to copy
+      public: Quaternion(const Quaternion<T> &_qt)
+      {
+        this->qw = _qt.qw;
+        this->qx = _qt.qx;
+        this->qy = _qt.qy;
+        this->qz = _qt.qz;
+      }
+
+      /// \brief Destructor
+      public: ~Quaternion() {}
+
+      /// \brief Equal operator
+      /// \param[in] _qt Quaternion<T> to copy
+      public: Quaternion<T> &operator=(const Quaternion<T> &_qt)
+      {
+        this->qw = _qt.qw;
+        this->qx = _qt.qx;
+        this->qy = _qt.qy;
+        this->qz = _qt.qz;
+
+        return *this;
+      }
+
+      /// \brief Invert the quaternion
+      public: void Invert()
+      {
+        this->Normalize();
+        // this->qw = this->qw;
+        this->qx = -this->qx;
+        this->qy = -this->qy;
+        this->qz = -this->qz;
+      }
+
+      /// \brief Get the inverse of this quaternion
+      /// \return Inverse quaternion
+      public: inline Quaternion<T> Inverse() const
+              {
+                T s = 0;
+                Quaternion<T> q(this->qw, this->qx, this->qy, this->qz);
+
+                // use s to test if quaternion is valid
+                s = q.qw * q.qw + q.qx * q.qx + q.qy * q.qy + q.qz * q.qz;
+
+                if (equal<T>(s, static_cast<T>(0)))
+                {
+                  q.qw = 1.0;
+                  q.qx = 0.0;
+                  q.qy = 0.0;
+                  q.qz = 0.0;
+                }
+                else
+                {
+                  // deal with non-normalized quaternion
+                  // div by s so q * qinv = identity
+                  q.qw =  q.qw / s;
+                  q.qx = -q.qx / s;
+                  q.qy = -q.qy / s;
+                  q.qz = -q.qz / s;
+                }
+                return q;
+              }
+
+      /// \brief Return the logarithm
+      /// \return the log
+      public: Quaternion<T> Log() const
+      {
+        // If q = cos(A)+sin(A)*(x*i+y*j+z*k) where (x, y, z) is unit length,
+        // then log(q) = A*(x*i+y*j+z*k).  If sin(A) is near zero, use log(q) =
+        // sin(A)*(x*i+y*j+z*k) since sin(A)/A has limit 1.
+
+        Quaternion<T> result;
+        result.qw = 0.0;
+
+        if (std::abs(this->qw) < 1.0)
+        {
+          T fAngle = acos(this->qw);
+          T fSin = sin(fAngle);
+          if (std::abs(fSin) >= 1e-3)
+          {
+            T fCoeff = fAngle/fSin;
+            result.qx = fCoeff*this->qx;
+            result.qy = fCoeff*this->qy;
+            result.qz = fCoeff*this->qz;
+            return result;
+          }
+        }
+
+        result.qx = this->qx;
+        result.qy = this->qy;
+        result.qz = this->qz;
+
+        return result;
+      }
+
+      /// \brief Return the exponent
+      /// \return the exp
+      public: Quaternion<T> Exp() const
+      {
+        // If q = A*(x*i+y*j+z*k) where (x, y, z) is unit length, then
+        // exp(q) = cos(A)+sin(A)*(x*i+y*j+z*k).  If sin(A) is near zero,
+        // use exp(q) = cos(A)+A*(x*i+y*j+z*k) since A/sin(A) has limit 1.
+
+        T fAngle = sqrt(this->qx*this->qx+
+            this->qy*this->qy+this->qz*this->qz);
+        T fSin = sin(fAngle);
+
+        Quaternion<T> result;
+        result.qw = cos(fAngle);
+
+        if (std::abs(fSin) >= 1e-3)
+        {
+          T fCoeff = fSin/fAngle;
+          result.qx = fCoeff*this->qx;
+          result.qy = fCoeff*this->qy;
+          result.qz = fCoeff*this->qz;
+        }
+        else
+        {
+          result.qx = this->qx;
+          result.qy = this->qy;
+          result.qz = this->qz;
+        }
+
+        return result;
+      }
+
+      /// \brief Normalize the quaternion
+      public: void Normalize()
+      {
+        T s = 0;
+
+        s = T(sqrt(this->qw * this->qw + this->qx * this->qx +
+            this->qy * this->qy + this->qz * this->qz));
+
+        if (equal<T>(s, static_cast<T>(0)))
+        {
+          this->qw = T(1.0);
+          this->qx = T(0.0);
+          this->qy = T(0.0);
+          this->qz = T(0.0);
+        }
+        else
+        {
+          this->qw /= s;
+          this->qx /= s;
+          this->qy /= s;
+          this->qz /= s;
+        }
+      }
+
+      /// \brief Set the quaternion from an axis and angle
+      /// \param[in] _x X axis
+      /// \param[in] _y Y axis
+      /// \param[in] _z Z axis
+      /// \param[in] _a Angle in radians
+      public: void Axis(T _ax, T _ay, T _az, T _aa)
+      {
+        T l;
+
+        l = _ax * _ax + _ay * _ay + _az * _az;
+
+        if (equal<T>(l, static_cast<T>(0)))
+        {
+          this->qw = 1;
+          this->qx = 0;
+          this->qy = 0;
+          this->qz = 0;
+        }
+        else
+        {
+          _aa *= 0.5;
+          l = sin(_aa) / sqrt(l);
+          this->qw = cos(_aa);
+          this->qx = _ax * l;
+          this->qy = _ay * l;
+          this->qz = _az * l;
+        }
+
+        this->Normalize();
+      }
+
+      /// \brief Set the quaternion from an axis and angle
+      /// \param[in] _axis Axis
+      /// \param[in] _a Angle in radians
+      public: void Axis(const Vector3<T> &_axis, T _a)
+      {
+        this->Axis(_axis.X(), _axis.Y(), _axis.Z(), _a);
+      }
+
+      /// \brief Set this quaternion from 4 floating numbers
+      /// \param[in] _u u
+      /// \param[in] _x x
+      /// \param[in] _y y
+      /// \param[in] _z z
+      public: void Set(T _w, T _x, T _y, T _z)
+      {
+        this->qw = _w;
+        this->qx = _x;
+        this->qy = _y;
+        this->qz = _z;
+      }
+
+      /// \brief Set the quaternion from Euler angles. The order of operations
+      /// is roll, pitch, yaw around a fixed body frame axis
+      /// (the original frame of the object before rotation is applied).
+      /// Roll is a rotation about x, pitch is about y, yaw is about z.
+      /// \param[in] _vec Euler angle
+      public: void Euler(const Vector3<T> &_vec)
+      {
+        this->Euler(_vec.X(), _vec.Y(), _vec.Z());
+      }
+
+      /// \brief Set the quaternion from Euler angles.
+      /// \param[in] _roll Roll angle (radians).
+      /// \param[in] _pitch Pitch angle (radians).
+      /// \param[in] _yaw Yaw angle (radians).
+      public: void Euler(T _roll, T _pitch, T _yaw)
+      {
+        T phi, the, psi;
+
+        phi = _roll / T(2.0);
+        the = _pitch / T(2.0);
+        psi = _yaw / T(2.0);
+
+        this->qw = T(cos(phi) * cos(the) * cos(psi) +
+          sin(phi) * sin(the) * sin(psi));
+        this->qx = T(sin(phi) * cos(the) * cos(psi) -
+          cos(phi) * sin(the) * sin(psi));
+        this->qy = T(cos(phi) * sin(the) * cos(psi) +
+          sin(phi) * cos(the) * sin(psi));
+        this->qz = T(cos(phi) * cos(the) * sin(psi) -
+          sin(phi) * sin(the) * cos(psi));
+
+        this->Normalize();
+      }
+
+      /// \brief Return the rotation in Euler angles
+      /// \return This quaternion as an Euler vector
+      public: Vector3<T> Euler() const
+      {
+        Vector3<T> vec;
+
+        T tol = static_cast<T>(1e-15);
+
+        Quaternion<T> copy = *this;
+        T squ;
+        T sqx;
+        T sqy;
+        T sqz;
+
+        copy.Normalize();
+
+        squ = copy.qw * copy.qw;
+        sqx = copy.qx * copy.qx;
+        sqy = copy.qy * copy.qy;
+        sqz = copy.qz * copy.qz;
+
+        // Pitch
+        T sarg = -2 * (copy.qx*copy.qz - copy.qw * copy.qy);
+        if (sarg <= T(-1.0))
+        {
+          vec.Y(T(-0.5*IGN_PI));
+        }
+        else if (sarg >= T(1.0))
+        {
+          vec.Y(T(0.5*IGN_PI));
+        }
+        else
+        {
+          vec.Y(T(asin(sarg)));
+        }
+
+        // If the pitch angle is PI/2 or -PI/2, we can only compute
+        // the sum roll + yaw.  However, any combination that gives
+        // the right sum will produce the correct orientation, so we
+        // set yaw = 0 and compute roll.
+        // pitch angle is PI/2
+        if (std::abs(sarg - 1) < tol)
+        {
+          vec.Z(0);
+          vec.X(T(atan2(2 * (copy.qx*copy.qy - copy.qz*copy.qw),
+                      squ - sqx + sqy - sqz)));
+        }
+        // pitch angle is -PI/2
+        else if (std::abs(sarg + 1) < tol)
+        {
+          vec.Z(0);
+          vec.X(T(atan2(-2 * (copy.qx*copy.qy - copy.qz*copy.qw),
+                       squ - sqx + sqy - sqz)));
+        }
+        else
+        {
+          // Roll
+          vec.X(T(atan2(2 * (copy.qy*copy.qz + copy.qw*copy.qx),
+                      squ - sqx - sqy + sqz)));
+
+          // Yaw
+          vec.Z(T(atan2(2 * (copy.qx*copy.qy + copy.qw*copy.qz),
+                      squ + sqx - sqy - sqz)));
+        }
+
+        return vec;
+      }
+
+      /// \brief Convert euler angles to quatern.
+      /// \param[in] _vec The vector of angles to convert.
+      /// \return The converted quaternion.
+      public: static Quaternion<T> EulerToQuaternion(const Vector3<T> &_vec)
+      {
+        Quaternion<T> result;
+        result.Euler(_vec);
+        return result;
+      }
+
+      /// \brief Convert euler angles to quatern.
+      /// \param[in] _x rotation along x
+      /// \param[in] _y rotation along y
+      /// \param[in] _z rotation along z
+      /// \return The converted quaternion.
+      public: static Quaternion<T> EulerToQuaternion(T _x, T _y, T _z)
+      {
+        return EulerToQuaternion(Vector3<T>(_x, _y, _z));
+      }
+
+      /// \brief Get the Euler roll angle in radians
+      /// \return the roll component
+      public: T Roll() const
+      {
+        return this->Euler().X();
+      }
+
+      /// \brief Get the Euler pitch angle in radians
+      /// \return the pitch component
+      public: T Pitch() const
+      {
+        return this->Euler().Y();
+      }
+
+      /// \brief Get the Euler yaw angle in radians
+      /// \return the yaw component
+      public: T Yaw() const
+      {
+        return this->Euler().Z();
+      }
+
+      /// \brief Return rotation as axis and angle
+      /// \param[in] _axis rotation axis
+      /// \param[in] _angle ccw angle in radians
+      public: void ToAxis(Vector3<T> &_axis, T &_angle) const
+      {
+        T len = this->qx*this->qx + this->qy*this->qy + this->qz*this->qz;
+        if (equal<T>(len, static_cast<T>(0)))
+        {
+          _angle = 0.0;
+          _axis.Set(1, 0, 0);
+        }
+        else
+        {
+          _angle = 2.0 * acos(this->qw);
+          T invLen =  1.0 / sqrt(len);
+          _axis.Set(this->qx*invLen, this->qy*invLen, this->qz*invLen);
+        }
+      }
+
+      /// \brief Set from a rotation matrix.
+      /// \param[in] _mat rotation matrix (must be orthogonal, the function
+      ///                 doesn't check it)
+      ///
+      /// Implementation inspired by
+      /// http://www.euclideanspace.com/maths/geometry/rotations/
+      /// conversions/matrixToQuaternion/
+      void Matrix(const Matrix3<T> &_mat)
+      {
+        const T trace = _mat(0, 0) + _mat(1, 1) + _mat(2, 2);
+        if (trace > 0.0000001)
+        {
+          qw = sqrt(1 + trace) / 2;
+          const T s = 1.0 / (4 * qw);
+          qx = (_mat(2, 1) - _mat(1, 2)) * s;
+          qy = (_mat(0, 2) - _mat(2, 0)) * s;
+          qz = (_mat(1, 0) - _mat(0, 1)) * s;
+        }
+        else if (_mat(0, 0) > _mat(1, 1) && _mat(0, 0) > _mat(2, 2))
+        {
+          qx = sqrt(1.0 + _mat(0, 0) - _mat(1, 1) - _mat(2, 2)) / 2;
+          const T s = 1.0 / (4 * qx);
+          qw = (_mat(2, 1) - _mat(1, 2)) * s;
+          qy = (_mat(1, 0) + _mat(0, 1)) * s;
+          qz = (_mat(0, 2) + _mat(2, 0)) * s;
+        }
+        else if (_mat(1, 1) > _mat(2, 2))
+        {
+          qy = sqrt(1.0 - _mat(0, 0) + _mat(1, 1) - _mat(2, 2)) / 2;
+          const T s = 1.0 / (4 * qy);
+          qw = (_mat(0, 2) - _mat(2, 0)) * s;
+          qx = (_mat(0, 1) + _mat(1, 0)) * s;
+          qz = (_mat(1, 2) + _mat(2, 1)) * s;
+        }
+        else
+        {
+          qz = sqrt(1.0 - _mat(0, 0) - _mat(1, 1) + _mat(2, 2)) / 2;
+          const T s = 1.0 / (4 * qz);
+          qw = (_mat(1, 0) - _mat(0, 1)) * s;
+          qx = (_mat(0, 2) + _mat(2, 0)) * s;
+          qy = (_mat(1, 2) + _mat(2, 1)) * s;
+        }
+      }
+
+      /// \brief Set this quaternion to represent rotation from
+      /// vector _v1 to vector _v2, so that
+      /// _v2.Normalize() == this * _v1.Normalize() holds.
+      ///
+      /// \param[in] _v1 The first vector
+      /// \param[in] _v2 The second vector
+      ///
+      /// Implementation inspired by
+      /// http://stackoverflow.com/a/11741520/1076564
+      public: void From2Axes(const Vector3<T> &_v1, const Vector3<T> &_v2)
+      {
+        // generally, we utilize the fact that a quat (w, x, y, z) represents
+        // rotation of angle 2*w about axis (x, y, z)
+        //
+        // so we want to take get a vector half-way between no rotation and the
+        // double rotation, which is
+        // [ (1, (0, 0, 0)) + (_v1 dot _v2, _v1 x _v2) ] / 2
+        // if _v1 and _v2 are unit quaternions
+        //
+        // since we normalize the result anyway, we can omit the division,
+        // getting the result:
+        // [ (1, (0, 0, 0)) + (_v1 dot _v2, _v1 x _v2) ].Normalized()
+        //
+        // if _v1 and _v2 are not normalized, the magnitude (1 + _v1 dot _v2)
+        // is multiplied by k = norm(_v1)*norm(_v2)
+
+        const T kCosTheta = _v1.Dot(_v2);
+        const T k = sqrt(_v1.SquaredLength() * _v2.SquaredLength());
+
+        if (fabs(kCosTheta/k + 1) < 1e-6)
+        {
+          // the vectors are opposite
+          // any vector orthogonal to _v1
+          Vector3<T> other;
+          {
+            const Vector3<T> _v1Abs(_v1.Abs());
+            if (_v1Abs.X() < _v1Abs.Y())
+            {
+              if (_v1Abs.X() < _v1Abs.Z())
+              {
+                other.Set(1, 0, 0);
+              }
+              else
+              {
+                other.Set(0, 0, 1);
+              }
+            }
+            else
+            {
+              if (_v1Abs.Y() < _v1Abs.Z())
+              {
+                other.Set(0, 1, 0);
+              }
+              else
+              {
+                other.Set(0, 0, 1);
+              }
+            }
+          }
+
+          const Vector3<T> axis(_v1.Cross(other).Normalize());
+
+          qw = 0;
+          qx = axis.X();
+          qy = axis.Y();
+          qz = axis.Z();
+        }
+        else
+        {
+          // the vectors are in general position
+          const Vector3<T> axis(_v1.Cross(_v2));
+          qw = kCosTheta + k;
+          qx = axis.X();
+          qy = axis.Y();
+          qz = axis.Z();
+          this->Normalize();
+        }
+      }
+
+      /// \brief Scale a Quaternion<T>ion
+      /// \param[in] _scale Amount to scale this rotation
+      public: void Scale(T _scale)
+      {
+        Quaternion<T> b;
+        Vector3<T> axis;
+        T angle;
+
+        // Convert to axis-and-angle
+        this->ToAxis(axis, angle);
+        angle *= _scale;
+
+        this->Axis(axis.X(), axis.Y(), axis.Z(), angle);
+      }
+
+      /// \brief Addition operator
+      /// \param[in] _qt quaternion for addition
+      /// \return this quaternion + _qt
+      public: Quaternion<T> operator+(const Quaternion<T> &_qt) const
+      {
+        Quaternion<T> result(this->qw + _qt.qw, this->qx + _qt.qx,
+                             this->qy + _qt.qy, this->qz + _qt.qz);
+        return result;
+      }
+
+      /// \brief Addition operator
+      /// \param[in] _qt quaternion for addition
+      /// \return this quaternion + qt
+      public: Quaternion<T> operator+=(const Quaternion<T> &_qt)
+      {
+        *this = *this + _qt;
+
+        return *this;
+      }
+
+      /// \brief Subtraction operator
+      /// \param[in] _qt quaternion to subtract
+      /// \return this quaternion - _qt
+      public: Quaternion<T> operator-(const Quaternion<T> &_qt) const
+      {
+        Quaternion<T> result(this->qw - _qt.qw, this->qx - _qt.qx,
+                       this->qy - _qt.qy, this->qz - _qt.qz);
+        return result;
+      }
+
+      /// \brief Subtraction operator
+      /// \param[in] _qt Quaternion<T> for subtraction
+      /// \return This quaternion - qt
+      public: Quaternion<T> operator-=(const Quaternion<T> &_qt)
+      {
+        *this = *this - _qt;
+        return *this;
+      }
+
+      /// \brief Multiplication operator
+      /// \param[in] _q Quaternion<T> for multiplication
+      /// \return This quaternion multiplied by the parameter
+      public: inline Quaternion<T> operator*(const Quaternion<T> &_q) const
+              {
+                return Quaternion<T>(
+                  this->qw*_q.qw-this->qx*_q.qx-this->qy*_q.qy-this->qz*_q.qz,
+                  this->qw*_q.qx+this->qx*_q.qw+this->qy*_q.qz-this->qz*_q.qy,
+                  this->qw*_q.qy-this->qx*_q.qz+this->qy*_q.qw+this->qz*_q.qx,
+                  this->qw*_q.qz+this->qx*_q.qy-this->qy*_q.qx+this->qz*_q.qw);
+              }
+
+      /// \brief Multiplication operator by a scalar.
+      /// \param[in] _f factor
+      /// \return quaternion multiplied by the scalar
+      public: Quaternion<T> operator*(const T &_f) const
+      {
+        return Quaternion<T>(this->qw*_f, this->qx*_f,
+                             this->qy*_f, this->qz*_f);
+      }
+
+      /// \brief Multiplication operator
+      /// \param[in] _qt Quaternion<T> for multiplication
+      /// \return This quaternion multiplied by the parameter
+      public: Quaternion<T> operator*=(const Quaternion<T> &qt)
+      {
+        *this = *this * qt;
+        return *this;
+      }
+
+      /// \brief Vector3 multiplication operator
+      /// \param[in] _v vector to multiply
+      /// \return The result of the vector multiplication
+      public: Vector3<T> operator*(const Vector3<T> &_v) const
+      {
+        Vector3<T> uv, uuv;
+        Vector3<T> qvec(this->qx, this->qy, this->qz);
+        uv = qvec.Cross(_v);
+        uuv = qvec.Cross(uv);
+        uv *= (2.0f * this->qw);
+        uuv *= 2.0f;
+
+        return _v + uv + uuv;
+      }
+
+      /// \brief Equal to operator
+      /// \param[in] _qt Quaternion<T> for comparison
+      /// \return True if equal
+      public: bool operator==(const Quaternion<T> &_qt) const
+      {
+        return equal(this->qx, _qt.qx, static_cast<T>(0.001)) &&
+               equal(this->qy, _qt.qy, static_cast<T>(0.001)) &&
+               equal(this->qz, _qt.qz, static_cast<T>(0.001)) &&
+               equal(this->qw, _qt.qw, static_cast<T>(0.001));
+      }
+
+      /// \brief Not equal to operator
+      /// \param[in] _qt Quaternion<T> for comparison
+      /// \return True if not equal
+      public: bool operator!=(const Quaternion<T> &_qt) const
+      {
+        return !equal(this->qx, _qt.qx, static_cast<T>(0.001)) ||
+               !equal(this->qy, _qt.qy, static_cast<T>(0.001)) ||
+               !equal(this->qz, _qt.qz, static_cast<T>(0.001)) ||
+               !equal(this->qw, _qt.qw, static_cast<T>(0.001));
+      }
+
+      /// \brief Unary minus operator
+      /// \return negates each component of the quaternion
+      public: Quaternion<T> operator-() const
+      {
+        return Quaternion<T>(-this->qw, -this->qx, -this->qy, -this->qz);
+      }
+
+      /// \brief Rotate a vector using the quaternion
+      /// \param[in] _vec vector to rotate
+      /// \return the rotated vector
+      public: inline Vector3<T> RotateVector(const Vector3<T> &_vec) const
+      {
+        Quaternion<T> tmp(static_cast<T>(0),
+            _vec.X(), _vec.Y(), _vec.Z());
+        tmp = (*this) * (tmp * this->Inverse());
+        return Vector3<T>(tmp.qx, tmp.qy, tmp.qz);
+      }
+
+      /// \brief Do the reverse rotation of a vector by this quaternion
+      /// \param[in] _vec the vector
+      /// \return the reversed vector
+      public: Vector3<T> RotateVectorReverse(Vector3<T> _vec) const
+      {
+        Quaternion<T> tmp(0.0, _vec.X(), _vec.Y(), _vec.Z());
+
+        tmp =  this->Inverse() * (tmp * (*this));
+
+        return Vector3<T>(tmp.qx, tmp.qy, tmp.qz);
+      }
+
+      /// \brief See if a quaternion is finite (e.g., not nan)
+      /// \return True if quaternion is finite
+      public: bool IsFinite() const
+      {
+        // std::isfinite works with floating point values, need to explicit
+        // cast to avoid ambiguity in vc++.
+        return std::isfinite(static_cast<double>(this->qw)) &&
+               std::isfinite(static_cast<double>(this->qx)) &&
+               std::isfinite(static_cast<double>(this->qy)) &&
+               std::isfinite(static_cast<double>(this->qz));
+      }
+
+      /// \brief Correct any nan values in this quaternion
+      public: inline void Correct()
+      {
+        // std::isfinite works with floating point values, need to explicit
+        // cast to avoid ambiguity in vc++.
+        if (!std::isfinite(static_cast<double>(this->qx)))
+          this->qx = 0;
+        if (!std::isfinite(static_cast<double>(this->qy)))
+          this->qy = 0;
+        if (!std::isfinite(static_cast<double>(this->qz)))
+          this->qz = 0;
+        if (!std::isfinite(static_cast<double>(this->qw)))
+          this->qw = 1;
+
+        if (equal(this->qw, static_cast<T>(0)) &&
+            equal(this->qx, static_cast<T>(0)) &&
+            equal(this->qy, static_cast<T>(0)) &&
+            equal(this->qz, static_cast<T>(0)))
+        {
+          this->qw = 1;
+        }
+      }
+
+      /// \brief Return the X axis
+      /// \return the X axis of the vector
+      public: Vector3<T> XAxis() const
+      {
+        T fTy  = 2.0f*this->qy;
+        T fTz  = 2.0f*this->qz;
+
+        T fTwy = fTy*this->qw;
+        T fTwz = fTz*this->qw;
+        T fTxy = fTy*this->qx;
+        T fTxz = fTz*this->qx;
+        T fTyy = fTy*this->qy;
+        T fTzz = fTz*this->qz;
+
+        return Vector3<T>(1.0f-(fTyy+fTzz), fTxy+fTwz, fTxz-fTwy);
+      }
+
+      /// \brief Return the Y axis
+      /// \return the Y axis of the vector
+      public: Vector3<T> YAxis() const
+      {
+        T fTx  = 2.0f*this->qx;
+        T fTy  = 2.0f*this->qy;
+        T fTz  = 2.0f*this->qz;
+        T fTwx = fTx*this->qw;
+        T fTwz = fTz*this->qw;
+        T fTxx = fTx*this->qx;
+        T fTxy = fTy*this->qx;
+        T fTyz = fTz*this->qy;
+        T fTzz = fTz*this->qz;
+
+        return Vector3<T>(fTxy-fTwz, 1.0f-(fTxx+fTzz), fTyz+fTwx);
+      }
+
+      /// \brief Return the Z axis
+      /// \return the Z axis of the vector
+      public: Vector3<T> ZAxis() const
+      {
+        T fTx  = 2.0f*this->qx;
+        T fTy  = 2.0f*this->qy;
+        T fTz  = 2.0f*this->qz;
+        T fTwx = fTx*this->qw;
+        T fTwy = fTy*this->qw;
+        T fTxx = fTx*this->qx;
+        T fTxz = fTz*this->qx;
+        T fTyy = fTy*this->qy;
+        T fTyz = fTz*this->qy;
+
+        return Vector3<T>(fTxz+fTwy, fTyz-fTwx, 1.0f-(fTxx+fTyy));
+      }
+
+      /// \brief Round all values to _precision decimal places
+      /// \param[in] _precision the precision
+      public: void Round(int _precision)
+      {
+        this->qx = precision(this->qx, _precision);
+        this->qy = precision(this->qy, _precision);
+        this->qz = precision(this->qz, _precision);
+        this->qw = precision(this->qw, _precision);
+      }
+
+      /// \brief Dot product
+      /// \param[in] _q the other quaternion
+      /// \return the product
+      public: T Dot(const Quaternion<T> &_q) const
+      {
+        return this->qw*_q.qw + this->qx * _q.qx +
+               this->qy*_q.qy + this->qz*_q.qz;
+      }
+
+      /// \brief Spherical quadratic interpolation
+      /// given the ends and an interpolation parameter between 0 and 1
+      /// \param[in] _ft the interpolation parameter
+      /// \param[in] _rkP the beginning quaternion
+      /// \param[in] _rkA first intermediate quaternion
+      /// \param[in] _rkB second intermediate quaternion
+      /// \param[in] _rkQ the end quaternion
+      /// \param[in] _shortestPath when true, the rotation may be inverted to
+      /// get to minimize rotation
+      /// \return The result of the quadratic interpolation
+      public: static Quaternion<T> Squad(T _fT,
+                  const Quaternion<T> &_rkP, const Quaternion<T> &_rkA,
+                  const Quaternion<T> &_rkB, const Quaternion<T> &_rkQ,
+                  bool _shortestPath = false)
+      {
+        T fSlerpT = 2.0f*_fT*(1.0f-_fT);
+        Quaternion<T> kSlerpP = Slerp(_fT, _rkP, _rkQ, _shortestPath);
+        Quaternion<T> kSlerpQ = Slerp(_fT, _rkA, _rkB);
+        return Slerp(fSlerpT, kSlerpP, kSlerpQ);
+      }
+
+      /// \brief Spherical linear interpolation between 2 quaternions,
+      /// given the ends and an interpolation parameter between 0 and 1
+      /// \param[in] _ft the interpolation parameter
+      /// \param[in] _rkP the beginning quaternion
+      /// \param[in] _rkQ the end quaternion
+      /// \param[in] _shortestPath when true, the rotation may be inverted to
+      /// get to minimize rotation
+      /// \return The result of the linear interpolation
+      public: static Quaternion<T> Slerp(T _fT,
+                  const Quaternion<T> &_rkP, const Quaternion<T> &_rkQ,
+                  bool _shortestPath = false)
+      {
+        T fCos = _rkP.Dot(_rkQ);
+        Quaternion<T> rkT;
+
+        // Do we need to invert rotation?
+        if (fCos < 0.0f && _shortestPath)
+        {
+          fCos = -fCos;
+          rkT = -_rkQ;
+        }
+        else
+        {
+          rkT = _rkQ;
+        }
+
+        if (std::abs(fCos) < 1 - 1e-03)
+        {
+          // Standard case (slerp)
+          T fSin = sqrt(1 - (fCos*fCos));
+          T fAngle = atan2(fSin, fCos);
+          // FIXME: should check if (std::abs(fSin) >= 1e-3)
+          T fInvSin = 1.0f / fSin;
+          T fCoeff0 = sin((1.0f - _fT) * fAngle) * fInvSin;
+          T fCoeff1 = sin(_fT * fAngle) * fInvSin;
+          return _rkP * fCoeff0 + rkT * fCoeff1;
+        }
+        else
+        {
+          // There are two situations:
+          // 1. "rkP" and "rkQ" are very close (fCos ~= +1),
+          // so we can do a linear interpolation safely.
+          // 2. "rkP" and "rkQ" are almost inverse of each
+          // other (fCos ~= -1), there
+          // are an infinite number of possibilities interpolation.
+          // but we haven't have method to fix this case, so just use
+          // linear interpolation here.
+          Quaternion<T> t = _rkP * (1.0f - _fT) + rkT * _fT;
+          // taking the complement requires renormalisation
+          t.Normalize();
+          return t;
+        }
+      }
+
+      /// \brief Integrate quaternion for constant angular velocity vector
+      /// along specified interval `_deltaT`.
+      /// Implementation based on:
+      /// http://physicsforgames.blogspot.com/2010/02/quaternions.html
+      /// \param[in] _angularVelocity Angular velocity vector, specified in
+      /// same reference frame as base of this quaternion.
+      /// \param[in] _deltaT Time interval in seconds to integrate over.
+      /// \return Quaternion at integrated configuration.
+      public: Quaternion<T> Integrate(const Vector3<T> &_angularVelocity,
+                                      const T _deltaT) const
+      {
+        Quaternion<T> deltaQ;
+        Vector3<T> theta = _angularVelocity * _deltaT * 0.5;
+        T thetaMagSq = theta.SquaredLength();
+        T s;
+        if (thetaMagSq * thetaMagSq / 24.0 < MIN_D)
+        {
+          deltaQ.W() = 1.0 - thetaMagSq / 2.0;
+          s = 1.0 - thetaMagSq / 6.0;
+        }
+        else
+        {
+          double thetaMag = sqrt(thetaMagSq);
+          deltaQ.W() = cos(thetaMag);
+          s = sin(thetaMag) / thetaMag;
+        }
+        deltaQ.X() = theta.X() * s;
+        deltaQ.Y() = theta.Y() * s;
+        deltaQ.Z() = theta.Z() * s;
+        return deltaQ * (*this);
+      }
+
+      /// \brief Get the w component.
+      /// \return The w quaternion component.
+      public: inline const T &W() const
+      {
+        return this->qw;
+      }
+
+      /// \brief Get the x component.
+      /// \return The x quaternion component.
+      public: inline const T &X() const
+      {
+        return this->qx;
+      }
+
+      /// \brief Get the y component.
+      /// \return The y quaternion component.
+      public: inline const T &Y() const
+      {
+        return this->qy;
+      }
+
+      /// \brief Get the z component.
+      /// \return The z quaternion component.
+      public: inline const T &Z() const
+      {
+        return this->qz;
+      }
+
+
+      /// \brief Get a mutable w component.
+      /// \return The w quaternion component.
+      public: inline T &W()
+      {
+        return this->qw;
+      }
+
+      /// \brief Get a mutable x component.
+      /// \return The x quaternion component.
+      public: inline T &X()
+      {
+        return this->qx;
+      }
+
+      /// \brief Get a mutable y component.
+      /// \return The y quaternion component.
+      public: inline T &Y()
+      {
+        return this->qy;
+      }
+
+      /// \brief Get a mutable z component.
+      /// \return The z quaternion component.
+      public: inline T &Z()
+      {
+        return this->qz;
+      }
+
+      /// \brief Set the x component.
+      /// \param[in] _v The new value for the x quaternion component.
+      public: inline void X(T _v)
+      {
+        this->qx = _v;
+      }
+
+      /// \brief Set the y component.
+      /// \param[in] _v The new value for the y quaternion component.
+      public: inline void Y(T _v)
+      {
+        this->qy = _v;
+      }
+
+      /// \brief Set the z component.
+      /// \param[in] _v The new value for the z quaternion component.
+      public: inline void Z(T _v)
+      {
+        this->qz = _v;
+      }
+
+      /// \brief Set the w component.
+      /// \param[in] _v The new value for the w quaternion component.
+      public: inline void W(T _v)
+      {
+        this->qw = _v;
+      }
+
+      /// \brief Stream insertion operator
+      /// \param[in] _out output stream
+      /// \param[in] _q quaternion to output
+      /// \return the stream
+      public: friend std::ostream &operator<<(std::ostream &_out,
+                  const ignition::math::Quaternion<T> &_q)
+      {
+        Vector3<T> v(_q.Euler());
+        _out << precision(v.X(), 6) << " " << precision(v.Y(), 6) << " "
+             << precision(v.Z(), 6);
+        return _out;
+      }
+
+      /// \brief Stream extraction operator
+      /// \param[in] _in input stream
+      /// \param[in] _q Quaternion<T> to read values into
+      /// \return The istream
+      public: friend std::istream &operator>>(std::istream &_in,
+          ignition::math::Quaternion<T> &_q)
+      {
+        Angle roll, pitch, yaw;
+
+        // Skip white spaces
+        _in.setf(std::ios_base::skipws);
+        _in >> roll >> pitch >> yaw;
+
+        _q.Euler(Vector3<T>(*roll, *pitch, *yaw));
+
+        return _in;
+      }
+
+      /// \brief w value of the quaternion
+      private: T qw;
+
+      /// \brief x value of the quaternion
+      private: T qx;
+
+      /// \brief y value of the quaternion
+      private: T qy;
+
+      /// \brief z value of the quaternion
+      private: T qz;
+    };
+
+    template<typename T> const Quaternion<T>
+      Quaternion<T>::Identity(1, 0, 0, 0);
+
+    template<typename T> const Quaternion<T>
+      Quaternion<T>::Zero(0, 0, 0, 0);
+
+    typedef Quaternion<double> Quaterniond;
+    typedef Quaternion<float> Quaternionf;
+    typedef Quaternion<int> Quaternioni;
+  }
+}
+#endif
diff --git a/include/ignition/math/Rand.hh b/include/ignition/math/Rand.hh
new file mode 100644
index 0000000..6695d9d
--- /dev/null
+++ b/include/ignition/math/Rand.hh
@@ -0,0 +1,86 @@
+/*
+ * Copyright (C) 2012 Open Source Robotics Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+*/
+#ifndef IGNITION_MATH_RAND_HH_
+#define IGNITION_MATH_RAND_HH_
+
+#include <random>
+#include <cmath>
+#include <cstdint>
+#include <ignition/math/Helpers.hh>
+
+namespace ignition
+{
+  namespace math
+  {
+    /// \def GeneratorType
+    /// \brief std::mt19937
+    typedef std::mt19937 GeneratorType;
+    /// \def UniformRealDist
+    /// \brief std::uniform_real_distribution<double>
+    typedef std::uniform_real_distribution<double> UniformRealDist;
+    /// \def NormalRealDist
+    /// \brief std::normal_distribution<double>
+    typedef std::normal_distribution<double> NormalRealDist;
+    /// \def UniformIntDist
+    /// \brief std::uniform_int<int>
+    typedef std::uniform_int_distribution<int32_t> UniformIntDist;
+
+    /// \class Rand Rand.hh ignition/math/Rand.hh
+    /// \brief Random number generator class
+    class IGNITION_MATH_VISIBLE Rand
+    {
+      /// \brief Set the seed value.
+      /// \param[in] _seed The seed used to initialize the randon number
+      /// generator.
+      public: static void Seed(unsigned int _seed);
+
+      /// \brief Get the seed value.
+      /// \return The seed value used to initialize the random number
+      /// generator.
+      public: static unsigned int Seed();
+
+      /// \brief Get a double from a uniform distribution
+      /// \param[in] _min Minimum bound for the random number
+      /// \param[in] _max Maximum bound for the random number
+      public: static double DblUniform(double _min = 0, double _max = 1);
+
+      /// \brief Get a double from a normal distribution
+      /// \param[in] _mean Mean value for the distribution
+      /// \param[in] _sigma Sigma value for the distribution
+      public: static double DblNormal(double _mean = 0, double _sigma = 1);
+
+      /// \brief Get an integer from a uniform distribution
+      /// \param[in] _min Minimum bound for the random number
+      /// \param[in] _max Maximum bound for the random number
+      public: static int32_t IntUniform(int _min, int _max);
+
+      /// \brief Get an integer from a normal distribution
+      /// \param[in] _mean Mean value for the distribution
+      /// \param[in] _sigma Sigma value for the distribution
+      public: static int32_t IntNormal(int _mean, int _sigma);
+
+      /// \brief Get a mutable reference to the seed (create the static
+      /// member if it hasn't been created yet).
+      private: static uint32_t &SeedMutable();
+
+      /// \brief Get a mutable reference to the random generator (create the
+      /// static member if it hasn't been created yet).
+      private: static GeneratorType &RandGenerator();
+    };
+  }
+}
+#endif
diff --git a/include/ignition/math/RotationSpline.hh b/include/ignition/math/RotationSpline.hh
new file mode 100644
index 0000000..0f3a986
--- /dev/null
+++ b/include/ignition/math/RotationSpline.hh
@@ -0,0 +1,121 @@
+/*
+ * Copyright (C) 2012 Open Source Robotics Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+*/
+#ifndef IGNITION_MATH_ROTATIONSPLINE_HH_
+#define IGNITION_MATH_ROTATIONSPLINE_HH_
+
+#include <ignition/math/Quaternion.hh>
+
+namespace ignition
+{
+  namespace math
+  {
+    // Forward declare private data
+    class RotationSplinePrivate;
+
+    /// \class RotationSpline RotationSpline.hh ignition/math/RotationSpline.hh
+    /// \brief Spline for rotations
+    class IGNITION_MATH_VISIBLE  RotationSpline
+    {
+      /// \brief Constructor. Sets the autoCalc to true
+      public: RotationSpline();
+
+      /// \brief Destructor. Nothing is done
+      public: ~RotationSpline();
+
+      /// \brief Adds a control point to the end of the spline.
+      /// \param[in] _p control point
+      public: void AddPoint(const Quaterniond &_p);
+
+      /// \brief Gets the detail of one of the control points of the spline.
+      /// \param[in] _index the index of the control point. _index is
+      /// clamped to [0, PointCount()-1].
+      /// \remarks This point must already exist in the spline.
+      /// \return The quaternion at the specified point.
+      /// If there are no points, then a Quaterniond with a value of
+      /// [INF, INF, INF, INF] is returned.
+      public: const Quaterniond &Point(const unsigned int _index) const;
+
+      /// \brief Gets the number of control points in the spline.
+      /// \return the count
+      public: unsigned int PointCount() const;
+
+      /// \brief Clears all the points in the spline.
+      public: void Clear();
+
+      /// \brief Updates a single point in the spline.
+      /// \remarks This point must already exist in the spline.
+      /// \param[in] _index index
+      /// \param[in] _value the new control point value
+      /// \return True on success, false if _index is larger or equal than
+      /// PointCount().
+      public: bool UpdatePoint(const unsigned int _index,
+                               const Quaterniond &_value);
+
+      /// \brief Returns an interpolated point based on a parametric
+      ///        value over the whole series.
+      /// \remarks Given a t value between 0 and 1 representing the
+      ///          parametric distance along the whole length of the spline,
+      ///          this method returns an interpolated point.
+      /// \param[in] _t Parametric value.
+      /// \param[in] _useShortestPath Defines if rotation should take the
+      ///        shortest possible path
+      /// \return The rotation, or [INF, INF, INF, INF] on error. Use
+      /// Quateriond::IsFinite() to check for an error
+      public: Quaterniond Interpolate(double _t,
+                                      const bool _useShortestPath = true);
+
+      /// \brief Interpolates a single segment of the spline
+      ///        given a parametric value.
+      /// \param[in] _fromIndex The point index to treat as t = 0.
+      ///        _fromIndex + 1 is deemed to be t = 1
+      /// \param[in] _t Parametric value
+      /// \param[in] _useShortestPath Defines if rotation should take the
+      ///         shortest possible path
+      /// \return the rotation, or [INF, INF, INF, INF] on error. Use
+      /// Quateriond::IsFinite() to check for an error
+      public: Quaterniond Interpolate(const unsigned int _fromIndex,
+                  const double _t, const bool _useShortestPath = true);
+
+      /// \brief Tells the spline whether it should automatically calculate
+      ///        tangents on demand as points are added.
+      /// \remarks The spline calculates tangents at each point automatically
+      ///          based on the input points.  Normally it does this every
+      ///          time a point changes. However, if you have a lot of points
+      ///          to add in one go, you probably don't want to incur this
+      ///          overhead and would prefer to defer the calculation until
+      ///          you are finished setting all the points. You can do this
+      ///          by calling this method with a parameter of 'false'. Just
+      ///          remember to manually call the recalcTangents method when
+      ///          you are done.
+      /// \param[in] _autoCalc If true, tangents are calculated for you
+      /// whenever a point changes. If false, you must call reclacTangents to
+      /// recalculate them when it best suits.
+      public: void AutoCalculate(bool _autoCalc);
+
+      /// \brief Recalculates the tangents associated with this spline.
+      /// \remarks If you tell the spline not to update on demand by calling
+      /// setAutoCalculate(false) then you must call this after
+      /// completing your updates to the spline points.
+      public: void RecalcTangents();
+
+      /// \brief Private data pointer
+      private: RotationSplinePrivate *dataPtr;
+    };
+  }
+}
+
+#endif
diff --git a/include/ignition/math/SemanticVersion.hh b/include/ignition/math/SemanticVersion.hh
new file mode 100644
index 0000000..8f28723
--- /dev/null
+++ b/include/ignition/math/SemanticVersion.hh
@@ -0,0 +1,159 @@
+/*
+ * Copyright (C) 2016 Open Source Robotics Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+*/
+
+#ifndef IGNITION_MATH_SEMANTICVERSION_HH_
+#define IGNITION_MATH_SEMANTICVERSION_HH_
+
+#include <memory>
+#include <string>
+#include <ignition/math/Helpers.hh>
+
+namespace ignition
+{
+  namespace math
+  {
+    // Forward declare private data class
+    class SemanticVersionPrivate;
+
+    /// \class SemanticVersion SemanticVersion.hh
+    ///        ignition/math/SemanticVersion.hh
+    /// \brief Version comparison class based on Semantic Versioning 2.0.0
+    /// http://semver.org/
+    /// Compares versions and converts versions from string.
+    class IGNITION_MATH_VISIBLE SemanticVersion
+    {
+      /// \brief Default constructor. Use the Parse function to populate
+      /// an instance with version information.
+      public: SemanticVersion();
+
+      /// \brief Constructor
+      /// \param[in] _v the string version. ex: "0.3.2"
+      public: explicit SemanticVersion(const std::string &_v);
+
+      /// \brief Copy constructor
+      /// \param[in] _copy the other version
+      public: SemanticVersion(const SemanticVersion &_copy);
+
+      /// \brief Assignment operator
+      /// \param[in] _other The version to assign from.
+      /// \return The reference to this instance
+      public: SemanticVersion &operator=(const SemanticVersion &_other);
+
+      /// \brief Constructor
+      /// \param[in] _major The major number
+      /// \param[in] _minor The minor number
+      /// \param[in] _patch The patch number
+      /// \param[in] _prerelease The prerelease string
+      /// \param[in] _build The build metadata string
+      public: SemanticVersion(const unsigned int _major,
+                              const unsigned int _minor = 0,
+                              const unsigned int _patch = 0,
+                              const std::string &_prerelease = "",
+                              const std::string &_build = "");
+
+      /// \brief Destructor
+      public: ~SemanticVersion();
+
+      /// \brief Parse a version string and set the major, minor, patch
+      /// numbers, and prerelease and build strings.
+      /// \param[in] _versionStr The version string, such as "1.2.3-pr+123"
+      /// \retur True on success.
+      public: bool Parse(const std::string &_versionStr);
+
+      /// \brief Returns the version as a string
+      /// \return The semantic version string
+      public: std::string Version() const;
+
+      /// \brief Get the major number
+      /// \return The major number
+      public: unsigned int Major() const;
+
+      /// \brief Get the minor number
+      /// \return The minor number
+      public: unsigned int Minor() const;
+
+      /// \brief Get the patch number
+      /// \return The patch number
+      public: unsigned int Patch() const;
+
+      /// \brief Get the prerelease string.
+      /// \return Prelrease string, empty if a prerelease string was not
+      /// specified.
+      public: std::string Prerelease() const;
+
+      /// \brief Get the build metadata string. Build meta data is not used
+      /// when determining precedence.
+      /// \return Build metadata string, empty if a build metadata string was
+      /// not specified.
+      public: std::string Build() const;
+
+      /// \brief Less than comparison operator
+      /// \param[in] _other The other version to compare to
+      /// \return True if _other version is newer
+      public: bool operator<(const SemanticVersion &_other) const;
+
+      /// \brief Less than or equal comparison operator
+      /// \param[in] _other The other version to compare to
+      /// \return True if _other version is newer or equal
+      public: bool operator<=(const SemanticVersion &_other) const;
+
+      /// \brief Greater than comparison operator
+      /// \param[in] _other The other version to compare to
+      /// \return True if _other version is older
+      public: bool operator>(const SemanticVersion &_other) const;
+
+      /// \brief Greater than or equal comparison operator
+      /// \param[in] _other The other version to compare to
+      /// \return True if _other version is older or the same
+      public: bool operator>=(const SemanticVersion &_other) const;
+
+      /// \brief Equality comparison operator
+      /// \param[in] _other The other version to compare to
+      /// \return True if _other version is the same
+      public: bool operator==(const SemanticVersion &_other) const;
+
+      /// \brief Inequality comparison operator
+      /// \param[in] _other The other version to compare to
+      /// \return True if _other version is different
+      public: bool operator!=(const SemanticVersion &_other) const;
+
+      /// \brief Stream insertion operator
+      /// \param _out output stream
+      /// \param _v Semantic version to output
+      /// \return the stream
+      public: friend std::ostream &operator<<(std::ostream &_out,
+                                              const SemanticVersion &_v)
+      {
+        _out << _v.Version();
+        return _out;
+      }
+
+#ifdef _WIN32
+// Disable warning C4251 which is triggered by
+// std::unique_ptr
+#pragma warning(push)
+#pragma warning(disable: 4251)
+#endif
+      /// \brief Pointer to private data
+      private: std::unique_ptr<SemanticVersionPrivate> dataPtr;
+#ifdef _WIN32
+#pragma warning(pop)
+#endif
+    };
+  }
+}
+#endif
diff --git a/include/ignition/math/SignalStats.hh b/include/ignition/math/SignalStats.hh
new file mode 100644
index 0000000..eb5350d
--- /dev/null
+++ b/include/ignition/math/SignalStats.hh
@@ -0,0 +1,258 @@
+/*
+ * Copyright (C) 2015 Open Source Robotics Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+*/
+#ifndef IGNITION_MATH_SIGNALSTATS_HH_
+#define IGNITION_MATH_SIGNALSTATS_HH_
+
+#include <map>
+#include <memory>
+#include <string>
+#include <ignition/math/Helpers.hh>
+
+namespace ignition
+{
+  namespace math
+  {
+    /// \brief Forward declare private data class.
+    class SignalStatisticPrivate;
+
+    /// \class SignalStatistic SignalStats.hh ignition/math/SignalStats.hh
+    /// \brief Statistical properties of a discrete time scalar signal.
+    class IGNITION_MATH_VISIBLE SignalStatistic
+    {
+      /// \brief Constructor
+      public: SignalStatistic();
+
+      /// \brief Destructor
+      public: virtual ~SignalStatistic();
+
+      /// \brief Copy constructor
+      /// \param[in] _ss SignalStatistic to copy
+      public: SignalStatistic(const SignalStatistic &_ss);
+
+      /// \brief Get the current value of the statistical measure.
+      /// \return Current value of the statistical measure.
+      public: virtual double Value() const = 0;
+
+      /// \brief Get a short version of the name of this statistical measure.
+      /// \return Short name of the statistical measure.
+      public: virtual std::string ShortName() const = 0;
+
+      /// \brief Get number of data points in measurement.
+      /// \return Number of data points in measurement.
+      public: virtual size_t Count() const;
+
+      /// \brief Add a new sample to the statistical measure.
+      /// \param[in] _data New signal data point.
+      public: virtual void InsertData(const double _data) = 0;
+
+      /// \brief Forget all previous data.
+      public: virtual void Reset();
+
+#ifdef _WIN32
+// Disable warning C4251 which is triggered by
+// std::unique_ptr
+#pragma warning(push)
+#pragma warning(disable: 4251)
+#endif
+      /// \brief Pointer to private data.
+      protected: std::unique_ptr<SignalStatisticPrivate> dataPtr;
+#ifdef _WIN32
+#pragma warning(pop)
+#endif
+    };
+    /// \}
+
+    /// \class SignalMaximum SignalStats.hh ignition/math/SignalStats.hh
+    /// \brief Computing the maximum value of a discretely sampled signal.
+    class IGNITION_MATH_VISIBLE SignalMaximum : public SignalStatistic
+    {
+      // Documentation inherited.
+      public: virtual double Value() const;
+
+      /// \brief Get a short version of the name of this statistical measure.
+      /// \return "max"
+      public: virtual std::string ShortName() const;
+
+      // Documentation inherited.
+      public: virtual void InsertData(const double _data);
+    };
+    /// \}
+
+    /// \class SignalMean SignalStats.hh ignition/math/SignalStats.hh
+    /// \brief Computing the mean value of a discretely sampled signal.
+    class IGNITION_MATH_VISIBLE SignalMean : public SignalStatistic
+    {
+      // Documentation inherited.
+      public: virtual double Value() const;
+
+      /// \brief Get a short version of the name of this statistical measure.
+      /// \return "mean"
+      public: virtual std::string ShortName() const;
+
+      // Documentation inherited.
+      public: virtual void InsertData(const double _data);
+    };
+    /// \}
+
+    /// \class SignalMinimum SignalStats.hh ignition/math/SignalStats.hh
+    /// \brief Computing the minimum value of a discretely sampled signal.
+    class IGNITION_MATH_VISIBLE SignalMinimum : public SignalStatistic
+    {
+      // Documentation inherited.
+      public: virtual double Value() const;
+
+      /// \brief Get a short version of the name of this statistical measure.
+      /// \return "min"
+      public: virtual std::string ShortName() const;
+
+      // Documentation inherited.
+      public: virtual void InsertData(const double _data);
+    };
+    /// \}
+
+    /// \class SignalRootMeanSquare SignalStats.hh ignition/math/SignalStats.hh
+    /// \brief Computing the square root of the mean squared value
+    /// of a discretely sampled signal.
+    class IGNITION_MATH_VISIBLE SignalRootMeanSquare : public SignalStatistic
+    {
+      // Documentation inherited.
+      public: virtual double Value() const;
+
+      /// \brief Get a short version of the name of this statistical measure.
+      /// \return "rms"
+      public: virtual std::string ShortName() const;
+
+      // Documentation inherited.
+      public: virtual void InsertData(const double _data);
+    };
+    /// \}
+
+    /// \class SignalMaxAbsoluteValue SignalStats.hh
+    /// ignition/math/SignalStats.hh
+    /// \brief Computing the maximum of the absolute value
+    /// of a discretely sampled signal.
+    /// Also known as the maximum norm, infinity norm, or supremum norm.
+    class IGNITION_MATH_VISIBLE SignalMaxAbsoluteValue : public SignalStatistic
+    {
+      // Documentation inherited.
+      public: virtual double Value() const;
+
+      /// \brief Get a short version of the name of this statistical measure.
+      /// \return "maxAbs"
+      public: virtual std::string ShortName() const;
+
+      // Documentation inherited.
+      public: virtual void InsertData(const double _data);
+    };
+    /// \}
+
+    /// \class SignalVariance SignalStats.hh ignition/math/SignalStats.hh
+    /// \brief Computing the incremental variance
+    /// of a discretely sampled signal.
+    class IGNITION_MATH_VISIBLE SignalVariance : public SignalStatistic
+    {
+      // Documentation inherited.
+      public: virtual double Value() const;
+
+      /// \brief Get a short version of the name of this statistical measure.
+      /// \return "var"
+      public: virtual std::string ShortName() const;
+
+      // Documentation inherited.
+      public: virtual void InsertData(const double _data);
+    };
+    /// \}
+
+    /// \brief Forward declare private data class.
+    class SignalStatsPrivate;
+
+    /// \class SignalStats SignalStats.hh ignition/math/SignalStats.hh
+    /// \brief Collection of statistics for a scalar signal.
+    class IGNITION_MATH_VISIBLE SignalStats
+    {
+      /// \brief Constructor
+      public: SignalStats();
+
+      /// \brief Destructor
+      public: ~SignalStats();
+
+      /// \brief Copy constructor
+      /// \param[in] _ss SignalStats to copy
+      public: SignalStats(const SignalStats &_ss);
+
+      /// \brief Get number of data points in first statistic.
+      /// Technically you can have different numbers of data points
+      /// in each statistic if you call InsertStatistic after InsertData,
+      /// but this is not a recommended use case.
+      /// \return Number of data points in first statistic.
+      public: size_t Count() const;
+
+      /// \brief Get the current values of each statistical measure,
+      /// stored in a map using the short name as the key.
+      /// \return Map with short name of each statistic as key
+      /// and value of statistic as the value.
+      public: std::map<std::string, double> Map() const;
+
+      /// \brief Add a new sample to the statistical measures.
+      /// \param[in] _data New signal data point.
+      public: void InsertData(const double _data);
+
+      /// \brief Add a new type of statistic.
+      /// \param[in] _name Short name of new statistic.
+      /// Valid values include:
+      ///  "maxAbs"
+      ///  "mean"
+      ///  "rms"
+      /// \return True if statistic was successfully added,
+      /// false if name was not recognized or had already
+      /// been inserted.
+      public: bool InsertStatistic(const std::string &_name);
+
+      /// \brief Add multiple statistics.
+      /// \param[in] _names Comma-separated list of new statistics.
+      /// For example, all statistics could be added with:
+      ///  "maxAbs,mean,rms"
+      /// \return True if all statistics were successfully added,
+      /// false if any names were not recognized or had already
+      /// been inserted.
+      public: bool InsertStatistics(const std::string &_names);
+
+      /// \brief Forget all previous data.
+      public: void Reset();
+
+      /// \brief Assignment operator
+      /// \param[in] _v A SignalStats to copy
+      /// \return this
+      public: SignalStats &operator=(const SignalStats &_s);
+
+#ifdef _WIN32
+// Disable warning C4251 which is triggered by
+// std::unique_ptr
+#pragma warning(push)
+#pragma warning(disable: 4251)
+#endif
+      /// \brief Pointer to private data.
+      private: std::unique_ptr<SignalStatsPrivate> dataPtr;
+#ifdef _WIN32
+#pragma warning(pop)
+#endif
+    };
+    /// \}
+  }
+}
+#endif
+
diff --git a/include/ignition/math/SphericalCoordinates.hh b/include/ignition/math/SphericalCoordinates.hh
new file mode 100644
index 0000000..d138be5
--- /dev/null
+++ b/include/ignition/math/SphericalCoordinates.hh
@@ -0,0 +1,232 @@
+/*
+ * Copyright (C) 2012 Open Source Robotics Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+*/
+#ifndef IGNITION_MATH_SPHERICALCOORDINATES_HH_
+#define IGNITION_MATH_SPHERICALCOORDINATES_HH_
+
+#include <memory>
+#include <string>
+
+#include <ignition/math/Angle.hh>
+#include <ignition/math/Vector3.hh>
+#include <ignition/math/Helpers.hh>
+
+namespace ignition
+{
+  namespace math
+  {
+    class SphericalCoordinatesPrivate;
+
+    /// \class SphericalCoordinates SphericalCoordinates.hh commmon/common.hh
+    /// \brief Convert spherical coordinates for planetary surfaces.
+    class IGNITION_MATH_VISIBLE SphericalCoordinates
+    {
+      /// \enum SurfaceType
+      /// \brief Unique identifiers for planetary surface models.
+      public: enum SurfaceType
+              {
+                /// \brief Model of reference ellipsoid for earth, based on
+                /// WGS 84 standard. see wikipedia: World_Geodetic_System
+                EARTH_WGS84 = 1
+              };
+
+      /// \enum CoordinateType
+      /// \brief Unique identifiers for coordinate types.
+      public: enum CoordinateType
+              {
+                /// \brief Latitude, Longitude and Altitude by SurfaceType
+                SPHERICAL = 1,
+
+                /// \brief Earth centered, earth fixed Cartesian
+                ECEF = 2,
+
+                /// \brief Local tangent plane (East, North, Up)
+                GLOBAL = 3,
+
+                /// \brief Heading-adjusted tangent plane (X, Y, Z)
+                LOCAL = 4
+              };
+
+      /// \brief Constructor.
+      public: SphericalCoordinates();
+
+      /// \brief Constructor with surface type input.
+      /// \param[in] _type SurfaceType specification.
+      public: explicit SphericalCoordinates(const SurfaceType _type);
+
+      /// \brief Constructor with surface type, angle, and elevation inputs.
+      /// \param[in] _type SurfaceType specification.
+      /// \param[in] _latitude Reference latitude.
+      /// \param[in] _longitude Reference longitude.
+      /// \param[in] _elevation Reference elevation.
+      /// \param[in] _heading Heading offset.
+      public: SphericalCoordinates(const SurfaceType _type,
+                                   const ignition::math::Angle &_latitude,
+                                   const ignition::math::Angle &_longitude,
+                                   const double _elevation,
+                                   const ignition::math::Angle &_heading);
+
+      /// \brief Copy constructor.
+      /// \param[in] _sc Spherical coordinates to copy.
+      public: SphericalCoordinates(const SphericalCoordinates &_sc);
+
+      /// \brief Destructor.
+      public: ~SphericalCoordinates();
+
+      /// \brief Convert a Cartesian position vector to geodetic coordinates.
+      /// \param[in] _xyz Cartesian position vector in the world frame.
+      /// \return Cooordinates: geodetic latitude (deg), longitude (deg),
+      ///         altitude above sea level (m).
+      public: ignition::math::Vector3d SphericalFromLocalPosition(
+                  const ignition::math::Vector3d &_xyz) const;
+
+      /// \brief Convert a Cartesian velocity vector in the local frame
+      ///        to a global Cartesian frame with components East, North, Up.
+      /// \param[in] _xyz Cartesian velocity vector in the world frame.
+      /// \return Rotated vector with components (x,y,z): (East, North, Up).
+      public: ignition::math::Vector3d GlobalFromLocalVelocity(
+                  const ignition::math::Vector3d &_xyz) const;
+
+      /// \brief Convert a string to a SurfaceType.
+      /// Allowed values: ["EARTH_WGS84"].
+      /// \param[in] _str String to convert.
+      /// \return Conversion to SurfaceType.
+      public: static SurfaceType Convert(const std::string &_str);
+
+      /// \brief Get the distance between two points expressed in geographic
+      /// latitude and longitude. It assumes that both points are at sea level.
+      /// Example: _latA = 38.0016667 and _lonA = -123.0016667) represents
+      /// the point with latitude 38d 0'6.00"N and longitude 123d 0'6.00"W.
+      /// \param[in] _latA Latitude of point A.
+      /// \param[in] _longA Longitude of point A.
+      /// \param[in] _latB Latitude of point B.
+      /// \param[in] _longB Longitude of point B.
+      /// \return Distance in meters.
+      public: static double Distance(const ignition::math::Angle &_latA,
+                                     const ignition::math::Angle &_lonA,
+                                     const ignition::math::Angle &_latB,
+                                     const ignition::math::Angle &_lonB);
+
+      /// \brief Get SurfaceType currently in use.
+      /// \return Current SurfaceType value.
+      public: SurfaceType Surface() const;
+
+      /// \brief Get reference geodetic latitude.
+      /// \return Reference geodetic latitude.
+      public: ignition::math::Angle LatitudeReference() const;
+
+      /// \brief Get reference longitude.
+      /// \return Reference longitude.
+      public: ignition::math::Angle LongitudeReference() const;
+
+      /// \brief Get reference elevation in meters.
+      /// \return Reference elevation.
+      public: double ElevationReference() const;
+
+      /// \brief Get heading offset for the reference frame, expressed as
+      ///        angle from East to x-axis, or equivalently
+      ///        from North to y-axis.
+      /// \return Heading offset of reference frame.
+      public: ignition::math::Angle HeadingOffset() const;
+
+      /// \brief Set SurfaceType for planetary surface model.
+      /// \param[in] _type SurfaceType value.
+      public: void SetSurface(const SurfaceType &_type);
+
+      /// \brief Set reference geodetic latitude.
+      /// \param[in] _angle Reference geodetic latitude.
+      public: void SetLatitudeReference(const ignition::math::Angle &_angle);
+
+      /// \brief Set reference longitude.
+      /// \param[in] _angle Reference longitude.
+      public: void SetLongitudeReference(const ignition::math::Angle &_angle);
+
+      /// \brief Set reference elevation above sea level in meters.
+      /// \param[in] _elevation Reference elevation.
+      public: void SetElevationReference(const double _elevation);
+
+      /// \brief Set heading angle offset for the frame.
+      /// \param[in] _angle Heading offset for the frame.
+      public: void SetHeadingOffset(const ignition::math::Angle &_angle);
+
+      /// \brief Convert a geodetic position vector to Cartesian coordinates.
+      /// \param[in] _xyz Geodetic position in the planetary frame of reference
+      /// \return Cartesian position vector in the world frame
+      public: ignition::math::Vector3d LocalFromSphericalPosition(
+                  const ignition::math::Vector3d &_xyz) const;
+
+      /// \brief Convert a Cartesian velocity vector with components East,
+      /// North, Up to a local cartesian frame vector XYZ.
+      /// \param[in] Vector with components (x,y,z): (East, North, Up).
+      /// \return Cartesian vector in the world frame.
+      public: ignition::math::Vector3d LocalFromGlobalVelocity(
+                  const ignition::math::Vector3d &_xyz) const;
+
+      /// \brief Update coordinate transformation matrix with reference location
+      public: void UpdateTransformationMatrix();
+
+      /// \brief Convert between positions in SPHERICAL/ECEF/LOCAL/GLOBAL frame
+      /// \param[in] _pos Position vector in frame defined by parameter _in
+      /// \param[in] _in  CoordinateType for input
+      /// \param[in] _out CoordinateType for output
+      /// \return Transformed coordinate using cached orgin
+      public: ignition::math::Vector3d
+              PositionTransform(const ignition::math::Vector3d &_pos,
+                  const CoordinateType &_in, const CoordinateType &_out) const;
+
+      /// \brief Convert between velocity in SPHERICAL/ECEF/LOCAL/GLOBAL frame
+      /// \param[in] _vel Velocity vector in frame defined by parameter _in
+      /// \param[in] _in  CoordinateType for input
+      /// \param[in] _out CoordinateType for output
+      /// \return Transformed velocity vector
+      public: ignition::math::Vector3d VelocityTransform(
+                  const ignition::math::Vector3d &_vel,
+                  const CoordinateType &_in, const CoordinateType &_out) const;
+
+      /// \brief Equality operator, result = this == _sc
+      /// \param[in] _sc Spherical coordinates to check for equality
+      /// \return true if this == _sc
+      public: bool operator==(const SphericalCoordinates &_sc) const;
+
+      /// \brief Inequality
+      /// \param[in] _sc Spherical coordinates to check for inequality
+      /// \return true if this != _sc
+      public: bool operator!=(const SphericalCoordinates &_sc) const;
+
+      /// \brief Assignment operator
+      /// \param[in] _sc The spherical coordinates to copy from.
+      /// \return this
+      public: SphericalCoordinates &operator=(
+        const SphericalCoordinates &_sc);
+
+
+#ifdef _WIN32
+// Disable warning C4251 which is triggered by
+// std::unique_ptr
+#pragma warning(push)
+#pragma warning(disable: 4251)
+#endif
+      /// \internal
+      /// \brief Pointer to the private data
+      private: std::unique_ptr<SphericalCoordinatesPrivate> dataPtr;
+#ifdef _WIN32
+#pragma warning(pop)
+#endif
+    };
+    /// \}
+  }
+}
+#endif
diff --git a/include/ignition/math/Spline.hh b/include/ignition/math/Spline.hh
new file mode 100644
index 0000000..ef16ca7
--- /dev/null
+++ b/include/ignition/math/Spline.hh
@@ -0,0 +1,261 @@
+/*
+ * Copyright (C) 2012 Open Source Robotics Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+*/
+// Note: Originally cribbed from Ogre3d. Modified to implement Cardinal
+// spline and catmull-rom spline
+#ifndef IGNITION_MATH_SPLINE_HH_
+#define IGNITION_MATH_SPLINE_HH_
+
+#include <ignition/math/Helpers.hh>
+#include <ignition/math/Vector3.hh>
+
+namespace ignition
+{
+  namespace math
+  {
+    // Forward declare private classes
+    class ControlPoint;
+    class SplinePrivate;
+
+    /// \class Spline Spline.hh ignition/math/Spline.hh
+    /// \brief Splines
+    class IGNITION_MATH_VISIBLE Spline
+    {
+      /// \brief constructor
+      public: Spline();
+
+      /// \brief destructor
+      public: ~Spline();
+
+      /// \brief Sets the tension parameter.
+      /// \remarks A value of 0 results in a Catmull-Rom
+      /// spline.
+      /// \param[in] _t Tension value between 0.0 and 1.0
+      public: void Tension(double _t);
+
+      /// \brief Gets the tension value.
+      /// \return the value of the tension, which is between 0.0 and 1.0.
+      public: double Tension() const;
+
+      /// \brief Gets spline arc length.
+      /// \return arc length or INF on error.
+      public: double ArcLength() const;
+
+      /// \brief Gets spline arc length up to
+      /// a given parameter value \p _t.
+      /// \param[in] _t parameter value (range 0 to 1).
+      /// \return arc length up to \p _t or INF on error.
+      public: double ArcLength(const double _t) const;
+
+      /// \brief Gets a spline segment arc length.
+      /// \param[in] _index of the spline segment.
+      /// \param[in] _t parameter value (range 0 to 1).
+      /// \return arc length of a given segment up to
+      /// \p _t or INF on error.
+      public: double ArcLength(const unsigned int _index,
+                               const double _t) const;
+
+      /// \brief Adds a single control point to the
+      /// end of the spline.
+      /// \param[in] _p control point value to add.
+      public: void AddPoint(const Vector3d &_p);
+
+      /// \brief Adds a single control point to the end
+      /// of the spline with fixed tangent.
+      /// \param[in] _p control point value to add.
+      /// \param[in] _t tangent at \p _p.
+      public: void AddPoint(const Vector3d &_p, const Vector3d &_t);
+
+      /// \brief Adds a single control point to the end
+      /// of the spline.
+      /// \param[in] _cp control point to add.
+      /// \param[in] _fixed whether this control point
+      /// should not be subject to tangent recomputation.
+      private: void AddPoint(const ControlPoint &_cp, const bool _fixed);
+
+      /// \brief Gets the value for one of the control points
+      /// of the spline.
+      /// \param[in] _index the control point index.
+      /// \return the control point value, or [INF, INF, INF]
+      /// on error. Use Vector3d::IsFinite() to check for an error.
+      public: Vector3d Point(const unsigned int _index) const;
+
+      /// \brief Gets the tangent value for one of the control points
+      /// of the spline.
+      /// \param[in] _index the control point index.
+      /// \return the control point tangent, or [INF, INF, INF]
+      /// on error. Use Vector3d::IsFinite() to check for an error.
+      public: Vector3d Tangent(const unsigned int _index) const;
+
+      /// \brief Gets the mth derivative for one of the control points
+      /// of the spline.
+      /// \param[in] _index the control point index.
+      /// \param[in] _mth derivative order.
+      /// \return the control point mth derivative, or [INF, INF, INF]
+      ///  on error. Use Vector3d::IsFinite() to check for an error.
+      public: Vector3d MthDerivative(const unsigned int _index,
+                                     const unsigned int _mth) const;
+
+      /// \brief Gets the number of control points in the spline.
+      /// \return the count
+      public: size_t PointCount() const;
+
+      /// \brief Clears all the points in the spline.
+      public: void Clear();
+
+      /// \brief Updates a single control point value in the spline,
+      /// keeping its tangent.
+      /// \param[in] _index the control point index.
+      /// \param[in] _p the new control point value.
+      /// \return True on success.
+      public: bool UpdatePoint(const unsigned int _index,
+                               const Vector3d &_p);
+
+      /// \brief Updates a single control point in the spline, along
+      /// with its tangent.
+      /// \param[in] _index the control point index.
+      /// \param[in] _p the new control point value.
+      /// \param[in] _t the new control point tangent.
+      /// \return True on success.
+      public: bool UpdatePoint(const unsigned int _index,
+                               const Vector3d &_p,
+                               const Vector3d &_t);
+
+      /// \brief Updates a single control point in the spline.
+      /// \param[in] _index the control point index
+      /// \param[in] _cp the new control point
+      /// \param[in] _fixed whether the new control point should not be
+      /// subject to tangent recomputation
+      /// \return True on success.
+      private: bool UpdatePoint(const unsigned int _index,
+                                const ControlPoint &_cp,
+                                const bool _fixed);
+
+      /// \brief Interpolates a point on the spline
+      /// at parameter value \p _t.
+      /// \remarks Parameter value is normalized over the
+      /// whole spline arc length. Arc length is assumed
+      /// to be linear with the parameter.
+      /// \param[in] _t parameter value (range 0 to 1).
+      /// \return the interpolated point, or
+      /// [INF, INF, INF] on error. Use
+      /// Vector3d::IsFinite() to check for an error.
+      public: Vector3d Interpolate(const double _t) const;
+
+      /// \brief Interpolates a point on a segment of the spline
+      /// at parameter value \p _t.
+      /// \remarks Parameter value is normalized over the
+      /// segment arc length. Arc length is assumed
+      /// to be linear with the parameter.
+      /// \param[in] _fromIndex The point index to treat as t = 0.
+      /// fromIndex + 1 is deemed to be t = 1.
+      /// \param[in] _t parameter value (range 0 to 1).
+      /// \return the interpolated point, or [INF, INF, INF] on
+      /// error. Use Vector3d::IsFinite() to check for an error.
+      public: Vector3d Interpolate(const unsigned int _fromIndex,
+                                   const double _t) const;
+
+      /// \brief Interpolates a tangent on the spline at
+      /// parameter value \p _t.
+      /// \remarks Parameter value is normalized over the
+      /// whole spline arc length. Arc length is assumed
+      /// to be linear with the parameter.
+      /// \param[in] _t parameter value (range 0 to 1).
+      /// \return the interpolated point, or [INF, INF, INF]
+      /// on error. Use Vector3d::IsFinte() to check for an error.
+      public: Vector3d InterpolateTangent(const double _t) const;
+
+      /// \brief Interpolates the tangent on a segment of the spline
+      /// at parameter value \p _t.
+      /// \remarks Parameter value is normalized over the
+      /// segment arc length. Arc length is assumed
+      /// to be linear with the parameter.
+      /// \param[in] _fromIndex the point index to treat as t = 0.
+      /// fromIndex + 1 is deemed to be t = 1.
+      /// \param[in] _t parameter value (range 0 to 1).
+      /// \return the interpolated point, or [INF, INF, INF] on
+      /// error. Use Vector3d::IsFinte() to check for an error.
+      public: Vector3d InterpolateTangent(const unsigned int _fromIndex,
+                                          const double _t) const;
+
+      /// \brief Interpolates the mth derivative of the spline at
+      /// parameter value \p _t.
+      /// \param[in] _mth order of curve derivative to interpolate.
+      /// \param[in] _t parameter value (range 0 to 1).
+      /// \return the interpolated mth derivative, or [INF, INF, INF]
+      /// on error. Use Vector3d::IsFinite() to check for an error.
+      public: Vector3d InterpolateMthDerivative(const unsigned int _mth,
+                                                const double _1) const;
+
+      /// \brief Interpolates the mth derivative of a segment of the spline
+      /// at parameter value \p _t.
+      /// \remarks Parameter value is normalized over the segment
+      /// arc length. Arc length is assumed to be linear with the parameter.
+      /// \param[in] _fromIndex point index to treat as t = 0, fromIndex + 1
+      /// is deemed to be t = 1.
+      /// \param[in] _mth order of curve derivative to interpolate.
+      /// \param[in] _t parameter value (range 0 to 1).
+      /// \return the interpolated mth derivative, or [INF, INF, INF] on
+      /// error. Use Vector3d::IsFinite() to check for an error.
+      public: Vector3d InterpolateMthDerivative(const unsigned int _fromIndex,
+                                                const unsigned int _mth,
+                                                const double _s) const;
+
+      /// \brief Tells the spline whether it should automatically
+      ///        calculate tangents on demand as points are added.
+      /// \remarks The spline calculates tangents at each point
+      ///          automatically based on the input points. Normally it
+      ///          does this every time a point changes. However, if you
+      ///          have a lot of points to add in one go, you probably
+      ///          don't want to incur this overhead and would prefer to
+      ///          defer the calculation until you are finished setting all
+      ///          the points. You can do this by calling this method with a
+      ///          parameter of 'false'. Just remember to manually call the
+      ///          recalcTangents method when you are done.
+      /// \param[in] _autoCalc If true, tangents are calculated for you whenever
+      ///        a point changes. If false, you must call RecalcTangents to
+      ///        recalculate them when it best suits.
+      public: void AutoCalculate(bool _autoCalc);
+
+      /// \brief Recalculates the tangents associated with this spline.
+      /// \remarks If you tell the spline not to update on demand by
+      ///          calling setAutoCalculate(false) then you must call this
+      ///          after completing your updates to the spline points.
+      public: void RecalcTangents();
+
+      /// \brief Rebuilds spline segments.
+      private: void Rebuild();
+
+      /// \internal
+      /// \brief Maps \p _t parameter value over the whole spline
+      /// to the right segment (starting at point \p _index) with
+      /// the proper parameter value fraction \p _fraction.
+      /// \remarks Arc length is assumed to be linear with the parameter.
+      /// \param[in] _t parameter value over the whole spline (range 0 to 1).
+      /// \param[out] _index point index at which the segment starts.
+      /// \param[out] _fraction parameter value fraction for the given segment.
+      /// \return True on success.
+      private: bool MapToSegment(const double _t,
+                                 unsigned int &_index,
+                                 double &_fraction) const;
+
+      /// \internal
+      /// \brief Private data pointer
+      private: SplinePrivate *dataPtr;
+    };
+  }
+}
+#endif
diff --git a/include/ignition/math/Temperature.hh b/include/ignition/math/Temperature.hh
new file mode 100644
index 0000000..ffb1c80
--- /dev/null
+++ b/include/ignition/math/Temperature.hh
@@ -0,0 +1,375 @@
+/*
+ * Copyright (C) 2016 Open Source Robotics Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+*/
+#ifndef IGNITION_MATH_TEMPERATURE_HH_
+#define IGNITION_MATH_TEMPERATURE_HH_
+
+#include <iostream>
+#include <memory>
+
+#include "ignition/math/Helpers.hh"
+
+namespace ignition
+{
+  namespace math
+  {
+    // Forward declare private data class.
+    class TemperaturePrivate;
+
+    /// \brief A class that stores temperature information, and allows
+    /// conversion between different units.
+    ///
+    /// This class is mostly for convenience. It can be used to easily
+    /// convert between temperature units and encapsulate temperature values.
+    ///
+    /// The default unit is Kelvin. Most functions that accept a double
+    /// value will assume the double is Kelvin. The exceptions are a few of
+    /// the conversion functions, such as CelsiusToFahrenheit. Similarly,
+    /// most doubles that are returned will be in Kelvin.
+    ///
+    /// ## Example usage ##
+    ///
+    /// ### Convert from Kelvin to Celsius ###
+    ///
+    ///     double celsius = ignition::math::Temperature::KelvinToCelsius(2.5);
+    ///
+    /// ### Create and use a Temperature object ###
+    ///
+    ///     ignition::math::Temperature temp(123.5);
+    ///     std::cout << "Temperature in Kelvin = " << temp << std::endl;
+    ///     std::cout << "Temperature in Celsius = "
+    ///               << temp.Celsius() << std::endl;
+    ///
+    ///     temp += 100.0;
+    ///     std::cout << "Temperature + 100.0 = " << temp << "K" << std::endl;
+    ///
+    ///     ignition::math::Temperature newTemp(temp);
+    ///     newTemp += temp + 23.5;
+    ///     std::cout << "Copied the temp object and added 23.5K. newTemp = "
+    ///               << newTemp.Fahrenheit() << "F" << std::endl;
+    ///
+    class IGNITION_MATH_VISIBLE Temperature
+    {
+      /// \brief Default constructor
+      public: Temperature();
+
+      /// \brief Kelvin value constructor. This is a conversion constructor
+      /// \param[in] _temp Temperature in Kelvin
+      // cppcheck-suppress noExplicitConstructor
+      public: Temperature(const double _temp);
+
+      /// \brief Copy constructor
+      /// \param[in] _temp Temperature object to copy.
+      public: Temperature(const Temperature &_temp);
+
+      /// \brief Destructor
+      public: virtual ~Temperature();
+
+      /// \brief Convert Kelvin to Celsius
+      /// \param[in] _temp Temperature in Kelvin
+      /// \return Temperature in Celsius
+      public: static double KelvinToCelsius(const double _temp);
+
+      /// \brief Convert Kelvin to Fahrenheit
+      /// \param[in] _temp Temperature in Kelvin
+      /// \return Temperature in Fahrenheit
+      public: static double KelvinToFahrenheit(const double _temp);
+
+      /// \brief Convert Celsius to Fahrenheit
+      /// \param[in] _temp Temperature in Celsius
+      /// \return Temperature in Fahrenheit
+      public: static double CelsiusToFahrenheit(const double _temp);
+
+      /// \brief Convert Celsius to Kelvin
+      /// \param[in] _temp Temperature in Celsius
+      /// \return Temperature in Kelvin
+      public: static double CelsiusToKelvin(const double _temp);
+
+      /// \brief Convert Fahrenheit to Celsius
+      /// \param[in] _temp Temperature in Fahrenheit
+      /// \return Temperature in Celsius
+      public: static double FahrenheitToCelsius(const double _temp);
+
+      /// \brief Convert Fahrenheit to Kelvin
+      /// \param[in] _temp Temperature in Fahrenheit
+      /// \return Temperature in Kelvin
+      public: static double FahrenheitToKelvin(const double _temp);
+
+      /// \brief Set the temperature from a Kelvin value
+      /// \param[in] _temp Temperature in Kelvin
+      public: void SetKelvin(const double _temp);
+
+      /// \brief Set the temperature from a Celsius value
+      /// \param[in] _temp Temperature in Celsius
+      public: void SetCelsius(const double _temp);
+
+      /// \brief Set the temperature from a Fahrenheit value
+      /// \param[in] _temp Temperature in Fahrenheit
+      public: void SetFahrenheit(const double _temp);
+
+      /// \brief Get the temperature in Kelvin
+      /// \return Temperature in Kelvin
+      public: double Kelvin() const;
+
+      /// \brief Get the temperature in Celsius
+      /// \return Temperature in Celsius
+      public: double Celsius() const;
+
+      /// \brief Get the temperature in Fahrenheit
+      /// \return Temperature in Fahrenheit
+      public: double Fahrenheit() const;
+
+      /// \brief Accessor operator
+      /// \return Temperature in Kelvin
+      /// \sa Kelvin()
+      public: double operator()() const;
+
+      /// \brief Assignment operator
+      /// \param[in] _temp Temperature in Kelvin
+      /// \return Reference to this instance
+      public: Temperature &operator=(const double _temp);
+
+      /// \brief Assignment operator
+      /// \param[in] _temp Temperature object
+      /// \return Reference to this instance
+      public: Temperature &operator=(const Temperature &_temp);
+
+      /// \brief Addition operator
+      /// \param[in] _temp Temperature in Kelvin
+      /// \return Resulting temperature
+      public: Temperature operator+(const double _temp);
+
+      /// \brief Addition operator
+      /// \param[in] _temp Temperature object
+      /// \return Resulting temperature
+      public: Temperature operator+(const Temperature &_temp);
+
+      /// \brief Addition operator for double type.
+      /// \param[in] _t Temperature in kelvin
+      /// \param[in] _temp Temperature object
+      /// \return Resulting temperature
+      public: friend Temperature operator+(double _t, const Temperature &_temp)
+      {
+        return _t + _temp.Kelvin();
+      }
+
+      /// \brief Addition assignment operator
+      /// \param[in] _temp Temperature in Kelvin
+      /// \return Reference to this instance
+      public: const Temperature &operator+=(const double _temp);
+
+      /// \brief Addition assignment operator
+      /// \param[in] _temp Temperature object
+      /// \return Reference to this instance
+      public: const Temperature &operator+=(const Temperature &_temp);
+
+      /// \brief Subtraction operator
+      /// \param[in] _temp Temperature in Kelvin
+      /// \return Resulting temperature
+      public: Temperature operator-(const double _temp);
+
+      /// \brief Subtraction operator
+      /// \param[in] _temp Temperature object
+      /// \return Resulting temperature
+      public: Temperature operator-(const Temperature &_temp);
+
+      /// \brief Subtraction operator for double type.
+      /// \param[in] _t Temperature in kelvin
+      /// \param[in] _temp Temperature object
+      /// \return Resulting temperature
+      public: friend Temperature operator-(double _t, const Temperature &_temp)
+      {
+        return _t - _temp.Kelvin();
+      }
+
+      /// \brief Subtraction assignment operator
+      /// \param[in] _temp Temperature in Kelvin
+      /// \return Reference to this instance
+      public: const Temperature &operator-=(const double _temp);
+
+      /// \brief Subtraction assignment operator
+      /// \param[in] _temp Temperature object
+      /// \return Reference to this instance
+      public: const Temperature &operator-=(const Temperature &_temp);
+
+      /// \brief Multiplication operator
+      /// \param[in] _temp Temperature in Kelvin
+      /// \return Resulting temperature
+      public: Temperature operator*(const double _temp);
+
+      /// \brief Multiplication operator
+      /// \param[in] _temp Temperature object
+      /// \return Resulting temperature
+      public: Temperature operator*(const Temperature &_temp);
+
+      /// \brief Multiplication operator for double type.
+      /// \param[in] _t Temperature in kelvin
+      /// \param[in] _temp Temperature object
+      /// \return Resulting temperature
+      public: friend Temperature operator*(double _t, const Temperature &_temp)
+      {
+        return _t * _temp.Kelvin();
+      }
+
+      /// \brief Multiplication assignment operator
+      /// \param[in] _temp Temperature in Kelvin
+      /// \return Reference to this instance
+      public: const Temperature &operator*=(const double _temp);
+
+      /// \brief Multiplication assignment operator
+      /// \param[in] _temp Temperature object
+      /// \return Reference to this instance
+      public: const Temperature &operator*=(const Temperature &_temp);
+
+      /// \brief Division operator
+      /// \param[in] _temp Temperature in Kelvin
+      /// \return Resulting temperature
+      public: Temperature operator/(const double _temp);
+
+      /// \brief Division operator
+      /// \param[in] _temp Temperature object
+      /// \return Resulting temperature
+      public: Temperature operator/(const Temperature &_temp);
+
+      /// \brief Division operator for double type.
+      /// \param[in] _t Temperature in kelvin
+      /// \param[in] _temp Temperature object
+      /// \return Resulting temperature
+      public: friend Temperature operator/(double _t, const Temperature &_temp)
+      {
+        return _t / _temp.Kelvin();
+      }
+
+      /// \brief Division assignment operator
+      /// \param[in] _temp Temperature in Kelvin
+      /// \return Reference to this instance
+      public: const Temperature &operator/=(const double _temp);
+
+      /// \brief Division assignment operator
+      /// \param[in] _temp Temperature object
+      /// \return Reference to this instance
+      public: const Temperature &operator/=(const Temperature &_temp);
+
+      /// \brief Equal to operator
+      /// \param[in] _temp The temperature to compare
+      /// \return true if the temperatures are the same, false otherwise
+      public: bool operator==(const Temperature &_temp) const;
+
+      /// \brief Equal to operator, where the value of _temp is assumed to
+      /// be in Kelvin
+      /// \param[in] _temp The temperature (in Kelvin) to compare
+      /// \return true if the temperatures are the same, false otherwise
+      public: bool operator==(const double _temp) const;
+
+      /// \brief Inequality to operator
+      /// \param[in] _temp The temperature to compare
+      /// \return false if the temperatures are the same, true otherwise
+      public: bool operator!=(const Temperature &_temp) const;
+
+      /// \brief Inequality to operator, where the value of _temp is assumed to
+      /// be in Kelvin
+      /// \param[in] _temp The temperature (in Kelvin) to compare
+      /// \return false if the temperatures are the same, true otherwise
+      public: bool operator!=(const double _temp) const;
+
+      /// \brief Less than to operator
+      /// \param[in] _temp The temperature to compare
+      /// \return True if this is less than _temp.
+      public: bool operator<(const Temperature &_temp) const;
+
+      /// \brief Less than operator, where the value of _temp is assumed to
+      /// be in Kelvin
+      /// \param[in] _temp The temperature (in Kelvin) to compare
+      /// \return True if this is less than _temp.
+      public: bool operator<(const double _temp) const;
+
+      /// \brief Less than or equal to operator
+      /// \param[in] _temp The temperature to compare
+      /// \return True if this is less than or equal _temp.
+      public: bool operator<=(const Temperature &_temp) const;
+
+      /// \brief Less than or equal operator,
+      /// where the value of _temp is assumed to be in Kelvin
+      /// \param[in] _temp The temperature (in Kelvin) to compare
+      /// \return True if this is less than or equal to _temp.
+      public: bool operator<=(const double _temp) const;
+
+      /// \brief Greater than operator
+      /// \param[in] _temp The temperature to compare
+      /// \return True if this is greater than _temp.
+      public: bool operator>(const Temperature &_temp) const;
+
+      /// \brief Greater than operator, where the value of _temp is assumed to
+      /// be in Kelvin
+      /// \param[in] _temp The temperature (in Kelvin) to compare
+      /// \return True if this is greater than _temp.
+      public: bool operator>(const double _temp) const;
+
+      /// \brief Greater than or equal to operator
+      /// \param[in] _temp The temperature to compare
+      /// \return True if this is greater than or equal to _temp.
+      public: bool operator>=(const Temperature &_temp) const;
+
+      /// \brief Greater than equal operator,
+      /// where the value of _temp is assumed to be in Kelvin
+      /// \param[in] _temp The temperature (in Kelvin) to compare
+      /// \return True if this is greater than or equal to _temp.
+      public: bool operator>=(const double _temp) const;
+
+      /// \brief Stream insertion operator
+      /// \param[in] _out the output stream
+      /// \param[in] _temp Temperature to write to the stream
+      /// \return the output stream
+      public: friend std::ostream &operator<<(std::ostream &_out,
+                  const ignition::math::Temperature &_temp)
+              {
+                _out << _temp.Kelvin();
+                return _out;
+              }
+
+      /// \brief Stream extraction operator
+      /// \param[in] _in the input stream
+      /// \param[in] _temp Temperature to read from to the stream. Assumes
+      /// temperature value is in Kelvin.
+      /// \return the input stream
+      public: friend std::istream &operator>>(std::istream &_in,
+                  ignition::math::Temperature &_temp)
+              {
+                // Skip white spaces
+                _in.setf(std::ios_base::skipws);
+
+                double kelvin;
+                _in >> kelvin;
+
+                _temp.SetKelvin(kelvin);
+                return _in;
+              }
+
+#ifdef _WIN32
+// Disable warning C4251 which is triggered by
+// std::unique_ptr
+#pragma warning(push)
+#pragma warning(disable: 4251)
+#endif
+      /// \brief Private data pointer.
+      private: std::unique_ptr<TemperaturePrivate> dataPtr;
+#ifdef _WIN32
+#pragma warning(pop)
+#endif
+    };
+  }
+}
+#endif
diff --git a/include/ignition/math/Triangle.hh b/include/ignition/math/Triangle.hh
new file mode 100644
index 0000000..ce27979
--- /dev/null
+++ b/include/ignition/math/Triangle.hh
@@ -0,0 +1,242 @@
+/*
+ * Copyright (C) 2014 Open Source Robotics Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+*/
+#ifndef IGNITION_MATH_TRIANGLE_HH_
+#define IGNITION_MATH_TRIANGLE_HH_
+
+#include <set>
+#include <ignition/math/Helpers.hh>
+#include <ignition/math/Line2.hh>
+#include <ignition/math/Vector2.hh>
+
+namespace ignition
+{
+  namespace math
+  {
+    /// \class Triangle Triangle.hh ignition/math/Triangle.hh
+    /// \brief Triangle class and related functions.
+    template<typename T>
+    class Triangle
+    {
+      /// \brief Default constructor
+      public: Triangle() = default;
+
+      /// \brief Constructor
+      /// \param[in] _pt1 First point that defines the triangle.
+      /// \param[in] _pt2 Second point that defines the triangle.
+      /// \param[in] _pt3 Third point that defines the triangle.
+      public: Triangle(const math::Vector2<T> &_pt1,
+                       const math::Vector2<T> &_pt2,
+                       const math::Vector2<T> &_pt3)
+      {
+        this->Set(_pt1, _pt2, _pt3);
+      }
+
+      /// \brief Set one vertex of the triangle.
+      /// \param[in] _index Index of the point to set, where
+      /// 0 == first vertex, 1 == second vertex, and 2 == third vertex.
+      /// The index is clamped to the range [0, 2].
+      /// \param[in] _pt Value of the point to set.
+      public: void Set(const unsigned int _index, const math::Vector2<T> &_pt)
+      {
+        this->pts[clamp(_index, 0u, 2u)] = _pt;
+      }
+
+      /// \brief Set all vertices of the triangle.
+      /// \param[in] _pt1 First point that defines the triangle.
+      /// \param[in] _pt2 Second point that defines the triangle.
+      /// \param[in] _pt3 Third point that defines the triangle.
+      public: void Set(const math::Vector2<T> &_pt1,
+                       const math::Vector2<T> &_pt2,
+                       const math::Vector2<T> &_pt3)
+      {
+        this->pts[0] = _pt1;
+        this->pts[1] = _pt2;
+        this->pts[2] = _pt3;
+      }
+
+      /// \brief Get whether this triangle is valid, based on triangle
+      /// inequality: the sum of the lengths of any two sides must be greater
+      /// than the length of the remaining side.
+      /// \return True if the triangle inequality holds
+      public: bool Valid() const
+      {
+        T a = this->Side(0).Length();
+        T b = this->Side(1).Length();
+        T c = this->Side(2).Length();
+        return (a+b) > c && (b+c) > a && (c+a) > b;
+      }
+
+      /// \brief Get a line segment for one side of the triangle.
+      /// \param[in] _index Index of the side to retreive, where
+      /// 0 == Line2(pt1, pt2),
+      /// 1 == Line2(pt2, pt3),
+      /// 2 == Line2(pt3, pt1)
+      /// The index is clamped to the range [0, 2]
+      /// \return Line segment of the requested side.
+      public: Line2<T> Side(const unsigned int _index) const
+      {
+        if (_index == 0)
+          return Line2<T>(this->pts[0], this->pts[1]);
+        else if (_index == 1)
+          return Line2<T>(this->pts[1], this->pts[2]);
+        else
+          return Line2<T>(this->pts[2], this->pts[0]);
+      }
+
+      /// \brief Check if this triangle completely contains the given line
+      /// segment.
+      /// \param[in] _line Line to check.
+      /// \return True if the line's start and end points are both inside
+      /// this triangle.
+      public: bool Contains(const Line2<T> &_line) const
+      {
+        return this->Contains(_line[0]) && this->Contains(_line[1]);
+      }
+
+      /// \brief Get whether this triangle contains the given point.
+      /// \param[in] _pt Point to check.
+      /// \return True if the point is inside or on the triangle.
+      public: bool Contains(const math::Vector2<T> &_pt) const
+      {
+        // Compute vectors
+        math::Vector2<T> v0 = this->pts[2] -this->pts[0];
+        math::Vector2<T> v1 = this->pts[1] -this->pts[0];
+        math::Vector2<T> v2 = _pt - this->pts[0];
+
+        // Compute dot products
+        double dot00 = v0.Dot(v0);
+        double dot01 = v0.Dot(v1);
+        double dot02 = v0.Dot(v2);
+        double dot11 = v1.Dot(v1);
+        double dot12 = v1.Dot(v2);
+
+        // Compute barycentric coordinates
+        double invDenom = 1.0 / (dot00 * dot11 - dot01 * dot01);
+        double u = (dot11 * dot02 - dot01 * dot12) * invDenom;
+        double v = (dot00 * dot12 - dot01 * dot02) * invDenom;
+
+        // Check if point is in triangle
+        return (u >= 0) && (v >= 0) && (u + v <= 1);
+      }
+
+      /// \brief Get whether the given line intersects this triangle.
+      /// \param[in] _line Line to check.
+      /// \param[out] _ipt1 Return value of the first intersection point,
+      /// only valid if the return value of the function is true.
+      /// \param[out] _ipt2 Return value of the second intersection point,
+      /// only valid if the return value of the function is true.
+      /// \return True if the given line intersects this triangle.
+      public: bool Intersects(const Line2<T> &_line,
+                              math::Vector2<T> &_ipt1,
+                              math::Vector2<T> &_ipt2) const
+      {
+        if (this->Contains(_line))
+        {
+          _ipt1 = _line[0];
+          _ipt2 = _line[1];
+          return true;
+        }
+
+        Line2<T> line1(this->pts[0], this->pts[1]);
+        Line2<T> line2(this->pts[1], this->pts[2]);
+        Line2<T> line3(this->pts[2], this->pts[0]);
+
+        math::Vector2<T> pt;
+        std::set<math::Vector2<T> > points;
+
+        if (line1.Intersect(_line, pt))
+          points.insert(pt);
+
+        if (line2.Intersect(_line, pt))
+          points.insert(pt);
+
+        if (line3.Intersect(_line, pt))
+          points.insert(pt);
+
+        if (points.empty())
+        {
+          return false;
+        }
+        else if (points.size() == 1)
+        {
+          auto iter = points.begin();
+
+          _ipt1 = *iter;
+          if (this->Contains(_line[0]))
+            _ipt2 = _line[0];
+          else
+          {
+            _ipt2 = _line[1];
+          }
+        }
+        else
+        {
+          auto iter = points.begin();
+          _ipt1 = *(iter++);
+          _ipt2 = *iter;
+        }
+
+        return true;
+      }
+
+      /// \brief Get the length of the triangle's perimeter.
+      /// \return Sum of the triangle's line segments.
+      public: T Perimeter() const
+      {
+        return this->Side(0).Length() + this->Side(1).Length() +
+               this->Side(2).Length();
+      }
+
+      /// \brief Get the area of this triangle.
+      /// \return Triangle's area.
+      public: double Area() const
+      {
+        double s = this->Perimeter() / 2.0;
+        T a = this->Side(0).Length();
+        T b = this->Side(1).Length();
+        T c = this->Side(2).Length();
+
+        // Heron's formula
+        // http://en.wikipedia.org/wiki/Heron%27s_formula
+        return sqrt(s * (s-a) * (s-b) * (s-c));
+      }
+
+      /// \brief Get one of points that define the triangle.
+      /// \param[in] _index The index, where 0 == first vertex,
+      /// 1 == second vertex, and 2 == third vertex.
+      /// The index is clamped to the range [0, 2]
+      /// \return The point specified by _index.
+      public: math::Vector2<T> operator[](const size_t _index) const
+      {
+        return this->pts[clamp(_index, IGN_ZERO_SIZE_T, IGN_TWO_SIZE_T)];
+      }
+
+      /// The points of the triangle
+      private: math::Vector2<T> pts[3];
+    };
+
+    /// Integer specialization of the Triangle class.
+    typedef Triangle<int> Trianglei;
+
+    /// Double specialization of the Triangle class.
+    typedef Triangle<double> Triangled;
+
+    /// Float specialization of the Triangle class.
+    typedef Triangle<float> Trianglef;
+  }
+}
+#endif
diff --git a/include/ignition/math/Triangle3.hh b/include/ignition/math/Triangle3.hh
new file mode 100644
index 0000000..12a02af
--- /dev/null
+++ b/include/ignition/math/Triangle3.hh
@@ -0,0 +1,278 @@
+/*
+ * Copyright (C) 2016 Open Source Robotics Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+*/
+#ifndef IGNITION_MATH_TRIANGLE3_HH_
+#define IGNITION_MATH_TRIANGLE3_HH_
+
+#include <ignition/math/Helpers.hh>
+#include <ignition/math/Line3.hh>
+#include <ignition/math/Plane.hh>
+#include <ignition/math/Vector3.hh>
+
+namespace ignition
+{
+  namespace math
+  {
+    /// \class Triangle3 Triangle3.hh ignition/math/Triangle3.hh
+    /// \brief A 3-dimensional triangle and related functions.
+    template<typename T>
+    class Triangle3
+    {
+      /// \brief Default constructor
+      public: Triangle3() = default;
+
+      /// \brief Constructor.
+      ///
+      /// Keep in mind that the triangle normal
+      /// is determined by the order of these vertices. Search
+      /// the internet for "triangle winding" for more information.
+      /// \param[in] _pt1 First point that defines the triangle.
+      /// \param[in] _pt2 Second point that defines the triangle.
+      /// \param[in] _pt3 Third point that defines the triangle.
+      public: Triangle3(const Vector3<T> &_pt1,
+                        const Vector3<T> &_pt2,
+                        const Vector3<T> &_pt3)
+      {
+        this->Set(_pt1, _pt2, _pt3);
+      }
+
+      /// \brief Set one vertex of the triangle.
+      ///
+      /// Keep in mind that the triangle normal
+      /// is determined by the order of these vertices. Search
+      /// the internet for "triangle winding" for more information.
+      ///
+      /// \param[in] _index Index of the point to set. _index is clamped
+      /// to the range [0,2].
+      /// \param[in] _pt Value of the point to set.
+      public: void Set(const unsigned int _index, const Vector3<T> &_pt)
+      {
+        this->pts[clamp(_index, 0u, 2u)] = _pt;
+      }
+
+      /// \brief Set all vertices of the triangle.
+      ///
+      /// Keep in mind that the triangle normal
+      /// is determined by the order of these vertices. Search
+      /// the internet for "triangle winding" for more information.
+      ///
+      /// \param[in] _pt1 First point that defines the triangle.
+      /// \param[in] _pt2 Second point that defines the triangle.
+      /// \param[in] _pt3 Third point that defines the triangle.
+      public: void Set(const Vector3<T> &_pt1,
+                       const Vector3<T> &_pt2,
+                       const Vector3<T> &_pt3)
+      {
+        this->pts[0] = _pt1;
+        this->pts[1] = _pt2;
+        this->pts[2] = _pt3;
+      }
+
+      /// \brief Get whether this triangle is valid, based on triangle
+      /// inequality: the sum of the lengths of any two sides must be greater
+      /// than the length of the remaining side.
+      /// \return True if the triangle inequality holds
+      public: bool Valid() const
+      {
+        T a = this->Side(0).Length();
+        T b = this->Side(1).Length();
+        T c = this->Side(2).Length();
+        return (a+b) > c && (b+c) > a && (c+a) > b;
+      }
+
+      /// \brief Get a line segment for one side of the triangle.
+      /// \param[in] _index Index of the side to retrieve, where
+      /// 0 == Line3(pt1, pt2),
+      /// 1 == Line3(pt2, pt3),
+      /// 2 == Line3(pt3, pt1).
+      /// _index is clamped to the range [0,2].
+      /// \return Line segment of the requested side.
+      public: Line3<T> Side(const unsigned int _index) const
+      {
+        if (_index == 0)
+          return Line3<T>(this->pts[0], this->pts[1]);
+        else if (_index == 1)
+          return Line3<T>(this->pts[1], this->pts[2]);
+        else
+          return Line3<T>(this->pts[2], this->pts[0]);
+      }
+
+      /// \brief Check if this triangle completely contains the given line
+      /// segment.
+      /// \param[in] _line Line to check.
+      /// \return True if the line's start and end points are both inside
+      /// this triangle.
+      public: bool Contains(const Line3<T> &_line) const
+      {
+        return this->Contains(_line[0]) && this->Contains(_line[1]);
+      }
+
+      /// \brief Get whether this triangle contains the given point.
+      /// \param[in] _pt Point to check.
+      /// \return True if the point is inside or on the triangle.
+      public: bool Contains(const Vector3<T> &_pt) const
+      {
+        // Make sure the point is on the same plane as the triangle
+        if (Planed(this->Normal()).Side(_pt) == Planed::NO_SIDE)
+        {
+          Vector3d v0 = this->pts[2] - this->pts[0];
+          Vector3d v1 = this->pts[1] - this->pts[0];
+          Vector3d v2 = _pt - this->pts[0];
+
+          double dot00 = v0.Dot(v0);
+          double dot01 = v0.Dot(v1);
+          double dot02 = v0.Dot(v2);
+          double dot11 = v1.Dot(v1);
+          double dot12 = v1.Dot(v2);
+
+          // Compute barycentric coordinates
+          double invDenom = 1.0 / (dot00 * dot11 - dot01 * dot01);
+          double u = (dot11 * dot02 - dot01 * dot12) * invDenom;
+          double v = (dot00 * dot12 - dot01 * dot02) * invDenom;
+
+          // Check if point is in triangle
+          return (u >= 0) && (v >= 0) && (u + v <= 1);
+        }
+        else
+        {
+          return false;
+        }
+      }
+
+      /// \brief Get the triangle's normal vector.
+      /// \return The normal vector for the triangle.
+      public: Vector3d Normal() const
+      {
+         return Vector3d::Normal(this->pts[0], this->pts[1], this->pts[2]);
+      }
+
+      /// \brief Get whether the given line intersects an edge of this triangle.
+      ///
+      /// The returned intersection point is one of:
+      ///
+      /// * If the line is coplanar with the triangle:
+      ///   * The point on the closest edge of the triangle that the line
+      ///     intersects.
+      ///   OR
+      ///   * The first point on the line, if the line is completely contained
+      /// * If the line is not coplanar, the point on the triangle that the
+      ///   line intersects.
+      ///
+      /// \param[in] _line Line to check.
+      /// \param[out] _ipt1 Return value of the first intersection point,
+      /// only valid if the return value of the function is true.
+      /// \return True if the given line intersects this triangle.
+      public: bool Intersects(const Line3<T> &_line, Vector3<T> &_ipt1) const
+      {
+        // Triangle normal
+        Vector3d norm = this->Normal();
+
+        // Ray direction to intersect with triangle
+        Vector3d dir = (_line[1] - _line[0]).Normalize();
+
+        double denom = norm.Dot(dir);
+
+        // Handle the case when the line is not co-planar with the triangle
+        if (!math::equal(denom, 0.0))
+        {
+          // Distance from line start to triangle intersection
+          double intersection =
+            -norm.Dot(_line[0] - this->pts[0]) / denom;
+
+          // Make sure the ray intersects the triangle
+          if (intersection < 1.0 || intersection > _line.Length())
+            return false;
+
+          // Return point of intersection
+          _ipt1 = _line[0] + (dir * intersection);
+
+          return true;
+        }
+        // Line co-planar with triangle
+        else
+        {
+          // If the line is completely inside the triangle
+          if (this->Contains(_line))
+          {
+            _ipt1 = _line[0];
+            return true;
+          }
+          // If the line intersects the first side
+          else if (_line.Intersect(this->Side(0), _ipt1))
+          {
+            return true;
+          }
+          // If the line intersects the second side
+          else if (_line.Intersect(this->Side(1), _ipt1))
+          {
+            return true;
+          }
+          // If the line intersects the third side
+          else if (_line.Intersect(this->Side(2), _ipt1))
+          {
+            return true;
+          }
+        }
+
+        return false;
+      }
+
+      /// \brief Get the length of the triangle's perimeter.
+      /// \return Sum of the triangle's line segments.
+      public: T Perimeter() const
+      {
+        return this->Side(0).Length() + this->Side(1).Length() +
+               this->Side(2).Length();
+      }
+
+      /// \brief Get the area of this triangle.
+      /// \return Triangle's area.
+      public: double Area() const
+      {
+        double s = this->Perimeter() / 2.0;
+        T a = this->Side(0).Length();
+        T b = this->Side(1).Length();
+        T c = this->Side(2).Length();
+
+        // Heron's formula
+        // http://en.wikipedia.org/wiki/Heron%27s_formula
+        return sqrt(s * (s-a) * (s-b) * (s-c));
+      }
+
+      /// \brief Get one of points that define the triangle.
+      /// \param[in] _index: 0, 1, or 2. _index is clamped to the range
+      /// [0,2].
+      /// \return The triangle point at _index.
+      public: Vector3<T> operator[](const size_t _index) const
+      {
+        return this->pts[clamp(_index, IGN_ZERO_SIZE_T, IGN_TWO_SIZE_T)];
+      }
+
+      /// The points of the triangle
+      private: Vector3<T> pts[3];
+    };
+
+    /// \brief Integer specialization of the Triangle class.
+    typedef Triangle3<int> Triangle3i;
+
+    /// \brief Double specialization of the Triangle class.
+    typedef Triangle3<double> Triangle3d;
+
+    /// \brief Float specialization of the Triangle class.
+    typedef Triangle3<float> Triangle3f;
+  }
+}
+#endif
diff --git a/include/ignition/math/Vector2.hh b/include/ignition/math/Vector2.hh
new file mode 100644
index 0000000..96a27aa
--- /dev/null
+++ b/include/ignition/math/Vector2.hh
@@ -0,0 +1,478 @@
+/*
+ * Copyright (C) 2012 Open Source Robotics Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+*/
+#ifndef IGNITION_MATH_VECTOR2_HH_
+#define IGNITION_MATH_VECTOR2_HH_
+
+#include <ignition/math/Helpers.hh>
+
+namespace ignition
+{
+  namespace math
+  {
+    /// \class Vector2 Vector2.hh ignition/math/Vector2.hh
+    /// \brief Two dimensional (x, y) vector.
+    template<typename T>
+    class Vector2
+    {
+      /// \brief math::Vector2(0, 0)
+      public: static const Vector2<T> Zero;
+
+      /// \brief math::Vector2(1, 1)
+      public: static const Vector2<T> One;
+
+      /// \brief Default Constructor
+      public: Vector2()
+      {
+        this->data[0] = 0;
+        this->data[1] = 0;
+      }
+
+      /// \brief Constructor
+      /// \param[in] _x value along x
+      /// \param[in] _y value along y
+      public: Vector2(const T &_x, const T &_y)
+      {
+        this->data[0] = _x;
+        this->data[1] = _y;
+      }
+
+      /// \brief Copy constructor
+      /// \param[in] _v the value
+      public: Vector2(const Vector2<T> &_v)
+      {
+        this->data[0] = _v[0];
+        this->data[1] = _v[1];
+      }
+
+      /// \brief Destructor
+      public: virtual ~Vector2() {}
+
+      /// \brief Calc distance to the given point
+      /// \param[in] _pt The point to measure to
+      /// \return the distance
+      public: double Distance(const Vector2 &_pt) const
+      {
+        return sqrt((this->data[0]-_pt[0])*(this->data[0]-_pt[0]) +
+                    (this->data[1]-_pt[1])*(this->data[1]-_pt[1]));
+      }
+
+      /// \brief Returns the length (magnitude) of the vector
+      /// \return The length
+      public: T Length() const
+      {
+        return sqrt(this->SquaredLength());
+      }
+
+      /// \brief Returns the square of the length (magnitude) of the vector
+      /// \return The squared length
+      public: T SquaredLength() const
+      {
+        return std::pow(this->data[0], 2)
+             + std::pow(this->data[1], 2);
+      }
+
+      /// \brief Normalize the vector length
+      public: void Normalize()
+      {
+        double d = this->Length();
+
+        if (!equal<T>(d, static_cast<T>(0.0)))
+        {
+          this->data[0] /= d;
+          this->data[1] /= d;
+        }
+      }
+
+      /// \brief Set the contents of the vector
+      /// \param[in] _x value along x
+      /// \param[in] _y value along y
+      public: void Set(T _x, T _y)
+      {
+        this->data[0] = _x;
+        this->data[1] = _y;
+      }
+
+      /// \brief Get the dot product of this vector and _v
+      /// \param[in] _v the vector
+      /// \return The dot product
+      public: T Dot(const Vector2<T> &_v) const
+      {
+        return (this->data[0] * _v[0]) + (this->data[1] * _v[1]);
+      }
+
+      /// \brief Assignment operator
+      /// \param[in] _v a value for x and y element
+      /// \return this
+      public: Vector2 &operator=(const Vector2 &_v)
+      {
+        this->data[0] = _v[0];
+        this->data[1] = _v[1];
+
+        return *this;
+      }
+
+      /// \brief Assignment operator
+      /// \param[in] _v the value for x and y element
+      /// \return this
+      public: const Vector2 &operator=(T _v)
+      {
+        this->data[0] = _v;
+        this->data[1] = _v;
+
+        return *this;
+      }
+
+      /// \brief Addition operator
+      /// \param[in] _v vector to add
+      /// \return sum vector
+      public: Vector2 operator+(const Vector2 &_v) const
+      {
+        return Vector2(this->data[0] + _v[0], this->data[1] + _v[1]);
+      }
+
+      /// \brief Addition assignment operator
+      /// \param[in] _v the vector to add
+      // \return this
+      public: const Vector2 &operator+=(const Vector2 &_v)
+      {
+        this->data[0] += _v[0];
+        this->data[1] += _v[1];
+
+        return *this;
+      }
+
+      /// \brief Addition operators
+      /// \param[in] _s the scalar addend
+      /// \return sum vector
+      public: inline Vector2<T> operator+(const T _s) const
+      {
+        return Vector2<T>(this->data[0] + _s,
+                          this->data[1] + _s);
+      }
+
+      /// \brief Addition operators
+      /// \param[in] _s the scalar addend
+      /// \param[in] _v input vector
+      /// \return sum vector
+      public: friend inline Vector2<T> operator+(const T _s,
+                                                 const Vector2<T> &_v)
+      {
+        return _v + _s;
+      }
+
+      /// \brief Addition assignment operator
+      /// \param[in] _s scalar addend
+      /// \return this
+      public: const Vector2<T> &operator+=(const T _s)
+      {
+        this->data[0] += _s;
+        this->data[1] += _s;
+
+        return *this;
+      }
+
+      /// \brief Negation operator
+      /// \return negative of this vector
+      public: inline Vector2 operator-() const
+      {
+        return Vector2(-this->data[0], -this->data[1]);
+      }
+
+      /// \brief Subtraction operator
+      /// \param[in] _v the vector to substract
+      /// \return the subtracted vector
+      public: Vector2 operator-(const Vector2 &_v) const
+      {
+        return Vector2(this->data[0] - _v[0], this->data[1] - _v[1]);
+      }
+
+      /// \brief Subtraction assignment operator
+      /// \param[in] _v the vector to substract
+      /// \return this
+      public: const Vector2 &operator-=(const Vector2 &_v)
+      {
+        this->data[0] -= _v[0];
+        this->data[1] -= _v[1];
+
+        return *this;
+      }
+
+      /// \brief Subtraction operators
+      /// \param[in] _s the scalar subtrahend
+      /// \return difference vector
+      public: inline Vector2<T> operator-(const T _s) const
+      {
+        return Vector2<T>(this->data[0] - _s,
+                          this->data[1] - _s);
+      }
+
+      /// \brief Subtraction operators
+      /// \param[in] _s the scalar minuend
+      /// \param[in] _v vector subtrahend
+      /// \return difference vector
+      public: friend inline Vector2<T> operator-(const T _s,
+                                                 const Vector2<T> &_v)
+      {
+        return {_s - _v.X(), _s - _v.Y()};
+      }
+
+      /// \brief Subtraction assignment operator
+      /// \param[in] _s scalar subtrahend
+      /// \return this
+      public: const Vector2<T> &operator-=(T _s)
+      {
+        this->data[0] -= _s;
+        this->data[1] -= _s;
+
+        return *this;
+      }
+
+      /// \brief Division operator
+      /// \remarks this is an element wise division
+      /// \param[in] _v a vector
+      /// \result a result
+      public: const Vector2 operator/(const Vector2 &_v) const
+      {
+        return Vector2(this->data[0] / _v[0], this->data[1] / _v[1]);
+      }
+
+      /// \brief Division operator
+      /// \remarks this is an element wise division
+      /// \param[in] _v a vector
+      /// \return this
+      public: const Vector2 &operator/=(const Vector2 &_v)
+      {
+        this->data[0] /= _v[0];
+        this->data[1] /= _v[1];
+
+        return *this;
+      }
+
+      /// \brief Division operator
+      /// \param[in] _v the value
+      /// \return a vector
+      public: const Vector2 operator/(T _v) const
+      {
+        return Vector2(this->data[0] / _v, this->data[1] / _v);
+      }
+
+      /// \brief Division operator
+      /// \param[in] _v the divisor
+      /// \return a vector
+      public: const Vector2 &operator/=(T _v)
+      {
+        this->data[0] /= _v;
+        this->data[1] /= _v;
+
+        return *this;
+      }
+
+      /// \brief Multiplication operators
+      /// \param[in] _v the vector
+      /// \return the result
+      public: const Vector2 operator*(const Vector2 &_v) const
+      {
+        return Vector2(this->data[0] * _v[0], this->data[1] * _v[1]);
+      }
+
+      /// \brief Multiplication assignment operator
+      /// \remarks this is an element wise multiplication
+      /// \param[in] _v the vector
+      /// \return this
+      public: const Vector2 &operator*=(const Vector2 &_v)
+      {
+        this->data[0] *= _v[0];
+        this->data[1] *= _v[1];
+
+        return *this;
+      }
+
+      /// \brief Multiplication operators
+      /// \param[in] _v the scaling factor
+      /// \return a scaled vector
+      public: const Vector2 operator*(T _v) const
+      {
+        return Vector2(this->data[0] * _v, this->data[1] * _v);
+      }
+
+      /// \brief Scalar left multiplication operators
+      /// \param[in] _s the scaling factor
+      /// \param[in] _v the vector to scale
+      /// \return a scaled vector
+      public: friend inline const Vector2 operator*(const T _s,
+                                                    const Vector2 &_v)
+      {
+        return Vector2(_v * _s);
+      }
+
+      /// \brief Multiplication assignment operator
+      /// \param[in] _v the scaling factor
+      /// \return a scaled vector
+      public: const Vector2 &operator*=(T _v)
+      {
+        this->data[0] *= _v;
+        this->data[1] *= _v;
+
+        return *this;
+      }
+
+      /// \brief Equality test with tolerance.
+      /// \param[in] _v the vector to compare to
+      /// \param[in] _tol equality tolerance.
+      /// \return true if the elements of the vectors are equal within
+      /// the tolerence specified by _tol.
+      public: bool Equal(const Vector2 &_v, const T &_tol) const
+      {
+        return equal<T>(this->data[0], _v[0], _tol)
+            && equal<T>(this->data[1], _v[1], _tol);
+      }
+
+      /// \brief Equal to operator
+      /// \param[in] _v the vector to compare to
+      /// \return true if the elements of the 2 vectors are equal within
+      /// a tolerence (1e-6)
+      public: bool operator==(const Vector2 &_v) const
+      {
+        return this->Equal(_v, static_cast<T>(1e-6));
+      }
+
+      /// \brief Not equal to operator
+      /// \return true if elements are of diffent values (tolerence 1e-6)
+      public: bool operator!=(const Vector2 &_v) const
+      {
+        return !(*this == _v);
+      }
+
+      /// \brief See if a point is finite (e.g., not nan)
+      /// \return true if finite, false otherwise
+      public: bool IsFinite() const
+      {
+        // std::isfinite works with floating point values,
+        // need to explicit cast to avoid ambiguity in vc++.
+        return std::isfinite(static_cast<double>(this->data[0])) &&
+               std::isfinite(static_cast<double>(this->data[1]));
+      }
+
+      /// \brief Array subscript operator
+      /// \param[in] _index The index, where 0 == x and 1 == y.
+      /// The index is clamped to the range [0,1].
+      public: T &operator[](const std::size_t _index)
+      {
+        return this->data[clamp(_index, IGN_ZERO_SIZE_T, IGN_ONE_SIZE_T)];
+      }
+
+      /// \brief Const-qualified array subscript operator
+      /// \param[in] _index The index, where 0 == x and 1 == y.
+      /// The index is clamped to the range [0,1].
+      public: T operator[](const std::size_t _index) const
+      {
+        return this->data[clamp(_index, IGN_ZERO_SIZE_T, IGN_ONE_SIZE_T)];
+      }
+
+      /// \brief Return the x value.
+      /// \return Value of the X component.
+      public: inline T X() const
+      {
+        return this->data[0];
+      }
+
+      /// \brief Return the y value.
+      /// \return Value of the Y component.
+      public: inline T Y() const
+      {
+        return this->data[1];
+      }
+
+      /// \brief Return a mutable x value.
+      /// \return Value of the X component.
+      public: inline T &X()
+      {
+        return this->data[0];
+      }
+
+      /// \brief Return a mutable y value.
+      /// \return Value of the Y component.
+      public: inline T &Y()
+      {
+        return this->data[1];
+      }
+
+      /// \brief Set the x value.
+      /// \param[in] _v Value for the x component.
+      public: inline void X(const T &_v)
+      {
+        this->data[0] = _v;
+      }
+
+      /// \brief Set the y value.
+      /// \param[in] _v Value for the y component.
+      public: inline void Y(const T &_v)
+      {
+        this->data[1] = _v;
+      }
+
+      /// \brief Stream extraction operator
+      /// \param[in] _out output stream
+      /// \param[in] _pt Vector2 to output
+      /// \return The stream
+      public: friend std::ostream
+      &operator<<(std::ostream &_out, const Vector2<T> &_pt)
+      {
+        _out << _pt[0] << " " << _pt[1];
+        return _out;
+      }
+
+      /// \brief Less than operator.
+      /// \param[in] _pt Vector to compare.
+      /// \return True if this vector's first or second value is less than
+      /// the given vector's first or second value.
+      public: bool operator<(const Vector2<T> &_pt) const
+      {
+        return this->data[0] < _pt[0] || this->data[1] < _pt[1];
+      }
+
+      /// \brief Stream extraction operator
+      /// \param[in] _in input stream
+      /// \param[in] _pt Vector2 to read values into
+      /// \return The stream
+      public: friend std::istream
+      &operator>>(std::istream &_in, Vector2<T> &_pt)
+      {
+        T x, y;
+        // Skip white spaces
+        _in.setf(std::ios_base::skipws);
+        _in >> x >> y;
+        _pt.Set(x, y);
+        return _in;
+      }
+
+      /// \brief The x and y values.
+      private: T data[2];
+    };
+
+    template<typename T>
+    const Vector2<T> Vector2<T>::Zero(0, 0);
+
+    template<typename T>
+    const Vector2<T> Vector2<T>::One(1, 1);
+
+    typedef Vector2<int> Vector2i;
+    typedef Vector2<double> Vector2d;
+    typedef Vector2<float> Vector2f;
+  }
+}
+#endif
diff --git a/include/ignition/math/Vector3.hh b/include/ignition/math/Vector3.hh
new file mode 100644
index 0000000..698bce0
--- /dev/null
+++ b/include/ignition/math/Vector3.hh
@@ -0,0 +1,757 @@
+/*
+ * Copyright (C) 2014 Open Source Robotics Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+*/
+#ifndef IGNITION_MATH_VECTOR3_HH_
+#define IGNITION_MATH_VECTOR3_HH_
+
+#include <iostream>
+#include <fstream>
+#include <cmath>
+#include <algorithm>
+
+#include <ignition/math/Helpers.hh>
+
+namespace ignition
+{
+  namespace math
+  {
+    /// \class Vector3 Vector3.hh ignition/math/Vector3.hh
+    /// \brief The Vector3 class represents the generic vector containing 3
+    /// elements.  Since it's commonly used to keep coordinate system
+    /// related information, its elements are labeled by x, y, z.
+    template<typename T>
+    class Vector3
+    {
+      /// \brief math::Vector3(0, 0, 0)
+      public: static const Vector3 Zero;
+
+      /// \brief math::Vector3(1, 1, 1)
+      public: static const Vector3 One;
+
+      /// \brief math::Vector3(1, 0, 0)
+      public: static const Vector3 UnitX;
+
+      /// \brief math::Vector3(0, 1, 0)
+      public: static const Vector3 UnitY;
+
+      /// \brief math::Vector3(0, 0, 1)
+      public: static const Vector3 UnitZ;
+
+      /// \brief Constructor
+      public: Vector3()
+      {
+        this->data[0] = 0;
+        this->data[1] = 0;
+        this->data[2] = 0;
+      }
+
+      /// \brief Constructor
+      /// \param[in] _x value along x
+      /// \param[in] _y value along y
+      /// \param[in] _z value along z
+      public: Vector3(const T &_x, const T &_y, const T &_z)
+      {
+        this->data[0] = _x;
+        this->data[1] = _y;
+        this->data[2] = _z;
+      }
+
+      /// \brief Copy constructor
+      /// \param[in] _v a vector
+      public: Vector3(const Vector3<T> &_v)
+      {
+        this->data[0] = _v[0];
+        this->data[1] = _v[1];
+        this->data[2] = _v[2];
+      }
+
+      /// \brief Destructor
+      public: virtual ~Vector3() {}
+
+      /// \brief Return the sum of the values
+      /// \return the sum
+      public: T Sum() const
+      {
+        return this->data[0] + this->data[1] + this->data[2];
+      }
+
+      /// \brief Calc distance to the given point
+      /// \param[in] _pt the point
+      /// \return the distance
+      public: T Distance(const Vector3<T> &_pt) const
+      {
+        return sqrt((this->data[0]-_pt[0])*(this->data[0]-_pt[0]) +
+                    (this->data[1]-_pt[1])*(this->data[1]-_pt[1]) +
+                    (this->data[2]-_pt[2])*(this->data[2]-_pt[2]));
+      }
+
+      /// \brief Calc distance to the given point
+      /// \param[in] _x value along x
+      /// \param[in] _y value along y
+      /// \param[in] _z value along z
+      /// \return the distance
+      public: T Distance(T _x, T _y, T _z) const
+      {
+        return this->Distance(Vector3(_x, _y, _z));
+      }
+
+      /// \brief Returns the length (magnitude) of the vector
+      /// \return the length
+      public: T Length() const
+      {
+        return sqrt(this->SquaredLength());
+      }
+
+      /// \brief Return the square of the length (magnitude) of the vector
+      /// \return the squared length
+      public: T SquaredLength() const
+      {
+        return std::pow(this->data[0], 2)
+             + std::pow(this->data[1], 2)
+             + std::pow(this->data[2], 2);
+      }
+
+      /// \brief Normalize the vector length
+      /// \return unit length vector
+      public: Vector3 Normalize()
+      {
+        T d = this->Length();
+
+        if (!equal<T>(d, static_cast<T>(0.0)))
+        {
+          this->data[0] /= d;
+          this->data[1] /= d;
+          this->data[2] /= d;
+        }
+
+        return *this;
+      }
+
+      /// \brief Return a normalized vector
+      /// \return unit length vector
+      public: Vector3 Normalized() const
+      {
+        Vector3<T> result = *this;
+        result.Normalize();
+        return result;
+      }
+
+      /// \brief Round to near whole number, return the result.
+      /// \return the result
+      public: Vector3 Round()
+      {
+        this->data[0] = nearbyint(this->data[0]);
+        this->data[1] = nearbyint(this->data[1]);
+        this->data[2] = nearbyint(this->data[2]);
+        return *this;
+      }
+
+      /// \brief Get a rounded version of this vector
+      /// \return a rounded vector
+      public: Vector3 Rounded() const
+      {
+        Vector3<T> result = *this;
+        result.Round();
+        return result;
+      }
+
+      /// \brief Set the contents of the vector
+      /// \param[in] _x value along x
+      /// \param[in] _y value along y
+      /// \param[in] _z value aling z
+      public: inline void Set(T _x = 0, T _y = 0, T _z = 0)
+      {
+        this->data[0] = _x;
+        this->data[1] = _y;
+        this->data[2] = _z;
+      }
+
+      /// \brief Return the cross product of this vector with another vector.
+      /// \param[in] _v a vector
+      /// \return the cross product
+      public: Vector3 Cross(const Vector3<T> &_v) const
+      {
+        return Vector3(this->data[1] * _v[2] - this->data[2] * _v[1],
+                       this->data[2] * _v[0] - this->data[0] * _v[2],
+                       this->data[0] * _v[1] - this->data[1] * _v[0]);
+      }
+
+      /// \brief Return the dot product of this vector and another vector
+      /// \param[in] _v the vector
+      /// \return the dot product
+      public: T Dot(const Vector3<T> &_v) const
+      {
+        return this->data[0] * _v[0] +
+               this->data[1] * _v[1] +
+               this->data[2] * _v[2];
+      }
+
+      /// \brief Return the absolute dot product of this vector and
+      /// another vector. This is similar to the Dot function, except the
+      /// absolute value of each component of the vector is used.
+      ///
+      /// result = abs(x1 * x2) + abs(y1 * y2) + abs(z1 *z2)
+      ///
+      /// \param[in] _v the vector
+      /// \return The absolute dot product
+      public: T AbsDot(const Vector3<T> &_v) const
+      {
+        return std::abs(this->data[0] * _v[0]) +
+               std::abs(this->data[1] * _v[1]) +
+               std::abs(this->data[2] * _v[2]);
+      }
+
+      /// \brief Get the absolute value of the vector
+      /// \return a vector with positive elements
+      public: Vector3 Abs() const
+      {
+        return Vector3(std::abs(this->data[0]),
+                       std::abs(this->data[1]),
+                       std::abs(this->data[2]));
+      }
+
+      /// \brief Return a vector that is perpendicular to this one.
+      /// \return an orthogonal vector
+      public: Vector3 Perpendicular() const
+      {
+        static const T sqrZero = 1e-06 * 1e-06;
+
+        Vector3<T> perp = this->Cross(Vector3(1, 0, 0));
+
+        // Check the length of the vector
+        if (perp.SquaredLength() < sqrZero)
+        {
+          perp = this->Cross(Vector3(0, 1, 0));
+        }
+
+        return perp;
+      }
+
+      /// \brief Get a normal vector to a triangle
+      /// \param[in] _v1 first vertex of the triangle
+      /// \param[in] _v2 second vertex
+      /// \param[in] _v3 third vertex
+      /// \return the normal
+      public: static Vector3 Normal(const Vector3<T> &_v1,
+                  const Vector3<T> &_v2, const Vector3<T> &_v3)
+      {
+        Vector3<T> a = _v2 - _v1;
+        Vector3<T> b = _v3 - _v1;
+        Vector3<T> n = a.Cross(b);
+        return n.Normalize();
+      }
+
+      /// \brief Get distance to a line
+      /// \param[in] _pt1 first point on the line
+      /// \param[in] _pt2 second point on the line
+      /// \return the minimum distance from this point to the line
+      public: T DistToLine(const Vector3<T> &_pt1, const Vector3 &_pt2)
+      {
+        T d = ((*this) - _pt1).Cross((*this) - _pt2).Length();
+        d = d / (_pt2 - _pt1).Length();
+        return d;
+      }
+
+      /// \brief Set this vector's components to the maximum of itself and the
+      ///        passed in vector
+      /// \param[in] _v the maximum clamping vector
+      public: void Max(const Vector3<T> &_v)
+      {
+        if (_v[0] > this->data[0])
+          this->data[0] = _v[0];
+        if (_v[1] > this->data[1])
+          this->data[1] = _v[1];
+        if (_v[2] > this->data[2])
+          this->data[2] = _v[2];
+      }
+
+      /// \brief Set this vector's components to the minimum of itself and the
+      ///        passed in vector
+      /// \param[in] _v the minimum clamping vector
+      public: void Min(const Vector3<T> &_v)
+      {
+        if (_v[0] < this->data[0])
+          this->data[0] = _v[0];
+        if (_v[1] < this->data[1])
+          this->data[1] = _v[1];
+        if (_v[2] < this->data[2])
+          this->data[2] = _v[2];
+      }
+
+      /// \brief Get the maximum value in the vector
+      /// \return the maximum element
+      public: T Max() const
+      {
+        return std::max(std::max(this->data[0], this->data[1]), this->data[2]);
+      }
+
+      /// \brief Get the minimum value in the vector
+      /// \return the minimum element
+      public: T Min() const
+      {
+        return std::min(std::min(this->data[0], this->data[1]), this->data[2]);
+      }
+
+      /// \brief Assignment operator
+      /// \param[in] _v a new value
+      /// \return this
+      public: Vector3 &operator=(const Vector3<T> &_v)
+      {
+        this->data[0] = _v[0];
+        this->data[1] = _v[1];
+        this->data[2] = _v[2];
+
+        return *this;
+      }
+
+      /// \brief Assignment operator
+      /// \param[in] _value assigned to all elements
+      /// \return this
+      public: Vector3 &operator=(T _v)
+      {
+        this->data[0] = _v;
+        this->data[1] = _v;
+        this->data[2] = _v;
+
+        return *this;
+      }
+
+      /// \brief Addition operator
+      /// \param[in] _v vector to add
+      /// \return the sum vector
+      public: Vector3 operator+(const Vector3<T> &_v) const
+      {
+        return Vector3(this->data[0] + _v[0],
+                       this->data[1] + _v[1],
+                       this->data[2] + _v[2]);
+      }
+
+      /// \brief Addition assignment operator
+      /// \param[in] _v vector to add
+      /// \return the sum vector
+      public: const Vector3 &operator+=(const Vector3<T> &_v)
+      {
+        this->data[0] += _v[0];
+        this->data[1] += _v[1];
+        this->data[2] += _v[2];
+
+        return *this;
+      }
+
+      /// \brief Addition operators
+      /// \param[in] _s the scalar addend
+      /// \return sum vector
+      public: inline Vector3<T> operator+(const T _s) const
+      {
+        return Vector3<T>(this->data[0] + _s,
+                          this->data[1] + _s,
+                          this->data[2] + _s);
+      }
+
+      /// \brief Addition operators
+      /// \param[in] _s the scalar addend
+      /// \param[in] _v input vector
+      /// \return sum vector
+      public: friend inline Vector3<T> operator+(const T _s,
+                                                 const Vector3<T> &_v)
+      {
+        return {_v.X() + _s, _v.Y() + _s, _v.Z() + _s};
+      }
+
+      /// \brief Addition assignment operator
+      /// \param[in] _s scalar addend
+      /// \return this
+      public: const Vector3<T> &operator+=(const T _s)
+      {
+        this->data[0] += _s;
+        this->data[1] += _s;
+        this->data[2] += _s;
+
+        return *this;
+      }
+
+      /// \brief Negation operator
+      /// \return negative of this vector
+      public: inline Vector3 operator-() const
+      {
+        return Vector3(-this->data[0], -this->data[1], -this->data[2]);
+      }
+
+      /// \brief Subtraction operators
+      /// \param[in] _pt a vector to substract
+      /// \return a vector after the substraction
+      public: inline Vector3<T> operator-(const Vector3<T> &_pt) const
+      {
+        return Vector3(this->data[0] - _pt[0],
+                       this->data[1] - _pt[1],
+                       this->data[2] - _pt[2]);
+      }
+
+      /// \brief Subtraction assignment operators
+      /// \param[in] _pt subtrahend
+      /// \return a vector after the substraction
+      public: const Vector3<T> &operator-=(const Vector3<T> &_pt)
+      {
+        this->data[0] -= _pt[0];
+        this->data[1] -= _pt[1];
+        this->data[2] -= _pt[2];
+
+        return *this;
+      }
+
+      /// \brief Subtraction operators
+      /// \param[in] _s the scalar subtrahend
+      /// \return difference vector
+      public: inline Vector3<T> operator-(const T _s) const
+      {
+        return Vector3<T>(this->data[0] - _s,
+                          this->data[1] - _s,
+                          this->data[2] - _s);
+      }
+
+      /// \brief Subtraction operators
+      /// \param[in] _s the scalar minuend
+      /// \param[in] _v vector subtrahend
+      /// \return difference vector
+      public: friend inline Vector3<T> operator-(const T _s,
+                                                 const Vector3<T> &_v)
+      {
+        return {_s - _v.X(), _s - _v.Y(), _s - _v.Z()};
+      }
+
+      /// \brief Subtraction assignment operator
+      /// \param[in] _s scalar subtrahend
+      /// \return this
+      public: const Vector3<T> &operator-=(const T _s)
+      {
+        this->data[0] -= _s;
+        this->data[1] -= _s;
+        this->data[2] -= _s;
+
+        return *this;
+      }
+
+      /// \brief Division operator
+      /// \remarks this is an element wise division
+      /// \param[in] _pt the vector divisor
+      /// \return a vector
+      public: const Vector3<T> operator/(const Vector3<T> &_pt) const
+      {
+        return Vector3(this->data[0] / _pt[0],
+                       this->data[1] / _pt[1],
+                       this->data[2] / _pt[2]);
+      }
+
+      /// \brief Division assignment operator
+      /// \remarks this is an element wise division
+      /// \param[in] _pt the vector divisor
+      /// \return a vector
+      public: const Vector3<T> &operator/=(const Vector3<T> &_pt)
+      {
+        this->data[0] /= _pt[0];
+        this->data[1] /= _pt[1];
+        this->data[2] /= _pt[2];
+
+        return *this;
+      }
+
+      /// \brief Division operator
+      /// \remarks this is an element wise division
+      /// \param[in] _v the divisor
+      /// \return a vector
+      public: const Vector3<T> operator/(T _v) const
+      {
+        return Vector3(this->data[0] / _v,
+                       this->data[1] / _v,
+                       this->data[2] / _v);
+      }
+
+      /// \brief Division assignment operator
+      /// \remarks this is an element wise division
+      /// \param[in] _v the divisor
+      /// \return this
+      public: const Vector3<T> &operator/=(T _v)
+      {
+        this->data[0] /= _v;
+        this->data[1] /= _v;
+        this->data[2] /= _v;
+
+        return *this;
+      }
+
+      /// \brief Multiplication operator
+      /// \remarks this is an element wise multiplication, not a cross product
+      /// \param[in] _p multiplier operator
+      /// \return a vector
+      public: Vector3<T> operator*(const Vector3<T> &_p) const
+      {
+        return Vector3(this->data[0] * _p[0],
+                       this->data[1] * _p[1],
+                       this->data[2] * _p[2]);
+      }
+
+      /// \brief Multiplication assignment operators
+      /// \remarks this is an element wise multiplication, not a cross product
+      /// \param[in] _v a vector
+      /// \return this
+      public: const Vector3<T> &operator*=(const Vector3<T> &_v)
+      {
+        this->data[0] *= _v[0];
+        this->data[1] *= _v[1];
+        this->data[2] *= _v[2];
+
+        return *this;
+      }
+
+      /// \brief Multiplication operators
+      /// \param[in] _s the scaling factor
+      /// \return a scaled vector
+      public: inline Vector3<T> operator*(T _s) const
+      {
+        return Vector3<T>(this->data[0] * _s,
+                          this->data[1] * _s,
+                          this->data[2] * _s);
+      }
+
+      /// \brief Multiplication operators
+      /// \param[in] _s the scaling factor
+      /// \param[in] _v input vector
+      /// \return a scaled vector
+      public: friend inline Vector3<T> operator*(T _s, const Vector3<T> &_v)
+      {
+        return {_v.X() * _s, _v.Y() * _s, _v.Z() * _s};
+      }
+
+      /// \brief Multiplication operator
+      /// \param[in] _v scaling factor
+      /// \return this
+      public: const Vector3<T> &operator*=(T _v)
+      {
+        this->data[0] *= _v;
+        this->data[1] *= _v;
+        this->data[2] *= _v;
+
+        return *this;
+      }
+
+      /// \brief Equality test with tolerance.
+      /// \param[in] _v the vector to compare to
+      /// \param[in] _tol equality tolerance.
+      /// \return true if the elements of the vectors are equal within
+      /// the tolerence specified by _tol.
+      public: bool Equal(const Vector3 &_v, const T &_tol) const
+      {
+        return equal<T>(this->data[0], _v[0], _tol)
+            && equal<T>(this->data[1], _v[1], _tol)
+            && equal<T>(this->data[2], _v[2], _tol);
+      }
+
+      /// \brief Equal to operator
+      /// \param[in] _v The vector to compare against
+      /// \return true if each component is equal within a
+      /// default tolerence (1e-3), false otherwise
+      public: bool operator==(const Vector3<T> &_v) const
+      {
+        return this->Equal(_v, static_cast<T>(1e-3));
+      }
+
+      /// \brief Not equal to operator
+      /// \param[in] _v The vector to compare against
+      /// \return false if each component is equal within a
+      /// default tolerence (1e-3), true otherwise
+      public: bool operator!=(const Vector3<T> &_v) const
+      {
+        return !(*this == _v);
+      }
+
+      /// \brief See if a point is finite (e.g., not nan)
+      /// \return true if is finite or false otherwise
+      public: bool IsFinite() const
+      {
+        // std::isfinite works with floating point values,
+        // need to explicit cast to avoid ambiguity in vc++.
+        return std::isfinite(static_cast<double>(this->data[0])) &&
+               std::isfinite(static_cast<double>(this->data[1])) &&
+               std::isfinite(static_cast<double>(this->data[2]));
+      }
+
+      /// \brief Corrects any nan values
+      public: inline void Correct()
+      {
+        // std::isfinite works with floating point values,
+        // need to explicit cast to avoid ambiguity in vc++.
+        if (!std::isfinite(static_cast<double>(this->data[0])))
+          this->data[0] = 0;
+        if (!std::isfinite(static_cast<double>(this->data[1])))
+          this->data[1] = 0;
+        if (!std::isfinite(static_cast<double>(this->data[2])))
+          this->data[2] = 0;
+      }
+
+      /// \brief Array subscript operator
+      /// \param[in] _index The index, where 0 == x, 1 == y, 2 == z.
+      /// The index is clamped to the range [0,2].
+      /// \return The value.
+      public: T &operator[](const std::size_t _index)
+      {
+        return this->data[clamp(_index, IGN_ZERO_SIZE_T, IGN_TWO_SIZE_T)];
+      }
+
+      /// \brief Const-qualified array subscript operator
+      /// \param[in] _index The index, where 0 == x, 1 == y, 2 == z.
+      /// The index is clamped to the range [0,2].
+      /// \return The value.
+      public: T operator[](const std::size_t _index) const
+      {
+        return this->data[clamp(_index, IGN_ZERO_SIZE_T, IGN_TWO_SIZE_T)];
+      }
+
+      /// \brief Round all values to _precision decimal places
+      /// \param[in] _precision the decimal places
+      public: void Round(int _precision)
+      {
+        this->data[0] = precision(this->data[0], _precision);
+        this->data[1] = precision(this->data[1], _precision);
+        this->data[2] = precision(this->data[2], _precision);
+      }
+
+      /// \brief Equality test
+      /// \remarks This is equivalent to the == operator
+      /// \param[in] _v the other vector
+      /// \return true if the 2 vectors have the same values, false otherwise
+      public: bool Equal(const Vector3<T> &_v) const
+      {
+        return equal<T>(this->data[0], _v[0]) &&
+               equal<T>(this->data[1], _v[1]) &&
+               equal<T>(this->data[2], _v[2]);
+      }
+
+      /// \brief Get the x value.
+      /// \return The x component of the vector
+      public: inline T X() const
+      {
+        return this->data[0];
+      }
+
+      /// \brief Get the y value.
+      /// \return The y component of the vector
+      public: inline T Y() const
+      {
+        return this->data[1];
+      }
+
+      /// \brief Get the z value.
+      /// \return The z component of the vector
+      public: inline T Z() const
+      {
+        return this->data[2];
+      }
+
+      /// \brief Get a mutable reference to the x value.
+      /// \return The x component of the vector
+      public: inline T &X()
+      {
+        return this->data[0];
+      }
+
+      /// \brief Get a mutable reference to the y value.
+      /// \return The y component of the vector
+      public: inline T &Y()
+      {
+        return this->data[1];
+      }
+
+      /// \brief Get a mutable reference to the z value.
+      /// \return The z component of the vector
+      public: inline T &Z()
+      {
+        return this->data[2];
+      }
+
+      /// \brief Set the x value.
+      /// \param[in] _v Value for the x component.
+      public: inline void X(const T &_v)
+      {
+        this->data[0] = _v;
+      }
+
+      /// \brief Set the y value.
+      /// \param[in] _v Value for the y component.
+      public: inline void Y(const T &_v)
+      {
+        this->data[1] = _v;
+      }
+
+      /// \brief Set the z value.
+      /// \param[in] _v Value for the z component.
+      public: inline void Z(const T &_v)
+      {
+        this->data[2] = _v;
+      }
+
+      /// \brief Less than operator.
+      /// \param[in] _pt Vector to compare.
+      /// \return True if this vector's X(), Y(), or Z() value is less
+      /// than the given vector's corresponding values.
+      public: bool operator<(const Vector3<T> &_pt) const
+      {
+        return this->data[0] < _pt[0] || this->data[1] < _pt[1] ||
+               this->data[2] < _pt[2];
+      }
+
+      /// \brief Stream insertion operator
+      /// \param _out output stream
+      /// \param _pt Vector3 to output
+      /// \return the stream
+      public: friend std::ostream &operator<<(
+                  std::ostream &_out, const ignition::math::Vector3<T> &_pt)
+      {
+        _out << precision(_pt[0], 6) << " " << precision(_pt[1], 6) << " "
+          << precision(_pt[2], 6);
+        return _out;
+      }
+
+      /// \brief Stream extraction operator
+      /// \param _in input stream
+      /// \param _pt vector3 to read values into
+      /// \return the stream
+      public: friend std::istream &operator>>(
+                  std::istream &_in, ignition::math::Vector3<T> &_pt)
+      {
+        // Skip white spaces
+        _in.setf(std::ios_base::skipws);
+        T x, y, z;
+        _in >> x >> y >> z;
+        _pt.Set(x, y, z);
+        return _in;
+      }
+
+      /// \brief The x, y, and z values
+      private: T data[3];
+    };
+
+    template<typename T> const Vector3<T> Vector3<T>::Zero(0, 0, 0);
+    template<typename T> const Vector3<T> Vector3<T>::One(1, 1, 1);
+    template<typename T> const Vector3<T> Vector3<T>::UnitX(1, 0, 0);
+    template<typename T> const Vector3<T> Vector3<T>::UnitY(0, 1, 0);
+    template<typename T> const Vector3<T> Vector3<T>::UnitZ(0, 0, 1);
+
+    typedef Vector3<int> Vector3i;
+    typedef Vector3<double> Vector3d;
+    typedef Vector3<float> Vector3f;
+  }
+}
+#endif
diff --git a/include/ignition/math/Vector3Stats.hh b/include/ignition/math/Vector3Stats.hh
new file mode 100644
index 0000000..6fc323d
--- /dev/null
+++ b/include/ignition/math/Vector3Stats.hh
@@ -0,0 +1,107 @@
+/*
+ * Copyright (C) 2015 Open Source Robotics Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+*/
+#ifndef IGNITION_MATH_VECTOR3STATS_HH_
+#define IGNITION_MATH_VECTOR3STATS_HH_
+
+#include <string>
+#include <ignition/math/Helpers.hh>
+#include <ignition/math/SignalStats.hh>
+#include <ignition/math/Vector3.hh>
+
+namespace ignition
+{
+  namespace math
+  {
+    /// \brief Forward declare private data class.
+    class Vector3StatsPrivate;
+
+    /// \class Vector3Stats Vector3Stats.hh ignition/math/Vector3Stats.hh
+    /// \brief Collection of statistics for a Vector3 signal.
+    class IGNITION_MATH_VISIBLE Vector3Stats
+    {
+      /// \brief Constructor
+      public: Vector3Stats();
+
+      /// \brief Destructor
+      public: ~Vector3Stats();
+
+      /// \brief Add a new sample to the statistical measures.
+      /// \param[in] _data New signal data point.
+      public: void InsertData(const Vector3d &_data);
+
+      /// \brief Add a new type of statistic.
+      /// \param[in] _name Short name of new statistic.
+      /// Valid values include:
+      ///  "maxAbs"
+      ///  "mean"
+      ///  "rms"
+      /// \return True if statistic was successfully added,
+      /// false if name was not recognized or had already
+      /// been inserted.
+      public: bool InsertStatistic(const std::string &_name);
+
+      /// \brief Add multiple statistics.
+      /// \param[in] _names Comma-separated list of new statistics.
+      /// For example, all statistics could be added with:
+      ///  "maxAbs,mean,rms"
+      /// \return True if all statistics were successfully added,
+      /// false if any names were not recognized or had already
+      /// been inserted.
+      public: bool InsertStatistics(const std::string &_names);
+
+      /// \brief Forget all previous data.
+      public: void Reset();
+
+      /// \brief Get statistics for x component of signal.
+      /// \return Statistics for x component of signal.
+      public: const SignalStats &X() const;
+
+      /// \brief Get statistics for y component of signal.
+      /// \return Statistics for y component of signal.
+      public: const SignalStats &Y() const;
+
+      /// \brief Get statistics for z component of signal.
+      /// \return Statistics for z component of signal.
+      public: const SignalStats &Z() const;
+
+      /// \brief Get statistics for magnitude component of signal.
+      /// \return Statistics for magnitude component of signal.
+      public: const SignalStats &Mag() const;
+
+      /// \brief Get mutable reference to statistics for x component of signal.
+      /// \return Statistics for x component of signal.
+      public: SignalStats &X();
+
+      /// \brief Get mutable reference to statistics for y component of signal.
+      /// \return Statistics for y component of signal.
+      public: SignalStats &Y();
+
+      /// \brief Get mutable reference to statistics for z component of signal.
+      /// \return Statistics for z component of signal.
+      public: SignalStats &Z();
+
+      /// \brief Get mutable reference to statistics for magnitude of signal.
+      /// \return Statistics for magnitude of signal.
+      public: SignalStats &Mag();
+
+      /// \brief Pointer to private data.
+      protected: Vector3StatsPrivate *dataPtr;
+    };
+  }
+}
+#endif
+
diff --git a/include/ignition/math/Vector4.hh b/include/ignition/math/Vector4.hh
new file mode 100644
index 0000000..de3ffa5
--- /dev/null
+++ b/include/ignition/math/Vector4.hh
@@ -0,0 +1,589 @@
+/*
+ * Copyright (C) 2012 Open Source Robotics Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+*/
+#ifndef IGNITION_MATH_VECTOR4_HH_
+#define IGNITION_MATH_VECTOR4_HH_
+
+#include <ignition/math/Matrix4.hh>
+#include <ignition/math/Helpers.hh>
+
+namespace ignition
+{
+  namespace math
+  {
+    /// \class Vector4 Vector4.hh ignition/math/Vector4.hh
+    /// \brief T Generic x, y, z, w vector
+    template<typename T>
+    class Vector4
+    {
+      /// \brief math::Vector4(0, 0, 0, 0)
+      public: static const Vector4<T> Zero;
+
+      /// \brief math::Vector4(1, 1, 1, 1)
+      public: static const Vector4<T> One;
+
+      /// \brief Constructor
+      public: Vector4()
+      {
+        this->data[0] = this->data[1] = this->data[2] = this->data[3] = 0;
+      }
+
+      /// \brief Constructor with component values
+      /// \param[in] _x value along x axis
+      /// \param[in] _y value along y axis
+      /// \param[in] _z value along z axis
+      /// \param[in] _w value along w axis
+      public: Vector4(const T &_x, const T &_y, const T &_z, const T &_w)
+      {
+        this->data[0] = _x;
+        this->data[1] = _y;
+        this->data[2] = _z;
+        this->data[3] = _w;
+      }
+
+      /// \brief Copy constructor
+      /// \param[in] _v vector
+      public: Vector4(const Vector4<T> &_v)
+      {
+        this->data[0] = _v[0];
+        this->data[1] = _v[1];
+        this->data[2] = _v[2];
+        this->data[3] = _v[3];
+      }
+
+      /// \brief Destructor
+      public: virtual ~Vector4() {}
+
+      /// \brief Calc distance to the given point
+      /// \param[in] _pt the point
+      /// \return the distance
+      public: T Distance(const Vector4<T> &_pt) const
+      {
+        return sqrt((this->data[0]-_pt[0])*(this->data[0]-_pt[0]) +
+                    (this->data[1]-_pt[1])*(this->data[1]-_pt[1]) +
+                    (this->data[2]-_pt[2])*(this->data[2]-_pt[2]) +
+                    (this->data[3]-_pt[3])*(this->data[3]-_pt[3]));
+      }
+
+      /// \brief Returns the length (magnitude) of the vector
+      /// \return The length
+      public: T Length() const
+      {
+        return sqrt(this->SquaredLength());
+      }
+
+      /// \brief Return the square of the length (magnitude) of the vector
+      /// \return the length
+      public: T SquaredLength() const
+      {
+        return std::pow(this->data[0], 2)
+             + std::pow(this->data[1], 2)
+             + std::pow(this->data[2], 2)
+             + std::pow(this->data[3], 2);
+      }
+
+      /// \brief Normalize the vector length
+      public: void Normalize()
+      {
+        T d = this->Length();
+
+        if (!equal<T>(d, static_cast<T>(0.0)))
+        {
+          this->data[0] /= d;
+          this->data[1] /= d;
+          this->data[2] /= d;
+          this->data[3] /= d;
+        }
+      }
+
+      /// \brief Set the contents of the vector
+      /// \param[in] _x value along x axis
+      /// \param[in] _y value along y axis
+      /// \param[in] _z value along z axis
+      /// \param[in] _w value along w axis
+      public: void Set(T _x = 0, T _y = 0, T _z = 0, T _w = 0)
+      {
+        this->data[0] = _x;
+        this->data[1] = _y;
+        this->data[2] = _z;
+        this->data[3] = _w;
+      }
+
+      /// \brief Assignment operator
+      /// \param[in] _v the vector
+      /// \return a reference to this vector
+      public: Vector4<T> &operator=(const Vector4<T> &_v)
+      {
+        this->data[0] = _v[0];
+        this->data[1] = _v[1];
+        this->data[2] = _v[2];
+        this->data[3] = _v[3];
+
+        return *this;
+      }
+
+      /// \brief Assignment operator
+      /// \param[in] _value
+      public: Vector4<T> &operator=(T _value)
+      {
+        this->data[0] = _value;
+        this->data[1] = _value;
+        this->data[2] = _value;
+        this->data[3] = _value;
+
+        return *this;
+      }
+
+      /// \brief Addition operator
+      /// \param[in] _v the vector to add
+      /// \result a sum vector
+      public: Vector4<T> operator+(const Vector4<T> &_v) const
+      {
+        return Vector4<T>(this->data[0] + _v[0],
+                          this->data[1] + _v[1],
+                          this->data[2] + _v[2],
+                          this->data[3] + _v[3]);
+      }
+
+      /// \brief Addition operator
+      /// \param[in] _v the vector to add
+      /// \return this vector
+      public: const Vector4<T> &operator+=(const Vector4<T> &_v)
+      {
+        this->data[0] += _v[0];
+        this->data[1] += _v[1];
+        this->data[2] += _v[2];
+        this->data[3] += _v[3];
+
+        return *this;
+      }
+
+      /// \brief Addition operators
+      /// \param[in] _s the scalar addend
+      /// \return sum vector
+      public: inline Vector4<T> operator+(const T _s) const
+      {
+        return Vector4<T>(this->data[0] + _s,
+                          this->data[1] + _s,
+                          this->data[2] + _s,
+                          this->data[3] + _s);
+      }
+
+      /// \brief Addition operators
+      /// \param[in] _s the scalar addend
+      /// \param[in] _v input vector
+      /// \return sum vector
+      public: friend inline Vector4<T> operator+(const T _s,
+                                                 const Vector4<T> &_v)
+      {
+        return _v + _s;
+      }
+
+      /// \brief Addition assignment operator
+      /// \param[in] _s scalar addend
+      /// \return this
+      public: const Vector4<T> &operator+=(const T _s)
+      {
+        this->data[0] += _s;
+        this->data[1] += _s;
+        this->data[2] += _s;
+        this->data[3] += _s;
+
+        return *this;
+      }
+
+      /// \brief Negation operator
+      /// \return negative of this vector
+      public: inline Vector4 operator-() const
+      {
+        return Vector4(-this->data[0], -this->data[1],
+                       -this->data[2], -this->data[3]);
+      }
+
+      /// \brief Subtraction operator
+      /// \param[in] _v the vector to substract
+      /// \return a vector
+      public: Vector4<T> operator-(const Vector4<T> &_v) const
+      {
+        return Vector4<T>(this->data[0] - _v[0],
+                          this->data[1] - _v[1],
+                          this->data[2] - _v[2],
+                          this->data[3] - _v[3]);
+      }
+
+      /// \brief Subtraction assigment operators
+      /// \param[in] _v the vector to substract
+      /// \return this vector
+      public: const Vector4<T> &operator-=(const Vector4<T> &_v)
+      {
+        this->data[0] -= _v[0];
+        this->data[1] -= _v[1];
+        this->data[2] -= _v[2];
+        this->data[3] -= _v[3];
+
+        return *this;
+      }
+
+      /// \brief Subtraction operators
+      /// \param[in] _s the scalar subtrahend
+      /// \return difference vector
+      public: inline Vector4<T> operator-(const T _s) const
+      {
+        return Vector4<T>(this->data[0] - _s,
+                          this->data[1] - _s,
+                          this->data[2] - _s,
+                          this->data[3] - _s);
+      }
+
+      /// \brief Subtraction operators
+      /// \param[in] _s the scalar minuend
+      /// \param[in] _v vector subtrahend
+      /// \return difference vector
+      public: friend inline Vector4<T> operator-(const T _s,
+                                                 const Vector4<T> &_v)
+      {
+        return Vector4<T>(_s - _v.X(), _s - _v.Y(), _s - _v.Z(), _s - _v.W());
+      }
+
+      /// \brief Subtraction assignment operator
+      /// \param[in] _s scalar subtrahend
+      /// \return this
+      public: const Vector4<T> &operator-=(const T _s)
+      {
+        this->data[0] -= _s;
+        this->data[1] -= _s;
+        this->data[2] -= _s;
+        this->data[3] -= _s;
+
+        return *this;
+      }
+
+      /// \brief Division assignment operator
+      /// \remarks Performs element wise division,
+      /// which has limited use.
+      /// \param[in] _v the vector to perform element wise division with
+      /// \return a result vector
+      public: const Vector4<T> operator/(const Vector4<T> &_v) const
+      {
+        return Vector4<T>(this->data[0] / _v[0],
+                          this->data[1] / _v[1],
+                          this->data[2] / _v[2],
+                          this->data[3] / _v[3]);
+      }
+
+      /// \brief Division assignment operator
+      /// \remarks Performs element wise division,
+      /// which has limited use.
+      /// \param[in] _v the vector to perform element wise division with
+      /// \return this
+      public: const Vector4<T> &operator/=(const Vector4<T> &_v)
+      {
+        this->data[0] /= _v[0];
+        this->data[1] /= _v[1];
+        this->data[2] /= _v[2];
+        this->data[3] /= _v[3];
+
+        return *this;
+      }
+
+      /// \brief Division assignment operator
+      /// \remarks Performs element wise division,
+      /// which has limited use.
+      /// \param[in] _pt another vector
+      /// \return a result vector
+      public: const Vector4<T> operator/(T _v) const
+      {
+        return Vector4<T>(this->data[0] / _v, this->data[1] / _v,
+            this->data[2] / _v, this->data[3] / _v);
+      }
+
+      /// \brief Division operator
+      /// \param[in] _v scaling factor
+      /// \return a vector
+      public: const Vector4<T> &operator/=(T _v)
+      {
+        this->data[0] /= _v;
+        this->data[1] /= _v;
+        this->data[2] /= _v;
+        this->data[3] /= _v;
+
+        return *this;
+      }
+
+      /// \brief Multiplication operator.
+      /// \remarks Performs element wise multiplication,
+      /// which has limited use.
+      /// \param[in] _pt another vector
+      /// \return result vector
+      public: const Vector4<T> operator*(const Vector4<T> &_pt) const
+      {
+        return Vector4<T>(this->data[0] * _pt[0],
+                          this->data[1] * _pt[1],
+                          this->data[2] * _pt[2],
+                          this->data[3] * _pt[3]);
+      }
+
+      /// \brief Matrix multiplication operator.
+      /// \param[in] _m matrix
+      /// \return the vector multiplied by _m
+      public: const Vector4<T> operator*(const Matrix4<T> &_m) const
+      {
+        return Vector4<T>(
+            this->data[0]*_m(0, 0) + this->data[1]*_m(1, 0) +
+            this->data[2]*_m(2, 0) + this->data[3]*_m(3, 0),
+            this->data[0]*_m(0, 1) + this->data[1]*_m(1, 1) +
+            this->data[2]*_m(2, 1) + this->data[3]*_m(3, 1),
+            this->data[0]*_m(0, 2) + this->data[1]*_m(1, 2) +
+            this->data[2]*_m(2, 2) + this->data[3]*_m(3, 2),
+            this->data[0]*_m(0, 3) + this->data[1]*_m(1, 3) +
+            this->data[2]*_m(2, 3) + this->data[3]*_m(3, 3));
+      }
+
+      /// \brief Multiplication assignment operator
+      /// \remarks Performs element wise multiplication,
+      /// which has limited use.
+      /// \param[in] _pt a vector
+      /// \return this
+      public: const Vector4<T> &operator*=(const Vector4<T> &_pt)
+      {
+        this->data[0] *= _pt[0];
+        this->data[1] *= _pt[1];
+        this->data[2] *= _pt[2];
+        this->data[3] *= _pt[3];
+
+        return *this;
+      }
+
+      /// \brief Multiplication operators
+      /// \param[in] _v scaling factor
+      /// \return a  scaled vector
+      public: const Vector4<T> operator*(T _v) const
+      {
+        return Vector4<T>(this->data[0] * _v, this->data[1] * _v,
+            this->data[2] * _v, this->data[3] * _v);
+      }
+
+      /// \brief Scalar left multiplication operators
+      /// \param[in] _s the scaling factor
+      /// \param[in] _v the vector to scale
+      /// \return a scaled vector
+      public: friend inline const Vector4 operator*(const T _s,
+                                                    const Vector4 &_v)
+      {
+        return Vector4(_v * _s);
+      }
+
+      /// \brief Multiplication assignment operator
+      /// \param[in] _v scaling factor
+      /// \return this
+      public: const Vector4<T> &operator*=(T _v)
+      {
+        this->data[0] *= _v;
+        this->data[1] *= _v;
+        this->data[2] *= _v;
+        this->data[3] *= _v;
+
+        return *this;
+      }
+
+      /// \brief Equality test with tolerance.
+      /// \param[in] _v the vector to compare to
+      /// \param[in] _tol equality tolerance.
+      /// \return true if the elements of the vectors are equal within
+      /// the tolerence specified by _tol.
+      public: bool Equal(const Vector4 &_v, const T &_tol) const
+      {
+        return equal<T>(this->data[0], _v[0], _tol)
+            && equal<T>(this->data[1], _v[1], _tol)
+            && equal<T>(this->data[2], _v[2], _tol)
+            && equal<T>(this->data[3], _v[3], _tol);
+      }
+
+      /// \brief Equal to operator
+      /// \param[in] _v the other vector
+      /// \return true if each component is equal within a
+      /// default tolerence (1e-6), false otherwise
+      public: bool operator==(const Vector4<T> &_v) const
+      {
+        return this->Equal(_v, static_cast<T>(1e-6));
+      }
+
+      /// \brief Not equal to operator
+      /// \param[in] _pt the other vector
+      /// \return false if each component is equal within a
+      /// default tolerence (1e-6), true otherwise
+      public: bool operator!=(const Vector4<T> &_pt) const
+      {
+        return !(*this == _pt);
+      }
+
+      /// \brief See if a point is finite (e.g., not nan)
+      /// \return true if finite, false otherwise
+      public: bool IsFinite() const
+      {
+        // std::isfinite works with floating point values,
+        // need to explicit cast to avoid ambiguity in vc++.
+        return std::isfinite(static_cast<double>(this->data[0])) &&
+               std::isfinite(static_cast<double>(this->data[1])) &&
+               std::isfinite(static_cast<double>(this->data[2])) &&
+               std::isfinite(static_cast<double>(this->data[3]));
+      }
+
+      /// \brief Array subscript operator
+      /// \param[in] _index The index, where 0 == x, 1 == y, 2 == z, 3 == w.
+      /// The index is clamped to the range (0,3).
+      /// \return The value.
+      public: T &operator[](const std::size_t _index)
+      {
+        return this->data[clamp(_index, IGN_ZERO_SIZE_T, IGN_THREE_SIZE_T)];
+      }
+
+      /// \brief Const-qualified array subscript operator
+      /// \param[in] _index The index, where 0 == x, 1 == y, 2 == z, 3 == w.
+      /// The index is clamped to the range (0,3).
+      /// \return The value.
+      public: T operator[](const std::size_t _index) const
+      {
+        return this->data[clamp(_index, IGN_ZERO_SIZE_T, IGN_THREE_SIZE_T)];
+      }
+
+      /// \brief Return a mutable x value.
+      /// \return The x component of the vector
+      public: T &X()
+      {
+        return this->data[0];
+      }
+
+      /// \brief Return a mutable y value.
+      /// \return The y component of the vector
+      public: T &Y()
+      {
+        return this->data[1];
+      }
+
+      /// \brief Return a mutable z value.
+      /// \return The z component of the vector
+      public: T &Z()
+      {
+        return this->data[2];
+      }
+
+      /// \brief Return a mutable w value.
+      /// \return The w component of the vector
+      public: T &W()
+      {
+        return this->data[3];
+      }
+
+      /// \brief Get the x value.
+      /// \return The x component of the vector
+      public: T X() const
+      {
+        return this->data[0];
+      }
+
+      /// \brief Get the y value.
+      /// \return The y component of the vector
+      public: T Y() const
+      {
+        return this->data[1];
+      }
+
+      /// \brief Get the z value.
+      /// \return The z component of the vector
+      public: T Z() const
+      {
+        return this->data[2];
+      }
+
+      /// \brief Get the w value.
+      /// \return The w component of the vector
+      public: T W() const
+      {
+        return this->data[3];
+      }
+
+      /// \brief Set the x value.
+      /// \param[in] _v Value for the x component.
+      public: inline void X(const T &_v)
+      {
+        this->data[0] = _v;
+      }
+
+      /// \brief Set the y value.
+      /// \param[in] _v Value for the y component.
+      public: inline void Y(const T &_v)
+      {
+        this->data[1] = _v;
+      }
+
+      /// \brief Set the z value.
+      /// \param[in] _v Value for the z component.
+      public: inline void Z(const T &_v)
+      {
+        this->data[2] = _v;
+      }
+
+      /// \brief Set the w value.
+      /// \param[in] _v Value for the w component.
+      public: inline void W(const T &_v)
+      {
+        this->data[3] = _v;
+      }
+
+      /// \brief Stream insertion operator
+      /// \param[in] _out output stream
+      /// \param[in] _pt Vector4 to output
+      /// \return The stream
+      public: friend std::ostream &operator<<(
+                  std::ostream &_out, const ignition::math::Vector4<T> &_pt)
+      {
+        _out << _pt[0] << " " << _pt[1] << " " << _pt[2] << " " << _pt[3];
+        return _out;
+      }
+
+      /// \brief Stream extraction operator
+      /// \param[in] _in input stream
+      /// \param[in] _pt Vector4 to read values into
+      /// \return the stream
+      public: friend std::istream &operator>>(
+                  std::istream &_in, ignition::math::Vector4<T> &_pt)
+      {
+        T x, y, z, w;
+
+        // Skip white spaces
+        _in.setf(std::ios_base::skipws);
+        _in >> x >> y >> z >> w;
+        _pt.Set(x, y, z, w);
+        return _in;
+      }
+
+      /// \brief Data values, 0==x, 1==y, 2==z, 3==w
+      private: T data[4];
+    };
+
+    template<typename T>
+    const Vector4<T> Vector4<T>::Zero(0, 0, 0, 0);
+
+    template<typename T>
+    const Vector4<T> Vector4<T>::One(1, 1, 1, 1);
+
+    typedef Vector4<int> Vector4i;
+    typedef Vector4<double> Vector4d;
+    typedef Vector4<float> Vector4f;
+  }
+}
+#endif
diff --git a/include/ignition/math/config.hh.in b/include/ignition/math/config.hh.in
new file mode 100644
index 0000000..16cf225
--- /dev/null
+++ b/include/ignition/math/config.hh.in
@@ -0,0 +1,15 @@
+/* Config.hh. Generated by CMake for @PROJECT_NAME_NO_VERSION at . */
+
+/* Version number */
+#define IGNITION_MATH_MAJOR_VERSION ${PROJECT_MAJOR_VERSION}
+#define IGNITION_MATH_MINOR_VERSION ${PROJECT_MINOR_VERSION}
+#define IGNITION_MATH_PATCH_VERSION ${PROJECT_PATCH_VERSION}
+
+#define IGNITION_MATH_VERSION "${PROJECT_VERSION}"
+#define IGNITION_MATH_VERSION_FULL "${PROJECT_VERSION_FULL}"
+
+#define IGNITION_MATH_VERSION_HEADER "Ignition math, version ${PROJECT_VERSION_FULL}\nCopyright (C) 2014 Open Source Robotics Foundation.\nReleased under the Apache 2.0 License.\n\n"
+
+#cmakedefine IGNITION_MATH_BUILD_TYPE_PROFILE 1
+#cmakedefine IGNITION_MATH_BUILD_TYPE_DEBUG 1
+#cmakedefine IGNITION_MATH_BUILD_TYPE_RELEASE 1
diff --git a/include/ignition/math/graph/Edge.hh b/include/ignition/math/graph/Edge.hh
new file mode 100644
index 0000000..afed5b6
--- /dev/null
+++ b/include/ignition/math/graph/Edge.hh
@@ -0,0 +1,337 @@
+/*
+ * Copyright (C) 2017 Open Source Robotics Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+*/
+#ifndef IGNITION_MATH_GRAPH_EDGE_HH_
+#define IGNITION_MATH_GRAPH_EDGE_HH_
+
+// uint64_t
+#include <cstdint>
+#include <functional>
+#include <iostream>
+#include <map>
+#include <set>
+
+#include "ignition/math/graph/Vertex.hh"
+
+namespace ignition
+{
+namespace math
+{
+namespace graph
+{
+  /// \def EdgeId.
+  /// \brief The unique Id for an edge.
+  using EdgeId = uint64_t;
+
+  /// \brief Used in the Graph constructors for uniform initialization.
+  template<typename E>
+  struct EdgeInitializer
+  {
+    /// \brief Constructor.
+    /// \param[in] _vertices The vertices of the edge.
+    /// \param[in] _data The data stored in the edge.
+    /// \param[in] _weight The weight (cost) of the edge.
+    EdgeInitializer(const VertexId_P &_vertices,
+                    const E &_data = E(),
+                    const double _weight = 1)
+      : vertices(_vertices),
+        data(_data),
+        weight(_weight)
+    {
+    };
+
+    /// \brief IDs of the vertices.
+    public: VertexId_P vertices;
+
+    /// \brief User data.
+    public: E data;
+
+    /// \brief The weight (cost) of the edge.
+    public: double weight = 1;
+  };
+
+  /// \brief Generic edge class. An edge has two ends and some constraint
+  /// between them. For example, a directed edge only allows traversing the
+  /// edge in one direction.
+  template<typename E>
+  class Edge
+  {
+    /// \brief Constructor.
+    /// \param[in] _vertices The vertices of the edge.
+    /// \param[in] _data The data stored in the edge.
+    /// \param[in] _weight The weight (cost) of the edge.
+    /// \param[in] _id Optional unique id.
+    public: explicit Edge(const VertexId_P &_vertices,
+                          const E &_data,
+                          const double _weight,
+                          const EdgeId &_id = kNullId)
+      : id(_id),
+        vertices(_vertices),
+        data(_data),
+        weight(_weight)
+    {
+    }
+
+    /// \brief Get the edge Id.
+    /// \return The edge Id.
+    public: EdgeId Id() const
+    {
+      return this->id;
+    }
+
+    /// \brief Get the two vertices contained in the edge.
+    /// \return The two vertices contained in the edge.
+    public: VertexId_P Vertices() const
+    {
+      if (!this->Valid())
+        return {kNullId, kNullId};
+
+      return this->vertices;
+    }
+
+    /// \brief Get a non-mutable reference to the user data stored in the edge
+    /// \return The non-mutable reference to the user data stored in the edge.
+    public: const E &Data() const
+    {
+      return this->data;
+    }
+
+    /// \brief Get a mutable reference to the user data stored in the edge.
+    /// \return The mutable reference to the user data stored in the edge.
+    public: E &Data()
+    {
+      return this->data;
+    }
+
+    /// \brief The cost of traversing the _from end to the other end of the
+    /// edge.
+    /// \return The cost.
+    public: double Weight() const
+    {
+      return this->weight;
+    }
+
+    /// \brief Set the cost of the edge.
+    /// \param[in] _newWeight The new cost.
+    public: void SetWeight(const double _newWeight)
+    {
+      this->weight = _newWeight;
+    }
+
+    /// \brief Get the destination end that is reachable from a source end of
+    /// an edge.
+    ///
+    /// E.g.: Let's assume that we have an undirected edge (e1) with ends
+    /// (v1) and (v2): (v1)--(v2). The operation e1.From(v1) returns (v2).
+    /// The operation e1.From(v2) returns (v1).
+    ///
+    /// E.g.: Let's assume that we have a directed edge (e2) with the tail end
+    /// (v1) and the head end (v2): (v1)->(v2). The operation e2.From(v1)
+    /// returns (v2). The operation e2.From(v2) returns kNullId.
+    ///
+    /// \param[in] _from Source vertex.
+    /// \return The other vertex of the edge reachable from the "_from"
+    /// vertex or kNullId otherwise.
+    public: virtual VertexId From(const VertexId &_from) const = 0;
+
+    /// \brief Get the source end that can reach the destination end of
+    /// an edge.
+    ///
+    /// E.g.: Let's assume that we have an undirected edge (e1) with ends
+    /// (v1) and (v2): (v1)--(v2). The operation e1.To(v1) returns (v2).
+    /// The operation e1.To(v2) returns (v1).
+    ///
+    /// E.g.: Let's assume that we have a directed edge (e2) with the tail end
+    /// (v1) and the head end (v2): (v1)->(v2). The operation e2.To(v1)
+    /// returns kNullId. The operation e2.To(v2) returns v1.
+    ///
+    /// \param[in] _from Destination vertex.
+    /// \return The other vertex of the edge that can reach "_to"
+    /// vertex or kNullId otherwise.
+    public: virtual VertexId To(const VertexId &_to) const = 0;
+
+    /// \brief An edge is considered valid when its id is not kNullId.
+    /// \return Whether the edge is valid or not.
+    public: bool Valid() const
+    {
+      return this->id != kNullId;
+    }
+
+    /// \brief Unique edge Id.
+    private: EdgeId id = kNullId;
+
+    /// \brief The set of Ids of the two vertices.
+    private: VertexId_P vertices;
+
+    /// \brief User data.
+    private: E data;
+
+    /// \brief The weight (cost) of the edge. By default, the cost of an edge
+    /// is 1.0 .
+    private: double weight = 1.0;
+  };
+
+  /// \def EdgeId_S
+  /// \brief A set of edge Ids.
+  using EdgeId_S = std::set<EdgeId>;
+
+  /// \def EdgeRef_M
+  /// \brief A map of edges. The key is the edge Id. The value is a reference
+  /// to the edge.
+  template<typename EdgeType>
+  using EdgeRef_M = std::map<EdgeId, std::reference_wrapper<const EdgeType>>;
+
+  /// \brief An undirected edge represents a connection between two vertices.
+  /// The connection is bidirectional, it's possible to traverse the edge
+  /// in both directions.
+  template<typename E>
+  class UndirectedEdge : public Edge<E>
+  {
+    /// \brief An invalid undirected edge.
+    public: static UndirectedEdge<E> NullEdge;
+
+    /// \brief Constructor.
+    /// \param[in] _vertices The vertices of the edge.
+    /// \param[in] _data The data stored in the edge.
+    /// \param[in] _weight The weight (cost) of the edge.
+    /// \param[in] _id Optional unique id.
+    public: explicit UndirectedEdge(const VertexId_P &_vertices,
+                                    const E &_data,
+                                    const double _weight,
+                                    const EdgeId &_id = kNullId)
+      : Edge<E>(_vertices, _data, _weight, _id)
+    {
+    }
+
+    // Documentation inherited.
+    public: VertexId From(const VertexId &_from) const override
+    {
+      if (!this->Valid())
+        return kNullId;
+
+      if (this->Vertices().first != _from && this->Vertices().second != _from)
+        return kNullId;
+
+      if (this->Vertices().first == _from)
+        return this->Vertices().second;
+
+      return this->Vertices().first;
+    }
+
+    // Documentation inherited.
+    public: VertexId To(const VertexId &_to) const override
+    {
+      return this->From(_to);
+    }
+
+    /// \brief Stream insertion operator. The output uses DOT graph
+    /// description language.
+    /// \param[out] _out The output stream.
+    /// \param[in] _e Edge to write to the stream.
+    /// \ref https://en.wikipedia.org/wiki/DOT_(graph_description_language).
+    public: friend std::ostream &operator<<(std::ostream &_out,
+                                            const UndirectedEdge<E> &_e)
+    {
+      auto vertices = _e.Vertices();
+      _out << "  " << vertices.first << " -- " << vertices.second
+           << " [label=" << _e.Weight() << "];" << std::endl;
+      return _out;
+    }
+  };
+
+  /// \brief An invalid undirected edge.
+  template<typename E>
+  UndirectedEdge<E> UndirectedEdge<E>::NullEdge(
+    VertexId_P(kNullId, kNullId), E(), 1.0, kNullId);
+
+  /// \brief A directed edge represents a connection between two vertices.
+  /// The connection is unidirectional, it's only possible to traverse the edge
+  /// in one direction (from the tail to the head).
+  template<typename E>
+  class DirectedEdge : public Edge<E>
+  {
+    /// \brief An invalid directed edge.
+    public: static DirectedEdge<E> NullEdge;
+
+    /// \brief Constructor.
+    /// \param[in] _vertices The vertices of the edge.
+    /// \param[in] _data The data stored in the edge.
+    /// \param[in] _weight The weight (cost) of the edge.
+    /// \param[in] _id Optional unique id.
+    public: explicit DirectedEdge(const VertexId_P &_vertices,
+                                  const E &_data,
+                                  const double _weight,
+                                  const EdgeId &_id = kNullId)
+      : Edge<E>(_vertices, _data, _weight, _id)
+    {
+    }
+
+    /// \brief Get the Id of the tail vertex in this edge.
+    /// \return An id of the tail vertex in this edge.
+    /// \sa Head()
+    public: VertexId Tail() const
+    {
+      return this->Vertices().first;
+    }
+
+    /// \brief Get the Id of the head vertex in this edge.
+    /// \return An id of the head vertex in this edge.
+    /// \sa Tail()
+    public: VertexId Head() const
+    {
+      return this->Vertices().second;
+    }
+
+    // Documentation inherited.
+    public: VertexId From(const VertexId &_from) const override
+    {
+      if (_from != this->Tail())
+        return kNullId;
+
+      return this->Head();
+    }
+
+    // Documentation inherited.
+    public: VertexId To(const VertexId &_to) const override
+    {
+      if (_to != this->Head())
+        return kNullId;
+
+      return this->Tail();
+    }
+
+    /// \brief Stream insertion operator. The output uses DOT graph
+    /// description language.
+    /// \param[out] _out The output stream.
+    /// \param[in] _e Edge to write to the stream.
+    /// \ref https://en.wikipedia.org/wiki/DOT_(graph_description_language).
+    public: friend std::ostream &operator<<(std::ostream &_out,
+                                            const DirectedEdge<E> &_e)
+    {
+      _out << "  " << _e.Tail() << " -> " << _e.Head()
+           << " [label=" << _e.Weight() << "];" << std::endl;
+      return _out;
+    }
+  };
+
+  /// \brief An invalid directed edge.
+  template<typename E>
+  DirectedEdge<E> DirectedEdge<E>::NullEdge(
+    VertexId_P(kNullId, kNullId), E(), 1.0, kNullId);
+}
+}
+}
+#endif
diff --git a/include/ignition/math/graph/Graph.hh b/include/ignition/math/graph/Graph.hh
new file mode 100644
index 0000000..c9f3afa
--- /dev/null
+++ b/include/ignition/math/graph/Graph.hh
@@ -0,0 +1,763 @@
+/*
+ * Copyright (C) 2017 Open Source Robotics Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+*/
+#ifndef IGNITION_MATH_GRAPH_GRAPH_HH_
+#define IGNITION_MATH_GRAPH_GRAPH_HH_
+
+#include <cassert>
+#include <iostream>
+#include <map>
+#include <string>
+#include <vector>
+
+#include "ignition/math/graph/Edge.hh"
+#include "ignition/math/graph/Vertex.hh"
+
+namespace ignition
+{
+namespace math
+{
+namespace graph
+{
+  /// \brief A generic graph class.
+  /// Both vertices and edges can store user information. A vertex could be
+  /// created passing a custom Id if needed, otherwise it will be choosen
+  /// internally. The vertices also have a name that could be reused among
+  /// other vertices if needed. This class supports the use of different edge
+  /// types (e.g. directed or undirected edges).
+  ///
+  /// <b> Example directed graph</b>
+  //
+  /// \code{.cpp}
+  ///
+  /// // Create a directed graph that is capable of storing integer data in the
+  /// // vertices and double data on the edges.
+  /// ignition::math::graph::DirectedGraph<int, double> graph(
+  ///   // Create the vertices, with default data and vertex ids.
+  ///   {
+  ///     {"vertex1"}, {"vertex2"}, {"vertex3"}
+  ///   },
+  ///   // Create the edges, with default data and weight values.
+  ///   {
+  ///     // Edge from vertex 0 to vertex 1. Each number refers to a vertex id.
+  ///     // Vertex ids start from zero.
+  ///     {{0, 1}}, {{1, 2}}
+  ///   });
+  ///
+  /// // You can assign data to vertices.
+  /// ignition::math::graph::DirectedGraph<int, double> graph2(
+  ///   // Create the vertices, with custom data and default vertex ids.
+  ///   {
+  ///     {"vertex1", 1}, {"vertex2", 2}, {"vertex3", 10}
+  ///   },
+  ///   // Create the edges, with default data and weight values.
+  ///   {
+  ///     // Edge from vertex 0 to vertex 1. Each number refers to a vertex id
+  ///     // specified above.
+  ///     {{0, 2}}, {{1, 2}}
+  ///   });
+  ///
+  ///
+  /// // It's also possible to specify vertex ids.
+  /// ignition::math::graph::DirectedGraph<int, double> graph3(
+  ///   // Create the vertices with custom data and vertex ids.
+  ///   {
+  ///     {"vertex1", 1, 2}, {"vertex2", 2, 3}, {"vertex3", 10, 4}
+  ///   },
+  ///   // Create the edges, with custom data and default weight values.
+  ///   {
+  ///     {{2, 3}, 6.3}, {{3, 4}, 4.2}
+  ///   });
+  ///
+  /// // Finally, you can also assign weights to the edges.
+  /// ignition::math::graph::DirectedGraph<int, double> graph4(
+  ///   // Create the vertices with custom data and vertex ids.
+  ///   {
+  ///     {"vertex1", 1, 2}, {"vertex2", 2, 3}, {"vertex3", 10, 4}
+  ///   },
+  ///   // Create the edges, with custom data and default weight values
+  ///   {
+  ///     {{2, 3}, 6.3, 1.1}, {{3, 4}, 4.2, 2.3}
+  ///   });
+  /// \endcode
+  template<typename V, typename E, typename EdgeType>
+  class Graph
+  {
+    /// \brief Default constructor.
+    public: Graph() = default;
+
+    /// \brief Constructor.
+    /// \param[in] _vertices Collection of vertices.
+    /// \param[in] _edges Collection of edges.
+    public: Graph(const std::vector<Vertex<V>> &_vertices,
+                  const std::vector<EdgeInitializer<E>> &_edges)
+    {
+      // Add all vertices.
+      for (auto const &v : _vertices)
+      {
+        if (!this->AddVertex(v.Name(), v.Data(), v.Id()).Valid())
+        {
+          std::cerr << "Invalid vertex with Id [" << v.Id() << "]. Ignoring."
+                    << std::endl;
+        }
+      }
+
+      // Add all edges.
+      for (auto const &e : _edges)
+      {
+        if (!this->AddEdge(e.vertices, e.data, e.weight).Valid())
+          std::cerr << "Ignoring edge" << std::endl;
+      }
+    }
+
+    /// \brief Add a new vertex to the graph.
+    /// \param[in] _name Name of the vertex. It doesn't have to be unique.
+    /// \param[in] _data Data to be stored in the vertex.
+    /// \param[in] _id Optional Id to be used for this vertex. This Id must
+    /// be unique.
+    /// \return A reference to the new vertex.
+    public: Vertex<V> &AddVertex(const std::string &_name,
+                                 const V &_data,
+                                 const VertexId &_id = kNullId)
+    {
+      auto id = _id;
+
+      // The user didn't provide an Id, we generate it.
+      if (id == kNullId)
+      {
+        id = this->NextVertexId();
+
+        // No space for new Ids.
+        if (id == kNullId)
+        {
+          std::cerr << "[Graph::AddVertex()] The limit of vertices has been "
+                    << "reached. Ignoring vertex." << std::endl;
+          return Vertex<V>::NullVertex;
+        }
+      }
+
+      // Create the vertex.
+      auto ret = this->vertices.insert(
+        std::make_pair(id, Vertex<V>(_name, _data, id)));
+
+      // The Id already exists.
+      if (!ret.second)
+      {
+        std::cerr << "[Graph::AddVertex()] Repeated vertex [" << id << "]"
+                  << std::endl;
+        return Vertex<V>::NullVertex;
+      }
+
+      // Link the vertex with an empty list of edges.
+      this->adjList[id] = EdgeId_S();
+
+      // Update the map of names.
+      this->names.insert(std::make_pair(_name, id));
+
+      return ret.first->second;
+    }
+
+    /// \brief The collection of all vertices in the graph.
+    /// \return A map of vertices, where keys are Ids and values are
+    /// references to the vertices.
+    public: const VertexRef_M<V> Vertices() const
+    {
+      VertexRef_M<V> res;
+      for (auto const &v : this->vertices)
+        res.emplace(std::make_pair(v.first, std::cref(v.second)));
+
+      return std::move(res);
+    }
+
+    /// \brief The collection of all vertices in the graph with name == _name.
+    /// \return A map of vertices, where keys are Ids and values are
+    /// references to the vertices.
+    public: const VertexRef_M<V> Vertices(const std::string &_name) const
+    {
+      VertexRef_M<V> res;
+      for (auto const &vertex : this->vertices)
+      {
+        if (vertex.second.Name() == _name)
+          res.emplace(std::make_pair(vertex.first, std::cref(vertex.second)));
+      }
+
+      return std::move(res);
+    }
+
+    /// \brief Add a new edge to the graph.
+    /// \param[in] _vertices The set of Ids of the two vertices.
+    /// \param[in] _data User data.
+    /// \return Reference to the new edge created or NullEdge if the
+    /// edge was not created (e.g. incorrect vertices).
+    public: EdgeType &AddEdge(const VertexId_P &_vertices,
+                              const E &_data,
+                              const double _weight = 1.0)
+    {
+      auto id = this->NextEdgeId();
+
+      // No space for new Ids.
+      if (id == kNullId)
+      {
+        std::cerr << "[Graph::AddEdge()] The limit of edges has been reached. "
+                  << "Ignoring edge." << std::endl;
+        return EdgeType::NullEdge;
+      }
+
+      EdgeType newEdge(_vertices, _data, _weight, id);
+      return this->LinkEdge(std::move(newEdge));
+    }
+
+    /// \brief Links an edge to the graph. This function verifies that the
+    /// edge's two vertices exist in the graph, copies the edge into the
+    /// graph's internal data structure, and returns a reference to this
+    /// new edge.
+    /// \param[in] _edge An edge to copy into the graph.
+    /// \return A reference to the new edge.
+    public: EdgeType &LinkEdge(const EdgeType &_edge)
+    {
+      auto edgeVertices = _edge.Vertices();
+
+      // Sanity check: Both vertices should exist.
+      for (auto const &v : {edgeVertices.first, edgeVertices.second})
+      {
+        if (this->vertices.find(v) == this->vertices.end())
+          return EdgeType::NullEdge;
+      }
+
+      // Link the new edge.
+      for (auto const &v : {edgeVertices.first, edgeVertices.second})
+      {
+        if (v != kNullId)
+        {
+          auto vertexIt = this->adjList.find(v);
+          assert(vertexIt != this->adjList.end());
+          vertexIt->second.insert(_edge.Id());
+        }
+      }
+
+      auto ret = this->edges.insert(std::make_pair(_edge.Id(), _edge));
+
+      // Return the new edge.
+      return ret.first->second;
+    }
+
+    /// \brief The collection of all edges in the graph.
+    /// \return A map of edges, where keys are Ids and values are references
+    /// to the edges.
+    public: const EdgeRef_M<EdgeType> Edges() const
+    {
+      EdgeRef_M<EdgeType> res;
+      for (auto const &edge : this->edges)
+      {
+        res.emplace(std::make_pair(edge.first, std::cref(edge.second)));
+      }
+
+      return std::move(res);
+    }
+
+    /// \brief Get all vertices that are directly connected with one edge
+    /// from a given vertex. In other words, this function will return
+    /// child vertices of the given vertex (all vertices from the given
+    /// vertex).  E.g. j is adjacent from i (the given vertex) if there is an
+    /// edge (i->j).
+    ///
+    /// In an undirected graph, the result of this function will match
+    /// the result provided by AdjacentsTo.
+    ///
+    /// \param[in] _vertex The Id of the vertex from which adjacent
+    /// vertices will be returned.
+    /// \return A map of vertices, where keys are Ids and values are
+    /// references to the vertices. This is the set of adjacent vertices.
+    /// An empty map will be returned when the _vertex is not found in the
+    /// graph.
+    public: VertexRef_M<V> AdjacentsFrom(const VertexId &_vertex) const
+    {
+      VertexRef_M<V> res;
+
+      // Make sure the vertex exists
+      auto vertexIt = this->adjList.find(_vertex);
+      if (vertexIt == this->adjList.end())
+        return res;
+
+      for (auto const &edgeId : vertexIt->second)
+      {
+        const auto &edge = this->EdgeFromId(edgeId);
+        auto neighborVertexId = edge.From(_vertex);
+        if (neighborVertexId != kNullId)
+        {
+          const auto &neighborVertex = this->VertexFromId(neighborVertexId);
+          res.emplace(
+            std::make_pair(neighborVertexId, std::cref(neighborVertex)));
+        }
+      }
+
+      return res;
+    }
+
+    /// \brief Get all vertices that are directly connected with one edge
+    /// from a given vertex. In other words, this function will return
+    /// child vertices of the given vertex (all vertices from the given
+    /// vertex).  E.g. j is adjacent from i (the given vertex) if there is an
+    /// edge (i->j).
+    ///
+    /// In an undirected graph, the result of this function will match
+    /// the result provided by AdjacentsTo.
+    ///
+    /// \param[in] _vertex The Id of the vertex from which adjacent
+    /// vertices will be returned.
+    /// \return A map of vertices, where keys are Ids and values are
+    /// references to the vertices. This is the set of adjacent vertices.
+    /// An empty map will be returned when the _vertex is not found in the
+    /// graph.
+    public: VertexRef_M<V> AdjacentsFrom(const Vertex<V> &_vertex) const
+    {
+      return this->AdjacentsFrom(_vertex.Id());
+    }
+
+    /// \brief Get all vertices that are directly connected with one edge
+    /// to a given vertex. In other words, this function will return
+    /// child vertices of the given vertex (all vertices from the given
+    /// vertex).
+    ///
+    /// In an undirected graph, the result of this function will match
+    /// the result provided by AdjacentsFrom.
+    ///
+    /// E.g. i is adjacent to j (the given vertex) if there is an
+    /// edge (i->j).
+    /// \param[in] _vertex The Id of the vertex to check adjacentsTo.
+    /// \return A map of vertices, where keys are Ids and values are
+    /// references to the vertices. An empty map is returned if the
+    /// _vertex is not present in this graph, or when there are no
+    /// adjacent vertices.
+    public: VertexRef_M<V> AdjacentsTo(const VertexId &_vertex) const
+    {
+      auto incidentEdges = this->IncidentsTo(_vertex);
+
+      VertexRef_M<V> res;
+      for (auto const &incidentEdgeRef : incidentEdges)
+      {
+        const auto &incidentEdgeId = incidentEdgeRef.first;
+        const auto &incidentEdge = this->EdgeFromId(incidentEdgeId);
+        const auto &neighborVertexId = incidentEdge.To(_vertex);
+        const auto &neighborVertex = this->VertexFromId(neighborVertexId);
+        res.emplace(
+            std::make_pair(neighborVertexId, std::cref(neighborVertex)));
+      }
+
+      return res;
+    }
+
+    /// \brief Get all vertices that are directly connected with one edge
+    /// to a given vertex. In other words, this function will return
+    /// child vertices of the given vertex (all vertices from the given
+    /// vertex).
+    ///
+    /// In an undirected graph, the result of this function will match
+    /// the result provided by AdjacentsFrom.
+    ///
+    /// E.g. i is adjacent to j (the given vertex) if there is an
+    /// edge (i->j).
+    /// \param[in] _vertex The vertex to check adjacentsTo.
+    /// \return A map of vertices, where keys are Ids and values are
+    /// references to the vertices. An empty map is returned if the
+    /// _vertex is not present in this graph, or when there are no
+    /// adjacent vertices.
+    public: VertexRef_M<V> AdjacentsTo(const Vertex<V> &_vertex) const
+    {
+      return this->AdjacentsTo(_vertex.Id());
+    }
+
+    /// \brief Get the number of edges incident to a vertex.
+    /// \param[in] _vertex The vertex Id.
+    /// \return The number of edges incidents to a vertex.
+    public: size_t InDegree(const VertexId &_vertex) const
+    {
+      return this->IncidentsTo(_vertex).size();
+    }
+
+    /// \brief Get the number of edges incident to a vertex.
+    /// \param[in] _vertex The vertex.
+    /// \return The number of edges incidents to a vertex.
+    public: size_t InDegree(const Vertex<V> &_vertex) const
+    {
+      return this->IncidentsTo(this->VertexFromId(_vertex.Id())).size();
+    }
+
+    /// \brief Get the number of edges incident from a vertex.
+    /// \param[in] _vertex The vertex Id.
+    /// \return The number of edges incidents from a vertex.
+    public: size_t OutDegree(const VertexId &_vertex) const
+    {
+      return this->IncidentsFrom(_vertex).size();
+    }
+
+    /// \brief Get the number of edges incident from a vertex.
+    /// \param[in] _vertex The vertex.
+    /// \return The number of edges incidents from a vertex.
+    public: size_t OutDegree(const Vertex<V> &_vertex) const
+    {
+      return this->IncidentsFrom(this->VertexFromId(_vertex.Id())).size();
+    }
+
+    /// \brief Get the set of outgoing edges from a given vertex.
+    /// \param[in] _vertex Id of the vertex.
+    /// \return A map of edges, where keys are Ids and values are
+    /// references to the edges. An empty map is returned when the provided
+    /// vertex does not exist, or when there are no outgoing edges.
+    public: const EdgeRef_M<EdgeType> IncidentsFrom(const VertexId &_vertex)
+      const
+    {
+      EdgeRef_M<EdgeType> res;
+
+      const auto &adjIt = this->adjList.find(_vertex);
+      if (adjIt == this->adjList.end())
+        return res;
+
+      const auto &edgeIds = adjIt->second;
+      for (auto const &edgeId : edgeIds)
+      {
+        const auto &edge = this->EdgeFromId(edgeId);
+        if (edge.From(_vertex) != kNullId)
+          res.emplace(std::make_pair(edge.Id(), std::cref(edge)));
+      }
+
+      return std::move(res);
+    }
+
+    /// \brief Get the set of outgoing edges from a given vertex.
+    /// \param[in] _vertex The vertex.
+    /// \return A map of edges, where keys are Ids and values are
+    /// references to the edges. An empty map is returned when the provided
+    /// vertex does not exist, or when there are no outgoing edges.
+    public: const EdgeRef_M<EdgeType> IncidentsFrom(
+                const Vertex<V> &_vertex) const
+    {
+      return this->IncidentsFrom(_vertex.Id());
+    }
+
+    /// \brief Get the set of incoming edges to a given vertex.
+    /// \param[in] _vertex Id of the vertex.
+    /// \return A map of edges, where keys are Ids and values are
+    /// references to the edges. An empty map is returned when the provided
+    /// vertex does not exist, or when there are no incoming edges.
+    public: const EdgeRef_M<EdgeType> IncidentsTo(
+                const VertexId &_vertex) const
+    {
+      EdgeRef_M<EdgeType> res;
+
+      const auto &adjIt = this->adjList.find(_vertex);
+      if (adjIt == this->adjList.end())
+        return res;
+
+      const auto &edgeIds = adjIt->second;
+      for (auto const &edgeId : edgeIds)
+      {
+        const auto &edge = this->EdgeFromId(edgeId);
+        if (edge.To(_vertex) != kNullId)
+          res.emplace(std::make_pair(edge.Id(), std::cref(edge)));
+      }
+
+      return std::move(res);
+    }
+
+    /// \brief Get the set of incoming edges to a given vertex.
+    /// \param[in] _vertex The vertex.
+    /// \return A map of edges, where keys are Ids and values are
+    /// references to the edges. An empty map is returned when the provided
+    /// vertex does not exist, or when there are no incoming edges.
+    public: const EdgeRef_M<EdgeType> IncidentsTo(const Vertex<V> &_vertex)
+      const
+    {
+      return this->IncidentsTo(_vertex.Id());
+    }
+
+    /// \brief Get whether the graph is empty.
+    /// \return True when there are no vertices in the graph or
+    /// false otherwise.
+    public: bool Empty() const
+    {
+      return this->vertices.empty();
+    }
+
+    /// \brief Remove an existing vertex from the graph.
+    /// \param[in] _vertex Id of the vertex to be removed.
+    /// \return True when the vertex was removed or false otherwise.
+    public: bool RemoveVertex(const VertexId &_vertex)
+    {
+      auto vIt = this->vertices.find(_vertex);
+      if (vIt == this->vertices.end())
+        return false;
+
+      std::string name = vIt->second.Name();
+
+      // Remove incident edges.
+      auto incidents = this->IncidentsTo(_vertex);
+      for (auto edgePair : incidents)
+        this->RemoveEdge(edgePair.first);
+
+      // Remove all outgoing edges.
+      incidents = this->IncidentsFrom(_vertex);
+      for (auto edgePair : incidents)
+        this->RemoveEdge(edgePair.first);
+
+      // Remove the vertex (key) from the adjacency list.
+      this->adjList.erase(_vertex);
+
+      // Remove the vertex.
+      this->vertices.erase(_vertex);
+
+      // Get an iterator to all vertices sharing name.
+      auto iterPair = this->names.equal_range(name);
+      for (auto it = iterPair.first; it != iterPair.second; ++it)
+      {
+        if (it->second == _vertex)
+        {
+          this->names.erase(it);
+          break;
+        }
+      }
+
+      return true;
+    }
+
+    /// \brief Remove an existing vertex from the graph.
+    /// \param[in] _vertex The vertex to be removed.
+    /// \return True when the vertex was removed or false otherwise.
+    public: bool RemoveVertex(Vertex<V> &_vertex)
+    {
+      return this->RemoveVertex(_vertex.Id());
+    }
+
+    /// \brief Remove all vertices with name == _name.
+    /// \param[in] _name Name of the vertices to be removed.
+    /// \return The number of vertices removed.
+    public: size_t RemoveVertices(const std::string &_name)
+    {
+      size_t numVertices = this->names.count(_name);
+      size_t result = 0;
+      for (size_t i = 0; i < numVertices; ++i)
+      {
+        auto iter = this->names.find(_name);
+        if (this->RemoveVertex(iter->second))
+          ++result;
+      }
+
+      return result;
+    }
+
+    /// \brief Remove an existing edge from the graph. After the removal, it
+    /// won't be possible to reach any of the vertices from the edge, unless
+    /// there are other edges that connect the to vertices.
+    /// \param[in] _edge Id of the edge to be removed.
+    /// \return True when the edge was removed or false otherwise.
+    public: bool RemoveEdge(const EdgeId &_edge)
+    {
+      auto edgeIt = this->edges.find(_edge);
+      if (edgeIt == this->edges.end())
+        return false;
+
+      auto edgeVertices = edgeIt->second.Vertices();
+
+      // Unlink the edge.
+      for (auto const &v : {edgeVertices.first, edgeVertices.second})
+      {
+        if (edgeIt->second.From(v) != kNullId)
+        {
+          auto vertex = this->adjList.find(v);
+          assert(vertex != this->adjList.end());
+          vertex->second.erase(_edge);
+        }
+      }
+
+      this->edges.erase(_edge);
+
+      return true;
+    }
+
+    /// \brief Remove an existing edge from the graph. After the removal, it
+    /// won't be possible to reach any of the vertices from the edge, unless
+    /// there are other edges that connect the to vertices.
+    /// \param[in] _edge The edge to be removed.
+    /// \return True when the edge was removed or false otherwise.
+    public: bool RemoveEdge(EdgeType &_edge)
+    {
+      return this->RemoveEdge(_edge.Id());
+    }
+
+    /// \brief Get a reference to a vertex using its Id.
+    /// \param[in] _id The Id of the vertex.
+    /// \return A reference to the vertex with Id = _id or NullVertex if
+    /// not found.
+    public: const Vertex<V> &VertexFromId(const VertexId &_id) const
+    {
+      auto iter = this->vertices.find(_id);
+      if (iter == this->vertices.end())
+        return Vertex<V>::NullVertex;
+
+      return iter->second;
+    }
+
+    /// \brief Get a mutable reference to a vertex using its Id.
+    /// \param[in] _id The Id of the vertex.
+    /// \return A mutable reference to the vertex with Id = _id or NullVertex
+    /// if not found.
+    public: Vertex<V> &VertexFromId(const VertexId &_id)
+    {
+      auto iter = this->vertices.find(_id);
+      if (iter == this->vertices.end())
+        return Vertex<V>::NullVertex;
+
+      return iter->second;
+    }
+
+    /// \brief Get a reference to an edge using its Id.
+    /// \param[in] _id The Id of the edge.
+    /// \return A reference to the edge with Id = _id or NullEdge if
+    /// not found.
+    public: const EdgeType &EdgeFromId(const EdgeId &_id) const
+    {
+      auto iter = this->edges.find(_id);
+      if (iter == this->edges.end())
+        return EdgeType::NullEdge;
+
+      return iter->second;
+    }
+
+    /// \brief Stream insertion operator. The output uses DOT graph
+    /// description language.
+    /// \param[out] _out The output stream.
+    /// \param[in] _g Graph to write to the stream.
+    /// \ref https://en.wikipedia.org/wiki/DOT_(graph_description_language).
+    public: template<typename VV, typename EE, typename EEdgeType>
+    friend std::ostream &operator<<(std::ostream &_out,
+                                    const Graph<VV, EE, EEdgeType> &_g);
+
+    /// \brief Get an available Id to be assigned to a new vertex.
+    /// \return The next available Id or kNullId if there aren't ids available.
+    private: VertexId &NextVertexId()
+    {
+      while (this->vertices.find(this->nextVertexId) != this->vertices.end()
+          && this->nextVertexId < MAX_UI64)
+      {
+        ++this->nextVertexId;
+      }
+
+      return this->nextVertexId;
+    }
+
+    /// \brief Get an available Id to be assigned to a new edge.
+    /// \return The next available Id or kNullId if there aren't ids available.
+    private: VertexId &NextEdgeId()
+    {
+      while (this->edges.find(this->nextEdgeId) != this->edges.end() &&
+             this->nextEdgeId < MAX_UI64)
+      {
+        ++this->nextEdgeId;
+      }
+
+      return this->nextEdgeId;
+    }
+
+    /// \brief The next vertex Id to be assigned to a new vertex.
+    protected: VertexId nextVertexId = 0u;
+
+    /// \brief The next edge Id to be assigned to a new edge.
+    protected: VertexId nextEdgeId = 0u;
+
+    /// \brief The set of vertices.
+    private: std::map<VertexId, Vertex<V>> vertices;
+
+    /// \brief The set of edges.
+    private: std::map<EdgeId, EdgeType> edges;
+
+    /// \brief The adjacency list.
+    /// A map where the keys are vertex Ids. For each vertex (v)
+    /// with id (vId), the map value contains a set of edge Ids. Each of
+    /// the edges (e) with Id (eId) represents a connected path from (v) to
+    /// another vertex via (e).
+    private: std::map<VertexId, EdgeId_S> adjList;
+
+    /// \brief Association between names and vertices curently used.
+    private: std::multimap<std::string, VertexId> names;
+  };
+
+  /////////////////////////////////////////////////
+  /// Partial template specification for undirected edges.
+  template<typename VV, typename EE>
+  std::ostream &operator<<(std::ostream &_out,
+                           const Graph<VV, EE, UndirectedEdge<EE>> &_g)
+  {
+    _out << "graph {" << std::endl;
+
+    // All vertices with the name and Id as a "label" attribute.
+    for (auto const &vertexMap : _g.Vertices())
+    {
+      auto vertex = vertexMap.second.get();
+      _out << vertex;
+    }
+
+    // All edges.
+    for (auto const &edgeMap : _g.Edges())
+    {
+      auto edge = edgeMap.second.get();
+      _out << edge;
+    }
+
+    _out << "}" << std::endl;
+
+    return _out;
+  }
+
+  /////////////////////////////////////////////////
+  /// Partial template specification for directed edges.
+  template<typename VV, typename EE>
+  std::ostream &operator<<(std::ostream &_out,
+                           const Graph<VV, EE, DirectedEdge<EE>> &_g)
+  {
+    _out << "digraph {" << std::endl;
+
+    // All vertices with the name and Id as a "label" attribute.
+    for (auto const &vertexMap : _g.Vertices())
+    {
+      auto vertex = vertexMap.second.get();
+      _out << vertex;
+    }
+
+    // All edges.
+    for (auto const &edgeMap : _g.Edges())
+    {
+      auto edge = edgeMap.second.get();
+      _out << edge;
+    }
+
+    _out << "}" << std::endl;
+
+    return _out;
+  }
+
+  /// \def UndirectedGraph
+  /// \brief An undirected graph.
+  template<typename V, typename E>
+  using UndirectedGraph = Graph<V, E, UndirectedEdge<E>>;
+
+  /// \def DirectedGraph
+  /// \brief A directed graph.
+  template<typename V, typename E>
+  using DirectedGraph = Graph<V, E, DirectedEdge<E>>;
+}
+}
+}
+#endif
diff --git a/include/ignition/math/graph/GraphAlgorithms.hh b/include/ignition/math/graph/GraphAlgorithms.hh
new file mode 100644
index 0000000..b8796e0
--- /dev/null
+++ b/include/ignition/math/graph/GraphAlgorithms.hh
@@ -0,0 +1,323 @@
+/*
+ * Copyright (C) 2017 Open Source Robotics Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+*/
+#ifndef IGNITION_MATH_GRAPH_GRAPHALGORITHMS_HH_
+#define IGNITION_MATH_GRAPH_GRAPHALGORITHMS_HH_
+
+#include <functional>
+#include <list>
+#include <map>
+#include <queue>
+#include <stack>
+#include <utility>
+#include <vector>
+
+#include "ignition/math/graph/Graph.hh"
+#include "ignition/math/Helpers.hh"
+
+namespace ignition
+{
+namespace math
+{
+namespace graph
+{
+  /// \def CostInfo.
+  /// \brief Used in Dijkstra. For a given source vertex, this pair represents
+  /// the cost (first element) to reach a destination vertex (second element).
+  using CostInfo = std::pair<double, VertexId>;
+
+  /// \brief Breadth first sort (BFS).
+  /// Starting from the vertex == _from, it traverses the graph exploring the
+  /// neighbors first, before moving to the next level neighbors.
+  /// \param[in] _graph A graph.
+  /// \param[in] _from The starting vertex.
+  /// \return The vector of vertices Ids traversed in a breadth first manner.
+  template<typename V, typename E, typename EdgeType>
+  std::vector<VertexId> BreadthFirstSort(const Graph<V, E, EdgeType> &_graph,
+                                         const VertexId &_from)
+  {
+    // Create an auxiliary graph, where the data is just a boolean value that
+    // stores whether the vertex has been visited or not.
+    Graph<bool, E, EdgeType> visitorGraph;
+
+    // Copy the vertices (just the Id).
+    for (auto const &v : _graph.Vertices())
+      visitorGraph.AddVertex("", false, v.first);
+
+    // Copy the edges (without data).
+    for (auto const &e : _graph.Edges())
+      visitorGraph.AddEdge(e.second.get().Vertices(), E());
+
+    std::vector<VertexId> visited;
+    std::list<VertexId> pending = {_from};
+
+    while (!pending.empty())
+    {
+      auto vId = pending.front();
+      pending.pop_front();
+
+      // If the vertex has been visited, skip.
+      auto &vertex = visitorGraph.VertexFromId(vId);
+      if (vertex.Data())
+        continue;
+
+      visited.push_back(vId);
+      vertex.Data() = true;
+
+      // Add more vertices to visit if they haven't been visited yet.
+      auto adjacents = visitorGraph.AdjacentsFrom(vId);
+      for (auto const &adj : adjacents)
+      {
+        vId = adj.first;
+        auto &v = adj.second.get();
+        if (!v.Data())
+          pending.push_back(vId);
+      }
+    }
+
+    return visited;
+  }
+
+  /// \brief Depth first sort (DFS).
+  /// Starting from the vertex == _from, it visits the graph as far as
+  /// possible along each branch before backtracking.
+  /// \param[in] _graph A graph.
+  /// \param[in] _from The starting vertex.
+  /// \return The vector of vertices Ids visited in a depth first manner.
+  template<typename V, typename E, typename EdgeType>
+  std::vector<VertexId> DepthFirstSort(const Graph<V, E, EdgeType> &_graph,
+                                       const VertexId &_from)
+  {
+    // Create an auxiliary graph, where the data is just a boolean value that
+    // stores whether the vertex has been visited or not.
+    Graph<bool, E, EdgeType> visitorGraph;
+
+    // Copy the vertices (just the Id).
+    for (auto const &v : _graph.Vertices())
+      visitorGraph.AddVertex("", false, v.first);
+
+    // Copy the edges (without data).
+    for (auto const &e : _graph.Edges())
+      visitorGraph.AddEdge(e.second.get().Vertices(), E());
+
+    std::vector<VertexId> visited;
+    std::stack<VertexId> pending({_from});
+
+    while (!pending.empty())
+    {
+      auto vId = pending.top();
+      pending.pop();
+
+      // If the vertex has been visited, skip.
+      auto &vertex = visitorGraph.VertexFromId(vId);
+      if (vertex.Data())
+        continue;
+
+      visited.push_back(vId);
+      vertex.Data() = true;
+
+      // Add more vertices to visit if they haven't been visited yet.
+      auto adjacents = visitorGraph.AdjacentsFrom(vId);
+      for (auto const &adj : adjacents)
+      {
+        vId = adj.first;
+        auto &v = adj.second.get();
+        if (!v.Data())
+          pending.push(vId);
+      }
+    }
+
+    return visited;
+  }
+
+  /// \brief Dijkstra algorithm.
+  /// Find the shortest path between the vertices in a graph.
+  /// If only a graph and a source vertex is provided, the algorithm will
+  /// find shortest paths from the source vertex to all other vertices in the
+  /// graph. If an additional destination vertex is provided, the algorithm
+  /// will stop when the shortest path is found between the source and
+  /// destination vertex.
+  /// \param[in] _graph A graph.
+  /// \param[in] _from The starting vertex.
+  /// \param[in] _to Optional destination vertex.
+  /// \return A map where the keys are the destination vertices. For each
+  /// destination, the value is another pair, where the key is the shortest
+  /// cost from the origin vertex. The value is the previous neighbor Id in the
+  /// shortest path.
+  /// Note: In the case of providing a destination vertex, only the entry in the
+  /// map with key = _to should be used. The rest of the map may contain
+  /// incomplete information. If you want all shortest paths to all other
+  /// vertices, please remove the destination vertex.
+  /// If the source or destination vertex don't exist, the function will return
+  /// an empty map.
+  ///
+  /// E.g.: Given the following undirected graph, g, with five vertices:
+  ///
+  ///              (6)                |
+  ///           0-------1             |
+  ///           |      /|\            |
+  ///           |     / | \(5)        |
+  ///           | (2)/  |  \          |
+  ///           |   /   |   2         |
+  ///        (1)|  / (2)|  /          |
+  ///           | /     | /(5)        |
+  ///           |/      |/            |
+  ///           3-------4             |
+  ///              (1)                |
+  ///
+  /// This is the resut of Dijkstra(g, 0):
+  ///
+  /// ================================
+  /// | Dst | Cost | Previous vertex |
+  /// ================================
+  /// |  0  |  0   |        0        |
+  /// |  1  |  3   |        3        |
+  /// |  2  |  7   |        4        |
+  /// |  3  |  1   |        0        |
+  /// |  4  |  2   |        3        |
+  /// ================================
+  ///
+  /// This is the result of Dijkstra(g, 0, 3):
+  ///
+  /// ================================
+  /// | Dst | Cost | Previous vertex |
+  /// ================================
+  /// |  0  |  0   |        0        |
+  /// |  1  |ignore|     ignore      |
+  /// |  2  |ignore|     ignore      |
+  /// |  3  |  1   |        0        |
+  /// |  4  |ignore|     ignore      |
+  /// ================================
+  template<typename V, typename E, typename EdgeType>
+  std::map<VertexId, CostInfo> Dijkstra(const Graph<V, E, EdgeType> &_graph,
+                                        const VertexId &_from,
+                                        const VertexId &_to = kNullId)
+  {
+    auto allVertices = _graph.Vertices();
+
+    // Sanity check: The source vertex should exist.
+    if (allVertices.find(_from) == allVertices.end())
+    {
+      std::cerr << "Vertex [" << _from << "] Not found" << std::endl;
+      return {};
+    }
+
+    // Sanity check: The destination vertex should exist (if used).
+    if (_to != kNullId &&
+        allVertices.find(_to) == allVertices.end())
+    {
+      std::cerr << "Vertex [" << _from << "] Not found" << std::endl;
+      return {};
+    }
+
+    // Store vertices that are being preprocessed.
+    std::priority_queue<CostInfo,
+      std::vector<CostInfo>, std::greater<CostInfo>> pq;
+
+    // Create a map for distances and next neightbor and initialize all
+    // distances as infinite.
+    std::map<VertexId, CostInfo> dist;
+    for (auto const &v : allVertices)
+    {
+      auto id = v.first;
+      dist[id] = std::make_pair(MAX_D, kNullId);
+    }
+
+    // Insert _from in the priority queue and initialize its distance as 0.
+    pq.push(std::make_pair(0.0, _from));
+    dist[_from] = std::make_pair(0.0, _from);
+
+    while (!pq.empty())
+    {
+      // This is the minimum distance vertex.
+      VertexId u = pq.top().second;
+
+      // Shortcut: Destination vertex found, exiting.
+      if (_to != kNullId && _to == u)
+        break;
+
+      pq.pop();
+
+      for (auto const &edgePair : _graph.IncidentsFrom(u))
+      {
+        const auto &edge = edgePair.second.get();
+        const auto &v = edge.From(u);
+        double weight = edge.Weight();
+
+        //  If there is shorted path to v through u.
+        if (dist[v].first > dist[u].first + weight)
+        {
+          // Updating distance of v.
+          dist[v] = std::make_pair(dist[u].first + weight, u);
+          pq.push(std::make_pair(dist[v].first, v));
+        }
+      }
+    }
+
+    return dist;
+  }
+
+  /// \brief Calculate the connected components of an undirected graph.
+  /// A connected component of an undirected graph is a subgraph in which any
+  /// two vertices are connected to each other by paths, and which is connected
+  /// to no additional vertices in the supergraph.
+  /// \ref https://en.wikipedia.org/wiki/Connected_component_(graph_theory)
+  /// \param[in] _graph A graph.
+  /// \return A vector of graphs. Each element of the graph is a component
+  /// (subgraph) of the original graph.
+  template<typename V, typename E>
+  std::vector<UndirectedGraph<V, E>> ConnectedComponents(
+    const UndirectedGraph<V, E> &_graph)
+  {
+    std::map<VertexId, unsigned int> visited;
+    unsigned int componentCount = 0;
+
+    for (auto const &v : _graph.Vertices())
+    {
+      if (visited.find(v.first) == visited.end())
+      {
+        auto component = BreadthFirstSort(_graph, v.first);
+        for (auto const &vId : component)
+          visited[vId] = componentCount;
+        ++componentCount;
+      }
+    }
+
+    std::vector<UndirectedGraph<V, E>> res(componentCount);
+
+    // Create the vertices.
+    for (auto const &vPair : _graph.Vertices())
+    {
+      const auto &v = vPair.second.get();
+      const auto &componentId = visited[v.Id()];
+      res[componentId].AddVertex(v.Name(), v.Data(), v.Id());
+    }
+
+    // Create the edges.
+    for (auto const &ePair : _graph.Edges())
+    {
+      const auto &e = ePair.second.get();
+      const auto &vertices = e.Vertices();
+      const auto &componentId = visited[vertices.first];
+      res[componentId].AddEdge(vertices, e.Data(), e.Weight());
+    }
+
+    return res;
+  }
+}
+}
+}
+#endif
diff --git a/include/ignition/math/graph/Vertex.hh b/include/ignition/math/graph/Vertex.hh
new file mode 100644
index 0000000..20f39dc
--- /dev/null
+++ b/include/ignition/math/graph/Vertex.hh
@@ -0,0 +1,140 @@
+/*
+ * Copyright (C) 2017 Open Source Robotics Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+*/
+#ifndef IGNITION_MATH_GRAPH_VERTEX_HH_
+#define IGNITION_MATH_GRAPH_VERTEX_HH_
+
+// uint64_t
+#include <cstdint>
+#include <functional>
+#include <iostream>
+#include <map>
+#include <string>
+#include <utility>
+
+#include <ignition/math/Helpers.hh>
+
+namespace ignition
+{
+namespace math
+{
+namespace graph
+{
+  /// \def VertexId.
+  /// \brief The unique Id of each vertex.
+  using VertexId = uint64_t;
+
+  /// \def VertexId_P
+  /// \brief A pair of two vertex Ids.
+  using VertexId_P = std::pair<VertexId, VertexId>;
+
+  /// \brief Represents an invalid Id.
+  static const VertexId kNullId = MAX_UI64;
+
+  /// \brief A vertex of a graph. It stores user information, an optional name,
+  /// and keeps an internal unique Id. This class does not enforce to choose a
+  /// unique name.
+  template<typename V>
+  class Vertex
+  {
+    /// \brief An invalid vertex.
+    public: static Vertex<V> NullVertex;
+
+    /// \brief Constructor.
+    /// \param[in] _name Non-unique vertex name.
+    /// \param[in] _data User information.
+    /// \param[in] _id Optional unique id.
+    public: Vertex(const std::string &_name,
+                   const V &_data = V(),
+                   const VertexId _id = kNullId)
+      : name(_name),
+        data(_data),
+        id(_id)
+    {
+    }
+
+    /// \brief Retrieve the user information.
+    /// \return Reference to the user information.
+    public: const V &Data() const
+    {
+      return this->data;
+    }
+
+    /// \brief Get a mutable reference to the user information.
+    /// \return Mutable reference to the user information.
+    public: V &Data()
+    {
+      return this->data;
+    }
+
+    /// \brief Get the vertex Id.
+    /// \return The vertex Id.
+    public: VertexId Id() const
+    {
+      return this->id;
+    }
+
+    /// \brief Get the vertex name.
+    /// \return The vertex name.
+    public: std::string Name() const
+    {
+      return this->name;
+    }
+
+    /// \brief Whether the vertex is considered valid or not (id==kNullId).
+    /// \return True when the vertex is valid or false otherwise (id==kNullId)
+    public: bool Valid() const
+    {
+      return this->id != kNullId;
+    }
+
+    /// \brief Stream insertion operator. The output uses DOT graph
+    /// description language.
+    /// \param[out] _out The output stream.
+    /// \param[in] _v Vertex to write to the stream.
+    /// \ref https://en.wikipedia.org/wiki/DOT_(graph_description_language).
+    public: friend std::ostream &operator<<(std::ostream &_out,
+                                            const Vertex<V> &_v)
+    {
+      _out << "  " << _v.Id() << " [label=\"" << _v.Name()
+           << " (" << _v.Id() << ")\"];" << std::endl;
+      return _out;
+    }
+
+    /// \brief Non-unique vertex name.
+    private: std::string name = "";
+
+    /// \brief User information.
+    private: V data;
+
+    /// \brief Unique vertex Id.
+    private: VertexId id = kNullId;
+  };
+
+  /// \brief An invalid vertex.
+  template<typename V>
+  Vertex<V> Vertex<V>::NullVertex("__null__", V(), kNullId);
+
+  /// \def VertexRef_M
+  /// \brief Map of vertices. The key is the vertex Id. The value is a
+  /// reference to the vertex.
+  template<typename V>
+  using VertexRef_M =
+    std::map<VertexId, std::reference_wrapper<const Vertex<V>>>;
+}
+}
+}
+#endif
diff --git a/include/ignition/math/math.hh.in b/include/ignition/math/math.hh.in
new file mode 100644
index 0000000..4b76db8
--- /dev/null
+++ b/include/ignition/math/math.hh.in
@@ -0,0 +1,3 @@
+// Automatically generated
+#include <ignition/math/config.hh>
+${ign_headers}
diff --git a/src/Angle.cc b/src/Angle.cc
new file mode 100644
index 0000000..def990b
--- /dev/null
+++ b/src/Angle.cc
@@ -0,0 +1,173 @@
+/*
+ * Copyright (C) 2012 Open Source Robotics Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+*/
+#include "ignition/math/Helpers.hh"
+#include "ignition/math/Angle.hh"
+
+using namespace ignition;
+using namespace math;
+
+const Angle Angle::Zero = math::Angle(0);
+const Angle Angle::Pi = math::Angle(IGN_PI);
+const Angle Angle::HalfPi = math::Angle(IGN_PI_2);
+const Angle Angle::TwoPi = math::Angle(IGN_PI * 2.0);
+
+//////////////////////////////////////////////////
+Angle::Angle()
+{
+  this->value = 0;
+}
+
+//////////////////////////////////////////////////
+Angle::Angle(const double _radian)
+{
+  this->value = _radian;
+}
+
+//////////////////////////////////////////////////
+Angle::Angle(const Angle &_angle)
+{
+  this->value = _angle.value;
+}
+
+//////////////////////////////////////////////////
+Angle::~Angle()
+{
+}
+
+//////////////////////////////////////////////////
+void Angle::Radian(double _radian)
+{
+  this->value = _radian;
+}
+
+//////////////////////////////////////////////////
+void Angle::Degree(double _degree)
+{
+  this->value = _degree * IGN_PI / 180.0;
+}
+
+//////////////////////////////////////////////////
+double Angle::Radian() const
+{
+  return this->value;
+}
+
+//////////////////////////////////////////////////
+double Angle::Degree() const
+{
+  return this->value * 180.0 / IGN_PI;
+}
+
+//////////////////////////////////////////////////
+void Angle::Normalize()
+{
+  this->value = atan2(sin(this->value), cos(this->value));
+}
+
+//////////////////////////////////////////////////
+Angle Angle::operator-(const Angle &angle) const
+{
+  return Angle(this->value - angle.value);
+}
+
+//////////////////////////////////////////////////
+Angle Angle::operator+(const Angle &angle) const
+{
+  return Angle(this->value + angle.value);
+}
+
+//////////////////////////////////////////////////
+Angle Angle::operator*(const Angle &angle) const
+{
+  return Angle(this->value * angle.value);
+}
+
+//////////////////////////////////////////////////
+Angle Angle::operator/(const Angle &angle) const
+{
+  return Angle(this->value / angle.value);
+}
+
+//////////////////////////////////////////////////
+Angle Angle::operator-=(const Angle &angle)
+{
+  this->value -= angle.value;
+  return *this;
+}
+
+//////////////////////////////////////////////////
+Angle Angle::operator+=(const Angle &angle)
+{
+  this->value += angle.value;
+  return *this;
+}
+
+//////////////////////////////////////////////////
+Angle Angle::operator*=(const Angle &angle)
+{
+  this->value *= angle.value;
+  return *this;
+}
+
+//////////////////////////////////////////////////
+Angle Angle::operator/=(const Angle &angle)
+{
+  this->value /= angle.value;
+  return *this;
+}
+
+//////////////////////////////////////////////////
+bool Angle::operator==(const Angle &angle) const
+{
+  return equal(this->value, angle.value, 0.001);
+}
+
+//////////////////////////////////////////////////
+bool Angle::operator!=(const Angle &angle) const
+{
+  return !(*this == angle);
+}
+
+//////////////////////////////////////////////////
+bool Angle::operator<(const Angle &angle) const
+{
+  return this->value < angle.value;
+}
+
+//////////////////////////////////////////////////
+bool Angle::operator<=(const Angle &angle) const
+{
+  return this->value < angle.value || math::equal(this->value, angle.value);
+}
+
+//////////////////////////////////////////////////
+bool Angle::operator>(const Angle &angle) const
+{
+  return this->value > angle.value;
+}
+
+//////////////////////////////////////////////////
+bool Angle::operator>=(const Angle &angle) const
+{
+  return this->value > angle.value || math::equal(this->value, angle.value);
+}
+
+//////////////////////////////////////////////////
+double Angle::operator()() const
+{
+  return this->value;
+}
diff --git a/src/Angle_TEST.cc b/src/Angle_TEST.cc
new file mode 100644
index 0000000..a6e6f91
--- /dev/null
+++ b/src/Angle_TEST.cc
@@ -0,0 +1,119 @@
+/*
+ * Copyright (C) 2012 Open Source Robotics Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+*/
+
+#include <gtest/gtest.h>
+
+#include <cmath>
+
+#include "ignition/math/Helpers.hh"
+#include "ignition/math/Angle.hh"
+
+using namespace ignition;
+
+/////////////////////////////////////////////////
+TEST(AngleTest, Angle)
+{
+  math::Angle angle1;
+  EXPECT_TRUE(math::equal(0.0, angle1.Radian()));
+
+  angle1.Degree(180.0);
+  EXPECT_TRUE(angle1 == IGN_PI);
+
+  EXPECT_FALSE(angle1 == IGN_PI + 0.1);
+  EXPECT_TRUE(angle1 == IGN_PI + 0.0001);
+  EXPECT_TRUE(angle1 == IGN_PI - 0.0001);
+  EXPECT_TRUE(math::Angle(0) == math::Angle(0));
+  EXPECT_TRUE(math::Angle(0) == math::Angle(0.001));
+
+  angle1 = math::Angle(0.1) - math::Angle(0.3);
+  EXPECT_TRUE(angle1 == -0.2);
+
+  math::Angle angle(0.5);
+  EXPECT_TRUE(math::equal(0.5, angle.Radian()));
+
+  angle.Radian(IGN_PI);
+  EXPECT_TRUE(math::equal(IGN_RTOD(IGN_PI), angle.Degree()));
+
+  angle.Normalize();
+  EXPECT_TRUE(math::equal(IGN_RTOD(IGN_PI), angle.Degree()));
+
+  angle = math::Angle(0.1) + math::Angle(0.2);
+  EXPECT_TRUE(math::equal(0.3, angle.Radian()));
+
+  angle = math::Angle(0.1) * math::Angle(0.2);
+  EXPECT_TRUE(math::equal(0.02, angle.Radian()));
+
+  angle = math::Angle(0.1) / math::Angle(0.2);
+  EXPECT_TRUE(math::equal(0.5, angle.Radian()));
+
+  angle -= math::Angle(0.1);
+  EXPECT_TRUE(math::equal(0.4, angle.Radian()));
+
+  angle += math::Angle(0.2);
+  EXPECT_TRUE(math::equal(0.6, angle.Radian()));
+
+  angle *= math::Angle(0.5);
+  EXPECT_TRUE(math::equal(0.3, angle.Radian()));
+
+  angle /= math::Angle(0.1);
+  EXPECT_TRUE(math::equal(3.0, angle.Radian()));
+  EXPECT_TRUE(angle == math::Angle(3));
+  EXPECT_TRUE(angle != math::Angle(2));
+  EXPECT_TRUE(angle < math::Angle(4));
+  EXPECT_TRUE(angle > math::Angle(2));
+  EXPECT_TRUE(angle >= math::Angle(3));
+  EXPECT_TRUE(angle <= math::Angle(3));
+
+  angle = 1.2;
+  EXPECT_TRUE(angle <= 1.21);
+  EXPECT_FALSE(angle <= 1.19);
+  EXPECT_TRUE(angle <= 1.2);
+  EXPECT_FALSE(angle <= -1.19);
+
+  EXPECT_TRUE(math::Angle(1.2) <= math::Angle(1.2000000001));
+  EXPECT_TRUE(math::Angle(1.2000000001) <= math::Angle(1.2));
+
+  angle = 1.2;
+  EXPECT_FALSE(angle >= 1.21);
+  EXPECT_TRUE(angle >= 1.19);
+  EXPECT_TRUE(angle >= 1.2);
+  EXPECT_TRUE(angle >= -1.19);
+
+  EXPECT_TRUE(math::Angle(1.2) >= math::Angle(1.2000000001));
+  EXPECT_TRUE(math::Angle(1.2000000001) >= math::Angle(1.2));
+}
+
+/////////////////////////////////////////////////
+TEST(AngleTest, StreamExtraction)
+{
+  math::Angle angle;
+  std::istringstream stream("1.25");
+
+  EXPECT_NEAR(*angle, 0, 1e-2);
+
+  stream >> angle;
+  EXPECT_NEAR(*angle, 1.25, 1e-2);
+}
+
+/////////////////////////////////////////////////
+TEST(AngleTest, OperatorStreamOut)
+{
+  math::Angle a(0.1);
+  std::ostringstream stream;
+  stream << a;
+  EXPECT_EQ(stream.str(), "0.1");
+}
diff --git a/src/Box.cc b/src/Box.cc
new file mode 100644
index 0000000..0dd587e
--- /dev/null
+++ b/src/Box.cc
@@ -0,0 +1,296 @@
+/*
+ * Copyright (C) 2012 Open Source Robotics Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+*/
+#include <cmath>
+#include <ignition/math/Box.hh>
+
+#include "BoxPrivate.hh"
+
+using namespace ignition;
+using namespace math;
+
+//////////////////////////////////////////////////
+Box::Box()
+: dataPtr(new BoxPrivate)
+{
+}
+
+//////////////////////////////////////////////////
+Box::Box(double _vec1X, double _vec1Y, double _vec1Z,
+         double _vec2X, double _vec2Y, double _vec2Z)
+: dataPtr(new BoxPrivate)
+{
+  this->dataPtr->min.Set(_vec1X, _vec1Y, _vec1Z);
+  this->dataPtr->max.Set(_vec2X, _vec2Y, _vec2Z);
+
+  this->dataPtr->min.Min(math::Vector3d(_vec2X, _vec2Y, _vec2Z));
+  this->dataPtr->max.Max(math::Vector3d(_vec1X, _vec1Y, _vec1Z));
+}
+
+//////////////////////////////////////////////////
+Box::Box(const Vector3d &_vec1, const Vector3d &_vec2)
+: dataPtr(new BoxPrivate)
+{
+  this->dataPtr->min = _vec1;
+  this->dataPtr->min.Min(_vec2);
+
+  this->dataPtr->max = _vec2;
+  this->dataPtr->max.Max(_vec1);
+}
+
+//////////////////////////////////////////////////
+Box::Box(const Box &_b)
+: dataPtr(new BoxPrivate)
+{
+  this->dataPtr->min = _b.dataPtr->min;
+  this->dataPtr->max = _b.dataPtr->max;
+}
+
+//////////////////////////////////////////////////
+Box::~Box()
+{
+  delete this->dataPtr;
+  this->dataPtr = NULL;
+}
+
+//////////////////////////////////////////////////
+double Box::XLength() const
+{
+  return std::max(0.0, this->dataPtr->max.X() - this->dataPtr->min.X());
+}
+
+//////////////////////////////////////////////////
+double Box::YLength() const
+{
+  return std::max(0.0, this->dataPtr->max.Y() - this->dataPtr->min.Y());
+}
+
+//////////////////////////////////////////////////
+double Box::ZLength() const
+{
+  return std::max(0.0, this->dataPtr->max.Z() - this->dataPtr->min.Z());
+}
+
+//////////////////////////////////////////////////
+math::Vector3d Box::Size() const
+{
+  return math::Vector3d(this->XLength(),
+                        this->YLength(),
+                        this->ZLength());
+}
+
+//////////////////////////////////////////////////
+math::Vector3d Box::Center() const
+{
+  return 0.5 * this->dataPtr->min + 0.5 * this->dataPtr->max;
+}
+
+
+//////////////////////////////////////////////////
+void Box::Merge(const Box &_box)
+{
+  this->dataPtr->min.Min(_box.dataPtr->min);
+  this->dataPtr->max.Max(_box.dataPtr->max);
+}
+
+//////////////////////////////////////////////////
+Box &Box::operator =(const Box &_b)
+{
+  this->dataPtr->max = _b.dataPtr->max;
+  this->dataPtr->min = _b.dataPtr->min;
+
+  return *this;
+}
+
+//////////////////////////////////////////////////
+Box Box::operator+(const Box &_b) const
+{
+  Box result(*this);
+  result += _b;
+  return result;
+}
+
+//////////////////////////////////////////////////
+const Box &Box::operator+=(const Box &_b)
+{
+  this->dataPtr->min.Min(_b.dataPtr->min);
+  this->dataPtr->max.Max(_b.dataPtr->max);
+  return *this;
+}
+
+//////////////////////////////////////////////////
+bool Box::operator==(const Box &_b) const
+{
+  return this->dataPtr->min == _b.dataPtr->min &&
+         this->dataPtr->max == _b.dataPtr->max;
+}
+
+//////////////////////////////////////////////////
+bool Box::operator!=(const Box &_b) const
+{
+  return !(*this == _b);
+}
+
+//////////////////////////////////////////////////
+Box Box::operator-(const Vector3d &_v)
+{
+  return Box(this->dataPtr->min - _v, this->dataPtr->max - _v);
+}
+
+//////////////////////////////////////////////////
+bool Box::Intersects(const Box &_box) const
+{
+  // Check the six separating planes.
+  if (this->Max().X() < _box.Min().X())
+    return false;
+  if (this->Max().Y() < _box.Min().Y())
+    return false;
+  if (this->Max().Z() < _box.Min().Z())
+    return false;
+
+  if (this->Min().X() > _box.Max().X())
+    return false;
+  if (this->Min().Y() > _box.Max().Y())
+    return false;
+  if (this->Min().Z() > _box.Max().Z())
+    return false;
+
+  // Otherwise the two boxes must intersect.
+  return true;
+}
+
+//////////////////////////////////////////////////
+const Vector3d &Box::Min() const
+{
+  return this->dataPtr->min;
+}
+
+//////////////////////////////////////////////////
+const Vector3d &Box::Max() const
+{
+  return this->dataPtr->max;
+}
+
+//////////////////////////////////////////////////
+Vector3d &Box::Min()
+{
+  return this->dataPtr->min;
+}
+
+//////////////////////////////////////////////////
+Vector3d &Box::Max()
+{
+  return this->dataPtr->max;
+}
+
+//////////////////////////////////////////////////
+bool Box::Contains(const Vector3d &_p) const
+{
+  return _p.X() >= this->dataPtr->min.X() && _p.X() <= this->dataPtr->max.X() &&
+         _p.Y() >= this->dataPtr->min.Y() && _p.Y() <= this->dataPtr->max.Y() &&
+         _p.Z() >= this->dataPtr->min.Z() && _p.Z() <= this->dataPtr->max.Z();
+}
+
+//////////////////////////////////////////////////
+bool Box::ClipLine(const int _d, const Line3d &_line,
+                   double &_low, double &_high) const
+{
+  // dimLow and dimHigh are the results we're calculating for this
+  // current dimension.
+  double dimLow, dimHigh;
+
+  // Find the point of intersection in this dimension only as a fraction of
+  // the total vector http://youtu.be/USjbg5QXk3g?t=3m12s
+  dimLow = (this->dataPtr->min[_d] - _line[0][_d]) /
+    (_line[1][_d] - _line[0][_d]);
+
+  dimHigh = (this->dataPtr->max[_d] - _line[0][_d]) /
+    (_line[1][_d] - _line[0][_d]);
+
+  // Make sure low is less than high
+  if (dimHigh < dimLow)
+    std::swap(dimHigh, dimLow);
+
+  // If this dimension's high is less than the low we got then we definitely
+  // missed. http://youtu.be/USjbg5QXk3g?t=7m16s
+  if (dimHigh < _low)
+    return false;
+
+  // Likewise if the low is less than the high.
+  if (dimLow > _high)
+    return false;
+
+  // Add the clip from this dimension to the previous results
+  // http://youtu.be/USjbg5QXk3g?t=5m32s
+  if (std::isfinite(dimLow))
+    _low = std::max(dimLow, _low);
+
+  if (std::isfinite(dimHigh))
+    _high = std::min(dimHigh, _high);
+
+  return true;
+}
+
+/////////////////////////////////////////////////
+bool Box::IntersectCheck(const Vector3d &_origin, const Vector3d &_dir,
+    const double _min, const double _max) const
+{
+  return std::get<0>(this->Intersect(_origin, _dir, _min, _max));
+}
+
+/////////////////////////////////////////////////
+std::tuple<bool, double> Box::IntersectDist(const Vector3d &_origin,
+    const Vector3d &_dir, const double _min, const double _max) const
+{
+  return std::make_tuple(
+      std::get<0>(this->Intersect(_origin, _dir, _min, _max)),
+      std::get<1>(this->Intersect(_origin, _dir, _min, _max)));
+}
+
+/////////////////////////////////////////////////
+std::tuple<bool, double, Vector3d>  Box::Intersect(
+    const Vector3d &_origin, const Vector3d &_dir,
+    const double _min, const double _max) const
+{
+  Vector3d dir = _dir;
+  dir.Normalize();
+  return this->Intersect(Line3d(_origin + dir * _min, _origin + dir * _max));
+}
+
+/////////////////////////////////////////////////
+// Find the intersection of a line from v0 to v1 and an
+// axis-aligned bounding box http://www.youtube.com/watch?v=USjbg5QXk3g
+std::tuple<bool, double, Vector3d> Box::Intersect(const Line3d &_line) const
+{
+  // low and high are the results from all clipping so far.
+  // We'll write our results back out to those parameters.
+  double low = 0;
+  double high = 1;
+
+  if (!this->ClipLine(0, _line, low, high))
+    return std::make_tuple(false, 0, Vector3d::Zero);
+
+  if (!this->ClipLine(1, _line, low, high))
+    return std::make_tuple(false, 0, Vector3d::Zero);
+
+  if (!this->ClipLine(2, _line, low, high))
+    return std::make_tuple(false, 0, Vector3d::Zero);
+
+  // The formula for I: http://youtu.be/USjbg5QXk3g?t=6m24s
+  Vector3d intersection = _line[0] + ((_line[1] - _line[0]) * low);
+
+  return std::make_tuple(true, _line[0].Distance(intersection), intersection);
+}
diff --git a/src/BoxPrivate.hh b/src/BoxPrivate.hh
new file mode 100644
index 0000000..583711b
--- /dev/null
+++ b/src/BoxPrivate.hh
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2015 Open Source Robotics Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+*/
+#ifndef IGNITION_MATH_BOXPRIVATE_HH_
+#define IGNITION_MATH_BOXPRIVATE_HH_
+
+#include <ignition/math/Vector3.hh>
+
+namespace ignition
+{
+  namespace math
+  {
+    /// \internal
+    /// \brief Private data for Box class
+    class BoxPrivate
+    {
+      /// \brief Minimum corner of the box
+      public: Vector3d min = Vector3d(MAX_D, MAX_D, MAX_D);
+
+      /// \brief Maximum corner of the box
+      public: Vector3d max = Vector3d(LOW_D, LOW_D, LOW_D);
+    };
+  }
+}
+#endif
diff --git a/src/Box_TEST.cc b/src/Box_TEST.cc
new file mode 100644
index 0000000..81b636d
--- /dev/null
+++ b/src/Box_TEST.cc
@@ -0,0 +1,567 @@
+/*
+ * Copyright (C) 2012 Open Source Robotics Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+*/
+#include <gtest/gtest.h>
+#include <cmath>
+
+#include "ignition/math/Box.hh"
+
+using namespace ignition;
+
+class myBox : public math::Box
+{
+  public: myBox()
+          : math::Box()
+  {}
+};
+
+class ExampleBox : public ::testing::Test
+{
+  protected:
+    virtual void SetUp()
+    {
+       box = math::Box(math::Vector3d(0, -1, 2), math::Vector3d(1, -2, 3));
+    }
+
+    math::Box box;
+};
+
+/////////////////////////////////////////////////
+TEST(BoxTest, Inherit)
+{
+  myBox *box = NULL;
+
+  {
+    box = new myBox();
+    EXPECT_TRUE(box != NULL);
+  }
+
+  EXPECT_TRUE(box->Min() == math::Vector3d(math::MAX_D, math::MAX_D,
+      math::MAX_D));
+  EXPECT_TRUE(box->Max() == math::Vector3d(math::LOW_D, math::LOW_D,
+      math::LOW_D));
+
+  {
+    delete box;
+    box = NULL;
+  }
+}
+
+/////////////////////////////////////////////////
+TEST(BoxTest, EmptyConstructorNew)
+{
+  math::Box *box = NULL;
+
+  {
+    box = new math::Box;
+    EXPECT_TRUE(box != NULL);
+  }
+
+  EXPECT_TRUE(box->Min() == math::Vector3d(math::MAX_D, math::MAX_D,
+      math::MAX_D));
+  EXPECT_TRUE(box->Max() == math::Vector3d(math::LOW_D, math::LOW_D,
+      math::LOW_D));
+
+  {
+    delete box;
+    box = NULL;
+  }
+}
+
+/////////////////////////////////////////////////
+TEST(BoxTest, EmptyConstructor)
+{
+  math::Box box;
+  EXPECT_TRUE(box.Min() == math::Vector3d(math::MAX_D, math::MAX_D,
+      math::MAX_D));
+  EXPECT_TRUE(box.Max() == math::Vector3d(math::LOW_D, math::LOW_D,
+      math::LOW_D));
+}
+
+/////////////////////////////////////////////////
+TEST_F(ExampleBox, Constructor)
+{
+  EXPECT_EQ(box.Min(), math::Vector3d(0, -2, 2));
+  EXPECT_EQ(box.Max(), math::Vector3d(1, -1, 3));
+}
+
+/////////////////////////////////////////////////
+TEST_F(ExampleBox, CopyConstructor)
+{
+  math::Box box1(box);
+  EXPECT_TRUE(box1.Min() == box.Min());
+  EXPECT_TRUE(box1.Max() == box.Max());
+}
+
+/////////////////////////////////////////////////
+TEST_F(ExampleBox, ManuallySet)
+{
+  math::Box box1;
+  box1.Min().Set(-2, 2, 3);
+  box1.Max().Set(0, 0, 3);
+
+  box1 += box;
+  EXPECT_DOUBLE_EQ(box1.Min().X(), -2);
+  EXPECT_DOUBLE_EQ(box1.Min().Y(), -2);
+  EXPECT_DOUBLE_EQ(box1.Min().Z(),  2);
+
+  EXPECT_DOUBLE_EQ(box1.Max().X(), 1);
+  EXPECT_DOUBLE_EQ(box1.Max().Y(), 0);
+  EXPECT_DOUBLE_EQ(box1.Max().Z(), 3);
+
+  math::Box box2;
+  box2.Max().Set(1, 1, 1);
+  EXPECT_DOUBLE_EQ(box2.Size().X(), 0);
+  EXPECT_DOUBLE_EQ(box2.Size().Y(), 0);
+  EXPECT_DOUBLE_EQ(box2.Size().Z(), 0);
+
+  math::Box box3;
+  box3.Min().Set(-1, -1, -1);
+  EXPECT_DOUBLE_EQ(box3.Size().X(), 0);
+  EXPECT_DOUBLE_EQ(box3.Size().Y(), 0);
+  EXPECT_DOUBLE_EQ(box3.Size().Z(), 0);
+}
+
+/////////////////////////////////////////////////
+TEST_F(ExampleBox, Length)
+{
+  EXPECT_DOUBLE_EQ(box.XLength(), 1);
+  EXPECT_DOUBLE_EQ(box.YLength(), 1);
+  EXPECT_DOUBLE_EQ(box.ZLength(), 1);
+}
+
+/////////////////////////////////////////////////
+TEST_F(ExampleBox, Size)
+{
+  EXPECT_TRUE(box.Size() == math::Vector3d(1, 1, 1));
+}
+
+/////////////////////////////////////////////////
+TEST_F(ExampleBox, Center)
+{
+  EXPECT_TRUE(box.Center() == math::Vector3d(0.5, -1.5, 2.5));
+}
+
+/////////////////////////////////////////////////
+TEST(BoxTest, MergeEmpty)
+{
+  math::Box box1;
+  math::Box box2;
+
+  box1.Merge(box2);
+  EXPECT_DOUBLE_EQ(box1.Min().X(), math::MAX_D);
+  EXPECT_DOUBLE_EQ(box1.Min().Y(), math::MAX_D);
+  EXPECT_DOUBLE_EQ(box1.Min().Z(), math::MAX_D);
+
+  EXPECT_DOUBLE_EQ(box1.Max().X(), math::LOW_D);
+  EXPECT_DOUBLE_EQ(box1.Max().Y(), math::LOW_D);
+  EXPECT_DOUBLE_EQ(box1.Max().Z(), math::LOW_D);
+}
+
+/////////////////////////////////////////////////
+TEST(BoxTest, DefaultConstructor)
+{
+  math::Box defaultBox1, defaultBox2;
+
+  EXPECT_DOUBLE_EQ(defaultBox1.Size().X(), 0);
+  EXPECT_DOUBLE_EQ(defaultBox1.Size().Y(), 0);
+  EXPECT_DOUBLE_EQ(defaultBox1.Size().Z(), 0);
+
+  EXPECT_DOUBLE_EQ(defaultBox1.XLength(), 0);
+  EXPECT_DOUBLE_EQ(defaultBox1.YLength(), 0);
+  EXPECT_DOUBLE_EQ(defaultBox1.ZLength(), 0);
+
+  EXPECT_DOUBLE_EQ(defaultBox1.Center().X(), 0);
+  EXPECT_DOUBLE_EQ(defaultBox1.Center().Y(), 0);
+  EXPECT_DOUBLE_EQ(defaultBox1.Center().Z(), 0);
+
+  EXPECT_FALSE(defaultBox1.Intersects(defaultBox2));
+
+  EXPECT_FALSE(defaultBox1.Intersects(math::Box(
+          math::Vector3d(0, 0, 0), math::Vector3d(1, 1, 1))));
+
+  EXPECT_FALSE(defaultBox2.Contains(math::Vector3d::Zero));
+}
+
+/////////////////////////////////////////////////
+TEST(BoxTest, Minus)
+{
+  math::Box box1(1, 2, 3, 4, 5, 6);
+  math::Vector3d sub(1, 1, 1);
+
+  math::Box box2 = box1 - sub;
+  EXPECT_EQ(box2.Min(), box1.Min() - sub);
+  EXPECT_EQ(box2.Max(), box1.Max() - sub);
+}
+
+/////////////////////////////////////////////////
+TEST(BoxTest, PlusEmpty)
+{
+  math::Box box1;
+  math::Box box2;
+
+  box1 += box2;
+  EXPECT_DOUBLE_EQ(box1.Min().X(), math::MAX_D);
+  EXPECT_DOUBLE_EQ(box1.Min().Y(), math::MAX_D);
+  EXPECT_DOUBLE_EQ(box1.Min().Z(), math::MAX_D);
+
+  EXPECT_DOUBLE_EQ(box1.Max().X(), math::LOW_D);
+  EXPECT_DOUBLE_EQ(box1.Max().Y(), math::LOW_D);
+  EXPECT_DOUBLE_EQ(box1.Max().Z(), math::LOW_D);
+
+  math::Box box3 = box2 + box1;
+  EXPECT_DOUBLE_EQ(box3.Min().X(), math::MAX_D);
+  EXPECT_DOUBLE_EQ(box3.Min().Y(), math::MAX_D);
+  EXPECT_DOUBLE_EQ(box3.Min().Z(), math::MAX_D);
+
+  EXPECT_DOUBLE_EQ(box3.Max().X(), math::LOW_D);
+  EXPECT_DOUBLE_EQ(box3.Max().Y(), math::LOW_D);
+  EXPECT_DOUBLE_EQ(box3.Max().Z(), math::LOW_D);
+}
+
+/////////////////////////////////////////////////
+TEST_F(ExampleBox, Merge)
+{
+  box.Merge(math::Box(math::Vector3d(-1, -1, -1), math::Vector3d(2, 2, 2)));
+  EXPECT_TRUE(box == math::Box(math::Vector3d(-1, -2, -1),
+                               math::Vector3d(2, 2, 3)));
+}
+
+/////////////////////////////////////////////////
+TEST(BoxTest, OperatorEqual)
+{
+  math::Box box = math::Box(math::Vector3d(1, 1, 1), math::Vector3d(3, 3, 3));
+  math::Box box2 = math::Box(math::Vector3d(1, 1, 1), math::Vector3d(1, 3, 3));
+  math::Box box3 = math::Box(math::Vector3d(0, 1, 1), math::Vector3d(1, 3, 3));
+  EXPECT_TRUE(box == math::Box(math::Vector3d(1, 1, 1),
+        math::Vector3d(3, 3, 3)));
+  EXPECT_FALSE(box == box2);
+  EXPECT_FALSE(box3 == box);
+}
+
+/////////////////////////////////////////////////
+TEST(BoxTest, OperatorNotEqual)
+{
+  math::Box box = math::Box(math::Vector3d(1, 1, 1), math::Vector3d(3, 3, 3));
+  math::Box box2 = math::Box(math::Vector3d(1, 1, 1), math::Vector3d(1, 3, 3));
+  math::Box box3 = math::Box(math::Vector3d(0, 1, 1), math::Vector3d(1, 3, 3));
+  EXPECT_FALSE(box != math::Box(math::Vector3d(1, 1, 1),
+        math::Vector3d(3, 3, 3)));
+  EXPECT_TRUE(box != box2);
+  EXPECT_TRUE(box3 != box);
+}
+
+/////////////////////////////////////////////////
+TEST(BoxTest, OperatorPlusEqual)
+{
+  math::Box box = math::Box(math::Vector3d(1, 1, 1), math::Vector3d(3, 3, 3));
+  box += math::Box(math::Vector3d(2, 2, 2), math::Vector3d(4, 4, 4));
+  EXPECT_TRUE(box == math::Box(math::Vector3d(1, 1, 1),
+        math::Vector3d(4, 4, 4)));
+}
+
+/////////////////////////////////////////////////
+TEST(BoxTest, OperatorPlus)
+{
+  math::Box box = math::Box(math::Vector3d(1, 1, 1), math::Vector3d(4, 4, 4));
+  box = box + math::Box(math::Vector3d(-2, -2, -2), math::Vector3d(4, 4, 4));
+  EXPECT_TRUE(box == math::Box(math::Vector3d(-2, -2, -2),
+                               math::Vector3d(4, 4, 4)));
+}
+
+/////////////////////////////////////////////////
+TEST(BoxTest, Intersects)
+{
+  math::Box box = math::Box(math::Vector3d(0, 0, 0), math::Vector3d(1, 1, 1));
+
+  EXPECT_FALSE(box.Intersects(math::Box(
+          math::Vector3d(1.1, 0, 0), math::Vector3d(2, 1, 1))));
+
+  EXPECT_FALSE(box.Intersects(math::Box(
+          math::Vector3d(0, 1.1, 0), math::Vector3d(1, 2, 1))));
+
+  EXPECT_FALSE(box.Intersects(math::Box(
+          math::Vector3d(0, 0, 1.1), math::Vector3d(1, 1, 2))));
+
+
+  EXPECT_FALSE(box.Intersects(math::Box(
+          math::Vector3d(-1, -1, -1), math::Vector3d(-0.1, 0, 0))));
+
+  EXPECT_FALSE(box.Intersects(math::Box(
+          math::Vector3d(-1, -1, -1), math::Vector3d(0, -0.1, 0))));
+
+  EXPECT_FALSE(box.Intersects(math::Box(
+          math::Vector3d(-1, -1, -1), math::Vector3d(0, 0, -0.1))));
+
+  EXPECT_TRUE(box.Intersects(math::Box(
+          math::Vector3d(0, 0, 0), math::Vector3d(1, 1, 1))));
+}
+
+/////////////////////////////////////////////////
+TEST(BoxTest, Contains)
+{
+  math::Box box = math::Box(math::Vector3d(0, 0, 0), math::Vector3d(1, 1, 1));
+
+  EXPECT_TRUE(box.Contains(math::Vector3d(0, 0, 0)));
+  EXPECT_TRUE(box.Contains(math::Vector3d(0, 0, 1)));
+  EXPECT_TRUE(box.Contains(math::Vector3d(0, 1, 1)));
+  EXPECT_TRUE(box.Contains(math::Vector3d(1, 1, 1)));
+  EXPECT_TRUE(box.Contains(math::Vector3d(1, 1, 0)));
+  EXPECT_TRUE(box.Contains(math::Vector3d(1, 0, 0)));
+  EXPECT_TRUE(box.Contains(math::Vector3d(0.5, 0.5, 0.5)));
+
+  EXPECT_FALSE(box.Contains(math::Vector3d(0, 0, -1)));
+  EXPECT_FALSE(box.Contains(math::Vector3d(0, -1, -1)));
+  EXPECT_FALSE(box.Contains(math::Vector3d(-1, -1, -1)));
+  EXPECT_FALSE(box.Contains(math::Vector3d(-1, -1, 0)));
+  EXPECT_FALSE(box.Contains(math::Vector3d(-1, 0, 0)));
+
+  EXPECT_FALSE(box.Contains(math::Vector3d(0.5, 0.5, -0.5)));
+  EXPECT_FALSE(box.Contains(math::Vector3d(0.5, -0.5, 0.5)));
+  EXPECT_FALSE(box.Contains(math::Vector3d(-0.5, 0.5, 0.5)));
+  EXPECT_FALSE(box.Contains(math::Vector3d(-0.5, -0.5, 0.5)));
+  EXPECT_FALSE(box.Contains(math::Vector3d(-0.5, -0.5, -0.5)));
+
+  EXPECT_FALSE(box.Contains(math::Vector3d(0, 0, -0.01)));
+  EXPECT_FALSE(box.Contains(math::Vector3d(0, -0.01, 0)));
+  EXPECT_FALSE(box.Contains(math::Vector3d(-0.01, 0, 0)));
+}
+
+/////////////////////////////////////////////////
+TEST(BoxTest, OperatorStreamOut)
+{
+  math::Box b(0.1, 1.2, 2.3, 1.1, 2.2, 4.3);
+  std::ostringstream stream;
+  stream << b;
+  EXPECT_EQ(stream.str(), "Min[0.1 1.2 2.3] Max[1.1 2.2 4.3]");
+}
+
+/////////////////////////////////////////////////
+TEST(BoxTest, Intersect)
+{
+  math::Box b(0, 0, 0, 1, 1, 1);
+
+  bool intersect = false;
+  double dist = 0;
+  math::Vector3d pt;
+
+  std::tie(intersect, dist, pt) = b.Intersect(math::Vector3d(-1, 0, 0),
+      math::Vector3d(1, 0, 0), 0, 1000);
+  EXPECT_TRUE(intersect);
+  EXPECT_TRUE(b.IntersectCheck(math::Vector3d(-1, 0, 0),
+      math::Vector3d(1, 0, 0), 0, 1000));
+  EXPECT_DOUBLE_EQ(dist, 1);
+  EXPECT_DOUBLE_EQ(std::get<1>(b.Intersect(math::Vector3d(-1, 0, 0),
+          math::Vector3d(1, 0, 0), 0, 1000)), dist);
+  EXPECT_EQ(pt, math::Vector3d::Zero);
+
+  std::tie(intersect, dist, pt) = b.Intersect(math::Vector3d(1, 0, 0),
+      math::Vector3d(-1, 0, 0), 0, 1000);
+  EXPECT_TRUE(intersect);
+  EXPECT_TRUE(b.IntersectCheck(math::Vector3d(1, 0, 0),
+      math::Vector3d(-1, 0, 0), 0, 1000));
+  EXPECT_DOUBLE_EQ(dist, 0);
+  EXPECT_DOUBLE_EQ(std::get<1>(b.IntersectDist(math::Vector3d(1, 0, 0),
+      math::Vector3d(-1, 0, 0), 0, 1000)), dist);
+  EXPECT_EQ(pt, math::Vector3d(1, 0, 0));
+
+  std::tie(intersect, dist, pt) = b.Intersect(math::Vector3d(2, 2, 0),
+      math::Vector3d(-1, -1, 0), 0, 1000);
+  EXPECT_TRUE(intersect);
+  EXPECT_TRUE(b.IntersectCheck(math::Vector3d(2, 2, 0),
+      math::Vector3d(-1, -1, 0), 0, 1000));
+  EXPECT_DOUBLE_EQ(dist, IGN_SQRT2);
+  EXPECT_DOUBLE_EQ(std::get<1>(b.IntersectDist(math::Vector3d(2, 2, 0),
+      math::Vector3d(-1, -1, 0), 0, 1000)), dist);
+  EXPECT_EQ(pt, math::Vector3d(1, 1, 0));
+
+  std::tie(intersect, dist, pt) = b.Intersect(math::Vector3d(-10, -10, 0),
+      math::Vector3d(1, 1, 0), 0, 1000);
+  EXPECT_TRUE(intersect);
+  EXPECT_TRUE(b.IntersectCheck(math::Vector3d(-10, -10, 0),
+      math::Vector3d(1, 1, 0), 0, 1000));
+  EXPECT_DOUBLE_EQ(dist, std::sqrt(200));
+  EXPECT_DOUBLE_EQ(std::get<1>(b.IntersectDist(math::Vector3d(-10, -10, 0),
+      math::Vector3d(1, 1, 0), 0, 1000)), dist);
+  EXPECT_EQ(pt, math::Vector3d::Zero);
+
+  std::tie(intersect, dist, pt) = b.Intersect(math::Vector3d(-1, -2, 0),
+      math::Vector3d(1, 1, 0), 0, 1000);
+  EXPECT_TRUE(intersect);
+  EXPECT_TRUE(b.IntersectCheck(math::Vector3d(-1, -2, 0),
+      math::Vector3d(1, 1, 0), 0, 1000));
+  EXPECT_DOUBLE_EQ(dist, 2*IGN_SQRT2);
+  EXPECT_DOUBLE_EQ(std::get<1>(b.IntersectDist(math::Vector3d(-1, -2, 0),
+      math::Vector3d(1, 1, 0), 0, 1000)), dist);
+  EXPECT_EQ(pt, math::Vector3d(1, 0, 0));
+
+  std::tie(intersect, dist, pt) = b.Intersect(math::Vector3d(2, 1, 0),
+      math::Vector3d(-1, -1, 0), 0, 1000);
+  EXPECT_TRUE(intersect);
+  EXPECT_TRUE(b.IntersectCheck(math::Vector3d(2, 1, 0),
+      math::Vector3d(-1, -1, 0), 0, 1000));
+  EXPECT_DOUBLE_EQ(dist, IGN_SQRT2);
+  EXPECT_DOUBLE_EQ(std::get<1>(b.IntersectDist(math::Vector3d(2, 1, 0),
+      math::Vector3d(-1, -1, 0), 0, 1000)), dist);
+  EXPECT_EQ(pt, math::Vector3d(1, 0, 0));
+
+  std::tie(intersect, dist, pt) = b.Intersect(math::Vector3d(0.5, 0.5, 2),
+      math::Vector3d(0, 0, -1), 0, 1000);
+  EXPECT_TRUE(intersect);
+  EXPECT_TRUE(b.IntersectCheck(math::Vector3d(0.5, 0.5, 2),
+      math::Vector3d(0, 0, -1), 0, 1000));
+  EXPECT_DOUBLE_EQ(dist, 1);
+  EXPECT_DOUBLE_EQ(std::get<1>(b.IntersectDist(math::Vector3d(0.5, 0.5, 2),
+      math::Vector3d(0, 0, -1), 0, 1000)), dist);
+  EXPECT_EQ(pt, math::Vector3d(0.5, 0.5, 1));
+
+  std::tie(intersect, dist, pt) = b.Intersect(math::Vector3d(0.5, 0.5, 2),
+      math::Vector3d(0, 0, 1), 0, 1000);
+  EXPECT_FALSE(intersect);
+  EXPECT_FALSE(b.IntersectCheck(math::Vector3d(0.5, 0.5, 2),
+      math::Vector3d(0, 0, 1), 0, 1000));
+  EXPECT_EQ(pt, math::Vector3d::Zero);
+
+  std::tie(intersect, dist, pt) = b.Intersect(math::Vector3d(-1, -1, 1),
+      math::Vector3d(0, 0, -1), 0, 1000);
+  EXPECT_FALSE(intersect);
+  EXPECT_FALSE(b.IntersectCheck(math::Vector3d(-1, -1, 1),
+      math::Vector3d(0, 0, -1), 0, 1000));
+  EXPECT_EQ(pt, math::Vector3d::Zero);
+
+  std::tie(intersect, dist, pt) = b.Intersect(math::Vector3d(2, 2, 0),
+      math::Vector3d(1, 1, 0), 0, 1000);
+  EXPECT_FALSE(intersect);
+  EXPECT_FALSE(b.IntersectCheck(math::Vector3d(2, 2, 0),
+      math::Vector3d(1, 1, 0), 0, 1000));
+  EXPECT_EQ(pt, math::Vector3d::Zero);
+
+  std::tie(intersect, dist, pt) = b.Intersect(math::Vector3d(2, 2, 0),
+      math::Vector3d(0, 1, 0), 0, 1000);
+  EXPECT_FALSE(intersect);
+  EXPECT_FALSE(b.IntersectCheck(math::Vector3d(2, 2, 0),
+      math::Vector3d(0, 1, 0), 0, 1000));
+  EXPECT_EQ(pt, math::Vector3d::Zero);
+
+  std::tie(intersect, dist, pt) = b.Intersect(math::Vector3d(0.1, 0.1, 200),
+      math::Vector3d(0, 0, -1), 0, 100);
+  EXPECT_FALSE(intersect);
+  EXPECT_FALSE(b.IntersectCheck(math::Vector3d(0.1, 0.1, 200),
+      math::Vector3d(0, 0, -1), 0, 100));
+  EXPECT_DOUBLE_EQ(dist, 0);
+  EXPECT_DOUBLE_EQ(std::get<1>(b.IntersectDist(math::Vector3d(0.1, 0.1, 200),
+      math::Vector3d(0, 0, -1), 0, 100)), dist);
+  EXPECT_EQ(pt, math::Vector3d::Zero);
+
+  std::tie(intersect, dist, pt) = b.Intersect(math::Vector3d(0.1, 0.1, 1),
+      math::Vector3d(0, 0, -1), 1.0, 1000);
+  EXPECT_TRUE(intersect);
+  EXPECT_TRUE(b.IntersectCheck(math::Vector3d(0.1, 0.1, 1),
+      math::Vector3d(0, 0, -1), 1.0, 1000));
+  EXPECT_DOUBLE_EQ(dist, 0.0);
+  EXPECT_DOUBLE_EQ(std::get<1>(b.IntersectDist(math::Vector3d(0.1, 0.1, 1),
+      math::Vector3d(0, 0, -1), 1.0, 1000)), dist);
+  EXPECT_EQ(pt, math::Vector3d(0.1, 0.1, 0));
+
+  std::tie(intersect, dist, pt) = b.Intersect(math::Vector3d(0.1, 0.1, 1),
+      math::Vector3d(0, 0, -1), 1.1, 1000);
+  EXPECT_FALSE(intersect);
+  EXPECT_FALSE(b.IntersectCheck(math::Vector3d(0.1, 0.1, 1),
+      math::Vector3d(0, 0, -1), 1.1, 1000));
+  EXPECT_EQ(pt, math::Vector3d::Zero);
+
+  std::tie(intersect, dist, pt) = b.Intersect(math::Vector3d(0.1, 0.1, 10),
+      math::Vector3d(0, 0, -1), 1.1, 5);
+  EXPECT_FALSE(intersect);
+  EXPECT_FALSE(b.IntersectCheck(math::Vector3d(0.1, 0.1, 10),
+      math::Vector3d(0, 0, -1), 1.1, 5));
+  EXPECT_DOUBLE_EQ(dist, 0);
+  EXPECT_DOUBLE_EQ(std::get<1>(b.IntersectDist(math::Vector3d(0.1, 0.1, 10),
+      math::Vector3d(0, 0, -1), 1.1, 5)), dist);
+  EXPECT_EQ(pt, math::Vector3d::Zero);
+
+  std::tie(intersect, dist, pt) = b.Intersect(
+      math::Line3d(math::Vector3d(4, 0, 0.5), math::Vector3d(0, 10, 0.5)));
+  EXPECT_FALSE(intersect);
+  EXPECT_DOUBLE_EQ(dist, 0);
+  EXPECT_EQ(pt, math::Vector3d::Zero);
+
+  std::tie(intersect, dist, pt) = b.Intersect(
+      math::Line3d(math::Vector3d(1, -1, 1.5), math::Vector3d(0, 1, 1.5)));
+  EXPECT_FALSE(intersect);
+  EXPECT_DOUBLE_EQ(dist, 0);
+  EXPECT_EQ(pt, math::Vector3d::Zero);
+
+  std::tie(intersect, dist, pt) = b.Intersect(math::Vector3d(0, 0, 1),
+      math::Vector3d(0, 0, -1), 0, 1000);
+  EXPECT_TRUE(intersect);
+  EXPECT_TRUE(b.IntersectCheck(math::Vector3d(0, 0, 1),
+      math::Vector3d(0, 0, -1), 0, 1000));
+  EXPECT_DOUBLE_EQ(dist, 0);
+  EXPECT_DOUBLE_EQ(std::get<1>(b.IntersectDist(math::Vector3d(0, 0, 1),
+      math::Vector3d(0, 0, -1), 0, 1000)), dist);
+  EXPECT_EQ(pt, math::Vector3d(0, 0, 1));
+
+  std::tie(intersect, dist, pt) = b.Intersect(math::Vector3d(0, 0, 0),
+      math::Vector3d(1, 0, 0), 0, 1000);
+  EXPECT_TRUE(intersect);
+  EXPECT_TRUE(b.IntersectCheck(math::Vector3d(0, 0, 0),
+      math::Vector3d(1, 0, 0), 0, 1000));
+  EXPECT_DOUBLE_EQ(dist, 0);
+  EXPECT_DOUBLE_EQ(std::get<1>(b.IntersectDist(math::Vector3d(0, 0, 0),
+      math::Vector3d(1, 0, 0), 0, 1000)), dist);
+  EXPECT_EQ(pt, math::Vector3d::Zero);
+
+  std::tie(intersect, dist, pt) = b.Intersect(math::Vector3d(0, 0, 0),
+      math::Vector3d(-1, 0, 0), 0, 1000);
+  EXPECT_TRUE(intersect);
+  EXPECT_TRUE(b.IntersectCheck(math::Vector3d(0, 0, 0),
+      math::Vector3d(-1, 0, 0), 0, 1000));
+  EXPECT_DOUBLE_EQ(dist, 0);
+  EXPECT_DOUBLE_EQ(std::get<1>(b.IntersectDist(math::Vector3d(0, 0, 0),
+      math::Vector3d(-1, 0, 0), 0, 1000)), dist);
+  EXPECT_EQ(pt, math::Vector3d::Zero);
+
+  std::tie(intersect, dist, pt) = b.Intersect(math::Vector3d(0, 0, 0),
+      math::Vector3d(0, 1, 0), 0, 1000);
+  EXPECT_TRUE(intersect);
+  EXPECT_TRUE(b.IntersectCheck(math::Vector3d(0, 0, 0),
+      math::Vector3d(0, 1, 0), 0, 1000));
+  EXPECT_DOUBLE_EQ(dist, 0);
+  EXPECT_DOUBLE_EQ(std::get<1>(b.IntersectDist(math::Vector3d(0, 0, 0),
+      math::Vector3d(0, 1, 0), 0, 1000)), dist);
+  EXPECT_EQ(pt, math::Vector3d::Zero);
+
+  std::tie(intersect, dist, pt) = b.Intersect(math::Vector3d(0.5, 0.5, 0.5),
+      math::Vector3d(-.707107, 0, -0.707107), 0, 1000);
+  EXPECT_TRUE(intersect);
+  EXPECT_TRUE(b.IntersectCheck(math::Vector3d(0.5, 0.5, 0.5),
+      math::Vector3d(-.707107, 0, -0.707107), 0, 1000));
+  EXPECT_NEAR(dist, 0, 1e-5);
+  EXPECT_NEAR(std::get<1>(b.Intersect(math::Vector3d(0.5, 0.5, 0.5),
+      math::Vector3d(-.707107, 0, -0.707107), 0, 1000)), dist, 1e-5);
+  EXPECT_EQ(pt, math::Vector3d(0.5, 0.5, 0.5));
+
+  std::tie(intersect, dist, pt) = b.Intersect(math::Vector3d(1.2, 0, 0.5),
+      math::Vector3d(-0.707107, 0, -0.707107), 0, 1000);
+  EXPECT_TRUE(intersect);
+  EXPECT_TRUE(b.IntersectCheck(math::Vector3d(1.2, 0, 0.5),
+      math::Vector3d(-0.707107, 0, -0.707107), 0, 1000));
+  EXPECT_NEAR(dist, 0.28284, 1e-5);
+  EXPECT_NEAR(std::get<1>(b.Intersect(math::Vector3d(1.2, 0, 0.5),
+      math::Vector3d(-0.707107, 0, -0.707107), 0, 1000)), dist, 1e-5);
+  EXPECT_EQ(pt, math::Vector3d(1, 0, 0.3));
+}
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
new file mode 100644
index 0000000..912e5e8
--- /dev/null
+++ b/src/CMakeLists.txt
@@ -0,0 +1,20 @@
+
+# Collect source files into the "sources" variable and unit test files into the
+# "gtest_sources" variable
+ign_get_libsources_and_unittests(sources gtest_sources)
+
+# Create the library target
+ign_add_library(${PROJECT_LIBRARY_TARGET_NAME} ${sources})
+
+# Turn on C++14 support for the library
+ign_set_project_public_cxx_standard(14)
+
+# Create installation instructions for the library target. This must be called
+# in the same scope that the target is created.
+ign_install_library()
+
+# Build the unit tests
+ign_build_tests(TYPE UNIT SOURCES ${gtest_sources})
+
+# graph namespace
+add_subdirectory(graph)
diff --git a/src/Color.cc b/src/Color.cc
new file mode 100644
index 0000000..2d6f7d6
--- /dev/null
+++ b/src/Color.cc
@@ -0,0 +1,583 @@
+/*
+ * Copyright (C) 2017 Open Source Robotics Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+#include <math.h>
+#include <algorithm>
+
+#include "ignition/math/Color.hh"
+
+using namespace ignition;
+using namespace math;
+
+const Color Color::White = Color(1, 1, 1, 1);
+const Color Color::Black = Color(0, 0, 0, 1);
+const Color Color::Red = Color(1, 0, 0, 1);
+const Color Color::Green = Color(0, 1, 0, 1);
+const Color Color::Blue = Color(0, 0, 1, 1);
+const Color Color::Yellow = Color(1, 1, 0, 1);
+const Color Color::Magenta = Color(1, 0, 1, 1);
+const Color Color::Cyan = Color(0, 1, 1, 1);
+
+//////////////////////////////////////////////////
+Color::Color()
+{
+}
+
+//////////////////////////////////////////////////
+Color::Color(const float _r, const float _g, const float _b, const float _a)
+: r(_r), g(_g), b(_b), a(_a)
+{
+  this->Clamp();
+}
+
+//////////////////////////////////////////////////
+Color::Color(const Color &_pt)
+: r(_pt.r), g(_pt.g), b(_pt.b), a(_pt.a)
+{
+  this->Clamp();
+}
+
+//////////////////////////////////////////////////
+Color::~Color()
+{
+}
+
+//////////////////////////////////////////////////
+void Color::Reset()
+{
+  this->r = this->g = this->b = 0;
+  this->a = 1;
+}
+
+//////////////////////////////////////////////////
+void Color::Set(const float _r, const float _g, const float _b, const float _a)
+{
+  this->r = _r;
+  this->g = _g;
+  this->b = _b;
+  this->a = _a;
+
+  this->Clamp();
+}
+
+//////////////////////////////////////////////////
+void Color::SetFromHSV(const float _h, const float _s, const float _v)
+{
+  int i;
+  float f, p , q, t;
+
+  float h = static_cast<float>(static_cast<int>(_h < 0 ? 0 : _h) % 360);
+
+  if (equal(_s, 0.0f))
+  {
+    // acromatic (grey)
+    this->r = this->g = this->b = _v;
+    return;
+  }
+
+  // sector 0 - 5
+  h /= 60;
+
+  i = static_cast<int>(floor(h));
+
+  f = h - i;
+
+  p = _v * (1-_s);
+  q = _v * (1 - _s * f);
+  t = _v * (1 - _s * (1-f));
+
+  switch (i)
+  {
+    case 0:
+      this->r = _v;
+      this->g = t;
+      this->b = p;
+      break;
+    case 1:
+      this->r = q;
+      this->g = _v;
+      this->b = p;
+      break;
+    case 2:
+      this->r = p;
+      this->g = _v;
+      this->b = t;
+      break;
+    case 3:
+      this->r = p;
+      this->g = q;
+      this->b = _v;
+      break;
+    case 4:
+      this->r = t;
+      this->g = p;
+      this->b = _v;
+      break;
+    case 5:
+    default:
+      this->r = _v;
+      this->g = p;
+      this->b = q;
+      break;
+  }
+
+  this->Clamp();
+}
+
+//////////////////////////////////////////////////
+Vector3f Color::HSV() const
+{
+  Vector3f hsv;
+
+  float min = std::min(this->r, std::min(this->g, this->b));
+  float max = std::max(this->r, std::max(this->g, this->b));
+  float delta = max - min;
+
+  hsv.Y() = delta / max;
+  hsv.Z() = max;
+
+  if (equal(delta, 0.0f))
+  {
+    hsv.X() = -1;
+    hsv.Y() = 0.0;
+  }
+  else if (equal(this->r, min))
+    hsv.X() = 3 - ((this->g - this->b) / delta);
+  else if (equal(this->g, min))
+    hsv.X() = 5 - ((this->b - this->r) / delta);
+  else
+    hsv.X() = 1 - ((this->r - this->g) / delta);
+
+  return hsv;
+}
+
+//////////////////////////////////////////////////
+Vector3f Color::YUV() const
+{
+  Vector3f yuv;
+
+  yuv.X() = 0.299f*this->r + 0.587f*this->g + 0.114f*this->b;
+  yuv.Y() = -0.1679f*this->r - 0.332f*this->g + 0.5f*this->b + 0.5f;
+  yuv.Z() = 0.5f*this->r - 0.4189f*this->g - 0.08105f*this->b + 0.5f;
+
+  yuv.X() = yuv.X() < 0 ? 0: yuv.X();
+  yuv.X() = yuv.X() > 255 ? 255.0f: yuv.X();
+
+  yuv.Y() = yuv.Y() < 0 ? 0: yuv.Y();
+  yuv.Y() = yuv.Y() > 255 ? 255.0f: yuv.Y();
+
+  yuv.Z() = yuv.Z() < 0 ? 0: yuv.Z();
+  yuv.Z() = yuv.Z() > 255 ? 255.0f: yuv.Z();
+
+  return yuv;
+}
+
+//////////////////////////////////////////////////
+void Color::SetFromYUV(const float _y, const float _u, const float _v)
+{
+  this->r = _y + 1.140f*_v;
+  this->g = _y - 0.395f*_u - 0.581f*_v;
+  this->b = _y + 2.032f*_u;
+  this->Clamp();
+}
+
+//////////////////////////////////////////////////
+float Color::operator[](const unsigned int index)
+{
+  switch (index)
+  {
+    case 0:
+      return this->r;
+    case 1:
+      return this->g;
+    case 2:
+      return this->b;
+    case 3:
+      return this->a;
+    default:
+      break;
+  }
+
+  return NAN_F;
+}
+
+//////////////////////////////////////////////////
+Color::RGBA Color::AsRGBA() const
+{
+  uint8_t val8;
+  unsigned int val32;
+
+  // Convert to 32bit pattern
+  // (RGBA = 8888)
+
+  val8 = static_cast<uint8_t>(this->r * 255);
+  val32 = val8 << 24;
+
+  val8 = static_cast<uint8_t>(this->g * 255);
+  val32 += val8 << 16;
+
+  val8 = static_cast<uint8_t>(this->b * 255);
+  val32 += val8 << 8;
+
+  val8 = static_cast<uint8_t>(this->a * 255);
+  val32 += val8;
+
+  return val32;
+}
+
+//////////////////////////////////////////////////
+Color::BGRA Color::AsBGRA() const
+{
+  uint8_t val8;
+  unsigned int val32 = 0;
+
+  // Convert to 32bit pattern
+  // (BGRA = 8888)
+
+  val8 = static_cast<uint8_t>(this->b * 255);
+  val32 = val8 << 24;
+
+  val8 = static_cast<uint8_t>(this->g * 255);
+  val32 += val8 << 16;
+
+  val8 = static_cast<uint8_t>(this->r * 255);
+  val32 += val8 << 8;
+
+  val8 = static_cast<uint8_t>(this->a * 255);
+  val32 += val8;
+
+  return val32;
+}
+
+//////////////////////////////////////////////////
+Color::ARGB Color::AsARGB() const
+{
+  uint8_t val8;
+  unsigned int val32 = 0;
+
+  // Convert to 32bit pattern
+  // (ARGB = 8888)
+
+  val8 = static_cast<uint8_t>(this->a * 255);
+  val32 = val8 << 24;
+
+  val8 = static_cast<uint8_t>(this->r * 255);
+  val32 += val8 << 16;
+
+  val8 = static_cast<uint8_t>(this->g * 255);
+  val32 += val8 << 8;
+
+  val8 = static_cast<uint8_t>(this->b * 255);
+  val32 += val8;
+
+  return val32;
+}
+
+//////////////////////////////////////////////////
+Color::ABGR Color::AsABGR() const
+{
+  uint8_t val8;
+  unsigned int val32 = 0;
+
+  // Convert to 32bit pattern
+  // (ABGR = 8888)
+
+  val8 = static_cast<uint8_t>(this->a * 255);
+  val32 = val8 << 24;
+
+  val8 = static_cast<uint8_t>(this->b * 255);
+  val32 += val8 << 16;
+
+  val8 = static_cast<uint8_t>(this->g * 255);
+  val32 += val8 << 8;
+
+  val8 = static_cast<uint8_t>(this->r * 255);
+  val32 += val8;
+
+  return val32;
+}
+
+//////////////////////////////////////////////////
+void Color::SetFromRGBA(const Color::RGBA _v)
+{
+  unsigned int val32 = _v;
+
+  // Convert from 32bit pattern
+  // (RGBA = 8888)
+
+  this->r = ((val32 >> 24) & 0xFF) / 255.0f;
+  this->g = ((val32 >> 16) & 0xFF) / 255.0f;
+  this->b = ((val32 >> 8) & 0xFF) / 255.0f;
+  this->a = (val32 & 0xFF) / 255.0f;
+}
+
+//////////////////////////////////////////////////
+void Color::SetFromBGRA(const Color::BGRA _v)
+{
+  unsigned int val32 = _v;
+
+  // Convert from 32bit pattern
+  // (BGRA = 8888)
+
+  this->b = ((val32 >> 24) & 0xFF) / 255.0f;
+  this->g = ((val32 >> 16) & 0xFF) / 255.0f;
+  this->r = ((val32 >> 8) & 0xFF) / 255.0f;
+  this->a = (val32 & 0xFF) / 255.0f;
+}
+
+//////////////////////////////////////////////////
+void Color::SetFromARGB(const Color::ARGB _v)
+{
+  unsigned int val32 = _v;
+
+  // Convert from 32bit pattern
+  // (ARGB = 8888)
+
+  this->a = ((val32 >> 24) & 0xFF) / 255.0f;
+  this->r = ((val32 >> 16) & 0xFF) / 255.0f;
+  this->g = ((val32 >> 8) & 0xFF) / 255.0f;
+  this->b = (val32 & 0xFF) / 255.0f;
+}
+
+//////////////////////////////////////////////////
+void Color::SetFromABGR(const Color::ABGR _v)
+{
+  unsigned int val32 = _v;
+
+  // Convert from 32bit pattern
+  // (ABGR = 8888)
+
+  this->a = ((val32 >> 24) & 0xFF) / 255.0f;
+  this->b = ((val32 >> 16) & 0xFF) / 255.0f;
+  this->g = ((val32 >> 8) & 0xFF) / 255.0f;
+  this->r = (val32 & 0xFF) / 255.0f;
+}
+
+//////////////////////////////////////////////////
+Color &Color::operator=(const Color &_clr)
+{
+  this->r = _clr.r;
+  this->g = _clr.g;
+  this->b = _clr.b;
+  this->a = _clr.a;
+
+  return *this;
+}
+
+//////////////////////////////////////////////////
+Color Color::operator+(const Color &_pt) const
+{
+  return Color(this->r + _pt.r, this->g + _pt.g,
+      this->b + _pt.b, this->a + _pt.a);
+}
+
+//////////////////////////////////////////////////
+Color Color::operator+(const float &_v) const
+{
+  return Color(this->r + _v, this->g + _v, this->b + _v, this->a + _v);
+}
+
+//////////////////////////////////////////////////
+const Color &Color::operator+=(const Color &_pt)
+{
+  this->r += _pt.r;
+  this->g += _pt.g;
+  this->b += _pt.b;
+  this->a += _pt.a;
+
+  this->Clamp();
+
+  return *this;
+}
+
+//////////////////////////////////////////////////
+Color Color::operator-(const Color &_pt) const
+{
+  return Color(this->r - _pt.r, this->g - _pt.g,
+      this->b - _pt.b, this->a - _pt.a);
+}
+
+//////////////////////////////////////////////////
+Color Color::operator-(const float &_v) const
+{
+  return Color(this->r - _v, this->g - _v, this->b - _v, this->a - _v);
+}
+
+//////////////////////////////////////////////////
+const Color &Color::operator-=(const Color &_pt)
+{
+  this->r -= _pt.r;
+  this->g -= _pt.g;
+  this->b -= _pt.b;
+  this->a -= _pt.a;
+
+  this->Clamp();
+
+  return *this;
+}
+
+//////////////////////////////////////////////////
+const Color Color::operator/(const float &_i) const
+{
+  return Color(this->r / _i, this->g / _i, this->b / _i, this->a / _i);
+}
+
+//////////////////////////////////////////////////
+const Color Color::operator/(const Color &_pt) const
+{
+  return Color(this->r / _pt.r, this->g / _pt.g,
+      this->b / _pt.b, this->a / _pt.a);
+}
+
+//////////////////////////////////////////////////
+const Color &Color::operator/=(const Color &_pt)
+{
+  this->r /= _pt.r;
+  this->g /= _pt.g;
+  this->b /= _pt.b;
+  this->a /= _pt.a;
+
+  this->Clamp();
+
+  return *this;
+}
+
+//////////////////////////////////////////////////
+const Color Color::operator*(const float &_i) const
+{
+  return Color(this->r * _i, this->g * _i, this->b * _i, this->a * _i);
+}
+
+//////////////////////////////////////////////////
+const Color Color::operator*(const Color &_pt) const
+{
+  return Color(this->r * _pt.r, this->g * _pt.g,
+      this->b * _pt.b, this->a * _pt.a);
+}
+
+//////////////////////////////////////////////////
+const Color &Color::operator*=(const Color &_pt)
+{
+  this->r *= _pt.r;
+  this->g *= _pt.g;
+  this->b *= _pt.b;
+  this->a *= _pt.a;
+
+  this->Clamp();
+
+  return *this;
+}
+
+//////////////////////////////////////////////////
+bool Color::operator==(const Color &_pt) const
+{
+  return equal(this->r, _pt.r) && equal(this->g, _pt.g) &&
+         equal(this->b, _pt.b) && equal(this->a, _pt.a);
+}
+
+//////////////////////////////////////////////////
+bool Color::operator!=(const Color &_pt) const
+{
+  return !(*this == _pt);
+}
+
+//////////////////////////////////////////////////
+void Color::Clamp()
+{
+  this->r = this->r < 0 || isnan(this->r) ? 0: this->r;
+  this->r = this->r > 1 ? this->r/255.0f: this->r;
+
+  this->g = this->g < 0 || isnan(this->g) ? 0: this->g;
+  this->g = this->g > 1 ? this->g/255.0f: this->g;
+
+  this->b = this->b < 0 || isnan(this->b) ? 0: this->b;
+  this->b = this->b > 1 ? this->b/255.0f: this->b;
+
+  this->a = this->a < 0 || isnan(this->a) ? 0: this->a;
+  this->a = this->a > 1 ? 1.0f: this->a;
+}
+
+//////////////////////////////////////////////////
+float Color::R() const
+{
+  return this->r;
+}
+
+//////////////////////////////////////////////////
+float Color::G() const
+{
+  return this->g;
+}
+
+//////////////////////////////////////////////////
+float Color::B() const
+{
+  return this->b;
+}
+
+//////////////////////////////////////////////////
+float Color::A() const
+{
+  return this->a;
+}
+
+//////////////////////////////////////////////////
+float &Color::R()
+{
+  return this->r;
+}
+
+//////////////////////////////////////////////////
+float &Color::G()
+{
+  return this->g;
+}
+
+//////////////////////////////////////////////////
+float &Color::B()
+{
+  return this->b;
+}
+
+//////////////////////////////////////////////////
+float &Color::A()
+{
+  return this->a;
+}
+
+//////////////////////////////////////////////////
+void Color::R(const float _r)
+{
+  this->r = _r;
+}
+
+//////////////////////////////////////////////////
+void Color::G(const float _g)
+{
+  this->g = _g;
+}
+
+//////////////////////////////////////////////////
+void Color::B(const float _b)
+{
+  this->b = _b;
+}
+
+//////////////////////////////////////////////////
+void Color::A(const float _a)
+{
+  this->a = _a;
+}
diff --git a/src/Color_TEST.cc b/src/Color_TEST.cc
new file mode 100644
index 0000000..4b0bf2d
--- /dev/null
+++ b/src/Color_TEST.cc
@@ -0,0 +1,379 @@
+/*
+ * Copyright (C) 2017 Open Source Robotics Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.A()pache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+*/
+
+#include <math.h>
+#include <gtest/gtest.h>
+
+#include <ignition/math/Color.hh>
+
+using namespace ignition;
+
+/////////////////////////////////////////////////
+TEST(Color, ConstColors)
+{
+  EXPECT_FLOAT_EQ(1.0f, math::Color::White.R());
+  EXPECT_FLOAT_EQ(1.0f, math::Color::White.G());
+  EXPECT_FLOAT_EQ(1.0f, math::Color::White.B());
+  EXPECT_FLOAT_EQ(1.0f, math::Color::White.A());
+
+  EXPECT_FLOAT_EQ(0.0f, math::Color::Black.R());
+  EXPECT_FLOAT_EQ(0.0f, math::Color::Black.G());
+  EXPECT_FLOAT_EQ(0.0f, math::Color::Black.B());
+  EXPECT_FLOAT_EQ(1.0f, math::Color::Black.A());
+
+  EXPECT_FLOAT_EQ(1.0f, math::Color::Red.R());
+  EXPECT_FLOAT_EQ(0.0f, math::Color::Red.G());
+  EXPECT_FLOAT_EQ(0.0f, math::Color::Red.B());
+  EXPECT_FLOAT_EQ(1.0f, math::Color::Red.A());
+
+  EXPECT_FLOAT_EQ(0.0f, math::Color::Green.R());
+  EXPECT_FLOAT_EQ(1.0f, math::Color::Green.G());
+  EXPECT_FLOAT_EQ(0.0f, math::Color::Green.B());
+  EXPECT_FLOAT_EQ(1.0f, math::Color::Green.A());
+
+  EXPECT_FLOAT_EQ(0.0f, math::Color::Blue.R());
+  EXPECT_FLOAT_EQ(0.0f, math::Color::Blue.G());
+  EXPECT_FLOAT_EQ(1.0f, math::Color::Blue.B());
+  EXPECT_FLOAT_EQ(1.0f, math::Color::Blue.A());
+
+  EXPECT_FLOAT_EQ(1.0f, math::Color::Yellow.R());
+  EXPECT_FLOAT_EQ(1.0f, math::Color::Yellow.G());
+  EXPECT_FLOAT_EQ(0.0f, math::Color::Yellow.B());
+  EXPECT_FLOAT_EQ(1.0f, math::Color::Yellow.A());
+
+  EXPECT_FLOAT_EQ(1.0f, math::Color::Magenta.R());
+  EXPECT_FLOAT_EQ(0.0f, math::Color::Magenta.G());
+  EXPECT_FLOAT_EQ(1.0f, math::Color::Magenta.B());
+  EXPECT_FLOAT_EQ(1.0f, math::Color::Magenta.A());
+
+  EXPECT_FLOAT_EQ(0.0f, math::Color::Cyan.R());
+  EXPECT_FLOAT_EQ(1.0f, math::Color::Cyan.G());
+  EXPECT_FLOAT_EQ(1.0f, math::Color::Cyan.B());
+  EXPECT_FLOAT_EQ(1.0f, math::Color::Cyan.A());
+}
+
+/////////////////////////////////////////////////
+TEST(Color, Color)
+{
+  math::Color clr0;
+  EXPECT_FLOAT_EQ(0.0f, clr0.R());
+  EXPECT_FLOAT_EQ(0.0f, clr0.G());
+  EXPECT_FLOAT_EQ(0.0f, clr0.B());
+  EXPECT_FLOAT_EQ(1.0f, clr0.A());
+  EXPECT_EQ(clr0.AsRGBA(), 255u);
+  clr0.A(0.0);
+  EXPECT_EQ(clr0.AsRGBA(), 0u);
+
+  math::Color clr(.1f, .2f, .3f, 1.0f);
+  EXPECT_FLOAT_EQ(0.1f, clr.R());
+  EXPECT_FLOAT_EQ(0.2f, clr.G());
+  EXPECT_FLOAT_EQ(0.3f, clr.B());
+  EXPECT_FLOAT_EQ(1.0f, clr.A());
+
+  clr.Set(1, 0, 0, 0);
+  EXPECT_EQ(clr.AsRGBA(), static_cast<uint32_t>(255) << 24);
+  EXPECT_EQ(clr.AsBGRA(), static_cast<uint32_t>(255) << 8);
+  EXPECT_EQ(clr.AsARGB(), static_cast<uint32_t>(255) << 16);
+  EXPECT_EQ(clr.AsABGR(), static_cast<uint32_t>(255));
+  clr0.SetFromRGBA(static_cast<uint32_t>(255) << 24);
+  EXPECT_EQ(clr0, clr);
+  clr0.SetFromBGRA(static_cast<uint32_t>(255) << 8);
+  EXPECT_EQ(clr0, clr);
+  clr0.SetFromARGB(static_cast<uint32_t>(255) << 16);
+  EXPECT_EQ(clr0, clr);
+  clr0.SetFromABGR(static_cast<uint32_t>(255));
+  EXPECT_EQ(clr0, clr);
+
+  clr.Set(0, 1, 0, 0);
+  EXPECT_EQ(clr.AsRGBA(), static_cast<uint32_t>(255) << 16);
+  EXPECT_EQ(clr.AsBGRA(), static_cast<uint32_t>(255) << 16);
+  EXPECT_EQ(clr.AsARGB(), static_cast<uint32_t>(255) << 8);
+  EXPECT_EQ(clr.AsABGR(), static_cast<uint32_t>(255) << 8);
+  clr0.SetFromRGBA(static_cast<uint32_t>(255) << 16);
+  EXPECT_EQ(clr0, clr);
+  clr0.SetFromBGRA(static_cast<uint32_t>(255) << 16);
+  EXPECT_EQ(clr0, clr);
+  clr0.SetFromARGB(static_cast<uint32_t>(255) << 8);
+  EXPECT_EQ(clr0, clr);
+  clr0.SetFromABGR(static_cast<uint32_t>(255) << 8);
+  EXPECT_EQ(clr0, clr);
+
+  clr.Set(0, 0, 1, 0);
+  EXPECT_EQ(clr.AsRGBA(), static_cast<uint32_t>(255) << 8);
+  EXPECT_EQ(clr.AsBGRA(), static_cast<uint32_t>(255) << 24);
+  EXPECT_EQ(clr.AsARGB(), static_cast<uint32_t>(255));
+  EXPECT_EQ(clr.AsABGR(), static_cast<uint32_t>(255) << 16);
+  clr0.SetFromRGBA(static_cast<uint32_t>(255) << 8);
+  EXPECT_EQ(clr0, clr);
+  clr0.SetFromBGRA(static_cast<uint32_t>(255) << 24);
+  EXPECT_EQ(clr0, clr);
+  clr0.SetFromARGB(static_cast<uint32_t>(255));
+  EXPECT_EQ(clr0, clr);
+  clr0.SetFromABGR(static_cast<uint32_t>(255) << 16);
+  EXPECT_EQ(clr0, clr);
+
+  clr.Set(0, 0, 0, 1);
+  EXPECT_EQ(clr.AsRGBA(), static_cast<uint32_t>(255));
+  EXPECT_EQ(clr.AsBGRA(), static_cast<uint32_t>(255));
+  EXPECT_EQ(clr.AsARGB(), static_cast<uint32_t>(255) << 24);
+  EXPECT_EQ(clr.AsABGR(), static_cast<uint32_t>(255) << 24);
+  clr0.SetFromRGBA(static_cast<uint32_t>(255));
+  EXPECT_EQ(clr0, clr);
+  clr0.SetFromBGRA(static_cast<uint32_t>(255));
+  EXPECT_EQ(clr0, clr);
+  clr0.SetFromARGB(static_cast<uint32_t>(255) << 24);
+  EXPECT_EQ(clr0, clr);
+  clr0.SetFromABGR(static_cast<uint32_t>(255) << 24);
+  EXPECT_EQ(clr0, clr);
+
+  clr.Reset();
+  EXPECT_FLOAT_EQ(0.0f, clr.R());
+  EXPECT_FLOAT_EQ(0.0f, clr.G());
+  EXPECT_FLOAT_EQ(0.0f, clr.B());
+  EXPECT_FLOAT_EQ(1.0f, clr.A());
+
+  clr.SetFromHSV(0, 0.5, 1.0);
+  EXPECT_FLOAT_EQ(1.0f, clr.R());
+  EXPECT_FLOAT_EQ(0.5f, clr.G());
+  EXPECT_FLOAT_EQ(0.5f, clr.B());
+  EXPECT_FLOAT_EQ(1.0f, clr.A());
+
+  EXPECT_TRUE(clr.HSV() == math::Vector3f(6, 0.5, 1));
+
+  clr.SetFromHSV(60, 0.0, 1.0);
+  EXPECT_FLOAT_EQ(1.0f, clr.R());
+  EXPECT_FLOAT_EQ(1.0f, clr.G());
+  EXPECT_FLOAT_EQ(1.0f, clr.B());
+  EXPECT_FLOAT_EQ(1.0f, clr.A());
+
+  clr.SetFromHSV(120, 0.5, 1.0);
+  EXPECT_FLOAT_EQ(0.5f, clr.R());
+  EXPECT_FLOAT_EQ(1.0f, clr.G());
+  EXPECT_FLOAT_EQ(0.5f, clr.B());
+  EXPECT_FLOAT_EQ(1.0f, clr.A());
+
+  clr.SetFromHSV(180, 0.5, 1.0);
+  EXPECT_FLOAT_EQ(0.5f, clr.R());
+  EXPECT_FLOAT_EQ(1.0f, clr.G());
+  EXPECT_FLOAT_EQ(1.0f, clr.B());
+  EXPECT_FLOAT_EQ(1.0f, clr.A());
+
+  clr.SetFromHSV(240, 0.5, 1.0);
+  EXPECT_FLOAT_EQ(0.5f, clr.R());
+  EXPECT_FLOAT_EQ(0.5f, clr.G());
+  EXPECT_FLOAT_EQ(1.0f, clr.B());
+  EXPECT_FLOAT_EQ(1.0f, clr.A());
+
+  clr.SetFromHSV(300, 0.5, 1.0);
+  EXPECT_FLOAT_EQ(1.0f, clr[0]);
+  EXPECT_FLOAT_EQ(0.5f, clr[1]);
+  EXPECT_FLOAT_EQ(1.0f, clr[2]);
+  EXPECT_FLOAT_EQ(1.0f, clr[3]);
+  EXPECT_TRUE(std::isnan(clr[4]));
+
+  clr.R() = 0.1f;
+  clr.G() = 0.2f;
+  clr.B() = 0.3f;
+  clr.A() = 0.4f;
+  EXPECT_FLOAT_EQ(0.1f, clr[0]);
+  EXPECT_FLOAT_EQ(0.2f, clr[1]);
+  EXPECT_FLOAT_EQ(0.3f, clr[2]);
+  EXPECT_FLOAT_EQ(0.4f, clr[3]);
+
+  clr.Set(0.1f, 0.2f, 0.3f, 0.4f);
+  clr = clr + 0.2f;
+  EXPECT_TRUE(clr == math::Color(0.3f, 0.4f, 0.5f, 0.6f));
+
+  clr.Set(0.1f, 0.2f, 0.3f, 0.4f);
+  clr += math::Color(0.2f, 0.2f, 0.2f, 0.2f);
+  EXPECT_TRUE(clr == math::Color(0.3f, 0.4f, 0.5f, 0.6f));
+
+
+  clr.Set(0.1f, 0.2f, 0.3f, 0.4f);
+  clr = clr - 0.1f;
+  EXPECT_TRUE(clr == math::Color(0.0f, 0.1f, 0.2f, 0.3f));
+
+  clr.Set(0.1f, 0.2f, 0.3f, 0.4f);
+  clr -= math::Color(0.1f, 0.1f, 0.1f, 0.1f);
+  EXPECT_TRUE(clr == math::Color(0.0f, 0.1f, 0.2f, 0.3f));
+
+
+  clr.Set(1.f, 1.f, 1.f, 1.f);
+  clr = clr / 1.6f;
+  EXPECT_TRUE(clr == math::Color(0.625f, 0.625f, 0.625f, 0.625f));
+
+  clr.Set(1.f, 1.f, 1.f, 1.f);
+  clr /= math::Color(1.f, 1.f, 1.f, 1.f);
+  EXPECT_TRUE(clr == math::Color(1.f, 1.f, 1.f, 1.f));
+
+
+  clr.Set(.1f, .2f, .3f, .4f);
+  clr = clr * .1f;
+  EXPECT_TRUE(clr == math::Color(0.01f, 0.02f, 0.03f, 0.04f));
+
+  clr.Set(.1f, .2f, .3f, .4f);
+  clr *= math::Color(0.1f, 0.1f, 0.1f, 0.1f);
+  EXPECT_TRUE(clr == math::Color(0.01f, 0.02f, 0.03f, 0.04f));
+
+
+  clr.SetFromYUV(0.5f, 0.2f, 0.8f);
+  EXPECT_TRUE(math::equal(0.00553f, clr.R(), 1e-3f));
+  EXPECT_TRUE(math::equal(0.0f, clr.G()));
+  EXPECT_TRUE(math::equal(0.9064f, clr.B(), 1e-3f));
+  EXPECT_TRUE(math::equal(0.04f, clr.A()));
+
+  EXPECT_TRUE(clr.YUV() == math::Vector3f(0.104985f, 0.95227f, 0.429305f));
+
+  clr = math::Color(1.0f, 0.0f, 0.5f, 1.0f) +
+    math::Color(0.1f, 0.3f, 0.4f, 1.0f);
+  EXPECT_TRUE(math::equal(0.00431373f, clr.R()));
+  EXPECT_TRUE(math::equal(0.3f, clr.G()));
+  EXPECT_TRUE(math::equal(0.9f, clr.B()));
+  EXPECT_TRUE(math::equal(1.0f, clr.A()));
+
+  clr = math::Color(1.0f, 0.0f, 0.5f, 1.0f) -
+    math::Color(0.1f, 0.3f, 0.4f, 1.0f);
+  EXPECT_TRUE(math::equal(0.9f, clr.R()));
+  EXPECT_TRUE(math::equal(0.0f, clr.G()));
+  EXPECT_TRUE(math::equal(0.1f, clr.B()));
+  EXPECT_TRUE(math::equal(0.0f, clr.A()));
+
+  clr = math::Color(0.5f, 0.2f, 0.4f, 0.6f) / 2.0f;
+  EXPECT_TRUE(math::equal(0.25f, clr.R()));
+  EXPECT_TRUE(math::equal(0.1f, clr.G()));
+  EXPECT_TRUE(math::equal(0.2f, clr.B()));
+  EXPECT_TRUE(math::equal(0.3f, clr.A()));
+}
+
+
+/////////////////////////////////////////////////
+TEST(Color, MulOp)
+{
+  math::Color clr(0.0f, 0.01f, 0.2f, 1.0f);
+  math::Color clr2(1.0f, 0.2f, 0.2f, 0.0f);
+  math::Color clr3 = clr * clr2;
+
+  EXPECT_FLOAT_EQ(clr3.R(), 0.0f);
+  EXPECT_FLOAT_EQ(clr3.G(), 0.002f);
+  EXPECT_FLOAT_EQ(clr3.B(), 0.04f);
+  EXPECT_FLOAT_EQ(clr3.A(), 0.0f);
+}
+
+/////////////////////////////////////////////////
+TEST(Color, DivisonOp)
+{
+  math::Color clr(0.0f, 0.01f, 0.2f, 1.0f);
+  math::Color clr2 = clr / 0.2f;
+  EXPECT_FLOAT_EQ(clr2.R(), 0.0f);
+  EXPECT_FLOAT_EQ(clr2.G(), 0.05f);
+  EXPECT_FLOAT_EQ(clr2.B(), 1.0f);
+  EXPECT_FLOAT_EQ(clr2.A(), 1.0f);
+
+  clr2 = clr / 2.0f;
+  EXPECT_FLOAT_EQ(clr2.R(), 0.0f);
+  EXPECT_FLOAT_EQ(clr2.G(), 0.005f);
+  EXPECT_FLOAT_EQ(clr2.B(), 0.1f);
+  EXPECT_FLOAT_EQ(clr2.A(), 0.5f);
+
+  clr2.Set(0.0f, 0.2f, 0.4f, 0.5f);
+  math::Color clr3 = clr / clr2;
+  EXPECT_FLOAT_EQ(clr3.R(), 0.0f);
+  EXPECT_FLOAT_EQ(clr3.G(), 0.05f);
+  EXPECT_FLOAT_EQ(clr3.B(), 0.5f);
+  EXPECT_FLOAT_EQ(clr3.A(), 1.0f);
+
+  clr.Set(0.0f, 0.0f, 0.0f, 0.0f);
+  clr2.Set(0.0f, 0.0f, 0.0f, 0.0f);
+  clr3 = clr / clr2;
+  EXPECT_FLOAT_EQ(clr3.R(), 0.0f);
+  EXPECT_FLOAT_EQ(clr3.G(), 0.0f);
+  EXPECT_FLOAT_EQ(clr3.B(), 0.0f);
+  EXPECT_FLOAT_EQ(clr3.A(), 0.0f);
+}
+
+/////////////////////////////////////////////////
+TEST(Color, ConstAndSet)
+{
+  const math::Color clr(0.1f, 0.2f, 0.3f, 0.4f);
+
+  EXPECT_FLOAT_EQ(clr.R(), 0.1f);
+  EXPECT_FLOAT_EQ(clr.G(), 0.2f);
+  EXPECT_FLOAT_EQ(clr.B(), 0.3f);
+  EXPECT_FLOAT_EQ(clr.A(), 0.4f);
+
+  math::Color clr2;
+  clr2.R(0.4f);
+  clr2.G(0.3f);
+  clr2.B(0.2f);
+  clr2.A(0.1f);
+  EXPECT_FLOAT_EQ(clr2.R(), 0.4f);
+  EXPECT_FLOAT_EQ(clr2.G(), 0.3f);
+  EXPECT_FLOAT_EQ(clr2.B(), 0.2f);
+  EXPECT_FLOAT_EQ(clr2.A(), 0.1f);
+
+  EXPECT_TRUE(clr2 != clr);
+}
+
+/////////////////////////////////////////////////
+TEST(Color, OperatorStreamOut)
+{
+  math::Color c(0.1f, 0.2f, 0.3f, 0.5f);
+  std::ostringstream stream;
+  stream << c;
+  EXPECT_EQ(stream.str(), "0.1 0.2 0.3 0.5");
+}
+
+/////////////////////////////////////////////////
+TEST(Color, HSV)
+{
+  math::Color clr;
+  math::Vector3f hsv = clr.HSV();
+  EXPECT_FLOAT_EQ(hsv.X(), -1.0f);
+  EXPECT_FLOAT_EQ(hsv.Y(), 0.0f);
+  EXPECT_FLOAT_EQ(hsv.Z(), 0.0f);
+
+  clr.Set(0.1f, 0.2f, 0.3f, 1.0f);
+  hsv = clr.HSV();
+  EXPECT_NEAR(hsv.X(), 3.5f, 1e-3);
+  EXPECT_NEAR(hsv.Y(), 0.666667f, 1e-3);
+  EXPECT_NEAR(hsv.Z(), 0.3f, 1e-3);
+
+  clr.Set(0.3f, 0.2f, 0.1f, 1.0f);
+  hsv = clr.HSV();
+  EXPECT_NEAR(hsv.X(), 0.5f, 1e-3);
+  EXPECT_NEAR(hsv.Y(), 0.666667f, 1e-3);
+  EXPECT_NEAR(hsv.Z(), 0.3f, 1e-3);
+
+  clr.SetFromHSV(60, 10, 5);
+  EXPECT_NEAR(clr.R(), 0.0196078f, 1e-3);
+  EXPECT_NEAR(clr.G(), 0.0196078f, 1e-3);
+  EXPECT_NEAR(clr.B(), 0.0f, 1e-3);
+  EXPECT_NEAR(clr.A(), 1.0, 1e-3);
+
+  clr.SetFromHSV(360.0f, 0.5f, 0.6f);
+  EXPECT_NEAR(clr.R(), 0.6f, 1e-3);
+  EXPECT_NEAR(clr.G(), 0.3f, 1e-3);
+  EXPECT_NEAR(clr.B(), 0.3f, 1e-3);
+  EXPECT_NEAR(clr.A(), 1.0, 1e-3);
+}
+
+/////////////////////////////////////////////////
+int main(int argc, char **argv)
+{
+  ::testing::InitGoogleTest(&argc, argv);
+  return RUN_ALL_TESTS();
+}
diff --git a/src/Filter_TEST.cc b/src/Filter_TEST.cc
new file mode 100644
index 0000000..8451066
--- /dev/null
+++ b/src/Filter_TEST.cc
@@ -0,0 +1,105 @@
+/*
+ * Copyright (C) 2012 Open Source Robotics Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+*/
+
+#include <gtest/gtest.h>
+
+#include "ignition/math/Filter.hh"
+
+using namespace ignition;
+
+/////////////////////////////////////////////////
+TEST(FilterTest, OnePole)
+{
+  math::OnePole<double> filterA;
+  EXPECT_DOUBLE_EQ(filterA.Process(0.2), 0.0);
+
+  filterA.Fc(0.6, 1.4);
+  EXPECT_DOUBLE_EQ(filterA.Process(2.5), 2.3307710879153634);
+
+  math::OnePole<double> filterB(0.1, 0.2);
+  EXPECT_DOUBLE_EQ(filterB.Process(0.5), 0.47839304086811385);
+
+  filterB.Set(5.4);
+  EXPECT_DOUBLE_EQ(filterB.Value(), 5.4);
+}
+
+/////////////////////////////////////////////////
+TEST(FilterTest, OnePoleQuaternion)
+{
+  math::OnePoleQuaternion filterA;
+  EXPECT_EQ(filterA.Value(), math::Quaterniond(1, 0, 0, 0));
+
+  math::OnePoleQuaternion filterB(0.4, 1.4);
+  EXPECT_EQ(filterB.Value(), math::Quaterniond(1, 0, 0, 0));
+
+  EXPECT_EQ(filterA.Process(math::Quaterniond(0.1, 0.2, 0.3)),
+            math::Quaterniond(1, 0, 0, 0));
+
+  EXPECT_EQ(filterB.Process(math::Quaterniond(0.1, 0.2, 0.3)),
+            math::Quaterniond(0.98841, 0.0286272, 0.0885614, 0.119929));
+}
+
+/////////////////////////////////////////////////
+TEST(FilterTest, OnePoleVector3)
+{
+  math::OnePoleVector3 filterA;
+  EXPECT_EQ(filterA.Value(), math::Vector3d(0, 0, 0));
+
+  math::OnePoleVector3 filterB(1.2, 3.4);
+  EXPECT_EQ(filterB.Value(), math::Vector3d(0, 0, 0));
+
+  EXPECT_EQ(filterA.Process(math::Vector3d(0.1, 0.2, 0.3)),
+            math::Vector3d(0, 0, 0));
+
+  EXPECT_EQ(filterB.Process(math::Vector3d(0.1, 0.2, 0.3)),
+            math::Vector3d(0.089113, 0.178226, 0.267339));
+}
+
+/////////////////////////////////////////////////
+TEST(FilterTest, Biquad)
+{
+  math::BiQuad<double> filterA;
+  EXPECT_NEAR(filterA.Value(), 0.0, 1e-10);
+  EXPECT_NEAR(filterA.Process(1.1), 0.0, 1e-10);
+
+  filterA.Fc(0.3, 1.4);
+  EXPECT_DOUBLE_EQ(filterA.Process(1.2), 0.66924691484768517);
+
+  filterA.Fc(0.3, 1.4, 0.1);
+  EXPECT_DOUBLE_EQ(filterA.Process(10.25), 0.96057152402651302);
+
+  math::BiQuad<double> filterB(4.3, 10.6);
+  EXPECT_NEAR(filterB.Value(), 0.0, 1e-10);
+  EXPECT_DOUBLE_EQ(filterB.Process(0.1234),  0.072418159950486546);
+
+  filterB.Set(4.5);
+  EXPECT_DOUBLE_EQ(filterB.Value(), 4.5);
+}
+
+/////////////////////////////////////////////////
+TEST(FilterTest, BiquadVector3)
+{
+  math::BiQuadVector3 filterA;
+  EXPECT_EQ(filterA.Value(), math::Vector3d(0, 0, 0));
+  EXPECT_EQ(filterA.Process(math::Vector3d(1.1, 2.3, 3.4)),
+            math::Vector3d(0, 0, 0));
+
+  math::BiQuadVector3 filterB(6.5, 22.4);
+  EXPECT_EQ(filterB.Value(), math::Vector3d(0, 0, 0));
+  EXPECT_EQ(filterB.Process(math::Vector3d(0.1, 20.3, 33.45)),
+            math::Vector3d(0.031748, 6.44475, 10.6196));
+}
diff --git a/src/Frustum.cc b/src/Frustum.cc
new file mode 100644
index 0000000..9246798
--- /dev/null
+++ b/src/Frustum.cc
@@ -0,0 +1,254 @@
+/*
+ * Copyright (C) 2015 Open Source Robotics Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+*/
+#include <cmath>
+
+#include "ignition/math/Matrix4.hh"
+#include "FrustumPrivate.hh"
+#include "ignition/math/Frustum.hh"
+
+using namespace ignition;
+using namespace math;
+
+/////////////////////////////////////////////////
+Frustum::Frustum()
+  : dataPtr(new FrustumPrivate(0, 1, IGN_DTOR(45), 1, Pose3d::Zero))
+{
+}
+
+/////////////////////////////////////////////////
+Frustum::Frustum(const double _near,
+                 const double _far,
+                 const Angle &_fov,
+                 const double _aspectRatio,
+                 const Pose3d &_pose)
+  : dataPtr(new FrustumPrivate(_near, _far, _fov, _aspectRatio, _pose))
+{
+  // Compute plane based on near distance, far distance, field of view,
+  // aspect ratio, and pose
+  this->ComputePlanes();
+}
+
+/////////////////////////////////////////////////
+Frustum::~Frustum()
+{
+  delete this->dataPtr;
+  this->dataPtr = NULL;
+}
+
+/////////////////////////////////////////////////
+Frustum::Frustum(const Frustum &_p)
+  : dataPtr(new FrustumPrivate(_p.Near(), _p.Far(), _p.FOV(),
+        _p.AspectRatio(), _p.Pose()))
+{
+  for (int i = 0; i < 6; ++i)
+    this->dataPtr->planes[i] = _p.dataPtr->planes[i];
+}
+
+/////////////////////////////////////////////////
+Planed Frustum::Plane(const FrustumPlane _plane) const
+{
+  return this->dataPtr->planes[_plane];
+}
+
+/////////////////////////////////////////////////
+bool Frustum::Contains(const Box &_b) const
+{
+  // If the box is on the negative side of a plane, then the box is not
+  // visible.
+  for (auto const &plane : this->dataPtr->planes)
+  {
+    if (plane.Side(_b) == Planed::NEGATIVE_SIDE)
+      return false;
+  }
+
+  return true;
+}
+
+/////////////////////////////////////////////////
+bool Frustum::Contains(const Vector3d &_p) const
+{
+  // If the point is on the negative side of a plane, then the point is not
+  // visible.
+  for (auto const &plane : this->dataPtr->planes)
+  {
+    if (plane.Side(_p) == Planed::NEGATIVE_SIDE)
+      return false;
+  }
+
+  return true;
+}
+
+/////////////////////////////////////////////////
+double Frustum::Near() const
+{
+  return this->dataPtr->near;
+}
+
+/////////////////////////////////////////////////
+void Frustum::SetNear(const double _near)
+{
+  this->dataPtr->near = _near;
+  this->ComputePlanes();
+}
+
+/////////////////////////////////////////////////
+double Frustum::Far() const
+{
+  return this->dataPtr->far;
+}
+
+/////////////////////////////////////////////////
+void Frustum::SetFar(const double _far)
+{
+  this->dataPtr->far = _far;
+  this->ComputePlanes();
+}
+
+/////////////////////////////////////////////////
+Angle Frustum::FOV() const
+{
+  return this->dataPtr->fov;
+}
+
+/////////////////////////////////////////////////
+void Frustum::SetFOV(const Angle &_angle)
+{
+  this->dataPtr->fov = _angle;
+  this->ComputePlanes();
+}
+
+/////////////////////////////////////////////////
+Pose3d Frustum::Pose() const
+{
+  return this->dataPtr->pose;
+}
+
+/////////////////////////////////////////////////
+void Frustum::SetPose(const Pose3d &_pose)
+{
+  this->dataPtr->pose = _pose;
+  this->ComputePlanes();
+}
+
+/////////////////////////////////////////////////
+double Frustum::AspectRatio() const
+{
+  return this->dataPtr->aspectRatio;
+}
+
+/////////////////////////////////////////////////
+void Frustum::SetAspectRatio(const double _aspectRatio)
+{
+  this->dataPtr->aspectRatio = _aspectRatio;
+  this->ComputePlanes();
+}
+
+/////////////////////////////////////////////////
+void Frustum::ComputePlanes()
+{
+  // Tangent of half the field of view.
+  double tanFOV2 = std::tan(this->dataPtr->fov() * 0.5);
+
+  // Width of near plane
+  double nearWidth = 2.0 * tanFOV2 * this->dataPtr->near;
+
+  // Height of near plane
+  double nearHeight = nearWidth / this->dataPtr->aspectRatio;
+
+  // Width of far plane
+  double farWidth = 2.0 * tanFOV2 * this->dataPtr->far;
+
+  // Height of far plane
+  double farHeight = farWidth / this->dataPtr->aspectRatio;
+
+  // Up, right, and forward unit vectors.
+  Vector3d forward = this->dataPtr->pose.Rot().RotateVector(Vector3d::UnitX);
+  Vector3d up = this->dataPtr->pose.Rot().RotateVector(Vector3d::UnitZ);
+  Vector3d right = this->dataPtr->pose.Rot().RotateVector(-Vector3d::UnitY);
+
+  // Near plane center
+  Vector3d nearCenter = this->dataPtr->pose.Pos() + forward *
+    this->dataPtr->near;
+
+  // Far plane center
+  Vector3d farCenter = this->dataPtr->pose.Pos() + forward *
+    this->dataPtr->far;
+
+  // These four variables are here for convenience.
+  Vector3d upNearHeight2 = up * (nearHeight * 0.5);
+  Vector3d rightNearWidth2 = right * (nearWidth * 0.5);
+  Vector3d upFarHeight2 = up * (farHeight * 0.5);
+  Vector3d rightFarWidth2 = right * (farWidth * 0.5);
+
+  // Compute the vertices of the near plane
+  Vector3d nearTopLeft = nearCenter + upNearHeight2 - rightNearWidth2;
+  Vector3d nearTopRight = nearCenter + upNearHeight2 + rightNearWidth2;
+  Vector3d nearBottomLeft = nearCenter - upNearHeight2 - rightNearWidth2;
+  Vector3d nearBottomRight = nearCenter - upNearHeight2 + rightNearWidth2;
+
+  // Compute the vertices of the far plane
+  Vector3d farTopLeft = farCenter + upFarHeight2 - rightFarWidth2;
+  Vector3d farTopRight = farCenter + upFarHeight2 + rightFarWidth2;
+  Vector3d farBottomLeft = farCenter - upFarHeight2 - rightFarWidth2;
+  Vector3d farBottomRight = farCenter - upFarHeight2 + rightFarWidth2;
+
+  Vector3d leftCenter =
+    (farTopLeft + nearTopLeft + farBottomLeft + nearBottomLeft) / 4.0;
+
+  Vector3d rightCenter =
+    (farTopRight + nearTopRight + farBottomRight + nearBottomRight) / 4.0;
+
+  Vector3d topCenter =
+    (farTopRight + nearTopRight + farTopLeft + nearTopLeft) / 4.0;
+
+  Vector3d bottomCenter =
+    (farBottomRight + nearBottomRight + farBottomLeft + nearBottomLeft) / 4.0;
+
+  // Compute plane offsets
+  // Set the planes, where the first value is the plane normal and the
+  // second the plane offset
+  Vector3d norm = Vector3d::Normal(nearTopLeft, nearTopRight, nearBottomLeft);
+  this->dataPtr->planes[FRUSTUM_PLANE_NEAR].Set(norm, nearCenter.Dot(norm));
+
+  norm = Vector3d::Normal(farTopRight, farTopLeft, farBottomLeft);
+  this->dataPtr->planes[FRUSTUM_PLANE_FAR].Set(norm, farCenter.Dot(norm));
+
+  norm = Vector3d::Normal(farTopLeft, nearTopLeft, nearBottomLeft);
+  this->dataPtr->planes[FRUSTUM_PLANE_LEFT].Set(norm, leftCenter.Dot(norm));
+
+  norm = Vector3d::Normal(nearTopRight, farTopRight, farBottomRight);
+  this->dataPtr->planes[FRUSTUM_PLANE_RIGHT].Set(norm, rightCenter.Dot(norm));
+
+  norm = Vector3d::Normal(nearTopLeft, farTopLeft, nearTopRight);
+  this->dataPtr->planes[FRUSTUM_PLANE_TOP].Set(norm, topCenter.Dot(norm));
+
+  norm = Vector3d::Normal(nearBottomLeft, nearBottomRight, farBottomRight);
+  this->dataPtr->planes[FRUSTUM_PLANE_BOTTOM].Set(norm, bottomCenter.Dot(norm));
+}
+
+//////////////////////////////////////////////////
+Frustum &Frustum::operator =(const Frustum &_f)
+{
+  this->dataPtr->near = _f.dataPtr->near;
+  this->dataPtr->far = _f.dataPtr->far;
+  this->dataPtr->fov = _f.dataPtr->fov;
+  this->dataPtr->aspectRatio = _f.dataPtr->aspectRatio;
+  this->dataPtr->pose = _f.dataPtr->pose;
+  this->ComputePlanes();
+
+  return *this;
+}
diff --git a/src/FrustumPrivate.hh b/src/FrustumPrivate.hh
new file mode 100644
index 0000000..251dd65
--- /dev/null
+++ b/src/FrustumPrivate.hh
@@ -0,0 +1,78 @@
+/*
+ * Copyright (C) 2015 Open Source Robotics Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+*/
+#ifndef IGNITION_MATH_FRUSTUMPRIVATE_HH_
+#define IGNITION_MATH_FRUSTUMPRIVATE_HH_
+
+#include <array>
+
+#include <ignition/math/Pose3.hh>
+#include <ignition/math/Angle.hh>
+#include <ignition/math/Plane.hh>
+
+namespace ignition
+{
+  namespace math
+  {
+    /// \internal
+    /// \brief Private data for the Frustum class
+    class FrustumPrivate
+    {
+      /// \brief Constructor
+      /// \param[in] _near Near distance. This is the distance from
+      /// the frustum's vertex to the closest plane
+      /// \param[in] _far Far distance. This is the distance from the
+      /// frustum's vertex to the farthest plane.
+      /// \param[in] _fov Field of view. The field of view is the
+      /// angle between the frustum's vertex and the edges of the near or far
+      /// plane. This value represents the horizontal angle.
+      /// \param[in] _aspectRatio The aspect ratio, which is the width divided
+      /// by height of the near or far planes.
+      /// \param[in] _pose Pose of the frustum, which is the vertex (top of
+      /// the pyramid).
+      public: FrustumPrivate(const double _near,
+                             const double _far,
+                             const math::Angle &_fov,
+                             const double _aspectRatio,
+                             const Pose3d &_pose)
+              : near(_near), far(_far), fov(_fov),
+                aspectRatio(_aspectRatio), pose(_pose)
+              {
+              }
+
+      /// \brief Near distance
+      public: double near;
+
+      /// \brief Far distance
+      public: double far;
+
+      /// \brief Field of view
+      public: math::Angle fov;
+
+      /// \brief Aspect ratio of the near and far planes. This is the
+      // width divided by the height.
+      public: double aspectRatio;
+
+      /// \brief Pose of the frustum
+      public: math::Pose3d pose;
+
+      /// \brief Each plane of the frustum.
+      /// \sa Frustum::FrustumPlane
+      public: std::array<Planed, 6> planes;
+    };
+  }
+}
+#endif
diff --git a/src/Frustum_TEST.cc b/src/Frustum_TEST.cc
new file mode 100644
index 0000000..e51bb82
--- /dev/null
+++ b/src/Frustum_TEST.cc
@@ -0,0 +1,472 @@
+/*
+ * Copyright (C) 2015 Open Source Robotics Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+*/
+
+#include <gtest/gtest.h>
+
+#include "ignition/math/Helpers.hh"
+#include "ignition/math/Frustum.hh"
+
+using namespace ignition;
+using namespace math;
+
+/////////////////////////////////////////////////
+TEST(FrustumTest, Constructor)
+{
+  Frustum frustum;
+
+  EXPECT_DOUBLE_EQ(frustum.Near(), 0.0);
+  EXPECT_DOUBLE_EQ(frustum.Far(), 1.0);
+  EXPECT_EQ(frustum.FOV(), IGN_DTOR(45));
+  EXPECT_DOUBLE_EQ(frustum.AspectRatio(), 1.0);
+  EXPECT_EQ(frustum.Pose(), Pose3d::Zero);
+}
+
+/////////////////////////////////////////////////
+TEST(FrustumTest, CopyConstructor)
+{
+  // Frustum pointing down the +x axis
+  Frustum frustum(
+      // Near distance
+      1,
+      // Far distance
+      10,
+      // Field of view
+      Angle(IGN_DTOR(45)),
+      // Aspect ratio
+      320.0/240.0,
+      // Pose
+      Pose3d(0, 0, 0, 0, 0, 0));
+
+  Frustum frustum2(frustum);
+
+  EXPECT_EQ(frustum.FOV(), frustum2.FOV());
+  EXPECT_DOUBLE_EQ(frustum.Near(), frustum2.Near());
+  EXPECT_DOUBLE_EQ(frustum.Far(), frustum2.Far());
+  EXPECT_DOUBLE_EQ(frustum.AspectRatio(), frustum2.AspectRatio());
+  EXPECT_DOUBLE_EQ(frustum.AspectRatio(), frustum2.AspectRatio());
+
+  EXPECT_EQ(frustum.Plane(Frustum::FRUSTUM_PLANE_NEAR).Normal(),
+            frustum2.Plane(Frustum::FRUSTUM_PLANE_NEAR).Normal());
+
+  EXPECT_EQ(frustum.Plane(Frustum::FRUSTUM_PLANE_FAR).Normal(),
+            frustum2.Plane(Frustum::FRUSTUM_PLANE_FAR).Normal());
+
+  EXPECT_EQ(frustum.Plane(Frustum::FRUSTUM_PLANE_LEFT).Normal(),
+            frustum2.Plane(Frustum::FRUSTUM_PLANE_LEFT).Normal());
+
+  EXPECT_EQ(frustum.Plane(Frustum::FRUSTUM_PLANE_RIGHT).Normal(),
+            frustum2.Plane(Frustum::FRUSTUM_PLANE_RIGHT).Normal());
+
+  EXPECT_EQ(frustum.Plane(Frustum::FRUSTUM_PLANE_TOP).Normal(),
+            frustum2.Plane(Frustum::FRUSTUM_PLANE_TOP).Normal());
+
+  EXPECT_EQ(frustum.Plane(Frustum::FRUSTUM_PLANE_BOTTOM).Normal(),
+            frustum2.Plane(Frustum::FRUSTUM_PLANE_BOTTOM).Normal());
+}
+
+/////////////////////////////////////////////////
+TEST(FrustumTest, AssignmentOperator)
+{
+  // Frustum pointing to the +X+Y diagonal
+  Frustum frustum(
+      // Near distance
+      1,
+      // Far distance
+      10,
+      // Field of view
+      Angle(IGN_DTOR(45)),
+      // Aspect ratio
+      320.0/240.0,
+      // Pose
+      Pose3d(0, 0, 0, 0, 0, IGN_DTOR(45)));
+
+  Frustum frustum2;
+  frustum2 = frustum;
+
+  EXPECT_EQ(frustum.FOV(), frustum2.FOV());
+  EXPECT_DOUBLE_EQ(frustum.Near(), frustum2.Near());
+  EXPECT_DOUBLE_EQ(frustum.Far(), frustum2.Far());
+  EXPECT_DOUBLE_EQ(frustum.AspectRatio(), frustum2.AspectRatio());
+  EXPECT_DOUBLE_EQ(frustum.AspectRatio(), frustum2.AspectRatio());
+
+  EXPECT_EQ(frustum.Plane(Frustum::FRUSTUM_PLANE_NEAR).Normal(),
+            frustum2.Plane(Frustum::FRUSTUM_PLANE_NEAR).Normal());
+
+  EXPECT_EQ(frustum.Plane(Frustum::FRUSTUM_PLANE_FAR).Normal(),
+            frustum2.Plane(Frustum::FRUSTUM_PLANE_FAR).Normal());
+
+  EXPECT_EQ(frustum.Plane(Frustum::FRUSTUM_PLANE_LEFT).Normal(),
+            frustum2.Plane(Frustum::FRUSTUM_PLANE_LEFT).Normal());
+
+  EXPECT_EQ(frustum.Plane(Frustum::FRUSTUM_PLANE_RIGHT).Normal(),
+            frustum2.Plane(Frustum::FRUSTUM_PLANE_RIGHT).Normal());
+
+  EXPECT_EQ(frustum.Plane(Frustum::FRUSTUM_PLANE_TOP).Normal(),
+            frustum2.Plane(Frustum::FRUSTUM_PLANE_TOP).Normal());
+
+  EXPECT_EQ(frustum.Plane(Frustum::FRUSTUM_PLANE_BOTTOM).Normal(),
+            frustum2.Plane(Frustum::FRUSTUM_PLANE_BOTTOM).Normal());
+}
+
+/////////////////////////////////////////////////
+TEST(FrustumTest, PyramidXAxisPos)
+{
+  // Frustum pointing down the +x axis
+  Frustum frustum(
+      // Near distance
+      1,
+      // Far distance
+      10,
+      // Field of view
+      Angle(IGN_DTOR(45)),
+      // Aspect ratio
+      320.0/240.0,
+      // Pose
+      Pose3d(0, 0, 0, 0, 0, 0));
+
+  EXPECT_FALSE(frustum.Contains(Vector3d(0, 0, 0)));
+  EXPECT_TRUE(frustum.Contains(Vector3d(1, 0, 0)));
+
+  EXPECT_TRUE(frustum.Contains(Vector3d(2, 0, 0)));
+  EXPECT_TRUE(frustum.Contains(Vector3d(10, 0, 0)));
+  EXPECT_FALSE(frustum.Contains(Vector3d(10.1, 0, 0)));
+
+  EXPECT_TRUE(frustum.Contains(Box(Vector3d(1, 0, 0), Vector3d(5, 5, 5))));
+  EXPECT_FALSE(frustum.Contains(Box(Vector3d(-1, 0, 0), Vector3d(.1, .2, .3))));
+}
+
+/////////////////////////////////////////////////
+TEST(FrustumTest, PyramidXAxisNeg)
+{
+  // Frustum pointing down the -x axis
+  Frustum frustum(
+      // Near distance
+      1,
+      // Far distance
+      10,
+      // Field of view
+      Angle(IGN_DTOR(45)),
+      // Aspect ratio
+      320.0/240.0,
+      // Pose
+      Pose3d(0, 0, 0, 0, 0, IGN_PI));
+
+  EXPECT_FALSE(frustum.Contains(Vector3d(0, 0, 0)));
+  EXPECT_FALSE(frustum.Contains(Vector3d(-0.5, 0, 0)));
+  EXPECT_FALSE(frustum.Contains(Vector3d(-10.1, 0, 0)));
+
+  EXPECT_TRUE(frustum.Contains(Vector3d(-1, 0, 0)));
+  EXPECT_TRUE(frustum.Contains(Vector3d(-2, 0, 0)));
+  EXPECT_TRUE(frustum.Contains(Vector3d(-10, 0, 0)));
+
+  EXPECT_FALSE(frustum.Contains(Box(Vector3d(1, 0, 0), Vector3d(5, 5, 5))));
+  EXPECT_TRUE(frustum.Contains(Box(Vector3d(-1, 0, 0), Vector3d(.1, .2, .3))));
+}
+
+/////////////////////////////////////////////////
+TEST(FrustumTest, PyramidYAxis)
+{
+  // Frustum pointing down the +y axis
+  Frustum frustum(
+      // Near distance
+      .1,
+      // Far distance
+      5,
+      // Field of view
+      Angle(IGN_DTOR(45)),
+      // Aspect ratio
+      320.0/320.0,
+      // Pose
+      Pose3d(0, 0, 0, 0, 0, IGN_PI*0.5));
+
+  EXPECT_FALSE(frustum.Contains(Vector3d(0, 0, 0)));
+  EXPECT_FALSE(frustum.Contains(Vector3d(1, 0, 0)));
+  EXPECT_FALSE(frustum.Contains(Vector3d(.05, 0, 0)));
+
+  EXPECT_TRUE(frustum.Contains(Vector3d(0, .1, 0)));
+  EXPECT_TRUE(frustum.Contains(Vector3d(0, 1, 0)));
+  EXPECT_TRUE(frustum.Contains(Vector3d(0, 5, 0)));
+
+  EXPECT_TRUE(frustum.Contains(Box(Vector3d(0, 1, 0), Vector3d(5, 5, 5))));
+  EXPECT_FALSE(frustum.Contains(Box(Vector3d(0, -1, 0), Vector3d(.1, 0, .3))));
+}
+
+/////////////////////////////////////////////////
+TEST(FrustumTest, PyramidZAxis)
+{
+  // Frustum pointing down the -z axis
+  Frustum frustum(
+      // Near distance
+      1,
+      // Far distance
+      10,
+      // Field of view
+      Angle(IGN_DTOR(45)),
+      // Aspect ratio
+      320.0/320.0,
+      // Pose
+      Pose3d(0, 0, 0, 0, IGN_PI*0.5, 0));
+
+  EXPECT_FALSE(frustum.Contains(Vector3d(0, 0, 0)));
+  EXPECT_FALSE(frustum.Contains(Vector3d(0, 0, -0.9)));
+  EXPECT_FALSE(frustum.Contains(Vector3d(0, 0, -10.5)));
+  EXPECT_FALSE(frustum.Contains(Vector3d(0, 0, 0.9)));
+  EXPECT_FALSE(frustum.Contains(Vector3d(0, 0, 10.5)));
+
+  EXPECT_TRUE(frustum.Contains(Vector3d(0, 0, -1.1)));
+  EXPECT_TRUE(frustum.Contains(Vector3d(0.5, 0.5, -5.5)));
+  EXPECT_TRUE(frustum.Contains(Vector3d(0, 0, -10)));
+
+  EXPECT_FALSE(frustum.Contains(Box(Vector3d(0, 0, 0), Vector3d(5, 5, 5))));
+  EXPECT_TRUE(frustum.Contains(Box(Vector3d(0, 0, -1), Vector3d(.1, 0, .3))));
+}
+
+/////////////////////////////////////////////////
+TEST(FrustumTest, NearFar)
+{
+  Frustum frustum(
+      // Near distance
+      1,
+      // Far distance
+      10,
+      // Field of view
+      Angle(IGN_DTOR(45)),
+      // Aspect ratio
+      320.0/320.0,
+      // Pose
+      Pose3d(0, 0, 0, 0, IGN_PI*0.5, 0));
+
+  EXPECT_DOUBLE_EQ(frustum.Near(), 1.0);
+  EXPECT_DOUBLE_EQ(frustum.Far(), 10.0);
+
+  frustum.SetNear(-1.0);
+  frustum.SetFar(-10.0);
+
+  EXPECT_DOUBLE_EQ(frustum.Near(), -1.0);
+  EXPECT_DOUBLE_EQ(frustum.Far(), -10.0);
+}
+
+/////////////////////////////////////////////////
+TEST(FrustumTest, FOV)
+{
+  Frustum frustum(
+      // Near distance
+      1,
+      // Far distance
+      10,
+      // Field of view
+      Angle(IGN_DTOR(45)),
+      // Aspect ratio
+      320.0/320.0,
+      // Pose
+      Pose3d(0, 0, 0, 0, IGN_PI*0.5, 0));
+
+  EXPECT_EQ(frustum.FOV(), math::Angle(IGN_DTOR(45)));
+
+  frustum.SetFOV(1.5707);
+
+  EXPECT_EQ(frustum.FOV(), math::Angle(1.5707));
+}
+
+/////////////////////////////////////////////////
+TEST(FrustumTest, AspectRatio)
+{
+  Frustum frustum(
+      // Near distance
+      1,
+      // Far distance
+      10,
+      // Field of view
+      Angle(IGN_DTOR(45)),
+      // Aspect ratio
+      320.0/320.0,
+      // Pose
+      Pose3d(0, 0, 0, 0, IGN_PI*0.5, 0));
+
+  EXPECT_DOUBLE_EQ(frustum.AspectRatio(), 320.0/320.0);
+
+  frustum.SetAspectRatio(1.3434);
+
+  EXPECT_DOUBLE_EQ(frustum.AspectRatio(), 1.3434);
+}
+
+/////////////////////////////////////////////////
+TEST(FrustumTest, Pose)
+{
+  Frustum frustum(
+      // Near distance
+      1,
+      // Far distance
+      10,
+      // Field of view
+      Angle(IGN_DTOR(45)),
+      // Aspect ratio
+      320.0/320.0,
+      // Pose
+      Pose3d(0, 0, 0, 0, IGN_PI*0.5, 0));
+
+  EXPECT_EQ(frustum.Pose(), Pose3d(0, 0, 0, 0, IGN_PI*0.5, 0));
+
+  frustum.SetPose(Pose3d(1, 2, 3, IGN_PI, 0, 0));
+
+  EXPECT_EQ(frustum.Pose(), Pose3d(1, 2, 3, IGN_PI, 0, 0));
+}
+
+/////////////////////////////////////////////////
+TEST(FrustumTest, PoseContains)
+{
+  Frustum frustum(
+      // Near distance
+      1,
+      // Far distance
+      10,
+      // Field of view
+      Angle(IGN_DTOR(60)),
+      // Aspect ratio
+      1920.0/1080.0,
+      // Pose
+      Pose3d(0, -5, 0, 0, 0, IGN_PI*0.5));
+
+  // Test the near clip boundary
+  EXPECT_FALSE(frustum.Contains(Vector3d(0, -4.01, 0)));
+  EXPECT_TRUE(frustum.Contains(Vector3d(0, -4.0, 0)));
+
+  // Test a point between the near and far clip planes
+  EXPECT_TRUE(frustum.Contains(Vector3d(0, 1, 0)));
+
+  // Test the far clip boundary
+  EXPECT_TRUE(frustum.Contains(Vector3d(0, 5, 0)));
+  EXPECT_FALSE(frustum.Contains(Vector3d(0, 5.001, 0)));
+
+  // Use an offset for the test points. This makes the test more stable, and
+  // is also used to generate point outside the frustum.
+  double offset = 0.00001;
+
+  // Compute near clip points
+  Vector3d nearTopLeft(
+      -tan(IGN_DTOR(30)) + offset,
+      frustum.Pose().Pos().Y() + frustum.Near() + offset,
+      tan(IGN_DTOR(30)) / frustum.AspectRatio() - offset);
+
+  Vector3d nearTopLeftBad(
+      -tan(IGN_DTOR(30)) - offset,
+      frustum.Pose().Pos().Y() + frustum.Near() - offset,
+      tan(IGN_DTOR(30)) / frustum.AspectRatio() + offset);
+
+  Vector3d nearTopRight(
+      tan(IGN_DTOR(30)) - offset,
+      frustum.Pose().Pos().Y() + frustum.Near() + offset,
+      tan(IGN_DTOR(30)) / frustum.AspectRatio() - offset);
+
+  Vector3d nearTopRightBad(
+      tan(IGN_DTOR(30)) + offset,
+      frustum.Pose().Pos().Y() + frustum.Near() - offset,
+      tan(IGN_DTOR(30)) / frustum.AspectRatio() + offset);
+
+  Vector3d nearBottomLeft(
+      -tan(IGN_DTOR(30)) + offset,
+      frustum.Pose().Pos().Y() + frustum.Near() + offset,
+      -tan(IGN_DTOR(30)) / frustum.AspectRatio() + offset);
+
+  Vector3d nearBottomLeftBad(
+      -tan(IGN_DTOR(30)) - offset,
+      frustum.Pose().Pos().Y() + frustum.Near() - offset,
+      -tan(IGN_DTOR(30)) / frustum.AspectRatio() - offset);
+
+  Vector3d nearBottomRight(
+      tan(IGN_DTOR(30)) - offset,
+      frustum.Pose().Pos().Y() + frustum.Near() + offset,
+      -tan(IGN_DTOR(30)) / frustum.AspectRatio() + offset);
+
+  Vector3d nearBottomRightBad(
+      tan(IGN_DTOR(30)) + offset,
+      frustum.Pose().Pos().Y() + frustum.Near() - offset,
+      -tan(IGN_DTOR(30)) / frustum.AspectRatio() - offset);
+
+  // Test near clip corners
+  EXPECT_TRUE(frustum.Contains(nearTopLeft));
+  EXPECT_FALSE(frustum.Contains(nearTopLeftBad));
+
+  EXPECT_TRUE(frustum.Contains(nearTopRight));
+  EXPECT_FALSE(frustum.Contains(nearTopRightBad));
+
+  EXPECT_TRUE(frustum.Contains(nearBottomLeft));
+  EXPECT_FALSE(frustum.Contains(nearBottomLeftBad));
+
+  EXPECT_TRUE(frustum.Contains(nearBottomRight));
+  EXPECT_FALSE(frustum.Contains(nearBottomRightBad));
+
+  // Compute far clip points
+  Vector3d farTopLeft(
+      -tan(IGN_DTOR(30)) * frustum.Far() + offset,
+      frustum.Pose().Pos().Y() + frustum.Far() - offset,
+      (tan(IGN_DTOR(30)) * frustum.Far()) / frustum.AspectRatio() - offset);
+
+  Vector3d farTopLeftBad(
+      -tan(IGN_DTOR(30))*frustum.Far() - offset,
+      frustum.Pose().Pos().Y() + frustum.Far() + offset,
+      (tan(IGN_DTOR(30) * frustum.Far())) / frustum.AspectRatio() + offset);
+
+  Vector3d farTopRight(
+      tan(IGN_DTOR(30))*frustum.Far() - offset,
+      frustum.Pose().Pos().Y() + frustum.Far() - offset,
+      (tan(IGN_DTOR(30)) * frustum.Far()) / frustum.AspectRatio() - offset);
+
+  Vector3d farTopRightBad(
+      tan(IGN_DTOR(30))*frustum.Far() + offset,
+      frustum.Pose().Pos().Y() + frustum.Far() + offset,
+      (tan(IGN_DTOR(30)) * frustum.Far()) / frustum.AspectRatio() + offset);
+
+  Vector3d farBottomLeft(
+      -tan(IGN_DTOR(30))*frustum.Far() + offset,
+      frustum.Pose().Pos().Y() + frustum.Far() - offset,
+      (-tan(IGN_DTOR(30)) * frustum.Far()) / frustum.AspectRatio() + offset);
+
+  Vector3d farBottomLeftBad(
+      -tan(IGN_DTOR(30))*frustum.Far() - offset,
+      frustum.Pose().Pos().Y() + frustum.Far() + offset,
+      (-tan(IGN_DTOR(30)) * frustum.Far()) / frustum.AspectRatio() - offset);
+
+  Vector3d farBottomRight(
+      tan(IGN_DTOR(30))*frustum.Far() - offset,
+      frustum.Pose().Pos().Y() + frustum.Far() - offset,
+      (-tan(IGN_DTOR(30)) * frustum.Far()) / frustum.AspectRatio() + offset);
+
+  Vector3d farBottomRightBad(
+      tan(IGN_DTOR(30))*frustum.Far() + offset,
+      frustum.Pose().Pos().Y() + frustum.Far() + offset,
+      (-tan(IGN_DTOR(30)) * frustum.Far()) / frustum.AspectRatio() - offset);
+
+  // Test far clip corners
+  EXPECT_TRUE(frustum.Contains(farTopLeft));
+  EXPECT_FALSE(frustum.Contains(farTopLeftBad));
+
+  EXPECT_TRUE(frustum.Contains(farTopRight));
+  EXPECT_FALSE(frustum.Contains(farTopRightBad));
+
+  EXPECT_TRUE(frustum.Contains(farBottomLeft));
+  EXPECT_FALSE(frustum.Contains(farBottomLeftBad));
+
+  EXPECT_TRUE(frustum.Contains(farBottomRight));
+  EXPECT_FALSE(frustum.Contains(farBottomRightBad));
+
+  // Adjust to 45 degrees rotation
+  frustum.SetPose(Pose3d(1, 1, 0, 0, 0, -IGN_PI*0.25));
+  EXPECT_TRUE(frustum.Contains(Vector3d(2, -1, 0)));
+  EXPECT_FALSE(frustum.Contains(Vector3d(0, 0, 0)));
+  EXPECT_FALSE(frustum.Contains(Vector3d(1, 1, 0)));
+}
diff --git a/src/Helpers.cc b/src/Helpers.cc
new file mode 100644
index 0000000..836a613
--- /dev/null
+++ b/src/Helpers.cc
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2012 Open Source Robotics Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+*/
+#include "ignition/math/Helpers.hh"
+
+/////////////////////////////////////////////
+ignition::math::PairOutput ignition::math::Pair(
+    const ignition::math::PairInput _a, const ignition::math::PairInput _b)
+{
+  // Store in 64bit local variable so that we don't overflow.
+  uint64_t a = _a;
+  uint64_t b = _b;
+
+  // Szudzik's function
+  return _a >= _b ?
+          static_cast<PairOutput>(a * a + a + b) :
+          static_cast<PairOutput>(a + b * b);
+}
+
+/////////////////////////////////////////////
+std::tuple<ignition::math::PairInput, ignition::math::PairInput>
+ignition::math::Unpair(const ignition::math::PairOutput _key)
+{
+  // Must explicitly cast so that the _key is not auto cast to a double
+  uint64_t sqrt = static_cast<uint64_t>(
+      std::floor(std::sqrt(static_cast<long double>(_key))));
+  uint64_t sq = sqrt * sqrt;
+
+  return ((_key - sq) >= sqrt) ?
+    std::make_tuple(static_cast<PairInput>(sqrt),
+                    static_cast<PairInput>(_key - sq - sqrt)) :
+    std::make_tuple(static_cast<PairInput>(_key - sq),
+                    static_cast<PairInput>(sqrt));
+}
diff --git a/src/Helpers_TEST.cc b/src/Helpers_TEST.cc
new file mode 100644
index 0000000..a573ca4
--- /dev/null
+++ b/src/Helpers_TEST.cc
@@ -0,0 +1,517 @@
+/*
+ * Copyright (C) 2012 Open Source Robotics Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+*/
+
+#include <gtest/gtest.h>
+
+#include "ignition/math/Rand.hh"
+#include "ignition/math/Vector3.hh"
+#include "ignition/math/Helpers.hh"
+
+using namespace ignition;
+
+/////////////////////////////////////////////////
+// Test a few function in Helpers
+TEST(HelpersTest, Helpers)
+{
+  EXPECT_EQ(12345, math::parseInt("12345"));
+  EXPECT_EQ(-12345, math::parseInt("-12345"));
+  EXPECT_EQ(-12345, math::parseInt("    -12345"));
+  EXPECT_EQ(0, math::parseInt("    "));
+
+  EXPECT_EQ(math::NAN_I, math::parseInt(""));
+  EXPECT_EQ(math::NAN_I, math::parseInt("?"));
+  EXPECT_EQ(math::NAN_I, math::parseInt("23ab67"));
+
+  EXPECT_DOUBLE_EQ(12.345, math::parseFloat("12.345"));
+  EXPECT_DOUBLE_EQ(-12.345, math::parseFloat("-12.345"));
+  EXPECT_DOUBLE_EQ(-12.345, math::parseFloat("    -12.345"));
+  EXPECT_DOUBLE_EQ(0.0, math::parseFloat("    "));
+  EXPECT_TRUE(math::equal(123.45, math::parseFloat("1.2345e2"), 1e-2));
+  EXPECT_TRUE(math::equal(123.45, math::parseFloat("1.2345e+2"), 1e-2));
+  EXPECT_TRUE(math::equal(123.45, math::parseFloat("1.2345e+002"), 1e-2));
+  EXPECT_TRUE(math::equal(.012345, math::parseFloat("1.2345e-2"), 1e-2));
+  EXPECT_TRUE(math::equal(.012345, math::parseFloat("1.2345e-002"), 1e-2));
+  EXPECT_TRUE(math::equal(1.2345, math::parseFloat("1.2345e+"), 1e-2));
+  EXPECT_TRUE(math::equal(1.2345, math::parseFloat("1.2345e-"), 1e-2));
+  EXPECT_TRUE(math::lessOrNearEqual(1.0, 2.0, 1e-2));
+  EXPECT_TRUE(math::lessOrNearEqual(1.0, 1.0 - 9e-3, 1e-2));
+  EXPECT_FALSE(math::lessOrNearEqual(1.0, 1.0 - 1.1e-2, 1e-2));
+  EXPECT_TRUE(math::greaterOrNearEqual(1.0, 0.5, 1e-2));
+  EXPECT_TRUE(math::greaterOrNearEqual(1.0, 1.0 + 9e-3, 1e-2));
+  EXPECT_FALSE(math::greaterOrNearEqual(1.0, 1.0 + 1.1e-2, 1e-2));
+  EXPECT_DOUBLE_EQ(1.2345, math::parseFloat("1.2345e+0"));
+
+  EXPECT_TRUE(math::isnan(math::parseFloat("")));
+  EXPECT_TRUE(math::isnan(math::parseFloat("?")));
+  EXPECT_TRUE(math::isnan(math::parseFloat("23ab67")));
+
+  EXPECT_EQ(1u, math::roundUpPowerOfTwo(0));
+  EXPECT_EQ(1u, math::roundUpPowerOfTwo(1));
+  EXPECT_EQ(2u, math::roundUpPowerOfTwo(2));
+  EXPECT_EQ(2048u, math::roundUpPowerOfTwo(1025));
+}
+
+/////////////////////////////////////////////////
+// Test Helpers::precision
+TEST(HelpersTest, Precision)
+{
+  EXPECT_DOUBLE_EQ(0, math::precision(0.0, 1));
+  EXPECT_DOUBLE_EQ(0.1, math::precision(0.1, 1));
+  EXPECT_DOUBLE_EQ(0.1, math::precision(0.14, 1));
+  EXPECT_DOUBLE_EQ(0.2, math::precision(0.15, 1));
+  EXPECT_DOUBLE_EQ(0.15, math::precision(0.15, 2));
+
+  EXPECT_DOUBLE_EQ(1, math::precision(1.4, 0));
+  EXPECT_EQ(0, math::precision(0, 0));
+}
+
+/////////////////////////////////////////////////
+// Test Helpers::isPowerOfTwo
+TEST(HelpersTest, PowerOfTwo)
+{
+  EXPECT_FALSE(math::isPowerOfTwo(0));
+  EXPECT_FALSE(math::isPowerOfTwo(3));
+
+  EXPECT_TRUE(math::isPowerOfTwo(1));
+
+  EXPECT_TRUE(math::isPowerOfTwo(2));
+  EXPECT_TRUE(math::isPowerOfTwo(4));
+}
+
+// MSVC report errors on division by zero
+#ifndef _MSC_VER
+/////////////////////////////////////////////////
+// Test Helpers::fixnan functions
+TEST(HelpersTest, FixNaN)
+{
+  EXPECT_DOUBLE_EQ(math::fixnan(1.0 / 0.0), 0.0);
+  EXPECT_DOUBLE_EQ(math::fixnan(-1.0 / 0.0), 0.0);
+  EXPECT_DOUBLE_EQ(math::fixnan(0.0 / 0.0), 0.0);
+
+  EXPECT_DOUBLE_EQ(math::fixnan(42.0), 42.0);
+  EXPECT_DOUBLE_EQ(math::fixnan(-42.0), -42.0);
+
+  EXPECT_FLOAT_EQ(math::fixnan(1.0f / 0.0f), 0.0f);
+  EXPECT_FLOAT_EQ(math::fixnan(-1.0f / 0.0f), 0.0f);
+  EXPECT_FLOAT_EQ(math::fixnan(0.0f / 0.0f), 0.0f);
+
+  EXPECT_FLOAT_EQ(math::fixnan(42.0f), 42.0f);
+  EXPECT_FLOAT_EQ(math::fixnan(-42.0f), -42.0f);
+}
+#endif
+
+/////////////////////////////////////////////////
+// Even test
+TEST(HelpersTest, Even)
+{
+  int i = 1;
+  signed s = 1;
+  signed int si = 1;
+  unsigned u = 1;
+  unsigned int ui = 1;
+
+  EXPECT_FALSE(math::isEven(i));
+  EXPECT_FALSE(math::isEven(s));
+  EXPECT_FALSE(math::isEven(si));
+  EXPECT_FALSE(math::isEven(u));
+  EXPECT_FALSE(math::isEven(ui));
+
+  i = -1;
+  s = -1;
+  si = -1;
+
+  EXPECT_FALSE(math::isEven(i));
+  EXPECT_FALSE(math::isEven(s));
+  EXPECT_FALSE(math::isEven(si));
+
+  i = 4;
+  s = 4;
+  si = 4;
+  u = 4;
+  ui = 4;
+
+  EXPECT_TRUE(math::isEven(i));
+  EXPECT_TRUE(math::isEven(s));
+  EXPECT_TRUE(math::isEven(si));
+  EXPECT_TRUE(math::isEven(u));
+  EXPECT_TRUE(math::isEven(ui));
+
+  i = -2;
+  s = -2;
+  si = -2;
+
+  EXPECT_TRUE(math::isEven(i));
+  EXPECT_TRUE(math::isEven(s));
+  EXPECT_TRUE(math::isEven(si));
+
+  i = 0;
+  s = 0;
+  si = 0;
+  u = 0;
+  ui = 0;
+
+  EXPECT_TRUE(math::isEven(i));
+  EXPECT_TRUE(math::isEven(s));
+  EXPECT_TRUE(math::isEven(si));
+  EXPECT_TRUE(math::isEven(u));
+  EXPECT_TRUE(math::isEven(ui));
+}
+
+/////////////////////////////////////////////////
+// Odd test
+TEST(HelpersTest, Odd)
+{
+  int i = 1;
+  signed s = 1;
+  signed int si = 1;
+  unsigned u = 1;
+  unsigned int ui = 1;
+
+  EXPECT_TRUE(math::isOdd(i));
+  EXPECT_TRUE(math::isOdd(s));
+  EXPECT_TRUE(math::isOdd(si));
+  EXPECT_TRUE(math::isOdd(u));
+  EXPECT_TRUE(math::isOdd(ui));
+
+  i = -1;
+  s = -1;
+  si = -1;
+
+  EXPECT_TRUE(math::isOdd(i));
+  EXPECT_TRUE(math::isOdd(s));
+  EXPECT_TRUE(math::isOdd(si));
+
+  i = 4;
+  s = 4;
+  si = 4;
+  u = 4;
+  ui = 4;
+
+  EXPECT_FALSE(math::isOdd(i));
+  EXPECT_FALSE(math::isOdd(s));
+  EXPECT_FALSE(math::isOdd(si));
+  EXPECT_FALSE(math::isOdd(u));
+  EXPECT_FALSE(math::isOdd(ui));
+
+  i = -2;
+  s = -2;
+  si = -2;
+
+  EXPECT_FALSE(math::isOdd(i));
+  EXPECT_FALSE(math::isOdd(s));
+  EXPECT_FALSE(math::isOdd(si));
+
+  i = 0;
+  s = 0;
+  si = 0;
+  u = 0;
+  ui = 0;
+
+  EXPECT_FALSE(math::isOdd(i));
+  EXPECT_FALSE(math::isOdd(s));
+  EXPECT_FALSE(math::isOdd(si));
+  EXPECT_FALSE(math::isOdd(u));
+  EXPECT_FALSE(math::isOdd(ui));
+}
+
+/////////////////////////////////////////////////
+// Signum test
+TEST(HelpersTest, Signum)
+{
+  int i = 1;
+  signed s = 1;
+  signed int si = 1;
+  unsigned u = 1;
+  unsigned int ui = 1;
+  float f = 1.f;
+  double d = 1.;
+
+  EXPECT_EQ(1, math::signum(i));
+  EXPECT_EQ(1, math::signum(s));
+  EXPECT_EQ(1, math::signum(si));
+  EXPECT_EQ(1, math::signum(u));
+  EXPECT_EQ(1, math::signum(ui));
+  EXPECT_EQ(1, math::signum(f));
+  EXPECT_EQ(1, math::signum(d));
+
+  i = s = si = u = ui = 2;
+  f = 2.f;
+  d = 2.;
+
+  EXPECT_EQ(1, math::signum(i));
+  EXPECT_EQ(1, math::signum(s));
+  EXPECT_EQ(1, math::signum(si));
+  EXPECT_EQ(1, math::signum(u));
+  EXPECT_EQ(1, math::signum(ui));
+  EXPECT_EQ(1, math::signum(f));
+  EXPECT_EQ(1, math::signum(d));
+
+  i = s = si = u = ui = 0;
+  f = 0.f;
+  d = 0.;
+
+  EXPECT_EQ(0, math::signum(i));
+  EXPECT_EQ(0, math::signum(s));
+  EXPECT_EQ(0, math::signum(si));
+  EXPECT_EQ(0, math::signum(u));
+  EXPECT_EQ(0, math::signum(ui));
+  EXPECT_EQ(0, math::signum(f));
+  EXPECT_EQ(0, math::signum(d));
+
+  i = s = si = -1;
+  f = -1.f;
+  d = -1.;
+
+  EXPECT_EQ(-1, math::signum(i));
+  EXPECT_EQ(-1, math::signum(s));
+  EXPECT_EQ(-1, math::signum(si));
+  EXPECT_EQ(-1, math::signum(f));
+  EXPECT_EQ(-1, math::signum(d));
+
+  i = s = si = -2;
+  f = -2.f;
+  d = -2.;
+
+  EXPECT_EQ(-1, math::signum(i));
+  EXPECT_EQ(-1, math::signum(s));
+  EXPECT_EQ(-1, math::signum(si));
+  EXPECT_EQ(-1, math::signum(f));
+  EXPECT_EQ(-1, math::signum(d));
+
+  f = -2.5f;
+  d = -2.5;
+
+  EXPECT_EQ(-1, math::signum(f));
+  EXPECT_EQ(-1, math::signum(d));
+
+  f = 2.5f;
+  d = 2.5;
+
+  EXPECT_EQ(1, math::signum(f));
+  EXPECT_EQ(1, math::signum(d));
+
+  f = 1e-10f;
+  d = 1e-10;
+
+  EXPECT_EQ(1, math::signum(f));
+  EXPECT_EQ(1, math::signum(d));
+}
+
+/////////////////////////////////////////////////
+TEST(HelpersTest, Sort)
+{
+  {
+    int a = 2;
+    int b = -1;
+    math::sort2(a, b);
+    EXPECT_LE(a, b);
+  }
+
+  {
+    int a = 0;
+    int b = 1;
+    math::sort2(a, b);
+    EXPECT_LE(a, b);
+  }
+
+  {
+    int a = 2;
+    int b = -1;
+    int c = 0;
+    math::sort3(a, b, c);
+    EXPECT_LE(a, b);
+    EXPECT_LE(b, c);
+  }
+
+  {
+    unsigned int a = 2;
+    unsigned int b = 1;
+    math::sort2(a, b);
+    EXPECT_LE(a, b);
+  }
+
+  {
+    unsigned int a = 2;
+    unsigned int b = 1;
+    unsigned int c = 0;
+    math::sort3(a, b, c);
+    EXPECT_LE(a, b);
+    EXPECT_LE(b, c);
+  }
+  {
+    unsigned int a = 0;
+    unsigned int b = 1;
+    unsigned int c = 2;
+    math::sort3(a, b, c);
+    EXPECT_LE(a, b);
+    EXPECT_LE(b, c);
+  }
+
+
+  {
+    float a = 2.1f;
+    float b = -1.1e-1f;
+    math::sort2(a, b);
+    EXPECT_LE(a, b);
+  }
+
+  {
+    float a = 34.5f;
+    float b = -1.34f;
+    float c = 0.194f;
+    math::sort3(a, b, c);
+    EXPECT_LE(a, b);
+    EXPECT_LE(b, c);
+  }
+
+  {
+    double a = 2.1;
+    double b = -1.1e-1;
+    math::sort2(a, b);
+    EXPECT_LE(a, b);
+  }
+
+  {
+    double a = 34.5;
+    double b = -1.34;
+    double c = 0.194;
+    math::sort3(a, b, c);
+    EXPECT_LE(a, b);
+    EXPECT_LE(b, c);
+  }
+}
+
+/////////////////////////////////////////////////
+TEST(HelpersTest, Volume)
+{
+  EXPECT_DOUBLE_EQ(IGN_SPHERE_VOLUME(1.0), 4.0*IGN_PI*std::pow(1, 3)/3.0);
+  EXPECT_DOUBLE_EQ(IGN_SPHERE_VOLUME(0.1), 4.0*IGN_PI*std::pow(.1, 3)/3.0);
+  EXPECT_DOUBLE_EQ(IGN_SPHERE_VOLUME(-1.1), 4.0*IGN_PI*std::pow(-1.1, 3)/3.0);
+
+  EXPECT_DOUBLE_EQ(IGN_CYLINDER_VOLUME(0.5, 2.0), 2 * IGN_PI * std::pow(.5, 2));
+  EXPECT_DOUBLE_EQ(IGN_CYLINDER_VOLUME(1, -1), -1 * IGN_PI * std::pow(1, 2));
+
+  EXPECT_DOUBLE_EQ(IGN_BOX_VOLUME(1, 2, 3), 1 * 2 * 3);
+  EXPECT_DOUBLE_EQ(IGN_BOX_VOLUME(.1, .2, .3),
+                   IGN_BOX_VOLUME_V(math::Vector3d(0.1, 0.2, 0.3)));
+}
+
+/////////////////////////////////////////////////
+TEST(HelpersTest, Pair)
+{
+#ifdef _MSC_VER
+  math::PairInput maxA = math::MAX_UI16;
+  math::PairInput maxB = math::MAX_UI16;
+#else
+  math::PairInput maxA = math::MAX_UI32;
+  math::PairInput maxB = math::MAX_UI32;
+#endif
+
+  math::PairInput maxC, maxD;
+
+  // Maximum parameters should generate a maximum key
+  math::PairOutput maxKey = math::Pair(maxA, maxB);
+#ifdef _MSC_VER
+  EXPECT_EQ(maxKey, math::MAX_UI32);
+#else
+  EXPECT_EQ(maxKey, math::MAX_UI64);
+#endif
+
+  std::tie(maxC, maxD) = math::Unpair(maxKey);
+  EXPECT_EQ(maxC, maxA);
+  EXPECT_EQ(maxD, maxB);
+
+#ifdef _MSC_VER
+  math::PairInput minA = math::MIN_UI16;
+  math::PairInput minB = math::MIN_UI16;
+#else
+  math::PairInput minA = math::MIN_UI32;
+  math::PairInput minB = math::MIN_UI32;
+#endif
+  math::PairInput minC, minD;
+
+  // Minimum parameters should generate a minimum key
+  math::PairOutput minKey = math::Pair(minA, minB);
+#ifdef _MSC_VER
+  EXPECT_EQ(minKey, math::MIN_UI32);
+#else
+  EXPECT_EQ(minKey, math::MIN_UI64);
+#endif
+
+  std::tie(minC, minD) = math::Unpair(minKey);
+  EXPECT_EQ(minC, minA);
+  EXPECT_EQ(minD, minB);
+
+  // Max key != min key
+  EXPECT_TRUE(minKey != maxKey);
+
+  // Just a simple test case
+  {
+    unsigned int a = 10;
+    unsigned int b = 20;
+    math::PairInput c, d;
+
+    auto key = math::Pair(static_cast<math::PairInput>(a),
+                          static_cast<math::PairInput>(b));
+    EXPECT_EQ(key, 410u);
+    EXPECT_TRUE(key != maxKey);
+    EXPECT_TRUE(key != minKey);
+
+    std::tie(c, d) = math::Unpair(key);
+    EXPECT_EQ(c, a);
+    EXPECT_EQ(d, b);
+  }
+
+  {
+    math::PairInput c, d;
+    std::set<math::PairOutput> set;
+
+    // Iterate over range of pairs, and check for unique keys.
+    for (uint16_t a = math::MIN_UI16; a < math::MAX_UI16 - 500;
+         a += static_cast<uint16_t>(math::Rand::IntUniform(100, 500)))
+    {
+      for (uint16_t b = math::MIN_UI16; b < math::MAX_UI16 - 500;
+         b += static_cast<uint16_t>(math::Rand::IntUniform(100, 500)))
+      {
+        math::PairOutput key = math::Pair(a, b);
+        std::tie(c, d) = math::Unpair(key);
+        EXPECT_EQ(a, c);
+        EXPECT_EQ(b, d);
+        EXPECT_TRUE(set.find(key) == set.end());
+        EXPECT_TRUE(key != maxKey);
+        set.insert(key);
+      }
+    }
+
+#ifndef _MSC_VER
+    // Iterate over large numbers, and check for unique keys.
+    for (math::PairInput a = math::MAX_UI32-5000; a < math::MAX_UI32; a++)
+    {
+      for (math::PairInput b = math::MAX_UI32-5000; b < math::MAX_UI32; b++)
+      {
+        math::PairOutput key = math::Pair(a, b);
+        std::tie(c, d) = math::Unpair(key);
+        EXPECT_EQ(a, c);
+        EXPECT_EQ(b, d);
+        EXPECT_TRUE(set.find(key) == set.end());
+        EXPECT_TRUE(key != minKey);
+        set.insert(key);
+      }
+    }
+#endif
+  }
+}
diff --git a/src/Inertial_TEST.cc b/src/Inertial_TEST.cc
new file mode 100644
index 0000000..db9e390
--- /dev/null
+++ b/src/Inertial_TEST.cc
@@ -0,0 +1,527 @@
+/*
+ * Copyright (C) 2015 Open Source Robotics Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+*/
+
+#include <gtest/gtest.h>
+#include <cmath>
+
+#include "ignition/math/Inertial.hh"
+
+using namespace ignition;
+
+/////////////////////////////////////////////////
+/// \brief Compare quaternions, but allow rotations of PI about any axis.
+void CompareModuloPi(const math::Quaterniond &_q1,
+                     const math::Quaterniond &_q2,
+                     const double _tol = 1e-6)
+{
+  const auto rotErrorEuler = (_q1.Inverse() * _q2).Euler();
+  EXPECT_NEAR(sin(rotErrorEuler.X()), 0.0, _tol);
+  EXPECT_NEAR(sin(rotErrorEuler.Y()), 0.0, _tol);
+  EXPECT_NEAR(sin(rotErrorEuler.Z()), 0.0, _tol);
+}
+
+/////////////////////////////////////////////////
+// Simple constructor, test default values
+TEST(Inertiald_Test, Constructor)
+{
+  math::Inertiald inertial;
+  EXPECT_EQ(inertial.Pose(), math::Pose3d::Zero);
+  EXPECT_EQ(inertial.MassMatrix(), math::MassMatrix3d());
+  EXPECT_EQ(inertial.MOI(), math::Matrix3d::Zero);
+}
+
+/////////////////////////////////////////////////
+// Constructor with default arguments
+// Should match simple constructor and with copy constructor
+TEST(Inertiald_Test, ConstructorDefaultValues)
+{
+  math::Inertiald inertial(math::MassMatrix3d(), math::Pose3d::Zero);
+  EXPECT_EQ(inertial, math::Inertiald());
+  EXPECT_EQ(inertial, math::Inertiald(inertial));
+}
+
+/////////////////////////////////////////////////
+// Constructor with non-default arguments
+TEST(Inertiald_Test, ConstructorNonDefaultValues)
+{
+  const double mass = 5.0;
+  const math::Vector3d Ixxyyzz(2.0, 3.0, 4.0);
+  const math::Vector3d Ixyxzyz(0.2, 0.3, 0.4);
+  math::MassMatrix3d m(mass, Ixxyyzz, Ixyxzyz);
+  EXPECT_TRUE(m.IsPositive());
+  EXPECT_TRUE(m.IsValid());
+  const math::Pose3d pose(1, 2, 3, IGN_PI/6, 0, 0);
+  math::Inertiald inertial(m, pose);
+
+  // Should not match simple constructor
+  EXPECT_NE(inertial, math::Inertiald());
+
+  // Should match with copy constructor
+  EXPECT_EQ(inertial, math::Inertiald(inertial));
+
+  // Test accessors
+  EXPECT_EQ(inertial.MassMatrix(), m);
+  EXPECT_EQ(inertial.Pose(), pose);
+  EXPECT_TRUE(inertial.MassMatrix().IsPositive());
+  EXPECT_TRUE(inertial.MassMatrix().IsValid());
+
+  // Test assignment operator
+  math::Inertiald inertial2;
+  EXPECT_NE(inertial, inertial2);
+  inertial2 = inertial;
+  EXPECT_EQ(inertial, inertial2);
+}
+
+/////////////////////////////////////////////////
+TEST(Inertiald_Test, CoverageExtra)
+{
+  // getting full destructor coverage
+  math::Inertiald *p = new math::Inertiald;
+  EXPECT_TRUE(p != NULL);
+  delete p;
+}
+
+/////////////////////////////////////////////////
+TEST(Inertiald_Test, Setters)
+{
+  const double mass = 5.0;
+  const math::Vector3d Ixxyyzz(2.0, 3.0, 4.0);
+  const math::Vector3d Ixyxzyz(0.2, 0.3, 0.4);
+  math::MassMatrix3d m(mass, Ixxyyzz, Ixyxzyz);
+  EXPECT_TRUE(m.IsPositive());
+  EXPECT_TRUE(m.IsValid());
+  const math::Pose3d pose(1, 2, 3, IGN_PI/6, 0, 0);
+  math::Inertiald inertial;
+
+  // Initially invalid
+  EXPECT_FALSE(inertial.SetPose(pose));
+
+  // Valid once valid mass matrix is set
+  EXPECT_TRUE(inertial.SetMassMatrix(m));
+
+  // Verify values
+  EXPECT_EQ(inertial.MassMatrix(), m);
+  EXPECT_EQ(inertial.Pose(), pose);
+
+  // Invalid again if an invalid inertia is set
+  math::MassMatrix3d mInvalid(-1, Ixxyyzz, Ixyxzyz);
+  EXPECT_FALSE(inertial.SetMassMatrix(mInvalid));
+}
+
+/////////////////////////////////////////////////
+TEST(Inertiald_Test, MOI_Diagonal)
+{
+  const double mass = 12.0;
+  const math::Vector3d Ixxyyzz(2.0, 3.0, 4.0);
+  const math::Vector3d Ixyxzyz(0, 0, 0);
+  const math::MassMatrix3d m(mass, Ixxyyzz, Ixyxzyz);
+  EXPECT_TRUE(m.IsPositive());
+  EXPECT_TRUE(m.IsValid());
+
+  // no rotation, expect MOI's to match
+  {
+    const math::Pose3d pose(0, 0, 0, 0, 0, 0);
+    math::Inertiald inertial(m, pose);
+    EXPECT_EQ(inertial.MOI(), m.MOI());
+  }
+
+  // 90 deg rotation about X axis, expect different MOI
+  {
+    const math::Pose3d pose(0, 0, 0, IGN_PI_2, 0, 0);
+    const math::Matrix3d expectedMOI(2, 0, 0, 0, 4, 0, 0, 0, 3);
+    math::Inertiald inertial(m, pose);
+    EXPECT_NE(inertial.MOI(), m.MOI());
+    EXPECT_EQ(inertial.MOI(), expectedMOI);
+  }
+
+  // 90 deg rotation about Y axis, expect different MOI
+  {
+    const math::Pose3d pose(0, 0, 0, 0, IGN_PI_2, 0);
+    const math::Matrix3d expectedMOI(4, 0, 0, 0, 3, 0, 0, 0, 2);
+    math::Inertiald inertial(m, pose);
+    EXPECT_NE(inertial.MOI(), m.MOI());
+    EXPECT_EQ(inertial.MOI(), expectedMOI);
+  }
+
+  // 90 deg rotation about Z axis, expect different MOI
+  {
+    const math::Pose3d pose(0, 0, 0, 0, 0, IGN_PI_2);
+    const math::Matrix3d expectedMOI(3, 0, 0, 0, 2, 0, 0, 0, 4);
+    math::Inertiald inertial(m, pose);
+    EXPECT_NE(inertial.MOI(), m.MOI());
+    EXPECT_EQ(inertial.MOI(), expectedMOI);
+  }
+
+  // 45 deg rotation about Z axis, expect different MOI
+  {
+    const math::Pose3d pose(0, 0, 0, 0, 0, IGN_PI_4);
+    const math::Matrix3d expectedMOI(2.5, -0.5, 0, -0.5, 2.5, 0, 0, 0, 4);
+    math::Inertiald inertial(m, pose);
+    EXPECT_NE(inertial.MOI(), m.MOI());
+    EXPECT_EQ(inertial.MOI(), expectedMOI);
+
+    // double check with a second MassMatrix3 instance
+    // that has the same base frame MOI but no pose rotation
+    math::MassMatrix3d m2;
+    EXPECT_FALSE(m2.Mass(mass));
+    EXPECT_TRUE(m2.MOI(expectedMOI));
+    EXPECT_EQ(inertial.MOI(), m2.MOI());
+    // There are multiple correct rotations due to symmetry
+    CompareModuloPi(m2.PrincipalAxesOffset(), pose.Rot());
+  }
+}
+
+/////////////////////////////////////////////////
+// Base frame MOI should be invariant
+void SetRotation(const double _mass,
+    const math::Vector3d &_ixxyyzz,
+    const math::Vector3d &_ixyxzyz,
+    const bool _unique = true)
+{
+  const math::MassMatrix3d m(_mass, _ixxyyzz, _ixyxzyz);
+  EXPECT_TRUE(m.IsPositive());
+  EXPECT_TRUE(m.IsValid());
+
+  math::Pose3d pose(math::Vector3d::Zero, math::Quaterniond::Identity);
+  const math::Inertiald inertialRef(m, pose);
+  const auto moi = inertialRef.MOI();
+
+  const std::vector<math::Quaterniond> rotations = {
+    math::Quaterniond::Identity,
+    math::Quaterniond(IGN_PI, 0, 0),
+    math::Quaterniond(0, IGN_PI, 0),
+    math::Quaterniond(0, 0, IGN_PI),
+    math::Quaterniond(IGN_PI_2, 0, 0),
+    math::Quaterniond(0, IGN_PI_2, 0),
+    math::Quaterniond(0, 0, IGN_PI_2),
+    math::Quaterniond(IGN_PI_4, 0, 0),
+    math::Quaterniond(0, IGN_PI_4, 0),
+    math::Quaterniond(0, 0, IGN_PI_4),
+    math::Quaterniond(IGN_PI/6, 0, 0),
+    math::Quaterniond(0, IGN_PI/6, 0),
+    math::Quaterniond(0, 0, IGN_PI/6),
+    math::Quaterniond(0.1, 0.2, 0.3),
+    math::Quaterniond(-0.1, 0.2, -0.3),
+    math::Quaterniond(0.4, 0.2, 0.5),
+    math::Quaterniond(-0.1, 0.7, -0.7)};
+  for (const auto rot : rotations)
+  {
+    {
+      auto inertial = inertialRef;
+
+      const double tol  = -1e-6;
+      EXPECT_TRUE(inertial.SetMassMatrixRotation(rot, tol));
+      EXPECT_EQ(moi, inertial.MOI());
+      if (_unique)
+      {
+        CompareModuloPi(rot, inertial.MassMatrix().PrincipalAxesOffset(tol));
+      }
+
+      EXPECT_TRUE(inertial.SetInertialRotation(rot));
+      EXPECT_EQ(rot, inertial.Pose().Rot());
+      EXPECT_EQ(moi, inertial.MOI());
+    }
+
+    {
+      auto inertial = inertialRef;
+
+      EXPECT_TRUE(inertial.SetInertialRotation(rot));
+      EXPECT_EQ(rot, inertial.Pose().Rot());
+      EXPECT_EQ(moi, inertial.MOI());
+
+      const double tol = -1e-6;
+      EXPECT_TRUE(inertial.SetMassMatrixRotation(rot, tol));
+      EXPECT_EQ(moi, inertial.MOI());
+      if (_unique)
+      {
+        CompareModuloPi(rot, inertial.MassMatrix().PrincipalAxesOffset(tol));
+      }
+    }
+  }
+}
+
+/////////////////////////////////////////////////
+TEST(Inertiald_Test, SetRotationUniqueDiagonal)
+{
+  SetRotation(12, math::Vector3d(2, 3, 4), math::Vector3d::Zero);
+  SetRotation(12, math::Vector3d(3, 2, 4), math::Vector3d::Zero);
+  SetRotation(12, math::Vector3d(2, 4, 3), math::Vector3d::Zero);
+  SetRotation(12, math::Vector3d(3, 4, 2), math::Vector3d::Zero);
+  SetRotation(12, math::Vector3d(4, 2, 3), math::Vector3d::Zero);
+  SetRotation(12, math::Vector3d(4, 3, 2), math::Vector3d::Zero);
+}
+
+/////////////////////////////////////////////////
+TEST(Inertiald_Test, SetRotationUniqueNondiagonal)
+{
+  SetRotation(12, math::Vector3d(2, 3, 4), math::Vector3d(0.3, 0.2, 0.1));
+}
+
+/////////////////////////////////////////////////
+TEST(Inertiald_Test, SetRotationNonuniqueDiagonal)
+{
+  SetRotation(12, math::Vector3d(2, 2, 2), math::Vector3d::Zero, false);
+  SetRotation(12, math::Vector3d(2, 2, 3), math::Vector3d::Zero, false);
+  SetRotation(12, math::Vector3d(2, 3, 2), math::Vector3d::Zero, false);
+  SetRotation(12, math::Vector3d(3, 2, 2), math::Vector3d::Zero, false);
+  SetRotation(12, math::Vector3d(2, 3, 3), math::Vector3d::Zero, false);
+  SetRotation(12, math::Vector3d(3, 2, 3), math::Vector3d::Zero, false);
+  SetRotation(12, math::Vector3d(3, 3, 2), math::Vector3d::Zero, false);
+}
+
+/////////////////////////////////////////////////
+TEST(Inertiald_Test, SetRotationNonuniqueNondiagonal)
+{
+  SetRotation(12, math::Vector3d(4, 4, 3), math::Vector3d(-1, 0, 0), false);
+  SetRotation(12, math::Vector3d(4, 3, 4), math::Vector3d(0, -1, 0), false);
+  SetRotation(12, math::Vector3d(3, 4, 4), math::Vector3d(0, 0, -1), false);
+  SetRotation(12, math::Vector3d(4, 4, 5), math::Vector3d(-1, 0, 0), false);
+  SetRotation(12, math::Vector3d(5, 4, 4), math::Vector3d(0, 0, -1), false);
+  SetRotation(12, math::Vector3d(5.5, 4.125, 4.375),
+             0.25*math::Vector3d(-sqrt(3), 3.0, -sqrt(3)/2), false);
+  SetRotation(12, math::Vector3d(4.125, 5.5, 4.375),
+                      0.25*math::Vector3d(-sqrt(3), -sqrt(3)/2, 3.0), false);
+}
+
+/////////////////////////////////////////////////
+// test for diagonalizing MassMatrix
+// verify MOI is conserved
+// and that off-diagonal terms are zero
+void Diagonalize(
+    const double _mass,
+    const math::Vector3d &_ixxyyzz,
+    const math::Vector3d &_ixyxzyz)
+{
+  const math::MassMatrix3d m(_mass, _ixxyyzz, _ixyxzyz);
+  EXPECT_TRUE(m.IsPositive());
+  EXPECT_TRUE(m.IsValid());
+
+  math::Pose3d pose(math::Vector3d::Zero, math::Quaterniond::Identity);
+  math::Inertiald inertial(m, pose);
+  const auto moi = inertial.MOI();
+
+  EXPECT_TRUE(inertial.SetMassMatrixRotation(math::Quaterniond::Identity));
+  EXPECT_EQ(moi, inertial.MOI());
+  EXPECT_EQ(inertial.MassMatrix().OffDiagonalMoments(), math::Vector3d::Zero);
+
+  // try again with negative tolerance
+  EXPECT_TRUE(
+    inertial.SetMassMatrixRotation(math::Quaterniond::Identity, -1e-6));
+  EXPECT_EQ(moi, inertial.MOI());
+  EXPECT_EQ(inertial.MassMatrix().OffDiagonalMoments(), math::Vector3d::Zero);
+}
+
+/////////////////////////////////////////////////
+TEST(Inertiald_Test, Diagonalize)
+{
+  Diagonalize(12, math::Vector3d(2, 3, 4), math::Vector3d::Zero);
+  Diagonalize(12, math::Vector3d(3, 2, 4), math::Vector3d::Zero);
+  Diagonalize(12, math::Vector3d(2, 4, 3), math::Vector3d::Zero);
+  Diagonalize(12, math::Vector3d(3, 4, 2), math::Vector3d::Zero);
+  Diagonalize(12, math::Vector3d(4, 2, 3), math::Vector3d::Zero);
+  Diagonalize(12, math::Vector3d(4, 3, 2), math::Vector3d::Zero);
+  Diagonalize(12, math::Vector3d(2, 3, 4), math::Vector3d(0.3, 0.2, 0.1));
+  Diagonalize(12, math::Vector3d(2, 2, 2), math::Vector3d::Zero);
+  Diagonalize(12, math::Vector3d(2, 2, 3), math::Vector3d::Zero);
+  Diagonalize(12, math::Vector3d(2, 3, 2), math::Vector3d::Zero);
+  Diagonalize(12, math::Vector3d(3, 2, 2), math::Vector3d::Zero);
+  Diagonalize(12, math::Vector3d(2, 3, 3), math::Vector3d::Zero);
+  Diagonalize(12, math::Vector3d(3, 2, 3), math::Vector3d::Zero);
+  Diagonalize(12, math::Vector3d(3, 3, 2), math::Vector3d::Zero);
+  Diagonalize(12, math::Vector3d(4, 4, 3), math::Vector3d(-1, 0, 0));
+  Diagonalize(12, math::Vector3d(4, 3, 4), math::Vector3d(0, -1, 0));
+  Diagonalize(12, math::Vector3d(3, 4, 4), math::Vector3d(0, 0, -1));
+  Diagonalize(12, math::Vector3d(4, 4, 5), math::Vector3d(-1, 0, 0));
+  Diagonalize(12, math::Vector3d(5, 4, 4), math::Vector3d(0, 0, -1));
+  Diagonalize(12, math::Vector3d(5.5, 4.125, 4.375),
+                               0.25*math::Vector3d(-sqrt(3), 3.0, -sqrt(3)/2));
+  Diagonalize(12, math::Vector3d(4.125, 5.5, 4.375),
+                      0.25*math::Vector3d(-sqrt(3), -sqrt(3)/2, 3.0));
+}
+/////////////////////////////////////////////////
+TEST(Inertiald_Test, Addition)
+{
+  // Add two half-cubes together
+  {
+    const double mass = 12.0;
+    const math::Vector3d size(1, 1, 1);
+    math::MassMatrix3d cubeMM3;
+    EXPECT_TRUE(cubeMM3.SetFromBox(mass, size));
+    const math::Inertiald cube(cubeMM3, math::Pose3d::Zero);
+    math::MassMatrix3d half;
+    EXPECT_TRUE(half.SetFromBox(0.5*mass, math::Vector3d(0.5, 1, 1)));
+    math::Inertiald left(half, math::Pose3d(-0.25, 0, 0, 0, 0, 0));
+    math::Inertiald right(half, math::Pose3d(0.25, 0, 0, 0, 0, 0));
+    EXPECT_EQ(cube, left + right);
+    EXPECT_EQ(cube, right + left);
+    // test += operator
+    {
+      math::Inertiald tmp = left;
+      tmp += right;
+      EXPECT_EQ(cube, tmp);
+    }
+    {
+      math::Inertiald tmp = right;
+      tmp += left;
+      EXPECT_EQ(cube, tmp);
+    }
+    // Test EquivalentBox
+    {
+      math::Vector3d size2;
+      math::Quaterniond rot2;
+      EXPECT_TRUE((left + right).MassMatrix().EquivalentBox(size2, rot2));
+      EXPECT_EQ(size, size2);
+      EXPECT_EQ(rot2, math::Quaterniond::Identity);
+    }
+    {
+      math::Vector3d size2;
+      math::Quaterniond rot2;
+      EXPECT_TRUE((right + left).MassMatrix().EquivalentBox(size2, rot2));
+      EXPECT_EQ(size, size2);
+      EXPECT_EQ(rot2, math::Quaterniond::Identity);
+    }
+  }
+
+  // Add two rotated half-cubes together
+  {
+    const double mass = 12.0;
+    const math::Vector3d size(1, 1, 1);
+    math::MassMatrix3d cubeMM3;
+    EXPECT_TRUE(cubeMM3.SetFromBox(mass, size));
+    const math::Inertiald cube(cubeMM3, math::Pose3d(0, 0, 0, IGN_PI_4, 0, 0));
+
+    math::MassMatrix3d half;
+    EXPECT_TRUE(half.SetFromBox(0.5*mass, math::Vector3d(0.5, 1, 1)));
+    math::Inertiald left(half, math::Pose3d(-0.25, 0, 0, IGN_PI_4, 0, 0));
+    math::Inertiald right(half, math::Pose3d(0.25, 0, 0, IGN_PI_4, 0, 0));
+
+    // objects won't match exactly
+    // since inertia matrices will all be in base frame
+    // but mass, center of mass, and base-frame MOI should match
+    EXPECT_NE(cube, left + right);
+    EXPECT_NE(cube, right + left);
+    EXPECT_DOUBLE_EQ(cubeMM3.Mass(), (left + right).MassMatrix().Mass());
+    EXPECT_DOUBLE_EQ(cubeMM3.Mass(), (right + left).MassMatrix().Mass());
+    EXPECT_EQ(cube.Pose().Pos(), (left + right).Pose().Pos());
+    EXPECT_EQ(cube.Pose().Pos(), (right + left).Pose().Pos());
+    EXPECT_EQ(cube.MOI(), (left + right).MOI());
+    EXPECT_EQ(cube.MOI(), (right + left).MOI());
+  }
+
+  // Add eight cubes together into larger cube
+  {
+    const double mass = 12.0;
+    const math::Vector3d size(1, 1, 1);
+    math::MassMatrix3d cubeMM3;
+    EXPECT_TRUE(cubeMM3.SetFromBox(mass, size));
+    const math::Inertiald addedCube =
+      math::Inertiald(cubeMM3, math::Pose3d(-0.5, -0.5, -0.5, 0, 0, 0)) +
+      math::Inertiald(cubeMM3, math::Pose3d(-0.5,  0.5, -0.5, 0, 0, 0)) +
+      math::Inertiald(cubeMM3, math::Pose3d(0.5,  -0.5, -0.5, 0, 0, 0)) +
+      math::Inertiald(cubeMM3, math::Pose3d(0.5,   0.5, -0.5, 0, 0, 0)) +
+      math::Inertiald(cubeMM3, math::Pose3d(-0.5, -0.5, 0.5, 0, 0, 0)) +
+      math::Inertiald(cubeMM3, math::Pose3d(-0.5,  0.5, 0.5, 0, 0, 0)) +
+      math::Inertiald(cubeMM3, math::Pose3d(0.5,  -0.5, 0.5, 0, 0, 0)) +
+      math::Inertiald(cubeMM3, math::Pose3d(0.5,   0.5, 0.5, 0, 0, 0));
+
+    math::MassMatrix3d trueCubeMM3;
+    EXPECT_TRUE(trueCubeMM3.SetFromBox(8*mass, 2*size));
+    EXPECT_EQ(addedCube, math::Inertiald(trueCubeMM3, math::Pose3d::Zero));
+  }
+
+  // Add eight rotated cubes together into larger cube
+  {
+    const double mass = 12.0;
+    const math::Vector3d size(1, 1, 1);
+    math::MassMatrix3d cubeMM3;
+    EXPECT_TRUE(cubeMM3.SetFromBox(mass, size));
+    const math::Inertiald addedCube =
+      math::Inertiald(cubeMM3, math::Pose3d(-0.5, -0.5, -0.5, 0, 0, 0)) +
+      math::Inertiald(cubeMM3, math::Pose3d(-0.5,  0.5, -0.5, IGN_PI_2, 0, 0)) +
+      math::Inertiald(cubeMM3, math::Pose3d(0.5,  -0.5, -0.5, 0, IGN_PI_2, 0)) +
+      math::Inertiald(cubeMM3, math::Pose3d(0.5,   0.5, -0.5, 0, 0, IGN_PI_2)) +
+      math::Inertiald(cubeMM3, math::Pose3d(-0.5, -0.5, 0.5, IGN_PI, 0, 0)) +
+      math::Inertiald(cubeMM3, math::Pose3d(-0.5,  0.5, 0.5, 0, IGN_PI, 0)) +
+      math::Inertiald(cubeMM3, math::Pose3d(0.5,  -0.5, 0.5, 0, 0, IGN_PI)) +
+      math::Inertiald(cubeMM3, math::Pose3d(0.5,   0.5, 0.5, 0, 0, 0));
+
+    math::MassMatrix3d trueCubeMM3;
+    EXPECT_TRUE(trueCubeMM3.SetFromBox(8*mass, 2*size));
+    EXPECT_EQ(addedCube, math::Inertiald(trueCubeMM3, math::Pose3d::Zero));
+  }
+}
+
+/////////////////////////////////////////////////
+// Addition operator has different behavior if mass is non-positive
+TEST(Inertiald_Test, AdditionInvalid)
+{
+  // inertias all zero
+  const math::MassMatrix3d m0(0.0, math::Vector3d::Zero, math::Vector3d::Zero);
+  EXPECT_FALSE(m0.IsPositive());
+  EXPECT_FALSE(m0.IsValid());
+
+  // both inertials with zero mass
+  {
+    math::Inertiald left(m0, math::Pose3d(-1, 0, 0, 0, 0, 0));
+    math::Inertiald right(m0, math::Pose3d(1, 0, 0, 0, 0, 0));
+
+    // expect sum to equal left argument
+    EXPECT_EQ(left, left + right);
+    EXPECT_EQ(right, right + left);
+    {
+      math::Inertiald tmp = left;
+      tmp += right;
+      EXPECT_EQ(tmp, left);
+    }
+    {
+      math::Inertiald tmp = right;
+      tmp += left;
+      EXPECT_EQ(tmp, right);
+    }
+  }
+
+  // one inertial with zero inertias should not affect the sum
+  {
+    math::MassMatrix3d m(12.0,
+      math::Vector3d(2, 3, 4),
+      math::Vector3d(0.1, 0.2, 0.3));
+    EXPECT_TRUE(m.IsPositive());
+    EXPECT_TRUE(m.IsValid());
+
+    math::Inertiald i(m, math::Pose3d(-1, 0, 0, 0, 0, 0));
+    math::Inertiald i0(m0, math::Pose3d(1, 0, 0, 0, 0, 0));
+
+    // expect i0 to not affect the sum
+    EXPECT_EQ(i, i + i0);
+    EXPECT_EQ(i, i0 + i);
+    {
+      math::Inertiald tmp = i;
+      tmp += i0;
+      EXPECT_EQ(tmp, i);
+    }
+    {
+      math::Inertiald tmp = i0;
+      tmp += i;
+      EXPECT_EQ(tmp, i);
+    }
+
+    EXPECT_TRUE((i + i0).MassMatrix().IsPositive());
+    EXPECT_TRUE((i0 + i).MassMatrix().IsPositive());
+    EXPECT_TRUE((i + i0).MassMatrix().IsValid());
+    EXPECT_TRUE((i0 + i).MassMatrix().IsValid());
+  }
+}
diff --git a/src/Kmeans.cc b/src/Kmeans.cc
new file mode 100644
index 0000000..a524c23
--- /dev/null
+++ b/src/Kmeans.cc
@@ -0,0 +1,172 @@
+/*
+ * Copyright (C) 2014 Open Source Robotics Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+*/
+
+#include <iostream>
+#include <ignition/math/Kmeans.hh>
+#include <ignition/math/Rand.hh>
+#include "KmeansPrivate.hh"
+
+using namespace ignition;
+using namespace math;
+
+//////////////////////////////////////////////////
+Kmeans::Kmeans(const std::vector<Vector3d> &_obs)
+: dataPtr(new KmeansPrivate)
+{
+  this->Observations(_obs);
+}
+
+//////////////////////////////////////////////////
+Kmeans::~Kmeans()
+{
+  delete this->dataPtr;
+  this->dataPtr = NULL;
+}
+
+//////////////////////////////////////////////////
+std::vector<Vector3d> Kmeans::Observations() const
+{
+  return this->dataPtr->obs;
+}
+
+//////////////////////////////////////////////////
+bool Kmeans::Observations(const std::vector<Vector3d> &_obs)
+{
+  if (_obs.empty())
+  {
+    std::cerr << "Kmeans::SetObservations() error: Observations vector is empty"
+              << std::endl;
+    return false;
+  }
+  this->dataPtr->obs = _obs;
+  return true;
+}
+
+//////////////////////////////////////////////////
+bool Kmeans::AppendObservations(const std::vector<Vector3d> &_obs)
+{
+  if (_obs.empty())
+  {
+    std::cerr << "Kmeans::AppendObservations() error: input vector is empty"
+              << std::endl;
+    return false;
+  }
+  this->dataPtr->obs.insert(this->dataPtr->obs.end(), _obs.begin(), _obs.end());
+  return true;
+}
+
+//////////////////////////////////////////////////
+bool Kmeans::Cluster(int _k,
+                     std::vector<Vector3d> &_centroids,
+                     std::vector<unsigned int> &_labels)
+{
+  // Sanity check.
+  if (this->dataPtr->obs.empty())
+  {
+    std::cerr << "Kmeans error: The set of observations is empty" << std::endl;
+    return false;
+  }
+
+  if (_k <= 0)
+  {
+    std::cerr << "Kmeans error: The number of clusters has to"
+              << " be positive but its value is [" << _k << "]"
+              << std::endl;
+    return false;
+  }
+
+  if (_k > static_cast<int>(this->dataPtr->obs.size()))
+  {
+    std::cerr << "Kmeans error: The number of clusters [" << _k << "] has to be"
+              << " lower or equal to the number of observations ["
+              << this->dataPtr->obs.size() << "]" << std::endl;
+    return false;
+  }
+
+  size_t changed = 0;
+
+  // Initialize the size of the vectors;
+  this->dataPtr->centroids.clear();
+  this->dataPtr->labels.resize(this->dataPtr->obs.size());
+  this->dataPtr->sums.resize(_k);
+  this->dataPtr->counters.resize(_k);
+
+  for (auto i = 0; i < _k; ++i)
+  {
+    // Choose a random observation and make sure it has not been chosen before.
+    // Note: This is not really random but it's faster than choosing a random
+    // one and verifying that it was not taken before.
+    this->dataPtr->centroids.push_back(this->dataPtr->obs[i]);
+  }
+
+  // Initialize labels.
+  for (auto i = 0u; i < this->dataPtr->obs.size(); ++i)
+    this->dataPtr->labels[i] = 0;
+
+  do
+  {
+    // Reset sums and counters.
+    for (auto i = 0u; i < this->dataPtr->centroids.size(); ++i)
+    {
+      this->dataPtr->sums[i] = Vector3d::Zero;
+      this->dataPtr->counters[i] = 0;
+    }
+    changed = 0;
+
+    for (auto i = 0u; i < this->dataPtr->obs.size(); ++i)
+    {
+      // Update the labels containing the closest centroid for each point.
+      auto label = this->ClosestCentroid(this->dataPtr->obs[i]);
+      if (this->dataPtr->labels[i] != label)
+      {
+        this->dataPtr->labels[i] = label;
+        changed++;
+      }
+      this->dataPtr->sums[label] += this->dataPtr->obs[i];
+      this->dataPtr->counters[label]++;
+    }
+
+    // Update the centroids.
+    for (auto i = 0u; i < this->dataPtr->centroids.size(); ++i)
+    {
+      this->dataPtr->centroids[i] =
+        this->dataPtr->sums[i] / this->dataPtr->counters[i];
+    }
+  }
+  while (changed > (this->dataPtr->obs.size() >> 10));
+
+  _centroids = this->dataPtr->centroids;
+  _labels = this->dataPtr->labels;
+  return true;
+}
+
+//////////////////////////////////////////////////
+unsigned int Kmeans::ClosestCentroid(const Vector3d &_p) const
+{
+  double min = HUGE_VAL;
+  unsigned int minIdx = 0;
+  for (auto i = 0u; i < this->dataPtr->centroids.size(); ++i)
+  {
+    double d = _p.Distance(this->dataPtr->centroids[i]);
+    if (d < min)
+    {
+      min = d;
+      minIdx = i;
+    }
+  }
+  return minIdx;
+}
diff --git a/src/KmeansPrivate.hh b/src/KmeansPrivate.hh
new file mode 100644
index 0000000..8c1cbbb
--- /dev/null
+++ b/src/KmeansPrivate.hh
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 2015 Open Source Robotics Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+*/
+#ifndef IGNITION_MATH_KMEANSPRIVATE_HH_
+#define IGNITION_MATH_KMEANSPRIVATE_HH_
+
+#include <vector>
+#include <ignition/math/Vector3.hh>
+#include <ignition/math/Helpers.hh>
+
+namespace ignition
+{
+  namespace math
+  {
+    /// \internal
+    /// \brief Private data for Kmeans class
+    class KmeansPrivate
+    {
+      /// \brief Observations.
+      public: std::vector<Vector3d> obs;
+
+      /// \brief Centroids.
+      public: std::vector<Vector3d> centroids;
+
+      /// \brief Each element stores the cluster to which observation i belongs.
+      public: std::vector<unsigned int> labels;
+
+      /// \brief Used to calculate the centroid of each partition.
+      public: std::vector<Vector3d> sums;
+
+      /// \brief Counts the number of observations contained in each partition.
+      public: std::vector<unsigned int> counters;
+    };
+  }
+}
+#endif
+
+
diff --git a/src/Kmeans_TEST.cc b/src/Kmeans_TEST.cc
new file mode 100644
index 0000000..4478f26
--- /dev/null
+++ b/src/Kmeans_TEST.cc
@@ -0,0 +1,142 @@
+/*
+ * Copyright (C) 2014 Open Source Robotics Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+*/
+
+#include <gtest/gtest.h>
+#include <vector>
+#include "ignition/math/Kmeans.hh"
+
+using namespace ignition;
+
+//////////////////////////////////////////////////
+TEST(KmeansTest, Kmeans)
+{
+  // Create some observations.
+  std::vector<math::Vector3d> obs;
+  obs.push_back(math::Vector3d(1.0, 1.0, 0.0));
+  obs.push_back(math::Vector3d(1.1, 1.0, 0.0));
+  obs.push_back(math::Vector3d(1.2, 1.0, 0.0));
+  obs.push_back(math::Vector3d(1.3, 1.0, 0.0));
+  obs.push_back(math::Vector3d(1.4, 1.0, 0.0));
+  obs.push_back(math::Vector3d(5.0, 1.0, 0.0));
+  obs.push_back(math::Vector3d(5.1, 1.0, 0.0));
+  obs.push_back(math::Vector3d(5.2, 1.0, 0.0));
+  obs.push_back(math::Vector3d(5.3, 1.0, 0.0));
+  obs.push_back(math::Vector3d(5.4, 1.0, 0.0));
+
+  // Initialize Kmeans with two partitions.
+  math::Kmeans kmeans(obs);
+
+  // ::GetObservations()
+  std::vector<math::Vector3d> obsCopy;
+  obsCopy = kmeans.Observations();
+  for (size_t i = 0; i < obsCopy.size(); ++i)
+    EXPECT_EQ(obsCopy[i], obs[i]);
+
+  // ::SetObservations()
+  for (auto &elem : obsCopy)
+    elem += math::Vector3d(0.1, 0.2, 0.0);
+
+  EXPECT_TRUE(kmeans.Observations(obsCopy));
+
+  obsCopy = kmeans.Observations();
+  for (size_t i = 0; i < obsCopy.size(); ++i)
+    EXPECT_EQ(obsCopy[i], obs[i] + math::Vector3d(0.1, 0.2, 0.0));
+  EXPECT_TRUE(kmeans.Observations(obs));
+
+  // ::Cluster()
+  std::vector<math::Vector3d> centroids;
+  std::vector<unsigned int> labels;
+  EXPECT_TRUE(kmeans.Cluster(2, centroids, labels));
+
+  // Check that there are two centroids.
+  EXPECT_EQ(centroids.size(), 2u);
+
+  // Check that the observations are clustered properly.
+  EXPECT_EQ(labels[0], labels[1]);
+  EXPECT_EQ(labels[1], labels[2]);
+  EXPECT_EQ(labels[2], labels[3]);
+  EXPECT_EQ(labels[3], labels[4]);
+
+  EXPECT_NE(labels[4], labels[5]);
+
+  EXPECT_EQ(labels[5], labels[6]);
+  EXPECT_EQ(labels[6], labels[7]);
+  EXPECT_EQ(labels[7], labels[8]);
+  EXPECT_EQ(labels[8], labels[9]);
+
+  // Check the centroids.
+  math::Vector3d expectedCentroid1(1.2, 1.0, 0.0);
+  math::Vector3d expectedCentroid2(5.2, 1.0, 0.0);
+  if (centroids[0] == expectedCentroid1)
+    EXPECT_EQ(centroids[1], expectedCentroid2);
+  else if (centroids[0] == expectedCentroid2)
+    EXPECT_EQ(centroids[1], expectedCentroid1);
+  else
+    FAIL();
+
+  // Try to use an empty observation vector.
+  obsCopy.clear();
+  EXPECT_FALSE(kmeans.Observations(obsCopy));
+
+  // Try to call 'Cluster()' with an empty vector.
+  math::Kmeans kmeansEmpty(obsCopy);
+  EXPECT_FALSE(kmeansEmpty.Cluster(2, centroids, labels));
+
+  // Try to use a non positive k.
+  EXPECT_FALSE(kmeans.Cluster(0, centroids, labels));
+
+  // Try to use a k > num_observations.
+  EXPECT_FALSE(kmeans.Cluster(static_cast<int>(obs.size() + 1),
+                              centroids, labels));
+}
+
+//////////////////////////////////////////////////
+TEST(KmeansTest, Append)
+{
+  // Create some observations.
+  std::vector<math::Vector3d> obs, obs2, obsTotal;
+
+  obs.push_back(math::Vector3d(1.0, 1.0, 0.0));
+  obs.push_back(math::Vector3d(1.1, 1.0, 0.0));
+  obs.push_back(math::Vector3d(1.2, 1.0, 0.0));
+  obs.push_back(math::Vector3d(1.3, 1.0, 0.0));
+  obs.push_back(math::Vector3d(1.4, 1.0, 0.0));
+
+  obs2.push_back(math::Vector3d(5.0, 1.0, 0.0));
+  obs2.push_back(math::Vector3d(5.1, 1.0, 0.0));
+  obs2.push_back(math::Vector3d(5.2, 1.0, 0.0));
+  obs2.push_back(math::Vector3d(5.3, 1.0, 0.0));
+  obs2.push_back(math::Vector3d(5.4, 1.0, 0.0));
+
+  obsTotal.insert(obsTotal.end(), obs.begin(), obs.end());
+  obsTotal.insert(obsTotal.end(), obs2.begin(), obs2.end());
+
+  // Initialize Kmeans with two partitions.
+  math::Kmeans kmeans(obs);
+
+  kmeans.AppendObservations(obs2);
+
+  std::vector<math::Vector3d> obsCopy;
+  obsCopy = kmeans.Observations();
+
+  for (size_t i = 0; i < obsCopy.size(); ++i)
+    EXPECT_EQ(obsTotal[i], obsCopy[i]);
+
+  // Append an empty vector.
+  std::vector<math::Vector3d> emptyVector;
+  EXPECT_FALSE(kmeans.AppendObservations(emptyVector));
+}
diff --git a/src/Line2_TEST.cc b/src/Line2_TEST.cc
new file mode 100644
index 0000000..6ac2654
--- /dev/null
+++ b/src/Line2_TEST.cc
@@ -0,0 +1,268 @@
+/*
+ * Copyright (C) 2014 Open Source Robotics Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+*/
+
+#include <gtest/gtest.h>
+
+#include "ignition/math/Line2.hh"
+#include "ignition/math/Helpers.hh"
+
+using namespace ignition;
+
+/////////////////////////////////////////////////
+TEST(Line2Test, Constructor)
+{
+  math::Line2d lineA(0, 0, 10, 10);
+  EXPECT_DOUBLE_EQ(lineA[0].X(), 0.0);
+  EXPECT_DOUBLE_EQ(lineA[0].Y(), 0.0);
+  EXPECT_DOUBLE_EQ(lineA[1].X(), 10.0);
+  EXPECT_DOUBLE_EQ(lineA[1].Y(), 10.0);
+
+  math::Line2d lineB(math::Vector2d(1, 2), math::Vector2d(3, 4));
+  EXPECT_DOUBLE_EQ(lineB[0].X(), 1.0);
+  EXPECT_DOUBLE_EQ(lineB[0].Y(), 2.0);
+  EXPECT_DOUBLE_EQ(lineB[1].X(), 3.0);
+  EXPECT_DOUBLE_EQ(lineB[1].Y(), 4.0);
+
+  EXPECT_NO_THROW(lineB[2].X());
+  EXPECT_DOUBLE_EQ(lineB[2].X(), lineB[1].X());
+  EXPECT_NO_THROW(lineA[0].X());
+}
+
+/////////////////////////////////////////////////
+TEST(Line2Test, Length)
+{
+  math::Line2d lineA(0, 0, 10, 10);
+  EXPECT_NEAR(lineA.Length(), sqrt(200), 1e-10);
+}
+
+#ifdef _MSC_VER
+#pragma warning(push)
+// C4723: potential divide by 0
+#pragma warning(disable : 4723)
+#endif
+/////////////////////////////////////////////////
+TEST(Line2Test, Slope)
+{
+  {
+    math::Line2d line(0, 0, 10, 10);
+    EXPECT_NEAR(line.Slope(), 1.0, 1e-10);
+  }
+
+  {
+    math::Line2d line(0, 0, 0, 10);
+    EXPECT_TRUE(math::isnan(line.Slope()));
+  }
+
+  {
+    math::Line2d line(-10, 0, 100, 0);
+    EXPECT_DOUBLE_EQ(line.Slope(), 0.0);
+  }
+}
+#ifdef _MSC_VER
+#pragma warning(pop)
+#endif
+
+/////////////////////////////////////////////////
+TEST(Line2Test, ParallelLine)
+{
+  {
+    // Line is always parallel with itself
+    math::Line2d line(0, 0, 10, 0);
+    EXPECT_TRUE(line.Parallel(line, 1e-10));
+  }
+
+  {
+    // Degenerate line segment
+    // Still expect Line is parallel with itself
+    math::Line2d line(0, 0, 0, 0);
+    EXPECT_TRUE(line.Parallel(line, 1e-10));
+  }
+
+  math::Line2d lineA(0, 0, 10, 0);
+  math::Line2d lineB(0, 0, 10, 0);
+  EXPECT_TRUE(lineA.Parallel(lineB, 1e-10));
+
+  lineB.Set(0, 0, 0, 10);
+  EXPECT_FALSE(lineA.Parallel(lineB));
+
+  lineB.Set(0, 10, 10, 10);
+  EXPECT_TRUE(lineA.Parallel(lineB));
+
+  lineB.Set(0, 10, 10, 10.00001);
+  EXPECT_FALSE(lineA.Parallel(lineB, 1e-10));
+  EXPECT_FALSE(lineA.Parallel(lineB));
+  EXPECT_TRUE(lineA.Parallel(lineB, 1e-3));
+}
+
+/////////////////////////////////////////////////
+TEST(Line2Test, CollinearLine)
+{
+  {
+    // Line is always collinear with itself
+    math::Line2d line(0, 0, 10, 0);
+    EXPECT_TRUE(line.Collinear(line, 1e-10));
+  }
+
+  math::Line2d lineA(0, 0, 10, 0);
+  math::Line2d lineB(0, 0, 10, 0);
+  EXPECT_TRUE(lineA.Collinear(lineB, 1e-10));
+
+  lineB.Set(0, 10, 10, 10);
+  EXPECT_FALSE(lineA.Collinear(lineB));
+
+  lineB.Set(9, 0, 10, 0.00001);
+  EXPECT_FALSE(lineA.Collinear(lineB, 1e-10));
+  EXPECT_FALSE(lineA.Collinear(lineB));
+  EXPECT_TRUE(lineA.Collinear(lineB, 1e-3));
+}
+
+/////////////////////////////////////////////////
+TEST(Line2Test, CollinearPoint)
+{
+  math::Line2d lineA(0, 0, 10, 0);
+  math::Vector2d pt(0, 0);
+  EXPECT_TRUE(lineA.Collinear(pt));
+  {
+    math::Line2d ptLine(pt, pt);
+    EXPECT_TRUE(lineA.Collinear(ptLine));
+  }
+
+  pt.Set(1000, 0);
+  EXPECT_TRUE(lineA.Collinear(pt, 1e-10));
+  {
+    math::Line2d ptLine(pt, pt);
+    EXPECT_TRUE(lineA.Parallel(ptLine));
+    EXPECT_FALSE(lineA.Intersect(ptLine));
+    EXPECT_FALSE(lineA.Collinear(ptLine, 1e-10));
+
+    pt.Set(10, 0);
+    ptLine.Set(pt, pt);
+    EXPECT_TRUE(lineA.Collinear(ptLine, 1e-10));
+  }
+
+  pt.Set(0, 0.00001);
+  EXPECT_FALSE(lineA.Collinear(pt));
+  EXPECT_TRUE(lineA.Collinear(pt, 1e-3));
+  {
+    math::Line2d ptLine(pt, pt);
+    EXPECT_FALSE(lineA.Collinear(ptLine));
+    EXPECT_TRUE(lineA.Parallel(ptLine));
+    EXPECT_FALSE(lineA.Intersect(ptLine));
+    EXPECT_TRUE(lineA.Intersect(ptLine, 1e-2));
+    EXPECT_TRUE(lineA.Collinear(ptLine, 1e-3));
+  }
+
+  pt.Set(0, -0.00001);
+  EXPECT_FALSE(lineA.Collinear(pt));
+  EXPECT_TRUE(lineA.Collinear(pt, 1e-3));
+  {
+    math::Line2d ptLine(pt, pt);
+    EXPECT_FALSE(lineA.Collinear(ptLine));
+    EXPECT_TRUE(lineA.Collinear(ptLine, 1e-4));
+  }
+}
+
+/////////////////////////////////////////////////
+TEST(Line2Test, Intersect)
+{
+  math::Vector2d pt;
+
+  // Parallel horizontal lines
+  math::Line2d lineA(1, 1, 2, 1);
+  math::Line2d lineB(1, 2, 2, 2);
+  EXPECT_FALSE(lineA.Intersect(lineB, pt));
+
+  // Parallel vertical lines
+  lineA.Set(1, 1, 1, 10);
+  lineB.Set(2, 1, 2, 10);
+  EXPECT_FALSE(lineA.Intersect(lineB, pt));
+
+  // Two lines that form an inverted T with a gap
+  lineA.Set(1, 1, 1, 10);
+  lineB.Set(0, 0, 2, 0);
+  EXPECT_FALSE(lineA.Intersect(lineB, pt));
+
+  // Two lines that form a T with a gap
+  lineA.Set(1, 1, 1, 10);
+  lineB.Set(0, 10.1, 2, 10.1);
+  EXPECT_FALSE(lineA.Intersect(lineB, pt));
+
+  // Two lines that form an inverted T with a gap
+  lineA.Set(0, -10, 0, 10);
+  lineB.Set(1, 0, 10, 0);
+  EXPECT_FALSE(lineA.Intersect(lineB, pt));
+
+  // Two lines that form a T with a gap
+  lineA.Set(0, -10, 0, 10);
+  lineB.Set(-1, 0, -10, 0);
+  EXPECT_FALSE(lineA.Intersect(lineB, pt));
+
+  // Two collinear lines, one starts where the other stopped
+  lineA.Set(1, 1, 1, 10);
+  lineB.Set(1, 10, 1, 11);
+  EXPECT_TRUE(lineA.Intersect(lineB, pt));
+  EXPECT_EQ(pt, math::Vector2d(1, 10));
+
+  // Two collinear lines, one overlaps the other
+  lineA.Set(0, 0, 0, 10);
+  lineB.Set(0, 9, 0, 11);
+  EXPECT_TRUE(lineA.Intersect(lineB, pt));
+  EXPECT_EQ(pt, math::Vector2d(0, 9));
+
+  // Two collinear lines, one overlaps the other
+  lineA.Set(0, 0, 0, 10);
+  lineB.Set(0, -10, 0, 1);
+  EXPECT_TRUE(lineA.Intersect(lineB, pt));
+  EXPECT_EQ(pt, math::Vector2d(0, 1));
+
+  // Two intersecting lines
+  lineA.Set(0, 0, 10, 10);
+  lineB.Set(0, 10, 10, 0);
+  EXPECT_TRUE(lineA.Intersect(lineB, pt));
+  EXPECT_EQ(pt, math::Vector2d(5, 5));
+}
+
+/////////////////////////////////////////////////
+TEST(Line2Test, Equality)
+{
+  math::Line2d lineA(1, 1, 2, 1);
+  math::Line2d lineB(1, 2, 2, 2);
+
+  EXPECT_TRUE(lineA != lineB);
+  EXPECT_TRUE(lineA == lineA);
+
+  lineB.Set(1, 1, 2, 1.1);
+  EXPECT_FALSE(lineA == lineB);
+
+  lineB.Set(1, 1, 2.1, 1);
+  EXPECT_FALSE(lineA == lineB);
+
+  lineB.Set(1, 1.1, 2, 1);
+  EXPECT_FALSE(lineA == lineB);
+
+  lineB.Set(1.1, 1, 2, 1);
+  EXPECT_FALSE(lineA == lineB);
+}
+
+/////////////////////////////////////////////////
+TEST(Line2Test, OperatorStreamOut)
+{
+  math::Line2d line(0, 1, 2, 3);
+  std::ostringstream stream;
+  stream << line;
+  EXPECT_EQ(stream.str(), "0 1 2 3");
+}
diff --git a/src/Line3_TEST.cc b/src/Line3_TEST.cc
new file mode 100644
index 0000000..05a0605
--- /dev/null
+++ b/src/Line3_TEST.cc
@@ -0,0 +1,293 @@
+/*
+ * Copyright (C) 2015 Open Source Robotics Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+*/
+
+#include <gtest/gtest.h>
+
+#include "ignition/math/Line3.hh"
+#include "ignition/math/Helpers.hh"
+
+using namespace ignition;
+
+/////////////////////////////////////////////////
+TEST(Line3Test, Constructor)
+{
+  math::Line3d lineA(0, 0, 10, 10);
+  EXPECT_DOUBLE_EQ(lineA[0].X(), 0.0);
+  EXPECT_DOUBLE_EQ(lineA[0].Y(), 0.0);
+  EXPECT_DOUBLE_EQ(lineA[0].Z(), 0.0);
+  EXPECT_DOUBLE_EQ(lineA[1].X(), 10.0);
+  EXPECT_DOUBLE_EQ(lineA[1].Y(), 10.0);
+  EXPECT_DOUBLE_EQ(lineA[1].Z(), 0.0);
+
+  math::Line3d lineB(math::Vector3d(1, 2, 3), math::Vector3d(4, 5, 6));
+  EXPECT_DOUBLE_EQ(lineB[0].X(), 1.0);
+  EXPECT_DOUBLE_EQ(lineB[0].Y(), 2.0);
+  EXPECT_DOUBLE_EQ(lineB[0].Z(), 3.0);
+  EXPECT_DOUBLE_EQ(lineB[1].X(), 4.0);
+  EXPECT_DOUBLE_EQ(lineB[1].Y(), 5.0);
+  EXPECT_DOUBLE_EQ(lineB[1].Z(), 6.0);
+
+  math::Line3d lineC(0, 0, 5, 10, 10, 6);
+  EXPECT_DOUBLE_EQ(lineC[0].X(), 0.0);
+  EXPECT_DOUBLE_EQ(lineC[0].Y(), 0.0);
+  EXPECT_DOUBLE_EQ(lineC[0].Z(), 5.0);
+  EXPECT_DOUBLE_EQ(lineC[1].X(), 10.0);
+  EXPECT_DOUBLE_EQ(lineC[1].Y(), 10.0);
+  EXPECT_DOUBLE_EQ(lineC[1].Z(), 6.0);
+
+  EXPECT_NO_THROW(lineB[2].X());
+  EXPECT_DOUBLE_EQ(lineB[2].X(), lineB[1].X());
+  EXPECT_NO_THROW(lineA[0].X());
+}
+
+TEST(Line3Test, Set)
+{
+  math::Line3d lineA;
+  lineA.Set(1, 1, 2, 2);
+  EXPECT_DOUBLE_EQ(lineA[0].X(), 1.0);
+  EXPECT_DOUBLE_EQ(lineA[0].Y(), 1.0);
+  EXPECT_DOUBLE_EQ(lineA[0].Z(), 0.0);
+  EXPECT_DOUBLE_EQ(lineA[1].X(), 2.0);
+  EXPECT_DOUBLE_EQ(lineA[1].Y(), 2.0);
+  EXPECT_DOUBLE_EQ(lineA[1].Z(), 0.0);
+
+  lineA.Set(10, 11, 12, 13, 14, 15);
+  EXPECT_DOUBLE_EQ(lineA[0].X(), 10.0);
+  EXPECT_DOUBLE_EQ(lineA[0].Y(), 11.0);
+  EXPECT_DOUBLE_EQ(lineA[0].Z(), 12.0);
+  EXPECT_DOUBLE_EQ(lineA[1].X(), 13.0);
+  EXPECT_DOUBLE_EQ(lineA[1].Y(), 14.0);
+  EXPECT_DOUBLE_EQ(lineA[1].Z(), 15.0);
+
+  lineA.SetA(math::Vector3<double>(0, -1, -2));
+  EXPECT_DOUBLE_EQ(lineA[0].X(), 0.0);
+  EXPECT_DOUBLE_EQ(lineA[0].Y(), -1.0);
+  EXPECT_DOUBLE_EQ(lineA[0].Z(), -2.0);
+  EXPECT_DOUBLE_EQ(lineA[1].X(), 13.0);
+  EXPECT_DOUBLE_EQ(lineA[1].Y(), 14.0);
+  EXPECT_DOUBLE_EQ(lineA[1].Z(), 15.0);
+
+  lineA.SetB(math::Vector3<double>(5, 6, 7));
+  EXPECT_DOUBLE_EQ(lineA[0].X(), 0.0);
+  EXPECT_DOUBLE_EQ(lineA[0].Y(), -1.0);
+  EXPECT_DOUBLE_EQ(lineA[0].Z(), -2.0);
+  EXPECT_DOUBLE_EQ(lineA[1].X(), 5.0);
+  EXPECT_DOUBLE_EQ(lineA[1].Y(), 6.0);
+  EXPECT_DOUBLE_EQ(lineA[1].Z(), 7.0);
+}
+
+/////////////////////////////////////////////////
+TEST(Line3Test, Length)
+{
+  math::Line3d lineA(0, 0, 0, 10, 10, 10);
+  EXPECT_NEAR(lineA.Length(), sqrt(300), 1e-10);
+}
+
+/////////////////////////////////////////////////
+TEST(Line3Test, Equality)
+{
+  math::Line3d lineA(1, 1, 1, 2, 1, 2);
+  math::Line3d lineB(1, 2, 3, 2, 2, 4);
+
+  EXPECT_TRUE(lineA != lineB);
+  EXPECT_TRUE(lineA == lineA);
+
+  lineB.Set(1, 1, 1, 2, 1.1, 2);
+  EXPECT_FALSE(lineA == lineB);
+
+  lineB.Set(1, 1, 1, 2.1, 1, 2);
+  EXPECT_FALSE(lineA == lineB);
+
+  lineB.Set(1, 1, 1.1, 2, 1, 2);
+  EXPECT_FALSE(lineA == lineB);
+
+  lineB.Set(1.1, 1, 1, 2, 1, 2);
+  EXPECT_FALSE(lineA == lineB);
+}
+
+/////////////////////////////////////////////////
+TEST(Line3Test, OperatorStreamOut)
+{
+  math::Line3d line(0, 1, 4, 2, 3, 7);
+  std::ostringstream stream;
+  stream << line;
+  EXPECT_EQ(stream.str(), "0 1 4 2 3 7");
+}
+
+/////////////////////////////////////////////////
+TEST(Line3Test, CopyConstructor)
+{
+  math::Line3d lineA(0, 1, 4, 2, 3, 7);
+  math::Line3d lineB(lineA);
+
+  EXPECT_EQ(lineA, lineB);
+}
+
+/////////////////////////////////////////////////
+TEST(Line3Test, OperatorAssign)
+{
+  math::Line3d lineA(0, 1, 4, 2, 3, 7);
+  math::Line3d lineB = lineA;
+
+  EXPECT_EQ(lineA, lineB);
+}
+
+/////////////////////////////////////////////////
+TEST(Line3Test, Direction)
+{
+  math::Line3d lineA(1, 1, 1, 0, 0, 0);
+  math::Line3d lineB(2, 2, 2, 0, 0, 0);
+  math::Line3d lineC(0, 0, 0, 1, 1, 1);
+  EXPECT_TRUE(lineA.Direction() == (lineA[1] - lineA[0]).Normalize());
+  EXPECT_TRUE(lineA.Direction() == lineB.Direction());
+  EXPECT_FALSE(lineA.Direction() == lineC.Direction());
+
+  lineA.Set(1, 1, 2, 1, 1, 10);
+  EXPECT_TRUE(lineA.Direction() == math::Vector3d::UnitZ);
+
+  lineA.Set(1, 5, 1, 1, 1, 1);
+  EXPECT_TRUE(lineA.Direction() == -math::Vector3d::UnitY);
+
+  lineA.Set(1, 1, 1, 7, 1, 1);
+  EXPECT_TRUE(lineA.Direction() == math::Vector3d::UnitX);
+}
+
+/////////////////////////////////////////////////
+TEST(Line3Test, Within)
+{
+  math::Line3d line(0, 0, 0, 1, 1, 1);
+  EXPECT_TRUE(line.Within(math::Vector3d(0, 0, 0)));
+  EXPECT_TRUE(line.Within(math::Vector3d(1, 1, 1)));
+  EXPECT_TRUE(line.Within(math::Vector3d(0.5, 0.5, 0.5)));
+
+  EXPECT_FALSE(line.Within(math::Vector3d(-0.5, 0.5, 0.5)));
+  EXPECT_FALSE(line.Within(math::Vector3d(0.5, -0.5, 0.5)));
+  EXPECT_FALSE(line.Within(math::Vector3d(0.5, 0.5, -0.5)));
+}
+
+/////////////////////////////////////////////////
+TEST(Line3Test, Distance)
+{
+  math::Line3d line(0, 0, 0, 0, 1, 0);
+  math::Line3d result;
+
+  EXPECT_TRUE(line.Distance(math::Line3d(1, 0.5, 0, -1, 0.5, 0), result));
+  EXPECT_DOUBLE_EQ(result.Length(), 0);
+  EXPECT_EQ(result, math::Line3d(0, 0.5, 0, 0, 0.5, 0));
+
+  EXPECT_TRUE(line.Distance(math::Line3d(1, 0, 0, -1, 0, 0), result));
+  EXPECT_DOUBLE_EQ(result.Length(), 0);
+  EXPECT_EQ(result, math::Line3d(0, 0, 0, 0, 0, 0));
+
+  EXPECT_TRUE(line.Distance(math::Line3d(1, 1.1, 0, -1, 1.1, 0), result));
+  EXPECT_NEAR(result.Length(), 0.1, 1e-4);
+  EXPECT_EQ(result, math::Line3d(0, 1, 0, 0, 1.1, 0));
+
+  EXPECT_TRUE(line.Distance(math::Line3d(1, 0.5, 0.4, -1, 0.5, 0.4), result));
+  EXPECT_NEAR(result.Length(), 0.4, 1e-4);
+  EXPECT_EQ(result, math::Line3d(0, 0.5, 0, 0, 0.5, 0.4));
+
+  EXPECT_TRUE(line.Distance(math::Line3d(0, 0.5, 1, 1, 0.5, 0), result));
+  EXPECT_NEAR(result.Length(), sin(IGN_PI / 4), 1e-4);
+  EXPECT_EQ(result, math::Line3d(0, 0.5, 0, 0.5, 0.5, 0.5));
+
+  // Expect true when lines are parallel
+  EXPECT_TRUE(line.Distance(math::Line3d(2, 0, 0, 2, 1, 0), result));
+  EXPECT_EQ(result[0], line[0]);
+  EXPECT_EQ(result[1], math::Vector3d(2, 0, 0));
+
+  EXPECT_TRUE(line.Distance(math::Line3d(2, 1, 0, 2, 0, 0), result));
+  EXPECT_EQ(result[0], line[0]);
+  EXPECT_EQ(result[1], math::Vector3d(2, 0, 0));
+
+  EXPECT_TRUE(line.Distance(math::Line3d(1, 1, 0, 1, 2, 0), result));
+  EXPECT_EQ(result[0], line[1]);
+  EXPECT_EQ(result[1], math::Vector3d(1, 1, 0));
+
+  EXPECT_TRUE(line.Distance(math::Line3d(1, 2, 0, 1, 1, 0), result));
+  EXPECT_EQ(result[0], line[1]);
+  EXPECT_EQ(result[1], math::Vector3d(1, 1, 0));
+
+  // Expect false when the passed in line is a point
+  EXPECT_FALSE(line.Distance(math::Line3d(2, 0, 0, 2, 0, 0), result));
+
+  // Expect false when the first line is a point.
+  line.Set(0, 0, 0, 0, 0, 0);
+  EXPECT_FALSE(line.Distance(math::Line3d(2, 0, 0, 2, 1, 0), result));
+}
+
+/////////////////////////////////////////////////
+TEST(Line3Test, Intersect)
+{
+  math::Line3d line(0, 0, 0, 0, 1, 0);
+  math::Vector3d pt;
+
+  EXPECT_TRUE(line.Intersect(math::Line3d(1, 0.5, 0, -1, 0.5, 0)));
+  EXPECT_TRUE(line.Intersect(math::Line3d(1, 0.5, 0, -1, 0.5, 0), pt));
+  EXPECT_EQ(pt, math::Vector3d(0, 0.5, 0));
+
+  EXPECT_TRUE(line.Intersect(math::Line3d(1, 0, 0, -1, 0, 0)));
+  EXPECT_TRUE(line.Intersect(math::Line3d(1, 0, 0, -1, 0, 0), pt));
+  EXPECT_EQ(pt, math::Vector3d(0, 0, 0));
+
+  EXPECT_TRUE(line.Intersect(math::Line3d(1, 1, 0, -1, 1, 0)));
+  EXPECT_TRUE(line.Intersect(math::Line3d(1, 1, 0, -1, 1, 0), pt));
+  EXPECT_EQ(pt, math::Vector3d(0, 1, 0));
+
+  EXPECT_TRUE(line.Intersect(math::Line3d(0, 0.5, -1, 0, 0.5, 1)));
+  EXPECT_TRUE(line.Intersect(math::Line3d(0, 0.5, -1, 0, 0.5, 1), pt));
+  EXPECT_EQ(pt, math::Vector3d(0, 0.5, 0));
+
+  EXPECT_TRUE(line.Intersect(math::Line3d(-1, 0.5, -1, 1, 0.5, 1)));
+  EXPECT_TRUE(line.Intersect(math::Line3d(-1, 0.5, -1, 1, 0.5, 1), pt));
+  EXPECT_EQ(pt, math::Vector3d(0, 0.5, 0));
+
+  EXPECT_FALSE(line.Intersect(math::Line3d(1, 1.1, 0, -1, 1.1, 0)));
+  EXPECT_FALSE(line.Intersect(math::Line3d(1, -0.1, 0, -1, -0.1, 0)));
+
+  EXPECT_FALSE(line.Intersect(math::Line3d(0.1, 0.1, 0, 0.6, 0.6, 0)));
+  EXPECT_FALSE(line.Intersect(math::Line3d(-0.1, 0, 0, -0.1, 1, 0)));
+
+  EXPECT_TRUE(line.Intersect(math::Line3d(0, -1, 0, 0, 0.1, 0)));
+  EXPECT_TRUE(line.Intersect(math::Line3d(0, 1, 0, 0, 1.1, 0)));
+}
+
+/////////////////////////////////////////////////
+TEST(Line3Test, Parallel)
+{
+  math::Line3d line(0, 0, 0, 0, 1, 0);
+  EXPECT_TRUE(line.Parallel(math::Line3d(1, 0, 0, 1, 1, 0)));
+  EXPECT_TRUE(line.Parallel(math::Line3d(1, 1, 0, 1, 0, 0)));
+  EXPECT_TRUE(line.Parallel(math::Line3d(0, 0, 0, 0, 10, 0)));
+  EXPECT_TRUE(line.Parallel(math::Line3d(-100, 100, 20, -100, 200, 20)));
+
+  EXPECT_FALSE(line.Parallel(math::Line3d(1, 0, 0, 1, 1, 1)));
+  EXPECT_FALSE(line.Parallel(math::Line3d(1, 0, 0, 2, 0, 0)));
+  EXPECT_FALSE(line.Parallel(math::Line3d(1, 0, 1, 2, 0, 1)));
+}
+
+/////////////////////////////////////////////////
+TEST(Line3Test, Coplanar)
+{
+  math::Line3d line(0, 0, 0, 0, 1, 0);
+  EXPECT_TRUE(line.Coplanar(math::Line3d(1, 0, 0, 1, 1, 0)));
+  EXPECT_TRUE(line.Coplanar(math::Line3d(0, 0, 0, 0, 10, 0)));
+  EXPECT_TRUE(line.Coplanar(math::Line3d(-100, 100, 20, -100, 200, 20)));
+
+  EXPECT_FALSE(line.Coplanar(math::Line3d(1, 0, 0, 1, 1, 1)));
+  EXPECT_FALSE(line.Coplanar(math::Line3d(1, 0, 1, 2, 0, 0)));
+}
diff --git a/src/MassMatrix3_TEST.cc b/src/MassMatrix3_TEST.cc
new file mode 100644
index 0000000..b56094e
--- /dev/null
+++ b/src/MassMatrix3_TEST.cc
@@ -0,0 +1,858 @@
+/*
+ * Copyright (C) 2015 Open Source Robotics Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+*/
+
+#include <gtest/gtest.h>
+#include <cmath>
+
+#include "ignition/math/Helpers.hh"
+#include "ignition/math/MassMatrix3.hh"
+
+using namespace ignition;
+
+/////////////////////////////////////////////////
+TEST(MassMatrix3dTest, Constructors)
+{
+  // Simple constructor, test default values
+  {
+    math::MassMatrix3d m;
+    EXPECT_DOUBLE_EQ(m.Mass(), 0.0);
+    EXPECT_DOUBLE_EQ(m.IXX(), 0.0);
+    EXPECT_DOUBLE_EQ(m.IYY(), 0.0);
+    EXPECT_DOUBLE_EQ(m.IZZ(), 0.0);
+    EXPECT_DOUBLE_EQ(m.IXY(), 0.0);
+    EXPECT_DOUBLE_EQ(m.IXZ(), 0.0);
+    EXPECT_DOUBLE_EQ(m.IYZ(), 0.0);
+    EXPECT_EQ(m.DiagonalMoments(), math::Vector3d::Zero);
+    EXPECT_EQ(m.OffDiagonalMoments(), math::Vector3d::Zero);
+    EXPECT_EQ(m.MOI(), math::Matrix3d::Zero);
+    EXPECT_FALSE(m.IsPositive());
+    EXPECT_FALSE(m.IsValid());
+  }
+
+  // Constructor with default arguments
+  // Should match simple constructor and with copy constructor
+  {
+    math::MassMatrix3d m(0, math::Vector3d::Zero, math::Vector3d::Zero);
+    EXPECT_EQ(m, math::MassMatrix3d());
+    EXPECT_EQ(m, math::MassMatrix3d(m));
+    EXPECT_FALSE(m.IsPositive());
+    EXPECT_FALSE(m.IsValid());
+  }
+
+  // Constructor with non-default arguments
+  {
+    const double mass = 5.0;
+    const math::Vector3d Ixxyyzz(2.0, 3.0, 4.0);
+    const math::Vector3d Ixyxzyz(0.2, 0.3, 0.4);
+    const math::Matrix3d MOI(2.0, 0.2, 0.3,
+                             0.2, 3.0, 0.4,
+                             0.3, 0.4, 4.0);
+    math::MassMatrix3d m(mass, Ixxyyzz, Ixyxzyz);
+
+    // Should not match simple constructor
+    EXPECT_NE(m, math::MassMatrix3d());
+
+    // Should match with copy constructor
+    EXPECT_EQ(m, math::MassMatrix3d(m));
+
+    // Test accessors
+    EXPECT_DOUBLE_EQ(m.Mass(), mass);
+    EXPECT_DOUBLE_EQ(m.IXX(), Ixxyyzz[0]);
+    EXPECT_DOUBLE_EQ(m.IYY(), Ixxyyzz[1]);
+    EXPECT_DOUBLE_EQ(m.IZZ(), Ixxyyzz[2]);
+    EXPECT_DOUBLE_EQ(m.IXY(), Ixyxzyz[0]);
+    EXPECT_DOUBLE_EQ(m.IXZ(), Ixyxzyz[1]);
+    EXPECT_DOUBLE_EQ(m.IYZ(), Ixyxzyz[2]);
+    EXPECT_EQ(m.DiagonalMoments(), Ixxyyzz);
+    EXPECT_EQ(m.OffDiagonalMoments(), Ixyxzyz);
+    EXPECT_EQ(m.MOI(), MOI);
+    EXPECT_TRUE(m.IsPositive());
+    EXPECT_TRUE(m.IsValid());
+
+    // Test assignment operator
+    math::MassMatrix3d m2;
+    EXPECT_NE(m, m2);
+    m2 = m;
+    EXPECT_EQ(m, m2);
+  }
+}
+
+/////////////////////////////////////////////////
+TEST(MassMatrix3dTest, Setters)
+{
+  const double mass = 5.0;
+  const math::Vector3d Ixxyyzz(2.0, 3.0, 4.0);
+  const math::Vector3d Ixyxzyz(0.2, 0.3, 0.4);
+  const math::Matrix3d MOI(2.0, 0.2, 0.3,
+                           0.2, 3.0, 0.4,
+                           0.3, 0.4, 4.0);
+
+  // Scalar setters with simple constructor
+  // MassMatrix3 won't be valid until enough properties are set
+  {
+    math::MassMatrix3d m;
+    EXPECT_FALSE(m.IsPositive());
+    EXPECT_FALSE(m.IsValid());
+
+    // Initially invalid
+    EXPECT_FALSE(m.Mass(mass));
+    EXPECT_FALSE(m.IXX(Ixxyyzz[0]));
+    EXPECT_FALSE(m.IYY(Ixxyyzz[1]));
+
+    // Valid once enough properties are set
+    EXPECT_TRUE(m.IZZ(Ixxyyzz[2]));
+    EXPECT_TRUE(m.IXY(Ixyxzyz[0]));
+    EXPECT_TRUE(m.IXZ(Ixyxzyz[1]));
+    EXPECT_TRUE(m.IYZ(Ixyxzyz[2]));
+
+    // Verify values
+    EXPECT_DOUBLE_EQ(m.Mass(), mass);
+    EXPECT_DOUBLE_EQ(m.IXX(), Ixxyyzz[0]);
+    EXPECT_DOUBLE_EQ(m.IYY(), Ixxyyzz[1]);
+    EXPECT_DOUBLE_EQ(m.IZZ(), Ixxyyzz[2]);
+    EXPECT_DOUBLE_EQ(m.IXY(), Ixyxzyz[0]);
+    EXPECT_DOUBLE_EQ(m.IXZ(), Ixyxzyz[1]);
+    EXPECT_DOUBLE_EQ(m.IYZ(), Ixyxzyz[2]);
+    EXPECT_EQ(m.DiagonalMoments(), Ixxyyzz);
+    EXPECT_EQ(m.OffDiagonalMoments(), Ixyxzyz);
+    EXPECT_EQ(m.MOI(), MOI);
+    EXPECT_TRUE(m.IsPositive());
+    EXPECT_TRUE(m.IsValid());
+
+    // Invalid again if an invalid inertia is set
+    EXPECT_FALSE(m.Mass(-1));
+  }
+
+  // Test vector setters for moment of inertia
+  {
+    math::MassMatrix3d m;
+    EXPECT_FALSE(m.IsPositive());
+    EXPECT_FALSE(m.IsValid());
+
+    // Initially invalid
+    EXPECT_FALSE(m.Mass(mass));
+
+    // Valid once enough properties are set
+    EXPECT_TRUE(m.DiagonalMoments(Ixxyyzz));
+    EXPECT_TRUE(m.OffDiagonalMoments(Ixyxzyz));
+
+    // Verify values
+    EXPECT_DOUBLE_EQ(m.Mass(), mass);
+    EXPECT_DOUBLE_EQ(m.IXX(), Ixxyyzz[0]);
+    EXPECT_DOUBLE_EQ(m.IYY(), Ixxyyzz[1]);
+    EXPECT_DOUBLE_EQ(m.IZZ(), Ixxyyzz[2]);
+    EXPECT_DOUBLE_EQ(m.IXY(), Ixyxzyz[0]);
+    EXPECT_DOUBLE_EQ(m.IXZ(), Ixyxzyz[1]);
+    EXPECT_DOUBLE_EQ(m.IYZ(), Ixyxzyz[2]);
+    EXPECT_EQ(m.DiagonalMoments(), Ixxyyzz);
+    EXPECT_EQ(m.OffDiagonalMoments(), Ixyxzyz);
+    EXPECT_EQ(m.MOI(), MOI);
+    EXPECT_TRUE(m.IsPositive());
+    EXPECT_TRUE(m.IsValid());
+
+    // Invalid if an invalid inertia is set
+    EXPECT_FALSE(m.IXX(-1));
+  }
+
+  // Test Matrix3 setter for moment of inertia
+  {
+    math::MassMatrix3d m;
+    EXPECT_FALSE(m.IsPositive());
+    EXPECT_FALSE(m.IsValid());
+
+    // Initially invalid
+    EXPECT_FALSE(m.Mass(mass));
+
+    // Valid once enough properties are set
+    EXPECT_TRUE(m.MOI(MOI));
+
+    // Verify values
+    EXPECT_DOUBLE_EQ(m.Mass(), mass);
+    EXPECT_DOUBLE_EQ(m.IXX(), Ixxyyzz[0]);
+    EXPECT_DOUBLE_EQ(m.IYY(), Ixxyyzz[1]);
+    EXPECT_DOUBLE_EQ(m.IZZ(), Ixxyyzz[2]);
+    EXPECT_DOUBLE_EQ(m.IXY(), Ixyxzyz[0]);
+    EXPECT_DOUBLE_EQ(m.IXZ(), Ixyxzyz[1]);
+    EXPECT_DOUBLE_EQ(m.IYZ(), Ixyxzyz[2]);
+    EXPECT_EQ(m.DiagonalMoments(), Ixxyyzz);
+    EXPECT_EQ(m.OffDiagonalMoments(), Ixyxzyz);
+    EXPECT_EQ(m.MOI(), MOI);
+    EXPECT_TRUE(m.IsPositive());
+    EXPECT_TRUE(m.IsValid());
+
+    // Invalid if an excessive off-diagonal inertia is set
+    EXPECT_FALSE(m.IXY(1e3));
+  }
+
+  // // Test atomic InertiaMatrix setter
+  {
+    math::MassMatrix3d m;
+    EXPECT_FALSE(m.IsPositive());
+    EXPECT_FALSE(m.IsValid());
+
+    // Initially invalid
+    EXPECT_FALSE(m.Mass(mass));
+
+    // Valid once enough properties are set
+    EXPECT_TRUE(m.InertiaMatrix(2, 3, 4, 0.2, 0.3, 0.4));
+
+    // Verify values
+    EXPECT_DOUBLE_EQ(m.Mass(), mass);
+    EXPECT_DOUBLE_EQ(m.IXX(), Ixxyyzz[0]);
+    EXPECT_DOUBLE_EQ(m.IYY(), Ixxyyzz[1]);
+    EXPECT_DOUBLE_EQ(m.IZZ(), Ixxyyzz[2]);
+    EXPECT_DOUBLE_EQ(m.IXY(), Ixyxzyz[0]);
+    EXPECT_DOUBLE_EQ(m.IXZ(), Ixyxzyz[1]);
+    EXPECT_DOUBLE_EQ(m.IYZ(), Ixyxzyz[2]);
+    EXPECT_EQ(m.DiagonalMoments(), Ixxyyzz);
+    EXPECT_EQ(m.OffDiagonalMoments(), Ixyxzyz);
+    EXPECT_EQ(m.MOI(), MOI);
+    EXPECT_TRUE(m.IsPositive());
+    EXPECT_TRUE(m.IsValid());
+  }
+}
+
+/////////////////////////////////////////////////
+TEST(MassMatrix3dTest, CoverageExtra)
+{
+  // getting full destructor coverage
+  math::MassMatrix3d *p = new math::MassMatrix3d;
+  EXPECT_TRUE(p != NULL);
+  delete p;
+}
+
+/////////////////////////////////////////////////
+TEST(MassMatrix3dTest, PrincipalMoments)
+{
+  // Diagonal inertia moments (1, 1, 1)
+  {
+    math::MassMatrix3d m(1.0, math::Vector3d::One, math::Vector3d::Zero);
+    EXPECT_EQ(m.PrincipalMoments(), math::Vector3d::One);
+
+    // Minor perturbations of product moments
+    // shouldn't affect PrincipalMoments, given the tolerance
+    // of the Vector3 equality operator
+    EXPECT_TRUE(m.IXY(1e-10));
+    EXPECT_TRUE(m.IXZ(2e-10));
+    EXPECT_TRUE(m.IYZ(3e-10));
+    EXPECT_EQ(m.PrincipalMoments(), math::Vector3d::One);
+    EXPECT_TRUE(m.IsPositive());
+    EXPECT_TRUE(m.IsValid());
+  }
+
+  // Non-equal eigen-moments
+  {
+    const math::Vector3d Ixxyyzz(2.0, 3.0, 4.0);
+    math::MassMatrix3d m(1.0, Ixxyyzz, math::Vector3d::Zero);
+    EXPECT_TRUE(m.DiagonalMoments(Ixxyyzz));
+    EXPECT_EQ(m.PrincipalMoments(), Ixxyyzz);
+
+    // Minor perturbation of product moments
+    EXPECT_TRUE(m.IXY(1e-10));
+    EXPECT_TRUE(m.IXZ(2e-10));
+    EXPECT_TRUE(m.IYZ(3e-10));
+    EXPECT_EQ(m.PrincipalMoments(), Ixxyyzz);
+    EXPECT_TRUE(m.IsPositive());
+    EXPECT_TRUE(m.IsValid());
+  }
+
+  // Non-trivial off-diagonal product moments
+  // Symmetric positive definite matrix from
+  // Strang's Intro to Linear Algebra textbook
+  // This isn't actually a valid inertia matrix though,
+  // since it doesn't satisfy the triangle inequality
+  // 2-sqrt(2) + 2 ~= 2.59
+  // 2+sqrt(2) ~= 3.41
+  {
+    const math::Vector3d Ixxyyzz(2.0, 2.0, 2.0);
+    const math::Vector3d Ixyxzyz(-1.0, 0, -1.0);
+    math::MassMatrix3d m(1.0, Ixxyyzz, Ixyxzyz);
+    const math::Vector3d Ieigen(2-IGN_SQRT2, 2, 2+IGN_SQRT2);
+    EXPECT_EQ(m.PrincipalMoments(), Ieigen);
+    EXPECT_TRUE(m.IsPositive());
+    EXPECT_FALSE(m.IsValid());
+  }
+
+  // Non-trivial off-diagonal product moments
+  // variant of previous example that is valid inertia matrix
+  {
+    const math::Vector3d Ixxyyzz(4.0, 4.0, 4.0);
+    const math::Vector3d Ixyxzyz(-1.0, 0, -1.0);
+    math::MassMatrix3d m(1.0, Ixxyyzz, Ixyxzyz);
+    const math::Vector3d Ieigen(4-IGN_SQRT2, 4, 4+IGN_SQRT2);
+    EXPECT_EQ(m.PrincipalMoments(), Ieigen);
+    EXPECT_TRUE(m.IsPositive());
+    EXPECT_TRUE(m.IsValid());
+  }
+
+  // Degenerate matrix with eigenvalue of 0
+  // not positive definite
+  {
+    const math::Vector3d Ixxyyzz(1.0, 1.0, 1.0);
+    const math::Vector3d Ixyxzyz(1.0, 0, 0);
+    math::MassMatrix3d m(1.0, Ixxyyzz, Ixyxzyz);
+    const math::Vector3d Ieigen(0, 1, 2);
+    EXPECT_EQ(m.PrincipalMoments(), Ieigen);
+    EXPECT_FALSE(m.IsPositive());
+    EXPECT_FALSE(m.IsValid());
+  }
+
+  // Matrix with large condition number
+  // barely positive definite
+  // invalid inertia matrix since it doesn't satisfy triangle inequality
+  // 5e-6 + 1.0 < 2+5e-6
+  {
+    const math::Vector3d Ixxyyzz(1.0, 1.00001, 1.0);
+    const math::Vector3d Ixyxzyz(1.0, 0, 0);
+    math::MassMatrix3d m(1.0, Ixxyyzz, Ixyxzyz);
+    const math::Vector3d Ieigen(5e-6, 1.0, 2 + 5e-6);
+    EXPECT_EQ(m.PrincipalMoments(), Ieigen);
+    EXPECT_TRUE(m.IsPositive());
+    EXPECT_FALSE(m.IsValid());
+  }
+
+  // Another matrix with large condition number
+  // invalid inertia matrix since it doesn't satisfy triangle inequality
+  // 0.98 + 1e8-1e3 < 1e8+1e3
+  // 0.98 < 2e3
+  {
+    const math::Vector3d Ixxyyzz(1e8, 1e8, 1);
+    const math::Vector3d Ixyxzyz(1e3, 1e3, 1e3);
+    math::MassMatrix3d m(1.0, Ixxyyzz, Ixyxzyz);
+    const math::Vector3d Ieigen(0.98, 1e8-1e3, 1e8+1e3);
+    // the accuracy is approximately 2e-2
+    EXPECT_TRUE(m.PrincipalMoments().Equal(Ieigen, 2.5e-2));
+    EXPECT_FALSE(m.PrincipalMoments().Equal(Ieigen, 1.5e-2));
+    // the default tolerance for == is 1e-6
+    // so this should resolve as not equal
+    EXPECT_NE(m.PrincipalMoments(), Ieigen);
+    EXPECT_TRUE(m.IsPositive());
+    EXPECT_FALSE(m.IsValid());
+  }
+}
+
+/////////////////////////////////////////////////
+TEST(MassMatrix3dTest, PrincipalAxesOffsetIdentity)
+{
+  // Identity inertia matrix, expect unit quaternion
+  math::MassMatrix3d m(1.0, math::Vector3d::One, math::Vector3d::Zero);
+  EXPECT_EQ(m.PrincipalAxesOffset(), math::Quaterniond());
+
+  // Scale the diagonal terms
+  EXPECT_TRUE(m.DiagonalMoments(3.5 * math::Vector3d::One));
+  EXPECT_TRUE(m.OffDiagonalMoments(math::Vector3d::Zero));
+  EXPECT_TRUE(m.IsValid());
+  EXPECT_EQ(m.PrincipalAxesOffset(), math::Quaterniond::Identity);
+}
+
+/////////////////////////////////////////////////
+/// \brief Helper function for verifying principal moments
+/// and axes offset by reconstructing the moment of inertia matrix
+/// from the eigenvectors and diagonalized matrix.
+/// \param[in] _m mass matrix to verify
+/// \param[in] _tolerance relative tolerance to use
+void VerifyPrincipalMomentsAndAxes(const math::MassMatrix3d &_m,
+                                   const double _tolerance = 1e-6)
+{
+  auto q = _m.PrincipalAxesOffset(_tolerance);
+  auto R = math::Matrix3d(q);
+  EXPECT_FALSE(math::equal(q.W(), 0.0, 1e-6) && math::equal(q.X(), 0.0, 1e-6) &&
+               math::equal(q.Y(), 0.0, 1e-6) && math::equal(q.Z(), 0.0, 1e-6));
+  auto moments = _m.PrincipalMoments(_tolerance);
+  math::Matrix3d L(moments[0], 0, 0,
+                   0, moments[1], 0,
+                   0, 0, moments[2]);
+  EXPECT_EQ(_m.MOI(), R * L * R.Transposed());
+}
+
+/////////////////////////////////////////////////
+/// \brief Helper function for testing diagonal inertia matrices.
+/// Expect the following:
+/// * that principal moments match the diagonal values,
+/// * that mass matrix is valid,
+/// * that principal axes have no offset (identity quaternion)
+/// * that reconstructed moment of inertia matrix matches the original
+/// \param[in] _moments Diagonal/principal moments of inertia.
+void VerifyDiagonalMomentsAndAxes(const math::Vector3d &_moments)
+{
+  math::MassMatrix3d m(1.0, math::Vector3d::Zero, math::Vector3d::Zero);
+  EXPECT_TRUE(m.DiagonalMoments(_moments));
+  EXPECT_EQ(m.PrincipalMoments(), m.DiagonalMoments());
+  EXPECT_TRUE(m.IsValid());
+  // Expect unit quaternion
+  EXPECT_EQ(m.PrincipalAxesOffset(), math::Quaterniond::Identity);
+  VerifyPrincipalMomentsAndAxes(m);
+
+  // Try with negative tolerance, expect sorted principal moments
+  math::Vector3d sortedMoments;
+  {
+    double m0 = _moments[0];
+    double m1 = _moments[1];
+    double m2 = _moments[2];
+    math::sort3(m0, m1, m2);
+    sortedMoments.Set(m0, m1, m2);
+  }
+  const double tolerance = -1e-6;
+  EXPECT_EQ(m.PrincipalMoments(tolerance), sortedMoments);
+  VerifyPrincipalMomentsAndAxes(m, tolerance);
+}
+
+/////////////////////////////////////////////////
+TEST(MassMatrix3dTest, PrincipalAxesOffsetDiagonal)
+{
+  // all repeated moments [3, 3, 3]
+  VerifyDiagonalMomentsAndAxes(math::Vector3d(3.0, 3.0, 3.0));
+  // repeated moments [2, 3, 3]
+  VerifyDiagonalMomentsAndAxes(math::Vector3d(2.0, 3.0, 3.0));
+  VerifyDiagonalMomentsAndAxes(math::Vector3d(3.0, 2.0, 3.0));
+  VerifyDiagonalMomentsAndAxes(math::Vector3d(3.0, 3.0, 2.0));
+  // repeated moments [2, 2, 3]
+  VerifyDiagonalMomentsAndAxes(math::Vector3d(3.0, 2.0, 2.0));
+  VerifyDiagonalMomentsAndAxes(math::Vector3d(2.0, 3.0, 2.0));
+  VerifyDiagonalMomentsAndAxes(math::Vector3d(2.0, 2.0, 3.0));
+  // non-repeated moments
+  VerifyDiagonalMomentsAndAxes(math::Vector3d(2.0, 3.0, 4.0));
+  VerifyDiagonalMomentsAndAxes(math::Vector3d(4.0, 2.0, 3.0));
+  VerifyDiagonalMomentsAndAxes(math::Vector3d(3.0, 4.0, 2.0));
+  VerifyDiagonalMomentsAndAxes(math::Vector3d(2.0, 4.0, 3.0));
+  VerifyDiagonalMomentsAndAxes(math::Vector3d(3.0, 2.0, 4.0));
+  VerifyDiagonalMomentsAndAxes(math::Vector3d(4.0, 3.0, 2.0));
+}
+
+/////////////////////////////////////////////////
+/// \brief Helper function for testing non-diagonal inertia matrices.
+/// Expect the following:
+/// * that principal moments match the supplied values,
+/// * that mass matrix is valid,
+/// * that principal axes have an offset (non-identity quaternion)
+/// * that reconstructed moment of inertia matrix matches the original
+/// \param[in] _principalMoments Expected principal moments of inertia
+/// \param[in] _ixxyyzz Diagonal moments of inertia.
+/// \param[in] _ixyxzyz Off-diagonal moments of inertia.
+/// \param[in] _tolerance Absolute tolerance for eigenvalue expectation.
+void VerifyNondiagonalMomentsAndAxes(const math::Vector3d &_principalMoments,
+                                     const math::Vector3d &_ixxyyzz,
+                                     const math::Vector3d &_ixyxzyz,
+                                     const double _tolerance = 1e-6)
+{
+  math::MassMatrix3d m(1.0, _ixxyyzz, _ixyxzyz);
+  // EXPECT_EQ with default tolerance of 1e-6
+  // this outputs more useful error messages
+  EXPECT_EQ(m.PrincipalMoments(_tolerance), _principalMoments);
+  // also check equality with custom tolerance for small moments
+  EXPECT_TRUE(
+    m.PrincipalMoments(_tolerance).Equal(_principalMoments, _tolerance));
+  EXPECT_TRUE(m.IsValid());
+  // Expect non-unit quaternion
+  EXPECT_NE(m.PrincipalAxesOffset(_tolerance), math::Quaterniond());
+  VerifyPrincipalMomentsAndAxes(m, _tolerance);
+
+  // Try also with negated tolerance
+  EXPECT_TRUE(
+    m.PrincipalMoments(-_tolerance).Equal(_principalMoments, _tolerance));
+  VerifyPrincipalMomentsAndAxes(m, -_tolerance);
+}
+
+/////////////////////////////////////////////////
+TEST(MassMatrix3dTest, PrincipalAxesOffsetRepeat)
+{
+  // Principal moments: [3, 3, 5]
+  // Non-zero Ixy
+  VerifyNondiagonalMomentsAndAxes(math::Vector3d(3, 3, 5),
+    math::Vector3d(4, 4, 3), math::Vector3d(-1, 0, 0));
+  // Non-zero Ixz
+  VerifyNondiagonalMomentsAndAxes(math::Vector3d(3, 3, 5),
+    math::Vector3d(4, 3, 4), math::Vector3d(0, -1, 0));
+  // Non-zero Iyz
+  VerifyNondiagonalMomentsAndAxes(math::Vector3d(3, 3, 5),
+    math::Vector3d(3, 4, 4), math::Vector3d(0, 0, -1));
+
+  // Principal moments: [3, 5, 5]
+  // Non-zero Ixy
+  VerifyNondiagonalMomentsAndAxes(math::Vector3d(3, 5, 5),
+    math::Vector3d(4, 4, 5), math::Vector3d(-1, 0, 0));
+  // Non-zero Ixz
+  VerifyNondiagonalMomentsAndAxes(math::Vector3d(3, 5, 5),
+    math::Vector3d(4, 5, 4), math::Vector3d(0, -1, 0));
+  // Non-zero Iyz
+  VerifyNondiagonalMomentsAndAxes(math::Vector3d(3, 5, 5),
+    math::Vector3d(5, 4, 4), math::Vector3d(0, 0, -1));
+
+  // Principal moments: [4, 5, 5]
+  // Rotated by [45, 45, 0] degrees
+  VerifyNondiagonalMomentsAndAxes(math::Vector3d(4, 5, 5),
+    math::Vector3d(4.5, 4.75, 4.75),
+    0.25*math::Vector3d(-IGN_SQRT2, IGN_SQRT2, 1));
+  // Rotated by [-45, 45, 0] degrees
+  VerifyNondiagonalMomentsAndAxes(math::Vector3d(4, 5, 5),
+    math::Vector3d(4.5, 4.75, 4.75),
+    0.25*math::Vector3d(IGN_SQRT2, IGN_SQRT2, -1));
+  // Rotated by [45, -45, 0] degrees
+  VerifyNondiagonalMomentsAndAxes(math::Vector3d(4, 5, 5),
+    math::Vector3d(4.5, 4.75, 4.75),
+    0.25*math::Vector3d(IGN_SQRT2, -IGN_SQRT2, 1));
+  // Rotated by [-45, -45, 0] degrees
+  VerifyNondiagonalMomentsAndAxes(math::Vector3d(4, 5, 5),
+    math::Vector3d(4.5, 4.75, 4.75),
+    0.25*math::Vector3d(-IGN_SQRT2, -IGN_SQRT2, -1));
+
+  // Principal moments: [4, 4, 5]
+  // Rotated by [45, 45, 45] degrees
+  VerifyNondiagonalMomentsAndAxes(math::Vector3d(4, 4, 5),
+    math::Vector3d(4.5, 4.25, 4.25),
+    0.25*math::Vector3d(-IGN_SQRT2, IGN_SQRT2, -1));
+  // different rotation
+  VerifyNondiagonalMomentsAndAxes(math::Vector3d(4, 4, 5),
+    math::Vector3d(4.5, 4.25, 4.25),
+    0.25*math::Vector3d(IGN_SQRT2, IGN_SQRT2, 1));
+  // different rotation
+  VerifyNondiagonalMomentsAndAxes(math::Vector3d(4, 4, 5),
+    math::Vector3d(4.5, 4.25, 4.25),
+    0.25*math::Vector3d(-IGN_SQRT2, -IGN_SQRT2, 1));
+  // different rotation
+  VerifyNondiagonalMomentsAndAxes(math::Vector3d(4, 4, 5),
+    math::Vector3d(4.5, 4.25, 4.25),
+    0.25*math::Vector3d(IGN_SQRT2, -IGN_SQRT2, -1));
+
+  // Principal moments [4e-9, 4e-9, 5e-9]
+  // Rotated by [45, 45, 45] degrees
+  // use tolerance of 1e-15
+  VerifyNondiagonalMomentsAndAxes(1e-9 * math::Vector3d(4, 4, 5),
+    1e-9 * math::Vector3d(4.5, 4.25, 4.25),
+    0.25e-9*math::Vector3d(-IGN_SQRT2, IGN_SQRT2, -1), 1e-15);
+  // different rotation
+  VerifyNondiagonalMomentsAndAxes(1e-9 * math::Vector3d(4, 4, 5),
+    1e-9 * math::Vector3d(4.5, 4.25, 4.25),
+    0.25e-9*math::Vector3d(IGN_SQRT2, IGN_SQRT2, 1));
+  // different rotation
+  VerifyNondiagonalMomentsAndAxes(1e-9 * math::Vector3d(4, 4, 5),
+    1e-9 * math::Vector3d(4.5, 4.25, 4.25),
+    0.25e-9*math::Vector3d(-IGN_SQRT2, -IGN_SQRT2, 1));
+  // different rotation
+  VerifyNondiagonalMomentsAndAxes(1e-9 * math::Vector3d(4, 4, 5),
+    1e-9 * math::Vector3d(4.5, 4.25, 4.25),
+    0.25e-9*math::Vector3d(IGN_SQRT2, -IGN_SQRT2, -1), 1e-15);
+
+  // Principal moments [4, 4, 6]
+  // rotate by 30, 60, 0 degrees
+  VerifyNondiagonalMomentsAndAxes(math::Vector3d(4, 4, 6),
+    math::Vector3d(5.5, 4.125, 4.375),
+    0.25*math::Vector3d(-sqrt(3), 3.0, -sqrt(3)/2));
+
+  // different rotation
+  VerifyNondiagonalMomentsAndAxes(math::Vector3d(4, 4, 6),
+    math::Vector3d(4.125, 5.5, 4.375),
+    0.25*math::Vector3d(-sqrt(3), -sqrt(3)/2, 3.0));
+}
+
+/////////////////////////////////////////////////
+TEST(MassMatrix3dTest, PrincipalAxesOffsetNoRepeat)
+{
+  // Non-diagonal inertia matrix with f1 = 0
+  VerifyNondiagonalMomentsAndAxes(math::Vector3d(3, 4, 6),
+    math::Vector3d(3.0, 5.0, 5.0),
+    math::Vector3d(0, 0, 1));
+  // Non-diagonal inertia matrix with f1 = 0
+  VerifyNondiagonalMomentsAndAxes(math::Vector3d(3, 4, 6),
+    math::Vector3d(3.0, 5.0, 5.0),
+    math::Vector3d(0, 0, -1));
+
+  // Non-diagonal inertia matrix with f2 = 0
+  VerifyNondiagonalMomentsAndAxes(math::Vector3d(3, 4, 6),
+    math::Vector3d(5.0, 4.0, 4.0),
+    math::Vector3d(-1, 1, 0));
+  // Non-diagonal inertia matrix with f2 = 0
+  VerifyNondiagonalMomentsAndAxes(math::Vector3d(3, 4, 6),
+    math::Vector3d(5.0, 4.0, 4.0),
+    math::Vector3d(1, -1, 0));
+  // Non-diagonal inertia matrix with f2 = 0
+  VerifyNondiagonalMomentsAndAxes(math::Vector3d(3, 4, 6),
+    math::Vector3d(5.0, 4.0, 4.0),
+    math::Vector3d(-1, -1, 0));
+  // Non-diagonal inertia matrix with f2 = 0
+  VerifyNondiagonalMomentsAndAxes(math::Vector3d(3, 4, 6),
+    math::Vector3d(5.0, 4.0, 4.0),
+    math::Vector3d(1, 1, 0));
+
+  // Similar non-diagonal inertia matrix with f2 != 0
+  VerifyNondiagonalMomentsAndAxes(math::Vector3d(3, 4, 6),
+    math::Vector3d(4.0, 4.0, 5.0),
+    math::Vector3d(0, 1, 1));
+  VerifyNondiagonalMomentsAndAxes(math::Vector3d(3, 4, 6),
+    math::Vector3d(4.0, 4.0, 5.0),
+    math::Vector3d(0, -1, 1));
+  VerifyNondiagonalMomentsAndAxes(math::Vector3d(3, 4, 6),
+    math::Vector3d(4.0, 4.0, 5.0),
+    math::Vector3d(0, 1, -1));
+  VerifyNondiagonalMomentsAndAxes(math::Vector3d(3, 4, 6),
+    math::Vector3d(4.0, 4.0, 5.0),
+    math::Vector3d(0, -1, -1));
+
+  // Test case for v = 0
+  VerifyNondiagonalMomentsAndAxes(math::Vector3d(2.5, 3.5, 4.0),
+    math::Vector3d(4.0, 3.0, 3.0),
+    math::Vector3d(0.0, 0, -0.5));
+
+  // Tri-diagonal matrix with identical diagonal terms
+  VerifyNondiagonalMomentsAndAxes(math::Vector3d(4-IGN_SQRT2, 4, 4+IGN_SQRT2),
+    math::Vector3d(4.0, 4.0, 4.0),
+    math::Vector3d(-1.0, 0, -1.0));
+  // small magnitude, use tolerance of 1e-15
+  VerifyNondiagonalMomentsAndAxes(
+    1e-9 * math::Vector3d(4-IGN_SQRT2, 4, 4+IGN_SQRT2),
+    1e-9 * math::Vector3d(4.0, 4.0, 4.0),
+    1e-9 * math::Vector3d(-1.0, 0, -1.0), 1e-15);
+
+  // Tri-diagonal matrix with unique diagonal terms
+  VerifyNondiagonalMomentsAndAxes(math::Vector3d(5-sqrt(3), 5, 5+sqrt(3)),
+    math::Vector3d(4.0, 5.0, 6.0),
+    math::Vector3d(-1.0, 0, -1.0));
+  // small magnitude, use tolerance of 1e-15
+  VerifyNondiagonalMomentsAndAxes(1e-9*math::Vector3d(5-sqrt(3), 5, 5+sqrt(3)),
+    1e-9 * math::Vector3d(4.0, 5.0, 6.0),
+    1e-9 * math::Vector3d(-1.0, 0, -1.0), 1e-15);
+
+  // Nonzero values for all off-axis terms
+  VerifyNondiagonalMomentsAndAxes(math::Vector3d(10, 12, 14),
+    math::Vector3d(13, 11.75, 11.25),
+    math::Vector3d(-0.5*sqrt(3), 1.5, 0.25*sqrt(3)));
+
+  // Nonzero values for all off-axis terms
+  VerifyNondiagonalMomentsAndAxes(
+    math::Vector3d(6.6116, 8.2393186767, 13.983881323),
+    math::Vector3d(11.6116, 8.6116, 8.6116),
+    math::Vector3d(2, 2, 2));
+}
+
+/////////////////////////////////////////////////
+TEST(MassMatrix3dTest, EquivalentBox)
+{
+  // Default mass matrix with non-positive inertia
+  {
+    math::MassMatrix3d m;
+    math::Vector3d size;
+    math::Quaterniond rot;
+
+    // size is all zeros, so SetFromBox should fail
+    EXPECT_FALSE(m.SetFromBox(0.0, size, rot));
+    EXPECT_FALSE(m.SetFromBox(size, rot));
+
+    // even if mass is valid, it should not be set if size is invalid
+    EXPECT_FALSE(m.SetFromBox(1.0, size, rot));
+    EXPECT_DOUBLE_EQ(m.Mass(), 0.0);
+
+    // equivalent box should not be findable
+    EXPECT_FALSE(m.EquivalentBox(size, rot));
+  }
+
+  // Moment of inertia matrix that doesn't satisfy triangle inequality
+  {
+    const math::Vector3d ixxyyzz(2.0, 2.0, 2.0);
+    const math::Vector3d ixyxzyz(-1.0, 0, -1.0);
+    math::MassMatrix3d m(1.0, ixxyyzz, ixyxzyz);
+    math::Vector3d size;
+    math::Quaterniond rot;
+    EXPECT_FALSE(m.EquivalentBox(size, rot));
+  }
+
+  // Identity inertia matrix
+  // expect cube with side length sqrt(6)
+  {
+    const double mass = 1.0;
+    math::MassMatrix3d m(mass, math::Vector3d::One, math::Vector3d::Zero);
+    math::Vector3d size;
+    math::Vector3d sizeTrue(sqrt(6) * math::Vector3d::One);
+    math::Quaterniond rot;
+    math::Quaterniond rotTrue(math::Quaterniond::Identity);
+    EXPECT_TRUE(m.EquivalentBox(size, rot));
+    EXPECT_EQ(size, sizeTrue);
+    EXPECT_EQ(rot, rotTrue);
+
+    // create new MassMatrix3d
+    // it initially has zero mass, so SetFromBox(size, rot) will fail
+    math::MassMatrix3d m2;
+    EXPECT_FALSE(m2.SetFromBox(sizeTrue, rotTrue));
+    EXPECT_TRUE(m2.SetFromBox(mass, sizeTrue, rotTrue));
+    EXPECT_EQ(m, m2);
+  }
+
+  // unit box with mass 1.0
+  {
+    const double mass = 1.0;
+    const math::Vector3d size(1, 1, 1);
+    double ixx = mass/12 * (std::pow(size.Y(), 2) + std::pow(size.Z(), 2));
+    double iyy = mass/12 * (std::pow(size.Z(), 2) + std::pow(size.X(), 2));
+    double izz = mass/12 * (std::pow(size.X(), 2) + std::pow(size.Y(), 2));
+    math::Vector3d ixxyyzz(ixx, iyy, izz);
+    math::MassMatrix3d m(mass, ixxyyzz, math::Vector3d::Zero);
+    math::Vector3d size2;
+    math::Quaterniond rot;
+    EXPECT_TRUE(m.EquivalentBox(size2, rot));
+    EXPECT_EQ(size, size2);
+    EXPECT_EQ(rot, math::Quaterniond::Identity);
+
+    math::MassMatrix3d m2;
+    EXPECT_TRUE(m2.SetFromBox(mass, size, rot));
+    EXPECT_EQ(m, m2);
+  }
+
+  // box 1x4x9
+  {
+    const double mass = 12.0;
+    const math::Vector3d ixxyyzz(97, 82, 17);
+    math::MassMatrix3d m(mass, ixxyyzz, math::Vector3d::Zero);
+    math::Vector3d size;
+    math::Quaterniond rot;
+    EXPECT_TRUE(m.EquivalentBox(size, rot));
+    EXPECT_EQ(size, math::Vector3d(1, 4, 9));
+    EXPECT_EQ(rot, math::Quaterniond::Identity);
+
+    math::MassMatrix3d m2;
+    EXPECT_TRUE(m2.SetFromBox(mass, size, rot));
+    EXPECT_EQ(m, m2);
+  }
+
+  // box 1x4x9 rotated by 90 degrees around Z
+  {
+    const double mass = 12.0;
+    const math::Vector3d ixxyyzz(82, 17, 97);
+    math::MassMatrix3d m(mass, ixxyyzz, math::Vector3d::Zero);
+    math::Vector3d size;
+    math::Quaterniond rot;
+    EXPECT_TRUE(m.EquivalentBox(size, rot, -1e-6));
+    EXPECT_EQ(size, math::Vector3d(9, 4, 1));
+    EXPECT_EQ(rot, math::Quaterniond(0, 0, IGN_PI/2));
+
+    math::MassMatrix3d m2;
+    EXPECT_TRUE(m2.SetFromBox(mass, size, rot));
+    EXPECT_EQ(m, m2);
+  }
+
+  // box 1x4x9 rotated by 45 degrees around Z
+  {
+    const double mass = 12.0;
+    const math::Vector3d ixxyyzz(49.5, 49.5, 97);
+    const math::Vector3d ixyxzyz(-32.5, 0.0, 0.0);
+    math::MassMatrix3d m(mass, ixxyyzz, ixyxzyz);
+    math::Vector3d size;
+    math::Quaterniond rot;
+    EXPECT_TRUE(m.EquivalentBox(size, rot));
+    EXPECT_EQ(size, math::Vector3d(9, 4, 1));
+    // There are multiple correct rotations due to box symmetry
+    EXPECT_TRUE(rot == math::Quaterniond(0, 0, IGN_PI/4) ||
+                rot == math::Quaterniond(IGN_PI, 0, IGN_PI/4));
+
+    math::MassMatrix3d m2;
+    EXPECT_TRUE(m2.SetFromBox(mass, size, rot));
+    EXPECT_EQ(m, m2);
+  }
+
+  // long slender box
+  {
+    const double mass = 12.0;
+    const math::Vector3d ixxyyzz(1, 1, 2e-6);
+    math::MassMatrix3d m(mass, ixxyyzz, math::Vector3d::Zero);
+    math::Vector3d size;
+    math::Quaterniond rot;
+    EXPECT_TRUE(m.EquivalentBox(size, rot));
+    EXPECT_EQ(size, math::Vector3d(1e-3, 1e-3, 1));
+    EXPECT_EQ(rot, math::Quaterniond::Identity);
+
+    math::MassMatrix3d m2;
+    EXPECT_TRUE(m2.SetFromBox(mass, size, rot));
+    EXPECT_EQ(m, m2);
+  }
+}
+
+/////////////////////////////////////////////////
+TEST(MassMatrix3dTest, SetFromCylinderZ)
+{
+  const math::Quaterniond q0 = math::Quaterniond::Identity;
+
+  // Default mass matrix with non-positive inertia
+  {
+    math::MassMatrix3d m;
+
+    // input is all zeros, so SetFromCylinderZ should fail
+    EXPECT_FALSE(m.SetFromCylinderZ(0, 0, 0, q0));
+    EXPECT_FALSE(m.SetFromCylinderZ(0, 0, q0));
+
+    // even if some parameters are valid, none should be set if they
+    // are not all valid
+    EXPECT_FALSE(m.SetFromCylinderZ(1, 0, 0, q0));
+    EXPECT_FALSE(m.SetFromCylinderZ(1, 1, 0, q0));
+    EXPECT_FALSE(m.SetFromCylinderZ(1, 0, 1, q0));
+    EXPECT_DOUBLE_EQ(m.Mass(), 0.0);
+  }
+
+  // unit cylinder with mass 1.0
+  {
+    const double mass = 1.0;
+    const double length = 1.0;
+    const double radius = 0.5;
+    math::MassMatrix3d m;
+    EXPECT_TRUE(m.SetFromCylinderZ(mass, length, radius, q0));
+
+    double ixx = mass / 12.0 * (3*std::pow(radius, 2) + std::pow(length, 2));
+    double iyy = ixx;
+    double izz = mass / 2.0 * std::pow(radius, 2);
+    const math::Vector3d ixxyyzz(ixx, iyy, izz);
+    EXPECT_EQ(m.DiagonalMoments(), ixxyyzz);
+    EXPECT_EQ(m.OffDiagonalMoments(), math::Vector3d::Zero);
+
+    // double the length and radius
+    EXPECT_TRUE(m.SetFromCylinderZ(mass, 2*length, 2*radius, q0));
+    EXPECT_EQ(m.DiagonalMoments(), 4*ixxyyzz);
+  }
+}
+
+/////////////////////////////////////////////////
+TEST(MassMatrix3dTest, SetFromSphere)
+{
+  // Default mass matrix with non-positive inertia
+  {
+    math::MassMatrix3d m;
+
+    // input is all zeros, so SetFromSphere should fail
+    EXPECT_FALSE(m.SetFromSphere(0.0, 0.0));
+    EXPECT_FALSE(m.SetFromSphere(0.0));
+
+    // even if mass is valid, it should not be set if radius is invalid
+    EXPECT_FALSE(m.SetFromSphere(1.0, 0.0));
+    EXPECT_DOUBLE_EQ(m.Mass(), 0.0);
+  }
+
+  // unit sphere with mass 1.0
+  {
+    const double mass = 1.0;
+    const double radius = 0.5;
+    math::MassMatrix3d m;
+    EXPECT_TRUE(m.SetFromSphere(mass, radius));
+
+    double ixx = 0.4 * mass * std::pow(radius, 2);
+    double iyy = ixx;
+    double izz = ixx;
+    const math::Vector3d ixxyyzz(ixx, iyy, izz);
+    EXPECT_EQ(m.DiagonalMoments(), ixxyyzz);
+    EXPECT_EQ(m.OffDiagonalMoments(), math::Vector3d::Zero);
+
+    // double the radius
+    EXPECT_TRUE(m.SetFromSphere(mass, 2*radius));
+    EXPECT_EQ(m.DiagonalMoments(), 4*ixxyyzz);
+  }
+}
+
diff --git a/src/Matrix3_TEST.cc b/src/Matrix3_TEST.cc
new file mode 100644
index 0000000..ddcdbf6
--- /dev/null
+++ b/src/Matrix3_TEST.cc
@@ -0,0 +1,400 @@
+/*
+ * Copyright (C) 2012 Open Source Robotics Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+*/
+
+#include <gtest/gtest.h>
+
+#include "ignition/math/Helpers.hh"
+#include "ignition/math/Matrix3.hh"
+
+using namespace ignition;
+
+/////////////////////////////////////////////////
+TEST(Matrix3dTest, Matrix3d)
+{
+  {
+    math::Matrix3d matrix;
+    EXPECT_TRUE(matrix == math::Matrix3d(0, 0, 0, 0, 0, 0, 0, 0, 0));
+  }
+
+  {
+    math::Matrix3d matrix(1, 2, 3, 4, 5, 6, 7, 8, 9);
+    EXPECT_TRUE(matrix == math::Matrix3d(1, 2, 3, 4, 5, 6, 7, 8, 9));
+
+    math::Matrix3d matrix1(matrix);
+    EXPECT_TRUE(matrix1 == math::Matrix3d(1, 2, 3, 4, 5, 6, 7, 8, 9));
+  }
+
+  math::Matrix3d matrix;
+  matrix.Axes(math::Vector3d(1, 1, 1), math::Vector3d(2, 2, 2),
+                     math::Vector3d(3, 3, 3));
+  EXPECT_TRUE(matrix == math::Matrix3d(1, 2, 3, 1, 2, 3, 1, 2, 3));
+
+  matrix.Axis(math::Vector3d(1, 1, 1), IGN_PI);
+  EXPECT_TRUE(matrix == math::Matrix3d(1, 2, 2, 2, 1, 2, 2, 2, 1));
+
+  matrix.Col(0, math::Vector3d(3, 4, 5));
+  EXPECT_TRUE(matrix == math::Matrix3d(3, 2, 2, 4, 1, 2, 5, 2, 1));
+
+  EXPECT_NO_THROW(matrix.Col(3, math::Vector3d(1, 1, 1)));
+  EXPECT_TRUE(matrix == math::Matrix3d(3, 2, 1, 4, 1, 1, 5, 2, 1));
+}
+
+/////////////////////////////////////////////////
+TEST(Matrix3dTest, NoIndexException)
+{
+  math::Matrix3d mat = math::Matrix3d::Zero;
+  for (int i = 0; i < 3; ++i)
+    for (int j = 0; j < 3; ++j)
+      EXPECT_NO_THROW(mat(i, j));
+
+  EXPECT_NO_THROW(math::equal(mat(3, 0), 0.0));
+  EXPECT_NO_THROW(math::equal(mat(0, 3), 0.0));
+  EXPECT_NO_THROW(math::equal(mat(3, 3), 0.0));
+
+  EXPECT_NO_THROW(mat(3, 0) = 0);
+  EXPECT_NO_THROW(mat(0, 3) = 0);
+  EXPECT_NO_THROW(mat(3, 3) = 0);
+
+  const math::Matrix3d constMat(math::Matrix3d::Zero);
+
+  EXPECT_NO_THROW(math::equal(constMat(3, 0), 0.0));
+  EXPECT_NO_THROW(math::equal(constMat(0, 3), 0.0));
+  EXPECT_NO_THROW(math::equal(constMat(3, 3), 0.0));
+}
+
+/////////////////////////////////////////////////
+TEST(Matrix3dTest, OperatorSubtract)
+{
+  math::Matrix3d matZero = math::Matrix3d::Zero;
+  math::Matrix3d matIdent = math::Matrix3d::Identity;
+
+  math::Matrix3d mat = matIdent - matZero;
+  EXPECT_EQ(mat, matIdent);
+
+  math::Matrix3d matA(1, 2, 3,
+                      4, 5, 6,
+                      7, 8, 9);
+
+  math::Matrix3d matB(10, 20, 30,
+                      40, 50, 60,
+                      70, 80, 90);
+
+  mat = matB - matA;
+  EXPECT_EQ(mat, math::Matrix3d(9, 18, 27, 36, 45, 54, 63, 72, 81));
+}
+
+/////////////////////////////////////////////////
+TEST(Matrix3dTest, OperatorAdd)
+{
+  math::Matrix3d matZero = math::Matrix3d::Zero;
+  math::Matrix3d matIdent = math::Matrix3d::Identity;
+
+  math::Matrix3d mat = matIdent + matZero;
+  EXPECT_EQ(mat, matIdent);
+
+  math::Matrix3d matA(1, 2, 3,
+                      4, 5, 6,
+                      7, 8, 9);
+
+  math::Matrix3d matB(10, 20, 30,
+                      40, 50, 60,
+                      70, 80, 90);
+
+  mat = matB + matA;
+  EXPECT_EQ(mat, math::Matrix3d(11, 22, 33, 44, 55, 66, 77, 88, 99));
+}
+
+/////////////////////////////////////////////////
+TEST(Matrix3dTest, OperatorMul)
+{
+  math::Matrix3d matZero = math::Matrix3d::Zero;
+  math::Matrix3d matIdent = math::Matrix3d::Identity;
+
+  math::Matrix3d mat = matIdent * matZero;
+  EXPECT_EQ(mat, matZero);
+
+  math::Matrix3d matA(1, 2, 3,
+                      4, 5, 6,
+                      7, 8, 9);
+
+  math::Matrix3d matB(10, 20, 30,
+                      40, 50, 60,
+                      70, 80, 90);
+
+  mat = matA * matB;
+  EXPECT_EQ(mat, math::Matrix3d(300, 360, 420,
+                                660, 810, 960,
+                                1020, 1260, 1500));
+
+  mat = matB * matA;
+  EXPECT_EQ(mat, math::Matrix3d(300, 360, 420,
+                                660, 810, 960,
+                                1020, 1260, 1500));
+
+  mat = mat * 2.0;
+  EXPECT_EQ(mat, math::Matrix3d(600, 720, 840,
+                                1320, 1620, 1920,
+                                2040, 2520, 3000));
+}
+
+/////////////////////////////////////////////////
+TEST(Matrix3dTest, OperatorStreamOut)
+{
+  math::Matrix3d matA(1, 2, 3,
+                      4, 5, 6,
+                      7, 8, 9);
+
+  std::ostringstream stream;
+  stream << matA;
+  EXPECT_EQ(stream.str(), "1 2 3 4 5 6 7 8 9");
+}
+
+/////////////////////////////////////////////////
+TEST(Matrix3dTest, OperatorStreamIn)
+{
+  math::Matrix3d mat;
+  EXPECT_EQ(mat, math::Matrix3d::Zero);
+
+  std::istringstream stream("1 2 3 4 5 6 7 8 9");
+  stream >> mat;
+  EXPECT_EQ(mat, math::Matrix3d(1, 2, 3, 4, 5, 6, 7, 8, 9));
+}
+
+/////////////////////////////////////////////////
+TEST(Matrix3dTest, Vector3Multiplication)
+{
+  {
+    // Multiply arbitrary matrix by zeros of different sizes
+    math::Matrix3d matrix(1, 2, 3, 4, 5, 6, 7, 8, 9);
+
+    // Scalar 0
+    EXPECT_EQ(math::Matrix3d::Zero, matrix * 0);
+    EXPECT_EQ(math::Matrix3d::Zero, 0 * matrix);
+
+    // Vector3::Zero
+    EXPECT_EQ(math::Vector3d::Zero, matrix * math::Vector3d::Zero);
+    EXPECT_EQ(math::Vector3d::Zero, math::Vector3d::Zero * matrix);
+    // left multiply with Vector3 not implemented
+
+    // Matrix3::Zero
+    EXPECT_EQ(math::Matrix3d::Zero, matrix * math::Matrix3d::Zero);
+    EXPECT_EQ(math::Matrix3d::Zero, math::Matrix3d::Zero * matrix);
+  }
+
+  {
+    // Multiply arbitrary matrix by identity values
+    math::Matrix3d matrix(1, 2, 3, 4, 5, 6, 7, 8, 9);
+
+    // scalar 1.0
+    EXPECT_EQ(matrix, matrix * 1.0);
+    EXPECT_EQ(matrix, 1.0 * matrix);
+
+    // Vector3::Unit[X|Y|Z]
+    // right multiply
+    EXPECT_EQ(math::Vector3d(matrix(0, 0), matrix(1, 0), matrix(2, 0)),
+              matrix * math::Vector3d::UnitX);
+    EXPECT_EQ(math::Vector3d(matrix(0, 1), matrix(1, 1), matrix(2, 1)),
+              matrix * math::Vector3d::UnitY);
+    EXPECT_EQ(math::Vector3d(matrix(0, 2), matrix(1, 2), matrix(2, 2)),
+              matrix * math::Vector3d::UnitZ);
+    // left multiply
+    EXPECT_EQ(math::Vector3d(matrix(0, 0), matrix(0, 1), matrix(0, 2)),
+              math::Vector3d::UnitX * matrix);
+    EXPECT_EQ(math::Vector3d(matrix(1, 0), matrix(1, 1), matrix(1, 2)),
+              math::Vector3d::UnitY * matrix);
+    EXPECT_EQ(math::Vector3d(matrix(2, 0), matrix(2, 1), matrix(2, 2)),
+              math::Vector3d::UnitZ * matrix);
+
+    // Matrix3::IDENTITY
+    EXPECT_EQ(matrix, matrix * math::Matrix3d::Identity);
+    EXPECT_EQ(matrix, math::Matrix3d::Identity * matrix);
+  }
+
+  {
+    // Multiply arbitrary matrix by itself
+    math::Matrix3d matrix(1, 2, 3, 4, 5, 6, 7, 8, 9);
+    math::Matrix3d matrix2(30,  36,  42,
+                           66,  81,  96,
+                           102, 126, 150);
+
+    EXPECT_EQ(matrix * matrix, matrix2);
+  }
+}
+
+/////////////////////////////////////////////////
+TEST(Matrix3dTest, NotEqual)
+{
+  {
+    math::Matrix3d matrix1;
+    math::Matrix3d matrix2;
+    EXPECT_TRUE(matrix1 == matrix2);
+    EXPECT_FALSE(matrix1 != matrix2);
+  }
+
+  {
+    math::Matrix3d matrix1(1, 2, 3, 4, 5, 6, 7, 8, 9);
+    math::Matrix3d matrix2(matrix1);
+
+    EXPECT_FALSE(matrix1 != matrix1);
+
+    matrix2(0, 0) = 1.00001;
+    EXPECT_TRUE(matrix1 != matrix2);
+
+    matrix2(0, 0) = 1.000001;
+    EXPECT_FALSE(matrix1 != matrix2);
+  }
+}
+
+/////////////////////////////////////////////////
+// Test Equal function with specified tolerance
+TEST(Matrix3Test, EqualTolerance)
+{
+  EXPECT_FALSE(math::Matrix3d::Zero.Equal(math::Matrix3d::Identity, 1e-6));
+  EXPECT_FALSE(math::Matrix3d::Zero.Equal(math::Matrix3d::Identity, 1e-3));
+  EXPECT_FALSE(math::Matrix3d::Zero.Equal(math::Matrix3d::Identity, 1e-1));
+  EXPECT_TRUE(math::Matrix3d::Zero.Equal(math::Matrix3d::Identity, 1));
+  EXPECT_TRUE(math::Matrix3d::Zero.Equal(math::Matrix3d::Identity, 1.1));
+}
+
+/////////////////////////////////////////////////
+TEST(Matrix3dTest, Inverse)
+{
+  // Inverse of identity matrix is itself
+  EXPECT_EQ(math::Matrix3d::Identity, math::Matrix3d::Identity.Inverse());
+
+  // Matrix multiplied by its inverse results in the identity matrix
+  math::Matrix3d matrix1(-2, 4, 0, 0.1, 9, 55, -7, 1, 26);
+  math::Matrix3d matrix2 = matrix1.Inverse();
+  EXPECT_EQ(matrix1 * matrix2, math::Matrix3d::Identity);
+  EXPECT_EQ(matrix2 * matrix1, math::Matrix3d::Identity);
+
+  // Inverse of inverse results in the same matrix
+  EXPECT_EQ((matrix1.Inverse()).Inverse(), matrix1);
+
+  // Invert multiplication by scalar
+  double scalar = 2.5;
+  EXPECT_EQ((matrix1 * scalar).Inverse(), matrix1.Inverse() * (1.0/scalar));
+}
+
+/////////////////////////////////////////////////
+TEST(Matrix3dTest, Determinant)
+{
+  // |Zero matrix| = 0.0
+  EXPECT_DOUBLE_EQ(0.0, math::Matrix3d::Zero.Determinant());
+
+  // |Identity matrix| = 1.0
+  EXPECT_DOUBLE_EQ(1.0, math::Matrix3d::Identity.Determinant());
+
+  // Determinant of arbitrary matrix
+  math::Matrix3d m(-2, 4, 0, 0.1, 9, 55, -7, 1, 26);
+  EXPECT_DOUBLE_EQ(-1908.4, m.Determinant());
+}
+
+/////////////////////////////////////////////////
+TEST(Matrix3dTest, Transpose)
+{
+  // Transpose of zero matrix is itself
+  EXPECT_EQ(math::Matrix3d::Zero, math::Matrix3d::Zero.Transposed());
+
+  // Transpose of identity matrix is itself
+  EXPECT_EQ(math::Matrix3d::Identity, math::Matrix3d::Identity.Transposed());
+
+  // Matrix and expected transpose
+  math::Matrix3d m(-2, 4, 0,
+                  0.1, 9, 55,
+                   -7, 1, 26);
+  math::Matrix3d mT(-2, 0.1, -7,
+                     4,   9, 1,
+                     0,  55, 26);
+  EXPECT_NE(m, mT);
+  EXPECT_EQ(m.Transposed(), mT);
+  EXPECT_DOUBLE_EQ(m.Determinant(), m.Transposed().Determinant());
+
+  mT.Transpose();
+  EXPECT_EQ(m, mT);
+}
+
+/////////////////////////////////////////////////
+TEST(Matrix3dTest, From2Axes)
+{
+  math::Vector3d v1(1.0, 0.0, 0.0);
+  math::Vector3d v2(0.0, 1.0, 0.0);
+
+  math::Matrix3d m1;
+  m1.From2Axes(v1, v2);
+
+  math::Matrix3d m2;
+  m2.From2Axes(v2, v1);
+
+  math::Matrix3d m1Correct(0, -1, 0,
+                           1, 0, 0,
+                           0, 0, 1);
+  math::Matrix3d m2Correct(m1Correct);
+  m2Correct.Transpose();
+
+  EXPECT_NE(m1, m2);
+  EXPECT_EQ(m1Correct, m1);
+  EXPECT_EQ(m2Correct, m2);
+  EXPECT_EQ(math::Matrix3d::Identity, m1 * m2);
+  EXPECT_EQ(v2, m1 * v1);
+  EXPECT_EQ(v1, m2 * v2);
+
+  // rotation about 45 degrees
+  v1.Set(1.0, 0.0, 0.0);
+  v2.Set(1.0, 1.0, 0.0);
+  m2.From2Axes(v1, v2);
+  // m1 is 90 degrees rotation
+  EXPECT_EQ(m1, m2*m2);
+
+  // with non-unit vectors
+  v1.Set(0.5, 0.5, 0);
+  v2.Set(-0.5, 0.5, 0);
+
+  m1.From2Axes(v1, v2);
+  m2.From2Axes(v2, v1);
+
+  EXPECT_NE(m1, m2);
+  EXPECT_EQ(m1Correct, m1);
+  EXPECT_EQ(m2Correct, m2);
+  EXPECT_EQ(math::Matrix3d::Identity, m1 * m2);
+  EXPECT_EQ(v2, m1 * v1);
+  EXPECT_EQ(v1, m2 * v2);
+
+  // For zero-length vectors, a unit matrix is returned
+  v1.Set(0, 0, 0);
+  v2.Set(-0.5, 0.5, 0);
+  m1.From2Axes(v1, v2);
+  EXPECT_EQ(math::Matrix3d::Identity, m1);
+
+  // For zero-length vectors, a unit matrix is returned
+  v1.Set(-0.5, 0.5, 0);
+  v2.Set(0, 0, 0);
+  m1.From2Axes(v1, v2);
+  EXPECT_EQ(math::Matrix3d::Identity, m1);
+
+  // Parallel vectors
+  v1.Set(1, 0, 0);
+  v2.Set(2, 0, 0);
+  m1.From2Axes(v1, v2);
+  EXPECT_EQ(math::Matrix3d::Identity, m1);
+
+  // Opposite vectors
+  v1.Set(1, 0, 0);
+  v2.Set(-2, 0, 0);
+  m1.From2Axes(v1, v2);
+  EXPECT_EQ(math::Matrix3d::Zero - math::Matrix3d::Identity, m1);
+}
diff --git a/src/Matrix4_TEST.cc b/src/Matrix4_TEST.cc
new file mode 100644
index 0000000..37ffc05
--- /dev/null
+++ b/src/Matrix4_TEST.cc
@@ -0,0 +1,656 @@
+/*
+ * Copyright (C) 2012 Open Source Robotics Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+*/
+
+#include <gtest/gtest.h>
+
+#include "ignition/math/Pose3.hh"
+#include "ignition/math/Quaternion.hh"
+#include "ignition/math/Matrix4.hh"
+#include "ignition/math/Vector3.hh"
+
+using namespace ignition;
+
+/////////////////////////////////////////////////
+TEST(Matrix4dTest, Construct)
+{
+  math::Matrix4d mat;
+  for (int i = 0; i < 4; ++i)
+  {
+    for (int j = 0; j < 4; ++j)
+    {
+      EXPECT_DOUBLE_EQ(mat(i, i), 0.0);
+    }
+  }
+
+  math::Matrix4d mat2(mat);
+  for (int i = 0; i < 4; ++i)
+  {
+    for (int j = 0; j < 4; ++j)
+    {
+      EXPECT_DOUBLE_EQ(mat2(i, i), 0.0);
+    }
+  }
+  EXPECT_TRUE(mat2 == mat);
+
+
+  // Set individual values.
+  math::Matrix4d mat3(0.0, 1.0, 2.0, 3.0,
+                     4.0, 5.0, 6.0, 7.0,
+                     8.0, 9.0, 10.0, 11.0,
+                     12.0, 13.0, 14.0, 15.0);
+
+  math::Matrix4d mat4;
+  mat4 = mat3;
+  EXPECT_EQ(mat4, mat3);
+
+  EXPECT_DOUBLE_EQ(mat3(0, 0), 0.0);
+  EXPECT_DOUBLE_EQ(mat3(0, 1), 1.0);
+  EXPECT_DOUBLE_EQ(mat3(0, 2), 2.0);
+  EXPECT_DOUBLE_EQ(mat3(0, 3), 3.0);
+  EXPECT_DOUBLE_EQ(mat3(1, 0), 4.0);
+  EXPECT_DOUBLE_EQ(mat3(1, 1), 5.0);
+  EXPECT_DOUBLE_EQ(mat3(1, 2), 6.0);
+  EXPECT_DOUBLE_EQ(mat3(1, 3), 7.0);
+  EXPECT_DOUBLE_EQ(mat3(2, 0), 8.0);
+  EXPECT_DOUBLE_EQ(mat3(2, 1), 9.0);
+  EXPECT_DOUBLE_EQ(mat3(2, 2), 10.0);
+  EXPECT_DOUBLE_EQ(mat3(2, 3), 11.0);
+  EXPECT_DOUBLE_EQ(mat3(3, 0), 12.0);
+  EXPECT_DOUBLE_EQ(mat3(3, 1), 13.0);
+  EXPECT_DOUBLE_EQ(mat3(3, 2), 14.0);
+  EXPECT_DOUBLE_EQ(mat3(3, 3), 15.0);
+}
+
+/////////////////////////////////////////////////
+TEST(Matrix4dTest, ConstructFromPose3d)
+{
+  {
+    math::Vector3d trans(1, 2, 3);
+    math::Quaterniond qt(0.1, 0.2, 0.3);
+    math::Pose3d pose(trans, qt);
+    math::Matrix4d mat(pose);
+
+    EXPECT_EQ(pose, mat.Pose());
+    EXPECT_EQ(trans, mat.Translation());
+    EXPECT_EQ(qt, mat.Rotation());
+    EXPECT_EQ(pose.Inverse(), mat.Inverse().Pose());
+  }
+
+  // Zero values
+  {
+    math::Vector3d trans(0, 0, 0);
+    math::Quaterniond qt(0, 0, 0);
+    math::Pose3d pose(trans, qt);
+    math::Matrix4d mat(pose);
+
+    EXPECT_EQ(pose, mat.Pose());
+    EXPECT_EQ(trans, mat.Translation());
+    EXPECT_EQ(qt, mat.Rotation());
+    EXPECT_EQ(pose.Inverse(), mat.Inverse().Pose());
+  }
+
+  // Rotate pitch by pi/2 so yaw coincides with roll causing a gimbal lock
+  {
+    math::Vector3d trans(3, 2, 1);
+    math::Quaterniond qt(0, IGN_PI/2, 0);
+    math::Pose3d pose(trans, qt);
+    math::Matrix4d mat(pose);
+
+    EXPECT_EQ(pose, mat.Pose());
+    EXPECT_EQ(trans, mat.Translation());
+    EXPECT_EQ(qt, mat.Rotation());
+    EXPECT_EQ(pose.Inverse(), mat.Inverse().Pose());
+  }
+}
+
+/////////////////////////////////////////////////
+TEST(Matrix4dTest, CoverageExtra)
+{
+  // getting full destructor coverage
+  math::Matrix4d *p = new math::Matrix4d;
+  EXPECT_NE(p, nullptr);
+  delete p;
+}
+
+/////////////////////////////////////////////////
+TEST(Matrix4dTest, Scale)
+{
+  math::Matrix4d mat, mat2;
+  mat.Scale(math::Vector3d(1, 2, 3));
+  mat2.Scale(1, 2, 3);
+
+  EXPECT_EQ(mat, mat2);
+
+  EXPECT_DOUBLE_EQ(mat(0, 0), 1.0);
+  EXPECT_DOUBLE_EQ(mat(1, 1), 2.0);
+  EXPECT_DOUBLE_EQ(mat(2, 2), 3.0);
+  EXPECT_DOUBLE_EQ(mat(3, 3), 1.0);
+
+  EXPECT_DOUBLE_EQ(mat2(0, 0), 1.0);
+  EXPECT_DOUBLE_EQ(mat2(1, 1), 2.0);
+  EXPECT_DOUBLE_EQ(mat2(2, 2), 3.0);
+  EXPECT_DOUBLE_EQ(mat2(3, 3), 1.0);
+
+  EXPECT_EQ(mat.Scale(), mat2.Scale());
+  EXPECT_EQ(mat.Scale(), math::Vector3d(1, 2, 3));
+
+  for (int i = 0; i < 4; ++i)
+  {
+    for (int j = 0; j < 4; ++j)
+    {
+      if (i != j)
+      {
+        EXPECT_DOUBLE_EQ(mat(i, j), 0.0);
+        EXPECT_DOUBLE_EQ(mat2(i, j), 0.0);
+      }
+      else if (i == 3 && j == 3)
+      {
+        EXPECT_DOUBLE_EQ(mat(i, j), 1.0);
+        EXPECT_DOUBLE_EQ(mat2(i, j), 1.0);
+      }
+    }
+  }
+}
+
+/////////////////////////////////////////////////
+TEST(Matrix4dTest, MultiplyV)
+{
+  math::Matrix4d mat;
+  math::Vector3d vec(-1.2, 2.3, 10.5);
+
+  for (int i = 0; i < 4; ++i)
+  {
+    for (int j = 0; j < 4; ++j)
+    {
+      mat(i, j) = i-j;
+    }
+  }
+
+  EXPECT_EQ(mat * vec, math::Vector3d(-26.3, -13.7, -1.1));
+}
+
+/////////////////////////////////////////////////
+TEST(Matrix4dTest, Multiply4)
+{
+  math::Matrix4d mat, mat1;
+
+  for (int i = 0; i < 4; ++i)
+  {
+    for (int j = 0; j < 4; ++j)
+    {
+      mat(i, j) = i-j;
+      mat1(j, i) = i+j;
+    }
+  }
+
+  math::Matrix4d mat3(
+      -14, -20, -26, -32,
+      -8, -10, -12, -14,
+      -2, 0, 2, 4,
+      4, 10, 16, 22);
+
+  math::Matrix4d mat2 = mat * mat1;
+  EXPECT_EQ(mat2, mat3);
+}
+
+/////////////////////////////////////////////////
+TEST(Matrix4dTest, Inverse)
+{
+  math::Matrix4d mat(2, 3, 1, 5,
+                    1, 0, 3, 1,
+                    0, 2, -3, 2,
+                    0, 2, 3, 1);
+
+  math::Matrix4d mat1 = mat.Inverse();
+  EXPECT_EQ(mat1, math::Matrix4d(18, -35, -28, 1,
+                               9, -18, -14, 1,
+                               -2, 4, 3, 0,
+                               -12, 24, 19, -1));
+}
+
+/////////////////////////////////////////////////
+TEST(Matrix4dTest, GetAsPose3d)
+{
+  math::Matrix4d mat(2, 3, 1, 5,
+                    1, 0, 3, 1,
+                    0, 2, -3, 2,
+                    0, 2, 3, 1);
+  math::Pose3d pose = mat.Pose();
+
+  EXPECT_EQ(pose,
+      math::Pose3d(5, 1, 2, -0.204124, 1.22474, 0.816497, 0.204124));
+}
+
+/////////////////////////////////////////////////
+TEST(Matrix4dTest, Translate)
+{
+  math::Matrix4d mat, mat2;
+  mat.Translate(math::Vector3d(1, 2, 3));
+  mat2.Translate(1, 2, 3);
+
+  EXPECT_EQ(mat, mat2);
+
+  EXPECT_DOUBLE_EQ(mat(0, 3), 1.0);
+  EXPECT_DOUBLE_EQ(mat(1, 3), 2.0);
+  EXPECT_DOUBLE_EQ(mat(2, 3), 3.0);
+
+  EXPECT_DOUBLE_EQ(mat2(0, 3), 1.0);
+  EXPECT_DOUBLE_EQ(mat2(1, 3), 2.0);
+  EXPECT_DOUBLE_EQ(mat2(2, 3), 3.0);
+
+  EXPECT_EQ(mat.Translation(), mat2.Translation());
+  EXPECT_EQ(mat.Translation(), math::Vector3d(1, 2, 3));
+
+  for (int i = 0; i < 4; ++i)
+  {
+    for (int j = 0; j < 2; ++j)
+    {
+      EXPECT_DOUBLE_EQ(mat(i, j), 0.0);
+      EXPECT_DOUBLE_EQ(mat2(i, j), 0.0);
+    }
+  }
+  EXPECT_DOUBLE_EQ(mat(3, 3), 0.0);
+  EXPECT_DOUBLE_EQ(mat2(3, 3), 0.0);
+}
+
+/////////////////////////////////////////////////
+TEST(Matrix4dTest, RotationDiagZero)
+{
+  math::Matrix4d mat;
+  mat(0, 0) = 0;
+  mat(0, 1) = 0.2;
+  mat(0, 2) = 0.3;
+  mat(0, 3) = 0.4;
+
+  mat(1, 0) = 0.5;
+  mat(1, 1) = 0;
+  mat(1, 2) = 0.7;
+  mat(1, 3) = 0.8;
+
+  mat(2, 0) = 0.9;
+  mat(2, 1) = 1.0;
+  mat(2, 2) = 0;
+  mat(2, 3) = 1.2;
+
+  mat(3, 0) = 1.3;
+  mat(3, 1) = 1.4;
+  mat(3, 2) = 1.5;
+  mat(3, 3) = 1.0;
+
+  math::Quaterniond quat = mat.Rotation();
+  EXPECT_NEAR(quat.X(), 0.5, 1e-6);
+  EXPECT_NEAR(quat.Y(), 0.35, 1e-6);
+  EXPECT_NEAR(quat.Z(), 0.6, 1e-6);
+  EXPECT_NEAR(quat.W(), 0.15, 1e-6);
+
+  math::Vector3d euler = mat.EulerRotation(true);
+  EXPECT_EQ(euler, math::Vector3d(1.5708, -1.11977, 1.5708));
+
+  euler = mat.EulerRotation(false);
+  EXPECT_EQ(euler, math::Vector3d(-1.5708, 4.26136, -1.5708));
+}
+
+/////////////////////////////////////////////////
+TEST(Matrix4dTest, RotationDiagLessThanZero)
+{
+  math::Matrix4d mat;
+  mat(0, 0) = -0.1;
+  mat(0, 1) = 0.2;
+  mat(0, 2) = 0.3;
+  mat(0, 3) = 0.4;
+
+  mat(1, 0) = 0.5;
+  mat(1, 1) = 0;
+  mat(1, 2) = 0.7;
+  mat(1, 3) = 0.8;
+
+  mat(2, 0) = 0.9;
+  mat(2, 1) = 1.0;
+  mat(2, 2) = 0;
+  mat(2, 3) = 1.2;
+
+  mat(3, 0) = 1.3;
+  mat(3, 1) = 1.4;
+  mat(3, 2) = 1.5;
+  mat(3, 3) = 1.0;
+
+  {
+    math::Quaterniond quat = mat.Rotation();
+    EXPECT_NEAR(quat.X(), 0.333712, 1e-6);
+    EXPECT_NEAR(quat.Y(), 0.524404, 1e-6);
+    EXPECT_NEAR(quat.Z(), 0.810443, 1e-6);
+    EXPECT_NEAR(quat.W(), -0.286039, 1e-6);
+
+    math::Vector3d euler = mat.EulerRotation(true);
+    EXPECT_EQ(euler, math::Vector3d(1.5708, -1.11977, 1.76819));
+
+    euler = mat.EulerRotation(false);
+    EXPECT_EQ(euler, math::Vector3d(-1.5708, 4.26136, -1.3734));
+  }
+
+
+  {
+    mat(0, 0) = -0.1;
+    mat(1, 1) = -0.2;
+    mat(2, 2) = 0.0;
+
+    math::Quaterniond quat = mat.Rotation();
+    EXPECT_NEAR(quat.X(), 0.526235, 1e-6);
+    EXPECT_NEAR(quat.Y(), 0.745499, 1e-6);
+    EXPECT_NEAR(quat.Z(), 0.570088, 1e-6);
+    EXPECT_NEAR(quat.W(), 0.131559, 1e-6);
+
+    math::Vector3d euler = mat.EulerRotation(true);
+    EXPECT_EQ(euler, math::Vector3d(1.5708, -1.11977, 1.76819));
+
+    euler = mat.EulerRotation(false);
+    EXPECT_EQ(euler, math::Vector3d(-1.5708, 4.26136, -1.3734));
+  }
+}
+
+
+/////////////////////////////////////////////////
+TEST(Matrix4dTest, Rotation)
+{
+  math::Matrix4d mat;
+  mat(0, 0) = 0.1;
+  mat(0, 1) = 0.2;
+  mat(0, 2) = 0.3;
+  mat(0, 3) = 0.4;
+
+  mat(1, 0) = 0.5;
+  mat(1, 1) = 0.6;
+  mat(1, 2) = 0.7;
+  mat(1, 3) = 0.8;
+
+  mat(2, 0) = 0.9;
+  mat(2, 1) = 1.0;
+  mat(2, 2) = 1.1;
+  mat(2, 3) = 1.2;
+
+  mat(3, 0) = 1.3;
+  mat(3, 1) = 1.4;
+  mat(3, 2) = 1.5;
+  mat(3, 3) = 1.6;
+
+  math::Quaterniond quat = mat.Rotation();
+  EXPECT_NEAR(quat.X(), 0.0896421, 1e-6);
+  EXPECT_NEAR(quat.Y(), -0.179284, 1e-6);
+  EXPECT_NEAR(quat.Z(), 0.0896421, 1e-6);
+  EXPECT_NEAR(quat.W(), 0.83666, 1e-6);
+
+  math::Vector3d euler = mat.EulerRotation(true);
+  EXPECT_EQ(euler, math::Vector3d(0.737815, -1.11977, 1.3734));
+
+  euler = mat.EulerRotation(false);
+  EXPECT_EQ(euler, math::Vector3d(-2.40378, 4.26136, -1.76819));
+}
+
+/////////////////////////////////////////////////
+TEST(Matrix4dTest, EulerRotation2)
+{
+  math::Matrix4d mat;
+  mat(0, 0) = 0.1;
+  mat(0, 1) = 0.2;
+  mat(0, 2) = 0.3;
+  mat(0, 3) = 0.4;
+
+  mat(1, 0) = 0.5;
+  mat(1, 1) = 0.6;
+  mat(1, 2) = 0.7;
+  mat(1, 3) = 0.8;
+
+  mat(2, 0) = 1.9;
+  mat(2, 1) = 1.2;
+  mat(2, 2) = 1.1;
+  mat(2, 3) = 1.2;
+
+  mat(3, 0) = 1.3;
+  mat(3, 1) = 1.4;
+  mat(3, 2) = 1.5;
+  mat(3, 3) = 1.6;
+
+  math::Vector3d euler = mat.EulerRotation(true);
+  EXPECT_EQ(euler, math::Vector3d(-2.55359, -1.5708, 0));
+
+  euler = mat.EulerRotation(false);
+  EXPECT_EQ(euler, math::Vector3d(-2.55359, -1.5708, 0));
+
+  mat(2, 0) = -1.2;
+  euler = mat.EulerRotation(true);
+  EXPECT_EQ(euler, math::Vector3d(0.588003, 1.5708, 0));
+
+  euler = mat.EulerRotation(false);
+  EXPECT_EQ(euler, math::Vector3d(0.588003, 1.5708, 0));
+}
+
+/////////////////////////////////////////////////
+TEST(Matrix4dTest, AffineTransform)
+{
+  math::Matrix4d mat = math::Matrix4d::Zero;
+  math::Vector3d vec(1, 2, 3);
+
+  math::Vector3d v;
+  EXPECT_NO_THROW(mat.TransformAffine(vec, v));
+  EXPECT_FALSE(mat.TransformAffine(vec, v));
+
+  mat = math::Matrix4d::Identity;
+  EXPECT_NO_THROW(mat.TransformAffine(vec, v));
+  EXPECT_TRUE(mat.TransformAffine(vec, v));
+}
+
+/////////////////////////////////////////////////
+TEST(Matrix4dTest, NoIndexException)
+{
+  math::Matrix4d mat = math::Matrix4d::Zero;
+  for (int i = 0; i < 4; ++i)
+    for (int j = 0; j < 4; ++j)
+      EXPECT_NO_THROW(mat(i, j));
+
+  EXPECT_NO_THROW(math::equal(mat(4, 0), 0.0));
+  EXPECT_NO_THROW(math::equal(mat(0, 4), 0.0));
+  EXPECT_NO_THROW(math::equal(mat(4, 4), 0.0));
+
+  EXPECT_NO_THROW(mat(4, 0) = 0);
+  EXPECT_NO_THROW(mat(0, 4) = 0);
+  EXPECT_NO_THROW(mat(4, 4) = 0);
+
+  const math::Matrix4d constMat(math::Matrix4d::Zero);
+
+  EXPECT_NO_THROW(math::equal(constMat(4, 0), 0.0));
+  EXPECT_NO_THROW(math::equal(constMat(0, 4), 0.0));
+  EXPECT_NO_THROW(math::equal(constMat(4, 4), 0.0));
+}
+
+/////////////////////////////////////////////////
+TEST(Matrix4dTest, OperatorStreamOut)
+{
+  math::Matrix4d matA(1, 2, 3, 4,
+                      5, 6, 7, 8,
+                      9, 10, 11, 12,
+                      13, 14, 15, 16);
+
+  std::ostringstream stream;
+  stream << matA;
+  EXPECT_EQ(stream.str(), "1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16");
+}
+
+/////////////////////////////////////////////////
+TEST(Matrix4dTest, OperatorStreamIn)
+{
+  math::Matrix4d mat;
+  EXPECT_EQ(mat, math::Matrix4d::Zero);
+
+  std::istringstream stream("1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16");
+  stream >> mat;
+  EXPECT_EQ(mat, math::Matrix4d(1, 2, 3, 4,
+                                5, 6, 7, 8,
+                                9, 10, 11, 12,
+                                13, 14, 15, 16));
+}
+
+/////////////////////////////////////////////////
+TEST(Matrix4dTest, NotEqual)
+{
+  {
+    math::Matrix4d matrix1;
+    math::Matrix4d matrix2;
+    EXPECT_TRUE(matrix1 == matrix2);
+    EXPECT_FALSE(matrix1 != matrix2);
+  }
+
+  {
+    math::Matrix4d matrix1(1, 2, 3, 4,
+                           5, 6, 7, 8,
+                           9, 10, 11, 12,
+                           13, 14, 15, 16);
+    math::Matrix4d matrix2(matrix1);
+
+    EXPECT_FALSE(matrix1 != matrix1);
+
+    matrix2(0, 0) = 1.00001;
+    EXPECT_TRUE(matrix1 != matrix2);
+
+    matrix2(0, 0) = 1.000001;
+    EXPECT_FALSE(matrix1 != matrix2);
+  }
+}
+
+/////////////////////////////////////////////////
+// Test Equal function with specified tolerance
+TEST(Matrix4Test, EqualTolerance)
+{
+  EXPECT_FALSE(math::Matrix4d::Zero.Equal(math::Matrix4d::Identity, 1e-6));
+  EXPECT_FALSE(math::Matrix4d::Zero.Equal(math::Matrix4d::Identity, 1e-3));
+  EXPECT_FALSE(math::Matrix4d::Zero.Equal(math::Matrix4d::Identity, 1e-1));
+  EXPECT_TRUE(math::Matrix4d::Zero.Equal(math::Matrix4d::Identity, 1));
+  EXPECT_TRUE(math::Matrix4d::Zero.Equal(math::Matrix4d::Identity, 1.1));
+}
+
+/////////////////////////////////////////////////
+TEST(Matrix4dTest, Determinant)
+{
+  // |Zero matrix| = 0.0
+  EXPECT_DOUBLE_EQ(0.0, math::Matrix4d::Zero.Determinant());
+
+  // |Identity matrix| = 1.0
+  EXPECT_DOUBLE_EQ(1.0, math::Matrix4d::Identity.Determinant());
+
+  // Determinant of arbitrary matrix
+  math::Matrix4d m(2, 3, 0.1, -5, 1, 0, 3.2, 1,
+                   0, 2, -3, 2.1, 0, 2, 3.2, 1);
+  EXPECT_DOUBLE_EQ(129.82, m.Determinant());
+}
+
+/////////////////////////////////////////////////
+TEST(Matrix4dTest, Transpose)
+{
+  // Transpose of zero matrix is itself
+  EXPECT_EQ(math::Matrix4d::Zero, math::Matrix4d::Zero.Transposed());
+
+  // Transpose of identity matrix is itself
+  EXPECT_EQ(math::Matrix4d::Identity, math::Matrix4d::Identity.Transposed());
+
+  // Matrix and expected transpose
+  math::Matrix4d m(-2, 4,  0, -3.5,
+                  0.1, 9, 55,  1.2,
+                   -7, 1, 26, 11.5,
+                   .2, 3, -5, -0.1);
+  math::Matrix4d mT(-2, 0.1,   -7, .2,
+                     4,   9,    1, 3,
+                     0,  55,   26, -5,
+                  -3.5, 1.2, 11.5, -0.1);
+  EXPECT_NE(m, mT);
+  EXPECT_EQ(m.Transposed(), mT);
+  EXPECT_DOUBLE_EQ(m.Determinant(), m.Transposed().Determinant());
+
+  mT.Transpose();
+  EXPECT_EQ(m, mT);
+}
+
+/////////////////////////////////////////////////
+TEST(Matrix4dTest, LookAt)
+{
+  EXPECT_EQ(math::Matrix4d::LookAt(-math::Vector3d::UnitX,
+                                    math::Vector3d::Zero).Pose(),
+            math::Pose3d(-1, 0, 0, 0, 0, 0));
+
+  EXPECT_EQ(math::Matrix4d::LookAt(math::Vector3d(3, 2, 0),
+                                   math::Vector3d(0, 2, 0)).Pose(),
+            math::Pose3d(3, 2, 0, 0, 0, IGN_PI));
+
+  EXPECT_EQ(math::Matrix4d::LookAt(math::Vector3d(1, 6, 1),
+                                   math::Vector3d::One).Pose(),
+            math::Pose3d(1, 6, 1, 0, 0, -IGN_PI_2));
+
+  EXPECT_EQ(math::Matrix4d::LookAt(math::Vector3d(-1, -1, 0),
+                                   math::Vector3d(1, 1, 0)).Pose(),
+            math::Pose3d(-1, -1, 0, 0, 0, IGN_PI_4));
+
+  // Default up is Z
+  EXPECT_EQ(math::Matrix4d::LookAt(math::Vector3d(0.1, -5, 222),
+                                   math::Vector3d(999, -0.6, 0)),
+            math::Matrix4d::LookAt(math::Vector3d(0.1, -5, 222),
+                                   math::Vector3d(999, -0.6, 0),
+                                   math::Vector3d::UnitZ));
+
+  // up == zero, default up = +Z
+  EXPECT_EQ(math::Matrix4d::LookAt(math::Vector3d(1.23, 456, 0.7),
+                                   math::Vector3d(0, 8.9, -10),
+                                   math::Vector3d::Zero),
+            math::Matrix4d::LookAt(math::Vector3d(1.23, 456, 0.7),
+                                   math::Vector3d(0, 8.9, -10)));
+
+  // up == +X, default up = +Z
+  EXPECT_EQ(math::Matrix4d::LookAt(math::Vector3d(0.25, 9, -5),
+                                   math::Vector3d(-6, 0, 0.4),
+                                   math::Vector3d::UnitX),
+            math::Matrix4d::LookAt(math::Vector3d(0.25, 9, -5),
+                                   math::Vector3d(-6, 0, 0.4)));
+
+  // up == -X, default up = +Z
+  EXPECT_EQ(math::Matrix4d::LookAt(math::Vector3d(0, 0, 0.2),
+                                   math::Vector3d(-8, 0, -6),
+                                   -math::Vector3d::UnitX),
+            math::Matrix4d::LookAt(math::Vector3d(0, 0, 0.2),
+                                   math::Vector3d(-8, 0, -6)));
+
+  // eye == target, default direction = +X
+  EXPECT_EQ(math::Matrix4d::LookAt(math::Vector3d::One,
+                                   math::Vector3d::One),
+            math::Matrix4d::LookAt(math::Vector3d::One,
+                                   math::Vector3d(1.0001, 1, 1)));
+
+  // Not possible to keep _up on +Z
+  EXPECT_EQ(math::Matrix4d::LookAt(math::Vector3d(-1, 0, 10),
+                                   math::Vector3d(-1, 0, 0)),
+            math::Matrix4d::LookAt(math::Vector3d(-1, 0, 10),
+                                   math::Vector3d(-1, 0, 0),
+                                   -math::Vector3d::UnitX));
+
+  // Different ups
+  EXPECT_EQ(math::Matrix4d::LookAt(math::Vector3d::One,
+                                   math::Vector3d(0, 1, 1),
+                                   math::Vector3d::UnitY).Pose(),
+            math::Pose3d(1, 1, 1, IGN_PI_2, 0, IGN_PI));
+
+  EXPECT_EQ(math::Matrix4d::LookAt(math::Vector3d::One,
+                                   math::Vector3d(0, 1, 1),
+                                   math::Vector3d(0, 1, 1)).Pose(),
+            math::Pose3d(1, 1, 1, IGN_PI_4, 0, IGN_PI));
+}
+
diff --git a/src/OrientedBox_TEST.cc b/src/OrientedBox_TEST.cc
new file mode 100644
index 0000000..f89c878
--- /dev/null
+++ b/src/OrientedBox_TEST.cc
@@ -0,0 +1,335 @@
+/*
+ * Copyright (C) 2017 Open Source Robotics Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+*/
+#include <gtest/gtest.h>
+#include <cmath>
+
+#include "ignition/math/Angle.hh"
+#include "ignition/math/OrientedBox.hh"
+
+using namespace ignition;
+using namespace math;
+
+auto g_tolerance = 1e-6;
+
+/////////////////////////////////////////////////
+TEST(OrientedBoxTest, EmptyConstructorNew)
+{
+  OrientedBoxd *box = nullptr;
+
+  {
+    box = new OrientedBoxd;
+    EXPECT_TRUE(box != nullptr);
+  }
+
+  EXPECT_TRUE(box->Size() == Vector3d::Zero);
+  EXPECT_TRUE(box->Pose() == Pose3d::Zero);
+
+  {
+    delete box;
+    box = nullptr;
+  }
+}
+
+/////////////////////////////////////////////////
+TEST(OrientedBoxTest, EmptyConstructor)
+{
+  OrientedBoxd box;
+  EXPECT_TRUE(box.Size() == Vector3d::Zero);
+  EXPECT_TRUE(box.Pose() == Pose3d::Zero);
+}
+
+/////////////////////////////////////////////////
+TEST(OrientedBoxTest, SizeOnlyConstructor)
+{
+  OrientedBoxd box(Vector3d(1, 2, 3));
+  EXPECT_EQ(box.Size(), Vector3d(1, 2, 3));
+  EXPECT_EQ(box.Pose(), Pose3d::Zero);
+}
+
+/////////////////////////////////////////////////
+TEST(OrientedBoxTest, NegativeSizeConstructor)
+{
+  OrientedBoxd box(Vector3d(-1, 0, -3));
+  EXPECT_EQ(box.Size(), Vector3d(1, 0, 3));
+}
+
+/////////////////////////////////////////////////
+TEST(OrientedBoxTest, SizePoseConstructor)
+{
+  OrientedBoxi box(Vector3i(1, 2, 3), Pose3i(-1, -2, -3, 0, 1, 2));
+  EXPECT_EQ(box.Size(), Vector3i(1, 2, 3));
+  EXPECT_EQ(box.Pose(), Pose3i(-1, -2, -3, 0, 1, 2));
+}
+
+/////////////////////////////////////////////////
+TEST(OrientedBoxTest, CopyConstructor)
+{
+  OrientedBoxf box1(Vector3f(0.1f, 0.2f, 0.3f),
+                     Pose3f(-0.1f, -0.2f, 0.0f, 1.1f, 1.2f, 1.3f));
+  OrientedBoxf box2(box1);
+
+  EXPECT_EQ(box2.Size(), Vector3f(0.1f, 0.2f, 0.3f));
+  EXPECT_EQ(box2.Pose(), Pose3f(-0.1f, -0.2f, 0.0f, 1.1f, 1.2f, 1.3f));
+}
+
+/////////////////////////////////////////////////
+TEST(OrientedBoxTest, Length)
+{
+  OrientedBoxd box(Vector3d(0.1, -2.1, 0.0));
+  EXPECT_DOUBLE_EQ(box.XLength(), 0.1);
+  EXPECT_DOUBLE_EQ(box.YLength(), 2.1);
+  EXPECT_DOUBLE_EQ(box.ZLength(), 0.0);
+}
+
+/////////////////////////////////////////////////
+TEST(OrientedBoxTest, OperatorEqual)
+{
+  OrientedBoxd box = OrientedBoxd(Vector3d(1, 1, 1));
+  OrientedBoxd box2 = OrientedBoxd(Vector3d(1, 1, 1),
+                                     Pose3d(1, 2, 3, 4, 5, 6));
+  OrientedBoxd box3 = OrientedBoxd(Vector3d(0, 0, 0),
+                                     Pose3d(1, 2, 3, 4, 5, 6));
+  EXPECT_TRUE(box == OrientedBoxd(Vector3d(1, 1, 1)));
+  EXPECT_FALSE(box == box2);
+  EXPECT_FALSE(box3 == box);
+}
+
+/////////////////////////////////////////////////
+TEST(OrientedBoxTest, ContainsZeroBox)
+{
+  OrientedBoxd box;
+
+  EXPECT_TRUE(box.Contains(Vector3d(0, 0, 0)));
+  EXPECT_FALSE(box.Contains(Vector3d(0, 0, 0.0001)));
+}
+
+/////////////////////////////////////////////////
+TEST(OrientedBoxTest, ContainsZeroPose)
+{
+  OrientedBoxd box(Vector3d(1, 2, 3));
+
+  // Vertices
+  EXPECT_TRUE(box.Contains(Vector3d(-0.5, -1.0, -1.5)));
+  EXPECT_TRUE(box.Contains(Vector3d(-0.5, -1.0, +1.5)));
+  EXPECT_TRUE(box.Contains(Vector3d(-0.5, +1.0, -1.5)));
+  EXPECT_TRUE(box.Contains(Vector3d(-0.5, +1.0, +1.5)));
+
+  EXPECT_TRUE(box.Contains(Vector3d(+0.5, -1.0, -1.5)));
+  EXPECT_TRUE(box.Contains(Vector3d(+0.5, -1.0, +1.5)));
+  EXPECT_TRUE(box.Contains(Vector3d(+0.5, +1.0, -1.5)));
+  EXPECT_TRUE(box.Contains(Vector3d(+0.5, +1.0, +1.5)));
+
+  // Edges
+  EXPECT_TRUE(box.Contains(Vector3d(0.0, -1.0, -1.5)));
+  EXPECT_TRUE(box.Contains(Vector3d(0.0, -1.0, +1.5)));
+  EXPECT_TRUE(box.Contains(Vector3d(0.0, +1.0, -1.5)));
+  EXPECT_TRUE(box.Contains(Vector3d(0.0, +1.0, +1.5)));
+
+  EXPECT_TRUE(box.Contains(Vector3d(-0.5, -1.0, 0.0)));
+  EXPECT_TRUE(box.Contains(Vector3d(-0.5, +1.0, 0.0)));
+  EXPECT_TRUE(box.Contains(Vector3d(+0.5, -1.0, 0.0)));
+  EXPECT_TRUE(box.Contains(Vector3d(+0.5, +1.0, 0.0)));
+
+  EXPECT_TRUE(box.Contains(Vector3d(-0.5, 0.0, -1.5)));
+  EXPECT_TRUE(box.Contains(Vector3d(-0.5, 0.0, +1.5)));
+  EXPECT_TRUE(box.Contains(Vector3d(+0.5, 0.0, -1.5)));
+  EXPECT_TRUE(box.Contains(Vector3d(+0.5, 0.0, +1.5)));
+
+  // Inside
+  EXPECT_TRUE(box.Contains(Vector3d(-0.5+g_tolerance,
+                                    -1.0+g_tolerance,
+                                    -1.5+g_tolerance)));
+  EXPECT_TRUE(box.Contains(Vector3d(-0.5+g_tolerance,
+                                    -1.0+g_tolerance,
+                                    +1.5-g_tolerance)));
+  EXPECT_TRUE(box.Contains(Vector3d(-0.5+g_tolerance,
+                                    +1.0-g_tolerance,
+                                    -1.5+g_tolerance)));
+  EXPECT_TRUE(box.Contains(Vector3d(-0.5+g_tolerance,
+                                    +1.0-g_tolerance,
+                                    +1.5-g_tolerance)));
+
+  EXPECT_TRUE(box.Contains(Vector3d(+0.5-g_tolerance,
+                                    -1.0+g_tolerance,
+                                    -1.5+g_tolerance)));
+  EXPECT_TRUE(box.Contains(Vector3d(+0.5-g_tolerance,
+                                    -1.0+g_tolerance,
+                                    +1.5-g_tolerance)));
+  EXPECT_TRUE(box.Contains(Vector3d(+0.5-g_tolerance,
+                                    +1.0-g_tolerance,
+                                    -1.5+g_tolerance)));
+  EXPECT_TRUE(box.Contains(Vector3d(+0.5-g_tolerance,
+                                    +1.0-g_tolerance,
+                                    +1.5-g_tolerance)));
+
+  // Outside
+  EXPECT_FALSE(box.Contains(Vector3d(-0.5-g_tolerance,
+                                    -1.0-g_tolerance,
+                                    -1.5-g_tolerance)));
+  EXPECT_FALSE(box.Contains(Vector3d(-0.5-g_tolerance,
+                                    -1.0-g_tolerance,
+                                    +1.5+g_tolerance)));
+  EXPECT_FALSE(box.Contains(Vector3d(-0.5-g_tolerance,
+                                    +1.0+g_tolerance,
+                                    -1.5-g_tolerance)));
+  EXPECT_FALSE(box.Contains(Vector3d(-0.5-g_tolerance,
+                                    +1.0+g_tolerance,
+                                    +1.5+g_tolerance)));
+
+  EXPECT_FALSE(box.Contains(Vector3d(+0.5-g_tolerance,
+                                    -1.0-g_tolerance,
+                                    -1.5-g_tolerance)));
+  EXPECT_FALSE(box.Contains(Vector3d(+0.5-g_tolerance,
+                                    -1.0-g_tolerance,
+                                    +1.5+g_tolerance)));
+  EXPECT_FALSE(box.Contains(Vector3d(+0.5-g_tolerance,
+                                    +1.0+g_tolerance,
+                                    -1.5-g_tolerance)));
+  EXPECT_FALSE(box.Contains(Vector3d(+0.5-g_tolerance,
+                                    +1.0+g_tolerance,
+                                    +1.5+g_tolerance)));
+}
+
+/////////////////////////////////////////////////
+TEST(OrientedBoxTest, ContainsOrientedPosition)
+{
+  OrientedBoxd box(Vector3d(1, 2, 3),
+                    Pose3d(10, 20, 30, 0, 0, 0));
+
+  // Vertices
+  EXPECT_TRUE(box.Contains(Vector3d(10-0.5, 20-1.0, 30-1.5)));
+  EXPECT_TRUE(box.Contains(Vector3d(10-0.5, 20-1.0, 30+1.5)));
+  EXPECT_TRUE(box.Contains(Vector3d(10-0.5, 20+1.0, 30-1.5)));
+  EXPECT_TRUE(box.Contains(Vector3d(10-0.5, 20+1.0, 30+1.5)));
+
+  EXPECT_TRUE(box.Contains(Vector3d(10+0.5, 20-1.0, 30-1.5)));
+  EXPECT_TRUE(box.Contains(Vector3d(10+0.5, 20-1.0, 30+1.5)));
+  EXPECT_TRUE(box.Contains(Vector3d(10+0.5, 20+1.0, 30-1.5)));
+  EXPECT_TRUE(box.Contains(Vector3d(10+0.5, 20+1.0, 30+1.5)));
+
+  // Edges
+  EXPECT_TRUE(box.Contains(Vector3d(10.0, 20-1.0, 30-1.5)));
+  EXPECT_TRUE(box.Contains(Vector3d(10.0, 20-1.0, 30+1.5)));
+  EXPECT_TRUE(box.Contains(Vector3d(10.0, 20+1.0, 30-1.5)));
+  EXPECT_TRUE(box.Contains(Vector3d(10.0, 20+1.0, 30+1.5)));
+
+  EXPECT_TRUE(box.Contains(Vector3d(10-0.5, 20-1.0, 30.0)));
+  EXPECT_TRUE(box.Contains(Vector3d(10-0.5, 20+1.0, 30.0)));
+  EXPECT_TRUE(box.Contains(Vector3d(10+0.5, 20-1.0, 30.0)));
+  EXPECT_TRUE(box.Contains(Vector3d(10+0.5, 20+1.0, 30.0)));
+
+  EXPECT_TRUE(box.Contains(Vector3d(10-0.5, 20.0, 30-1.5)));
+  EXPECT_TRUE(box.Contains(Vector3d(10-0.5, 20.0, 30+1.5)));
+  EXPECT_TRUE(box.Contains(Vector3d(10+0.5, 20.0, 30-1.5)));
+  EXPECT_TRUE(box.Contains(Vector3d(10+0.5, 20.0, 30+1.5)));
+
+  // Inside
+  EXPECT_TRUE(box.Contains(Vector3d(10, 20, 30)));
+  EXPECT_TRUE(box.Contains(Vector3d(10-0.25, 20-0.5, 30-0.75)));
+  EXPECT_TRUE(box.Contains(Vector3d(10+0.25, 20+0.5, 30+0.75)));
+
+  // Outside
+  EXPECT_FALSE(box.Contains(Vector3d(10-1.0, 20-1.0, 30-1.5)));
+  EXPECT_FALSE(box.Contains(Vector3d(10-0.5, 20-2.0, 30-1.5)));
+  EXPECT_FALSE(box.Contains(Vector3d(10-0.5, 20-1.0, 30-2.0)));
+
+  EXPECT_FALSE(box.Contains(Vector3d(10+1.0, 20+1.0, 30+1.5)));
+  EXPECT_FALSE(box.Contains(Vector3d(10+0.5, 20+2.0, 30+1.5)));
+  EXPECT_FALSE(box.Contains(Vector3d(10+0.5, 20+1.0, 30+2.0)));
+}
+
+/////////////////////////////////////////////////
+TEST(OrientedBoxTest, ContainsOrientedRotation)
+{
+  // Rotate PI/2 about +x: swap Z and Y
+  OrientedBoxd box(Vector3d(1, 2, 3), Pose3d(0, 0, 0, IGN_PI*0.5, 0, 0));
+
+  // Doesn't contain non-rotated vertices
+  EXPECT_FALSE(box.Contains(Vector3d(-0.5, -1.0, -1.5)));
+  EXPECT_FALSE(box.Contains(Vector3d(-0.5, -1.0, +1.5)));
+  EXPECT_FALSE(box.Contains(Vector3d(-0.5, +1.0, -1.5)));
+  EXPECT_FALSE(box.Contains(Vector3d(-0.5, +1.0, +1.5)));
+
+  EXPECT_FALSE(box.Contains(Vector3d(+0.5, -1.0, -1.5)));
+  EXPECT_FALSE(box.Contains(Vector3d(+0.5, -1.0, +1.5)));
+  EXPECT_FALSE(box.Contains(Vector3d(+0.5, +1.0, -1.5)));
+  EXPECT_FALSE(box.Contains(Vector3d(+0.5, +1.0, +1.5)));
+
+  // Inside
+  EXPECT_TRUE(box.Contains(Vector3d(-0.5+g_tolerance,
+                                    -1.5+g_tolerance,
+                                    -1.0+g_tolerance)));
+  EXPECT_TRUE(box.Contains(Vector3d(-0.5+g_tolerance,
+                                    -1.5+g_tolerance,
+                                    +1.0-g_tolerance)));
+  EXPECT_TRUE(box.Contains(Vector3d(-0.5+g_tolerance,
+                                    +1.5-g_tolerance,
+                                    -1.0+g_tolerance)));
+  EXPECT_TRUE(box.Contains(Vector3d(-0.5+g_tolerance,
+                                    +1.5-g_tolerance,
+                                    +1.0-g_tolerance)));
+
+  EXPECT_TRUE(box.Contains(Vector3d(+0.5-g_tolerance,
+                                    -1.5+g_tolerance,
+                                    -1.0+g_tolerance)));
+  EXPECT_TRUE(box.Contains(Vector3d(+0.5-g_tolerance,
+                                    -1.5+g_tolerance,
+                                    +1.0-g_tolerance)));
+  EXPECT_TRUE(box.Contains(Vector3d(+0.5-g_tolerance,
+                                    +1.5-g_tolerance, -1.0+g_tolerance)));
+  EXPECT_TRUE(box.Contains(Vector3d(+0.5-g_tolerance,
+                                    +1.5-g_tolerance,
+                                    +1.0-g_tolerance)));
+
+  // Outside
+  EXPECT_FALSE(box.Contains(Vector3d(-0.5-g_tolerance,
+                                     -1.5-g_tolerance,
+                                     -1.0-g_tolerance)));
+  EXPECT_FALSE(box.Contains(Vector3d(-0.5-g_tolerance,
+                                     -1.5-g_tolerance,
+                                     +1.0+g_tolerance)));
+  EXPECT_FALSE(box.Contains(Vector3d(-0.5-g_tolerance,
+                                     +1.5+g_tolerance,
+                                     -1.0-g_tolerance)));
+  EXPECT_FALSE(box.Contains(Vector3d(-0.5-g_tolerance,
+                                     +1.5+g_tolerance,
+                                     +1.0+g_tolerance)));
+
+  EXPECT_FALSE(box.Contains(Vector3d(+0.5-g_tolerance,
+                                     -1.5-g_tolerance,
+                                     -1.0-g_tolerance)));
+  EXPECT_FALSE(box.Contains(Vector3d(+0.5-g_tolerance,
+                                     -1.5-g_tolerance,
+                                     +1.0+g_tolerance)));
+  EXPECT_FALSE(box.Contains(Vector3d(+0.5-g_tolerance,
+                                     +1.5+g_tolerance,
+                                     -1.0-g_tolerance)));
+  EXPECT_FALSE(box.Contains(Vector3d(+0.5-g_tolerance,
+                                     +1.5+g_tolerance,
+                                     +1.0+g_tolerance)));
+}
+
+/////////////////////////////////////////////////
+TEST(OrientedBoxTest, OperatorStreamOut)
+{
+  OrientedBoxd b(Vector3d(0.1, 1.2, 2.3),
+                  Pose3d(3.4, 4.5, 5.6, 0.0, -0.1, 0.2));
+  std::ostringstream stream;
+  stream << b;
+  EXPECT_EQ(stream.str(), "Size[0.1 1.2 2.3] Pose[3.4 4.5 5.6 0 -0.1 0.2]");
+}
+
diff --git a/src/PID.cc b/src/PID.cc
new file mode 100644
index 0000000..c1fad87
--- /dev/null
+++ b/src/PID.cc
@@ -0,0 +1,243 @@
+/*
+ * Copyright (C) 2016 Open Source Robotics Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+*/
+
+#include <chrono>
+#include <cmath>
+#include "ignition/math/Helpers.hh"
+#include "ignition/math/PID.hh"
+
+using namespace ignition;
+using namespace math;
+
+/////////////////////////////////////////////////
+PID::PID(const double _p, const double _i, const double _d,
+         const double _imax, const double _imin, const double _cmdMax,
+         const double _cmdMin, const double _cmdOffset)
+: pGain(_p), iGain(_i), dGain(_d), iMax(_imax), iMin(_imin),
+  cmdMax(_cmdMax), cmdMin(_cmdMin), cmdOffset(_cmdOffset)
+{
+  this->Reset();
+}
+
+/////////////////////////////////////////////////
+void PID::Init(const double _p, const double _i, const double _d,
+               const double _imax, const double _imin, const double _cmdMax,
+               const double _cmdMin, const double _cmdOffset)
+{
+  this->pGain = _p;
+  this->iGain = _i;
+  this->dGain = _d;
+  this->iMax = _imax;
+  this->iMin = _imin;
+  this->cmdMax = _cmdMax;
+  this->cmdMin = _cmdMin;
+  this->cmdOffset = _cmdOffset;
+
+  this->Reset();
+}
+
+/////////////////////////////////////////////////
+PID &PID::operator=(const PID &_p)
+{
+  if (this == &_p)
+    return *this;
+
+  this->pGain = _p.pGain;
+  this->iGain = _p.iGain;
+  this->dGain = _p.dGain;
+  this->iMax = _p.iMax;
+  this->iMin = _p.iMin;
+  this->cmdMax = _p.cmdMax;
+  this->cmdMin = _p.cmdMin;
+  this->cmdOffset = _p.cmdOffset;
+  this->pErrLast = _p.pErrLast;
+  this->pErr = _p.pErr;
+  this->iErr = _p.iErr;
+  this->dErr = _p.dErr;
+  this->cmd = _p.cmd;
+
+  return *this;
+}
+
+/////////////////////////////////////////////////
+void PID::SetPGain(const double _p)
+{
+  this->pGain = _p;
+}
+
+/////////////////////////////////////////////////
+void PID::SetIGain(const double _i)
+{
+  this->iGain = _i;
+}
+
+/////////////////////////////////////////////////
+void PID::SetDGain(const double _d)
+{
+  this->dGain = _d;
+}
+
+/////////////////////////////////////////////////
+void PID::SetIMax(const double _i)
+{
+  this->iMax = _i;
+}
+
+/////////////////////////////////////////////////
+void PID::SetIMin(const double _i)
+{
+  this->iMin = _i;
+}
+
+/////////////////////////////////////////////////
+void PID::SetCmdMax(const double _c)
+{
+  this->cmdMax = _c;
+}
+
+/////////////////////////////////////////////////
+void PID::SetCmdMin(const double _c)
+{
+  this->cmdMin = _c;
+}
+
+/////////////////////////////////////////////////
+void PID::SetCmdOffset(const double _c)
+{
+  this->cmdOffset = _c;
+}
+
+/////////////////////////////////////////////////
+void PID::Reset()
+{
+  this->pErrLast = 0.0;
+  this->pErr = 0.0;
+  this->iErr = 0.0;
+  this->dErr = 0.0;
+  this->cmd = 0.0;
+}
+
+/////////////////////////////////////////////////
+double PID::Update(const double _error,
+                   const std::chrono::duration<double> &_dt)
+{
+  if (_dt == std::chrono::duration<double>(0) ||
+      ignition::math::isnan(_error) || std::isinf(_error))
+  {
+    return 0.0;
+  }
+
+  double pTerm, dTerm;
+  this->pErr = _error;
+
+  // Calculate proportional contribution to command
+  pTerm = this->pGain * this->pErr;
+
+  // Calculate the integral error
+  this->iErr = this->iErr + this->iGain * _dt.count() * this->pErr;
+
+  // Check the integral limits
+  // If enabled, this will limit iErr so that the limit is meaningful
+  // in the output
+  if (this->iMax >= this->iMin)
+    this->iErr = clamp(this->iErr, this->iMin, this->iMax);
+
+  // Calculate the derivative error
+  if (_dt != std::chrono::duration<double>(0))
+  {
+    this->dErr = (this->pErr - this->pErrLast) / _dt.count();
+    this->pErrLast = this->pErr;
+  }
+
+  // Calculate derivative contribution to command
+  dTerm = this->dGain * this->dErr;
+  this->cmd = this->cmdOffset -pTerm - this->iErr - dTerm;
+
+  // Check the command limits
+  if (this->cmdMax >= this->cmdMin)
+    this->cmd = clamp(this->cmd, this->cmdMin, this->cmdMax);
+
+  return this->cmd;
+}
+
+/////////////////////////////////////////////////
+void PID::SetCmd(const double _cmd)
+{
+  this->cmd = _cmd;
+}
+
+/////////////////////////////////////////////////
+double PID::Cmd() const
+{
+  return this->cmd;
+}
+
+/////////////////////////////////////////////////
+void PID::Errors(double &_pe, double &_ie, double &_de) const
+{
+  _pe = this->pErr;
+  _ie = this->iErr;
+  _de = this->dErr;
+}
+
+/////////////////////////////////////////////////
+double PID::PGain() const
+{
+  return this->pGain;
+}
+
+/////////////////////////////////////////////////
+double PID::IGain() const
+{
+  return this->iGain;
+}
+
+/////////////////////////////////////////////////
+double PID::DGain() const
+{
+  return this->dGain;
+}
+
+/////////////////////////////////////////////////
+double PID::IMax() const
+{
+  return this->iMax;
+}
+
+/////////////////////////////////////////////////
+double PID::IMin() const
+{
+  return this->iMin;
+}
+
+/////////////////////////////////////////////////
+double PID::CmdMax() const
+{
+  return this->cmdMax;
+}
+
+/////////////////////////////////////////////////
+double PID::CmdMin() const
+{
+  return this->cmdMin;
+}
+
+/////////////////////////////////////////////////
+double PID::CmdOffset() const
+{
+  return this->cmdOffset;
+}
diff --git a/src/PID_TEST.cc b/src/PID_TEST.cc
new file mode 100644
index 0000000..1a01583
--- /dev/null
+++ b/src/PID_TEST.cc
@@ -0,0 +1,402 @@
+/*
+ * Copyright (C) 2016 Open Source Robotics Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+*/
+
+#include <gtest/gtest.h>
+
+#include "ignition/math/PID.hh"
+#include "ignition/math/Helpers.hh"
+
+using namespace ignition;
+
+/////////////////////////////////////////////////
+TEST(PidTest, ConstructorDefault)
+{
+  const math::PID pid;
+  EXPECT_DOUBLE_EQ(0.0, pid.PGain());
+  EXPECT_DOUBLE_EQ(0.0, pid.IGain());
+  EXPECT_DOUBLE_EQ(0.0, pid.DGain());
+  EXPECT_DOUBLE_EQ(-1.0, pid.IMax());
+  EXPECT_DOUBLE_EQ(0.0, pid.IMin());
+  EXPECT_DOUBLE_EQ(-1.0, pid.CmdMax());
+  EXPECT_DOUBLE_EQ(0.0, pid.CmdMin());
+  EXPECT_DOUBLE_EQ(0.0, pid.CmdOffset());
+  EXPECT_DOUBLE_EQ(0.0, pid.Cmd());
+
+  double pe, ie, de;
+  pid.Errors(pe, ie, de);
+  EXPECT_DOUBLE_EQ(pe, 0.0);
+  EXPECT_DOUBLE_EQ(ie, 0.0);
+  EXPECT_DOUBLE_EQ(de, 0.0);
+}
+
+/////////////////////////////////////////////////
+TEST(PidTest, CoverageExtra)
+{
+  // getting full destructor coverage
+  math::PID *p = new math::PID;
+  EXPECT_TRUE(p != NULL);
+  delete p;
+}
+
+/////////////////////////////////////////////////
+TEST(PidTest, SetValues)
+{
+  const math::PID pid2(1.0, 2.1, -4.5, 10.5, 1.4, 45, -35, 1.3);
+  EXPECT_DOUBLE_EQ(1.0,  pid2.PGain());
+  EXPECT_DOUBLE_EQ(2.1,  pid2.IGain());
+  EXPECT_DOUBLE_EQ(-4.5, pid2.DGain());
+  EXPECT_DOUBLE_EQ(10.5, pid2.IMax());
+  EXPECT_DOUBLE_EQ(1.4,  pid2.IMin());
+  EXPECT_DOUBLE_EQ(45,   pid2.CmdMax());
+  EXPECT_DOUBLE_EQ(-35,  pid2.CmdMin());
+  EXPECT_DOUBLE_EQ(1.3,  pid2.CmdOffset());
+  EXPECT_DOUBLE_EQ(0.0,  pid2.Cmd());
+
+  // Test Set*() functions
+  {
+    const double cmd = 10.4;
+    math::PID pid;
+    pid.SetPGain(pid2.PGain());
+    pid.SetIGain(pid2.IGain());
+    pid.SetDGain(pid2.DGain());
+    pid.SetIMax(pid2.IMax());
+    pid.SetIMin(pid2.IMin());
+    pid.SetCmdMax(pid2.CmdMax());
+    pid.SetCmdMin(pid2.CmdMin());
+    pid.SetCmdOffset(pid2.CmdOffset());
+    pid.SetCmd(cmd);
+
+    EXPECT_DOUBLE_EQ(pid.PGain(), pid2.PGain());
+    EXPECT_DOUBLE_EQ(pid.IGain(), pid2.IGain());
+    EXPECT_DOUBLE_EQ(pid.DGain(), pid2.DGain());
+    EXPECT_DOUBLE_EQ(pid.IMax(), pid2.IMax());
+    EXPECT_DOUBLE_EQ(pid.IMin(), pid2.IMin());
+    EXPECT_DOUBLE_EQ(pid.CmdMax(), pid2.CmdMax());
+    EXPECT_DOUBLE_EQ(pid.CmdMin(), pid2.CmdMin());
+    EXPECT_DOUBLE_EQ(pid.CmdOffset(), pid2.CmdOffset());
+    EXPECT_DOUBLE_EQ(pid.Cmd(), cmd);
+  }
+
+  // Assignment operator
+  {
+    math::PID pid;
+    pid = pid2;
+    EXPECT_DOUBLE_EQ(pid.PGain(), pid2.PGain());
+    EXPECT_DOUBLE_EQ(pid.IGain(), pid2.IGain());
+    EXPECT_DOUBLE_EQ(pid.DGain(), pid2.DGain());
+    EXPECT_DOUBLE_EQ(pid.IMax(), pid2.IMax());
+    EXPECT_DOUBLE_EQ(pid.IMin(), pid2.IMin());
+    EXPECT_DOUBLE_EQ(pid.CmdMax(), pid2.CmdMax());
+    EXPECT_DOUBLE_EQ(pid.CmdMin(), pid2.CmdMin());
+    EXPECT_DOUBLE_EQ(pid.CmdOffset(), pid2.CmdOffset());
+    EXPECT_DOUBLE_EQ(pid.Cmd(), pid2.Cmd());
+  }
+}
+
+/////////////////////////////////////////////////
+TEST(PidTest, EqualOperatorCornerCase)
+{
+  math::PID pid(1.0, 2.1, -4.5, 10.5, 1.4, 45, -35, 1.23);
+  EXPECT_DOUBLE_EQ(pid.PGain(), 1.0);
+  EXPECT_DOUBLE_EQ(pid.IGain(), 2.1);
+  EXPECT_DOUBLE_EQ(pid.DGain(), -4.5);
+  EXPECT_DOUBLE_EQ(pid.IMax(), 10.5);
+  EXPECT_DOUBLE_EQ(pid.IMin(), 1.4);
+  EXPECT_DOUBLE_EQ(pid.CmdMax(), 45.0);
+  EXPECT_DOUBLE_EQ(pid.CmdMin(), -35.0);
+  EXPECT_DOUBLE_EQ(pid.CmdOffset(), 1.23);
+  EXPECT_DOUBLE_EQ(pid.Cmd(), 0.0);
+
+  pid = pid;
+
+  EXPECT_DOUBLE_EQ(pid.PGain(), 1.0);
+  EXPECT_DOUBLE_EQ(pid.IGain(), 2.1);
+  EXPECT_DOUBLE_EQ(pid.DGain(), -4.5);
+  EXPECT_DOUBLE_EQ(pid.IMax(), 10.5);
+  EXPECT_DOUBLE_EQ(pid.IMin(), 1.4);
+  EXPECT_DOUBLE_EQ(pid.CmdMax(), 45.0);
+  EXPECT_DOUBLE_EQ(pid.CmdMin(), -35.0);
+  EXPECT_DOUBLE_EQ(pid.CmdOffset(), 1.23);
+  EXPECT_DOUBLE_EQ(pid.Cmd(), 0.0);
+}
+
+/////////////////////////////////////////////////
+TEST(PidTest, Update)
+{
+  math::PID pid;
+  pid.Init(1.0, 0.1, 0.5, 10, 0, 20, -20);
+
+  double result = pid.Update(5.0, std::chrono::duration<double>(0.0));
+  EXPECT_DOUBLE_EQ(result, 0.0);
+
+  result = pid.Update(5.0, std::chrono::duration<double>(10.0));
+  EXPECT_DOUBLE_EQ(result, -10.25);
+
+  double pe, ie, de;
+  pid.Errors(pe, ie, de);
+  EXPECT_DOUBLE_EQ(pe, 5);
+  EXPECT_DOUBLE_EQ(ie, 5);
+  EXPECT_DOUBLE_EQ(de, 0.5);
+
+  // Test max integral term
+  pid.SetIMax(0.2);
+  pid.SetIGain(10.0);
+  result = pid.Update(5.0, std::chrono::duration<double>(10.0));
+  EXPECT_DOUBLE_EQ(result, -5.2);
+  pid.Errors(pe, ie, de);
+  EXPECT_DOUBLE_EQ(pe, 5);
+  EXPECT_DOUBLE_EQ(ie, 0.2);
+  EXPECT_DOUBLE_EQ(de, 0.0);
+
+  // Test min integral term
+  pid.SetIMax(20);
+  pid.SetIMin(1.4);
+  pid.SetIGain(0.01);
+  result = pid.Update(5.0, std::chrono::duration<double>(10.0));
+  EXPECT_DOUBLE_EQ(result, -6.4);
+  pid.Errors(pe, ie, de);
+  EXPECT_DOUBLE_EQ(pe, 5);
+  EXPECT_DOUBLE_EQ(ie, 1.4);
+  EXPECT_DOUBLE_EQ(de, 0.0);
+}
+
+/////////////////////////////////////////////////
+/// \brief Helper function for testing PID::Update
+/// \param[in] _pid PID object.
+/// \param[in] _result Expected PID output.
+/// \param[in] _error Error input to Update.
+/// \param[in] _dt Time interval.
+/// \param[in] _pErr Expected proportional error.
+/// \param[in] _iErr Expected integral error.
+/// \param[in] _dErr Expected derivative error.
+void UpdateTest(math::PID &_pid, const double _result, const double _error,
+                const std::chrono::duration<double> &_dt,
+                const double _pErr, const double _iErr, const double _dErr)
+{
+  EXPECT_DOUBLE_EQ(_result, _pid.Update(_error, _dt));
+  double pErr, iErr, dErr;
+  _pid.Errors(pErr, iErr, dErr);
+  EXPECT_DOUBLE_EQ(pErr, _pErr);
+  EXPECT_DOUBLE_EQ(iErr, _iErr);
+  EXPECT_DOUBLE_EQ(dErr, _dErr);
+}
+
+/////////////////////////////////////////////////
+TEST(PidTest, ZeroGains)
+{
+  // controller with zero gains, no command limits
+  math::PID pid;
+
+  std::cerr << "zero inputs, expect zero outputs" << std::endl;
+  // repeat once to test derivative and integral error
+  UpdateTest(pid, 0, 0, std::chrono::duration<double>(0), 0, 0, 0);
+  UpdateTest(pid, 0, 0, std::chrono::duration<double>(0), 0, 0, 0);
+
+  std::cerr << "dt = 0, no change since previous state" << std::endl;
+  UpdateTest(pid, 0,  1, std::chrono::duration<double>(0), 0, 0, 0);
+  UpdateTest(pid, 0,  1, std::chrono::duration<double>(0), 0, 0, 0);
+  UpdateTest(pid, 0, -1, std::chrono::duration<double>(0), 0, 0, 0);
+  UpdateTest(pid, 0, -1, std::chrono::duration<double>(0), 0, 0, 0);
+  UpdateTest(pid, 0,  1, std::chrono::duration<double>(0), 0, 0, 0);
+  UpdateTest(pid, 0,  1, std::chrono::duration<double>(0), 0, 0, 0);
+
+  std::cerr << "dt > 0, but gains still zero" << std::endl;
+  UpdateTest(pid, 0,  1, std::chrono::duration<double>(1),  1, 0, 1);
+  UpdateTest(pid, 0,  1, std::chrono::duration<double>(1),  1, 0, 0);
+  UpdateTest(pid, 0, -1, std::chrono::duration<double>(1), -1, 0, -2);
+  UpdateTest(pid, 0, -1, std::chrono::duration<double>(1), -1, 0, 0);
+  UpdateTest(pid, 0,  1, std::chrono::duration<double>(1),  1, 0, 2);
+  UpdateTest(pid, 0,  1, std::chrono::duration<double>(1),  1, 0, 0);
+
+  std::cerr << "dt = 0, no change since previous state" << std::endl;
+  UpdateTest(pid, 0,  1, std::chrono::duration<double>(0), 1, 0, 0);
+  UpdateTest(pid, 0,  1, std::chrono::duration<double>(0), 1, 0, 0);
+  UpdateTest(pid, 0, -1, std::chrono::duration<double>(0), 1, 0, 0);
+  UpdateTest(pid, 0, -1, std::chrono::duration<double>(0), 1, 0, 0);
+  UpdateTest(pid, 0,  1, std::chrono::duration<double>(0), 1, 0, 0);
+  UpdateTest(pid, 0,  1, std::chrono::duration<double>(0), 1, 0, 0);
+
+  std::cerr << "dt < 0, but gains still zero" << std::endl;
+  UpdateTest(pid, 0,  1, std::chrono::duration<double>(-1),  1, 0, 0);
+  UpdateTest(pid, 0,  1, std::chrono::duration<double>(-1),  1, 0, 0);
+  UpdateTest(pid, 0, -1, std::chrono::duration<double>(-1), -1, 0, 2);
+  UpdateTest(pid, 0, -1, std::chrono::duration<double>(-1), -1, 0, 0);
+  UpdateTest(pid, 0,  1, std::chrono::duration<double>(-1),  1, 0, -2);
+  UpdateTest(pid, 0,  1, std::chrono::duration<double>(-1),  1, 0, 0);
+
+  std::cerr << "Reset" << std::endl;
+  pid.Reset();
+  UpdateTest(pid, 0,  1, std::chrono::duration<double>(0), 0, 0, 0);
+
+  std::cerr << "unclamp Cmd values" << std::endl;
+  // CmdMax defaults to -1.0
+  // setting CmdMin to -10.0, means output should now be -1.0
+  // when time is non-zero
+  pid.SetCmdMin(-10.0);
+  EXPECT_DOUBLE_EQ(-10.0, pid.CmdMin());
+  // command hasn't been updated yet
+  EXPECT_DOUBLE_EQ(0.0, pid.Cmd());
+
+  std::cerr << "dt = 0, still report cmd = 0" << std::endl;
+  UpdateTest(pid, 0,  1, std::chrono::duration<double>(0), 0, 0, 0);
+  UpdateTest(pid, 0,  1, std::chrono::duration<double>(0), 0, 0, 0);
+  UpdateTest(pid, 0, -1, std::chrono::duration<double>(0), 0, 0, 0);
+  UpdateTest(pid, 0, -1, std::chrono::duration<double>(0), 0, 0, 0);
+  UpdateTest(pid, 0,  1, std::chrono::duration<double>(0), 0, 0, 0);
+  UpdateTest(pid, 0,  1, std::chrono::duration<double>(0), 0, 0, 0);
+
+  std::cerr << "dt > 0, report clamped value" << std::endl;
+  UpdateTest(pid, -1,  1, std::chrono::duration<double>(1),  1, 0, 1);
+  UpdateTest(pid, -1,  1, std::chrono::duration<double>(1),  1, 0, 0);
+  UpdateTest(pid, -1, -1, std::chrono::duration<double>(1), -1, 0, -2);
+  UpdateTest(pid, -1, -1, std::chrono::duration<double>(1), -1, 0, 0);
+  UpdateTest(pid, -1,  1, std::chrono::duration<double>(1),  1, 0, 2);
+  UpdateTest(pid, -1,  1, std::chrono::duration<double>(1),  1, 0, 0);
+
+  std::cerr << "Reset" << std::endl;
+  pid.Reset();
+  UpdateTest(pid, 0,  1, std::chrono::duration<double>(0), 0, 0, 0);
+
+  std::cerr << "unclamp iErr values" << std::endl;
+  // IMax defaults to -1.0
+  // setting IMin to -10.0, means output should now be -1.0
+  // when time is non-zero
+  pid.SetIMin(-10.0);
+  EXPECT_DOUBLE_EQ(-10.0, pid.IMin());
+  // iErr hasn't been updated yet
+  {
+    double pErr, iErr, dErr;
+    pid.Errors(pErr, iErr, dErr);
+    EXPECT_DOUBLE_EQ(0.0, iErr);
+  }
+
+  std::cerr << "dt = 0, still report iErr = 0" << std::endl;
+  UpdateTest(pid, 0,  1, std::chrono::duration<double>(0), 0, 0, 0);
+  UpdateTest(pid, 0,  1, std::chrono::duration<double>(0), 0, 0, 0);
+  UpdateTest(pid, 0, -1, std::chrono::duration<double>(0), 0, 0, 0);
+  UpdateTest(pid, 0, -1, std::chrono::duration<double>(0), 0, 0, 0);
+  UpdateTest(pid, 0,  1, std::chrono::duration<double>(0), 0, 0, 0);
+  UpdateTest(pid, 0,  1, std::chrono::duration<double>(0), 0, 0, 0);
+
+  std::cerr << "dt > 0, report clamped value" << std::endl;
+  UpdateTest(pid, -1,  1, std::chrono::duration<double>(1),  1, -1, 1);
+  UpdateTest(pid, -1,  1, std::chrono::duration<double>(1),  1, -1, 0);
+  UpdateTest(pid, -1, -1, std::chrono::duration<double>(1), -1, -1, -2);
+  UpdateTest(pid, -1, -1, std::chrono::duration<double>(1), -1, -1, 0);
+  UpdateTest(pid, -1,  1, std::chrono::duration<double>(1),  1, -1, 2);
+  UpdateTest(pid, -1,  1, std::chrono::duration<double>(1),  1, -1, 0);
+
+  std::cerr << "Reset" << std::endl;
+  pid.Reset();
+  UpdateTest(pid, 0,  1, std::chrono::duration<double>(0), 0, 0, 0);
+
+  std::cerr << "set Cmd Offset" << std::endl;
+  pid.SetCmdOffset(-20.0);
+  EXPECT_DOUBLE_EQ(-20.0, pid.CmdOffset());
+  // Cmd hasn't been updated yet
+  EXPECT_DOUBLE_EQ(0.0, pid.Cmd());
+
+  std::cerr << "dt = 0, still return 0" << std::endl;
+  UpdateTest(pid, 0,  1, std::chrono::duration<double>(0), 0, 0, 0);
+  UpdateTest(pid, 0,  1, std::chrono::duration<double>(0), 0, 0, 0);
+  UpdateTest(pid, 0, -1, std::chrono::duration<double>(0), 0, 0, 0);
+  UpdateTest(pid, 0, -1, std::chrono::duration<double>(0), 0, 0, 0);
+  UpdateTest(pid, 0,  1, std::chrono::duration<double>(0), 0, 0, 0);
+  UpdateTest(pid, 0,  1, std::chrono::duration<double>(0), 0, 0, 0);
+
+  std::cerr << "dt > 0, report negative min value" << std::endl;
+  UpdateTest(pid, -10,  1, std::chrono::duration<double>(1),  1, -1, 1);
+  UpdateTest(pid, -10,  1, std::chrono::duration<double>(1),  1, -1, 0);
+  UpdateTest(pid, -10, -1, std::chrono::duration<double>(1), -1, -1, -2);
+  UpdateTest(pid, -10, -1, std::chrono::duration<double>(1), -1, -1, 0);
+  UpdateTest(pid, -10,  1, std::chrono::duration<double>(1),  1, -1, 2);
+  UpdateTest(pid, -10,  1, std::chrono::duration<double>(1),  1, -1, 0);
+}
+
+/////////////////////////////////////////////////
+TEST(PidTest, Pcontrol)
+{
+  math::PID pid(1);
+  std::chrono::duration<double> dt(1);
+  const int N = 5;
+  for (int i = 0; i < N; ++i)
+  {
+    double d = static_cast<double>(i);
+    EXPECT_DOUBLE_EQ(-d, pid.Update(d, std::chrono::duration<double>(1)));
+  }
+
+  pid.SetPGain(2);
+  for (int i = 0; i < N; ++i)
+  {
+    double d = static_cast<double>(i);
+    EXPECT_DOUBLE_EQ(-2*d, pid.Update(d, std::chrono::duration<double>(1)));
+  }
+}
+
+/////////////////////////////////////////////////
+TEST(PidTest, Icontrol)
+{
+  math::PID pid(0, 1);
+  std::chrono::duration<double> dt(1);
+  const int N = 5;
+  for (int i = 0; i < N; ++i)
+  {
+    double d = static_cast<double>(i+1);
+    EXPECT_DOUBLE_EQ(-d, pid.Update(1, std::chrono::duration<double>(1)));
+  }
+
+  pid.SetIGain(2);
+  double I0;
+  {
+    double pErr, iErr, dErr;
+    pid.Errors(pErr, iErr, dErr);
+    EXPECT_DOUBLE_EQ(N, iErr);
+    I0 = iErr;
+  }
+
+  // confirm that changing gain doesn't cause jumps in integral control
+  EXPECT_DOUBLE_EQ(-I0, pid.Update(0, std::chrono::duration<double>(1)));
+  EXPECT_DOUBLE_EQ(-I0, pid.Update(0, std::chrono::duration<double>(1)));
+
+  for (int i = 0; i < N; ++i)
+  {
+    double d = static_cast<double>(i+1);
+    EXPECT_DOUBLE_EQ(-I0-2*d, pid.Update(1, std::chrono::duration<double>(1)));
+  }
+}
+
+/////////////////////////////////////////////////
+TEST(PidTest, Dcontrol)
+{
+  math::PID pid(0, 0, 1);
+  std::chrono::duration<double> dt(1);
+  EXPECT_DOUBLE_EQ(1, pid.Update(-1, std::chrono::duration<double>(1)));
+  const int N = 5;
+  for (int i = 0; i < N; ++i)
+  {
+    double d = static_cast<double>(i);
+    EXPECT_DOUBLE_EQ(-1, pid.Update(d, std::chrono::duration<double>(1)));
+  }
+
+  pid.SetDGain(2);
+  EXPECT_DOUBLE_EQ(10, pid.Update(-1, std::chrono::duration<double>(1)));
+  for (int i = 0; i < N; ++i)
+  {
+    double d = static_cast<double>(i);
+    EXPECT_DOUBLE_EQ(-2, pid.Update(d, std::chrono::duration<double>(1)));
+  }
+}
diff --git a/src/Plane_TEST.cc b/src/Plane_TEST.cc
new file mode 100644
index 0000000..c32eb3e
--- /dev/null
+++ b/src/Plane_TEST.cc
@@ -0,0 +1,147 @@
+/*
+ * Copyright (C) 2012 Open Source Robotics Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+*/
+
+#include <gtest/gtest.h>
+
+#include "ignition/math/Helpers.hh"
+#include "ignition/math/Plane.hh"
+
+using namespace ignition;
+using namespace math;
+
+/////////////////////////////////////////////////
+TEST(PlaneTest, PlaneConstructor)
+{
+  Planed plane(Vector3d(1, 0, 0), 0.1);
+  EXPECT_EQ(plane.Normal(), Vector3d(1, 0, 0));
+  EXPECT_NEAR(plane.Offset(), 0.1, 1e-6);
+}
+
+#ifdef _MSC_VER
+#pragma warning(push)
+// C4723: potential divide by 0
+#pragma warning(disable : 4723)
+#endif
+/////////////////////////////////////////////////
+TEST(PlaneTest, Distance)
+{
+  Planed plane(Vector3d(0, 0, 1), 0.1);
+  EXPECT_NEAR(plane.Distance(Vector3d(0, 0, 0),
+              Vector3d(0, 0, 1)), 0.1, 1e-6);
+
+  EXPECT_NEAR(plane.Distance(Vector3d(0, 0, 0.1),
+              Vector3d(0, 0, 1)), 0, 1e-6);
+
+  EXPECT_NEAR(plane.Distance(Vector3d(0, 0, 0.2),
+              Vector3d(0, 0, 1)), -0.1, 1e-6);
+  EXPECT_NEAR(plane.Distance(Vector3d(0, 0, 0.1),
+              Vector3d(1, 0, 0)), 0, 1e-6);
+}
+#ifdef _MSC_VER
+#pragma warning(pop)
+#endif
+
+/////////////////////////////////////////////////
+TEST(PlaneTest, Plane)
+{
+  {
+    Planed plane;
+    EXPECT_TRUE(equal(plane.Offset(), 0.0));
+    EXPECT_TRUE(plane.Normal() == Vector3d());
+    EXPECT_TRUE(plane.Size() == Vector2d(0, 0));
+  }
+
+  {
+    Planed plane(Vector3d(0, 0, 1), Vector2d(2, 3), 2.0);
+    EXPECT_TRUE(equal(plane.Offset(), 2.0));
+    EXPECT_TRUE(plane.Normal() == Vector3d(0, 0, 1));
+    EXPECT_TRUE(plane.Size() == Vector2d(2, 3));
+
+    EXPECT_DOUBLE_EQ(-1, plane.Distance(Vector3d(0, 0, 1),
+          Vector3d(0, 0, -1)));
+
+    plane.Set(Vector3d(1, 0, 0), Vector2d(1, 1), 1.0);
+    EXPECT_TRUE(equal(plane.Offset(), 1.0));
+    EXPECT_TRUE(plane.Normal() == Vector3d(1, 0, 0));
+    EXPECT_TRUE(plane.Size() == Vector2d(1, 1));
+
+    plane = Planed(Vector3d(0, 1, 0), Vector2d(4, 4), 5.0);
+    EXPECT_TRUE(equal(plane.Offset(), 5.0));
+    EXPECT_TRUE(plane.Normal() == Vector3d(0, 1, 0));
+    EXPECT_TRUE(plane.Size() == Vector2d(4, 4));
+  }
+}
+
+/////////////////////////////////////////////////
+TEST(PlaneTest, SidePoint)
+{
+  Planed plane(Vector3d(0, 0, 1), 1);
+
+  // On the negative side of the plane (below the plane)
+  Vector3d point(0, 0, 0);
+  EXPECT_EQ(plane.Side(point), Planed::NEGATIVE_SIDE);
+
+  // Still on the negative side of the plane (below the plane)
+  point.Set(1, 1, 0);
+  EXPECT_EQ(plane.Side(point), Planed::NEGATIVE_SIDE);
+
+  // Above the plane (positive side)
+  point.Set(1, 1, 2);
+  EXPECT_EQ(plane.Side(point), Planed::POSITIVE_SIDE);
+
+  // On the plane
+  point.Set(0, 0, 1);
+  EXPECT_EQ(plane.Side(point), Planed::NO_SIDE);
+
+  // Change the plane, but the point is still on the negative side
+  plane.Set(Vector3d(1, 0, 0), 4);
+  EXPECT_EQ(plane.Side(point), Planed::NEGATIVE_SIDE);
+
+  // Point is now on the positive side
+  point.Set(4.1, 0, 1);
+  EXPECT_EQ(plane.Side(point), Planed::POSITIVE_SIDE);
+}
+
+/////////////////////////////////////////////////
+TEST(PlaneTest, SideBox)
+{
+  Planed plane(Vector3d(0, 0, 1), 1);
+
+  // On the negative side of the plane (below the plane)
+  {
+    Box box(Vector3d(-.5, -.5, -.5), Vector3d(.5, .5, .5));
+    EXPECT_EQ(plane.Side(box), Planed::NEGATIVE_SIDE);
+  }
+
+  // Still on the negative side of the plane (below the plane)
+  {
+    Box box(Vector3d(-10, -10, -10), Vector3d(.9, .9, .9));
+    EXPECT_EQ(plane.Side(box), Planed::NEGATIVE_SIDE);
+  }
+
+  // Above the plane (positive side)
+  {
+    Box box(Vector3d(2, 2, 2), Vector3d(3, 3, 3));
+    EXPECT_EQ(plane.Side(box), Planed::POSITIVE_SIDE);
+  }
+
+  // On both sides the plane
+  {
+    Box box(Vector3d(0, 0, 0), Vector3d(3, 3, 3));
+    EXPECT_EQ(plane.Side(box), Planed::BOTH_SIDE);
+  }
+}
diff --git a/src/Pose_TEST.cc b/src/Pose_TEST.cc
new file mode 100644
index 0000000..cb38c86
--- /dev/null
+++ b/src/Pose_TEST.cc
@@ -0,0 +1,157 @@
+/*
+ * Copyright (C) 2012 Open Source Robotics Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+*/
+
+#include <gtest/gtest.h>
+
+#include "ignition/math/Helpers.hh"
+#include "ignition/math/Pose3.hh"
+
+using namespace ignition;
+
+/////////////////////////////////////////////////
+TEST(PoseTest, Pose)
+{
+  {
+    // test hypothesis that if
+    // A is the transform from O to P specified in frame O
+    // B is the transform from P to Q specified in frame P
+    // then, B + A is the transform from O to Q specified in frame O
+    math::Pose3d A(math::Vector3d(1, 0, 0),
+                   math::Quaterniond(0, 0, IGN_PI/4.0));
+    math::Pose3d B(math::Vector3d(1, 0, 0),
+                   math::Quaterniond(0, 0, IGN_PI/2.0));
+    EXPECT_TRUE(math::equal((B + A).Pos().X(), 1.0 + 1.0/sqrt(2)));
+    EXPECT_TRUE(math::equal((B + A).Pos().Y(),       1.0/sqrt(2)));
+    EXPECT_TRUE(math::equal((B + A).Pos().Z(),               0.0));
+    EXPECT_TRUE(math::equal((B + A).Rot().Euler().X(),  0.0));
+    EXPECT_TRUE(math::equal((B + A).Rot().Euler().Y(),  0.0));
+    EXPECT_TRUE(math::equal((B + A).Rot().Euler().Z(), 3.0*IGN_PI/4.0));
+  }
+  {
+    // If:
+    // A is the transform from O to P in frame O
+    // B is the transform from O to Q in frame O
+    // then -A is transform from P to O specified in frame P
+    math::Pose3d A(math::Vector3d(1, 0, 0),
+        math::Quaterniond(0, 0, IGN_PI/4.0));
+    EXPECT_TRUE(math::equal((math::Pose3d() - A).Pos().X(),      -1.0/sqrt(2)));
+    EXPECT_TRUE(math::equal((math::Pose3d() - A).Pos().Y(),       1.0/sqrt(2)));
+    EXPECT_TRUE(math::equal((math::Pose3d() - A).Pos().Z(),               0.0));
+    EXPECT_TRUE(math::equal((math::Pose3d() - A).Rot().Euler().X(),  0.0));
+    EXPECT_TRUE(math::equal((math::Pose3d() - A).Rot().Euler().Y(),  0.0));
+    EXPECT_TRUE(
+        math::equal((math::Pose3d() - A).Rot().Euler().Z(), -IGN_PI/4));
+
+    // test negation operator
+    EXPECT_TRUE(math::equal((-A).Pos().X(),      -1.0/sqrt(2)));
+    EXPECT_TRUE(math::equal((-A).Pos().Y(),       1.0/sqrt(2)));
+    EXPECT_TRUE(math::equal((-A).Pos().Z(),               0.0));
+    EXPECT_TRUE(math::equal((-A).Rot().Euler().X(),  0.0));
+    EXPECT_TRUE(math::equal((-A).Rot().Euler().Y(),  0.0));
+    EXPECT_TRUE(math::equal((-A).Rot().Euler().Z(), -IGN_PI/4.0));
+  }
+  {
+    // If:
+    // A is the transform from O to P in frame O
+    // B is the transform from O to Q in frame O
+    // B - A is the transform from P to Q in frame P
+    math::Pose3d A(math::Vector3d(1, 0, 0),
+        math::Quaterniond(0, 0, IGN_PI/4.0));
+    math::Pose3d B(math::Vector3d(1, 1, 0),
+        math::Quaterniond(0, 0, IGN_PI/2.0));
+    EXPECT_TRUE(math::equal((B - A).Pos().X(),       1.0/sqrt(2)));
+    EXPECT_TRUE(math::equal((B - A).Pos().Y(),       1.0/sqrt(2)));
+    EXPECT_TRUE(math::equal((B - A).Pos().Z(),               0.0));
+    EXPECT_TRUE(math::equal((B - A).Rot().Euler().X(),  0.0));
+    EXPECT_TRUE(math::equal((B - A).Rot().Euler().Y(),  0.0));
+    EXPECT_TRUE(math::equal((B - A).Rot().Euler().Z(), IGN_PI/4.0));
+  }
+  {
+    math::Pose3d pose;
+    EXPECT_TRUE(pose.Pos() == math::Vector3d(0, 0, 0));
+    EXPECT_TRUE(pose.Rot() == math::Quaterniond(0, 0, 0));
+  }
+
+  math::Pose3d pose(math::Vector3d(1, 2, 3), math::Quaterniond(.1, .2, .3));
+  EXPECT_TRUE(pose.Pos() == math::Vector3d(1, 2, 3));
+  EXPECT_TRUE(pose.Rot() == math::Quaterniond(.1, .2, .3));
+
+  math::Pose3d pose1(pose);
+  EXPECT_TRUE(pose1 == pose);
+
+  pose.Set(math::Vector3d(2, 3, 4), math::Quaterniond(.3, .4, .5));
+  EXPECT_TRUE(pose.Pos() == math::Vector3d(2, 3, 4));
+  EXPECT_TRUE(pose.Rot() == math::Quaterniond(.3, .4, .5));
+  EXPECT_TRUE(pose.IsFinite());
+
+  pose1 = pose.Inverse();
+  EXPECT_TRUE(pose1.Pos() == math::Vector3d(-1.38368, -3.05541, -4.21306));
+  EXPECT_TRUE(pose1.Rot() ==
+      math::Quaterniond(0.946281, -0.0933066, -0.226566, -0.210984));
+
+  pose = math::Pose3d(1, 2, 3, .1, .2, .3) + math::Pose3d(4, 5, 6, .4, .5, .6);
+  EXPECT_TRUE(pose ==
+      math::Pose3d(5.74534, 7.01053, 8.62899, 0.675732, 0.535753, 1.01174));
+
+  pose += pose;
+  EXPECT_TRUE(pose ==
+      math::Pose3d(11.314, 16.0487, 15.2559, 1.49463, 0.184295, 2.13932));
+
+  pose -= math::Pose3d(pose);
+  EXPECT_TRUE(pose ==
+      math::Pose3d(0, 0, 0, 0, 0, 0));
+
+  pose.Pos().Set(5, 6, 7);
+  pose.Rot().Euler(math::Vector3d(.4, .6, 0));
+
+  EXPECT_TRUE(pose.CoordPositionAdd(math::Vector3d(1, 2, 3)) ==
+      math::Vector3d(7.82531, 6.67387, 9.35871));
+
+  EXPECT_TRUE(pose.CoordPositionAdd(pose1) ==
+      math::Vector3d(2.58141, 2.4262, 3.8013));
+  EXPECT_TRUE(pose.CoordRotationAdd(math::Quaterniond(0.1, 0, 0.2)) ==
+      math::Quaterniond(0.520975, 0.596586, 0.268194));
+  EXPECT_TRUE(pose.CoordPoseSolve(pose1) ==
+      math::Pose3d(-0.130957, -11.552, -10.2329,
+                 -0.462955, -1.15624, -0.00158047));
+
+  EXPECT_TRUE(pose.RotatePositionAboutOrigin(math::Quaterniond(0.1, 0, 0.2)) ==
+      math::Pose3d(6.09235, 5.56147, 6.47714, 0.4, 0.6, 0));
+
+  pose.Reset();
+  EXPECT_TRUE(pose.Pos() == math::Vector3d(0, 0, 0));
+  EXPECT_TRUE(pose.Rot() == math::Quaterniond(0, 0, 0));
+}
+
+/////////////////////////////////////////////////
+TEST(PoseTest, ConstPose)
+{
+  const math::Pose3d pose(0, 1, 2, 0, 0, 0);
+
+  EXPECT_TRUE(pose.Pos() == math::Vector3d(0, 1, 2));
+  EXPECT_TRUE(pose.Rot() == math::Quaterniond(0, 0, 0));
+}
+
+/////////////////////////////////////////////////
+TEST(PoseTest, OperatorStreamOut)
+{
+  math::Pose3d p(0.1, 1.2, 2.3, 0.0, 0.1, 1.0);
+  std::ostringstream stream;
+  stream << p;
+  EXPECT_EQ(stream.str(), "0.1 1.2 2.3 0 0.1 1");
+}
+
diff --git a/src/Quaternion_TEST.cc b/src/Quaternion_TEST.cc
new file mode 100644
index 0000000..59a05d8
--- /dev/null
+++ b/src/Quaternion_TEST.cc
@@ -0,0 +1,568 @@
+/*
+ * Copyright (C) 2012 Open Source Robotics Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+*/
+
+#include <gtest/gtest.h>
+
+#include <cmath>
+
+#include "ignition/math/Helpers.hh"
+#include "ignition/math/Quaternion.hh"
+#include "ignition/math/Matrix3.hh"
+#include "ignition/math/Matrix4.hh"
+
+using namespace ignition;
+
+/////////////////////////////////////////////////
+TEST(QuaternionTest, Unit)
+{
+  math::Quaterniond q;
+  EXPECT_TRUE(math::equal(q.W(), 1.0));
+  EXPECT_TRUE(math::equal(q.X(), 0.0));
+  EXPECT_TRUE(math::equal(q.Y(), 0.0));
+  EXPECT_TRUE(math::equal(q.Z(), 0.0));
+}
+
+/////////////////////////////////////////////////
+TEST(QuaternionTest, ConstructWithValues)
+{
+  math::Quaterniond q(1, 2, 3, 4);
+  EXPECT_TRUE(math::equal(q.W(), 1.0));
+  EXPECT_TRUE(math::equal(q.X(), 2.0));
+  EXPECT_TRUE(math::equal(q.Y(), 3.0));
+  EXPECT_TRUE(math::equal(q.Z(), 4.0));
+}
+
+/////////////////////////////////////////////////
+TEST(QuaternionTest, ConstructZero)
+{
+  math::Quaterniond q(0, 0, 0, 0);
+  EXPECT_TRUE(math::equal(q.W(), 0.0));
+  EXPECT_TRUE(math::equal(q.X(), 0.0));
+  EXPECT_TRUE(math::equal(q.Y(), 0.0));
+  EXPECT_TRUE(math::equal(q.Z(), 0.0));
+
+  math::Quaterniond qI = q.Inverse();
+  EXPECT_TRUE(math::equal(qI.W(), 1.0));
+  EXPECT_TRUE(math::equal(qI.X(), 0.0));
+  EXPECT_TRUE(math::equal(qI.Y(), 0.0));
+  EXPECT_TRUE(math::equal(qI.Z(), 0.0));
+}
+
+/////////////////////////////////////////////////
+TEST(QuaternionTest, ConstructEuler)
+{
+  math::Quaterniond q(0, 1, 2);
+  EXPECT_TRUE(q == math::Quaterniond(math::Vector3d(0, 1, 2)));
+
+  // Make sure that singularities are being handled properly.
+  // There are an infinite number of equivalent Euler angle
+  // representations when pitch = PI/2, so rather than comparing Euler
+  // angles, we will compare quaternions.
+  for (double pitch : { -IGN_PI_2, IGN_PI_2 })
+  {
+    for (double roll = 0; roll < 2 * IGN_PI + 0.1; roll += IGN_PI_4)
+    {
+      for (double yaw = 0; yaw < 2 * IGN_PI + 0.1; yaw += IGN_PI_4)
+      {
+        math::Quaterniond q_orig(roll, pitch, yaw);
+        math::Quaterniond q_derived(q_orig.Euler());
+        EXPECT_TRUE(q_orig == q_derived || q_orig == -q_derived);
+      }
+    }
+  }
+}
+
+/////////////////////////////////////////////////
+TEST(QuaternionTest, ConstructAxisAngle)
+{
+  math::Quaterniond q1(math::Vector3d(0, 0, 1), IGN_PI);
+  EXPECT_TRUE(math::equal(q1.X(), 0.0));
+  EXPECT_TRUE(math::equal(q1.Y(), 0.0));
+  EXPECT_TRUE(math::equal(q1.Z(), 1.0));
+  EXPECT_TRUE(math::equal(q1.W(), 0.0));
+
+  math::Quaterniond q(q1);
+  EXPECT_TRUE(q == q1);
+}
+
+/////////////////////////////////////////////////
+TEST(QuaternionTest, Identity)
+{
+  math::Quaterniond q = math::Quaterniond::Identity;
+  EXPECT_TRUE(math::equal(q.W(), 1.0));
+  EXPECT_TRUE(math::equal(q.X(), 0.0));
+  EXPECT_TRUE(math::equal(q.Y(), 0.0));
+  EXPECT_TRUE(math::equal(q.Z(), 0.0));
+}
+
+//////////////////////////////////////////////////
+TEST(QuaternionTest, Integrate)
+{
+  // Integrate by zero, expect no change
+  {
+    const math::Quaterniond q(0.5, 0.5, 0.5, 0.5);
+    EXPECT_EQ(q, q.Integrate(math::Vector3d::Zero, 1.0));
+    EXPECT_EQ(q, q.Integrate(math::Vector3d::UnitX, 0.0));
+    EXPECT_EQ(q, q.Integrate(math::Vector3d::UnitY, 0.0));
+    EXPECT_EQ(q, q.Integrate(math::Vector3d::UnitZ, 0.0));
+  }
+
+  // Integrate along single axes,
+  // expect linear change in roll, pitch, yaw
+  {
+    const math::Quaterniond q(1, 0, 0, 0);
+    math::Quaterniond qRoll  = q.Integrate(math::Vector3d::UnitX, 1.0);
+    math::Quaterniond qPitch = q.Integrate(math::Vector3d::UnitY, 1.0);
+    math::Quaterniond qYaw   = q.Integrate(math::Vector3d::UnitZ, 1.0);
+    EXPECT_EQ(qRoll.Euler(),  math::Vector3d::UnitX);
+    EXPECT_EQ(qPitch.Euler(), math::Vector3d::UnitY);
+    EXPECT_EQ(qYaw.Euler(),   math::Vector3d::UnitZ);
+  }
+
+  // Integrate sequentially along single axes in order XYZ,
+  // expect rotations to match Euler Angles
+  {
+    const math::Quaterniond q(1, 0, 0, 0);
+    const double angle = 0.5;
+    math::Quaterniond qX   = q.Integrate(math::Vector3d::UnitX, angle);
+    math::Quaterniond qXY  = qX.Integrate(math::Vector3d::UnitY, angle);
+    EXPECT_EQ(qXY.Euler(), angle*math::Vector3d(1, 1, 0));
+  }
+  {
+    const math::Quaterniond q(1, 0, 0, 0);
+    const double angle = 0.5;
+    math::Quaterniond qX   = q.Integrate(math::Vector3d::UnitX, angle);
+    math::Quaterniond qXZ  = qX.Integrate(math::Vector3d::UnitZ, angle);
+    EXPECT_EQ(qXZ.Euler(), angle*math::Vector3d(1, 0, 1));
+  }
+  {
+    const math::Quaterniond q(1, 0, 0, 0);
+    const double angle = 0.5;
+    math::Quaterniond qY   = q.Integrate(math::Vector3d::UnitY, angle);
+    math::Quaterniond qYZ  = qY.Integrate(math::Vector3d::UnitZ, angle);
+    EXPECT_EQ(qYZ.Euler(), angle*math::Vector3d(0, 1, 1));
+  }
+  {
+    const math::Quaterniond q(1, 0, 0, 0);
+    const double angle = 0.5;
+    math::Quaterniond qX   = q.Integrate(math::Vector3d::UnitX, angle);
+    math::Quaterniond qXY  = qX.Integrate(math::Vector3d::UnitY, angle);
+    math::Quaterniond qXYZ = qXY.Integrate(math::Vector3d::UnitZ, angle);
+    EXPECT_EQ(qXYZ.Euler(), angle*math::Vector3d::One);
+  }
+
+  // Integrate sequentially along single axes in order ZYX,
+  // expect rotations to not match Euler Angles
+  {
+    const math::Quaterniond q(1, 0, 0, 0);
+    const double angle = 0.5;
+    math::Quaterniond qZ   = q.Integrate(math::Vector3d::UnitZ, angle);
+    math::Quaterniond qZY  = qZ.Integrate(math::Vector3d::UnitY, angle);
+    EXPECT_NE(qZY.Euler(), angle*math::Vector3d(0, 1, 1));
+  }
+  {
+    const math::Quaterniond q(1, 0, 0, 0);
+    const double angle = 0.5;
+    math::Quaterniond qZ   = q.Integrate(math::Vector3d::UnitZ, angle);
+    math::Quaterniond qZX  = qZ.Integrate(math::Vector3d::UnitX, angle);
+    EXPECT_NE(qZX.Euler(), angle*math::Vector3d(1, 0, 1));
+  }
+  {
+    const math::Quaterniond q(1, 0, 0, 0);
+    const double angle = 0.5;
+    math::Quaterniond qZ   = q.Integrate(math::Vector3d::UnitZ, angle);
+    math::Quaterniond qZY  = qZ.Integrate(math::Vector3d::UnitY, angle);
+    math::Quaterniond qZYX = qZY.Integrate(math::Vector3d::UnitX, angle);
+    EXPECT_NE(qZYX.Euler(), angle*math::Vector3d(1, 1, 1));
+  }
+  {
+    const math::Quaterniond q(1, 0, 0, 0);
+    const double angle = 0.5;
+    math::Quaterniond qY   = q.Integrate(math::Vector3d::UnitY, angle);
+    math::Quaterniond qYX  = qY.Integrate(math::Vector3d::UnitX, angle);
+    EXPECT_NE(qYX.Euler(), angle*math::Vector3d(1, 1, 0));
+  }
+
+  // Integrate a full rotation about different axes,
+  // expect no change.
+  {
+    const math::Quaterniond q(0.5, 0.5, 0.5, 0.5);
+    const double fourPi = 4 * IGN_PI;
+    math::Quaterniond qX = q.Integrate(math::Vector3d::UnitX, fourPi);
+    math::Quaterniond qY = q.Integrate(math::Vector3d::UnitY, fourPi);
+    math::Quaterniond qZ = q.Integrate(math::Vector3d::UnitZ, fourPi);
+    EXPECT_EQ(q, qX);
+    EXPECT_EQ(q, qY);
+    EXPECT_EQ(q, qZ);
+  }
+}
+
+/////////////////////////////////////////////////
+TEST(QuaternionTest, Math)
+{
+  math::Quaterniond q(IGN_PI*0.1, IGN_PI*0.5, IGN_PI);
+  EXPECT_TRUE(q == math::Quaterniond(0.110616, -0.698401, 0.110616, 0.698401));
+
+  EXPECT_TRUE(q.Log() ==
+      math::Quaterniond(0, -1.02593, 0.162491, 1.02593));
+
+  EXPECT_TRUE(q.Exp() ==
+      math::Quaterniond(0.545456, -0.588972, 0.093284, 0.588972));
+
+  math::Quaterniond q1 = q;
+  q1.W(2.0);
+  EXPECT_TRUE(q1.Log() ==
+      math::Quaterniond(0, -0.698401, 0.110616, 0.698401));
+
+  q1.X(0.000000001);
+  q1.Y(0.0);
+  q1.Z(0.0);
+  q1.W(0.0);
+  EXPECT_TRUE(q1.Exp() == math::Quaterniond(1, 0, 0, 0));
+
+  q.Invert();
+  EXPECT_TRUE(q == math::Quaterniond(0.110616, 0.698401, -0.110616, -0.698401));
+
+  q.Axis(0, 1, 0, IGN_PI);
+  EXPECT_TRUE(q == math::Quaterniond(6.12303e-17, 0, 1, 0));
+
+  q.Axis(math::Vector3d(1, 0, 0), IGN_PI);
+  EXPECT_TRUE(q == math::Quaterniond(0, 1, 0, 0));
+
+  q.Set(1, 2, 3, 4);
+  EXPECT_TRUE(math::equal(q.W(), 1.0));
+  EXPECT_TRUE(math::equal(q.X(), 2.0));
+  EXPECT_TRUE(math::equal(q.Y(), 3.0));
+  EXPECT_TRUE(math::equal(q.Z(), 4.0));
+
+  q.Normalize();
+  EXPECT_TRUE(q == math::Quaterniond(0.182574, 0.365148, 0.547723, 0.730297));
+
+
+  EXPECT_TRUE(math::equal(q.Roll(), 1.4289, 1e-3));
+  EXPECT_TRUE(math::equal(q.Pitch(), -0.339837, 1e-3));
+  EXPECT_TRUE(math::equal(q.Yaw(), 2.35619, 1e-3));
+
+  math::Vector3d axis;
+  double angle;
+  q.ToAxis(axis, angle);
+  EXPECT_TRUE(axis == math::Vector3d(0.371391, 0.557086, 0.742781));
+  EXPECT_TRUE(math::equal(angle, 2.77438, 1e-3));
+
+  q.Scale(0.1);
+  EXPECT_TRUE(q == math::Quaterniond(0.990394, 0.051354, 0.0770309, 0.102708));
+
+  q = q + math::Quaterniond(0, 1, 2);
+  EXPECT_TRUE(q == math::Quaterniond(1.46455, -0.352069, 0.336066, 0.841168));
+
+  q += q;
+  EXPECT_TRUE(q == math::Quaterniond(2.92911, -0.704137, 0.672131, 1.68234));
+
+  q -= math::Quaterniond(.4, .2, .1);
+  EXPECT_TRUE(q == math::Quaterniond(1.95416, -0.896677, 0.56453, 1.65341));
+
+  q = q - math::Quaterniond(0, 1, 2);
+  EXPECT_TRUE(q == math::Quaterniond(1.48, -0.493254, 0.305496, 0.914947));
+
+  q *= math::Quaterniond(.4, .1, .01);
+  EXPECT_TRUE(q == math::Quaterniond(1.53584, -0.236801, 0.551841, 0.802979));
+
+  q = q * 5.0;
+  EXPECT_TRUE(q == math::Quaterniond(7.67918, -1.184, 2.7592, 4.0149));
+
+  EXPECT_TRUE(q.RotateVectorReverse(math::Vector3d(1, 2, 3)) ==
+      math::Vector3d(-0.104115, 0.4975, 3.70697));
+
+  EXPECT_TRUE(math::equal(q.Dot(math::Quaterniond(.4, .2, .1)), 7.67183, 1e-3));
+
+  EXPECT_TRUE(math::Quaterniond::Squad(1.1, math::Quaterniond(.1, 0, .2),
+        math::Quaterniond(0, .3, .4), math::Quaterniond(.5, .2, 1),
+        math::Quaterniond(0, 0, 2), true) ==
+      math::Quaterniond(0.346807, -0.0511734, -0.0494723, 0.935232));
+
+  EXPECT_TRUE(math::Quaterniond::EulerToQuaternion(
+        math::Vector3d(.1, .2, .3)) ==
+      math::Quaterniond(0.983347, 0.0342708, 0.106021, 0.143572));
+
+  q.Round(2);
+  EXPECT_TRUE(math::equal(-1.18, q.X()));
+  EXPECT_TRUE(math::equal(2.76, q.Y()));
+  EXPECT_TRUE(math::equal(4.01, q.Z()));
+  EXPECT_TRUE(math::equal(7.68, q.W()));
+
+  q.X(0.0);
+  q.Y(0.0);
+  q.Z(0.0);
+  q.W(0.0);
+  q.Normalize();
+  EXPECT_TRUE(q == math::Quaterniond());
+
+  q.Axis(0, 0, 0, 0);
+  EXPECT_TRUE(q == math::Quaterniond());
+
+  EXPECT_TRUE(math::Quaterniond::EulerToQuaternion(0.1, 0.2, 0.3) ==
+      math::Quaterniond(0.983347, 0.0342708, 0.106021, 0.143572));
+
+  q.X(0.0);
+  q.Y(0.0);
+  q.Z(0.0);
+  q.W(0.0);
+  q.ToAxis(axis, angle);
+  EXPECT_TRUE(axis == math::Vector3d(1, 0, 0));
+  EXPECT_TRUE(math::equal(angle, 0.0, 1e-3));
+  {
+    // simple 180 rotation about yaw, should result in x and y flipping signs
+    q = math::Quaterniond(0, 0, IGN_PI);
+    math::Vector3d v = math::Vector3d(1, 2, 3);
+    math::Vector3d r1 = q.RotateVector(v);
+    math::Vector3d r2 = q.RotateVectorReverse(v);
+    std::cout << "[" << q.W() << ", " << q.X() << ", "
+      << q.Y() << ", " << q.Z() << "]\n";
+    std::cout << " forward turns [" << v << "] to [" << r1 << "]\n";
+    std::cout << " reverse turns [" << v << "] to [" << r2 << "]\n";
+    EXPECT_TRUE(r1 == math::Vector3d(-1, -2, 3));
+    EXPECT_TRUE(r2 == math::Vector3d(-1, -2, 3));
+  }
+
+  {
+    // simple  90 rotation about yaw, should map x to y, y to -x
+    // simple -90 rotation about yaw, should map x to -y, y to x
+    q = math::Quaterniond(0, 0, 0.5*IGN_PI);
+    math::Vector3d v = math::Vector3d(1, 2, 3);
+    math::Vector3d r1 = q.RotateVector(v);
+    math::Vector3d r2 = q.RotateVectorReverse(v);
+    std::cout << "[" << q.W() << ", " << q.X() << ", "
+      << q.Y() << ", " << q.Z() << "]\n";
+    std::cout << " forward turns [" << v << "] to [" << r1 << "]\n";
+    std::cout << " reverse turns [" << v << "] to [" << r2 << "]\n";
+    std::cout << " x axis [" << q.XAxis() << "]\n";
+    std::cout << " y axis [" << q.YAxis() << "]\n";
+    std::cout << " z axis [" << q.ZAxis() << "]\n";
+    EXPECT_TRUE(r1 == math::Vector3d(-2, 1, 3));
+    EXPECT_TRUE(r2 == math::Vector3d(2, -1, 3));
+    EXPECT_TRUE(q.Inverse().XAxis() == math::Vector3d(0, -1, 0));
+    EXPECT_TRUE(q.Inverse().YAxis() == math::Vector3d(1, 0, 0));
+    EXPECT_TRUE(q.Inverse().ZAxis() == math::Vector3d(0, 0, 1));
+  }
+
+  // Test RPY fixed-body-frame convention:
+  // Rotate each unit vector in roll and pitch
+  {
+    q = math::Quaterniond(IGN_PI/2.0, IGN_PI/2.0, 0);
+    math::Vector3d v1(1, 0, 0);
+    math::Vector3d r1 = q.RotateVector(v1);
+    // 90 degrees about X does nothing,
+    // 90 degrees about Y sends point down to -Z
+    EXPECT_EQ(r1, math::Vector3d(0, 0, -1));
+
+    math::Vector3d v2(0, 1, 0);
+    math::Vector3d r2 = q.RotateVector(v2);
+    // 90 degrees about X sends point to +Z
+    // 90 degrees about Y sends point to +X
+    EXPECT_EQ(r2, math::Vector3d(1, 0, 0));
+
+    math::Vector3d v3(0, 0, 1);
+    math::Vector3d r3 = q.RotateVector(v3);
+    // 90 degrees about X sends point to -Y
+    // 90 degrees about Y does nothing
+    EXPECT_EQ(r3, math::Vector3d(0, -1, 0));
+  }
+
+  {
+    // now try a harder case (axis[1,2,3], rotation[0.3*pi])
+    // verified with octave
+    q.Axis(math::Vector3d(1, 2, 3), 0.3*IGN_PI);
+    std::cout << "[" << q.W() << ", " << q.X() << ", "
+      << q.Y() << ", " << q.Z() << "]\n";
+    std::cout << " x [" << q.Inverse().XAxis() << "]\n";
+    std::cout << " y [" << q.Inverse().YAxis() << "]\n";
+    std::cout << " z [" << q.Inverse().ZAxis() << "]\n";
+    EXPECT_TRUE(q.Inverse().XAxis() ==
+                math::Vector3d(0.617229, -0.589769, 0.520770));
+    EXPECT_TRUE(q.Inverse().YAxis() ==
+                math::Vector3d(0.707544, 0.705561, -0.039555));
+    EXPECT_TRUE(q.Inverse().ZAxis() ==
+                math::Vector3d(-0.344106, 0.392882, 0.852780));
+
+    // rotate about the axis of rotation should not change axis
+    math::Vector3d v = math::Vector3d(1, 2, 3);
+    math::Vector3d r1 = q.RotateVector(v);
+    math::Vector3d r2 = q.RotateVectorReverse(v);
+    EXPECT_TRUE(r1 == math::Vector3d(1, 2, 3));
+    EXPECT_TRUE(r2 == math::Vector3d(1, 2, 3));
+
+    // rotate unit vectors
+    v = math::Vector3d(0, 0, 1);
+    r1 = q.RotateVector(v);
+    r2 = q.RotateVectorReverse(v);
+    EXPECT_TRUE(r1 == math::Vector3d(0.520770, -0.039555, 0.852780));
+    EXPECT_TRUE(r2 == math::Vector3d(-0.34411, 0.39288, 0.85278));
+    v = math::Vector3d(0, 1, 0);
+    r1 = q.RotateVector(v);
+    r2 = q.RotateVectorReverse(v);
+    EXPECT_TRUE(r1 == math::Vector3d(-0.58977, 0.70556, 0.39288));
+    EXPECT_TRUE(r2 == math::Vector3d(0.707544, 0.705561, -0.039555));
+    v = math::Vector3d(1, 0, 0);
+    r1 = q.RotateVector(v);
+    r2 = q.RotateVectorReverse(v);
+    EXPECT_TRUE(r1 == math::Vector3d(0.61723, 0.70754, -0.34411));
+    EXPECT_TRUE(r2 == math::Vector3d(0.61723, -0.58977, 0.52077));
+
+    EXPECT_TRUE(-q == math::Quaterniond(-0.891007, -0.121334,
+                                       -0.242668, -0.364002));
+
+    EXPECT_TRUE(math::Matrix3d(q) == math::Matrix3d(
+                0.617229, -0.589769, 0.52077,
+                0.707544, 0.705561, -0.0395554,
+                -0.344106, 0.392882, 0.85278));
+
+    math::Matrix3d matFromQ;
+    matFromQ = q;
+    EXPECT_TRUE(matFromQ == math::Matrix3d(
+                0.617229, -0.589769, 0.52077,
+                0.707544, 0.705561, -0.0395554,
+                -0.344106, 0.392882, 0.85278));
+
+    EXPECT_TRUE(math::Matrix4d(q) == math::Matrix4d(
+                0.617229, -0.589769, 0.52077, 0,
+                0.707544, 0.705561, -0.0395554, 0,
+                -0.344106, 0.392882, 0.85278, 0,
+                0, 0, 0, 1));
+
+    math::Matrix3d matFromQuat(q);
+
+    math::Quaterniond quatFromMat(matFromQuat);
+    math::Quaterniond quatFromMat2; quatFromMat2.Matrix(matFromQuat);
+
+    EXPECT_TRUE(q == quatFromMat);
+    EXPECT_TRUE(q == quatFromMat2);
+
+    // test the cases where matrix trace is negative (requires special handling)
+    q = math::Quaterniond(0, 0, 0, 1);
+    EXPECT_TRUE(q == math::Quaterniond(math::Matrix3d(
+                -1,  0, 0,
+                 0, -1, 0,
+                 0,  0, 1)));
+
+    q = math::Quaterniond(0, 0, 1, 0);
+    EXPECT_TRUE(q == math::Quaterniond(math::Matrix3d(
+                -1,  0,  0,
+                 0,  1,  0,
+                 0,  0, -1)));
+
+    q = math::Quaterniond(0, 1, 0, 0);
+    EXPECT_TRUE(q == math::Quaterniond(math::Matrix3d(
+                1,  0,  0,
+                0, -1,  0,
+                0,  0, -1)));
+  }
+}
+
+/////////////////////////////////////////////////
+TEST(QuaternionTest, OperatorStreamOut)
+{
+  math::Quaterniond q(0.1, 1.2, 2.3);
+  std::ostringstream stream;
+  stream << q;
+  EXPECT_EQ(stream.str(), "0.1 1.2 2.3");
+}
+
+/////////////////////////////////////////////////
+TEST(QuaternionTest, Slerp)
+{
+  math::Quaterniond q1(0.1, 1.2, 2.3);
+  math::Quaterniond q2(1.2, 2.3, -3.4);
+
+  math::Quaterniond q3 = math::Quaterniond::Slerp(1.0, q1, q2, true);
+  EXPECT_EQ(q3, math::Quaterniond(0.554528, -0.717339, 0.32579, 0.267925));
+}
+
+/////////////////////////////////////////////////
+TEST(QuaterniondTest, From2Axes)
+{
+  math::Vector3d v1(1.0, 0.0, 0.0);
+  math::Vector3d v2(0.0, 1.0, 0.0);
+
+  math::Quaterniond q1;
+  q1.From2Axes(v1, v2);
+
+  math::Quaterniond q2;
+  q2.From2Axes(v2, v1);
+
+  math::Quaterniond q1Correct(sqrt(2)/2, 0, 0, sqrt(2)/2);
+  math::Quaterniond q2Correct(sqrt(2)/2, 0, 0, -sqrt(2)/2);
+
+  EXPECT_NE(q1, q2);
+  EXPECT_EQ(q1Correct, q1);
+  EXPECT_EQ(q2Correct, q2);
+  EXPECT_EQ(math::Quaterniond::Identity, q1 * q2);
+  EXPECT_EQ(v2, q1 * v1);
+  EXPECT_EQ(v1, q2 * v2);
+
+  // still the same rotation, but with non-unit vectors
+  v1.Set(0.5, 0.5, 0);
+  v2.Set(-0.5, 0.5, 0);
+
+  q1.From2Axes(v1, v2);
+  q2.From2Axes(v2, v1);
+
+  EXPECT_NE(q1, q2);
+  EXPECT_EQ(q1Correct, q1);
+  EXPECT_EQ(q2Correct, q2);
+  EXPECT_EQ(math::Quaterniond::Identity, q1 * q2);
+  EXPECT_EQ(v2, q1 * v1);
+  EXPECT_EQ(v1, q2 * v2);
+
+  // Test various settings of opposite vectors (which need special care)
+
+  v1.Set(1, 0, 0);
+  v2.Set(-1, 0, 0);
+  q1.From2Axes(v1, v2);
+  q2 = q1 * q1;
+  EXPECT_TRUE(math::equal(q2.W(), 1.0) || math::equal(q2.W(), -1.0));
+  EXPECT_TRUE(math::equal(q2.X(), 0.0));
+  EXPECT_TRUE(math::equal(q2.Y(), 0.0));
+  EXPECT_TRUE(math::equal(q2.Z(), 0.0));
+
+  v1.Set(0, 1, 0);
+  v2.Set(0, -1, 0);
+  q1.From2Axes(v1, v2);
+  q2 = q1 * q1;
+  EXPECT_TRUE(math::equal(q2.W(), 1.0) || math::equal(q2.W(), -1.0));
+  EXPECT_TRUE(math::equal(q2.X(), 0.0));
+  EXPECT_TRUE(math::equal(q2.Y(), 0.0));
+  EXPECT_TRUE(math::equal(q2.Z(), 0.0));
+
+  v1.Set(0, 0, 1);
+  v2.Set(0, 0, -1);
+  q1.From2Axes(v1, v2);
+  q2 = q1 * q1;
+  EXPECT_TRUE(math::equal(q2.W(), 1.0) || math::equal(q2.W(), -1.0));
+  EXPECT_TRUE(math::equal(q2.X(), 0.0));
+  EXPECT_TRUE(math::equal(q2.Y(), 0.0));
+  EXPECT_TRUE(math::equal(q2.Z(), 0.0));
+
+  v1.Set(0, 1, 1);
+  v2.Set(0, -1, -1);
+  q1.From2Axes(v1, v2);
+  q2 = q1 * q1;
+  EXPECT_TRUE(math::equal(q2.W(), 1.0) || math::equal(q2.W(), -1.0));
+  EXPECT_TRUE(math::equal(q2.X(), 0.0));
+  EXPECT_TRUE(math::equal(q2.Y(), 0.0));
+  EXPECT_TRUE(math::equal(q2.Z(), 0.0));
+}
+
diff --git a/src/Rand.cc b/src/Rand.cc
new file mode 100644
index 0000000..95fcae4
--- /dev/null
+++ b/src/Rand.cc
@@ -0,0 +1,92 @@
+/*
+ * Copyright (C) 2012 Open Source Robotics Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+*/
+
+#include <sys/types.h>
+#include <ctime>
+
+#ifdef _WIN32
+  #include <process.h>
+  #define getpid _getpid
+#else
+  #include <unistd.h>
+#endif
+
+#include "ignition/math/Rand.hh"
+
+using namespace ignition;
+using namespace math;
+
+//////////////////////////////////////////////////
+void Rand::Seed(unsigned int _seed)
+{
+  std::seed_seq seq{_seed};
+  SeedMutable() = _seed;
+  RandGenerator().seed(seq);
+}
+
+//////////////////////////////////////////////////
+unsigned int Rand::Seed()
+{
+  return SeedMutable();
+}
+
+//////////////////////////////////////////////////
+double Rand::DblUniform(double _min, double _max)
+{
+  UniformRealDist d(_min, _max);
+  return d(RandGenerator());
+}
+
+//////////////////////////////////////////////////
+double Rand::DblNormal(double _mean, double _sigma)
+{
+  NormalRealDist d(_mean, _sigma);
+  return d(RandGenerator());
+}
+
+//////////////////////////////////////////////////
+int32_t Rand::IntUniform(int _min, int _max)
+{
+  UniformIntDist d(_min, _max);
+
+  return d(RandGenerator());
+}
+
+//////////////////////////////////////////////////
+int32_t Rand::IntNormal(int _mean, int _sigma)
+{
+  NormalRealDist d(_mean, _sigma);
+
+  return static_cast<int32_t>(d(RandGenerator()));
+}
+
+//////////////////////////////////////////////////
+uint32_t &Rand::SeedMutable()
+{
+  // We don't seed with time for the cases when two processes are started the
+  // same time (this mostly happens with launch scripts that start a server
+  // and gui simultaneously).
+  static uint32_t seed = std::random_device {}();
+  return seed;
+}
+
+//////////////////////////////////////////////////
+GeneratorType &Rand::RandGenerator()
+{
+  static GeneratorType randGenerator(Seed());
+  return randGenerator;
+}
diff --git a/src/Rand_TEST.cc b/src/Rand_TEST.cc
new file mode 100644
index 0000000..f422a67
--- /dev/null
+++ b/src/Rand_TEST.cc
@@ -0,0 +1,79 @@
+/*
+ * Copyright (C) 2012 Open Source Robotics Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+*/
+
+#include <gtest/gtest.h>
+
+#include "ignition/math/Helpers.hh"
+#include "ignition/math/Rand.hh"
+
+using namespace ignition;
+
+//////////////////////////////////////////////////
+TEST(RandTest, Rand)
+{
+  // TODO: implement a proper random number generator test
+
+  double d = math::Rand::DblUniform(1, 2);
+  EXPECT_GE(d, 1);
+  EXPECT_LE(d, 2);
+
+  int i = math::Rand::IntUniform(1, 2);
+  EXPECT_GE(i, 1);
+  EXPECT_LE(i, 2);
+
+#ifndef _MSC_VER
+  {
+    // Test setting the random number seed
+    math::Rand::Seed(1001);
+
+    d = math::Rand::DblNormal(2, 3);
+    i = math::Rand::IntNormal(10, 5);
+
+    // \todo OSX seems to produce different results. See issue #14.
+#ifdef __APPLE__
+    EXPECT_EQ(i, 8);
+    EXPECT_NEAR(d, 5.01545, 1e-5);
+#else
+    EXPECT_EQ(i, 9);
+    EXPECT_NEAR(d, 3.00618, 1e-5);
+#endif
+  }
+#endif
+}
+
+//////////////////////////////////////////////////
+TEST(RandTest, SetSeed)
+{
+  int N = 10;
+  std::vector<int> first;
+  std::vector<int> second;
+
+  for (int i = 0; i < N; ++i)
+  {
+    math::Rand::Seed(i);
+    first.push_back(math::Rand::IntUniform(-10, 10));
+    second.push_back(math::Rand::IntUniform(-10, 10));
+  }
+
+  for (int i = 0; i < N; ++i)
+  {
+    math::Rand::Seed(i);
+    EXPECT_EQ(math::Rand::Seed(), static_cast<unsigned int>(i));
+    EXPECT_EQ(first[i], math::Rand::IntUniform(-10, 10));
+    EXPECT_EQ(second[i], math::Rand::IntUniform(-10, 10));
+  }
+}
diff --git a/src/RotationSpline.cc b/src/RotationSpline.cc
new file mode 100644
index 0000000..974fbc3
--- /dev/null
+++ b/src/RotationSpline.cc
@@ -0,0 +1,211 @@
+/*
+ * Copyright (C) 2012 Open Source Robotics Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+*/
+#include "ignition/math/Quaternion.hh"
+#include "ignition/math/RotationSpline.hh"
+#include "RotationSplinePrivate.hh"
+
+using namespace ignition;
+using namespace math;
+
+/////////////////////////////////////////////////
+RotationSpline::RotationSpline()
+: dataPtr(new RotationSplinePrivate)
+{
+}
+
+/////////////////////////////////////////////////
+RotationSpline::~RotationSpline()
+{
+  delete this->dataPtr;
+  this->dataPtr = NULL;
+}
+
+/////////////////////////////////////////////////
+void RotationSpline::AddPoint(const Quaterniond &_p)
+{
+  this->dataPtr->points.push_back(_p);
+  if (this->dataPtr->autoCalc)
+    this->RecalcTangents();
+}
+
+/////////////////////////////////////////////////
+Quaterniond RotationSpline::Interpolate(double _t,
+                                        const bool _useShortestPath)
+{
+  // Work out which segment this is in
+  double fSeg = _t * (this->dataPtr->points.size() - 1);
+  unsigned int segIdx = (unsigned int)fSeg;
+
+  // Apportion t
+  _t = fSeg - segIdx;
+
+  return this->Interpolate(segIdx, _t, _useShortestPath);
+}
+
+/////////////////////////////////////////////////
+Quaterniond RotationSpline::Interpolate(const unsigned int _fromIndex,
+    const double _t, const bool _useShortestPath)
+{
+  // Bounds check
+  if (_fromIndex >= this->dataPtr->points.size())
+    return Quaterniond(INF_D, INF_D, INF_D, INF_D);
+
+  if ((_fromIndex + 1) == this->dataPtr->points.size())
+  {
+    // Duff request, cannot blend to nothing
+    // Just return source
+    return this->dataPtr->points[_fromIndex];
+  }
+
+  // Fast special cases
+  if (math::equal(_t, 0.0))
+    return this->dataPtr->points[_fromIndex];
+  else if (math::equal(_t, 1.0))
+    return this->dataPtr->points[_fromIndex + 1];
+
+  // double interpolation
+  // Use squad using tangents we've already set up
+  Quaterniond &p = this->dataPtr->points[_fromIndex];
+  Quaterniond &q = this->dataPtr->points[_fromIndex+1];
+  Quaterniond &a = this->dataPtr->tangents[_fromIndex];
+  Quaterniond &b = this->dataPtr->tangents[_fromIndex+1];
+
+  // NB interpolate to nearest rotation
+  return Quaterniond::Squad(_t, p, a, b, q, _useShortestPath);
+}
+
+/////////////////////////////////////////////////
+void RotationSpline::RecalcTangents()
+{
+  // ShoeMake (1987) approach
+  // Just like Catmull-Rom really, just more gnarly
+  // And no, I don't understand how to derive this!
+  //
+  // let p = point[i], pInv = p.Inverse
+  // tangent[i] = p * exp(-0.25 *
+  // (log(pInv * point[i+1]) + log(pInv * point[i-1])))
+  //
+  // Assume endpoint tangents are parallel with line with neighbour
+
+  unsigned int i;
+  bool isClosed;
+
+  size_t numPoints = this->dataPtr->points.size();
+
+  if (numPoints < 2)
+  {
+    // Can't do anything yet
+    return;
+  }
+
+  this->dataPtr->tangents.resize(numPoints);
+
+  if (this->dataPtr->points[0] == this->dataPtr->points[numPoints-1])
+    isClosed = true;
+  else
+    isClosed = false;
+
+  Quaterniond invp, part1, part2, preExp;
+  for (i = 0; i < numPoints; ++i)
+  {
+    Quaterniond &p = this->dataPtr->points[i];
+    invp = p.Inverse();
+
+    if (i == 0)
+    {
+      // special case start
+      part1 = (invp * this->dataPtr->points[i+1]).Log();
+      if (isClosed)
+      {
+        // Use numPoints-2 since numPoints-1 == end == start == this one
+        part2 = (invp * this->dataPtr->points[numPoints-2]).Log();
+      }
+      else
+      {
+        part2 = (invp * p).Log();
+      }
+    }
+    else if (i == numPoints-1)
+    {
+      // special case end
+      if (isClosed)
+      {
+        // Wrap to [1] (not [0], this is the same as end == this one)
+        part1 = (invp * this->dataPtr->points[1]).Log();
+      }
+      else
+      {
+        part1 = (invp * p).Log();
+      }
+      part2 = (invp * this->dataPtr->points[i-1]).Log();
+    }
+    else
+    {
+      part1 = (invp * this->dataPtr->points[i+1]).Log();
+      part2 = (invp * this->dataPtr->points[i-1]).Log();
+    }
+
+    preExp = (part1 + part2) * -0.25;
+    this->dataPtr->tangents[i] = p * preExp.Exp();
+  }
+}
+
+/////////////////////////////////////////////////
+const Quaterniond &RotationSpline::Point(const unsigned int _index) const
+{
+  static Quaterniond inf(INF_D, INF_D, INF_D, INF_D);
+
+  if (this->dataPtr->points.empty())
+    return inf;
+
+  return this->dataPtr->points[
+    clamp(_index, 0u, static_cast<unsigned int>(
+          this->dataPtr->points.size()-1))];
+}
+
+/////////////////////////////////////////////////
+unsigned int RotationSpline::PointCount() const
+{
+  return static_cast<unsigned int>(this->dataPtr->points.size());
+}
+
+/////////////////////////////////////////////////
+void RotationSpline::Clear()
+{
+  this->dataPtr->points.clear();
+  this->dataPtr->tangents.clear();
+}
+
+/////////////////////////////////////////////////
+bool RotationSpline::UpdatePoint(const unsigned int _index,
+                                 const Quaterniond &_value)
+{
+  if (_index >= this->dataPtr->points.size())
+    return false;
+
+  this->dataPtr->points[_index] = _value;
+  if (this->dataPtr->autoCalc)
+    this->RecalcTangents();
+
+  return true;
+}
+
+/////////////////////////////////////////////////
+void RotationSpline::AutoCalculate(bool _autoCalc)
+{
+  this->dataPtr->autoCalc = _autoCalc;
+}
diff --git a/src/RotationSplinePrivate.cc b/src/RotationSplinePrivate.cc
new file mode 100644
index 0000000..1396e82
--- /dev/null
+++ b/src/RotationSplinePrivate.cc
@@ -0,0 +1,26 @@
+/*
+ * Copyright (C) 2015 Open Source Robotics Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+*/
+#include "RotationSplinePrivate.hh"
+
+using namespace ignition;
+using namespace math;
+
+/////////////////////////////////////////////////
+RotationSplinePrivate::RotationSplinePrivate()
+: autoCalc(true)
+{
+}
diff --git a/src/RotationSplinePrivate.hh b/src/RotationSplinePrivate.hh
new file mode 100644
index 0000000..c668034
--- /dev/null
+++ b/src/RotationSplinePrivate.hh
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2015 Open Source Robotics Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+*/
+#ifndef IGNITION_MATH_ROTATIONSPLINEPRIVATE_HH_
+#define IGNITION_MATH_ROTATIONSPLINEPRIVATE_HH_
+
+#include <vector>
+#include "ignition/math/Quaternion.hh"
+
+namespace ignition
+{
+  namespace math
+  {
+    /// \internal
+    /// \brief Private data for RotationSpline
+    class RotationSplinePrivate
+    {
+      /// \brief Constructor
+      public: RotationSplinePrivate();
+
+      /// \brief Automatic recalculation of tangents when control points are
+      /// updated
+      public: bool autoCalc;
+
+      /// \brief the control points
+      public: std::vector<Quaterniond> points;
+
+      /// \brief the tangents
+      public: std::vector<Quaterniond> tangents;
+    };
+  }
+}
+#endif
diff --git a/src/RotationSpline_TEST.cc b/src/RotationSpline_TEST.cc
new file mode 100644
index 0000000..57a1e6b
--- /dev/null
+++ b/src/RotationSpline_TEST.cc
@@ -0,0 +1,100 @@
+/*
+ * Copyright (C) 2012 Open Source Robotics Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+*/
+
+#include <gtest/gtest.h>
+
+#include "ignition/math/Helpers.hh"
+#include "ignition/math/Vector3.hh"
+#include "ignition/math/Quaternion.hh"
+#include "ignition/math/RotationSpline.hh"
+
+using namespace ignition;
+
+/////////////////////////////////////////////////
+TEST(RotationSplineTest, RotationSpline)
+{
+  math::RotationSpline s;
+
+  s.AddPoint(math::Quaterniond(0, 0, 0));
+  EXPECT_EQ(static_cast<unsigned int>(1), s.PointCount());
+
+  s.Clear();
+  EXPECT_EQ(static_cast<unsigned int>(0), s.PointCount());
+
+  s.AddPoint(math::Quaterniond(0, 0, 0));
+  EXPECT_TRUE(s.Point(0) == math::Quaterniond(0, 0, 0));
+  s.AddPoint(math::Quaterniond(.1, .1, .1));
+  EXPECT_TRUE(s.Point(1) == math::Quaterniond(.1, .1, .1));
+
+  // ::UpdatePoint
+  EXPECT_NO_THROW(s.UpdatePoint(2, math::Quaterniond(.2, .2, .2)));
+  EXPECT_FALSE(s.UpdatePoint(2, math::Quaterniond(.2, .2, .2)));
+
+  EXPECT_TRUE(s.UpdatePoint(1, math::Quaterniond(.2, .2, .2)));
+  s.AutoCalculate(false);
+  EXPECT_TRUE(s.UpdatePoint(0, math::Quaterniond(
+    math::Vector3d(-.1, -.1, -.1))));
+  s.AutoCalculate(true);
+
+  // ::Interpolate
+  EXPECT_TRUE(s.Interpolate(0.5) ==
+      math::Quaterniond(0.998089, 0.0315333, 0.0427683, 0.0315333));
+
+  // ::Interpolate
+  s.AddPoint(math::Quaterniond(.4, .4, .4));
+  EXPECT_NO_THROW(s.Interpolate(4, 0.2));
+  EXPECT_FALSE(s.Interpolate(4, 0.2).IsFinite());
+
+  EXPECT_EQ(s.Interpolate(s.PointCount()-1, 0.2),
+            s.Point(s.PointCount()-1));
+  EXPECT_TRUE(s.Interpolate(1, 0.2) ==
+      math::Quaterniond(0.978787, 0.107618, 0.137159, 0.107618));
+  EXPECT_EQ(s.Interpolate(1, 0.0), s.Point(1));
+  EXPECT_EQ(s.Interpolate(1, 1.0), s.Point(2));
+}
+
+/////////////////////////////////////////////////
+TEST(RotationSplineTest, GetPoint)
+{
+  math::RotationSpline s;
+  EXPECT_NO_THROW(s.Point(0));
+  EXPECT_FALSE(s.Point(0).IsFinite());
+  EXPECT_NO_THROW(s.Point(1));
+  EXPECT_FALSE(s.Point(1).IsFinite());
+
+  s.AddPoint(math::Quaterniond(0, 0, 0));
+  EXPECT_NO_THROW(s.Point(0));
+  EXPECT_NO_THROW(s.Point(1));
+  EXPECT_TRUE(s.Point(1).IsFinite());
+}
+
+/////////////////////////////////////////////////
+TEST(RotationSplineTest, RecalcTangents)
+{
+  math::RotationSpline s;
+  s.AddPoint(math::Quaterniond(0, 0, 0));
+  s.AddPoint(math::Quaterniond(.4, .4, .4));
+  s.AddPoint(math::Quaterniond(0, 0, 0));
+
+  s.RecalcTangents();
+  EXPECT_EQ(s.Interpolate(0, 0.5),
+      math::Quaterniond(0.987225, 0.077057, 0.11624, 0.077057));
+
+  math::Quaterniond q = s.Interpolate(1, 0.5);
+  EXPECT_EQ(s.Interpolate(1, 0.5),
+      math::Quaterniond(0.987225, 0.077057, 0.11624, 0.077057));
+}
diff --git a/src/SemanticVersion.cc b/src/SemanticVersion.cc
new file mode 100644
index 0000000..2f1efba
--- /dev/null
+++ b/src/SemanticVersion.cc
@@ -0,0 +1,294 @@
+/*
+ * Copyright (C) 2016 Open Source Robotics Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+*/
+
+#include <sstream>
+
+#include "ignition/math/SemanticVersion.hh"
+
+using namespace ignition;
+using namespace math;
+
+namespace ignition
+{
+  namespace math
+  {
+    class SemanticVersionPrivate
+    {
+      /// \brief Major revision (incompatible api changes)
+      public: unsigned int maj = 0;
+
+      /// \brief Minor revision (backwards compatible new functionality)
+      public: unsigned int min = 0;
+
+      /// \brief Patch (bug fixes)
+      public: unsigned int patch = 0;
+
+      /// \brief Optional pre-release info. A prerelease string may be
+      /// denoted by appending a hyphen and a series of dot separated
+      /// identifiers immediately following the patch version
+      public: std::string prerelease = "";
+
+      /// \brief Optional build meta-data. Build metadata may be denoted by
+      /// appending a plus sign and a series of dot separated identifiers
+      /// immediately following the patch or pre-release version
+      public: std::string build = "";
+    };
+  }
+}
+
+/////////////////////////////////////////////////
+SemanticVersion::SemanticVersion()
+: dataPtr(new SemanticVersionPrivate())
+{
+}
+
+/////////////////////////////////////////////////
+SemanticVersion::SemanticVersion(const std::string &_versionStr)
+: dataPtr(new SemanticVersionPrivate())
+{
+  this->Parse(_versionStr);
+}
+
+/////////////////////////////////////////////////
+SemanticVersion::SemanticVersion(const unsigned int _major,
+  const unsigned int _minor,
+  const unsigned int _patch,
+  const std::string &_prerelease,
+  const std::string &_build)
+: dataPtr(new SemanticVersionPrivate())
+{
+  this->dataPtr->maj = _major;
+  this->dataPtr->min = _minor;
+  this->dataPtr->patch = _patch;
+  this->dataPtr->prerelease = _prerelease;
+  this->dataPtr->build = _build;
+}
+
+/////////////////////////////////////////////////
+SemanticVersion::SemanticVersion(const SemanticVersion  &_copy)
+: dataPtr(new SemanticVersionPrivate())
+{
+  *this->dataPtr = *_copy.dataPtr;
+}
+
+/////////////////////////////////////////////////
+SemanticVersion& SemanticVersion::operator=(const SemanticVersion &_other)
+{
+  *this->dataPtr = *_other.dataPtr;
+  return *this;
+}
+
+/////////////////////////////////////////////////
+SemanticVersion::~SemanticVersion()
+{
+}
+
+/////////////////////////////////////////////////
+std::string SemanticVersion::Version() const
+{
+  std::string result = std::to_string(this->dataPtr->maj) + "." +
+    std::to_string(this->dataPtr->min) + "." +
+    std::to_string(this->dataPtr->patch);
+
+  if (!this->dataPtr->prerelease.empty())
+    result += "-" + this->dataPtr->prerelease;
+
+  if (!this->dataPtr->build.empty())
+    result += "+" + this->dataPtr->build;
+
+  return result;
+}
+
+/////////////////////////////////////////////////
+bool SemanticVersion::operator<(const SemanticVersion &_other) const
+{
+  if (this == &_other)
+    return false;
+
+  if (this->dataPtr->maj < _other.dataPtr->maj)
+  {
+    return true;
+  }
+  if (this->dataPtr->maj > _other.dataPtr->maj)
+  {
+    return false;
+  }
+  if (this->dataPtr->min < _other.dataPtr->min)
+  {
+    return true;
+  }
+  if (this->dataPtr->min > _other.dataPtr->min)
+  {
+    return false;
+  }
+  if (this->dataPtr->patch < _other.dataPtr->patch)
+  {
+    return true;
+  }
+  if (this->dataPtr->patch > _other.dataPtr->patch)
+  {
+    return false;
+  }
+
+  // If this version has prelrease and the _other doesn't, then this
+  // version is lower. We don't compare the prerelease strings because
+  // they can contain any alphanumeric values.
+  if (!this->dataPtr->prerelease.empty() && _other.dataPtr->prerelease.empty())
+    return true;
+
+  // _other is equal
+  return false;
+}
+
+/////////////////////////////////////////////////
+bool SemanticVersion::operator<=(const SemanticVersion &_other) const
+{
+  return (_other > *this) || (_other == *this);
+}
+
+/////////////////////////////////////////////////
+bool SemanticVersion::operator>(const SemanticVersion &_other) const
+{
+  return (_other < *this);
+}
+
+/////////////////////////////////////////////////
+bool SemanticVersion::operator>=(const SemanticVersion &_other) const
+{
+  return (_other < *this) || (_other == *this);
+}
+
+/////////////////////////////////////////////////
+bool SemanticVersion::operator==(const SemanticVersion &_other) const
+{
+  if (this == &_other)
+    return true;
+
+  return (_other.dataPtr->maj == this->dataPtr->maj)
+    && (_other.dataPtr->min == this->dataPtr->min)
+    && (_other.dataPtr->patch == this->dataPtr->patch);
+}
+
+/////////////////////////////////////////////////
+bool SemanticVersion::operator!=(const SemanticVersion &_other) const
+{
+  return !(*this == _other);
+}
+
+/////////////////////////////////////////////////
+unsigned int SemanticVersion::Major() const
+{
+  return this->dataPtr->maj;
+}
+
+/////////////////////////////////////////////////
+unsigned int SemanticVersion::Minor() const
+{
+  return this->dataPtr->min;
+}
+
+/////////////////////////////////////////////////
+unsigned int SemanticVersion::Patch() const
+{
+  return this->dataPtr->patch;
+}
+
+/////////////////////////////////////////////////
+std::string SemanticVersion::Prerelease() const
+{
+  return this->dataPtr->prerelease;
+}
+
+/////////////////////////////////////////////////
+std::string SemanticVersion::Build() const
+{
+  return this->dataPtr->build;
+}
+
+/////////////////////////////////////////////////
+bool SemanticVersion::Parse(const std::string &_versionStr)
+{
+  if (_versionStr.empty())
+    return false;
+
+  size_t numericEnd = _versionStr.size();
+  size_t prereleaseStart = _versionStr.find("-");
+  size_t buildStart = _versionStr.find("+");
+
+  // Build meta data, if present, must be after prerelease string, if
+  // present
+  if (buildStart != std::string::npos &&
+      prereleaseStart != std::string::npos &&
+      buildStart < prereleaseStart)
+  {
+    return false;
+  }
+
+  // Check if a prerelease version is present
+  if (prereleaseStart != std::string::npos)
+  {
+    // Set the end of the numeric (major.minor.patch) portion to the
+    // start of the prerelease
+    numericEnd = prereleaseStart;
+
+    // Check if build metadata is present
+    if (buildStart != std::string::npos)
+    {
+      // Set prerelease to the portion between "-" and "+"
+      this->dataPtr->prerelease = _versionStr.substr(numericEnd + 1,
+           buildStart - numericEnd - 1);
+
+      // Get the build metadata.
+      this->dataPtr->build = _versionStr.substr(buildStart + 1);
+    }
+    else
+    {
+      // Set prerelease to the portion between "-" and the string's end
+      this->dataPtr->prerelease = _versionStr.substr(numericEnd + 1);
+    }
+  }
+  // Check if build metadata is present
+  else if (buildStart != std::string::npos)
+  {
+    // Set the end of the numeric (major.minor.patch) portion to the
+    // start of the build metadata
+    numericEnd = buildStart;
+    // Pre-release info can't follow the build metadata.
+    this->dataPtr->build = _versionStr.substr(numericEnd + 1);
+  }
+
+  std::string numeric = _versionStr.substr(0, numericEnd);
+  std::istringstream is(numeric);
+  std::string token;
+  for (int i = 0; std::getline(is, token, '.'); ++i)
+  {
+    switch (i)
+    {
+      default:
+      case 0:
+        this->dataPtr->maj = std::stoi(token);
+        break;
+      case 1:
+        this->dataPtr->min = std::stoi(token);
+        break;
+      case 2:
+        this->dataPtr->patch = std::stoi(token);
+        break;
+    };
+  }
+  return true;
+}
diff --git a/src/SemanticVersion_TEST.cc b/src/SemanticVersion_TEST.cc
new file mode 100644
index 0000000..66f60d2
--- /dev/null
+++ b/src/SemanticVersion_TEST.cc
@@ -0,0 +1,217 @@
+/*
+ * Copyright (C) 2016 Open Source Robotics Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+*/
+
+#include <gtest/gtest.h>
+
+#include "ignition/math/SemanticVersion.hh"
+
+using namespace ignition;
+using namespace math;
+
+/////////////////////////////////////////////////
+TEST(SemVerTest, Prerelease)
+{
+  SemanticVersion a("0.1.0");
+  SemanticVersion b("0.1.0-pr2");
+
+  EXPECT_TRUE(b < a);
+  EXPECT_TRUE(a.Prerelease().empty());
+  EXPECT_EQ(b.Prerelease(), "pr2");
+
+  EXPECT_EQ(b.Major(), a.Major());
+  EXPECT_EQ(b.Minor(), a.Minor());
+  EXPECT_EQ(b.Patch(), a.Patch());
+  EXPECT_EQ(b.Build(), a.Build());
+
+  EXPECT_EQ(a.Version(), "0.1.0");
+  EXPECT_EQ(b.Version(), "0.1.0-pr2");
+}
+
+/////////////////////////////////////////////////
+TEST(SemVerTest, Build)
+{
+  SemanticVersion a("0.1.0");
+  SemanticVersion b("0.1.0+012345");
+
+  EXPECT_TRUE(b == a);
+  EXPECT_TRUE(a.Build().empty());
+  EXPECT_EQ(b.Build(), "012345");
+
+  EXPECT_EQ(b.Major(), a.Major());
+  EXPECT_EQ(b.Minor(), a.Minor());
+  EXPECT_EQ(b.Patch(), a.Patch());
+  EXPECT_EQ(b.Prerelease(), a.Prerelease());
+
+  EXPECT_EQ(a.Version(), "0.1.0");
+  EXPECT_EQ(b.Version(), "0.1.0+012345");
+}
+
+/////////////////////////////////////////////////
+TEST(SemVerTest, PrereleaseBuild)
+{
+  SemanticVersion a("0.1.0");
+  SemanticVersion b("0.1.0-pr2");
+  SemanticVersion c("0.1.0+012345");
+  SemanticVersion d("0.1.0-pr2+012345");
+
+  EXPECT_EQ(a.Version(), "0.1.0");
+  EXPECT_EQ(b.Version(), "0.1.0-pr2");
+  EXPECT_EQ(c.Version(), "0.1.0+012345");
+  EXPECT_EQ(d.Version(), "0.1.0-pr2+012345");
+
+  EXPECT_TRUE(b < a);
+  EXPECT_TRUE(b < c);
+  EXPECT_TRUE(b == d);
+  EXPECT_TRUE(a == c);
+
+  EXPECT_EQ(a.Major(), b.Major());
+  EXPECT_EQ(a.Minor(), b.Minor());
+  EXPECT_EQ(a.Patch(), b.Patch());
+  EXPECT_TRUE(a.Prerelease().empty());
+  EXPECT_TRUE(a.Build().empty());
+
+  EXPECT_EQ(b.Major(), c.Major());
+  EXPECT_EQ(b.Minor(), c.Minor());
+  EXPECT_EQ(b.Patch(), c.Patch());
+  EXPECT_EQ(b.Prerelease(), d.Prerelease());
+
+  EXPECT_EQ(c.Major(), d.Major());
+  EXPECT_EQ(c.Minor(), d.Minor());
+  EXPECT_EQ(c.Patch(), d.Patch());
+  EXPECT_EQ(c.Build(), d.Build());
+
+  EXPECT_EQ(d.Build(), "012345");
+  EXPECT_EQ(d.Prerelease(), "pr2");
+}
+
+/////////////////////////////////////////////////
+TEST(SemVerTest, OperatorStreamOut)
+{
+  SemanticVersion a("0.1.0");
+  SemanticVersion b("0.1.0-pr2");
+  SemanticVersion c("0.1.0+012345");
+  SemanticVersion d("0.1.0-pr2+012345");
+
+  {
+    std::ostringstream stream;
+    stream << a;
+    EXPECT_EQ(stream.str(), "0.1.0");
+  }
+
+  {
+    std::ostringstream stream;
+    stream << b;
+    EXPECT_EQ(stream.str(), "0.1.0-pr2");
+  }
+
+  {
+    std::ostringstream stream;
+    stream << c;
+    EXPECT_EQ(stream.str(), "0.1.0+012345");
+  }
+
+  {
+    std::ostringstream stream;
+    stream << d;
+    EXPECT_EQ(stream.str(), "0.1.0-pr2+012345");
+  }
+}
+
+/////////////////////////////////////////////////
+TEST(SemVerTest, Operators)
+{
+  SemanticVersion a("0.1.0");
+  SemanticVersion b("1.0.0");
+  SemanticVersion c("1.0.0");
+  SemanticVersion c2("1.0.2");
+  SemanticVersion d("0.2.0");
+
+  // check that the short form is the same as the long one
+  SemanticVersion aa("0.1");
+  EXPECT_EQ(aa.Version(), "0.1.0");
+
+  // check second constructor
+  SemanticVersion c2b(1, 0, 2);
+  EXPECT_TRUE(c2 == c2b);
+
+  EXPECT_FALSE(a < a);
+  EXPECT_FALSE(b < a);
+  EXPECT_TRUE(a < d);
+  EXPECT_FALSE(d < a);
+
+  EXPECT_TRUE(a < b);
+  EXPECT_TRUE(a <= b);
+
+  // equality
+  EXPECT_TRUE(a != b);
+  EXPECT_TRUE(b == c);
+  EXPECT_FALSE(a == b);
+  EXPECT_FALSE(a != a);
+
+  // other operators
+  EXPECT_TRUE(b <= c);
+  EXPECT_TRUE(b >= c);
+  EXPECT_TRUE(c2 > c);
+  EXPECT_FALSE(c2 < c);
+  EXPECT_TRUE(b == b);
+}
+
+/////////////////////////////////////////////////
+TEST(SemVerTest, AssignCopy)
+{
+  SemanticVersion a("0.1+pr2");
+  SemanticVersion b("0.2");
+
+  SemanticVersion aa(a);
+  EXPECT_TRUE(a == aa);
+  SemanticVersion aaa = aa;
+  EXPECT_TRUE(a == aaa);
+  // change a
+  a = b;
+  // aaa unchanged
+  EXPECT_TRUE(aa == aaa);
+  // a and aaa now different
+  EXPECT_TRUE(a != aaa);
+}
+
+/////////////////////////////////////////////////
+TEST(SemVerTest, Parse)
+{
+  SemanticVersion a;
+  EXPECT_FALSE(a.Parse(""));
+  EXPECT_FALSE(a.Parse("0.1.2+1-1"));
+}
+
+/////////////////////////////////////////////////
+TEST(SemVerTest, Constructor)
+{
+  SemanticVersion a;
+
+  EXPECT_EQ(a.Major(), 0u);
+  EXPECT_EQ(a.Minor(), 0u);
+  EXPECT_EQ(a.Patch(), 0u);
+  EXPECT_TRUE(a.Prerelease().empty());
+  EXPECT_TRUE(a.Build().empty());
+}
+
+/////////////////////////////////////////////////
+int main(int argc, char **argv)
+{
+  ::testing::InitGoogleTest(&argc, argv);
+  return RUN_ALL_TESTS();
+}
+
diff --git a/src/SignalStats.cc b/src/SignalStats.cc
new file mode 100644
index 0000000..4523bef
--- /dev/null
+++ b/src/SignalStats.cc
@@ -0,0 +1,359 @@
+/*
+ * Copyright (C) 2015 Open Source Robotics Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+*/
+#include <cmath>
+#include <iostream>
+#include <ignition/math/SignalStats.hh>
+#include "SignalStatsPrivate.hh"
+
+using namespace ignition;
+using namespace math;
+
+//////////////////////////////////////////////////
+SignalStatistic::SignalStatistic()
+  : dataPtr(new SignalStatisticPrivate)
+{
+  this->dataPtr->data = 0.0;
+  this->dataPtr->extraData = 0.0;
+  this->dataPtr->count = 0;
+}
+
+//////////////////////////////////////////////////
+SignalStatistic::~SignalStatistic()
+{
+}
+
+//////////////////////////////////////////////////
+SignalStatistic::SignalStatistic(const SignalStatistic &_ss)
+  : dataPtr(_ss.dataPtr->Clone())
+{
+}
+
+//////////////////////////////////////////////////
+size_t SignalStatistic::Count() const
+{
+  return this->dataPtr->count;
+}
+
+//////////////////////////////////////////////////
+void SignalStatistic::Reset()
+{
+  this->dataPtr->data = 0;
+  this->dataPtr->count = 0;
+}
+
+//////////////////////////////////////////////////
+double SignalMaximum::Value() const
+{
+  return this->dataPtr->data;
+}
+
+//////////////////////////////////////////////////
+std::string SignalMaximum::ShortName() const
+{
+  return "max";
+}
+
+//////////////////////////////////////////////////
+void SignalMaximum::InsertData(const double _data)
+{
+  if (this->dataPtr->count == 0 || _data > this->dataPtr->data)
+  {
+    this->dataPtr->data = _data;
+  }
+  this->dataPtr->count++;
+}
+
+//////////////////////////////////////////////////
+double SignalMean::Value() const
+{
+  if (this->dataPtr->count == 0)
+  {
+    return 0;
+  }
+  return this->dataPtr->data / this->dataPtr->count;
+}
+
+//////////////////////////////////////////////////
+std::string SignalMean::ShortName() const
+{
+  return "mean";
+}
+
+//////////////////////////////////////////////////
+void SignalMean::InsertData(const double _data)
+{
+  this->dataPtr->data += _data;
+  this->dataPtr->count++;
+}
+
+//////////////////////////////////////////////////
+double SignalMinimum::Value() const
+{
+  return this->dataPtr->data;
+}
+
+//////////////////////////////////////////////////
+std::string SignalMinimum::ShortName() const
+{
+  return "min";
+}
+
+//////////////////////////////////////////////////
+void SignalMinimum::InsertData(const double _data)
+{
+  if (this->dataPtr->count == 0 || _data < this->dataPtr->data)
+  {
+    this->dataPtr->data = _data;
+  }
+  this->dataPtr->count++;
+}
+
+//////////////////////////////////////////////////
+double SignalRootMeanSquare::Value() const
+{
+  if (this->dataPtr->count == 0)
+  {
+    return 0;
+  }
+  return sqrt(this->dataPtr->data / this->dataPtr->count);
+}
+
+//////////////////////////////////////////////////
+std::string SignalRootMeanSquare::ShortName() const
+{
+  return "rms";
+}
+
+//////////////////////////////////////////////////
+void SignalRootMeanSquare::InsertData(const double _data)
+{
+  this->dataPtr->data += _data * _data;
+  this->dataPtr->count++;
+}
+
+//////////////////////////////////////////////////
+double SignalMaxAbsoluteValue::Value() const
+{
+  return this->dataPtr->data;
+}
+
+//////////////////////////////////////////////////
+std::string SignalMaxAbsoluteValue::ShortName() const
+{
+  return "maxAbs";
+}
+
+//////////////////////////////////////////////////
+void SignalMaxAbsoluteValue::InsertData(const double _data)
+{
+  double absData = std::abs(_data);
+  if (absData > this->dataPtr->data)
+  {
+    this->dataPtr->data = absData;
+  }
+  this->dataPtr->count++;
+}
+
+//////////////////////////////////////////////////
+// wikipedia.org/wiki/Algorithms_for_calculating_variance#Online_algorithm
+// based on Knuth's algorithm
+double SignalVariance::Value() const
+{
+  if (this->dataPtr->count < 2)
+    return 0.0;
+
+  // variance = M2 / (n - 1)
+  return this->dataPtr->data / (this->dataPtr->count - 1);
+}
+
+//////////////////////////////////////////////////
+std::string SignalVariance::ShortName() const
+{
+  return "var";
+}
+
+//////////////////////////////////////////////////
+// wikipedia.org/wiki/Algorithms_for_calculating_variance#Online_algorithm
+// based on Knuth's algorithm
+void SignalVariance::InsertData(const double _data)
+{
+  // n++
+  this->dataPtr->count++;
+
+  // delta = x - mean
+  double delta = _data - this->dataPtr->extraData;
+
+  // mean += delta / n
+  this->dataPtr->extraData += delta / this->dataPtr->count;
+
+  // M2 += delta*(x - mean)
+  this->dataPtr->data += delta * (_data - this->dataPtr->extraData);
+}
+
+//////////////////////////////////////////////////
+SignalStats::SignalStats()
+  : dataPtr(new SignalStatsPrivate)
+{
+}
+
+//////////////////////////////////////////////////
+SignalStats::~SignalStats()
+{
+}
+
+//////////////////////////////////////////////////
+SignalStats::SignalStats(const SignalStats &_ss)
+  : dataPtr(_ss.dataPtr->Clone())
+{
+}
+
+//////////////////////////////////////////////////
+size_t SignalStats::Count() const
+{
+  if (this->dataPtr->stats.empty())
+    return 0;
+
+  return this->dataPtr->stats.front()->Count();
+}
+
+//////////////////////////////////////////////////
+std::map<std::string, double> SignalStats::Map() const
+{
+  std::map<std::string, double> map;
+  for (auto const &statistic : this->dataPtr->stats)
+  {
+    map[statistic->ShortName()] = statistic->Value();
+  }
+  return map;
+}
+
+//////////////////////////////////////////////////
+void SignalStats::InsertData(const double _data)
+{
+  for (auto &statistic : this->dataPtr->stats)
+  {
+    statistic->InsertData(_data);
+  }
+}
+
+//////////////////////////////////////////////////
+bool SignalStats::InsertStatistic(const std::string &_name)
+{
+  // Check if the statistic is already inserted
+  {
+    auto map = this->Map();
+    if (map.find(_name) != map.end())
+    {
+      std::cerr << "Unable to InsertStatistic ["
+                << _name
+                << "] since it has already been inserted."
+                << std::endl;
+      return false;
+    }
+  }
+
+  SignalStatisticPtr stat;
+  if (_name == "max")
+  {
+    stat.reset(new SignalMaximum());
+  }
+  else if (_name == "maxAbs")
+  {
+    stat.reset(new SignalMaxAbsoluteValue());
+  }
+  else if (_name == "mean")
+  {
+    stat.reset(new SignalMean());
+  }
+  else if (_name == "min")
+  {
+    stat.reset(new SignalMinimum());
+  }
+  else if (_name == "rms")
+  {
+    stat.reset(new SignalRootMeanSquare());
+  }
+  else if (_name == "var")
+  {
+    stat.reset(new SignalVariance());
+  }
+  else
+  {
+    // Unrecognized name string
+    std::cerr << "Unable to InsertStatistic ["
+              << _name
+              << "] since it is an unrecognized name."
+              << std::endl;
+    return false;
+  }
+  this->dataPtr->stats.push_back(stat);
+  return true;
+}
+
+//////////////////////////////////////////////////
+bool SignalStats::InsertStatistics(const std::string &_names)
+{
+  if (_names.empty())
+  {
+    std::cerr << "Unable to InsertStatistics "
+              << "since no names were supplied."
+              << std::endl;
+    return false;
+  }
+
+  bool result = true;
+  std::vector<std::string> names;
+  // Replace the following with std::string functions
+  // boost::split(names, _names, boost::is_any_of(","));
+  // std::regex_token_iterator may be considered when it
+  // is supported by gcc
+  {
+    std::string::size_type start = 0;
+    std::string::size_type end = _names.find(',', start);
+    while (end != std::string::npos)
+    {
+      names.push_back(_names.substr(start, end-start));
+      start = end + 1;
+      end = _names.find(',', start);
+    }
+    if (start < _names.length())
+    {
+      names.push_back(_names.substr(start));
+    }
+  }
+  for (auto const &name : names)
+  {
+    result = result && this->InsertStatistic(name);
+  }
+  return result;
+}
+
+//////////////////////////////////////////////////
+void SignalStats::Reset()
+{
+  for (auto &statistic : this->dataPtr->stats)
+  {
+    statistic->Reset();
+  }
+}
+
+//////////////////////////////////////////////////
+SignalStats &SignalStats::operator=(const SignalStats &_s)
+{
+  this->dataPtr = _s.dataPtr->Clone();
+  return *this;
+}
diff --git a/src/SignalStatsPrivate.hh b/src/SignalStatsPrivate.hh
new file mode 100644
index 0000000..6c7240a
--- /dev/null
+++ b/src/SignalStatsPrivate.hh
@@ -0,0 +1,77 @@
+/*
+ * Copyright (C) 2015 Open Source Robotics Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+*/
+#ifndef IGNITION_MATH_SIGNALSTATSPRIVATE_HH_
+#define IGNITION_MATH_SIGNALSTATSPRIVATE_HH_
+
+#include <memory>
+#include <vector>
+
+namespace ignition
+{
+  namespace math
+  {
+    /// \brief Private data class for the SignalStatistic class.
+    class SignalStatisticPrivate
+    {
+      /// \brief Scalar representation of signal data.
+      public: double data;
+
+      /// \brief Scalar representation of extra signal data.
+      /// For example, the standard deviation statistic needs an extra variable.
+      public: double extraData;
+
+      /// \brief Count of data values in mean.
+      public: unsigned int count;
+
+      /// \brief Clone the SignalStatisticPrivate object. Used for implementing
+      /// copy semantics.
+      public: std::unique_ptr<SignalStatisticPrivate> Clone() const
+      {
+        std::unique_ptr<SignalStatisticPrivate> dataPtr(
+            new SignalStatisticPrivate(*this));
+        return dataPtr;
+      }
+    };
+
+    class SignalStatistic;
+
+    /// \def SignalStatisticPtr
+    /// \brief Shared pointer to SignalStatistic object
+    typedef std::shared_ptr<SignalStatistic> SignalStatisticPtr;
+
+    /// \def SignalStatistic_V
+    /// \brief Vector of SignalStatisticPtr
+    typedef std::vector<SignalStatisticPtr> SignalStatistic_V;
+
+    /// \brief Private data class for the SignalStats class.
+    class SignalStatsPrivate
+    {
+      /// \brief Vector of `SignalStatistic`s.
+      public: SignalStatistic_V stats;
+
+      /// \brief Clone the SignalStatsPrivate object. Used for implementing
+      /// copy semantics.
+      public: std::unique_ptr<SignalStatsPrivate> Clone() const
+      {
+        std::unique_ptr<SignalStatsPrivate> dataPtr(
+            new SignalStatsPrivate(*this));
+        return dataPtr;
+      }
+    };
+  }
+}
+#endif
diff --git a/src/SignalStats_TEST.cc b/src/SignalStats_TEST.cc
new file mode 100644
index 0000000..8024fb9
--- /dev/null
+++ b/src/SignalStats_TEST.cc
@@ -0,0 +1,641 @@
+/*
+ * Copyright (C) 2015 Open Source Robotics Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+*/
+
+#include <gtest/gtest.h>
+
+#include <ignition/math/Rand.hh>
+#include <ignition/math/SignalStats.hh>
+
+using namespace ignition;
+
+//////////////////////////////////////////////////
+TEST(SignalStatsTest, SignalMaximumConstructor)
+{
+  // Constructor
+  math::SignalMaximum max;
+  EXPECT_DOUBLE_EQ(max.Value(), 0.0);
+  EXPECT_EQ(max.Count(), 0u);
+  EXPECT_EQ(max.ShortName(), std::string("max"));
+
+  math::SignalMaximum maxCopy(max);
+
+  EXPECT_DOUBLE_EQ(max.Value(), maxCopy.Value());
+  EXPECT_EQ(max.Count(), maxCopy.Count());
+  EXPECT_EQ(max.ShortName(), maxCopy.ShortName());
+
+  // Reset
+  max.Reset();
+  EXPECT_DOUBLE_EQ(max.Value(), 0.0);
+  EXPECT_EQ(max.Count(), 0u);
+}
+
+//////////////////////////////////////////////////
+TEST(SignalStatsTest, SignalMaximumConstantValues)
+{
+  // Constant values, max should match
+  math::SignalMaximum max;
+  EXPECT_DOUBLE_EQ(max.Value(), 0.0);
+  EXPECT_EQ(max.Count(), 0u);
+
+  const double value = 3.14159;
+
+  // Loop two times to verify Reset
+  for (int j = 0; j < 2; ++j)
+  {
+    for (unsigned int i = 1; i <= 10; ++i)
+    {
+      max.InsertData(value);
+      EXPECT_DOUBLE_EQ(max.Value(), value);
+      EXPECT_EQ(max.Count(), i);
+    }
+
+    // Reset
+    max.Reset();
+    EXPECT_DOUBLE_EQ(max.Value(), 0.0);
+    EXPECT_EQ(max.Count(), 0u);
+  }
+}
+
+//////////////////////////////////////////////////
+TEST(SignalStatsTest, SignalMaximumAlternatingValues)
+{
+  // Values with alternating sign, increasing magnitude
+  // Should always match positive value
+  math::SignalMaximum max;
+  EXPECT_DOUBLE_EQ(max.Value(), 0.0);
+  EXPECT_EQ(max.Count(), 0u);
+
+  const double value = 3.14159;
+
+  // Loop two times to verify Reset
+  for (int j = 0; j < 2; ++j)
+  {
+    for (unsigned int i = 1; i <= 10; ++i)
+    {
+      max.InsertData(value * i);
+      EXPECT_DOUBLE_EQ(max.Value(), value * i);
+      max.InsertData(-value * i);
+      EXPECT_DOUBLE_EQ(max.Value(), value * i);
+      EXPECT_EQ(max.Count(), i*2);
+    }
+
+    // Reset
+    max.Reset();
+    EXPECT_DOUBLE_EQ(max.Value(), 0.0);
+    EXPECT_EQ(max.Count(), 0u);
+  }
+}
+
+//////////////////////////////////////////////////
+TEST(SignalStatsTest, SignalMean)
+{
+  {
+    // Constructor
+    math::SignalMean mean;
+    EXPECT_DOUBLE_EQ(mean.Value(), 0.0);
+    EXPECT_EQ(mean.Count(), 0u);
+    EXPECT_EQ(mean.ShortName(), std::string("mean"));
+
+    // Reset
+    mean.Reset();
+    EXPECT_DOUBLE_EQ(mean.Value(), 0.0);
+    EXPECT_EQ(mean.Count(), 0u);
+  }
+
+  {
+    // Constant values, mean should match
+    math::SignalMean mean;
+    EXPECT_DOUBLE_EQ(mean.Value(), 0.0);
+    EXPECT_EQ(mean.Count(), 0u);
+
+    const double value = 3.14159;
+
+    // Loop two times to verify Reset
+    for (int j = 0; j < 2; ++j)
+    {
+      for (unsigned int i = 1; i <= 10; ++i)
+      {
+        mean.InsertData(value);
+        EXPECT_DOUBLE_EQ(mean.Value(), value);
+        EXPECT_EQ(mean.Count(), i);
+      }
+
+      // Reset
+      mean.Reset();
+      EXPECT_DOUBLE_EQ(mean.Value(), 0.0);
+      EXPECT_EQ(mean.Count(), 0u);
+    }
+  }
+
+  {
+    // Values with alternating sign, increasing magnitude
+    // Should be zero every other time
+    math::SignalMean mean;
+    EXPECT_DOUBLE_EQ(mean.Value(), 0.0);
+    EXPECT_EQ(mean.Count(), 0u);
+
+    const double value = 3.14159;
+
+    // Loop two times to verify Reset
+    for (int j = 0; j < 2; ++j)
+    {
+      for (unsigned int i = 1; i <= 10; ++i)
+      {
+        mean.InsertData(value * i);
+        mean.InsertData(-value * i);
+        EXPECT_DOUBLE_EQ(mean.Value(), 0.0);
+        EXPECT_EQ(mean.Count(), i*2);
+      }
+
+      // Reset
+      mean.Reset();
+      EXPECT_DOUBLE_EQ(mean.Value(), 0.0);
+      EXPECT_EQ(mean.Count(), 0u);
+    }
+  }
+}
+
+//////////////////////////////////////////////////
+TEST(SignalStatsTest, SignalMinimumConstructor)
+{
+  // Constructor
+  math::SignalMinimum min;
+  EXPECT_DOUBLE_EQ(min.Value(), 0.0);
+  EXPECT_EQ(min.Count(), 0u);
+  EXPECT_EQ(min.ShortName(), std::string("min"));
+
+  // Reset
+  min.Reset();
+  EXPECT_DOUBLE_EQ(min.Value(), 0.0);
+  EXPECT_EQ(min.Count(), 0u);
+}
+
+//////////////////////////////////////////////////
+TEST(SignalStatsTest, SignalMinimumConstantValues)
+{
+  // Constant values, min should match
+  math::SignalMinimum min;
+  EXPECT_DOUBLE_EQ(min.Value(), 0.0);
+  EXPECT_EQ(min.Count(), 0u);
+
+  const double value = 3.14159;
+
+  // Loop two times to verify Reset
+  for (int j = 0; j < 2; ++j)
+  {
+    for (unsigned int i = 1; i <= 10; ++i)
+    {
+      min.InsertData(value);
+      EXPECT_DOUBLE_EQ(min.Value(), value);
+      EXPECT_EQ(min.Count(), i);
+    }
+
+    // Reset
+    min.Reset();
+    EXPECT_DOUBLE_EQ(min.Value(), 0.0);
+    EXPECT_EQ(min.Count(), 0u);
+  }
+}
+
+//////////////////////////////////////////////////
+TEST(SignalStatsTest, SignalMinimumAlternatingValues)
+{
+  // Values with alternating sign, increasing magnitude
+  // Should always match negative value
+  math::SignalMinimum min;
+  EXPECT_DOUBLE_EQ(min.Value(), 0.0);
+  EXPECT_EQ(min.Count(), 0u);
+
+  const double value = 3.14159;
+
+  // Loop two times to verify Reset
+  for (int j = 0; j < 2; ++j)
+  {
+    for (unsigned int i = 1; i <= 10; ++i)
+    {
+      min.InsertData(value * i);
+      min.InsertData(-value * i);
+      EXPECT_DOUBLE_EQ(min.Value(), -value * i);
+      EXPECT_EQ(min.Count(), i*2);
+    }
+
+    // Reset
+    min.Reset();
+    EXPECT_DOUBLE_EQ(min.Value(), 0.0);
+    EXPECT_EQ(min.Count(), 0u);
+  }
+}
+
+//////////////////////////////////////////////////
+TEST(SignalStatsTest, SignalRootMeanSquare)
+{
+  {
+    // Constructor
+    math::SignalRootMeanSquare rms;
+    EXPECT_DOUBLE_EQ(rms.Value(), 0.0);
+    EXPECT_EQ(rms.Count(), 0u);
+    EXPECT_EQ(rms.ShortName(), std::string("rms"));
+
+    // Reset
+    rms.Reset();
+    EXPECT_DOUBLE_EQ(rms.Value(), 0.0);
+    EXPECT_EQ(rms.Count(), 0u);
+  }
+
+  {
+    // Constant values, rms should match
+    math::SignalRootMeanSquare rms;
+    EXPECT_DOUBLE_EQ(rms.Value(), 0.0);
+    EXPECT_EQ(rms.Count(), 0u);
+
+    const double value = 3.14159;
+
+    // Loop two times to verify Reset
+    for (int j = 0; j < 2; ++j)
+    {
+      for (unsigned int i = 1; i <= 10; ++i)
+      {
+        rms.InsertData(value);
+        EXPECT_DOUBLE_EQ(rms.Value(), value);
+        EXPECT_EQ(rms.Count(), i);
+      }
+
+      // Reset
+      rms.Reset();
+      EXPECT_DOUBLE_EQ(rms.Value(), 0.0);
+      EXPECT_EQ(rms.Count(), 0u);
+    }
+  }
+
+  {
+    // Values with alternating sign, same magnitude
+    // rms should match absolute value every time
+    math::SignalRootMeanSquare rms;
+    EXPECT_DOUBLE_EQ(rms.Value(), 0.0);
+    EXPECT_EQ(rms.Count(), 0u);
+
+    const double value = 3.14159;
+
+    // Loop two times to verify Reset
+    for (int j = 0; j < 2; ++j)
+    {
+      for (unsigned int i = 1; i <= 10; ++i)
+      {
+        rms.InsertData(value);
+        EXPECT_DOUBLE_EQ(rms.Value(), value);
+        EXPECT_EQ(rms.Count(), i*2-1);
+
+        rms.InsertData(-value);
+        EXPECT_DOUBLE_EQ(rms.Value(), value);
+        EXPECT_EQ(rms.Count(), i*2);
+      }
+
+      // Reset
+      rms.Reset();
+      EXPECT_DOUBLE_EQ(rms.Value(), 0.0);
+      EXPECT_EQ(rms.Count(), 0u);
+    }
+  }
+}
+
+//////////////////////////////////////////////////
+TEST(SignalStatsTest, SignalMaxAbsoluteValue)
+{
+  {
+    // Constructor
+    math::SignalMaxAbsoluteValue max;
+    EXPECT_DOUBLE_EQ(max.Value(), 0.0);
+    EXPECT_EQ(max.Count(), 0u);
+    EXPECT_EQ(max.ShortName(), std::string("maxAbs"));
+
+    // Reset
+    max.Reset();
+    EXPECT_DOUBLE_EQ(max.Value(), 0.0);
+    EXPECT_EQ(max.Count(), 0u);
+  }
+
+  {
+    // Constant values, max should match
+    math::SignalMaxAbsoluteValue max;
+    EXPECT_DOUBLE_EQ(max.Value(), 0.0);
+    EXPECT_EQ(max.Count(), 0u);
+
+    const double value = 3.14159;
+
+    // Loop two times to verify Reset
+    for (int j = 0; j < 2; ++j)
+    {
+      for (unsigned int i = 1; i <= 10; ++i)
+      {
+        max.InsertData(value);
+        EXPECT_DOUBLE_EQ(max.Value(), value);
+        EXPECT_EQ(max.Count(), i);
+      }
+
+      // Reset
+      max.Reset();
+      EXPECT_DOUBLE_EQ(max.Value(), 0.0);
+      EXPECT_EQ(max.Count(), 0u);
+    }
+  }
+
+  {
+    // Values with alternating sign, increasing magnitude
+    // max should match absolute value every time
+    math::SignalMaxAbsoluteValue max;
+    EXPECT_DOUBLE_EQ(max.Value(), 0.0);
+    EXPECT_EQ(max.Count(), 0u);
+
+    const double value = 3.14159;
+
+    // Loop two times to verify Reset
+    for (int j = 0; j < 2; ++j)
+    {
+      for (unsigned int i = 1; i <= 10; ++i)
+      {
+        max.InsertData(value * i);
+        EXPECT_DOUBLE_EQ(max.Value(), value * i);
+        EXPECT_EQ(max.Count(), i*2-1);
+
+        max.InsertData(-value * i);
+        EXPECT_DOUBLE_EQ(max.Value(), value * i);
+        EXPECT_EQ(max.Count(), i*2);
+      }
+
+      // Reset
+      max.Reset();
+      EXPECT_DOUBLE_EQ(max.Value(), 0.0);
+      EXPECT_EQ(max.Count(), 0u);
+    }
+  }
+}
+
+//////////////////////////////////////////////////
+TEST(SignalStatsTest, SignalVarianceConstructor)
+{
+  // Constructor
+  math::SignalVariance var;
+  EXPECT_DOUBLE_EQ(var.Value(), 0.0);
+  EXPECT_EQ(var.Count(), 0u);
+  EXPECT_EQ(var.ShortName(), std::string("var"));
+
+  // Reset
+  var.Reset();
+  EXPECT_DOUBLE_EQ(var.Value(), 0.0);
+  EXPECT_EQ(var.Count(), 0u);
+}
+
+//////////////////////////////////////////////////
+TEST(SignalStatsTest, SignalVarianceOneValue)
+{
+  // Add one value, expect 0.0 variance
+  std::vector<double> values = {0, 1.0, 10.0, -100.0};
+  for (auto value : values)
+  {
+    math::SignalVariance var;
+    var.InsertData(value);
+    EXPECT_EQ(var.Count(), 1u);
+    EXPECT_DOUBLE_EQ(0.0, var.Value());
+
+    // Reset
+    var.Reset();
+    EXPECT_DOUBLE_EQ(0.0, var.Value());
+    EXPECT_EQ(var.Count(), 0u);
+  }
+}
+
+//////////////////////////////////////////////////
+TEST(SignalStatsTest, SignalVarianceConstantValues)
+{
+  // Constant values, expect 0.0 variance
+  math::SignalVariance var;
+  const double value = 3.14159;
+
+  // Loop two times to verify Reset
+  for (int j = 0; j < 2; ++j)
+  {
+    for (unsigned int i = 1; i <= 10; ++i)
+    {
+      var.InsertData(value);
+      EXPECT_DOUBLE_EQ(0.0, var.Value());
+      EXPECT_EQ(var.Count(), i);
+    }
+
+    // Reset
+    var.Reset();
+    EXPECT_DOUBLE_EQ(var.Value(), 0.0);
+    EXPECT_EQ(var.Count(), 0u);
+  }
+}
+
+//////////////////////////////////////////////////
+TEST(SignalStatsTest, SignalVarianceRandomValues)
+{
+  // Random normally distributed values
+  // The sample variance has the following variance:
+  // 2 variance^2 / (count - 1)
+  // en.wikipedia.org/wiki/Variance#Distribution_of_the_sample_variance
+  // We will use 5 sigma (4e-5 chance of failure)
+  math::SignalVariance var;
+  const double stdDev = 3.14159;
+  const int count = 10000;
+  const double sigma = 5.0;
+  for (int i = 0; i < count; ++i)
+  {
+    var.InsertData(math::Rand::DblNormal(0.0, stdDev));
+  }
+  const double variance = stdDev*stdDev;
+  double sampleVariance2 = 2 * variance*variance / (count - 1);
+  EXPECT_NEAR(var.Value(), variance, sigma*sqrt(sampleVariance2));
+  std::cout << "True variance " << variance
+            << ", measured variance " << var.Value()
+            << ", sigma " << sqrt(sampleVariance2)
+            << std::endl;
+
+  // Reset
+  var.Reset();
+  EXPECT_DOUBLE_EQ(var.Value(), 0.0);
+  EXPECT_EQ(var.Count(), 0u);
+}
+
+//////////////////////////////////////////////////
+TEST(SignalStatsTest, SignalStats)
+{
+  {
+    // Constructor
+    math::SignalStats stats;
+    EXPECT_TRUE(stats.Map().empty());
+    EXPECT_EQ(stats.Count(), 0u);
+
+    const math::SignalStats &stats2 = stats;
+    EXPECT_EQ(stats.Count(), stats2.Count());
+
+    // Reset
+    stats.Reset();
+    EXPECT_TRUE(stats.Map().empty());
+    EXPECT_EQ(stats.Count(), 0u);
+  }
+
+  {
+    // InsertStatistic
+    math::SignalStats stats;
+    EXPECT_TRUE(stats.Map().empty());
+
+    EXPECT_TRUE(stats.InsertStatistic("max"));
+    EXPECT_FALSE(stats.InsertStatistic("max"));
+    EXPECT_FALSE(stats.Map().empty());
+
+    EXPECT_TRUE(stats.InsertStatistic("maxAbs"));
+    EXPECT_FALSE(stats.InsertStatistic("maxAbs"));
+    EXPECT_FALSE(stats.Map().empty());
+
+    EXPECT_TRUE(stats.InsertStatistic("mean"));
+    EXPECT_FALSE(stats.InsertStatistic("mean"));
+    EXPECT_FALSE(stats.Map().empty());
+
+    EXPECT_TRUE(stats.InsertStatistic("min"));
+    EXPECT_FALSE(stats.InsertStatistic("min"));
+    EXPECT_FALSE(stats.Map().empty());
+
+    EXPECT_TRUE(stats.InsertStatistic("rms"));
+    EXPECT_FALSE(stats.InsertStatistic("rms"));
+    EXPECT_FALSE(stats.Map().empty());
+
+    EXPECT_TRUE(stats.InsertStatistic("var"));
+    EXPECT_FALSE(stats.InsertStatistic("var"));
+    EXPECT_FALSE(stats.Map().empty());
+
+    EXPECT_FALSE(stats.InsertStatistic("FakeStatistic"));
+
+    // Map with no data
+    std::map<std::string, double> map = stats.Map();
+    EXPECT_FALSE(map.empty());
+    EXPECT_EQ(map.size(), 6u);
+    EXPECT_EQ(map.count("max"), 1u);
+    EXPECT_EQ(map.count("maxAbs"), 1u);
+    EXPECT_EQ(map.count("mean"), 1u);
+    EXPECT_EQ(map.count("min"), 1u);
+    EXPECT_EQ(map.count("rms"), 1u);
+    EXPECT_EQ(map.count("var"), 1u);
+    EXPECT_EQ(map.count("FakeStatistic"), 0u);
+
+    math::SignalStats stats2(stats);
+    std::map<std::string, double> map2 = stats2.Map();
+    EXPECT_FALSE(map2.empty());
+    EXPECT_EQ(map.size(), map2.size());
+    EXPECT_EQ(map.count("max"), map2.count("max"));
+    EXPECT_EQ(map.count("maxAbs"), map2.count("maxAbs"));
+    EXPECT_EQ(map.count("mean"), map2.count("mean"));
+    EXPECT_EQ(map.count("min"), map2.count("min"));
+    EXPECT_EQ(map.count("rms"), map2.count("rms"));
+    EXPECT_EQ(map.count("var"), map2.count("var"));
+    EXPECT_EQ(map.count("FakeStatistic"), map2.count("FakeStatistic"));
+  }
+
+  {
+    // InsertStatistics
+    math::SignalStats stats;
+    EXPECT_FALSE(stats.InsertStatistics(""));
+    EXPECT_TRUE(stats.Map().empty());
+
+    EXPECT_TRUE(stats.InsertStatistics("maxAbs,rms"));
+    EXPECT_EQ(stats.Map().size(), 2u);
+    EXPECT_FALSE(stats.InsertStatistics("maxAbs,rms"));
+    EXPECT_FALSE(stats.InsertStatistics("maxAbs"));
+    EXPECT_FALSE(stats.InsertStatistics("rms"));
+    EXPECT_EQ(stats.Map().size(), 2u);
+
+    EXPECT_FALSE(stats.InsertStatistics("mean,FakeStatistic"));
+    EXPECT_EQ(stats.Map().size(), 3u);
+
+    EXPECT_FALSE(stats.InsertStatistics("var,FakeStatistic"));
+    EXPECT_EQ(stats.Map().size(), 4u);
+
+    EXPECT_FALSE(stats.InsertStatistics("max,FakeStatistic"));
+    EXPECT_EQ(stats.Map().size(), 5u);
+
+    EXPECT_FALSE(stats.InsertStatistics("min,FakeStatistic"));
+    EXPECT_EQ(stats.Map().size(), 6u);
+
+    EXPECT_FALSE(stats.InsertStatistics("FakeStatistic"));
+    EXPECT_EQ(stats.Map().size(), 6u);
+
+    // Map with no data
+    std::map<std::string, double> map = stats.Map();
+    EXPECT_FALSE(map.empty());
+    EXPECT_EQ(map.size(), 6u);
+    EXPECT_EQ(map.count("max"), 1u);
+    EXPECT_EQ(map.count("maxAbs"), 1u);
+    EXPECT_EQ(map.count("mean"), 1u);
+    EXPECT_EQ(map.count("min"), 1u);
+    EXPECT_EQ(map.count("rms"), 1u);
+    EXPECT_EQ(map.count("var"), 1u);
+    EXPECT_EQ(map.count("FakeStatistic"), 0u);
+  }
+
+  {
+    // Add some statistics
+    math::SignalStats stats;
+    EXPECT_TRUE(stats.InsertStatistics("max,maxAbs,mean,min,rms"));
+    EXPECT_EQ(stats.Map().size(), 5u);
+
+    // No data yet
+    EXPECT_EQ(stats.Count(), 0u);
+
+    // Insert data with alternating signs
+    const double value = 3.14159;
+    stats.InsertData(value);
+    stats.InsertData(-value);
+    EXPECT_EQ(stats.Count(), 2u);
+
+    {
+      std::map<std::string, double> map = stats.Map();
+      EXPECT_DOUBLE_EQ(map["max"], value);
+      EXPECT_DOUBLE_EQ(map["maxAbs"], value);
+      EXPECT_DOUBLE_EQ(map["min"], -value);
+      EXPECT_DOUBLE_EQ(map["rms"], value);
+      EXPECT_DOUBLE_EQ(map["mean"], 0.0);
+    }
+
+    // test operator=
+    {
+      math::SignalStats copy;
+      copy = stats;
+      EXPECT_EQ(copy.Count(), 2u);
+      auto map = stats.Map();
+      EXPECT_EQ(map.size(), 5u);
+      EXPECT_DOUBLE_EQ(map["max"], value);
+      EXPECT_DOUBLE_EQ(map["maxAbs"], value);
+      EXPECT_DOUBLE_EQ(map["min"], -value);
+      EXPECT_DOUBLE_EQ(map["rms"], value);
+      EXPECT_DOUBLE_EQ(map["mean"], 0.0);
+    }
+
+    stats.Reset();
+    EXPECT_EQ(stats.Map().size(), 5u);
+    EXPECT_EQ(stats.Count(), 0u);
+    {
+      std::map<std::string, double> map = stats.Map();
+      EXPECT_DOUBLE_EQ(map["max"], 0.0);
+      EXPECT_DOUBLE_EQ(map["maxAbs"], 0.0);
+      EXPECT_DOUBLE_EQ(map["min"], 0.0);
+      EXPECT_DOUBLE_EQ(map["rms"], 0.0);
+      EXPECT_DOUBLE_EQ(map["mean"], 0.0);
+    }
+  }
+}
+
diff --git a/src/SphericalCoordinates.cc b/src/SphericalCoordinates.cc
new file mode 100644
index 0000000..9beb891
--- /dev/null
+++ b/src/SphericalCoordinates.cc
@@ -0,0 +1,557 @@
+/*
+ * Copyright (C) 2012 Open Source Robotics Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+*/
+#include <string>
+
+#include "ignition/math/Matrix3.hh"
+#include "ignition/math/SphericalCoordinates.hh"
+
+using namespace ignition;
+using namespace math;
+
+// Parameters for EARTH_WGS84 model
+// wikipedia: World_Geodetic_System#A_new_World_Geodetic_System:_WGS_84
+
+// a: Equatorial radius. Semi-major axis of the WGS84 spheroid (meters).
+const double g_EarthWGS84AxisEquatorial = 6378137.0;
+
+// b: Polar radius. Semi-minor axis of the wgs84 spheroid (meters).
+const double g_EarthWGS84AxisPolar = 6356752.314245;
+
+// if: WGS84 inverse flattening parameter (no units)
+const double g_EarthWGS84Flattening = 1.0/298.257223563;
+
+// Radius of the Earth (meters).
+const double g_EarthRadius = 6371000.0;
+
+// Private data for the SphericalCoordinates class.
+class ignition::math::SphericalCoordinatesPrivate
+{
+  /// \brief Type of surface being used.
+  public: SphericalCoordinates::SurfaceType surfaceType;
+
+  /// \brief Latitude of reference point.
+  public: ignition::math::Angle latitudeReference;
+
+  /// \brief Longitude of reference point.
+  public: ignition::math::Angle longitudeReference;
+
+  /// \brief Elevation of reference point relative to sea level in meters.
+  public: double elevationReference;
+
+  /// \brief Heading offset, expressed as angle from East to
+  ///        gazebo x-axis, or equivalently from North to gazebo y-axis.
+  public: ignition::math::Angle headingOffset;
+
+  /// \brief Semi-major axis ellipse parameter
+  public: double ellA;
+
+  /// \brief Semi-minor axis ellipse parameter
+  public: double ellB;
+
+  /// \brief Flattening ellipse parameter
+  public: double ellF;
+
+  /// \brief First eccentricity ellipse parameter
+  public: double ellE;
+
+  /// \brief Second eccentricity ellipse parameter
+  public: double ellP;
+
+  /// \brief Rotation matrix that moves ECEF to GLOBAL
+  public: ignition::math::Matrix3d rotECEFToGlobal;
+
+  /// \brief Rotation matrix that moves GLOBAL to ECEF
+  public: ignition::math::Matrix3d rotGlobalToECEF;
+
+  /// \brief Cache the ECEF position of the the origin
+  public: ignition::math::Vector3d origin;
+
+  /// \brief Cache cosine head transform
+  public: double cosHea;
+
+  /// \brief Cache sine head transform
+  public: double sinHea;
+};
+
+//////////////////////////////////////////////////
+SphericalCoordinates::SurfaceType SphericalCoordinates::Convert(
+  const std::string &_str)
+{
+  if ("EARTH_WGS84" == _str)
+    return EARTH_WGS84;
+
+  std::cerr << "SurfaceType string not recognized, "
+    << "EARTH_WGS84 returned by default" << std::endl;
+  return EARTH_WGS84;
+}
+
+//////////////////////////////////////////////////
+SphericalCoordinates::SphericalCoordinates()
+  : dataPtr(new SphericalCoordinatesPrivate)
+{
+  this->SetSurface(EARTH_WGS84);
+  this->SetElevationReference(0.0);
+}
+
+//////////////////////////////////////////////////
+SphericalCoordinates::SphericalCoordinates(const SurfaceType _type)
+  : dataPtr(new SphericalCoordinatesPrivate)
+{
+  this->SetSurface(_type);
+  this->SetElevationReference(0.0);
+}
+
+//////////////////////////////////////////////////
+SphericalCoordinates::SphericalCoordinates(const SurfaceType _type,
+    const ignition::math::Angle &_latitude,
+    const ignition::math::Angle &_longitude,
+    const double _elevation,
+    const ignition::math::Angle &_heading)
+: dataPtr(new SphericalCoordinatesPrivate)
+{
+  // Set the reference and calculate ellipse parameters
+  this->SetSurface(_type);
+
+  // Set the coordinate transform parameters
+  this->dataPtr->latitudeReference = _latitude;
+  this->dataPtr->longitudeReference = _longitude;
+  this->dataPtr->elevationReference = _elevation;
+  this->dataPtr->headingOffset = _heading;
+
+  // Generate transformation matrix
+  this->UpdateTransformationMatrix();
+}
+
+//////////////////////////////////////////////////
+SphericalCoordinates::SphericalCoordinates(const SphericalCoordinates &_sc)
+  : SphericalCoordinates()
+{
+  (*this) = _sc;
+}
+
+//////////////////////////////////////////////////
+SphericalCoordinates::~SphericalCoordinates()
+{
+}
+
+//////////////////////////////////////////////////
+SphericalCoordinates::SurfaceType SphericalCoordinates::Surface() const
+{
+  return this->dataPtr->surfaceType;
+}
+
+//////////////////////////////////////////////////
+ignition::math::Angle SphericalCoordinates::LatitudeReference() const
+{
+  return this->dataPtr->latitudeReference;
+}
+
+//////////////////////////////////////////////////
+ignition::math::Angle SphericalCoordinates::LongitudeReference() const
+{
+  return this->dataPtr->longitudeReference;
+}
+
+//////////////////////////////////////////////////
+double SphericalCoordinates::ElevationReference() const
+{
+  return this->dataPtr->elevationReference;
+}
+
+//////////////////////////////////////////////////
+ignition::math::Angle SphericalCoordinates::HeadingOffset() const
+{
+  return this->dataPtr->headingOffset;
+}
+
+//////////////////////////////////////////////////
+void SphericalCoordinates::SetSurface(const SurfaceType &_type)
+{
+  this->dataPtr->surfaceType = _type;
+
+  switch (this->dataPtr->surfaceType)
+  {
+    case EARTH_WGS84:
+      {
+      // Set the semi-major axis
+      this->dataPtr->ellA = g_EarthWGS84AxisEquatorial;
+
+      // Set the semi-minor axis
+      this->dataPtr->ellB = g_EarthWGS84AxisPolar;
+
+      // Set the flattening parameter
+      this->dataPtr->ellF = g_EarthWGS84Flattening;
+
+      // Set the first eccentricity ellipse parameter
+      // https://en.wikipedia.org/wiki/Eccentricity_(mathematics)#Ellipses
+      this->dataPtr->ellE = sqrt(1.0 -
+          std::pow(this->dataPtr->ellB, 2) / std::pow(this->dataPtr->ellA, 2));
+
+      // Set the second eccentricity ellipse parameter
+      // https://en.wikipedia.org/wiki/Eccentricity_(mathematics)#Ellipses
+      this->dataPtr->ellP = sqrt(
+          std::pow(this->dataPtr->ellA, 2) / std::pow(this->dataPtr->ellB, 2) -
+          1.0);
+
+      break;
+      }
+    default:
+      {
+        std::cerr << "Unknown surface type["
+          << this->dataPtr->surfaceType << "]\n";
+      break;
+      }
+  }
+}
+
+//////////////////////////////////////////////////
+void SphericalCoordinates::SetLatitudeReference(
+    const ignition::math::Angle &_angle)
+{
+  this->dataPtr->latitudeReference = _angle;
+  this->UpdateTransformationMatrix();
+}
+
+//////////////////////////////////////////////////
+void SphericalCoordinates::SetLongitudeReference(
+    const ignition::math::Angle &_angle)
+{
+  this->dataPtr->longitudeReference = _angle;
+  this->UpdateTransformationMatrix();
+}
+
+//////////////////////////////////////////////////
+void SphericalCoordinates::SetElevationReference(const double _elevation)
+{
+  this->dataPtr->elevationReference = _elevation;
+  this->UpdateTransformationMatrix();
+}
+
+//////////////////////////////////////////////////
+void SphericalCoordinates::SetHeadingOffset(const ignition::math::Angle &_angle)
+{
+  this->dataPtr->headingOffset.Radian(_angle.Radian());
+  this->UpdateTransformationMatrix();
+}
+
+//////////////////////////////////////////////////
+ignition::math::Vector3d SphericalCoordinates::SphericalFromLocalPosition(
+    const ignition::math::Vector3d &_xyz) const
+{
+  ignition::math::Vector3d result =
+    this->PositionTransform(_xyz, LOCAL, SPHERICAL);
+  result.X(IGN_RTOD(result.X()));
+  result.Y(IGN_RTOD(result.Y()));
+  return result;
+}
+
+//////////////////////////////////////////////////
+ignition::math::Vector3d SphericalCoordinates::LocalFromSphericalPosition(
+    const ignition::math::Vector3d &_xyz) const
+{
+  ignition::math::Vector3d result = _xyz;
+  result.X(IGN_DTOR(result.X()));
+  result.Y(IGN_DTOR(result.Y()));
+  return this->PositionTransform(result, SPHERICAL, LOCAL);
+}
+
+//////////////////////////////////////////////////
+ignition::math::Vector3d SphericalCoordinates::GlobalFromLocalVelocity(
+    const ignition::math::Vector3d &_xyz) const
+{
+  return this->VelocityTransform(_xyz, LOCAL, GLOBAL);
+}
+
+//////////////////////////////////////////////////
+ignition::math::Vector3d SphericalCoordinates::LocalFromGlobalVelocity(
+    const ignition::math::Vector3d &_xyz) const
+{
+  return this->VelocityTransform(_xyz, GLOBAL, LOCAL);
+}
+
+//////////////////////////////////////////////////
+/// Based on Haversine formula (http://en.wikipedia.org/wiki/Haversine_formula).
+double SphericalCoordinates::Distance(const ignition::math::Angle &_latA,
+                                      const ignition::math::Angle &_lonA,
+                                      const ignition::math::Angle &_latB,
+                                      const ignition::math::Angle &_lonB)
+{
+  ignition::math::Angle dLat = _latB - _latA;
+  ignition::math::Angle dLon = _lonB - _lonA;
+
+  double a = sin(dLat.Radian() / 2) * sin(dLat.Radian() / 2) +
+             sin(dLon.Radian() / 2) * sin(dLon.Radian() / 2) *
+             cos(_latA.Radian()) * cos(_latB.Radian());
+
+  double c = 2 * atan2(sqrt(a), sqrt(1 - a));
+  double d = g_EarthRadius * c;
+  return d;
+}
+
+//////////////////////////////////////////////////
+void SphericalCoordinates::UpdateTransformationMatrix()
+{
+  // Cache trig results
+  double cosLat = cos(this->dataPtr->latitudeReference.Radian());
+  double sinLat = sin(this->dataPtr->latitudeReference.Radian());
+  double cosLon = cos(this->dataPtr->longitudeReference.Radian());
+  double sinLon = sin(this->dataPtr->longitudeReference.Radian());
+
+  // Create a rotation matrix that moves ECEF to GLOBAL
+  // http://www.navipedia.net/index.php/
+  // Transformations_between_ECEF_and_ENU_coordinates
+  this->dataPtr->rotECEFToGlobal = ignition::math::Matrix3d(
+                      -sinLon,           cosLon,          0.0,
+                      -cosLon * sinLat, -sinLon * sinLat, cosLat,
+                       cosLon * cosLat,  sinLon * cosLat, sinLat);
+
+  // Create a rotation matrix that moves GLOBAL to ECEF
+  // http://www.navipedia.net/index.php/
+  // Transformations_between_ECEF_and_ENU_coordinates
+  this->dataPtr->rotGlobalToECEF = ignition::math::Matrix3d(
+                      -sinLon, -cosLon * sinLat, cosLon * cosLat,
+                       cosLon, -sinLon * sinLat, sinLon * cosLat,
+                       0,      cosLat,           sinLat);
+
+  // Cache heading transforms -- note that we have to negate the heading in
+  // order to preserve backward compatibility. ie. Gazebo has traditionally
+  // expressed positive angle as a CLOCKWISE rotation that takes the GLOBAL
+  // frame to the LOCAL frame. However, right hand coordinate systems require
+  // this to be expressed as an ANTI-CLOCKWISE rotation. So, we negate it.
+  this->dataPtr->cosHea = cos(-this->dataPtr->headingOffset.Radian());
+  this->dataPtr->sinHea = sin(-this->dataPtr->headingOffset.Radian());
+
+  // Cache the ECEF coordinate of the origin
+  this->dataPtr->origin = ignition::math::Vector3d(
+    this->dataPtr->latitudeReference.Radian(),
+    this->dataPtr->longitudeReference.Radian(),
+    this->dataPtr->elevationReference);
+  this->dataPtr->origin =
+    this->PositionTransform(this->dataPtr->origin, SPHERICAL, ECEF);
+}
+
+/////////////////////////////////////////////////
+ignition::math::Vector3d SphericalCoordinates::PositionTransform(
+    const ignition::math::Vector3d &_pos,
+    const CoordinateType &_in, const CoordinateType &_out) const
+{
+  ignition::math::Vector3d tmp = _pos;
+
+  // Cache trig results
+  double cosLat = cos(_pos.X());
+  double sinLat = sin(_pos.X());
+  double cosLon = cos(_pos.Y());
+  double sinLon = sin(_pos.Y());
+
+  // Radius of planet curvature (meters)
+  double curvature = 1.0 -
+    this->dataPtr->ellE * this->dataPtr->ellE * sinLat * sinLat;
+  curvature = this->dataPtr->ellA / sqrt(curvature);
+
+  // Convert whatever arrives to a more flexible ECEF coordinate
+  switch (_in)
+  {
+    // East, North, Up (ENU), note no break at end of case
+    case LOCAL:
+      {
+        tmp.X(-_pos.X() * this->dataPtr->cosHea + _pos.Y() *
+            this->dataPtr->sinHea);
+        tmp.Y(-_pos.X() * this->dataPtr->sinHea - _pos.Y() *
+            this->dataPtr->cosHea);
+      }
+
+    case GLOBAL:
+      {
+        tmp = this->dataPtr->origin + this->dataPtr->rotGlobalToECEF * tmp;
+        break;
+      }
+
+    case SPHERICAL:
+      {
+        tmp.X((_pos.Z() + curvature) * cosLat * cosLon);
+        tmp.Y((_pos.Z() + curvature) * cosLat * sinLon);
+        tmp.Z(((this->dataPtr->ellB * this->dataPtr->ellB)/
+              (this->dataPtr->ellA * this->dataPtr->ellA) *
+              curvature + _pos.Z()) * sinLat);
+        break;
+      }
+
+    // Do nothing
+    case ECEF:
+      break;
+    default:
+      {
+        std::cerr << "Invalid coordinate type[" << _in << "]\n";
+        return _pos;
+      }
+  }
+
+  // Convert ECEF to the requested output coordinate system
+  switch (_out)
+  {
+    case SPHERICAL:
+      {
+        // Convert from ECEF to SPHERICAL
+        double p = sqrt(tmp.X() * tmp.X() + tmp.Y() * tmp.Y());
+        double theta = atan((tmp.Z() * this->dataPtr->ellA) /
+            (p * this->dataPtr->ellB));
+
+        // Calculate latitude and longitude
+        double lat = atan(
+            (tmp.Z() + std::pow(this->dataPtr->ellP, 2) * this->dataPtr->ellB *
+             std::pow(sin(theta), 3)) /
+            (p - std::pow(this->dataPtr->ellE, 2) *
+             this->dataPtr->ellA * std::pow(cos(theta), 3)));
+
+        double lon = atan2(tmp.Y(), tmp.X());
+
+        // Recalculate radius of planet curvature at the current latitude.
+        double nCurvature = 1.0 - std::pow(this->dataPtr->ellE, 2) *
+          std::pow(sin(lat), 2);
+        nCurvature = this->dataPtr->ellA / sqrt(nCurvature);
+
+        tmp.X(lat);
+        tmp.Y(lon);
+
+        // Now calculate Z
+        tmp.Z(p/cos(lat) - nCurvature);
+        break;
+      }
+
+    // Convert from ECEF TO GLOBAL
+    case GLOBAL:
+      tmp = this->dataPtr->rotECEFToGlobal * (tmp - this->dataPtr->origin);
+      break;
+
+    // Convert from ECEF TO LOCAL
+    case LOCAL:
+      tmp = this->dataPtr->rotECEFToGlobal * (tmp - this->dataPtr->origin);
+
+      tmp = ignition::math::Vector3d(
+          tmp.X() * this->dataPtr->cosHea - tmp.Y() * this->dataPtr->sinHea,
+          tmp.X() * this->dataPtr->sinHea + tmp.Y() * this->dataPtr->cosHea,
+          tmp.Z());
+      break;
+
+    // Return ECEF (do nothing)
+    case ECEF:
+      break;
+
+    default:
+      std::cerr << "Unknown coordinate type[" << _out << "]\n";
+      return _pos;
+  }
+
+  return tmp;
+}
+
+//////////////////////////////////////////////////
+ignition::math::Vector3d SphericalCoordinates::VelocityTransform(
+    const ignition::math::Vector3d &_vel,
+    const CoordinateType &_in, const CoordinateType &_out) const
+{
+  // Sanity check -- velocity should not be expressed in spherical coordinates
+  if (_in == SPHERICAL || _out == SPHERICAL)
+  {
+    return _vel;
+  }
+
+  // Intermediate data type
+  ignition::math::Vector3d tmp = _vel;
+
+  // First, convert to an ECEF vector
+  switch (_in)
+  {
+    // ENU (note no break at end of case)
+    case LOCAL:
+      tmp.X(-_vel.X() * this->dataPtr->cosHea + _vel.Y() *
+            this->dataPtr->sinHea);
+      tmp.Y(-_vel.X() * this->dataPtr->sinHea - _vel.Y() *
+            this->dataPtr->cosHea);
+    // spherical
+    case GLOBAL:
+      tmp = this->dataPtr->rotGlobalToECEF * tmp;
+      break;
+    // Do nothing
+    case ECEF:
+      tmp = _vel;
+      break;
+    default:
+      std::cerr << "Unknown coordinate type[" << _in << "]\n";
+      return _vel;
+  }
+
+  // Then, convert to the request coordinate type
+  switch (_out)
+  {
+    // ECEF, do nothing
+    case ECEF:
+      break;
+
+    // Convert from ECEF to global
+    case GLOBAL:
+      tmp = this->dataPtr->rotECEFToGlobal * tmp;
+      break;
+
+    // Convert from ECEF to local
+    case LOCAL:
+      tmp = this->dataPtr->rotECEFToGlobal * tmp;
+      tmp = ignition::math::Vector3d(
+          tmp.X() * this->dataPtr->cosHea - tmp.Y() * this->dataPtr->sinHea,
+          tmp.X() * this->dataPtr->sinHea + tmp.Y() * this->dataPtr->cosHea,
+          tmp.Z());
+      break;
+
+    default:
+      std::cerr << "Unknown coordinate type[" << _out << "]\n";
+      return _vel;
+  }
+
+  return tmp;
+}
+
+//////////////////////////////////////////////////
+bool SphericalCoordinates::operator==(const SphericalCoordinates &_sc) const
+{
+  return this->Surface() == _sc.Surface() &&
+         this->LatitudeReference() == _sc.LatitudeReference() &&
+         this->LongitudeReference() == _sc.LongitudeReference() &&
+         math::equal(this->ElevationReference(), _sc.ElevationReference()) &&
+         this->HeadingOffset() == _sc.HeadingOffset();
+}
+
+//////////////////////////////////////////////////
+bool SphericalCoordinates::operator!=(const SphericalCoordinates &_sc) const
+{
+  return !(*this == _sc);
+}
+
+//////////////////////////////////////////////////
+SphericalCoordinates &SphericalCoordinates::operator=(
+  const SphericalCoordinates &_sc)
+{
+  this->SetSurface(_sc.Surface());
+  this->SetLatitudeReference(_sc.LatitudeReference());
+  this->SetLongitudeReference(_sc.LongitudeReference());
+  this->SetElevationReference(_sc.ElevationReference());
+  this->SetHeadingOffset(_sc.HeadingOffset());
+
+  // Generate transformation matrix
+  this->UpdateTransformationMatrix();
+
+  return *this;
+}
diff --git a/src/SphericalCoordinates_TEST.cc b/src/SphericalCoordinates_TEST.cc
new file mode 100644
index 0000000..b7b1159
--- /dev/null
+++ b/src/SphericalCoordinates_TEST.cc
@@ -0,0 +1,385 @@
+/*
+ * Copyright (C) 2012 Open Source Robotics Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+*/
+#include <gtest/gtest.h>
+
+#include "ignition/math/SphericalCoordinates.hh"
+
+using namespace ignition;
+
+//////////////////////////////////////////////////
+// Test different constructors, default parameters
+TEST(SphericalCoordinatesTest, Constructor)
+{
+  // Default surface type
+  math::SphericalCoordinates::SurfaceType st =
+    math::SphericalCoordinates::EARTH_WGS84;
+
+  // No arguments, default parameters
+  {
+    math::SphericalCoordinates sc;
+    EXPECT_EQ(sc.Surface(), st);
+    EXPECT_EQ(sc.LatitudeReference(), ignition::math::Angle());
+    EXPECT_EQ(sc.LongitudeReference(), ignition::math::Angle());
+    EXPECT_EQ(sc.HeadingOffset(), ignition::math::Angle());
+    EXPECT_NEAR(sc.ElevationReference(), 0.0, 1e-6);
+  }
+
+  // SurfaceType argument, default parameters
+  {
+    math::SphericalCoordinates sc(st);
+    EXPECT_EQ(sc.Surface(), st);
+    EXPECT_EQ(sc.LatitudeReference(), ignition::math::Angle());
+    EXPECT_EQ(sc.LongitudeReference(), ignition::math::Angle());
+    EXPECT_EQ(sc.HeadingOffset(), ignition::math::Angle());
+    EXPECT_NEAR(sc.ElevationReference(), 0.0, 1e-6);
+  }
+
+  // All arguments
+  {
+    ignition::math::Angle lat(0.3), lon(-1.2), heading(0.5);
+    double elev = 354.1;
+    math::SphericalCoordinates sc(st, lat, lon, elev, heading);
+    EXPECT_EQ(sc.Surface(), st);
+    EXPECT_EQ(sc.LatitudeReference(), lat);
+    EXPECT_EQ(sc.LongitudeReference(), lon);
+    EXPECT_EQ(sc.HeadingOffset(), heading);
+    EXPECT_NEAR(sc.ElevationReference(), elev, 1e-6);
+
+    // Copy constructor
+    math::SphericalCoordinates sc2(sc);
+    EXPECT_EQ(sc, sc2);
+  }
+}
+
+//////////////////////////////////////////////////
+// SurfaceType Convert function
+TEST(SphericalCoordinatesTest, Convert)
+{
+  // Default surface type
+  math::SphericalCoordinates::SurfaceType st =
+    math::SphericalCoordinates::EARTH_WGS84;
+
+  EXPECT_EQ(math::SphericalCoordinates::Convert("EARTH_WGS84"), st);
+
+  EXPECT_EQ(math::SphericalCoordinates::EARTH_WGS84,
+            math::SphericalCoordinates::Convert("OTHER-COORD"));
+}
+
+//////////////////////////////////////////////////
+// Test Set functions
+TEST(SphericalCoordinatesTest, SetFunctions)
+{
+  // Default surface type
+  math::SphericalCoordinates::SurfaceType st =
+    math::SphericalCoordinates::EARTH_WGS84;
+
+  // Default parameters
+  math::SphericalCoordinates sc;
+  EXPECT_EQ(sc.Surface(), st);
+  EXPECT_EQ(sc.LatitudeReference(), ignition::math::Angle());
+  EXPECT_EQ(sc.LongitudeReference(), ignition::math::Angle());
+  EXPECT_EQ(sc.HeadingOffset(), ignition::math::Angle());
+  EXPECT_NEAR(sc.ElevationReference(), 0.0, 1e-6);
+
+  {
+    ignition::math::Angle lat(0.3), lon(-1.2), heading(0.5);
+    double elev = 354.1;
+    sc.SetSurface(st);
+    sc.SetLatitudeReference(lat);
+    sc.SetLongitudeReference(lon);
+    sc.SetHeadingOffset(heading);
+    sc.SetElevationReference(elev);
+
+    EXPECT_EQ(sc.Surface(), st);
+    EXPECT_EQ(sc.LatitudeReference(), lat);
+    EXPECT_EQ(sc.LongitudeReference(), lon);
+    EXPECT_EQ(sc.HeadingOffset(), heading);
+    EXPECT_NEAR(sc.ElevationReference(), elev, 1e-6);
+  }
+}
+
+//////////////////////////////////////////////////
+// Test coordinate transformations
+TEST(SphericalCoordinatesTest, CoordinateTransforms)
+{
+  // Default surface type
+  math::SphericalCoordinates::SurfaceType st =
+    math::SphericalCoordinates::EARTH_WGS84;
+
+  {
+    // Parameters
+    ignition::math::Angle lat(0.3), lon(-1.2),
+      heading(ignition::math::Angle::HalfPi);
+    double elev = 354.1;
+    math::SphericalCoordinates sc(st, lat, lon, elev, heading);
+
+    // Check GlobalFromLocal with heading offset of 90 degrees
+    {
+      // local frame
+      ignition::math::Vector3d xyz;
+      // east, north, up
+      ignition::math::Vector3d enu;
+
+      xyz.Set(1, 0, 0);
+      enu = sc.GlobalFromLocalVelocity(xyz);
+      EXPECT_NEAR(enu.Y(), xyz.X(), 1e-6);
+      EXPECT_NEAR(enu.X(), -xyz.Y(), 1e-6);
+      EXPECT_EQ(xyz, sc.LocalFromGlobalVelocity(enu));
+
+      xyz.Set(0, 1, 0);
+      enu = sc.GlobalFromLocalVelocity(xyz);
+      EXPECT_NEAR(enu.Y(), xyz.X(), 1e-6);
+      EXPECT_NEAR(enu.X(), -xyz.Y(), 1e-6);
+      EXPECT_EQ(xyz, sc.LocalFromGlobalVelocity(enu));
+
+      xyz.Set(1, -1, 0);
+      enu = sc.GlobalFromLocalVelocity(xyz);
+      EXPECT_NEAR(enu.Y(), xyz.X(), 1e-6);
+      EXPECT_NEAR(enu.X(), -xyz.Y(), 1e-6);
+      EXPECT_EQ(xyz, sc.LocalFromGlobalVelocity(enu));
+
+      xyz.Set(2243.52334, 556.35, 435.6553);
+      enu = sc.GlobalFromLocalVelocity(xyz);
+      EXPECT_NEAR(enu.Y(), xyz.X(), 1e-6);
+      EXPECT_NEAR(enu.X(), -xyz.Y(), 1e-6);
+      EXPECT_EQ(xyz, sc.LocalFromGlobalVelocity(enu));
+    }
+
+    // Check SphericalFromLocal
+    {
+      // local frame
+      ignition::math::Vector3d xyz;
+      // spherical coordinates
+      ignition::math::Vector3d sph;
+
+      // No offset
+      xyz.Set(0, 0, 0);
+      sph = sc.SphericalFromLocalPosition(xyz);
+      // latitude
+      EXPECT_NEAR(sph.X(), lat.Degree(), 1e-6);
+      // longitude
+      EXPECT_NEAR(sph.Y(), lon.Degree(), 1e-6);
+      // elevation
+      EXPECT_NEAR(sph.Z(), elev, 1e-6);
+
+      // 200 km offset in x (pi/2 heading offset means North). We use
+      // SphericalFromLocal, which means that xyz is a linear movement on
+      // a plane (not along the curvature of Earth). This will result in
+      // a large height offset.
+      xyz.Set(2e5, 0, 0);
+      sph = sc.SphericalFromLocalPosition(xyz);
+      // increase in latitude about 1.8 degrees
+      EXPECT_NEAR(sph.X(), lat.Degree() + 1.8, 0.008);
+      // no change in longitude
+      EXPECT_NEAR(sph.Z(), 3507.024791, 1e-6);
+
+      ignition::math::Vector3d xyz2 = sc.LocalFromSphericalPosition(sph);
+      EXPECT_EQ(xyz, xyz2);
+    }
+
+    // Check position projection
+    {
+      // WGS84 coordinate obtained from online mapping software
+      // > gdaltransform -s_srs WGS84 -t_srs EPSG:4978
+      // > latitude longitude altitude
+      // > X Y Z
+      ignition::math::Vector3d tmp;
+      ignition::math::Vector3d osrf_s(37.3877349, -122.0651166, 32.0);
+      ignition::math::Vector3d osrf_e(
+          -2693701.91434394, -4299942.14687992, 3851691.0393571);
+      ignition::math::Vector3d goog_s(37.4216719, -122.0821853, 30.0);
+      ignition::math::Vector3d goog_e(
+          -2693766.71906146, -4297199.59926038, 3854681.81878812);
+
+      // Local tangent plane coordinates (ENU = GLOBAL) coordinates of
+      // Google when OSRF is taken as the origin:
+      // > proj +ellps=WGS84  +proj=tmerc
+      // +lat_0=37.3877349 +lon_0=-122.0651166 +k=1 +x_0=0 +y_0=0
+      // > -122.0821853 37.4216719 (LON,LAT)
+      // > -1510.88 3766.64 (EAST,NORTH)
+      ignition::math::Vector3d vec(-1510.88, 3766.64, -3.29);
+
+      // Convert degrees to radians
+      osrf_s.X() *= 0.0174532925;
+      osrf_s.Y() *= 0.0174532925;
+
+      // Set the ORIGIN to be the Open Source Robotics Foundation
+      math::SphericalCoordinates sc2(st, ignition::math::Angle(osrf_s.X()),
+          ignition::math::Angle(osrf_s.Y()), osrf_s.Z(),
+          ignition::math::Angle::Zero);
+
+      // Check that SPHERICAL -> ECEF works
+      tmp = sc2.PositionTransform(osrf_s,
+          math::SphericalCoordinates::SPHERICAL,
+          math::SphericalCoordinates::ECEF);
+
+      EXPECT_NEAR(tmp.X(), osrf_e.X(), 8e-2);
+      EXPECT_NEAR(tmp.Y(), osrf_e.Y(), 8e-2);
+      EXPECT_NEAR(tmp.Z(), osrf_e.Z(), 1e-2);
+
+      // Check that ECEF -> SPHERICAL works
+      tmp = sc2.PositionTransform(tmp,
+          math::SphericalCoordinates::ECEF,
+          math::SphericalCoordinates::SPHERICAL);
+
+      EXPECT_NEAR(tmp.X(), osrf_s.X(), 1e-2);
+      EXPECT_NEAR(tmp.Y(), osrf_s.Y(), 1e-2);
+      EXPECT_NEAR(tmp.Z(), osrf_s.Z(), 1e-2);
+
+      // Check that SPHERICAL -> LOCAL works
+      tmp = sc2.LocalFromSphericalPosition(goog_s);
+      EXPECT_NEAR(tmp.X(), vec.X(), 8e-2);
+      EXPECT_NEAR(tmp.Y(), vec.Y(), 8e-2);
+      EXPECT_NEAR(tmp.Z(), vec.Z(), 1e-2);
+
+      // Check that SPHERICAL -> LOCAL -> SPHERICAL works
+      tmp = sc2.SphericalFromLocalPosition(tmp);
+      EXPECT_NEAR(tmp.X(), goog_s.X(), 8e-2);
+      EXPECT_NEAR(tmp.Y(), goog_s.Y(), 8e-2);
+      EXPECT_NEAR(tmp.Z(), goog_s.Z(), 1e-2);
+    }
+  }
+}
+
+//////////////////////////////////////////////////
+// Test distance
+TEST(SphericalCoordinatesTest, Distance)
+{
+  ignition::math::Angle latA, longA, latB, longB;
+  latA.Degree(46.250944);
+  longA.Degree(-122.249972);
+  latB.Degree(46.124953);
+  longB.Degree(-122.251683);
+  double d = math::SphericalCoordinates::Distance(latA, longA, latB, longB);
+
+  EXPECT_NEAR(14002, d, 20);
+}
+
+//////////////////////////////////////////////////
+TEST(SphericalCoordinatesTest, BadSetSurface)
+{
+  math::SphericalCoordinates sc;
+  sc.SetSurface(static_cast<math::SphericalCoordinates::SurfaceType>(2));
+  EXPECT_EQ(sc.Surface(), 2);
+}
+
+//////////////////////////////////////////////////
+TEST(SphericalCoordinatesTest, Transform)
+{
+  math::SphericalCoordinates sc;
+  math::Vector3d vel(1, 2, -4);
+  math::Vector3d result = sc.VelocityTransform(vel,
+      math::SphericalCoordinates::ECEF,
+      math::SphericalCoordinates::ECEF);
+
+  EXPECT_EQ(result, vel);
+
+  math::Vector3d pos(-1510.88, 2, -4);
+  result = sc.PositionTransform(pos,
+      math::SphericalCoordinates::ECEF,
+      math::SphericalCoordinates::GLOBAL);
+
+  EXPECT_NEAR(result.X(), 2, 1e-6);
+  EXPECT_NEAR(result.Y(), -4, 1e-6);
+  EXPECT_NEAR(result.Z(), -6379647.8799999999, 1e-6);
+
+  std::cout << "NEW POS[" << result << "]\n";
+}
+
+//////////////////////////////////////////////////
+TEST(SphericalCoordinatesTest, BadCoordinateType)
+{
+  math::SphericalCoordinates sc;
+  math::Vector3d pos(1, 2, -4);
+  math::Vector3d result = sc.PositionTransform(pos,
+      static_cast<math::SphericalCoordinates::CoordinateType>(5),
+      static_cast<math::SphericalCoordinates::CoordinateType>(6));
+
+  EXPECT_EQ(result, pos);
+
+  result = sc.PositionTransform(pos,
+      static_cast<math::SphericalCoordinates::CoordinateType>(4),
+      static_cast<math::SphericalCoordinates::CoordinateType>(6));
+
+  EXPECT_EQ(result, pos);
+
+  result = sc.VelocityTransform(pos,
+      math::SphericalCoordinates::SPHERICAL,
+      math::SphericalCoordinates::ECEF);
+  EXPECT_EQ(result, pos);
+
+  result = sc.VelocityTransform(pos,
+      math::SphericalCoordinates::ECEF,
+      math::SphericalCoordinates::SPHERICAL);
+  EXPECT_EQ(result, pos);
+
+  result = sc.VelocityTransform(pos,
+      static_cast<math::SphericalCoordinates::CoordinateType>(5),
+      math::SphericalCoordinates::ECEF);
+  EXPECT_EQ(result, pos);
+
+  result = sc.VelocityTransform(pos,
+      math::SphericalCoordinates::ECEF,
+      static_cast<math::SphericalCoordinates::CoordinateType>(5));
+  EXPECT_EQ(result, pos);
+}
+
+//////////////////////////////////////////////////
+// Test [in]equality operators.
+TEST(SphericalCoordinatesTest, EqualityOps)
+{
+  // Default surface type
+  math::SphericalCoordinates::SurfaceType st =
+    math::SphericalCoordinates::EARTH_WGS84;
+  ignition::math::Angle lat(0.3), lon(-1.2), heading(0.5);
+  double elev = 354.1;
+  math::SphericalCoordinates sc1(st, lat, lon, elev, heading);
+
+  math::SphericalCoordinates sc2(st, lat, lon, elev, heading);
+  EXPECT_TRUE(sc1 == sc2);
+  EXPECT_FALSE(sc1 != sc2);
+  math::SphericalCoordinates sc3(st, ignition::math::Angle::Zero, lon, elev,
+    heading);
+  EXPECT_FALSE(sc1 == sc3);
+  EXPECT_TRUE(sc1 != sc3);
+  math::SphericalCoordinates sc4(st, lat, ignition::math::Angle::Zero, elev,
+    heading);
+  EXPECT_FALSE(sc1 == sc4);
+  EXPECT_TRUE(sc1 != sc4);
+  math::SphericalCoordinates sc5(st, lat, lon, elev + 1, heading);
+  EXPECT_FALSE(sc1 == sc5);
+  EXPECT_TRUE(sc1 != sc5);
+  math::SphericalCoordinates sc6(st, lat, lon, elev,
+    ignition::math::Angle::Zero);
+  EXPECT_FALSE(sc1 == sc6);
+  EXPECT_TRUE(sc1 != sc6);
+}
+
+//////////////////////////////////////////////////
+// Test assignment operator.
+TEST(SphericalCoordinatesTest, AssignmentOp)
+{
+  // Default surface type
+  math::SphericalCoordinates::SurfaceType st =
+    math::SphericalCoordinates::EARTH_WGS84;
+  ignition::math::Angle lat(0.3), lon(-1.2), heading(0.5);
+  double elev = 354.1;
+  math::SphericalCoordinates sc1(st, lat, lon, elev, heading);
+
+  math::SphericalCoordinates sc2 = sc1;
+  EXPECT_EQ(sc1, sc2);
+}
diff --git a/src/Spline.cc b/src/Spline.cc
new file mode 100644
index 0000000..c54b3e3
--- /dev/null
+++ b/src/Spline.cc
@@ -0,0 +1,385 @@
+/*
+ * Copyright (C) 2012 Open Source Robotics Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+*/
+// Note: Originally cribbed from Ogre3d. Modified to implement Cardinal
+// spline and catmull-rom spline
+
+#include "SplinePrivate.hh"
+#include "ignition/math/Helpers.hh"
+#include "ignition/math/Vector4.hh"
+#include "ignition/math/Spline.hh"
+
+using namespace ignition;
+using namespace math;
+
+///////////////////////////////////////////////////////////
+Spline::Spline()
+    : dataPtr(new SplinePrivate())
+{
+  // Set up matrix
+  this->dataPtr->autoCalc = true;
+  this->dataPtr->tension = 0.0;
+  this->dataPtr->arcLength = INF_D;
+}
+
+///////////////////////////////////////////////////////////
+Spline::~Spline()
+{
+  delete this->dataPtr;
+  this->dataPtr = NULL;
+}
+
+///////////////////////////////////////////////////////////
+void Spline::Tension(double _t)
+{
+  this->dataPtr->tension = _t;
+  if (this->dataPtr->autoCalc)
+    this->RecalcTangents();
+}
+
+///////////////////////////////////////////////////////////
+double Spline::Tension() const
+{
+  return this->dataPtr->tension;
+}
+
+///////////////////////////////////////////////////////////
+double Spline::ArcLength() const
+{
+  return this->dataPtr->arcLength;
+}
+
+///////////////////////////////////////////////////////////
+double Spline::ArcLength(const double _t) const
+{
+  unsigned int fromIndex; double tFraction;
+  if (!this->MapToSegment(_t, fromIndex, tFraction))
+    return INF_D;
+  return (this->dataPtr->cumulativeArcLengths[fromIndex] +
+          this->ArcLength(fromIndex, tFraction));
+}
+
+///////////////////////////////////////////////////////////
+double Spline::ArcLength(const unsigned int _index,
+                         const double _t) const
+{
+  if (_index >= this->dataPtr->segments.size())
+    return INF_D;
+  return this->dataPtr->segments[_index].ArcLength(_t);
+}
+
+///////////////////////////////////////////////////////////
+void Spline::AddPoint(const Vector3d &_p)
+{
+  this->AddPoint(
+      ControlPoint({_p, Vector3d(INF_D, INF_D, INF_D)}), false);
+}
+
+///////////////////////////////////////////////////////////
+void Spline::AddPoint(const Vector3d &_p, const Vector3d &_t)
+{
+  this->AddPoint(
+      ControlPoint({_p, _t}), true);
+}
+
+///////////////////////////////////////////////////////////
+void Spline::AddPoint(const ControlPoint &_cp, const bool _fixed)
+{
+  this->dataPtr->points.push_back(_cp);
+  this->dataPtr->fixings.push_back(_fixed);
+  if (this->dataPtr->autoCalc)
+    this->RecalcTangents();
+  else
+    this->Rebuild();
+}
+
+///////////////////////////////////////////////////////////
+Vector3d Spline::InterpolateMthDerivative(const unsigned int _mth,
+                                          const double _t) const
+{
+  unsigned int fromIndex; double tFraction;
+  this->MapToSegment(_t, fromIndex, tFraction);
+  return this->InterpolateMthDerivative(fromIndex, _mth, tFraction);
+}
+
+///////////////////////////////////////////////////////////
+Vector3d Spline::InterpolateMthDerivative(const unsigned int _fromIndex,
+                                          const unsigned int _mth,
+                                          const double _t) const
+{
+  // Bounds check
+  if (_fromIndex >= this->dataPtr->points.size())
+    return Vector3d(INF_D, INF_D, INF_D);
+
+  if (_fromIndex == this->dataPtr->segments.size())
+  {
+    // Duff request, cannot blend to nothing
+    // Just return source
+    return this->dataPtr->points[_fromIndex].MthDerivative(_mth);
+  }
+
+  // Interpolate derivative
+  return this->dataPtr->segments[_fromIndex].InterpolateMthDerivative(_mth, _t);
+}
+
+///////////////////////////////////////////////////////////
+Vector3d Spline::Interpolate(const double _t) const
+{
+  return this->InterpolateMthDerivative(0, _t);
+}
+
+///////////////////////////////////////////////////////////
+Vector3d Spline::Interpolate(const unsigned int _fromIndex,
+                             const double _t) const
+{
+  return this->InterpolateMthDerivative(_fromIndex, 0, _t);
+}
+
+///////////////////////////////////////////////////////////
+Vector3d Spline::InterpolateTangent(const double _t) const
+{
+  return this->InterpolateMthDerivative(1, _t);
+}
+
+///////////////////////////////////////////////////////////
+Vector3d Spline::InterpolateTangent(const unsigned int _fromIndex,
+                                    const double _t) const
+{
+  return this->InterpolateMthDerivative(_fromIndex, 1, _t);
+}
+
+///////////////////////////////////////////////////////////
+void Spline::RecalcTangents()
+{
+  // Catmull-Rom approach
+  //
+  // tangent[i] = 0.5 * (point[i+1] - point[i-1])
+  //
+  // Assume endpoint tangents are parallel with line with neighbour
+
+  size_t i, numPoints;
+  bool isClosed;
+
+  numPoints = this->dataPtr->points.size();
+  if (numPoints < 2)
+  {
+    // Can't do anything yet
+    return;
+  }
+
+  // Closed or open?
+  if (this->dataPtr->points[0].MthDerivative(0) ==
+      this->dataPtr->points[numPoints-1].MthDerivative(0))
+    isClosed = true;
+  else
+    isClosed = false;
+
+  double t = 1.0 - this->dataPtr->tension;
+
+  for (i = 0; i < numPoints; ++i)
+  {
+    if (!this->dataPtr->fixings[i])
+    {
+      if (i == 0)
+      {
+        // Special case start
+        if (isClosed)
+        {
+          // Use this->dataPtr->points-2 since this->dataPtr->points-1
+          // is the last point and == [0]
+          this->dataPtr->points[i].MthDerivative(1) =
+              ((this->dataPtr->points[1].MthDerivative(0) -
+                this->dataPtr->points[numPoints-2].MthDerivative(0)) * 0.5) * t;
+        }
+        else
+        {
+          this->dataPtr->points[i].MthDerivative(1) =
+              ((this->dataPtr->points[1].MthDerivative(0) -
+                this->dataPtr->points[0].MthDerivative(0)) * 0.5) * t;
+        }
+      }
+      else if (i == numPoints-1)
+      {
+        // Special case end
+        if (isClosed)
+        {
+          // Use same tangent as already calculated for [0]
+          this->dataPtr->points[i].MthDerivative(1) =
+              this->dataPtr->points[0].MthDerivative(1);
+        }
+        else
+        {
+          this->dataPtr->points[i].MthDerivative(1) =
+              ((this->dataPtr->points[i].MthDerivative(0) -
+                this->dataPtr->points[i-1].MthDerivative(0)) * 0.5) * t;
+        }
+      }
+      else
+      {
+        this->dataPtr->points[i].MthDerivative(1) =
+            ((this->dataPtr->points[i+1].MthDerivative(0) -
+              this->dataPtr->points[i-1].MthDerivative(0)) * 0.5) * t;
+      }
+    }
+  }
+  this->Rebuild();
+}
+
+///////////////////////////////////////////////////////////
+bool Spline::MapToSegment(const double _t,
+                          unsigned int &_index,
+                          double &_fraction) const
+{
+  _index = 0;
+  _fraction = 0.0;
+
+  // Check corner cases
+  if (this->dataPtr->segments.empty())
+    return false;
+
+  if (equal(_t, 0.0))
+    return true;
+
+  if (equal(_t, 1.0))
+  {
+    _index = static_cast<unsigned int>(this->dataPtr->segments.size()-1);
+    _fraction = 1.0;
+    return true;
+  }
+
+  // Assume linear relationship between t and arclength
+  double tArc = _t * this->dataPtr->arcLength;
+
+  // Get segment index where t would lie
+  auto it = std::lower_bound(this->dataPtr->cumulativeArcLengths.begin(),
+                             this->dataPtr->cumulativeArcLengths.end(),
+                             tArc);
+
+  if (it != this->dataPtr->cumulativeArcLengths.begin())
+    _index = static_cast<unsigned int>(
+        (it - this->dataPtr->cumulativeArcLengths.begin() - 1));
+
+  // Get fraction of t, but renormalized to the segment
+  _fraction = (tArc - this->dataPtr->cumulativeArcLengths[_index])
+              / this->dataPtr->segments[_index].ArcLength();
+  return true;
+}
+
+///////////////////////////////////////////////////////////
+void Spline::Rebuild()
+{
+  size_t numPoints = this->dataPtr->points.size();
+
+  if (numPoints < 2) {
+    // Can't do anything yet
+    return;
+  }
+
+  size_t numSegments = numPoints - 1;
+  this->dataPtr->segments.resize(numSegments);
+  this->dataPtr->cumulativeArcLengths.resize(numSegments);
+  for (size_t i = 0 ; i < numSegments ; ++i)
+  {
+    this->dataPtr->segments[i].SetPoints(this->dataPtr->points[i],
+                                         this->dataPtr->points[i+1]);
+
+    if (i > 0) {
+      this->dataPtr->cumulativeArcLengths[i] =
+          (this->dataPtr->segments[i-1].ArcLength()
+           + this->dataPtr->cumulativeArcLengths[i-1]);
+    }
+    else
+    {
+      this->dataPtr->cumulativeArcLengths[i] = 0.0;
+    }
+  }
+  this->dataPtr->arcLength = (this->dataPtr->cumulativeArcLengths.back()
+                              + this->dataPtr->segments.back().ArcLength());
+}
+
+///////////////////////////////////////////////////////////
+Vector3d Spline::Point(const unsigned int _index) const
+{
+  return this->MthDerivative(_index, 0);
+}
+
+///////////////////////////////////////////////////////////
+Vector3d Spline::Tangent(const unsigned int _index) const
+{
+  return this->MthDerivative(_index, 1);
+}
+
+///////////////////////////////////////////////////////////
+Vector3d Spline::MthDerivative(const unsigned int _index,
+                               const unsigned int _mth) const
+{
+  if (_index >= this->dataPtr->points.size())
+    return Vector3d(INF_D, INF_D, INF_D);
+  return this->dataPtr->points[_index].MthDerivative(_mth);
+}
+
+///////////////////////////////////////////////////////////
+size_t Spline::PointCount() const
+{
+  return this->dataPtr->points.size();
+}
+
+///////////////////////////////////////////////////////////
+void Spline::Clear()
+{
+  this->dataPtr->points.clear();
+  this->dataPtr->segments.clear();
+  this->dataPtr->fixings.clear();
+}
+
+///////////////////////////////////////////////////////////
+bool Spline::UpdatePoint(const unsigned int _index,
+                         const Vector3d &_point)
+{
+  return this->UpdatePoint(_index, ControlPoint({_point}), false);
+}
+
+///////////////////////////////////////////////////////////
+bool Spline::UpdatePoint(const unsigned int _index,
+                         const Vector3d &_point,
+                         const Vector3d &_tangent)
+{
+  return this->UpdatePoint(_index, ControlPoint({_point, _tangent}), true);
+}
+
+///////////////////////////////////////////////////////////
+bool Spline::UpdatePoint(const unsigned int _index,
+                         const ControlPoint &_point,
+                         const bool _fixed)
+{
+  if (_index >= this->dataPtr->points.size())
+    return false;
+
+  this->dataPtr->points[_index].Match(_point);
+  this->dataPtr->fixings[_index] = _fixed;
+
+  if (this->dataPtr->autoCalc)
+    this->RecalcTangents();
+  else
+    this->Rebuild();
+  return true;
+}
+
+///////////////////////////////////////////////////////////
+void Spline::AutoCalculate(bool _autoCalc)
+{
+  this->dataPtr->autoCalc = _autoCalc;
+}
diff --git a/src/SplinePrivate.cc b/src/SplinePrivate.cc
new file mode 100644
index 0000000..7248fe8
--- /dev/null
+++ b/src/SplinePrivate.cc
@@ -0,0 +1,156 @@
+/*
+ * Copyright (C) 2017 Open Source Robotics Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+*/
+
+#include "ignition/math/Matrix4.hh"
+
+#include "SplinePrivate.hh"
+
+namespace ignition
+{
+namespace math
+{
+
+///////////////////////////////////////////////////////////
+Vector4d PolynomialPowers(const unsigned int _order,
+                          const double _t)
+{
+  // It is much faster to go over this table than
+  // delving into factorials and power computations.
+  double t2 = _t * _t;
+  double t3 = t2 * _t;
+  switch (_order) {
+    case 0:
+      return Vector4d(t3, t2, _t, 1.0);
+    case 1:
+      return Vector4d(3*t2, 2*_t, 1.0, 0.0);
+    case 2:
+      return Vector4d(6*_t, 2.0, 0.0, 0.0);
+    case 3:
+      return Vector4d(6.0, 0.0, 0.0, 0.0);
+    default:
+      return Vector4d(0.0, 0.0, 0.0, 0.0);
+  }
+}
+
+///////////////////////////////////////////////////////////
+void ComputeCubicBernsteinHermiteCoeff(const ControlPoint &_startPoint,
+                                       const ControlPoint &_endPoint,
+                                       Matrix4d &_coeffs)
+{
+  // Get values and tangents
+  const Vector3d &point0 = _startPoint.MthDerivative(0);
+  const Vector3d &point1 = _endPoint.MthDerivative(0);
+  const Vector3d &tan0 = _startPoint.MthDerivative(1);
+  const Vector3d &tan1 = _endPoint.MthDerivative(1);
+
+  // Hermite basis matrix
+  const Matrix4d bmatrix(2.0, -2.0,  1.0,  1.0,
+                        -3.0,  3.0, -2.0, -1.0,
+                         0.0,  0.0,  1.0,  0.0,
+                         1.0,  0.0,  0.0,  0.0);
+
+  // Control vectors matrix
+  Matrix4d cmatrix(point0.X(), point0.Y(), point0.Z(), 1.0,
+                   point1.X(), point1.Y(), point1.Z(), 1.0,
+                   tan0.X(),   tan0.Y(),   tan0.Z(),   1.0,
+                   tan1.X(),   tan1.Y(),   tan1.Z(),   1.0);
+
+  // Compute coefficients
+  _coeffs = bmatrix * cmatrix;
+}
+
+///////////////////////////////////////////////////////////
+IntervalCubicSpline::IntervalCubicSpline()
+    : startPoint({Vector3d::Zero, Vector3d::Zero}),
+      endPoint({Vector3d::Zero, Vector3d::Zero}),
+      coeffs(Matrix4d::Zero),
+      arcLength(0.0)
+{
+}
+
+///////////////////////////////////////////////////////////
+void IntervalCubicSpline::SetPoints(const ControlPoint &_startPoint,
+                                    const ControlPoint &_endPoint)
+{
+  this->startPoint = _startPoint;
+  this->endPoint = _endPoint;
+
+  ComputeCubicBernsteinHermiteCoeff(
+      this->startPoint, this->endPoint, this->coeffs);
+
+  this->startPoint.MthDerivative(2) = this->DoInterpolateMthDerivative(2, 0.0);
+  this->startPoint.MthDerivative(3) = this->DoInterpolateMthDerivative(3, 0.0);
+  this->endPoint.MthDerivative(2) = this->DoInterpolateMthDerivative(2, 1.0);
+  this->endPoint.MthDerivative(3) = this->DoInterpolateMthDerivative(3, 1.0);
+  this->arcLength = this->ArcLength(1.0);
+}
+
+///////////////////////////////////////////////////////////
+double IntervalCubicSpline::ArcLength(const double _t) const
+{
+  // Bound check
+  if (_t < 0.0 || _t > 1.0)
+    return INF_D;
+
+  // 5 Point Gauss-Legendre quadrature rule for numerical path integration
+  // TODO: generalize into a numerical integration toolkit ?
+  double w1 = 0.28444444444444444 * _t;
+  double w23 = 0.23931433524968326 * _t;
+  double w45 = 0.11846344252809456 * _t;
+  double x1 = 0.5 * _t;
+  double x2 = 0.23076534494715845 * _t;
+  double x3 = 0.7692346550528415 * _t;
+  double x4 = 0.0469100770306680 * _t;
+  double x5 = 0.9530899229693319 * _t;
+
+  double arc_length = w1 * this->InterpolateMthDerivative(1, x1).Length();
+  arc_length += w23 * this->InterpolateMthDerivative(1, x2).Length();
+  arc_length += w23 * this->InterpolateMthDerivative(1, x3).Length();
+  arc_length += w45 * this->InterpolateMthDerivative(1, x4).Length();
+  arc_length += w45 * this->InterpolateMthDerivative(1, x5).Length();
+  return arc_length;
+}
+
+///////////////////////////////////////////////////////////
+Vector3d IntervalCubicSpline::DoInterpolateMthDerivative(
+    const unsigned int _mth, const double _t) const
+{
+  Vector4d powers = PolynomialPowers(_mth, _t);
+  Vector4d interpolation = powers * this->coeffs;
+  return Vector3d(interpolation.X(), interpolation.Y(), interpolation.Z());
+}
+
+///////////////////////////////////////////////////////////
+Vector3d IntervalCubicSpline::InterpolateMthDerivative(
+    const unsigned int _mth, const double _t) const
+{
+  // Bound check
+  if (_t < 0.0 || _t > 1.0)
+    return Vector3d(INF_D, INF_D, INF_D);
+
+  if (equal(_t, 0.0))
+    return this->startPoint.MthDerivative(_mth);
+  else if (equal(_t, 1.0))
+    return this->endPoint.MthDerivative(_mth);
+
+  return this->DoInterpolateMthDerivative(_mth, _t);
+}
+
+
+
+}
+}
diff --git a/src/SplinePrivate.hh b/src/SplinePrivate.hh
new file mode 100644
index 0000000..9106f07
--- /dev/null
+++ b/src/SplinePrivate.hh
@@ -0,0 +1,207 @@
+/*
+ * Copyright (C) 2015 Open Source Robotics Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+*/
+#ifndef IGNITION_MATH_SPLINEPRIVATE_HH_
+#define IGNITION_MATH_SPLINEPRIVATE_HH_
+
+#include <algorithm>
+#include <vector>
+#include <ignition/math/Vector3.hh>
+#include <ignition/math/Vector4.hh>
+#include <ignition/math/Matrix4.hh>
+
+namespace ignition
+{
+  namespace math
+  {
+    /// \brief Control point representation for
+    /// polynomial interpolation, defined in terms
+    /// of arbitrary m derivatives at such point.
+    class ControlPoint
+    {
+      /// \brief Default constructor.
+      public: ControlPoint()
+      {
+      }
+
+      /// \brief Constructor that takes the M derivatives that
+      /// define the control point.
+      /// \param[in] _initList with the M derivatives.
+      public: explicit ControlPoint(const std::vector<Vector3d> &_initList)
+          : derivatives(_initList.begin(), _initList.end())
+      {
+      }
+
+      /// \brief Matches all mth derivatives defined in \p _other
+      /// to this.
+      /// \remarks Higher order derivatives in this and not defined
+      /// in \p _other are kept.
+      /// \param[in] _other control point to be matches.
+      public: inline void Match(const ControlPoint &_other)
+      {
+        std::copy(_other.derivatives.begin(),
+                  _other.derivatives.end(),
+                  this->derivatives.begin());
+      }
+
+      /// \brief Checks for control point equality.
+      /// \param[in] _other control point to compare against.
+      /// \return whether this and \p _other can be seen as equal.
+      public: inline bool operator==(const ControlPoint &_other) const
+      {
+        // Workaround to compare the two vector of vectors in MSVC 2013
+        // and MSVC 2015. See
+        // https://bitbucket.org/ignitionrobotics/ign-math/issues/70
+        if (this->derivatives.size() != _other.derivatives.size())
+          return false;
+
+        for (size_t i = 0; i < this->derivatives.size(); ++i)
+          if (this->derivatives[i] != _other.derivatives[i])
+            return false;
+
+        return true;
+      }
+
+      /// \brief Gets the mth derivative of this control point.
+      /// \remarks Higher derivatives than those defined
+      /// default to [0.0, 0.0, 0.0].
+      /// \param[in] _mth derivative order.
+      /// \return The mth derivative value.
+      public: inline Vector3d MthDerivative(const unsigned int _mth) const
+      {
+        if (_mth >= this->derivatives.size())
+          return Vector3d(0.0, 0.0, 0.0);
+        return this->derivatives[_mth];
+      }
+
+      /// \brief Returns a mutable reference to the mth derivative of
+      /// this control point.
+      /// \remarks Higher derivatives than those defined
+      /// default to [0.0, 0.0, 0.0].
+      /// \param[in] _mth derivative order.
+      /// \return The mth derivative value.
+      public: inline Vector3d& MthDerivative(const unsigned int _mth)
+      {
+        if (_mth >= this->derivatives.size())
+        {
+          this->derivatives.insert(this->derivatives.end(),
+                                   _mth - this->derivatives.size() + 1,
+                                   Vector3d(0.0, 0.0, 0.0));
+        }
+        return this->derivatives[_mth];
+      }
+
+      /// \brief control point M derivatives (0 to M-1).
+      private: std::vector<Vector3d> derivatives;
+    };
+
+    /// \brief Cubic interpolator for splines defined
+    /// between each pair of control points.
+    class IntervalCubicSpline
+    {
+      /// \brief Dummy constructor.
+      public: IntervalCubicSpline();
+
+      /// \brief Sets both control points.
+      /// \param[in] _startPoint start control point.
+      /// \param[in] _endPoint end control point.
+      public: void SetPoints(const ControlPoint &_startPoint,
+                             const ControlPoint &_endPoint);
+
+      /// \brief Gets the start control point.
+      /// \return the start control point.
+      public: inline const ControlPoint &StartPoint() const
+      {
+        return this->startPoint;
+      };
+
+      /// \brief Gets the end control point.
+      /// \return the end control point.
+      public: inline const ControlPoint &EndPoint() const
+      {
+        return this->endPoint;
+      };
+
+      /// \brief Interpolates the curve mth derivative at
+      /// parameter value \p _t.
+      /// \param[in] _mth order of curve derivative to interpolate.
+      /// \param[in] _t parameter value (range 0 to 1).
+      /// \return the interpolated mth derivative, or [INF, INF, INF]
+      /// on error. Use Vector3d::IsFinite() to check for an error.
+      public: Vector3d InterpolateMthDerivative(
+          const unsigned int _mth, const double _t) const;
+
+      /// \brief Gets curve arc length
+      /// \return the arc length
+      public: inline double ArcLength() const { return this->arcLength; }
+
+      /// \brief Gets curve arc length up to a given point \p _t.
+      /// \param[in] _t parameter value (range 0 to 1).
+      /// \return the arc length up to \p _t or INF on error.
+      public: double ArcLength(const double _t) const;
+
+      /// \internal
+      /// \brief Interpolates the curve mth derivative at parameter
+      /// value \p _t.
+      /// \param[in] _mth order of curve derivative to interpolate.
+      /// \param[in] _t parameter value (range 0 to 1).
+      /// \return the interpolated mth derivative of the curve.
+      private: Vector3d DoInterpolateMthDerivative(
+          const unsigned int _mth, const double _t) const;
+
+      /// \brief start control point for the curve.
+      private: ControlPoint startPoint;
+
+      /// \brief end control point for the curve.
+      private: ControlPoint endPoint;
+
+      /// \brief Bernstein-Hermite polynomial coefficients
+      /// for interpolation.
+      private: Matrix4d coeffs;
+
+      /// \brief curve arc length.
+      private: double arcLength;
+    };
+
+    /// \brief Private data for Spline class.
+    class SplinePrivate
+    {
+      /// \brief when true, the tangents are recalculated when the control
+      /// point change.
+      public: bool autoCalc;
+
+      /// \brief tension of 0 = Catmull-Rom spline, otherwise a Cardinal spline.
+      public: double tension;
+
+      /// \brief fixings for control points.
+      public: std::vector<bool> fixings;
+
+      /// \brief control points.
+      public: std::vector<ControlPoint> points;
+
+      // \brief interpolated segments.
+      public: std::vector<IntervalCubicSpline> segments;
+
+      // \brief segments arc length cumulative distribution.
+      public: std::vector<double> cumulativeArcLengths;
+
+      // \brief spline arc length.
+      public: double arcLength;
+    };
+  }
+}
+
+#endif
diff --git a/src/Spline_TEST.cc b/src/Spline_TEST.cc
new file mode 100644
index 0000000..d1d0133
--- /dev/null
+++ b/src/Spline_TEST.cc
@@ -0,0 +1,179 @@
+/*
+ * Copyright (C) 2012 Open Source Robotics Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+*/
+
+#include <gtest/gtest.h>
+
+#include "ignition/math/Vector3.hh"
+#include "ignition/math/Spline.hh"
+
+using namespace ignition;
+
+/////////////////////////////////////////////////
+TEST(SplineTest, Spline)
+{
+  math::Spline s;
+
+  s.AddPoint(math::Vector3d(0, 0, 0));
+  EXPECT_EQ(static_cast<unsigned int>(1), s.PointCount());
+
+  s.Clear();
+  EXPECT_EQ(static_cast<unsigned int>(0), s.PointCount());
+
+  s.AddPoint(math::Vector3d(0, 0, 0));
+  EXPECT_TRUE(s.Point(0) == math::Vector3d(0, 0, 0));
+  s.AddPoint(math::Vector3d(1, 1, 1));
+  EXPECT_TRUE(s.Point(1) == math::Vector3d(1, 1, 1));
+
+  // ::UpdatePoint
+  EXPECT_FALSE(s.UpdatePoint(2, math::Vector3d(2, 2, 2)));
+
+  EXPECT_TRUE(s.UpdatePoint(1, math::Vector3d(2, 2, 2)));
+  s.AutoCalculate(false);
+  EXPECT_TRUE(s.UpdatePoint(0, math::Vector3d(-1, -1, -1)));
+  s.AutoCalculate(true);
+
+  // ::Interpolate
+  EXPECT_EQ(s.Interpolate(0.0), math::Vector3d(-1, -1, -1));
+  EXPECT_EQ(s.Interpolate(0.5), math::Vector3d(0.5, 0.5, 0.5));
+  EXPECT_EQ(s.Interpolate(1.0), math::Vector3d(2, 2, 2));
+
+  // ::Interpolate
+  s.AddPoint(math::Vector3d(4, 4, 4));
+  EXPECT_EQ(s.Interpolate(1, 0.2), math::Vector3d(2.496, 2.496, 2.496));
+}
+
+/////////////////////////////////////////////////
+TEST(SplineTest, FixedTangentSpline)
+{
+  math::Spline s;
+
+  // ::AddPoint
+  s.AutoCalculate(false);
+  s.AddPoint(math::Vector3d(0, 0, 0));
+  s.AddPoint(math::Vector3d(0, 0.5, 0), math::Vector3d(0, 1, 0));
+  s.AddPoint(math::Vector3d(0.5, 1, 0), math::Vector3d(1, 0, 0));
+  s.AddPoint(math::Vector3d(1, 1, 0), math::Vector3d(1, 0, 0));
+
+  // ::UpdatePoint
+  s.UpdatePoint(0, math::Vector3d(0, 0, 0), math::Vector3d(0, 1, 0));
+
+  s.AutoCalculate(true);
+
+  s.RecalcTangents();
+
+  // ::Interpolate
+  EXPECT_EQ(s.Interpolate(0, 0.5), math::Vector3d(0, 0.25, 0));
+  EXPECT_EQ(s.InterpolateTangent(0, 0.5), math::Vector3d(0, 0.25, 0));
+  EXPECT_EQ(s.Interpolate(1, 0.5), math::Vector3d(0.125, 0.875, 0));
+  EXPECT_EQ(s.Interpolate(2, 0.5), math::Vector3d(0.75, 1, 0));
+  EXPECT_EQ(s.InterpolateTangent(2, 0.5), math::Vector3d(0.25, 0, 0));
+}
+
+/////////////////////////////////////////////////
+TEST(SplineTest, ArcLength)
+{
+  math::Spline s;
+  EXPECT_FALSE(std::isfinite(s.ArcLength()));
+  s.AddPoint(math::Vector3d(1, 1, 1), math::Vector3d(1, 1, 1));
+  EXPECT_FALSE(std::isfinite(s.ArcLength(0)));
+  s.AddPoint(math::Vector3d(3, 3, 3), math::Vector3d(1, 1, 1));
+  s.AddPoint(math::Vector3d(4, 4, 4), math::Vector3d(1, 1, 1));
+  EXPECT_NEAR(s.ArcLength(0, 1.0), 3.46410161513775, 1e-14);
+  EXPECT_NEAR(s.ArcLength(), 5.19615242270663, 1e-14);
+  EXPECT_DOUBLE_EQ(s.ArcLength(), s.ArcLength(1.0));
+  EXPECT_FALSE(std::isfinite(s.ArcLength(-1.0)));
+  EXPECT_FALSE(std::isfinite(s.ArcLength(4, 0.0)));
+}
+
+/////////////////////////////////////////////////
+TEST(SplineTest, Tension)
+{
+  math::Spline s;
+  s.Tension(0.1);
+
+  EXPECT_DOUBLE_EQ(s.Tension(), 0.1);
+}
+
+/////////////////////////////////////////////////
+TEST(SplineTest, Interpolate)
+{
+  math::Spline s;
+  EXPECT_NO_THROW(s.Interpolate(0, 0.1));
+  EXPECT_FALSE(s.Interpolate(0, 0.1).IsFinite());
+
+  s.AddPoint(math::Vector3d(0, 0, 0));
+  EXPECT_EQ(s.Interpolate(0, 0.1), math::Vector3d(0, 0, 0));
+  EXPECT_FALSE(s.InterpolateTangent(0.1).IsFinite());
+
+  s.AddPoint(math::Vector3d(1, 2, 3));
+  EXPECT_EQ(s.Interpolate(0, 0.0), s.Point(0));
+  EXPECT_FALSE(s.Interpolate(0, -0.1).IsFinite());
+  EXPECT_EQ(s.InterpolateTangent(0, 0.0), s.Tangent(0));
+
+  // Fast and slow call variations
+  EXPECT_EQ(s.Interpolate(0, 0.5), math::Vector3d(0.5, 1.0, 1.5));
+  EXPECT_EQ(s.Interpolate(0, 1.0), s.Point(1));
+  EXPECT_EQ(s.InterpolateTangent(0, 0.5), math::Vector3d(1.25, 2.5, 3.75));
+  EXPECT_EQ(s.InterpolateTangent(0, 1.0), s.Tangent(1));
+  EXPECT_EQ(s.InterpolateMthDerivative(2, 0.5), math::Vector3d(0, 0, 0));
+  EXPECT_EQ(s.InterpolateMthDerivative(2, 1.0), math::Vector3d(-3, -6, -9));
+  EXPECT_EQ(s.InterpolateMthDerivative(3, 0.5), math::Vector3d(-6, -12, -18));
+  EXPECT_EQ(s.InterpolateMthDerivative(3, 1.0), math::Vector3d(-6, -12, -18));
+  EXPECT_EQ(s.InterpolateMthDerivative(4, 0.5), math::Vector3d(0, 0, 0));
+  EXPECT_EQ(s.InterpolateMthDerivative(4, 1.0), math::Vector3d(0, 0, 0));
+}
+
+/////////////////////////////////////////////////
+TEST(SplineTest, Point)
+{
+  math::Spline s;
+  EXPECT_NO_THROW(s.Point(0));
+  EXPECT_FALSE(s.Point(0).IsFinite());
+}
+
+/////////////////////////////////////////////////
+TEST(SplineTest, Tangent)
+{
+  math::Spline s;
+  EXPECT_NO_THROW(s.Tangent(0));
+  EXPECT_FALSE(s.Tangent(0).IsFinite());
+
+  s.AddPoint(math::Vector3d(0, 0, 0));
+  EXPECT_NO_THROW(s.Tangent(0));
+  EXPECT_FALSE(s.Tangent(0).IsFinite());
+
+  s.AddPoint(math::Vector3d(1, 0, 0));
+  EXPECT_EQ(s.Tangent(0), math::Vector3d(0.5, 0, 0));
+
+  s.AddPoint(math::Vector3d(1, 1, 0), math::Vector3d(-1, 1, 0));
+  EXPECT_EQ(s.Tangent(1), math::Vector3d(0.5, 0.5, 0));
+  EXPECT_EQ(s.Tangent(2), math::Vector3d(-1, 1, 0));
+}
+
+/////////////////////////////////////////////////
+TEST(SplineTest, RecalcTangents)
+{
+  math::Spline s;
+  s.AddPoint(math::Vector3d(0, 0, 0));
+  s.AddPoint(math::Vector3d(.4, .4, .4));
+  s.AddPoint(math::Vector3d(0, 0, 0));
+
+  s.RecalcTangents();
+
+  EXPECT_EQ(s.Interpolate(0, 0.5), math::Vector3d(0.2, 0.2, 0.2));
+  EXPECT_EQ(s.Interpolate(1, 0.5), math::Vector3d(0.2, 0.2, 0.2));
+}
diff --git a/src/Temperature.cc b/src/Temperature.cc
new file mode 100644
index 0000000..711d316
--- /dev/null
+++ b/src/Temperature.cc
@@ -0,0 +1,325 @@
+/*
+ * Copyright (C) 2016 Open Source Robotics Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License")
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+*/
+#include "ignition/math/Temperature.hh"
+
+/// \brief Private data for the Temperature class.
+class ignition::math::TemperaturePrivate
+{
+  /// \brief Default constructor
+  public: TemperaturePrivate() : kelvin(0.0) {}
+
+  /// \brief Constructor
+  /// \param[in] _temp Temperature in Kelvin
+  public: explicit TemperaturePrivate(const double _temp) : kelvin(_temp) {}
+
+  /// \brief Temperature value in Kelvin.
+  public: double kelvin;
+};
+
+using namespace ignition;
+using namespace math;
+
+/////////////////////////////////////////////////
+Temperature::Temperature()
+: dataPtr(new TemperaturePrivate)
+{
+}
+
+/////////////////////////////////////////////////
+Temperature::Temperature(const double _temp)
+: dataPtr(new TemperaturePrivate(_temp))
+{
+}
+
+/////////////////////////////////////////////////
+Temperature::Temperature(const Temperature &_temp)
+: dataPtr(new TemperaturePrivate(_temp.Kelvin()))
+{
+}
+
+/////////////////////////////////////////////////
+Temperature::~Temperature()
+{
+}
+
+/////////////////////////////////////////////////
+double Temperature::KelvinToCelsius(const double _temp)
+{
+  return _temp - 273.15;
+}
+
+/////////////////////////////////////////////////
+double Temperature::KelvinToFahrenheit(const double _temp)
+{
+  return _temp * 1.8 - 459.67;
+}
+
+/////////////////////////////////////////////////
+double Temperature::CelsiusToFahrenheit(const double _temp)
+{
+  return _temp * 1.8 + 32.0;
+}
+
+/////////////////////////////////////////////////
+double Temperature::CelsiusToKelvin(const double _temp)
+{
+  return _temp + 273.15;
+}
+
+/////////////////////////////////////////////////
+double Temperature::FahrenheitToCelsius(const double _temp)
+{
+  return (_temp - 32.0) / 1.8;
+}
+
+/////////////////////////////////////////////////
+double Temperature::FahrenheitToKelvin(const double _temp)
+{
+  return (_temp + 459.67) / 1.8;
+}
+
+/////////////////////////////////////////////////
+void Temperature::SetKelvin(const double _temp)
+{
+  this->dataPtr->kelvin = _temp;
+}
+
+/////////////////////////////////////////////////
+void Temperature::SetCelsius(const double _temp)
+{
+  this->SetKelvin(CelsiusToKelvin(_temp));
+}
+
+/////////////////////////////////////////////////
+void Temperature::SetFahrenheit(const double _temp)
+{
+  this->SetKelvin(FahrenheitToKelvin(_temp));
+}
+
+/////////////////////////////////////////////////
+double Temperature::Kelvin() const
+{
+  return this->dataPtr->kelvin;
+}
+
+/////////////////////////////////////////////////
+double Temperature::Celsius() const
+{
+  return KelvinToCelsius(this->dataPtr->kelvin);
+}
+
+/////////////////////////////////////////////////
+double Temperature::Fahrenheit() const
+{
+  return KelvinToFahrenheit(this->dataPtr->kelvin);
+}
+
+/////////////////////////////////////////////////
+double Temperature::operator()() const
+{
+  return this->dataPtr->kelvin;
+}
+
+/////////////////////////////////////////////////
+Temperature &Temperature::operator=(const double _temp)
+{
+  this->SetKelvin(_temp);
+  return *this;
+}
+
+/////////////////////////////////////////////////
+Temperature &Temperature::operator=(const Temperature &_temp)
+{
+  this->SetKelvin(_temp.Kelvin());
+  return *this;
+}
+
+/////////////////////////////////////////////////
+Temperature Temperature::operator+(const double _temp)
+{
+  return this->dataPtr->kelvin + _temp;
+}
+
+/////////////////////////////////////////////////
+Temperature Temperature::operator+(const Temperature &_temp)
+{
+  return this->dataPtr->kelvin + _temp;
+}
+
+/////////////////////////////////////////////////
+const Temperature &Temperature::operator+=(const double _temp)
+{
+  this->dataPtr->kelvin += _temp;
+  return *this;
+}
+
+/////////////////////////////////////////////////
+const Temperature &Temperature::operator+=(const Temperature &_temp)
+{
+  this->dataPtr->kelvin += _temp.Kelvin();
+  return *this;
+}
+
+/////////////////////////////////////////////////
+Temperature Temperature::operator-(const double _temp)
+{
+  return this->dataPtr->kelvin - _temp;
+}
+
+/////////////////////////////////////////////////
+Temperature Temperature::operator-(const Temperature &_temp)
+{
+  return this->dataPtr->kelvin - _temp.Kelvin();
+}
+
+/////////////////////////////////////////////////
+const Temperature &Temperature::operator-=(const double _temp)
+{
+  this->dataPtr->kelvin -= _temp;
+  return *this;
+}
+
+/////////////////////////////////////////////////
+const Temperature &Temperature::operator-=(const Temperature &_temp)
+{
+  this->dataPtr->kelvin -= _temp.Kelvin();
+  return *this;
+}
+
+/////////////////////////////////////////////////
+Temperature Temperature::operator*(const double _temp)
+{
+  return Temperature(this->dataPtr->kelvin * _temp);
+}
+
+/////////////////////////////////////////////////
+Temperature Temperature::operator*(const Temperature &_temp)
+{
+  return Temperature(this->dataPtr->kelvin * _temp.Kelvin());
+}
+
+/////////////////////////////////////////////////
+const Temperature &Temperature::operator*=(const double _temp)
+{
+  this->dataPtr->kelvin *= _temp;
+  return *this;
+}
+
+/////////////////////////////////////////////////
+const Temperature &Temperature::operator*=(const Temperature &_temp)
+{
+  this->dataPtr->kelvin *= _temp.Kelvin();
+  return *this;
+}
+
+/////////////////////////////////////////////////
+Temperature Temperature::operator/(const double _temp)
+{
+  return Temperature(this->dataPtr->kelvin / _temp);
+}
+
+/////////////////////////////////////////////////
+Temperature Temperature::operator/(const Temperature &_temp)
+{
+  return Temperature(this->dataPtr->kelvin / _temp.Kelvin());
+}
+
+/////////////////////////////////////////////////
+const Temperature &Temperature::operator/=(const double _temp)
+{
+  this->dataPtr->kelvin /= _temp;
+  return *this;
+}
+
+/////////////////////////////////////////////////
+const Temperature &Temperature::operator/=(const Temperature &_temp)
+{
+  this->dataPtr->kelvin /= _temp.Kelvin();
+  return *this;
+}
+
+/////////////////////////////////////////////////
+bool Temperature::operator==(const Temperature &_temp) const
+{
+  return ignition::math::equal(this->dataPtr->kelvin, _temp.Kelvin());
+}
+
+/////////////////////////////////////////////////
+bool Temperature::operator==(const double _temp) const
+{
+  return ignition::math::equal(this->dataPtr->kelvin, _temp);
+}
+
+/////////////////////////////////////////////////
+bool Temperature::operator!=(const Temperature &_temp) const
+{
+  return !(*this == _temp);
+}
+
+/////////////////////////////////////////////////
+bool Temperature::operator!=(const double _temp) const
+{
+  return !(*this == _temp);
+}
+
+/////////////////////////////////////////////////
+bool Temperature::operator<(const Temperature &_temp) const
+{
+  return this->dataPtr->kelvin < _temp.Kelvin();
+}
+
+/////////////////////////////////////////////////
+bool Temperature::operator<(const double _temp) const
+{
+  return this->dataPtr->kelvin < _temp;
+}
+
+/////////////////////////////////////////////////
+bool Temperature::operator<=(const Temperature &_temp) const
+{
+  return this->dataPtr->kelvin <= _temp.Kelvin();
+}
+
+/////////////////////////////////////////////////
+bool Temperature::operator<=(const double _temp) const
+{
+  return this->dataPtr->kelvin <= _temp;
+}
+
+/////////////////////////////////////////////////
+bool Temperature::operator>(const Temperature &_temp) const
+{
+  return this->dataPtr->kelvin > _temp.Kelvin();
+}
+
+/////////////////////////////////////////////////
+bool Temperature::operator>(const double _temp) const
+{
+  return this->dataPtr->kelvin > _temp;
+}
+
+/////////////////////////////////////////////////
+bool Temperature::operator>=(const Temperature &_temp) const
+{
+  return this->dataPtr->kelvin >= _temp.Kelvin();
+}
+
+/////////////////////////////////////////////////
+bool Temperature::operator>=(const double _temp) const
+{
+  return this->dataPtr->kelvin >= _temp;
+}
diff --git a/src/Temperature_TEST.cc b/src/Temperature_TEST.cc
new file mode 100644
index 0000000..0cb39cc
--- /dev/null
+++ b/src/Temperature_TEST.cc
@@ -0,0 +1,178 @@
+/*
+ * Copyright (C) 2016 Open Source Robotics Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+*/
+#include <gtest/gtest.h>
+
+#include "ignition/math/Temperature.hh"
+
+using namespace ignition;
+using namespace math;
+
+/////////////////////////////////////////////////
+TEST(TemperatureTest, Constructor)
+{
+  Temperature temp;
+  EXPECT_NEAR(temp.Kelvin(), 0.0, 1e-6);
+
+  Temperature temp2(1.1);
+  EXPECT_NEAR(temp2.Kelvin(), 1.1, 1e-6);
+
+  Temperature temp3(temp2);
+  EXPECT_NEAR(temp3.Kelvin(), 1.1, 1e-6);
+  EXPECT_NEAR(temp3.Celsius(), -272.05, 1e-6);
+
+  EXPECT_TRUE(temp2 == temp3);
+  EXPECT_TRUE(temp2 == 1.1);
+  EXPECT_TRUE(temp2 != temp);
+  EXPECT_TRUE(temp2 != 1.2);
+
+  EXPECT_TRUE(temp < temp2);
+  EXPECT_TRUE(temp < 10.0);
+  EXPECT_TRUE(temp <= temp2);
+  EXPECT_TRUE(temp <= 0.0);
+  EXPECT_TRUE(temp <= 0.1);
+
+  EXPECT_FALSE(temp > temp2);
+  EXPECT_FALSE(temp > 80.0);
+  EXPECT_FALSE(temp >= temp2);
+  EXPECT_FALSE(temp >= 0.1);
+  EXPECT_TRUE(temp >= 0.0);
+}
+
+/////////////////////////////////////////////////
+TEST(TemperatureTest, Conversions)
+{
+  EXPECT_NEAR(Temperature::KelvinToCelsius(0), -273.15, 1e-6);
+  EXPECT_NEAR(Temperature::KelvinToFahrenheit(300), 80.33, 1e-6);
+
+  EXPECT_NEAR(Temperature::CelsiusToFahrenheit(20.0), 68.0, 1e-6);
+  EXPECT_NEAR(Temperature::CelsiusToKelvin(10.0), 283.15, 1e-6);
+
+  EXPECT_NEAR(Temperature::FahrenheitToCelsius(-40.0),
+              Temperature::CelsiusToFahrenheit(-40.0), 1e-6);
+  EXPECT_NEAR(Temperature::FahrenheitToKelvin(60.0), 288.7055, 1e-3);
+}
+
+/////////////////////////////////////////////////
+TEST(TemperatureTest, MutatorsAccessors)
+{
+  Temperature temp;
+  EXPECT_NEAR(temp.Kelvin(), 0.0, 1e-6);
+
+  temp.SetKelvin(10);
+  EXPECT_NEAR(temp.Kelvin(), 10.0, 1e-6);
+
+  temp.SetCelsius(20);
+  EXPECT_NEAR(temp(), 293.15, 1e-6);
+
+  temp.SetFahrenheit(30);
+  EXPECT_NEAR(temp.Fahrenheit(), 30.0, 1e-6);
+  EXPECT_NEAR(temp(), 272.0388889, 1e-6);
+}
+
+/////////////////////////////////////////////////
+TEST(TemperatureTest, Operators)
+{
+  Temperature temp(20);
+  EXPECT_NEAR(temp(), 20, 1e-6);
+
+  temp = 30;
+  EXPECT_NEAR(temp(), 30, 1e-6);
+
+  Temperature temp2 = temp;
+  // cppcheck-suppress knownConditionTrueFalse
+  EXPECT_TRUE(temp == temp2);
+
+  EXPECT_NEAR((temp + temp2).Kelvin(), 60, 1e-6);
+  EXPECT_NEAR((temp + 40).Kelvin(), 70, 1e-6);
+
+  EXPECT_NEAR((temp - temp2).Kelvin(), 0, 1e-6);
+  EXPECT_NEAR((temp - 20).Kelvin(), 10.0, 1e-6);
+
+  EXPECT_NEAR((temp * temp2).Kelvin(), 900, 1e-6);
+  EXPECT_NEAR((temp * 2).Kelvin(), 60.0, 1e-6);
+
+  EXPECT_NEAR((temp / temp2).Kelvin(), 1.0, 1e-6);
+  EXPECT_NEAR((temp / 2).Kelvin(), 15.0, 1e-6);
+
+  temp += temp2;
+  EXPECT_NEAR(temp.Kelvin(), 60.0, 1e-6);
+  temp -= temp2;
+  EXPECT_NEAR(temp.Kelvin(), 30.0, 1e-6);
+
+  temp += 5.0;
+  EXPECT_NEAR(temp.Kelvin(), 35.0, 1e-6);
+  temp -= 5.0;
+  EXPECT_NEAR(temp.Kelvin(), 30.0, 1e-6);
+
+  temp *= temp2;
+  EXPECT_NEAR(temp.Kelvin(), 900, 1e-6);
+  temp /= temp2;
+  EXPECT_NEAR(temp.Kelvin(), 30, 1e-6);
+
+  temp *= 4.0;
+  EXPECT_NEAR(temp.Kelvin(), 120, 1e-6);
+  temp /= 4.0;
+  EXPECT_NEAR(temp.Kelvin(), 30, 1e-6);
+
+  Temperature temp3;
+  temp3 = temp;
+  EXPECT_TRUE(temp3 == temp);
+  EXPECT_TRUE(temp3 == temp2);
+}
+
+/////////////////////////////////////////////////
+TEST(TemperatureTest, OperatorStreamOut)
+{
+  Temperature temp(55.45);
+  std::ostringstream stream;
+  stream << temp;
+  EXPECT_EQ(stream.str(), "55.45");
+}
+
+/////////////////////////////////////////////////
+TEST(TemperatureTest, OperatorStreamIn)
+{
+  Temperature temp;
+  std::istringstream stream("23.4");
+  stream >> temp;
+  EXPECT_NEAR(temp.Kelvin(), 23.4, 1e-6);
+}
+
+/////////////////////////////////////////////////
+TEST(TemperatureTest, Negative)
+{
+  Temperature temp(235.0);
+
+  Temperature temp2 = 103.0 - temp;
+  EXPECT_NEAR(temp2.Kelvin(), -132.0, 1e-6);
+
+  Temperature temp3 = 133.0 + temp2;
+  EXPECT_NEAR(temp3.Kelvin(), 1.0, 1e-6);
+
+  Temperature temp4 = 4.0 * temp3;
+  EXPECT_NEAR(temp4.Kelvin(), 4.0, 1e-6);
+
+  Temperature temp5 = 2.0 / temp3;
+  EXPECT_NEAR(temp5.Kelvin(), 2.0, 1e-6);
+}
+
+/////////////////////////////////////////////////
+int main(int argc, char **argv)
+{
+  ::testing::InitGoogleTest(&argc, argv);
+  return RUN_ALL_TESTS();
+}
diff --git a/src/Triangle3_TEST.cc b/src/Triangle3_TEST.cc
new file mode 100644
index 0000000..bcc798e
--- /dev/null
+++ b/src/Triangle3_TEST.cc
@@ -0,0 +1,261 @@
+/*
+ * Copyright (C) 2015 Open Source Robotics Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+*/
+
+#include <gtest/gtest.h>
+
+#include "ignition/math/Triangle3.hh"
+#include "ignition/math/Helpers.hh"
+
+using namespace ignition;
+using namespace math;
+
+/////////////////////////////////////////////////
+TEST(Triangle3Test, Constructor)
+{
+  {
+    // Default constructor
+    Triangle3d tri;
+    EXPECT_EQ(tri[0], Vector3d(0, 0, 0));
+    EXPECT_EQ(tri[1], Vector3d(0, 0, 0));
+    EXPECT_EQ(tri[2], Vector3d(0, 0, 0));
+    EXPECT_FALSE(tri.Valid());
+  }
+
+  {
+    // Construct from three points
+    Triangle3d tri(Vector3d(0, 0, 0), Vector3d(0, 1, 0), Vector3d(1, 0, 0));
+
+    EXPECT_TRUE(tri.Valid());
+
+    EXPECT_EQ(tri[0], Vector3d(0, 0, 0));
+    EXPECT_EQ(tri[1], Vector3d(0, 1, 0));
+    EXPECT_EQ(tri[2], Vector3d(1, 0, 0));
+    EXPECT_NO_THROW(tri[3]);
+    EXPECT_EQ(tri[3], tri[2]);
+  }
+
+  {
+    // Construct degenerate from 3 collinear points
+    Triangle3d tri(Vector3d(0, 0, 0), Vector3d(0, 1, 0), Vector3d(0, 2, 0));
+
+    // Expect not Valid
+    EXPECT_FALSE(tri.Valid());
+  }
+}
+
+/////////////////////////////////////////////////
+TEST(Triangle3Test, Set)
+{
+  Triangle3d tri;
+
+  tri.Set(0, Vector3d(3, 4, 1));
+  tri.Set(1, Vector3d(5, -6, 2));
+  tri.Set(2, Vector3d(7, 8, -3));
+  EXPECT_EQ(tri[0], Vector3d(3, 4, 1));
+  EXPECT_EQ(tri[1], Vector3d(5, -6, 2));
+  EXPECT_EQ(tri[2], Vector3d(7, 8, -3));
+
+  tri.Set(Vector3d(0.1, 0.2, -0.3),
+          Vector3d(0.3, -0.4, 0.5),
+          Vector3d(1.5, -2.6, 3.7));
+  EXPECT_EQ(tri[0], Vector3d(0.1, 0.2, -0.3));
+  EXPECT_EQ(tri[1], Vector3d(0.3, -0.4, 0.5));
+  EXPECT_EQ(tri[2], Vector3d(1.5, -2.6, 3.7));
+
+  EXPECT_NO_THROW(tri.Set(3, Vector3d(1.5, 2.6, 3.8)));
+  EXPECT_EQ(tri[3], Vector3d(1.5, 2.6, 3.8));
+}
+
+/////////////////////////////////////////////////
+TEST(Triangle3Test, Side)
+{
+  Triangle3d tri(Vector3d(0, 0, 0), Vector3d(0, 1, 1), Vector3d(1, 0, 2));
+
+  EXPECT_TRUE(tri.Side(0) == Line3d(0, 0, 0, 0, 1, 1));
+  EXPECT_TRUE(tri.Side(1) == Line3d(0, 1, 1, 1, 0, 2));
+  EXPECT_TRUE(tri.Side(2) == Line3d(1, 0, 2, 0, 0, 0));
+
+  EXPECT_NO_THROW(tri.Side(3));
+  EXPECT_TRUE(tri.Side(3) == tri.Side(2));
+}
+
+/////////////////////////////////////////////////
+TEST(Triangle3Test, ContainsLine)
+{
+  Triangle3d tri(Vector3d(0, 0, 0), Vector3d(0, 1, 0), Vector3d(1, 0, 0));
+
+  EXPECT_TRUE(tri.Contains(tri.Side(0)));
+  EXPECT_TRUE(tri.Contains(tri.Side(1)));
+  EXPECT_TRUE(tri.Contains(tri.Side(2)));
+
+  EXPECT_TRUE(tri.Contains(Line3d(0.1, 0.1, 0, 0.5, 0.5, 0)));
+
+  EXPECT_FALSE(tri.Contains(Line3d(0.1, 0.1, 0, 0.6, 0.6, 0)));
+  EXPECT_FALSE(tri.Contains(Line3d(-0.1, -0.1, 0, 0.5, 0.5, 0)));
+  EXPECT_FALSE(tri.Contains(Line3d(0.1, 0.1, 0.1, 0.5, 0.5, 0.1)));
+  EXPECT_FALSE(tri.Contains(Line3d(0.1, 0.1, -0.1, 0.1, 0.1, 0.1)));
+}
+
+/////////////////////////////////////////////////
+TEST(Triangle3Test, Intersects)
+{
+  Vector3d pt1;
+  Triangle3d tri(Vector3d(0, 0, 0),
+                 Vector3d(0, 1, 0),
+                 Vector3d(1, 0, 0));
+
+  EXPECT_TRUE(tri.Intersects(tri.Side(0), pt1));
+  EXPECT_EQ(pt1, Vector3d(0, 0, 0));
+
+  EXPECT_TRUE(tri.Intersects(tri.Side(1), pt1));
+  EXPECT_EQ(pt1, Vector3d(0, 1, 0));
+
+  EXPECT_TRUE(tri.Intersects(tri.Side(2), pt1));
+  EXPECT_EQ(pt1, Vector3d(1, 0, 0));
+
+  EXPECT_TRUE(tri.Intersects(Line3d(0.1, 0.1, 0, 0.5, 0.5, 0), pt1));
+  EXPECT_EQ(pt1, Vector3d(0.1, 0.1, 0));
+
+  EXPECT_TRUE(tri.Intersects(Line3d(0.1, 0.1, 0, 0.6, 0.6, 0), pt1));
+  EXPECT_EQ(pt1, Vector3d(0.5, 0.5, 0));
+
+  EXPECT_TRUE(tri.Intersects(Line3d(0.6, 0.6, 0, 0.1, 0.1, 0), pt1));
+  EXPECT_EQ(pt1, Vector3d(0.5, 0.5, 0));
+
+  EXPECT_TRUE(tri.Intersects(Line3d(0.1, 0.1, 0, -0.6, 0.1, 0), pt1));
+  EXPECT_EQ(pt1, Vector3d(0.0, 0.1, 0));
+
+  EXPECT_TRUE(tri.Intersects(Line3d(0.1, 0.1, 0, 0.1, -0.1, 0), pt1));
+  EXPECT_EQ(pt1, Vector3d(0.1, 0, 0));
+
+  EXPECT_TRUE(tri.Intersects(Line3d(-0.1, -0.1, 0, 0.5, 0.5, 0), pt1));
+  EXPECT_EQ(pt1, Vector3d(0.0, 0.0, 0));
+
+  EXPECT_TRUE(tri.Intersects(Line3d(-2, -2, 0, 0.2, 0.2, 0), pt1));
+  EXPECT_EQ(pt1, Vector3d(0.0, 0.0, 0));
+
+  EXPECT_TRUE(tri.Intersects(Line3d(0.1, 0.1, -1, 0.1, 0.1, 1), pt1));
+  EXPECT_EQ(pt1, Vector3d(0.1, 0.1, 0));
+
+  EXPECT_TRUE(tri.Intersects(Line3d(0.1, 0.1, -1, 0.3, 0.3, 1), pt1));
+  EXPECT_EQ(pt1, Vector3d(0.2, 0.2, 0));
+
+  EXPECT_FALSE(tri.Intersects(Line3d(-0.1, 0, 0, -0.1, 1, 0), pt1));
+
+  // A flat triangle raised along the z-axis
+  {
+    tri.Set(Vector3d(0, 0, 0.5),
+        Vector3d(0, 1, 0.5),
+        Vector3d(1, 0, 0.5));
+    EXPECT_TRUE(tri.Intersects(Line3d(0.5, 0.5, 2, 0.5, 0.5, 0), pt1));
+    EXPECT_EQ(pt1, Vector3d(0.5, 0.5, 0.5));
+  }
+
+  // An angled triangle
+  {
+    tri.Set(Vector3d(0, 0, 1),
+        Vector3d(1, 0, 0),
+        Vector3d(0, 1, 0));
+
+    EXPECT_TRUE(tri.Intersects(Line3d(1, 0, 2, 1, 0, 0), pt1));
+    EXPECT_EQ(pt1, Vector3d(1, 0, 0));
+
+    EXPECT_FALSE(tri.Intersects(Line3d(1.1, 0, 2, 1.1, 0, 0), pt1));
+    EXPECT_FALSE(tri.Intersects(Line3d(0, 1.1, 2, 0, 1.1, 0), pt1));
+    EXPECT_FALSE(tri.Intersects(Line3d(-0.1, 0, 2, -0.1, 0, 0), pt1));
+    EXPECT_FALSE(tri.Intersects(Line3d(0.51, 0.51, 2, 0.51, 0.51, 0), pt1));
+
+    EXPECT_TRUE(tri.Intersects(Line3d(0, 1, 2, 0, 1, 0), pt1));
+    EXPECT_EQ(pt1, Vector3d(0, 1, 0));
+
+    EXPECT_TRUE(tri.Intersects(Line3d(0, 0, 2, 0, 0, 0), pt1));
+    EXPECT_EQ(pt1, Vector3d(0, 0, 1.0));
+
+    EXPECT_TRUE(tri.Intersects(Line3d(0.1, 0.1, 2, 0.1, 0.1, 0), pt1));
+    EXPECT_EQ(pt1, Vector3d(0.1, 0.1, 0.8));
+
+    EXPECT_TRUE(tri.Intersects(Line3d(0.2, 0.2, 2, 0.2, 0.2, 0), pt1));
+    EXPECT_EQ(pt1, Vector3d(0.2, 0.2, 0.6));
+
+    EXPECT_TRUE(tri.Intersects(Line3d(0.3, 0.3, 2, 0.3, 0.3, 0), pt1));
+    EXPECT_EQ(pt1, Vector3d(0.3, 0.3, 0.4));
+
+    EXPECT_TRUE(tri.Intersects(Line3d(0.4, 0.4, 2, 0.4, 0.4, 0), pt1));
+    EXPECT_EQ(pt1, Vector3d(0.4, 0.4, 0.2));
+
+    EXPECT_TRUE(tri.Intersects(Line3d(0.5, 0.5, 2, 0.5, 0.5, 0), pt1));
+    EXPECT_EQ(pt1, Vector3d(0.5, 0.5, 0));
+  }
+}
+
+/////////////////////////////////////////////////
+TEST(Triangle3Test, ContainsPt)
+{
+  Triangle3d tri(Vector3d(0, 0, 0),
+                 Vector3d(0, 1, 0),
+                 Vector3d(1, 0, 0));
+
+  EXPECT_TRUE(tri.Contains(tri[0]));
+  EXPECT_TRUE(tri.Contains(tri[1]));
+  EXPECT_TRUE(tri.Contains(tri[2]));
+
+  EXPECT_TRUE(tri.Contains(Vector3d(0.1, 0.1, 0)));
+  EXPECT_TRUE(tri.Contains(Vector3d(0, 0.5, 0)));
+  EXPECT_TRUE(tri.Contains(Vector3d(0.5, 0, 0)));
+  EXPECT_TRUE(tri.Contains(Vector3d(0.5, 0.5, 0)));
+
+  EXPECT_FALSE(tri.Contains(Vector3d(-0.01, -0.01, 0)));
+  EXPECT_FALSE(tri.Contains(Vector3d(1.01, 0, 0)));
+  EXPECT_FALSE(tri.Contains(Vector3d(0, 1.01, 0)));
+  EXPECT_FALSE(tri.Contains(Vector3d(0.1, 0.1, 0.1)));
+  EXPECT_FALSE(tri.Contains(Vector3d(0.1, 0.1, -0.1)));
+}
+
+/////////////////////////////////////////////////
+TEST(Triangle3Test, Perimeter)
+{
+  {
+    Triangle3d tri(Vector3d(0, 0, 0),
+                   Vector3d(0, 1, 0),
+                   Vector3d(1, 0, 0));
+
+    EXPECT_DOUBLE_EQ(tri.Perimeter(), 2.0 + sqrt(2.0));
+  }
+  {
+    Triangle3d tri(Vector3d(0, 0, 1),
+                   Vector3d(0, 1, 0),
+                   Vector3d(1, 0, 0));
+
+    EXPECT_DOUBLE_EQ(tri.Perimeter(), 3*sqrt(2.0));
+  }
+}
+
+/////////////////////////////////////////////////
+TEST(Triangle3Test, Area)
+{
+  {
+    Triangle3d tri(Vector3d(0, 0, 0), Vector3d(0, 1, 0), Vector3d(1, 0, 0));
+
+    EXPECT_NEAR(tri.Area(), 0.5, 1e-6);
+  }
+  {
+    Triangle3d tri(Vector3d(0, 0, 1), Vector3d(0, 1, 0), Vector3d(1, 0, 0));
+
+    // (base * height) / 2
+    EXPECT_NEAR(tri.Area(), (sqrt(2) * sqrt(1.5))*0.5, 1e-6);
+  }
+}
diff --git a/src/Triangle_TEST.cc b/src/Triangle_TEST.cc
new file mode 100644
index 0000000..0e2e337
--- /dev/null
+++ b/src/Triangle_TEST.cc
@@ -0,0 +1,194 @@
+/*
+ * Copyright (C) 2014 Open Source Robotics Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+*/
+
+#include <gtest/gtest.h>
+
+#include "ignition/math/Triangle.hh"
+#include "ignition/math/Helpers.hh"
+
+using namespace ignition;
+
+/////////////////////////////////////////////////
+TEST(TriangleTest, Constructor)
+{
+  {
+    // Default constructor
+    math::Triangled tri;
+    EXPECT_EQ(tri[0], math::Vector2d(0, 0));
+    EXPECT_EQ(tri[1], math::Vector2d(0, 0));
+    EXPECT_EQ(tri[2], math::Vector2d(0, 0));
+  }
+
+  {
+    // Construct from three points
+    math::Triangled tri(math::Vector2d(0, 0),
+                         math::Vector2d(0, 1),
+                         math::Vector2d(1, 0));
+
+    EXPECT_TRUE(tri.Valid());
+
+    EXPECT_EQ(tri[0], math::Vector2d(0, 0));
+    EXPECT_EQ(tri[1], math::Vector2d(0, 1));
+    EXPECT_EQ(tri[2], math::Vector2d(1, 0));
+    EXPECT_NO_THROW(tri[3]);
+    EXPECT_EQ(tri[3], tri[2]);
+  }
+
+  {
+    // Construct degenerate from 3 collinear points
+    math::Triangled tri(math::Vector2d(0, 0),
+                         math::Vector2d(0, 1),
+                         math::Vector2d(0, 2));
+
+    // Expect not Valid
+    EXPECT_FALSE(tri.Valid());
+  }
+}
+
+/////////////////////////////////////////////////
+TEST(TriangleTest, Set)
+{
+  math::Triangled tri;
+
+  tri.Set(0, math::Vector2d(3, 4));
+  tri.Set(1, math::Vector2d(5, 6));
+  tri.Set(2, math::Vector2d(7, 8));
+  EXPECT_EQ(tri[0], math::Vector2d(3, 4));
+  EXPECT_EQ(tri[1], math::Vector2d(5, 6));
+  EXPECT_EQ(tri[2], math::Vector2d(7, 8));
+
+  tri.Set(math::Vector2d(0.1, 0.2),
+          math::Vector2d(0.3, 0.4),
+          math::Vector2d(1.5, 2.6));
+  EXPECT_EQ(tri[0], math::Vector2d(0.1, 0.2));
+  EXPECT_EQ(tri[1], math::Vector2d(0.3, 0.4));
+  EXPECT_EQ(tri[2], math::Vector2d(1.5, 2.6));
+
+  EXPECT_NO_THROW(tri.Set(3, math::Vector2d(1.5, 2.6)));
+}
+
+/////////////////////////////////////////////////
+TEST(TriangleTest, Side)
+{
+  math::Triangled tri(math::Vector2d(0, 0),
+                      math::Vector2d(0, 1),
+                      math::Vector2d(1, 0));
+
+  EXPECT_TRUE(tri.Side(0) == math::Line2d(0, 0, 0, 1));
+  EXPECT_TRUE(tri.Side(1) == math::Line2d(0, 1, 1, 0));
+  EXPECT_TRUE(tri.Side(2) == math::Line2d(1, 0, 0, 0));
+
+  EXPECT_NO_THROW(tri.Side(3));
+}
+
+/////////////////////////////////////////////////
+TEST(TriangleTest, ContainsLine)
+{
+  math::Triangled tri(math::Vector2d(0, 0),
+                      math::Vector2d(0, 1),
+                      math::Vector2d(1, 0));
+
+  EXPECT_TRUE(tri.Contains(tri.Side(0)));
+  EXPECT_TRUE(tri.Contains(tri.Side(1)));
+  EXPECT_TRUE(tri.Contains(tri.Side(2)));
+
+  EXPECT_TRUE(tri.Contains(math::Line2d(0.1, 0.1, 0.5, 0.5)));
+
+  EXPECT_FALSE(tri.Contains(math::Line2d(0.1, 0.1, 0.6, 0.6)));
+  EXPECT_FALSE(tri.Contains(math::Line2d(-0.1, -0.1, 0.5, 0.5)));
+}
+
+/////////////////////////////////////////////////
+TEST(TriangleTest, Intersects)
+{
+  math::Vector2d pt1, pt2;
+  math::Triangled tri(math::Vector2d(0, 0),
+                      math::Vector2d(0, 1),
+                      math::Vector2d(1, 0));
+
+  EXPECT_TRUE(tri.Intersects(tri.Side(0), pt1, pt2));
+  EXPECT_EQ(pt1, math::Vector2d(0, 0));
+  EXPECT_EQ(pt2, math::Vector2d(0, 1));
+
+  EXPECT_TRUE(tri.Intersects(tri.Side(1), pt1, pt2));
+  EXPECT_EQ(pt1, math::Vector2d(0, 1));
+  EXPECT_EQ(pt2, math::Vector2d(1, 0));
+
+  EXPECT_TRUE(tri.Intersects(tri.Side(2), pt1, pt2));
+  EXPECT_EQ(pt1, math::Vector2d(1, 0));
+  EXPECT_EQ(pt2, math::Vector2d(0, 0));
+
+
+  EXPECT_TRUE(tri.Intersects(math::Line2d(0.1, 0.1, 0.5, 0.5), pt1, pt2));
+  EXPECT_EQ(pt1, math::Vector2d(0.1, 0.1));
+  EXPECT_EQ(pt2, math::Vector2d(0.5, 0.5));
+
+  EXPECT_TRUE(tri.Intersects(math::Line2d(0.1, 0.1, 0.6, 0.6), pt1, pt2));
+  EXPECT_EQ(pt1, math::Vector2d(0.5, 0.5));
+  EXPECT_EQ(pt2, math::Vector2d(0.1, 0.1));
+
+  EXPECT_TRUE(tri.Intersects(math::Line2d(-0.1, -0.1, 0.5, 0.5), pt1, pt2));
+  EXPECT_EQ(pt1, math::Vector2d(0.0, 0.0));
+  EXPECT_EQ(pt2, math::Vector2d(0.5, 0.5));
+
+  EXPECT_TRUE(tri.Intersects(math::Line2d(-2, -2, 0.2, 0.2), pt1, pt2));
+  EXPECT_EQ(pt1, math::Vector2d(0.0, 0.0));
+  EXPECT_EQ(pt2, math::Vector2d(0.2, 0.2));
+
+  EXPECT_FALSE(tri.Intersects(math::Line2d(-0.1, 0, -0.1, 1), pt1, pt2));
+}
+
+/////////////////////////////////////////////////
+TEST(TriangleTest, ContainsPt)
+{
+  math::Triangled tri(math::Vector2d(0, 0),
+                      math::Vector2d(0, 1),
+                      math::Vector2d(1, 0));
+
+  EXPECT_TRUE(tri.Contains(tri[0]));
+  EXPECT_TRUE(tri.Contains(tri[1]));
+  EXPECT_TRUE(tri.Contains(tri[2]));
+
+  EXPECT_TRUE(tri.Contains(math::Vector2d(0.1, 0.1)));
+  EXPECT_TRUE(tri.Contains(math::Vector2d(0, 0.5)));
+  EXPECT_TRUE(tri.Contains(math::Vector2d(0.5, 0)));
+  EXPECT_TRUE(tri.Contains(math::Vector2d(0.5, 0.5)));
+
+  EXPECT_FALSE(tri.Contains(math::Vector2d(-0.01, -0.01)));
+  EXPECT_FALSE(tri.Contains(math::Vector2d(1.01, 0)));
+  EXPECT_FALSE(tri.Contains(math::Vector2d(0, 1.01)));
+}
+
+/////////////////////////////////////////////////
+TEST(TriangleTest, Perimeter)
+{
+  math::Triangled tri(math::Vector2d(0, 0),
+                      math::Vector2d(0, 1),
+                      math::Vector2d(1, 0));
+
+  EXPECT_DOUBLE_EQ(tri.Perimeter(), 2.0 + sqrt(2.0));
+}
+
+/////////////////////////////////////////////////
+TEST(TriangleTest, Area)
+{
+  math::Triangled tri(math::Vector2d(0, 0),
+                      math::Vector2d(0, 1),
+                      math::Vector2d(1, 0));
+
+  EXPECT_NEAR(tri.Area(), 0.499999, 1e-6);
+}
diff --git a/src/Vector2_TEST.cc b/src/Vector2_TEST.cc
new file mode 100644
index 0000000..9c1cd74
--- /dev/null
+++ b/src/Vector2_TEST.cc
@@ -0,0 +1,304 @@
+/*
+ * Copyright (C) 2012 Open Source Robotics Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+*/
+
+#include <gtest/gtest.h>
+#include <cmath>
+
+#include "ignition/math/Helpers.hh"
+#include "ignition/math/Vector2.hh"
+
+using namespace ignition;
+
+/////////////////////////////////////////////////
+TEST(Vector2Test, Vector2)
+{
+  {
+    math::Vector2d v;
+    EXPECT_DOUBLE_EQ(0, v.X());
+    EXPECT_DOUBLE_EQ(0, v.Y());
+  }
+
+  // Constructor
+  math::Vector2d v(1, 2);
+  EXPECT_DOUBLE_EQ(1, v.X());
+  EXPECT_DOUBLE_EQ(2, v.Y());
+
+  // ::Distance
+  EXPECT_TRUE(math::equal(2.236, v.Distance(math::Vector2d(0, 0)), 1e-2));
+
+  // ::Normalize
+  v.Normalize();
+  EXPECT_TRUE(v == math::Vector2d(0.447214, 0.894427));
+
+  // ::Set
+  v.Set(4, 5);
+  EXPECT_TRUE(v == math::Vector2d(4, 5));
+
+  // ::operator=
+  v = math::Vector2d(6, 7);
+  EXPECT_TRUE(v == math::Vector2d(6, 7));
+
+  // ::operator= int
+  v = 5;
+  EXPECT_TRUE(v == math::Vector2d(5, 5));
+
+  // ::operator+
+  v = v + math::Vector2d(1, 2);
+  EXPECT_TRUE(v == math::Vector2d(6, 7));
+
+  // ::operator +=
+  v += math::Vector2d(5, 6);
+  EXPECT_TRUE(v == math::Vector2d(11, 13));
+
+  // ::operator -
+  v = v - math::Vector2d(2, 4);
+  EXPECT_TRUE(v == math::Vector2d(9, 9));
+
+  // ::operator -=
+  v.Set(2, 4);
+  v -= math::Vector2d(1, 6);
+  EXPECT_TRUE(v == math::Vector2d(1, -2));
+
+  // ::operator /
+  v.Set(10, 6);
+  v = v / math::Vector2d(2, 3);
+  EXPECT_TRUE(v == math::Vector2d(5, 2));
+
+  // ::operator /=
+  v.Set(10, 6);
+  v /= math::Vector2d(2, 3);
+  EXPECT_TRUE(v == math::Vector2d(5, 2));
+
+  // ::operator / int
+  v.Set(10, 6);
+  v = v / 2;
+  EXPECT_TRUE(v == math::Vector2d(5, 3));
+
+  // ::operator /= int
+  v.Set(10, 6);
+  v /= 2;
+  EXPECT_TRUE(v == math::Vector2d(5, 3));
+
+  // ::operator * int
+  v.Set(10, 6);
+  v = v * 2;
+  EXPECT_TRUE(v == math::Vector2d(20, 12));
+
+  // ::operator *= int
+  v.Set(10, 6);
+  v *= 2;
+  EXPECT_TRUE(v == math::Vector2d(20, 12));
+
+  // ::operator * vector2i
+  v.Set(10, 6);
+  v = v * math::Vector2d(2, 4);
+  EXPECT_TRUE(v == math::Vector2d(20, 24));
+
+  // ::operator *= vector2i
+  v.Set(10, 6);
+  v *= math::Vector2d(2, 4);
+  EXPECT_TRUE(v == math::Vector2d(20, 24));
+
+
+  // ::IsFinite
+  EXPECT_TRUE(v.IsFinite());
+
+  // ::operator[]
+  v[0] = 6;
+  v[1] = 7;
+  EXPECT_DOUBLE_EQ(6, v[0]);
+  EXPECT_DOUBLE_EQ(7, v[1]);
+}
+
+/////////////////////////////////////////////////
+TEST(Vector2Test, NoException)
+{
+  math::Vector2d v(1, 2);
+  EXPECT_NO_THROW(math::equal(v[0], 1.0));
+  EXPECT_NO_THROW(math::equal(v[1], 2.0));
+
+  EXPECT_NO_THROW(math::equal(v[2], 1.0));
+  EXPECT_DOUBLE_EQ(v[2], 2.0);
+}
+
+/////////////////////////////////////////////////
+// Test Equal function with specified tolerance
+TEST(Vector2Test, EqualTolerance)
+{
+  EXPECT_FALSE(math::Vector2d::Zero.Equal(math::Vector2d::One, 1e-6));
+  EXPECT_FALSE(math::Vector2d::Zero.Equal(math::Vector2d::One, 1e-3));
+  EXPECT_FALSE(math::Vector2d::Zero.Equal(math::Vector2d::One, 1e-1));
+  EXPECT_TRUE(math::Vector2d::Zero.Equal(math::Vector2d::One, 1));
+  EXPECT_TRUE(math::Vector2d::Zero.Equal(math::Vector2d::One, 1.1));
+}
+
+/////////////////////////////////////////////////
+TEST(Vector2Test, Dot)
+{
+  math::Vector2d v(1, 2);
+
+  EXPECT_DOUBLE_EQ(v.Dot(math::Vector2d(3, 4)), 11.0);
+  EXPECT_DOUBLE_EQ(v.Dot(math::Vector2d(0, 0)), 0.0);
+  EXPECT_DOUBLE_EQ(v.Dot(math::Vector2d(1, 0)), 1.0);
+  EXPECT_DOUBLE_EQ(v.Dot(math::Vector2d(0, 1)), 2.0);
+}
+
+/////////////////////////////////////////////////
+TEST(Vector2Test, OperatorStreamOut)
+{
+  math::Vector2d v(0.1, 1.2);
+  std::ostringstream stream;
+  stream << v;
+  EXPECT_EQ(stream.str(), "0.1 1.2");
+}
+
+/////////////////////////////////////////////////
+TEST(Vector2dTest, Add)
+{
+  math::Vector2d vec1(0.1, 0.2);
+  math::Vector2d vec2(1.1, 2.2);
+
+  math::Vector2d vec3 = vec1;
+  vec3 += vec2;
+
+  EXPECT_EQ(vec1 + vec2, math::Vector2d(1.2, 2.4));
+  EXPECT_EQ(vec3, math::Vector2d(1.2, 2.4));
+
+  // Add zeros
+  {
+    // Scalar left and right
+    EXPECT_EQ(0 + vec1, vec1);
+    EXPECT_EQ(vec1 + 0, vec1);
+
+    // Vector left and right
+    EXPECT_EQ(math::Vector2d::Zero + vec1, vec1);
+    EXPECT_EQ(vec1 + math::Vector2d::Zero, vec1);
+
+    // Addition assignment
+    math::Vector2d vec4(vec1);
+    vec4 += 0;
+    EXPECT_EQ(vec4, vec1);
+    vec4 += math::Vector2d::Zero;
+    EXPECT_EQ(vec4, vec1);
+  }
+
+  // Add non-trivial scalar values left and right
+  {
+    EXPECT_EQ(2.5 + vec1, math::Vector2d(2.6, 2.7));
+    EXPECT_EQ(vec1 + 2.5, math::Vector2d(2.6, 2.7));
+
+    math::Vector2d vec4(vec1);
+    vec4 += 2.5;
+    EXPECT_EQ(vec4, math::Vector2d(2.6, 2.7));
+  }
+}
+
+/////////////////////////////////////////////////
+TEST(Vector2dTest, Sub)
+{
+  math::Vector2d vec1(0.1, 0.2);
+  math::Vector2d vec2(1.1, 2.2);
+
+  math::Vector2d vec3 = vec2;
+  vec3 -= vec1;
+
+  EXPECT_EQ(vec2 - vec1, math::Vector2d(1.0, 2.0));
+  EXPECT_EQ(vec3, math::Vector2d(1.0, 2.0));
+
+  // Subtraction with zeros
+  {
+    // Scalar left and right
+    EXPECT_EQ(0 - vec1, -vec1);
+    EXPECT_EQ(vec1 - 0, vec1);
+
+    // Vector left and right
+    EXPECT_EQ(math::Vector2d::Zero - vec1, -vec1);
+    EXPECT_EQ(vec1 - math::Vector2d::Zero, vec1);
+
+    // Subtraction assignment
+    math::Vector2d vec4(vec1);
+    vec4 -= 0;
+    EXPECT_EQ(vec4, vec1);
+    vec4 -= math::Vector2d::Zero;
+    EXPECT_EQ(vec4, vec1);
+  }
+
+  // Subtract non-trivial scalar values left and right
+  {
+    EXPECT_EQ(2.5 - vec1, math::Vector2d(2.4, 2.3));
+    EXPECT_EQ(vec1 - 2.5, -math::Vector2d(2.4, 2.3));
+
+    math::Vector2d vec4(vec1);
+    vec4 -= 2.5;
+    EXPECT_EQ(vec4, -math::Vector2d(2.4, 2.3));
+  }
+}
+
+/////////////////////////////////////////////////
+TEST(Vector2Test, Multiply)
+{
+  math::Vector2d v(0.1, -4.2);
+
+  // Multiply by zero
+  {
+    // Scalar left and right
+    EXPECT_EQ(0 * v, math::Vector2d::Zero);
+    EXPECT_EQ(v * 0, math::Vector2d::Zero);
+
+    // Element-wise vector multiplication
+    EXPECT_EQ(v * math::Vector2d::Zero, math::Vector2d::Zero);
+  }
+
+  // Multiply by one
+  {
+    // Scalar left and right
+    EXPECT_EQ(1 * v, v);
+    EXPECT_EQ(v * 1, v);
+
+    // Element-wise vector multiplication
+    EXPECT_EQ(v * math::Vector2d::One, v);
+  }
+
+  // Multiply by non-trivial scalar value
+  {
+    const double scalar = 2.5;
+    math::Vector2d expect(0.25, -10.5);
+    EXPECT_EQ(scalar * v, expect);
+    EXPECT_EQ(v * scalar, expect);
+  }
+
+  // Multiply by itself element-wise
+  EXPECT_EQ(v*v, math::Vector2d(0.01, 17.64));
+}
+
+/////////////////////////////////////////////////
+TEST(Vector2dTest, Length)
+{
+  // Zero vector
+  EXPECT_DOUBLE_EQ(math::Vector2d::Zero.Length(), 0.0);
+  EXPECT_DOUBLE_EQ(math::Vector2d::Zero.SquaredLength(), 0.0);
+
+  // One vector
+  EXPECT_NEAR(math::Vector2d::One.Length(), IGN_SQRT2, 1e-10);
+  EXPECT_DOUBLE_EQ(math::Vector2d::One.SquaredLength(), 2.0);
+
+  // Arbitrary vector
+  math::Vector2d v(0.1, -4.2);
+  EXPECT_NEAR(v.Length(), 4.20119030752, 1e-10);
+  EXPECT_DOUBLE_EQ(v.SquaredLength(), 17.65);
+}
+
diff --git a/src/Vector3Stats.cc b/src/Vector3Stats.cc
new file mode 100644
index 0000000..10ad3a2
--- /dev/null
+++ b/src/Vector3Stats.cc
@@ -0,0 +1,121 @@
+/*
+ * Copyright (C) 2015 Open Source Robotics Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+*/
+#include <ignition/math/Vector3Stats.hh>
+#include "Vector3StatsPrivate.hh"
+
+using namespace ignition;
+using namespace math;
+
+//////////////////////////////////////////////////
+Vector3Stats::Vector3Stats()
+  : dataPtr(new Vector3StatsPrivate)
+{
+}
+
+//////////////////////////////////////////////////
+Vector3Stats::~Vector3Stats()
+{
+  delete this->dataPtr;
+  this->dataPtr = 0;
+}
+
+//////////////////////////////////////////////////
+void Vector3Stats::InsertData(const Vector3d &_data)
+{
+  this->dataPtr->x.InsertData(_data.X());
+  this->dataPtr->y.InsertData(_data.Y());
+  this->dataPtr->z.InsertData(_data.Z());
+  this->dataPtr->mag.InsertData(_data.Length());
+}
+
+//////////////////////////////////////////////////
+bool Vector3Stats::InsertStatistic(const std::string &_name)
+{
+  bool x = this->dataPtr->x.InsertStatistic(_name);
+  bool y = this->dataPtr->y.InsertStatistic(_name);
+  bool z = this->dataPtr->z.InsertStatistic(_name);
+  bool mag = this->dataPtr->mag.InsertStatistic(_name);
+  return x && y && z && mag;
+}
+
+//////////////////////////////////////////////////
+bool Vector3Stats::InsertStatistics(const std::string &_names)
+{
+  bool x = this->dataPtr->x.InsertStatistics(_names);
+  bool y = this->dataPtr->y.InsertStatistics(_names);
+  bool z = this->dataPtr->z.InsertStatistics(_names);
+  bool mag = this->dataPtr->mag.InsertStatistics(_names);
+  return x && y && z && mag;
+}
+
+//////////////////////////////////////////////////
+void Vector3Stats::Reset()
+{
+  this->dataPtr->x.Reset();
+  this->dataPtr->y.Reset();
+  this->dataPtr->z.Reset();
+  this->dataPtr->mag.Reset();
+}
+
+//////////////////////////////////////////////////
+const SignalStats &Vector3Stats::X() const
+{
+  return this->dataPtr->x;
+}
+
+//////////////////////////////////////////////////
+const SignalStats &Vector3Stats::Y() const
+{
+  return this->dataPtr->y;
+}
+
+//////////////////////////////////////////////////
+const SignalStats &Vector3Stats::Z() const
+{
+  return this->dataPtr->z;
+}
+
+//////////////////////////////////////////////////
+const SignalStats &Vector3Stats::Mag() const
+{
+  return this->dataPtr->mag;
+}
+
+//////////////////////////////////////////////////
+SignalStats &Vector3Stats::X()
+{
+  return this->dataPtr->x;
+}
+
+//////////////////////////////////////////////////
+SignalStats &Vector3Stats::Y()
+{
+  return this->dataPtr->y;
+}
+
+//////////////////////////////////////////////////
+SignalStats &Vector3Stats::Z()
+{
+  return this->dataPtr->z;
+}
+
+//////////////////////////////////////////////////
+SignalStats &Vector3Stats::Mag()
+{
+  return this->dataPtr->mag;
+}
+
diff --git a/src/Vector3StatsPrivate.hh b/src/Vector3StatsPrivate.hh
new file mode 100644
index 0000000..d4439b3
--- /dev/null
+++ b/src/Vector3StatsPrivate.hh
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2015 Open Source Robotics Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+*/
+#ifndef IGNITION_MATH_VECTOR3STATSPRIVATE_HH_
+#define IGNITION_MATH_VECTOR3STATSPRIVATE_HH_
+
+#include <ignition/math/SignalStats.hh>
+
+namespace ignition
+{
+  namespace math
+  {
+    /// \brief Private data class for the Vector3Stats class.
+    class Vector3StatsPrivate
+    {
+      /// \brief Statistics for x component of signal.
+      public: SignalStats x;
+
+      /// \brief Statistics for y component of signal.
+      public: SignalStats y;
+
+      /// \brief Statistics for z component of signal.
+      public: SignalStats z;
+
+      /// \brief Statistics for magnitude of signal.
+      public: SignalStats mag;
+    };
+  }
+}
+#endif
+
diff --git a/src/Vector3Stats_TEST.cc b/src/Vector3Stats_TEST.cc
new file mode 100644
index 0000000..39fc5a5
--- /dev/null
+++ b/src/Vector3Stats_TEST.cc
@@ -0,0 +1,189 @@
+/*
+ * Copyright (C) 2015 Open Source Robotics Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+*/
+
+#include <gtest/gtest.h>
+
+#include <ignition/math/Vector3Stats.hh>
+
+using namespace ignition;
+
+class Vector3StatsTest : public ::testing::Test
+{
+  /// \brief Get X value of statistic _name.
+  /// \param[in] _name Name of statistic.
+  /// \return X value of statistic.
+  public: double X(const std::string &_name) const;
+
+  /// \brief Get Y value of statistic _name.
+  /// \param[in] _name Name of statistic.
+  /// \return Y value of statistic.
+  public: double Y(const std::string &_name) const;
+
+  /// \brief Get Z value of statistic _name.
+  /// \param[in] _name Name of statistic.
+  /// \return Z value of statistic.
+  public: double Z(const std::string &_name) const;
+
+  /// \brief Get Magnitude value of statistic _name.
+  /// \param[in] _name Name of statistic.
+  /// \return Magnitude value of statistic.
+  public: double Mag(const std::string &_name) const;
+
+  /// \brief Stats instance.
+  public: math::Vector3Stats stats;
+};
+
+//////////////////////////////////////////////////
+double Vector3StatsTest::X(const std::string &_name) const
+{
+  return this->stats.X().Map()[_name];
+}
+
+//////////////////////////////////////////////////
+double Vector3StatsTest::Y(const std::string &_name) const
+{
+  return this->stats.Y().Map()[_name];
+}
+
+//////////////////////////////////////////////////
+double Vector3StatsTest::Z(const std::string &_name) const
+{
+  return this->stats.Z().Map()[_name];
+}
+
+//////////////////////////////////////////////////
+double Vector3StatsTest::Mag(const std::string &_name) const
+{
+  return this->stats.Mag().Map()[_name];
+}
+
+//////////////////////////////////////////////////
+TEST_F(Vector3StatsTest, Vector3Stats)
+{
+  {
+    // Constructor
+    math::Vector3Stats v3stats;
+    EXPECT_TRUE(v3stats.X().Map().empty());
+    EXPECT_TRUE(v3stats.Y().Map().empty());
+    EXPECT_TRUE(v3stats.Z().Map().empty());
+    EXPECT_TRUE(v3stats.Mag().Map().empty());
+    EXPECT_EQ(v3stats.X().Count(), 0u);
+    EXPECT_EQ(v3stats.Y().Count(), 0u);
+    EXPECT_EQ(v3stats.Z().Count(), 0u);
+    EXPECT_EQ(v3stats.Mag().Count(), 0u);
+
+    // Reset
+    v3stats.Reset();
+    EXPECT_TRUE(v3stats.X().Map().empty());
+    EXPECT_TRUE(v3stats.Y().Map().empty());
+    EXPECT_TRUE(v3stats.Z().Map().empty());
+    EXPECT_TRUE(v3stats.Mag().Map().empty());
+    EXPECT_EQ(v3stats.X().Count(), 0u);
+    EXPECT_EQ(v3stats.Y().Count(), 0u);
+    EXPECT_EQ(v3stats.Z().Count(), 0u);
+    EXPECT_EQ(v3stats.Mag().Count(), 0u);
+  }
+
+  {
+    // InsertStatistics
+    math::Vector3Stats v3stats;
+    EXPECT_TRUE(v3stats.X().Map().empty());
+    EXPECT_TRUE(v3stats.Y().Map().empty());
+    EXPECT_TRUE(v3stats.Z().Map().empty());
+    EXPECT_TRUE(v3stats.Mag().Map().empty());
+
+    EXPECT_TRUE(v3stats.InsertStatistics("maxAbs"));
+    EXPECT_FALSE(v3stats.InsertStatistics("maxAbs"));
+    EXPECT_FALSE(v3stats.InsertStatistic("maxAbs"));
+    EXPECT_FALSE(v3stats.X().Map().empty());
+    EXPECT_FALSE(v3stats.Y().Map().empty());
+    EXPECT_FALSE(v3stats.Z().Map().empty());
+    EXPECT_FALSE(v3stats.Mag().Map().empty());
+
+    // Map with no data
+    {
+      std::map<std::string, double> map = v3stats.X().Map();
+      EXPECT_EQ(map.size(), 1u);
+      EXPECT_EQ(map.count("maxAbs"), 1u);
+    }
+    {
+      std::map<std::string, double> map = v3stats.Y().Map();
+      EXPECT_EQ(map.size(), 1u);
+      EXPECT_EQ(map.count("maxAbs"), 1u);
+    }
+    {
+      std::map<std::string, double> map = v3stats.Z().Map();
+      EXPECT_EQ(map.size(), 1u);
+      EXPECT_EQ(map.count("maxAbs"), 1u);
+    }
+    {
+      std::map<std::string, double> map = v3stats.Mag().Map();
+      EXPECT_EQ(map.size(), 1u);
+      EXPECT_EQ(map.count("maxAbs"), 1u);
+    }
+
+    // Insert some data
+    EXPECT_EQ(v3stats.X().Count(), 0u);
+    EXPECT_EQ(v3stats.Y().Count(), 0u);
+    EXPECT_EQ(v3stats.Z().Count(), 0u);
+    EXPECT_EQ(v3stats.Mag().Count(), 0u);
+
+    v3stats.InsertData(math::Vector3d::UnitX);
+    v3stats.InsertData(math::Vector3d::UnitX);
+    v3stats.InsertData(math::Vector3d::UnitY);
+
+    EXPECT_EQ(v3stats.X().Count(), 3u);
+    EXPECT_EQ(v3stats.Y().Count(), 3u);
+    EXPECT_EQ(v3stats.Z().Count(), 3u);
+    EXPECT_EQ(v3stats.Mag().Count(), 3u);
+
+    EXPECT_NEAR(v3stats.X().Map()["maxAbs"], 1.0, 1e-10);
+    EXPECT_NEAR(v3stats.Y().Map()["maxAbs"], 1.0, 1e-10);
+    EXPECT_DOUBLE_EQ(v3stats.Z().Map()["maxAbs"], 0.0);
+    EXPECT_NEAR(v3stats.Mag().Map()["maxAbs"], 1.0, 1e-10);
+  }
+
+  // Const accessors
+  {
+    EXPECT_TRUE(this->stats.X().Map().empty());
+    EXPECT_TRUE(this->stats.Y().Map().empty());
+    EXPECT_TRUE(this->stats.Z().Map().empty());
+    EXPECT_TRUE(this->stats.Mag().Map().empty());
+
+    const std::string name("maxAbs");
+    EXPECT_TRUE(this->stats.InsertStatistics(name));
+
+    this->stats.InsertData(math::Vector3d::UnitX);
+    this->stats.InsertData(math::Vector3d::UnitX);
+    this->stats.InsertData(math::Vector3d::UnitY);
+
+    EXPECT_EQ(this->stats.X().Count(), 3u);
+    EXPECT_EQ(this->stats.Y().Count(), 3u);
+    EXPECT_EQ(this->stats.Z().Count(), 3u);
+    EXPECT_EQ(this->stats.Mag().Count(), 3u);
+
+    EXPECT_NEAR(this->stats.X().Map()[name], 1.0, 1e-10);
+    EXPECT_NEAR(this->stats.Y().Map()[name], 1.0, 1e-10);
+    EXPECT_DOUBLE_EQ(this->stats.Z().Map()[name], 0.0);
+    EXPECT_NEAR(this->stats.Mag().Map()[name], 1.0, 1e-10);
+
+    EXPECT_NEAR(this->X(name), 1.0, 1e-10);
+    EXPECT_NEAR(this->Y(name), 1.0, 1e-10);
+    EXPECT_DOUBLE_EQ(this->Z(name), 0.0);
+    EXPECT_NEAR(this->Mag(name), 1.0, 1e-10);
+  }
+}
diff --git a/src/Vector3_TEST.cc b/src/Vector3_TEST.cc
new file mode 100644
index 0000000..20529dc
--- /dev/null
+++ b/src/Vector3_TEST.cc
@@ -0,0 +1,418 @@
+/*
+ * Copyright (C) 2012 Open Source Robotics Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+*/
+
+#include <gtest/gtest.h>
+
+#include "ignition/math/Vector3.hh"
+#include "ignition/math/Helpers.hh"
+
+using namespace ignition;
+
+/////////////////////////////////////////////////
+TEST(Vector3Test, Vector3d)
+{
+  math::Vector3d v;
+
+  // ::Distance, ::Length()
+  v.Set(1, 2, 3);
+  EXPECT_DOUBLE_EQ(v.Length(), v.Distance(math::Vector3d(0, 0, 0)));
+
+  // ::Round
+  v.Set(1.23, 2.34, 3.55);
+  EXPECT_TRUE(v.Rounded() == math::Vector3d(1, 2, 4));
+
+  // ::Round
+  v.Round();
+  EXPECT_TRUE(v.Round() == math::Vector3d(1, 2, 4));
+
+  // ::DotProd
+  EXPECT_TRUE(math::equal(17.0, v.Dot(math::Vector3d(1, 2, 3)), 1e-2));
+
+  // ::DistToLine
+  v.Set(0, 0, 0);
+  EXPECT_DOUBLE_EQ(1.0, v.DistToLine(math::Vector3d(1, -1, 0),
+        math::Vector3d(1, 1, 0)));
+
+  // ::operator= double
+  v = 4.0;
+  EXPECT_TRUE(v == math::Vector3d(4, 4, 4));
+
+  // ::operator/ vector3
+  v = v / math::Vector3d(1, 2, 4);
+  EXPECT_TRUE(v == math::Vector3d(4, 2, 1));
+
+  // ::operator / double
+  v = v / 2;
+  EXPECT_TRUE(v == math::Vector3d(2, 1, .5));
+
+  // ::operator * vector3
+  v = v * math::Vector3d(2, 3, 4);
+  EXPECT_TRUE(v == math::Vector3d(4, 3, 2));
+
+  // ::operator[]
+  v[0] = 40;
+  v[1] = 30;
+  v[2] = 20;
+  EXPECT_DOUBLE_EQ(v[0], 40);
+  EXPECT_DOUBLE_EQ(v[1], 30);
+  EXPECT_DOUBLE_EQ(v[2], 20);
+
+  v.Set(1.23, 2.35, 3.654321);
+  v.Round(1);
+  EXPECT_TRUE(v == math::Vector3d(1.2, 2.4, 3.7));
+
+  // operator GetAbs
+  v.Set(-1, -2, -3);
+  EXPECT_TRUE(v.Abs() == math::Vector3d(1, 2, 3));
+
+  // operator /=
+  v.Set(1, 2, 4);
+  v /= math::Vector3d(1, 4, 4);
+  EXPECT_TRUE(v == math::Vector3d(1, .5, 1));
+
+  // operator *=
+  v.Set(1, 2, 4);
+  v *= math::Vector3d(2, .5, .1);
+  EXPECT_TRUE(v.Equal(math::Vector3d(2, 1, .4)));
+
+  // Test the static defines.
+  EXPECT_TRUE(math::Vector3d::Zero == math::Vector3d(0, 0, 0));
+  EXPECT_TRUE(math::Vector3d::One == math::Vector3d(1, 1, 1));
+  EXPECT_TRUE(math::Vector3d::UnitX == math::Vector3d(1, 0, 0));
+  EXPECT_TRUE(math::Vector3d::UnitY == math::Vector3d(0, 1, 0));
+  EXPECT_TRUE(math::Vector3d::UnitZ == math::Vector3d(0, 0, 1));
+}
+
+/////////////////////////////////////////////////
+TEST(Vector3dTest, Distance)
+{
+  math::Vector3d vec1(0, 0, 0);
+  math::Vector3d vec2(1, 2, 3);
+
+  double dist = vec1.Distance(vec2);
+  EXPECT_NEAR(dist, 3.74165738677, 1e-6);
+
+  double dist2 = vec1.Distance(1, 2, 3);
+  EXPECT_DOUBLE_EQ(dist, dist2);
+}
+
+/////////////////////////////////////////////////
+TEST(Vector3dTest, Sum)
+{
+  math::Vector3d vec1(0, 0, 0);
+  math::Vector3d vec2(1, 2, 3);
+
+  double sum1 = vec1.Sum();
+  double sum2 = vec2.Sum();
+
+  EXPECT_DOUBLE_EQ(sum1, 0);
+  EXPECT_DOUBLE_EQ(sum2, 6);
+}
+
+/////////////////////////////////////////////////
+TEST(Vector3dTest, SquaredLength)
+{
+  math::Vector3d vec1(0, 0, 0);
+  math::Vector3d vec2(1, 2, 3);
+
+  double sum1 = vec1.SquaredLength();
+  double sum2 = vec2.SquaredLength();
+
+  EXPECT_DOUBLE_EQ(sum1, 0);
+  EXPECT_DOUBLE_EQ(sum2, 14);
+}
+
+/////////////////////////////////////////////////
+TEST(Vector3dTest, Length)
+{
+  // Zero vector
+  EXPECT_DOUBLE_EQ(math::Vector3d::Zero.Length(), 0.0);
+  EXPECT_DOUBLE_EQ(math::Vector3d::Zero.SquaredLength(), 0.0);
+
+  // UnitXYZ vectors
+  EXPECT_DOUBLE_EQ(math::Vector3d::UnitX.Length(), 1.0);
+  EXPECT_DOUBLE_EQ(math::Vector3d::UnitY.Length(), 1.0);
+  EXPECT_DOUBLE_EQ(math::Vector3d::UnitZ.Length(), 1.0);
+  EXPECT_DOUBLE_EQ(math::Vector3d::UnitX.SquaredLength(), 1.0);
+  EXPECT_DOUBLE_EQ(math::Vector3d::UnitY.SquaredLength(), 1.0);
+  EXPECT_DOUBLE_EQ(math::Vector3d::UnitZ.SquaredLength(), 1.0);
+
+  // One vector
+  EXPECT_NEAR(math::Vector3d::One.Length(), sqrt(3.0), 1e-10);
+  EXPECT_DOUBLE_EQ(math::Vector3d::One.SquaredLength(), 3.0);
+
+  // Arbitrary vector
+  math::Vector3d v(0.1, -4.2, 2.5);
+  EXPECT_NEAR(v.Length(), 4.88876262463, 1e-10);
+  EXPECT_DOUBLE_EQ(v.SquaredLength(), 23.9);
+}
+
+/////////////////////////////////////////////////
+TEST(Vector3dTest, Normalize)
+{
+  math::Vector3d vec1(0, 0, 0);
+  math::Vector3d vec2(1, 2, 3);
+
+  math::Vector3d vec3 = vec1.Normalize();
+  EXPECT_EQ(vec3, vec1);
+  EXPECT_EQ(vec1, math::Vector3d(0, 0, 0));
+
+  vec3 = vec2.Normalize();
+  EXPECT_EQ(vec3, vec2);
+  EXPECT_EQ(vec2, math::Vector3d(0.267261, 0.534522, 0.801784));
+
+  const math::Vector3d vecConst(1, 2, 3);
+  EXPECT_EQ(vecConst.Normalized(), vec3);
+  EXPECT_EQ(vecConst, math::Vector3d(1, 2, 3));
+}
+
+/////////////////////////////////////////////////
+TEST(Vector3dTest, GetNormal)
+{
+  math::Vector3d vec1(0, 0, 0);
+  math::Vector3d vec2(0, 1, 0);
+  math::Vector3d vec3(1, 1, 0);
+
+  math::Vector3d norm = math::Vector3d::Normal(vec1, vec2, vec3);
+  EXPECT_EQ(norm, math::Vector3d(0, 0, -1));
+}
+
+/////////////////////////////////////////////////
+TEST(Vector3dTest, Perpendicular)
+{
+  math::Vector3d vec1(1, 1, 0);
+  math::Vector3d vec2(0, 1, 1);
+  math::Vector3d vec3(1e-7, 1e-7, 1e-7);
+  math::Vector3d vec4(1, 0, 0);
+
+  EXPECT_EQ(vec1.Perpendicular(), math::Vector3d(0, 0, -1));
+  EXPECT_EQ(vec2.Perpendicular(), math::Vector3d(0, 1, -1));
+  EXPECT_EQ(vec3.Perpendicular(), math::Vector3d(0, 0, 0));
+  EXPECT_EQ(vec4.Perpendicular(), math::Vector3d(0, 0, 1));
+}
+
+/////////////////////////////////////////////////
+TEST(Vector3dTest, Max)
+{
+  math::Vector3d vec1(0.1, 0.2, 0.3);
+  math::Vector3d vec2(0.2, 0.3, 0.4);
+  math::Vector3d vec3(0.1, 0.2, 0.3);
+
+  EXPECT_DOUBLE_EQ(vec1.Max(), 0.3);
+
+  vec1.Max(vec2);
+  EXPECT_EQ(vec1, math::Vector3d(0.2, 0.3, 0.4));
+
+  vec1.Max(vec3);
+  EXPECT_EQ(vec1, math::Vector3d(0.2, 0.3, 0.4));
+}
+
+/////////////////////////////////////////////////
+TEST(Vector3dTest, Min)
+{
+  math::Vector3d vec1(0.1, 0.2, 0.3);
+  math::Vector3d vec2(0.2, 0.3, 0.4);
+  math::Vector3d vec3(0.05, 0.1, 0.2);
+
+  EXPECT_DOUBLE_EQ(vec1.Min(), 0.1);
+
+  vec1.Min(vec2);
+  EXPECT_EQ(vec1, math::Vector3d(0.1, 0.2, 0.3));
+
+  vec1.Min(vec3);
+  EXPECT_EQ(vec1, math::Vector3d(0.05, 0.1, 0.2));
+}
+
+/////////////////////////////////////////////////
+TEST(Vector3dTest, Add)
+{
+  math::Vector3d vec1(0.1, 0.2, 0.4);
+  math::Vector3d vec2(1.1, 2.2, 3.4);
+
+  math::Vector3d vec3 = vec1;
+  vec3 += vec2;
+
+  EXPECT_EQ(vec1 + vec2, math::Vector3d(1.2, 2.4, 3.8));
+  EXPECT_EQ(vec3, math::Vector3d(1.2, 2.4, 3.8));
+
+  // Add zeros
+  {
+    // Scalar left and right
+    EXPECT_EQ(0 + vec1, vec1);
+    EXPECT_EQ(vec1 + 0, vec1);
+
+    // Vector left and right
+    EXPECT_EQ(math::Vector3d::Zero + vec1, vec1);
+    EXPECT_EQ(vec1 + math::Vector3d::Zero, vec1);
+
+    // Addition assignment
+    math::Vector3d vec4(vec1);
+    vec4 += 0;
+    EXPECT_EQ(vec4, vec1);
+    vec4 += math::Vector3d::Zero;
+    EXPECT_EQ(vec4, vec1);
+  }
+
+  // Add non-trivial scalar values left and right
+  {
+    EXPECT_EQ(2.5 + vec1, math::Vector3d(2.6, 2.7, 2.9));
+    EXPECT_EQ(vec1 + 2.5, math::Vector3d(2.6, 2.7, 2.9));
+
+    math::Vector3d vec4(vec1);
+    vec4 += 2.5;
+    EXPECT_EQ(vec4, math::Vector3d(2.6, 2.7, 2.9));
+  }
+}
+
+/////////////////////////////////////////////////
+TEST(Vector3dTest, Sub)
+{
+  math::Vector3d vec1(0.1, 0.2, 0.4);
+  math::Vector3d vec2(1.1, 2.2, 3.4);
+
+  math::Vector3d vec3 = vec2;
+  vec3 -= vec1;
+
+  EXPECT_EQ(vec2 - vec1, math::Vector3d(1.0, 2.0, 3.0));
+  EXPECT_EQ(vec3, math::Vector3d(1.0, 2.0, 3.0));
+
+  // Subtraction with zeros
+  {
+    // Scalar left and right
+    EXPECT_EQ(0 - vec1, -vec1);
+    EXPECT_EQ(vec1 - 0, vec1);
+
+    // Vector left and right
+    EXPECT_EQ(math::Vector3d::Zero - vec1, -vec1);
+    EXPECT_EQ(vec1 - math::Vector3d::Zero, vec1);
+
+    // Subtraction assignment
+    math::Vector3d vec4(vec1);
+    vec4 -= 0;
+    EXPECT_EQ(vec4, vec1);
+    vec4 -= math::Vector3d::Zero;
+    EXPECT_EQ(vec4, vec1);
+  }
+
+  // Subtract non-trivial scalar values left and right
+  {
+    EXPECT_EQ(2.5 - vec1, math::Vector3d(2.4, 2.3, 2.1));
+    EXPECT_EQ(vec1 - 2.5, -math::Vector3d(2.4, 2.3, 2.1));
+
+    math::Vector3d vec4(vec1);
+    vec4 -= 2.5;
+    EXPECT_EQ(vec4, -math::Vector3d(2.4, 2.3, 2.1));
+  }
+}
+
+/////////////////////////////////////////////////
+TEST(Vector3dTest, Divide)
+{
+  math::Vector3d vec1(0.1, 0.2, 0.4);
+
+  math::Vector3d vec3 = vec1 / 2.0;
+  EXPECT_EQ(vec3, math::Vector3d(0.05, 0.1, 0.2));
+
+  vec3 /= 4.0;
+  EXPECT_EQ(vec3, math::Vector3d(0.0125, 0.025, 0.05));
+}
+
+/////////////////////////////////////////////////
+TEST(Vector3dTest, Multiply)
+{
+  math::Vector3d v(0.1, 0.2, 0.3);
+
+  math::Vector3d vec3 = v * 2.0;
+  EXPECT_EQ(vec3, math::Vector3d(0.2, 0.4, 0.6));
+
+  vec3 *= 4.0;
+  EXPECT_EQ(vec3, math::Vector3d(0.8, 1.6, 2.4));
+
+  // Multiply by zero
+  {
+    // Scalar left and right
+    EXPECT_EQ(0 * v, math::Vector3d::Zero);
+    EXPECT_EQ(v * 0, math::Vector3d::Zero);
+
+    // Element-wise vector multiplication
+    EXPECT_EQ(v * math::Vector3d::Zero, math::Vector3d::Zero);
+  }
+
+  // Multiply by one
+  {
+    // Scalar left and right
+    EXPECT_EQ(1 * v, v);
+    EXPECT_EQ(v * 1, v);
+
+    // Element-wise vector multiplication
+    EXPECT_EQ(v * math::Vector3d::One, v);
+  }
+
+  // Multiply by non-trivial scalar value
+  {
+    const double scalar = 2.5;
+    math::Vector3d expect(0.25, 0.5, 0.75);
+    EXPECT_EQ(scalar * v, expect);
+    EXPECT_EQ(v * scalar, expect);
+  }
+
+  // Multiply by itself element-wise
+  EXPECT_EQ(v*v, math::Vector3d(0.01, 0.04, 0.09));
+}
+
+/////////////////////////////////////////////////
+TEST(Vector3dTest, NotEqual)
+{
+  math::Vector3d vec1(0.1, 0.2, 0.3);
+  math::Vector3d vec2(0.2, 0.2, 0.3);
+  math::Vector3d vec3(0.1, 0.2, 0.3);
+
+  EXPECT_TRUE(vec1 != vec2);
+  EXPECT_FALSE(vec1 != vec3);
+}
+
+/////////////////////////////////////////////////
+// Test Equal function with specified tolerance
+TEST(Vector2Test, EqualTolerance)
+{
+  EXPECT_FALSE(math::Vector3d::Zero.Equal(math::Vector3d::One, 1e-6));
+  EXPECT_FALSE(math::Vector3d::Zero.Equal(math::Vector3d::One, 1e-3));
+  EXPECT_FALSE(math::Vector3d::Zero.Equal(math::Vector3d::One, 1e-1));
+  EXPECT_TRUE(math::Vector3d::Zero.Equal(math::Vector3d::One, 1));
+  EXPECT_TRUE(math::Vector3d::Zero.Equal(math::Vector3d::One, 1.1));
+}
+
+/////////////////////////////////////////////////
+TEST(Vector3dTest, Finite)
+{
+  math::Vector3d vec1(0.1, 0.2, 0.3);
+
+  EXPECT_TRUE(vec1.IsFinite());
+}
+
+/////////////////////////////////////////////////
+TEST(Vector3dTest, NoException)
+{
+  math::Vector3d v(1, 2, 3);
+  EXPECT_NO_THROW(math::equal(v[0], 1.0));
+  EXPECT_NO_THROW(math::equal(v[1], 2.0));
+  EXPECT_NO_THROW(math::equal(v[2], 3.0));
+
+  EXPECT_NO_THROW(math::equal(v[3], 4.0));
+  EXPECT_DOUBLE_EQ(v[3], 3.0);
+}
+
diff --git a/src/Vector4_TEST.cc b/src/Vector4_TEST.cc
new file mode 100644
index 0000000..9c7c679
--- /dev/null
+++ b/src/Vector4_TEST.cc
@@ -0,0 +1,314 @@
+/*
+ * Copyright (C) 2012 Open Source Robotics Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+*/
+
+#include <gtest/gtest.h>
+
+#include "ignition/math/Helpers.hh"
+#include "ignition/math/Matrix4.hh"
+#include "ignition/math/Vector4.hh"
+
+using namespace ignition;
+
+/////////////////////////////////////////////////
+TEST(Vector4dTest, Vector4d)
+{
+  {
+    math::Vector4d v;
+    EXPECT_TRUE(math::equal(v.X(), 0.0));
+    EXPECT_TRUE(math::equal(v.Y(), 0.0));
+    EXPECT_TRUE(math::equal(v.Z(), 0.0));
+    EXPECT_TRUE(math::equal(v.W(), 0.0));
+  }
+
+  math::Vector4d v1(1, 2, 3, 4);
+  EXPECT_TRUE(math::equal(v1.X(), 1.0));
+  EXPECT_TRUE(math::equal(v1.Y(), 2.0));
+  EXPECT_TRUE(math::equal(v1.Z(), 3.0));
+  EXPECT_TRUE(math::equal(v1.W(), 4.0));
+
+  math::Vector4d v(v1);
+  EXPECT_EQ(v, v1);
+
+  EXPECT_TRUE(math::equal(v.Distance(
+          math::Vector4d(0, 0, 0, 0)), 5.4772, 1e-3));
+
+  // ::Length()
+  v.Set(1, 2, 3, 4);
+  EXPECT_TRUE(math::equal(v.Length(), 5.4772, 1e-3));
+
+  // ::SquaredLength()
+  EXPECT_TRUE(math::equal(v.SquaredLength(), 30.0));
+
+  // ::Normalize
+  v.Normalize();
+  EXPECT_EQ(v, math::Vector4d(0.182574, 0.365148, 0.547723, 0.730297));
+
+  // ::Set
+  v.Set(2, 4, 6, 8);
+  EXPECT_EQ(v, math::Vector4d(2, 4, 6, 8));
+
+  // ::operator= vector4
+  v = v1;
+  EXPECT_EQ(v, v1);
+
+  // ::operator= double
+  v = 1.2;
+  EXPECT_EQ(v, math::Vector4d(1.2, 1.2, 1.2, 1.2));
+
+  // ::operator+ vector4
+  v = v + math::Vector4d(1, 2, 3, 4);
+  EXPECT_EQ(v, math::Vector4d(2.2, 3.2, 4.2, 5.2));
+
+  // ::operator+=
+  v += v;
+  EXPECT_EQ(v, math::Vector4d(4.4, 6.4, 8.4, 10.4));
+
+  // ::operator- vector4
+  v = v - math::Vector4d(1, 1, 1, 1);
+  EXPECT_EQ(v, math::Vector4d(3.4, 5.4, 7.4, 9.4));
+
+  // ::operator-= vector4
+  v -= math::Vector4d(1, 1, 1, 1);
+  EXPECT_EQ(v, math::Vector4d(2.4, 4.4, 6.4, 8.4));
+
+
+  // ::operator/ vector4
+  v = v / math::Vector4d(.1, .1, .1, .1);
+  EXPECT_EQ(v, math::Vector4d(24, 44, 64, 84));
+
+  // ::operator/ double
+  v = v / 2.0;
+  EXPECT_EQ(v, math::Vector4d(12, 22, 32, 42));
+
+  // ::operator/= vector4
+  v /= math::Vector4d(4, 4, 4, 4);
+  EXPECT_EQ(v, math::Vector4d(3, 5.5, 8, 10.5));
+
+  // ::operator/= double
+  v /= .1;
+  EXPECT_EQ(v, math::Vector4d(30, 55, 80, 105));
+
+  // ::operator * matrix4
+  v = v * math::Matrix4d(1, 2, 3, 4,
+                        5, 6, 7, 8,
+                        9, 10, 11, 12,
+                        13, 14, 15, 16);
+  EXPECT_EQ(v, math::Vector4d(2390, 2660, 2930, 3200));
+
+
+  // ::operator * vector4
+  v = v * math::Vector4d(.2, .3, .4, .5);
+  EXPECT_EQ(v, math::Vector4d(478, 798, 1172, 1600));
+
+  // ::operator *= vector4
+  v *= math::Vector4d(2, 4, 6, 8);
+  EXPECT_EQ(v, math::Vector4d(956, 3192, 7032, 12800));
+
+  // ::operator * double
+  v = v * 5.2;
+  EXPECT_EQ(v, math::Vector4d(4971.2, 16598.4, 36566.4, 66560));
+
+  // ::operator *= double
+  v *= 10.0;
+  EXPECT_EQ(v, math::Vector4d(49712, 1.65984e+05, 3.65664e+05, 6.656e+05));
+
+  // ::operator != vector4
+  EXPECT_NE(v, math::Vector4d());
+
+  // ::IsFinite
+  EXPECT_TRUE(v.IsFinite());
+
+  // ::operator[]
+  v[0] = 1;
+  v[1] = 2;
+  v[2] = 3;
+  v[3] = 4;
+  EXPECT_DOUBLE_EQ(v[0], 1);
+  EXPECT_DOUBLE_EQ(v[1], 2);
+  EXPECT_DOUBLE_EQ(v[2], 3);
+  EXPECT_DOUBLE_EQ(v[3], 4);
+}
+
+/////////////////////////////////////////////////
+TEST(Vector4dTest, NoException)
+{
+  math::Vector4d v(1, 2, 3, 4);
+  EXPECT_NO_THROW(math::equal(v[0], 1.0));
+  EXPECT_NO_THROW(math::equal(v[1], 2.0));
+  EXPECT_NO_THROW(math::equal(v[2], 3.0));
+  EXPECT_NO_THROW(math::equal(v[3], 4.0));
+
+  EXPECT_NO_THROW(math::equal(v[4], 5.0));
+  EXPECT_DOUBLE_EQ(v[4], 4.0);
+}
+
+/////////////////////////////////////////////////
+// Test Equal function with specified tolerance
+TEST(Vector2Test, EqualTolerance)
+{
+  EXPECT_FALSE(math::Vector4d::Zero.Equal(math::Vector4d::One, 1e-6));
+  EXPECT_FALSE(math::Vector4d::Zero.Equal(math::Vector4d::One, 1e-3));
+  EXPECT_FALSE(math::Vector4d::Zero.Equal(math::Vector4d::One, 1e-1));
+  EXPECT_TRUE(math::Vector4d::Zero.Equal(math::Vector4d::One, 1));
+  EXPECT_TRUE(math::Vector4d::Zero.Equal(math::Vector4d::One, 1.1));
+}
+
+/////////////////////////////////////////////////
+TEST(Vector4dTest, Add)
+{
+  math::Vector4d vec1(0.1, 0.2, 0.4, 0.8);
+  math::Vector4d vec2(1.1, 2.2, 3.4, 4.8);
+
+  math::Vector4d vec3 = vec1;
+  vec3 += vec2;
+
+  EXPECT_EQ(vec1 + vec2, math::Vector4d(1.2, 2.4, 3.8, 5.6));
+  EXPECT_EQ(vec3, math::Vector4d(1.2, 2.4, 3.8, 5.6));
+
+  // Add zeros
+  {
+    // Scalar left and right
+    EXPECT_EQ(0 + vec1, vec1);
+    EXPECT_EQ(vec1 + 0, vec1);
+
+    // Vector left and right
+    EXPECT_EQ(math::Vector4d::Zero + vec1, vec1);
+    EXPECT_EQ(vec1 + math::Vector4d::Zero, vec1);
+
+    // Addition assignment
+    math::Vector4d vec4(vec1);
+    vec4 += 0;
+    EXPECT_EQ(vec4, vec1);
+    vec4 += math::Vector4d::Zero;
+    EXPECT_EQ(vec4, vec1);
+  }
+
+  // Add non-trivial scalar values left and right
+  {
+    EXPECT_EQ(2.5 + vec1, math::Vector4d(2.6, 2.7, 2.9, 3.3));
+    EXPECT_EQ(vec1 + 2.5, math::Vector4d(2.6, 2.7, 2.9, 3.3));
+
+    math::Vector4d vec4(vec1);
+    vec4 += 2.5;
+    EXPECT_EQ(vec4, math::Vector4d(2.6, 2.7, 2.9, 3.3));
+  }
+}
+
+/////////////////////////////////////////////////
+TEST(Vector4dTest, Sub)
+{
+  math::Vector4d vec1(0.1, 0.2, 0.4, 0.8);
+  math::Vector4d vec2(1.1, 2.2, 3.4, 4.8);
+
+  math::Vector4d vec3 = vec2;
+  vec3 -= vec1;
+
+  EXPECT_EQ(vec2 - vec1, math::Vector4d(1.0, 2.0, 3.0, 4.0));
+  EXPECT_EQ(vec3, math::Vector4d(1.0, 2.0, 3.0, 4.0));
+
+  // Subtraction with zeros
+  {
+    // Scalar left and right
+    EXPECT_EQ(0 - vec1, -vec1);
+    EXPECT_EQ(vec1 - 0, vec1);
+
+    // Vector left and right
+    EXPECT_EQ(math::Vector4d::Zero - vec1, -vec1);
+    EXPECT_EQ(vec1 - math::Vector4d::Zero, vec1);
+
+    // Subtraction assignment
+    math::Vector4d vec4(vec1);
+    vec4 -= 0;
+    EXPECT_EQ(vec4, vec1);
+    vec4 -= math::Vector4d::Zero;
+    EXPECT_EQ(vec4, vec1);
+  }
+
+  // Subtract non-trivial scalar values left and right
+  {
+    EXPECT_EQ(2.5 - vec1, math::Vector4d(2.4, 2.3, 2.1, 1.7));
+    EXPECT_EQ(vec1 - 2.5, -math::Vector4d(2.4, 2.3, 2.1, 1.7));
+
+    math::Vector4d vec4(vec1);
+    vec4 -= 2.5;
+    EXPECT_EQ(vec4, -math::Vector4d(2.4, 2.3, 2.1, 1.7));
+  }
+}
+
+/////////////////////////////////////////////////
+TEST(Vector4dTest, OperatorStreamOut)
+{
+  math::Vector4d v(0.1, 1.2, 2.3, 0.0);
+  std::ostringstream stream;
+  stream << v;
+  EXPECT_EQ(stream.str(), "0.1 1.2 2.3 0");
+}
+
+/////////////////////////////////////////////////
+TEST(Vector4Test, Multiply)
+{
+  math::Vector4d v(0.1, -4.2, 11.1, 8.4);
+
+  // Multiply by zero
+  {
+    // Scalar left and right
+    EXPECT_EQ(0 * v, math::Vector4d::Zero);
+    EXPECT_EQ(v * 0, math::Vector4d::Zero);
+
+    // Element-wise vector multiplication
+    EXPECT_EQ(v * math::Vector4d::Zero, math::Vector4d::Zero);
+  }
+
+  // Multiply by one
+  {
+    // Scalar left and right
+    EXPECT_EQ(1 * v, v);
+    EXPECT_EQ(v * 1, v);
+
+    // Element-wise vector multiplication
+    EXPECT_EQ(v * math::Vector4d::One, v);
+  }
+
+  // Multiply by non-trivial scalar value
+  {
+    const double scalar = 2.5;
+    math::Vector4d expect(0.25, -10.5, 27.75, 21.0);
+    EXPECT_EQ(scalar * v, expect);
+    EXPECT_EQ(v * scalar, expect);
+  }
+
+  // Multiply by itself element-wise
+  EXPECT_EQ(v*v, math::Vector4d(0.01, 17.64, 123.21, 70.56));
+}
+
+/////////////////////////////////////////////////
+TEST(Vector4dTest, Length)
+{
+  // Zero vector
+  EXPECT_DOUBLE_EQ(math::Vector4d::Zero.Length(), 0.0);
+  EXPECT_DOUBLE_EQ(math::Vector4d::Zero.SquaredLength(), 0.0);
+
+  // One vector
+  EXPECT_DOUBLE_EQ(math::Vector4d::One.Length(), 2.0);
+  EXPECT_DOUBLE_EQ(math::Vector4d::One.SquaredLength(), 4.0);
+
+  // Arbitrary vector
+  math::Vector4d v(0.1, -4.2, 2.5, 1.0);
+  EXPECT_NEAR(v.Length(), 4.98998997995, 1e-10);
+  EXPECT_DOUBLE_EQ(v.SquaredLength(), 24.9);
+}
+
diff --git a/src/graph/CMakeLists.txt b/src/graph/CMakeLists.txt
new file mode 100644
index 0000000..70ba555
--- /dev/null
+++ b/src/graph/CMakeLists.txt
@@ -0,0 +1,7 @@
+
+# Collect source files into the "sources" variable and unit test files into the
+# "gtest_sources" variable
+ign_get_libsources_and_unittests(sources gtest_sources)
+
+# Build the unit tests
+ign_build_tests(TYPE UNIT SOURCES ${gtest_sources})
diff --git a/src/graph/Edge_TEST.cc b/src/graph/Edge_TEST.cc
new file mode 100644
index 0000000..ac6c1a2
--- /dev/null
+++ b/src/graph/Edge_TEST.cc
@@ -0,0 +1,225 @@
+/*
+ * Copyright (C) 2017 Open Source Robotics Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+*/
+
+#include <gtest/gtest.h>
+#include <iostream>
+#include <string>
+
+#include "ignition/math/graph/Edge.hh"
+#include "ignition/math/graph/Vertex.hh"
+
+using namespace ignition;
+using namespace math;
+using namespace graph;
+
+// Define a test fixture class template.
+template <class T>
+class EdgeTestFixture : public testing::Test
+{
+};
+
+// The list of edges we want to test.
+using EdgeTypes = ::testing::Types<DirectedEdge<int>,
+                                   UndirectedEdge<int>>;
+TYPED_TEST_CASE(EdgeTestFixture, EdgeTypes);
+
+/////////////////////////////////////////////////
+TYPED_TEST(EdgeTestFixture, Accessors)
+{
+  {
+    EdgeId id = 1;
+    double weight = 2.0;
+    double newWeight = 3.0;
+    VertexId_P vertices = {0, 1};
+    int data = 3;
+    TypeParam edge(vertices, data, weight, id);
+
+    // Id.
+    EXPECT_EQ(id, edge.Id());
+
+    // Weight.
+    EXPECT_DOUBLE_EQ(weight, edge.Weight());
+    edge.SetWeight(newWeight);
+    EXPECT_DOUBLE_EQ(newWeight, edge.Weight());
+
+    // Vertices.
+    EXPECT_EQ(vertices, edge.Vertices());
+
+    // Data.
+    EXPECT_EQ(data, edge.Data());
+    edge.Data() += 1;
+    EXPECT_EQ(data + 1, edge.Data());
+
+    // Validation.
+    EXPECT_TRUE(edge.Valid());
+  }
+
+  {
+    double weight = 2.0;
+    VertexId_P vertices = {0, 1};
+    int data = 3;
+    TypeParam edge(vertices, data, weight);
+
+    // Id.
+    EXPECT_EQ(kNullId, edge.Id());
+
+    // Weight.
+    EXPECT_DOUBLE_EQ(weight, edge.Weight());
+
+    // Vertices.
+    VertexId_P expectedVertices = {kNullId, kNullId};
+    EXPECT_EQ(expectedVertices, edge.Vertices());
+
+    // Data.
+    EXPECT_EQ(data, edge.Data());
+    edge.Data() += 1;
+    EXPECT_EQ(data + 1, edge.Data());
+
+    // Validation. It does not have a valid Id.
+    EXPECT_FALSE(edge.Valid());
+  }
+}
+
+/////////////////////////////////////////////////
+TEST(EdgeTest, Initializer)
+{
+  VertexId_P vertices = {1, 2};
+  std::string data = "hi";
+
+  {
+    double weight = 2.0;
+    EdgeInitializer<std::string> edgeInitializer(vertices, data, weight);
+    EXPECT_EQ(vertices, edgeInitializer.vertices);
+    EXPECT_EQ(data, edgeInitializer.data);
+    EXPECT_DOUBLE_EQ(weight, edgeInitializer.weight);
+  }
+  {
+    EdgeInitializer<std::string> edgeInitializer(vertices, "hi");
+    EXPECT_EQ(vertices, edgeInitializer.vertices);
+    EXPECT_EQ("hi", edgeInitializer.data);
+    EXPECT_DOUBLE_EQ(1.0, edgeInitializer.weight);
+  }
+}
+
+/////////////////////////////////////////////////
+TEST(EdgeTest, FromToDirected)
+{
+  {
+    EdgeId id = 1;
+    double weight = 2.0;
+    VertexId_P vertices = {0, 1};
+    int data = 3;
+    DirectedEdge<int> edge(vertices, data, weight, id);
+
+    EXPECT_EQ(0u, edge.Tail());
+    EXPECT_EQ(1u, edge.Head());
+
+    EXPECT_EQ(edge.Head(), edge.From(edge.Tail()));
+    EXPECT_EQ(edge.Tail(), edge.To(edge.Head()));
+
+    // It's a directed edge, you cannot go in this direction.
+    EXPECT_EQ(kNullId, edge.From(edge.Head()));
+    EXPECT_EQ(kNullId, edge.To(edge.Tail()));
+
+    // The Id doesn't exit.
+    EXPECT_EQ(kNullId, edge.From(99));
+    EXPECT_EQ(kNullId, edge.To(99));
+  }
+
+  {
+    double weight = 2.0;
+    VertexId_P vertices = {0, 1};
+    int data = 3;
+    DirectedEdge<int> edge(vertices, data, weight);
+    // The edge is not valid because the Id == kNullId.
+    EXPECT_FALSE(edge.Valid());
+
+    EXPECT_EQ(kNullId, edge.From(edge.Tail()));
+    EXPECT_EQ(kNullId, edge.To(edge.Head()));
+    EXPECT_EQ(kNullId, edge.From(edge.Head()));
+    EXPECT_EQ(kNullId, edge.To(edge.Tail()));
+  }
+}
+
+/////////////////////////////////////////////////
+TEST(EdgeTest, FromToUndirected)
+{
+  {
+    EdgeId id = 1;
+    double weight = 2.0;
+    VertexId_P vertices = {0, 1};
+    int data = 3;
+    UndirectedEdge<int> edge(vertices, data, weight, id);
+
+    EXPECT_EQ(1u, edge.From(0));
+    EXPECT_EQ(0u, edge.To(1));
+    EXPECT_EQ(0u, edge.From(1));
+    EXPECT_EQ(1u, edge.To(0));
+
+    // The Id doesn't exit.
+    EXPECT_EQ(kNullId, edge.From(99));
+    EXPECT_EQ(kNullId, edge.To(99));
+  }
+
+  {
+    EdgeId id = kNullId;
+    double weight = 2.0;
+    // Only one vertex.
+    VertexId_P vertices = {0, 1};
+    int data = 3;
+    UndirectedEdge<int> edge(vertices, data, weight, id);
+    // The edge is not valid because the Id == kNullId.
+    EXPECT_FALSE(edge.Valid());
+
+    EXPECT_EQ(kNullId, edge.From(0));
+    EXPECT_EQ(kNullId, edge.To(1));
+    EXPECT_EQ(kNullId, edge.From(1));
+    EXPECT_EQ(kNullId, edge.To(0));
+  }
+}
+
+/////////////////////////////////////////////////
+TEST(EdgeTest, StreamInsertionDirected)
+{
+  EdgeId id = 1;
+  double weight = 2.0;
+  VertexId_P vertices = {0, 1};
+  int data = 3;
+  DirectedEdge<int> edge(vertices, data, weight, id);
+
+  std::ostringstream output;
+  output << edge;
+
+  std::string expectedOutput = "  0 -> 1 [label=2];\n";
+  EXPECT_EQ(expectedOutput, output.str());
+}
+
+/////////////////////////////////////////////////
+TEST(EdgeTest, StreamInsertionUndirected)
+{
+  EdgeId id = 1;
+  double weight = 2.0;
+  VertexId_P vertices = {0, 1};
+  int data = 3;
+  UndirectedEdge<int> edge(vertices, data, weight, id);
+
+  std::ostringstream output;
+  output << edge;
+
+  std::string expectedOutput = "  0 -- 1 [label=2];\n";
+  EXPECT_EQ(expectedOutput, output.str());
+}
diff --git a/src/graph/GraphAlgorithms_TEST.cc b/src/graph/GraphAlgorithms_TEST.cc
new file mode 100644
index 0000000..898ce65
--- /dev/null
+++ b/src/graph/GraphAlgorithms_TEST.cc
@@ -0,0 +1,312 @@
+/*
+ * Copyright (C) 2017 Open Source Robotics Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+*/
+
+#include <gtest/gtest.h>
+#include <string>
+
+#include "ignition/math/graph/Graph.hh"
+#include "ignition/math/graph/GraphAlgorithms.hh"
+
+using namespace ignition;
+using namespace math;
+using namespace graph;
+
+// Define a test fixture class template.
+template <class T>
+class GraphTestFixture : public testing::Test
+{
+};
+
+// The list of graphs we want to test.
+using GraphTypes = ::testing::Types<DirectedGraph<int, double>,
+                                    UndirectedGraph<int, double>>;
+TYPED_TEST_CASE(GraphTestFixture, GraphTypes);
+
+/////////////////////////////////////////////////
+TYPED_TEST(GraphTestFixture, BreadthFirstSort)
+{
+  TypeParam graph(
+  {
+    // Vertices.
+    {{"A", 0, 0}, {"B", 1, 1}, {"C", 2, 2}, {"D", 3, 3}, {"E", 4, 4},
+     {"F", 5, 5}, {"G", 6, 6}},
+    // Edges.
+    {{{0, 1}, 2.0}, {{0, 2}, 3.0}, {{0, 4}, 4.0},
+     {{1, 3}, 2.0}, {{1, 5}, 3.0}, {{2, 6}, 4.0},
+     {{5, 4}, 2.0}}
+  });
+
+  auto res = BreadthFirstSort(graph, 0);
+  std::vector<VertexId> expected = {0, 1, 2, 4, 3, 5, 6};
+  EXPECT_EQ(expected, res);
+}
+
+/////////////////////////////////////////////////
+TEST(GraphTest, DepthFirstSortDirected)
+{
+  DirectedGraph<int, double> graph(
+  {
+    // Vertices.
+    {{"A", 0, 0}, {"B", 1, 1}, {"C", 2, 2}, {"D", 3, 3}, {"E", 4, 4},
+     {"F", 5, 5}, {"G", 6, 6}},
+    // Edges.
+    {{{0, 1}, 2.0}, {{0, 2}, 3.0}, {{0, 4}, 4.0}, {{1, 3}, 2.0},
+     {{1, 5}, 3.0}, {{2, 6}, 4.0}, {{5, 4}, 2.0}}
+  });
+
+  auto res = DepthFirstSort(graph, 0);
+  std::vector<VertexId> expected = {0, 4, 2, 6, 1, 5, 3};
+  EXPECT_EQ(expected, res);
+}
+
+/////////////////////////////////////////////////
+TEST(UndirectedGraphTest, DepthFirstSortUndirected)
+{
+  UndirectedGraph<int, double> graph(
+  {
+    // Vertices.
+    {{"A", 0, 0}, {"B", 1, 1}, {"C", 2, 2}, {"D", 3, 3}, {"E", 4, 4},
+     {"F", 5, 5}, {"G", 6, 6}},
+    // Edges.
+    {{{0, 1}, 2.0}, {{0, 2}, 3.0}, {{0, 4}, 4.0}, {{1, 3}, 2.0},
+     {{1, 5}, 3.0}, {{2, 6}, 4.0}, {{5, 4}, 2.0}}
+  });
+
+  auto res = DepthFirstSort(graph, 0);
+  std::vector<VertexId> expected = {0, 4, 5, 1, 3, 2, 6};
+  EXPECT_EQ(expected, res);
+}
+
+/////////////////////////////////////////////////
+TEST(GraphTestFixture, DijkstraUndirected)
+{
+  ///              (6)                 |
+  ///           0-------1              |
+  ///           |      /|\             |
+  ///           |     / | \(5)         |
+  ///           | (2)/  |  \           |
+  ///           |   /   |   2          |
+  ///        (1)|  / (2)|  /           |
+  ///           | /     | /(5)         |
+  ///           |/      |/             |
+  ///           3-------4              |
+  ///              (1)                 |
+  UndirectedGraph<int, double> graph(
+  {
+    // Vertices.
+    {{"0", 0, 0}, {"1", 1, 1}, {"2", 2, 2}, {"3", 3, 3}, {"4", 4, 4}},
+    // Edges.
+    {{{0, 1}, 2.0, 6.0}, {{0, 3}, 3.0, 1.0},
+     {{1, 2}, 4.0, 5.0}, {{1, 3}, 4.0, 2.0}, {{1, 4}, 4.0, 2.0},
+     {{2, 4}, 2.0, 5.0},
+     {{3, 4}, 2.0, 1.0}}
+  });
+
+  // Inexistent source vertex.
+  auto res = Dijkstra(graph, 99);
+  EXPECT_TRUE(res.empty());
+
+  // Inexistent destination vertex.
+  res = Dijkstra(graph, 0, 99);
+  EXPECT_TRUE(res.empty());
+
+  // Calculate all shortest paths from 0.
+  res = Dijkstra(graph, 0);
+
+  ASSERT_NE(res.end(), res.find(0));
+  EXPECT_DOUBLE_EQ(0, res.at(0).first);
+  EXPECT_EQ(0u, res.at(0).second);
+  ASSERT_NE(res.end(), res.find(1));
+  EXPECT_DOUBLE_EQ(3, res.at(1).first);
+  EXPECT_EQ(3u, res.at(1).second);
+  ASSERT_NE(res.end(), res.find(2));
+  EXPECT_DOUBLE_EQ(7, res.at(2).first);
+  EXPECT_EQ(4u, res.at(2).second);
+  ASSERT_NE(res.end(), res.find(3));
+  EXPECT_DOUBLE_EQ(1, res.at(3).first);
+  EXPECT_EQ(0u, res.at(3).second);
+  ASSERT_NE(res.end(), res.find(4));
+  EXPECT_DOUBLE_EQ(2, res.at(4).first);
+  EXPECT_EQ(3u, res.at(4).second);
+
+  // Calculate the shortest path between 0 and 1.
+  res = Dijkstra(graph, 0, 1);
+
+  ASSERT_NE(res.end(), res.find(1));
+  EXPECT_DOUBLE_EQ(3, res.at(1).first);
+  EXPECT_EQ(3u, res.at(1).second);
+}
+
+/////////////////////////////////////////////////
+TEST(GraphTestFixture, DijkstraDirected)
+{
+  ///              (6)                  |
+  ///           0------>1               |
+  ///           |      /|\              |
+  ///           |     / | \(5)          |
+  ///           | (2)/  |  ┘            |
+  ///           |   /   |   2           |
+  ///        (1)|  / (2)|  /            |
+  ///           | /     | /(5)          |
+  ///           VL      VL              |
+  ///           3------>4               |
+  ///              (1)                  |
+  DirectedGraph<int, double> graph(
+  {
+    // Vertices.
+    {{"0", 0, 0}, {"1", 1, 1}, {"2", 2, 2}, {"3", 3, 3}, {"4", 4, 4}},
+    // Edges.
+    {{{0, 1}, 2.0, 6.0}, {{0, 3}, 3.0, 1.0},
+     {{1, 2}, 4.0, 5.0}, {{1, 3}, 4.0, 2.0}, {{1, 4}, 4.0, 2.0},
+     {{2, 4}, 2.0, 5.0},
+     {{3, 4}, 2.0, 1.0}}
+  });
+
+  // Inexistent source vertex.
+  auto res = Dijkstra(graph, 99);
+  EXPECT_TRUE(res.empty());
+
+  // Inexistent destination vertex.
+  res = Dijkstra(graph, 0, 99);
+  EXPECT_TRUE(res.empty());
+
+  // Calculate all shortest paths from 0.
+  res = Dijkstra(graph, 0);
+
+  ASSERT_NE(res.end(), res.find(0));
+  EXPECT_DOUBLE_EQ(0, res.at(0).first);
+  EXPECT_EQ(0u, res.at(0).second);
+  ASSERT_NE(res.end(), res.find(1));
+  EXPECT_DOUBLE_EQ(6, res.at(1).first);
+  EXPECT_EQ(0u, res.at(1).second);
+  ASSERT_NE(res.end(), res.find(2));
+  EXPECT_DOUBLE_EQ(11, res.at(2).first);
+  EXPECT_EQ(1u, res.at(2).second);
+  ASSERT_NE(res.end(), res.find(3));
+  EXPECT_DOUBLE_EQ(1, res.at(3).first);
+  EXPECT_EQ(0u, res.at(3).second);
+  ASSERT_NE(res.end(), res.find(4));
+  EXPECT_DOUBLE_EQ(2, res.at(4).first);
+  EXPECT_EQ(3u, res.at(4).second);
+
+  // Calculate the shortest path between 0 and 1.
+  res = Dijkstra(graph, 0, 1);
+
+  ASSERT_NE(res.end(), res.find(1));
+  EXPECT_DOUBLE_EQ(6, res.at(1).first);
+  EXPECT_EQ(0u, res.at(1).second);
+}
+
+/////////////////////////////////////////////////
+TEST(GraphTestFixture, ConnectedComponents)
+{
+  // Connected components of an empty graph.
+  UndirectedGraph<int, double> emptyGraph;
+  auto components = ConnectedComponents(emptyGraph);
+  EXPECT_TRUE(components.empty());
+
+  UndirectedGraph<int, double> graph(
+  {
+    // Vertices.
+    {{"A", 0, 0}, {"B", 1, 1}, {"C", 2, 2}, {"D", 3, 3}, {"E", 4, 4}},
+    // Edges.
+    {{{0, 2}, 2.0, 6.0},
+     {{1, 4}, 4.0, 5.0}}
+  });
+
+  // Connected components of a graph with three components.
+  components = ConnectedComponents(graph);
+  ASSERT_EQ(3u, components.size());
+
+  // Component #0.
+  auto component = components.at(0);
+  auto vertices = component.Vertices();
+  EXPECT_EQ(2u, vertices.size());
+  EXPECT_NE(vertices.end(), vertices.find(0));
+  EXPECT_NE(vertices.end(), vertices.find(2));
+  for (auto const &vertexPair : vertices)
+  {
+    auto &vertex = vertexPair.second.get();
+    switch (vertex.Id())
+    {
+      case 0:
+      {
+        EXPECT_EQ("A", vertex.Name());
+        EXPECT_EQ(0, vertex.Data());
+        break;
+      }
+      case 2:
+      {
+        EXPECT_EQ("C", vertex.Name());
+        EXPECT_EQ(2, vertex.Data());
+        break;
+      }
+      default:
+        FAIL();
+    };
+  }
+
+  // Component #1.
+  component = components.at(1);
+  vertices = component.Vertices();
+  EXPECT_EQ(2u, vertices.size());
+  EXPECT_NE(vertices.end(), vertices.find(1));
+  EXPECT_NE(vertices.end(), vertices.find(4));
+  for (auto const &vertexPair : vertices)
+  {
+    auto &vertex = vertexPair.second.get();
+    switch (vertex.Id())
+    {
+      case 1:
+      {
+        EXPECT_EQ("B", vertex.Name());
+        EXPECT_EQ(1, vertex.Data());
+        break;
+      }
+      case 4:
+      {
+        EXPECT_EQ("E", vertex.Name());
+        EXPECT_EQ(4, vertex.Data());
+        break;
+      }
+      default:
+        FAIL();
+    };
+  }
+
+  // Component #2.
+  component = components.at(2);
+  vertices = component.Vertices();
+  EXPECT_EQ(1u, vertices.size());
+  EXPECT_NE(vertices.end(), vertices.find(3));
+  for (auto const &vertexPair : vertices)
+  {
+    auto &vertex = vertexPair.second.get();
+    switch (vertex.Id())
+    {
+      case 3:
+      {
+        EXPECT_EQ("D", vertex.Name());
+        EXPECT_EQ(3, vertex.Data());
+        break;
+      }
+      default:
+        FAIL();
+    };
+  }
+}
+
diff --git a/src/graph/GraphDirected_TEST.cc b/src/graph/GraphDirected_TEST.cc
new file mode 100644
index 0000000..81984f5
--- /dev/null
+++ b/src/graph/GraphDirected_TEST.cc
@@ -0,0 +1,500 @@
+/*
+ * Copyright (C) 2017 Open Source Robotics Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+*/
+
+#include <gtest/gtest.h>
+#include <iostream>
+#include <string>
+
+#include "ignition/math/graph/Graph.hh"
+
+using namespace ignition;
+using namespace math;
+using namespace graph;
+
+/////////////////////////////////////////////////
+TEST(GraphTest, Edges)
+{
+  // Create a graph with edges [(v0-->v0), (v0-->v1), (v1-->v2), (v2-->v0)]
+  DirectedGraph<int, double> graph(
+  {
+    {{"0", 0, 0}, {"1", 1, 1}, {"2", 2, 2}},
+    {{{0, 0}, 1.0}, {{0, 1}, 2.0}, {{1, 2}, 3.0}, {{2, 0}, 4.0}}
+  });
+
+  auto edges = graph.Edges();
+  EXPECT_EQ(4u, edges.size());
+
+  // Check the Ids.
+  for (auto i = 0; i < 4; ++i)
+    EXPECT_NE(edges.end(), edges.find(i));
+
+  // Check the references.
+  for (auto const &edgePair : edges)
+  {
+    auto &edge = edgePair.second.get();
+    switch (edge.Id())
+    {
+      case 0:
+      {
+        EXPECT_EQ(0u, edge.Tail());
+        EXPECT_EQ(0u, edge.Head());
+        EXPECT_DOUBLE_EQ(1.0, edge.Data());
+        break;
+      }
+      case 1:
+      {
+        EXPECT_EQ(0u, edge.Tail());
+        EXPECT_EQ(1u, edge.Head());
+        EXPECT_DOUBLE_EQ(2.0, edge.Data());
+        break;
+      }
+      case 2:
+      {
+        EXPECT_EQ(1u, edge.Tail());
+        EXPECT_EQ(2u, edge.Head());
+        EXPECT_DOUBLE_EQ(3.0, edge.Data());
+        break;
+      }
+      case 3:
+      {
+        EXPECT_EQ(2u, edge.Tail());
+        EXPECT_EQ(0u, edge.Head());
+        EXPECT_DOUBLE_EQ(4.0, edge.Data());
+        break;
+      }
+      default:
+        FAIL();
+    };
+  }
+}
+
+/////////////////////////////////////////////////
+TEST(GraphTest, AdjacentsFrom)
+{
+  // Create a graph with edges [(v0-->v0), (v0-->v1), (v1-->v2), (v2-->v0)]
+  DirectedGraph<int, double> graph(
+  {
+    {{"0", 0, 0}, {"1", 1, 1}, {"2", 2, 2}},
+    {{{0, 0}, 1.0}, {{0, 1}, 2.0}, {{1, 2}, 3.0}, {{2, 0}, 4.0}}
+  });
+
+  // Try to get the adjacents from an inexistent vertex.
+  auto adjacents = graph.AdjacentsFrom(kNullId);
+  EXPECT_TRUE(adjacents.empty());
+
+  adjacents = graph.AdjacentsFrom(0);
+  EXPECT_EQ(2u, adjacents.size());
+  EXPECT_NE(adjacents.end(), adjacents.find(0));
+  EXPECT_NE(adjacents.end(), adjacents.find(1));
+
+  auto vertex = graph.VertexFromId(0);
+  adjacents = graph.AdjacentsFrom(vertex);
+  EXPECT_EQ(2u, adjacents.size());
+  EXPECT_NE(adjacents.end(), adjacents.find(0));
+  EXPECT_NE(adjacents.end(), adjacents.find(1));
+
+  // Check the references.
+  for (auto const &vertexPair : adjacents)
+  {
+    auto &neighborVertex = vertexPair.second.get();
+    switch (neighborVertex.Id())
+    {
+      case 0:
+      {
+        EXPECT_EQ("0", neighborVertex.Name());
+        EXPECT_EQ(0, neighborVertex.Data());
+        break;
+      }
+      case 1:
+      {
+        EXPECT_EQ("1", neighborVertex.Name());
+        EXPECT_EQ(1, neighborVertex.Data());
+        break;
+      }
+      default:
+        FAIL();
+    };
+  }
+}
+
+/////////////////////////////////////////////////
+TEST(GraphTest, AdjacentsTo)
+{
+  // Create a graph with edges [(v0-->v0), (v0-->v1), (v1-->v2), (v2-->v1)]
+  DirectedGraph<int, double> graph(
+  {
+    {{"0", 0, 0}, {"1", 1, 1}, {"2", 2, 2}},
+    {{{0, 0}, 1.0}, {{0, 1}, 2.0}, {{1, 2}, 3.0}, {{2, 1}, 4.0}}
+  });
+
+  // Try to get the adjacents to an inexistent vertex.
+  auto adjacents = graph.AdjacentsTo(kNullId);
+  EXPECT_TRUE(adjacents.empty());
+
+  adjacents = graph.AdjacentsTo(0);
+  EXPECT_EQ(1u, adjacents.size());
+  EXPECT_NE(adjacents.end(), adjacents.find(0));
+
+  adjacents = graph.AdjacentsTo(1);
+  EXPECT_EQ(2u, adjacents.size());
+  EXPECT_NE(adjacents.end(), adjacents.find(0));
+  EXPECT_NE(adjacents.end(), adjacents.find(2));
+
+  auto vertex = graph.VertexFromId(2);
+  adjacents = graph.AdjacentsTo(vertex);
+  EXPECT_EQ(1u, adjacents.size());
+  EXPECT_NE(adjacents.end(), adjacents.find(1));
+
+  // Check the references.
+  for (auto const &vertexPair : adjacents)
+  {
+    auto &neighborVertex = vertexPair.second.get();
+    switch (neighborVertex.Id())
+    {
+      case 1:
+      {
+        EXPECT_EQ("1", neighborVertex.Name());
+        EXPECT_EQ(1, neighborVertex.Data());
+        break;
+      }
+      default:
+        FAIL();
+    };
+  }
+}
+
+/////////////////////////////////////////////////
+TEST(GraphTest, IncidentsFrom)
+{
+  // Create a graph with edges [(v0-->v0), (v0-->v1), (v1-->v0), (v1-->v2)]
+  DirectedGraph<int, double> graph(
+  {
+    {{"0", 0, 0}, {"1", 1, 1}, {"2", 2, 2}},
+    {{{0, 0}, 1.0}, {{0, 1}, 2.0}, {{1, 0}, 3.0}, {{1, 2}, 4.0}}
+  });
+
+  auto incidents = graph.IncidentsFrom(0);
+  EXPECT_EQ(2u, incidents.size());
+  EXPECT_NE(incidents.end(), incidents.find(0));
+  EXPECT_NE(incidents.end(), incidents.find(1));
+
+  auto vertex = graph.VertexFromId(1);
+  incidents = graph.IncidentsFrom(vertex);
+  EXPECT_EQ(2u, incidents.size());
+  EXPECT_NE(incidents.end(), incidents.find(2));
+  EXPECT_NE(incidents.end(), incidents.find(3));
+
+  // Check the references.
+  for (auto const &edgePair : incidents)
+  {
+    auto &edge = edgePair.second.get();
+    switch (edge.Id())
+    {
+      case 2:
+      {
+        auto vertices = edge.Vertices();
+        EXPECT_EQ(1u, vertices.first);
+        EXPECT_EQ(0u, vertices.second);
+        EXPECT_DOUBLE_EQ(3.0, edge.Data());
+        break;
+      }
+      case 3:
+      {
+        auto vertices = edge.Vertices();
+        EXPECT_EQ(1u, vertices.first);
+        EXPECT_EQ(2u, vertices.second);
+        EXPECT_DOUBLE_EQ(4.0, edge.Data());
+        break;
+      }
+      default:
+        FAIL();
+    };
+  }
+
+  incidents = graph.IncidentsFrom(2);
+  EXPECT_TRUE(incidents.empty());
+
+  // Try an inexistent vertex.
+  incidents = graph.IncidentsFrom(kNullId);
+  EXPECT_EQ(0u, incidents.size());
+}
+
+/////////////////////////////////////////////////
+TEST(GraphTest, IncidentsTo)
+{
+  // Create a graph with edges [(v0-->v0), (v0-->v1), (v1-->v2), (v2-->v0)]
+  DirectedGraph<int, double> graph(
+  {
+    {{"0", 0, 0}, {"1", 1, 1}, {"2", 2, 2}},
+    {{{0, 0}, 1.0}, {{0, 1}, 2.0}, {{1, 2}, 3.0}, {{2, 0}, 4.0}}
+  });
+
+  auto incidents = graph.IncidentsTo(0);
+  EXPECT_EQ(2u, incidents.size());
+  EXPECT_NE(incidents.end(), incidents.find(0));
+  EXPECT_NE(incidents.end(), incidents.find(3));
+
+  auto vertex = graph.VertexFromId(0);
+  incidents = graph.IncidentsTo(vertex);
+  EXPECT_EQ(2u, incidents.size());
+  EXPECT_NE(incidents.end(), incidents.find(0));
+  EXPECT_NE(incidents.end(), incidents.find(3));
+
+  // Check the references.
+  for (auto const &edgePair : incidents)
+  {
+    auto &edge = edgePair.second.get();
+    switch (edge.Id())
+    {
+      case 0:
+      {
+        auto vertices = edge.Vertices();
+        EXPECT_EQ(0u, vertices.first);
+        EXPECT_EQ(0u, vertices.second);
+        EXPECT_DOUBLE_EQ(1.0, edge.Data());
+        break;
+      }
+      case 3:
+      {
+        auto vertices = edge.Vertices();
+        EXPECT_EQ(2u, vertices.first);
+        EXPECT_EQ(0u, vertices.second);
+        EXPECT_DOUBLE_EQ(4.0, edge.Data());
+        break;
+      }
+      default:
+        FAIL();
+    };
+  }
+}
+
+/////////////////////////////////////////////////
+TEST(GraphTest, InDegree)
+{
+  // Create a graph with edges [(v0-->v0), (v0-->v1), (v1-->v2), (v2-->v1) x 2]
+  DirectedGraph<int, double> graph(
+  {
+    {{"0", 0, 0}, {"1", 1, 1}, {"2", 2, 2}},
+    {{{0, 0}, 1.0}, {{0, 1}, 2.0}, {{1, 2}, 3.0}, {{2, 1}, 4.0}, {{2, 1}, 4.0}}
+  });
+
+  EXPECT_EQ(1u, graph.InDegree(0));
+  EXPECT_EQ(1u, graph.InDegree(graph.VertexFromId(0)));
+  EXPECT_EQ(3u, graph.InDegree(1));
+  EXPECT_EQ(3u, graph.InDegree(graph.VertexFromId(1)));
+  EXPECT_EQ(1u, graph.InDegree(2));
+  EXPECT_EQ(1u, graph.InDegree(graph.VertexFromId(2)));
+}
+
+/////////////////////////////////////////////////
+TEST(GraphTest, OutDegree)
+{
+  // Create a graph with edges [(v0-->v0), (v0-->v1), (v1-->v0), (v1-->v2) x 2]
+  DirectedGraph<int, double> graph(
+  {
+    {{"0", 0, 0}, {"1", 1, 1}, {"2", 2, 2}},
+    {{{0, 0}, 1.0}, {{0, 1}, 2.0}, {{1, 0}, 3.0}, {{1, 2}, 4.0}, {{1, 2}, 5.0}}
+  });
+
+  EXPECT_EQ(2u, graph.OutDegree(0));
+  EXPECT_EQ(2u, graph.OutDegree(graph.VertexFromId(0)));
+  EXPECT_EQ(3u, graph.OutDegree(1));
+  EXPECT_EQ(3u, graph.OutDegree(graph.VertexFromId(1)));
+  EXPECT_EQ(0u, graph.OutDegree(2));
+  EXPECT_EQ(0u, graph.OutDegree(graph.VertexFromId(2)));
+}
+
+/////////////////////////////////////////////////
+TEST(GraphTest, AddEdge)
+{
+  // Create a graph with three vertices.
+  DirectedGraph<int, double> graph(
+  {
+    {{"0", 0, 0}, {"1", 1, 1}, {"2", 2, 2}},
+    {}
+  });
+
+  // Create some edges [(v0-->v1), (v1-->v2), (v2-->v0)]
+  auto &e0 = graph.AddEdge({0, 1}, 2.0);
+  auto &e1 = graph.AddEdge({1, 2}, 3.0);
+  auto &e2 = graph.AddEdge({2, 0}, 4.0);
+
+  // Check the edge content.
+  EXPECT_DOUBLE_EQ(2.0, e0.Data());
+  EXPECT_DOUBLE_EQ(3.0, e1.Data());
+  EXPECT_DOUBLE_EQ(4.0, e2.Data());
+
+  // Change some content and verity it.
+  e2.Data() = 5.0;
+  e2.SetWeight(6.0);
+  auto edge = graph.EdgeFromId(e2.Id());
+  EXPECT_DOUBLE_EQ(5.0, edge.Data());
+  EXPECT_DOUBLE_EQ(6.0, edge.Weight());
+
+  // Check that the edges point to the right vertices.
+  EXPECT_EQ(0u, e0.Tail());
+  EXPECT_EQ(1u, e0.Head());
+
+  auto edges = graph.Edges();
+  EXPECT_EQ(3u, edges.size());
+
+  // Try to add an edge with an incorrect tail.
+  edge = graph.AddEdge({kNullId, 1}, 2.0);
+  EXPECT_EQ(kNullId, edge.Id());
+  EXPECT_EQ(3u, graph.Edges().size());
+
+  // Try to add an edge with an incorrect head.
+  edge = graph.AddEdge({0, kNullId}, 2.0);
+  EXPECT_EQ(kNullId, edge.Id());
+  EXPECT_EQ(3u, graph.Edges().size());
+}
+
+/////////////////////////////////////////////////
+TEST(GraphTest, RemoveEdge)
+{
+  // Create a graph with edges [(v0-->v1), (v1-->v2), (v2-->v0)]
+  DirectedGraph<int, double> graph(
+  {
+    {{"0", 0, 0}, {"1", 1, 1}, {"2", 2, 2}},
+    {{{0, 1}, 2.0}, {{1, 2}, 3.0}, {{2, 0}, 4.0}}
+  });
+
+  // Remove a nonexistent edge shouldn't cause any effect.
+  EXPECT_FALSE(graph.RemoveEdge(kNullId));
+  EXPECT_EQ(3u, graph.Edges().size());
+  EXPECT_EQ(1u, graph.IncidentsTo(1).size());
+
+  // Remove the edge (v0-->v1)
+  EXPECT_TRUE(graph.RemoveEdge(0));
+  EXPECT_EQ(2u, graph.Edges().size());
+  EXPECT_EQ(0u, graph.IncidentsTo(1).size());
+
+  // Remove the edge (v1-->v2)
+  auto edge = graph.EdgeFromId(1);
+  EXPECT_TRUE(graph.RemoveEdge(edge));
+  EXPECT_EQ(1u, graph.Edges().size());
+
+  // Try to remove an edge that doesn't exist anymore.
+  EXPECT_FALSE(graph.RemoveEdge(1));
+  EXPECT_EQ(1u, graph.Edges().size());
+
+  // Remove the edge (v2-->v0)
+  EXPECT_TRUE(graph.RemoveEdge(2));
+  EXPECT_EQ(0u, graph.Edges().size());
+}
+
+/////////////////////////////////////////////////
+TEST(GraphTest, RemoveVertex)
+{
+  // Create a graph with edges [(v0-->v1), (v1-->v2), (v2-->v0)]
+  DirectedGraph<int, double> graph(
+  {
+    {{"0", 0, 0}, {"1", 1, 1}, {"2", 2, 2}},
+    {{{0, 1}, 2.0}, {{1, 2}, 3.0}, {{2, 0}, 4.0}}
+  });
+
+  // Remove a nonexistent vertex shouldn't cause any effect.
+  EXPECT_FALSE(graph.RemoveVertex(kNullId));
+  EXPECT_EQ(3u, graph.Vertices().size());
+  EXPECT_EQ(1u, graph.AdjacentsFrom(1).size());
+
+  // Remove vertex #2.
+  EXPECT_TRUE(graph.RemoveVertex(2));
+  EXPECT_EQ(2u, graph.Vertices().size());
+  EXPECT_EQ(1u, graph.Edges().size());
+  EXPECT_EQ(0u, graph.AdjacentsFrom(1).size());
+
+  // Remove vertex #1.
+  auto vertex = graph.VertexFromId(1);
+  EXPECT_TRUE(graph.RemoveVertex(vertex));
+  EXPECT_EQ(1u, graph.Vertices().size());
+  EXPECT_TRUE(graph.Edges().empty());
+
+  // Try to remove a vertex (#1) that doesn't exist anymore.
+  EXPECT_FALSE(graph.RemoveVertex(1));
+  EXPECT_EQ(1u, graph.Vertices().size());
+  EXPECT_TRUE(graph.Edges().empty());
+
+  // Remove vertex #0.
+  EXPECT_TRUE(graph.RemoveVertex(0));
+  EXPECT_TRUE(graph.Vertices().empty());
+
+  EXPECT_TRUE(graph.Empty());
+}
+
+/////////////////////////////////////////////////
+TEST(GraphTest, RemoveVertices)
+{
+  // Create a graph with edges [(v0-->v1), (v1-->v2), (v2-->v3), (v3-->v0)]
+  DirectedGraph<int, double> graph(
+  {
+    {{"v0", 0, 0}, {"v1", 1, 1}, {"common", 2, 2}, {"common", 3, 3}},
+    {{{0, 1}, 2.0}, {{1, 2}, 3.0}, {{2, 3}, 4.0}, {{3, 0}, 5.0}}
+  });
+
+  // Try to remove a node with a name that doesn't exist.
+  EXPECT_EQ(graph.RemoveVertices("wrong_name"), 0u);
+  EXPECT_EQ(4u, graph.Vertices().size());
+  EXPECT_EQ(1u, graph.AdjacentsFrom(1).size());
+
+  // Remove two vertices at the same time.
+  EXPECT_EQ(2u, graph.RemoveVertices("common"));
+  EXPECT_EQ(2u, graph.Vertices().size());
+  EXPECT_EQ(1u, graph.Edges().size());
+
+  EXPECT_EQ(0u, graph.AdjacentsFrom(1).size());
+
+  EXPECT_EQ(1u, graph.RemoveVertices("v1"));
+  EXPECT_EQ(1u, graph.Vertices().size());
+  EXPECT_TRUE(graph.Edges().empty());
+
+  EXPECT_EQ(1u, graph.RemoveVertices("v0"));
+  EXPECT_TRUE(graph.Vertices().empty());
+
+  EXPECT_TRUE(graph.Empty());
+}
+
+/////////////////////////////////////////////////
+TEST(GraphTest, StreamInsertion)
+{
+  // Create a graph with 4 vertices and
+  // edges [(v0-->v0), (v0-->v1), (v1-->v2), (v2-->v3)]
+  DirectedGraph<int, double> graph(
+  {
+    {{"v0", 0, 0}, {"v1", 1, 1}, {"v2", 2, 2}, {"v3", 3, 3}},
+    {{{0, 1}, 2.0, 4.0}, {{0, 0}, 2.0, 6.0}, {{1, 2}, 3.0}, {{2, 0}, 4.0}}
+  });
+
+  std::ostringstream output;
+  output << graph;
+
+  std::cout << "# Use this snippet with your favorite DOT tool." << std::endl;
+  std::cout << graph << std::endl;
+
+  for (auto const &s : {"digraph {\n",
+                        "  0 [label=\"v0 (0)\"];\n",
+                        "  1 [label=\"v1 (1)\"];\n",
+                        "  2 [label=\"v2 (2)\"];\n",
+                        "  3 [label=\"v3 (3)\"];\n",
+                        "  0 -> 1 [label=4];\n",
+                        "  0 -> 0 [label=6];\n",
+                        "  1 -> 2 [label=1];\n",
+                        "  2 -> 0 [label=1];\n"})
+  {
+    EXPECT_NE(std::string::npos, output.str().find(s));
+  }
+}
diff --git a/src/graph/GraphUndirected_TEST.cc b/src/graph/GraphUndirected_TEST.cc
new file mode 100644
index 0000000..dd34afc
--- /dev/null
+++ b/src/graph/GraphUndirected_TEST.cc
@@ -0,0 +1,534 @@
+/*
+ * Copyright (C) 2017 Open Source Robotics Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+*/
+
+#include <gtest/gtest.h>
+#include <iostream>
+#include <string>
+#include <utility>
+#include <vector>
+
+#include "ignition/math/graph/Graph.hh"
+
+using namespace ignition;
+using namespace math;
+using namespace graph;
+
+/////////////////////////////////////////////////
+TEST(UndirectedGraphTest, Edges)
+{
+  // Create a graph with edges [(v0--v0), (v0--v1), (v1--v2), (v2--v0)]
+  UndirectedGraph<int, double> graph(
+  {
+    {{"0", 0, 0}, {"1", 1, 1}, {"2", 2, 2}},
+    {{{0, 0}, 1.0}, {{0, 1}, 2.0}, {{1, 2}, 3.0}, {{2, 0}, 4.0}}
+  });
+
+  auto edges = graph.Edges();
+  EXPECT_EQ(4u, edges.size());
+
+  // Check the Ids.
+  for (auto i = 0; i < 4; ++i)
+    EXPECT_NE(edges.end(), edges.find(i));
+
+  // Check the references.
+  for (auto const &edgePair : edges)
+  {
+    auto &edge = edgePair.second.get();
+    switch (edge.Id())
+    {
+      case 0:
+      {
+        auto vertices = edge.Vertices();
+        EXPECT_EQ(0u, vertices.first);
+        EXPECT_EQ(0u, vertices.second);
+        EXPECT_DOUBLE_EQ(1.0, edge.Data());
+        break;
+      }
+      case 1:
+      {
+        auto vertices = edge.Vertices();
+        EXPECT_EQ(0u, vertices.first);
+        EXPECT_EQ(1u, vertices.second);
+        EXPECT_DOUBLE_EQ(2.0, edge.Data());
+        break;
+      }
+      case 2:
+      {
+        auto vertices = edge.Vertices();
+        EXPECT_EQ(1u, vertices.first);
+        EXPECT_EQ(2u, vertices.second);
+        EXPECT_DOUBLE_EQ(3.0, edge.Data());
+        break;
+      }
+      case 3:
+      {
+        auto vertices = edge.Vertices();
+        EXPECT_EQ(2u, vertices.first);
+        EXPECT_EQ(0u, vertices.second);
+        EXPECT_DOUBLE_EQ(4.0, edge.Data());
+        break;
+      }
+      default:
+        FAIL();
+    };
+  }
+}
+
+/////////////////////////////////////////////////
+TEST(UndirectedGraphTest, AdjacentsFrom)
+{
+  // Create a graph with edges [(v0--v0), (v0--v1), (v1--v2), (v2--v0)]
+  UndirectedGraph<int, double> graph(
+  {
+    {{"0", 0, 0}, {"1", 1, 1}, {"2", 2, 2}},
+    {{{0, 0}, 1.0}, {{0, 1}, 2.0}, {{1, 2}, 3.0}, {{2, 0}, 4.0}}
+  });
+
+  // Try to get the adjacents from an inexistent vertex.
+  auto adjacents = graph.AdjacentsFrom(kNullId);
+  EXPECT_TRUE(adjacents.empty());
+
+  adjacents = graph.AdjacentsFrom(0);
+  EXPECT_EQ(3u, adjacents.size());
+  EXPECT_NE(adjacents.end(), adjacents.find(0));
+  EXPECT_NE(adjacents.end(), adjacents.find(1));
+  EXPECT_NE(adjacents.end(), adjacents.find(2));
+
+  auto vertex = graph.VertexFromId(0);
+  adjacents = graph.AdjacentsFrom(vertex);
+  EXPECT_EQ(3u, adjacents.size());
+  EXPECT_NE(adjacents.end(), adjacents.find(0));
+  EXPECT_NE(adjacents.end(), adjacents.find(1));
+  EXPECT_NE(adjacents.end(), adjacents.find(2));
+
+  // Check the references.
+  for (auto const &vertexPair : adjacents)
+  {
+    auto &neighborVertex = vertexPair.second.get();
+    switch (neighborVertex.Id())
+    {
+      case 0:
+      {
+        EXPECT_EQ("0", neighborVertex.Name());
+        EXPECT_EQ(0, neighborVertex.Data());
+        break;
+      }
+      case 1:
+      {
+        EXPECT_EQ("1", neighborVertex.Name());
+        EXPECT_EQ(1, neighborVertex.Data());
+        break;
+      }
+      case 2:
+      {
+        EXPECT_EQ("2", neighborVertex.Name());
+        EXPECT_EQ(2, neighborVertex.Data());
+        break;
+      }
+      default:
+        FAIL();
+    };
+  }
+}
+
+/////////////////////////////////////////////////
+TEST(UndirectedGraphTest, AdjacentsTo)
+{
+  // Create a graph with edges [(v0--v0), (v0--v1), (v1--v2)]
+  UndirectedGraph<int, double> graph(
+  {
+    {{"0", 0, 0}, {"1", 1, 1}, {"2", 2, 2}},
+    {{{0, 0}, 1.0}, {{0, 1}, 2.0}, {{1, 2}, 3.0}}
+  });
+
+  // Try to get the adjacents from an inexistent vertex.
+  auto adjacents = graph.AdjacentsTo(kNullId);
+  EXPECT_TRUE(adjacents.empty());
+
+  adjacents = graph.AdjacentsTo(0);
+  EXPECT_EQ(2u, adjacents.size());
+  EXPECT_NE(adjacents.end(), adjacents.find(0));
+  EXPECT_NE(adjacents.end(), adjacents.find(1));
+
+  auto vertex = graph.VertexFromId(1);
+  adjacents = graph.AdjacentsTo(vertex);
+  EXPECT_EQ(2u, adjacents.size());
+  EXPECT_NE(adjacents.end(), adjacents.find(0));
+  EXPECT_NE(adjacents.end(), adjacents.find(2));
+
+  // Check the references.
+  for (auto const &vertexPair : adjacents)
+  {
+    auto &neighborVertex = vertexPair.second.get();
+    switch (neighborVertex.Id())
+    {
+      case 0:
+      {
+        EXPECT_EQ("0", neighborVertex.Name());
+        EXPECT_EQ(0, neighborVertex.Data());
+        break;
+      }
+      case 2:
+      {
+        EXPECT_EQ("2", neighborVertex.Name());
+        EXPECT_EQ(2, neighborVertex.Data());
+        break;
+      }
+      default:
+        FAIL();
+    };
+  }
+}
+
+/////////////////////////////////////////////////
+TEST(UndirectedGraphTest, IncidentsFrom)
+{
+  // Create a graph with edges [(v0--v0), (v0--v1), (v1--v2)]
+  UndirectedGraph<int, double> graph(
+  {
+    {{"0", 0, 0}, {"1", 1, 1}, {"2", 2, 2}},
+    {{{0, 0}, 1.0}, {{0, 1}, 2.0}, {{1, 2}, 3.0}}
+  });
+
+  auto incidents = graph.IncidentsFrom(0);
+  EXPECT_EQ(2u, incidents.size());
+  EXPECT_NE(incidents.end(), incidents.find(0));
+  EXPECT_NE(incidents.end(), incidents.find(1));
+
+  auto vertex = graph.VertexFromId(1);
+  incidents = graph.IncidentsFrom(vertex);
+  EXPECT_EQ(2u, incidents.size());
+  EXPECT_NE(incidents.end(), incidents.find(1));
+  EXPECT_NE(incidents.end(), incidents.find(2));
+
+  // Check the references.
+  for (auto const &edgePair : incidents)
+  {
+    auto &edge = edgePair.second.get();
+    switch (edge.Id())
+    {
+      case 1:
+      {
+        auto vertices = edge.Vertices();
+        EXPECT_EQ(0u, vertices.first);
+        EXPECT_EQ(1u, vertices.second);
+        EXPECT_DOUBLE_EQ(2.0, edge.Data());
+        break;
+      }
+      case 2:
+      {
+        auto vertices = edge.Vertices();
+        EXPECT_EQ(1u, vertices.first);
+        EXPECT_EQ(2u, vertices.second);
+        EXPECT_DOUBLE_EQ(3.0, edge.Data());
+        break;
+      }
+      default:
+        FAIL();
+    };
+  }
+
+  // Try an inexistent vertex.
+  incidents = graph.IncidentsFrom(kNullId);
+  EXPECT_EQ(0u, incidents.size());
+}
+
+/////////////////////////////////////////////////
+TEST(UndirectedGraphTest, IncidentsTo)
+{
+  // Create a graph with edges [(v0--v0), (v0--v1), (v1--v2), (v2--v0)]
+  UndirectedGraph<int, double> graph(
+  {
+    {{"0", 0, 0}, {"1", 1, 1}, {"2", 2, 2}},
+    {{{0, 0}, 1.0}, {{0, 1}, 2.0}, {{1, 2}, 3.0}, {{2, 0}, 4.0}}
+  });
+
+  auto incidents = graph.IncidentsTo(0);
+  EXPECT_EQ(3u, incidents.size());
+  EXPECT_NE(incidents.end(), incidents.find(0));
+  EXPECT_NE(incidents.end(), incidents.find(1));
+  EXPECT_NE(incidents.end(), incidents.find(3));
+
+  auto vertex = graph.VertexFromId(0);
+  incidents = graph.IncidentsTo(vertex);
+  EXPECT_EQ(3u, incidents.size());
+  EXPECT_NE(incidents.end(), incidents.find(0));
+  EXPECT_NE(incidents.end(), incidents.find(1));
+  EXPECT_NE(incidents.end(), incidents.find(3));
+
+  // Check the references.
+  for (auto const &edgePair : incidents)
+  {
+    auto &edge = edgePair.second.get();
+    switch (edge.Id())
+    {
+      case 0:
+      {
+        auto vertices = edge.Vertices();
+        EXPECT_EQ(0u, vertices.first);
+        EXPECT_EQ(0u, vertices.second);
+        EXPECT_DOUBLE_EQ(1.0, edge.Data());
+        break;
+      }
+      case 1:
+      {
+        auto vertices = edge.Vertices();
+        EXPECT_EQ(0u, vertices.first);
+        EXPECT_EQ(1u, vertices.second);
+        EXPECT_DOUBLE_EQ(2.0, edge.Data());
+        break;
+      }
+      case 3:
+      {
+        auto vertices = edge.Vertices();
+        EXPECT_EQ(2u, vertices.first);
+        EXPECT_EQ(0u, vertices.second);
+        EXPECT_DOUBLE_EQ(4.0, edge.Data());
+        break;
+      }
+      default:
+        FAIL();
+    };
+  }
+}
+
+/////////////////////////////////////////////////
+TEST(UndirectedGraphTest, InDegree)
+{
+  // Create a graph with edges [(v0--v0), (v0--v1), (v1--v2) x 2]
+  UndirectedGraph<int, double> graph(
+  {
+    {{"0", 0, 0}, {"1", 1, 1}, {"2", 2, 2}},
+    {{{0, 0}, 1.0}, {{0, 1}, 2.0}, {{1, 2}, 3.0}, {{1, 2}, 4.0}}
+  });
+
+  EXPECT_EQ(2u, graph.InDegree(0));
+  EXPECT_EQ(2u, graph.InDegree(graph.VertexFromId(0)));
+  EXPECT_EQ(3u, graph.InDegree(1));
+  EXPECT_EQ(3u, graph.InDegree(graph.VertexFromId(1)));
+  EXPECT_EQ(2u, graph.InDegree(2));
+  EXPECT_EQ(2u, graph.InDegree(graph.VertexFromId(2)));
+}
+
+/////////////////////////////////////////////////
+TEST(UndirectedGraphTest, OutDegree)
+{
+  // Create a graph with edges [(v0--v0), (v0--v1), (v1--v2) x 2]
+  UndirectedGraph<int, double> graph(
+  {
+    {{"0", 0, 0}, {"1", 1, 1}, {"2", 2, 2}},
+    {{{0, 0}, 1.0}, {{0, 1}, 2.0}, {{1, 2}, 3.0}, {{1, 2}, 4.0}}
+  });
+
+  EXPECT_EQ(2u, graph.OutDegree(0));
+  EXPECT_EQ(2u, graph.OutDegree(graph.VertexFromId(0)));
+  EXPECT_EQ(3u, graph.OutDegree(1));
+  EXPECT_EQ(3u, graph.OutDegree(graph.VertexFromId(1)));
+  EXPECT_EQ(2u, graph.OutDegree(2));
+  EXPECT_EQ(2u, graph.OutDegree(graph.VertexFromId(2)));
+}
+
+/////////////////////////////////////////////////
+TEST(UndirectedGraphTest, AddEdge)
+{
+  // Create a graph with three vertices.
+  UndirectedGraph<int, double> graph(
+  {
+    {{"0", 0, 0}, {"1", 1, 1}, {"2", 2, 2}},
+    {}
+  });
+
+  // Create some edges [(v0--v1), (v1--v2), (v2--v0)]
+  auto &e0 = graph.AddEdge({0, 1}, 2.0);
+  auto &e1 = graph.AddEdge({1, 2}, 3.0);
+  auto &e2 = graph.AddEdge({2, 0}, 4.0);
+
+  // Check the edge content.
+  EXPECT_DOUBLE_EQ(2.0, e0.Data());
+  EXPECT_DOUBLE_EQ(3.0, e1.Data());
+  EXPECT_DOUBLE_EQ(4.0, e2.Data());
+
+  // Change some content and verity it.
+  e2.Data() = 5.0;
+  e2.SetWeight(6.0);
+  auto edge = graph.EdgeFromId(e2.Id());
+  EXPECT_DOUBLE_EQ(5.0, edge.Data());
+  EXPECT_DOUBLE_EQ(6.0, edge.Weight());
+
+  // Check that the edges point to the right vertices.
+  EXPECT_EQ(0u, e0.Vertices().first);
+
+  auto edges = graph.Edges();
+  EXPECT_EQ(3u, edges.size());
+
+  // Try to add an edge with an incorrect tail.
+  edge = graph.AddEdge({kNullId, 1}, 2.0);
+  EXPECT_EQ(kNullId, edge.Id());
+  EXPECT_EQ(3u, graph.Edges().size());
+
+  // Try to add an edge with an incorrect head.
+  edge = graph.AddEdge({0, kNullId}, 2.0);
+  EXPECT_EQ(kNullId, edge.Id());
+  EXPECT_EQ(3u, graph.Edges().size());
+}
+
+/////////////////////////////////////////////////
+TEST(UndirectedGraphTest, RemoveEdge)
+{
+  // Create a graph with edges [(v0--v1), (v1--v2), (v2--v0)]
+  UndirectedGraph<int, double> graph(
+  {
+    {{"0", 0, 0}, {"1", 1, 1}, {"2", 2, 2}},
+    {{{0, 1}, 2.0}, {{1, 2}, 3.0}, {{2, 0}, 4.0}}
+  });
+
+  // Remove a nonexistent edge shouldn't cause any effect.
+  EXPECT_FALSE(graph.RemoveEdge(kNullId));
+  EXPECT_EQ(3u, graph.Edges().size());
+  EXPECT_EQ(2u, graph.IncidentsTo(1).size());
+
+  // Remove the edge (v0--v1)
+  EXPECT_TRUE(graph.RemoveEdge(0));
+  EXPECT_EQ(2u, graph.Edges().size());
+  EXPECT_EQ(1u, graph.IncidentsTo(1).size());
+
+  // Remove the edge (v1--v2)
+  auto edge = graph.EdgeFromId(1);
+  EXPECT_TRUE(graph.RemoveEdge(edge));
+  EXPECT_EQ(1u, graph.Edges().size());
+
+  // Try to remove an edge that doesn't exist anymore.
+  EXPECT_FALSE(graph.RemoveEdge(1));
+  EXPECT_EQ(1u, graph.Edges().size());
+
+  // Remove the edge (v2--v0)
+  EXPECT_TRUE(graph.RemoveEdge(2));
+  EXPECT_EQ(0u, graph.Edges().size());
+}
+
+/////////////////////////////////////////////////
+TEST(UndirectedGraphTest, RemoveVertex)
+{
+  // Create a graph with edges [(v0--v1), (v1--v2), (v2--v0)]
+  UndirectedGraph<int, double> graph(
+  {
+    {{"0", 0, 0}, {"1", 1, 1}, {"2", 2, 2}},
+    {{{0, 1}, 2.0}, {{1, 2}, 3.0}, {{2, 0}, 4.0}}
+  });
+
+  // Remove a nonexistent vertex shouldn't cause any effect.
+  EXPECT_FALSE(graph.RemoveVertex(kNullId));
+  EXPECT_EQ(3u, graph.Vertices().size());
+  EXPECT_EQ(2u, graph.AdjacentsFrom(1).size());
+
+  // Remove vertex #2.
+  EXPECT_TRUE(graph.RemoveVertex(2));
+  EXPECT_EQ(2u, graph.Vertices().size());
+  EXPECT_EQ(1u, graph.Edges().size());
+  EXPECT_EQ(1u, graph.AdjacentsFrom(1).size());
+
+  // Remove vertex #1.
+  auto vertex = graph.VertexFromId(1);
+  EXPECT_TRUE(graph.RemoveVertex(vertex));
+  EXPECT_EQ(1u, graph.Vertices().size());
+  EXPECT_TRUE(graph.Edges().empty());
+
+  // Try to remove a vertex (#1) that doesn't exist anymore.
+  EXPECT_FALSE(graph.RemoveVertex(1));
+  EXPECT_EQ(1u, graph.Vertices().size());
+  EXPECT_TRUE(graph.Edges().empty());
+
+  // Remove vertex #0.
+  EXPECT_TRUE(graph.RemoveVertex(0));
+  EXPECT_TRUE(graph.Vertices().empty());
+  EXPECT_TRUE(graph.Empty());
+}
+
+/////////////////////////////////////////////////
+TEST(UndirectedGraphTest, RemoveVertices)
+{
+  // Create a graph with edges [(v0--v1), (v1--v2), (v2--v3), (v3--v0)]
+  UndirectedGraph<int, double> graph(
+  {
+    {{"v0", 0, 0}, {"v1", 1, 1}, {"common", 2, 2}, {"common", 3, 3}},
+    {{{0, 1}, 2.0}, {{1, 2}, 3.0}, {{2, 3}, 4.0}, {{3, 0}, 5.0}}
+  });
+
+  // Try to remove a node with a name that doesn't exist.
+  EXPECT_EQ(0u, graph.RemoveVertices("wrong_name"));
+  EXPECT_EQ(4u, graph.Vertices().size());
+  EXPECT_EQ(2u, graph.AdjacentsFrom(1).size());
+
+  // Remove two vertices at the same time.
+  EXPECT_EQ(2u, graph.RemoveVertices("common"));
+  EXPECT_EQ(2u, graph.Vertices().size());
+  EXPECT_EQ(1u, graph.Edges().size());
+  EXPECT_EQ(1u, graph.AdjacentsFrom(1).size());
+
+  // Remove vertex #1.
+  EXPECT_EQ(1u, graph.RemoveVertices("v1"));
+  EXPECT_EQ(1u, graph.Vertices().size());
+  EXPECT_TRUE(graph.Edges().empty());
+
+  // Remove vertex #0.
+  EXPECT_EQ(1u, graph.RemoveVertices("v0"));
+  EXPECT_TRUE(graph.Vertices().empty());
+  EXPECT_TRUE(graph.Empty());
+}
+
+/////////////////////////////////////////////////
+TEST(UndirectedGraphTest, StreamInsertion)
+{
+  // Create a graph with 4 vertices and
+  // edges [(v0-->v0), (v0-->v1), (v1-->v2), (v2-->v3)]
+  UndirectedGraph<int, double> graph(
+  {
+    {{"v0", 0, 0}, {"v1", 1, 1}, {"v2", 2, 2}, {"v3", 3, 3}},
+    {{{0, 1}, 2.0, 4.0}, {{0, 0}, 2.0, 6.0}, {{1, 2}, 3.0}, {{2, 0}, 4.0}}
+  });
+
+  std::ostringstream output;
+  output << graph;
+
+  std::cout << "# Use this snippet with your favorite DOT tool." << std::endl;
+  std::cout << graph << std::endl;
+
+  for (auto const &s : {"graph {\n",
+                        "  0 [label=\"v0 (0)\"];\n",
+                        "  1 [label=\"v1 (1)\"];\n",
+                        "  2 [label=\"v2 (2)\"];\n",
+                        "  3 [label=\"v3 (3)\"];\n"})
+  {
+    EXPECT_NE(std::string::npos, output.str().find(s));
+  }
+
+  // We don't really know the order in which the edges will be printed.
+  // We also don't know the order in which the vertices on each edge will be
+  // printed.
+  std::vector<std::pair<std::string, std::string>> expectedEdges =
+    {
+      {"  0 -- 0 [label=6];\n", "  0 -- 0 [label=6];\n"},
+      {"  0 -- 1 [label=4];\n", "  1 -- 0 [label=4];\n"},
+      {"  1 -- 2 [label=1];\n", "  2 -- 1 [label=1];\n"},
+      {"  0 -- 2 [label=1];\n", "  2 -- 0 [label=1];\n"}
+    };
+  for (auto const &edge : expectedEdges)
+  {
+    EXPECT_TRUE((output.str().find(std::get<0>(edge)) != std::string::npos) ||
+                (output.str().find(std::get<1>(edge)) != std::string::npos));
+  }
+}
diff --git a/src/graph/Graph_TEST.cc b/src/graph/Graph_TEST.cc
new file mode 100644
index 0000000..1d75e70
--- /dev/null
+++ b/src/graph/Graph_TEST.cc
@@ -0,0 +1,435 @@
+/*
+ * Copyright (C) 2017 Open Source Robotics Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+*/
+
+#include <gtest/gtest.h>
+#include <string>
+
+#include "ignition/math/graph/Graph.hh"
+
+using namespace ignition;
+using namespace math;
+using namespace graph;
+
+// Define a test fixture class template.
+template <class T>
+class GraphTestFixture : public testing::Test
+{
+};
+
+// Simulate a class with the maximum allowed number of vertices used.
+template <typename V, typename E>
+class MockVerticesFullUndirectedGraph : public UndirectedGraph<V, E>
+{
+  // Default constructor.
+  public: MockVerticesFullUndirectedGraph()
+  {
+    this->nextVertexId = MAX_UI64;
+  }
+};
+
+// Simulate a class with the maximum allowed number of edges used.
+template <typename V, typename E>
+class MockEdgesFullUndirectedGraph : public UndirectedGraph<V, E>
+{
+  // Default constructor.
+  public: MockEdgesFullUndirectedGraph()
+  {
+    this->nextEdgeId = MAX_UI64;
+  }
+};
+
+// The list of graphs we want to test.
+using GraphTypes = ::testing::Types<DirectedGraph<int, double>,
+                                    UndirectedGraph<int, double>>;
+TYPED_TEST_CASE(GraphTestFixture, GraphTypes);
+
+/////////////////////////////////////////////////
+TYPED_TEST(GraphTestFixture, UniformInitialization)
+{
+  {
+    TypeParam graph(
+    {
+      // Create vertices with custom Ids.
+      {{"0", 0, 0}, {"1", 1, 1}, {"2", 2, 2}},
+      // Create edges.
+      {{{0, 1}, 0.0}, {{1, 2}, 0.0}}
+    });
+
+    // Verify the vertices.
+    auto vertices = graph.Vertices();
+    EXPECT_EQ(3u, vertices.size());
+
+    for (int i = 0; i < 3; ++i)
+    {
+      unsigned int iu = i;
+      ASSERT_NE(vertices.find(i), vertices.end());
+      auto v = vertices.at(i).get();
+      EXPECT_EQ(std::to_string(i), v.Name());
+      EXPECT_EQ(iu, v.Id());
+      EXPECT_EQ(i, v.Data());
+    }
+
+    // Verify the edges.
+    auto edges = graph.Edges();
+    EXPECT_EQ(2u, edges.size());
+  }
+  {
+    TypeParam graph(
+    {
+      // Create vertices with automatic Id selection.
+      {{"0", 0}, {"1", 1}, {"2", 2}},
+      // Create edges.
+      {{{0, 1}, 0.0}, {{1, 2}, 0.0}}
+    });
+
+    // Verify the vertices.
+    auto vertices = graph.Vertices();
+    EXPECT_EQ(3u, vertices.size());
+
+    for (int i = 0; i < 3; ++i)
+    {
+      unsigned int iu = i;
+      ASSERT_NE(vertices.find(i), vertices.end());
+      auto v = vertices.at(i).get();
+      EXPECT_EQ(std::to_string(i), v.Name());
+      EXPECT_EQ(iu, v.Id());
+      EXPECT_EQ(i, v.Data());
+    }
+
+    // Verify the edges.
+    auto edges = graph.Edges();
+    EXPECT_EQ(2u, edges.size());
+  }
+}
+
+/////////////////////////////////////////////////
+TEST(GraphTest, BadUniformInitializationMock)
+{
+  // There's no space for more vertices (mocked).
+  {
+    MockVerticesFullUndirectedGraph<int, double> graph;
+    graph.AddVertex("0", 0);
+    auto vertices = graph.Vertices();
+    EXPECT_EQ(0u, vertices.size());
+  }
+
+  // There's no space for more edges (mocked).
+  {
+    MockEdgesFullUndirectedGraph<int, double> graph;
+    graph.AddVertex("0", 0);
+    graph.AddVertex("1", 1);
+    graph.AddEdge({0, 1}, 1.0);
+    auto edges = graph.Edges();
+    EXPECT_EQ(0u, edges.size());
+  }
+}
+
+/////////////////////////////////////////////////
+TYPED_TEST(GraphTestFixture, BadUniformInitialization)
+{
+  // Bad graph initialization: repeated vertex Id.
+  {
+    TypeParam graph(
+    {
+      // Create vertices with custom Ids.
+      {{"0", 0, 0}, {"1", 1, 0}, {"1", 1, 1}},
+      // Create edges.
+      {{{0, 1}, 0.0}}
+    });
+
+    // Verify the vertices.
+    auto vertices = graph.Vertices();
+    EXPECT_EQ(2u, vertices.size());
+
+    for (int i = 0; i < 2; ++i)
+    {
+      unsigned int iu = i;
+      ASSERT_NE(vertices.find(i), vertices.end());
+      auto v = vertices.at(i).get();
+      EXPECT_EQ(std::to_string(i), v.Name());
+      EXPECT_EQ(iu, v.Id());
+      EXPECT_EQ(i, v.Data());
+    }
+  }
+  // Bad graph initialization: edges referencing an inexistent vertex.
+  {
+    TypeParam graph(
+    {
+      // Create vertices with custom Ids.
+      {{"0", 0, 0}, {"1", 1, 1}, {"2", 2, 2}},
+      // Create edges.
+      {{{0, 3}, 0.0}}
+    });
+
+    // Verify the edges.
+    auto edges = graph.Edges();
+    EXPECT_EQ(0u, edges.size());
+  }
+}
+
+/////////////////////////////////////////////////
+TYPED_TEST(GraphTestFixture, VertexFromId)
+{
+  // Mutable version of VertexFromId().
+  {
+    TypeParam graph;
+
+    // Create some vertices.
+    auto &v0 = graph.AddVertex("0", 0, 0);
+    EXPECT_EQ("0", v0.Name());
+    graph.AddVertex("1", 1, 1);
+    graph.AddVertex("2", 2, 2);
+
+    auto v = graph.VertexFromId(v0.Id());
+    EXPECT_EQ(v0.Id(), v.Id());
+
+    // Id not found.
+    v = graph.VertexFromId(500);
+    EXPECT_EQ(kNullId, v.Id());
+  }
+
+  // Non-mutable version of VertexFromId().
+  {
+    const TypeParam graph(
+    {
+      {{"0", 0}, {"1", 1}, {"2", 2}},
+      {}
+    });
+
+    auto v = graph.VertexFromId(0);
+    EXPECT_EQ(0u, v.Id());
+
+    // Id not found.
+    v = graph.VertexFromId(500);
+    EXPECT_EQ(kNullId, v.Id());
+  }
+}
+
+/////////////////////////////////////////////////
+TYPED_TEST(GraphTestFixture, Vertices)
+{
+  TypeParam graph(
+  {
+    {{"0", 10, 0}, {"1", 20, 1}, {"2", 30, 2}},
+    {{{0, 1}, 0.0}, {{1, 2}, 0.0}}
+  });
+
+  auto vertices = graph.Vertices();
+  EXPECT_EQ(3u, vertices.size());
+
+  // Check that the vertex Ids start from 0.
+  EXPECT_NE(vertices.end(), vertices.find(0));
+  EXPECT_NE(vertices.end(), vertices.find(1));
+  EXPECT_NE(vertices.end(), vertices.find(2));
+
+  // Check the references.
+  for (auto const &vertexPair : vertices)
+  {
+    auto &vertex = vertexPair.second.get();
+    switch (vertex.Id())
+    {
+      case 0:
+      {
+        EXPECT_EQ("0", vertex.Name());
+        EXPECT_EQ(10, vertex.Data());
+        break;
+      }
+      case 1:
+      {
+        EXPECT_EQ("1", vertex.Name());
+        EXPECT_EQ(20, vertex.Data());
+        break;
+      }
+      case 2:
+      {
+        EXPECT_EQ("2", vertex.Name());
+        EXPECT_EQ(30, vertex.Data());
+        break;
+      }
+      default:
+        FAIL();
+    };
+  }
+}
+
+/////////////////////////////////////////////////
+TYPED_TEST(GraphTestFixture, VerticesNames)
+{
+  // Create a few vertices with two of them sharing the same name.
+  TypeParam graph(
+  {
+    {{"vertex_0", 0}, {"vertex_1", 1}, {"common", 2}, {"common", 3}},
+    {}
+  });
+
+  auto vertices = graph.Vertices("common");
+  EXPECT_EQ(2u, vertices.size());
+
+  // Check the Ids.
+  EXPECT_NE(vertices.end(), vertices.find(2));
+  EXPECT_NE(vertices.end(), vertices.find(3));
+
+  // Check the references.
+  for (auto const &vertexPair : vertices)
+  {
+    auto &vertex = vertexPair.second.get();
+    switch (vertex.Id())
+    {
+      case 2:
+      {
+        EXPECT_EQ("common", vertex.Name());
+        EXPECT_EQ(2, vertex.Data());
+        break;
+      }
+      case 3:
+      {
+        EXPECT_EQ("common", vertex.Name());
+        EXPECT_EQ(3, vertex.Data());
+        break;
+      }
+      default:
+        FAIL();
+    };
+  }
+}
+
+/////////////////////////////////////////////////
+TYPED_TEST(GraphTestFixture, Empty)
+{
+  TypeParam graph;
+
+  EXPECT_TRUE(graph.Empty());
+
+  // Create a vertex.
+  auto &v0 = graph.AddVertex("0", 0);
+  ASSERT_TRUE(v0.Valid());
+  EXPECT_FALSE(graph.Empty());
+}
+
+/////////////////////////////////////////////////
+TYPED_TEST(GraphTestFixture, AddVertex)
+{
+  TypeParam graph;
+
+  // Create some vertices without Id.
+  auto &v0 = graph.AddVertex("0", 0);
+  EXPECT_TRUE(v0.Id() != kNullId);
+  auto &v1 = graph.AddVertex("1", 1);
+  EXPECT_TRUE(v1.Id() != kNullId);
+  auto &v2 = graph.AddVertex("2", 2);
+  EXPECT_TRUE(v2.Id() != kNullId);
+
+  // Create a vertex with Id.
+  auto &v3 = graph.AddVertex("3", 5, 3);
+  EXPECT_EQ(3u, v3.Id());
+  EXPECT_EQ(5, v3.Data());
+  EXPECT_EQ("3", v3.Name());
+
+  // Create a vertex with an already used Id.
+  auto &v4 = graph.AddVertex("3", 0, 3);
+  ASSERT_TRUE(v4.Id() == kNullId);
+
+  auto vertices = graph.Vertices();
+  EXPECT_EQ(4u, vertices.size());
+
+  // Change data in v3 and verify that is propagated into the graph.
+  v3.Data() = 10;
+  auto &vertex = graph.VertexFromId(v3.Id());
+  EXPECT_EQ(10, vertex.Data());
+
+  // Try to change data in v4 and verify that is not propagated into the graph.
+  v4.Data() = 20;
+  for (auto const &vertexPair : vertices)
+  {
+    auto &v = vertexPair.second.get();
+    EXPECT_NE(20, v.Data());
+  }
+}
+
+/////////////////////////////////////////////////
+TYPED_TEST(GraphTestFixture, EdgeFromId)
+{
+  // Mutable version of EdgeFromId().
+  {
+    TypeParam graph(
+    {
+      {{"0", 0}, {"1", 1}, {"2", 2}},
+      {{{0, 1}, 2.0}, {{1, 2}, 3.0}}
+    });
+
+    auto e = graph.EdgeFromId(1);
+    EXPECT_EQ(1u, e.Id());
+
+    // Id not found.
+    e = graph.EdgeFromId(500);
+    EXPECT_EQ(kNullId, e.Id());
+  }
+
+  // Non-mutable version of EdgeFromId().
+  {
+    const TypeParam graph(
+    {
+      {{"0", 0}, {"1", 1}, {"2", 2}},
+      {{{0, 1}, 2.0}, {{1, 2}, 3.0}}
+    });
+
+    auto e = graph.EdgeFromId(1);
+    EXPECT_EQ(1u, e.Id());
+
+    // Id not found.
+    e = graph.EdgeFromId(500);
+    EXPECT_EQ(kNullId, e.Id());
+  }
+}
+
+/////////////////////////////////////////////////
+TYPED_TEST(GraphTestFixture, EdgelessInDegree)
+{
+  TypeParam graph;
+
+  // add a bunch of vertices but no edges
+  const int vertexCount = 10000;
+  for (int i = 0; i < vertexCount; ++i)
+  {
+    auto &v = graph.AddVertex(std::to_string(i), i);
+    EXPECT_TRUE(v.Valid());
+  }
+
+  for (auto const &idVertex : graph.Vertices())
+  {
+    EXPECT_EQ(0u, graph.InDegree(idVertex.first));
+  }
+}
+
+/////////////////////////////////////////////////
+TYPED_TEST(GraphTestFixture, EdgelessOutDegree)
+{
+  TypeParam graph;
+
+  // add a bunch of vertices but no edges
+  const int vertexCount = 10000;
+  for (int i = 0; i < vertexCount; ++i)
+  {
+    auto &v = graph.AddVertex(std::to_string(i), i);
+    EXPECT_TRUE(v.Valid());
+  }
+
+  for (auto const &idVertex : graph.Vertices())
+  {
+    EXPECT_EQ(0u, graph.OutDegree(idVertex.first));
+  }
+}
diff --git a/src/graph/Vertex_TEST.cc b/src/graph/Vertex_TEST.cc
new file mode 100644
index 0000000..9b24cd6
--- /dev/null
+++ b/src/graph/Vertex_TEST.cc
@@ -0,0 +1,69 @@
+/*
+ * Copyright (C) 2017 Open Source Robotics Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+*/
+
+#include <gtest/gtest.h>
+#include <iostream>
+#include <string>
+
+#include "ignition/math/graph/Vertex.hh"
+
+using namespace ignition;
+using namespace math;
+using namespace graph;
+
+/////////////////////////////////////////////////
+TEST(VertexTest, Accessors)
+{
+  {
+    int data = 5;
+    Vertex<int> vertex("", data);
+    EXPECT_TRUE(vertex.Name().empty());
+    EXPECT_EQ(vertex.Data(), data);
+    EXPECT_EQ(vertex.Id(), kNullId);
+    EXPECT_FALSE(vertex.Valid());
+  }
+
+  {
+    std::string name = "my_vertex";
+    int data = 10;
+    VertexId id = 2;
+    Vertex<int> vertex(name, data, id);
+    EXPECT_EQ(vertex.Name(), name);
+    EXPECT_EQ(vertex.Id(), id);
+    EXPECT_EQ(vertex.Data(), data);
+    // Modify the data
+    vertex.Data() += 1;
+    EXPECT_EQ(vertex.Data(), data + 1);
+    EXPECT_TRUE(vertex.Valid());
+  }
+}
+
+/////////////////////////////////////////////////
+TEST(VertexTest, StreamInsertion)
+{
+  std::string name = "my_vertex";
+  int data = 10;
+  VertexId id = 2;
+  Vertex<int> vertex(name, data, id);
+
+  std::ostringstream output;
+  output << vertex;
+
+  std::string expectedOutput = "  " + std::to_string(id) + " [label=\"" + name +
+    " (" + std::to_string(id) + ")\"];\n";
+  EXPECT_EQ(output.str(), expectedOutput);
+}
diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt
new file mode 100644
index 0000000..b40c9d6
--- /dev/null
+++ b/test/CMakeLists.txt
@@ -0,0 +1,22 @@
+include_directories (
+  ${PROJECT_SOURCE_DIR}/test/gtest/include
+  ${PROJECT_SOURCE_DIR}/test/gtest
+  ${PROJECT_SOURCE_DIR}/test
+)
+
+configure_file (test_config.h.in ${PROJECT_BINARY_DIR}/test_config.h)
+
+# Build gtest
+add_library(gtest STATIC gtest/src/gtest-all.cc)
+add_library(gtest_main STATIC gtest/src/gtest_main.cc)
+target_link_libraries(gtest_main gtest)
+set(GTEST_LIBRARY "${PROJECT_BINARY_DIR}/test/libgtest.a")
+set(GTEST_MAIN_LIBRARY "${PROJECT_BINARY_DIR}/test/libgtest_main.a")
+
+execute_process(COMMAND cmake -E remove_directory ${CMAKE_BINARY_DIR}/test_results)
+execute_process(COMMAND cmake -E make_directory ${CMAKE_BINARY_DIR}/test_results)
+include_directories(${GTEST_INCLUDE_DIRS})
+
+add_subdirectory(integration)
+add_subdirectory(performance)
+add_subdirectory(regression)
diff --git a/test/gtest/cmake/internal_utils.cmake b/test/gtest/cmake/internal_utils.cmake
new file mode 100644
index 0000000..8cb2189
--- /dev/null
+++ b/test/gtest/cmake/internal_utils.cmake
@@ -0,0 +1,227 @@
+# Defines functions and macros useful for building Google Test and
+# Google Mock.
+#
+# Note:
+#
+# - This file will be run twice when building Google Mock (once via
+#   Google Test's CMakeLists.txt, and once via Google Mock's).
+#   Therefore it shouldn't have any side effects other than defining
+#   the functions and macros.
+#
+# - The functions/macros defined in this file may depend on Google
+#   Test and Google Mock's option() definitions, and thus must be
+#   called *after* the options have been defined.
+
+# Tweaks CMake's default compiler/linker settings to suit Google Test's needs.
+#
+# This must be a macro(), as inside a function string() can only
+# update variables in the function scope.
+macro(fix_default_compiler_settings_)
+  if (MSVC)
+    # For MSVC, CMake sets certain flags to defaults we want to override.
+    # This replacement code is taken from sample in the CMake Wiki at
+    # http://www.cmake.org/Wiki/CMake_FAQ#Dynamic_Replace.
+    foreach (flag_var
+             CMAKE_CXX_FLAGS CMAKE_CXX_FLAGS_DEBUG CMAKE_CXX_FLAGS_RELEASE
+             CMAKE_CXX_FLAGS_MINSIZEREL CMAKE_CXX_FLAGS_RELWITHDEBINFO)
+      if (NOT BUILD_SHARED_LIBS AND NOT gtest_force_shared_crt)
+        # When Google Test is built as a shared library, it should also use
+        # shared runtime libraries.  Otherwise, it may end up with multiple
+        # copies of runtime library data in different modules, resulting in
+        # hard-to-find crashes. When it is built as a static library, it is
+        # preferable to use CRT as static libraries, as we don't have to rely
+        # on CRT DLLs being available. CMake always defaults to using shared
+        # CRT libraries, so we override that default here.
+        string(REPLACE "/MD" "-MT" ${flag_var} "${${flag_var}}")
+      endif()
+
+      # We prefer more strict warning checking for building Google Test.
+      # Replaces /W3 with /W4 in defaults.
+      string(REPLACE "/W3" "-W4" ${flag_var} "${${flag_var}}")
+    endforeach()
+  endif()
+endmacro()
+
+# Defines the compiler/linker flags used to build Google Test and
+# Google Mock.  You can tweak these definitions to suit your need.  A
+# variable's value is empty before it's explicitly assigned to.
+macro(config_compiler_and_linker)
+  if (NOT gtest_disable_pthreads)
+    # Defines CMAKE_USE_PTHREADS_INIT and CMAKE_THREAD_LIBS_INIT.
+    find_package(Threads)
+  endif()
+
+  fix_default_compiler_settings_()
+  if (MSVC)
+    # Newlines inside flags variables break CMake's NMake generator.
+    # TODO(vladl at google.com): Add -RTCs and -RTCu to debug builds.
+    set(cxx_base_flags "-GS -W4 -WX -wd4127 -wd4251 -wd4275 -nologo -J -Zi")
+    if (MSVC_VERSION LESS 1400)
+      # Suppress spurious warnings MSVC 7.1 sometimes issues.
+      # Forcing value to bool.
+      set(cxx_base_flags "${cxx_base_flags} -wd4800")
+      # Copy constructor and assignment operator could not be generated.
+      set(cxx_base_flags "${cxx_base_flags} -wd4511 -wd4512")
+      # Compatibility warnings not applicable to Google Test.
+      # Resolved overload was found by argument-dependent lookup.
+      set(cxx_base_flags "${cxx_base_flags} -wd4675")
+    endif()
+    set(cxx_base_flags "${cxx_base_flags} -D_UNICODE -DUNICODE -DWIN32 -D_WIN32")
+    set(cxx_base_flags "${cxx_base_flags} -DSTRICT -DWIN32_LEAN_AND_MEAN")
+    set(cxx_exception_flags "-EHsc -D_HAS_EXCEPTIONS=1")
+    set(cxx_no_exception_flags "-D_HAS_EXCEPTIONS=0")
+    set(cxx_no_rtti_flags "-GR-")
+  elseif (CMAKE_COMPILER_IS_GNUCXX)
+    set(cxx_base_flags "-Wall -Wshadow")
+    set(cxx_exception_flags "-fexceptions")
+    set(cxx_no_exception_flags "-fno-exceptions")
+    # Until version 4.3.2, GCC doesn't define a macro to indicate
+    # whether RTTI is enabled.  Therefore we define GTEST_HAS_RTTI
+    # explicitly.
+    set(cxx_no_rtti_flags "-fno-rtti -DGTEST_HAS_RTTI=0")
+    set(cxx_strict_flags
+      "-Wextra -Wno-unused-parameter -Wno-missing-field-initializers")
+  elseif (CMAKE_CXX_COMPILER_ID STREQUAL "SunPro")
+    set(cxx_exception_flags "-features=except")
+    # Sun Pro doesn't provide macros to indicate whether exceptions and
+    # RTTI are enabled, so we define GTEST_HAS_* explicitly.
+    set(cxx_no_exception_flags "-features=no%except -DGTEST_HAS_EXCEPTIONS=0")
+    set(cxx_no_rtti_flags "-features=no%rtti -DGTEST_HAS_RTTI=0")
+  elseif (CMAKE_CXX_COMPILER_ID STREQUAL "VisualAge" OR
+      CMAKE_CXX_COMPILER_ID STREQUAL "XL")
+    # CMake 2.8 changes Visual Age's compiler ID to "XL".
+    set(cxx_exception_flags "-qeh")
+    set(cxx_no_exception_flags "-qnoeh")
+    # Until version 9.0, Visual Age doesn't define a macro to indicate
+    # whether RTTI is enabled.  Therefore we define GTEST_HAS_RTTI
+    # explicitly.
+    set(cxx_no_rtti_flags "-qnortti -DGTEST_HAS_RTTI=0")
+  elseif (CMAKE_CXX_COMPILER_ID STREQUAL "HP")
+    set(cxx_base_flags "-AA -mt")
+    set(cxx_exception_flags "-DGTEST_HAS_EXCEPTIONS=1")
+    set(cxx_no_exception_flags "+noeh -DGTEST_HAS_EXCEPTIONS=0")
+    # RTTI can not be disabled in HP aCC compiler.
+    set(cxx_no_rtti_flags "")
+  endif()
+
+  if (CMAKE_USE_PTHREADS_INIT)  # The pthreads library is available and allowed.
+    set(cxx_base_flags "${cxx_base_flags} -DGTEST_HAS_PTHREAD=1")
+  else()
+    set(cxx_base_flags "${cxx_base_flags} -DGTEST_HAS_PTHREAD=0")
+  endif()
+
+  # For building gtest's own tests and samples.
+  set(cxx_exception "${CMAKE_CXX_FLAGS} ${cxx_base_flags} ${cxx_exception_flags}")
+  set(cxx_no_exception
+    "${CMAKE_CXX_FLAGS} ${cxx_base_flags} ${cxx_no_exception_flags}")
+  set(cxx_default "${cxx_exception}")
+  set(cxx_no_rtti "${cxx_default} ${cxx_no_rtti_flags}")
+  set(cxx_use_own_tuple "${cxx_default} -DGTEST_USE_OWN_TR1_TUPLE=1")
+
+  # For building the gtest libraries.
+  set(cxx_strict "${cxx_default} ${cxx_strict_flags}")
+endmacro()
+
+# Defines the gtest & gtest_main libraries.  User tests should link
+# with one of them.
+function(cxx_library_with_type name type cxx_flags)
+  # type can be either STATIC or SHARED to denote a static or shared library.
+  # ARGN refers to additional arguments after 'cxx_flags'.
+  add_library(${name} ${type} ${ARGN})
+  set_target_properties(${name}
+    PROPERTIES
+    COMPILE_FLAGS "${cxx_flags}")
+  if (BUILD_SHARED_LIBS OR type STREQUAL "SHARED")
+    set_target_properties(${name}
+      PROPERTIES
+      COMPILE_DEFINITIONS "GTEST_CREATE_SHARED_LIBRARY=1")
+  endif()
+  if (CMAKE_USE_PTHREADS_INIT)
+    target_link_libraries(${name} ${CMAKE_THREAD_LIBS_INIT})
+  endif()
+endfunction()
+
+########################################################################
+#
+# Helper functions for creating build targets.
+
+function(cxx_shared_library name cxx_flags)
+  cxx_library_with_type(${name} SHARED "${cxx_flags}" ${ARGN})
+endfunction()
+
+function(cxx_library name cxx_flags)
+  cxx_library_with_type(${name} "" "${cxx_flags}" ${ARGN})
+endfunction()
+
+# cxx_executable_with_flags(name cxx_flags libs srcs...)
+#
+# creates a named C++ executable that depends on the given libraries and
+# is built from the given source files with the given compiler flags.
+function(cxx_executable_with_flags name cxx_flags libs)
+  add_executable(${name} ${ARGN})
+  if (cxx_flags)
+    set_target_properties(${name}
+      PROPERTIES
+      COMPILE_FLAGS "${cxx_flags}")
+  endif()
+  if (BUILD_SHARED_LIBS)
+    set_target_properties(${name}
+      PROPERTIES
+      COMPILE_DEFINITIONS "GTEST_LINKED_AS_SHARED_LIBRARY=1")
+  endif()
+  # To support mixing linking in static and dynamic libraries, link each
+  # library in with an extra call to target_link_libraries.
+  foreach (lib "${libs}")
+    target_link_libraries(${name} ${lib})
+  endforeach()
+endfunction()
+
+# cxx_executable(name dir lib srcs...)
+#
+# creates a named target that depends on the given libs and is built
+# from the given source files.  dir/name.cc is implicitly included in
+# the source file list.
+function(cxx_executable name dir libs)
+  cxx_executable_with_flags(
+    ${name} "${cxx_default}" "${libs}" "${dir}/${name}.cc" ${ARGN})
+endfunction()
+
+# Sets PYTHONINTERP_FOUND and PYTHON_EXECUTABLE.
+find_package(PythonInterp)
+
+# cxx_test_with_flags(name cxx_flags libs srcs...)
+#
+# creates a named C++ test that depends on the given libs and is built
+# from the given source files with the given compiler flags.
+function(cxx_test_with_flags name cxx_flags libs)
+  cxx_executable_with_flags(${name} "${cxx_flags}" "${libs}" ${ARGN})
+  add_test(${name} ${name})
+endfunction()
+
+# cxx_test(name libs srcs...)
+#
+# creates a named test target that depends on the given libs and is
+# built from the given source files.  Unlike cxx_test_with_flags,
+# test/name.cc is already implicitly included in the source file list.
+function(cxx_test name libs)
+  cxx_test_with_flags("${name}" "${cxx_default}" "${libs}"
+    "test/${name}.cc" ${ARGN})
+endfunction()
+
+# py_test(name)
+#
+# creates a Python test with the given name whose main module is in
+# test/name.py.  It does nothing if Python is not installed.
+function(py_test name)
+  # We are not supporting Python tests on Linux yet as they consider
+  # all Linux environments to be google3 and try to use google3 features.
+  if (PYTHONINTERP_FOUND)
+    # ${CMAKE_BINARY_DIR} is known at configuration time, so we can
+    # directly bind it from cmake. ${CTEST_CONFIGURATION_TYPE} is known
+    # only at ctest runtime (by calling ctest -c <Configuration>), so
+    # we have to escape $ to delay variable substitution here.
+    add_test(${name}
+      ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/test/${name}.py
+          --build_dir=${CMAKE_CURRENT_BINARY_DIR}/\${CTEST_CONFIGURATION_TYPE})
+  endif()
+endfunction()
diff --git a/test/gtest/gtest-1.7.0.diff b/test/gtest/gtest-1.7.0.diff
new file mode 100644
index 0000000..e878396
--- /dev/null
+++ b/test/gtest/gtest-1.7.0.diff
@@ -0,0 +1,44 @@
+diff -r a5e72dd0ecf3 test/gtest/include/gtest/gtest-typed-test.h
+--- a/test/gtest/include/gtest/gtest-typed-test.h	Mon Nov 04 11:47:43 2013 -0800
++++ b/test/gtest/include/gtest/gtest-typed-test.h	Mon Nov 04 11:49:12 2013 -0800
+@@ -31,6 +31,7 @@
+ 
+ #ifndef GTEST_INCLUDE_GTEST_GTEST_TYPED_TEST_H_
+ #define GTEST_INCLUDE_GTEST_GTEST_TYPED_TEST_H_
++#pragma GCC system_header
+ 
+ // This header implements typed tests and type-parameterized tests.
+ 
+diff -r a5e72dd0ecf3 test/gtest/src/gtest.cc
+--- a/test/gtest/src/gtest.cc	Mon Nov 04 11:47:43 2013 -0800
++++ b/test/gtest/src/gtest.cc	Mon Nov 04 11:49:12 2013 -0800
+@@ -33,6 +33,7 @@
+ 
+ #include "gtest/gtest.h"
+ #include "gtest/gtest-spi.h"
++#pragma GCC system_header
+ 
+ #include <ctype.h>
+ #include <math.h>
+diff -r c33b44f8a9a1 test/gtest/include/gtest/internal/gtest-port.h
+--- a/test/gtest/include/gtest/internal/gtest-port.h	Wed Nov 06 11:23:38 2013 -0800
++++ b/test/gtest/include/gtest/internal/gtest-port.h	Wed Nov 06 17:12:57 2013 -0800
+@@ -39,6 +39,7 @@
+ 
+ #ifndef GTEST_INCLUDE_GTEST_INTERNAL_GTEST_PORT_H_
+ #define GTEST_INCLUDE_GTEST_INTERNAL_GTEST_PORT_H_
++#pragma GCC system_header
+ 
+ // The user can define the following macros in the build script to
+ // control Google Test's behavior.  If the user doesn't define a macro
+diff -r e980730656c1 test/gtest/include/gtest/gtest-printers.h
+--- a/test/gtest/include/gtest/gtest-printers.h	Wed Nov 06 17:13:57 2013 -0800
++++ b/test/gtest/include/gtest/gtest-printers.h	Thu Nov 07 09:29:28 2013 -0800
+@@ -94,6 +94,7 @@
+ 
+ #ifndef GTEST_INCLUDE_GTEST_GTEST_PRINTERS_H_
+ #define GTEST_INCLUDE_GTEST_GTEST_PRINTERS_H_
++#pragma GCC system_header
+ 
+ #include <ostream>  // NOLINT
+ #include <sstream>
diff --git a/test/gtest/include/gtest/gtest-death-test.h b/test/gtest/include/gtest/gtest-death-test.h
new file mode 100644
index 0000000..957a69c
--- /dev/null
+++ b/test/gtest/include/gtest/gtest-death-test.h
@@ -0,0 +1,294 @@
+// Copyright 2005, Google Inc.
+// All rights reserved.
+//
+// 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: wan at google.com (Zhanyong Wan)
+//
+// The Google C++ Testing Framework (Google Test)
+//
+// This header file defines the public API for death tests.  It is
+// #included by gtest.h so a user doesn't need to include this
+// directly.
+
+#ifndef GTEST_INCLUDE_GTEST_GTEST_DEATH_TEST_H_
+#define GTEST_INCLUDE_GTEST_GTEST_DEATH_TEST_H_
+
+#include "gtest/internal/gtest-death-test-internal.h"
+
+namespace testing {
+
+// This flag controls the style of death tests.  Valid values are "threadsafe",
+// meaning that the death test child process will re-execute the test binary
+// from the start, running only a single death test, or "fast",
+// meaning that the child process will execute the test logic immediately
+// after forking.
+GTEST_DECLARE_string_(death_test_style);
+
+#if GTEST_HAS_DEATH_TEST
+
+namespace internal {
+
+// Returns a Boolean value indicating whether the caller is currently
+// executing in the context of the death test child process.  Tools such as
+// Valgrind heap checkers may need this to modify their behavior in death
+// tests.  IMPORTANT: This is an internal utility.  Using it may break the
+// implementation of death tests.  User code MUST NOT use it.
+GTEST_API_ bool InDeathTestChild();
+
+}  // namespace internal
+
+// The following macros are useful for writing death tests.
+
+// Here's what happens when an ASSERT_DEATH* or EXPECT_DEATH* is
+// executed:
+//
+//   1. It generates a warning if there is more than one active
+//   thread.  This is because it's safe to fork() or clone() only
+//   when there is a single thread.
+//
+//   2. The parent process clone()s a sub-process and runs the death
+//   test in it; the sub-process exits with code 0 at the end of the
+//   death test, if it hasn't exited already.
+//
+//   3. The parent process waits for the sub-process to terminate.
+//
+//   4. The parent process checks the exit code and error message of
+//   the sub-process.
+//
+// Examples:
+//
+//   ASSERT_DEATH(server.SendMessage(56, "Hello"), "Invalid port number");
+//   for (int i = 0; i < 5; i++) {
+//     EXPECT_DEATH(server.ProcessRequest(i),
+//                  "Invalid request .* in ProcessRequest()")
+//                  << "Failed to die on request " << i;
+//   }
+//
+//   ASSERT_EXIT(server.ExitNow(), ::testing::ExitedWithCode(0), "Exiting");
+//
+//   bool KilledBySIGHUP(int exit_code) {
+//     return WIFSIGNALED(exit_code) && WTERMSIG(exit_code) == SIGHUP;
+//   }
+//
+//   ASSERT_EXIT(client.HangUpServer(), KilledBySIGHUP, "Hanging up!");
+//
+// On the regular expressions used in death tests:
+//
+//   On POSIX-compliant systems (*nix), we use the <regex.h> library,
+//   which uses the POSIX extended regex syntax.
+//
+//   On other platforms (e.g. Windows), we only support a simple regex
+//   syntax implemented as part of Google Test.  This limited
+//   implementation should be enough most of the time when writing
+//   death tests; though it lacks many features you can find in PCRE
+//   or POSIX extended regex syntax.  For example, we don't support
+//   union ("x|y"), grouping ("(xy)"), brackets ("[xy]"), and
+//   repetition count ("x{5,7}"), among others.
+//
+//   Below is the syntax that we do support.  We chose it to be a
+//   subset of both PCRE and POSIX extended regex, so it's easy to
+//   learn wherever you come from.  In the following: 'A' denotes a
+//   literal character, period (.), or a single \\ escape sequence;
+//   'x' and 'y' denote regular expressions; 'm' and 'n' are for
+//   natural numbers.
+//
+//     c     matches any literal character c
+//     \\d   matches any decimal digit
+//     \\D   matches any character that's not a decimal digit
+//     \\f   matches \f
+//     \\n   matches \n
+//     \\r   matches \r
+//     \\s   matches any ASCII whitespace, including \n
+//     \\S   matches any character that's not a whitespace
+//     \\t   matches \t
+//     \\v   matches \v
+//     \\w   matches any letter, _, or decimal digit
+//     \\W   matches any character that \\w doesn't match
+//     \\c   matches any literal character c, which must be a punctuation
+//     .     matches any single character except \n
+//     A?    matches 0 or 1 occurrences of A
+//     A*    matches 0 or many occurrences of A
+//     A+    matches 1 or many occurrences of A
+//     ^     matches the beginning of a string (not that of each line)
+//     $     matches the end of a string (not that of each line)
+//     xy    matches x followed by y
+//
+//   If you accidentally use PCRE or POSIX extended regex features
+//   not implemented by us, you will get a run-time failure.  In that
+//   case, please try to rewrite your regular expression within the
+//   above syntax.
+//
+//   This implementation is *not* meant to be as highly tuned or robust
+//   as a compiled regex library, but should perform well enough for a
+//   death test, which already incurs significant overhead by launching
+//   a child process.
+//
+// Known caveats:
+//
+//   A "threadsafe" style death test obtains the path to the test
+//   program from argv[0] and re-executes it in the sub-process.  For
+//   simplicity, the current implementation doesn't search the PATH
+//   when launching the sub-process.  This means that the user must
+//   invoke the test program via a path that contains at least one
+//   path separator (e.g. path/to/foo_test and
+//   /absolute/path/to/bar_test are fine, but foo_test is not).  This
+//   is rarely a problem as people usually don't put the test binary
+//   directory in PATH.
+//
+// TODO(wan at google.com): make thread-safe death tests search the PATH.
+
+// Asserts that a given statement causes the program to exit, with an
+// integer exit status that satisfies predicate, and emitting error output
+// that matches regex.
+# define ASSERT_EXIT(statement, predicate, regex) \
+    GTEST_DEATH_TEST_(statement, predicate, regex, GTEST_FATAL_FAILURE_)
+
+// Like ASSERT_EXIT, but continues on to successive tests in the
+// test case, if any:
+# define EXPECT_EXIT(statement, predicate, regex) \
+    GTEST_DEATH_TEST_(statement, predicate, regex, GTEST_NONFATAL_FAILURE_)
+
+// Asserts that a given statement causes the program to exit, either by
+// explicitly exiting with a nonzero exit code or being killed by a
+// signal, and emitting error output that matches regex.
+# define ASSERT_DEATH(statement, regex) \
+    ASSERT_EXIT(statement, ::testing::internal::ExitedUnsuccessfully, regex)
+
+// Like ASSERT_DEATH, but continues on to successive tests in the
+// test case, if any:
+# define EXPECT_DEATH(statement, regex) \
+    EXPECT_EXIT(statement, ::testing::internal::ExitedUnsuccessfully, regex)
+
+// Two predicate classes that can be used in {ASSERT,EXPECT}_EXIT*:
+
+// Tests that an exit code describes a normal exit with a given exit code.
+class GTEST_API_ ExitedWithCode {
+ public:
+  explicit ExitedWithCode(int exit_code);
+  bool operator()(int exit_status) const;
+ private:
+  // No implementation - assignment is unsupported.
+  void operator=(const ExitedWithCode& other);
+
+  const int exit_code_;
+};
+
+# if !GTEST_OS_WINDOWS
+// Tests that an exit code describes an exit due to termination by a
+// given signal.
+class GTEST_API_ KilledBySignal {
+ public:
+  explicit KilledBySignal(int signum);
+  bool operator()(int exit_status) const;
+ private:
+  const int signum_;
+};
+# endif  // !GTEST_OS_WINDOWS
+
+// EXPECT_DEBUG_DEATH asserts that the given statements die in debug mode.
+// The death testing framework causes this to have interesting semantics,
+// since the sideeffects of the call are only visible in opt mode, and not
+// in debug mode.
+//
+// In practice, this can be used to test functions that utilize the
+// LOG(DFATAL) macro using the following style:
+//
+// int DieInDebugOr12(int* sideeffect) {
+//   if (sideeffect) {
+//     *sideeffect = 12;
+//   }
+//   LOG(DFATAL) << "death";
+//   return 12;
+// }
+//
+// TEST(TestCase, TestDieOr12WorksInDgbAndOpt) {
+//   int sideeffect = 0;
+//   // Only asserts in dbg.
+//   EXPECT_DEBUG_DEATH(DieInDebugOr12(&sideeffect), "death");
+//
+// #ifdef NDEBUG
+//   // opt-mode has sideeffect visible.
+//   EXPECT_EQ(12, sideeffect);
+// #else
+//   // dbg-mode no visible sideeffect.
+//   EXPECT_EQ(0, sideeffect);
+// #endif
+// }
+//
+// This will assert that DieInDebugReturn12InOpt() crashes in debug
+// mode, usually due to a DCHECK or LOG(DFATAL), but returns the
+// appropriate fallback value (12 in this case) in opt mode. If you
+// need to test that a function has appropriate side-effects in opt
+// mode, include assertions against the side-effects.  A general
+// pattern for this is:
+//
+// EXPECT_DEBUG_DEATH({
+//   // Side-effects here will have an effect after this statement in
+//   // opt mode, but none in debug mode.
+//   EXPECT_EQ(12, DieInDebugOr12(&sideeffect));
+// }, "death");
+//
+# ifdef NDEBUG
+
+#  define EXPECT_DEBUG_DEATH(statement, regex) \
+  GTEST_EXECUTE_STATEMENT_(statement, regex)
+
+#  define ASSERT_DEBUG_DEATH(statement, regex) \
+  GTEST_EXECUTE_STATEMENT_(statement, regex)
+
+# else
+
+#  define EXPECT_DEBUG_DEATH(statement, regex) \
+  EXPECT_DEATH(statement, regex)
+
+#  define ASSERT_DEBUG_DEATH(statement, regex) \
+  ASSERT_DEATH(statement, regex)
+
+# endif  // NDEBUG for EXPECT_DEBUG_DEATH
+#endif  // GTEST_HAS_DEATH_TEST
+
+// EXPECT_DEATH_IF_SUPPORTED(statement, regex) and
+// ASSERT_DEATH_IF_SUPPORTED(statement, regex) expand to real death tests if
+// death tests are supported; otherwise they just issue a warning.  This is
+// useful when you are combining death test assertions with normal test
+// assertions in one test.
+#if GTEST_HAS_DEATH_TEST
+# define EXPECT_DEATH_IF_SUPPORTED(statement, regex) \
+    EXPECT_DEATH(statement, regex)
+# define ASSERT_DEATH_IF_SUPPORTED(statement, regex) \
+    ASSERT_DEATH(statement, regex)
+#else
+# define EXPECT_DEATH_IF_SUPPORTED(statement, regex) \
+    GTEST_UNSUPPORTED_DEATH_TEST_(statement, regex, )
+# define ASSERT_DEATH_IF_SUPPORTED(statement, regex) \
+    GTEST_UNSUPPORTED_DEATH_TEST_(statement, regex, return)
+#endif
+
+}  // namespace testing
+
+#endif  // GTEST_INCLUDE_GTEST_GTEST_DEATH_TEST_H_
diff --git a/test/gtest/include/gtest/gtest-message.h b/test/gtest/include/gtest/gtest-message.h
new file mode 100644
index 0000000..fe879bc
--- /dev/null
+++ b/test/gtest/include/gtest/gtest-message.h
@@ -0,0 +1,250 @@
+// Copyright 2005, Google Inc.
+// All rights reserved.
+//
+// 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: wan at google.com (Zhanyong Wan)
+//
+// The Google C++ Testing Framework (Google Test)
+//
+// This header file defines the Message class.
+//
+// IMPORTANT NOTE: Due to limitation of the C++ language, we have to
+// leave some internal implementation details in this header file.
+// They are clearly marked by comments like this:
+//
+//   // INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM.
+//
+// Such code is NOT meant to be used by a user directly, and is subject
+// to CHANGE WITHOUT NOTICE.  Therefore DO NOT DEPEND ON IT in a user
+// program!
+
+#ifndef GTEST_INCLUDE_GTEST_GTEST_MESSAGE_H_
+#define GTEST_INCLUDE_GTEST_GTEST_MESSAGE_H_
+
+#include <limits>
+
+#include "gtest/internal/gtest-port.h"
+
+// Ensures that there is at least one operator<< in the global namespace.
+// See Message& operator<<(...) below for why.
+void operator<<(const testing::internal::Secret&, int);
+
+namespace testing {
+
+// The Message class works like an ostream repeater.
+//
+// Typical usage:
+//
+//   1. You stream a bunch of values to a Message object.
+//      It will remember the text in a stringstream.
+//   2. Then you stream the Message object to an ostream.
+//      This causes the text in the Message to be streamed
+//      to the ostream.
+//
+// For example;
+//
+//   testing::Message foo;
+//   foo << 1 << " != " << 2;
+//   std::cout << foo;
+//
+// will print "1 != 2".
+//
+// Message is not intended to be inherited from.  In particular, its
+// destructor is not virtual.
+//
+// Note that stringstream behaves differently in gcc and in MSVC.  You
+// can stream a NULL char pointer to it in the former, but not in the
+// latter (it causes an access violation if you do).  The Message
+// class hides this difference by treating a NULL char pointer as
+// "(null)".
+class GTEST_API_ Message {
+ private:
+  // The type of basic IO manipulators (endl, ends, and flush) for
+  // narrow streams.
+  typedef std::ostream& (*BasicNarrowIoManip)(std::ostream&);
+
+ public:
+  // Constructs an empty Message.
+  Message();
+
+  // Copy constructor.
+  Message(const Message& msg) : ss_(new ::std::stringstream) {  // NOLINT
+    *ss_ << msg.GetString();
+  }
+
+  // Constructs a Message from a C-string.
+  explicit Message(const char* str) : ss_(new ::std::stringstream) {
+    *ss_ << str;
+  }
+
+#if GTEST_OS_SYMBIAN
+  // Streams a value (either a pointer or not) to this object.
+  template <typename T>
+  inline Message& operator <<(const T& value) {
+    StreamHelper(typename internal::is_pointer<T>::type(), value);
+    return *this;
+  }
+#else
+  // Streams a non-pointer value to this object.
+  template <typename T>
+  inline Message& operator <<(const T& val) {
+    // Some libraries overload << for STL containers.  These
+    // overloads are defined in the global namespace instead of ::std.
+    //
+    // C++'s symbol lookup rule (i.e. Koenig lookup) says that these
+    // overloads are visible in either the std namespace or the global
+    // namespace, but not other namespaces, including the testing
+    // namespace which Google Test's Message class is in.
+    //
+    // To allow STL containers (and other types that has a << operator
+    // defined in the global namespace) to be used in Google Test
+    // assertions, testing::Message must access the custom << operator
+    // from the global namespace.  With this using declaration,
+    // overloads of << defined in the global namespace and those
+    // visible via Koenig lookup are both exposed in this function.
+    using ::operator <<;
+    *ss_ << val;
+    return *this;
+  }
+
+  // Streams a pointer value to this object.
+  //
+  // This function is an overload of the previous one.  When you
+  // stream a pointer to a Message, this definition will be used as it
+  // is more specialized.  (The C++ Standard, section
+  // [temp.func.order].)  If you stream a non-pointer, then the
+  // previous definition will be used.
+  //
+  // The reason for this overload is that streaming a NULL pointer to
+  // ostream is undefined behavior.  Depending on the compiler, you
+  // may get "0", "(nil)", "(null)", or an access violation.  To
+  // ensure consistent result across compilers, we always treat NULL
+  // as "(null)".
+  template <typename T>
+  inline Message& operator <<(T* const& pointer) {  // NOLINT
+    if (pointer == NULL) {
+      *ss_ << "(null)";
+    } else {
+      *ss_ << pointer;
+    }
+    return *this;
+  }
+#endif  // GTEST_OS_SYMBIAN
+
+  // Since the basic IO manipulators are overloaded for both narrow
+  // and wide streams, we have to provide this specialized definition
+  // of operator <<, even though its body is the same as the
+  // templatized version above.  Without this definition, streaming
+  // endl or other basic IO manipulators to Message will confuse the
+  // compiler.
+  Message& operator <<(BasicNarrowIoManip val) {
+    *ss_ << val;
+    return *this;
+  }
+
+  // Instead of 1/0, we want to see true/false for bool values.
+  Message& operator <<(bool b) {
+    return *this << (b ? "true" : "false");
+  }
+
+  // These two overloads allow streaming a wide C string to a Message
+  // using the UTF-8 encoding.
+  Message& operator <<(const wchar_t* wide_c_str);
+  Message& operator <<(wchar_t* wide_c_str);
+
+#if GTEST_HAS_STD_WSTRING
+  // Converts the given wide string to a narrow string using the UTF-8
+  // encoding, and streams the result to this Message object.
+  Message& operator <<(const ::std::wstring& wstr);
+#endif  // GTEST_HAS_STD_WSTRING
+
+#if GTEST_HAS_GLOBAL_WSTRING
+  // Converts the given wide string to a narrow string using the UTF-8
+  // encoding, and streams the result to this Message object.
+  Message& operator <<(const ::wstring& wstr);
+#endif  // GTEST_HAS_GLOBAL_WSTRING
+
+  // Gets the text streamed to this object so far as an std::string.
+  // Each '\0' character in the buffer is replaced with "\\0".
+  //
+  // INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM.
+  std::string GetString() const;
+
+ private:
+
+#if GTEST_OS_SYMBIAN
+  // These are needed as the Nokia Symbian Compiler cannot decide between
+  // const T& and const T* in a function template. The Nokia compiler _can_
+  // decide between class template specializations for T and T*, so a
+  // tr1::type_traits-like is_pointer works, and we can overload on that.
+  template <typename T>
+  inline void StreamHelper(internal::true_type /*is_pointer*/, T* pointer) {
+    if (pointer == NULL) {
+      *ss_ << "(null)";
+    } else {
+      *ss_ << pointer;
+    }
+  }
+  template <typename T>
+  inline void StreamHelper(internal::false_type /*is_pointer*/,
+                           const T& value) {
+    // See the comments in Message& operator <<(const T&) above for why
+    // we need this using statement.
+    using ::operator <<;
+    *ss_ << value;
+  }
+#endif  // GTEST_OS_SYMBIAN
+
+  // We'll hold the text streamed to this object here.
+  const internal::scoped_ptr< ::std::stringstream> ss_;
+
+  // We declare (but don't implement) this to prevent the compiler
+  // from implementing the assignment operator.
+  void operator=(const Message&);
+};
+
+// Streams a Message to an ostream.
+inline std::ostream& operator <<(std::ostream& os, const Message& sb) {
+  return os << sb.GetString();
+}
+
+namespace internal {
+
+// Converts a streamable value to an std::string.  A NULL pointer is
+// converted to "(null)".  When the input value is a ::string,
+// ::std::string, ::wstring, or ::std::wstring object, each NUL
+// character in it is replaced with "\\0".
+template <typename T>
+std::string StreamableToString(const T& streamable) {
+  return (Message() << streamable).GetString();
+}
+
+}  // namespace internal
+}  // namespace testing
+
+#endif  // GTEST_INCLUDE_GTEST_GTEST_MESSAGE_H_
diff --git a/test/gtest/include/gtest/gtest-param-test.h b/test/gtest/include/gtest/gtest-param-test.h
new file mode 100644
index 0000000..d6702c8
--- /dev/null
+++ b/test/gtest/include/gtest/gtest-param-test.h
@@ -0,0 +1,1421 @@
+// This file was GENERATED by command:
+//     pump.py gtest-param-test.h.pump
+// DO NOT EDIT BY HAND!!!
+
+// Copyright 2008, Google Inc.
+// All rights reserved.
+//
+// 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.
+//
+// Authors: vladl at google.com (Vlad Losev)
+//
+// Macros and functions for implementing parameterized tests
+// in Google C++ Testing Framework (Google Test)
+//
+// This file is generated by a SCRIPT.  DO NOT EDIT BY HAND!
+//
+#ifndef GTEST_INCLUDE_GTEST_GTEST_PARAM_TEST_H_
+#define GTEST_INCLUDE_GTEST_GTEST_PARAM_TEST_H_
+
+
+// Value-parameterized tests allow you to test your code with different
+// parameters without writing multiple copies of the same test.
+//
+// Here is how you use value-parameterized tests:
+
+#if 0
+
+// To write value-parameterized tests, first you should define a fixture
+// class. It is usually derived from testing::TestWithParam<T> (see below for
+// another inheritance scheme that's sometimes useful in more complicated
+// class hierarchies), where the type of your parameter values.
+// TestWithParam<T> is itself derived from testing::Test. T can be any
+// copyable type. If it's a raw pointer, you are responsible for managing the
+// lifespan of the pointed values.
+
+class FooTest : public ::testing::TestWithParam<const char*> {
+  // You can implement all the usual class fixture members here.
+};
+
+// Then, use the TEST_P macro to define as many parameterized tests
+// for this fixture as you want. The _P suffix is for "parameterized"
+// or "pattern", whichever you prefer to think.
+
+TEST_P(FooTest, DoesBlah) {
+  // Inside a test, access the test parameter with the GetParam() method
+  // of the TestWithParam<T> class:
+  EXPECT_TRUE(foo.Blah(GetParam()));
+  ...
+}
+
+TEST_P(FooTest, HasBlahBlah) {
+  ...
+}
+
+// Finally, you can use INSTANTIATE_TEST_CASE_P to instantiate the test
+// case with any set of parameters you want. Google Test defines a number
+// of functions for generating test parameters. They return what we call
+// (surprise!) parameter generators. Here is a  summary of them, which
+// are all in the testing namespace:
+//
+//
+//  Range(begin, end [, step]) - Yields values {begin, begin+step,
+//                               begin+step+step, ...}. The values do not
+//                               include end. step defaults to 1.
+//  Values(v1, v2, ..., vN)    - Yields values {v1, v2, ..., vN}.
+//  ValuesIn(container)        - Yields values from a C-style array, an STL
+//  ValuesIn(begin,end)          container, or an iterator range [begin, end).
+//  Bool()                     - Yields sequence {false, true}.
+//  Combine(g1, g2, ..., gN)   - Yields all combinations (the Cartesian product
+//                               for the math savvy) of the values generated
+//                               by the N generators.
+//
+// For more details, see comments at the definitions of these functions below
+// in this file.
+//
+// The following statement will instantiate tests from the FooTest test case
+// each with parameter values "meeny", "miny", and "moe".
+
+INSTANTIATE_TEST_CASE_P(InstantiationName,
+                        FooTest,
+                        Values("meeny", "miny", "moe"));
+
+// To distinguish different instances of the pattern, (yes, you
+// can instantiate it more then once) the first argument to the
+// INSTANTIATE_TEST_CASE_P macro is a prefix that will be added to the
+// actual test case name. Remember to pick unique prefixes for different
+// instantiations. The tests from the instantiation above will have
+// these names:
+//
+//    * InstantiationName/FooTest.DoesBlah/0 for "meeny"
+//    * InstantiationName/FooTest.DoesBlah/1 for "miny"
+//    * InstantiationName/FooTest.DoesBlah/2 for "moe"
+//    * InstantiationName/FooTest.HasBlahBlah/0 for "meeny"
+//    * InstantiationName/FooTest.HasBlahBlah/1 for "miny"
+//    * InstantiationName/FooTest.HasBlahBlah/2 for "moe"
+//
+// You can use these names in --gtest_filter.
+//
+// This statement will instantiate all tests from FooTest again, each
+// with parameter values "cat" and "dog":
+
+const char* pets[] = {"cat", "dog"};
+INSTANTIATE_TEST_CASE_P(AnotherInstantiationName, FooTest, ValuesIn(pets));
+
+// The tests from the instantiation above will have these names:
+//
+//    * AnotherInstantiationName/FooTest.DoesBlah/0 for "cat"
+//    * AnotherInstantiationName/FooTest.DoesBlah/1 for "dog"
+//    * AnotherInstantiationName/FooTest.HasBlahBlah/0 for "cat"
+//    * AnotherInstantiationName/FooTest.HasBlahBlah/1 for "dog"
+//
+// Please note that INSTANTIATE_TEST_CASE_P will instantiate all tests
+// in the given test case, whether their definitions come before or
+// AFTER the INSTANTIATE_TEST_CASE_P statement.
+//
+// Please also note that generator expressions (including parameters to the
+// generators) are evaluated in InitGoogleTest(), after main() has started.
+// This allows the user on one hand, to adjust generator parameters in order
+// to dynamically determine a set of tests to run and on the other hand,
+// give the user a chance to inspect the generated tests with Google Test
+// reflection API before RUN_ALL_TESTS() is executed.
+//
+// You can see samples/sample7_unittest.cc and samples/sample8_unittest.cc
+// for more examples.
+//
+// In the future, we plan to publish the API for defining new parameter
+// generators. But for now this interface remains part of the internal
+// implementation and is subject to change.
+//
+//
+// A parameterized test fixture must be derived from testing::Test and from
+// testing::WithParamInterface<T>, where T is the type of the parameter
+// values. Inheriting from TestWithParam<T> satisfies that requirement because
+// TestWithParam<T> inherits from both Test and WithParamInterface. In more
+// complicated hierarchies, however, it is occasionally useful to inherit
+// separately from Test and WithParamInterface. For example:
+
+class BaseTest : public ::testing::Test {
+  // You can inherit all the usual members for a non-parameterized test
+  // fixture here.
+};
+
+class DerivedTest : public BaseTest, public ::testing::WithParamInterface<int> {
+  // The usual test fixture members go here too.
+};
+
+TEST_F(BaseTest, HasFoo) {
+  // This is an ordinary non-parameterized test.
+}
+
+TEST_P(DerivedTest, DoesBlah) {
+  // GetParam works just the same here as if you inherit from TestWithParam.
+  EXPECT_TRUE(foo.Blah(GetParam()));
+}
+
+#endif  // 0
+
+#include "gtest/internal/gtest-port.h"
+
+#if !GTEST_OS_SYMBIAN
+# include <utility>
+#endif
+
+// scripts/fuse_gtest.py depends on gtest's own header being #included
+// *unconditionally*.  Therefore these #includes cannot be moved
+// inside #if GTEST_HAS_PARAM_TEST.
+#include "gtest/internal/gtest-internal.h"
+#include "gtest/internal/gtest-param-util.h"
+#include "gtest/internal/gtest-param-util-generated.h"
+
+#if GTEST_HAS_PARAM_TEST
+
+namespace testing {
+
+// Functions producing parameter generators.
+//
+// Google Test uses these generators to produce parameters for value-
+// parameterized tests. When a parameterized test case is instantiated
+// with a particular generator, Google Test creates and runs tests
+// for each element in the sequence produced by the generator.
+//
+// In the following sample, tests from test case FooTest are instantiated
+// each three times with parameter values 3, 5, and 8:
+//
+// class FooTest : public TestWithParam<int> { ... };
+//
+// TEST_P(FooTest, TestThis) {
+// }
+// TEST_P(FooTest, TestThat) {
+// }
+// INSTANTIATE_TEST_CASE_P(TestSequence, FooTest, Values(3, 5, 8));
+//
+
+// Range() returns generators providing sequences of values in a range.
+//
+// Synopsis:
+// Range(start, end)
+//   - returns a generator producing a sequence of values {start, start+1,
+//     start+2, ..., }.
+// Range(start, end, step)
+//   - returns a generator producing a sequence of values {start, start+step,
+//     start+step+step, ..., }.
+// Notes:
+//   * The generated sequences never include end. For example, Range(1, 5)
+//     returns a generator producing a sequence {1, 2, 3, 4}. Range(1, 9, 2)
+//     returns a generator producing {1, 3, 5, 7}.
+//   * start and end must have the same type. That type may be any integral or
+//     floating-point type or a user defined type satisfying these conditions:
+//     * It must be assignable (have operator=() defined).
+//     * It must have operator+() (operator+(int-compatible type) for
+//       two-operand version).
+//     * It must have operator<() defined.
+//     Elements in the resulting sequences will also have that type.
+//   * Condition start < end must be satisfied in order for resulting sequences
+//     to contain any elements.
+//
+template <typename T, typename IncrementT>
+internal::ParamGenerator<T> Range(T start, T end, IncrementT step) {
+  return internal::ParamGenerator<T>(
+      new internal::RangeGenerator<T, IncrementT>(start, end, step));
+}
+
+template <typename T>
+internal::ParamGenerator<T> Range(T start, T end) {
+  return Range(start, end, 1);
+}
+
+// ValuesIn() function allows generation of tests with parameters coming from
+// a container.
+//
+// Synopsis:
+// ValuesIn(const T (&array)[N])
+//   - returns a generator producing sequences with elements from
+//     a C-style array.
+// ValuesIn(const Container& container)
+//   - returns a generator producing sequences with elements from
+//     an STL-style container.
+// ValuesIn(Iterator begin, Iterator end)
+//   - returns a generator producing sequences with elements from
+//     a range [begin, end) defined by a pair of STL-style iterators. These
+//     iterators can also be plain C pointers.
+//
+// Please note that ValuesIn copies the values from the containers
+// passed in and keeps them to generate tests in RUN_ALL_TESTS().
+//
+// Examples:
+//
+// This instantiates tests from test case StringTest
+// each with C-string values of "foo", "bar", and "baz":
+//
+// const char* strings[] = {"foo", "bar", "baz"};
+// INSTANTIATE_TEST_CASE_P(StringSequence, SrtingTest, ValuesIn(strings));
+//
+// This instantiates tests from test case StlStringTest
+// each with STL strings with values "a" and "b":
+//
+// ::std::vector< ::std::string> GetParameterStrings() {
+//   ::std::vector< ::std::string> v;
+//   v.push_back("a");
+//   v.push_back("b");
+//   return v;
+// }
+//
+// INSTANTIATE_TEST_CASE_P(CharSequence,
+//                         StlStringTest,
+//                         ValuesIn(GetParameterStrings()));
+//
+//
+// This will also instantiate tests from CharTest
+// each with parameter values 'a' and 'b':
+//
+// ::std::list<char> GetParameterChars() {
+//   ::std::list<char> list;
+//   list.push_back('a');
+//   list.push_back('b');
+//   return list;
+// }
+// ::std::list<char> l = GetParameterChars();
+// INSTANTIATE_TEST_CASE_P(CharSequence2,
+//                         CharTest,
+//                         ValuesIn(l.begin(), l.end()));
+//
+template <typename ForwardIterator>
+internal::ParamGenerator<
+  typename ::testing::internal::IteratorTraits<ForwardIterator>::value_type>
+ValuesIn(ForwardIterator begin, ForwardIterator end) {
+  typedef typename ::testing::internal::IteratorTraits<ForwardIterator>
+      ::value_type ParamType;
+  return internal::ParamGenerator<ParamType>(
+      new internal::ValuesInIteratorRangeGenerator<ParamType>(begin, end));
+}
+
+template <typename T, size_t N>
+internal::ParamGenerator<T> ValuesIn(const T (&array)[N]) {
+  return ValuesIn(array, array + N);
+}
+
+template <class Container>
+internal::ParamGenerator<typename Container::value_type> ValuesIn(
+    const Container& container) {
+  return ValuesIn(container.begin(), container.end());
+}
+
+// Values() allows generating tests from explicitly specified list of
+// parameters.
+//
+// Synopsis:
+// Values(T v1, T v2, ..., T vN)
+//   - returns a generator producing sequences with elements v1, v2, ..., vN.
+//
+// For example, this instantiates tests from test case BarTest each
+// with values "one", "two", and "three":
+//
+// INSTANTIATE_TEST_CASE_P(NumSequence, BarTest, Values("one", "two", "three"));
+//
+// This instantiates tests from test case BazTest each with values 1, 2, 3.5.
+// The exact type of values will depend on the type of parameter in BazTest.
+//
+// INSTANTIATE_TEST_CASE_P(FloatingNumbers, BazTest, Values(1, 2, 3.5));
+//
+// Currently, Values() supports from 1 to 50 parameters.
+//
+template <typename T1>
+internal::ValueArray1<T1> Values(T1 v1) {
+  return internal::ValueArray1<T1>(v1);
+}
+
+template <typename T1, typename T2>
+internal::ValueArray2<T1, T2> Values(T1 v1, T2 v2) {
+  return internal::ValueArray2<T1, T2>(v1, v2);
+}
+
+template <typename T1, typename T2, typename T3>
+internal::ValueArray3<T1, T2, T3> Values(T1 v1, T2 v2, T3 v3) {
+  return internal::ValueArray3<T1, T2, T3>(v1, v2, v3);
+}
+
+template <typename T1, typename T2, typename T3, typename T4>
+internal::ValueArray4<T1, T2, T3, T4> Values(T1 v1, T2 v2, T3 v3, T4 v4) {
+  return internal::ValueArray4<T1, T2, T3, T4>(v1, v2, v3, v4);
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5>
+internal::ValueArray5<T1, T2, T3, T4, T5> Values(T1 v1, T2 v2, T3 v3, T4 v4,
+    T5 v5) {
+  return internal::ValueArray5<T1, T2, T3, T4, T5>(v1, v2, v3, v4, v5);
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6>
+internal::ValueArray6<T1, T2, T3, T4, T5, T6> Values(T1 v1, T2 v2, T3 v3,
+    T4 v4, T5 v5, T6 v6) {
+  return internal::ValueArray6<T1, T2, T3, T4, T5, T6>(v1, v2, v3, v4, v5, v6);
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7>
+internal::ValueArray7<T1, T2, T3, T4, T5, T6, T7> Values(T1 v1, T2 v2, T3 v3,
+    T4 v4, T5 v5, T6 v6, T7 v7) {
+  return internal::ValueArray7<T1, T2, T3, T4, T5, T6, T7>(v1, v2, v3, v4, v5,
+      v6, v7);
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8>
+internal::ValueArray8<T1, T2, T3, T4, T5, T6, T7, T8> Values(T1 v1, T2 v2,
+    T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8) {
+  return internal::ValueArray8<T1, T2, T3, T4, T5, T6, T7, T8>(v1, v2, v3, v4,
+      v5, v6, v7, v8);
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9>
+internal::ValueArray9<T1, T2, T3, T4, T5, T6, T7, T8, T9> Values(T1 v1, T2 v2,
+    T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9) {
+  return internal::ValueArray9<T1, T2, T3, T4, T5, T6, T7, T8, T9>(v1, v2, v3,
+      v4, v5, v6, v7, v8, v9);
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10>
+internal::ValueArray10<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10> Values(T1 v1,
+    T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, T10 v10) {
+  return internal::ValueArray10<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10>(v1,
+      v2, v3, v4, v5, v6, v7, v8, v9, v10);
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11>
+internal::ValueArray11<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10,
+    T11> Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9,
+    T10 v10, T11 v11) {
+  return internal::ValueArray11<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10,
+      T11>(v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11);
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12>
+internal::ValueArray12<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11,
+    T12> Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9,
+    T10 v10, T11 v11, T12 v12) {
+  return internal::ValueArray12<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11,
+      T12>(v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12);
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13>
+internal::ValueArray13<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12,
+    T13> Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9,
+    T10 v10, T11 v11, T12 v12, T13 v13) {
+  return internal::ValueArray13<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11,
+      T12, T13>(v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13);
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14>
+internal::ValueArray14<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+    T14> Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9,
+    T10 v10, T11 v11, T12 v12, T13 v13, T14 v14) {
+  return internal::ValueArray14<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11,
+      T12, T13, T14>(v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13,
+      v14);
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15>
+internal::ValueArray15<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+    T14, T15> Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8,
+    T9 v9, T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15) {
+  return internal::ValueArray15<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11,
+      T12, T13, T14, T15>(v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12,
+      v13, v14, v15);
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16>
+internal::ValueArray16<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+    T14, T15, T16> Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7,
+    T8 v8, T9 v9, T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15,
+    T16 v16) {
+  return internal::ValueArray16<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11,
+      T12, T13, T14, T15, T16>(v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11,
+      v12, v13, v14, v15, v16);
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17>
+internal::ValueArray17<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+    T14, T15, T16, T17> Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7,
+    T8 v8, T9 v9, T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15,
+    T16 v16, T17 v17) {
+  return internal::ValueArray17<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11,
+      T12, T13, T14, T15, T16, T17>(v1, v2, v3, v4, v5, v6, v7, v8, v9, v10,
+      v11, v12, v13, v14, v15, v16, v17);
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18>
+internal::ValueArray18<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+    T14, T15, T16, T17, T18> Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6,
+    T7 v7, T8 v8, T9 v9, T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15,
+    T16 v16, T17 v17, T18 v18) {
+  return internal::ValueArray18<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11,
+      T12, T13, T14, T15, T16, T17, T18>(v1, v2, v3, v4, v5, v6, v7, v8, v9,
+      v10, v11, v12, v13, v14, v15, v16, v17, v18);
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19>
+internal::ValueArray19<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+    T14, T15, T16, T17, T18, T19> Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5,
+    T6 v6, T7 v7, T8 v8, T9 v9, T10 v10, T11 v11, T12 v12, T13 v13, T14 v14,
+    T15 v15, T16 v16, T17 v17, T18 v18, T19 v19) {
+  return internal::ValueArray19<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11,
+      T12, T13, T14, T15, T16, T17, T18, T19>(v1, v2, v3, v4, v5, v6, v7, v8,
+      v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19);
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20>
+internal::ValueArray20<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+    T14, T15, T16, T17, T18, T19, T20> Values(T1 v1, T2 v2, T3 v3, T4 v4,
+    T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, T10 v10, T11 v11, T12 v12, T13 v13,
+    T14 v14, T15 v15, T16 v16, T17 v17, T18 v18, T19 v19, T20 v20) {
+  return internal::ValueArray20<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11,
+      T12, T13, T14, T15, T16, T17, T18, T19, T20>(v1, v2, v3, v4, v5, v6, v7,
+      v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20);
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21>
+internal::ValueArray21<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+    T14, T15, T16, T17, T18, T19, T20, T21> Values(T1 v1, T2 v2, T3 v3, T4 v4,
+    T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, T10 v10, T11 v11, T12 v12, T13 v13,
+    T14 v14, T15 v15, T16 v16, T17 v17, T18 v18, T19 v19, T20 v20, T21 v21) {
+  return internal::ValueArray21<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11,
+      T12, T13, T14, T15, T16, T17, T18, T19, T20, T21>(v1, v2, v3, v4, v5, v6,
+      v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21);
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22>
+internal::ValueArray22<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+    T14, T15, T16, T17, T18, T19, T20, T21, T22> Values(T1 v1, T2 v2, T3 v3,
+    T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, T10 v10, T11 v11, T12 v12,
+    T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, T18 v18, T19 v19, T20 v20,
+    T21 v21, T22 v22) {
+  return internal::ValueArray22<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11,
+      T12, T13, T14, T15, T16, T17, T18, T19, T20, T21, T22>(v1, v2, v3, v4,
+      v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19,
+      v20, v21, v22);
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23>
+internal::ValueArray23<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+    T14, T15, T16, T17, T18, T19, T20, T21, T22, T23> Values(T1 v1, T2 v2,
+    T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, T10 v10, T11 v11, T12 v12,
+    T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, T18 v18, T19 v19, T20 v20,
+    T21 v21, T22 v22, T23 v23) {
+  return internal::ValueArray23<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11,
+      T12, T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23>(v1, v2, v3,
+      v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19,
+      v20, v21, v22, v23);
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24>
+internal::ValueArray24<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+    T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24> Values(T1 v1, T2 v2,
+    T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, T10 v10, T11 v11, T12 v12,
+    T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, T18 v18, T19 v19, T20 v20,
+    T21 v21, T22 v22, T23 v23, T24 v24) {
+  return internal::ValueArray24<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11,
+      T12, T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24>(v1, v2,
+      v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18,
+      v19, v20, v21, v22, v23, v24);
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25>
+internal::ValueArray25<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+    T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25> Values(T1 v1,
+    T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, T10 v10, T11 v11,
+    T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, T18 v18, T19 v19,
+    T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25) {
+  return internal::ValueArray25<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11,
+      T12, T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25>(v1,
+      v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17,
+      v18, v19, v20, v21, v22, v23, v24, v25);
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26>
+internal::ValueArray26<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+    T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25,
+    T26> Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9,
+    T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17,
+    T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25,
+    T26 v26) {
+  return internal::ValueArray26<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11,
+      T12, T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25,
+      T26>(v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15,
+      v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26);
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27>
+internal::ValueArray27<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+    T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26,
+    T27> Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9,
+    T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17,
+    T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25,
+    T26 v26, T27 v27) {
+  return internal::ValueArray27<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11,
+      T12, T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25,
+      T26, T27>(v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14,
+      v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27);
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28>
+internal::ValueArray28<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+    T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27,
+    T28> Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9,
+    T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17,
+    T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25,
+    T26 v26, T27 v27, T28 v28) {
+  return internal::ValueArray28<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11,
+      T12, T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25,
+      T26, T27, T28>(v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13,
+      v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27,
+      v28);
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29>
+internal::ValueArray29<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+    T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28,
+    T29> Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9,
+    T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17,
+    T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25,
+    T26 v26, T27 v27, T28 v28, T29 v29) {
+  return internal::ValueArray29<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11,
+      T12, T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25,
+      T26, T27, T28, T29>(v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12,
+      v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26,
+      v27, v28, v29);
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30>
+internal::ValueArray30<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+    T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28,
+    T29, T30> Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8,
+    T9 v9, T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16,
+    T17 v17, T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24,
+    T25 v25, T26 v26, T27 v27, T28 v28, T29 v29, T30 v30) {
+  return internal::ValueArray30<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11,
+      T12, T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25,
+      T26, T27, T28, T29, T30>(v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11,
+      v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25,
+      v26, v27, v28, v29, v30);
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31>
+internal::ValueArray31<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+    T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28,
+    T29, T30, T31> Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7,
+    T8 v8, T9 v9, T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15,
+    T16 v16, T17 v17, T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23,
+    T24 v24, T25 v25, T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31) {
+  return internal::ValueArray31<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11,
+      T12, T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25,
+      T26, T27, T28, T29, T30, T31>(v1, v2, v3, v4, v5, v6, v7, v8, v9, v10,
+      v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24,
+      v25, v26, v27, v28, v29, v30, v31);
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32>
+internal::ValueArray32<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+    T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28,
+    T29, T30, T31, T32> Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7,
+    T8 v8, T9 v9, T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15,
+    T16 v16, T17 v17, T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23,
+    T24 v24, T25 v25, T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31,
+    T32 v32) {
+  return internal::ValueArray32<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11,
+      T12, T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25,
+      T26, T27, T28, T29, T30, T31, T32>(v1, v2, v3, v4, v5, v6, v7, v8, v9,
+      v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23,
+      v24, v25, v26, v27, v28, v29, v30, v31, v32);
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32, typename T33>
+internal::ValueArray33<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+    T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28,
+    T29, T30, T31, T32, T33> Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6,
+    T7 v7, T8 v8, T9 v9, T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15,
+    T16 v16, T17 v17, T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23,
+    T24 v24, T25 v25, T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31,
+    T32 v32, T33 v33) {
+  return internal::ValueArray33<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11,
+      T12, T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25,
+      T26, T27, T28, T29, T30, T31, T32, T33>(v1, v2, v3, v4, v5, v6, v7, v8,
+      v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23,
+      v24, v25, v26, v27, v28, v29, v30, v31, v32, v33);
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32, typename T33, typename T34>
+internal::ValueArray34<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+    T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28,
+    T29, T30, T31, T32, T33, T34> Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5,
+    T6 v6, T7 v7, T8 v8, T9 v9, T10 v10, T11 v11, T12 v12, T13 v13, T14 v14,
+    T15 v15, T16 v16, T17 v17, T18 v18, T19 v19, T20 v20, T21 v21, T22 v22,
+    T23 v23, T24 v24, T25 v25, T26 v26, T27 v27, T28 v28, T29 v29, T30 v30,
+    T31 v31, T32 v32, T33 v33, T34 v34) {
+  return internal::ValueArray34<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11,
+      T12, T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25,
+      T26, T27, T28, T29, T30, T31, T32, T33, T34>(v1, v2, v3, v4, v5, v6, v7,
+      v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22,
+      v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34);
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32, typename T33, typename T34, typename T35>
+internal::ValueArray35<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+    T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28,
+    T29, T30, T31, T32, T33, T34, T35> Values(T1 v1, T2 v2, T3 v3, T4 v4,
+    T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, T10 v10, T11 v11, T12 v12, T13 v13,
+    T14 v14, T15 v15, T16 v16, T17 v17, T18 v18, T19 v19, T20 v20, T21 v21,
+    T22 v22, T23 v23, T24 v24, T25 v25, T26 v26, T27 v27, T28 v28, T29 v29,
+    T30 v30, T31 v31, T32 v32, T33 v33, T34 v34, T35 v35) {
+  return internal::ValueArray35<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11,
+      T12, T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25,
+      T26, T27, T28, T29, T30, T31, T32, T33, T34, T35>(v1, v2, v3, v4, v5, v6,
+      v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21,
+      v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35);
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32, typename T33, typename T34, typename T35,
+    typename T36>
+internal::ValueArray36<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+    T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28,
+    T29, T30, T31, T32, T33, T34, T35, T36> Values(T1 v1, T2 v2, T3 v3, T4 v4,
+    T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, T10 v10, T11 v11, T12 v12, T13 v13,
+    T14 v14, T15 v15, T16 v16, T17 v17, T18 v18, T19 v19, T20 v20, T21 v21,
+    T22 v22, T23 v23, T24 v24, T25 v25, T26 v26, T27 v27, T28 v28, T29 v29,
+    T30 v30, T31 v31, T32 v32, T33 v33, T34 v34, T35 v35, T36 v36) {
+  return internal::ValueArray36<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11,
+      T12, T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25,
+      T26, T27, T28, T29, T30, T31, T32, T33, T34, T35, T36>(v1, v2, v3, v4,
+      v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19,
+      v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33,
+      v34, v35, v36);
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32, typename T33, typename T34, typename T35,
+    typename T36, typename T37>
+internal::ValueArray37<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+    T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28,
+    T29, T30, T31, T32, T33, T34, T35, T36, T37> Values(T1 v1, T2 v2, T3 v3,
+    T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, T10 v10, T11 v11, T12 v12,
+    T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, T18 v18, T19 v19, T20 v20,
+    T21 v21, T22 v22, T23 v23, T24 v24, T25 v25, T26 v26, T27 v27, T28 v28,
+    T29 v29, T30 v30, T31 v31, T32 v32, T33 v33, T34 v34, T35 v35, T36 v36,
+    T37 v37) {
+  return internal::ValueArray37<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11,
+      T12, T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25,
+      T26, T27, T28, T29, T30, T31, T32, T33, T34, T35, T36, T37>(v1, v2, v3,
+      v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19,
+      v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33,
+      v34, v35, v36, v37);
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32, typename T33, typename T34, typename T35,
+    typename T36, typename T37, typename T38>
+internal::ValueArray38<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+    T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28,
+    T29, T30, T31, T32, T33, T34, T35, T36, T37, T38> Values(T1 v1, T2 v2,
+    T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, T10 v10, T11 v11, T12 v12,
+    T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, T18 v18, T19 v19, T20 v20,
+    T21 v21, T22 v22, T23 v23, T24 v24, T25 v25, T26 v26, T27 v27, T28 v28,
+    T29 v29, T30 v30, T31 v31, T32 v32, T33 v33, T34 v34, T35 v35, T36 v36,
+    T37 v37, T38 v38) {
+  return internal::ValueArray38<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11,
+      T12, T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25,
+      T26, T27, T28, T29, T30, T31, T32, T33, T34, T35, T36, T37, T38>(v1, v2,
+      v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18,
+      v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32,
+      v33, v34, v35, v36, v37, v38);
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32, typename T33, typename T34, typename T35,
+    typename T36, typename T37, typename T38, typename T39>
+internal::ValueArray39<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+    T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28,
+    T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39> Values(T1 v1, T2 v2,
+    T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, T10 v10, T11 v11, T12 v12,
+    T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, T18 v18, T19 v19, T20 v20,
+    T21 v21, T22 v22, T23 v23, T24 v24, T25 v25, T26 v26, T27 v27, T28 v28,
+    T29 v29, T30 v30, T31 v31, T32 v32, T33 v33, T34 v34, T35 v35, T36 v36,
+    T37 v37, T38 v38, T39 v39) {
+  return internal::ValueArray39<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11,
+      T12, T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25,
+      T26, T27, T28, T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39>(v1,
+      v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17,
+      v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31,
+      v32, v33, v34, v35, v36, v37, v38, v39);
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32, typename T33, typename T34, typename T35,
+    typename T36, typename T37, typename T38, typename T39, typename T40>
+internal::ValueArray40<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+    T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28,
+    T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40> Values(T1 v1,
+    T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, T10 v10, T11 v11,
+    T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, T18 v18, T19 v19,
+    T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25, T26 v26, T27 v27,
+    T28 v28, T29 v29, T30 v30, T31 v31, T32 v32, T33 v33, T34 v34, T35 v35,
+    T36 v36, T37 v37, T38 v38, T39 v39, T40 v40) {
+  return internal::ValueArray40<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11,
+      T12, T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25,
+      T26, T27, T28, T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39,
+      T40>(v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15,
+      v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29,
+      v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40);
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32, typename T33, typename T34, typename T35,
+    typename T36, typename T37, typename T38, typename T39, typename T40,
+    typename T41>
+internal::ValueArray41<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+    T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28,
+    T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40,
+    T41> Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9,
+    T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17,
+    T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25,
+    T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, T32 v32, T33 v33,
+    T34 v34, T35 v35, T36 v36, T37 v37, T38 v38, T39 v39, T40 v40, T41 v41) {
+  return internal::ValueArray41<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11,
+      T12, T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25,
+      T26, T27, T28, T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39,
+      T40, T41>(v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14,
+      v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28,
+      v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41);
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32, typename T33, typename T34, typename T35,
+    typename T36, typename T37, typename T38, typename T39, typename T40,
+    typename T41, typename T42>
+internal::ValueArray42<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+    T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28,
+    T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41,
+    T42> Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9,
+    T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17,
+    T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25,
+    T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, T32 v32, T33 v33,
+    T34 v34, T35 v35, T36 v36, T37 v37, T38 v38, T39 v39, T40 v40, T41 v41,
+    T42 v42) {
+  return internal::ValueArray42<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11,
+      T12, T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25,
+      T26, T27, T28, T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39,
+      T40, T41, T42>(v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13,
+      v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27,
+      v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41,
+      v42);
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32, typename T33, typename T34, typename T35,
+    typename T36, typename T37, typename T38, typename T39, typename T40,
+    typename T41, typename T42, typename T43>
+internal::ValueArray43<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+    T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28,
+    T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41, T42,
+    T43> Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9,
+    T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17,
+    T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25,
+    T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, T32 v32, T33 v33,
+    T34 v34, T35 v35, T36 v36, T37 v37, T38 v38, T39 v39, T40 v40, T41 v41,
+    T42 v42, T43 v43) {
+  return internal::ValueArray43<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11,
+      T12, T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25,
+      T26, T27, T28, T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39,
+      T40, T41, T42, T43>(v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12,
+      v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26,
+      v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40,
+      v41, v42, v43);
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32, typename T33, typename T34, typename T35,
+    typename T36, typename T37, typename T38, typename T39, typename T40,
+    typename T41, typename T42, typename T43, typename T44>
+internal::ValueArray44<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+    T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28,
+    T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41, T42, T43,
+    T44> Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9,
+    T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17,
+    T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25,
+    T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, T32 v32, T33 v33,
+    T34 v34, T35 v35, T36 v36, T37 v37, T38 v38, T39 v39, T40 v40, T41 v41,
+    T42 v42, T43 v43, T44 v44) {
+  return internal::ValueArray44<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11,
+      T12, T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25,
+      T26, T27, T28, T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39,
+      T40, T41, T42, T43, T44>(v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11,
+      v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25,
+      v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39,
+      v40, v41, v42, v43, v44);
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32, typename T33, typename T34, typename T35,
+    typename T36, typename T37, typename T38, typename T39, typename T40,
+    typename T41, typename T42, typename T43, typename T44, typename T45>
+internal::ValueArray45<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+    T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28,
+    T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41, T42, T43,
+    T44, T45> Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8,
+    T9 v9, T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16,
+    T17 v17, T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24,
+    T25 v25, T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, T32 v32,
+    T33 v33, T34 v34, T35 v35, T36 v36, T37 v37, T38 v38, T39 v39, T40 v40,
+    T41 v41, T42 v42, T43 v43, T44 v44, T45 v45) {
+  return internal::ValueArray45<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11,
+      T12, T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25,
+      T26, T27, T28, T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39,
+      T40, T41, T42, T43, T44, T45>(v1, v2, v3, v4, v5, v6, v7, v8, v9, v10,
+      v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24,
+      v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38,
+      v39, v40, v41, v42, v43, v44, v45);
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32, typename T33, typename T34, typename T35,
+    typename T36, typename T37, typename T38, typename T39, typename T40,
+    typename T41, typename T42, typename T43, typename T44, typename T45,
+    typename T46>
+internal::ValueArray46<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+    T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28,
+    T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41, T42, T43,
+    T44, T45, T46> Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7,
+    T8 v8, T9 v9, T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15,
+    T16 v16, T17 v17, T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23,
+    T24 v24, T25 v25, T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31,
+    T32 v32, T33 v33, T34 v34, T35 v35, T36 v36, T37 v37, T38 v38, T39 v39,
+    T40 v40, T41 v41, T42 v42, T43 v43, T44 v44, T45 v45, T46 v46) {
+  return internal::ValueArray46<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11,
+      T12, T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25,
+      T26, T27, T28, T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39,
+      T40, T41, T42, T43, T44, T45, T46>(v1, v2, v3, v4, v5, v6, v7, v8, v9,
+      v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23,
+      v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37,
+      v38, v39, v40, v41, v42, v43, v44, v45, v46);
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32, typename T33, typename T34, typename T35,
+    typename T36, typename T37, typename T38, typename T39, typename T40,
+    typename T41, typename T42, typename T43, typename T44, typename T45,
+    typename T46, typename T47>
+internal::ValueArray47<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+    T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28,
+    T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41, T42, T43,
+    T44, T45, T46, T47> Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7,
+    T8 v8, T9 v9, T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15,
+    T16 v16, T17 v17, T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23,
+    T24 v24, T25 v25, T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31,
+    T32 v32, T33 v33, T34 v34, T35 v35, T36 v36, T37 v37, T38 v38, T39 v39,
+    T40 v40, T41 v41, T42 v42, T43 v43, T44 v44, T45 v45, T46 v46, T47 v47) {
+  return internal::ValueArray47<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11,
+      T12, T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25,
+      T26, T27, T28, T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39,
+      T40, T41, T42, T43, T44, T45, T46, T47>(v1, v2, v3, v4, v5, v6, v7, v8,
+      v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23,
+      v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37,
+      v38, v39, v40, v41, v42, v43, v44, v45, v46, v47);
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32, typename T33, typename T34, typename T35,
+    typename T36, typename T37, typename T38, typename T39, typename T40,
+    typename T41, typename T42, typename T43, typename T44, typename T45,
+    typename T46, typename T47, typename T48>
+internal::ValueArray48<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+    T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28,
+    T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41, T42, T43,
+    T44, T45, T46, T47, T48> Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6,
+    T7 v7, T8 v8, T9 v9, T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15,
+    T16 v16, T17 v17, T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23,
+    T24 v24, T25 v25, T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31,
+    T32 v32, T33 v33, T34 v34, T35 v35, T36 v36, T37 v37, T38 v38, T39 v39,
+    T40 v40, T41 v41, T42 v42, T43 v43, T44 v44, T45 v45, T46 v46, T47 v47,
+    T48 v48) {
+  return internal::ValueArray48<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11,
+      T12, T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25,
+      T26, T27, T28, T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39,
+      T40, T41, T42, T43, T44, T45, T46, T47, T48>(v1, v2, v3, v4, v5, v6, v7,
+      v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22,
+      v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36,
+      v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48);
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32, typename T33, typename T34, typename T35,
+    typename T36, typename T37, typename T38, typename T39, typename T40,
+    typename T41, typename T42, typename T43, typename T44, typename T45,
+    typename T46, typename T47, typename T48, typename T49>
+internal::ValueArray49<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+    T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28,
+    T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41, T42, T43,
+    T44, T45, T46, T47, T48, T49> Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5,
+    T6 v6, T7 v7, T8 v8, T9 v9, T10 v10, T11 v11, T12 v12, T13 v13, T14 v14,
+    T15 v15, T16 v16, T17 v17, T18 v18, T19 v19, T20 v20, T21 v21, T22 v22,
+    T23 v23, T24 v24, T25 v25, T26 v26, T27 v27, T28 v28, T29 v29, T30 v30,
+    T31 v31, T32 v32, T33 v33, T34 v34, T35 v35, T36 v36, T37 v37, T38 v38,
+    T39 v39, T40 v40, T41 v41, T42 v42, T43 v43, T44 v44, T45 v45, T46 v46,
+    T47 v47, T48 v48, T49 v49) {
+  return internal::ValueArray49<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11,
+      T12, T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25,
+      T26, T27, T28, T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39,
+      T40, T41, T42, T43, T44, T45, T46, T47, T48, T49>(v1, v2, v3, v4, v5, v6,
+      v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21,
+      v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35,
+      v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49);
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32, typename T33, typename T34, typename T35,
+    typename T36, typename T37, typename T38, typename T39, typename T40,
+    typename T41, typename T42, typename T43, typename T44, typename T45,
+    typename T46, typename T47, typename T48, typename T49, typename T50>
+internal::ValueArray50<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+    T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28,
+    T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41, T42, T43,
+    T44, T45, T46, T47, T48, T49, T50> Values(T1 v1, T2 v2, T3 v3, T4 v4,
+    T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, T10 v10, T11 v11, T12 v12, T13 v13,
+    T14 v14, T15 v15, T16 v16, T17 v17, T18 v18, T19 v19, T20 v20, T21 v21,
+    T22 v22, T23 v23, T24 v24, T25 v25, T26 v26, T27 v27, T28 v28, T29 v29,
+    T30 v30, T31 v31, T32 v32, T33 v33, T34 v34, T35 v35, T36 v36, T37 v37,
+    T38 v38, T39 v39, T40 v40, T41 v41, T42 v42, T43 v43, T44 v44, T45 v45,
+    T46 v46, T47 v47, T48 v48, T49 v49, T50 v50) {
+  return internal::ValueArray50<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11,
+      T12, T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25,
+      T26, T27, T28, T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39,
+      T40, T41, T42, T43, T44, T45, T46, T47, T48, T49, T50>(v1, v2, v3, v4,
+      v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19,
+      v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33,
+      v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47,
+      v48, v49, v50);
+}
+
+// Bool() allows generating tests with parameters in a set of (false, true).
+//
+// Synopsis:
+// Bool()
+//   - returns a generator producing sequences with elements {false, true}.
+//
+// It is useful when testing code that depends on Boolean flags. Combinations
+// of multiple flags can be tested when several Bool()'s are combined using
+// Combine() function.
+//
+// In the following example all tests in the test case FlagDependentTest
+// will be instantiated twice with parameters false and true.
+//
+// class FlagDependentTest : public testing::TestWithParam<bool> {
+//   virtual void SetUp() {
+//     external_flag = GetParam();
+//   }
+// }
+// INSTANTIATE_TEST_CASE_P(BoolSequence, FlagDependentTest, Bool());
+//
+inline internal::ParamGenerator<bool> Bool() {
+  return Values(false, true);
+}
+
+# if GTEST_HAS_COMBINE
+// Combine() allows the user to combine two or more sequences to produce
+// values of a Cartesian product of those sequences' elements.
+//
+// Synopsis:
+// Combine(gen1, gen2, ..., genN)
+//   - returns a generator producing sequences with elements coming from
+//     the Cartesian product of elements from the sequences generated by
+//     gen1, gen2, ..., genN. The sequence elements will have a type of
+//     tuple<T1, T2, ..., TN> where T1, T2, ..., TN are the types
+//     of elements from sequences produces by gen1, gen2, ..., genN.
+//
+// Combine can have up to 10 arguments. This number is currently limited
+// by the maximum number of elements in the tuple implementation used by Google
+// Test.
+//
+// Example:
+//
+// This will instantiate tests in test case AnimalTest each one with
+// the parameter values tuple("cat", BLACK), tuple("cat", WHITE),
+// tuple("dog", BLACK), and tuple("dog", WHITE):
+//
+// enum Color { BLACK, GRAY, WHITE };
+// class AnimalTest
+//     : public testing::TestWithParam<tuple<const char*, Color> > {...};
+//
+// TEST_P(AnimalTest, AnimalLooksNice) {...}
+//
+// INSTANTIATE_TEST_CASE_P(AnimalVariations, AnimalTest,
+//                         Combine(Values("cat", "dog"),
+//                                 Values(BLACK, WHITE)));
+//
+// This will instantiate tests in FlagDependentTest with all variations of two
+// Boolean flags:
+//
+// class FlagDependentTest
+//     : public testing::TestWithParam<tuple<bool, bool> > {
+//   virtual void SetUp() {
+//     // Assigns external_flag_1 and external_flag_2 values from the tuple.
+//     tie(external_flag_1, external_flag_2) = GetParam();
+//   }
+// };
+//
+// TEST_P(FlagDependentTest, TestFeature1) {
+//   // Test your code using external_flag_1 and external_flag_2 here.
+// }
+// INSTANTIATE_TEST_CASE_P(TwoBoolSequence, FlagDependentTest,
+//                         Combine(Bool(), Bool()));
+//
+template <typename Generator1, typename Generator2>
+internal::CartesianProductHolder2<Generator1, Generator2> Combine(
+    const Generator1& g1, const Generator2& g2) {
+  return internal::CartesianProductHolder2<Generator1, Generator2>(
+      g1, g2);
+}
+
+template <typename Generator1, typename Generator2, typename Generator3>
+internal::CartesianProductHolder3<Generator1, Generator2, Generator3> Combine(
+    const Generator1& g1, const Generator2& g2, const Generator3& g3) {
+  return internal::CartesianProductHolder3<Generator1, Generator2, Generator3>(
+      g1, g2, g3);
+}
+
+template <typename Generator1, typename Generator2, typename Generator3,
+    typename Generator4>
+internal::CartesianProductHolder4<Generator1, Generator2, Generator3,
+    Generator4> Combine(
+    const Generator1& g1, const Generator2& g2, const Generator3& g3,
+        const Generator4& g4) {
+  return internal::CartesianProductHolder4<Generator1, Generator2, Generator3,
+      Generator4>(
+      g1, g2, g3, g4);
+}
+
+template <typename Generator1, typename Generator2, typename Generator3,
+    typename Generator4, typename Generator5>
+internal::CartesianProductHolder5<Generator1, Generator2, Generator3,
+    Generator4, Generator5> Combine(
+    const Generator1& g1, const Generator2& g2, const Generator3& g3,
+        const Generator4& g4, const Generator5& g5) {
+  return internal::CartesianProductHolder5<Generator1, Generator2, Generator3,
+      Generator4, Generator5>(
+      g1, g2, g3, g4, g5);
+}
+
+template <typename Generator1, typename Generator2, typename Generator3,
+    typename Generator4, typename Generator5, typename Generator6>
+internal::CartesianProductHolder6<Generator1, Generator2, Generator3,
+    Generator4, Generator5, Generator6> Combine(
+    const Generator1& g1, const Generator2& g2, const Generator3& g3,
+        const Generator4& g4, const Generator5& g5, const Generator6& g6) {
+  return internal::CartesianProductHolder6<Generator1, Generator2, Generator3,
+      Generator4, Generator5, Generator6>(
+      g1, g2, g3, g4, g5, g6);
+}
+
+template <typename Generator1, typename Generator2, typename Generator3,
+    typename Generator4, typename Generator5, typename Generator6,
+    typename Generator7>
+internal::CartesianProductHolder7<Generator1, Generator2, Generator3,
+    Generator4, Generator5, Generator6, Generator7> Combine(
+    const Generator1& g1, const Generator2& g2, const Generator3& g3,
+        const Generator4& g4, const Generator5& g5, const Generator6& g6,
+        const Generator7& g7) {
+  return internal::CartesianProductHolder7<Generator1, Generator2, Generator3,
+      Generator4, Generator5, Generator6, Generator7>(
+      g1, g2, g3, g4, g5, g6, g7);
+}
+
+template <typename Generator1, typename Generator2, typename Generator3,
+    typename Generator4, typename Generator5, typename Generator6,
+    typename Generator7, typename Generator8>
+internal::CartesianProductHolder8<Generator1, Generator2, Generator3,
+    Generator4, Generator5, Generator6, Generator7, Generator8> Combine(
+    const Generator1& g1, const Generator2& g2, const Generator3& g3,
+        const Generator4& g4, const Generator5& g5, const Generator6& g6,
+        const Generator7& g7, const Generator8& g8) {
+  return internal::CartesianProductHolder8<Generator1, Generator2, Generator3,
+      Generator4, Generator5, Generator6, Generator7, Generator8>(
+      g1, g2, g3, g4, g5, g6, g7, g8);
+}
+
+template <typename Generator1, typename Generator2, typename Generator3,
+    typename Generator4, typename Generator5, typename Generator6,
+    typename Generator7, typename Generator8, typename Generator9>
+internal::CartesianProductHolder9<Generator1, Generator2, Generator3,
+    Generator4, Generator5, Generator6, Generator7, Generator8,
+    Generator9> Combine(
+    const Generator1& g1, const Generator2& g2, const Generator3& g3,
+        const Generator4& g4, const Generator5& g5, const Generator6& g6,
+        const Generator7& g7, const Generator8& g8, const Generator9& g9) {
+  return internal::CartesianProductHolder9<Generator1, Generator2, Generator3,
+      Generator4, Generator5, Generator6, Generator7, Generator8, Generator9>(
+      g1, g2, g3, g4, g5, g6, g7, g8, g9);
+}
+
+template <typename Generator1, typename Generator2, typename Generator3,
+    typename Generator4, typename Generator5, typename Generator6,
+    typename Generator7, typename Generator8, typename Generator9,
+    typename Generator10>
+internal::CartesianProductHolder10<Generator1, Generator2, Generator3,
+    Generator4, Generator5, Generator6, Generator7, Generator8, Generator9,
+    Generator10> Combine(
+    const Generator1& g1, const Generator2& g2, const Generator3& g3,
+        const Generator4& g4, const Generator5& g5, const Generator6& g6,
+        const Generator7& g7, const Generator8& g8, const Generator9& g9,
+        const Generator10& g10) {
+  return internal::CartesianProductHolder10<Generator1, Generator2, Generator3,
+      Generator4, Generator5, Generator6, Generator7, Generator8, Generator9,
+      Generator10>(
+      g1, g2, g3, g4, g5, g6, g7, g8, g9, g10);
+}
+# endif  // GTEST_HAS_COMBINE
+
+
+
+# define TEST_P(test_case_name, test_name) \
+  class GTEST_TEST_CLASS_NAME_(test_case_name, test_name) \
+      : public test_case_name { \
+   public: \
+    GTEST_TEST_CLASS_NAME_(test_case_name, test_name)() {} \
+    virtual void TestBody(); \
+   private: \
+    static int AddToRegistry() { \
+      ::testing::UnitTest::GetInstance()->parameterized_test_registry(). \
+          GetTestCasePatternHolder<test_case_name>(\
+              #test_case_name, __FILE__, __LINE__)->AddTestPattern(\
+                  #test_case_name, \
+                  #test_name, \
+                  new ::testing::internal::TestMetaFactory< \
+                      GTEST_TEST_CLASS_NAME_(test_case_name, test_name)>()); \
+      return 0; \
+    } \
+    static int gtest_registering_dummy_; \
+    GTEST_DISALLOW_COPY_AND_ASSIGN_(\
+        GTEST_TEST_CLASS_NAME_(test_case_name, test_name)); \
+  }; \
+  int GTEST_TEST_CLASS_NAME_(test_case_name, \
+                             test_name)::gtest_registering_dummy_ = \
+      GTEST_TEST_CLASS_NAME_(test_case_name, test_name)::AddToRegistry(); \
+  void GTEST_TEST_CLASS_NAME_(test_case_name, test_name)::TestBody()
+
+# define INSTANTIATE_TEST_CASE_P(prefix, test_case_name, generator) \
+  ::testing::internal::ParamGenerator<test_case_name::ParamType> \
+      gtest_##prefix##test_case_name##_EvalGenerator_() { return generator; } \
+  int gtest_##prefix##test_case_name##_dummy_ = \
+      ::testing::UnitTest::GetInstance()->parameterized_test_registry(). \
+          GetTestCasePatternHolder<test_case_name>(\
+              #test_case_name, __FILE__, __LINE__)->AddTestCaseInstantiation(\
+                  #prefix, \
+                  &gtest_##prefix##test_case_name##_EvalGenerator_, \
+                  __FILE__, __LINE__)
+
+}  // namespace testing
+
+#endif  // GTEST_HAS_PARAM_TEST
+
+#endif  // GTEST_INCLUDE_GTEST_GTEST_PARAM_TEST_H_
diff --git a/test/gtest/include/gtest/gtest-param-test.h.pump b/test/gtest/include/gtest/gtest-param-test.h.pump
new file mode 100644
index 0000000..2dc9303
--- /dev/null
+++ b/test/gtest/include/gtest/gtest-param-test.h.pump
@@ -0,0 +1,487 @@
+$$ -*- mode: c++; -*-
+$var n = 50  $$ Maximum length of Values arguments we want to support.
+$var maxtuple = 10  $$ Maximum number of Combine arguments we want to support.
+// Copyright 2008, Google Inc.
+// All rights reserved.
+//
+// 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.
+//
+// Authors: vladl at google.com (Vlad Losev)
+//
+// Macros and functions for implementing parameterized tests
+// in Google C++ Testing Framework (Google Test)
+//
+// This file is generated by a SCRIPT.  DO NOT EDIT BY HAND!
+//
+#ifndef GTEST_INCLUDE_GTEST_GTEST_PARAM_TEST_H_
+#define GTEST_INCLUDE_GTEST_GTEST_PARAM_TEST_H_
+
+
+// Value-parameterized tests allow you to test your code with different
+// parameters without writing multiple copies of the same test.
+//
+// Here is how you use value-parameterized tests:
+
+#if 0
+
+// To write value-parameterized tests, first you should define a fixture
+// class. It is usually derived from testing::TestWithParam<T> (see below for
+// another inheritance scheme that's sometimes useful in more complicated
+// class hierarchies), where the type of your parameter values.
+// TestWithParam<T> is itself derived from testing::Test. T can be any
+// copyable type. If it's a raw pointer, you are responsible for managing the
+// lifespan of the pointed values.
+
+class FooTest : public ::testing::TestWithParam<const char*> {
+  // You can implement all the usual class fixture members here.
+};
+
+// Then, use the TEST_P macro to define as many parameterized tests
+// for this fixture as you want. The _P suffix is for "parameterized"
+// or "pattern", whichever you prefer to think.
+
+TEST_P(FooTest, DoesBlah) {
+  // Inside a test, access the test parameter with the GetParam() method
+  // of the TestWithParam<T> class:
+  EXPECT_TRUE(foo.Blah(GetParam()));
+  ...
+}
+
+TEST_P(FooTest, HasBlahBlah) {
+  ...
+}
+
+// Finally, you can use INSTANTIATE_TEST_CASE_P to instantiate the test
+// case with any set of parameters you want. Google Test defines a number
+// of functions for generating test parameters. They return what we call
+// (surprise!) parameter generators. Here is a  summary of them, which
+// are all in the testing namespace:
+//
+//
+//  Range(begin, end [, step]) - Yields values {begin, begin+step,
+//                               begin+step+step, ...}. The values do not
+//                               include end. step defaults to 1.
+//  Values(v1, v2, ..., vN)    - Yields values {v1, v2, ..., vN}.
+//  ValuesIn(container)        - Yields values from a C-style array, an STL
+//  ValuesIn(begin,end)          container, or an iterator range [begin, end).
+//  Bool()                     - Yields sequence {false, true}.
+//  Combine(g1, g2, ..., gN)   - Yields all combinations (the Cartesian product
+//                               for the math savvy) of the values generated
+//                               by the N generators.
+//
+// For more details, see comments at the definitions of these functions below
+// in this file.
+//
+// The following statement will instantiate tests from the FooTest test case
+// each with parameter values "meeny", "miny", and "moe".
+
+INSTANTIATE_TEST_CASE_P(InstantiationName,
+                        FooTest,
+                        Values("meeny", "miny", "moe"));
+
+// To distinguish different instances of the pattern, (yes, you
+// can instantiate it more then once) the first argument to the
+// INSTANTIATE_TEST_CASE_P macro is a prefix that will be added to the
+// actual test case name. Remember to pick unique prefixes for different
+// instantiations. The tests from the instantiation above will have
+// these names:
+//
+//    * InstantiationName/FooTest.DoesBlah/0 for "meeny"
+//    * InstantiationName/FooTest.DoesBlah/1 for "miny"
+//    * InstantiationName/FooTest.DoesBlah/2 for "moe"
+//    * InstantiationName/FooTest.HasBlahBlah/0 for "meeny"
+//    * InstantiationName/FooTest.HasBlahBlah/1 for "miny"
+//    * InstantiationName/FooTest.HasBlahBlah/2 for "moe"
+//
+// You can use these names in --gtest_filter.
+//
+// This statement will instantiate all tests from FooTest again, each
+// with parameter values "cat" and "dog":
+
+const char* pets[] = {"cat", "dog"};
+INSTANTIATE_TEST_CASE_P(AnotherInstantiationName, FooTest, ValuesIn(pets));
+
+// The tests from the instantiation above will have these names:
+//
+//    * AnotherInstantiationName/FooTest.DoesBlah/0 for "cat"
+//    * AnotherInstantiationName/FooTest.DoesBlah/1 for "dog"
+//    * AnotherInstantiationName/FooTest.HasBlahBlah/0 for "cat"
+//    * AnotherInstantiationName/FooTest.HasBlahBlah/1 for "dog"
+//
+// Please note that INSTANTIATE_TEST_CASE_P will instantiate all tests
+// in the given test case, whether their definitions come before or
+// AFTER the INSTANTIATE_TEST_CASE_P statement.
+//
+// Please also note that generator expressions (including parameters to the
+// generators) are evaluated in InitGoogleTest(), after main() has started.
+// This allows the user on one hand, to adjust generator parameters in order
+// to dynamically determine a set of tests to run and on the other hand,
+// give the user a chance to inspect the generated tests with Google Test
+// reflection API before RUN_ALL_TESTS() is executed.
+//
+// You can see samples/sample7_unittest.cc and samples/sample8_unittest.cc
+// for more examples.
+//
+// In the future, we plan to publish the API for defining new parameter
+// generators. But for now this interface remains part of the internal
+// implementation and is subject to change.
+//
+//
+// A parameterized test fixture must be derived from testing::Test and from
+// testing::WithParamInterface<T>, where T is the type of the parameter
+// values. Inheriting from TestWithParam<T> satisfies that requirement because
+// TestWithParam<T> inherits from both Test and WithParamInterface. In more
+// complicated hierarchies, however, it is occasionally useful to inherit
+// separately from Test and WithParamInterface. For example:
+
+class BaseTest : public ::testing::Test {
+  // You can inherit all the usual members for a non-parameterized test
+  // fixture here.
+};
+
+class DerivedTest : public BaseTest, public ::testing::WithParamInterface<int> {
+  // The usual test fixture members go here too.
+};
+
+TEST_F(BaseTest, HasFoo) {
+  // This is an ordinary non-parameterized test.
+}
+
+TEST_P(DerivedTest, DoesBlah) {
+  // GetParam works just the same here as if you inherit from TestWithParam.
+  EXPECT_TRUE(foo.Blah(GetParam()));
+}
+
+#endif  // 0
+
+#include "gtest/internal/gtest-port.h"
+
+#if !GTEST_OS_SYMBIAN
+# include <utility>
+#endif
+
+// scripts/fuse_gtest.py depends on gtest's own header being #included
+// *unconditionally*.  Therefore these #includes cannot be moved
+// inside #if GTEST_HAS_PARAM_TEST.
+#include "gtest/internal/gtest-internal.h"
+#include "gtest/internal/gtest-param-util.h"
+#include "gtest/internal/gtest-param-util-generated.h"
+
+#if GTEST_HAS_PARAM_TEST
+
+namespace testing {
+
+// Functions producing parameter generators.
+//
+// Google Test uses these generators to produce parameters for value-
+// parameterized tests. When a parameterized test case is instantiated
+// with a particular generator, Google Test creates and runs tests
+// for each element in the sequence produced by the generator.
+//
+// In the following sample, tests from test case FooTest are instantiated
+// each three times with parameter values 3, 5, and 8:
+//
+// class FooTest : public TestWithParam<int> { ... };
+//
+// TEST_P(FooTest, TestThis) {
+// }
+// TEST_P(FooTest, TestThat) {
+// }
+// INSTANTIATE_TEST_CASE_P(TestSequence, FooTest, Values(3, 5, 8));
+//
+
+// Range() returns generators providing sequences of values in a range.
+//
+// Synopsis:
+// Range(start, end)
+//   - returns a generator producing a sequence of values {start, start+1,
+//     start+2, ..., }.
+// Range(start, end, step)
+//   - returns a generator producing a sequence of values {start, start+step,
+//     start+step+step, ..., }.
+// Notes:
+//   * The generated sequences never include end. For example, Range(1, 5)
+//     returns a generator producing a sequence {1, 2, 3, 4}. Range(1, 9, 2)
+//     returns a generator producing {1, 3, 5, 7}.
+//   * start and end must have the same type. That type may be any integral or
+//     floating-point type or a user defined type satisfying these conditions:
+//     * It must be assignable (have operator=() defined).
+//     * It must have operator+() (operator+(int-compatible type) for
+//       two-operand version).
+//     * It must have operator<() defined.
+//     Elements in the resulting sequences will also have that type.
+//   * Condition start < end must be satisfied in order for resulting sequences
+//     to contain any elements.
+//
+template <typename T, typename IncrementT>
+internal::ParamGenerator<T> Range(T start, T end, IncrementT step) {
+  return internal::ParamGenerator<T>(
+      new internal::RangeGenerator<T, IncrementT>(start, end, step));
+}
+
+template <typename T>
+internal::ParamGenerator<T> Range(T start, T end) {
+  return Range(start, end, 1);
+}
+
+// ValuesIn() function allows generation of tests with parameters coming from
+// a container.
+//
+// Synopsis:
+// ValuesIn(const T (&array)[N])
+//   - returns a generator producing sequences with elements from
+//     a C-style array.
+// ValuesIn(const Container& container)
+//   - returns a generator producing sequences with elements from
+//     an STL-style container.
+// ValuesIn(Iterator begin, Iterator end)
+//   - returns a generator producing sequences with elements from
+//     a range [begin, end) defined by a pair of STL-style iterators. These
+//     iterators can also be plain C pointers.
+//
+// Please note that ValuesIn copies the values from the containers
+// passed in and keeps them to generate tests in RUN_ALL_TESTS().
+//
+// Examples:
+//
+// This instantiates tests from test case StringTest
+// each with C-string values of "foo", "bar", and "baz":
+//
+// const char* strings[] = {"foo", "bar", "baz"};
+// INSTANTIATE_TEST_CASE_P(StringSequence, SrtingTest, ValuesIn(strings));
+//
+// This instantiates tests from test case StlStringTest
+// each with STL strings with values "a" and "b":
+//
+// ::std::vector< ::std::string> GetParameterStrings() {
+//   ::std::vector< ::std::string> v;
+//   v.push_back("a");
+//   v.push_back("b");
+//   return v;
+// }
+//
+// INSTANTIATE_TEST_CASE_P(CharSequence,
+//                         StlStringTest,
+//                         ValuesIn(GetParameterStrings()));
+//
+//
+// This will also instantiate tests from CharTest
+// each with parameter values 'a' and 'b':
+//
+// ::std::list<char> GetParameterChars() {
+//   ::std::list<char> list;
+//   list.push_back('a');
+//   list.push_back('b');
+//   return list;
+// }
+// ::std::list<char> l = GetParameterChars();
+// INSTANTIATE_TEST_CASE_P(CharSequence2,
+//                         CharTest,
+//                         ValuesIn(l.begin(), l.end()));
+//
+template <typename ForwardIterator>
+internal::ParamGenerator<
+  typename ::testing::internal::IteratorTraits<ForwardIterator>::value_type>
+ValuesIn(ForwardIterator begin, ForwardIterator end) {
+  typedef typename ::testing::internal::IteratorTraits<ForwardIterator>
+      ::value_type ParamType;
+  return internal::ParamGenerator<ParamType>(
+      new internal::ValuesInIteratorRangeGenerator<ParamType>(begin, end));
+}
+
+template <typename T, size_t N>
+internal::ParamGenerator<T> ValuesIn(const T (&array)[N]) {
+  return ValuesIn(array, array + N);
+}
+
+template <class Container>
+internal::ParamGenerator<typename Container::value_type> ValuesIn(
+    const Container& container) {
+  return ValuesIn(container.begin(), container.end());
+}
+
+// Values() allows generating tests from explicitly specified list of
+// parameters.
+//
+// Synopsis:
+// Values(T v1, T v2, ..., T vN)
+//   - returns a generator producing sequences with elements v1, v2, ..., vN.
+//
+// For example, this instantiates tests from test case BarTest each
+// with values "one", "two", and "three":
+//
+// INSTANTIATE_TEST_CASE_P(NumSequence, BarTest, Values("one", "two", "three"));
+//
+// This instantiates tests from test case BazTest each with values 1, 2, 3.5.
+// The exact type of values will depend on the type of parameter in BazTest.
+//
+// INSTANTIATE_TEST_CASE_P(FloatingNumbers, BazTest, Values(1, 2, 3.5));
+//
+// Currently, Values() supports from 1 to $n parameters.
+//
+$range i 1..n
+$for i [[
+$range j 1..i
+
+template <$for j, [[typename T$j]]>
+internal::ValueArray$i<$for j, [[T$j]]> Values($for j, [[T$j v$j]]) {
+  return internal::ValueArray$i<$for j, [[T$j]]>($for j, [[v$j]]);
+}
+
+]]
+
+// Bool() allows generating tests with parameters in a set of (false, true).
+//
+// Synopsis:
+// Bool()
+//   - returns a generator producing sequences with elements {false, true}.
+//
+// It is useful when testing code that depends on Boolean flags. Combinations
+// of multiple flags can be tested when several Bool()'s are combined using
+// Combine() function.
+//
+// In the following example all tests in the test case FlagDependentTest
+// will be instantiated twice with parameters false and true.
+//
+// class FlagDependentTest : public testing::TestWithParam<bool> {
+//   virtual void SetUp() {
+//     external_flag = GetParam();
+//   }
+// }
+// INSTANTIATE_TEST_CASE_P(BoolSequence, FlagDependentTest, Bool());
+//
+inline internal::ParamGenerator<bool> Bool() {
+  return Values(false, true);
+}
+
+# if GTEST_HAS_COMBINE
+// Combine() allows the user to combine two or more sequences to produce
+// values of a Cartesian product of those sequences' elements.
+//
+// Synopsis:
+// Combine(gen1, gen2, ..., genN)
+//   - returns a generator producing sequences with elements coming from
+//     the Cartesian product of elements from the sequences generated by
+//     gen1, gen2, ..., genN. The sequence elements will have a type of
+//     tuple<T1, T2, ..., TN> where T1, T2, ..., TN are the types
+//     of elements from sequences produces by gen1, gen2, ..., genN.
+//
+// Combine can have up to $maxtuple arguments. This number is currently limited
+// by the maximum number of elements in the tuple implementation used by Google
+// Test.
+//
+// Example:
+//
+// This will instantiate tests in test case AnimalTest each one with
+// the parameter values tuple("cat", BLACK), tuple("cat", WHITE),
+// tuple("dog", BLACK), and tuple("dog", WHITE):
+//
+// enum Color { BLACK, GRAY, WHITE };
+// class AnimalTest
+//     : public testing::TestWithParam<tuple<const char*, Color> > {...};
+//
+// TEST_P(AnimalTest, AnimalLooksNice) {...}
+//
+// INSTANTIATE_TEST_CASE_P(AnimalVariations, AnimalTest,
+//                         Combine(Values("cat", "dog"),
+//                                 Values(BLACK, WHITE)));
+//
+// This will instantiate tests in FlagDependentTest with all variations of two
+// Boolean flags:
+//
+// class FlagDependentTest
+//     : public testing::TestWithParam<tuple<bool, bool> > {
+//   virtual void SetUp() {
+//     // Assigns external_flag_1 and external_flag_2 values from the tuple.
+//     tie(external_flag_1, external_flag_2) = GetParam();
+//   }
+// };
+//
+// TEST_P(FlagDependentTest, TestFeature1) {
+//   // Test your code using external_flag_1 and external_flag_2 here.
+// }
+// INSTANTIATE_TEST_CASE_P(TwoBoolSequence, FlagDependentTest,
+//                         Combine(Bool(), Bool()));
+//
+$range i 2..maxtuple
+$for i [[
+$range j 1..i
+
+template <$for j, [[typename Generator$j]]>
+internal::CartesianProductHolder$i<$for j, [[Generator$j]]> Combine(
+    $for j, [[const Generator$j& g$j]]) {
+  return internal::CartesianProductHolder$i<$for j, [[Generator$j]]>(
+      $for j, [[g$j]]);
+}
+
+]]
+# endif  // GTEST_HAS_COMBINE
+
+
+
+# define TEST_P(test_case_name, test_name) \
+  class GTEST_TEST_CLASS_NAME_(test_case_name, test_name) \
+      : public test_case_name { \
+   public: \
+    GTEST_TEST_CLASS_NAME_(test_case_name, test_name)() {} \
+    virtual void TestBody(); \
+   private: \
+    static int AddToRegistry() { \
+      ::testing::UnitTest::GetInstance()->parameterized_test_registry(). \
+          GetTestCasePatternHolder<test_case_name>(\
+              #test_case_name, __FILE__, __LINE__)->AddTestPattern(\
+                  #test_case_name, \
+                  #test_name, \
+                  new ::testing::internal::TestMetaFactory< \
+                      GTEST_TEST_CLASS_NAME_(test_case_name, test_name)>()); \
+      return 0; \
+    } \
+    static int gtest_registering_dummy_; \
+    GTEST_DISALLOW_COPY_AND_ASSIGN_(\
+        GTEST_TEST_CLASS_NAME_(test_case_name, test_name)); \
+  }; \
+  int GTEST_TEST_CLASS_NAME_(test_case_name, \
+                             test_name)::gtest_registering_dummy_ = \
+      GTEST_TEST_CLASS_NAME_(test_case_name, test_name)::AddToRegistry(); \
+  void GTEST_TEST_CLASS_NAME_(test_case_name, test_name)::TestBody()
+
+# define INSTANTIATE_TEST_CASE_P(prefix, test_case_name, generator) \
+  ::testing::internal::ParamGenerator<test_case_name::ParamType> \
+      gtest_##prefix##test_case_name##_EvalGenerator_() { return generator; } \
+  int gtest_##prefix##test_case_name##_dummy_ = \
+      ::testing::UnitTest::GetInstance()->parameterized_test_registry(). \
+          GetTestCasePatternHolder<test_case_name>(\
+              #test_case_name, __FILE__, __LINE__)->AddTestCaseInstantiation(\
+                  #prefix, \
+                  &gtest_##prefix##test_case_name##_EvalGenerator_, \
+                  __FILE__, __LINE__)
+
+}  // namespace testing
+
+#endif  // GTEST_HAS_PARAM_TEST
+
+#endif  // GTEST_INCLUDE_GTEST_GTEST_PARAM_TEST_H_
diff --git a/test/gtest/include/gtest/gtest-printers.h b/test/gtest/include/gtest/gtest-printers.h
new file mode 100644
index 0000000..bc647b1
--- /dev/null
+++ b/test/gtest/include/gtest/gtest-printers.h
@@ -0,0 +1,858 @@
+// Copyright 2007, Google Inc.
+// All rights reserved.
+//
+// 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: wan at google.com (Zhanyong Wan)
+
+// Google Test - The Google C++ Testing Framework
+//
+// This file implements a universal value printer that can print a
+// value of any type T:
+//
+//   void ::testing::internal::UniversalPrinter<T>::Print(value, ostream_ptr);
+//
+// A user can teach this function how to print a class type T by
+// defining either operator<<() or PrintTo() in the namespace that
+// defines T.  More specifically, the FIRST defined function in the
+// following list will be used (assuming T is defined in namespace
+// foo):
+//
+//   1. foo::PrintTo(const T&, ostream*)
+//   2. operator<<(ostream&, const T&) defined in either foo or the
+//      global namespace.
+//
+// If none of the above is defined, it will print the debug string of
+// the value if it is a protocol buffer, or print the raw bytes in the
+// value otherwise.
+//
+// To aid debugging: when T is a reference type, the address of the
+// value is also printed; when T is a (const) char pointer, both the
+// pointer value and the NUL-terminated string it points to are
+// printed.
+//
+// We also provide some convenient wrappers:
+//
+//   // Prints a value to a string.  For a (const or not) char
+//   // pointer, the NUL-terminated string (but not the pointer) is
+//   // printed.
+//   std::string ::testing::PrintToString(const T& value);
+//
+//   // Prints a value tersely: for a reference type, the referenced
+//   // value (but not the address) is printed; for a (const or not) char
+//   // pointer, the NUL-terminated string (but not the pointer) is
+//   // printed.
+//   void ::testing::internal::UniversalTersePrint(const T& value, ostream*);
+//
+//   // Prints value using the type inferred by the compiler.  The difference
+//   // from UniversalTersePrint() is that this function prints both the
+//   // pointer and the NUL-terminated string for a (const or not) char pointer.
+//   void ::testing::internal::UniversalPrint(const T& value, ostream*);
+//
+//   // Prints the fields of a tuple tersely to a string vector, one
+//   // element for each field. Tuple support must be enabled in
+//   // gtest-port.h.
+//   std::vector<string> UniversalTersePrintTupleFieldsToStrings(
+//       const Tuple& value);
+//
+// Known limitation:
+//
+// The print primitives print the elements of an STL-style container
+// using the compiler-inferred type of *iter where iter is a
+// const_iterator of the container.  When const_iterator is an input
+// iterator but not a forward iterator, this inferred type may not
+// match value_type, and the print output may be incorrect.  In
+// practice, this is rarely a problem as for most containers
+// const_iterator is a forward iterator.  We'll fix this if there's an
+// actual need for it.  Note that this fix cannot rely on value_type
+// being defined as many user-defined container types don't have
+// value_type.
+
+#ifndef GTEST_INCLUDE_GTEST_GTEST_PRINTERS_H_
+#define GTEST_INCLUDE_GTEST_GTEST_PRINTERS_H_
+#ifndef _WIN32
+#pragma GCC system_header
+#endif
+
+#include <ostream>  // NOLINT
+#include <sstream>
+#include <string>
+#include <utility>
+#include <vector>
+#include "gtest/internal/gtest-port.h"
+#include "gtest/internal/gtest-internal.h"
+
+namespace testing {
+
+// Definitions in the 'internal' and 'internal2' name spaces are
+// subject to change without notice.  DO NOT USE THEM IN USER CODE!
+namespace internal2 {
+
+// Prints the given number of bytes in the given object to the given
+// ostream.
+GTEST_API_ void PrintBytesInObjectTo(const unsigned char* obj_bytes,
+                                     size_t count,
+                                     ::std::ostream* os);
+
+// For selecting which printer to use when a given type has neither <<
+// nor PrintTo().
+enum TypeKind {
+  kProtobuf,              // a protobuf type
+  kConvertibleToInteger,  // a type implicitly convertible to BiggestInt
+                          // (e.g. a named or unnamed enum type)
+  kOtherType              // anything else
+};
+
+// TypeWithoutFormatter<T, kTypeKind>::PrintValue(value, os) is called
+// by the universal printer to print a value of type T when neither
+// operator<< nor PrintTo() is defined for T, where kTypeKind is the
+// "kind" of T as defined by enum TypeKind.
+template <typename T, TypeKind kTypeKind>
+class TypeWithoutFormatter {
+ public:
+  // This default version is called when kTypeKind is kOtherType.
+  static void PrintValue(const T& value, ::std::ostream* os) {
+    PrintBytesInObjectTo(reinterpret_cast<const unsigned char*>(&value),
+                         sizeof(value), os);
+  }
+};
+
+// We print a protobuf using its ShortDebugString() when the string
+// doesn't exceed this many characters; otherwise we print it using
+// DebugString() for better readability.
+const size_t kProtobufOneLinerMaxLength = 50;
+
+template <typename T>
+class TypeWithoutFormatter<T, kProtobuf> {
+ public:
+  static void PrintValue(const T& value, ::std::ostream* os) {
+    const ::testing::internal::string short_str = value.ShortDebugString();
+    const ::testing::internal::string pretty_str =
+        short_str.length() <= kProtobufOneLinerMaxLength ?
+        short_str : ("\n" + value.DebugString());
+    *os << ("<" + pretty_str + ">");
+  }
+};
+
+template <typename T>
+class TypeWithoutFormatter<T, kConvertibleToInteger> {
+ public:
+  // Since T has no << operator or PrintTo() but can be implicitly
+  // converted to BiggestInt, we print it as a BiggestInt.
+  //
+  // Most likely T is an enum type (either named or unnamed), in which
+  // case printing it as an integer is the desired behavior.  In case
+  // T is not an enum, printing it as an integer is the best we can do
+  // given that it has no user-defined printer.
+  static void PrintValue(const T& value, ::std::ostream* os) {
+    const internal::BiggestInt kBigInt = value;
+    *os << kBigInt;
+  }
+};
+
+// Prints the given value to the given ostream.  If the value is a
+// protocol message, its debug string is printed; if it's an enum or
+// of a type implicitly convertible to BiggestInt, it's printed as an
+// integer; otherwise the bytes in the value are printed.  This is
+// what UniversalPrinter<T>::Print() does when it knows nothing about
+// type T and T has neither << operator nor PrintTo().
+//
+// A user can override this behavior for a class type Foo by defining
+// a << operator in the namespace where Foo is defined.
+//
+// We put this operator in namespace 'internal2' instead of 'internal'
+// to simplify the implementation, as much code in 'internal' needs to
+// use << in STL, which would conflict with our own << were it defined
+// in 'internal'.
+//
+// Note that this operator<< takes a generic std::basic_ostream<Char,
+// CharTraits> type instead of the more restricted std::ostream.  If
+// we define it to take an std::ostream instead, we'll get an
+// "ambiguous overloads" compiler error when trying to print a type
+// Foo that supports streaming to std::basic_ostream<Char,
+// CharTraits>, as the compiler cannot tell whether
+// operator<<(std::ostream&, const T&) or
+// operator<<(std::basic_stream<Char, CharTraits>, const Foo&) is more
+// specific.
+template <typename Char, typename CharTraits, typename T>
+::std::basic_ostream<Char, CharTraits>& operator<<(
+    ::std::basic_ostream<Char, CharTraits>& os, const T& x) {
+  TypeWithoutFormatter<T,
+      (internal::IsAProtocolMessage<T>::value ? kProtobuf :
+       internal::ImplicitlyConvertible<const T&, internal::BiggestInt>::value ?
+       kConvertibleToInteger : kOtherType)>::PrintValue(x, &os);
+  return os;
+}
+
+}  // namespace internal2
+}  // namespace testing
+
+// This namespace MUST NOT BE NESTED IN ::testing, or the name look-up
+// magic needed for implementing UniversalPrinter won't work.
+namespace testing_internal {
+
+// Used to print a value that is not an STL-style container when the
+// user doesn't define PrintTo() for it.
+template <typename T>
+void DefaultPrintNonContainerTo(const T& value, ::std::ostream* os) {
+  // With the following statement, during unqualified name lookup,
+  // testing::internal2::operator<< appears as if it was declared in
+  // the nearest enclosing namespace that contains both
+  // ::testing_internal and ::testing::internal2, i.e. the global
+  // namespace.  For more details, refer to the C++ Standard section
+  // 7.3.4-1 [namespace.udir].  This allows us to fall back onto
+  // testing::internal2::operator<< in case T doesn't come with a <<
+  // operator.
+  //
+  // We cannot write 'using ::testing::internal2::operator<<;', which
+  // gcc 3.3 fails to compile due to a compiler bug.
+  using namespace ::testing::internal2;  // NOLINT
+
+  // Assuming T is defined in namespace foo, in the next statement,
+  // the compiler will consider all of:
+  //
+  //   1. foo::operator<< (thanks to Koenig look-up),
+  //   2. ::operator<< (as the current namespace is enclosed in ::),
+  //   3. testing::internal2::operator<< (thanks to the using statement above).
+  //
+  // The operator<< whose type matches T best will be picked.
+  //
+  // We deliberately allow #2 to be a candidate, as sometimes it's
+  // impossible to define #1 (e.g. when foo is ::std, defining
+  // anything in it is undefined behavior unless you are a compiler
+  // vendor.).
+  *os << value;
+}
+
+}  // namespace testing_internal
+
+namespace testing {
+namespace internal {
+
+// UniversalPrinter<T>::Print(value, ostream_ptr) prints the given
+// value to the given ostream.  The caller must ensure that
+// 'ostream_ptr' is not NULL, or the behavior is undefined.
+//
+// We define UniversalPrinter as a class template (as opposed to a
+// function template), as we need to partially specialize it for
+// reference types, which cannot be done with function templates.
+template <typename T>
+class UniversalPrinter;
+
+template <typename T>
+void UniversalPrint(const T& value, ::std::ostream* os);
+
+// Used to print an STL-style container when the user doesn't define
+// a PrintTo() for it.
+template <typename C>
+void DefaultPrintTo(IsContainer /* dummy */,
+                    false_type /* is not a pointer */,
+                    const C& container, ::std::ostream* os) {
+  const size_t kMaxCount = 32;  // The maximum number of elements to print.
+  *os << '{';
+  size_t count = 0;
+  for (typename C::const_iterator it = container.begin();
+       it != container.end(); ++it, ++count) {
+    if (count > 0) {
+      *os << ',';
+      if (count == kMaxCount) {  // Enough has been printed.
+        *os << " ...";
+        break;
+      }
+    }
+    *os << ' ';
+    // We cannot call PrintTo(*it, os) here as PrintTo() doesn't
+    // handle *it being a native array.
+    internal::UniversalPrint(*it, os);
+  }
+
+  if (count > 0) {
+    *os << ' ';
+  }
+  *os << '}';
+}
+
+// Used to print a pointer that is neither a char pointer nor a member
+// pointer, when the user doesn't define PrintTo() for it.  (A member
+// variable pointer or member function pointer doesn't really point to
+// a location in the address space.  Their representation is
+// implementation-defined.  Therefore they will be printed as raw
+// bytes.)
+template <typename T>
+void DefaultPrintTo(IsNotContainer /* dummy */,
+                    true_type /* is a pointer */,
+                    T* p, ::std::ostream* os) {
+  if (p == NULL) {
+    *os << "NULL";
+  } else {
+    // C++ doesn't allow casting from a function pointer to any object
+    // pointer.
+    //
+    // IsTrue() silences warnings: "Condition is always true",
+    // "unreachable code".
+    if (IsTrue(ImplicitlyConvertible<T*, const void*>::value)) {
+      // T is not a function type.  We just call << to print p,
+      // relying on ADL to pick up user-defined << for their pointer
+      // types, if any.
+      *os << p;
+    } else {
+      // T is a function type, so '*os << p' doesn't do what we want
+      // (it just prints p as bool).  We want to print p as a const
+      // void*.  However, we cannot cast it to const void* directly,
+      // even using reinterpret_cast, as earlier versions of gcc
+      // (e.g. 3.4.5) cannot compile the cast when p is a function
+      // pointer.  Casting to UInt64 first solves the problem.
+      *os << reinterpret_cast<const void*>(
+          reinterpret_cast<internal::UInt64>(p));
+    }
+  }
+}
+
+// Used to print a non-container, non-pointer value when the user
+// doesn't define PrintTo() for it.
+template <typename T>
+void DefaultPrintTo(IsNotContainer /* dummy */,
+                    false_type /* is not a pointer */,
+                    const T& value, ::std::ostream* os) {
+  ::testing_internal::DefaultPrintNonContainerTo(value, os);
+}
+
+// Prints the given value using the << operator if it has one;
+// otherwise prints the bytes in it.  This is what
+// UniversalPrinter<T>::Print() does when PrintTo() is not specialized
+// or overloaded for type T.
+//
+// A user can override this behavior for a class type Foo by defining
+// an overload of PrintTo() in the namespace where Foo is defined.  We
+// give the user this option as sometimes defining a << operator for
+// Foo is not desirable (e.g. the coding style may prevent doing it,
+// or there is already a << operator but it doesn't do what the user
+// wants).
+template <typename T>
+void PrintTo(const T& value, ::std::ostream* os) {
+  // DefaultPrintTo() is overloaded.  The type of its first two
+  // arguments determine which version will be picked.  If T is an
+  // STL-style container, the version for container will be called; if
+  // T is a pointer, the pointer version will be called; otherwise the
+  // generic version will be called.
+  //
+  // Note that we check for container types here, prior to we check
+  // for protocol message types in our operator<<.  The rationale is:
+  //
+  // For protocol messages, we want to give people a chance to
+  // override Google Mock's format by defining a PrintTo() or
+  // operator<<.  For STL containers, other formats can be
+  // incompatible with Google Mock's format for the container
+  // elements; therefore we check for container types here to ensure
+  // that our format is used.
+  //
+  // The second argument of DefaultPrintTo() is needed to bypass a bug
+  // in Symbian's C++ compiler that prevents it from picking the right
+  // overload between:
+  //
+  //   PrintTo(const T& x, ...);
+  //   PrintTo(T* x, ...);
+  DefaultPrintTo(IsContainerTest<T>(0), is_pointer<T>(), value, os);
+}
+
+// The following list of PrintTo() overloads tells
+// UniversalPrinter<T>::Print() how to print standard types (built-in
+// types, strings, plain arrays, and pointers).
+
+// Overloads for various char types.
+GTEST_API_ void PrintTo(unsigned char c, ::std::ostream* os);
+GTEST_API_ void PrintTo(signed char c, ::std::ostream* os);
+inline void PrintTo(char c, ::std::ostream* os) {
+  // When printing a plain char, we always treat it as unsigned.  This
+  // way, the output won't be affected by whether the compiler thinks
+  // char is signed or not.
+  PrintTo(static_cast<unsigned char>(c), os);
+}
+
+// Overloads for other simple built-in types.
+inline void PrintTo(bool x, ::std::ostream* os) {
+  *os << (x ? "true" : "false");
+}
+
+// Overload for wchar_t type.
+// Prints a wchar_t as a symbol if it is printable or as its internal
+// code otherwise and also as its decimal code (except for L'\0').
+// The L'\0' char is printed as "L'\\0'". The decimal code is printed
+// as signed integer when wchar_t is implemented by the compiler
+// as a signed type and is printed as an unsigned integer when wchar_t
+// is implemented as an unsigned type.
+GTEST_API_ void PrintTo(wchar_t wc, ::std::ostream* os);
+
+// Overloads for C strings.
+GTEST_API_ void PrintTo(const char* s, ::std::ostream* os);
+inline void PrintTo(char* s, ::std::ostream* os) {
+  PrintTo(ImplicitCast_<const char*>(s), os);
+}
+
+// signed/unsigned char is often used for representing binary data, so
+// we print pointers to it as void* to be safe.
+inline void PrintTo(const signed char* s, ::std::ostream* os) {
+  PrintTo(ImplicitCast_<const void*>(s), os);
+}
+inline void PrintTo(signed char* s, ::std::ostream* os) {
+  PrintTo(ImplicitCast_<const void*>(s), os);
+}
+inline void PrintTo(const unsigned char* s, ::std::ostream* os) {
+  PrintTo(ImplicitCast_<const void*>(s), os);
+}
+inline void PrintTo(unsigned char* s, ::std::ostream* os) {
+  PrintTo(ImplicitCast_<const void*>(s), os);
+}
+
+// MSVC can be configured to define wchar_t as a typedef of unsigned
+// short.  It defines _NATIVE_WCHAR_T_DEFINED when wchar_t is a native
+// type.  When wchar_t is a typedef, defining an overload for const
+// wchar_t* would cause unsigned short* be printed as a wide string,
+// possibly causing invalid memory accesses.
+#if !defined(_MSC_VER) || defined(_NATIVE_WCHAR_T_DEFINED)
+// Overloads for wide C strings
+GTEST_API_ void PrintTo(const wchar_t* s, ::std::ostream* os);
+inline void PrintTo(wchar_t* s, ::std::ostream* os) {
+  PrintTo(ImplicitCast_<const wchar_t*>(s), os);
+}
+#endif
+
+// Overload for C arrays.  Multi-dimensional arrays are printed
+// properly.
+
+// Prints the given number of elements in an array, without printing
+// the curly braces.
+template <typename T>
+void PrintRawArrayTo(const T a[], size_t count, ::std::ostream* os) {
+  UniversalPrint(a[0], os);
+  for (size_t i = 1; i != count; i++) {
+    *os << ", ";
+    UniversalPrint(a[i], os);
+  }
+}
+
+// Overloads for ::string and ::std::string.
+#if GTEST_HAS_GLOBAL_STRING
+GTEST_API_ void PrintStringTo(const ::string&s, ::std::ostream* os);
+inline void PrintTo(const ::string& s, ::std::ostream* os) {
+  PrintStringTo(s, os);
+}
+#endif  // GTEST_HAS_GLOBAL_STRING
+
+GTEST_API_ void PrintStringTo(const ::std::string&s, ::std::ostream* os);
+inline void PrintTo(const ::std::string& s, ::std::ostream* os) {
+  PrintStringTo(s, os);
+}
+
+// Overloads for ::wstring and ::std::wstring.
+#if GTEST_HAS_GLOBAL_WSTRING
+GTEST_API_ void PrintWideStringTo(const ::wstring&s, ::std::ostream* os);
+inline void PrintTo(const ::wstring& s, ::std::ostream* os) {
+  PrintWideStringTo(s, os);
+}
+#endif  // GTEST_HAS_GLOBAL_WSTRING
+
+#if GTEST_HAS_STD_WSTRING
+GTEST_API_ void PrintWideStringTo(const ::std::wstring&s, ::std::ostream* os);
+inline void PrintTo(const ::std::wstring& s, ::std::ostream* os) {
+  PrintWideStringTo(s, os);
+}
+#endif  // GTEST_HAS_STD_WSTRING
+
+#if GTEST_HAS_TR1_TUPLE
+// Overload for ::std::tr1::tuple.  Needed for printing function arguments,
+// which are packed as tuples.
+
+// Helper function for printing a tuple.  T must be instantiated with
+// a tuple type.
+template <typename T>
+void PrintTupleTo(const T& t, ::std::ostream* os);
+
+// Overloaded PrintTo() for tuples of various arities.  We support
+// tuples of up-to 10 fields.  The following implementation works
+// regardless of whether tr1::tuple is implemented using the
+// non-standard variadic template feature or not.
+
+inline void PrintTo(const ::std::tr1::tuple<>& t, ::std::ostream* os) {
+  PrintTupleTo(t, os);
+}
+
+template <typename T1>
+void PrintTo(const ::std::tr1::tuple<T1>& t, ::std::ostream* os) {
+  PrintTupleTo(t, os);
+}
+
+template <typename T1, typename T2>
+void PrintTo(const ::std::tr1::tuple<T1, T2>& t, ::std::ostream* os) {
+  PrintTupleTo(t, os);
+}
+
+template <typename T1, typename T2, typename T3>
+void PrintTo(const ::std::tr1::tuple<T1, T2, T3>& t, ::std::ostream* os) {
+  PrintTupleTo(t, os);
+}
+
+template <typename T1, typename T2, typename T3, typename T4>
+void PrintTo(const ::std::tr1::tuple<T1, T2, T3, T4>& t, ::std::ostream* os) {
+  PrintTupleTo(t, os);
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5>
+void PrintTo(const ::std::tr1::tuple<T1, T2, T3, T4, T5>& t,
+             ::std::ostream* os) {
+  PrintTupleTo(t, os);
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+          typename T6>
+void PrintTo(const ::std::tr1::tuple<T1, T2, T3, T4, T5, T6>& t,
+             ::std::ostream* os) {
+  PrintTupleTo(t, os);
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+          typename T6, typename T7>
+void PrintTo(const ::std::tr1::tuple<T1, T2, T3, T4, T5, T6, T7>& t,
+             ::std::ostream* os) {
+  PrintTupleTo(t, os);
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+          typename T6, typename T7, typename T8>
+void PrintTo(const ::std::tr1::tuple<T1, T2, T3, T4, T5, T6, T7, T8>& t,
+             ::std::ostream* os) {
+  PrintTupleTo(t, os);
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+          typename T6, typename T7, typename T8, typename T9>
+void PrintTo(const ::std::tr1::tuple<T1, T2, T3, T4, T5, T6, T7, T8, T9>& t,
+             ::std::ostream* os) {
+  PrintTupleTo(t, os);
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+          typename T6, typename T7, typename T8, typename T9, typename T10>
+void PrintTo(
+    const ::std::tr1::tuple<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10>& t,
+    ::std::ostream* os) {
+  PrintTupleTo(t, os);
+}
+#endif  // GTEST_HAS_TR1_TUPLE
+
+// Overload for std::pair.
+template <typename T1, typename T2>
+void PrintTo(const ::std::pair<T1, T2>& value, ::std::ostream* os) {
+  *os << '(';
+  // We cannot use UniversalPrint(value.first, os) here, as T1 may be
+  // a reference type.  The same for printing value.second.
+  UniversalPrinter<T1>::Print(value.first, os);
+  *os << ", ";
+  UniversalPrinter<T2>::Print(value.second, os);
+  *os << ')';
+}
+
+// Implements printing a non-reference type T by letting the compiler
+// pick the right overload of PrintTo() for T.
+template <typename T>
+class UniversalPrinter {
+ public:
+  // MSVC warns about adding const to a function type, so we want to
+  // disable the warning.
+#ifdef _MSC_VER
+# pragma warning(push)          // Saves the current warning state.
+# pragma warning(disable:4180)  // Temporarily disables warning 4180.
+#endif  // _MSC_VER
+
+  // Note: we deliberately don't call this PrintTo(), as that name
+  // conflicts with ::testing::internal::PrintTo in the body of the
+  // function.
+  static void Print(const T& value, ::std::ostream* os) {
+    // By default, ::testing::internal::PrintTo() is used for printing
+    // the value.
+    //
+    // Thanks to Koenig look-up, if T is a class and has its own
+    // PrintTo() function defined in its namespace, that function will
+    // be visible here.  Since it is more specific than the generic ones
+    // in ::testing::internal, it will be picked by the compiler in the
+    // following statement - exactly what we want.
+    PrintTo(value, os);
+  }
+
+#ifdef _MSC_VER
+# pragma warning(pop)           // Restores the warning state.
+#endif  // _MSC_VER
+};
+
+// UniversalPrintArray(begin, len, os) prints an array of 'len'
+// elements, starting at address 'begin'.
+template <typename T>
+void UniversalPrintArray(const T* begin, size_t len, ::std::ostream* os) {
+  if (len == 0) {
+    *os << "{}";
+  } else {
+    *os << "{ ";
+    const size_t kThreshold = 18;
+    const size_t kChunkSize = 8;
+    // If the array has more than kThreshold elements, we'll have to
+    // omit some details by printing only the first and the last
+    // kChunkSize elements.
+    // TODO(wan at google.com): let the user control the threshold using a flag.
+    if (len <= kThreshold) {
+      PrintRawArrayTo(begin, len, os);
+    } else {
+      PrintRawArrayTo(begin, kChunkSize, os);
+      *os << ", ..., ";
+      PrintRawArrayTo(begin + len - kChunkSize, kChunkSize, os);
+    }
+    *os << " }";
+  }
+}
+// This overload prints a (const) char array compactly.
+GTEST_API_ void UniversalPrintArray(
+    const char* begin, size_t len, ::std::ostream* os);
+
+// This overload prints a (const) wchar_t array compactly.
+GTEST_API_ void UniversalPrintArray(
+    const wchar_t* begin, size_t len, ::std::ostream* os);
+
+// Implements printing an array type T[N].
+template <typename T, size_t N>
+class UniversalPrinter<T[N]> {
+ public:
+  // Prints the given array, omitting some elements when there are too
+  // many.
+  static void Print(const T (&a)[N], ::std::ostream* os) {
+    UniversalPrintArray(a, N, os);
+  }
+};
+
+// Implements printing a reference type T&.
+template <typename T>
+class UniversalPrinter<T&> {
+ public:
+  // MSVC warns about adding const to a function type, so we want to
+  // disable the warning.
+#ifdef _MSC_VER
+# pragma warning(push)          // Saves the current warning state.
+# pragma warning(disable:4180)  // Temporarily disables warning 4180.
+#endif  // _MSC_VER
+
+  static void Print(const T& value, ::std::ostream* os) {
+    // Prints the address of the value.  We use reinterpret_cast here
+    // as static_cast doesn't compile when T is a function type.
+    *os << "@" << reinterpret_cast<const void*>(&value) << " ";
+
+    // Then prints the value itself.
+    UniversalPrint(value, os);
+  }
+
+#ifdef _MSC_VER
+# pragma warning(pop)           // Restores the warning state.
+#endif  // _MSC_VER
+};
+
+// Prints a value tersely: for a reference type, the referenced value
+// (but not the address) is printed; for a (const) char pointer, the
+// NUL-terminated string (but not the pointer) is printed.
+
+template <typename T>
+class UniversalTersePrinter {
+ public:
+  static void Print(const T& value, ::std::ostream* os) {
+    UniversalPrint(value, os);
+  }
+};
+template <typename T>
+class UniversalTersePrinter<T&> {
+ public:
+  static void Print(const T& value, ::std::ostream* os) {
+    UniversalPrint(value, os);
+  }
+};
+template <typename T, size_t N>
+class UniversalTersePrinter<T[N]> {
+ public:
+  static void Print(const T (&value)[N], ::std::ostream* os) {
+    UniversalPrinter<T[N]>::Print(value, os);
+  }
+};
+template <>
+class UniversalTersePrinter<const char*> {
+ public:
+  static void Print(const char* str, ::std::ostream* os) {
+    if (str == NULL) {
+      *os << "NULL";
+    } else {
+      UniversalPrint(string(str), os);
+    }
+  }
+};
+template <>
+class UniversalTersePrinter<char*> {
+ public:
+  static void Print(char* str, ::std::ostream* os) {
+    UniversalTersePrinter<const char*>::Print(str, os);
+  }
+};
+
+#if GTEST_HAS_STD_WSTRING
+template <>
+class UniversalTersePrinter<const wchar_t*> {
+ public:
+  static void Print(const wchar_t* str, ::std::ostream* os) {
+    if (str == NULL) {
+      *os << "NULL";
+    } else {
+      UniversalPrint(::std::wstring(str), os);
+    }
+  }
+};
+#endif
+
+template <>
+class UniversalTersePrinter<wchar_t*> {
+ public:
+  static void Print(wchar_t* str, ::std::ostream* os) {
+    UniversalTersePrinter<const wchar_t*>::Print(str, os);
+  }
+};
+
+template <typename T>
+void UniversalTersePrint(const T& value, ::std::ostream* os) {
+  UniversalTersePrinter<T>::Print(value, os);
+}
+
+// Prints a value using the type inferred by the compiler.  The
+// difference between this and UniversalTersePrint() is that for a
+// (const) char pointer, this prints both the pointer and the
+// NUL-terminated string.
+template <typename T>
+void UniversalPrint(const T& value, ::std::ostream* os) {
+  // A workarond for the bug in VC++ 7.1 that prevents us from instantiating
+  // UniversalPrinter with T directly.
+  typedef T T1;
+  UniversalPrinter<T1>::Print(value, os);
+}
+
+#if GTEST_HAS_TR1_TUPLE
+typedef ::std::vector<string> Strings;
+
+// This helper template allows PrintTo() for tuples and
+// UniversalTersePrintTupleFieldsToStrings() to be defined by
+// induction on the number of tuple fields.  The idea is that
+// TuplePrefixPrinter<N>::PrintPrefixTo(t, os) prints the first N
+// fields in tuple t, and can be defined in terms of
+// TuplePrefixPrinter<N - 1>.
+
+// The inductive case.
+template <size_t N>
+struct TuplePrefixPrinter {
+  // Prints the first N fields of a tuple.
+  template <typename Tuple>
+  static void PrintPrefixTo(const Tuple& t, ::std::ostream* os) {
+    TuplePrefixPrinter<N - 1>::PrintPrefixTo(t, os);
+    *os << ", ";
+    UniversalPrinter<typename ::std::tr1::tuple_element<N - 1, Tuple>::type>
+        ::Print(::std::tr1::get<N - 1>(t), os);
+  }
+
+  // Tersely prints the first N fields of a tuple to a string vector,
+  // one element for each field.
+  template <typename Tuple>
+  static void TersePrintPrefixToStrings(const Tuple& t, Strings* strings) {
+    TuplePrefixPrinter<N - 1>::TersePrintPrefixToStrings(t, strings);
+    ::std::stringstream ss;
+    UniversalTersePrint(::std::tr1::get<N - 1>(t), &ss);
+    strings->push_back(ss.str());
+  }
+};
+
+// Base cases.
+template <>
+struct TuplePrefixPrinter<0> {
+  template <typename Tuple>
+  static void PrintPrefixTo(const Tuple&, ::std::ostream*) {}
+
+  template <typename Tuple>
+  static void TersePrintPrefixToStrings(const Tuple&, Strings*) {}
+};
+// We have to specialize the entire TuplePrefixPrinter<> class
+// template here, even though the definition of
+// TersePrintPrefixToStrings() is the same as the generic version, as
+// Embarcadero (formerly CodeGear, formerly Borland) C++ doesn't
+// support specializing a method template of a class template.
+template <>
+struct TuplePrefixPrinter<1> {
+  template <typename Tuple>
+  static void PrintPrefixTo(const Tuple& t, ::std::ostream* os) {
+    UniversalPrinter<typename ::std::tr1::tuple_element<0, Tuple>::type>::
+        Print(::std::tr1::get<0>(t), os);
+  }
+
+  template <typename Tuple>
+  static void TersePrintPrefixToStrings(const Tuple& t, Strings* strings) {
+    ::std::stringstream ss;
+    UniversalTersePrint(::std::tr1::get<0>(t), &ss);
+    strings->push_back(ss.str());
+  }
+};
+
+// Helper function for printing a tuple.  T must be instantiated with
+// a tuple type.
+template <typename T>
+void PrintTupleTo(const T& t, ::std::ostream* os) {
+  *os << "(";
+  TuplePrefixPrinter< ::std::tr1::tuple_size<T>::value>::
+      PrintPrefixTo(t, os);
+  *os << ")";
+}
+
+// Prints the fields of a tuple tersely to a string vector, one
+// element for each field.  See the comment before
+// UniversalTersePrint() for how we define "tersely".
+template <typename Tuple>
+Strings UniversalTersePrintTupleFieldsToStrings(const Tuple& value) {
+  Strings result;
+  TuplePrefixPrinter< ::std::tr1::tuple_size<Tuple>::value>::
+      TersePrintPrefixToStrings(value, &result);
+  return result;
+}
+#endif  // GTEST_HAS_TR1_TUPLE
+
+}  // namespace internal
+
+template <typename T>
+::std::string PrintToString(const T& value) {
+  ::std::stringstream ss;
+  internal::UniversalTersePrinter<T>::Print(value, &ss);
+  return ss.str();
+}
+
+}  // namespace testing
+
+#endif  // GTEST_INCLUDE_GTEST_GTEST_PRINTERS_H_
diff --git a/test/gtest/include/gtest/gtest-spi.h b/test/gtest/include/gtest/gtest-spi.h
new file mode 100644
index 0000000..f63fa9a
--- /dev/null
+++ b/test/gtest/include/gtest/gtest-spi.h
@@ -0,0 +1,232 @@
+// Copyright 2007, Google Inc.
+// All rights reserved.
+//
+// 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: wan at google.com (Zhanyong Wan)
+//
+// Utilities for testing Google Test itself and code that uses Google Test
+// (e.g. frameworks built on top of Google Test).
+
+#ifndef GTEST_INCLUDE_GTEST_GTEST_SPI_H_
+#define GTEST_INCLUDE_GTEST_GTEST_SPI_H_
+
+#include "gtest/gtest.h"
+
+namespace testing {
+
+// This helper class can be used to mock out Google Test failure reporting
+// so that we can test Google Test or code that builds on Google Test.
+//
+// An object of this class appends a TestPartResult object to the
+// TestPartResultArray object given in the constructor whenever a Google Test
+// failure is reported. It can either intercept only failures that are
+// generated in the same thread that created this object or it can intercept
+// all generated failures. The scope of this mock object can be controlled with
+// the second argument to the two arguments constructor.
+class GTEST_API_ ScopedFakeTestPartResultReporter
+    : public TestPartResultReporterInterface {
+ public:
+  // The two possible mocking modes of this object.
+  enum InterceptMode {
+    INTERCEPT_ONLY_CURRENT_THREAD,  // Intercepts only thread local failures.
+    INTERCEPT_ALL_THREADS           // Intercepts all failures.
+  };
+
+  // The c'tor sets this object as the test part result reporter used
+  // by Google Test.  The 'result' parameter specifies where to report the
+  // results. This reporter will only catch failures generated in the current
+  // thread. DEPRECATED
+  explicit ScopedFakeTestPartResultReporter(TestPartResultArray* result);
+
+  // Same as above, but you can choose the interception scope of this object.
+  ScopedFakeTestPartResultReporter(InterceptMode intercept_mode,
+                                   TestPartResultArray* result);
+
+  // The d'tor restores the previous test part result reporter.
+  virtual ~ScopedFakeTestPartResultReporter();
+
+  // Appends the TestPartResult object to the TestPartResultArray
+  // received in the constructor.
+  //
+  // This method is from the TestPartResultReporterInterface
+  // interface.
+  virtual void ReportTestPartResult(const TestPartResult& result);
+ private:
+  void Init();
+
+  const InterceptMode intercept_mode_;
+  TestPartResultReporterInterface* old_reporter_;
+  TestPartResultArray* const result_;
+
+  GTEST_DISALLOW_COPY_AND_ASSIGN_(ScopedFakeTestPartResultReporter);
+};
+
+namespace internal {
+
+// A helper class for implementing EXPECT_FATAL_FAILURE() and
+// EXPECT_NONFATAL_FAILURE().  Its destructor verifies that the given
+// TestPartResultArray contains exactly one failure that has the given
+// type and contains the given substring.  If that's not the case, a
+// non-fatal failure will be generated.
+class GTEST_API_ SingleFailureChecker {
+ public:
+  // The constructor remembers the arguments.
+  SingleFailureChecker(const TestPartResultArray* results,
+                       TestPartResult::Type type,
+                       const string& substr);
+  ~SingleFailureChecker();
+ private:
+  const TestPartResultArray* const results_;
+  const TestPartResult::Type type_;
+  const string substr_;
+
+  GTEST_DISALLOW_COPY_AND_ASSIGN_(SingleFailureChecker);
+};
+
+}  // namespace internal
+
+}  // namespace testing
+
+// A set of macros for testing Google Test assertions or code that's expected
+// to generate Google Test fatal failures.  It verifies that the given
+// statement will cause exactly one fatal Google Test failure with 'substr'
+// being part of the failure message.
+//
+// There are two different versions of this macro. EXPECT_FATAL_FAILURE only
+// affects and considers failures generated in the current thread and
+// EXPECT_FATAL_FAILURE_ON_ALL_THREADS does the same but for all threads.
+//
+// The verification of the assertion is done correctly even when the statement
+// throws an exception or aborts the current function.
+//
+// Known restrictions:
+//   - 'statement' cannot reference local non-static variables or
+//     non-static members of the current object.
+//   - 'statement' cannot return a value.
+//   - You cannot stream a failure message to this macro.
+//
+// Note that even though the implementations of the following two
+// macros are much alike, we cannot refactor them to use a common
+// helper macro, due to some peculiarity in how the preprocessor
+// works.  The AcceptsMacroThatExpandsToUnprotectedComma test in
+// gtest_unittest.cc will fail to compile if we do that.
+#define EXPECT_FATAL_FAILURE(statement, substr) \
+  do { \
+    class GTestExpectFatalFailureHelper {\
+     public:\
+      static void Execute() { statement; }\
+    };\
+    ::testing::TestPartResultArray gtest_failures;\
+    ::testing::internal::SingleFailureChecker gtest_checker(\
+        &gtest_failures, ::testing::TestPartResult::kFatalFailure, (substr));\
+    {\
+      ::testing::ScopedFakeTestPartResultReporter gtest_reporter(\
+          ::testing::ScopedFakeTestPartResultReporter:: \
+          INTERCEPT_ONLY_CURRENT_THREAD, &gtest_failures);\
+      GTestExpectFatalFailureHelper::Execute();\
+    }\
+  } while (::testing::internal::AlwaysFalse())
+
+#define EXPECT_FATAL_FAILURE_ON_ALL_THREADS(statement, substr) \
+  do { \
+    class GTestExpectFatalFailureHelper {\
+     public:\
+      static void Execute() { statement; }\
+    };\
+    ::testing::TestPartResultArray gtest_failures;\
+    ::testing::internal::SingleFailureChecker gtest_checker(\
+        &gtest_failures, ::testing::TestPartResult::kFatalFailure, (substr));\
+    {\
+      ::testing::ScopedFakeTestPartResultReporter gtest_reporter(\
+          ::testing::ScopedFakeTestPartResultReporter:: \
+          INTERCEPT_ALL_THREADS, &gtest_failures);\
+      GTestExpectFatalFailureHelper::Execute();\
+    }\
+  } while (::testing::internal::AlwaysFalse())
+
+// A macro for testing Google Test assertions or code that's expected to
+// generate Google Test non-fatal failures.  It asserts that the given
+// statement will cause exactly one non-fatal Google Test failure with 'substr'
+// being part of the failure message.
+//
+// There are two different versions of this macro. EXPECT_NONFATAL_FAILURE only
+// affects and considers failures generated in the current thread and
+// EXPECT_NONFATAL_FAILURE_ON_ALL_THREADS does the same but for all threads.
+//
+// 'statement' is allowed to reference local variables and members of
+// the current object.
+//
+// The verification of the assertion is done correctly even when the statement
+// throws an exception or aborts the current function.
+//
+// Known restrictions:
+//   - You cannot stream a failure message to this macro.
+//
+// Note that even though the implementations of the following two
+// macros are much alike, we cannot refactor them to use a common
+// helper macro, due to some peculiarity in how the preprocessor
+// works.  If we do that, the code won't compile when the user gives
+// EXPECT_NONFATAL_FAILURE() a statement that contains a macro that
+// expands to code containing an unprotected comma.  The
+// AcceptsMacroThatExpandsToUnprotectedComma test in gtest_unittest.cc
+// catches that.
+//
+// For the same reason, we have to write
+//   if (::testing::internal::AlwaysTrue()) { statement; }
+// instead of
+//   GTEST_SUPPRESS_UNREACHABLE_CODE_WARNING_BELOW_(statement)
+// to avoid an MSVC warning on unreachable code.
+#define EXPECT_NONFATAL_FAILURE(statement, substr) \
+  do {\
+    ::testing::TestPartResultArray gtest_failures;\
+    ::testing::internal::SingleFailureChecker gtest_checker(\
+        &gtest_failures, ::testing::TestPartResult::kNonFatalFailure, \
+        (substr));\
+    {\
+      ::testing::ScopedFakeTestPartResultReporter gtest_reporter(\
+          ::testing::ScopedFakeTestPartResultReporter:: \
+          INTERCEPT_ONLY_CURRENT_THREAD, &gtest_failures);\
+      if (::testing::internal::AlwaysTrue()) { statement; }\
+    }\
+  } while (::testing::internal::AlwaysFalse())
+
+#define EXPECT_NONFATAL_FAILURE_ON_ALL_THREADS(statement, substr) \
+  do {\
+    ::testing::TestPartResultArray gtest_failures;\
+    ::testing::internal::SingleFailureChecker gtest_checker(\
+        &gtest_failures, ::testing::TestPartResult::kNonFatalFailure, \
+        (substr));\
+    {\
+      ::testing::ScopedFakeTestPartResultReporter gtest_reporter(\
+          ::testing::ScopedFakeTestPartResultReporter::INTERCEPT_ALL_THREADS, \
+          &gtest_failures);\
+      if (::testing::internal::AlwaysTrue()) { statement; }\
+    }\
+  } while (::testing::internal::AlwaysFalse())
+
+#endif  // GTEST_INCLUDE_GTEST_GTEST_SPI_H_
diff --git a/test/gtest/include/gtest/gtest-test-part.h b/test/gtest/include/gtest/gtest-test-part.h
new file mode 100644
index 0000000..77eb844
--- /dev/null
+++ b/test/gtest/include/gtest/gtest-test-part.h
@@ -0,0 +1,179 @@
+// Copyright 2008, Google Inc.
+// All rights reserved.
+//
+// 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: mheule at google.com (Markus Heule)
+//
+
+#ifndef GTEST_INCLUDE_GTEST_GTEST_TEST_PART_H_
+#define GTEST_INCLUDE_GTEST_GTEST_TEST_PART_H_
+
+#include <iosfwd>
+#include <vector>
+#include "gtest/internal/gtest-internal.h"
+#include "gtest/internal/gtest-string.h"
+
+namespace testing {
+
+// A copyable object representing the result of a test part (i.e. an
+// assertion or an explicit FAIL(), ADD_FAILURE(), or SUCCESS()).
+//
+// Don't inherit from TestPartResult as its destructor is not virtual.
+class GTEST_API_ TestPartResult {
+ public:
+  // The possible outcomes of a test part (i.e. an assertion or an
+  // explicit SUCCEED(), FAIL(), or ADD_FAILURE()).
+  enum Type {
+    kSuccess,          // Succeeded.
+    kNonFatalFailure,  // Failed but the test can continue.
+    kFatalFailure      // Failed and the test should be terminated.
+  };
+
+  // C'tor.  TestPartResult does NOT have a default constructor.
+  // Always use this constructor (with parameters) to create a
+  // TestPartResult object.
+  TestPartResult(Type a_type,
+                 const char* a_file_name,
+                 int a_line_number,
+                 const char* a_message)
+      : type_(a_type),
+        file_name_(a_file_name == NULL ? "" : a_file_name),
+        line_number_(a_line_number),
+        summary_(ExtractSummary(a_message)),
+        message_(a_message) {
+  }
+
+  // Gets the outcome of the test part.
+  Type type() const { return type_; }
+
+  // Gets the name of the source file where the test part took place, or
+  // NULL if it's unknown.
+  const char* file_name() const {
+    return file_name_.empty() ? NULL : file_name_.c_str();
+  }
+
+  // Gets the line in the source file where the test part took place,
+  // or -1 if it's unknown.
+  int line_number() const { return line_number_; }
+
+  // Gets the summary of the failure message.
+  const char* summary() const { return summary_.c_str(); }
+
+  // Gets the message associated with the test part.
+  const char* message() const { return message_.c_str(); }
+
+  // Returns true iff the test part passed.
+  bool passed() const { return type_ == kSuccess; }
+
+  // Returns true iff the test part failed.
+  bool failed() const { return type_ != kSuccess; }
+
+  // Returns true iff the test part non-fatally failed.
+  bool nonfatally_failed() const { return type_ == kNonFatalFailure; }
+
+  // Returns true iff the test part fatally failed.
+  bool fatally_failed() const { return type_ == kFatalFailure; }
+
+ private:
+  Type type_;
+
+  // Gets the summary of the failure message by omitting the stack
+  // trace in it.
+  static std::string ExtractSummary(const char* message);
+
+  // The name of the source file where the test part took place, or
+  // "" if the source file is unknown.
+  std::string file_name_;
+  // The line in the source file where the test part took place, or -1
+  // if the line number is unknown.
+  int line_number_;
+  std::string summary_;  // The test failure summary.
+  std::string message_;  // The test failure message.
+};
+
+// Prints a TestPartResult object.
+std::ostream& operator<<(std::ostream& os, const TestPartResult& result);
+
+// An array of TestPartResult objects.
+//
+// Don't inherit from TestPartResultArray as its destructor is not
+// virtual.
+class GTEST_API_ TestPartResultArray {
+ public:
+  TestPartResultArray() {}
+
+  // Appends the given TestPartResult to the array.
+  void Append(const TestPartResult& result);
+
+  // Returns the TestPartResult at the given index (0-based).
+  const TestPartResult& GetTestPartResult(int index) const;
+
+  // Returns the number of TestPartResult objects in the array.
+  int size() const;
+
+ private:
+  std::vector<TestPartResult> array_;
+
+  GTEST_DISALLOW_COPY_AND_ASSIGN_(TestPartResultArray);
+};
+
+// This interface knows how to report a test part result.
+class TestPartResultReporterInterface {
+ public:
+  virtual ~TestPartResultReporterInterface() {}
+
+  virtual void ReportTestPartResult(const TestPartResult& result) = 0;
+};
+
+namespace internal {
+
+// This helper class is used by {ASSERT|EXPECT}_NO_FATAL_FAILURE to check if a
+// statement generates new fatal failures. To do so it registers itself as the
+// current test part result reporter. Besides checking if fatal failures were
+// reported, it only delegates the reporting to the former result reporter.
+// The original result reporter is restored in the destructor.
+// INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM.
+class GTEST_API_ HasNewFatalFailureHelper
+    : public TestPartResultReporterInterface {
+ public:
+  HasNewFatalFailureHelper();
+  virtual ~HasNewFatalFailureHelper();
+  virtual void ReportTestPartResult(const TestPartResult& result);
+  bool has_new_fatal_failure() const { return has_new_fatal_failure_; }
+ private:
+  bool has_new_fatal_failure_;
+  TestPartResultReporterInterface* original_reporter_;
+
+  GTEST_DISALLOW_COPY_AND_ASSIGN_(HasNewFatalFailureHelper);
+};
+
+}  // namespace internal
+
+}  // namespace testing
+
+#endif  // GTEST_INCLUDE_GTEST_GTEST_TEST_PART_H_
diff --git a/test/gtest/include/gtest/gtest-typed-test.h b/test/gtest/include/gtest/gtest-typed-test.h
new file mode 100644
index 0000000..9e62fdb
--- /dev/null
+++ b/test/gtest/include/gtest/gtest-typed-test.h
@@ -0,0 +1,263 @@
+// Copyright 2008 Google Inc.
+// All Rights Reserved.
+//
+// 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: wan at google.com (Zhanyong Wan)
+
+#ifndef GTEST_INCLUDE_GTEST_GTEST_TYPED_TEST_H_
+#define GTEST_INCLUDE_GTEST_GTEST_TYPED_TEST_H_
+
+#ifndef _WIN32
+#pragma GCC system_header
+#endif
+
+// This header implements typed tests and type-parameterized tests.
+
+// Typed (aka type-driven) tests repeat the same test for types in a
+// list.  You must know which types you want to test with when writing
+// typed tests. Here's how you do it:
+
+#if 0
+
+// First, define a fixture class template.  It should be parameterized
+// by a type.  Remember to derive it from testing::Test.
+template <typename T>
+class FooTest : public testing::Test {
+ public:
+  ...
+  typedef std::list<T> List;
+  static T shared_;
+  T value_;
+};
+
+// Next, associate a list of types with the test case, which will be
+// repeated for each type in the list.  The typedef is necessary for
+// the macro to parse correctly.
+typedef testing::Types<char, int, unsigned int> MyTypes;
+TYPED_TEST_CASE(FooTest, MyTypes);
+
+// If the type list contains only one type, you can write that type
+// directly without Types<...>:
+//   TYPED_TEST_CASE(FooTest, int);
+
+// Then, use TYPED_TEST() instead of TEST_F() to define as many typed
+// tests for this test case as you want.
+TYPED_TEST(FooTest, DoesBlah) {
+  // Inside a test, refer to TypeParam to get the type parameter.
+  // Since we are inside a derived class template, C++ requires use to
+  // visit the members of FooTest via 'this'.
+  TypeParam n = this->value_;
+
+  // To visit static members of the fixture, add the TestFixture::
+  // prefix.
+  n += TestFixture::shared_;
+
+  // To refer to typedefs in the fixture, add the "typename
+  // TestFixture::" prefix.
+  typename TestFixture::List values;
+  values.push_back(n);
+  ...
+}
+
+TYPED_TEST(FooTest, HasPropertyA) { ... }
+
+#endif  // 0
+
+// Type-parameterized tests are abstract test patterns parameterized
+// by a type.  Compared with typed tests, type-parameterized tests
+// allow you to define the test pattern without knowing what the type
+// parameters are.  The defined pattern can be instantiated with
+// different types any number of times, in any number of translation
+// units.
+//
+// If you are designing an interface or concept, you can define a
+// suite of type-parameterized tests to verify properties that any
+// valid implementation of the interface/concept should have.  Then,
+// each implementation can easily instantiate the test suite to verify
+// that it conforms to the requirements, without having to write
+// similar tests repeatedly.  Here's an example:
+
+#if 0
+
+// First, define a fixture class template.  It should be parameterized
+// by a type.  Remember to derive it from testing::Test.
+template <typename T>
+class FooTest : public testing::Test {
+  ...
+};
+
+// Next, declare that you will define a type-parameterized test case
+// (the _P suffix is for "parameterized" or "pattern", whichever you
+// prefer):
+TYPED_TEST_CASE_P(FooTest);
+
+// Then, use TYPED_TEST_P() to define as many type-parameterized tests
+// for this type-parameterized test case as you want.
+TYPED_TEST_P(FooTest, DoesBlah) {
+  // Inside a test, refer to TypeParam to get the type parameter.
+  TypeParam n = 0;
+  ...
+}
+
+TYPED_TEST_P(FooTest, HasPropertyA) { ... }
+
+// Now the tricky part: you need to register all test patterns before
+// you can instantiate them.  The first argument of the macro is the
+// test case name; the rest are the names of the tests in this test
+// case.
+REGISTER_TYPED_TEST_CASE_P(FooTest,
+                           DoesBlah, HasPropertyA);
+
+// Finally, you are free to instantiate the pattern with the types you
+// want.  If you put the above code in a header file, you can #include
+// it in multiple C++ source files and instantiate it multiple times.
+//
+// To distinguish different instances of the pattern, the first
+// argument to the INSTANTIATE_* macro is a prefix that will be added
+// to the actual test case name.  Remember to pick unique prefixes for
+// different instances.
+typedef testing::Types<char, int, unsigned int> MyTypes;
+INSTANTIATE_TYPED_TEST_CASE_P(My, FooTest, MyTypes);
+
+// If the type list contains only one type, you can write that type
+// directly without Types<...>:
+//   INSTANTIATE_TYPED_TEST_CASE_P(My, FooTest, int);
+
+#endif  // 0
+
+#include "gtest/internal/gtest-port.h"
+#include "gtest/internal/gtest-type-util.h"
+
+// Implements typed tests.
+
+#if GTEST_HAS_TYPED_TEST
+
+// INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE.
+//
+// Expands to the name of the typedef for the type parameters of the
+// given test case.
+# define GTEST_TYPE_PARAMS_(TestCaseName) gtest_type_params_##TestCaseName##_
+
+// The 'Types' template argument below must have spaces around it
+// since some compilers may choke on '>>' when passing a template
+// instance (e.g. Types<int>)
+# define TYPED_TEST_CASE(CaseName, Types) \
+  typedef ::testing::internal::TypeList< Types >::type \
+      GTEST_TYPE_PARAMS_(CaseName)
+
+# define TYPED_TEST(CaseName, TestName) \
+  template <typename gtest_TypeParam_> \
+  class GTEST_TEST_CLASS_NAME_(CaseName, TestName) \
+      : public CaseName<gtest_TypeParam_> { \
+   private: \
+    typedef CaseName<gtest_TypeParam_> TestFixture; \
+    typedef gtest_TypeParam_ TypeParam; \
+    virtual void TestBody(); \
+  }; \
+  bool gtest_##CaseName##_##TestName##_registered_ GTEST_ATTRIBUTE_UNUSED_ = \
+      ::testing::internal::TypeParameterizedTest< \
+          CaseName, \
+          ::testing::internal::TemplateSel< \
+              GTEST_TEST_CLASS_NAME_(CaseName, TestName)>, \
+          GTEST_TYPE_PARAMS_(CaseName)>::Register(\
+              "", #CaseName, #TestName, 0); \
+  template <typename gtest_TypeParam_> \
+  void GTEST_TEST_CLASS_NAME_(CaseName, TestName)<gtest_TypeParam_>::TestBody()
+
+#endif  // GTEST_HAS_TYPED_TEST
+
+// Implements type-parameterized tests.
+
+#if GTEST_HAS_TYPED_TEST_P
+
+// INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE.
+//
+// Expands to the namespace name that the type-parameterized tests for
+// the given type-parameterized test case are defined in.  The exact
+// name of the namespace is subject to change without notice.
+# define GTEST_CASE_NAMESPACE_(TestCaseName) \
+  gtest_case_##TestCaseName##_
+
+// INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE.
+//
+// Expands to the name of the variable used to remember the names of
+// the defined tests in the given test case.
+# define GTEST_TYPED_TEST_CASE_P_STATE_(TestCaseName) \
+  gtest_typed_test_case_p_state_##TestCaseName##_
+
+// INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE DIRECTLY.
+//
+// Expands to the name of the variable used to remember the names of
+// the registered tests in the given test case.
+# define GTEST_REGISTERED_TEST_NAMES_(TestCaseName) \
+  gtest_registered_test_names_##TestCaseName##_
+
+// The variables defined in the type-parameterized test macros are
+// static as typically these macros are used in a .h file that can be
+// #included in multiple translation units linked together.
+# define TYPED_TEST_CASE_P(CaseName) \
+  static ::testing::internal::TypedTestCasePState \
+      GTEST_TYPED_TEST_CASE_P_STATE_(CaseName)
+
+# define TYPED_TEST_P(CaseName, TestName) \
+  namespace GTEST_CASE_NAMESPACE_(CaseName) { \
+  template <typename gtest_TypeParam_> \
+  class TestName : public CaseName<gtest_TypeParam_> { \
+   private: \
+    typedef CaseName<gtest_TypeParam_> TestFixture; \
+    typedef gtest_TypeParam_ TypeParam; \
+    virtual void TestBody(); \
+  }; \
+  static bool gtest_##TestName##_defined_ GTEST_ATTRIBUTE_UNUSED_ = \
+      GTEST_TYPED_TEST_CASE_P_STATE_(CaseName).AddTestName(\
+          __FILE__, __LINE__, #CaseName, #TestName); \
+  } \
+  template <typename gtest_TypeParam_> \
+  void GTEST_CASE_NAMESPACE_(CaseName)::TestName<gtest_TypeParam_>::TestBody()
+
+# define REGISTER_TYPED_TEST_CASE_P(CaseName, ...) \
+  namespace GTEST_CASE_NAMESPACE_(CaseName) { \
+  typedef ::testing::internal::Templates<__VA_ARGS__>::type gtest_AllTests_; \
+  } \
+  static const char* const GTEST_REGISTERED_TEST_NAMES_(CaseName) = \
+      GTEST_TYPED_TEST_CASE_P_STATE_(CaseName).VerifyRegisteredTestNames(\
+          __FILE__, __LINE__, #__VA_ARGS__)
+
+// The 'Types' template argument below must have spaces around it
+// since some compilers may choke on '>>' when passing a template
+// instance (e.g. Types<int>)
+# define INSTANTIATE_TYPED_TEST_CASE_P(Prefix, CaseName, Types) \
+  bool gtest_##Prefix##_##CaseName GTEST_ATTRIBUTE_UNUSED_ = \
+      ::testing::internal::TypeParameterizedTestCase<CaseName, \
+          GTEST_CASE_NAMESPACE_(CaseName)::gtest_AllTests_, \
+          ::testing::internal::TypeList< Types >::type>::Register(\
+              #Prefix, #CaseName, GTEST_REGISTERED_TEST_NAMES_(CaseName))
+
+#endif  // GTEST_HAS_TYPED_TEST_P
+
+#endif  // GTEST_INCLUDE_GTEST_GTEST_TYPED_TEST_H_
diff --git a/test/gtest/include/gtest/gtest.h b/test/gtest/include/gtest/gtest.h
new file mode 100644
index 0000000..6fa0a39
--- /dev/null
+++ b/test/gtest/include/gtest/gtest.h
@@ -0,0 +1,2291 @@
+// Copyright 2005, Google Inc.
+// All rights reserved.
+//
+// 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: wan at google.com (Zhanyong Wan)
+//
+// The Google C++ Testing Framework (Google Test)
+//
+// This header file defines the public API for Google Test.  It should be
+// included by any test program that uses Google Test.
+//
+// IMPORTANT NOTE: Due to limitation of the C++ language, we have to
+// leave some internal implementation details in this header file.
+// They are clearly marked by comments like this:
+//
+//   // INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM.
+//
+// Such code is NOT meant to be used by a user directly, and is subject
+// to CHANGE WITHOUT NOTICE.  Therefore DO NOT DEPEND ON IT in a user
+// program!
+//
+// Acknowledgment: Google Test borrowed the idea of automatic test
+// registration from Barthelemy Dagenais' (barthelemy at prologique.com)
+// easyUnit framework.
+
+#ifndef GTEST_INCLUDE_GTEST_GTEST_H_
+#define GTEST_INCLUDE_GTEST_GTEST_H_
+
+#include <limits>
+#include <ostream>
+#include <vector>
+
+#include "gtest/internal/gtest-internal.h"
+#include "gtest/internal/gtest-string.h"
+#include "gtest/gtest-death-test.h"
+#include "gtest/gtest-message.h"
+#include "gtest/gtest-param-test.h"
+#include "gtest/gtest-printers.h"
+#include "gtest/gtest_prod.h"
+#include "gtest/gtest-test-part.h"
+#include "gtest/gtest-typed-test.h"
+
+// Depending on the platform, different string classes are available.
+// On Linux, in addition to ::std::string, Google also makes use of
+// class ::string, which has the same interface as ::std::string, but
+// has a different implementation.
+//
+// The user can define GTEST_HAS_GLOBAL_STRING to 1 to indicate that
+// ::string is available AND is a distinct type to ::std::string, or
+// define it to 0 to indicate otherwise.
+//
+// If the user's ::std::string and ::string are the same class due to
+// aliasing, he should define GTEST_HAS_GLOBAL_STRING to 0.
+//
+// If the user doesn't define GTEST_HAS_GLOBAL_STRING, it is defined
+// heuristically.
+
+namespace testing {
+
+// Declares the flags.
+
+// This flag temporary enables the disabled tests.
+GTEST_DECLARE_bool_(also_run_disabled_tests);
+
+// This flag brings the debugger on an assertion failure.
+GTEST_DECLARE_bool_(break_on_failure);
+
+// This flag controls whether Google Test catches all test-thrown exceptions
+// and logs them as failures.
+GTEST_DECLARE_bool_(catch_exceptions);
+
+// This flag enables using colors in terminal output. Available values are
+// "yes" to enable colors, "no" (disable colors), or "auto" (the default)
+// to let Google Test decide.
+GTEST_DECLARE_string_(color);
+
+// This flag sets up the filter to select by name using a glob pattern
+// the tests to run. If the filter is not given all tests are executed.
+GTEST_DECLARE_string_(filter);
+
+// This flag causes the Google Test to list tests. None of the tests listed
+// are actually run if the flag is provided.
+GTEST_DECLARE_bool_(list_tests);
+
+// This flag controls whether Google Test emits a detailed XML report to a file
+// in addition to its normal textual output.
+GTEST_DECLARE_string_(output);
+
+// This flags control whether Google Test prints the elapsed time for each
+// test.
+GTEST_DECLARE_bool_(print_time);
+
+// This flag specifies the random number seed.
+GTEST_DECLARE_int32_(random_seed);
+
+// This flag sets how many times the tests are repeated. The default value
+// is 1. If the value is -1 the tests are repeating forever.
+GTEST_DECLARE_int32_(repeat);
+
+// This flag controls whether Google Test includes Google Test internal
+// stack frames in failure stack traces.
+GTEST_DECLARE_bool_(show_internal_stack_frames);
+
+// When this flag is specified, tests' order is randomized on every iteration.
+GTEST_DECLARE_bool_(shuffle);
+
+// This flag specifies the maximum number of stack frames to be
+// printed in a failure message.
+GTEST_DECLARE_int32_(stack_trace_depth);
+
+// When this flag is specified, a failed assertion will throw an
+// exception if exceptions are enabled, or exit the program with a
+// non-zero code otherwise.
+GTEST_DECLARE_bool_(throw_on_failure);
+
+// When this flag is set with a "host:port" string, on supported
+// platforms test results are streamed to the specified port on
+// the specified host machine.
+GTEST_DECLARE_string_(stream_result_to);
+
+// The upper limit for valid stack trace depths.
+const int kMaxStackTraceDepth = 100;
+
+namespace internal {
+
+class AssertHelper;
+class DefaultGlobalTestPartResultReporter;
+class ExecDeathTest;
+class NoExecDeathTest;
+class FinalSuccessChecker;
+class GTestFlagSaver;
+class StreamingListenerTest;
+class TestResultAccessor;
+class TestEventListenersAccessor;
+class TestEventRepeater;
+class UnitTestRecordPropertyTestHelper;
+class WindowsDeathTest;
+class UnitTestImpl* GetUnitTestImpl();
+void ReportFailureInUnknownLocation(TestPartResult::Type result_type,
+                                    const std::string& message);
+
+}  // namespace internal
+
+// The friend relationship of some of these classes is cyclic.
+// If we don't forward declare them the compiler might confuse the classes
+// in friendship clauses with same named classes on the scope.
+class Test;
+class TestCase;
+class TestInfo;
+class UnitTest;
+
+// A class for indicating whether an assertion was successful.  When
+// the assertion wasn't successful, the AssertionResult object
+// remembers a non-empty message that describes how it failed.
+//
+// To create an instance of this class, use one of the factory functions
+// (AssertionSuccess() and AssertionFailure()).
+//
+// This class is useful for two purposes:
+//   1. Defining predicate functions to be used with Boolean test assertions
+//      EXPECT_TRUE/EXPECT_FALSE and their ASSERT_ counterparts
+//   2. Defining predicate-format functions to be
+//      used with predicate assertions (ASSERT_PRED_FORMAT*, etc).
+//
+// For example, if you define IsEven predicate:
+//
+//   testing::AssertionResult IsEven(int n) {
+//     if ((n % 2) == 0)
+//       return testing::AssertionSuccess();
+//     else
+//       return testing::AssertionFailure() << n << " is odd";
+//   }
+//
+// Then the failed expectation EXPECT_TRUE(IsEven(Fib(5)))
+// will print the message
+//
+//   Value of: IsEven(Fib(5))
+//     Actual: false (5 is odd)
+//   Expected: true
+//
+// instead of a more opaque
+//
+//   Value of: IsEven(Fib(5))
+//     Actual: false
+//   Expected: true
+//
+// in case IsEven is a simple Boolean predicate.
+//
+// If you expect your predicate to be reused and want to support informative
+// messages in EXPECT_FALSE and ASSERT_FALSE (negative assertions show up
+// about half as often as positive ones in our tests), supply messages for
+// both success and failure cases:
+//
+//   testing::AssertionResult IsEven(int n) {
+//     if ((n % 2) == 0)
+//       return testing::AssertionSuccess() << n << " is even";
+//     else
+//       return testing::AssertionFailure() << n << " is odd";
+//   }
+//
+// Then a statement EXPECT_FALSE(IsEven(Fib(6))) will print
+//
+//   Value of: IsEven(Fib(6))
+//     Actual: true (8 is even)
+//   Expected: false
+//
+// NB: Predicates that support negative Boolean assertions have reduced
+// performance in positive ones so be careful not to use them in tests
+// that have lots (tens of thousands) of positive Boolean assertions.
+//
+// To use this class with EXPECT_PRED_FORMAT assertions such as:
+//
+//   // Verifies that Foo() returns an even number.
+//   EXPECT_PRED_FORMAT1(IsEven, Foo());
+//
+// you need to define:
+//
+//   testing::AssertionResult IsEven(const char* expr, int n) {
+//     if ((n % 2) == 0)
+//       return testing::AssertionSuccess();
+//     else
+//       return testing::AssertionFailure()
+//         << "Expected: " << expr << " is even\n  Actual: it's " << n;
+//   }
+//
+// If Foo() returns 5, you will see the following message:
+//
+//   Expected: Foo() is even
+//     Actual: it's 5
+//
+class GTEST_API_ AssertionResult {
+ public:
+  // Copy constructor.
+  // Used in EXPECT_TRUE/FALSE(assertion_result).
+  AssertionResult(const AssertionResult& other);
+  // Used in the EXPECT_TRUE/FALSE(bool_expression).
+  explicit AssertionResult(bool success) : success_(success) {}
+
+  // Returns true iff the assertion succeeded.
+  operator bool() const { return success_; }  // NOLINT
+
+  // Returns the assertion's negation. Used with EXPECT/ASSERT_FALSE.
+  AssertionResult operator!() const;
+
+  // Returns the text streamed into this AssertionResult. Test assertions
+  // use it when they fail (i.e., the predicate's outcome doesn't match the
+  // assertion's expectation). When nothing has been streamed into the
+  // object, returns an empty string.
+  const char* message() const {
+    return message_.get() != NULL ?  message_->c_str() : "";
+  }
+  // TODO(vladl at google.com): Remove this after making sure no clients use it.
+  // Deprecated; please use message() instead.
+  const char* failure_message() const { return message(); }
+
+  // Streams a custom failure message into this object.
+  template <typename T> AssertionResult& operator<<(const T& value) {
+    AppendMessage(Message() << value);
+    return *this;
+  }
+
+  // Allows streaming basic output manipulators such as endl or flush into
+  // this object.
+  AssertionResult& operator<<(
+      ::std::ostream& (*basic_manipulator)(::std::ostream& stream)) {
+    AppendMessage(Message() << basic_manipulator);
+    return *this;
+  }
+
+ private:
+  // Appends the contents of message to message_.
+  void AppendMessage(const Message& a_message) {
+    if (message_.get() == NULL)
+      message_.reset(new ::std::string);
+    message_->append(a_message.GetString().c_str());
+  }
+
+  // Stores result of the assertion predicate.
+  bool success_;
+  // Stores the message describing the condition in case the expectation
+  // construct is not satisfied with the predicate's outcome.
+  // Referenced via a pointer to avoid taking too much stack frame space
+  // with test assertions.
+  internal::scoped_ptr< ::std::string> message_;
+
+  GTEST_DISALLOW_ASSIGN_(AssertionResult);
+};
+
+// Makes a successful assertion result.
+GTEST_API_ AssertionResult AssertionSuccess();
+
+// Makes a failed assertion result.
+GTEST_API_ AssertionResult AssertionFailure();
+
+// Makes a failed assertion result with the given failure message.
+// Deprecated; use AssertionFailure() << msg.
+GTEST_API_ AssertionResult AssertionFailure(const Message& msg);
+
+// The abstract class that all tests inherit from.
+//
+// In Google Test, a unit test program contains one or many TestCases, and
+// each TestCase contains one or many Tests.
+//
+// When you define a test using the TEST macro, you don't need to
+// explicitly derive from Test - the TEST macro automatically does
+// this for you.
+//
+// The only time you derive from Test is when defining a test fixture
+// to be used a TEST_F.  For example:
+//
+//   class FooTest : public testing::Test {
+//    protected:
+//     virtual void SetUp() { ... }
+//     virtual void TearDown() { ... }
+//     ...
+//   };
+//
+//   TEST_F(FooTest, Bar) { ... }
+//   TEST_F(FooTest, Baz) { ... }
+//
+// Test is not copyable.
+class GTEST_API_ Test {
+ public:
+  friend class TestInfo;
+
+  // Defines types for pointers to functions that set up and tear down
+  // a test case.
+  typedef internal::SetUpTestCaseFunc SetUpTestCaseFunc;
+  typedef internal::TearDownTestCaseFunc TearDownTestCaseFunc;
+
+  // The d'tor is virtual as we intend to inherit from Test.
+  virtual ~Test();
+
+  // Sets up the stuff shared by all tests in this test case.
+  //
+  // Google Test will call Foo::SetUpTestCase() before running the first
+  // test in test case Foo.  Hence a sub-class can define its own
+  // SetUpTestCase() method to shadow the one defined in the super
+  // class.
+  static void SetUpTestCase() {}
+
+  // Tears down the stuff shared by all tests in this test case.
+  //
+  // Google Test will call Foo::TearDownTestCase() after running the last
+  // test in test case Foo.  Hence a sub-class can define its own
+  // TearDownTestCase() method to shadow the one defined in the super
+  // class.
+  static void TearDownTestCase() {}
+
+  // Returns true iff the current test has a fatal failure.
+  static bool HasFatalFailure();
+
+  // Returns true iff the current test has a non-fatal failure.
+  static bool HasNonfatalFailure();
+
+  // Returns true iff the current test has a (either fatal or
+  // non-fatal) failure.
+  static bool HasFailure() { return HasFatalFailure() || HasNonfatalFailure(); }
+
+  // Logs a property for the current test, test case, or for the entire
+  // invocation of the test program when used outside of the context of a
+  // test case.  Only the last value for a given key is remembered.  These
+  // are public static so they can be called from utility functions that are
+  // not members of the test fixture.  Calls to RecordProperty made during
+  // lifespan of the test (from the moment its constructor starts to the
+  // moment its destructor finishes) will be output in XML as attributes of
+  // the <testcase> element.  Properties recorded from fixture's
+  // SetUpTestCase or TearDownTestCase are logged as attributes of the
+  // corresponding <testsuite> element.  Calls to RecordProperty made in the
+  // global context (before or after invocation of RUN_ALL_TESTS and from
+  // SetUp/TearDown method of Environment objects registered with Google
+  // Test) will be output as attributes of the <testsuites> element.
+  static void RecordProperty(const std::string& key, const std::string& value);
+  static void RecordProperty(const std::string& key, int value);
+
+ protected:
+  // Creates a Test object.
+  Test();
+
+  // Sets up the test fixture.
+  virtual void SetUp();
+
+  // Tears down the test fixture.
+  virtual void TearDown();
+
+ private:
+  // Returns true iff the current test has the same fixture class as
+  // the first test in the current test case.
+  static bool HasSameFixtureClass();
+
+  // Runs the test after the test fixture has been set up.
+  //
+  // A sub-class must implement this to define the test logic.
+  //
+  // DO NOT OVERRIDE THIS FUNCTION DIRECTLY IN A USER PROGRAM.
+  // Instead, use the TEST or TEST_F macro.
+  virtual void TestBody() = 0;
+
+  // Sets up, executes, and tears down the test.
+  void Run();
+
+  // Deletes self.  We deliberately pick an unusual name for this
+  // internal method to avoid clashing with names used in user TESTs.
+  void DeleteSelf_() { delete this; }
+
+  // Uses a GTestFlagSaver to save and restore all Google Test flags.
+  const internal::GTestFlagSaver* const gtest_flag_saver_;
+
+  // Often a user mis-spells SetUp() as Setup() and spends a long time
+  // wondering why it is never called by Google Test.  The declaration of
+  // the following method is solely for catching such an error at
+  // compile time:
+  //
+  //   - The return type is deliberately chosen to be not void, so it
+  //   will be a conflict if a user declares void Setup() in his test
+  //   fixture.
+  //
+  //   - This method is private, so it will be another compiler error
+  //   if a user calls it from his test fixture.
+  //
+  // DO NOT OVERRIDE THIS FUNCTION.
+  //
+  // If you see an error about overriding the following function or
+  // about it being private, you have mis-spelled SetUp() as Setup().
+  struct Setup_should_be_spelled_SetUp {};
+  virtual Setup_should_be_spelled_SetUp* Setup() { return NULL; }
+
+  // We disallow copying Tests.
+  GTEST_DISALLOW_COPY_AND_ASSIGN_(Test);
+};
+
+typedef internal::TimeInMillis TimeInMillis;
+
+// A copyable object representing a user specified test property which can be
+// output as a key/value string pair.
+//
+// Don't inherit from TestProperty as its destructor is not virtual.
+class TestProperty {
+ public:
+  // C'tor.  TestProperty does NOT have a default constructor.
+  // Always use this constructor (with parameters) to create a
+  // TestProperty object.
+  TestProperty(const std::string& a_key, const std::string& a_value) :
+    key_(a_key), value_(a_value) {
+  }
+
+  // Gets the user supplied key.
+  const char* key() const {
+    return key_.c_str();
+  }
+
+  // Gets the user supplied value.
+  const char* value() const {
+    return value_.c_str();
+  }
+
+  // Sets a new value, overriding the one supplied in the constructor.
+  void SetValue(const std::string& new_value) {
+    value_ = new_value;
+  }
+
+ private:
+  // The key supplied by the user.
+  std::string key_;
+  // The value supplied by the user.
+  std::string value_;
+};
+
+// The result of a single Test.  This includes a list of
+// TestPartResults, a list of TestProperties, a count of how many
+// death tests there are in the Test, and how much time it took to run
+// the Test.
+//
+// TestResult is not copyable.
+class GTEST_API_ TestResult {
+ public:
+  // Creates an empty TestResult.
+  TestResult();
+
+  // D'tor.  Do not inherit from TestResult.
+  ~TestResult();
+
+  // Gets the number of all test parts.  This is the sum of the number
+  // of successful test parts and the number of failed test parts.
+  int total_part_count() const;
+
+  // Returns the number of the test properties.
+  int test_property_count() const;
+
+  // Returns true iff the test passed (i.e. no test part failed).
+  bool Passed() const { return !Failed(); }
+
+  // Returns true iff the test failed.
+  bool Failed() const;
+
+  // Returns true iff the test fatally failed.
+  bool HasFatalFailure() const;
+
+  // Returns true iff the test has a non-fatal failure.
+  bool HasNonfatalFailure() const;
+
+  // Returns the elapsed time, in milliseconds.
+  TimeInMillis elapsed_time() const { return elapsed_time_; }
+
+  // Returns the i-th test part result among all the results. i can range
+  // from 0 to test_property_count() - 1. If i is not in that range, aborts
+  // the program.
+  const TestPartResult& GetTestPartResult(int i) const;
+
+  // Returns the i-th test property. i can range from 0 to
+  // test_property_count() - 1. If i is not in that range, aborts the
+  // program.
+  const TestProperty& GetTestProperty(int i) const;
+
+ private:
+  friend class TestInfo;
+  friend class TestCase;
+  friend class UnitTest;
+  friend class internal::DefaultGlobalTestPartResultReporter;
+  friend class internal::ExecDeathTest;
+  friend class internal::TestResultAccessor;
+  friend class internal::UnitTestImpl;
+  friend class internal::WindowsDeathTest;
+
+  // Gets the vector of TestPartResults.
+  const std::vector<TestPartResult>& test_part_results() const {
+    return test_part_results_;
+  }
+
+  // Gets the vector of TestProperties.
+  const std::vector<TestProperty>& test_properties() const {
+    return test_properties_;
+  }
+
+  // Sets the elapsed time.
+  void set_elapsed_time(TimeInMillis elapsed) { elapsed_time_ = elapsed; }
+
+  // Adds a test property to the list. The property is validated and may add
+  // a non-fatal failure if invalid (e.g., if it conflicts with reserved
+  // key names). If a property is already recorded for the same key, the
+  // value will be updated, rather than storing multiple values for the same
+  // key.  xml_element specifies the element for which the property is being
+  // recorded and is used for validation.
+  void RecordProperty(const std::string& xml_element,
+                      const TestProperty& test_property);
+
+  // Adds a failure if the key is a reserved attribute of Google Test
+  // testcase tags.  Returns true if the property is valid.
+  // TODO(russr): Validate attribute names are legal and human readable.
+  static bool ValidateTestProperty(const std::string& xml_element,
+                                   const TestProperty& test_property);
+
+  // Adds a test part result to the list.
+  void AddTestPartResult(const TestPartResult& test_part_result);
+
+  // Returns the death test count.
+  int death_test_count() const { return death_test_count_; }
+
+  // Increments the death test count, returning the new count.
+  int increment_death_test_count() { return ++death_test_count_; }
+
+  // Clears the test part results.
+  void ClearTestPartResults();
+
+  // Clears the object.
+  void Clear();
+
+  // Protects mutable state of the property vector and of owned
+  // properties, whose values may be updated.
+  internal::Mutex test_properites_mutex_;
+
+  // The vector of TestPartResults
+  std::vector<TestPartResult> test_part_results_;
+  // The vector of TestProperties
+  std::vector<TestProperty> test_properties_;
+  // Running count of death tests.
+  int death_test_count_;
+  // The elapsed time, in milliseconds.
+  TimeInMillis elapsed_time_;
+
+  // We disallow copying TestResult.
+  GTEST_DISALLOW_COPY_AND_ASSIGN_(TestResult);
+};  // class TestResult
+
+// A TestInfo object stores the following information about a test:
+//
+//   Test case name
+//   Test name
+//   Whether the test should be run
+//   A function pointer that creates the test object when invoked
+//   Test result
+//
+// The constructor of TestInfo registers itself with the UnitTest
+// singleton such that the RUN_ALL_TESTS() macro knows which tests to
+// run.
+class GTEST_API_ TestInfo {
+ public:
+  // Destructs a TestInfo object.  This function is not virtual, so
+  // don't inherit from TestInfo.
+  ~TestInfo();
+
+  // Returns the test case name.
+  const char* test_case_name() const { return test_case_name_.c_str(); }
+
+  // Returns the test name.
+  const char* name() const { return name_.c_str(); }
+
+  // Returns the name of the parameter type, or NULL if this is not a typed
+  // or a type-parameterized test.
+  const char* type_param() const {
+    if (type_param_.get() != NULL)
+      return type_param_->c_str();
+    return NULL;
+  }
+
+  // Returns the text representation of the value parameter, or NULL if this
+  // is not a value-parameterized test.
+  const char* value_param() const {
+    if (value_param_.get() != NULL)
+      return value_param_->c_str();
+    return NULL;
+  }
+
+  // Returns true if this test should run, that is if the test is not
+  // disabled (or it is disabled but the also_run_disabled_tests flag has
+  // been specified) and its full name matches the user-specified filter.
+  //
+  // Google Test allows the user to filter the tests by their full names.
+  // The full name of a test Bar in test case Foo is defined as
+  // "Foo.Bar".  Only the tests that match the filter will run.
+  //
+  // A filter is a colon-separated list of glob (not regex) patterns,
+  // optionally followed by a '-' and a colon-separated list of
+  // negative patterns (tests to exclude).  A test is run if it
+  // matches one of the positive patterns and does not match any of
+  // the negative patterns.
+  //
+  // For example, *A*:Foo.* is a filter that matches any string that
+  // contains the character 'A' or starts with "Foo.".
+  bool should_run() const { return should_run_; }
+
+  // Returns true iff this test will appear in the XML report.
+  bool is_reportable() const {
+    // For now, the XML report includes all tests matching the filter.
+    // In the future, we may trim tests that are excluded because of
+    // sharding.
+    return matches_filter_;
+  }
+
+  // Returns the result of the test.
+  const TestResult* result() const { return &result_; }
+
+ private:
+#if GTEST_HAS_DEATH_TEST
+  friend class internal::DefaultDeathTestFactory;
+#endif  // GTEST_HAS_DEATH_TEST
+  friend class Test;
+  friend class TestCase;
+  friend class internal::UnitTestImpl;
+  friend class internal::StreamingListenerTest;
+  friend TestInfo* internal::MakeAndRegisterTestInfo(
+      const char* test_case_name,
+      const char* name,
+      const char* type_param,
+      const char* value_param,
+      internal::TypeId fixture_class_id,
+      Test::SetUpTestCaseFunc set_up_tc,
+      Test::TearDownTestCaseFunc tear_down_tc,
+      internal::TestFactoryBase* factory);
+
+  // Constructs a TestInfo object. The newly constructed instance assumes
+  // ownership of the factory object.
+  TestInfo(const std::string& test_case_name,
+           const std::string& name,
+           const char* a_type_param,   // NULL if not a type-parameterized test
+           const char* a_value_param,  // NULL if not a value-parameterized test
+           internal::TypeId fixture_class_id,
+           internal::TestFactoryBase* factory);
+
+  // Increments the number of death tests encountered in this test so
+  // far.
+  int increment_death_test_count() {
+    return result_.increment_death_test_count();
+  }
+
+  // Creates the test object, runs it, records its result, and then
+  // deletes it.
+  void Run();
+
+  static void ClearTestResult(TestInfo* test_info) {
+    test_info->result_.Clear();
+  }
+
+  // These fields are immutable properties of the test.
+  const std::string test_case_name_;     // Test case name
+  const std::string name_;               // Test name
+  // Name of the parameter type, or NULL if this is not a typed or a
+  // type-parameterized test.
+  const internal::scoped_ptr<const ::std::string> type_param_;
+  // Text representation of the value parameter, or NULL if this is not a
+  // value-parameterized test.
+  const internal::scoped_ptr<const ::std::string> value_param_;
+  const internal::TypeId fixture_class_id_;   // ID of the test fixture class
+  bool should_run_;                 // True iff this test should run
+  bool is_disabled_;                // True iff this test is disabled
+  bool matches_filter_;             // True if this test matches the
+                                    // user-specified filter.
+  internal::TestFactoryBase* const factory_;  // The factory that creates
+                                              // the test object
+
+  // This field is mutable and needs to be reset before running the
+  // test for the second time.
+  TestResult result_;
+
+  GTEST_DISALLOW_COPY_AND_ASSIGN_(TestInfo);
+};
+
+// A test case, which consists of a vector of TestInfos.
+//
+// TestCase is not copyable.
+class GTEST_API_ TestCase {
+ public:
+  // Creates a TestCase with the given name.
+  //
+  // TestCase does NOT have a default constructor.  Always use this
+  // constructor to create a TestCase object.
+  //
+  // Arguments:
+  //
+  //   name:         name of the test case
+  //   a_type_param: the name of the test's type parameter, or NULL if
+  //                 this is not a type-parameterized test.
+  //   set_up_tc:    pointer to the function that sets up the test case
+  //   tear_down_tc: pointer to the function that tears down the test case
+  TestCase(const char* name, const char* a_type_param,
+           Test::SetUpTestCaseFunc set_up_tc,
+           Test::TearDownTestCaseFunc tear_down_tc);
+
+  // Destructor of TestCase.
+  virtual ~TestCase();
+
+  // Gets the name of the TestCase.
+  const char* name() const { return name_.c_str(); }
+
+  // Returns the name of the parameter type, or NULL if this is not a
+  // type-parameterized test case.
+  const char* type_param() const {
+    if (type_param_.get() != NULL)
+      return type_param_->c_str();
+    return NULL;
+  }
+
+  // Returns true if any test in this test case should run.
+  bool should_run() const { return should_run_; }
+
+  // Gets the number of successful tests in this test case.
+  int successful_test_count() const;
+
+  // Gets the number of failed tests in this test case.
+  int failed_test_count() const;
+
+  // Gets the number of disabled tests that will be reported in the XML report.
+  int reportable_disabled_test_count() const;
+
+  // Gets the number of disabled tests in this test case.
+  int disabled_test_count() const;
+
+  // Gets the number of tests to be printed in the XML report.
+  int reportable_test_count() const;
+
+  // Get the number of tests in this test case that should run.
+  int test_to_run_count() const;
+
+  // Gets the number of all tests in this test case.
+  int total_test_count() const;
+
+  // Returns true iff the test case passed.
+  bool Passed() const { return !Failed(); }
+
+  // Returns true iff the test case failed.
+  bool Failed() const { return failed_test_count() > 0; }
+
+  // Returns the elapsed time, in milliseconds.
+  TimeInMillis elapsed_time() const { return elapsed_time_; }
+
+  // Returns the i-th test among all the tests. i can range from 0 to
+  // total_test_count() - 1. If i is not in that range, returns NULL.
+  const TestInfo* GetTestInfo(int i) const;
+
+  // Returns the TestResult that holds test properties recorded during
+  // execution of SetUpTestCase and TearDownTestCase.
+  const TestResult& ad_hoc_test_result() const { return ad_hoc_test_result_; }
+
+ private:
+  friend class Test;
+  friend class internal::UnitTestImpl;
+
+  // Gets the (mutable) vector of TestInfos in this TestCase.
+  std::vector<TestInfo*>& test_info_list() { return test_info_list_; }
+
+  // Gets the (immutable) vector of TestInfos in this TestCase.
+  const std::vector<TestInfo*>& test_info_list() const {
+    return test_info_list_;
+  }
+
+  // Returns the i-th test among all the tests. i can range from 0 to
+  // total_test_count() - 1. If i is not in that range, returns NULL.
+  TestInfo* GetMutableTestInfo(int i);
+
+  // Sets the should_run member.
+  void set_should_run(bool should) { should_run_ = should; }
+
+  // Adds a TestInfo to this test case.  Will delete the TestInfo upon
+  // destruction of the TestCase object.
+  void AddTestInfo(TestInfo * test_info);
+
+  // Clears the results of all tests in this test case.
+  void ClearResult();
+
+  // Clears the results of all tests in the given test case.
+  static void ClearTestCaseResult(TestCase* test_case) {
+    test_case->ClearResult();
+  }
+
+  // Runs every test in this TestCase.
+  void Run();
+
+  // Runs SetUpTestCase() for this TestCase.  This wrapper is needed
+  // for catching exceptions thrown from SetUpTestCase().
+  void RunSetUpTestCase() { (*set_up_tc_)(); }
+
+  // Runs TearDownTestCase() for this TestCase.  This wrapper is
+  // needed for catching exceptions thrown from TearDownTestCase().
+  void RunTearDownTestCase() { (*tear_down_tc_)(); }
+
+  // Returns true iff test passed.
+  static bool TestPassed(const TestInfo* test_info) {
+    return test_info->should_run() && test_info->result()->Passed();
+  }
+
+  // Returns true iff test failed.
+  static bool TestFailed(const TestInfo* test_info) {
+    return test_info->should_run() && test_info->result()->Failed();
+  }
+
+  // Returns true iff the test is disabled and will be reported in the XML
+  // report.
+  static bool TestReportableDisabled(const TestInfo* test_info) {
+    return test_info->is_reportable() && test_info->is_disabled_;
+  }
+
+  // Returns true iff test is disabled.
+  static bool TestDisabled(const TestInfo* test_info) {
+    return test_info->is_disabled_;
+  }
+
+  // Returns true iff this test will appear in the XML report.
+  static bool TestReportable(const TestInfo* test_info) {
+    return test_info->is_reportable();
+  }
+
+  // Returns true if the given test should run.
+  static bool ShouldRunTest(const TestInfo* test_info) {
+    return test_info->should_run();
+  }
+
+  // Shuffles the tests in this test case.
+  void ShuffleTests(internal::Random* random);
+
+  // Restores the test order to before the first shuffle.
+  void UnshuffleTests();
+
+  // Name of the test case.
+  std::string name_;
+  // Name of the parameter type, or NULL if this is not a typed or a
+  // type-parameterized test.
+  const internal::scoped_ptr<const ::std::string> type_param_;
+  // The vector of TestInfos in their original order.  It owns the
+  // elements in the vector.
+  std::vector<TestInfo*> test_info_list_;
+  // Provides a level of indirection for the test list to allow easy
+  // shuffling and restoring the test order.  The i-th element in this
+  // vector is the index of the i-th test in the shuffled test list.
+  std::vector<int> test_indices_;
+  // Pointer to the function that sets up the test case.
+  Test::SetUpTestCaseFunc set_up_tc_;
+  // Pointer to the function that tears down the test case.
+  Test::TearDownTestCaseFunc tear_down_tc_;
+  // True iff any test in this test case should run.
+  bool should_run_;
+  // Elapsed time, in milliseconds.
+  TimeInMillis elapsed_time_;
+  // Holds test properties recorded during execution of SetUpTestCase and
+  // TearDownTestCase.
+  TestResult ad_hoc_test_result_;
+
+  // We disallow copying TestCases.
+  GTEST_DISALLOW_COPY_AND_ASSIGN_(TestCase);
+};
+
+// An Environment object is capable of setting up and tearing down an
+// environment.  The user should subclass this to define his own
+// environment(s).
+//
+// An Environment object does the set-up and tear-down in virtual
+// methods SetUp() and TearDown() instead of the constructor and the
+// destructor, as:
+//
+//   1. You cannot safely throw from a destructor.  This is a problem
+//      as in some cases Google Test is used where exceptions are enabled, and
+//      we may want to implement ASSERT_* using exceptions where they are
+//      available.
+//   2. You cannot use ASSERT_* directly in a constructor or
+//      destructor.
+class Environment {
+ public:
+  // The d'tor is virtual as we need to subclass Environment.
+  virtual ~Environment() {}
+
+  // Override this to define how to set up the environment.
+  virtual void SetUp() {}
+
+  // Override this to define how to tear down the environment.
+  virtual void TearDown() {}
+ private:
+  // If you see an error about overriding the following function or
+  // about it being private, you have mis-spelled SetUp() as Setup().
+  struct Setup_should_be_spelled_SetUp {};
+  virtual Setup_should_be_spelled_SetUp* Setup() { return NULL; }
+};
+
+// The interface for tracing execution of tests. The methods are organized in
+// the order the corresponding events are fired.
+class TestEventListener {
+ public:
+  virtual ~TestEventListener() {}
+
+  // Fired before any test activity starts.
+  virtual void OnTestProgramStart(const UnitTest& unit_test) = 0;
+
+  // Fired before each iteration of tests starts.  There may be more than
+  // one iteration if GTEST_FLAG(repeat) is set. iteration is the iteration
+  // index, starting from 0.
+  virtual void OnTestIterationStart(const UnitTest& unit_test,
+                                    int iteration) = 0;
+
+  // Fired before environment set-up for each iteration of tests starts.
+  virtual void OnEnvironmentsSetUpStart(const UnitTest& unit_test) = 0;
+
+  // Fired after environment set-up for each iteration of tests ends.
+  virtual void OnEnvironmentsSetUpEnd(const UnitTest& unit_test) = 0;
+
+  // Fired before the test case starts.
+  virtual void OnTestCaseStart(const TestCase& test_case) = 0;
+
+  // Fired before the test starts.
+  virtual void OnTestStart(const TestInfo& test_info) = 0;
+
+  // Fired after a failed assertion or a SUCCEED() invocation.
+  virtual void OnTestPartResult(const TestPartResult& test_part_result) = 0;
+
+  // Fired after the test ends.
+  virtual void OnTestEnd(const TestInfo& test_info) = 0;
+
+  // Fired after the test case ends.
+  virtual void OnTestCaseEnd(const TestCase& test_case) = 0;
+
+  // Fired before environment tear-down for each iteration of tests starts.
+  virtual void OnEnvironmentsTearDownStart(const UnitTest& unit_test) = 0;
+
+  // Fired after environment tear-down for each iteration of tests ends.
+  virtual void OnEnvironmentsTearDownEnd(const UnitTest& unit_test) = 0;
+
+  // Fired after each iteration of tests finishes.
+  virtual void OnTestIterationEnd(const UnitTest& unit_test,
+                                  int iteration) = 0;
+
+  // Fired after all test activities have ended.
+  virtual void OnTestProgramEnd(const UnitTest& unit_test) = 0;
+};
+
+// The convenience class for users who need to override just one or two
+// methods and are not concerned that a possible change to a signature of
+// the methods they override will not be caught during the build.  For
+// comments about each method please see the definition of TestEventListener
+// above.
+class EmptyTestEventListener : public TestEventListener {
+ public:
+  virtual void OnTestProgramStart(const UnitTest& /*unit_test*/) {}
+  virtual void OnTestIterationStart(const UnitTest& /*unit_test*/,
+                                    int /*iteration*/) {}
+  virtual void OnEnvironmentsSetUpStart(const UnitTest& /*unit_test*/) {}
+  virtual void OnEnvironmentsSetUpEnd(const UnitTest& /*unit_test*/) {}
+  virtual void OnTestCaseStart(const TestCase& /*test_case*/) {}
+  virtual void OnTestStart(const TestInfo& /*test_info*/) {}
+  virtual void OnTestPartResult(const TestPartResult& /*test_part_result*/) {}
+  virtual void OnTestEnd(const TestInfo& /*test_info*/) {}
+  virtual void OnTestCaseEnd(const TestCase& /*test_case*/) {}
+  virtual void OnEnvironmentsTearDownStart(const UnitTest& /*unit_test*/) {}
+  virtual void OnEnvironmentsTearDownEnd(const UnitTest& /*unit_test*/) {}
+  virtual void OnTestIterationEnd(const UnitTest& /*unit_test*/,
+                                  int /*iteration*/) {}
+  virtual void OnTestProgramEnd(const UnitTest& /*unit_test*/) {}
+};
+
+// TestEventListeners lets users add listeners to track events in Google Test.
+class GTEST_API_ TestEventListeners {
+ public:
+  TestEventListeners();
+  ~TestEventListeners();
+
+  // Appends an event listener to the end of the list. Google Test assumes
+  // the ownership of the listener (i.e. it will delete the listener when
+  // the test program finishes).
+  void Append(TestEventListener* listener);
+
+  // Removes the given event listener from the list and returns it.  It then
+  // becomes the caller's responsibility to delete the listener. Returns
+  // NULL if the listener is not found in the list.
+  TestEventListener* Release(TestEventListener* listener);
+
+  // Returns the standard listener responsible for the default console
+  // output.  Can be removed from the listeners list to shut down default
+  // console output.  Note that removing this object from the listener list
+  // with Release transfers its ownership to the caller and makes this
+  // function return NULL the next time.
+  TestEventListener* default_result_printer() const {
+    return default_result_printer_;
+  }
+
+  // Returns the standard listener responsible for the default XML output
+  // controlled by the --gtest_output=xml flag.  Can be removed from the
+  // listeners list by users who want to shut down the default XML output
+  // controlled by this flag and substitute it with custom one.  Note that
+  // removing this object from the listener list with Release transfers its
+  // ownership to the caller and makes this function return NULL the next
+  // time.
+  TestEventListener* default_xml_generator() const {
+    return default_xml_generator_;
+  }
+
+ private:
+  friend class TestCase;
+  friend class TestInfo;
+  friend class internal::DefaultGlobalTestPartResultReporter;
+  friend class internal::NoExecDeathTest;
+  friend class internal::TestEventListenersAccessor;
+  friend class internal::UnitTestImpl;
+
+  // Returns repeater that broadcasts the TestEventListener events to all
+  // subscribers.
+  TestEventListener* repeater();
+
+  // Sets the default_result_printer attribute to the provided listener.
+  // The listener is also added to the listener list and previous
+  // default_result_printer is removed from it and deleted. The listener can
+  // also be NULL in which case it will not be added to the list. Does
+  // nothing if the previous and the current listener objects are the same.
+  void SetDefaultResultPrinter(TestEventListener* listener);
+
+  // Sets the default_xml_generator attribute to the provided listener.  The
+  // listener is also added to the listener list and previous
+  // default_xml_generator is removed from it and deleted. The listener can
+  // also be NULL in which case it will not be added to the list. Does
+  // nothing if the previous and the current listener objects are the same.
+  void SetDefaultXmlGenerator(TestEventListener* listener);
+
+  // Controls whether events will be forwarded by the repeater to the
+  // listeners in the list.
+  bool EventForwardingEnabled() const;
+  void SuppressEventForwarding();
+
+  // The actual list of listeners.
+  internal::TestEventRepeater* repeater_;
+  // Listener responsible for the standard result output.
+  TestEventListener* default_result_printer_;
+  // Listener responsible for the creation of the XML output file.
+  TestEventListener* default_xml_generator_;
+
+  // We disallow copying TestEventListeners.
+  GTEST_DISALLOW_COPY_AND_ASSIGN_(TestEventListeners);
+};
+
+// A UnitTest consists of a vector of TestCases.
+//
+// This is a singleton class.  The only instance of UnitTest is
+// created when UnitTest::GetInstance() is first called.  This
+// instance is never deleted.
+//
+// UnitTest is not copyable.
+//
+// This class is thread-safe as long as the methods are called
+// according to their specification.
+class GTEST_API_ UnitTest {
+ public:
+  // Gets the singleton UnitTest object.  The first time this method
+  // is called, a UnitTest object is constructed and returned.
+  // Consecutive calls will return the same object.
+  static UnitTest* GetInstance();
+
+  // Runs all tests in this UnitTest object and prints the result.
+  // Returns 0 if successful, or 1 otherwise.
+  //
+  // This method can only be called from the main thread.
+  //
+  // INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM.
+  int Run() GTEST_MUST_USE_RESULT_;
+
+  // Returns the working directory when the first TEST() or TEST_F()
+  // was executed.  The UnitTest object owns the string.
+  const char* original_working_dir() const;
+
+  // Returns the TestCase object for the test that's currently running,
+  // or NULL if no test is running.
+  const TestCase* current_test_case() const
+      GTEST_LOCK_EXCLUDED_(mutex_);
+
+  // Returns the TestInfo object for the test that's currently running,
+  // or NULL if no test is running.
+  const TestInfo* current_test_info() const
+      GTEST_LOCK_EXCLUDED_(mutex_);
+
+  // Returns the random seed used at the start of the current test run.
+  int random_seed() const;
+
+#if GTEST_HAS_PARAM_TEST
+  // Returns the ParameterizedTestCaseRegistry object used to keep track of
+  // value-parameterized tests and instantiate and register them.
+  //
+  // INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM.
+  internal::ParameterizedTestCaseRegistry& parameterized_test_registry()
+      GTEST_LOCK_EXCLUDED_(mutex_);
+#endif  // GTEST_HAS_PARAM_TEST
+
+  // Gets the number of successful test cases.
+  int successful_test_case_count() const;
+
+  // Gets the number of failed test cases.
+  int failed_test_case_count() const;
+
+  // Gets the number of all test cases.
+  int total_test_case_count() const;
+
+  // Gets the number of all test cases that contain at least one test
+  // that should run.
+  int test_case_to_run_count() const;
+
+  // Gets the number of successful tests.
+  int successful_test_count() const;
+
+  // Gets the number of failed tests.
+  int failed_test_count() const;
+
+  // Gets the number of disabled tests that will be reported in the XML report.
+  int reportable_disabled_test_count() const;
+
+  // Gets the number of disabled tests.
+  int disabled_test_count() const;
+
+  // Gets the number of tests to be printed in the XML report.
+  int reportable_test_count() const;
+
+  // Gets the number of all tests.
+  int total_test_count() const;
+
+  // Gets the number of tests that should run.
+  int test_to_run_count() const;
+
+  // Gets the time of the test program start, in ms from the start of the
+  // UNIX epoch.
+  TimeInMillis start_timestamp() const;
+
+  // Gets the elapsed time, in milliseconds.
+  TimeInMillis elapsed_time() const;
+
+  // Returns true iff the unit test passed (i.e. all test cases passed).
+  bool Passed() const;
+
+  // Returns true iff the unit test failed (i.e. some test case failed
+  // or something outside of all tests failed).
+  bool Failed() const;
+
+  // Gets the i-th test case among all the test cases. i can range from 0 to
+  // total_test_case_count() - 1. If i is not in that range, returns NULL.
+  const TestCase* GetTestCase(int i) const;
+
+  // Returns the TestResult containing information on test failures and
+  // properties logged outside of individual test cases.
+  const TestResult& ad_hoc_test_result() const;
+
+  // Returns the list of event listeners that can be used to track events
+  // inside Google Test.
+  TestEventListeners& listeners();
+
+ private:
+  // Registers and returns a global test environment.  When a test
+  // program is run, all global test environments will be set-up in
+  // the order they were registered.  After all tests in the program
+  // have finished, all global test environments will be torn-down in
+  // the *reverse* order they were registered.
+  //
+  // The UnitTest object takes ownership of the given environment.
+  //
+  // This method can only be called from the main thread.
+  Environment* AddEnvironment(Environment* env);
+
+  // Adds a TestPartResult to the current TestResult object.  All
+  // Google Test assertion macros (e.g. ASSERT_TRUE, EXPECT_EQ, etc)
+  // eventually call this to report their results.  The user code
+  // should use the assertion macros instead of calling this directly.
+  void AddTestPartResult(TestPartResult::Type result_type,
+                         const char* file_name,
+                         int line_number,
+                         const std::string& message,
+                         const std::string& os_stack_trace)
+      GTEST_LOCK_EXCLUDED_(mutex_);
+
+  // Adds a TestProperty to the current TestResult object when invoked from
+  // inside a test, to current TestCase's ad_hoc_test_result_ when invoked
+  // from SetUpTestCase or TearDownTestCase, or to the global property set
+  // when invoked elsewhere.  If the result already contains a property with
+  // the same key, the value will be updated.
+  void RecordProperty(const std::string& key, const std::string& value);
+
+  // Gets the i-th test case among all the test cases. i can range from 0 to
+  // total_test_case_count() - 1. If i is not in that range, returns NULL.
+  TestCase* GetMutableTestCase(int i);
+
+  // Accessors for the implementation object.
+  internal::UnitTestImpl* impl() { return impl_; }
+  const internal::UnitTestImpl* impl() const { return impl_; }
+
+  // These classes and funcions are friends as they need to access private
+  // members of UnitTest.
+  friend class Test;
+  friend class internal::AssertHelper;
+  friend class internal::ScopedTrace;
+  friend class internal::StreamingListenerTest;
+  friend class internal::UnitTestRecordPropertyTestHelper;
+  friend Environment* AddGlobalTestEnvironment(Environment* env);
+  friend internal::UnitTestImpl* internal::GetUnitTestImpl();
+  friend void internal::ReportFailureInUnknownLocation(
+      TestPartResult::Type result_type,
+      const std::string& message);
+
+  // Creates an empty UnitTest.
+  UnitTest();
+
+  // D'tor
+  virtual ~UnitTest();
+
+  // Pushes a trace defined by SCOPED_TRACE() on to the per-thread
+  // Google Test trace stack.
+  void PushGTestTrace(const internal::TraceInfo& trace)
+      GTEST_LOCK_EXCLUDED_(mutex_);
+
+  // Pops a trace from the per-thread Google Test trace stack.
+  void PopGTestTrace()
+      GTEST_LOCK_EXCLUDED_(mutex_);
+
+  // Protects mutable state in *impl_.  This is mutable as some const
+  // methods need to lock it too.
+  mutable internal::Mutex mutex_;
+
+  // Opaque implementation object.  This field is never changed once
+  // the object is constructed.  We don't mark it as const here, as
+  // doing so will cause a warning in the constructor of UnitTest.
+  // Mutable state in *impl_ is protected by mutex_.
+  internal::UnitTestImpl* impl_;
+
+  // We disallow copying UnitTest.
+  GTEST_DISALLOW_COPY_AND_ASSIGN_(UnitTest);
+};
+
+// A convenient wrapper for adding an environment for the test
+// program.
+//
+// You should call this before RUN_ALL_TESTS() is called, probably in
+// main().  If you use gtest_main, you need to call this before main()
+// starts for it to take effect.  For example, you can define a global
+// variable like this:
+//
+//   testing::Environment* const foo_env =
+//       testing::AddGlobalTestEnvironment(new FooEnvironment);
+//
+// However, we strongly recommend you to write your own main() and
+// call AddGlobalTestEnvironment() there, as relying on initialization
+// of global variables makes the code harder to read and may cause
+// problems when you register multiple environments from different
+// translation units and the environments have dependencies among them
+// (remember that the compiler doesn't guarantee the order in which
+// global variables from different translation units are initialized).
+inline Environment* AddGlobalTestEnvironment(Environment* env) {
+  return UnitTest::GetInstance()->AddEnvironment(env);
+}
+
+// Initializes Google Test.  This must be called before calling
+// RUN_ALL_TESTS().  In particular, it parses a command line for the
+// flags that Google Test recognizes.  Whenever a Google Test flag is
+// seen, it is removed from argv, and *argc is decremented.
+//
+// No value is returned.  Instead, the Google Test flag variables are
+// updated.
+//
+// Calling the function for the second time has no user-visible effect.
+GTEST_API_ void InitGoogleTest(int* argc, char** argv);
+
+// This overloaded version can be used in Windows programs compiled in
+// UNICODE mode.
+GTEST_API_ void InitGoogleTest(int* argc, wchar_t** argv);
+
+namespace internal {
+
+// FormatForComparison<ToPrint, OtherOperand>::Format(value) formats a
+// value of type ToPrint that is an operand of a comparison assertion
+// (e.g. ASSERT_EQ).  OtherOperand is the type of the other operand in
+// the comparison, and is used to help determine the best way to
+// format the value.  In particular, when the value is a C string
+// (char pointer) and the other operand is an STL string object, we
+// want to format the C string as a string, since we know it is
+// compared by value with the string object.  If the value is a char
+// pointer but the other operand is not an STL string object, we don't
+// know whether the pointer is supposed to point to a NUL-terminated
+// string, and thus want to print it as a pointer to be safe.
+//
+// INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM.
+
+// The default case.
+template <typename ToPrint, typename OtherOperand>
+class FormatForComparison {
+ public:
+  static ::std::string Format(const ToPrint& value) {
+    return ::testing::PrintToString(value);
+  }
+};
+
+// Array.
+template <typename ToPrint, size_t N, typename OtherOperand>
+class FormatForComparison<ToPrint[N], OtherOperand> {
+ public:
+  static ::std::string Format(const ToPrint* value) {
+    return FormatForComparison<const ToPrint*, OtherOperand>::Format(value);
+  }
+};
+
+// By default, print C string as pointers to be safe, as we don't know
+// whether they actually point to a NUL-terminated string.
+
+#define GTEST_IMPL_FORMAT_C_STRING_AS_POINTER_(CharType)                \
+  template <typename OtherOperand>                                      \
+  class FormatForComparison<CharType*, OtherOperand> {                  \
+   public:                                                              \
+    static ::std::string Format(CharType* value) {                      \
+      return ::testing::PrintToString(static_cast<const void*>(value)); \
+    }                                                                   \
+  }
+
+GTEST_IMPL_FORMAT_C_STRING_AS_POINTER_(char);
+GTEST_IMPL_FORMAT_C_STRING_AS_POINTER_(const char);
+GTEST_IMPL_FORMAT_C_STRING_AS_POINTER_(wchar_t);
+GTEST_IMPL_FORMAT_C_STRING_AS_POINTER_(const wchar_t);
+
+#undef GTEST_IMPL_FORMAT_C_STRING_AS_POINTER_
+
+// If a C string is compared with an STL string object, we know it's meant
+// to point to a NUL-terminated string, and thus can print it as a string.
+
+#define GTEST_IMPL_FORMAT_C_STRING_AS_STRING_(CharType, OtherStringType) \
+  template <>                                                           \
+  class FormatForComparison<CharType*, OtherStringType> {               \
+   public:                                                              \
+    static ::std::string Format(CharType* value) {                      \
+      return ::testing::PrintToString(value);                           \
+    }                                                                   \
+  }
+
+GTEST_IMPL_FORMAT_C_STRING_AS_STRING_(char, ::std::string);
+GTEST_IMPL_FORMAT_C_STRING_AS_STRING_(const char, ::std::string);
+
+#if GTEST_HAS_GLOBAL_STRING
+GTEST_IMPL_FORMAT_C_STRING_AS_STRING_(char, ::string);
+GTEST_IMPL_FORMAT_C_STRING_AS_STRING_(const char, ::string);
+#endif
+
+#if GTEST_HAS_GLOBAL_WSTRING
+GTEST_IMPL_FORMAT_C_STRING_AS_STRING_(wchar_t, ::wstring);
+GTEST_IMPL_FORMAT_C_STRING_AS_STRING_(const wchar_t, ::wstring);
+#endif
+
+#if GTEST_HAS_STD_WSTRING
+GTEST_IMPL_FORMAT_C_STRING_AS_STRING_(wchar_t, ::std::wstring);
+GTEST_IMPL_FORMAT_C_STRING_AS_STRING_(const wchar_t, ::std::wstring);
+#endif
+
+#undef GTEST_IMPL_FORMAT_C_STRING_AS_STRING_
+
+// Formats a comparison assertion (e.g. ASSERT_EQ, EXPECT_LT, and etc)
+// operand to be used in a failure message.  The type (but not value)
+// of the other operand may affect the format.  This allows us to
+// print a char* as a raw pointer when it is compared against another
+// char* or void*, and print it as a C string when it is compared
+// against an std::string object, for example.
+//
+// INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM.
+template <typename T1, typename T2>
+std::string FormatForComparisonFailureMessage(
+    const T1& value, const T2& /* other_operand */) {
+  return FormatForComparison<T1, T2>::Format(value);
+}
+
+// The helper function for {ASSERT|EXPECT}_EQ.
+template <typename T1, typename T2>
+AssertionResult CmpHelperEQ(const char* expected_expression,
+                            const char* actual_expression,
+                            const T1& expected,
+                            const T2& actual) {
+#ifdef _MSC_VER
+# pragma warning(push)          // Saves the current warning state.
+# pragma warning(disable:4389)  // Temporarily disables warning on
+                                // signed/unsigned mismatch.
+#endif
+
+  if (expected == actual) {
+    return AssertionSuccess();
+  }
+
+#ifdef _MSC_VER
+# pragma warning(pop)          // Restores the warning state.
+#endif
+
+  return EqFailure(expected_expression,
+                   actual_expression,
+                   FormatForComparisonFailureMessage(expected, actual),
+                   FormatForComparisonFailureMessage(actual, expected),
+                   false);
+}
+
+// With this overloaded version, we allow anonymous enums to be used
+// in {ASSERT|EXPECT}_EQ when compiled with gcc 4, as anonymous enums
+// can be implicitly cast to BiggestInt.
+GTEST_API_ AssertionResult CmpHelperEQ(const char* expected_expression,
+                                       const char* actual_expression,
+                                       BiggestInt expected,
+                                       BiggestInt actual);
+
+// The helper class for {ASSERT|EXPECT}_EQ.  The template argument
+// lhs_is_null_literal is true iff the first argument to ASSERT_EQ()
+// is a null pointer literal.  The following default implementation is
+// for lhs_is_null_literal being false.
+template <bool lhs_is_null_literal>
+class EqHelper {
+ public:
+  // This templatized version is for the general case.
+  template <typename T1, typename T2>
+  static AssertionResult Compare(const char* expected_expression,
+                                 const char* actual_expression,
+                                 const T1& expected,
+                                 const T2& actual) {
+    return CmpHelperEQ(expected_expression, actual_expression, expected,
+                       actual);
+  }
+
+  // With this overloaded version, we allow anonymous enums to be used
+  // in {ASSERT|EXPECT}_EQ when compiled with gcc 4, as anonymous
+  // enums can be implicitly cast to BiggestInt.
+  //
+  // Even though its body looks the same as the above version, we
+  // cannot merge the two, as it will make anonymous enums unhappy.
+  static AssertionResult Compare(const char* expected_expression,
+                                 const char* actual_expression,
+                                 BiggestInt expected,
+                                 BiggestInt actual) {
+    return CmpHelperEQ(expected_expression, actual_expression, expected,
+                       actual);
+  }
+};
+
+// This specialization is used when the first argument to ASSERT_EQ()
+// is a null pointer literal, like NULL, false, or 0.
+template <>
+class EqHelper<true> {
+ public:
+  // We define two overloaded versions of Compare().  The first
+  // version will be picked when the second argument to ASSERT_EQ() is
+  // NOT a pointer, e.g. ASSERT_EQ(0, AnIntFunction()) or
+  // EXPECT_EQ(false, a_bool).
+  template <typename T1, typename T2>
+  static AssertionResult Compare(
+      const char* expected_expression,
+      const char* actual_expression,
+      const T1& expected,
+      const T2& actual,
+      // The following line prevents this overload from being considered if T2
+      // is not a pointer type.  We need this because ASSERT_EQ(NULL, my_ptr)
+      // expands to Compare("", "", NULL, my_ptr), which requires a conversion
+      // to match the Secret* in the other overload, which would otherwise make
+      // this template match better.
+      typename EnableIf<!is_pointer<T2>::value>::type* = 0) {
+    return CmpHelperEQ(expected_expression, actual_expression, expected,
+                       actual);
+  }
+
+  // This version will be picked when the second argument to ASSERT_EQ() is a
+  // pointer, e.g. ASSERT_EQ(NULL, a_pointer).
+  template <typename T>
+  static AssertionResult Compare(
+      const char* expected_expression,
+      const char* actual_expression,
+      // We used to have a second template parameter instead of Secret*.  That
+      // template parameter would deduce to 'long', making this a better match
+      // than the first overload even without the first overload's EnableIf.
+      // Unfortunately, gcc with -Wconversion-null warns when "passing NULL to
+      // non-pointer argument" (even a deduced integral argument), so the old
+      // implementation caused warnings in user code.
+      Secret* /* expected (NULL) */,
+      T* actual) {
+    // We already know that 'expected' is a null pointer.
+    return CmpHelperEQ(expected_expression, actual_expression,
+                       static_cast<T*>(NULL), actual);
+  }
+};
+
+// A macro for implementing the helper functions needed to implement
+// ASSERT_?? and EXPECT_??.  It is here just to avoid copy-and-paste
+// of similar code.
+//
+// For each templatized helper function, we also define an overloaded
+// version for BiggestInt in order to reduce code bloat and allow
+// anonymous enums to be used with {ASSERT|EXPECT}_?? when compiled
+// with gcc 4.
+//
+// INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM.
+#define GTEST_IMPL_CMP_HELPER_(op_name, op)\
+template <typename T1, typename T2>\
+AssertionResult CmpHelper##op_name(const char* expr1, const char* expr2, \
+                                   const T1& val1, const T2& val2) {\
+  if (val1 op val2) {\
+    return AssertionSuccess();\
+  } else {\
+    return AssertionFailure() \
+        << "Expected: (" << expr1 << ") " #op " (" << expr2\
+        << "), actual: " << FormatForComparisonFailureMessage(val1, val2)\
+        << " vs " << FormatForComparisonFailureMessage(val2, val1);\
+  }\
+}\
+GTEST_API_ AssertionResult CmpHelper##op_name(\
+    const char* expr1, const char* expr2, BiggestInt val1, BiggestInt val2)
+
+// INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM.
+
+// Implements the helper function for {ASSERT|EXPECT}_NE
+GTEST_IMPL_CMP_HELPER_(NE, !=);
+// Implements the helper function for {ASSERT|EXPECT}_LE
+GTEST_IMPL_CMP_HELPER_(LE, <=);
+// Implements the helper function for {ASSERT|EXPECT}_LT
+GTEST_IMPL_CMP_HELPER_(LT, <);
+// Implements the helper function for {ASSERT|EXPECT}_GE
+GTEST_IMPL_CMP_HELPER_(GE, >=);
+// Implements the helper function for {ASSERT|EXPECT}_GT
+GTEST_IMPL_CMP_HELPER_(GT, >);
+
+#undef GTEST_IMPL_CMP_HELPER_
+
+// The helper function for {ASSERT|EXPECT}_STREQ.
+//
+// INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM.
+GTEST_API_ AssertionResult CmpHelperSTREQ(const char* expected_expression,
+                                          const char* actual_expression,
+                                          const char* expected,
+                                          const char* actual);
+
+// The helper function for {ASSERT|EXPECT}_STRCASEEQ.
+//
+// INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM.
+GTEST_API_ AssertionResult CmpHelperSTRCASEEQ(const char* expected_expression,
+                                              const char* actual_expression,
+                                              const char* expected,
+                                              const char* actual);
+
+// The helper function for {ASSERT|EXPECT}_STRNE.
+//
+// INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM.
+GTEST_API_ AssertionResult CmpHelperSTRNE(const char* s1_expression,
+                                          const char* s2_expression,
+                                          const char* s1,
+                                          const char* s2);
+
+// The helper function for {ASSERT|EXPECT}_STRCASENE.
+//
+// INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM.
+GTEST_API_ AssertionResult CmpHelperSTRCASENE(const char* s1_expression,
+                                              const char* s2_expression,
+                                              const char* s1,
+                                              const char* s2);
+
+
+// Helper function for *_STREQ on wide strings.
+//
+// INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM.
+GTEST_API_ AssertionResult CmpHelperSTREQ(const char* expected_expression,
+                                          const char* actual_expression,
+                                          const wchar_t* expected,
+                                          const wchar_t* actual);
+
+// Helper function for *_STRNE on wide strings.
+//
+// INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM.
+GTEST_API_ AssertionResult CmpHelperSTRNE(const char* s1_expression,
+                                          const char* s2_expression,
+                                          const wchar_t* s1,
+                                          const wchar_t* s2);
+
+}  // namespace internal
+
+// IsSubstring() and IsNotSubstring() are intended to be used as the
+// first argument to {EXPECT,ASSERT}_PRED_FORMAT2(), not by
+// themselves.  They check whether needle is a substring of haystack
+// (NULL is considered a substring of itself only), and return an
+// appropriate error message when they fail.
+//
+// The {needle,haystack}_expr arguments are the stringified
+// expressions that generated the two real arguments.
+GTEST_API_ AssertionResult IsSubstring(
+    const char* needle_expr, const char* haystack_expr,
+    const char* needle, const char* haystack);
+GTEST_API_ AssertionResult IsSubstring(
+    const char* needle_expr, const char* haystack_expr,
+    const wchar_t* needle, const wchar_t* haystack);
+GTEST_API_ AssertionResult IsNotSubstring(
+    const char* needle_expr, const char* haystack_expr,
+    const char* needle, const char* haystack);
+GTEST_API_ AssertionResult IsNotSubstring(
+    const char* needle_expr, const char* haystack_expr,
+    const wchar_t* needle, const wchar_t* haystack);
+GTEST_API_ AssertionResult IsSubstring(
+    const char* needle_expr, const char* haystack_expr,
+    const ::std::string& needle, const ::std::string& haystack);
+GTEST_API_ AssertionResult IsNotSubstring(
+    const char* needle_expr, const char* haystack_expr,
+    const ::std::string& needle, const ::std::string& haystack);
+
+#if GTEST_HAS_STD_WSTRING
+GTEST_API_ AssertionResult IsSubstring(
+    const char* needle_expr, const char* haystack_expr,
+    const ::std::wstring& needle, const ::std::wstring& haystack);
+GTEST_API_ AssertionResult IsNotSubstring(
+    const char* needle_expr, const char* haystack_expr,
+    const ::std::wstring& needle, const ::std::wstring& haystack);
+#endif  // GTEST_HAS_STD_WSTRING
+
+namespace internal {
+
+// Helper template function for comparing floating-points.
+//
+// Template parameter:
+//
+//   RawType: the raw floating-point type (either float or double)
+//
+// INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM.
+template <typename RawType>
+AssertionResult CmpHelperFloatingPointEQ(const char* expected_expression,
+                                         const char* actual_expression,
+                                         RawType expected,
+                                         RawType actual) {
+  const FloatingPoint<RawType> lhs(expected), rhs(actual);
+
+  if (lhs.AlmostEquals(rhs)) {
+    return AssertionSuccess();
+  }
+
+  ::std::stringstream expected_ss;
+  expected_ss << std::setprecision(std::numeric_limits<RawType>::digits10 + 2)
+              << expected;
+
+  ::std::stringstream actual_ss;
+  actual_ss << std::setprecision(std::numeric_limits<RawType>::digits10 + 2)
+            << actual;
+
+  return EqFailure(expected_expression,
+                   actual_expression,
+                   StringStreamToString(&expected_ss),
+                   StringStreamToString(&actual_ss),
+                   false);
+}
+
+// Helper function for implementing ASSERT_NEAR.
+//
+// INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM.
+GTEST_API_ AssertionResult DoubleNearPredFormat(const char* expr1,
+                                                const char* expr2,
+                                                const char* abs_error_expr,
+                                                double val1,
+                                                double val2,
+                                                double abs_error);
+
+// INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE.
+// A class that enables one to stream messages to assertion macros
+class GTEST_API_ AssertHelper {
+ public:
+  // Constructor.
+  AssertHelper(TestPartResult::Type type,
+               const char* file,
+               int line,
+               const char* message);
+  ~AssertHelper();
+
+  // Message assignment is a semantic trick to enable assertion
+  // streaming; see the GTEST_MESSAGE_ macro below.
+  void operator=(const Message& message) const;
+
+ private:
+  // We put our data in a struct so that the size of the AssertHelper class can
+  // be as small as possible.  This is important because gcc is incapable of
+  // re-using stack space even for temporary variables, so every EXPECT_EQ
+  // reserves stack space for another AssertHelper.
+  struct AssertHelperData {
+    AssertHelperData(TestPartResult::Type t,
+                     const char* srcfile,
+                     int line_num,
+                     const char* msg)
+        : type(t), file(srcfile), line(line_num), message(msg) { }
+
+    TestPartResult::Type const type;
+    const char* const file;
+    int const line;
+    std::string const message;
+
+   private:
+    GTEST_DISALLOW_COPY_AND_ASSIGN_(AssertHelperData);
+  };
+
+  AssertHelperData* const data_;
+
+  GTEST_DISALLOW_COPY_AND_ASSIGN_(AssertHelper);
+};
+
+}  // namespace internal
+
+#if GTEST_HAS_PARAM_TEST
+// The pure interface class that all value-parameterized tests inherit from.
+// A value-parameterized class must inherit from both ::testing::Test and
+// ::testing::WithParamInterface. In most cases that just means inheriting
+// from ::testing::TestWithParam, but more complicated test hierarchies
+// may need to inherit from Test and WithParamInterface at different levels.
+//
+// This interface has support for accessing the test parameter value via
+// the GetParam() method.
+//
+// Use it with one of the parameter generator defining functions, like Range(),
+// Values(), ValuesIn(), Bool(), and Combine().
+//
+// class FooTest : public ::testing::TestWithParam<int> {
+//  protected:
+//   FooTest() {
+//     // Can use GetParam() here.
+//   }
+//   virtual ~FooTest() {
+//     // Can use GetParam() here.
+//   }
+//   virtual void SetUp() {
+//     // Can use GetParam() here.
+//   }
+//   virtual void TearDown {
+//     // Can use GetParam() here.
+//   }
+// };
+// TEST_P(FooTest, DoesBar) {
+//   // Can use GetParam() method here.
+//   Foo foo;
+//   ASSERT_TRUE(foo.DoesBar(GetParam()));
+// }
+// INSTANTIATE_TEST_CASE_P(OneToTenRange, FooTest, ::testing::Range(1, 10));
+
+template <typename T>
+class WithParamInterface {
+ public:
+  typedef T ParamType;
+  virtual ~WithParamInterface() {}
+
+  // The current parameter value. Is also available in the test fixture's
+  // constructor. This member function is non-static, even though it only
+  // references static data, to reduce the opportunity for incorrect uses
+  // like writing 'WithParamInterface<bool>::GetParam()' for a test that
+  // uses a fixture whose parameter type is int.
+  const ParamType& GetParam() const {
+    GTEST_CHECK_(parameter_ != NULL)
+        << "GetParam() can only be called inside a value-parameterized test "
+        << "-- did you intend to write TEST_P instead of TEST_F?";
+    return *parameter_;
+  }
+
+ private:
+  // Sets parameter value. The caller is responsible for making sure the value
+  // remains alive and unchanged throughout the current test.
+  static void SetParam(const ParamType* parameter) {
+    parameter_ = parameter;
+  }
+
+  // Static value used for accessing parameter during a test lifetime.
+  static const ParamType* parameter_;
+
+  // TestClass must be a subclass of WithParamInterface<T> and Test.
+  template <class TestClass> friend class internal::ParameterizedTestFactory;
+};
+
+template <typename T>
+const T* WithParamInterface<T>::parameter_ = NULL;
+
+// Most value-parameterized classes can ignore the existence of
+// WithParamInterface, and can just inherit from ::testing::TestWithParam.
+
+template <typename T>
+class TestWithParam : public Test, public WithParamInterface<T> {
+};
+
+#endif  // GTEST_HAS_PARAM_TEST
+
+// Macros for indicating success/failure in test code.
+
+// ADD_FAILURE unconditionally adds a failure to the current test.
+// SUCCEED generates a success - it doesn't automatically make the
+// current test successful, as a test is only successful when it has
+// no failure.
+//
+// EXPECT_* verifies that a certain condition is satisfied.  If not,
+// it behaves like ADD_FAILURE.  In particular:
+//
+//   EXPECT_TRUE  verifies that a Boolean condition is true.
+//   EXPECT_FALSE verifies that a Boolean condition is false.
+//
+// FAIL and ASSERT_* are similar to ADD_FAILURE and EXPECT_*, except
+// that they will also abort the current function on failure.  People
+// usually want the fail-fast behavior of FAIL and ASSERT_*, but those
+// writing data-driven tests often find themselves using ADD_FAILURE
+// and EXPECT_* more.
+
+// Generates a nonfatal failure with a generic message.
+#define ADD_FAILURE() GTEST_NONFATAL_FAILURE_("Failed")
+
+// Generates a nonfatal failure at the given source file location with
+// a generic message.
+#define ADD_FAILURE_AT(file, line) \
+  GTEST_MESSAGE_AT_(file, line, "Failed", \
+                    ::testing::TestPartResult::kNonFatalFailure)
+
+// Generates a fatal failure with a generic message.
+#define GTEST_FAIL() GTEST_FATAL_FAILURE_("Failed")
+
+// Define this macro to 1 to omit the definition of FAIL(), which is a
+// generic name and clashes with some other libraries.
+#if !GTEST_DONT_DEFINE_FAIL
+# define FAIL() GTEST_FAIL()
+#endif
+
+// Generates a success with a generic message.
+#define GTEST_SUCCEED() GTEST_SUCCESS_("Succeeded")
+
+// Define this macro to 1 to omit the definition of SUCCEED(), which
+// is a generic name and clashes with some other libraries.
+#if !GTEST_DONT_DEFINE_SUCCEED
+# define SUCCEED() GTEST_SUCCEED()
+#endif
+
+// Macros for testing exceptions.
+//
+//    * {ASSERT|EXPECT}_THROW(statement, expected_exception):
+//         Tests that the statement throws the expected exception.
+//    * {ASSERT|EXPECT}_NO_THROW(statement):
+//         Tests that the statement doesn't throw any exception.
+//    * {ASSERT|EXPECT}_ANY_THROW(statement):
+//         Tests that the statement throws an exception.
+
+#define EXPECT_THROW(statement, expected_exception) \
+  GTEST_TEST_THROW_(statement, expected_exception, GTEST_NONFATAL_FAILURE_)
+#define EXPECT_NO_THROW(statement) \
+  GTEST_TEST_NO_THROW_(statement, GTEST_NONFATAL_FAILURE_)
+#define EXPECT_ANY_THROW(statement) \
+  GTEST_TEST_ANY_THROW_(statement, GTEST_NONFATAL_FAILURE_)
+#define ASSERT_THROW(statement, expected_exception) \
+  GTEST_TEST_THROW_(statement, expected_exception, GTEST_FATAL_FAILURE_)
+#define ASSERT_NO_THROW(statement) \
+  GTEST_TEST_NO_THROW_(statement, GTEST_FATAL_FAILURE_)
+#define ASSERT_ANY_THROW(statement) \
+  GTEST_TEST_ANY_THROW_(statement, GTEST_FATAL_FAILURE_)
+
+// Boolean assertions. Condition can be either a Boolean expression or an
+// AssertionResult. For more information on how to use AssertionResult with
+// these macros see comments on that class.
+#define EXPECT_TRUE(condition) \
+  GTEST_TEST_BOOLEAN_(condition, #condition, false, true, \
+                      GTEST_NONFATAL_FAILURE_)
+#define EXPECT_FALSE(condition) \
+  GTEST_TEST_BOOLEAN_(!(condition), #condition, true, false, \
+                      GTEST_NONFATAL_FAILURE_)
+#define ASSERT_TRUE(condition) \
+  GTEST_TEST_BOOLEAN_(condition, #condition, false, true, \
+                      GTEST_FATAL_FAILURE_)
+#define ASSERT_FALSE(condition) \
+  GTEST_TEST_BOOLEAN_(!(condition), #condition, true, false, \
+                      GTEST_FATAL_FAILURE_)
+
+// Includes the auto-generated header that implements a family of
+// generic predicate assertion macros.
+#include "gtest/gtest_pred_impl.h"
+
+// Macros for testing equalities and inequalities.
+//
+//    * {ASSERT|EXPECT}_EQ(expected, actual): Tests that expected == actual
+//    * {ASSERT|EXPECT}_NE(v1, v2):           Tests that v1 != v2
+//    * {ASSERT|EXPECT}_LT(v1, v2):           Tests that v1 < v2
+//    * {ASSERT|EXPECT}_LE(v1, v2):           Tests that v1 <= v2
+//    * {ASSERT|EXPECT}_GT(v1, v2):           Tests that v1 > v2
+//    * {ASSERT|EXPECT}_GE(v1, v2):           Tests that v1 >= v2
+//
+// When they are not, Google Test prints both the tested expressions and
+// their actual values.  The values must be compatible built-in types,
+// or you will get a compiler error.  By "compatible" we mean that the
+// values can be compared by the respective operator.
+//
+// Note:
+//
+//   1. It is possible to make a user-defined type work with
+//   {ASSERT|EXPECT}_??(), but that requires overloading the
+//   comparison operators and is thus discouraged by the Google C++
+//   Usage Guide.  Therefore, you are advised to use the
+//   {ASSERT|EXPECT}_TRUE() macro to assert that two objects are
+//   equal.
+//
+//   2. The {ASSERT|EXPECT}_??() macros do pointer comparisons on
+//   pointers (in particular, C strings).  Therefore, if you use it
+//   with two C strings, you are testing how their locations in memory
+//   are related, not how their content is related.  To compare two C
+//   strings by content, use {ASSERT|EXPECT}_STR*().
+//
+//   3. {ASSERT|EXPECT}_EQ(expected, actual) is preferred to
+//   {ASSERT|EXPECT}_TRUE(expected == actual), as the former tells you
+//   what the actual value is when it fails, and similarly for the
+//   other comparisons.
+//
+//   4. Do not depend on the order in which {ASSERT|EXPECT}_??()
+//   evaluate their arguments, which is undefined.
+//
+//   5. These macros evaluate their arguments exactly once.
+//
+// Examples:
+//
+//   EXPECT_NE(5, Foo());
+//   EXPECT_EQ(NULL, a_pointer);
+//   ASSERT_LT(i, array_size);
+//   ASSERT_GT(records.size(), 0) << "There is no record left.";
+
+#define EXPECT_EQ(expected, actual) \
+  EXPECT_PRED_FORMAT2(::testing::internal:: \
+                      EqHelper<GTEST_IS_NULL_LITERAL_(expected)>::Compare, \
+                      expected, actual)
+#define EXPECT_NE(expected, actual) \
+  EXPECT_PRED_FORMAT2(::testing::internal::CmpHelperNE, expected, actual)
+#define EXPECT_LE(val1, val2) \
+  EXPECT_PRED_FORMAT2(::testing::internal::CmpHelperLE, val1, val2)
+#define EXPECT_LT(val1, val2) \
+  EXPECT_PRED_FORMAT2(::testing::internal::CmpHelperLT, val1, val2)
+#define EXPECT_GE(val1, val2) \
+  EXPECT_PRED_FORMAT2(::testing::internal::CmpHelperGE, val1, val2)
+#define EXPECT_GT(val1, val2) \
+  EXPECT_PRED_FORMAT2(::testing::internal::CmpHelperGT, val1, val2)
+
+#define GTEST_ASSERT_EQ(expected, actual) \
+  ASSERT_PRED_FORMAT2(::testing::internal:: \
+                      EqHelper<GTEST_IS_NULL_LITERAL_(expected)>::Compare, \
+                      expected, actual)
+#define GTEST_ASSERT_NE(val1, val2) \
+  ASSERT_PRED_FORMAT2(::testing::internal::CmpHelperNE, val1, val2)
+#define GTEST_ASSERT_LE(val1, val2) \
+  ASSERT_PRED_FORMAT2(::testing::internal::CmpHelperLE, val1, val2)
+#define GTEST_ASSERT_LT(val1, val2) \
+  ASSERT_PRED_FORMAT2(::testing::internal::CmpHelperLT, val1, val2)
+#define GTEST_ASSERT_GE(val1, val2) \
+  ASSERT_PRED_FORMAT2(::testing::internal::CmpHelperGE, val1, val2)
+#define GTEST_ASSERT_GT(val1, val2) \
+  ASSERT_PRED_FORMAT2(::testing::internal::CmpHelperGT, val1, val2)
+
+// Define macro GTEST_DONT_DEFINE_ASSERT_XY to 1 to omit the definition of
+// ASSERT_XY(), which clashes with some users' own code.
+
+#if !GTEST_DONT_DEFINE_ASSERT_EQ
+# define ASSERT_EQ(val1, val2) GTEST_ASSERT_EQ(val1, val2)
+#endif
+
+#if !GTEST_DONT_DEFINE_ASSERT_NE
+# define ASSERT_NE(val1, val2) GTEST_ASSERT_NE(val1, val2)
+#endif
+
+#if !GTEST_DONT_DEFINE_ASSERT_LE
+# define ASSERT_LE(val1, val2) GTEST_ASSERT_LE(val1, val2)
+#endif
+
+#if !GTEST_DONT_DEFINE_ASSERT_LT
+# define ASSERT_LT(val1, val2) GTEST_ASSERT_LT(val1, val2)
+#endif
+
+#if !GTEST_DONT_DEFINE_ASSERT_GE
+# define ASSERT_GE(val1, val2) GTEST_ASSERT_GE(val1, val2)
+#endif
+
+#if !GTEST_DONT_DEFINE_ASSERT_GT
+# define ASSERT_GT(val1, val2) GTEST_ASSERT_GT(val1, val2)
+#endif
+
+// C-string Comparisons.  All tests treat NULL and any non-NULL string
+// as different.  Two NULLs are equal.
+//
+//    * {ASSERT|EXPECT}_STREQ(s1, s2):     Tests that s1 == s2
+//    * {ASSERT|EXPECT}_STRNE(s1, s2):     Tests that s1 != s2
+//    * {ASSERT|EXPECT}_STRCASEEQ(s1, s2): Tests that s1 == s2, ignoring case
+//    * {ASSERT|EXPECT}_STRCASENE(s1, s2): Tests that s1 != s2, ignoring case
+//
+// For wide or narrow string objects, you can use the
+// {ASSERT|EXPECT}_??() macros.
+//
+// Don't depend on the order in which the arguments are evaluated,
+// which is undefined.
+//
+// These macros evaluate their arguments exactly once.
+
+#define EXPECT_STREQ(expected, actual) \
+  EXPECT_PRED_FORMAT2(::testing::internal::CmpHelperSTREQ, expected, actual)
+#define EXPECT_STRNE(s1, s2) \
+  EXPECT_PRED_FORMAT2(::testing::internal::CmpHelperSTRNE, s1, s2)
+#define EXPECT_STRCASEEQ(expected, actual) \
+  EXPECT_PRED_FORMAT2(::testing::internal::CmpHelperSTRCASEEQ, expected, actual)
+#define EXPECT_STRCASENE(s1, s2)\
+  EXPECT_PRED_FORMAT2(::testing::internal::CmpHelperSTRCASENE, s1, s2)
+
+#define ASSERT_STREQ(expected, actual) \
+  ASSERT_PRED_FORMAT2(::testing::internal::CmpHelperSTREQ, expected, actual)
+#define ASSERT_STRNE(s1, s2) \
+  ASSERT_PRED_FORMAT2(::testing::internal::CmpHelperSTRNE, s1, s2)
+#define ASSERT_STRCASEEQ(expected, actual) \
+  ASSERT_PRED_FORMAT2(::testing::internal::CmpHelperSTRCASEEQ, expected, actual)
+#define ASSERT_STRCASENE(s1, s2)\
+  ASSERT_PRED_FORMAT2(::testing::internal::CmpHelperSTRCASENE, s1, s2)
+
+// Macros for comparing floating-point numbers.
+//
+//    * {ASSERT|EXPECT}_FLOAT_EQ(expected, actual):
+//         Tests that two float values are almost equal.
+//    * {ASSERT|EXPECT}_DOUBLE_EQ(expected, actual):
+//         Tests that two double values are almost equal.
+//    * {ASSERT|EXPECT}_NEAR(v1, v2, abs_error):
+//         Tests that v1 and v2 are within the given distance to each other.
+//
+// Google Test uses ULP-based comparison to automatically pick a default
+// error bound that is appropriate for the operands.  See the
+// FloatingPoint template class in gtest-internal.h if you are
+// interested in the implementation details.
+
+#define EXPECT_FLOAT_EQ(expected, actual)\
+  EXPECT_PRED_FORMAT2(::testing::internal::CmpHelperFloatingPointEQ<float>, \
+                      expected, actual)
+
+#define EXPECT_DOUBLE_EQ(expected, actual)\
+  EXPECT_PRED_FORMAT2(::testing::internal::CmpHelperFloatingPointEQ<double>, \
+                      expected, actual)
+
+#define ASSERT_FLOAT_EQ(expected, actual)\
+  ASSERT_PRED_FORMAT2(::testing::internal::CmpHelperFloatingPointEQ<float>, \
+                      expected, actual)
+
+#define ASSERT_DOUBLE_EQ(expected, actual)\
+  ASSERT_PRED_FORMAT2(::testing::internal::CmpHelperFloatingPointEQ<double>, \
+                      expected, actual)
+
+#define EXPECT_NEAR(val1, val2, abs_error)\
+  EXPECT_PRED_FORMAT3(::testing::internal::DoubleNearPredFormat, \
+                      val1, val2, abs_error)
+
+#define ASSERT_NEAR(val1, val2, abs_error)\
+  ASSERT_PRED_FORMAT3(::testing::internal::DoubleNearPredFormat, \
+                      val1, val2, abs_error)
+
+// These predicate format functions work on floating-point values, and
+// can be used in {ASSERT|EXPECT}_PRED_FORMAT2*(), e.g.
+//
+//   EXPECT_PRED_FORMAT2(testing::DoubleLE, Foo(), 5.0);
+
+// Asserts that val1 is less than, or almost equal to, val2.  Fails
+// otherwise.  In particular, it fails if either val1 or val2 is NaN.
+GTEST_API_ AssertionResult FloatLE(const char* expr1, const char* expr2,
+                                   float val1, float val2);
+GTEST_API_ AssertionResult DoubleLE(const char* expr1, const char* expr2,
+                                    double val1, double val2);
+
+
+#if GTEST_OS_WINDOWS
+
+// Macros that test for HRESULT failure and success, these are only useful
+// on Windows, and rely on Windows SDK macros and APIs to compile.
+//
+//    * {ASSERT|EXPECT}_HRESULT_{SUCCEEDED|FAILED}(expr)
+//
+// When expr unexpectedly fails or succeeds, Google Test prints the
+// expected result and the actual result with both a human-readable
+// string representation of the error, if available, as well as the
+// hex result code.
+# define EXPECT_HRESULT_SUCCEEDED(expr) \
+    EXPECT_PRED_FORMAT1(::testing::internal::IsHRESULTSuccess, (expr))
+
+# define ASSERT_HRESULT_SUCCEEDED(expr) \
+    ASSERT_PRED_FORMAT1(::testing::internal::IsHRESULTSuccess, (expr))
+
+# define EXPECT_HRESULT_FAILED(expr) \
+    EXPECT_PRED_FORMAT1(::testing::internal::IsHRESULTFailure, (expr))
+
+# define ASSERT_HRESULT_FAILED(expr) \
+    ASSERT_PRED_FORMAT1(::testing::internal::IsHRESULTFailure, (expr))
+
+#endif  // GTEST_OS_WINDOWS
+
+// Macros that execute statement and check that it doesn't generate new fatal
+// failures in the current thread.
+//
+//   * {ASSERT|EXPECT}_NO_FATAL_FAILURE(statement);
+//
+// Examples:
+//
+//   EXPECT_NO_FATAL_FAILURE(Process());
+//   ASSERT_NO_FATAL_FAILURE(Process()) << "Process() failed";
+//
+#define ASSERT_NO_FATAL_FAILURE(statement) \
+    GTEST_TEST_NO_FATAL_FAILURE_(statement, GTEST_FATAL_FAILURE_)
+#define EXPECT_NO_FATAL_FAILURE(statement) \
+    GTEST_TEST_NO_FATAL_FAILURE_(statement, GTEST_NONFATAL_FAILURE_)
+
+// Causes a trace (including the source file path, the current line
+// number, and the given message) to be included in every test failure
+// message generated by code in the current scope.  The effect is
+// undone when the control leaves the current scope.
+//
+// The message argument can be anything streamable to std::ostream.
+//
+// In the implementation, we include the current line number as part
+// of the dummy variable name, thus allowing multiple SCOPED_TRACE()s
+// to appear in the same block - as long as they are on different
+// lines.
+#define SCOPED_TRACE(message) \
+  ::testing::internal::ScopedTrace GTEST_CONCAT_TOKEN_(gtest_trace_, __LINE__)(\
+    __FILE__, __LINE__, ::testing::Message() << (message))
+
+// Compile-time assertion for type equality.
+// StaticAssertTypeEq<type1, type2>() compiles iff type1 and type2 are
+// the same type.  The value it returns is not interesting.
+//
+// Instead of making StaticAssertTypeEq a class template, we make it a
+// function template that invokes a helper class template.  This
+// prevents a user from misusing StaticAssertTypeEq<T1, T2> by
+// defining objects of that type.
+//
+// CAVEAT:
+//
+// When used inside a method of a class template,
+// StaticAssertTypeEq<T1, T2>() is effective ONLY IF the method is
+// instantiated.  For example, given:
+//
+//   template <typename T> class Foo {
+//    public:
+//     void Bar() { testing::StaticAssertTypeEq<int, T>(); }
+//   };
+//
+// the code:
+//
+//   void Test1() { Foo<bool> foo; }
+//
+// will NOT generate a compiler error, as Foo<bool>::Bar() is never
+// actually instantiated.  Instead, you need:
+//
+//   void Test2() { Foo<bool> foo; foo.Bar(); }
+//
+// to cause a compiler error.
+template <typename T1, typename T2>
+bool StaticAssertTypeEq() {
+  (void)internal::StaticAssertTypeEqHelper<T1, T2>();
+  return true;
+}
+
+// Defines a test.
+//
+// The first parameter is the name of the test case, and the second
+// parameter is the name of the test within the test case.
+//
+// The convention is to end the test case name with "Test".  For
+// example, a test case for the Foo class can be named FooTest.
+//
+// The user should put his test code between braces after using this
+// macro.  Example:
+//
+//   TEST(FooTest, InitializesCorrectly) {
+//     Foo foo;
+//     EXPECT_TRUE(foo.StatusIsOK());
+//   }
+
+// Note that we call GetTestTypeId() instead of GetTypeId<
+// ::testing::Test>() here to get the type ID of testing::Test.  This
+// is to work around a suspected linker bug when using Google Test as
+// a framework on Mac OS X.  The bug causes GetTypeId<
+// ::testing::Test>() to return different values depending on whether
+// the call is from the Google Test framework itself or from user test
+// code.  GetTestTypeId() is guaranteed to always return the same
+// value, as it always calls GetTypeId<>() from the Google Test
+// framework.
+#define GTEST_TEST(test_case_name, test_name)\
+  GTEST_TEST_(test_case_name, test_name, \
+              ::testing::Test, ::testing::internal::GetTestTypeId())
+
+// Define this macro to 1 to omit the definition of TEST(), which
+// is a generic name and clashes with some other libraries.
+#if !GTEST_DONT_DEFINE_TEST
+# define TEST(test_case_name, test_name) GTEST_TEST(test_case_name, test_name)
+#endif
+
+// Defines a test that uses a test fixture.
+//
+// The first parameter is the name of the test fixture class, which
+// also doubles as the test case name.  The second parameter is the
+// name of the test within the test case.
+//
+// A test fixture class must be declared earlier.  The user should put
+// his test code between braces after using this macro.  Example:
+//
+//   class FooTest : public testing::Test {
+//    protected:
+//     virtual void SetUp() { b_.AddElement(3); }
+//
+//     Foo a_;
+//     Foo b_;
+//   };
+//
+//   TEST_F(FooTest, InitializesCorrectly) {
+//     EXPECT_TRUE(a_.StatusIsOK());
+//   }
+//
+//   TEST_F(FooTest, ReturnsElementCountCorrectly) {
+//     EXPECT_EQ(0, a_.size());
+//     EXPECT_EQ(1, b_.size());
+//   }
+
+#define TEST_F(test_fixture, test_name)\
+  GTEST_TEST_(test_fixture, test_name, test_fixture, \
+              ::testing::internal::GetTypeId<test_fixture>())
+
+}  // namespace testing
+
+// Use this function in main() to run all tests.  It returns 0 if all
+// tests are successful, or 1 otherwise.
+//
+// RUN_ALL_TESTS() should be invoked after the command line has been
+// parsed by InitGoogleTest().
+//
+// This function was formerly a macro; thus, it is in the global
+// namespace and has an all-caps name.
+int RUN_ALL_TESTS() GTEST_MUST_USE_RESULT_;
+
+inline int RUN_ALL_TESTS() {
+  return ::testing::UnitTest::GetInstance()->Run();
+}
+
+#endif  // GTEST_INCLUDE_GTEST_GTEST_H_
diff --git a/test/gtest/include/gtest/gtest_pred_impl.h b/test/gtest/include/gtest/gtest_pred_impl.h
new file mode 100644
index 0000000..30ae712
--- /dev/null
+++ b/test/gtest/include/gtest/gtest_pred_impl.h
@@ -0,0 +1,358 @@
+// Copyright 2006, Google Inc.
+// All rights reserved.
+//
+// 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.
+
+// This file is AUTOMATICALLY GENERATED on 10/31/2011 by command
+// 'gen_gtest_pred_impl.py 5'.  DO NOT EDIT BY HAND!
+//
+// Implements a family of generic predicate assertion macros.
+
+#ifndef GTEST_INCLUDE_GTEST_GTEST_PRED_IMPL_H_
+#define GTEST_INCLUDE_GTEST_GTEST_PRED_IMPL_H_
+
+// Makes sure this header is not included before gtest.h.
+#ifndef GTEST_INCLUDE_GTEST_GTEST_H_
+# error Do not include gtest_pred_impl.h directly.  Include gtest.h instead.
+#endif  // GTEST_INCLUDE_GTEST_GTEST_H_
+
+// This header implements a family of generic predicate assertion
+// macros:
+//
+//   ASSERT_PRED_FORMAT1(pred_format, v1)
+//   ASSERT_PRED_FORMAT2(pred_format, v1, v2)
+//   ...
+//
+// where pred_format is a function or functor that takes n (in the
+// case of ASSERT_PRED_FORMATn) values and their source expression
+// text, and returns a testing::AssertionResult.  See the definition
+// of ASSERT_EQ in gtest.h for an example.
+//
+// If you don't care about formatting, you can use the more
+// restrictive version:
+//
+//   ASSERT_PRED1(pred, v1)
+//   ASSERT_PRED2(pred, v1, v2)
+//   ...
+//
+// where pred is an n-ary function or functor that returns bool,
+// and the values v1, v2, ..., must support the << operator for
+// streaming to std::ostream.
+//
+// We also define the EXPECT_* variations.
+//
+// For now we only support predicates whose arity is at most 5.
+// Please email googletestframework at googlegroups.com if you need
+// support for higher arities.
+
+// GTEST_ASSERT_ is the basic statement to which all of the assertions
+// in this file reduce.  Don't use this in your code.
+
+#define GTEST_ASSERT_(expression, on_failure) \
+  GTEST_AMBIGUOUS_ELSE_BLOCKER_ \
+  if (const ::testing::AssertionResult gtest_ar = (expression)) \
+    ; \
+  else \
+    on_failure(gtest_ar.failure_message())
+
+
+// Helper function for implementing {EXPECT|ASSERT}_PRED1.  Don't use
+// this in your code.
+template <typename Pred,
+          typename T1>
+AssertionResult AssertPred1Helper(const char* pred_text,
+                                  const char* e1,
+                                  Pred pred,
+                                  const T1& v1) {
+  if (pred(v1)) return AssertionSuccess();
+
+  return AssertionFailure() << pred_text << "("
+                            << e1 << ") evaluates to false, where"
+                            << "\n" << e1 << " evaluates to " << v1;
+}
+
+// Internal macro for implementing {EXPECT|ASSERT}_PRED_FORMAT1.
+// Don't use this in your code.
+#define GTEST_PRED_FORMAT1_(pred_format, v1, on_failure)\
+  GTEST_ASSERT_(pred_format(#v1, v1), \
+                on_failure)
+
+// Internal macro for implementing {EXPECT|ASSERT}_PRED1.  Don't use
+// this in your code.
+#define GTEST_PRED1_(pred, v1, on_failure)\
+  GTEST_ASSERT_(::testing::AssertPred1Helper(#pred, \
+                                             #v1, \
+                                             pred, \
+                                             v1), on_failure)
+
+// Unary predicate assertion macros.
+#define EXPECT_PRED_FORMAT1(pred_format, v1) \
+  GTEST_PRED_FORMAT1_(pred_format, v1, GTEST_NONFATAL_FAILURE_)
+#define EXPECT_PRED1(pred, v1) \
+  GTEST_PRED1_(pred, v1, GTEST_NONFATAL_FAILURE_)
+#define ASSERT_PRED_FORMAT1(pred_format, v1) \
+  GTEST_PRED_FORMAT1_(pred_format, v1, GTEST_FATAL_FAILURE_)
+#define ASSERT_PRED1(pred, v1) \
+  GTEST_PRED1_(pred, v1, GTEST_FATAL_FAILURE_)
+
+
+
+// Helper function for implementing {EXPECT|ASSERT}_PRED2.  Don't use
+// this in your code.
+template <typename Pred,
+          typename T1,
+          typename T2>
+AssertionResult AssertPred2Helper(const char* pred_text,
+                                  const char* e1,
+                                  const char* e2,
+                                  Pred pred,
+                                  const T1& v1,
+                                  const T2& v2) {
+  if (pred(v1, v2)) return AssertionSuccess();
+
+  return AssertionFailure() << pred_text << "("
+                            << e1 << ", "
+                            << e2 << ") evaluates to false, where"
+                            << "\n" << e1 << " evaluates to " << v1
+                            << "\n" << e2 << " evaluates to " << v2;
+}
+
+// Internal macro for implementing {EXPECT|ASSERT}_PRED_FORMAT2.
+// Don't use this in your code.
+#define GTEST_PRED_FORMAT2_(pred_format, v1, v2, on_failure)\
+  GTEST_ASSERT_(pred_format(#v1, #v2, v1, v2), \
+                on_failure)
+
+// Internal macro for implementing {EXPECT|ASSERT}_PRED2.  Don't use
+// this in your code.
+#define GTEST_PRED2_(pred, v1, v2, on_failure)\
+  GTEST_ASSERT_(::testing::AssertPred2Helper(#pred, \
+                                             #v1, \
+                                             #v2, \
+                                             pred, \
+                                             v1, \
+                                             v2), on_failure)
+
+// Binary predicate assertion macros.
+#define EXPECT_PRED_FORMAT2(pred_format, v1, v2) \
+  GTEST_PRED_FORMAT2_(pred_format, v1, v2, GTEST_NONFATAL_FAILURE_)
+#define EXPECT_PRED2(pred, v1, v2) \
+  GTEST_PRED2_(pred, v1, v2, GTEST_NONFATAL_FAILURE_)
+#define ASSERT_PRED_FORMAT2(pred_format, v1, v2) \
+  GTEST_PRED_FORMAT2_(pred_format, v1, v2, GTEST_FATAL_FAILURE_)
+#define ASSERT_PRED2(pred, v1, v2) \
+  GTEST_PRED2_(pred, v1, v2, GTEST_FATAL_FAILURE_)
+
+
+
+// Helper function for implementing {EXPECT|ASSERT}_PRED3.  Don't use
+// this in your code.
+template <typename Pred,
+          typename T1,
+          typename T2,
+          typename T3>
+AssertionResult AssertPred3Helper(const char* pred_text,
+                                  const char* e1,
+                                  const char* e2,
+                                  const char* e3,
+                                  Pred pred,
+                                  const T1& v1,
+                                  const T2& v2,
+                                  const T3& v3) {
+  if (pred(v1, v2, v3)) return AssertionSuccess();
+
+  return AssertionFailure() << pred_text << "("
+                            << e1 << ", "
+                            << e2 << ", "
+                            << e3 << ") evaluates to false, where"
+                            << "\n" << e1 << " evaluates to " << v1
+                            << "\n" << e2 << " evaluates to " << v2
+                            << "\n" << e3 << " evaluates to " << v3;
+}
+
+// Internal macro for implementing {EXPECT|ASSERT}_PRED_FORMAT3.
+// Don't use this in your code.
+#define GTEST_PRED_FORMAT3_(pred_format, v1, v2, v3, on_failure)\
+  GTEST_ASSERT_(pred_format(#v1, #v2, #v3, v1, v2, v3), \
+                on_failure)
+
+// Internal macro for implementing {EXPECT|ASSERT}_PRED3.  Don't use
+// this in your code.
+#define GTEST_PRED3_(pred, v1, v2, v3, on_failure)\
+  GTEST_ASSERT_(::testing::AssertPred3Helper(#pred, \
+                                             #v1, \
+                                             #v2, \
+                                             #v3, \
+                                             pred, \
+                                             v1, \
+                                             v2, \
+                                             v3), on_failure)
+
+// Ternary predicate assertion macros.
+#define EXPECT_PRED_FORMAT3(pred_format, v1, v2, v3) \
+  GTEST_PRED_FORMAT3_(pred_format, v1, v2, v3, GTEST_NONFATAL_FAILURE_)
+#define EXPECT_PRED3(pred, v1, v2, v3) \
+  GTEST_PRED3_(pred, v1, v2, v3, GTEST_NONFATAL_FAILURE_)
+#define ASSERT_PRED_FORMAT3(pred_format, v1, v2, v3) \
+  GTEST_PRED_FORMAT3_(pred_format, v1, v2, v3, GTEST_FATAL_FAILURE_)
+#define ASSERT_PRED3(pred, v1, v2, v3) \
+  GTEST_PRED3_(pred, v1, v2, v3, GTEST_FATAL_FAILURE_)
+
+
+
+// Helper function for implementing {EXPECT|ASSERT}_PRED4.  Don't use
+// this in your code.
+template <typename Pred,
+          typename T1,
+          typename T2,
+          typename T3,
+          typename T4>
+AssertionResult AssertPred4Helper(const char* pred_text,
+                                  const char* e1,
+                                  const char* e2,
+                                  const char* e3,
+                                  const char* e4,
+                                  Pred pred,
+                                  const T1& v1,
+                                  const T2& v2,
+                                  const T3& v3,
+                                  const T4& v4) {
+  if (pred(v1, v2, v3, v4)) return AssertionSuccess();
+
+  return AssertionFailure() << pred_text << "("
+                            << e1 << ", "
+                            << e2 << ", "
+                            << e3 << ", "
+                            << e4 << ") evaluates to false, where"
+                            << "\n" << e1 << " evaluates to " << v1
+                            << "\n" << e2 << " evaluates to " << v2
+                            << "\n" << e3 << " evaluates to " << v3
+                            << "\n" << e4 << " evaluates to " << v4;
+}
+
+// Internal macro for implementing {EXPECT|ASSERT}_PRED_FORMAT4.
+// Don't use this in your code.
+#define GTEST_PRED_FORMAT4_(pred_format, v1, v2, v3, v4, on_failure)\
+  GTEST_ASSERT_(pred_format(#v1, #v2, #v3, #v4, v1, v2, v3, v4), \
+                on_failure)
+
+// Internal macro for implementing {EXPECT|ASSERT}_PRED4.  Don't use
+// this in your code.
+#define GTEST_PRED4_(pred, v1, v2, v3, v4, on_failure)\
+  GTEST_ASSERT_(::testing::AssertPred4Helper(#pred, \
+                                             #v1, \
+                                             #v2, \
+                                             #v3, \
+                                             #v4, \
+                                             pred, \
+                                             v1, \
+                                             v2, \
+                                             v3, \
+                                             v4), on_failure)
+
+// 4-ary predicate assertion macros.
+#define EXPECT_PRED_FORMAT4(pred_format, v1, v2, v3, v4) \
+  GTEST_PRED_FORMAT4_(pred_format, v1, v2, v3, v4, GTEST_NONFATAL_FAILURE_)
+#define EXPECT_PRED4(pred, v1, v2, v3, v4) \
+  GTEST_PRED4_(pred, v1, v2, v3, v4, GTEST_NONFATAL_FAILURE_)
+#define ASSERT_PRED_FORMAT4(pred_format, v1, v2, v3, v4) \
+  GTEST_PRED_FORMAT4_(pred_format, v1, v2, v3, v4, GTEST_FATAL_FAILURE_)
+#define ASSERT_PRED4(pred, v1, v2, v3, v4) \
+  GTEST_PRED4_(pred, v1, v2, v3, v4, GTEST_FATAL_FAILURE_)
+
+
+
+// Helper function for implementing {EXPECT|ASSERT}_PRED5.  Don't use
+// this in your code.
+template <typename Pred,
+          typename T1,
+          typename T2,
+          typename T3,
+          typename T4,
+          typename T5>
+AssertionResult AssertPred5Helper(const char* pred_text,
+                                  const char* e1,
+                                  const char* e2,
+                                  const char* e3,
+                                  const char* e4,
+                                  const char* e5,
+                                  Pred pred,
+                                  const T1& v1,
+                                  const T2& v2,
+                                  const T3& v3,
+                                  const T4& v4,
+                                  const T5& v5) {
+  if (pred(v1, v2, v3, v4, v5)) return AssertionSuccess();
+
+  return AssertionFailure() << pred_text << "("
+                            << e1 << ", "
+                            << e2 << ", "
+                            << e3 << ", "
+                            << e4 << ", "
+                            << e5 << ") evaluates to false, where"
+                            << "\n" << e1 << " evaluates to " << v1
+                            << "\n" << e2 << " evaluates to " << v2
+                            << "\n" << e3 << " evaluates to " << v3
+                            << "\n" << e4 << " evaluates to " << v4
+                            << "\n" << e5 << " evaluates to " << v5;
+}
+
+// Internal macro for implementing {EXPECT|ASSERT}_PRED_FORMAT5.
+// Don't use this in your code.
+#define GTEST_PRED_FORMAT5_(pred_format, v1, v2, v3, v4, v5, on_failure)\
+  GTEST_ASSERT_(pred_format(#v1, #v2, #v3, #v4, #v5, v1, v2, v3, v4, v5), \
+                on_failure)
+
+// Internal macro for implementing {EXPECT|ASSERT}_PRED5.  Don't use
+// this in your code.
+#define GTEST_PRED5_(pred, v1, v2, v3, v4, v5, on_failure)\
+  GTEST_ASSERT_(::testing::AssertPred5Helper(#pred, \
+                                             #v1, \
+                                             #v2, \
+                                             #v3, \
+                                             #v4, \
+                                             #v5, \
+                                             pred, \
+                                             v1, \
+                                             v2, \
+                                             v3, \
+                                             v4, \
+                                             v5), on_failure)
+
+// 5-ary predicate assertion macros.
+#define EXPECT_PRED_FORMAT5(pred_format, v1, v2, v3, v4, v5) \
+  GTEST_PRED_FORMAT5_(pred_format, v1, v2, v3, v4, v5, GTEST_NONFATAL_FAILURE_)
+#define EXPECT_PRED5(pred, v1, v2, v3, v4, v5) \
+  GTEST_PRED5_(pred, v1, v2, v3, v4, v5, GTEST_NONFATAL_FAILURE_)
+#define ASSERT_PRED_FORMAT5(pred_format, v1, v2, v3, v4, v5) \
+  GTEST_PRED_FORMAT5_(pred_format, v1, v2, v3, v4, v5, GTEST_FATAL_FAILURE_)
+#define ASSERT_PRED5(pred, v1, v2, v3, v4, v5) \
+  GTEST_PRED5_(pred, v1, v2, v3, v4, v5, GTEST_FATAL_FAILURE_)
+
+
+
+#endif  // GTEST_INCLUDE_GTEST_GTEST_PRED_IMPL_H_
diff --git a/test/gtest/include/gtest/gtest_prod.h b/test/gtest/include/gtest/gtest_prod.h
new file mode 100644
index 0000000..da80ddc
--- /dev/null
+++ b/test/gtest/include/gtest/gtest_prod.h
@@ -0,0 +1,58 @@
+// Copyright 2006, Google Inc.
+// All rights reserved.
+//
+// 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: wan at google.com (Zhanyong Wan)
+//
+// Google C++ Testing Framework definitions useful in production code.
+
+#ifndef GTEST_INCLUDE_GTEST_GTEST_PROD_H_
+#define GTEST_INCLUDE_GTEST_GTEST_PROD_H_
+
+// When you need to test the private or protected members of a class,
+// use the FRIEND_TEST macro to declare your tests as friends of the
+// class.  For example:
+//
+// class MyClass {
+//  private:
+//   void MyMethod();
+//   FRIEND_TEST(MyClassTest, MyMethod);
+// };
+//
+// class MyClassTest : public testing::Test {
+//   // ...
+// };
+//
+// TEST_F(MyClassTest, MyMethod) {
+//   // Can call MyClass::MyMethod() here.
+// }
+
+#define FRIEND_TEST(test_case_name, test_name)\
+friend class test_case_name##_##test_name##_Test
+
+#endif  // GTEST_INCLUDE_GTEST_GTEST_PROD_H_
diff --git a/test/gtest/include/gtest/internal/gtest-death-test-internal.h b/test/gtest/include/gtest/internal/gtest-death-test-internal.h
new file mode 100644
index 0000000..2b3a78f
--- /dev/null
+++ b/test/gtest/include/gtest/internal/gtest-death-test-internal.h
@@ -0,0 +1,319 @@
+// Copyright 2005, Google Inc.
+// All rights reserved.
+//
+// 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.
+//
+// Authors: wan at google.com (Zhanyong Wan), eefacm at gmail.com (Sean Mcafee)
+//
+// The Google C++ Testing Framework (Google Test)
+//
+// This header file defines internal utilities needed for implementing
+// death tests.  They are subject to change without notice.
+
+#ifndef GTEST_INCLUDE_GTEST_INTERNAL_GTEST_DEATH_TEST_INTERNAL_H_
+#define GTEST_INCLUDE_GTEST_INTERNAL_GTEST_DEATH_TEST_INTERNAL_H_
+
+#include "gtest/internal/gtest-internal.h"
+
+#include <stdio.h>
+
+namespace testing {
+namespace internal {
+
+GTEST_DECLARE_string_(internal_run_death_test);
+
+// Names of the flags (needed for parsing Google Test flags).
+const char kDeathTestStyleFlag[] = "death_test_style";
+const char kDeathTestUseFork[] = "death_test_use_fork";
+const char kInternalRunDeathTestFlag[] = "internal_run_death_test";
+
+#if GTEST_HAS_DEATH_TEST
+
+// DeathTest is a class that hides much of the complexity of the
+// GTEST_DEATH_TEST_ macro.  It is abstract; its static Create method
+// returns a concrete class that depends on the prevailing death test
+// style, as defined by the --gtest_death_test_style and/or
+// --gtest_internal_run_death_test flags.
+
+// In describing the results of death tests, these terms are used with
+// the corresponding definitions:
+//
+// exit status:  The integer exit information in the format specified
+//               by wait(2)
+// exit code:    The integer code passed to exit(3), _exit(2), or
+//               returned from main()
+class GTEST_API_ DeathTest {
+ public:
+  // Create returns false if there was an error determining the
+  // appropriate action to take for the current death test; for example,
+  // if the gtest_death_test_style flag is set to an invalid value.
+  // The LastMessage method will return a more detailed message in that
+  // case.  Otherwise, the DeathTest pointer pointed to by the "test"
+  // argument is set.  If the death test should be skipped, the pointer
+  // is set to NULL; otherwise, it is set to the address of a new concrete
+  // DeathTest object that controls the execution of the current test.
+  static bool Create(const char* statement, const RE* regex,
+                     const char* file, int line, DeathTest** test);
+  DeathTest();
+  virtual ~DeathTest() { }
+
+  // A helper class that aborts a death test when it's deleted.
+  class ReturnSentinel {
+   public:
+    explicit ReturnSentinel(DeathTest* test) : test_(test) { }
+    ~ReturnSentinel() { test_->Abort(TEST_ENCOUNTERED_RETURN_STATEMENT); }
+   private:
+    DeathTest* const test_;
+    GTEST_DISALLOW_COPY_AND_ASSIGN_(ReturnSentinel);
+  } GTEST_ATTRIBUTE_UNUSED_;
+
+  // An enumeration of possible roles that may be taken when a death
+  // test is encountered.  EXECUTE means that the death test logic should
+  // be executed immediately.  OVERSEE means that the program should prepare
+  // the appropriate environment for a child process to execute the death
+  // test, then wait for it to complete.
+  enum TestRole { OVERSEE_TEST, EXECUTE_TEST };
+
+  // An enumeration of the three reasons that a test might be aborted.
+  enum AbortReason {
+    TEST_ENCOUNTERED_RETURN_STATEMENT,
+    TEST_THREW_EXCEPTION,
+    TEST_DID_NOT_DIE
+  };
+
+  // Assumes one of the above roles.
+  virtual TestRole AssumeRole() = 0;
+
+  // Waits for the death test to finish and returns its status.
+  virtual int Wait() = 0;
+
+  // Returns true if the death test passed; that is, the test process
+  // exited during the test, its exit status matches a user-supplied
+  // predicate, and its stderr output matches a user-supplied regular
+  // expression.
+  // The user-supplied predicate may be a macro expression rather
+  // than a function pointer or functor, or else Wait and Passed could
+  // be combined.
+  virtual bool Passed(bool exit_status_ok) = 0;
+
+  // Signals that the death test did not die as expected.
+  virtual void Abort(AbortReason reason) = 0;
+
+  // Returns a human-readable outcome message regarding the outcome of
+  // the last death test.
+  static const char* LastMessage();
+
+  static void set_last_death_test_message(const std::string& message);
+
+ private:
+  // A string containing a description of the outcome of the last death test.
+  static std::string last_death_test_message_;
+
+  GTEST_DISALLOW_COPY_AND_ASSIGN_(DeathTest);
+};
+
+// Factory interface for death tests.  May be mocked out for testing.
+class DeathTestFactory {
+ public:
+  virtual ~DeathTestFactory() { }
+  virtual bool Create(const char* statement, const RE* regex,
+                      const char* file, int line, DeathTest** test) = 0;
+};
+
+// A concrete DeathTestFactory implementation for normal use.
+class DefaultDeathTestFactory : public DeathTestFactory {
+ public:
+  virtual bool Create(const char* statement, const RE* regex,
+                      const char* file, int line, DeathTest** test);
+};
+
+// Returns true if exit_status describes a process that was terminated
+// by a signal, or exited normally with a nonzero exit code.
+GTEST_API_ bool ExitedUnsuccessfully(int exit_status);
+
+// Traps C++ exceptions escaping statement and reports them as test
+// failures. Note that trapping SEH exceptions is not implemented here.
+# if GTEST_HAS_EXCEPTIONS
+#  define GTEST_EXECUTE_DEATH_TEST_STATEMENT_(statement, death_test) \
+  try { \
+    GTEST_SUPPRESS_UNREACHABLE_CODE_WARNING_BELOW_(statement); \
+  } catch (const ::std::exception& gtest_exception) { \
+    fprintf(\
+        stderr, \
+        "\n%s: Caught std::exception-derived exception escaping the " \
+        "death test statement. Exception message: %s\n", \
+        ::testing::internal::FormatFileLocation(__FILE__, __LINE__).c_str(), \
+        gtest_exception.what()); \
+    fflush(stderr); \
+    death_test->Abort(::testing::internal::DeathTest::TEST_THREW_EXCEPTION); \
+  } catch (...) { \
+    death_test->Abort(::testing::internal::DeathTest::TEST_THREW_EXCEPTION); \
+  }
+
+# else
+#  define GTEST_EXECUTE_DEATH_TEST_STATEMENT_(statement, death_test) \
+  GTEST_SUPPRESS_UNREACHABLE_CODE_WARNING_BELOW_(statement)
+
+# endif
+
+// This macro is for implementing ASSERT_DEATH*, EXPECT_DEATH*,
+// ASSERT_EXIT*, and EXPECT_EXIT*.
+# define GTEST_DEATH_TEST_(statement, predicate, regex, fail) \
+  GTEST_AMBIGUOUS_ELSE_BLOCKER_ \
+  if (::testing::internal::AlwaysTrue()) { \
+    const ::testing::internal::RE& gtest_regex = (regex); \
+    ::testing::internal::DeathTest* gtest_dt; \
+    if (!::testing::internal::DeathTest::Create(#statement, &gtest_regex, \
+        __FILE__, __LINE__, &gtest_dt)) { \
+      goto GTEST_CONCAT_TOKEN_(gtest_label_, __LINE__); \
+    } \
+    if (gtest_dt != NULL) { \
+      ::testing::internal::scoped_ptr< ::testing::internal::DeathTest> \
+          gtest_dt_ptr(gtest_dt); \
+      switch (gtest_dt->AssumeRole()) { \
+        case ::testing::internal::DeathTest::OVERSEE_TEST: \
+          if (!gtest_dt->Passed(predicate(gtest_dt->Wait()))) { \
+            goto GTEST_CONCAT_TOKEN_(gtest_label_, __LINE__); \
+          } \
+          break; \
+        case ::testing::internal::DeathTest::EXECUTE_TEST: { \
+          ::testing::internal::DeathTest::ReturnSentinel \
+              gtest_sentinel(gtest_dt); \
+          GTEST_EXECUTE_DEATH_TEST_STATEMENT_(statement, gtest_dt); \
+          gtest_dt->Abort(::testing::internal::DeathTest::TEST_DID_NOT_DIE); \
+          break; \
+        } \
+        default: \
+          break; \
+      } \
+    } \
+  } else \
+    GTEST_CONCAT_TOKEN_(gtest_label_, __LINE__): \
+      fail(::testing::internal::DeathTest::LastMessage())
+// The symbol "fail" here expands to something into which a message
+// can be streamed.
+
+// This macro is for implementing ASSERT/EXPECT_DEBUG_DEATH when compiled in
+// NDEBUG mode. In this case we need the statements to be executed, the regex is
+// ignored, and the macro must accept a streamed message even though the message
+// is never printed.
+# define GTEST_EXECUTE_STATEMENT_(statement, regex) \
+  GTEST_AMBIGUOUS_ELSE_BLOCKER_ \
+  if (::testing::internal::AlwaysTrue()) { \
+     GTEST_SUPPRESS_UNREACHABLE_CODE_WARNING_BELOW_(statement); \
+  } else \
+    ::testing::Message()
+
+// A class representing the parsed contents of the
+// --gtest_internal_run_death_test flag, as it existed when
+// RUN_ALL_TESTS was called.
+class InternalRunDeathTestFlag {
+ public:
+  InternalRunDeathTestFlag(const std::string& a_file,
+                           int a_line,
+                           int an_index,
+                           int a_write_fd)
+      : file_(a_file), line_(a_line), index_(an_index),
+        write_fd_(a_write_fd) {}
+
+  ~InternalRunDeathTestFlag() {
+    if (write_fd_ >= 0)
+      posix::Close(write_fd_);
+  }
+
+  const std::string& file() const { return file_; }
+  int line() const { return line_; }
+  int index() const { return index_; }
+  int write_fd() const { return write_fd_; }
+
+ private:
+  std::string file_;
+  int line_;
+  int index_;
+  int write_fd_;
+
+  GTEST_DISALLOW_COPY_AND_ASSIGN_(InternalRunDeathTestFlag);
+};
+
+// Returns a newly created InternalRunDeathTestFlag object with fields
+// initialized from the GTEST_FLAG(internal_run_death_test) flag if
+// the flag is specified; otherwise returns NULL.
+InternalRunDeathTestFlag* ParseInternalRunDeathTestFlag();
+
+#else  // GTEST_HAS_DEATH_TEST
+
+// This macro is used for implementing macros such as
+// EXPECT_DEATH_IF_SUPPORTED and ASSERT_DEATH_IF_SUPPORTED on systems where
+// death tests are not supported. Those macros must compile on such systems
+// iff EXPECT_DEATH and ASSERT_DEATH compile with the same parameters on
+// systems that support death tests. This allows one to write such a macro
+// on a system that does not support death tests and be sure that it will
+// compile on a death-test supporting system.
+//
+// Parameters:
+//   statement -  A statement that a macro such as EXPECT_DEATH would test
+//                for program termination. This macro has to make sure this
+//                statement is compiled but not executed, to ensure that
+//                EXPECT_DEATH_IF_SUPPORTED compiles with a certain
+//                parameter iff EXPECT_DEATH compiles with it.
+//   regex     -  A regex that a macro such as EXPECT_DEATH would use to test
+//                the output of statement.  This parameter has to be
+//                compiled but not evaluated by this macro, to ensure that
+//                this macro only accepts expressions that a macro such as
+//                EXPECT_DEATH would accept.
+//   terminator - Must be an empty statement for EXPECT_DEATH_IF_SUPPORTED
+//                and a return statement for ASSERT_DEATH_IF_SUPPORTED.
+//                This ensures that ASSERT_DEATH_IF_SUPPORTED will not
+//                compile inside functions where ASSERT_DEATH doesn't
+//                compile.
+//
+//  The branch that has an always false condition is used to ensure that
+//  statement and regex are compiled (and thus syntactically correct) but
+//  never executed. The unreachable code macro protects the terminator
+//  statement from generating an 'unreachable code' warning in case
+//  statement unconditionally returns or throws. The Message constructor at
+//  the end allows the syntax of streaming additional messages into the
+//  macro, for compilational compatibility with EXPECT_DEATH/ASSERT_DEATH.
+# define GTEST_UNSUPPORTED_DEATH_TEST_(statement, regex, terminator) \
+    GTEST_AMBIGUOUS_ELSE_BLOCKER_ \
+    if (::testing::internal::AlwaysTrue()) { \
+      GTEST_LOG_(WARNING) \
+          << "Death tests are not supported on this platform.\n" \
+          << "Statement '" #statement "' cannot be verified."; \
+    } else if (::testing::internal::AlwaysFalse()) { \
+      ::testing::internal::RE::PartialMatch(".*", (regex)); \
+      GTEST_SUPPRESS_UNREACHABLE_CODE_WARNING_BELOW_(statement); \
+      terminator; \
+    } else \
+      ::testing::Message()
+
+#endif  // GTEST_HAS_DEATH_TEST
+
+}  // namespace internal
+}  // namespace testing
+
+#endif  // GTEST_INCLUDE_GTEST_INTERNAL_GTEST_DEATH_TEST_INTERNAL_H_
diff --git a/test/gtest/include/gtest/internal/gtest-filepath.h b/test/gtest/include/gtest/internal/gtest-filepath.h
new file mode 100644
index 0000000..7a13b4b
--- /dev/null
+++ b/test/gtest/include/gtest/internal/gtest-filepath.h
@@ -0,0 +1,206 @@
+// Copyright 2008, Google Inc.
+// All rights reserved.
+//
+// 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: keith.ray at gmail.com (Keith Ray)
+//
+// Google Test filepath utilities
+//
+// This header file declares classes and functions used internally by
+// Google Test.  They are subject to change without notice.
+//
+// This file is #included in <gtest/internal/gtest-internal.h>.
+// Do not include this header file separately!
+
+#ifndef GTEST_INCLUDE_GTEST_INTERNAL_GTEST_FILEPATH_H_
+#define GTEST_INCLUDE_GTEST_INTERNAL_GTEST_FILEPATH_H_
+
+#include "gtest/internal/gtest-string.h"
+
+namespace testing {
+namespace internal {
+
+// FilePath - a class for file and directory pathname manipulation which
+// handles platform-specific conventions (like the pathname separator).
+// Used for helper functions for naming files in a directory for xml output.
+// Except for Set methods, all methods are const or static, which provides an
+// "immutable value object" -- useful for peace of mind.
+// A FilePath with a value ending in a path separator ("like/this/") represents
+// a directory, otherwise it is assumed to represent a file. In either case,
+// it may or may not represent an actual file or directory in the file system.
+// Names are NOT checked for syntax correctness -- no checking for illegal
+// characters, malformed paths, etc.
+
+class GTEST_API_ FilePath {
+ public:
+  FilePath() : pathname_("") { }
+  FilePath(const FilePath& rhs) : pathname_(rhs.pathname_) { }
+
+  explicit FilePath(const std::string& pathname) : pathname_(pathname) {
+    Normalize();
+  }
+
+  FilePath& operator=(const FilePath& rhs) {
+    Set(rhs);
+    return *this;
+  }
+
+  void Set(const FilePath& rhs) {
+    pathname_ = rhs.pathname_;
+  }
+
+  const std::string& string() const { return pathname_; }
+  const char* c_str() const { return pathname_.c_str(); }
+
+  // Returns the current working directory, or "" if unsuccessful.
+  static FilePath GetCurrentDir();
+
+  // Given directory = "dir", base_name = "test", number = 0,
+  // extension = "xml", returns "dir/test.xml". If number is greater
+  // than zero (e.g., 12), returns "dir/test_12.xml".
+  // On Windows platform, uses \ as the separator rather than /.
+  static FilePath MakeFileName(const FilePath& directory,
+                               const FilePath& base_name,
+                               int number,
+                               const char* extension);
+
+  // Given directory = "dir", relative_path = "test.xml",
+  // returns "dir/test.xml".
+  // On Windows, uses \ as the separator rather than /.
+  static FilePath ConcatPaths(const FilePath& directory,
+                              const FilePath& relative_path);
+
+  // Returns a pathname for a file that does not currently exist. The pathname
+  // will be directory/base_name.extension or
+  // directory/base_name_<number>.extension if directory/base_name.extension
+  // already exists. The number will be incremented until a pathname is found
+  // that does not already exist.
+  // Examples: 'dir/foo_test.xml' or 'dir/foo_test_1.xml'.
+  // There could be a race condition if two or more processes are calling this
+  // function at the same time -- they could both pick the same filename.
+  static FilePath GenerateUniqueFileName(const FilePath& directory,
+                                         const FilePath& base_name,
+                                         const char* extension);
+
+  // Returns true iff the path is "".
+  bool IsEmpty() const { return pathname_.empty(); }
+
+  // If input name has a trailing separator character, removes it and returns
+  // the name, otherwise return the name string unmodified.
+  // On Windows platform, uses \ as the separator, other platforms use /.
+  FilePath RemoveTrailingPathSeparator() const;
+
+  // Returns a copy of the FilePath with the directory part removed.
+  // Example: FilePath("path/to/file").RemoveDirectoryName() returns
+  // FilePath("file"). If there is no directory part ("just_a_file"), it returns
+  // the FilePath unmodified. If there is no file part ("just_a_dir/") it
+  // returns an empty FilePath ("").
+  // On Windows platform, '\' is the path separator, otherwise it is '/'.
+  FilePath RemoveDirectoryName() const;
+
+  // RemoveFileName returns the directory path with the filename removed.
+  // Example: FilePath("path/to/file").RemoveFileName() returns "path/to/".
+  // If the FilePath is "a_file" or "/a_file", RemoveFileName returns
+  // FilePath("./") or, on Windows, FilePath(".\\"). If the filepath does
+  // not have a file, like "just/a/dir/", it returns the FilePath unmodified.
+  // On Windows platform, '\' is the path separator, otherwise it is '/'.
+  FilePath RemoveFileName() const;
+
+  // Returns a copy of the FilePath with the case-insensitive extension removed.
+  // Example: FilePath("dir/file.exe").RemoveExtension("EXE") returns
+  // FilePath("dir/file"). If a case-insensitive extension is not
+  // found, returns a copy of the original FilePath.
+  FilePath RemoveExtension(const char* extension) const;
+
+  // Creates directories so that path exists. Returns true if successful or if
+  // the directories already exist; returns false if unable to create
+  // directories for any reason. Will also return false if the FilePath does
+  // not represent a directory (that is, it doesn't end with a path separator).
+  bool CreateDirectoriesRecursively() const;
+
+  // Create the directory so that path exists. Returns true if successful or
+  // if the directory already exists; returns false if unable to create the
+  // directory for any reason, including if the parent directory does not
+  // exist. Not named "CreateDirectory" because that's a macro on Windows.
+  bool CreateFolder() const;
+
+  // Returns true if FilePath describes something in the file-system,
+  // either a file, directory, or whatever, and that something exists.
+  bool FileOrDirectoryExists() const;
+
+  // Returns true if pathname describes a directory in the file-system
+  // that exists.
+  bool DirectoryExists() const;
+
+  // Returns true if FilePath ends with a path separator, which indicates that
+  // it is intended to represent a directory. Returns false otherwise.
+  // This does NOT check that a directory (or file) actually exists.
+  bool IsDirectory() const;
+
+  // Returns true if pathname describes a root directory. (Windows has one
+  // root directory per disk drive.)
+  bool IsRootDirectory() const;
+
+  // Returns true if pathname describes an absolute path.
+  bool IsAbsolutePath() const;
+
+ private:
+  // Replaces multiple consecutive separators with a single separator.
+  // For example, "bar///foo" becomes "bar/foo". Does not eliminate other
+  // redundancies that might be in a pathname involving "." or "..".
+  //
+  // A pathname with multiple consecutive separators may occur either through
+  // user error or as a result of some scripts or APIs that generate a pathname
+  // with a trailing separator. On other platforms the same API or script
+  // may NOT generate a pathname with a trailing "/". Then elsewhere that
+  // pathname may have another "/" and pathname components added to it,
+  // without checking for the separator already being there.
+  // The script language and operating system may allow paths like "foo//bar"
+  // but some of the functions in FilePath will not handle that correctly. In
+  // particular, RemoveTrailingPathSeparator() only removes one separator, and
+  // it is called in CreateDirectoriesRecursively() assuming that it will change
+  // a pathname from directory syntax (trailing separator) to filename syntax.
+  //
+  // On Windows this method also replaces the alternate path separator '/' with
+  // the primary path separator '\\', so that for example "bar\\/\\foo" becomes
+  // "bar\\foo".
+
+  void Normalize();
+
+  // Returns a pointer to the last occurence of a valid path separator in
+  // the FilePath. On Windows, for example, both '/' and '\' are valid path
+  // separators. Returns NULL if no path separator was found.
+  const char* FindLastPathSeparator() const;
+
+  std::string pathname_;
+};  // class FilePath
+
+}  // namespace internal
+}  // namespace testing
+
+#endif  // GTEST_INCLUDE_GTEST_INTERNAL_GTEST_FILEPATH_H_
diff --git a/test/gtest/include/gtest/internal/gtest-internal.h b/test/gtest/include/gtest/internal/gtest-internal.h
new file mode 100644
index 0000000..0dcc3a3
--- /dev/null
+++ b/test/gtest/include/gtest/internal/gtest-internal.h
@@ -0,0 +1,1158 @@
+// Copyright 2005, Google Inc.
+// All rights reserved.
+//
+// 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.
+//
+// Authors: wan at google.com (Zhanyong Wan), eefacm at gmail.com (Sean Mcafee)
+//
+// The Google C++ Testing Framework (Google Test)
+//
+// This header file declares functions and macros used internally by
+// Google Test.  They are subject to change without notice.
+
+#ifndef GTEST_INCLUDE_GTEST_INTERNAL_GTEST_INTERNAL_H_
+#define GTEST_INCLUDE_GTEST_INTERNAL_GTEST_INTERNAL_H_
+
+#include "gtest/internal/gtest-port.h"
+
+#if GTEST_OS_LINUX
+# include <stdlib.h>
+# include <sys/types.h>
+# include <sys/wait.h>
+# include <unistd.h>
+#endif  // GTEST_OS_LINUX
+
+#if GTEST_HAS_EXCEPTIONS
+# include <stdexcept>
+#endif
+
+#include <ctype.h>
+#include <float.h>
+#include <string.h>
+#include <iomanip>
+#include <limits>
+#include <set>
+
+#include "gtest/gtest-message.h"
+#include "gtest/internal/gtest-string.h"
+#include "gtest/internal/gtest-filepath.h"
+#include "gtest/internal/gtest-type-util.h"
+
+// Due to C++ preprocessor weirdness, we need double indirection to
+// concatenate two tokens when one of them is __LINE__.  Writing
+//
+//   foo ## __LINE__
+//
+// will result in the token foo__LINE__, instead of foo followed by
+// the current line number.  For more details, see
+// http://www.parashift.com/c++-faq-lite/misc-technical-issues.html#faq-39.6
+#define GTEST_CONCAT_TOKEN_(foo, bar) GTEST_CONCAT_TOKEN_IMPL_(foo, bar)
+#define GTEST_CONCAT_TOKEN_IMPL_(foo, bar) foo ## bar
+
+class ProtocolMessage;
+namespace proto2 { class Message; }
+
+namespace testing {
+
+// Forward declarations.
+
+class AssertionResult;                 // Result of an assertion.
+class Message;                         // Represents a failure message.
+class Test;                            // Represents a test.
+class TestInfo;                        // Information about a test.
+class TestPartResult;                  // Result of a test part.
+class UnitTest;                        // A collection of test cases.
+
+template <typename T>
+::std::string PrintToString(const T& value);
+
+namespace internal {
+
+struct TraceInfo;                      // Information about a trace point.
+class ScopedTrace;                     // Implements scoped trace.
+class TestInfoImpl;                    // Opaque implementation of TestInfo
+class UnitTestImpl;                    // Opaque implementation of UnitTest
+
+// How many times InitGoogleTest() has been called.
+GTEST_API_ extern int g_init_gtest_count;
+
+// The text used in failure messages to indicate the start of the
+// stack trace.
+GTEST_API_ extern const char kStackTraceMarker[];
+
+// Two overloaded helpers for checking at compile time whether an
+// expression is a null pointer literal (i.e. NULL or any 0-valued
+// compile-time integral constant).  Their return values have
+// different sizes, so we can use sizeof() to test which version is
+// picked by the compiler.  These helpers have no implementations, as
+// we only need their signatures.
+//
+// Given IsNullLiteralHelper(x), the compiler will pick the first
+// version if x can be implicitly converted to Secret*, and pick the
+// second version otherwise.  Since Secret is a secret and incomplete
+// type, the only expression a user can write that has type Secret* is
+// a null pointer literal.  Therefore, we know that x is a null
+// pointer literal if and only if the first version is picked by the
+// compiler.
+char IsNullLiteralHelper(Secret* p);
+char (&IsNullLiteralHelper(...))[2];  // NOLINT
+
+// A compile-time bool constant that is true if and only if x is a
+// null pointer literal (i.e. NULL or any 0-valued compile-time
+// integral constant).
+#ifdef GTEST_ELLIPSIS_NEEDS_POD_
+// We lose support for NULL detection where the compiler doesn't like
+// passing non-POD classes through ellipsis (...).
+# define GTEST_IS_NULL_LITERAL_(x) false
+#else
+# define GTEST_IS_NULL_LITERAL_(x) \
+    (sizeof(::testing::internal::IsNullLiteralHelper(x)) == 1)
+#endif  // GTEST_ELLIPSIS_NEEDS_POD_
+
+// Appends the user-supplied message to the Google-Test-generated message.
+GTEST_API_ std::string AppendUserMessage(
+    const std::string& gtest_msg, const Message& user_msg);
+
+#if GTEST_HAS_EXCEPTIONS
+
+// This exception is thrown by (and only by) a failed Google Test
+// assertion when GTEST_FLAG(throw_on_failure) is true (if exceptions
+// are enabled).  We derive it from std::runtime_error, which is for
+// errors presumably detectable only at run time.  Since
+// std::runtime_error inherits from std::exception, many testing
+// frameworks know how to extract and print the message inside it.
+class GTEST_API_ GoogleTestFailureException : public ::std::runtime_error {
+ public:
+  explicit GoogleTestFailureException(const TestPartResult& failure);
+};
+
+#endif  // GTEST_HAS_EXCEPTIONS
+
+// A helper class for creating scoped traces in user programs.
+class GTEST_API_ ScopedTrace {
+ public:
+  // The c'tor pushes the given source file location and message onto
+  // a trace stack maintained by Google Test.
+  ScopedTrace(const char* file, int line, const Message& message);
+
+  // The d'tor pops the info pushed by the c'tor.
+  //
+  // Note that the d'tor is not virtual in order to be efficient.
+  // Don't inherit from ScopedTrace!
+  ~ScopedTrace();
+
+ private:
+  GTEST_DISALLOW_COPY_AND_ASSIGN_(ScopedTrace);
+} GTEST_ATTRIBUTE_UNUSED_;  // A ScopedTrace object does its job in its
+                            // c'tor and d'tor.  Therefore it doesn't
+                            // need to be used otherwise.
+
+// Constructs and returns the message for an equality assertion
+// (e.g. ASSERT_EQ, EXPECT_STREQ, etc) failure.
+//
+// The first four parameters are the expressions used in the assertion
+// and their values, as strings.  For example, for ASSERT_EQ(foo, bar)
+// where foo is 5 and bar is 6, we have:
+//
+//   expected_expression: "foo"
+//   actual_expression:   "bar"
+//   expected_value:      "5"
+//   actual_value:        "6"
+//
+// The ignoring_case parameter is true iff the assertion is a
+// *_STRCASEEQ*.  When it's true, the string " (ignoring case)" will
+// be inserted into the message.
+GTEST_API_ AssertionResult EqFailure(const char* expected_expression,
+                                     const char* actual_expression,
+                                     const std::string& expected_value,
+                                     const std::string& actual_value,
+                                     bool ignoring_case);
+
+// Constructs a failure message for Boolean assertions such as EXPECT_TRUE.
+GTEST_API_ std::string GetBoolAssertionFailureMessage(
+    const AssertionResult& assertion_result,
+    const char* expression_text,
+    const char* actual_predicate_value,
+    const char* expected_predicate_value);
+
+// This template class represents an IEEE floating-point number
+// (either single-precision or double-precision, depending on the
+// template parameters).
+//
+// The purpose of this class is to do more sophisticated number
+// comparison.  (Due to round-off error, etc, it's very unlikely that
+// two floating-points will be equal exactly.  Hence a naive
+// comparison by the == operation often doesn't work.)
+//
+// Format of IEEE floating-point:
+//
+//   The most-significant bit being the leftmost, an IEEE
+//   floating-point looks like
+//
+//     sign_bit exponent_bits fraction_bits
+//
+//   Here, sign_bit is a single bit that designates the sign of the
+//   number.
+//
+//   For float, there are 8 exponent bits and 23 fraction bits.
+//
+//   For double, there are 11 exponent bits and 52 fraction bits.
+//
+//   More details can be found at
+//   http://en.wikipedia.org/wiki/IEEE_floating-point_standard.
+//
+// Template parameter:
+//
+//   RawType: the raw floating-point type (either float or double)
+template <typename RawType>
+class FloatingPoint {
+ public:
+  // Defines the unsigned integer type that has the same size as the
+  // floating point number.
+  typedef typename TypeWithSize<sizeof(RawType)>::UInt Bits;
+
+  // Constants.
+
+  // # of bits in a number.
+  static const size_t kBitCount = 8*sizeof(RawType);
+
+  // # of fraction bits in a number.
+  static const size_t kFractionBitCount =
+    std::numeric_limits<RawType>::digits - 1;
+
+  // # of exponent bits in a number.
+  static const size_t kExponentBitCount = kBitCount - 1 - kFractionBitCount;
+
+  // The mask for the sign bit.
+  static const Bits kSignBitMask = static_cast<Bits>(1) << (kBitCount - 1);
+
+  // The mask for the fraction bits.
+  static const Bits kFractionBitMask =
+    ~static_cast<Bits>(0) >> (kExponentBitCount + 1);
+
+  // The mask for the exponent bits.
+  static const Bits kExponentBitMask = ~(kSignBitMask | kFractionBitMask);
+
+  // How many ULP's (Units in the Last Place) we want to tolerate when
+  // comparing two numbers.  The larger the value, the more error we
+  // allow.  A 0 value means that two numbers must be exactly the same
+  // to be considered equal.
+  //
+  // The maximum error of a single floating-point operation is 0.5
+  // units in the last place.  On Intel CPU's, all floating-point
+  // calculations are done with 80-bit precision, while double has 64
+  // bits.  Therefore, 4 should be enough for ordinary use.
+  //
+  // See the following article for more details on ULP:
+  // http://randomascii.wordpress.com/2012/02/25/comparing-floating-point-numbers-2012-edition/
+  static const size_t kMaxUlps = 4;
+
+  // Constructs a FloatingPoint from a raw floating-point number.
+  //
+  // On an Intel CPU, passing a non-normalized NAN (Not a Number)
+  // around may change its bits, although the new value is guaranteed
+  // to be also a NAN.  Therefore, don't expect this constructor to
+  // preserve the bits in x when x is a NAN.
+  explicit FloatingPoint(const RawType& x) { u_.value_ = x; }
+
+  // Static methods
+
+  // Reinterprets a bit pattern as a floating-point number.
+  //
+  // This function is needed to test the AlmostEquals() method.
+  static RawType ReinterpretBits(const Bits bits) {
+    FloatingPoint fp(0);
+    fp.u_.bits_ = bits;
+    return fp.u_.value_;
+  }
+
+  // Returns the floating-point number that represent positive infinity.
+  static RawType Infinity() {
+    return ReinterpretBits(kExponentBitMask);
+  }
+
+  // Returns the maximum representable finite floating-point number.
+  static RawType Max();
+
+  // Non-static methods
+
+  // Returns the bits that represents this number.
+  const Bits &bits() const { return u_.bits_; }
+
+  // Returns the exponent bits of this number.
+  Bits exponent_bits() const { return kExponentBitMask & u_.bits_; }
+
+  // Returns the fraction bits of this number.
+  Bits fraction_bits() const { return kFractionBitMask & u_.bits_; }
+
+  // Returns the sign bit of this number.
+  Bits sign_bit() const { return kSignBitMask & u_.bits_; }
+
+  // Returns true iff this is NAN (not a number).
+  bool is_nan() const {
+    // It's a NAN if the exponent bits are all ones and the fraction
+    // bits are not entirely zeros.
+    return (exponent_bits() == kExponentBitMask) && (fraction_bits() != 0);
+  }
+
+  // Returns true iff this number is at most kMaxUlps ULP's away from
+  // rhs.  In particular, this function:
+  //
+  //   - returns false if either number is (or both are) NAN.
+  //   - treats really large numbers as almost equal to infinity.
+  //   - thinks +0.0 and -0.0 are 0 DLP's apart.
+  bool AlmostEquals(const FloatingPoint& rhs) const {
+    // The IEEE standard says that any comparison operation involving
+    // a NAN must return false.
+    if (is_nan() || rhs.is_nan()) return false;
+
+    return DistanceBetweenSignAndMagnitudeNumbers(u_.bits_, rhs.u_.bits_)
+        <= kMaxUlps;
+  }
+
+ private:
+  // The data type used to store the actual floating-point number.
+  union FloatingPointUnion {
+    RawType value_;  // The raw floating-point number.
+    Bits bits_;      // The bits that represent the number.
+  };
+
+  // Converts an integer from the sign-and-magnitude representation to
+  // the biased representation.  More precisely, let N be 2 to the
+  // power of (kBitCount - 1), an integer x is represented by the
+  // unsigned number x + N.
+  //
+  // For instance,
+  //
+  //   -N + 1 (the most negative number representable using
+  //          sign-and-magnitude) is represented by 1;
+  //   0      is represented by N; and
+  //   N - 1  (the biggest number representable using
+  //          sign-and-magnitude) is represented by 2N - 1.
+  //
+  // Read http://en.wikipedia.org/wiki/Signed_number_representations
+  // for more details on signed number representations.
+  static Bits SignAndMagnitudeToBiased(const Bits &sam) {
+    if (kSignBitMask & sam) {
+      // sam represents a negative number.
+      return ~sam + 1;
+    } else {
+      // sam represents a positive number.
+      return kSignBitMask | sam;
+    }
+  }
+
+  // Given two numbers in the sign-and-magnitude representation,
+  // returns the distance between them as an unsigned number.
+  static Bits DistanceBetweenSignAndMagnitudeNumbers(const Bits &sam1,
+                                                     const Bits &sam2) {
+    const Bits biased1 = SignAndMagnitudeToBiased(sam1);
+    const Bits biased2 = SignAndMagnitudeToBiased(sam2);
+    return (biased1 >= biased2) ? (biased1 - biased2) : (biased2 - biased1);
+  }
+
+  FloatingPointUnion u_;
+};
+
+// We cannot use std::numeric_limits<T>::max() as it clashes with the max()
+// macro defined by <windows.h>.
+template <>
+inline float FloatingPoint<float>::Max() { return FLT_MAX; }
+template <>
+inline double FloatingPoint<double>::Max() { return DBL_MAX; }
+
+// Typedefs the instances of the FloatingPoint template class that we
+// care to use.
+typedef FloatingPoint<float> Float;
+typedef FloatingPoint<double> Double;
+
+// In order to catch the mistake of putting tests that use different
+// test fixture classes in the same test case, we need to assign
+// unique IDs to fixture classes and compare them.  The TypeId type is
+// used to hold such IDs.  The user should treat TypeId as an opaque
+// type: the only operation allowed on TypeId values is to compare
+// them for equality using the == operator.
+typedef const void* TypeId;
+
+template <typename T>
+class TypeIdHelper {
+ public:
+  // dummy_ must not have a const type.  Otherwise an overly eager
+  // compiler (e.g. MSVC 7.1 & 8.0) may try to merge
+  // TypeIdHelper<T>::dummy_ for different Ts as an "optimization".
+  static bool dummy_;
+};
+
+template <typename T>
+bool TypeIdHelper<T>::dummy_ = false;
+
+// GetTypeId<T>() returns the ID of type T.  Different values will be
+// returned for different types.  Calling the function twice with the
+// same type argument is guaranteed to return the same ID.
+template <typename T>
+TypeId GetTypeId() {
+  // The compiler is required to allocate a different
+  // TypeIdHelper<T>::dummy_ variable for each T used to instantiate
+  // the template.  Therefore, the address of dummy_ is guaranteed to
+  // be unique.
+  return &(TypeIdHelper<T>::dummy_);
+}
+
+// Returns the type ID of ::testing::Test.  Always call this instead
+// of GetTypeId< ::testing::Test>() to get the type ID of
+// ::testing::Test, as the latter may give the wrong result due to a
+// suspected linker bug when compiling Google Test as a Mac OS X
+// framework.
+GTEST_API_ TypeId GetTestTypeId();
+
+// Defines the abstract factory interface that creates instances
+// of a Test object.
+class TestFactoryBase {
+ public:
+  virtual ~TestFactoryBase() {}
+
+  // Creates a test instance to run. The instance is both created and destroyed
+  // within TestInfoImpl::Run()
+  virtual Test* CreateTest() = 0;
+
+ protected:
+  TestFactoryBase() {}
+
+ private:
+  GTEST_DISALLOW_COPY_AND_ASSIGN_(TestFactoryBase);
+};
+
+// This class provides implementation of TeastFactoryBase interface.
+// It is used in TEST and TEST_F macros.
+template <class TestClass>
+class TestFactoryImpl : public TestFactoryBase {
+ public:
+  virtual Test* CreateTest() { return new TestClass; }
+};
+
+#if GTEST_OS_WINDOWS
+
+// Predicate-formatters for implementing the HRESULT checking macros
+// {ASSERT|EXPECT}_HRESULT_{SUCCEEDED|FAILED}
+// We pass a long instead of HRESULT to avoid causing an
+// include dependency for the HRESULT type.
+GTEST_API_ AssertionResult IsHRESULTSuccess(const char* expr,
+                                            long hr);  // NOLINT
+GTEST_API_ AssertionResult IsHRESULTFailure(const char* expr,
+                                            long hr);  // NOLINT
+
+#endif  // GTEST_OS_WINDOWS
+
+// Types of SetUpTestCase() and TearDownTestCase() functions.
+typedef void (*SetUpTestCaseFunc)();
+typedef void (*TearDownTestCaseFunc)();
+
+// Creates a new TestInfo object and registers it with Google Test;
+// returns the created object.
+//
+// Arguments:
+//
+//   test_case_name:   name of the test case
+//   name:             name of the test
+//   type_param        the name of the test's type parameter, or NULL if
+//                     this is not a typed or a type-parameterized test.
+//   value_param       text representation of the test's value parameter,
+//                     or NULL if this is not a type-parameterized test.
+//   fixture_class_id: ID of the test fixture class
+//   set_up_tc:        pointer to the function that sets up the test case
+//   tear_down_tc:     pointer to the function that tears down the test case
+//   factory:          pointer to the factory that creates a test object.
+//                     The newly created TestInfo instance will assume
+//                     ownership of the factory object.
+GTEST_API_ TestInfo* MakeAndRegisterTestInfo(
+    const char* test_case_name,
+    const char* name,
+    const char* type_param,
+    const char* value_param,
+    TypeId fixture_class_id,
+    SetUpTestCaseFunc set_up_tc,
+    TearDownTestCaseFunc tear_down_tc,
+    TestFactoryBase* factory);
+
+// If *pstr starts with the given prefix, modifies *pstr to be right
+// past the prefix and returns true; otherwise leaves *pstr unchanged
+// and returns false.  None of pstr, *pstr, and prefix can be NULL.
+GTEST_API_ bool SkipPrefix(const char* prefix, const char** pstr);
+
+#if GTEST_HAS_TYPED_TEST || GTEST_HAS_TYPED_TEST_P
+
+// State of the definition of a type-parameterized test case.
+class GTEST_API_ TypedTestCasePState {
+ public:
+  TypedTestCasePState() : registered_(false) {}
+
+  // Adds the given test name to defined_test_names_ and return true
+  // if the test case hasn't been registered; otherwise aborts the
+  // program.
+  bool AddTestName(const char* file, int line, const char* case_name,
+                   const char* test_name) {
+    if (registered_) {
+      fprintf(stderr, "%s Test %s must be defined before "
+              "REGISTER_TYPED_TEST_CASE_P(%s, ...).\n",
+              FormatFileLocation(file, line).c_str(), test_name, case_name);
+      fflush(stderr);
+      posix::Abort();
+    }
+    defined_test_names_.insert(test_name);
+    return true;
+  }
+
+  // Verifies that registered_tests match the test names in
+  // defined_test_names_; returns registered_tests if successful, or
+  // aborts the program otherwise.
+  const char* VerifyRegisteredTestNames(
+      const char* file, int line, const char* registered_tests);
+
+ private:
+  bool registered_;
+  ::std::set<const char*> defined_test_names_;
+};
+
+// Skips to the first non-space char after the first comma in 'str';
+// returns NULL if no comma is found in 'str'.
+inline const char* SkipComma(const char* str) {
+  const char* comma = strchr(str, ',');
+  if (comma == NULL) {
+    return NULL;
+  }
+  while (IsSpace(*(++comma))) {}
+  return comma;
+}
+
+// Returns the prefix of 'str' before the first comma in it; returns
+// the entire string if it contains no comma.
+inline std::string GetPrefixUntilComma(const char* str) {
+  const char* comma = strchr(str, ',');
+  return comma == NULL ? str : std::string(str, comma);
+}
+
+// TypeParameterizedTest<Fixture, TestSel, Types>::Register()
+// registers a list of type-parameterized tests with Google Test.  The
+// return value is insignificant - we just need to return something
+// such that we can call this function in a namespace scope.
+//
+// Implementation note: The GTEST_TEMPLATE_ macro declares a template
+// template parameter.  It's defined in gtest-type-util.h.
+template <GTEST_TEMPLATE_ Fixture, class TestSel, typename Types>
+class TypeParameterizedTest {
+ public:
+  // 'index' is the index of the test in the type list 'Types'
+  // specified in INSTANTIATE_TYPED_TEST_CASE_P(Prefix, TestCase,
+  // Types).  Valid values for 'index' are [0, N - 1] where N is the
+  // length of Types.
+  static bool Register(const char* prefix, const char* case_name,
+                       const char* test_names, int index) {
+    typedef typename Types::Head Type;
+    typedef Fixture<Type> FixtureClass;
+    typedef typename GTEST_BIND_(TestSel, Type) TestClass;
+
+    // First, registers the first type-parameterized test in the type
+    // list.
+    MakeAndRegisterTestInfo(
+        (std::string(prefix) + (prefix[0] == '\0' ? "" : "/") + case_name + "/"
+         + StreamableToString(index)).c_str(),
+        GetPrefixUntilComma(test_names).c_str(),
+        GetTypeName<Type>().c_str(),
+        NULL,  // No value parameter.
+        GetTypeId<FixtureClass>(),
+        TestClass::SetUpTestCase,
+        TestClass::TearDownTestCase,
+        new TestFactoryImpl<TestClass>);
+
+    // Next, recurses (at compile time) with the tail of the type list.
+    return TypeParameterizedTest<Fixture, TestSel, typename Types::Tail>
+        ::Register(prefix, case_name, test_names, index + 1);
+  }
+};
+
+// The base case for the compile time recursion.
+template <GTEST_TEMPLATE_ Fixture, class TestSel>
+class TypeParameterizedTest<Fixture, TestSel, Types0> {
+ public:
+  static bool Register(const char* /*prefix*/, const char* /*case_name*/,
+                       const char* /*test_names*/, int /*index*/) {
+    return true;
+  }
+};
+
+// TypeParameterizedTestCase<Fixture, Tests, Types>::Register()
+// registers *all combinations* of 'Tests' and 'Types' with Google
+// Test.  The return value is insignificant - we just need to return
+// something such that we can call this function in a namespace scope.
+template <GTEST_TEMPLATE_ Fixture, typename Tests, typename Types>
+class TypeParameterizedTestCase {
+ public:
+  static bool Register(const char* prefix, const char* case_name,
+                       const char* test_names) {
+    typedef typename Tests::Head Head;
+
+    // First, register the first test in 'Test' for each type in 'Types'.
+    TypeParameterizedTest<Fixture, Head, Types>::Register(
+        prefix, case_name, test_names, 0);
+
+    // Next, recurses (at compile time) with the tail of the test list.
+    return TypeParameterizedTestCase<Fixture, typename Tests::Tail, Types>
+        ::Register(prefix, case_name, SkipComma(test_names));
+  }
+};
+
+// The base case for the compile time recursion.
+template <GTEST_TEMPLATE_ Fixture, typename Types>
+class TypeParameterizedTestCase<Fixture, Templates0, Types> {
+ public:
+  static bool Register(const char* /*prefix*/, const char* /*case_name*/,
+                       const char* /*test_names*/) {
+    return true;
+  }
+};
+
+#endif  // GTEST_HAS_TYPED_TEST || GTEST_HAS_TYPED_TEST_P
+
+// Returns the current OS stack trace as an std::string.
+//
+// The maximum number of stack frames to be included is specified by
+// the gtest_stack_trace_depth flag.  The skip_count parameter
+// specifies the number of top frames to be skipped, which doesn't
+// count against the number of frames to be included.
+//
+// For example, if Foo() calls Bar(), which in turn calls
+// GetCurrentOsStackTraceExceptTop(..., 1), Foo() will be included in
+// the trace but Bar() and GetCurrentOsStackTraceExceptTop() won't.
+GTEST_API_ std::string GetCurrentOsStackTraceExceptTop(
+    UnitTest* unit_test, int skip_count);
+
+// Helpers for suppressing warnings on unreachable code or constant
+// condition.
+
+// Always returns true.
+GTEST_API_ bool AlwaysTrue();
+
+// Always returns false.
+inline bool AlwaysFalse() { return !AlwaysTrue(); }
+
+// Helper for suppressing false warning from Clang on a const char*
+// variable declared in a conditional expression always being NULL in
+// the else branch.
+struct GTEST_API_ ConstCharPtr {
+  ConstCharPtr(const char* str) : value(str) {}
+  operator bool() const { return true; }
+  const char* value;
+};
+
+// A simple Linear Congruential Generator for generating random
+// numbers with a uniform distribution.  Unlike rand() and srand(), it
+// doesn't use global state (and therefore can't interfere with user
+// code).  Unlike rand_r(), it's portable.  An LCG isn't very random,
+// but it's good enough for our purposes.
+class GTEST_API_ Random {
+ public:
+  static const UInt32 kMaxRange = 1u << 31;
+
+  explicit Random(UInt32 seed) : state_(seed) {}
+
+  void Reseed(UInt32 seed) { state_ = seed; }
+
+  // Generates a random number from [0, range).  Crashes if 'range' is
+  // 0 or greater than kMaxRange.
+  UInt32 Generate(UInt32 range);
+
+ private:
+  UInt32 state_;
+  GTEST_DISALLOW_COPY_AND_ASSIGN_(Random);
+};
+
+// Defining a variable of type CompileAssertTypesEqual<T1, T2> will cause a
+// compiler error iff T1 and T2 are different types.
+template <typename T1, typename T2>
+struct CompileAssertTypesEqual;
+
+template <typename T>
+struct CompileAssertTypesEqual<T, T> {
+};
+
+// Removes the reference from a type if it is a reference type,
+// otherwise leaves it unchanged.  This is the same as
+// tr1::remove_reference, which is not widely available yet.
+template <typename T>
+struct RemoveReference { typedef T type; };  // NOLINT
+template <typename T>
+struct RemoveReference<T&> { typedef T type; };  // NOLINT
+
+// A handy wrapper around RemoveReference that works when the argument
+// T depends on template parameters.
+#define GTEST_REMOVE_REFERENCE_(T) \
+    typename ::testing::internal::RemoveReference<T>::type
+
+// Removes const from a type if it is a const type, otherwise leaves
+// it unchanged.  This is the same as tr1::remove_const, which is not
+// widely available yet.
+template <typename T>
+struct RemoveConst { typedef T type; };  // NOLINT
+template <typename T>
+struct RemoveConst<const T> { typedef T type; };  // NOLINT
+
+// MSVC 8.0, Sun C++, and IBM XL C++ have a bug which causes the above
+// definition to fail to remove the const in 'const int[3]' and 'const
+// char[3][4]'.  The following specialization works around the bug.
+template <typename T, size_t N>
+struct RemoveConst<const T[N]> {
+  typedef typename RemoveConst<T>::type type[N];
+};
+
+#if defined(_MSC_VER) && _MSC_VER < 1400
+// This is the only specialization that allows VC++ 7.1 to remove const in
+// 'const int[3] and 'const int[3][4]'.  However, it causes trouble with GCC
+// and thus needs to be conditionally compiled.
+template <typename T, size_t N>
+struct RemoveConst<T[N]> {
+  typedef typename RemoveConst<T>::type type[N];
+};
+#endif
+
+// A handy wrapper around RemoveConst that works when the argument
+// T depends on template parameters.
+#define GTEST_REMOVE_CONST_(T) \
+    typename ::testing::internal::RemoveConst<T>::type
+
+// Turns const U&, U&, const U, and U all into U.
+#define GTEST_REMOVE_REFERENCE_AND_CONST_(T) \
+    GTEST_REMOVE_CONST_(GTEST_REMOVE_REFERENCE_(T))
+
+// Adds reference to a type if it is not a reference type,
+// otherwise leaves it unchanged.  This is the same as
+// tr1::add_reference, which is not widely available yet.
+template <typename T>
+struct AddReference { typedef T& type; };  // NOLINT
+template <typename T>
+struct AddReference<T&> { typedef T& type; };  // NOLINT
+
+// A handy wrapper around AddReference that works when the argument T
+// depends on template parameters.
+#define GTEST_ADD_REFERENCE_(T) \
+    typename ::testing::internal::AddReference<T>::type
+
+// Adds a reference to const on top of T as necessary.  For example,
+// it transforms
+//
+//   char         ==> const char&
+//   const char   ==> const char&
+//   char&        ==> const char&
+//   const char&  ==> const char&
+//
+// The argument T must depend on some template parameters.
+#define GTEST_REFERENCE_TO_CONST_(T) \
+    GTEST_ADD_REFERENCE_(const GTEST_REMOVE_REFERENCE_(T))
+
+// ImplicitlyConvertible<From, To>::value is a compile-time bool
+// constant that's true iff type From can be implicitly converted to
+// type To.
+template <typename From, typename To>
+class ImplicitlyConvertible {
+ private:
+  // We need the following helper functions only for their types.
+  // They have no implementations.
+
+  // MakeFrom() is an expression whose type is From.  We cannot simply
+  // use From(), as the type From may not have a public default
+  // constructor.
+  static From MakeFrom();
+
+  // These two functions are overloaded.  Given an expression
+  // Helper(x), the compiler will pick the first version if x can be
+  // implicitly converted to type To; otherwise it will pick the
+  // second version.
+  //
+  // The first version returns a value of size 1, and the second
+  // version returns a value of size 2.  Therefore, by checking the
+  // size of Helper(x), which can be done at compile time, we can tell
+  // which version of Helper() is used, and hence whether x can be
+  // implicitly converted to type To.
+  static char Helper(To);
+  static char (&Helper(...))[2];  // NOLINT
+
+  // We have to put the 'public' section after the 'private' section,
+  // or MSVC refuses to compile the code.
+ public:
+  // MSVC warns about implicitly converting from double to int for
+  // possible loss of data, so we need to temporarily disable the
+  // warning.
+#ifdef _MSC_VER
+# pragma warning(push)          // Saves the current warning state.
+# pragma warning(disable:4244)  // Temporarily disables warning 4244.
+
+  static const bool value =
+      sizeof(Helper(ImplicitlyConvertible::MakeFrom())) == 1;
+# pragma warning(pop)           // Restores the warning state.
+#elif defined(__BORLANDC__)
+  // C++Builder cannot use member overload resolution during template
+  // instantiation.  The simplest workaround is to use its C++0x type traits
+  // functions (C++Builder 2009 and above only).
+  static const bool value = __is_convertible(From, To);
+#else
+  static const bool value =
+      sizeof(Helper(ImplicitlyConvertible::MakeFrom())) == 1;
+#endif  // _MSV_VER
+};
+template <typename From, typename To>
+const bool ImplicitlyConvertible<From, To>::value;
+
+// IsAProtocolMessage<T>::value is a compile-time bool constant that's
+// true iff T is type ProtocolMessage, proto2::Message, or a subclass
+// of those.
+template <typename T>
+struct IsAProtocolMessage
+    : public bool_constant<
+  ImplicitlyConvertible<const T*, const ::ProtocolMessage*>::value ||
+  ImplicitlyConvertible<const T*, const ::proto2::Message*>::value> {
+};
+
+// When the compiler sees expression IsContainerTest<C>(0), if C is an
+// STL-style container class, the first overload of IsContainerTest
+// will be viable (since both C::iterator* and C::const_iterator* are
+// valid types and NULL can be implicitly converted to them).  It will
+// be picked over the second overload as 'int' is a perfect match for
+// the type of argument 0.  If C::iterator or C::const_iterator is not
+// a valid type, the first overload is not viable, and the second
+// overload will be picked.  Therefore, we can determine whether C is
+// a container class by checking the type of IsContainerTest<C>(0).
+// The value of the expression is insignificant.
+//
+// Note that we look for both C::iterator and C::const_iterator.  The
+// reason is that C++ injects the name of a class as a member of the
+// class itself (e.g. you can refer to class iterator as either
+// 'iterator' or 'iterator::iterator').  If we look for C::iterator
+// only, for example, we would mistakenly think that a class named
+// iterator is an STL container.
+//
+// Also note that the simpler approach of overloading
+// IsContainerTest(typename C::const_iterator*) and
+// IsContainerTest(...) doesn't work with Visual Age C++ and Sun C++.
+typedef int IsContainer;
+template <class C>
+IsContainer IsContainerTest(int /* dummy */,
+                            typename C::iterator* /* it */ = NULL,
+                            typename C::const_iterator* /* const_it */ = NULL) {
+  return 0;
+}
+
+typedef char IsNotContainer;
+template <class C>
+IsNotContainer IsContainerTest(long /* dummy */) { return '\0'; }
+
+// EnableIf<condition>::type is void when 'Cond' is true, and
+// undefined when 'Cond' is false.  To use SFINAE to make a function
+// overload only apply when a particular expression is true, add
+// "typename EnableIf<expression>::type* = 0" as the last parameter.
+template<bool> struct EnableIf;
+template<> struct EnableIf<true> { typedef void type; };  // NOLINT
+
+// Utilities for native arrays.
+
+// ArrayEq() compares two k-dimensional native arrays using the
+// elements' operator==, where k can be any integer >= 0.  When k is
+// 0, ArrayEq() degenerates into comparing a single pair of values.
+
+template <typename T, typename U>
+bool ArrayEq(const T* lhs, size_t size, const U* rhs);
+
+// This generic version is used when k is 0.
+template <typename T, typename U>
+inline bool ArrayEq(const T& lhs, const U& rhs) { return lhs == rhs; }
+
+// This overload is used when k >= 1.
+template <typename T, typename U, size_t N>
+inline bool ArrayEq(const T(&lhs)[N], const U(&rhs)[N]) {
+  return internal::ArrayEq(lhs, N, rhs);
+}
+
+// This helper reduces code bloat.  If we instead put its logic inside
+// the previous ArrayEq() function, arrays with different sizes would
+// lead to different copies of the template code.
+template <typename T, typename U>
+bool ArrayEq(const T* lhs, size_t size, const U* rhs) {
+  for (size_t i = 0; i != size; i++) {
+    if (!internal::ArrayEq(lhs[i], rhs[i]))
+      return false;
+  }
+  return true;
+}
+
+// Finds the first element in the iterator range [begin, end) that
+// equals elem.  Element may be a native array type itself.
+template <typename Iter, typename Element>
+Iter ArrayAwareFind(Iter begin, Iter end, const Element& elem) {
+  for (Iter it = begin; it != end; ++it) {
+    if (internal::ArrayEq(*it, elem))
+      return it;
+  }
+  return end;
+}
+
+// CopyArray() copies a k-dimensional native array using the elements'
+// operator=, where k can be any integer >= 0.  When k is 0,
+// CopyArray() degenerates into copying a single value.
+
+template <typename T, typename U>
+void CopyArray(const T* from, size_t size, U* to);
+
+// This generic version is used when k is 0.
+template <typename T, typename U>
+inline void CopyArray(const T& from, U* to) { *to = from; }
+
+// This overload is used when k >= 1.
+template <typename T, typename U, size_t N>
+inline void CopyArray(const T(&from)[N], U(*to)[N]) {
+  internal::CopyArray(from, N, *to);
+}
+
+// This helper reduces code bloat.  If we instead put its logic inside
+// the previous CopyArray() function, arrays with different sizes
+// would lead to different copies of the template code.
+template <typename T, typename U>
+void CopyArray(const T* from, size_t size, U* to) {
+  for (size_t i = 0; i != size; i++) {
+    internal::CopyArray(from[i], to + i);
+  }
+}
+
+// The relation between an NativeArray object (see below) and the
+// native array it represents.
+enum RelationToSource {
+  kReference,  // The NativeArray references the native array.
+  kCopy        // The NativeArray makes a copy of the native array and
+               // owns the copy.
+};
+
+// Adapts a native array to a read-only STL-style container.  Instead
+// of the complete STL container concept, this adaptor only implements
+// members useful for Google Mock's container matchers.  New members
+// should be added as needed.  To simplify the implementation, we only
+// support Element being a raw type (i.e. having no top-level const or
+// reference modifier).  It's the client's responsibility to satisfy
+// this requirement.  Element can be an array type itself (hence
+// multi-dimensional arrays are supported).
+template <typename Element>
+class NativeArray {
+ public:
+  // STL-style container typedefs.
+  typedef Element value_type;
+  typedef Element* iterator;
+  typedef const Element* const_iterator;
+
+  // Constructs from a native array.
+  NativeArray(const Element* array, size_t count, RelationToSource relation) {
+    Init(array, count, relation);
+  }
+
+  // Copy constructor.
+  NativeArray(const NativeArray& rhs) {
+    Init(rhs.array_, rhs.size_, rhs.relation_to_source_);
+  }
+
+  ~NativeArray() {
+    // Ensures that the user doesn't instantiate NativeArray with a
+    // const or reference type.
+    static_cast<void>(StaticAssertTypeEqHelper<Element,
+        GTEST_REMOVE_REFERENCE_AND_CONST_(Element)>());
+    if (relation_to_source_ == kCopy)
+      delete[] array_;
+  }
+
+  // STL-style container methods.
+  size_t size() const { return size_; }
+  const_iterator begin() const { return array_; }
+  const_iterator end() const { return array_ + size_; }
+  bool operator==(const NativeArray& rhs) const {
+    return size() == rhs.size() &&
+        ArrayEq(begin(), size(), rhs.begin());
+  }
+
+ private:
+  // Initializes this object; makes a copy of the input array if
+  // 'relation' is kCopy.
+  void Init(const Element* array, size_t a_size, RelationToSource relation) {
+    if (relation == kReference) {
+      array_ = array;
+    } else {
+      Element* const copy = new Element[a_size];
+      CopyArray(array, a_size, copy);
+      array_ = copy;
+    }
+    size_ = a_size;
+    relation_to_source_ = relation;
+  }
+
+  const Element* array_;
+  size_t size_;
+  RelationToSource relation_to_source_;
+
+  GTEST_DISALLOW_ASSIGN_(NativeArray);
+};
+
+}  // namespace internal
+}  // namespace testing
+
+#define GTEST_MESSAGE_AT_(file, line, message, result_type) \
+  ::testing::internal::AssertHelper(result_type, file, line, message) \
+    = ::testing::Message()
+
+#define GTEST_MESSAGE_(message, result_type) \
+  GTEST_MESSAGE_AT_(__FILE__, __LINE__, message, result_type)
+
+#define GTEST_FATAL_FAILURE_(message) \
+  return GTEST_MESSAGE_(message, ::testing::TestPartResult::kFatalFailure)
+
+#define GTEST_NONFATAL_FAILURE_(message) \
+  GTEST_MESSAGE_(message, ::testing::TestPartResult::kNonFatalFailure)
+
+#define GTEST_SUCCESS_(message) \
+  GTEST_MESSAGE_(message, ::testing::TestPartResult::kSuccess)
+
+// Suppresses MSVC warnings 4072 (unreachable code) for the code following
+// statement if it returns or throws (or doesn't return or throw in some
+// situations).
+#define GTEST_SUPPRESS_UNREACHABLE_CODE_WARNING_BELOW_(statement) \
+  if (::testing::internal::AlwaysTrue()) { statement; }
+
+#define GTEST_TEST_THROW_(statement, expected_exception, fail) \
+  GTEST_AMBIGUOUS_ELSE_BLOCKER_ \
+  if (::testing::internal::ConstCharPtr gtest_msg = "") { \
+    bool gtest_caught_expected = false; \
+    try { \
+      GTEST_SUPPRESS_UNREACHABLE_CODE_WARNING_BELOW_(statement); \
+    } \
+    catch (expected_exception const&) { \
+      gtest_caught_expected = true; \
+    } \
+    catch (...) { \
+      gtest_msg.value = \
+          "Expected: " #statement " throws an exception of type " \
+          #expected_exception ".\n  Actual: it throws a different type."; \
+      goto GTEST_CONCAT_TOKEN_(gtest_label_testthrow_, __LINE__); \
+    } \
+    if (!gtest_caught_expected) { \
+      gtest_msg.value = \
+          "Expected: " #statement " throws an exception of type " \
+          #expected_exception ".\n  Actual: it throws nothing."; \
+      goto GTEST_CONCAT_TOKEN_(gtest_label_testthrow_, __LINE__); \
+    } \
+  } else \
+    GTEST_CONCAT_TOKEN_(gtest_label_testthrow_, __LINE__): \
+      fail(gtest_msg.value)
+
+#define GTEST_TEST_NO_THROW_(statement, fail) \
+  GTEST_AMBIGUOUS_ELSE_BLOCKER_ \
+  if (::testing::internal::AlwaysTrue()) { \
+    try { \
+      GTEST_SUPPRESS_UNREACHABLE_CODE_WARNING_BELOW_(statement); \
+    } \
+    catch (...) { \
+      goto GTEST_CONCAT_TOKEN_(gtest_label_testnothrow_, __LINE__); \
+    } \
+  } else \
+    GTEST_CONCAT_TOKEN_(gtest_label_testnothrow_, __LINE__): \
+      fail("Expected: " #statement " doesn't throw an exception.\n" \
+           "  Actual: it throws.")
+
+#define GTEST_TEST_ANY_THROW_(statement, fail) \
+  GTEST_AMBIGUOUS_ELSE_BLOCKER_ \
+  if (::testing::internal::AlwaysTrue()) { \
+    bool gtest_caught_any = false; \
+    try { \
+      GTEST_SUPPRESS_UNREACHABLE_CODE_WARNING_BELOW_(statement); \
+    } \
+    catch (...) { \
+      gtest_caught_any = true; \
+    } \
+    if (!gtest_caught_any) { \
+      goto GTEST_CONCAT_TOKEN_(gtest_label_testanythrow_, __LINE__); \
+    } \
+  } else \
+    GTEST_CONCAT_TOKEN_(gtest_label_testanythrow_, __LINE__): \
+      fail("Expected: " #statement " throws an exception.\n" \
+           "  Actual: it doesn't.")
+
+
+// Implements Boolean test assertions such as EXPECT_TRUE. expression can be
+// either a boolean expression or an AssertionResult. text is a textual
+// represenation of expression as it was passed into the EXPECT_TRUE.
+#define GTEST_TEST_BOOLEAN_(expression, text, actual, expected, fail) \
+  GTEST_AMBIGUOUS_ELSE_BLOCKER_ \
+  if (const ::testing::AssertionResult gtest_ar_ = \
+      ::testing::AssertionResult(expression)) \
+    ; \
+  else \
+    fail(::testing::internal::GetBoolAssertionFailureMessage(\
+        gtest_ar_, text, #actual, #expected).c_str())
+
+#define GTEST_TEST_NO_FATAL_FAILURE_(statement, fail) \
+  GTEST_AMBIGUOUS_ELSE_BLOCKER_ \
+  if (::testing::internal::AlwaysTrue()) { \
+    ::testing::internal::HasNewFatalFailureHelper gtest_fatal_failure_checker; \
+    GTEST_SUPPRESS_UNREACHABLE_CODE_WARNING_BELOW_(statement); \
+    if (gtest_fatal_failure_checker.has_new_fatal_failure()) { \
+      goto GTEST_CONCAT_TOKEN_(gtest_label_testnofatal_, __LINE__); \
+    } \
+  } else \
+    GTEST_CONCAT_TOKEN_(gtest_label_testnofatal_, __LINE__): \
+      fail("Expected: " #statement " doesn't generate new fatal " \
+           "failures in the current thread.\n" \
+           "  Actual: it does.")
+
+// Expands to the name of the class that implements the given test.
+#define GTEST_TEST_CLASS_NAME_(test_case_name, test_name) \
+  test_case_name##_##test_name##_Test
+
+// Helper macro for defining tests.
+#define GTEST_TEST_(test_case_name, test_name, parent_class, parent_id)\
+class GTEST_TEST_CLASS_NAME_(test_case_name, test_name) : public parent_class {\
+ public:\
+  GTEST_TEST_CLASS_NAME_(test_case_name, test_name)() {}\
+ private:\
+  virtual void TestBody();\
+  static ::testing::TestInfo* const test_info_ GTEST_ATTRIBUTE_UNUSED_;\
+  GTEST_DISALLOW_COPY_AND_ASSIGN_(\
+      GTEST_TEST_CLASS_NAME_(test_case_name, test_name));\
+};\
+\
+::testing::TestInfo* const GTEST_TEST_CLASS_NAME_(test_case_name, test_name)\
+  ::test_info_ =\
+    ::testing::internal::MakeAndRegisterTestInfo(\
+        #test_case_name, #test_name, NULL, NULL, \
+        (parent_id), \
+        parent_class::SetUpTestCase, \
+        parent_class::TearDownTestCase, \
+        new ::testing::internal::TestFactoryImpl<\
+            GTEST_TEST_CLASS_NAME_(test_case_name, test_name)>);\
+void GTEST_TEST_CLASS_NAME_(test_case_name, test_name)::TestBody()
+
+#endif  // GTEST_INCLUDE_GTEST_INTERNAL_GTEST_INTERNAL_H_
diff --git a/test/gtest/include/gtest/internal/gtest-linked_ptr.h b/test/gtest/include/gtest/internal/gtest-linked_ptr.h
new file mode 100644
index 0000000..b1362cd
--- /dev/null
+++ b/test/gtest/include/gtest/internal/gtest-linked_ptr.h
@@ -0,0 +1,233 @@
+// Copyright 2003 Google Inc.
+// All rights reserved.
+//
+// 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.
+//
+// Authors: Dan Egnor (egnor at google.com)
+//
+// A "smart" pointer type with reference tracking.  Every pointer to a
+// particular object is kept on a circular linked list.  When the last pointer
+// to an object is destroyed or reassigned, the object is deleted.
+//
+// Used properly, this deletes the object when the last reference goes away.
+// There are several caveats:
+// - Like all reference counting schemes, cycles lead to leaks.
+// - Each smart pointer is actually two pointers (8 bytes instead of 4).
+// - Every time a pointer is assigned, the entire list of pointers to that
+//   object is traversed.  This class is therefore NOT SUITABLE when there
+//   will often be more than two or three pointers to a particular object.
+// - References are only tracked as long as linked_ptr<> objects are copied.
+//   If a linked_ptr<> is converted to a raw pointer and back, BAD THINGS
+//   will happen (double deletion).
+//
+// A good use of this class is storing object references in STL containers.
+// You can safely put linked_ptr<> in a vector<>.
+// Other uses may not be as good.
+//
+// Note: If you use an incomplete type with linked_ptr<>, the class
+// *containing* linked_ptr<> must have a constructor and destructor (even
+// if they do nothing!).
+//
+// Bill Gibbons suggested we use something like this.
+//
+// Thread Safety:
+//   Unlike other linked_ptr implementations, in this implementation
+//   a linked_ptr object is thread-safe in the sense that:
+//     - it's safe to copy linked_ptr objects concurrently,
+//     - it's safe to copy *from* a linked_ptr and read its underlying
+//       raw pointer (e.g. via get()) concurrently, and
+//     - it's safe to write to two linked_ptrs that point to the same
+//       shared object concurrently.
+// TODO(wan at google.com): rename this to safe_linked_ptr to avoid
+// confusion with normal linked_ptr.
+
+#ifndef GTEST_INCLUDE_GTEST_INTERNAL_GTEST_LINKED_PTR_H_
+#define GTEST_INCLUDE_GTEST_INTERNAL_GTEST_LINKED_PTR_H_
+
+#include <stdlib.h>
+#include <assert.h>
+
+#include "gtest/internal/gtest-port.h"
+
+namespace testing {
+namespace internal {
+
+// Protects copying of all linked_ptr objects.
+GTEST_API_ GTEST_DECLARE_STATIC_MUTEX_(g_linked_ptr_mutex);
+
+// This is used internally by all instances of linked_ptr<>.  It needs to be
+// a non-template class because different types of linked_ptr<> can refer to
+// the same object (linked_ptr<Superclass>(obj) vs linked_ptr<Subclass>(obj)).
+// So, it needs to be possible for different types of linked_ptr to participate
+// in the same circular linked list, so we need a single class type here.
+//
+// DO NOT USE THIS CLASS DIRECTLY YOURSELF.  Use linked_ptr<T>.
+class linked_ptr_internal {
+ public:
+  // Create a new circle that includes only this instance.
+  void join_new() {
+    next_ = this;
+  }
+
+  // Many linked_ptr operations may change p.link_ for some linked_ptr
+  // variable p in the same circle as this object.  Therefore we need
+  // to prevent two such operations from occurring concurrently.
+  //
+  // Note that different types of linked_ptr objects can coexist in a
+  // circle (e.g. linked_ptr<Base>, linked_ptr<Derived1>, and
+  // linked_ptr<Derived2>).  Therefore we must use a single mutex to
+  // protect all linked_ptr objects.  This can create serious
+  // contention in production code, but is acceptable in a testing
+  // framework.
+
+  // Join an existing circle.
+  void join(linked_ptr_internal const* ptr)
+      GTEST_LOCK_EXCLUDED_(g_linked_ptr_mutex) {
+    MutexLock lock(&g_linked_ptr_mutex);
+
+    linked_ptr_internal const* p = ptr;
+    while (p->next_ != ptr) p = p->next_;
+    p->next_ = this;
+    next_ = ptr;
+  }
+
+  // Leave whatever circle we're part of.  Returns true if we were the
+  // last member of the circle.  Once this is done, you can join() another.
+  bool depart()
+      GTEST_LOCK_EXCLUDED_(g_linked_ptr_mutex) {
+    MutexLock lock(&g_linked_ptr_mutex);
+
+    if (next_ == this) return true;
+    linked_ptr_internal const* p = next_;
+    while (p->next_ != this) p = p->next_;
+    p->next_ = next_;
+    return false;
+  }
+
+ private:
+  mutable linked_ptr_internal const* next_;
+};
+
+template <typename T>
+class linked_ptr {
+ public:
+  typedef T element_type;
+
+  // Take over ownership of a raw pointer.  This should happen as soon as
+  // possible after the object is created.
+  explicit linked_ptr(T* ptr = NULL) { capture(ptr); }
+  ~linked_ptr() { depart(); }
+
+  // Copy an existing linked_ptr<>, adding ourselves to the list of references.
+  template <typename U> linked_ptr(linked_ptr<U> const& ptr) { copy(&ptr); }
+  linked_ptr(linked_ptr const& ptr) {  // NOLINT
+    assert(&ptr != this);
+    copy(&ptr);
+  }
+
+  // Assignment releases the old value and acquires the new.
+  template <typename U> linked_ptr& operator=(linked_ptr<U> const& ptr) {
+    depart();
+    copy(&ptr);
+    return *this;
+  }
+
+  linked_ptr& operator=(linked_ptr const& ptr) {
+    if (&ptr != this) {
+      depart();
+      copy(&ptr);
+    }
+    return *this;
+  }
+
+  // Smart pointer members.
+  void reset(T* ptr = NULL) {
+    depart();
+    capture(ptr);
+  }
+  T* get() const { return value_; }
+  T* operator->() const { return value_; }
+  T& operator*() const { return *value_; }
+
+  bool operator==(T* p) const { return value_ == p; }
+  bool operator!=(T* p) const { return value_ != p; }
+  template <typename U>
+  bool operator==(linked_ptr<U> const& ptr) const {
+    return value_ == ptr.get();
+  }
+  template <typename U>
+  bool operator!=(linked_ptr<U> const& ptr) const {
+    return value_ != ptr.get();
+  }
+
+ private:
+  template <typename U>
+  friend class linked_ptr;
+
+  T* value_;
+  linked_ptr_internal link_;
+
+  void depart() {
+    if (link_.depart()) delete value_;
+  }
+
+  void capture(T* ptr) {
+    value_ = ptr;
+    link_.join_new();
+  }
+
+  template <typename U> void copy(linked_ptr<U> const* ptr) {
+    value_ = ptr->get();
+    if (value_)
+      link_.join(&ptr->link_);
+    else
+      link_.join_new();
+  }
+};
+
+template<typename T> inline
+bool operator==(T* ptr, const linked_ptr<T>& x) {
+  return ptr == x.get();
+}
+
+template<typename T> inline
+bool operator!=(T* ptr, const linked_ptr<T>& x) {
+  return ptr != x.get();
+}
+
+// A function to convert T* into linked_ptr<T>
+// Doing e.g. make_linked_ptr(new FooBarBaz<type>(arg)) is a shorter notation
+// for linked_ptr<FooBarBaz<type> >(new FooBarBaz<type>(arg))
+template <typename T>
+linked_ptr<T> make_linked_ptr(T* ptr) {
+  return linked_ptr<T>(ptr);
+}
+
+}  // namespace internal
+}  // namespace testing
+
+#endif  // GTEST_INCLUDE_GTEST_INTERNAL_GTEST_LINKED_PTR_H_
diff --git a/test/gtest/include/gtest/internal/gtest-param-util-generated.h b/test/gtest/include/gtest/internal/gtest-param-util-generated.h
new file mode 100644
index 0000000..e805485
--- /dev/null
+++ b/test/gtest/include/gtest/internal/gtest-param-util-generated.h
@@ -0,0 +1,5143 @@
+// This file was GENERATED by command:
+//     pump.py gtest-param-util-generated.h.pump
+// DO NOT EDIT BY HAND!!!
+
+// Copyright 2008 Google Inc.
+// All Rights Reserved.
+//
+// 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: vladl at google.com (Vlad Losev)
+
+// Type and function utilities for implementing parameterized tests.
+// This file is generated by a SCRIPT.  DO NOT EDIT BY HAND!
+//
+// Currently Google Test supports at most 50 arguments in Values,
+// and at most 10 arguments in Combine. Please contact
+// googletestframework at googlegroups.com if you need more.
+// Please note that the number of arguments to Combine is limited
+// by the maximum arity of the implementation of tr1::tuple which is
+// currently set at 10.
+
+#ifndef GTEST_INCLUDE_GTEST_INTERNAL_GTEST_PARAM_UTIL_GENERATED_H_
+#define GTEST_INCLUDE_GTEST_INTERNAL_GTEST_PARAM_UTIL_GENERATED_H_
+
+// scripts/fuse_gtest.py depends on gtest's own header being #included
+// *unconditionally*.  Therefore these #includes cannot be moved
+// inside #if GTEST_HAS_PARAM_TEST.
+#include "gtest/internal/gtest-param-util.h"
+#include "gtest/internal/gtest-port.h"
+
+#if GTEST_HAS_PARAM_TEST
+
+namespace testing {
+
+// Forward declarations of ValuesIn(), which is implemented in
+// include/gtest/gtest-param-test.h.
+template <typename ForwardIterator>
+internal::ParamGenerator<
+  typename ::testing::internal::IteratorTraits<ForwardIterator>::value_type>
+ValuesIn(ForwardIterator begin, ForwardIterator end);
+
+template <typename T, size_t N>
+internal::ParamGenerator<T> ValuesIn(const T (&array)[N]);
+
+template <class Container>
+internal::ParamGenerator<typename Container::value_type> ValuesIn(
+    const Container& container);
+
+namespace internal {
+
+// Used in the Values() function to provide polymorphic capabilities.
+template <typename T1>
+class ValueArray1 {
+ public:
+  explicit ValueArray1(T1 v1) : v1_(v1) {}
+
+  template <typename T>
+  operator ParamGenerator<T>() const { return ValuesIn(&v1_, &v1_ + 1); }
+
+ private:
+  // No implementation - assignment is unsupported.
+  void operator=(const ValueArray1& other);
+
+  const T1 v1_;
+};
+
+template <typename T1, typename T2>
+class ValueArray2 {
+ public:
+  ValueArray2(T1 v1, T2 v2) : v1_(v1), v2_(v2) {}
+
+  template <typename T>
+  operator ParamGenerator<T>() const {
+    const T array[] = {static_cast<T>(v1_), static_cast<T>(v2_)};
+    return ValuesIn(array);
+  }
+
+ private:
+  // No implementation - assignment is unsupported.
+  void operator=(const ValueArray2& other);
+
+  const T1 v1_;
+  const T2 v2_;
+};
+
+template <typename T1, typename T2, typename T3>
+class ValueArray3 {
+ public:
+  ValueArray3(T1 v1, T2 v2, T3 v3) : v1_(v1), v2_(v2), v3_(v3) {}
+
+  template <typename T>
+  operator ParamGenerator<T>() const {
+    const T array[] = {static_cast<T>(v1_), static_cast<T>(v2_),
+        static_cast<T>(v3_)};
+    return ValuesIn(array);
+  }
+
+ private:
+  // No implementation - assignment is unsupported.
+  void operator=(const ValueArray3& other);
+
+  const T1 v1_;
+  const T2 v2_;
+  const T3 v3_;
+};
+
+template <typename T1, typename T2, typename T3, typename T4>
+class ValueArray4 {
+ public:
+  ValueArray4(T1 v1, T2 v2, T3 v3, T4 v4) : v1_(v1), v2_(v2), v3_(v3),
+      v4_(v4) {}
+
+  template <typename T>
+  operator ParamGenerator<T>() const {
+    const T array[] = {static_cast<T>(v1_), static_cast<T>(v2_),
+        static_cast<T>(v3_), static_cast<T>(v4_)};
+    return ValuesIn(array);
+  }
+
+ private:
+  // No implementation - assignment is unsupported.
+  void operator=(const ValueArray4& other);
+
+  const T1 v1_;
+  const T2 v2_;
+  const T3 v3_;
+  const T4 v4_;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5>
+class ValueArray5 {
+ public:
+  ValueArray5(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5) : v1_(v1), v2_(v2), v3_(v3),
+      v4_(v4), v5_(v5) {}
+
+  template <typename T>
+  operator ParamGenerator<T>() const {
+    const T array[] = {static_cast<T>(v1_), static_cast<T>(v2_),
+        static_cast<T>(v3_), static_cast<T>(v4_), static_cast<T>(v5_)};
+    return ValuesIn(array);
+  }
+
+ private:
+  // No implementation - assignment is unsupported.
+  void operator=(const ValueArray5& other);
+
+  const T1 v1_;
+  const T2 v2_;
+  const T3 v3_;
+  const T4 v4_;
+  const T5 v5_;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6>
+class ValueArray6 {
+ public:
+  ValueArray6(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6) : v1_(v1), v2_(v2),
+      v3_(v3), v4_(v4), v5_(v5), v6_(v6) {}
+
+  template <typename T>
+  operator ParamGenerator<T>() const {
+    const T array[] = {static_cast<T>(v1_), static_cast<T>(v2_),
+        static_cast<T>(v3_), static_cast<T>(v4_), static_cast<T>(v5_),
+        static_cast<T>(v6_)};
+    return ValuesIn(array);
+  }
+
+ private:
+  // No implementation - assignment is unsupported.
+  void operator=(const ValueArray6& other);
+
+  const T1 v1_;
+  const T2 v2_;
+  const T3 v3_;
+  const T4 v4_;
+  const T5 v5_;
+  const T6 v6_;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7>
+class ValueArray7 {
+ public:
+  ValueArray7(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7) : v1_(v1),
+      v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7) {}
+
+  template <typename T>
+  operator ParamGenerator<T>() const {
+    const T array[] = {static_cast<T>(v1_), static_cast<T>(v2_),
+        static_cast<T>(v3_), static_cast<T>(v4_), static_cast<T>(v5_),
+        static_cast<T>(v6_), static_cast<T>(v7_)};
+    return ValuesIn(array);
+  }
+
+ private:
+  // No implementation - assignment is unsupported.
+  void operator=(const ValueArray7& other);
+
+  const T1 v1_;
+  const T2 v2_;
+  const T3 v3_;
+  const T4 v4_;
+  const T5 v5_;
+  const T6 v6_;
+  const T7 v7_;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8>
+class ValueArray8 {
+ public:
+  ValueArray8(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7,
+      T8 v8) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7),
+      v8_(v8) {}
+
+  template <typename T>
+  operator ParamGenerator<T>() const {
+    const T array[] = {static_cast<T>(v1_), static_cast<T>(v2_),
+        static_cast<T>(v3_), static_cast<T>(v4_), static_cast<T>(v5_),
+        static_cast<T>(v6_), static_cast<T>(v7_), static_cast<T>(v8_)};
+    return ValuesIn(array);
+  }
+
+ private:
+  // No implementation - assignment is unsupported.
+  void operator=(const ValueArray8& other);
+
+  const T1 v1_;
+  const T2 v2_;
+  const T3 v3_;
+  const T4 v4_;
+  const T5 v5_;
+  const T6 v6_;
+  const T7 v7_;
+  const T8 v8_;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9>
+class ValueArray9 {
+ public:
+  ValueArray9(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8,
+      T9 v9) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7),
+      v8_(v8), v9_(v9) {}
+
+  template <typename T>
+  operator ParamGenerator<T>() const {
+    const T array[] = {static_cast<T>(v1_), static_cast<T>(v2_),
+        static_cast<T>(v3_), static_cast<T>(v4_), static_cast<T>(v5_),
+        static_cast<T>(v6_), static_cast<T>(v7_), static_cast<T>(v8_),
+        static_cast<T>(v9_)};
+    return ValuesIn(array);
+  }
+
+ private:
+  // No implementation - assignment is unsupported.
+  void operator=(const ValueArray9& other);
+
+  const T1 v1_;
+  const T2 v2_;
+  const T3 v3_;
+  const T4 v4_;
+  const T5 v5_;
+  const T6 v6_;
+  const T7 v7_;
+  const T8 v8_;
+  const T9 v9_;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10>
+class ValueArray10 {
+ public:
+  ValueArray10(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9,
+      T10 v10) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7),
+      v8_(v8), v9_(v9), v10_(v10) {}
+
+  template <typename T>
+  operator ParamGenerator<T>() const {
+    const T array[] = {static_cast<T>(v1_), static_cast<T>(v2_),
+        static_cast<T>(v3_), static_cast<T>(v4_), static_cast<T>(v5_),
+        static_cast<T>(v6_), static_cast<T>(v7_), static_cast<T>(v8_),
+        static_cast<T>(v9_), static_cast<T>(v10_)};
+    return ValuesIn(array);
+  }
+
+ private:
+  // No implementation - assignment is unsupported.
+  void operator=(const ValueArray10& other);
+
+  const T1 v1_;
+  const T2 v2_;
+  const T3 v3_;
+  const T4 v4_;
+  const T5 v5_;
+  const T6 v6_;
+  const T7 v7_;
+  const T8 v8_;
+  const T9 v9_;
+  const T10 v10_;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11>
+class ValueArray11 {
+ public:
+  ValueArray11(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9,
+      T10 v10, T11 v11) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6),
+      v7_(v7), v8_(v8), v9_(v9), v10_(v10), v11_(v11) {}
+
+  template <typename T>
+  operator ParamGenerator<T>() const {
+    const T array[] = {static_cast<T>(v1_), static_cast<T>(v2_),
+        static_cast<T>(v3_), static_cast<T>(v4_), static_cast<T>(v5_),
+        static_cast<T>(v6_), static_cast<T>(v7_), static_cast<T>(v8_),
+        static_cast<T>(v9_), static_cast<T>(v10_), static_cast<T>(v11_)};
+    return ValuesIn(array);
+  }
+
+ private:
+  // No implementation - assignment is unsupported.
+  void operator=(const ValueArray11& other);
+
+  const T1 v1_;
+  const T2 v2_;
+  const T3 v3_;
+  const T4 v4_;
+  const T5 v5_;
+  const T6 v6_;
+  const T7 v7_;
+  const T8 v8_;
+  const T9 v9_;
+  const T10 v10_;
+  const T11 v11_;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12>
+class ValueArray12 {
+ public:
+  ValueArray12(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9,
+      T10 v10, T11 v11, T12 v12) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), v5_(v5),
+      v6_(v6), v7_(v7), v8_(v8), v9_(v9), v10_(v10), v11_(v11), v12_(v12) {}
+
+  template <typename T>
+  operator ParamGenerator<T>() const {
+    const T array[] = {static_cast<T>(v1_), static_cast<T>(v2_),
+        static_cast<T>(v3_), static_cast<T>(v4_), static_cast<T>(v5_),
+        static_cast<T>(v6_), static_cast<T>(v7_), static_cast<T>(v8_),
+        static_cast<T>(v9_), static_cast<T>(v10_), static_cast<T>(v11_),
+        static_cast<T>(v12_)};
+    return ValuesIn(array);
+  }
+
+ private:
+  // No implementation - assignment is unsupported.
+  void operator=(const ValueArray12& other);
+
+  const T1 v1_;
+  const T2 v2_;
+  const T3 v3_;
+  const T4 v4_;
+  const T5 v5_;
+  const T6 v6_;
+  const T7 v7_;
+  const T8 v8_;
+  const T9 v9_;
+  const T10 v10_;
+  const T11 v11_;
+  const T12 v12_;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13>
+class ValueArray13 {
+ public:
+  ValueArray13(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9,
+      T10 v10, T11 v11, T12 v12, T13 v13) : v1_(v1), v2_(v2), v3_(v3), v4_(v4),
+      v5_(v5), v6_(v6), v7_(v7), v8_(v8), v9_(v9), v10_(v10), v11_(v11),
+      v12_(v12), v13_(v13) {}
+
+  template <typename T>
+  operator ParamGenerator<T>() const {
+    const T array[] = {static_cast<T>(v1_), static_cast<T>(v2_),
+        static_cast<T>(v3_), static_cast<T>(v4_), static_cast<T>(v5_),
+        static_cast<T>(v6_), static_cast<T>(v7_), static_cast<T>(v8_),
+        static_cast<T>(v9_), static_cast<T>(v10_), static_cast<T>(v11_),
+        static_cast<T>(v12_), static_cast<T>(v13_)};
+    return ValuesIn(array);
+  }
+
+ private:
+  // No implementation - assignment is unsupported.
+  void operator=(const ValueArray13& other);
+
+  const T1 v1_;
+  const T2 v2_;
+  const T3 v3_;
+  const T4 v4_;
+  const T5 v5_;
+  const T6 v6_;
+  const T7 v7_;
+  const T8 v8_;
+  const T9 v9_;
+  const T10 v10_;
+  const T11 v11_;
+  const T12 v12_;
+  const T13 v13_;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14>
+class ValueArray14 {
+ public:
+  ValueArray14(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9,
+      T10 v10, T11 v11, T12 v12, T13 v13, T14 v14) : v1_(v1), v2_(v2), v3_(v3),
+      v4_(v4), v5_(v5), v6_(v6), v7_(v7), v8_(v8), v9_(v9), v10_(v10),
+      v11_(v11), v12_(v12), v13_(v13), v14_(v14) {}
+
+  template <typename T>
+  operator ParamGenerator<T>() const {
+    const T array[] = {static_cast<T>(v1_), static_cast<T>(v2_),
+        static_cast<T>(v3_), static_cast<T>(v4_), static_cast<T>(v5_),
+        static_cast<T>(v6_), static_cast<T>(v7_), static_cast<T>(v8_),
+        static_cast<T>(v9_), static_cast<T>(v10_), static_cast<T>(v11_),
+        static_cast<T>(v12_), static_cast<T>(v13_), static_cast<T>(v14_)};
+    return ValuesIn(array);
+  }
+
+ private:
+  // No implementation - assignment is unsupported.
+  void operator=(const ValueArray14& other);
+
+  const T1 v1_;
+  const T2 v2_;
+  const T3 v3_;
+  const T4 v4_;
+  const T5 v5_;
+  const T6 v6_;
+  const T7 v7_;
+  const T8 v8_;
+  const T9 v9_;
+  const T10 v10_;
+  const T11 v11_;
+  const T12 v12_;
+  const T13 v13_;
+  const T14 v14_;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15>
+class ValueArray15 {
+ public:
+  ValueArray15(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9,
+      T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15) : v1_(v1), v2_(v2),
+      v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7), v8_(v8), v9_(v9), v10_(v10),
+      v11_(v11), v12_(v12), v13_(v13), v14_(v14), v15_(v15) {}
+
+  template <typename T>
+  operator ParamGenerator<T>() const {
+    const T array[] = {static_cast<T>(v1_), static_cast<T>(v2_),
+        static_cast<T>(v3_), static_cast<T>(v4_), static_cast<T>(v5_),
+        static_cast<T>(v6_), static_cast<T>(v7_), static_cast<T>(v8_),
+        static_cast<T>(v9_), static_cast<T>(v10_), static_cast<T>(v11_),
+        static_cast<T>(v12_), static_cast<T>(v13_), static_cast<T>(v14_),
+        static_cast<T>(v15_)};
+    return ValuesIn(array);
+  }
+
+ private:
+  // No implementation - assignment is unsupported.
+  void operator=(const ValueArray15& other);
+
+  const T1 v1_;
+  const T2 v2_;
+  const T3 v3_;
+  const T4 v4_;
+  const T5 v5_;
+  const T6 v6_;
+  const T7 v7_;
+  const T8 v8_;
+  const T9 v9_;
+  const T10 v10_;
+  const T11 v11_;
+  const T12 v12_;
+  const T13 v13_;
+  const T14 v14_;
+  const T15 v15_;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16>
+class ValueArray16 {
+ public:
+  ValueArray16(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9,
+      T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16) : v1_(v1),
+      v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7), v8_(v8), v9_(v9),
+      v10_(v10), v11_(v11), v12_(v12), v13_(v13), v14_(v14), v15_(v15),
+      v16_(v16) {}
+
+  template <typename T>
+  operator ParamGenerator<T>() const {
+    const T array[] = {static_cast<T>(v1_), static_cast<T>(v2_),
+        static_cast<T>(v3_), static_cast<T>(v4_), static_cast<T>(v5_),
+        static_cast<T>(v6_), static_cast<T>(v7_), static_cast<T>(v8_),
+        static_cast<T>(v9_), static_cast<T>(v10_), static_cast<T>(v11_),
+        static_cast<T>(v12_), static_cast<T>(v13_), static_cast<T>(v14_),
+        static_cast<T>(v15_), static_cast<T>(v16_)};
+    return ValuesIn(array);
+  }
+
+ private:
+  // No implementation - assignment is unsupported.
+  void operator=(const ValueArray16& other);
+
+  const T1 v1_;
+  const T2 v2_;
+  const T3 v3_;
+  const T4 v4_;
+  const T5 v5_;
+  const T6 v6_;
+  const T7 v7_;
+  const T8 v8_;
+  const T9 v9_;
+  const T10 v10_;
+  const T11 v11_;
+  const T12 v12_;
+  const T13 v13_;
+  const T14 v14_;
+  const T15 v15_;
+  const T16 v16_;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17>
+class ValueArray17 {
+ public:
+  ValueArray17(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9,
+      T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16,
+      T17 v17) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7),
+      v8_(v8), v9_(v9), v10_(v10), v11_(v11), v12_(v12), v13_(v13), v14_(v14),
+      v15_(v15), v16_(v16), v17_(v17) {}
+
+  template <typename T>
+  operator ParamGenerator<T>() const {
+    const T array[] = {static_cast<T>(v1_), static_cast<T>(v2_),
+        static_cast<T>(v3_), static_cast<T>(v4_), static_cast<T>(v5_),
+        static_cast<T>(v6_), static_cast<T>(v7_), static_cast<T>(v8_),
+        static_cast<T>(v9_), static_cast<T>(v10_), static_cast<T>(v11_),
+        static_cast<T>(v12_), static_cast<T>(v13_), static_cast<T>(v14_),
+        static_cast<T>(v15_), static_cast<T>(v16_), static_cast<T>(v17_)};
+    return ValuesIn(array);
+  }
+
+ private:
+  // No implementation - assignment is unsupported.
+  void operator=(const ValueArray17& other);
+
+  const T1 v1_;
+  const T2 v2_;
+  const T3 v3_;
+  const T4 v4_;
+  const T5 v5_;
+  const T6 v6_;
+  const T7 v7_;
+  const T8 v8_;
+  const T9 v9_;
+  const T10 v10_;
+  const T11 v11_;
+  const T12 v12_;
+  const T13 v13_;
+  const T14 v14_;
+  const T15 v15_;
+  const T16 v16_;
+  const T17 v17_;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18>
+class ValueArray18 {
+ public:
+  ValueArray18(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9,
+      T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17,
+      T18 v18) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7),
+      v8_(v8), v9_(v9), v10_(v10), v11_(v11), v12_(v12), v13_(v13), v14_(v14),
+      v15_(v15), v16_(v16), v17_(v17), v18_(v18) {}
+
+  template <typename T>
+  operator ParamGenerator<T>() const {
+    const T array[] = {static_cast<T>(v1_), static_cast<T>(v2_),
+        static_cast<T>(v3_), static_cast<T>(v4_), static_cast<T>(v5_),
+        static_cast<T>(v6_), static_cast<T>(v7_), static_cast<T>(v8_),
+        static_cast<T>(v9_), static_cast<T>(v10_), static_cast<T>(v11_),
+        static_cast<T>(v12_), static_cast<T>(v13_), static_cast<T>(v14_),
+        static_cast<T>(v15_), static_cast<T>(v16_), static_cast<T>(v17_),
+        static_cast<T>(v18_)};
+    return ValuesIn(array);
+  }
+
+ private:
+  // No implementation - assignment is unsupported.
+  void operator=(const ValueArray18& other);
+
+  const T1 v1_;
+  const T2 v2_;
+  const T3 v3_;
+  const T4 v4_;
+  const T5 v5_;
+  const T6 v6_;
+  const T7 v7_;
+  const T8 v8_;
+  const T9 v9_;
+  const T10 v10_;
+  const T11 v11_;
+  const T12 v12_;
+  const T13 v13_;
+  const T14 v14_;
+  const T15 v15_;
+  const T16 v16_;
+  const T17 v17_;
+  const T18 v18_;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19>
+class ValueArray19 {
+ public:
+  ValueArray19(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9,
+      T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17,
+      T18 v18, T19 v19) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6),
+      v7_(v7), v8_(v8), v9_(v9), v10_(v10), v11_(v11), v12_(v12), v13_(v13),
+      v14_(v14), v15_(v15), v16_(v16), v17_(v17), v18_(v18), v19_(v19) {}
+
+  template <typename T>
+  operator ParamGenerator<T>() const {
+    const T array[] = {static_cast<T>(v1_), static_cast<T>(v2_),
+        static_cast<T>(v3_), static_cast<T>(v4_), static_cast<T>(v5_),
+        static_cast<T>(v6_), static_cast<T>(v7_), static_cast<T>(v8_),
+        static_cast<T>(v9_), static_cast<T>(v10_), static_cast<T>(v11_),
+        static_cast<T>(v12_), static_cast<T>(v13_), static_cast<T>(v14_),
+        static_cast<T>(v15_), static_cast<T>(v16_), static_cast<T>(v17_),
+        static_cast<T>(v18_), static_cast<T>(v19_)};
+    return ValuesIn(array);
+  }
+
+ private:
+  // No implementation - assignment is unsupported.
+  void operator=(const ValueArray19& other);
+
+  const T1 v1_;
+  const T2 v2_;
+  const T3 v3_;
+  const T4 v4_;
+  const T5 v5_;
+  const T6 v6_;
+  const T7 v7_;
+  const T8 v8_;
+  const T9 v9_;
+  const T10 v10_;
+  const T11 v11_;
+  const T12 v12_;
+  const T13 v13_;
+  const T14 v14_;
+  const T15 v15_;
+  const T16 v16_;
+  const T17 v17_;
+  const T18 v18_;
+  const T19 v19_;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20>
+class ValueArray20 {
+ public:
+  ValueArray20(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9,
+      T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17,
+      T18 v18, T19 v19, T20 v20) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), v5_(v5),
+      v6_(v6), v7_(v7), v8_(v8), v9_(v9), v10_(v10), v11_(v11), v12_(v12),
+      v13_(v13), v14_(v14), v15_(v15), v16_(v16), v17_(v17), v18_(v18),
+      v19_(v19), v20_(v20) {}
+
+  template <typename T>
+  operator ParamGenerator<T>() const {
+    const T array[] = {static_cast<T>(v1_), static_cast<T>(v2_),
+        static_cast<T>(v3_), static_cast<T>(v4_), static_cast<T>(v5_),
+        static_cast<T>(v6_), static_cast<T>(v7_), static_cast<T>(v8_),
+        static_cast<T>(v9_), static_cast<T>(v10_), static_cast<T>(v11_),
+        static_cast<T>(v12_), static_cast<T>(v13_), static_cast<T>(v14_),
+        static_cast<T>(v15_), static_cast<T>(v16_), static_cast<T>(v17_),
+        static_cast<T>(v18_), static_cast<T>(v19_), static_cast<T>(v20_)};
+    return ValuesIn(array);
+  }
+
+ private:
+  // No implementation - assignment is unsupported.
+  void operator=(const ValueArray20& other);
+
+  const T1 v1_;
+  const T2 v2_;
+  const T3 v3_;
+  const T4 v4_;
+  const T5 v5_;
+  const T6 v6_;
+  const T7 v7_;
+  const T8 v8_;
+  const T9 v9_;
+  const T10 v10_;
+  const T11 v11_;
+  const T12 v12_;
+  const T13 v13_;
+  const T14 v14_;
+  const T15 v15_;
+  const T16 v16_;
+  const T17 v17_;
+  const T18 v18_;
+  const T19 v19_;
+  const T20 v20_;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21>
+class ValueArray21 {
+ public:
+  ValueArray21(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9,
+      T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17,
+      T18 v18, T19 v19, T20 v20, T21 v21) : v1_(v1), v2_(v2), v3_(v3), v4_(v4),
+      v5_(v5), v6_(v6), v7_(v7), v8_(v8), v9_(v9), v10_(v10), v11_(v11),
+      v12_(v12), v13_(v13), v14_(v14), v15_(v15), v16_(v16), v17_(v17),
+      v18_(v18), v19_(v19), v20_(v20), v21_(v21) {}
+
+  template <typename T>
+  operator ParamGenerator<T>() const {
+    const T array[] = {static_cast<T>(v1_), static_cast<T>(v2_),
+        static_cast<T>(v3_), static_cast<T>(v4_), static_cast<T>(v5_),
+        static_cast<T>(v6_), static_cast<T>(v7_), static_cast<T>(v8_),
+        static_cast<T>(v9_), static_cast<T>(v10_), static_cast<T>(v11_),
+        static_cast<T>(v12_), static_cast<T>(v13_), static_cast<T>(v14_),
+        static_cast<T>(v15_), static_cast<T>(v16_), static_cast<T>(v17_),
+        static_cast<T>(v18_), static_cast<T>(v19_), static_cast<T>(v20_),
+        static_cast<T>(v21_)};
+    return ValuesIn(array);
+  }
+
+ private:
+  // No implementation - assignment is unsupported.
+  void operator=(const ValueArray21& other);
+
+  const T1 v1_;
+  const T2 v2_;
+  const T3 v3_;
+  const T4 v4_;
+  const T5 v5_;
+  const T6 v6_;
+  const T7 v7_;
+  const T8 v8_;
+  const T9 v9_;
+  const T10 v10_;
+  const T11 v11_;
+  const T12 v12_;
+  const T13 v13_;
+  const T14 v14_;
+  const T15 v15_;
+  const T16 v16_;
+  const T17 v17_;
+  const T18 v18_;
+  const T19 v19_;
+  const T20 v20_;
+  const T21 v21_;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22>
+class ValueArray22 {
+ public:
+  ValueArray22(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9,
+      T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17,
+      T18 v18, T19 v19, T20 v20, T21 v21, T22 v22) : v1_(v1), v2_(v2), v3_(v3),
+      v4_(v4), v5_(v5), v6_(v6), v7_(v7), v8_(v8), v9_(v9), v10_(v10),
+      v11_(v11), v12_(v12), v13_(v13), v14_(v14), v15_(v15), v16_(v16),
+      v17_(v17), v18_(v18), v19_(v19), v20_(v20), v21_(v21), v22_(v22) {}
+
+  template <typename T>
+  operator ParamGenerator<T>() const {
+    const T array[] = {static_cast<T>(v1_), static_cast<T>(v2_),
+        static_cast<T>(v3_), static_cast<T>(v4_), static_cast<T>(v5_),
+        static_cast<T>(v6_), static_cast<T>(v7_), static_cast<T>(v8_),
+        static_cast<T>(v9_), static_cast<T>(v10_), static_cast<T>(v11_),
+        static_cast<T>(v12_), static_cast<T>(v13_), static_cast<T>(v14_),
+        static_cast<T>(v15_), static_cast<T>(v16_), static_cast<T>(v17_),
+        static_cast<T>(v18_), static_cast<T>(v19_), static_cast<T>(v20_),
+        static_cast<T>(v21_), static_cast<T>(v22_)};
+    return ValuesIn(array);
+  }
+
+ private:
+  // No implementation - assignment is unsupported.
+  void operator=(const ValueArray22& other);
+
+  const T1 v1_;
+  const T2 v2_;
+  const T3 v3_;
+  const T4 v4_;
+  const T5 v5_;
+  const T6 v6_;
+  const T7 v7_;
+  const T8 v8_;
+  const T9 v9_;
+  const T10 v10_;
+  const T11 v11_;
+  const T12 v12_;
+  const T13 v13_;
+  const T14 v14_;
+  const T15 v15_;
+  const T16 v16_;
+  const T17 v17_;
+  const T18 v18_;
+  const T19 v19_;
+  const T20 v20_;
+  const T21 v21_;
+  const T22 v22_;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23>
+class ValueArray23 {
+ public:
+  ValueArray23(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9,
+      T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17,
+      T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23) : v1_(v1), v2_(v2),
+      v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7), v8_(v8), v9_(v9), v10_(v10),
+      v11_(v11), v12_(v12), v13_(v13), v14_(v14), v15_(v15), v16_(v16),
+      v17_(v17), v18_(v18), v19_(v19), v20_(v20), v21_(v21), v22_(v22),
+      v23_(v23) {}
+
+  template <typename T>
+  operator ParamGenerator<T>() const {
+    const T array[] = {static_cast<T>(v1_), static_cast<T>(v2_),
+        static_cast<T>(v3_), static_cast<T>(v4_), static_cast<T>(v5_),
+        static_cast<T>(v6_), static_cast<T>(v7_), static_cast<T>(v8_),
+        static_cast<T>(v9_), static_cast<T>(v10_), static_cast<T>(v11_),
+        static_cast<T>(v12_), static_cast<T>(v13_), static_cast<T>(v14_),
+        static_cast<T>(v15_), static_cast<T>(v16_), static_cast<T>(v17_),
+        static_cast<T>(v18_), static_cast<T>(v19_), static_cast<T>(v20_),
+        static_cast<T>(v21_), static_cast<T>(v22_), static_cast<T>(v23_)};
+    return ValuesIn(array);
+  }
+
+ private:
+  // No implementation - assignment is unsupported.
+  void operator=(const ValueArray23& other);
+
+  const T1 v1_;
+  const T2 v2_;
+  const T3 v3_;
+  const T4 v4_;
+  const T5 v5_;
+  const T6 v6_;
+  const T7 v7_;
+  const T8 v8_;
+  const T9 v9_;
+  const T10 v10_;
+  const T11 v11_;
+  const T12 v12_;
+  const T13 v13_;
+  const T14 v14_;
+  const T15 v15_;
+  const T16 v16_;
+  const T17 v17_;
+  const T18 v18_;
+  const T19 v19_;
+  const T20 v20_;
+  const T21 v21_;
+  const T22 v22_;
+  const T23 v23_;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24>
+class ValueArray24 {
+ public:
+  ValueArray24(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9,
+      T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17,
+      T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24) : v1_(v1),
+      v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7), v8_(v8), v9_(v9),
+      v10_(v10), v11_(v11), v12_(v12), v13_(v13), v14_(v14), v15_(v15),
+      v16_(v16), v17_(v17), v18_(v18), v19_(v19), v20_(v20), v21_(v21),
+      v22_(v22), v23_(v23), v24_(v24) {}
+
+  template <typename T>
+  operator ParamGenerator<T>() const {
+    const T array[] = {static_cast<T>(v1_), static_cast<T>(v2_),
+        static_cast<T>(v3_), static_cast<T>(v4_), static_cast<T>(v5_),
+        static_cast<T>(v6_), static_cast<T>(v7_), static_cast<T>(v8_),
+        static_cast<T>(v9_), static_cast<T>(v10_), static_cast<T>(v11_),
+        static_cast<T>(v12_), static_cast<T>(v13_), static_cast<T>(v14_),
+        static_cast<T>(v15_), static_cast<T>(v16_), static_cast<T>(v17_),
+        static_cast<T>(v18_), static_cast<T>(v19_), static_cast<T>(v20_),
+        static_cast<T>(v21_), static_cast<T>(v22_), static_cast<T>(v23_),
+        static_cast<T>(v24_)};
+    return ValuesIn(array);
+  }
+
+ private:
+  // No implementation - assignment is unsupported.
+  void operator=(const ValueArray24& other);
+
+  const T1 v1_;
+  const T2 v2_;
+  const T3 v3_;
+  const T4 v4_;
+  const T5 v5_;
+  const T6 v6_;
+  const T7 v7_;
+  const T8 v8_;
+  const T9 v9_;
+  const T10 v10_;
+  const T11 v11_;
+  const T12 v12_;
+  const T13 v13_;
+  const T14 v14_;
+  const T15 v15_;
+  const T16 v16_;
+  const T17 v17_;
+  const T18 v18_;
+  const T19 v19_;
+  const T20 v20_;
+  const T21 v21_;
+  const T22 v22_;
+  const T23 v23_;
+  const T24 v24_;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25>
+class ValueArray25 {
+ public:
+  ValueArray25(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9,
+      T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17,
+      T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24,
+      T25 v25) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7),
+      v8_(v8), v9_(v9), v10_(v10), v11_(v11), v12_(v12), v13_(v13), v14_(v14),
+      v15_(v15), v16_(v16), v17_(v17), v18_(v18), v19_(v19), v20_(v20),
+      v21_(v21), v22_(v22), v23_(v23), v24_(v24), v25_(v25) {}
+
+  template <typename T>
+  operator ParamGenerator<T>() const {
+    const T array[] = {static_cast<T>(v1_), static_cast<T>(v2_),
+        static_cast<T>(v3_), static_cast<T>(v4_), static_cast<T>(v5_),
+        static_cast<T>(v6_), static_cast<T>(v7_), static_cast<T>(v8_),
+        static_cast<T>(v9_), static_cast<T>(v10_), static_cast<T>(v11_),
+        static_cast<T>(v12_), static_cast<T>(v13_), static_cast<T>(v14_),
+        static_cast<T>(v15_), static_cast<T>(v16_), static_cast<T>(v17_),
+        static_cast<T>(v18_), static_cast<T>(v19_), static_cast<T>(v20_),
+        static_cast<T>(v21_), static_cast<T>(v22_), static_cast<T>(v23_),
+        static_cast<T>(v24_), static_cast<T>(v25_)};
+    return ValuesIn(array);
+  }
+
+ private:
+  // No implementation - assignment is unsupported.
+  void operator=(const ValueArray25& other);
+
+  const T1 v1_;
+  const T2 v2_;
+  const T3 v3_;
+  const T4 v4_;
+  const T5 v5_;
+  const T6 v6_;
+  const T7 v7_;
+  const T8 v8_;
+  const T9 v9_;
+  const T10 v10_;
+  const T11 v11_;
+  const T12 v12_;
+  const T13 v13_;
+  const T14 v14_;
+  const T15 v15_;
+  const T16 v16_;
+  const T17 v17_;
+  const T18 v18_;
+  const T19 v19_;
+  const T20 v20_;
+  const T21 v21_;
+  const T22 v22_;
+  const T23 v23_;
+  const T24 v24_;
+  const T25 v25_;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26>
+class ValueArray26 {
+ public:
+  ValueArray26(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9,
+      T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17,
+      T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25,
+      T26 v26) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7),
+      v8_(v8), v9_(v9), v10_(v10), v11_(v11), v12_(v12), v13_(v13), v14_(v14),
+      v15_(v15), v16_(v16), v17_(v17), v18_(v18), v19_(v19), v20_(v20),
+      v21_(v21), v22_(v22), v23_(v23), v24_(v24), v25_(v25), v26_(v26) {}
+
+  template <typename T>
+  operator ParamGenerator<T>() const {
+    const T array[] = {static_cast<T>(v1_), static_cast<T>(v2_),
+        static_cast<T>(v3_), static_cast<T>(v4_), static_cast<T>(v5_),
+        static_cast<T>(v6_), static_cast<T>(v7_), static_cast<T>(v8_),
+        static_cast<T>(v9_), static_cast<T>(v10_), static_cast<T>(v11_),
+        static_cast<T>(v12_), static_cast<T>(v13_), static_cast<T>(v14_),
+        static_cast<T>(v15_), static_cast<T>(v16_), static_cast<T>(v17_),
+        static_cast<T>(v18_), static_cast<T>(v19_), static_cast<T>(v20_),
+        static_cast<T>(v21_), static_cast<T>(v22_), static_cast<T>(v23_),
+        static_cast<T>(v24_), static_cast<T>(v25_), static_cast<T>(v26_)};
+    return ValuesIn(array);
+  }
+
+ private:
+  // No implementation - assignment is unsupported.
+  void operator=(const ValueArray26& other);
+
+  const T1 v1_;
+  const T2 v2_;
+  const T3 v3_;
+  const T4 v4_;
+  const T5 v5_;
+  const T6 v6_;
+  const T7 v7_;
+  const T8 v8_;
+  const T9 v9_;
+  const T10 v10_;
+  const T11 v11_;
+  const T12 v12_;
+  const T13 v13_;
+  const T14 v14_;
+  const T15 v15_;
+  const T16 v16_;
+  const T17 v17_;
+  const T18 v18_;
+  const T19 v19_;
+  const T20 v20_;
+  const T21 v21_;
+  const T22 v22_;
+  const T23 v23_;
+  const T24 v24_;
+  const T25 v25_;
+  const T26 v26_;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27>
+class ValueArray27 {
+ public:
+  ValueArray27(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9,
+      T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17,
+      T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25,
+      T26 v26, T27 v27) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6),
+      v7_(v7), v8_(v8), v9_(v9), v10_(v10), v11_(v11), v12_(v12), v13_(v13),
+      v14_(v14), v15_(v15), v16_(v16), v17_(v17), v18_(v18), v19_(v19),
+      v20_(v20), v21_(v21), v22_(v22), v23_(v23), v24_(v24), v25_(v25),
+      v26_(v26), v27_(v27) {}
+
+  template <typename T>
+  operator ParamGenerator<T>() const {
+    const T array[] = {static_cast<T>(v1_), static_cast<T>(v2_),
+        static_cast<T>(v3_), static_cast<T>(v4_), static_cast<T>(v5_),
+        static_cast<T>(v6_), static_cast<T>(v7_), static_cast<T>(v8_),
+        static_cast<T>(v9_), static_cast<T>(v10_), static_cast<T>(v11_),
+        static_cast<T>(v12_), static_cast<T>(v13_), static_cast<T>(v14_),
+        static_cast<T>(v15_), static_cast<T>(v16_), static_cast<T>(v17_),
+        static_cast<T>(v18_), static_cast<T>(v19_), static_cast<T>(v20_),
+        static_cast<T>(v21_), static_cast<T>(v22_), static_cast<T>(v23_),
+        static_cast<T>(v24_), static_cast<T>(v25_), static_cast<T>(v26_),
+        static_cast<T>(v27_)};
+    return ValuesIn(array);
+  }
+
+ private:
+  // No implementation - assignment is unsupported.
+  void operator=(const ValueArray27& other);
+
+  const T1 v1_;
+  const T2 v2_;
+  const T3 v3_;
+  const T4 v4_;
+  const T5 v5_;
+  const T6 v6_;
+  const T7 v7_;
+  const T8 v8_;
+  const T9 v9_;
+  const T10 v10_;
+  const T11 v11_;
+  const T12 v12_;
+  const T13 v13_;
+  const T14 v14_;
+  const T15 v15_;
+  const T16 v16_;
+  const T17 v17_;
+  const T18 v18_;
+  const T19 v19_;
+  const T20 v20_;
+  const T21 v21_;
+  const T22 v22_;
+  const T23 v23_;
+  const T24 v24_;
+  const T25 v25_;
+  const T26 v26_;
+  const T27 v27_;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28>
+class ValueArray28 {
+ public:
+  ValueArray28(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9,
+      T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17,
+      T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25,
+      T26 v26, T27 v27, T28 v28) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), v5_(v5),
+      v6_(v6), v7_(v7), v8_(v8), v9_(v9), v10_(v10), v11_(v11), v12_(v12),
+      v13_(v13), v14_(v14), v15_(v15), v16_(v16), v17_(v17), v18_(v18),
+      v19_(v19), v20_(v20), v21_(v21), v22_(v22), v23_(v23), v24_(v24),
+      v25_(v25), v26_(v26), v27_(v27), v28_(v28) {}
+
+  template <typename T>
+  operator ParamGenerator<T>() const {
+    const T array[] = {static_cast<T>(v1_), static_cast<T>(v2_),
+        static_cast<T>(v3_), static_cast<T>(v4_), static_cast<T>(v5_),
+        static_cast<T>(v6_), static_cast<T>(v7_), static_cast<T>(v8_),
+        static_cast<T>(v9_), static_cast<T>(v10_), static_cast<T>(v11_),
+        static_cast<T>(v12_), static_cast<T>(v13_), static_cast<T>(v14_),
+        static_cast<T>(v15_), static_cast<T>(v16_), static_cast<T>(v17_),
+        static_cast<T>(v18_), static_cast<T>(v19_), static_cast<T>(v20_),
+        static_cast<T>(v21_), static_cast<T>(v22_), static_cast<T>(v23_),
+        static_cast<T>(v24_), static_cast<T>(v25_), static_cast<T>(v26_),
+        static_cast<T>(v27_), static_cast<T>(v28_)};
+    return ValuesIn(array);
+  }
+
+ private:
+  // No implementation - assignment is unsupported.
+  void operator=(const ValueArray28& other);
+
+  const T1 v1_;
+  const T2 v2_;
+  const T3 v3_;
+  const T4 v4_;
+  const T5 v5_;
+  const T6 v6_;
+  const T7 v7_;
+  const T8 v8_;
+  const T9 v9_;
+  const T10 v10_;
+  const T11 v11_;
+  const T12 v12_;
+  const T13 v13_;
+  const T14 v14_;
+  const T15 v15_;
+  const T16 v16_;
+  const T17 v17_;
+  const T18 v18_;
+  const T19 v19_;
+  const T20 v20_;
+  const T21 v21_;
+  const T22 v22_;
+  const T23 v23_;
+  const T24 v24_;
+  const T25 v25_;
+  const T26 v26_;
+  const T27 v27_;
+  const T28 v28_;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29>
+class ValueArray29 {
+ public:
+  ValueArray29(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9,
+      T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17,
+      T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25,
+      T26 v26, T27 v27, T28 v28, T29 v29) : v1_(v1), v2_(v2), v3_(v3), v4_(v4),
+      v5_(v5), v6_(v6), v7_(v7), v8_(v8), v9_(v9), v10_(v10), v11_(v11),
+      v12_(v12), v13_(v13), v14_(v14), v15_(v15), v16_(v16), v17_(v17),
+      v18_(v18), v19_(v19), v20_(v20), v21_(v21), v22_(v22), v23_(v23),
+      v24_(v24), v25_(v25), v26_(v26), v27_(v27), v28_(v28), v29_(v29) {}
+
+  template <typename T>
+  operator ParamGenerator<T>() const {
+    const T array[] = {static_cast<T>(v1_), static_cast<T>(v2_),
+        static_cast<T>(v3_), static_cast<T>(v4_), static_cast<T>(v5_),
+        static_cast<T>(v6_), static_cast<T>(v7_), static_cast<T>(v8_),
+        static_cast<T>(v9_), static_cast<T>(v10_), static_cast<T>(v11_),
+        static_cast<T>(v12_), static_cast<T>(v13_), static_cast<T>(v14_),
+        static_cast<T>(v15_), static_cast<T>(v16_), static_cast<T>(v17_),
+        static_cast<T>(v18_), static_cast<T>(v19_), static_cast<T>(v20_),
+        static_cast<T>(v21_), static_cast<T>(v22_), static_cast<T>(v23_),
+        static_cast<T>(v24_), static_cast<T>(v25_), static_cast<T>(v26_),
+        static_cast<T>(v27_), static_cast<T>(v28_), static_cast<T>(v29_)};
+    return ValuesIn(array);
+  }
+
+ private:
+  // No implementation - assignment is unsupported.
+  void operator=(const ValueArray29& other);
+
+  const T1 v1_;
+  const T2 v2_;
+  const T3 v3_;
+  const T4 v4_;
+  const T5 v5_;
+  const T6 v6_;
+  const T7 v7_;
+  const T8 v8_;
+  const T9 v9_;
+  const T10 v10_;
+  const T11 v11_;
+  const T12 v12_;
+  const T13 v13_;
+  const T14 v14_;
+  const T15 v15_;
+  const T16 v16_;
+  const T17 v17_;
+  const T18 v18_;
+  const T19 v19_;
+  const T20 v20_;
+  const T21 v21_;
+  const T22 v22_;
+  const T23 v23_;
+  const T24 v24_;
+  const T25 v25_;
+  const T26 v26_;
+  const T27 v27_;
+  const T28 v28_;
+  const T29 v29_;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30>
+class ValueArray30 {
+ public:
+  ValueArray30(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9,
+      T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17,
+      T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25,
+      T26 v26, T27 v27, T28 v28, T29 v29, T30 v30) : v1_(v1), v2_(v2), v3_(v3),
+      v4_(v4), v5_(v5), v6_(v6), v7_(v7), v8_(v8), v9_(v9), v10_(v10),
+      v11_(v11), v12_(v12), v13_(v13), v14_(v14), v15_(v15), v16_(v16),
+      v17_(v17), v18_(v18), v19_(v19), v20_(v20), v21_(v21), v22_(v22),
+      v23_(v23), v24_(v24), v25_(v25), v26_(v26), v27_(v27), v28_(v28),
+      v29_(v29), v30_(v30) {}
+
+  template <typename T>
+  operator ParamGenerator<T>() const {
+    const T array[] = {static_cast<T>(v1_), static_cast<T>(v2_),
+        static_cast<T>(v3_), static_cast<T>(v4_), static_cast<T>(v5_),
+        static_cast<T>(v6_), static_cast<T>(v7_), static_cast<T>(v8_),
+        static_cast<T>(v9_), static_cast<T>(v10_), static_cast<T>(v11_),
+        static_cast<T>(v12_), static_cast<T>(v13_), static_cast<T>(v14_),
+        static_cast<T>(v15_), static_cast<T>(v16_), static_cast<T>(v17_),
+        static_cast<T>(v18_), static_cast<T>(v19_), static_cast<T>(v20_),
+        static_cast<T>(v21_), static_cast<T>(v22_), static_cast<T>(v23_),
+        static_cast<T>(v24_), static_cast<T>(v25_), static_cast<T>(v26_),
+        static_cast<T>(v27_), static_cast<T>(v28_), static_cast<T>(v29_),
+        static_cast<T>(v30_)};
+    return ValuesIn(array);
+  }
+
+ private:
+  // No implementation - assignment is unsupported.
+  void operator=(const ValueArray30& other);
+
+  const T1 v1_;
+  const T2 v2_;
+  const T3 v3_;
+  const T4 v4_;
+  const T5 v5_;
+  const T6 v6_;
+  const T7 v7_;
+  const T8 v8_;
+  const T9 v9_;
+  const T10 v10_;
+  const T11 v11_;
+  const T12 v12_;
+  const T13 v13_;
+  const T14 v14_;
+  const T15 v15_;
+  const T16 v16_;
+  const T17 v17_;
+  const T18 v18_;
+  const T19 v19_;
+  const T20 v20_;
+  const T21 v21_;
+  const T22 v22_;
+  const T23 v23_;
+  const T24 v24_;
+  const T25 v25_;
+  const T26 v26_;
+  const T27 v27_;
+  const T28 v28_;
+  const T29 v29_;
+  const T30 v30_;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31>
+class ValueArray31 {
+ public:
+  ValueArray31(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9,
+      T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17,
+      T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25,
+      T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31) : v1_(v1), v2_(v2),
+      v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7), v8_(v8), v9_(v9), v10_(v10),
+      v11_(v11), v12_(v12), v13_(v13), v14_(v14), v15_(v15), v16_(v16),
+      v17_(v17), v18_(v18), v19_(v19), v20_(v20), v21_(v21), v22_(v22),
+      v23_(v23), v24_(v24), v25_(v25), v26_(v26), v27_(v27), v28_(v28),
+      v29_(v29), v30_(v30), v31_(v31) {}
+
+  template <typename T>
+  operator ParamGenerator<T>() const {
+    const T array[] = {static_cast<T>(v1_), static_cast<T>(v2_),
+        static_cast<T>(v3_), static_cast<T>(v4_), static_cast<T>(v5_),
+        static_cast<T>(v6_), static_cast<T>(v7_), static_cast<T>(v8_),
+        static_cast<T>(v9_), static_cast<T>(v10_), static_cast<T>(v11_),
+        static_cast<T>(v12_), static_cast<T>(v13_), static_cast<T>(v14_),
+        static_cast<T>(v15_), static_cast<T>(v16_), static_cast<T>(v17_),
+        static_cast<T>(v18_), static_cast<T>(v19_), static_cast<T>(v20_),
+        static_cast<T>(v21_), static_cast<T>(v22_), static_cast<T>(v23_),
+        static_cast<T>(v24_), static_cast<T>(v25_), static_cast<T>(v26_),
+        static_cast<T>(v27_), static_cast<T>(v28_), static_cast<T>(v29_),
+        static_cast<T>(v30_), static_cast<T>(v31_)};
+    return ValuesIn(array);
+  }
+
+ private:
+  // No implementation - assignment is unsupported.
+  void operator=(const ValueArray31& other);
+
+  const T1 v1_;
+  const T2 v2_;
+  const T3 v3_;
+  const T4 v4_;
+  const T5 v5_;
+  const T6 v6_;
+  const T7 v7_;
+  const T8 v8_;
+  const T9 v9_;
+  const T10 v10_;
+  const T11 v11_;
+  const T12 v12_;
+  const T13 v13_;
+  const T14 v14_;
+  const T15 v15_;
+  const T16 v16_;
+  const T17 v17_;
+  const T18 v18_;
+  const T19 v19_;
+  const T20 v20_;
+  const T21 v21_;
+  const T22 v22_;
+  const T23 v23_;
+  const T24 v24_;
+  const T25 v25_;
+  const T26 v26_;
+  const T27 v27_;
+  const T28 v28_;
+  const T29 v29_;
+  const T30 v30_;
+  const T31 v31_;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32>
+class ValueArray32 {
+ public:
+  ValueArray32(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9,
+      T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17,
+      T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25,
+      T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, T32 v32) : v1_(v1),
+      v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7), v8_(v8), v9_(v9),
+      v10_(v10), v11_(v11), v12_(v12), v13_(v13), v14_(v14), v15_(v15),
+      v16_(v16), v17_(v17), v18_(v18), v19_(v19), v20_(v20), v21_(v21),
+      v22_(v22), v23_(v23), v24_(v24), v25_(v25), v26_(v26), v27_(v27),
+      v28_(v28), v29_(v29), v30_(v30), v31_(v31), v32_(v32) {}
+
+  template <typename T>
+  operator ParamGenerator<T>() const {
+    const T array[] = {static_cast<T>(v1_), static_cast<T>(v2_),
+        static_cast<T>(v3_), static_cast<T>(v4_), static_cast<T>(v5_),
+        static_cast<T>(v6_), static_cast<T>(v7_), static_cast<T>(v8_),
+        static_cast<T>(v9_), static_cast<T>(v10_), static_cast<T>(v11_),
+        static_cast<T>(v12_), static_cast<T>(v13_), static_cast<T>(v14_),
+        static_cast<T>(v15_), static_cast<T>(v16_), static_cast<T>(v17_),
+        static_cast<T>(v18_), static_cast<T>(v19_), static_cast<T>(v20_),
+        static_cast<T>(v21_), static_cast<T>(v22_), static_cast<T>(v23_),
+        static_cast<T>(v24_), static_cast<T>(v25_), static_cast<T>(v26_),
+        static_cast<T>(v27_), static_cast<T>(v28_), static_cast<T>(v29_),
+        static_cast<T>(v30_), static_cast<T>(v31_), static_cast<T>(v32_)};
+    return ValuesIn(array);
+  }
+
+ private:
+  // No implementation - assignment is unsupported.
+  void operator=(const ValueArray32& other);
+
+  const T1 v1_;
+  const T2 v2_;
+  const T3 v3_;
+  const T4 v4_;
+  const T5 v5_;
+  const T6 v6_;
+  const T7 v7_;
+  const T8 v8_;
+  const T9 v9_;
+  const T10 v10_;
+  const T11 v11_;
+  const T12 v12_;
+  const T13 v13_;
+  const T14 v14_;
+  const T15 v15_;
+  const T16 v16_;
+  const T17 v17_;
+  const T18 v18_;
+  const T19 v19_;
+  const T20 v20_;
+  const T21 v21_;
+  const T22 v22_;
+  const T23 v23_;
+  const T24 v24_;
+  const T25 v25_;
+  const T26 v26_;
+  const T27 v27_;
+  const T28 v28_;
+  const T29 v29_;
+  const T30 v30_;
+  const T31 v31_;
+  const T32 v32_;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32, typename T33>
+class ValueArray33 {
+ public:
+  ValueArray33(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9,
+      T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17,
+      T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25,
+      T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, T32 v32,
+      T33 v33) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7),
+      v8_(v8), v9_(v9), v10_(v10), v11_(v11), v12_(v12), v13_(v13), v14_(v14),
+      v15_(v15), v16_(v16), v17_(v17), v18_(v18), v19_(v19), v20_(v20),
+      v21_(v21), v22_(v22), v23_(v23), v24_(v24), v25_(v25), v26_(v26),
+      v27_(v27), v28_(v28), v29_(v29), v30_(v30), v31_(v31), v32_(v32),
+      v33_(v33) {}
+
+  template <typename T>
+  operator ParamGenerator<T>() const {
+    const T array[] = {static_cast<T>(v1_), static_cast<T>(v2_),
+        static_cast<T>(v3_), static_cast<T>(v4_), static_cast<T>(v5_),
+        static_cast<T>(v6_), static_cast<T>(v7_), static_cast<T>(v8_),
+        static_cast<T>(v9_), static_cast<T>(v10_), static_cast<T>(v11_),
+        static_cast<T>(v12_), static_cast<T>(v13_), static_cast<T>(v14_),
+        static_cast<T>(v15_), static_cast<T>(v16_), static_cast<T>(v17_),
+        static_cast<T>(v18_), static_cast<T>(v19_), static_cast<T>(v20_),
+        static_cast<T>(v21_), static_cast<T>(v22_), static_cast<T>(v23_),
+        static_cast<T>(v24_), static_cast<T>(v25_), static_cast<T>(v26_),
+        static_cast<T>(v27_), static_cast<T>(v28_), static_cast<T>(v29_),
+        static_cast<T>(v30_), static_cast<T>(v31_), static_cast<T>(v32_),
+        static_cast<T>(v33_)};
+    return ValuesIn(array);
+  }
+
+ private:
+  // No implementation - assignment is unsupported.
+  void operator=(const ValueArray33& other);
+
+  const T1 v1_;
+  const T2 v2_;
+  const T3 v3_;
+  const T4 v4_;
+  const T5 v5_;
+  const T6 v6_;
+  const T7 v7_;
+  const T8 v8_;
+  const T9 v9_;
+  const T10 v10_;
+  const T11 v11_;
+  const T12 v12_;
+  const T13 v13_;
+  const T14 v14_;
+  const T15 v15_;
+  const T16 v16_;
+  const T17 v17_;
+  const T18 v18_;
+  const T19 v19_;
+  const T20 v20_;
+  const T21 v21_;
+  const T22 v22_;
+  const T23 v23_;
+  const T24 v24_;
+  const T25 v25_;
+  const T26 v26_;
+  const T27 v27_;
+  const T28 v28_;
+  const T29 v29_;
+  const T30 v30_;
+  const T31 v31_;
+  const T32 v32_;
+  const T33 v33_;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32, typename T33, typename T34>
+class ValueArray34 {
+ public:
+  ValueArray34(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9,
+      T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17,
+      T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25,
+      T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, T32 v32, T33 v33,
+      T34 v34) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7),
+      v8_(v8), v9_(v9), v10_(v10), v11_(v11), v12_(v12), v13_(v13), v14_(v14),
+      v15_(v15), v16_(v16), v17_(v17), v18_(v18), v19_(v19), v20_(v20),
+      v21_(v21), v22_(v22), v23_(v23), v24_(v24), v25_(v25), v26_(v26),
+      v27_(v27), v28_(v28), v29_(v29), v30_(v30), v31_(v31), v32_(v32),
+      v33_(v33), v34_(v34) {}
+
+  template <typename T>
+  operator ParamGenerator<T>() const {
+    const T array[] = {static_cast<T>(v1_), static_cast<T>(v2_),
+        static_cast<T>(v3_), static_cast<T>(v4_), static_cast<T>(v5_),
+        static_cast<T>(v6_), static_cast<T>(v7_), static_cast<T>(v8_),
+        static_cast<T>(v9_), static_cast<T>(v10_), static_cast<T>(v11_),
+        static_cast<T>(v12_), static_cast<T>(v13_), static_cast<T>(v14_),
+        static_cast<T>(v15_), static_cast<T>(v16_), static_cast<T>(v17_),
+        static_cast<T>(v18_), static_cast<T>(v19_), static_cast<T>(v20_),
+        static_cast<T>(v21_), static_cast<T>(v22_), static_cast<T>(v23_),
+        static_cast<T>(v24_), static_cast<T>(v25_), static_cast<T>(v26_),
+        static_cast<T>(v27_), static_cast<T>(v28_), static_cast<T>(v29_),
+        static_cast<T>(v30_), static_cast<T>(v31_), static_cast<T>(v32_),
+        static_cast<T>(v33_), static_cast<T>(v34_)};
+    return ValuesIn(array);
+  }
+
+ private:
+  // No implementation - assignment is unsupported.
+  void operator=(const ValueArray34& other);
+
+  const T1 v1_;
+  const T2 v2_;
+  const T3 v3_;
+  const T4 v4_;
+  const T5 v5_;
+  const T6 v6_;
+  const T7 v7_;
+  const T8 v8_;
+  const T9 v9_;
+  const T10 v10_;
+  const T11 v11_;
+  const T12 v12_;
+  const T13 v13_;
+  const T14 v14_;
+  const T15 v15_;
+  const T16 v16_;
+  const T17 v17_;
+  const T18 v18_;
+  const T19 v19_;
+  const T20 v20_;
+  const T21 v21_;
+  const T22 v22_;
+  const T23 v23_;
+  const T24 v24_;
+  const T25 v25_;
+  const T26 v26_;
+  const T27 v27_;
+  const T28 v28_;
+  const T29 v29_;
+  const T30 v30_;
+  const T31 v31_;
+  const T32 v32_;
+  const T33 v33_;
+  const T34 v34_;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32, typename T33, typename T34, typename T35>
+class ValueArray35 {
+ public:
+  ValueArray35(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9,
+      T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17,
+      T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25,
+      T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, T32 v32, T33 v33,
+      T34 v34, T35 v35) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6),
+      v7_(v7), v8_(v8), v9_(v9), v10_(v10), v11_(v11), v12_(v12), v13_(v13),
+      v14_(v14), v15_(v15), v16_(v16), v17_(v17), v18_(v18), v19_(v19),
+      v20_(v20), v21_(v21), v22_(v22), v23_(v23), v24_(v24), v25_(v25),
+      v26_(v26), v27_(v27), v28_(v28), v29_(v29), v30_(v30), v31_(v31),
+      v32_(v32), v33_(v33), v34_(v34), v35_(v35) {}
+
+  template <typename T>
+  operator ParamGenerator<T>() const {
+    const T array[] = {static_cast<T>(v1_), static_cast<T>(v2_),
+        static_cast<T>(v3_), static_cast<T>(v4_), static_cast<T>(v5_),
+        static_cast<T>(v6_), static_cast<T>(v7_), static_cast<T>(v8_),
+        static_cast<T>(v9_), static_cast<T>(v10_), static_cast<T>(v11_),
+        static_cast<T>(v12_), static_cast<T>(v13_), static_cast<T>(v14_),
+        static_cast<T>(v15_), static_cast<T>(v16_), static_cast<T>(v17_),
+        static_cast<T>(v18_), static_cast<T>(v19_), static_cast<T>(v20_),
+        static_cast<T>(v21_), static_cast<T>(v22_), static_cast<T>(v23_),
+        static_cast<T>(v24_), static_cast<T>(v25_), static_cast<T>(v26_),
+        static_cast<T>(v27_), static_cast<T>(v28_), static_cast<T>(v29_),
+        static_cast<T>(v30_), static_cast<T>(v31_), static_cast<T>(v32_),
+        static_cast<T>(v33_), static_cast<T>(v34_), static_cast<T>(v35_)};
+    return ValuesIn(array);
+  }
+
+ private:
+  // No implementation - assignment is unsupported.
+  void operator=(const ValueArray35& other);
+
+  const T1 v1_;
+  const T2 v2_;
+  const T3 v3_;
+  const T4 v4_;
+  const T5 v5_;
+  const T6 v6_;
+  const T7 v7_;
+  const T8 v8_;
+  const T9 v9_;
+  const T10 v10_;
+  const T11 v11_;
+  const T12 v12_;
+  const T13 v13_;
+  const T14 v14_;
+  const T15 v15_;
+  const T16 v16_;
+  const T17 v17_;
+  const T18 v18_;
+  const T19 v19_;
+  const T20 v20_;
+  const T21 v21_;
+  const T22 v22_;
+  const T23 v23_;
+  const T24 v24_;
+  const T25 v25_;
+  const T26 v26_;
+  const T27 v27_;
+  const T28 v28_;
+  const T29 v29_;
+  const T30 v30_;
+  const T31 v31_;
+  const T32 v32_;
+  const T33 v33_;
+  const T34 v34_;
+  const T35 v35_;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32, typename T33, typename T34, typename T35,
+    typename T36>
+class ValueArray36 {
+ public:
+  ValueArray36(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9,
+      T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17,
+      T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25,
+      T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, T32 v32, T33 v33,
+      T34 v34, T35 v35, T36 v36) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), v5_(v5),
+      v6_(v6), v7_(v7), v8_(v8), v9_(v9), v10_(v10), v11_(v11), v12_(v12),
+      v13_(v13), v14_(v14), v15_(v15), v16_(v16), v17_(v17), v18_(v18),
+      v19_(v19), v20_(v20), v21_(v21), v22_(v22), v23_(v23), v24_(v24),
+      v25_(v25), v26_(v26), v27_(v27), v28_(v28), v29_(v29), v30_(v30),
+      v31_(v31), v32_(v32), v33_(v33), v34_(v34), v35_(v35), v36_(v36) {}
+
+  template <typename T>
+  operator ParamGenerator<T>() const {
+    const T array[] = {static_cast<T>(v1_), static_cast<T>(v2_),
+        static_cast<T>(v3_), static_cast<T>(v4_), static_cast<T>(v5_),
+        static_cast<T>(v6_), static_cast<T>(v7_), static_cast<T>(v8_),
+        static_cast<T>(v9_), static_cast<T>(v10_), static_cast<T>(v11_),
+        static_cast<T>(v12_), static_cast<T>(v13_), static_cast<T>(v14_),
+        static_cast<T>(v15_), static_cast<T>(v16_), static_cast<T>(v17_),
+        static_cast<T>(v18_), static_cast<T>(v19_), static_cast<T>(v20_),
+        static_cast<T>(v21_), static_cast<T>(v22_), static_cast<T>(v23_),
+        static_cast<T>(v24_), static_cast<T>(v25_), static_cast<T>(v26_),
+        static_cast<T>(v27_), static_cast<T>(v28_), static_cast<T>(v29_),
+        static_cast<T>(v30_), static_cast<T>(v31_), static_cast<T>(v32_),
+        static_cast<T>(v33_), static_cast<T>(v34_), static_cast<T>(v35_),
+        static_cast<T>(v36_)};
+    return ValuesIn(array);
+  }
+
+ private:
+  // No implementation - assignment is unsupported.
+  void operator=(const ValueArray36& other);
+
+  const T1 v1_;
+  const T2 v2_;
+  const T3 v3_;
+  const T4 v4_;
+  const T5 v5_;
+  const T6 v6_;
+  const T7 v7_;
+  const T8 v8_;
+  const T9 v9_;
+  const T10 v10_;
+  const T11 v11_;
+  const T12 v12_;
+  const T13 v13_;
+  const T14 v14_;
+  const T15 v15_;
+  const T16 v16_;
+  const T17 v17_;
+  const T18 v18_;
+  const T19 v19_;
+  const T20 v20_;
+  const T21 v21_;
+  const T22 v22_;
+  const T23 v23_;
+  const T24 v24_;
+  const T25 v25_;
+  const T26 v26_;
+  const T27 v27_;
+  const T28 v28_;
+  const T29 v29_;
+  const T30 v30_;
+  const T31 v31_;
+  const T32 v32_;
+  const T33 v33_;
+  const T34 v34_;
+  const T35 v35_;
+  const T36 v36_;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32, typename T33, typename T34, typename T35,
+    typename T36, typename T37>
+class ValueArray37 {
+ public:
+  ValueArray37(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9,
+      T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17,
+      T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25,
+      T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, T32 v32, T33 v33,
+      T34 v34, T35 v35, T36 v36, T37 v37) : v1_(v1), v2_(v2), v3_(v3), v4_(v4),
+      v5_(v5), v6_(v6), v7_(v7), v8_(v8), v9_(v9), v10_(v10), v11_(v11),
+      v12_(v12), v13_(v13), v14_(v14), v15_(v15), v16_(v16), v17_(v17),
+      v18_(v18), v19_(v19), v20_(v20), v21_(v21), v22_(v22), v23_(v23),
+      v24_(v24), v25_(v25), v26_(v26), v27_(v27), v28_(v28), v29_(v29),
+      v30_(v30), v31_(v31), v32_(v32), v33_(v33), v34_(v34), v35_(v35),
+      v36_(v36), v37_(v37) {}
+
+  template <typename T>
+  operator ParamGenerator<T>() const {
+    const T array[] = {static_cast<T>(v1_), static_cast<T>(v2_),
+        static_cast<T>(v3_), static_cast<T>(v4_), static_cast<T>(v5_),
+        static_cast<T>(v6_), static_cast<T>(v7_), static_cast<T>(v8_),
+        static_cast<T>(v9_), static_cast<T>(v10_), static_cast<T>(v11_),
+        static_cast<T>(v12_), static_cast<T>(v13_), static_cast<T>(v14_),
+        static_cast<T>(v15_), static_cast<T>(v16_), static_cast<T>(v17_),
+        static_cast<T>(v18_), static_cast<T>(v19_), static_cast<T>(v20_),
+        static_cast<T>(v21_), static_cast<T>(v22_), static_cast<T>(v23_),
+        static_cast<T>(v24_), static_cast<T>(v25_), static_cast<T>(v26_),
+        static_cast<T>(v27_), static_cast<T>(v28_), static_cast<T>(v29_),
+        static_cast<T>(v30_), static_cast<T>(v31_), static_cast<T>(v32_),
+        static_cast<T>(v33_), static_cast<T>(v34_), static_cast<T>(v35_),
+        static_cast<T>(v36_), static_cast<T>(v37_)};
+    return ValuesIn(array);
+  }
+
+ private:
+  // No implementation - assignment is unsupported.
+  void operator=(const ValueArray37& other);
+
+  const T1 v1_;
+  const T2 v2_;
+  const T3 v3_;
+  const T4 v4_;
+  const T5 v5_;
+  const T6 v6_;
+  const T7 v7_;
+  const T8 v8_;
+  const T9 v9_;
+  const T10 v10_;
+  const T11 v11_;
+  const T12 v12_;
+  const T13 v13_;
+  const T14 v14_;
+  const T15 v15_;
+  const T16 v16_;
+  const T17 v17_;
+  const T18 v18_;
+  const T19 v19_;
+  const T20 v20_;
+  const T21 v21_;
+  const T22 v22_;
+  const T23 v23_;
+  const T24 v24_;
+  const T25 v25_;
+  const T26 v26_;
+  const T27 v27_;
+  const T28 v28_;
+  const T29 v29_;
+  const T30 v30_;
+  const T31 v31_;
+  const T32 v32_;
+  const T33 v33_;
+  const T34 v34_;
+  const T35 v35_;
+  const T36 v36_;
+  const T37 v37_;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32, typename T33, typename T34, typename T35,
+    typename T36, typename T37, typename T38>
+class ValueArray38 {
+ public:
+  ValueArray38(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9,
+      T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17,
+      T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25,
+      T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, T32 v32, T33 v33,
+      T34 v34, T35 v35, T36 v36, T37 v37, T38 v38) : v1_(v1), v2_(v2), v3_(v3),
+      v4_(v4), v5_(v5), v6_(v6), v7_(v7), v8_(v8), v9_(v9), v10_(v10),
+      v11_(v11), v12_(v12), v13_(v13), v14_(v14), v15_(v15), v16_(v16),
+      v17_(v17), v18_(v18), v19_(v19), v20_(v20), v21_(v21), v22_(v22),
+      v23_(v23), v24_(v24), v25_(v25), v26_(v26), v27_(v27), v28_(v28),
+      v29_(v29), v30_(v30), v31_(v31), v32_(v32), v33_(v33), v34_(v34),
+      v35_(v35), v36_(v36), v37_(v37), v38_(v38) {}
+
+  template <typename T>
+  operator ParamGenerator<T>() const {
+    const T array[] = {static_cast<T>(v1_), static_cast<T>(v2_),
+        static_cast<T>(v3_), static_cast<T>(v4_), static_cast<T>(v5_),
+        static_cast<T>(v6_), static_cast<T>(v7_), static_cast<T>(v8_),
+        static_cast<T>(v9_), static_cast<T>(v10_), static_cast<T>(v11_),
+        static_cast<T>(v12_), static_cast<T>(v13_), static_cast<T>(v14_),
+        static_cast<T>(v15_), static_cast<T>(v16_), static_cast<T>(v17_),
+        static_cast<T>(v18_), static_cast<T>(v19_), static_cast<T>(v20_),
+        static_cast<T>(v21_), static_cast<T>(v22_), static_cast<T>(v23_),
+        static_cast<T>(v24_), static_cast<T>(v25_), static_cast<T>(v26_),
+        static_cast<T>(v27_), static_cast<T>(v28_), static_cast<T>(v29_),
+        static_cast<T>(v30_), static_cast<T>(v31_), static_cast<T>(v32_),
+        static_cast<T>(v33_), static_cast<T>(v34_), static_cast<T>(v35_),
+        static_cast<T>(v36_), static_cast<T>(v37_), static_cast<T>(v38_)};
+    return ValuesIn(array);
+  }
+
+ private:
+  // No implementation - assignment is unsupported.
+  void operator=(const ValueArray38& other);
+
+  const T1 v1_;
+  const T2 v2_;
+  const T3 v3_;
+  const T4 v4_;
+  const T5 v5_;
+  const T6 v6_;
+  const T7 v7_;
+  const T8 v8_;
+  const T9 v9_;
+  const T10 v10_;
+  const T11 v11_;
+  const T12 v12_;
+  const T13 v13_;
+  const T14 v14_;
+  const T15 v15_;
+  const T16 v16_;
+  const T17 v17_;
+  const T18 v18_;
+  const T19 v19_;
+  const T20 v20_;
+  const T21 v21_;
+  const T22 v22_;
+  const T23 v23_;
+  const T24 v24_;
+  const T25 v25_;
+  const T26 v26_;
+  const T27 v27_;
+  const T28 v28_;
+  const T29 v29_;
+  const T30 v30_;
+  const T31 v31_;
+  const T32 v32_;
+  const T33 v33_;
+  const T34 v34_;
+  const T35 v35_;
+  const T36 v36_;
+  const T37 v37_;
+  const T38 v38_;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32, typename T33, typename T34, typename T35,
+    typename T36, typename T37, typename T38, typename T39>
+class ValueArray39 {
+ public:
+  ValueArray39(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9,
+      T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17,
+      T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25,
+      T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, T32 v32, T33 v33,
+      T34 v34, T35 v35, T36 v36, T37 v37, T38 v38, T39 v39) : v1_(v1), v2_(v2),
+      v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7), v8_(v8), v9_(v9), v10_(v10),
+      v11_(v11), v12_(v12), v13_(v13), v14_(v14), v15_(v15), v16_(v16),
+      v17_(v17), v18_(v18), v19_(v19), v20_(v20), v21_(v21), v22_(v22),
+      v23_(v23), v24_(v24), v25_(v25), v26_(v26), v27_(v27), v28_(v28),
+      v29_(v29), v30_(v30), v31_(v31), v32_(v32), v33_(v33), v34_(v34),
+      v35_(v35), v36_(v36), v37_(v37), v38_(v38), v39_(v39) {}
+
+  template <typename T>
+  operator ParamGenerator<T>() const {
+    const T array[] = {static_cast<T>(v1_), static_cast<T>(v2_),
+        static_cast<T>(v3_), static_cast<T>(v4_), static_cast<T>(v5_),
+        static_cast<T>(v6_), static_cast<T>(v7_), static_cast<T>(v8_),
+        static_cast<T>(v9_), static_cast<T>(v10_), static_cast<T>(v11_),
+        static_cast<T>(v12_), static_cast<T>(v13_), static_cast<T>(v14_),
+        static_cast<T>(v15_), static_cast<T>(v16_), static_cast<T>(v17_),
+        static_cast<T>(v18_), static_cast<T>(v19_), static_cast<T>(v20_),
+        static_cast<T>(v21_), static_cast<T>(v22_), static_cast<T>(v23_),
+        static_cast<T>(v24_), static_cast<T>(v25_), static_cast<T>(v26_),
+        static_cast<T>(v27_), static_cast<T>(v28_), static_cast<T>(v29_),
+        static_cast<T>(v30_), static_cast<T>(v31_), static_cast<T>(v32_),
+        static_cast<T>(v33_), static_cast<T>(v34_), static_cast<T>(v35_),
+        static_cast<T>(v36_), static_cast<T>(v37_), static_cast<T>(v38_),
+        static_cast<T>(v39_)};
+    return ValuesIn(array);
+  }
+
+ private:
+  // No implementation - assignment is unsupported.
+  void operator=(const ValueArray39& other);
+
+  const T1 v1_;
+  const T2 v2_;
+  const T3 v3_;
+  const T4 v4_;
+  const T5 v5_;
+  const T6 v6_;
+  const T7 v7_;
+  const T8 v8_;
+  const T9 v9_;
+  const T10 v10_;
+  const T11 v11_;
+  const T12 v12_;
+  const T13 v13_;
+  const T14 v14_;
+  const T15 v15_;
+  const T16 v16_;
+  const T17 v17_;
+  const T18 v18_;
+  const T19 v19_;
+  const T20 v20_;
+  const T21 v21_;
+  const T22 v22_;
+  const T23 v23_;
+  const T24 v24_;
+  const T25 v25_;
+  const T26 v26_;
+  const T27 v27_;
+  const T28 v28_;
+  const T29 v29_;
+  const T30 v30_;
+  const T31 v31_;
+  const T32 v32_;
+  const T33 v33_;
+  const T34 v34_;
+  const T35 v35_;
+  const T36 v36_;
+  const T37 v37_;
+  const T38 v38_;
+  const T39 v39_;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32, typename T33, typename T34, typename T35,
+    typename T36, typename T37, typename T38, typename T39, typename T40>
+class ValueArray40 {
+ public:
+  ValueArray40(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9,
+      T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17,
+      T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25,
+      T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, T32 v32, T33 v33,
+      T34 v34, T35 v35, T36 v36, T37 v37, T38 v38, T39 v39, T40 v40) : v1_(v1),
+      v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7), v8_(v8), v9_(v9),
+      v10_(v10), v11_(v11), v12_(v12), v13_(v13), v14_(v14), v15_(v15),
+      v16_(v16), v17_(v17), v18_(v18), v19_(v19), v20_(v20), v21_(v21),
+      v22_(v22), v23_(v23), v24_(v24), v25_(v25), v26_(v26), v27_(v27),
+      v28_(v28), v29_(v29), v30_(v30), v31_(v31), v32_(v32), v33_(v33),
+      v34_(v34), v35_(v35), v36_(v36), v37_(v37), v38_(v38), v39_(v39),
+      v40_(v40) {}
+
+  template <typename T>
+  operator ParamGenerator<T>() const {
+    const T array[] = {static_cast<T>(v1_), static_cast<T>(v2_),
+        static_cast<T>(v3_), static_cast<T>(v4_), static_cast<T>(v5_),
+        static_cast<T>(v6_), static_cast<T>(v7_), static_cast<T>(v8_),
+        static_cast<T>(v9_), static_cast<T>(v10_), static_cast<T>(v11_),
+        static_cast<T>(v12_), static_cast<T>(v13_), static_cast<T>(v14_),
+        static_cast<T>(v15_), static_cast<T>(v16_), static_cast<T>(v17_),
+        static_cast<T>(v18_), static_cast<T>(v19_), static_cast<T>(v20_),
+        static_cast<T>(v21_), static_cast<T>(v22_), static_cast<T>(v23_),
+        static_cast<T>(v24_), static_cast<T>(v25_), static_cast<T>(v26_),
+        static_cast<T>(v27_), static_cast<T>(v28_), static_cast<T>(v29_),
+        static_cast<T>(v30_), static_cast<T>(v31_), static_cast<T>(v32_),
+        static_cast<T>(v33_), static_cast<T>(v34_), static_cast<T>(v35_),
+        static_cast<T>(v36_), static_cast<T>(v37_), static_cast<T>(v38_),
+        static_cast<T>(v39_), static_cast<T>(v40_)};
+    return ValuesIn(array);
+  }
+
+ private:
+  // No implementation - assignment is unsupported.
+  void operator=(const ValueArray40& other);
+
+  const T1 v1_;
+  const T2 v2_;
+  const T3 v3_;
+  const T4 v4_;
+  const T5 v5_;
+  const T6 v6_;
+  const T7 v7_;
+  const T8 v8_;
+  const T9 v9_;
+  const T10 v10_;
+  const T11 v11_;
+  const T12 v12_;
+  const T13 v13_;
+  const T14 v14_;
+  const T15 v15_;
+  const T16 v16_;
+  const T17 v17_;
+  const T18 v18_;
+  const T19 v19_;
+  const T20 v20_;
+  const T21 v21_;
+  const T22 v22_;
+  const T23 v23_;
+  const T24 v24_;
+  const T25 v25_;
+  const T26 v26_;
+  const T27 v27_;
+  const T28 v28_;
+  const T29 v29_;
+  const T30 v30_;
+  const T31 v31_;
+  const T32 v32_;
+  const T33 v33_;
+  const T34 v34_;
+  const T35 v35_;
+  const T36 v36_;
+  const T37 v37_;
+  const T38 v38_;
+  const T39 v39_;
+  const T40 v40_;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32, typename T33, typename T34, typename T35,
+    typename T36, typename T37, typename T38, typename T39, typename T40,
+    typename T41>
+class ValueArray41 {
+ public:
+  ValueArray41(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9,
+      T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17,
+      T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25,
+      T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, T32 v32, T33 v33,
+      T34 v34, T35 v35, T36 v36, T37 v37, T38 v38, T39 v39, T40 v40,
+      T41 v41) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7),
+      v8_(v8), v9_(v9), v10_(v10), v11_(v11), v12_(v12), v13_(v13), v14_(v14),
+      v15_(v15), v16_(v16), v17_(v17), v18_(v18), v19_(v19), v20_(v20),
+      v21_(v21), v22_(v22), v23_(v23), v24_(v24), v25_(v25), v26_(v26),
+      v27_(v27), v28_(v28), v29_(v29), v30_(v30), v31_(v31), v32_(v32),
+      v33_(v33), v34_(v34), v35_(v35), v36_(v36), v37_(v37), v38_(v38),
+      v39_(v39), v40_(v40), v41_(v41) {}
+
+  template <typename T>
+  operator ParamGenerator<T>() const {
+    const T array[] = {static_cast<T>(v1_), static_cast<T>(v2_),
+        static_cast<T>(v3_), static_cast<T>(v4_), static_cast<T>(v5_),
+        static_cast<T>(v6_), static_cast<T>(v7_), static_cast<T>(v8_),
+        static_cast<T>(v9_), static_cast<T>(v10_), static_cast<T>(v11_),
+        static_cast<T>(v12_), static_cast<T>(v13_), static_cast<T>(v14_),
+        static_cast<T>(v15_), static_cast<T>(v16_), static_cast<T>(v17_),
+        static_cast<T>(v18_), static_cast<T>(v19_), static_cast<T>(v20_),
+        static_cast<T>(v21_), static_cast<T>(v22_), static_cast<T>(v23_),
+        static_cast<T>(v24_), static_cast<T>(v25_), static_cast<T>(v26_),
+        static_cast<T>(v27_), static_cast<T>(v28_), static_cast<T>(v29_),
+        static_cast<T>(v30_), static_cast<T>(v31_), static_cast<T>(v32_),
+        static_cast<T>(v33_), static_cast<T>(v34_), static_cast<T>(v35_),
+        static_cast<T>(v36_), static_cast<T>(v37_), static_cast<T>(v38_),
+        static_cast<T>(v39_), static_cast<T>(v40_), static_cast<T>(v41_)};
+    return ValuesIn(array);
+  }
+
+ private:
+  // No implementation - assignment is unsupported.
+  void operator=(const ValueArray41& other);
+
+  const T1 v1_;
+  const T2 v2_;
+  const T3 v3_;
+  const T4 v4_;
+  const T5 v5_;
+  const T6 v6_;
+  const T7 v7_;
+  const T8 v8_;
+  const T9 v9_;
+  const T10 v10_;
+  const T11 v11_;
+  const T12 v12_;
+  const T13 v13_;
+  const T14 v14_;
+  const T15 v15_;
+  const T16 v16_;
+  const T17 v17_;
+  const T18 v18_;
+  const T19 v19_;
+  const T20 v20_;
+  const T21 v21_;
+  const T22 v22_;
+  const T23 v23_;
+  const T24 v24_;
+  const T25 v25_;
+  const T26 v26_;
+  const T27 v27_;
+  const T28 v28_;
+  const T29 v29_;
+  const T30 v30_;
+  const T31 v31_;
+  const T32 v32_;
+  const T33 v33_;
+  const T34 v34_;
+  const T35 v35_;
+  const T36 v36_;
+  const T37 v37_;
+  const T38 v38_;
+  const T39 v39_;
+  const T40 v40_;
+  const T41 v41_;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32, typename T33, typename T34, typename T35,
+    typename T36, typename T37, typename T38, typename T39, typename T40,
+    typename T41, typename T42>
+class ValueArray42 {
+ public:
+  ValueArray42(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9,
+      T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17,
+      T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25,
+      T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, T32 v32, T33 v33,
+      T34 v34, T35 v35, T36 v36, T37 v37, T38 v38, T39 v39, T40 v40, T41 v41,
+      T42 v42) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7),
+      v8_(v8), v9_(v9), v10_(v10), v11_(v11), v12_(v12), v13_(v13), v14_(v14),
+      v15_(v15), v16_(v16), v17_(v17), v18_(v18), v19_(v19), v20_(v20),
+      v21_(v21), v22_(v22), v23_(v23), v24_(v24), v25_(v25), v26_(v26),
+      v27_(v27), v28_(v28), v29_(v29), v30_(v30), v31_(v31), v32_(v32),
+      v33_(v33), v34_(v34), v35_(v35), v36_(v36), v37_(v37), v38_(v38),
+      v39_(v39), v40_(v40), v41_(v41), v42_(v42) {}
+
+  template <typename T>
+  operator ParamGenerator<T>() const {
+    const T array[] = {static_cast<T>(v1_), static_cast<T>(v2_),
+        static_cast<T>(v3_), static_cast<T>(v4_), static_cast<T>(v5_),
+        static_cast<T>(v6_), static_cast<T>(v7_), static_cast<T>(v8_),
+        static_cast<T>(v9_), static_cast<T>(v10_), static_cast<T>(v11_),
+        static_cast<T>(v12_), static_cast<T>(v13_), static_cast<T>(v14_),
+        static_cast<T>(v15_), static_cast<T>(v16_), static_cast<T>(v17_),
+        static_cast<T>(v18_), static_cast<T>(v19_), static_cast<T>(v20_),
+        static_cast<T>(v21_), static_cast<T>(v22_), static_cast<T>(v23_),
+        static_cast<T>(v24_), static_cast<T>(v25_), static_cast<T>(v26_),
+        static_cast<T>(v27_), static_cast<T>(v28_), static_cast<T>(v29_),
+        static_cast<T>(v30_), static_cast<T>(v31_), static_cast<T>(v32_),
+        static_cast<T>(v33_), static_cast<T>(v34_), static_cast<T>(v35_),
+        static_cast<T>(v36_), static_cast<T>(v37_), static_cast<T>(v38_),
+        static_cast<T>(v39_), static_cast<T>(v40_), static_cast<T>(v41_),
+        static_cast<T>(v42_)};
+    return ValuesIn(array);
+  }
+
+ private:
+  // No implementation - assignment is unsupported.
+  void operator=(const ValueArray42& other);
+
+  const T1 v1_;
+  const T2 v2_;
+  const T3 v3_;
+  const T4 v4_;
+  const T5 v5_;
+  const T6 v6_;
+  const T7 v7_;
+  const T8 v8_;
+  const T9 v9_;
+  const T10 v10_;
+  const T11 v11_;
+  const T12 v12_;
+  const T13 v13_;
+  const T14 v14_;
+  const T15 v15_;
+  const T16 v16_;
+  const T17 v17_;
+  const T18 v18_;
+  const T19 v19_;
+  const T20 v20_;
+  const T21 v21_;
+  const T22 v22_;
+  const T23 v23_;
+  const T24 v24_;
+  const T25 v25_;
+  const T26 v26_;
+  const T27 v27_;
+  const T28 v28_;
+  const T29 v29_;
+  const T30 v30_;
+  const T31 v31_;
+  const T32 v32_;
+  const T33 v33_;
+  const T34 v34_;
+  const T35 v35_;
+  const T36 v36_;
+  const T37 v37_;
+  const T38 v38_;
+  const T39 v39_;
+  const T40 v40_;
+  const T41 v41_;
+  const T42 v42_;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32, typename T33, typename T34, typename T35,
+    typename T36, typename T37, typename T38, typename T39, typename T40,
+    typename T41, typename T42, typename T43>
+class ValueArray43 {
+ public:
+  ValueArray43(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9,
+      T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17,
+      T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25,
+      T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, T32 v32, T33 v33,
+      T34 v34, T35 v35, T36 v36, T37 v37, T38 v38, T39 v39, T40 v40, T41 v41,
+      T42 v42, T43 v43) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6),
+      v7_(v7), v8_(v8), v9_(v9), v10_(v10), v11_(v11), v12_(v12), v13_(v13),
+      v14_(v14), v15_(v15), v16_(v16), v17_(v17), v18_(v18), v19_(v19),
+      v20_(v20), v21_(v21), v22_(v22), v23_(v23), v24_(v24), v25_(v25),
+      v26_(v26), v27_(v27), v28_(v28), v29_(v29), v30_(v30), v31_(v31),
+      v32_(v32), v33_(v33), v34_(v34), v35_(v35), v36_(v36), v37_(v37),
+      v38_(v38), v39_(v39), v40_(v40), v41_(v41), v42_(v42), v43_(v43) {}
+
+  template <typename T>
+  operator ParamGenerator<T>() const {
+    const T array[] = {static_cast<T>(v1_), static_cast<T>(v2_),
+        static_cast<T>(v3_), static_cast<T>(v4_), static_cast<T>(v5_),
+        static_cast<T>(v6_), static_cast<T>(v7_), static_cast<T>(v8_),
+        static_cast<T>(v9_), static_cast<T>(v10_), static_cast<T>(v11_),
+        static_cast<T>(v12_), static_cast<T>(v13_), static_cast<T>(v14_),
+        static_cast<T>(v15_), static_cast<T>(v16_), static_cast<T>(v17_),
+        static_cast<T>(v18_), static_cast<T>(v19_), static_cast<T>(v20_),
+        static_cast<T>(v21_), static_cast<T>(v22_), static_cast<T>(v23_),
+        static_cast<T>(v24_), static_cast<T>(v25_), static_cast<T>(v26_),
+        static_cast<T>(v27_), static_cast<T>(v28_), static_cast<T>(v29_),
+        static_cast<T>(v30_), static_cast<T>(v31_), static_cast<T>(v32_),
+        static_cast<T>(v33_), static_cast<T>(v34_), static_cast<T>(v35_),
+        static_cast<T>(v36_), static_cast<T>(v37_), static_cast<T>(v38_),
+        static_cast<T>(v39_), static_cast<T>(v40_), static_cast<T>(v41_),
+        static_cast<T>(v42_), static_cast<T>(v43_)};
+    return ValuesIn(array);
+  }
+
+ private:
+  // No implementation - assignment is unsupported.
+  void operator=(const ValueArray43& other);
+
+  const T1 v1_;
+  const T2 v2_;
+  const T3 v3_;
+  const T4 v4_;
+  const T5 v5_;
+  const T6 v6_;
+  const T7 v7_;
+  const T8 v8_;
+  const T9 v9_;
+  const T10 v10_;
+  const T11 v11_;
+  const T12 v12_;
+  const T13 v13_;
+  const T14 v14_;
+  const T15 v15_;
+  const T16 v16_;
+  const T17 v17_;
+  const T18 v18_;
+  const T19 v19_;
+  const T20 v20_;
+  const T21 v21_;
+  const T22 v22_;
+  const T23 v23_;
+  const T24 v24_;
+  const T25 v25_;
+  const T26 v26_;
+  const T27 v27_;
+  const T28 v28_;
+  const T29 v29_;
+  const T30 v30_;
+  const T31 v31_;
+  const T32 v32_;
+  const T33 v33_;
+  const T34 v34_;
+  const T35 v35_;
+  const T36 v36_;
+  const T37 v37_;
+  const T38 v38_;
+  const T39 v39_;
+  const T40 v40_;
+  const T41 v41_;
+  const T42 v42_;
+  const T43 v43_;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32, typename T33, typename T34, typename T35,
+    typename T36, typename T37, typename T38, typename T39, typename T40,
+    typename T41, typename T42, typename T43, typename T44>
+class ValueArray44 {
+ public:
+  ValueArray44(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9,
+      T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17,
+      T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25,
+      T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, T32 v32, T33 v33,
+      T34 v34, T35 v35, T36 v36, T37 v37, T38 v38, T39 v39, T40 v40, T41 v41,
+      T42 v42, T43 v43, T44 v44) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), v5_(v5),
+      v6_(v6), v7_(v7), v8_(v8), v9_(v9), v10_(v10), v11_(v11), v12_(v12),
+      v13_(v13), v14_(v14), v15_(v15), v16_(v16), v17_(v17), v18_(v18),
+      v19_(v19), v20_(v20), v21_(v21), v22_(v22), v23_(v23), v24_(v24),
+      v25_(v25), v26_(v26), v27_(v27), v28_(v28), v29_(v29), v30_(v30),
+      v31_(v31), v32_(v32), v33_(v33), v34_(v34), v35_(v35), v36_(v36),
+      v37_(v37), v38_(v38), v39_(v39), v40_(v40), v41_(v41), v42_(v42),
+      v43_(v43), v44_(v44) {}
+
+  template <typename T>
+  operator ParamGenerator<T>() const {
+    const T array[] = {static_cast<T>(v1_), static_cast<T>(v2_),
+        static_cast<T>(v3_), static_cast<T>(v4_), static_cast<T>(v5_),
+        static_cast<T>(v6_), static_cast<T>(v7_), static_cast<T>(v8_),
+        static_cast<T>(v9_), static_cast<T>(v10_), static_cast<T>(v11_),
+        static_cast<T>(v12_), static_cast<T>(v13_), static_cast<T>(v14_),
+        static_cast<T>(v15_), static_cast<T>(v16_), static_cast<T>(v17_),
+        static_cast<T>(v18_), static_cast<T>(v19_), static_cast<T>(v20_),
+        static_cast<T>(v21_), static_cast<T>(v22_), static_cast<T>(v23_),
+        static_cast<T>(v24_), static_cast<T>(v25_), static_cast<T>(v26_),
+        static_cast<T>(v27_), static_cast<T>(v28_), static_cast<T>(v29_),
+        static_cast<T>(v30_), static_cast<T>(v31_), static_cast<T>(v32_),
+        static_cast<T>(v33_), static_cast<T>(v34_), static_cast<T>(v35_),
+        static_cast<T>(v36_), static_cast<T>(v37_), static_cast<T>(v38_),
+        static_cast<T>(v39_), static_cast<T>(v40_), static_cast<T>(v41_),
+        static_cast<T>(v42_), static_cast<T>(v43_), static_cast<T>(v44_)};
+    return ValuesIn(array);
+  }
+
+ private:
+  // No implementation - assignment is unsupported.
+  void operator=(const ValueArray44& other);
+
+  const T1 v1_;
+  const T2 v2_;
+  const T3 v3_;
+  const T4 v4_;
+  const T5 v5_;
+  const T6 v6_;
+  const T7 v7_;
+  const T8 v8_;
+  const T9 v9_;
+  const T10 v10_;
+  const T11 v11_;
+  const T12 v12_;
+  const T13 v13_;
+  const T14 v14_;
+  const T15 v15_;
+  const T16 v16_;
+  const T17 v17_;
+  const T18 v18_;
+  const T19 v19_;
+  const T20 v20_;
+  const T21 v21_;
+  const T22 v22_;
+  const T23 v23_;
+  const T24 v24_;
+  const T25 v25_;
+  const T26 v26_;
+  const T27 v27_;
+  const T28 v28_;
+  const T29 v29_;
+  const T30 v30_;
+  const T31 v31_;
+  const T32 v32_;
+  const T33 v33_;
+  const T34 v34_;
+  const T35 v35_;
+  const T36 v36_;
+  const T37 v37_;
+  const T38 v38_;
+  const T39 v39_;
+  const T40 v40_;
+  const T41 v41_;
+  const T42 v42_;
+  const T43 v43_;
+  const T44 v44_;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32, typename T33, typename T34, typename T35,
+    typename T36, typename T37, typename T38, typename T39, typename T40,
+    typename T41, typename T42, typename T43, typename T44, typename T45>
+class ValueArray45 {
+ public:
+  ValueArray45(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9,
+      T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17,
+      T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25,
+      T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, T32 v32, T33 v33,
+      T34 v34, T35 v35, T36 v36, T37 v37, T38 v38, T39 v39, T40 v40, T41 v41,
+      T42 v42, T43 v43, T44 v44, T45 v45) : v1_(v1), v2_(v2), v3_(v3), v4_(v4),
+      v5_(v5), v6_(v6), v7_(v7), v8_(v8), v9_(v9), v10_(v10), v11_(v11),
+      v12_(v12), v13_(v13), v14_(v14), v15_(v15), v16_(v16), v17_(v17),
+      v18_(v18), v19_(v19), v20_(v20), v21_(v21), v22_(v22), v23_(v23),
+      v24_(v24), v25_(v25), v26_(v26), v27_(v27), v28_(v28), v29_(v29),
+      v30_(v30), v31_(v31), v32_(v32), v33_(v33), v34_(v34), v35_(v35),
+      v36_(v36), v37_(v37), v38_(v38), v39_(v39), v40_(v40), v41_(v41),
+      v42_(v42), v43_(v43), v44_(v44), v45_(v45) {}
+
+  template <typename T>
+  operator ParamGenerator<T>() const {
+    const T array[] = {static_cast<T>(v1_), static_cast<T>(v2_),
+        static_cast<T>(v3_), static_cast<T>(v4_), static_cast<T>(v5_),
+        static_cast<T>(v6_), static_cast<T>(v7_), static_cast<T>(v8_),
+        static_cast<T>(v9_), static_cast<T>(v10_), static_cast<T>(v11_),
+        static_cast<T>(v12_), static_cast<T>(v13_), static_cast<T>(v14_),
+        static_cast<T>(v15_), static_cast<T>(v16_), static_cast<T>(v17_),
+        static_cast<T>(v18_), static_cast<T>(v19_), static_cast<T>(v20_),
+        static_cast<T>(v21_), static_cast<T>(v22_), static_cast<T>(v23_),
+        static_cast<T>(v24_), static_cast<T>(v25_), static_cast<T>(v26_),
+        static_cast<T>(v27_), static_cast<T>(v28_), static_cast<T>(v29_),
+        static_cast<T>(v30_), static_cast<T>(v31_), static_cast<T>(v32_),
+        static_cast<T>(v33_), static_cast<T>(v34_), static_cast<T>(v35_),
+        static_cast<T>(v36_), static_cast<T>(v37_), static_cast<T>(v38_),
+        static_cast<T>(v39_), static_cast<T>(v40_), static_cast<T>(v41_),
+        static_cast<T>(v42_), static_cast<T>(v43_), static_cast<T>(v44_),
+        static_cast<T>(v45_)};
+    return ValuesIn(array);
+  }
+
+ private:
+  // No implementation - assignment is unsupported.
+  void operator=(const ValueArray45& other);
+
+  const T1 v1_;
+  const T2 v2_;
+  const T3 v3_;
+  const T4 v4_;
+  const T5 v5_;
+  const T6 v6_;
+  const T7 v7_;
+  const T8 v8_;
+  const T9 v9_;
+  const T10 v10_;
+  const T11 v11_;
+  const T12 v12_;
+  const T13 v13_;
+  const T14 v14_;
+  const T15 v15_;
+  const T16 v16_;
+  const T17 v17_;
+  const T18 v18_;
+  const T19 v19_;
+  const T20 v20_;
+  const T21 v21_;
+  const T22 v22_;
+  const T23 v23_;
+  const T24 v24_;
+  const T25 v25_;
+  const T26 v26_;
+  const T27 v27_;
+  const T28 v28_;
+  const T29 v29_;
+  const T30 v30_;
+  const T31 v31_;
+  const T32 v32_;
+  const T33 v33_;
+  const T34 v34_;
+  const T35 v35_;
+  const T36 v36_;
+  const T37 v37_;
+  const T38 v38_;
+  const T39 v39_;
+  const T40 v40_;
+  const T41 v41_;
+  const T42 v42_;
+  const T43 v43_;
+  const T44 v44_;
+  const T45 v45_;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32, typename T33, typename T34, typename T35,
+    typename T36, typename T37, typename T38, typename T39, typename T40,
+    typename T41, typename T42, typename T43, typename T44, typename T45,
+    typename T46>
+class ValueArray46 {
+ public:
+  ValueArray46(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9,
+      T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17,
+      T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25,
+      T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, T32 v32, T33 v33,
+      T34 v34, T35 v35, T36 v36, T37 v37, T38 v38, T39 v39, T40 v40, T41 v41,
+      T42 v42, T43 v43, T44 v44, T45 v45, T46 v46) : v1_(v1), v2_(v2), v3_(v3),
+      v4_(v4), v5_(v5), v6_(v6), v7_(v7), v8_(v8), v9_(v9), v10_(v10),
+      v11_(v11), v12_(v12), v13_(v13), v14_(v14), v15_(v15), v16_(v16),
+      v17_(v17), v18_(v18), v19_(v19), v20_(v20), v21_(v21), v22_(v22),
+      v23_(v23), v24_(v24), v25_(v25), v26_(v26), v27_(v27), v28_(v28),
+      v29_(v29), v30_(v30), v31_(v31), v32_(v32), v33_(v33), v34_(v34),
+      v35_(v35), v36_(v36), v37_(v37), v38_(v38), v39_(v39), v40_(v40),
+      v41_(v41), v42_(v42), v43_(v43), v44_(v44), v45_(v45), v46_(v46) {}
+
+  template <typename T>
+  operator ParamGenerator<T>() const {
+    const T array[] = {static_cast<T>(v1_), static_cast<T>(v2_),
+        static_cast<T>(v3_), static_cast<T>(v4_), static_cast<T>(v5_),
+        static_cast<T>(v6_), static_cast<T>(v7_), static_cast<T>(v8_),
+        static_cast<T>(v9_), static_cast<T>(v10_), static_cast<T>(v11_),
+        static_cast<T>(v12_), static_cast<T>(v13_), static_cast<T>(v14_),
+        static_cast<T>(v15_), static_cast<T>(v16_), static_cast<T>(v17_),
+        static_cast<T>(v18_), static_cast<T>(v19_), static_cast<T>(v20_),
+        static_cast<T>(v21_), static_cast<T>(v22_), static_cast<T>(v23_),
+        static_cast<T>(v24_), static_cast<T>(v25_), static_cast<T>(v26_),
+        static_cast<T>(v27_), static_cast<T>(v28_), static_cast<T>(v29_),
+        static_cast<T>(v30_), static_cast<T>(v31_), static_cast<T>(v32_),
+        static_cast<T>(v33_), static_cast<T>(v34_), static_cast<T>(v35_),
+        static_cast<T>(v36_), static_cast<T>(v37_), static_cast<T>(v38_),
+        static_cast<T>(v39_), static_cast<T>(v40_), static_cast<T>(v41_),
+        static_cast<T>(v42_), static_cast<T>(v43_), static_cast<T>(v44_),
+        static_cast<T>(v45_), static_cast<T>(v46_)};
+    return ValuesIn(array);
+  }
+
+ private:
+  // No implementation - assignment is unsupported.
+  void operator=(const ValueArray46& other);
+
+  const T1 v1_;
+  const T2 v2_;
+  const T3 v3_;
+  const T4 v4_;
+  const T5 v5_;
+  const T6 v6_;
+  const T7 v7_;
+  const T8 v8_;
+  const T9 v9_;
+  const T10 v10_;
+  const T11 v11_;
+  const T12 v12_;
+  const T13 v13_;
+  const T14 v14_;
+  const T15 v15_;
+  const T16 v16_;
+  const T17 v17_;
+  const T18 v18_;
+  const T19 v19_;
+  const T20 v20_;
+  const T21 v21_;
+  const T22 v22_;
+  const T23 v23_;
+  const T24 v24_;
+  const T25 v25_;
+  const T26 v26_;
+  const T27 v27_;
+  const T28 v28_;
+  const T29 v29_;
+  const T30 v30_;
+  const T31 v31_;
+  const T32 v32_;
+  const T33 v33_;
+  const T34 v34_;
+  const T35 v35_;
+  const T36 v36_;
+  const T37 v37_;
+  const T38 v38_;
+  const T39 v39_;
+  const T40 v40_;
+  const T41 v41_;
+  const T42 v42_;
+  const T43 v43_;
+  const T44 v44_;
+  const T45 v45_;
+  const T46 v46_;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32, typename T33, typename T34, typename T35,
+    typename T36, typename T37, typename T38, typename T39, typename T40,
+    typename T41, typename T42, typename T43, typename T44, typename T45,
+    typename T46, typename T47>
+class ValueArray47 {
+ public:
+  ValueArray47(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9,
+      T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17,
+      T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25,
+      T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, T32 v32, T33 v33,
+      T34 v34, T35 v35, T36 v36, T37 v37, T38 v38, T39 v39, T40 v40, T41 v41,
+      T42 v42, T43 v43, T44 v44, T45 v45, T46 v46, T47 v47) : v1_(v1), v2_(v2),
+      v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7), v8_(v8), v9_(v9), v10_(v10),
+      v11_(v11), v12_(v12), v13_(v13), v14_(v14), v15_(v15), v16_(v16),
+      v17_(v17), v18_(v18), v19_(v19), v20_(v20), v21_(v21), v22_(v22),
+      v23_(v23), v24_(v24), v25_(v25), v26_(v26), v27_(v27), v28_(v28),
+      v29_(v29), v30_(v30), v31_(v31), v32_(v32), v33_(v33), v34_(v34),
+      v35_(v35), v36_(v36), v37_(v37), v38_(v38), v39_(v39), v40_(v40),
+      v41_(v41), v42_(v42), v43_(v43), v44_(v44), v45_(v45), v46_(v46),
+      v47_(v47) {}
+
+  template <typename T>
+  operator ParamGenerator<T>() const {
+    const T array[] = {static_cast<T>(v1_), static_cast<T>(v2_),
+        static_cast<T>(v3_), static_cast<T>(v4_), static_cast<T>(v5_),
+        static_cast<T>(v6_), static_cast<T>(v7_), static_cast<T>(v8_),
+        static_cast<T>(v9_), static_cast<T>(v10_), static_cast<T>(v11_),
+        static_cast<T>(v12_), static_cast<T>(v13_), static_cast<T>(v14_),
+        static_cast<T>(v15_), static_cast<T>(v16_), static_cast<T>(v17_),
+        static_cast<T>(v18_), static_cast<T>(v19_), static_cast<T>(v20_),
+        static_cast<T>(v21_), static_cast<T>(v22_), static_cast<T>(v23_),
+        static_cast<T>(v24_), static_cast<T>(v25_), static_cast<T>(v26_),
+        static_cast<T>(v27_), static_cast<T>(v28_), static_cast<T>(v29_),
+        static_cast<T>(v30_), static_cast<T>(v31_), static_cast<T>(v32_),
+        static_cast<T>(v33_), static_cast<T>(v34_), static_cast<T>(v35_),
+        static_cast<T>(v36_), static_cast<T>(v37_), static_cast<T>(v38_),
+        static_cast<T>(v39_), static_cast<T>(v40_), static_cast<T>(v41_),
+        static_cast<T>(v42_), static_cast<T>(v43_), static_cast<T>(v44_),
+        static_cast<T>(v45_), static_cast<T>(v46_), static_cast<T>(v47_)};
+    return ValuesIn(array);
+  }
+
+ private:
+  // No implementation - assignment is unsupported.
+  void operator=(const ValueArray47& other);
+
+  const T1 v1_;
+  const T2 v2_;
+  const T3 v3_;
+  const T4 v4_;
+  const T5 v5_;
+  const T6 v6_;
+  const T7 v7_;
+  const T8 v8_;
+  const T9 v9_;
+  const T10 v10_;
+  const T11 v11_;
+  const T12 v12_;
+  const T13 v13_;
+  const T14 v14_;
+  const T15 v15_;
+  const T16 v16_;
+  const T17 v17_;
+  const T18 v18_;
+  const T19 v19_;
+  const T20 v20_;
+  const T21 v21_;
+  const T22 v22_;
+  const T23 v23_;
+  const T24 v24_;
+  const T25 v25_;
+  const T26 v26_;
+  const T27 v27_;
+  const T28 v28_;
+  const T29 v29_;
+  const T30 v30_;
+  const T31 v31_;
+  const T32 v32_;
+  const T33 v33_;
+  const T34 v34_;
+  const T35 v35_;
+  const T36 v36_;
+  const T37 v37_;
+  const T38 v38_;
+  const T39 v39_;
+  const T40 v40_;
+  const T41 v41_;
+  const T42 v42_;
+  const T43 v43_;
+  const T44 v44_;
+  const T45 v45_;
+  const T46 v46_;
+  const T47 v47_;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32, typename T33, typename T34, typename T35,
+    typename T36, typename T37, typename T38, typename T39, typename T40,
+    typename T41, typename T42, typename T43, typename T44, typename T45,
+    typename T46, typename T47, typename T48>
+class ValueArray48 {
+ public:
+  ValueArray48(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9,
+      T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17,
+      T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25,
+      T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, T32 v32, T33 v33,
+      T34 v34, T35 v35, T36 v36, T37 v37, T38 v38, T39 v39, T40 v40, T41 v41,
+      T42 v42, T43 v43, T44 v44, T45 v45, T46 v46, T47 v47, T48 v48) : v1_(v1),
+      v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7), v8_(v8), v9_(v9),
+      v10_(v10), v11_(v11), v12_(v12), v13_(v13), v14_(v14), v15_(v15),
+      v16_(v16), v17_(v17), v18_(v18), v19_(v19), v20_(v20), v21_(v21),
+      v22_(v22), v23_(v23), v24_(v24), v25_(v25), v26_(v26), v27_(v27),
+      v28_(v28), v29_(v29), v30_(v30), v31_(v31), v32_(v32), v33_(v33),
+      v34_(v34), v35_(v35), v36_(v36), v37_(v37), v38_(v38), v39_(v39),
+      v40_(v40), v41_(v41), v42_(v42), v43_(v43), v44_(v44), v45_(v45),
+      v46_(v46), v47_(v47), v48_(v48) {}
+
+  template <typename T>
+  operator ParamGenerator<T>() const {
+    const T array[] = {static_cast<T>(v1_), static_cast<T>(v2_),
+        static_cast<T>(v3_), static_cast<T>(v4_), static_cast<T>(v5_),
+        static_cast<T>(v6_), static_cast<T>(v7_), static_cast<T>(v8_),
+        static_cast<T>(v9_), static_cast<T>(v10_), static_cast<T>(v11_),
+        static_cast<T>(v12_), static_cast<T>(v13_), static_cast<T>(v14_),
+        static_cast<T>(v15_), static_cast<T>(v16_), static_cast<T>(v17_),
+        static_cast<T>(v18_), static_cast<T>(v19_), static_cast<T>(v20_),
+        static_cast<T>(v21_), static_cast<T>(v22_), static_cast<T>(v23_),
+        static_cast<T>(v24_), static_cast<T>(v25_), static_cast<T>(v26_),
+        static_cast<T>(v27_), static_cast<T>(v28_), static_cast<T>(v29_),
+        static_cast<T>(v30_), static_cast<T>(v31_), static_cast<T>(v32_),
+        static_cast<T>(v33_), static_cast<T>(v34_), static_cast<T>(v35_),
+        static_cast<T>(v36_), static_cast<T>(v37_), static_cast<T>(v38_),
+        static_cast<T>(v39_), static_cast<T>(v40_), static_cast<T>(v41_),
+        static_cast<T>(v42_), static_cast<T>(v43_), static_cast<T>(v44_),
+        static_cast<T>(v45_), static_cast<T>(v46_), static_cast<T>(v47_),
+        static_cast<T>(v48_)};
+    return ValuesIn(array);
+  }
+
+ private:
+  // No implementation - assignment is unsupported.
+  void operator=(const ValueArray48& other);
+
+  const T1 v1_;
+  const T2 v2_;
+  const T3 v3_;
+  const T4 v4_;
+  const T5 v5_;
+  const T6 v6_;
+  const T7 v7_;
+  const T8 v8_;
+  const T9 v9_;
+  const T10 v10_;
+  const T11 v11_;
+  const T12 v12_;
+  const T13 v13_;
+  const T14 v14_;
+  const T15 v15_;
+  const T16 v16_;
+  const T17 v17_;
+  const T18 v18_;
+  const T19 v19_;
+  const T20 v20_;
+  const T21 v21_;
+  const T22 v22_;
+  const T23 v23_;
+  const T24 v24_;
+  const T25 v25_;
+  const T26 v26_;
+  const T27 v27_;
+  const T28 v28_;
+  const T29 v29_;
+  const T30 v30_;
+  const T31 v31_;
+  const T32 v32_;
+  const T33 v33_;
+  const T34 v34_;
+  const T35 v35_;
+  const T36 v36_;
+  const T37 v37_;
+  const T38 v38_;
+  const T39 v39_;
+  const T40 v40_;
+  const T41 v41_;
+  const T42 v42_;
+  const T43 v43_;
+  const T44 v44_;
+  const T45 v45_;
+  const T46 v46_;
+  const T47 v47_;
+  const T48 v48_;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32, typename T33, typename T34, typename T35,
+    typename T36, typename T37, typename T38, typename T39, typename T40,
+    typename T41, typename T42, typename T43, typename T44, typename T45,
+    typename T46, typename T47, typename T48, typename T49>
+class ValueArray49 {
+ public:
+  ValueArray49(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9,
+      T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17,
+      T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25,
+      T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, T32 v32, T33 v33,
+      T34 v34, T35 v35, T36 v36, T37 v37, T38 v38, T39 v39, T40 v40, T41 v41,
+      T42 v42, T43 v43, T44 v44, T45 v45, T46 v46, T47 v47, T48 v48,
+      T49 v49) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7),
+      v8_(v8), v9_(v9), v10_(v10), v11_(v11), v12_(v12), v13_(v13), v14_(v14),
+      v15_(v15), v16_(v16), v17_(v17), v18_(v18), v19_(v19), v20_(v20),
+      v21_(v21), v22_(v22), v23_(v23), v24_(v24), v25_(v25), v26_(v26),
+      v27_(v27), v28_(v28), v29_(v29), v30_(v30), v31_(v31), v32_(v32),
+      v33_(v33), v34_(v34), v35_(v35), v36_(v36), v37_(v37), v38_(v38),
+      v39_(v39), v40_(v40), v41_(v41), v42_(v42), v43_(v43), v44_(v44),
+      v45_(v45), v46_(v46), v47_(v47), v48_(v48), v49_(v49) {}
+
+  template <typename T>
+  operator ParamGenerator<T>() const {
+    const T array[] = {static_cast<T>(v1_), static_cast<T>(v2_),
+        static_cast<T>(v3_), static_cast<T>(v4_), static_cast<T>(v5_),
+        static_cast<T>(v6_), static_cast<T>(v7_), static_cast<T>(v8_),
+        static_cast<T>(v9_), static_cast<T>(v10_), static_cast<T>(v11_),
+        static_cast<T>(v12_), static_cast<T>(v13_), static_cast<T>(v14_),
+        static_cast<T>(v15_), static_cast<T>(v16_), static_cast<T>(v17_),
+        static_cast<T>(v18_), static_cast<T>(v19_), static_cast<T>(v20_),
+        static_cast<T>(v21_), static_cast<T>(v22_), static_cast<T>(v23_),
+        static_cast<T>(v24_), static_cast<T>(v25_), static_cast<T>(v26_),
+        static_cast<T>(v27_), static_cast<T>(v28_), static_cast<T>(v29_),
+        static_cast<T>(v30_), static_cast<T>(v31_), static_cast<T>(v32_),
+        static_cast<T>(v33_), static_cast<T>(v34_), static_cast<T>(v35_),
+        static_cast<T>(v36_), static_cast<T>(v37_), static_cast<T>(v38_),
+        static_cast<T>(v39_), static_cast<T>(v40_), static_cast<T>(v41_),
+        static_cast<T>(v42_), static_cast<T>(v43_), static_cast<T>(v44_),
+        static_cast<T>(v45_), static_cast<T>(v46_), static_cast<T>(v47_),
+        static_cast<T>(v48_), static_cast<T>(v49_)};
+    return ValuesIn(array);
+  }
+
+ private:
+  // No implementation - assignment is unsupported.
+  void operator=(const ValueArray49& other);
+
+  const T1 v1_;
+  const T2 v2_;
+  const T3 v3_;
+  const T4 v4_;
+  const T5 v5_;
+  const T6 v6_;
+  const T7 v7_;
+  const T8 v8_;
+  const T9 v9_;
+  const T10 v10_;
+  const T11 v11_;
+  const T12 v12_;
+  const T13 v13_;
+  const T14 v14_;
+  const T15 v15_;
+  const T16 v16_;
+  const T17 v17_;
+  const T18 v18_;
+  const T19 v19_;
+  const T20 v20_;
+  const T21 v21_;
+  const T22 v22_;
+  const T23 v23_;
+  const T24 v24_;
+  const T25 v25_;
+  const T26 v26_;
+  const T27 v27_;
+  const T28 v28_;
+  const T29 v29_;
+  const T30 v30_;
+  const T31 v31_;
+  const T32 v32_;
+  const T33 v33_;
+  const T34 v34_;
+  const T35 v35_;
+  const T36 v36_;
+  const T37 v37_;
+  const T38 v38_;
+  const T39 v39_;
+  const T40 v40_;
+  const T41 v41_;
+  const T42 v42_;
+  const T43 v43_;
+  const T44 v44_;
+  const T45 v45_;
+  const T46 v46_;
+  const T47 v47_;
+  const T48 v48_;
+  const T49 v49_;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32, typename T33, typename T34, typename T35,
+    typename T36, typename T37, typename T38, typename T39, typename T40,
+    typename T41, typename T42, typename T43, typename T44, typename T45,
+    typename T46, typename T47, typename T48, typename T49, typename T50>
+class ValueArray50 {
+ public:
+  ValueArray50(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9,
+      T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17,
+      T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25,
+      T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, T32 v32, T33 v33,
+      T34 v34, T35 v35, T36 v36, T37 v37, T38 v38, T39 v39, T40 v40, T41 v41,
+      T42 v42, T43 v43, T44 v44, T45 v45, T46 v46, T47 v47, T48 v48, T49 v49,
+      T50 v50) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7),
+      v8_(v8), v9_(v9), v10_(v10), v11_(v11), v12_(v12), v13_(v13), v14_(v14),
+      v15_(v15), v16_(v16), v17_(v17), v18_(v18), v19_(v19), v20_(v20),
+      v21_(v21), v22_(v22), v23_(v23), v24_(v24), v25_(v25), v26_(v26),
+      v27_(v27), v28_(v28), v29_(v29), v30_(v30), v31_(v31), v32_(v32),
+      v33_(v33), v34_(v34), v35_(v35), v36_(v36), v37_(v37), v38_(v38),
+      v39_(v39), v40_(v40), v41_(v41), v42_(v42), v43_(v43), v44_(v44),
+      v45_(v45), v46_(v46), v47_(v47), v48_(v48), v49_(v49), v50_(v50) {}
+
+  template <typename T>
+  operator ParamGenerator<T>() const {
+    const T array[] = {static_cast<T>(v1_), static_cast<T>(v2_),
+        static_cast<T>(v3_), static_cast<T>(v4_), static_cast<T>(v5_),
+        static_cast<T>(v6_), static_cast<T>(v7_), static_cast<T>(v8_),
+        static_cast<T>(v9_), static_cast<T>(v10_), static_cast<T>(v11_),
+        static_cast<T>(v12_), static_cast<T>(v13_), static_cast<T>(v14_),
+        static_cast<T>(v15_), static_cast<T>(v16_), static_cast<T>(v17_),
+        static_cast<T>(v18_), static_cast<T>(v19_), static_cast<T>(v20_),
+        static_cast<T>(v21_), static_cast<T>(v22_), static_cast<T>(v23_),
+        static_cast<T>(v24_), static_cast<T>(v25_), static_cast<T>(v26_),
+        static_cast<T>(v27_), static_cast<T>(v28_), static_cast<T>(v29_),
+        static_cast<T>(v30_), static_cast<T>(v31_), static_cast<T>(v32_),
+        static_cast<T>(v33_), static_cast<T>(v34_), static_cast<T>(v35_),
+        static_cast<T>(v36_), static_cast<T>(v37_), static_cast<T>(v38_),
+        static_cast<T>(v39_), static_cast<T>(v40_), static_cast<T>(v41_),
+        static_cast<T>(v42_), static_cast<T>(v43_), static_cast<T>(v44_),
+        static_cast<T>(v45_), static_cast<T>(v46_), static_cast<T>(v47_),
+        static_cast<T>(v48_), static_cast<T>(v49_), static_cast<T>(v50_)};
+    return ValuesIn(array);
+  }
+
+ private:
+  // No implementation - assignment is unsupported.
+  void operator=(const ValueArray50& other);
+
+  const T1 v1_;
+  const T2 v2_;
+  const T3 v3_;
+  const T4 v4_;
+  const T5 v5_;
+  const T6 v6_;
+  const T7 v7_;
+  const T8 v8_;
+  const T9 v9_;
+  const T10 v10_;
+  const T11 v11_;
+  const T12 v12_;
+  const T13 v13_;
+  const T14 v14_;
+  const T15 v15_;
+  const T16 v16_;
+  const T17 v17_;
+  const T18 v18_;
+  const T19 v19_;
+  const T20 v20_;
+  const T21 v21_;
+  const T22 v22_;
+  const T23 v23_;
+  const T24 v24_;
+  const T25 v25_;
+  const T26 v26_;
+  const T27 v27_;
+  const T28 v28_;
+  const T29 v29_;
+  const T30 v30_;
+  const T31 v31_;
+  const T32 v32_;
+  const T33 v33_;
+  const T34 v34_;
+  const T35 v35_;
+  const T36 v36_;
+  const T37 v37_;
+  const T38 v38_;
+  const T39 v39_;
+  const T40 v40_;
+  const T41 v41_;
+  const T42 v42_;
+  const T43 v43_;
+  const T44 v44_;
+  const T45 v45_;
+  const T46 v46_;
+  const T47 v47_;
+  const T48 v48_;
+  const T49 v49_;
+  const T50 v50_;
+};
+
+# if GTEST_HAS_COMBINE
+// INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE.
+//
+// Generates values from the Cartesian product of values produced
+// by the argument generators.
+//
+template <typename T1, typename T2>
+class CartesianProductGenerator2
+    : public ParamGeneratorInterface< ::std::tr1::tuple<T1, T2> > {
+ public:
+  typedef ::std::tr1::tuple<T1, T2> ParamType;
+
+  CartesianProductGenerator2(const ParamGenerator<T1>& g1,
+      const ParamGenerator<T2>& g2)
+      : g1_(g1), g2_(g2) {}
+  virtual ~CartesianProductGenerator2() {}
+
+  virtual ParamIteratorInterface<ParamType>* Begin() const {
+    return new Iterator(this, g1_, g1_.begin(), g2_, g2_.begin());
+  }
+  virtual ParamIteratorInterface<ParamType>* End() const {
+    return new Iterator(this, g1_, g1_.end(), g2_, g2_.end());
+  }
+
+ private:
+  class Iterator : public ParamIteratorInterface<ParamType> {
+   public:
+    Iterator(const ParamGeneratorInterface<ParamType>* base,
+      const ParamGenerator<T1>& g1,
+      const typename ParamGenerator<T1>::iterator& current1,
+      const ParamGenerator<T2>& g2,
+      const typename ParamGenerator<T2>::iterator& current2)
+        : base_(base),
+          begin1_(g1.begin()), end1_(g1.end()), current1_(current1),
+          begin2_(g2.begin()), end2_(g2.end()), current2_(current2)    {
+      ComputeCurrentValue();
+    }
+    virtual ~Iterator() {}
+
+    virtual const ParamGeneratorInterface<ParamType>* BaseGenerator() const {
+      return base_;
+    }
+    // Advance should not be called on beyond-of-range iterators
+    // so no component iterators must be beyond end of range, either.
+    virtual void Advance() {
+      assert(!AtEnd());
+      ++current2_;
+      if (current2_ == end2_) {
+        current2_ = begin2_;
+        ++current1_;
+      }
+      ComputeCurrentValue();
+    }
+    virtual ParamIteratorInterface<ParamType>* Clone() const {
+      return new Iterator(*this);
+    }
+    virtual const ParamType* Current() const { return &current_value_; }
+    virtual bool Equals(const ParamIteratorInterface<ParamType>& other) const {
+      // Having the same base generator guarantees that the other
+      // iterator is of the same type and we can downcast.
+      GTEST_CHECK_(BaseGenerator() == other.BaseGenerator())
+          << "The program attempted to compare iterators "
+          << "from different generators." << std::endl;
+      const Iterator* typed_other =
+          CheckedDowncastToActualType<const Iterator>(&other);
+      // We must report iterators equal if they both point beyond their
+      // respective ranges. That can happen in a variety of fashions,
+      // so we have to consult AtEnd().
+      return (AtEnd() && typed_other->AtEnd()) ||
+         (
+          current1_ == typed_other->current1_ &&
+          current2_ == typed_other->current2_);
+    }
+
+   private:
+    Iterator(const Iterator& other)
+        : base_(other.base_),
+        begin1_(other.begin1_),
+        end1_(other.end1_),
+        current1_(other.current1_),
+        begin2_(other.begin2_),
+        end2_(other.end2_),
+        current2_(other.current2_) {
+      ComputeCurrentValue();
+    }
+
+    void ComputeCurrentValue() {
+      if (!AtEnd())
+        current_value_ = ParamType(*current1_, *current2_);
+    }
+    bool AtEnd() const {
+      // We must report iterator past the end of the range when either of the
+      // component iterators has reached the end of its range.
+      return
+          current1_ == end1_ ||
+          current2_ == end2_;
+    }
+
+    // No implementation - assignment is unsupported.
+    void operator=(const Iterator& other);
+
+    const ParamGeneratorInterface<ParamType>* const base_;
+    // begin[i]_ and end[i]_ define the i-th range that Iterator traverses.
+    // current[i]_ is the actual traversing iterator.
+    const typename ParamGenerator<T1>::iterator begin1_;
+    const typename ParamGenerator<T1>::iterator end1_;
+    typename ParamGenerator<T1>::iterator current1_;
+    const typename ParamGenerator<T2>::iterator begin2_;
+    const typename ParamGenerator<T2>::iterator end2_;
+    typename ParamGenerator<T2>::iterator current2_;
+    ParamType current_value_;
+  };  // class CartesianProductGenerator2::Iterator
+
+  // No implementation - assignment is unsupported.
+  void operator=(const CartesianProductGenerator2& other);
+
+  const ParamGenerator<T1> g1_;
+  const ParamGenerator<T2> g2_;
+};  // class CartesianProductGenerator2
+
+
+template <typename T1, typename T2, typename T3>
+class CartesianProductGenerator3
+    : public ParamGeneratorInterface< ::std::tr1::tuple<T1, T2, T3> > {
+ public:
+  typedef ::std::tr1::tuple<T1, T2, T3> ParamType;
+
+  CartesianProductGenerator3(const ParamGenerator<T1>& g1,
+      const ParamGenerator<T2>& g2, const ParamGenerator<T3>& g3)
+      : g1_(g1), g2_(g2), g3_(g3) {}
+  virtual ~CartesianProductGenerator3() {}
+
+  virtual ParamIteratorInterface<ParamType>* Begin() const {
+    return new Iterator(this, g1_, g1_.begin(), g2_, g2_.begin(), g3_,
+        g3_.begin());
+  }
+  virtual ParamIteratorInterface<ParamType>* End() const {
+    return new Iterator(this, g1_, g1_.end(), g2_, g2_.end(), g3_, g3_.end());
+  }
+
+ private:
+  class Iterator : public ParamIteratorInterface<ParamType> {
+   public:
+    Iterator(const ParamGeneratorInterface<ParamType>* base,
+      const ParamGenerator<T1>& g1,
+      const typename ParamGenerator<T1>::iterator& current1,
+      const ParamGenerator<T2>& g2,
+      const typename ParamGenerator<T2>::iterator& current2,
+      const ParamGenerator<T3>& g3,
+      const typename ParamGenerator<T3>::iterator& current3)
+        : base_(base),
+          begin1_(g1.begin()), end1_(g1.end()), current1_(current1),
+          begin2_(g2.begin()), end2_(g2.end()), current2_(current2),
+          begin3_(g3.begin()), end3_(g3.end()), current3_(current3)    {
+      ComputeCurrentValue();
+    }
+    virtual ~Iterator() {}
+
+    virtual const ParamGeneratorInterface<ParamType>* BaseGenerator() const {
+      return base_;
+    }
+    // Advance should not be called on beyond-of-range iterators
+    // so no component iterators must be beyond end of range, either.
+    virtual void Advance() {
+      assert(!AtEnd());
+      ++current3_;
+      if (current3_ == end3_) {
+        current3_ = begin3_;
+        ++current2_;
+      }
+      if (current2_ == end2_) {
+        current2_ = begin2_;
+        ++current1_;
+      }
+      ComputeCurrentValue();
+    }
+    virtual ParamIteratorInterface<ParamType>* Clone() const {
+      return new Iterator(*this);
+    }
+    virtual const ParamType* Current() const { return &current_value_; }
+    virtual bool Equals(const ParamIteratorInterface<ParamType>& other) const {
+      // Having the same base generator guarantees that the other
+      // iterator is of the same type and we can downcast.
+      GTEST_CHECK_(BaseGenerator() == other.BaseGenerator())
+          << "The program attempted to compare iterators "
+          << "from different generators." << std::endl;
+      const Iterator* typed_other =
+          CheckedDowncastToActualType<const Iterator>(&other);
+      // We must report iterators equal if they both point beyond their
+      // respective ranges. That can happen in a variety of fashions,
+      // so we have to consult AtEnd().
+      return (AtEnd() && typed_other->AtEnd()) ||
+         (
+          current1_ == typed_other->current1_ &&
+          current2_ == typed_other->current2_ &&
+          current3_ == typed_other->current3_);
+    }
+
+   private:
+    Iterator(const Iterator& other)
+        : base_(other.base_),
+        begin1_(other.begin1_),
+        end1_(other.end1_),
+        current1_(other.current1_),
+        begin2_(other.begin2_),
+        end2_(other.end2_),
+        current2_(other.current2_),
+        begin3_(other.begin3_),
+        end3_(other.end3_),
+        current3_(other.current3_) {
+      ComputeCurrentValue();
+    }
+
+    void ComputeCurrentValue() {
+      if (!AtEnd())
+        current_value_ = ParamType(*current1_, *current2_, *current3_);
+    }
+    bool AtEnd() const {
+      // We must report iterator past the end of the range when either of the
+      // component iterators has reached the end of its range.
+      return
+          current1_ == end1_ ||
+          current2_ == end2_ ||
+          current3_ == end3_;
+    }
+
+    // No implementation - assignment is unsupported.
+    void operator=(const Iterator& other);
+
+    const ParamGeneratorInterface<ParamType>* const base_;
+    // begin[i]_ and end[i]_ define the i-th range that Iterator traverses.
+    // current[i]_ is the actual traversing iterator.
+    const typename ParamGenerator<T1>::iterator begin1_;
+    const typename ParamGenerator<T1>::iterator end1_;
+    typename ParamGenerator<T1>::iterator current1_;
+    const typename ParamGenerator<T2>::iterator begin2_;
+    const typename ParamGenerator<T2>::iterator end2_;
+    typename ParamGenerator<T2>::iterator current2_;
+    const typename ParamGenerator<T3>::iterator begin3_;
+    const typename ParamGenerator<T3>::iterator end3_;
+    typename ParamGenerator<T3>::iterator current3_;
+    ParamType current_value_;
+  };  // class CartesianProductGenerator3::Iterator
+
+  // No implementation - assignment is unsupported.
+  void operator=(const CartesianProductGenerator3& other);
+
+  const ParamGenerator<T1> g1_;
+  const ParamGenerator<T2> g2_;
+  const ParamGenerator<T3> g3_;
+};  // class CartesianProductGenerator3
+
+
+template <typename T1, typename T2, typename T3, typename T4>
+class CartesianProductGenerator4
+    : public ParamGeneratorInterface< ::std::tr1::tuple<T1, T2, T3, T4> > {
+ public:
+  typedef ::std::tr1::tuple<T1, T2, T3, T4> ParamType;
+
+  CartesianProductGenerator4(const ParamGenerator<T1>& g1,
+      const ParamGenerator<T2>& g2, const ParamGenerator<T3>& g3,
+      const ParamGenerator<T4>& g4)
+      : g1_(g1), g2_(g2), g3_(g3), g4_(g4) {}
+  virtual ~CartesianProductGenerator4() {}
+
+  virtual ParamIteratorInterface<ParamType>* Begin() const {
+    return new Iterator(this, g1_, g1_.begin(), g2_, g2_.begin(), g3_,
+        g3_.begin(), g4_, g4_.begin());
+  }
+  virtual ParamIteratorInterface<ParamType>* End() const {
+    return new Iterator(this, g1_, g1_.end(), g2_, g2_.end(), g3_, g3_.end(),
+        g4_, g4_.end());
+  }
+
+ private:
+  class Iterator : public ParamIteratorInterface<ParamType> {
+   public:
+    Iterator(const ParamGeneratorInterface<ParamType>* base,
+      const ParamGenerator<T1>& g1,
+      const typename ParamGenerator<T1>::iterator& current1,
+      const ParamGenerator<T2>& g2,
+      const typename ParamGenerator<T2>::iterator& current2,
+      const ParamGenerator<T3>& g3,
+      const typename ParamGenerator<T3>::iterator& current3,
+      const ParamGenerator<T4>& g4,
+      const typename ParamGenerator<T4>::iterator& current4)
+        : base_(base),
+          begin1_(g1.begin()), end1_(g1.end()), current1_(current1),
+          begin2_(g2.begin()), end2_(g2.end()), current2_(current2),
+          begin3_(g3.begin()), end3_(g3.end()), current3_(current3),
+          begin4_(g4.begin()), end4_(g4.end()), current4_(current4)    {
+      ComputeCurrentValue();
+    }
+    virtual ~Iterator() {}
+
+    virtual const ParamGeneratorInterface<ParamType>* BaseGenerator() const {
+      return base_;
+    }
+    // Advance should not be called on beyond-of-range iterators
+    // so no component iterators must be beyond end of range, either.
+    virtual void Advance() {
+      assert(!AtEnd());
+      ++current4_;
+      if (current4_ == end4_) {
+        current4_ = begin4_;
+        ++current3_;
+      }
+      if (current3_ == end3_) {
+        current3_ = begin3_;
+        ++current2_;
+      }
+      if (current2_ == end2_) {
+        current2_ = begin2_;
+        ++current1_;
+      }
+      ComputeCurrentValue();
+    }
+    virtual ParamIteratorInterface<ParamType>* Clone() const {
+      return new Iterator(*this);
+    }
+    virtual const ParamType* Current() const { return &current_value_; }
+    virtual bool Equals(const ParamIteratorInterface<ParamType>& other) const {
+      // Having the same base generator guarantees that the other
+      // iterator is of the same type and we can downcast.
+      GTEST_CHECK_(BaseGenerator() == other.BaseGenerator())
+          << "The program attempted to compare iterators "
+          << "from different generators." << std::endl;
+      const Iterator* typed_other =
+          CheckedDowncastToActualType<const Iterator>(&other);
+      // We must report iterators equal if they both point beyond their
+      // respective ranges. That can happen in a variety of fashions,
+      // so we have to consult AtEnd().
+      return (AtEnd() && typed_other->AtEnd()) ||
+         (
+          current1_ == typed_other->current1_ &&
+          current2_ == typed_other->current2_ &&
+          current3_ == typed_other->current3_ &&
+          current4_ == typed_other->current4_);
+    }
+
+   private:
+    Iterator(const Iterator& other)
+        : base_(other.base_),
+        begin1_(other.begin1_),
+        end1_(other.end1_),
+        current1_(other.current1_),
+        begin2_(other.begin2_),
+        end2_(other.end2_),
+        current2_(other.current2_),
+        begin3_(other.begin3_),
+        end3_(other.end3_),
+        current3_(other.current3_),
+        begin4_(other.begin4_),
+        end4_(other.end4_),
+        current4_(other.current4_) {
+      ComputeCurrentValue();
+    }
+
+    void ComputeCurrentValue() {
+      if (!AtEnd())
+        current_value_ = ParamType(*current1_, *current2_, *current3_,
+            *current4_);
+    }
+    bool AtEnd() const {
+      // We must report iterator past the end of the range when either of the
+      // component iterators has reached the end of its range.
+      return
+          current1_ == end1_ ||
+          current2_ == end2_ ||
+          current3_ == end3_ ||
+          current4_ == end4_;
+    }
+
+    // No implementation - assignment is unsupported.
+    void operator=(const Iterator& other);
+
+    const ParamGeneratorInterface<ParamType>* const base_;
+    // begin[i]_ and end[i]_ define the i-th range that Iterator traverses.
+    // current[i]_ is the actual traversing iterator.
+    const typename ParamGenerator<T1>::iterator begin1_;
+    const typename ParamGenerator<T1>::iterator end1_;
+    typename ParamGenerator<T1>::iterator current1_;
+    const typename ParamGenerator<T2>::iterator begin2_;
+    const typename ParamGenerator<T2>::iterator end2_;
+    typename ParamGenerator<T2>::iterator current2_;
+    const typename ParamGenerator<T3>::iterator begin3_;
+    const typename ParamGenerator<T3>::iterator end3_;
+    typename ParamGenerator<T3>::iterator current3_;
+    const typename ParamGenerator<T4>::iterator begin4_;
+    const typename ParamGenerator<T4>::iterator end4_;
+    typename ParamGenerator<T4>::iterator current4_;
+    ParamType current_value_;
+  };  // class CartesianProductGenerator4::Iterator
+
+  // No implementation - assignment is unsupported.
+  void operator=(const CartesianProductGenerator4& other);
+
+  const ParamGenerator<T1> g1_;
+  const ParamGenerator<T2> g2_;
+  const ParamGenerator<T3> g3_;
+  const ParamGenerator<T4> g4_;
+};  // class CartesianProductGenerator4
+
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5>
+class CartesianProductGenerator5
+    : public ParamGeneratorInterface< ::std::tr1::tuple<T1, T2, T3, T4, T5> > {
+ public:
+  typedef ::std::tr1::tuple<T1, T2, T3, T4, T5> ParamType;
+
+  CartesianProductGenerator5(const ParamGenerator<T1>& g1,
+      const ParamGenerator<T2>& g2, const ParamGenerator<T3>& g3,
+      const ParamGenerator<T4>& g4, const ParamGenerator<T5>& g5)
+      : g1_(g1), g2_(g2), g3_(g3), g4_(g4), g5_(g5) {}
+  virtual ~CartesianProductGenerator5() {}
+
+  virtual ParamIteratorInterface<ParamType>* Begin() const {
+    return new Iterator(this, g1_, g1_.begin(), g2_, g2_.begin(), g3_,
+        g3_.begin(), g4_, g4_.begin(), g5_, g5_.begin());
+  }
+  virtual ParamIteratorInterface<ParamType>* End() const {
+    return new Iterator(this, g1_, g1_.end(), g2_, g2_.end(), g3_, g3_.end(),
+        g4_, g4_.end(), g5_, g5_.end());
+  }
+
+ private:
+  class Iterator : public ParamIteratorInterface<ParamType> {
+   public:
+    Iterator(const ParamGeneratorInterface<ParamType>* base,
+      const ParamGenerator<T1>& g1,
+      const typename ParamGenerator<T1>::iterator& current1,
+      const ParamGenerator<T2>& g2,
+      const typename ParamGenerator<T2>::iterator& current2,
+      const ParamGenerator<T3>& g3,
+      const typename ParamGenerator<T3>::iterator& current3,
+      const ParamGenerator<T4>& g4,
+      const typename ParamGenerator<T4>::iterator& current4,
+      const ParamGenerator<T5>& g5,
+      const typename ParamGenerator<T5>::iterator& current5)
+        : base_(base),
+          begin1_(g1.begin()), end1_(g1.end()), current1_(current1),
+          begin2_(g2.begin()), end2_(g2.end()), current2_(current2),
+          begin3_(g3.begin()), end3_(g3.end()), current3_(current3),
+          begin4_(g4.begin()), end4_(g4.end()), current4_(current4),
+          begin5_(g5.begin()), end5_(g5.end()), current5_(current5)    {
+      ComputeCurrentValue();
+    }
+    virtual ~Iterator() {}
+
+    virtual const ParamGeneratorInterface<ParamType>* BaseGenerator() const {
+      return base_;
+    }
+    // Advance should not be called on beyond-of-range iterators
+    // so no component iterators must be beyond end of range, either.
+    virtual void Advance() {
+      assert(!AtEnd());
+      ++current5_;
+      if (current5_ == end5_) {
+        current5_ = begin5_;
+        ++current4_;
+      }
+      if (current4_ == end4_) {
+        current4_ = begin4_;
+        ++current3_;
+      }
+      if (current3_ == end3_) {
+        current3_ = begin3_;
+        ++current2_;
+      }
+      if (current2_ == end2_) {
+        current2_ = begin2_;
+        ++current1_;
+      }
+      ComputeCurrentValue();
+    }
+    virtual ParamIteratorInterface<ParamType>* Clone() const {
+      return new Iterator(*this);
+    }
+    virtual const ParamType* Current() const { return &current_value_; }
+    virtual bool Equals(const ParamIteratorInterface<ParamType>& other) const {
+      // Having the same base generator guarantees that the other
+      // iterator is of the same type and we can downcast.
+      GTEST_CHECK_(BaseGenerator() == other.BaseGenerator())
+          << "The program attempted to compare iterators "
+          << "from different generators." << std::endl;
+      const Iterator* typed_other =
+          CheckedDowncastToActualType<const Iterator>(&other);
+      // We must report iterators equal if they both point beyond their
+      // respective ranges. That can happen in a variety of fashions,
+      // so we have to consult AtEnd().
+      return (AtEnd() && typed_other->AtEnd()) ||
+         (
+          current1_ == typed_other->current1_ &&
+          current2_ == typed_other->current2_ &&
+          current3_ == typed_other->current3_ &&
+          current4_ == typed_other->current4_ &&
+          current5_ == typed_other->current5_);
+    }
+
+   private:
+    Iterator(const Iterator& other)
+        : base_(other.base_),
+        begin1_(other.begin1_),
+        end1_(other.end1_),
+        current1_(other.current1_),
+        begin2_(other.begin2_),
+        end2_(other.end2_),
+        current2_(other.current2_),
+        begin3_(other.begin3_),
+        end3_(other.end3_),
+        current3_(other.current3_),
+        begin4_(other.begin4_),
+        end4_(other.end4_),
+        current4_(other.current4_),
+        begin5_(other.begin5_),
+        end5_(other.end5_),
+        current5_(other.current5_) {
+      ComputeCurrentValue();
+    }
+
+    void ComputeCurrentValue() {
+      if (!AtEnd())
+        current_value_ = ParamType(*current1_, *current2_, *current3_,
+            *current4_, *current5_);
+    }
+    bool AtEnd() const {
+      // We must report iterator past the end of the range when either of the
+      // component iterators has reached the end of its range.
+      return
+          current1_ == end1_ ||
+          current2_ == end2_ ||
+          current3_ == end3_ ||
+          current4_ == end4_ ||
+          current5_ == end5_;
+    }
+
+    // No implementation - assignment is unsupported.
+    void operator=(const Iterator& other);
+
+    const ParamGeneratorInterface<ParamType>* const base_;
+    // begin[i]_ and end[i]_ define the i-th range that Iterator traverses.
+    // current[i]_ is the actual traversing iterator.
+    const typename ParamGenerator<T1>::iterator begin1_;
+    const typename ParamGenerator<T1>::iterator end1_;
+    typename ParamGenerator<T1>::iterator current1_;
+    const typename ParamGenerator<T2>::iterator begin2_;
+    const typename ParamGenerator<T2>::iterator end2_;
+    typename ParamGenerator<T2>::iterator current2_;
+    const typename ParamGenerator<T3>::iterator begin3_;
+    const typename ParamGenerator<T3>::iterator end3_;
+    typename ParamGenerator<T3>::iterator current3_;
+    const typename ParamGenerator<T4>::iterator begin4_;
+    const typename ParamGenerator<T4>::iterator end4_;
+    typename ParamGenerator<T4>::iterator current4_;
+    const typename ParamGenerator<T5>::iterator begin5_;
+    const typename ParamGenerator<T5>::iterator end5_;
+    typename ParamGenerator<T5>::iterator current5_;
+    ParamType current_value_;
+  };  // class CartesianProductGenerator5::Iterator
+
+  // No implementation - assignment is unsupported.
+  void operator=(const CartesianProductGenerator5& other);
+
+  const ParamGenerator<T1> g1_;
+  const ParamGenerator<T2> g2_;
+  const ParamGenerator<T3> g3_;
+  const ParamGenerator<T4> g4_;
+  const ParamGenerator<T5> g5_;
+};  // class CartesianProductGenerator5
+
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6>
+class CartesianProductGenerator6
+    : public ParamGeneratorInterface< ::std::tr1::tuple<T1, T2, T3, T4, T5,
+        T6> > {
+ public:
+  typedef ::std::tr1::tuple<T1, T2, T3, T4, T5, T6> ParamType;
+
+  CartesianProductGenerator6(const ParamGenerator<T1>& g1,
+      const ParamGenerator<T2>& g2, const ParamGenerator<T3>& g3,
+      const ParamGenerator<T4>& g4, const ParamGenerator<T5>& g5,
+      const ParamGenerator<T6>& g6)
+      : g1_(g1), g2_(g2), g3_(g3), g4_(g4), g5_(g5), g6_(g6) {}
+  virtual ~CartesianProductGenerator6() {}
+
+  virtual ParamIteratorInterface<ParamType>* Begin() const {
+    return new Iterator(this, g1_, g1_.begin(), g2_, g2_.begin(), g3_,
+        g3_.begin(), g4_, g4_.begin(), g5_, g5_.begin(), g6_, g6_.begin());
+  }
+  virtual ParamIteratorInterface<ParamType>* End() const {
+    return new Iterator(this, g1_, g1_.end(), g2_, g2_.end(), g3_, g3_.end(),
+        g4_, g4_.end(), g5_, g5_.end(), g6_, g6_.end());
+  }
+
+ private:
+  class Iterator : public ParamIteratorInterface<ParamType> {
+   public:
+    Iterator(const ParamGeneratorInterface<ParamType>* base,
+      const ParamGenerator<T1>& g1,
+      const typename ParamGenerator<T1>::iterator& current1,
+      const ParamGenerator<T2>& g2,
+      const typename ParamGenerator<T2>::iterator& current2,
+      const ParamGenerator<T3>& g3,
+      const typename ParamGenerator<T3>::iterator& current3,
+      const ParamGenerator<T4>& g4,
+      const typename ParamGenerator<T4>::iterator& current4,
+      const ParamGenerator<T5>& g5,
+      const typename ParamGenerator<T5>::iterator& current5,
+      const ParamGenerator<T6>& g6,
+      const typename ParamGenerator<T6>::iterator& current6)
+        : base_(base),
+          begin1_(g1.begin()), end1_(g1.end()), current1_(current1),
+          begin2_(g2.begin()), end2_(g2.end()), current2_(current2),
+          begin3_(g3.begin()), end3_(g3.end()), current3_(current3),
+          begin4_(g4.begin()), end4_(g4.end()), current4_(current4),
+          begin5_(g5.begin()), end5_(g5.end()), current5_(current5),
+          begin6_(g6.begin()), end6_(g6.end()), current6_(current6)    {
+      ComputeCurrentValue();
+    }
+    virtual ~Iterator() {}
+
+    virtual const ParamGeneratorInterface<ParamType>* BaseGenerator() const {
+      return base_;
+    }
+    // Advance should not be called on beyond-of-range iterators
+    // so no component iterators must be beyond end of range, either.
+    virtual void Advance() {
+      assert(!AtEnd());
+      ++current6_;
+      if (current6_ == end6_) {
+        current6_ = begin6_;
+        ++current5_;
+      }
+      if (current5_ == end5_) {
+        current5_ = begin5_;
+        ++current4_;
+      }
+      if (current4_ == end4_) {
+        current4_ = begin4_;
+        ++current3_;
+      }
+      if (current3_ == end3_) {
+        current3_ = begin3_;
+        ++current2_;
+      }
+      if (current2_ == end2_) {
+        current2_ = begin2_;
+        ++current1_;
+      }
+      ComputeCurrentValue();
+    }
+    virtual ParamIteratorInterface<ParamType>* Clone() const {
+      return new Iterator(*this);
+    }
+    virtual const ParamType* Current() const { return &current_value_; }
+    virtual bool Equals(const ParamIteratorInterface<ParamType>& other) const {
+      // Having the same base generator guarantees that the other
+      // iterator is of the same type and we can downcast.
+      GTEST_CHECK_(BaseGenerator() == other.BaseGenerator())
+          << "The program attempted to compare iterators "
+          << "from different generators." << std::endl;
+      const Iterator* typed_other =
+          CheckedDowncastToActualType<const Iterator>(&other);
+      // We must report iterators equal if they both point beyond their
+      // respective ranges. That can happen in a variety of fashions,
+      // so we have to consult AtEnd().
+      return (AtEnd() && typed_other->AtEnd()) ||
+         (
+          current1_ == typed_other->current1_ &&
+          current2_ == typed_other->current2_ &&
+          current3_ == typed_other->current3_ &&
+          current4_ == typed_other->current4_ &&
+          current5_ == typed_other->current5_ &&
+          current6_ == typed_other->current6_);
+    }
+
+   private:
+    Iterator(const Iterator& other)
+        : base_(other.base_),
+        begin1_(other.begin1_),
+        end1_(other.end1_),
+        current1_(other.current1_),
+        begin2_(other.begin2_),
+        end2_(other.end2_),
+        current2_(other.current2_),
+        begin3_(other.begin3_),
+        end3_(other.end3_),
+        current3_(other.current3_),
+        begin4_(other.begin4_),
+        end4_(other.end4_),
+        current4_(other.current4_),
+        begin5_(other.begin5_),
+        end5_(other.end5_),
+        current5_(other.current5_),
+        begin6_(other.begin6_),
+        end6_(other.end6_),
+        current6_(other.current6_) {
+      ComputeCurrentValue();
+    }
+
+    void ComputeCurrentValue() {
+      if (!AtEnd())
+        current_value_ = ParamType(*current1_, *current2_, *current3_,
+            *current4_, *current5_, *current6_);
+    }
+    bool AtEnd() const {
+      // We must report iterator past the end of the range when either of the
+      // component iterators has reached the end of its range.
+      return
+          current1_ == end1_ ||
+          current2_ == end2_ ||
+          current3_ == end3_ ||
+          current4_ == end4_ ||
+          current5_ == end5_ ||
+          current6_ == end6_;
+    }
+
+    // No implementation - assignment is unsupported.
+    void operator=(const Iterator& other);
+
+    const ParamGeneratorInterface<ParamType>* const base_;
+    // begin[i]_ and end[i]_ define the i-th range that Iterator traverses.
+    // current[i]_ is the actual traversing iterator.
+    const typename ParamGenerator<T1>::iterator begin1_;
+    const typename ParamGenerator<T1>::iterator end1_;
+    typename ParamGenerator<T1>::iterator current1_;
+    const typename ParamGenerator<T2>::iterator begin2_;
+    const typename ParamGenerator<T2>::iterator end2_;
+    typename ParamGenerator<T2>::iterator current2_;
+    const typename ParamGenerator<T3>::iterator begin3_;
+    const typename ParamGenerator<T3>::iterator end3_;
+    typename ParamGenerator<T3>::iterator current3_;
+    const typename ParamGenerator<T4>::iterator begin4_;
+    const typename ParamGenerator<T4>::iterator end4_;
+    typename ParamGenerator<T4>::iterator current4_;
+    const typename ParamGenerator<T5>::iterator begin5_;
+    const typename ParamGenerator<T5>::iterator end5_;
+    typename ParamGenerator<T5>::iterator current5_;
+    const typename ParamGenerator<T6>::iterator begin6_;
+    const typename ParamGenerator<T6>::iterator end6_;
+    typename ParamGenerator<T6>::iterator current6_;
+    ParamType current_value_;
+  };  // class CartesianProductGenerator6::Iterator
+
+  // No implementation - assignment is unsupported.
+  void operator=(const CartesianProductGenerator6& other);
+
+  const ParamGenerator<T1> g1_;
+  const ParamGenerator<T2> g2_;
+  const ParamGenerator<T3> g3_;
+  const ParamGenerator<T4> g4_;
+  const ParamGenerator<T5> g5_;
+  const ParamGenerator<T6> g6_;
+};  // class CartesianProductGenerator6
+
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7>
+class CartesianProductGenerator7
+    : public ParamGeneratorInterface< ::std::tr1::tuple<T1, T2, T3, T4, T5, T6,
+        T7> > {
+ public:
+  typedef ::std::tr1::tuple<T1, T2, T3, T4, T5, T6, T7> ParamType;
+
+  CartesianProductGenerator7(const ParamGenerator<T1>& g1,
+      const ParamGenerator<T2>& g2, const ParamGenerator<T3>& g3,
+      const ParamGenerator<T4>& g4, const ParamGenerator<T5>& g5,
+      const ParamGenerator<T6>& g6, const ParamGenerator<T7>& g7)
+      : g1_(g1), g2_(g2), g3_(g3), g4_(g4), g5_(g5), g6_(g6), g7_(g7) {}
+  virtual ~CartesianProductGenerator7() {}
+
+  virtual ParamIteratorInterface<ParamType>* Begin() const {
+    return new Iterator(this, g1_, g1_.begin(), g2_, g2_.begin(), g3_,
+        g3_.begin(), g4_, g4_.begin(), g5_, g5_.begin(), g6_, g6_.begin(), g7_,
+        g7_.begin());
+  }
+  virtual ParamIteratorInterface<ParamType>* End() const {
+    return new Iterator(this, g1_, g1_.end(), g2_, g2_.end(), g3_, g3_.end(),
+        g4_, g4_.end(), g5_, g5_.end(), g6_, g6_.end(), g7_, g7_.end());
+  }
+
+ private:
+  class Iterator : public ParamIteratorInterface<ParamType> {
+   public:
+    Iterator(const ParamGeneratorInterface<ParamType>* base,
+      const ParamGenerator<T1>& g1,
+      const typename ParamGenerator<T1>::iterator& current1,
+      const ParamGenerator<T2>& g2,
+      const typename ParamGenerator<T2>::iterator& current2,
+      const ParamGenerator<T3>& g3,
+      const typename ParamGenerator<T3>::iterator& current3,
+      const ParamGenerator<T4>& g4,
+      const typename ParamGenerator<T4>::iterator& current4,
+      const ParamGenerator<T5>& g5,
+      const typename ParamGenerator<T5>::iterator& current5,
+      const ParamGenerator<T6>& g6,
+      const typename ParamGenerator<T6>::iterator& current6,
+      const ParamGenerator<T7>& g7,
+      const typename ParamGenerator<T7>::iterator& current7)
+        : base_(base),
+          begin1_(g1.begin()), end1_(g1.end()), current1_(current1),
+          begin2_(g2.begin()), end2_(g2.end()), current2_(current2),
+          begin3_(g3.begin()), end3_(g3.end()), current3_(current3),
+          begin4_(g4.begin()), end4_(g4.end()), current4_(current4),
+          begin5_(g5.begin()), end5_(g5.end()), current5_(current5),
+          begin6_(g6.begin()), end6_(g6.end()), current6_(current6),
+          begin7_(g7.begin()), end7_(g7.end()), current7_(current7)    {
+      ComputeCurrentValue();
+    }
+    virtual ~Iterator() {}
+
+    virtual const ParamGeneratorInterface<ParamType>* BaseGenerator() const {
+      return base_;
+    }
+    // Advance should not be called on beyond-of-range iterators
+    // so no component iterators must be beyond end of range, either.
+    virtual void Advance() {
+      assert(!AtEnd());
+      ++current7_;
+      if (current7_ == end7_) {
+        current7_ = begin7_;
+        ++current6_;
+      }
+      if (current6_ == end6_) {
+        current6_ = begin6_;
+        ++current5_;
+      }
+      if (current5_ == end5_) {
+        current5_ = begin5_;
+        ++current4_;
+      }
+      if (current4_ == end4_) {
+        current4_ = begin4_;
+        ++current3_;
+      }
+      if (current3_ == end3_) {
+        current3_ = begin3_;
+        ++current2_;
+      }
+      if (current2_ == end2_) {
+        current2_ = begin2_;
+        ++current1_;
+      }
+      ComputeCurrentValue();
+    }
+    virtual ParamIteratorInterface<ParamType>* Clone() const {
+      return new Iterator(*this);
+    }
+    virtual const ParamType* Current() const { return &current_value_; }
+    virtual bool Equals(const ParamIteratorInterface<ParamType>& other) const {
+      // Having the same base generator guarantees that the other
+      // iterator is of the same type and we can downcast.
+      GTEST_CHECK_(BaseGenerator() == other.BaseGenerator())
+          << "The program attempted to compare iterators "
+          << "from different generators." << std::endl;
+      const Iterator* typed_other =
+          CheckedDowncastToActualType<const Iterator>(&other);
+      // We must report iterators equal if they both point beyond their
+      // respective ranges. That can happen in a variety of fashions,
+      // so we have to consult AtEnd().
+      return (AtEnd() && typed_other->AtEnd()) ||
+         (
+          current1_ == typed_other->current1_ &&
+          current2_ == typed_other->current2_ &&
+          current3_ == typed_other->current3_ &&
+          current4_ == typed_other->current4_ &&
+          current5_ == typed_other->current5_ &&
+          current6_ == typed_other->current6_ &&
+          current7_ == typed_other->current7_);
+    }
+
+   private:
+    Iterator(const Iterator& other)
+        : base_(other.base_),
+        begin1_(other.begin1_),
+        end1_(other.end1_),
+        current1_(other.current1_),
+        begin2_(other.begin2_),
+        end2_(other.end2_),
+        current2_(other.current2_),
+        begin3_(other.begin3_),
+        end3_(other.end3_),
+        current3_(other.current3_),
+        begin4_(other.begin4_),
+        end4_(other.end4_),
+        current4_(other.current4_),
+        begin5_(other.begin5_),
+        end5_(other.end5_),
+        current5_(other.current5_),
+        begin6_(other.begin6_),
+        end6_(other.end6_),
+        current6_(other.current6_),
+        begin7_(other.begin7_),
+        end7_(other.end7_),
+        current7_(other.current7_) {
+      ComputeCurrentValue();
+    }
+
+    void ComputeCurrentValue() {
+      if (!AtEnd())
+        current_value_ = ParamType(*current1_, *current2_, *current3_,
+            *current4_, *current5_, *current6_, *current7_);
+    }
+    bool AtEnd() const {
+      // We must report iterator past the end of the range when either of the
+      // component iterators has reached the end of its range.
+      return
+          current1_ == end1_ ||
+          current2_ == end2_ ||
+          current3_ == end3_ ||
+          current4_ == end4_ ||
+          current5_ == end5_ ||
+          current6_ == end6_ ||
+          current7_ == end7_;
+    }
+
+    // No implementation - assignment is unsupported.
+    void operator=(const Iterator& other);
+
+    const ParamGeneratorInterface<ParamType>* const base_;
+    // begin[i]_ and end[i]_ define the i-th range that Iterator traverses.
+    // current[i]_ is the actual traversing iterator.
+    const typename ParamGenerator<T1>::iterator begin1_;
+    const typename ParamGenerator<T1>::iterator end1_;
+    typename ParamGenerator<T1>::iterator current1_;
+    const typename ParamGenerator<T2>::iterator begin2_;
+    const typename ParamGenerator<T2>::iterator end2_;
+    typename ParamGenerator<T2>::iterator current2_;
+    const typename ParamGenerator<T3>::iterator begin3_;
+    const typename ParamGenerator<T3>::iterator end3_;
+    typename ParamGenerator<T3>::iterator current3_;
+    const typename ParamGenerator<T4>::iterator begin4_;
+    const typename ParamGenerator<T4>::iterator end4_;
+    typename ParamGenerator<T4>::iterator current4_;
+    const typename ParamGenerator<T5>::iterator begin5_;
+    const typename ParamGenerator<T5>::iterator end5_;
+    typename ParamGenerator<T5>::iterator current5_;
+    const typename ParamGenerator<T6>::iterator begin6_;
+    const typename ParamGenerator<T6>::iterator end6_;
+    typename ParamGenerator<T6>::iterator current6_;
+    const typename ParamGenerator<T7>::iterator begin7_;
+    const typename ParamGenerator<T7>::iterator end7_;
+    typename ParamGenerator<T7>::iterator current7_;
+    ParamType current_value_;
+  };  // class CartesianProductGenerator7::Iterator
+
+  // No implementation - assignment is unsupported.
+  void operator=(const CartesianProductGenerator7& other);
+
+  const ParamGenerator<T1> g1_;
+  const ParamGenerator<T2> g2_;
+  const ParamGenerator<T3> g3_;
+  const ParamGenerator<T4> g4_;
+  const ParamGenerator<T5> g5_;
+  const ParamGenerator<T6> g6_;
+  const ParamGenerator<T7> g7_;
+};  // class CartesianProductGenerator7
+
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8>
+class CartesianProductGenerator8
+    : public ParamGeneratorInterface< ::std::tr1::tuple<T1, T2, T3, T4, T5, T6,
+        T7, T8> > {
+ public:
+  typedef ::std::tr1::tuple<T1, T2, T3, T4, T5, T6, T7, T8> ParamType;
+
+  CartesianProductGenerator8(const ParamGenerator<T1>& g1,
+      const ParamGenerator<T2>& g2, const ParamGenerator<T3>& g3,
+      const ParamGenerator<T4>& g4, const ParamGenerator<T5>& g5,
+      const ParamGenerator<T6>& g6, const ParamGenerator<T7>& g7,
+      const ParamGenerator<T8>& g8)
+      : g1_(g1), g2_(g2), g3_(g3), g4_(g4), g5_(g5), g6_(g6), g7_(g7),
+          g8_(g8) {}
+  virtual ~CartesianProductGenerator8() {}
+
+  virtual ParamIteratorInterface<ParamType>* Begin() const {
+    return new Iterator(this, g1_, g1_.begin(), g2_, g2_.begin(), g3_,
+        g3_.begin(), g4_, g4_.begin(), g5_, g5_.begin(), g6_, g6_.begin(), g7_,
+        g7_.begin(), g8_, g8_.begin());
+  }
+  virtual ParamIteratorInterface<ParamType>* End() const {
+    return new Iterator(this, g1_, g1_.end(), g2_, g2_.end(), g3_, g3_.end(),
+        g4_, g4_.end(), g5_, g5_.end(), g6_, g6_.end(), g7_, g7_.end(), g8_,
+        g8_.end());
+  }
+
+ private:
+  class Iterator : public ParamIteratorInterface<ParamType> {
+   public:
+    Iterator(const ParamGeneratorInterface<ParamType>* base,
+      const ParamGenerator<T1>& g1,
+      const typename ParamGenerator<T1>::iterator& current1,
+      const ParamGenerator<T2>& g2,
+      const typename ParamGenerator<T2>::iterator& current2,
+      const ParamGenerator<T3>& g3,
+      const typename ParamGenerator<T3>::iterator& current3,
+      const ParamGenerator<T4>& g4,
+      const typename ParamGenerator<T4>::iterator& current4,
+      const ParamGenerator<T5>& g5,
+      const typename ParamGenerator<T5>::iterator& current5,
+      const ParamGenerator<T6>& g6,
+      const typename ParamGenerator<T6>::iterator& current6,
+      const ParamGenerator<T7>& g7,
+      const typename ParamGenerator<T7>::iterator& current7,
+      const ParamGenerator<T8>& g8,
+      const typename ParamGenerator<T8>::iterator& current8)
+        : base_(base),
+          begin1_(g1.begin()), end1_(g1.end()), current1_(current1),
+          begin2_(g2.begin()), end2_(g2.end()), current2_(current2),
+          begin3_(g3.begin()), end3_(g3.end()), current3_(current3),
+          begin4_(g4.begin()), end4_(g4.end()), current4_(current4),
+          begin5_(g5.begin()), end5_(g5.end()), current5_(current5),
+          begin6_(g6.begin()), end6_(g6.end()), current6_(current6),
+          begin7_(g7.begin()), end7_(g7.end()), current7_(current7),
+          begin8_(g8.begin()), end8_(g8.end()), current8_(current8)    {
+      ComputeCurrentValue();
+    }
+    virtual ~Iterator() {}
+
+    virtual const ParamGeneratorInterface<ParamType>* BaseGenerator() const {
+      return base_;
+    }
+    // Advance should not be called on beyond-of-range iterators
+    // so no component iterators must be beyond end of range, either.
+    virtual void Advance() {
+      assert(!AtEnd());
+      ++current8_;
+      if (current8_ == end8_) {
+        current8_ = begin8_;
+        ++current7_;
+      }
+      if (current7_ == end7_) {
+        current7_ = begin7_;
+        ++current6_;
+      }
+      if (current6_ == end6_) {
+        current6_ = begin6_;
+        ++current5_;
+      }
+      if (current5_ == end5_) {
+        current5_ = begin5_;
+        ++current4_;
+      }
+      if (current4_ == end4_) {
+        current4_ = begin4_;
+        ++current3_;
+      }
+      if (current3_ == end3_) {
+        current3_ = begin3_;
+        ++current2_;
+      }
+      if (current2_ == end2_) {
+        current2_ = begin2_;
+        ++current1_;
+      }
+      ComputeCurrentValue();
+    }
+    virtual ParamIteratorInterface<ParamType>* Clone() const {
+      return new Iterator(*this);
+    }
+    virtual const ParamType* Current() const { return &current_value_; }
+    virtual bool Equals(const ParamIteratorInterface<ParamType>& other) const {
+      // Having the same base generator guarantees that the other
+      // iterator is of the same type and we can downcast.
+      GTEST_CHECK_(BaseGenerator() == other.BaseGenerator())
+          << "The program attempted to compare iterators "
+          << "from different generators." << std::endl;
+      const Iterator* typed_other =
+          CheckedDowncastToActualType<const Iterator>(&other);
+      // We must report iterators equal if they both point beyond their
+      // respective ranges. That can happen in a variety of fashions,
+      // so we have to consult AtEnd().
+      return (AtEnd() && typed_other->AtEnd()) ||
+         (
+          current1_ == typed_other->current1_ &&
+          current2_ == typed_other->current2_ &&
+          current3_ == typed_other->current3_ &&
+          current4_ == typed_other->current4_ &&
+          current5_ == typed_other->current5_ &&
+          current6_ == typed_other->current6_ &&
+          current7_ == typed_other->current7_ &&
+          current8_ == typed_other->current8_);
+    }
+
+   private:
+    Iterator(const Iterator& other)
+        : base_(other.base_),
+        begin1_(other.begin1_),
+        end1_(other.end1_),
+        current1_(other.current1_),
+        begin2_(other.begin2_),
+        end2_(other.end2_),
+        current2_(other.current2_),
+        begin3_(other.begin3_),
+        end3_(other.end3_),
+        current3_(other.current3_),
+        begin4_(other.begin4_),
+        end4_(other.end4_),
+        current4_(other.current4_),
+        begin5_(other.begin5_),
+        end5_(other.end5_),
+        current5_(other.current5_),
+        begin6_(other.begin6_),
+        end6_(other.end6_),
+        current6_(other.current6_),
+        begin7_(other.begin7_),
+        end7_(other.end7_),
+        current7_(other.current7_),
+        begin8_(other.begin8_),
+        end8_(other.end8_),
+        current8_(other.current8_) {
+      ComputeCurrentValue();
+    }
+
+    void ComputeCurrentValue() {
+      if (!AtEnd())
+        current_value_ = ParamType(*current1_, *current2_, *current3_,
+            *current4_, *current5_, *current6_, *current7_, *current8_);
+    }
+    bool AtEnd() const {
+      // We must report iterator past the end of the range when either of the
+      // component iterators has reached the end of its range.
+      return
+          current1_ == end1_ ||
+          current2_ == end2_ ||
+          current3_ == end3_ ||
+          current4_ == end4_ ||
+          current5_ == end5_ ||
+          current6_ == end6_ ||
+          current7_ == end7_ ||
+          current8_ == end8_;
+    }
+
+    // No implementation - assignment is unsupported.
+    void operator=(const Iterator& other);
+
+    const ParamGeneratorInterface<ParamType>* const base_;
+    // begin[i]_ and end[i]_ define the i-th range that Iterator traverses.
+    // current[i]_ is the actual traversing iterator.
+    const typename ParamGenerator<T1>::iterator begin1_;
+    const typename ParamGenerator<T1>::iterator end1_;
+    typename ParamGenerator<T1>::iterator current1_;
+    const typename ParamGenerator<T2>::iterator begin2_;
+    const typename ParamGenerator<T2>::iterator end2_;
+    typename ParamGenerator<T2>::iterator current2_;
+    const typename ParamGenerator<T3>::iterator begin3_;
+    const typename ParamGenerator<T3>::iterator end3_;
+    typename ParamGenerator<T3>::iterator current3_;
+    const typename ParamGenerator<T4>::iterator begin4_;
+    const typename ParamGenerator<T4>::iterator end4_;
+    typename ParamGenerator<T4>::iterator current4_;
+    const typename ParamGenerator<T5>::iterator begin5_;
+    const typename ParamGenerator<T5>::iterator end5_;
+    typename ParamGenerator<T5>::iterator current5_;
+    const typename ParamGenerator<T6>::iterator begin6_;
+    const typename ParamGenerator<T6>::iterator end6_;
+    typename ParamGenerator<T6>::iterator current6_;
+    const typename ParamGenerator<T7>::iterator begin7_;
+    const typename ParamGenerator<T7>::iterator end7_;
+    typename ParamGenerator<T7>::iterator current7_;
+    const typename ParamGenerator<T8>::iterator begin8_;
+    const typename ParamGenerator<T8>::iterator end8_;
+    typename ParamGenerator<T8>::iterator current8_;
+    ParamType current_value_;
+  };  // class CartesianProductGenerator8::Iterator
+
+  // No implementation - assignment is unsupported.
+  void operator=(const CartesianProductGenerator8& other);
+
+  const ParamGenerator<T1> g1_;
+  const ParamGenerator<T2> g2_;
+  const ParamGenerator<T3> g3_;
+  const ParamGenerator<T4> g4_;
+  const ParamGenerator<T5> g5_;
+  const ParamGenerator<T6> g6_;
+  const ParamGenerator<T7> g7_;
+  const ParamGenerator<T8> g8_;
+};  // class CartesianProductGenerator8
+
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9>
+class CartesianProductGenerator9
+    : public ParamGeneratorInterface< ::std::tr1::tuple<T1, T2, T3, T4, T5, T6,
+        T7, T8, T9> > {
+ public:
+  typedef ::std::tr1::tuple<T1, T2, T3, T4, T5, T6, T7, T8, T9> ParamType;
+
+  CartesianProductGenerator9(const ParamGenerator<T1>& g1,
+      const ParamGenerator<T2>& g2, const ParamGenerator<T3>& g3,
+      const ParamGenerator<T4>& g4, const ParamGenerator<T5>& g5,
+      const ParamGenerator<T6>& g6, const ParamGenerator<T7>& g7,
+      const ParamGenerator<T8>& g8, const ParamGenerator<T9>& g9)
+      : g1_(g1), g2_(g2), g3_(g3), g4_(g4), g5_(g5), g6_(g6), g7_(g7), g8_(g8),
+          g9_(g9) {}
+  virtual ~CartesianProductGenerator9() {}
+
+  virtual ParamIteratorInterface<ParamType>* Begin() const {
+    return new Iterator(this, g1_, g1_.begin(), g2_, g2_.begin(), g3_,
+        g3_.begin(), g4_, g4_.begin(), g5_, g5_.begin(), g6_, g6_.begin(), g7_,
+        g7_.begin(), g8_, g8_.begin(), g9_, g9_.begin());
+  }
+  virtual ParamIteratorInterface<ParamType>* End() const {
+    return new Iterator(this, g1_, g1_.end(), g2_, g2_.end(), g3_, g3_.end(),
+        g4_, g4_.end(), g5_, g5_.end(), g6_, g6_.end(), g7_, g7_.end(), g8_,
+        g8_.end(), g9_, g9_.end());
+  }
+
+ private:
+  class Iterator : public ParamIteratorInterface<ParamType> {
+   public:
+    Iterator(const ParamGeneratorInterface<ParamType>* base,
+      const ParamGenerator<T1>& g1,
+      const typename ParamGenerator<T1>::iterator& current1,
+      const ParamGenerator<T2>& g2,
+      const typename ParamGenerator<T2>::iterator& current2,
+      const ParamGenerator<T3>& g3,
+      const typename ParamGenerator<T3>::iterator& current3,
+      const ParamGenerator<T4>& g4,
+      const typename ParamGenerator<T4>::iterator& current4,
+      const ParamGenerator<T5>& g5,
+      const typename ParamGenerator<T5>::iterator& current5,
+      const ParamGenerator<T6>& g6,
+      const typename ParamGenerator<T6>::iterator& current6,
+      const ParamGenerator<T7>& g7,
+      const typename ParamGenerator<T7>::iterator& current7,
+      const ParamGenerator<T8>& g8,
+      const typename ParamGenerator<T8>::iterator& current8,
+      const ParamGenerator<T9>& g9,
+      const typename ParamGenerator<T9>::iterator& current9)
+        : base_(base),
+          begin1_(g1.begin()), end1_(g1.end()), current1_(current1),
+          begin2_(g2.begin()), end2_(g2.end()), current2_(current2),
+          begin3_(g3.begin()), end3_(g3.end()), current3_(current3),
+          begin4_(g4.begin()), end4_(g4.end()), current4_(current4),
+          begin5_(g5.begin()), end5_(g5.end()), current5_(current5),
+          begin6_(g6.begin()), end6_(g6.end()), current6_(current6),
+          begin7_(g7.begin()), end7_(g7.end()), current7_(current7),
+          begin8_(g8.begin()), end8_(g8.end()), current8_(current8),
+          begin9_(g9.begin()), end9_(g9.end()), current9_(current9)    {
+      ComputeCurrentValue();
+    }
+    virtual ~Iterator() {}
+
+    virtual const ParamGeneratorInterface<ParamType>* BaseGenerator() const {
+      return base_;
+    }
+    // Advance should not be called on beyond-of-range iterators
+    // so no component iterators must be beyond end of range, either.
+    virtual void Advance() {
+      assert(!AtEnd());
+      ++current9_;
+      if (current9_ == end9_) {
+        current9_ = begin9_;
+        ++current8_;
+      }
+      if (current8_ == end8_) {
+        current8_ = begin8_;
+        ++current7_;
+      }
+      if (current7_ == end7_) {
+        current7_ = begin7_;
+        ++current6_;
+      }
+      if (current6_ == end6_) {
+        current6_ = begin6_;
+        ++current5_;
+      }
+      if (current5_ == end5_) {
+        current5_ = begin5_;
+        ++current4_;
+      }
+      if (current4_ == end4_) {
+        current4_ = begin4_;
+        ++current3_;
+      }
+      if (current3_ == end3_) {
+        current3_ = begin3_;
+        ++current2_;
+      }
+      if (current2_ == end2_) {
+        current2_ = begin2_;
+        ++current1_;
+      }
+      ComputeCurrentValue();
+    }
+    virtual ParamIteratorInterface<ParamType>* Clone() const {
+      return new Iterator(*this);
+    }
+    virtual const ParamType* Current() const { return &current_value_; }
+    virtual bool Equals(const ParamIteratorInterface<ParamType>& other) const {
+      // Having the same base generator guarantees that the other
+      // iterator is of the same type and we can downcast.
+      GTEST_CHECK_(BaseGenerator() == other.BaseGenerator())
+          << "The program attempted to compare iterators "
+          << "from different generators." << std::endl;
+      const Iterator* typed_other =
+          CheckedDowncastToActualType<const Iterator>(&other);
+      // We must report iterators equal if they both point beyond their
+      // respective ranges. That can happen in a variety of fashions,
+      // so we have to consult AtEnd().
+      return (AtEnd() && typed_other->AtEnd()) ||
+         (
+          current1_ == typed_other->current1_ &&
+          current2_ == typed_other->current2_ &&
+          current3_ == typed_other->current3_ &&
+          current4_ == typed_other->current4_ &&
+          current5_ == typed_other->current5_ &&
+          current6_ == typed_other->current6_ &&
+          current7_ == typed_other->current7_ &&
+          current8_ == typed_other->current8_ &&
+          current9_ == typed_other->current9_);
+    }
+
+   private:
+    Iterator(const Iterator& other)
+        : base_(other.base_),
+        begin1_(other.begin1_),
+        end1_(other.end1_),
+        current1_(other.current1_),
+        begin2_(other.begin2_),
+        end2_(other.end2_),
+        current2_(other.current2_),
+        begin3_(other.begin3_),
+        end3_(other.end3_),
+        current3_(other.current3_),
+        begin4_(other.begin4_),
+        end4_(other.end4_),
+        current4_(other.current4_),
+        begin5_(other.begin5_),
+        end5_(other.end5_),
+        current5_(other.current5_),
+        begin6_(other.begin6_),
+        end6_(other.end6_),
+        current6_(other.current6_),
+        begin7_(other.begin7_),
+        end7_(other.end7_),
+        current7_(other.current7_),
+        begin8_(other.begin8_),
+        end8_(other.end8_),
+        current8_(other.current8_),
+        begin9_(other.begin9_),
+        end9_(other.end9_),
+        current9_(other.current9_) {
+      ComputeCurrentValue();
+    }
+
+    void ComputeCurrentValue() {
+      if (!AtEnd())
+        current_value_ = ParamType(*current1_, *current2_, *current3_,
+            *current4_, *current5_, *current6_, *current7_, *current8_,
+            *current9_);
+    }
+    bool AtEnd() const {
+      // We must report iterator past the end of the range when either of the
+      // component iterators has reached the end of its range.
+      return
+          current1_ == end1_ ||
+          current2_ == end2_ ||
+          current3_ == end3_ ||
+          current4_ == end4_ ||
+          current5_ == end5_ ||
+          current6_ == end6_ ||
+          current7_ == end7_ ||
+          current8_ == end8_ ||
+          current9_ == end9_;
+    }
+
+    // No implementation - assignment is unsupported.
+    void operator=(const Iterator& other);
+
+    const ParamGeneratorInterface<ParamType>* const base_;
+    // begin[i]_ and end[i]_ define the i-th range that Iterator traverses.
+    // current[i]_ is the actual traversing iterator.
+    const typename ParamGenerator<T1>::iterator begin1_;
+    const typename ParamGenerator<T1>::iterator end1_;
+    typename ParamGenerator<T1>::iterator current1_;
+    const typename ParamGenerator<T2>::iterator begin2_;
+    const typename ParamGenerator<T2>::iterator end2_;
+    typename ParamGenerator<T2>::iterator current2_;
+    const typename ParamGenerator<T3>::iterator begin3_;
+    const typename ParamGenerator<T3>::iterator end3_;
+    typename ParamGenerator<T3>::iterator current3_;
+    const typename ParamGenerator<T4>::iterator begin4_;
+    const typename ParamGenerator<T4>::iterator end4_;
+    typename ParamGenerator<T4>::iterator current4_;
+    const typename ParamGenerator<T5>::iterator begin5_;
+    const typename ParamGenerator<T5>::iterator end5_;
+    typename ParamGenerator<T5>::iterator current5_;
+    const typename ParamGenerator<T6>::iterator begin6_;
+    const typename ParamGenerator<T6>::iterator end6_;
+    typename ParamGenerator<T6>::iterator current6_;
+    const typename ParamGenerator<T7>::iterator begin7_;
+    const typename ParamGenerator<T7>::iterator end7_;
+    typename ParamGenerator<T7>::iterator current7_;
+    const typename ParamGenerator<T8>::iterator begin8_;
+    const typename ParamGenerator<T8>::iterator end8_;
+    typename ParamGenerator<T8>::iterator current8_;
+    const typename ParamGenerator<T9>::iterator begin9_;
+    const typename ParamGenerator<T9>::iterator end9_;
+    typename ParamGenerator<T9>::iterator current9_;
+    ParamType current_value_;
+  };  // class CartesianProductGenerator9::Iterator
+
+  // No implementation - assignment is unsupported.
+  void operator=(const CartesianProductGenerator9& other);
+
+  const ParamGenerator<T1> g1_;
+  const ParamGenerator<T2> g2_;
+  const ParamGenerator<T3> g3_;
+  const ParamGenerator<T4> g4_;
+  const ParamGenerator<T5> g5_;
+  const ParamGenerator<T6> g6_;
+  const ParamGenerator<T7> g7_;
+  const ParamGenerator<T8> g8_;
+  const ParamGenerator<T9> g9_;
+};  // class CartesianProductGenerator9
+
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10>
+class CartesianProductGenerator10
+    : public ParamGeneratorInterface< ::std::tr1::tuple<T1, T2, T3, T4, T5, T6,
+        T7, T8, T9, T10> > {
+ public:
+  typedef ::std::tr1::tuple<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10> ParamType;
+
+  CartesianProductGenerator10(const ParamGenerator<T1>& g1,
+      const ParamGenerator<T2>& g2, const ParamGenerator<T3>& g3,
+      const ParamGenerator<T4>& g4, const ParamGenerator<T5>& g5,
+      const ParamGenerator<T6>& g6, const ParamGenerator<T7>& g7,
+      const ParamGenerator<T8>& g8, const ParamGenerator<T9>& g9,
+      const ParamGenerator<T10>& g10)
+      : g1_(g1), g2_(g2), g3_(g3), g4_(g4), g5_(g5), g6_(g6), g7_(g7), g8_(g8),
+          g9_(g9), g10_(g10) {}
+  virtual ~CartesianProductGenerator10() {}
+
+  virtual ParamIteratorInterface<ParamType>* Begin() const {
+    return new Iterator(this, g1_, g1_.begin(), g2_, g2_.begin(), g3_,
+        g3_.begin(), g4_, g4_.begin(), g5_, g5_.begin(), g6_, g6_.begin(), g7_,
+        g7_.begin(), g8_, g8_.begin(), g9_, g9_.begin(), g10_, g10_.begin());
+  }
+  virtual ParamIteratorInterface<ParamType>* End() const {
+    return new Iterator(this, g1_, g1_.end(), g2_, g2_.end(), g3_, g3_.end(),
+        g4_, g4_.end(), g5_, g5_.end(), g6_, g6_.end(), g7_, g7_.end(), g8_,
+        g8_.end(), g9_, g9_.end(), g10_, g10_.end());
+  }
+
+ private:
+  class Iterator : public ParamIteratorInterface<ParamType> {
+   public:
+    Iterator(const ParamGeneratorInterface<ParamType>* base,
+      const ParamGenerator<T1>& g1,
+      const typename ParamGenerator<T1>::iterator& current1,
+      const ParamGenerator<T2>& g2,
+      const typename ParamGenerator<T2>::iterator& current2,
+      const ParamGenerator<T3>& g3,
+      const typename ParamGenerator<T3>::iterator& current3,
+      const ParamGenerator<T4>& g4,
+      const typename ParamGenerator<T4>::iterator& current4,
+      const ParamGenerator<T5>& g5,
+      const typename ParamGenerator<T5>::iterator& current5,
+      const ParamGenerator<T6>& g6,
+      const typename ParamGenerator<T6>::iterator& current6,
+      const ParamGenerator<T7>& g7,
+      const typename ParamGenerator<T7>::iterator& current7,
+      const ParamGenerator<T8>& g8,
+      const typename ParamGenerator<T8>::iterator& current8,
+      const ParamGenerator<T9>& g9,
+      const typename ParamGenerator<T9>::iterator& current9,
+      const ParamGenerator<T10>& g10,
+      const typename ParamGenerator<T10>::iterator& current10)
+        : base_(base),
+          begin1_(g1.begin()), end1_(g1.end()), current1_(current1),
+          begin2_(g2.begin()), end2_(g2.end()), current2_(current2),
+          begin3_(g3.begin()), end3_(g3.end()), current3_(current3),
+          begin4_(g4.begin()), end4_(g4.end()), current4_(current4),
+          begin5_(g5.begin()), end5_(g5.end()), current5_(current5),
+          begin6_(g6.begin()), end6_(g6.end()), current6_(current6),
+          begin7_(g7.begin()), end7_(g7.end()), current7_(current7),
+          begin8_(g8.begin()), end8_(g8.end()), current8_(current8),
+          begin9_(g9.begin()), end9_(g9.end()), current9_(current9),
+          begin10_(g10.begin()), end10_(g10.end()), current10_(current10)    {
+      ComputeCurrentValue();
+    }
+    virtual ~Iterator() {}
+
+    virtual const ParamGeneratorInterface<ParamType>* BaseGenerator() const {
+      return base_;
+    }
+    // Advance should not be called on beyond-of-range iterators
+    // so no component iterators must be beyond end of range, either.
+    virtual void Advance() {
+      assert(!AtEnd());
+      ++current10_;
+      if (current10_ == end10_) {
+        current10_ = begin10_;
+        ++current9_;
+      }
+      if (current9_ == end9_) {
+        current9_ = begin9_;
+        ++current8_;
+      }
+      if (current8_ == end8_) {
+        current8_ = begin8_;
+        ++current7_;
+      }
+      if (current7_ == end7_) {
+        current7_ = begin7_;
+        ++current6_;
+      }
+      if (current6_ == end6_) {
+        current6_ = begin6_;
+        ++current5_;
+      }
+      if (current5_ == end5_) {
+        current5_ = begin5_;
+        ++current4_;
+      }
+      if (current4_ == end4_) {
+        current4_ = begin4_;
+        ++current3_;
+      }
+      if (current3_ == end3_) {
+        current3_ = begin3_;
+        ++current2_;
+      }
+      if (current2_ == end2_) {
+        current2_ = begin2_;
+        ++current1_;
+      }
+      ComputeCurrentValue();
+    }
+    virtual ParamIteratorInterface<ParamType>* Clone() const {
+      return new Iterator(*this);
+    }
+    virtual const ParamType* Current() const { return &current_value_; }
+    virtual bool Equals(const ParamIteratorInterface<ParamType>& other) const {
+      // Having the same base generator guarantees that the other
+      // iterator is of the same type and we can downcast.
+      GTEST_CHECK_(BaseGenerator() == other.BaseGenerator())
+          << "The program attempted to compare iterators "
+          << "from different generators." << std::endl;
+      const Iterator* typed_other =
+          CheckedDowncastToActualType<const Iterator>(&other);
+      // We must report iterators equal if they both point beyond their
+      // respective ranges. That can happen in a variety of fashions,
+      // so we have to consult AtEnd().
+      return (AtEnd() && typed_other->AtEnd()) ||
+         (
+          current1_ == typed_other->current1_ &&
+          current2_ == typed_other->current2_ &&
+          current3_ == typed_other->current3_ &&
+          current4_ == typed_other->current4_ &&
+          current5_ == typed_other->current5_ &&
+          current6_ == typed_other->current6_ &&
+          current7_ == typed_other->current7_ &&
+          current8_ == typed_other->current8_ &&
+          current9_ == typed_other->current9_ &&
+          current10_ == typed_other->current10_);
+    }
+
+   private:
+    Iterator(const Iterator& other)
+        : base_(other.base_),
+        begin1_(other.begin1_),
+        end1_(other.end1_),
+        current1_(other.current1_),
+        begin2_(other.begin2_),
+        end2_(other.end2_),
+        current2_(other.current2_),
+        begin3_(other.begin3_),
+        end3_(other.end3_),
+        current3_(other.current3_),
+        begin4_(other.begin4_),
+        end4_(other.end4_),
+        current4_(other.current4_),
+        begin5_(other.begin5_),
+        end5_(other.end5_),
+        current5_(other.current5_),
+        begin6_(other.begin6_),
+        end6_(other.end6_),
+        current6_(other.current6_),
+        begin7_(other.begin7_),
+        end7_(other.end7_),
+        current7_(other.current7_),
+        begin8_(other.begin8_),
+        end8_(other.end8_),
+        current8_(other.current8_),
+        begin9_(other.begin9_),
+        end9_(other.end9_),
+        current9_(other.current9_),
+        begin10_(other.begin10_),
+        end10_(other.end10_),
+        current10_(other.current10_) {
+      ComputeCurrentValue();
+    }
+
+    void ComputeCurrentValue() {
+      if (!AtEnd())
+        current_value_ = ParamType(*current1_, *current2_, *current3_,
+            *current4_, *current5_, *current6_, *current7_, *current8_,
+            *current9_, *current10_);
+    }
+    bool AtEnd() const {
+      // We must report iterator past the end of the range when either of the
+      // component iterators has reached the end of its range.
+      return
+          current1_ == end1_ ||
+          current2_ == end2_ ||
+          current3_ == end3_ ||
+          current4_ == end4_ ||
+          current5_ == end5_ ||
+          current6_ == end6_ ||
+          current7_ == end7_ ||
+          current8_ == end8_ ||
+          current9_ == end9_ ||
+          current10_ == end10_;
+    }
+
+    // No implementation - assignment is unsupported.
+    void operator=(const Iterator& other);
+
+    const ParamGeneratorInterface<ParamType>* const base_;
+    // begin[i]_ and end[i]_ define the i-th range that Iterator traverses.
+    // current[i]_ is the actual traversing iterator.
+    const typename ParamGenerator<T1>::iterator begin1_;
+    const typename ParamGenerator<T1>::iterator end1_;
+    typename ParamGenerator<T1>::iterator current1_;
+    const typename ParamGenerator<T2>::iterator begin2_;
+    const typename ParamGenerator<T2>::iterator end2_;
+    typename ParamGenerator<T2>::iterator current2_;
+    const typename ParamGenerator<T3>::iterator begin3_;
+    const typename ParamGenerator<T3>::iterator end3_;
+    typename ParamGenerator<T3>::iterator current3_;
+    const typename ParamGenerator<T4>::iterator begin4_;
+    const typename ParamGenerator<T4>::iterator end4_;
+    typename ParamGenerator<T4>::iterator current4_;
+    const typename ParamGenerator<T5>::iterator begin5_;
+    const typename ParamGenerator<T5>::iterator end5_;
+    typename ParamGenerator<T5>::iterator current5_;
+    const typename ParamGenerator<T6>::iterator begin6_;
+    const typename ParamGenerator<T6>::iterator end6_;
+    typename ParamGenerator<T6>::iterator current6_;
+    const typename ParamGenerator<T7>::iterator begin7_;
+    const typename ParamGenerator<T7>::iterator end7_;
+    typename ParamGenerator<T7>::iterator current7_;
+    const typename ParamGenerator<T8>::iterator begin8_;
+    const typename ParamGenerator<T8>::iterator end8_;
+    typename ParamGenerator<T8>::iterator current8_;
+    const typename ParamGenerator<T9>::iterator begin9_;
+    const typename ParamGenerator<T9>::iterator end9_;
+    typename ParamGenerator<T9>::iterator current9_;
+    const typename ParamGenerator<T10>::iterator begin10_;
+    const typename ParamGenerator<T10>::iterator end10_;
+    typename ParamGenerator<T10>::iterator current10_;
+    ParamType current_value_;
+  };  // class CartesianProductGenerator10::Iterator
+
+  // No implementation - assignment is unsupported.
+  void operator=(const CartesianProductGenerator10& other);
+
+  const ParamGenerator<T1> g1_;
+  const ParamGenerator<T2> g2_;
+  const ParamGenerator<T3> g3_;
+  const ParamGenerator<T4> g4_;
+  const ParamGenerator<T5> g5_;
+  const ParamGenerator<T6> g6_;
+  const ParamGenerator<T7> g7_;
+  const ParamGenerator<T8> g8_;
+  const ParamGenerator<T9> g9_;
+  const ParamGenerator<T10> g10_;
+};  // class CartesianProductGenerator10
+
+
+// INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE.
+//
+// Helper classes providing Combine() with polymorphic features. They allow
+// casting CartesianProductGeneratorN<T> to ParamGenerator<U> if T is
+// convertible to U.
+//
+template <class Generator1, class Generator2>
+class CartesianProductHolder2 {
+ public:
+CartesianProductHolder2(const Generator1& g1, const Generator2& g2)
+      : g1_(g1), g2_(g2) {}
+  template <typename T1, typename T2>
+  operator ParamGenerator< ::std::tr1::tuple<T1, T2> >() const {
+    return ParamGenerator< ::std::tr1::tuple<T1, T2> >(
+        new CartesianProductGenerator2<T1, T2>(
+        static_cast<ParamGenerator<T1> >(g1_),
+        static_cast<ParamGenerator<T2> >(g2_)));
+  }
+
+ private:
+  // No implementation - assignment is unsupported.
+  void operator=(const CartesianProductHolder2& other);
+
+  const Generator1 g1_;
+  const Generator2 g2_;
+};  // class CartesianProductHolder2
+
+template <class Generator1, class Generator2, class Generator3>
+class CartesianProductHolder3 {
+ public:
+CartesianProductHolder3(const Generator1& g1, const Generator2& g2,
+    const Generator3& g3)
+      : g1_(g1), g2_(g2), g3_(g3) {}
+  template <typename T1, typename T2, typename T3>
+  operator ParamGenerator< ::std::tr1::tuple<T1, T2, T3> >() const {
+    return ParamGenerator< ::std::tr1::tuple<T1, T2, T3> >(
+        new CartesianProductGenerator3<T1, T2, T3>(
+        static_cast<ParamGenerator<T1> >(g1_),
+        static_cast<ParamGenerator<T2> >(g2_),
+        static_cast<ParamGenerator<T3> >(g3_)));
+  }
+
+ private:
+  // No implementation - assignment is unsupported.
+  void operator=(const CartesianProductHolder3& other);
+
+  const Generator1 g1_;
+  const Generator2 g2_;
+  const Generator3 g3_;
+};  // class CartesianProductHolder3
+
+template <class Generator1, class Generator2, class Generator3,
+    class Generator4>
+class CartesianProductHolder4 {
+ public:
+CartesianProductHolder4(const Generator1& g1, const Generator2& g2,
+    const Generator3& g3, const Generator4& g4)
+      : g1_(g1), g2_(g2), g3_(g3), g4_(g4) {}
+  template <typename T1, typename T2, typename T3, typename T4>
+  operator ParamGenerator< ::std::tr1::tuple<T1, T2, T3, T4> >() const {
+    return ParamGenerator< ::std::tr1::tuple<T1, T2, T3, T4> >(
+        new CartesianProductGenerator4<T1, T2, T3, T4>(
+        static_cast<ParamGenerator<T1> >(g1_),
+        static_cast<ParamGenerator<T2> >(g2_),
+        static_cast<ParamGenerator<T3> >(g3_),
+        static_cast<ParamGenerator<T4> >(g4_)));
+  }
+
+ private:
+  // No implementation - assignment is unsupported.
+  void operator=(const CartesianProductHolder4& other);
+
+  const Generator1 g1_;
+  const Generator2 g2_;
+  const Generator3 g3_;
+  const Generator4 g4_;
+};  // class CartesianProductHolder4
+
+template <class Generator1, class Generator2, class Generator3,
+    class Generator4, class Generator5>
+class CartesianProductHolder5 {
+ public:
+CartesianProductHolder5(const Generator1& g1, const Generator2& g2,
+    const Generator3& g3, const Generator4& g4, const Generator5& g5)
+      : g1_(g1), g2_(g2), g3_(g3), g4_(g4), g5_(g5) {}
+  template <typename T1, typename T2, typename T3, typename T4, typename T5>
+  operator ParamGenerator< ::std::tr1::tuple<T1, T2, T3, T4, T5> >() const {
+    return ParamGenerator< ::std::tr1::tuple<T1, T2, T3, T4, T5> >(
+        new CartesianProductGenerator5<T1, T2, T3, T4, T5>(
+        static_cast<ParamGenerator<T1> >(g1_),
+        static_cast<ParamGenerator<T2> >(g2_),
+        static_cast<ParamGenerator<T3> >(g3_),
+        static_cast<ParamGenerator<T4> >(g4_),
+        static_cast<ParamGenerator<T5> >(g5_)));
+  }
+
+ private:
+  // No implementation - assignment is unsupported.
+  void operator=(const CartesianProductHolder5& other);
+
+  const Generator1 g1_;
+  const Generator2 g2_;
+  const Generator3 g3_;
+  const Generator4 g4_;
+  const Generator5 g5_;
+};  // class CartesianProductHolder5
+
+template <class Generator1, class Generator2, class Generator3,
+    class Generator4, class Generator5, class Generator6>
+class CartesianProductHolder6 {
+ public:
+CartesianProductHolder6(const Generator1& g1, const Generator2& g2,
+    const Generator3& g3, const Generator4& g4, const Generator5& g5,
+    const Generator6& g6)
+      : g1_(g1), g2_(g2), g3_(g3), g4_(g4), g5_(g5), g6_(g6) {}
+  template <typename T1, typename T2, typename T3, typename T4, typename T5,
+      typename T6>
+  operator ParamGenerator< ::std::tr1::tuple<T1, T2, T3, T4, T5, T6> >() const {
+    return ParamGenerator< ::std::tr1::tuple<T1, T2, T3, T4, T5, T6> >(
+        new CartesianProductGenerator6<T1, T2, T3, T4, T5, T6>(
+        static_cast<ParamGenerator<T1> >(g1_),
+        static_cast<ParamGenerator<T2> >(g2_),
+        static_cast<ParamGenerator<T3> >(g3_),
+        static_cast<ParamGenerator<T4> >(g4_),
+        static_cast<ParamGenerator<T5> >(g5_),
+        static_cast<ParamGenerator<T6> >(g6_)));
+  }
+
+ private:
+  // No implementation - assignment is unsupported.
+  void operator=(const CartesianProductHolder6& other);
+
+  const Generator1 g1_;
+  const Generator2 g2_;
+  const Generator3 g3_;
+  const Generator4 g4_;
+  const Generator5 g5_;
+  const Generator6 g6_;
+};  // class CartesianProductHolder6
+
+template <class Generator1, class Generator2, class Generator3,
+    class Generator4, class Generator5, class Generator6, class Generator7>
+class CartesianProductHolder7 {
+ public:
+CartesianProductHolder7(const Generator1& g1, const Generator2& g2,
+    const Generator3& g3, const Generator4& g4, const Generator5& g5,
+    const Generator6& g6, const Generator7& g7)
+      : g1_(g1), g2_(g2), g3_(g3), g4_(g4), g5_(g5), g6_(g6), g7_(g7) {}
+  template <typename T1, typename T2, typename T3, typename T4, typename T5,
+      typename T6, typename T7>
+  operator ParamGenerator< ::std::tr1::tuple<T1, T2, T3, T4, T5, T6,
+      T7> >() const {
+    return ParamGenerator< ::std::tr1::tuple<T1, T2, T3, T4, T5, T6, T7> >(
+        new CartesianProductGenerator7<T1, T2, T3, T4, T5, T6, T7>(
+        static_cast<ParamGenerator<T1> >(g1_),
+        static_cast<ParamGenerator<T2> >(g2_),
+        static_cast<ParamGenerator<T3> >(g3_),
+        static_cast<ParamGenerator<T4> >(g4_),
+        static_cast<ParamGenerator<T5> >(g5_),
+        static_cast<ParamGenerator<T6> >(g6_),
+        static_cast<ParamGenerator<T7> >(g7_)));
+  }
+
+ private:
+  // No implementation - assignment is unsupported.
+  void operator=(const CartesianProductHolder7& other);
+
+  const Generator1 g1_;
+  const Generator2 g2_;
+  const Generator3 g3_;
+  const Generator4 g4_;
+  const Generator5 g5_;
+  const Generator6 g6_;
+  const Generator7 g7_;
+};  // class CartesianProductHolder7
+
+template <class Generator1, class Generator2, class Generator3,
+    class Generator4, class Generator5, class Generator6, class Generator7,
+    class Generator8>
+class CartesianProductHolder8 {
+ public:
+CartesianProductHolder8(const Generator1& g1, const Generator2& g2,
+    const Generator3& g3, const Generator4& g4, const Generator5& g5,
+    const Generator6& g6, const Generator7& g7, const Generator8& g8)
+      : g1_(g1), g2_(g2), g3_(g3), g4_(g4), g5_(g5), g6_(g6), g7_(g7),
+          g8_(g8) {}
+  template <typename T1, typename T2, typename T3, typename T4, typename T5,
+      typename T6, typename T7, typename T8>
+  operator ParamGenerator< ::std::tr1::tuple<T1, T2, T3, T4, T5, T6, T7,
+      T8> >() const {
+    return ParamGenerator< ::std::tr1::tuple<T1, T2, T3, T4, T5, T6, T7, T8> >(
+        new CartesianProductGenerator8<T1, T2, T3, T4, T5, T6, T7, T8>(
+        static_cast<ParamGenerator<T1> >(g1_),
+        static_cast<ParamGenerator<T2> >(g2_),
+        static_cast<ParamGenerator<T3> >(g3_),
+        static_cast<ParamGenerator<T4> >(g4_),
+        static_cast<ParamGenerator<T5> >(g5_),
+        static_cast<ParamGenerator<T6> >(g6_),
+        static_cast<ParamGenerator<T7> >(g7_),
+        static_cast<ParamGenerator<T8> >(g8_)));
+  }
+
+ private:
+  // No implementation - assignment is unsupported.
+  void operator=(const CartesianProductHolder8& other);
+
+  const Generator1 g1_;
+  const Generator2 g2_;
+  const Generator3 g3_;
+  const Generator4 g4_;
+  const Generator5 g5_;
+  const Generator6 g6_;
+  const Generator7 g7_;
+  const Generator8 g8_;
+};  // class CartesianProductHolder8
+
+template <class Generator1, class Generator2, class Generator3,
+    class Generator4, class Generator5, class Generator6, class Generator7,
+    class Generator8, class Generator9>
+class CartesianProductHolder9 {
+ public:
+CartesianProductHolder9(const Generator1& g1, const Generator2& g2,
+    const Generator3& g3, const Generator4& g4, const Generator5& g5,
+    const Generator6& g6, const Generator7& g7, const Generator8& g8,
+    const Generator9& g9)
+      : g1_(g1), g2_(g2), g3_(g3), g4_(g4), g5_(g5), g6_(g6), g7_(g7), g8_(g8),
+          g9_(g9) {}
+  template <typename T1, typename T2, typename T3, typename T4, typename T5,
+      typename T6, typename T7, typename T8, typename T9>
+  operator ParamGenerator< ::std::tr1::tuple<T1, T2, T3, T4, T5, T6, T7, T8,
+      T9> >() const {
+    return ParamGenerator< ::std::tr1::tuple<T1, T2, T3, T4, T5, T6, T7, T8,
+        T9> >(
+        new CartesianProductGenerator9<T1, T2, T3, T4, T5, T6, T7, T8, T9>(
+        static_cast<ParamGenerator<T1> >(g1_),
+        static_cast<ParamGenerator<T2> >(g2_),
+        static_cast<ParamGenerator<T3> >(g3_),
+        static_cast<ParamGenerator<T4> >(g4_),
+        static_cast<ParamGenerator<T5> >(g5_),
+        static_cast<ParamGenerator<T6> >(g6_),
+        static_cast<ParamGenerator<T7> >(g7_),
+        static_cast<ParamGenerator<T8> >(g8_),
+        static_cast<ParamGenerator<T9> >(g9_)));
+  }
+
+ private:
+  // No implementation - assignment is unsupported.
+  void operator=(const CartesianProductHolder9& other);
+
+  const Generator1 g1_;
+  const Generator2 g2_;
+  const Generator3 g3_;
+  const Generator4 g4_;
+  const Generator5 g5_;
+  const Generator6 g6_;
+  const Generator7 g7_;
+  const Generator8 g8_;
+  const Generator9 g9_;
+};  // class CartesianProductHolder9
+
+template <class Generator1, class Generator2, class Generator3,
+    class Generator4, class Generator5, class Generator6, class Generator7,
+    class Generator8, class Generator9, class Generator10>
+class CartesianProductHolder10 {
+ public:
+CartesianProductHolder10(const Generator1& g1, const Generator2& g2,
+    const Generator3& g3, const Generator4& g4, const Generator5& g5,
+    const Generator6& g6, const Generator7& g7, const Generator8& g8,
+    const Generator9& g9, const Generator10& g10)
+      : g1_(g1), g2_(g2), g3_(g3), g4_(g4), g5_(g5), g6_(g6), g7_(g7), g8_(g8),
+          g9_(g9), g10_(g10) {}
+  template <typename T1, typename T2, typename T3, typename T4, typename T5,
+      typename T6, typename T7, typename T8, typename T9, typename T10>
+  operator ParamGenerator< ::std::tr1::tuple<T1, T2, T3, T4, T5, T6, T7, T8,
+      T9, T10> >() const {
+    return ParamGenerator< ::std::tr1::tuple<T1, T2, T3, T4, T5, T6, T7, T8,
+        T9, T10> >(
+        new CartesianProductGenerator10<T1, T2, T3, T4, T5, T6, T7, T8, T9,
+            T10>(
+        static_cast<ParamGenerator<T1> >(g1_),
+        static_cast<ParamGenerator<T2> >(g2_),
+        static_cast<ParamGenerator<T3> >(g3_),
+        static_cast<ParamGenerator<T4> >(g4_),
+        static_cast<ParamGenerator<T5> >(g5_),
+        static_cast<ParamGenerator<T6> >(g6_),
+        static_cast<ParamGenerator<T7> >(g7_),
+        static_cast<ParamGenerator<T8> >(g8_),
+        static_cast<ParamGenerator<T9> >(g9_),
+        static_cast<ParamGenerator<T10> >(g10_)));
+  }
+
+ private:
+  // No implementation - assignment is unsupported.
+  void operator=(const CartesianProductHolder10& other);
+
+  const Generator1 g1_;
+  const Generator2 g2_;
+  const Generator3 g3_;
+  const Generator4 g4_;
+  const Generator5 g5_;
+  const Generator6 g6_;
+  const Generator7 g7_;
+  const Generator8 g8_;
+  const Generator9 g9_;
+  const Generator10 g10_;
+};  // class CartesianProductHolder10
+
+# endif  // GTEST_HAS_COMBINE
+
+}  // namespace internal
+}  // namespace testing
+
+#endif  //  GTEST_HAS_PARAM_TEST
+
+#endif  // GTEST_INCLUDE_GTEST_INTERNAL_GTEST_PARAM_UTIL_GENERATED_H_
diff --git a/test/gtest/include/gtest/internal/gtest-param-util-generated.h.pump b/test/gtest/include/gtest/internal/gtest-param-util-generated.h.pump
new file mode 100644
index 0000000..009206f
--- /dev/null
+++ b/test/gtest/include/gtest/internal/gtest-param-util-generated.h.pump
@@ -0,0 +1,301 @@
+$$ -*- mode: c++; -*-
+$var n = 50  $$ Maximum length of Values arguments we want to support.
+$var maxtuple = 10  $$ Maximum number of Combine arguments we want to support.
+// Copyright 2008 Google Inc.
+// All Rights Reserved.
+//
+// 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: vladl at google.com (Vlad Losev)
+
+// Type and function utilities for implementing parameterized tests.
+// This file is generated by a SCRIPT.  DO NOT EDIT BY HAND!
+//
+// Currently Google Test supports at most $n arguments in Values,
+// and at most $maxtuple arguments in Combine. Please contact
+// googletestframework at googlegroups.com if you need more.
+// Please note that the number of arguments to Combine is limited
+// by the maximum arity of the implementation of tr1::tuple which is
+// currently set at $maxtuple.
+
+#ifndef GTEST_INCLUDE_GTEST_INTERNAL_GTEST_PARAM_UTIL_GENERATED_H_
+#define GTEST_INCLUDE_GTEST_INTERNAL_GTEST_PARAM_UTIL_GENERATED_H_
+
+// scripts/fuse_gtest.py depends on gtest's own header being #included
+// *unconditionally*.  Therefore these #includes cannot be moved
+// inside #if GTEST_HAS_PARAM_TEST.
+#include "gtest/internal/gtest-param-util.h"
+#include "gtest/internal/gtest-port.h"
+
+#if GTEST_HAS_PARAM_TEST
+
+namespace testing {
+
+// Forward declarations of ValuesIn(), which is implemented in
+// include/gtest/gtest-param-test.h.
+template <typename ForwardIterator>
+internal::ParamGenerator<
+  typename ::testing::internal::IteratorTraits<ForwardIterator>::value_type>
+ValuesIn(ForwardIterator begin, ForwardIterator end);
+
+template <typename T, size_t N>
+internal::ParamGenerator<T> ValuesIn(const T (&array)[N]);
+
+template <class Container>
+internal::ParamGenerator<typename Container::value_type> ValuesIn(
+    const Container& container);
+
+namespace internal {
+
+// Used in the Values() function to provide polymorphic capabilities.
+template <typename T1>
+class ValueArray1 {
+ public:
+  explicit ValueArray1(T1 v1) : v1_(v1) {}
+
+  template <typename T>
+  operator ParamGenerator<T>() const { return ValuesIn(&v1_, &v1_ + 1); }
+
+ private:
+  // No implementation - assignment is unsupported.
+  void operator=(const ValueArray1& other);
+
+  const T1 v1_;
+};
+
+$range i 2..n
+$for i [[
+$range j 1..i
+
+template <$for j, [[typename T$j]]>
+class ValueArray$i {
+ public:
+  ValueArray$i($for j, [[T$j v$j]]) : $for j, [[v$(j)_(v$j)]] {}
+
+  template <typename T>
+  operator ParamGenerator<T>() const {
+    const T array[] = {$for j, [[static_cast<T>(v$(j)_)]]};
+    return ValuesIn(array);
+  }
+
+ private:
+  // No implementation - assignment is unsupported.
+  void operator=(const ValueArray$i& other);
+
+$for j [[
+
+  const T$j v$(j)_;
+]]
+
+};
+
+]]
+
+# if GTEST_HAS_COMBINE
+// INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE.
+//
+// Generates values from the Cartesian product of values produced
+// by the argument generators.
+//
+$range i 2..maxtuple
+$for i [[
+$range j 1..i
+$range k 2..i
+
+template <$for j, [[typename T$j]]>
+class CartesianProductGenerator$i
+    : public ParamGeneratorInterface< ::std::tr1::tuple<$for j, [[T$j]]> > {
+ public:
+  typedef ::std::tr1::tuple<$for j, [[T$j]]> ParamType;
+
+  CartesianProductGenerator$i($for j, [[const ParamGenerator<T$j>& g$j]])
+      : $for j, [[g$(j)_(g$j)]] {}
+  virtual ~CartesianProductGenerator$i() {}
+
+  virtual ParamIteratorInterface<ParamType>* Begin() const {
+    return new Iterator(this, $for j, [[g$(j)_, g$(j)_.begin()]]);
+  }
+  virtual ParamIteratorInterface<ParamType>* End() const {
+    return new Iterator(this, $for j, [[g$(j)_, g$(j)_.end()]]);
+  }
+
+ private:
+  class Iterator : public ParamIteratorInterface<ParamType> {
+   public:
+    Iterator(const ParamGeneratorInterface<ParamType>* base, $for j, [[
+
+      const ParamGenerator<T$j>& g$j,
+      const typename ParamGenerator<T$j>::iterator& current$(j)]])
+        : base_(base),
+$for j, [[
+
+          begin$(j)_(g$j.begin()), end$(j)_(g$j.end()), current$(j)_(current$j)
+]]    {
+      ComputeCurrentValue();
+    }
+    virtual ~Iterator() {}
+
+    virtual const ParamGeneratorInterface<ParamType>* BaseGenerator() const {
+      return base_;
+    }
+    // Advance should not be called on beyond-of-range iterators
+    // so no component iterators must be beyond end of range, either.
+    virtual void Advance() {
+      assert(!AtEnd());
+      ++current$(i)_;
+
+$for k [[
+      if (current$(i+2-k)_ == end$(i+2-k)_) {
+        current$(i+2-k)_ = begin$(i+2-k)_;
+        ++current$(i+2-k-1)_;
+      }
+
+]]
+      ComputeCurrentValue();
+    }
+    virtual ParamIteratorInterface<ParamType>* Clone() const {
+      return new Iterator(*this);
+    }
+    virtual const ParamType* Current() const { return &current_value_; }
+    virtual bool Equals(const ParamIteratorInterface<ParamType>& other) const {
+      // Having the same base generator guarantees that the other
+      // iterator is of the same type and we can downcast.
+      GTEST_CHECK_(BaseGenerator() == other.BaseGenerator())
+          << "The program attempted to compare iterators "
+          << "from different generators." << std::endl;
+      const Iterator* typed_other =
+          CheckedDowncastToActualType<const Iterator>(&other);
+      // We must report iterators equal if they both point beyond their
+      // respective ranges. That can happen in a variety of fashions,
+      // so we have to consult AtEnd().
+      return (AtEnd() && typed_other->AtEnd()) ||
+         ($for j  && [[
+
+          current$(j)_ == typed_other->current$(j)_
+]]);
+    }
+
+   private:
+    Iterator(const Iterator& other)
+        : base_(other.base_), $for j, [[
+
+        begin$(j)_(other.begin$(j)_),
+        end$(j)_(other.end$(j)_),
+        current$(j)_(other.current$(j)_)
+]] {
+      ComputeCurrentValue();
+    }
+
+    void ComputeCurrentValue() {
+      if (!AtEnd())
+        current_value_ = ParamType($for j, [[*current$(j)_]]);
+    }
+    bool AtEnd() const {
+      // We must report iterator past the end of the range when either of the
+      // component iterators has reached the end of its range.
+      return
+$for j  || [[
+
+          current$(j)_ == end$(j)_
+]];
+    }
+
+    // No implementation - assignment is unsupported.
+    void operator=(const Iterator& other);
+
+    const ParamGeneratorInterface<ParamType>* const base_;
+    // begin[i]_ and end[i]_ define the i-th range that Iterator traverses.
+    // current[i]_ is the actual traversing iterator.
+$for j [[
+
+    const typename ParamGenerator<T$j>::iterator begin$(j)_;
+    const typename ParamGenerator<T$j>::iterator end$(j)_;
+    typename ParamGenerator<T$j>::iterator current$(j)_;
+]]
+
+    ParamType current_value_;
+  };  // class CartesianProductGenerator$i::Iterator
+
+  // No implementation - assignment is unsupported.
+  void operator=(const CartesianProductGenerator$i& other);
+
+
+$for j [[
+  const ParamGenerator<T$j> g$(j)_;
+
+]]
+};  // class CartesianProductGenerator$i
+
+
+]]
+
+// INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE.
+//
+// Helper classes providing Combine() with polymorphic features. They allow
+// casting CartesianProductGeneratorN<T> to ParamGenerator<U> if T is
+// convertible to U.
+//
+$range i 2..maxtuple
+$for i [[
+$range j 1..i
+
+template <$for j, [[class Generator$j]]>
+class CartesianProductHolder$i {
+ public:
+CartesianProductHolder$i($for j, [[const Generator$j& g$j]])
+      : $for j, [[g$(j)_(g$j)]] {}
+  template <$for j, [[typename T$j]]>
+  operator ParamGenerator< ::std::tr1::tuple<$for j, [[T$j]]> >() const {
+    return ParamGenerator< ::std::tr1::tuple<$for j, [[T$j]]> >(
+        new CartesianProductGenerator$i<$for j, [[T$j]]>(
+$for j,[[
+
+        static_cast<ParamGenerator<T$j> >(g$(j)_)
+]]));
+  }
+
+ private:
+  // No implementation - assignment is unsupported.
+  void operator=(const CartesianProductHolder$i& other);
+
+
+$for j [[
+  const Generator$j g$(j)_;
+
+]]
+};  // class CartesianProductHolder$i
+
+]]
+
+# endif  // GTEST_HAS_COMBINE
+
+}  // namespace internal
+}  // namespace testing
+
+#endif  //  GTEST_HAS_PARAM_TEST
+
+#endif  // GTEST_INCLUDE_GTEST_INTERNAL_GTEST_PARAM_UTIL_GENERATED_H_
diff --git a/test/gtest/include/gtest/internal/gtest-param-util.h b/test/gtest/include/gtest/internal/gtest-param-util.h
new file mode 100644
index 0000000..d5e1028
--- /dev/null
+++ b/test/gtest/include/gtest/internal/gtest-param-util.h
@@ -0,0 +1,619 @@
+// Copyright 2008 Google Inc.
+// All Rights Reserved.
+//
+// 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: vladl at google.com (Vlad Losev)
+
+// Type and function utilities for implementing parameterized tests.
+
+#ifndef GTEST_INCLUDE_GTEST_INTERNAL_GTEST_PARAM_UTIL_H_
+#define GTEST_INCLUDE_GTEST_INTERNAL_GTEST_PARAM_UTIL_H_
+
+#include <iterator>
+#include <utility>
+#include <vector>
+
+// scripts/fuse_gtest.py depends on gtest's own header being #included
+// *unconditionally*.  Therefore these #includes cannot be moved
+// inside #if GTEST_HAS_PARAM_TEST.
+#include "gtest/internal/gtest-internal.h"
+#include "gtest/internal/gtest-linked_ptr.h"
+#include "gtest/internal/gtest-port.h"
+#include "gtest/gtest-printers.h"
+
+#if GTEST_HAS_PARAM_TEST
+
+namespace testing {
+namespace internal {
+
+// INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE.
+//
+// Outputs a message explaining invalid registration of different
+// fixture class for the same test case. This may happen when
+// TEST_P macro is used to define two tests with the same name
+// but in different namespaces.
+GTEST_API_ void ReportInvalidTestCaseType(const char* test_case_name,
+                                          const char* file, int line);
+
+template <typename> class ParamGeneratorInterface;
+template <typename> class ParamGenerator;
+
+// Interface for iterating over elements provided by an implementation
+// of ParamGeneratorInterface<T>.
+template <typename T>
+class ParamIteratorInterface {
+ public:
+  virtual ~ParamIteratorInterface() {}
+  // A pointer to the base generator instance.
+  // Used only for the purposes of iterator comparison
+  // to make sure that two iterators belong to the same generator.
+  virtual const ParamGeneratorInterface<T>* BaseGenerator() const = 0;
+  // Advances iterator to point to the next element
+  // provided by the generator. The caller is responsible
+  // for not calling Advance() on an iterator equal to
+  // BaseGenerator()->End().
+  virtual void Advance() = 0;
+  // Clones the iterator object. Used for implementing copy semantics
+  // of ParamIterator<T>.
+  virtual ParamIteratorInterface* Clone() const = 0;
+  // Dereferences the current iterator and provides (read-only) access
+  // to the pointed value. It is the caller's responsibility not to call
+  // Current() on an iterator equal to BaseGenerator()->End().
+  // Used for implementing ParamGenerator<T>::operator*().
+  virtual const T* Current() const = 0;
+  // Determines whether the given iterator and other point to the same
+  // element in the sequence generated by the generator.
+  // Used for implementing ParamGenerator<T>::operator==().
+  virtual bool Equals(const ParamIteratorInterface& other) const = 0;
+};
+
+// Class iterating over elements provided by an implementation of
+// ParamGeneratorInterface<T>. It wraps ParamIteratorInterface<T>
+// and implements the const forward iterator concept.
+template <typename T>
+class ParamIterator {
+ public:
+  typedef T value_type;
+  typedef const T& reference;
+  typedef ptrdiff_t difference_type;
+
+  // ParamIterator assumes ownership of the impl_ pointer.
+  ParamIterator(const ParamIterator& other) : impl_(other.impl_->Clone()) {}
+  ParamIterator& operator=(const ParamIterator& other) {
+    if (this != &other)
+      impl_.reset(other.impl_->Clone());
+    return *this;
+  }
+
+  const T& operator*() const { return *impl_->Current(); }
+  const T* operator->() const { return impl_->Current(); }
+  // Prefix version of operator++.
+  ParamIterator& operator++() {
+    impl_->Advance();
+    return *this;
+  }
+  // Postfix version of operator++.
+  ParamIterator operator++(int /*unused*/) {
+    ParamIteratorInterface<T>* clone = impl_->Clone();
+    impl_->Advance();
+    return ParamIterator(clone);
+  }
+  bool operator==(const ParamIterator& other) const {
+    return impl_.get() == other.impl_.get() || impl_->Equals(*other.impl_);
+  }
+  bool operator!=(const ParamIterator& other) const {
+    return !(*this == other);
+  }
+
+ private:
+  friend class ParamGenerator<T>;
+  explicit ParamIterator(ParamIteratorInterface<T>* impl) : impl_(impl) {}
+  scoped_ptr<ParamIteratorInterface<T> > impl_;
+};
+
+// ParamGeneratorInterface<T> is the binary interface to access generators
+// defined in other translation units.
+template <typename T>
+class ParamGeneratorInterface {
+ public:
+  typedef T ParamType;
+
+  virtual ~ParamGeneratorInterface() {}
+
+  // Generator interface definition
+  virtual ParamIteratorInterface<T>* Begin() const = 0;
+  virtual ParamIteratorInterface<T>* End() const = 0;
+};
+
+// Wraps ParamGeneratorInterface<T> and provides general generator syntax
+// compatible with the STL Container concept.
+// This class implements copy initialization semantics and the contained
+// ParamGeneratorInterface<T> instance is shared among all copies
+// of the original object. This is possible because that instance is immutable.
+template<typename T>
+class ParamGenerator {
+ public:
+  typedef ParamIterator<T> iterator;
+
+  explicit ParamGenerator(ParamGeneratorInterface<T>* impl) : impl_(impl) {}
+  ParamGenerator(const ParamGenerator& other) : impl_(other.impl_) {}
+
+  ParamGenerator& operator=(const ParamGenerator& other) {
+    impl_ = other.impl_;
+    return *this;
+  }
+
+  iterator begin() const { return iterator(impl_->Begin()); }
+  iterator end() const { return iterator(impl_->End()); }
+
+ private:
+  linked_ptr<const ParamGeneratorInterface<T> > impl_;
+};
+
+// Generates values from a range of two comparable values. Can be used to
+// generate sequences of user-defined types that implement operator+() and
+// operator<().
+// This class is used in the Range() function.
+template <typename T, typename IncrementT>
+class RangeGenerator : public ParamGeneratorInterface<T> {
+ public:
+  RangeGenerator(T begin, T end, IncrementT step)
+      : begin_(begin), end_(end),
+        step_(step), end_index_(CalculateEndIndex(begin, end, step)) {}
+  virtual ~RangeGenerator() {}
+
+  virtual ParamIteratorInterface<T>* Begin() const {
+    return new Iterator(this, begin_, 0, step_);
+  }
+  virtual ParamIteratorInterface<T>* End() const {
+    return new Iterator(this, end_, end_index_, step_);
+  }
+
+ private:
+  class Iterator : public ParamIteratorInterface<T> {
+   public:
+    Iterator(const ParamGeneratorInterface<T>* base, T value, int index,
+             IncrementT step)
+        : base_(base), value_(value), index_(index), step_(step) {}
+    virtual ~Iterator() {}
+
+    virtual const ParamGeneratorInterface<T>* BaseGenerator() const {
+      return base_;
+    }
+    virtual void Advance() {
+      value_ = value_ + step_;
+      index_++;
+    }
+    virtual ParamIteratorInterface<T>* Clone() const {
+      return new Iterator(*this);
+    }
+    virtual const T* Current() const { return &value_; }
+    virtual bool Equals(const ParamIteratorInterface<T>& other) const {
+      // Having the same base generator guarantees that the other
+      // iterator is of the same type and we can downcast.
+      GTEST_CHECK_(BaseGenerator() == other.BaseGenerator())
+          << "The program attempted to compare iterators "
+          << "from different generators." << std::endl;
+      const int other_index =
+          CheckedDowncastToActualType<const Iterator>(&other)->index_;
+      return index_ == other_index;
+    }
+
+   private:
+    Iterator(const Iterator& other)
+        : ParamIteratorInterface<T>(),
+          base_(other.base_), value_(other.value_), index_(other.index_),
+          step_(other.step_) {}
+
+    // No implementation - assignment is unsupported.
+    void operator=(const Iterator& other);
+
+    const ParamGeneratorInterface<T>* const base_;
+    T value_;
+    int index_;
+    const IncrementT step_;
+  };  // class RangeGenerator::Iterator
+
+  static int CalculateEndIndex(const T& begin,
+                               const T& end,
+                               const IncrementT& step) {
+    int end_index = 0;
+    for (T i = begin; i < end; i = i + step)
+      end_index++;
+    return end_index;
+  }
+
+  // No implementation - assignment is unsupported.
+  void operator=(const RangeGenerator& other);
+
+  const T begin_;
+  const T end_;
+  const IncrementT step_;
+  // The index for the end() iterator. All the elements in the generated
+  // sequence are indexed (0-based) to aid iterator comparison.
+  const int end_index_;
+};  // class RangeGenerator
+
+
+// Generates values from a pair of STL-style iterators. Used in the
+// ValuesIn() function. The elements are copied from the source range
+// since the source can be located on the stack, and the generator
+// is likely to persist beyond that stack frame.
+template <typename T>
+class ValuesInIteratorRangeGenerator : public ParamGeneratorInterface<T> {
+ public:
+  template <typename ForwardIterator>
+  ValuesInIteratorRangeGenerator(ForwardIterator begin, ForwardIterator end)
+      : container_(begin, end) {}
+  virtual ~ValuesInIteratorRangeGenerator() {}
+
+  virtual ParamIteratorInterface<T>* Begin() const {
+    return new Iterator(this, container_.begin());
+  }
+  virtual ParamIteratorInterface<T>* End() const {
+    return new Iterator(this, container_.end());
+  }
+
+ private:
+  typedef typename ::std::vector<T> ContainerType;
+
+  class Iterator : public ParamIteratorInterface<T> {
+   public:
+    Iterator(const ParamGeneratorInterface<T>* base,
+             typename ContainerType::const_iterator iterator)
+        : base_(base), iterator_(iterator) {}
+    virtual ~Iterator() {}
+
+    virtual const ParamGeneratorInterface<T>* BaseGenerator() const {
+      return base_;
+    }
+    virtual void Advance() {
+      ++iterator_;
+      value_.reset();
+    }
+    virtual ParamIteratorInterface<T>* Clone() const {
+      return new Iterator(*this);
+    }
+    // We need to use cached value referenced by iterator_ because *iterator_
+    // can return a temporary object (and of type other then T), so just
+    // having "return &*iterator_;" doesn't work.
+    // value_ is updated here and not in Advance() because Advance()
+    // can advance iterator_ beyond the end of the range, and we cannot
+    // detect that fact. The client code, on the other hand, is
+    // responsible for not calling Current() on an out-of-range iterator.
+    virtual const T* Current() const {
+      if (value_.get() == NULL)
+        value_.reset(new T(*iterator_));
+      return value_.get();
+    }
+    virtual bool Equals(const ParamIteratorInterface<T>& other) const {
+      // Having the same base generator guarantees that the other
+      // iterator is of the same type and we can downcast.
+      GTEST_CHECK_(BaseGenerator() == other.BaseGenerator())
+          << "The program attempted to compare iterators "
+          << "from different generators." << std::endl;
+      return iterator_ ==
+          CheckedDowncastToActualType<const Iterator>(&other)->iterator_;
+    }
+
+   private:
+    Iterator(const Iterator& other)
+          // The explicit constructor call suppresses a false warning
+          // emitted by gcc when supplied with the -Wextra option.
+        : ParamIteratorInterface<T>(),
+          base_(other.base_),
+          iterator_(other.iterator_) {}
+
+    const ParamGeneratorInterface<T>* const base_;
+    typename ContainerType::const_iterator iterator_;
+    // A cached value of *iterator_. We keep it here to allow access by
+    // pointer in the wrapping iterator's operator->().
+    // value_ needs to be mutable to be accessed in Current().
+    // Use of scoped_ptr helps manage cached value's lifetime,
+    // which is bound by the lifespan of the iterator itself.
+    mutable scoped_ptr<const T> value_;
+  };  // class ValuesInIteratorRangeGenerator::Iterator
+
+  // No implementation - assignment is unsupported.
+  void operator=(const ValuesInIteratorRangeGenerator& other);
+
+  const ContainerType container_;
+};  // class ValuesInIteratorRangeGenerator
+
+// INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE.
+//
+// Stores a parameter value and later creates tests parameterized with that
+// value.
+template <class TestClass>
+class ParameterizedTestFactory : public TestFactoryBase {
+ public:
+  typedef typename TestClass::ParamType ParamType;
+  explicit ParameterizedTestFactory(ParamType parameter) :
+      parameter_(parameter) {}
+  virtual Test* CreateTest() {
+    TestClass::SetParam(&parameter_);
+    return new TestClass();
+  }
+
+ private:
+  const ParamType parameter_;
+
+  GTEST_DISALLOW_COPY_AND_ASSIGN_(ParameterizedTestFactory);
+};
+
+// INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE.
+//
+// TestMetaFactoryBase is a base class for meta-factories that create
+// test factories for passing into MakeAndRegisterTestInfo function.
+template <class ParamType>
+class TestMetaFactoryBase {
+ public:
+  virtual ~TestMetaFactoryBase() {}
+
+  virtual TestFactoryBase* CreateTestFactory(ParamType parameter) = 0;
+};
+
+// INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE.
+//
+// TestMetaFactory creates test factories for passing into
+// MakeAndRegisterTestInfo function. Since MakeAndRegisterTestInfo receives
+// ownership of test factory pointer, same factory object cannot be passed
+// into that method twice. But ParameterizedTestCaseInfo is going to call
+// it for each Test/Parameter value combination. Thus it needs meta factory
+// creator class.
+template <class TestCase>
+class TestMetaFactory
+    : public TestMetaFactoryBase<typename TestCase::ParamType> {
+ public:
+  typedef typename TestCase::ParamType ParamType;
+
+  TestMetaFactory() {}
+
+  virtual TestFactoryBase* CreateTestFactory(ParamType parameter) {
+    return new ParameterizedTestFactory<TestCase>(parameter);
+  }
+
+ private:
+  GTEST_DISALLOW_COPY_AND_ASSIGN_(TestMetaFactory);
+};
+
+// INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE.
+//
+// ParameterizedTestCaseInfoBase is a generic interface
+// to ParameterizedTestCaseInfo classes. ParameterizedTestCaseInfoBase
+// accumulates test information provided by TEST_P macro invocations
+// and generators provided by INSTANTIATE_TEST_CASE_P macro invocations
+// and uses that information to register all resulting test instances
+// in RegisterTests method. The ParameterizeTestCaseRegistry class holds
+// a collection of pointers to the ParameterizedTestCaseInfo objects
+// and calls RegisterTests() on each of them when asked.
+class ParameterizedTestCaseInfoBase {
+ public:
+  virtual ~ParameterizedTestCaseInfoBase() {}
+
+  // Base part of test case name for display purposes.
+  virtual const string& GetTestCaseName() const = 0;
+  // Test case id to verify identity.
+  virtual TypeId GetTestCaseTypeId() const = 0;
+  // UnitTest class invokes this method to register tests in this
+  // test case right before running them in RUN_ALL_TESTS macro.
+  // This method should not be called more then once on any single
+  // instance of a ParameterizedTestCaseInfoBase derived class.
+  virtual void RegisterTests() = 0;
+
+ protected:
+  ParameterizedTestCaseInfoBase() {}
+
+ private:
+  GTEST_DISALLOW_COPY_AND_ASSIGN_(ParameterizedTestCaseInfoBase);
+};
+
+// INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE.
+//
+// ParameterizedTestCaseInfo accumulates tests obtained from TEST_P
+// macro invocations for a particular test case and generators
+// obtained from INSTANTIATE_TEST_CASE_P macro invocations for that
+// test case. It registers tests with all values generated by all
+// generators when asked.
+template <class TestCase>
+class ParameterizedTestCaseInfo : public ParameterizedTestCaseInfoBase {
+ public:
+  // ParamType and GeneratorCreationFunc are private types but are required
+  // for declarations of public methods AddTestPattern() and
+  // AddTestCaseInstantiation().
+  typedef typename TestCase::ParamType ParamType;
+  // A function that returns an instance of appropriate generator type.
+  typedef ParamGenerator<ParamType>(GeneratorCreationFunc)();
+
+  explicit ParameterizedTestCaseInfo(const char* name)
+      : test_case_name_(name) {}
+
+  // Test case base name for display purposes.
+  virtual const string& GetTestCaseName() const { return test_case_name_; }
+  // Test case id to verify identity.
+  virtual TypeId GetTestCaseTypeId() const { return GetTypeId<TestCase>(); }
+  // TEST_P macro uses AddTestPattern() to record information
+  // about a single test in a LocalTestInfo structure.
+  // test_case_name is the base name of the test case (without invocation
+  // prefix). test_base_name is the name of an individual test without
+  // parameter index. For the test SequenceA/FooTest.DoBar/1 FooTest is
+  // test case base name and DoBar is test base name.
+  void AddTestPattern(const char* test_case_name,
+                      const char* test_base_name,
+                      TestMetaFactoryBase<ParamType>* meta_factory) {
+    tests_.push_back(linked_ptr<TestInfo>(new TestInfo(test_case_name,
+                                                       test_base_name,
+                                                       meta_factory)));
+  }
+  // INSTANTIATE_TEST_CASE_P macro uses AddGenerator() to record information
+  // about a generator.
+  int AddTestCaseInstantiation(const string& instantiation_name,
+                               GeneratorCreationFunc* func,
+                               const char* /* file */,
+                               int /* line */) {
+    instantiations_.push_back(::std::make_pair(instantiation_name, func));
+    return 0;  // Return value used only to run this method in namespace scope.
+  }
+  // UnitTest class invokes this method to register tests in this test case
+  // test cases right before running tests in RUN_ALL_TESTS macro.
+  // This method should not be called more then once on any single
+  // instance of a ParameterizedTestCaseInfoBase derived class.
+  // UnitTest has a guard to prevent from calling this method more then once.
+  virtual void RegisterTests() {
+    for (typename TestInfoContainer::iterator test_it = tests_.begin();
+         test_it != tests_.end(); ++test_it) {
+      linked_ptr<TestInfo> test_info = *test_it;
+      for (typename InstantiationContainer::iterator gen_it =
+               instantiations_.begin(); gen_it != instantiations_.end();
+               ++gen_it) {
+        const string& instantiation_name = gen_it->first;
+        ParamGenerator<ParamType> generator((*gen_it->second)());
+
+        string test_case_name;
+        if ( !instantiation_name.empty() )
+          test_case_name = instantiation_name + "/";
+        test_case_name += test_info->test_case_base_name;
+
+        int i = 0;
+        for (typename ParamGenerator<ParamType>::iterator param_it =
+                 generator.begin();
+             param_it != generator.end(); ++param_it, ++i) {
+          Message test_name_stream;
+          test_name_stream << test_info->test_base_name << "/" << i;
+          MakeAndRegisterTestInfo(
+              test_case_name.c_str(),
+              test_name_stream.GetString().c_str(),
+              NULL,  // No type parameter.
+              PrintToString(*param_it).c_str(),
+              GetTestCaseTypeId(),
+              TestCase::SetUpTestCase,
+              TestCase::TearDownTestCase,
+              test_info->test_meta_factory->CreateTestFactory(*param_it));
+        }  // for param_it
+      }  // for gen_it
+    }  // for test_it
+  }  // RegisterTests
+
+ private:
+  // LocalTestInfo structure keeps information about a single test registered
+  // with TEST_P macro.
+  struct TestInfo {
+    TestInfo(const char* a_test_case_base_name,
+             const char* a_test_base_name,
+             TestMetaFactoryBase<ParamType>* a_test_meta_factory) :
+        test_case_base_name(a_test_case_base_name),
+        test_base_name(a_test_base_name),
+        test_meta_factory(a_test_meta_factory) {}
+
+    const string test_case_base_name;
+    const string test_base_name;
+    const scoped_ptr<TestMetaFactoryBase<ParamType> > test_meta_factory;
+  };
+  typedef ::std::vector<linked_ptr<TestInfo> > TestInfoContainer;
+  // Keeps pairs of <Instantiation name, Sequence generator creation function>
+  // received from INSTANTIATE_TEST_CASE_P macros.
+  typedef ::std::vector<std::pair<string, GeneratorCreationFunc*> >
+      InstantiationContainer;
+
+  const string test_case_name_;
+  TestInfoContainer tests_;
+  InstantiationContainer instantiations_;
+
+  GTEST_DISALLOW_COPY_AND_ASSIGN_(ParameterizedTestCaseInfo);
+};  // class ParameterizedTestCaseInfo
+
+// INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE.
+//
+// ParameterizedTestCaseRegistry contains a map of ParameterizedTestCaseInfoBase
+// classes accessed by test case names. TEST_P and INSTANTIATE_TEST_CASE_P
+// macros use it to locate their corresponding ParameterizedTestCaseInfo
+// descriptors.
+class ParameterizedTestCaseRegistry {
+ public:
+  ParameterizedTestCaseRegistry() {}
+  ~ParameterizedTestCaseRegistry() {
+    for (TestCaseInfoContainer::iterator it = test_case_infos_.begin();
+         it != test_case_infos_.end(); ++it) {
+      delete *it;
+    }
+  }
+
+  // Looks up or creates and returns a structure containing information about
+  // tests and instantiations of a particular test case.
+  template <class TestCase>
+  ParameterizedTestCaseInfo<TestCase>* GetTestCasePatternHolder(
+      const char* test_case_name,
+      const char* file,
+      int line) {
+    ParameterizedTestCaseInfo<TestCase>* typed_test_info = NULL;
+    for (TestCaseInfoContainer::iterator it = test_case_infos_.begin();
+         it != test_case_infos_.end(); ++it) {
+      if ((*it)->GetTestCaseName() == test_case_name) {
+        if ((*it)->GetTestCaseTypeId() != GetTypeId<TestCase>()) {
+          // Complain about incorrect usage of Google Test facilities
+          // and terminate the program since we cannot guaranty correct
+          // test case setup and tear-down in this case.
+          ReportInvalidTestCaseType(test_case_name,  file, line);
+          posix::Abort();
+        } else {
+          // At this point we are sure that the object we found is of the same
+          // type we are looking for, so we downcast it to that type
+          // without further checks.
+          typed_test_info = CheckedDowncastToActualType<
+              ParameterizedTestCaseInfo<TestCase> >(*it);
+        }
+        break;
+      }
+    }
+    if (typed_test_info == NULL) {
+      typed_test_info = new ParameterizedTestCaseInfo<TestCase>(test_case_name);
+      test_case_infos_.push_back(typed_test_info);
+    }
+    return typed_test_info;
+  }
+  void RegisterTests() {
+    for (TestCaseInfoContainer::iterator it = test_case_infos_.begin();
+         it != test_case_infos_.end(); ++it) {
+      (*it)->RegisterTests();
+    }
+  }
+
+ private:
+  typedef ::std::vector<ParameterizedTestCaseInfoBase*> TestCaseInfoContainer;
+
+  TestCaseInfoContainer test_case_infos_;
+
+  GTEST_DISALLOW_COPY_AND_ASSIGN_(ParameterizedTestCaseRegistry);
+};
+
+}  // namespace internal
+}  // namespace testing
+
+#endif  //  GTEST_HAS_PARAM_TEST
+
+#endif  // GTEST_INCLUDE_GTEST_INTERNAL_GTEST_PARAM_UTIL_H_
diff --git a/test/gtest/include/gtest/internal/gtest-port.h b/test/gtest/include/gtest/internal/gtest-port.h
new file mode 100644
index 0000000..bc46459
--- /dev/null
+++ b/test/gtest/include/gtest/internal/gtest-port.h
@@ -0,0 +1,1950 @@
+// Copyright 2005, Google Inc.
+// All rights reserved.
+//
+// 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.
+//
+// Authors: wan at google.com (Zhanyong Wan)
+//
+// Low-level types and utilities for porting Google Test to various
+// platforms.  They are subject to change without notice.  DO NOT USE
+// THEM IN USER CODE.
+//
+// This file is fundamental to Google Test.  All other Google Test source
+// files are expected to #include this.  Therefore, it cannot #include
+// any other Google Test header.
+
+#ifndef GTEST_INCLUDE_GTEST_INTERNAL_GTEST_PORT_H_
+#define GTEST_INCLUDE_GTEST_INTERNAL_GTEST_PORT_H_
+#ifndef _WIN32
+#pragma GCC system_header
+#endif
+
+// The user can define the following macros in the build script to
+// control Google Test's behavior.  If the user doesn't define a macro
+// in this list, Google Test will define it.
+//
+//   GTEST_HAS_CLONE          - Define it to 1/0 to indicate that clone(2)
+//                              is/isn't available.
+//   GTEST_HAS_EXCEPTIONS     - Define it to 1/0 to indicate that exceptions
+//                              are enabled.
+//   GTEST_HAS_GLOBAL_STRING  - Define it to 1/0 to indicate that ::string
+//                              is/isn't available (some systems define
+//                              ::string, which is different to std::string).
+//   GTEST_HAS_GLOBAL_WSTRING - Define it to 1/0 to indicate that ::string
+//                              is/isn't available (some systems define
+//                              ::wstring, which is different to std::wstring).
+//   GTEST_HAS_POSIX_RE       - Define it to 1/0 to indicate that POSIX regular
+//                              expressions are/aren't available.
+//   GTEST_HAS_PTHREAD        - Define it to 1/0 to indicate that <pthread.h>
+//                              is/isn't available.
+//   GTEST_HAS_RTTI           - Define it to 1/0 to indicate that RTTI is/isn't
+//                              enabled.
+//   GTEST_HAS_STD_WSTRING    - Define it to 1/0 to indicate that
+//                              std::wstring does/doesn't work (Google Test can
+//                              be used where std::wstring is unavailable).
+//   GTEST_HAS_TR1_TUPLE      - Define it to 1/0 to indicate tr1::tuple
+//                              is/isn't available.
+//   GTEST_HAS_SEH            - Define it to 1/0 to indicate whether the
+//                              compiler supports Microsoft's "Structured
+//                              Exception Handling".
+//   GTEST_HAS_STREAM_REDIRECTION
+//                            - Define it to 1/0 to indicate whether the
+//                              platform supports I/O stream redirection using
+//                              dup() and dup2().
+//   GTEST_USE_OWN_TR1_TUPLE  - Define it to 1/0 to indicate whether Google
+//                              Test's own tr1 tuple implementation should be
+//                              used.  Unused when the user sets
+//                              GTEST_HAS_TR1_TUPLE to 0.
+//   GTEST_LANG_CXX11         - Define it to 1/0 to indicate that Google Test
+//                              is building in C++11/C++98 mode.
+//   GTEST_LINKED_AS_SHARED_LIBRARY
+//                            - Define to 1 when compiling tests that use
+//                              Google Test as a shared library (known as
+//                              DLL on Windows).
+//   GTEST_CREATE_SHARED_LIBRARY
+//                            - Define to 1 when compiling Google Test itself
+//                              as a shared library.
+
+// This header defines the following utilities:
+//
+// Macros indicating the current platform (defined to 1 if compiled on
+// the given platform; otherwise undefined):
+//   GTEST_OS_AIX      - IBM AIX
+//   GTEST_OS_CYGWIN   - Cygwin
+//   GTEST_OS_HPUX     - HP-UX
+//   GTEST_OS_LINUX    - Linux
+//     GTEST_OS_LINUX_ANDROID - Google Android
+//   GTEST_OS_MAC      - Mac OS X
+//     GTEST_OS_IOS    - iOS
+//       GTEST_OS_IOS_SIMULATOR - iOS simulator
+//   GTEST_OS_NACL     - Google Native Client (NaCl)
+//   GTEST_OS_OPENBSD  - OpenBSD
+//   GTEST_OS_QNX      - QNX
+//   GTEST_OS_SOLARIS  - Sun Solaris
+//   GTEST_OS_SYMBIAN  - Symbian
+//   GTEST_OS_WINDOWS  - Windows (Desktop, MinGW, or Mobile)
+//     GTEST_OS_WINDOWS_DESKTOP  - Windows Desktop
+//     GTEST_OS_WINDOWS_MINGW    - MinGW
+//     GTEST_OS_WINDOWS_MOBILE   - Windows Mobile
+//   GTEST_OS_ZOS      - z/OS
+//
+// Among the platforms, Cygwin, Linux, Max OS X, and Windows have the
+// most stable support.  Since core members of the Google Test project
+// don't have access to other platforms, support for them may be less
+// stable.  If you notice any problems on your platform, please notify
+// googletestframework at googlegroups.com (patches for fixing them are
+// even more welcome!).
+//
+// Note that it is possible that none of the GTEST_OS_* macros are defined.
+//
+// Macros indicating available Google Test features (defined to 1 if
+// the corresponding feature is supported; otherwise undefined):
+//   GTEST_HAS_COMBINE      - the Combine() function (for value-parameterized
+//                            tests)
+//   GTEST_HAS_DEATH_TEST   - death tests
+//   GTEST_HAS_PARAM_TEST   - value-parameterized tests
+//   GTEST_HAS_TYPED_TEST   - typed tests
+//   GTEST_HAS_TYPED_TEST_P - type-parameterized tests
+//   GTEST_USES_POSIX_RE    - enhanced POSIX regex is used. Do not confuse with
+//                            GTEST_HAS_POSIX_RE (see above) which users can
+//                            define themselves.
+//   GTEST_USES_SIMPLE_RE   - our own simple regex is used;
+//                            the above two are mutually exclusive.
+//   GTEST_CAN_COMPARE_NULL - accepts untyped NULL in EXPECT_EQ().
+//
+// Macros for basic C++ coding:
+//   GTEST_AMBIGUOUS_ELSE_BLOCKER_ - for disabling a gcc warning.
+//   GTEST_ATTRIBUTE_UNUSED_  - declares that a class' instances or a
+//                              variable don't have to be used.
+//   GTEST_DISALLOW_ASSIGN_   - disables operator=.
+//   GTEST_DISALLOW_COPY_AND_ASSIGN_ - disables copy ctor and operator=.
+//   GTEST_MUST_USE_RESULT_   - declares that a function's result must be used.
+//
+// Synchronization:
+//   Mutex, MutexLock, ThreadLocal, GetThreadCount()
+//                  - synchronization primitives.
+//   GTEST_IS_THREADSAFE - defined to 1 to indicate that the above
+//                         synchronization primitives have real implementations
+//                         and Google Test is thread-safe; or 0 otherwise.
+//
+// Template meta programming:
+//   is_pointer     - as in TR1; needed on Symbian and IBM XL C/C++ only.
+//   IteratorTraits - partial implementation of std::iterator_traits, which
+//                    is not available in libCstd when compiled with Sun C++.
+//
+// Smart pointers:
+//   scoped_ptr     - as in TR2.
+//
+// Regular expressions:
+//   RE             - a simple regular expression class using the POSIX
+//                    Extended Regular Expression syntax on UNIX-like
+//                    platforms, or a reduced regular exception syntax on
+//                    other platforms, including Windows.
+//
+// Logging:
+//   GTEST_LOG_()   - logs messages at the specified severity level.
+//   LogToStderr()  - directs all log messages to stderr.
+//   FlushInfoLog() - flushes informational log messages.
+//
+// Stdout and stderr capturing:
+//   CaptureStdout()     - starts capturing stdout.
+//   GetCapturedStdout() - stops capturing stdout and returns the captured
+//                         string.
+//   CaptureStderr()     - starts capturing stderr.
+//   GetCapturedStderr() - stops capturing stderr and returns the captured
+//                         string.
+//
+// Integer types:
+//   TypeWithSize   - maps an integer to a int type.
+//   Int32, UInt32, Int64, UInt64, TimeInMillis
+//                  - integers of known sizes.
+//   BiggestInt     - the biggest signed integer type.
+//
+// Command-line utilities:
+//   GTEST_FLAG()       - references a flag.
+//   GTEST_DECLARE_*()  - declares a flag.
+//   GTEST_DEFINE_*()   - defines a flag.
+//   GetInjectableArgvs() - returns the command line as a vector of strings.
+//
+// Environment variable utilities:
+//   GetEnv()             - gets the value of an environment variable.
+//   BoolFromGTestEnv()   - parses a bool environment variable.
+//   Int32FromGTestEnv()  - parses an Int32 environment variable.
+//   StringFromGTestEnv() - parses a string environment variable.
+
+#include <ctype.h>   // for isspace, etc
+#include <stddef.h>  // for ptrdiff_t
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#ifndef _WIN32_WCE
+# include <sys/types.h>
+# include <sys/stat.h>
+#endif  // !_WIN32_WCE
+
+#if defined __APPLE__
+# include <AvailabilityMacros.h>
+# include <TargetConditionals.h>
+#endif
+
+#include <iostream>  // NOLINT
+#include <sstream>  // NOLINT
+#include <string>  // NOLINT
+
+#define GTEST_DEV_EMAIL_ "googletestframework@@googlegroups.com"
+#define GTEST_FLAG_PREFIX_ "gtest_"
+#define GTEST_FLAG_PREFIX_DASH_ "gtest-"
+#define GTEST_FLAG_PREFIX_UPPER_ "GTEST_"
+#define GTEST_NAME_ "Google Test"
+#define GTEST_PROJECT_URL_ "http://code.google.com/p/googletest/"
+
+// Determines the version of gcc that is used to compile this.
+#ifdef __GNUC__
+// 40302 means version 4.3.2.
+# define GTEST_GCC_VER_ \
+    (__GNUC__*10000 + __GNUC_MINOR__*100 + __GNUC_PATCHLEVEL__)
+#endif  // __GNUC__
+
+// Determines the platform on which Google Test is compiled.
+#ifdef __CYGWIN__
+# define GTEST_OS_CYGWIN 1
+#elif defined __SYMBIAN32__
+# define GTEST_OS_SYMBIAN 1
+#elif defined _WIN32
+# define GTEST_OS_WINDOWS 1
+# ifdef _WIN32_WCE
+#  define GTEST_OS_WINDOWS_MOBILE 1
+# elif defined(__MINGW__) || defined(__MINGW32__)
+#  define GTEST_OS_WINDOWS_MINGW 1
+# else
+#  define GTEST_OS_WINDOWS_DESKTOP 1
+# endif  // _WIN32_WCE
+#elif defined __APPLE__
+# define GTEST_OS_MAC 1
+# if TARGET_OS_IPHONE
+#  define GTEST_OS_IOS 1
+#  if TARGET_IPHONE_SIMULATOR
+#   define GTEST_OS_IOS_SIMULATOR 1
+#  endif
+# endif
+#elif defined __linux__
+# define GTEST_OS_LINUX 1
+# if defined __ANDROID__
+#  define GTEST_OS_LINUX_ANDROID 1
+# endif
+#elif defined __MVS__
+# define GTEST_OS_ZOS 1
+#elif defined(__sun) && defined(__SVR4)
+# define GTEST_OS_SOLARIS 1
+#elif defined(_AIX)
+# define GTEST_OS_AIX 1
+#elif defined(__hpux)
+# define GTEST_OS_HPUX 1
+#elif defined __native_client__
+# define GTEST_OS_NACL 1
+#elif defined __OpenBSD__
+# define GTEST_OS_OPENBSD 1
+#elif defined __QNX__
+# define GTEST_OS_QNX 1
+#endif  // __CYGWIN__
+
+#ifndef GTEST_LANG_CXX11
+// gcc and clang define __GXX_EXPERIMENTAL_CXX0X__ when
+// -std={c,gnu}++{0x,11} is passed.  The C++11 standard specifies a
+// value for __cplusplus, and recent versions of clang, gcc, and
+// probably other compilers set that too in C++11 mode.
+# if __GXX_EXPERIMENTAL_CXX0X__ || __cplusplus >= 201103L
+// Compiling in at least C++11 mode.
+#  define GTEST_LANG_CXX11 1
+# else
+#  define GTEST_LANG_CXX11 0
+# endif
+#endif
+
+// Brings in definitions for functions used in the testing::internal::posix
+// namespace (read, write, close, chdir, isatty, stat). We do not currently
+// use them on Windows Mobile.
+#if !GTEST_OS_WINDOWS
+// This assumes that non-Windows OSes provide unistd.h. For OSes where this
+// is not the case, we need to include headers that provide the functions
+// mentioned above.
+# include <unistd.h>
+# include <strings.h>
+#elif !GTEST_OS_WINDOWS_MOBILE
+# include <direct.h>
+# include <io.h>
+#endif
+
+#if GTEST_OS_LINUX_ANDROID
+// Used to define __ANDROID_API__ matching the target NDK API level.
+#  include <android/api-level.h>  // NOLINT
+#endif
+
+// Defines this to true iff Google Test can use POSIX regular expressions.
+#ifndef GTEST_HAS_POSIX_RE
+# if GTEST_OS_LINUX_ANDROID
+// On Android, <regex.h> is only available starting with Gingerbread.
+#  define GTEST_HAS_POSIX_RE (__ANDROID_API__ >= 9)
+# else
+#  define GTEST_HAS_POSIX_RE (!GTEST_OS_WINDOWS)
+# endif
+#endif
+
+#if GTEST_HAS_POSIX_RE
+
+// On some platforms, <regex.h> needs someone to define size_t, and
+// won't compile otherwise.  We can #include it here as we already
+// included <stdlib.h>, which is guaranteed to define size_t through
+// <stddef.h>.
+# include <regex.h>  // NOLINT
+
+# define GTEST_USES_POSIX_RE 1
+
+#elif GTEST_OS_WINDOWS
+
+// <regex.h> is not available on Windows.  Use our own simple regex
+// implementation instead.
+# define GTEST_USES_SIMPLE_RE 1
+
+#else
+
+// <regex.h> may not be available on this platform.  Use our own
+// simple regex implementation instead.
+# define GTEST_USES_SIMPLE_RE 1
+
+#endif  // GTEST_HAS_POSIX_RE
+
+#ifndef GTEST_HAS_EXCEPTIONS
+// The user didn't tell us whether exceptions are enabled, so we need
+// to figure it out.
+# if defined(_MSC_VER) || defined(__BORLANDC__)
+// MSVC's and C++Builder's implementations of the STL use the _HAS_EXCEPTIONS
+// macro to enable exceptions, so we'll do the same.
+// Assumes that exceptions are enabled by default.
+#  ifndef _HAS_EXCEPTIONS
+#   define _HAS_EXCEPTIONS 1
+#  endif  // _HAS_EXCEPTIONS
+#  define GTEST_HAS_EXCEPTIONS _HAS_EXCEPTIONS
+# elif defined(__GNUC__) && __EXCEPTIONS
+// gcc defines __EXCEPTIONS to 1 iff exceptions are enabled.
+#  define GTEST_HAS_EXCEPTIONS 1
+# elif defined(__SUNPRO_CC)
+// Sun Pro CC supports exceptions.  However, there is no compile-time way of
+// detecting whether they are enabled or not.  Therefore, we assume that
+// they are enabled unless the user tells us otherwise.
+#  define GTEST_HAS_EXCEPTIONS 1
+# elif defined(__IBMCPP__) && __EXCEPTIONS
+// xlC defines __EXCEPTIONS to 1 iff exceptions are enabled.
+#  define GTEST_HAS_EXCEPTIONS 1
+# elif defined(__HP_aCC)
+// Exception handling is in effect by default in HP aCC compiler. It has to
+// be turned of by +noeh compiler option if desired.
+#  define GTEST_HAS_EXCEPTIONS 1
+# else
+// For other compilers, we assume exceptions are disabled to be
+// conservative.
+#  define GTEST_HAS_EXCEPTIONS 0
+# endif  // defined(_MSC_VER) || defined(__BORLANDC__)
+#endif  // GTEST_HAS_EXCEPTIONS
+
+#if !defined(GTEST_HAS_STD_STRING)
+// Even though we don't use this macro any longer, we keep it in case
+// some clients still depend on it.
+# define GTEST_HAS_STD_STRING 1
+#elif !GTEST_HAS_STD_STRING
+// The user told us that ::std::string isn't available.
+# error "Google Test cannot be used where ::std::string isn't available."
+#endif  // !defined(GTEST_HAS_STD_STRING)
+
+#ifndef GTEST_HAS_GLOBAL_STRING
+// The user didn't tell us whether ::string is available, so we need
+// to figure it out.
+
+# define GTEST_HAS_GLOBAL_STRING 0
+
+#endif  // GTEST_HAS_GLOBAL_STRING
+
+#ifndef GTEST_HAS_STD_WSTRING
+// The user didn't tell us whether ::std::wstring is available, so we need
+// to figure it out.
+// TODO(wan at google.com): uses autoconf to detect whether ::std::wstring
+//   is available.
+
+// Cygwin 1.7 and below doesn't support ::std::wstring.
+// Solaris' libc++ doesn't support it either.  Android has
+// no support for it at least as recent as Froyo (2.2).
+# define GTEST_HAS_STD_WSTRING \
+    (!(GTEST_OS_LINUX_ANDROID || GTEST_OS_CYGWIN || GTEST_OS_SOLARIS))
+
+#endif  // GTEST_HAS_STD_WSTRING
+
+#ifndef GTEST_HAS_GLOBAL_WSTRING
+// The user didn't tell us whether ::wstring is available, so we need
+// to figure it out.
+# define GTEST_HAS_GLOBAL_WSTRING \
+    (GTEST_HAS_STD_WSTRING && GTEST_HAS_GLOBAL_STRING)
+#endif  // GTEST_HAS_GLOBAL_WSTRING
+
+// Determines whether RTTI is available.
+#ifndef GTEST_HAS_RTTI
+// The user didn't tell us whether RTTI is enabled, so we need to
+// figure it out.
+
+# ifdef _MSC_VER
+
+#  ifdef _CPPRTTI  // MSVC defines this macro iff RTTI is enabled.
+#   define GTEST_HAS_RTTI 1
+#  else
+#   define GTEST_HAS_RTTI 0
+#  endif
+
+// Starting with version 4.3.2, gcc defines __GXX_RTTI iff RTTI is enabled.
+# elif defined(__GNUC__) && (GTEST_GCC_VER_ >= 40302)
+
+#  ifdef __GXX_RTTI
+// When building against STLport with the Android NDK and with
+// -frtti -fno-exceptions, the build fails at link time with undefined
+// references to __cxa_bad_typeid. Note sure if STL or toolchain bug,
+// so disable RTTI when detected.
+#   if GTEST_OS_LINUX_ANDROID && defined(_STLPORT_MAJOR) && \
+       !defined(__EXCEPTIONS)
+#    define GTEST_HAS_RTTI 0
+#   else
+#    define GTEST_HAS_RTTI 1
+#   endif  // GTEST_OS_LINUX_ANDROID && __STLPORT_MAJOR && !__EXCEPTIONS
+#  else
+#   define GTEST_HAS_RTTI 0
+#  endif  // __GXX_RTTI
+
+// Clang defines __GXX_RTTI starting with version 3.0, but its manual recommends
+// using has_feature instead. has_feature(cxx_rtti) is supported since 2.7, the
+// first version with C++ support.
+# elif defined(__clang__)
+
+#  define GTEST_HAS_RTTI __has_feature(cxx_rtti)
+
+// Starting with version 9.0 IBM Visual Age defines __RTTI_ALL__ to 1 if
+// both the typeid and dynamic_cast features are present.
+# elif defined(__IBMCPP__) && (__IBMCPP__ >= 900)
+
+#  ifdef __RTTI_ALL__
+#   define GTEST_HAS_RTTI 1
+#  else
+#   define GTEST_HAS_RTTI 0
+#  endif
+
+# else
+
+// For all other compilers, we assume RTTI is enabled.
+#  define GTEST_HAS_RTTI 1
+
+# endif  // _MSC_VER
+
+#endif  // GTEST_HAS_RTTI
+
+// It's this header's responsibility to #include <typeinfo> when RTTI
+// is enabled.
+#if GTEST_HAS_RTTI
+# include <typeinfo>
+#endif
+
+// Determines whether Google Test can use the pthreads library.
+#ifndef GTEST_HAS_PTHREAD
+// The user didn't tell us explicitly, so we assume pthreads support is
+// available on Linux and Mac.
+//
+// To disable threading support in Google Test, add -DGTEST_HAS_PTHREAD=0
+// to your compiler flags.
+# define GTEST_HAS_PTHREAD (GTEST_OS_LINUX || GTEST_OS_MAC || GTEST_OS_HPUX \
+    || GTEST_OS_QNX)
+#endif  // GTEST_HAS_PTHREAD
+
+#if GTEST_HAS_PTHREAD
+// gtest-port.h guarantees to #include <pthread.h> when GTEST_HAS_PTHREAD is
+// true.
+# include <pthread.h>  // NOLINT
+
+// For timespec and nanosleep, used below.
+# include <time.h>  // NOLINT
+#endif
+
+// Determines whether Google Test can use tr1/tuple.  You can define
+// this macro to 0 to prevent Google Test from using tuple (any
+// feature depending on tuple with be disabled in this mode).
+#ifndef GTEST_HAS_TR1_TUPLE
+# if GTEST_OS_LINUX_ANDROID && defined(_STLPORT_MAJOR)
+// STLport, provided with the Android NDK, has neither <tr1/tuple> or <tuple>.
+#  define GTEST_HAS_TR1_TUPLE 0
+# else
+// The user didn't tell us not to do it, so we assume it's OK.
+#  define GTEST_HAS_TR1_TUPLE 1
+# endif
+#endif  // GTEST_HAS_TR1_TUPLE
+
+// Determines whether Google Test's own tr1 tuple implementation
+// should be used.
+#ifndef GTEST_USE_OWN_TR1_TUPLE
+// The user didn't tell us, so we need to figure it out.
+
+// We use our own TR1 tuple if we aren't sure the user has an
+// implementation of it already.  At this time, libstdc++ 4.0.0+ and
+// MSVC 2010 are the only mainstream standard libraries that come
+// with a TR1 tuple implementation.  NVIDIA's CUDA NVCC compiler
+// pretends to be GCC by defining __GNUC__ and friends, but cannot
+// compile GCC's tuple implementation.  MSVC 2008 (9.0) provides TR1
+// tuple in a 323 MB Feature Pack download, which we cannot assume the
+// user has.  QNX's QCC compiler is a modified GCC but it doesn't
+// support TR1 tuple.  libc++ only provides std::tuple, in C++11 mode,
+// and it can be used with some compilers that define __GNUC__.
+# if (defined(__GNUC__) && !defined(__CUDACC__) && (GTEST_GCC_VER_ >= 40000) \
+      && !GTEST_OS_QNX && !defined(_LIBCPP_VERSION)) || _MSC_VER >= 1600
+#  define GTEST_ENV_HAS_TR1_TUPLE_ 1
+# endif
+
+// C++11 specifies that <tuple> provides std::tuple. Use that if gtest is used
+// in C++11 mode and libstdc++ isn't very old (binaries targeting OS X 10.6
+// can build with clang but need to use gcc4.2's libstdc++).
+# if GTEST_LANG_CXX11 && (!defined(__GLIBCXX__) || __GLIBCXX__ > 20110325)
+#  define GTEST_ENV_HAS_STD_TUPLE_ 1
+# endif
+
+# if GTEST_ENV_HAS_TR1_TUPLE_ || GTEST_ENV_HAS_STD_TUPLE_
+#  define GTEST_USE_OWN_TR1_TUPLE 0
+# else
+#  define GTEST_USE_OWN_TR1_TUPLE 1
+# endif
+
+#endif  // GTEST_USE_OWN_TR1_TUPLE
+
+// To avoid conditional compilation everywhere, we make it
+// gtest-port.h's responsibility to #include the header implementing
+// tr1/tuple.
+#if GTEST_HAS_TR1_TUPLE
+
+# if GTEST_USE_OWN_TR1_TUPLE
+#  include "gtest/internal/gtest-tuple.h"
+# elif GTEST_ENV_HAS_STD_TUPLE_
+#  include <tuple>
+// C++11 puts its tuple into the ::std namespace rather than
+// ::std::tr1.  gtest expects tuple to live in ::std::tr1, so put it there.
+// This causes undefined behavior, but supported compilers react in
+// the way we intend.
+namespace std {
+namespace tr1 {
+using ::std::get;
+using ::std::make_tuple;
+using ::std::tuple;
+using ::std::tuple_element;
+using ::std::tuple_size;
+}
+}
+
+# elif GTEST_OS_SYMBIAN
+
+// On Symbian, BOOST_HAS_TR1_TUPLE causes Boost's TR1 tuple library to
+// use STLport's tuple implementation, which unfortunately doesn't
+// work as the copy of STLport distributed with Symbian is incomplete.
+// By making sure BOOST_HAS_TR1_TUPLE is undefined, we force Boost to
+// use its own tuple implementation.
+#  ifdef BOOST_HAS_TR1_TUPLE
+#   undef BOOST_HAS_TR1_TUPLE
+#  endif  // BOOST_HAS_TR1_TUPLE
+
+// This prevents <boost/tr1/detail/config.hpp>, which defines
+// BOOST_HAS_TR1_TUPLE, from being #included by Boost's <tuple>.
+#  define BOOST_TR1_DETAIL_CONFIG_HPP_INCLUDED
+#  include <tuple>
+
+# elif defined(__GNUC__) && (GTEST_GCC_VER_ >= 40000)
+// GCC 4.0+ implements tr1/tuple in the <tr1/tuple> header.  This does
+// not conform to the TR1 spec, which requires the header to be <tuple>.
+
+#  if !GTEST_HAS_RTTI && GTEST_GCC_VER_ < 40302
+// Until version 4.3.2, gcc has a bug that causes <tr1/functional>,
+// which is #included by <tr1/tuple>, to not compile when RTTI is
+// disabled.  _TR1_FUNCTIONAL is the header guard for
+// <tr1/functional>.  Hence the following #define is a hack to prevent
+// <tr1/functional> from being included.
+#   define _TR1_FUNCTIONAL 1
+#   include <tr1/tuple>
+#   undef _TR1_FUNCTIONAL  // Allows the user to #include
+                        // <tr1/functional> if he chooses to.
+#  else
+#   include <tr1/tuple>  // NOLINT
+#  endif  // !GTEST_HAS_RTTI && GTEST_GCC_VER_ < 40302
+
+# else
+// If the compiler is not GCC 4.0+, we assume the user is using a
+// spec-conforming TR1 implementation.
+#  include <tuple>  // NOLINT
+# endif  // GTEST_USE_OWN_TR1_TUPLE
+
+#endif  // GTEST_HAS_TR1_TUPLE
+
+// Determines whether clone(2) is supported.
+// Usually it will only be available on Linux, excluding
+// Linux on the Itanium architecture.
+// Also see http://linux.die.net/man/2/clone.
+#ifndef GTEST_HAS_CLONE
+// The user didn't tell us, so we need to figure it out.
+
+# if GTEST_OS_LINUX && !defined(__ia64__)
+#  if GTEST_OS_LINUX_ANDROID
+// On Android, clone() is only available on ARM starting with Gingerbread.
+#    if defined(__arm__) && __ANDROID_API__ >= 9
+#     define GTEST_HAS_CLONE 1
+#    else
+#     define GTEST_HAS_CLONE 0
+#    endif
+#  else
+#   define GTEST_HAS_CLONE 1
+#  endif
+# else
+#  define GTEST_HAS_CLONE 0
+# endif  // GTEST_OS_LINUX && !defined(__ia64__)
+
+#endif  // GTEST_HAS_CLONE
+
+// Determines whether to support stream redirection. This is used to test
+// output correctness and to implement death tests.
+#ifndef GTEST_HAS_STREAM_REDIRECTION
+// By default, we assume that stream redirection is supported on all
+// platforms except known mobile ones.
+# if GTEST_OS_WINDOWS_MOBILE || GTEST_OS_SYMBIAN
+#  define GTEST_HAS_STREAM_REDIRECTION 0
+# else
+#  define GTEST_HAS_STREAM_REDIRECTION 1
+# endif  // !GTEST_OS_WINDOWS_MOBILE && !GTEST_OS_SYMBIAN
+#endif  // GTEST_HAS_STREAM_REDIRECTION
+
+// Determines whether to support death tests.
+// Google Test does not support death tests for VC 7.1 and earlier as
+// abort() in a VC 7.1 application compiled as GUI in debug config
+// pops up a dialog window that cannot be suppressed programmatically.
+#if (GTEST_OS_LINUX || GTEST_OS_CYGWIN || GTEST_OS_SOLARIS || \
+     (GTEST_OS_MAC && !GTEST_OS_IOS) || GTEST_OS_IOS_SIMULATOR || \
+     (GTEST_OS_WINDOWS_DESKTOP && _MSC_VER >= 1400) || \
+     GTEST_OS_WINDOWS_MINGW || GTEST_OS_AIX || GTEST_OS_HPUX || \
+     GTEST_OS_OPENBSD || GTEST_OS_QNX)
+# define GTEST_HAS_DEATH_TEST 1
+# include <vector>  // NOLINT
+#endif
+
+// We don't support MSVC 7.1 with exceptions disabled now.  Therefore
+// all the compilers we care about are adequate for supporting
+// value-parameterized tests.
+#define GTEST_HAS_PARAM_TEST 1
+
+// Determines whether to support type-driven tests.
+
+// Typed tests need <typeinfo> and variadic macros, which GCC, VC++ 8.0,
+// Sun Pro CC, IBM Visual Age, and HP aCC support.
+#if defined(__GNUC__) || (_MSC_VER >= 1400) || defined(__SUNPRO_CC) || \
+    defined(__IBMCPP__) || defined(__HP_aCC)
+# define GTEST_HAS_TYPED_TEST 1
+# define GTEST_HAS_TYPED_TEST_P 1
+#endif
+
+// Determines whether to support Combine(). This only makes sense when
+// value-parameterized tests are enabled.  The implementation doesn't
+// work on Sun Studio since it doesn't understand templated conversion
+// operators.
+#if GTEST_HAS_PARAM_TEST && GTEST_HAS_TR1_TUPLE && !defined(__SUNPRO_CC)
+# define GTEST_HAS_COMBINE 1
+#endif
+
+// Determines whether the system compiler uses UTF-16 for encoding wide strings.
+#define GTEST_WIDE_STRING_USES_UTF16_ \
+    (GTEST_OS_WINDOWS || GTEST_OS_CYGWIN || GTEST_OS_SYMBIAN || GTEST_OS_AIX)
+
+// Determines whether test results can be streamed to a socket.
+#if GTEST_OS_LINUX
+# define GTEST_CAN_STREAM_RESULTS_ 1
+#endif
+
+// Defines some utility macros.
+
+// The GNU compiler emits a warning if nested "if" statements are followed by
+// an "else" statement and braces are not used to explicitly disambiguate the
+// "else" binding.  This leads to problems with code like:
+//
+//   if (gate)
+//     ASSERT_*(condition) << "Some message";
+//
+// The "switch (0) case 0:" idiom is used to suppress this.
+#ifdef __INTEL_COMPILER
+# define GTEST_AMBIGUOUS_ELSE_BLOCKER_
+#else
+# define GTEST_AMBIGUOUS_ELSE_BLOCKER_ switch (0) case 0: default:  // NOLINT
+#endif
+
+// Use this annotation at the end of a struct/class definition to
+// prevent the compiler from optimizing away instances that are never
+// used.  This is useful when all interesting logic happens inside the
+// c'tor and / or d'tor.  Example:
+//
+//   struct Foo {
+//     Foo() { ... }
+//   } GTEST_ATTRIBUTE_UNUSED_;
+//
+// Also use it after a variable or parameter declaration to tell the
+// compiler the variable/parameter does not have to be used.
+#if defined(__GNUC__) && !defined(COMPILER_ICC)
+# define GTEST_ATTRIBUTE_UNUSED_ __attribute__ ((unused))
+#else
+# define GTEST_ATTRIBUTE_UNUSED_
+#endif
+
+// A macro to disallow operator=
+// This should be used in the private: declarations for a class.
+#define GTEST_DISALLOW_ASSIGN_(type)\
+  void operator=(type const &)
+
+// A macro to disallow copy constructor and operator=
+// This should be used in the private: declarations for a class.
+#define GTEST_DISALLOW_COPY_AND_ASSIGN_(type)\
+  type(type const &);\
+  GTEST_DISALLOW_ASSIGN_(type)
+
+// Tell the compiler to warn about unused return values for functions declared
+// with this macro.  The macro should be used on function declarations
+// following the argument list:
+//
+//   Sprocket* AllocateSprocket() GTEST_MUST_USE_RESULT_;
+#if defined(__GNUC__) && (GTEST_GCC_VER_ >= 30400) && !defined(COMPILER_ICC)
+# define GTEST_MUST_USE_RESULT_ __attribute__ ((warn_unused_result))
+#else
+# define GTEST_MUST_USE_RESULT_
+#endif  // __GNUC__ && (GTEST_GCC_VER_ >= 30400) && !COMPILER_ICC
+
+// Determine whether the compiler supports Microsoft's Structured Exception
+// Handling.  This is supported by several Windows compilers but generally
+// does not exist on any other system.
+#ifndef GTEST_HAS_SEH
+// The user didn't tell us, so we need to figure it out.
+
+# if defined(_MSC_VER) || defined(__BORLANDC__)
+// These two compilers are known to support SEH.
+#  define GTEST_HAS_SEH 1
+# else
+// Assume no SEH.
+#  define GTEST_HAS_SEH 0
+# endif
+
+#endif  // GTEST_HAS_SEH
+
+#ifdef _MSC_VER
+
+# if GTEST_LINKED_AS_SHARED_LIBRARY
+#  define GTEST_API_ __declspec(dllimport)
+# elif GTEST_CREATE_SHARED_LIBRARY
+#  define GTEST_API_ __declspec(dllexport)
+# endif
+
+#endif  // _MSC_VER
+
+#ifndef GTEST_API_
+# define GTEST_API_
+#endif
+
+#ifdef __GNUC__
+// Ask the compiler to never inline a given function.
+# define GTEST_NO_INLINE_ __attribute__((noinline))
+#else
+# define GTEST_NO_INLINE_
+#endif
+
+// _LIBCPP_VERSION is defined by the libc++ library from the LLVM project.
+#if defined(__GLIBCXX__) || defined(_LIBCPP_VERSION)
+# define GTEST_HAS_CXXABI_H_ 1
+#else
+# define GTEST_HAS_CXXABI_H_ 0
+#endif
+
+namespace testing {
+
+class Message;
+
+namespace internal {
+
+// A secret type that Google Test users don't know about.  It has no
+// definition on purpose.  Therefore it's impossible to create a
+// Secret object, which is what we want.
+class Secret;
+
+// The GTEST_COMPILE_ASSERT_ macro can be used to verify that a compile time
+// expression is true. For example, you could use it to verify the
+// size of a static array:
+//
+//   GTEST_COMPILE_ASSERT_(ARRAYSIZE(content_type_names) == CONTENT_NUM_TYPES,
+//                         content_type_names_incorrect_size);
+//
+// or to make sure a struct is smaller than a certain size:
+//
+//   GTEST_COMPILE_ASSERT_(sizeof(foo) < 128, foo_too_large);
+//
+// The second argument to the macro is the name of the variable. If
+// the expression is false, most compilers will issue a warning/error
+// containing the name of the variable.
+
+template <bool>
+struct CompileAssert {
+};
+
+#define GTEST_COMPILE_ASSERT_(expr, msg) \
+  typedef ::testing::internal::CompileAssert<(static_cast<bool>(expr))> \
+      msg[static_cast<bool>(expr) ? 1 : -1] GTEST_ATTRIBUTE_UNUSED_
+
+// Implementation details of GTEST_COMPILE_ASSERT_:
+//
+// - GTEST_COMPILE_ASSERT_ works by defining an array type that has -1
+//   elements (and thus is invalid) when the expression is false.
+//
+// - The simpler definition
+//
+//    #define GTEST_COMPILE_ASSERT_(expr, msg) typedef char msg[(expr) ? 1 : -1]
+//
+//   does not work, as gcc supports variable-length arrays whose sizes
+//   are determined at run-time (this is gcc's extension and not part
+//   of the C++ standard).  As a result, gcc fails to reject the
+//   following code with the simple definition:
+//
+//     int foo;
+//     GTEST_COMPILE_ASSERT_(foo, msg); // not supposed to compile as foo is
+//                                      // not a compile-time constant.
+//
+// - By using the type CompileAssert<(bool(expr))>, we ensures that
+//   expr is a compile-time constant.  (Template arguments must be
+//   determined at compile-time.)
+//
+// - The outter parentheses in CompileAssert<(bool(expr))> are necessary
+//   to work around a bug in gcc 3.4.4 and 4.0.1.  If we had written
+//
+//     CompileAssert<bool(expr)>
+//
+//   instead, these compilers will refuse to compile
+//
+//     GTEST_COMPILE_ASSERT_(5 > 0, some_message);
+//
+//   (They seem to think the ">" in "5 > 0" marks the end of the
+//   template argument list.)
+//
+// - The array size is (bool(expr) ? 1 : -1), instead of simply
+//
+//     ((expr) ? 1 : -1).
+//
+//   This is to avoid running into a bug in MS VC 7.1, which
+//   causes ((0.0) ? 1 : -1) to incorrectly evaluate to 1.
+
+// StaticAssertTypeEqHelper is used by StaticAssertTypeEq defined in gtest.h.
+//
+// This template is declared, but intentionally undefined.
+template <typename T1, typename T2>
+struct StaticAssertTypeEqHelper;
+
+template <typename T>
+struct StaticAssertTypeEqHelper<T, T> {};
+
+#if GTEST_HAS_GLOBAL_STRING
+typedef ::string string;
+#else
+typedef ::std::string string;
+#endif  // GTEST_HAS_GLOBAL_STRING
+
+#if GTEST_HAS_GLOBAL_WSTRING
+typedef ::wstring wstring;
+#elif GTEST_HAS_STD_WSTRING
+typedef ::std::wstring wstring;
+#endif  // GTEST_HAS_GLOBAL_WSTRING
+
+// A helper for suppressing warnings on constant condition.  It just
+// returns 'condition'.
+GTEST_API_ bool IsTrue(bool condition);
+
+// Defines scoped_ptr.
+
+// This implementation of scoped_ptr is PARTIAL - it only contains
+// enough stuff to satisfy Google Test's need.
+template <typename T>
+class scoped_ptr {
+ public:
+  typedef T element_type;
+
+  explicit scoped_ptr(T* p = NULL) : ptr_(p) {}
+  ~scoped_ptr() { reset(); }
+
+  T& operator*() const { return *ptr_; }
+  T* operator->() const { return ptr_; }
+  T* get() const { return ptr_; }
+
+  T* release() {
+    T* const ptr = ptr_;
+    ptr_ = NULL;
+    return ptr;
+  }
+
+  void reset(T* p = NULL) {
+    if (p != ptr_) {
+      if (IsTrue(sizeof(T) > 0)) {  // Makes sure T is a complete type.
+        delete ptr_;
+      }
+      ptr_ = p;
+    }
+  }
+
+ private:
+  T* ptr_;
+
+  GTEST_DISALLOW_COPY_AND_ASSIGN_(scoped_ptr);
+};
+
+// Defines RE.
+
+// A simple C++ wrapper for <regex.h>.  It uses the POSIX Extended
+// Regular Expression syntax.
+class GTEST_API_ RE {
+ public:
+  // A copy constructor is required by the Standard to initialize object
+  // references from r-values.
+  RE(const RE& other) { Init(other.pattern()); }
+
+  // Constructs an RE from a string.
+  RE(const ::std::string& regex) { Init(regex.c_str()); }  // NOLINT
+
+#if GTEST_HAS_GLOBAL_STRING
+
+  RE(const ::string& regex) { Init(regex.c_str()); }  // NOLINT
+
+#endif  // GTEST_HAS_GLOBAL_STRING
+
+  RE(const char* regex) { Init(regex); }  // NOLINT
+  ~RE();
+
+  // Returns the string representation of the regex.
+  const char* pattern() const { return pattern_; }
+
+  // FullMatch(str, re) returns true iff regular expression re matches
+  // the entire str.
+  // PartialMatch(str, re) returns true iff regular expression re
+  // matches a substring of str (including str itself).
+  //
+  // TODO(wan at google.com): make FullMatch() and PartialMatch() work
+  // when str contains NUL characters.
+  static bool FullMatch(const ::std::string& str, const RE& re) {
+    return FullMatch(str.c_str(), re);
+  }
+  static bool PartialMatch(const ::std::string& str, const RE& re) {
+    return PartialMatch(str.c_str(), re);
+  }
+
+#if GTEST_HAS_GLOBAL_STRING
+
+  static bool FullMatch(const ::string& str, const RE& re) {
+    return FullMatch(str.c_str(), re);
+  }
+  static bool PartialMatch(const ::string& str, const RE& re) {
+    return PartialMatch(str.c_str(), re);
+  }
+
+#endif  // GTEST_HAS_GLOBAL_STRING
+
+  static bool FullMatch(const char* str, const RE& re);
+  static bool PartialMatch(const char* str, const RE& re);
+
+ private:
+  void Init(const char* regex);
+
+  // We use a const char* instead of an std::string, as Google Test used to be
+  // used where std::string is not available.  TODO(wan at google.com): change to
+  // std::string.
+  const char* pattern_;
+  bool is_valid_;
+
+#if GTEST_USES_POSIX_RE
+
+  regex_t full_regex_;     // For FullMatch().
+  regex_t partial_regex_;  // For PartialMatch().
+
+#else  // GTEST_USES_SIMPLE_RE
+
+  const char* full_pattern_;  // For FullMatch();
+
+#endif
+
+  GTEST_DISALLOW_ASSIGN_(RE);
+};
+
+// Formats a source file path and a line number as they would appear
+// in an error message from the compiler used to compile this code.
+GTEST_API_ ::std::string FormatFileLocation(const char* file, int line);
+
+// Formats a file location for compiler-independent XML output.
+// Although this function is not platform dependent, we put it next to
+// FormatFileLocation in order to contrast the two functions.
+GTEST_API_ ::std::string FormatCompilerIndependentFileLocation(const char* file,
+                                                               int line);
+
+// Defines logging utilities:
+//   GTEST_LOG_(severity) - logs messages at the specified severity level. The
+//                          message itself is streamed into the macro.
+//   LogToStderr()  - directs all log messages to stderr.
+//   FlushInfoLog() - flushes informational log messages.
+
+enum GTestLogSeverity {
+  GTEST_INFO,
+  GTEST_WARNING,
+  GTEST_ERROR,
+  GTEST_FATAL
+};
+
+// Formats log entry severity, provides a stream object for streaming the
+// log message, and terminates the message with a newline when going out of
+// scope.
+class GTEST_API_ GTestLog {
+ public:
+  GTestLog(GTestLogSeverity severity, const char* file, int line);
+
+  // Flushes the buffers and, if severity is GTEST_FATAL, aborts the program.
+  ~GTestLog();
+
+  ::std::ostream& GetStream() { return ::std::cerr; }
+
+ private:
+  const GTestLogSeverity severity_;
+
+  GTEST_DISALLOW_COPY_AND_ASSIGN_(GTestLog);
+};
+
+#define GTEST_LOG_(severity) \
+    ::testing::internal::GTestLog(::testing::internal::GTEST_##severity, \
+                                  __FILE__, __LINE__).GetStream()
+
+inline void LogToStderr() {}
+inline void FlushInfoLog() { fflush(NULL); }
+
+// INTERNAL IMPLEMENTATION - DO NOT USE.
+//
+// GTEST_CHECK_ is an all-mode assert. It aborts the program if the condition
+// is not satisfied.
+//  Synopsys:
+//    GTEST_CHECK_(boolean_condition);
+//     or
+//    GTEST_CHECK_(boolean_condition) << "Additional message";
+//
+//    This checks the condition and if the condition is not satisfied
+//    it prints message about the condition violation, including the
+//    condition itself, plus additional message streamed into it, if any,
+//    and then it aborts the program. It aborts the program irrespective of
+//    whether it is built in the debug mode or not.
+#define GTEST_CHECK_(condition) \
+    GTEST_AMBIGUOUS_ELSE_BLOCKER_ \
+    if (::testing::internal::IsTrue(condition)) \
+      ; \
+    else \
+      GTEST_LOG_(FATAL) << "Condition " #condition " failed. "
+
+// An all-mode assert to verify that the given POSIX-style function
+// call returns 0 (indicating success).  Known limitation: this
+// doesn't expand to a balanced 'if' statement, so enclose the macro
+// in {} if you need to use it as the only statement in an 'if'
+// branch.
+#define GTEST_CHECK_POSIX_SUCCESS_(posix_call) \
+  if (const int gtest_error = (posix_call)) \
+    GTEST_LOG_(FATAL) << #posix_call << "failed with error " \
+                      << gtest_error
+
+// INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE.
+//
+// Use ImplicitCast_ as a safe version of static_cast for upcasting in
+// the type hierarchy (e.g. casting a Foo* to a SuperclassOfFoo* or a
+// const Foo*).  When you use ImplicitCast_, the compiler checks that
+// the cast is safe.  Such explicit ImplicitCast_s are necessary in
+// surprisingly many situations where C++ demands an exact type match
+// instead of an argument type convertable to a target type.
+//
+// The syntax for using ImplicitCast_ is the same as for static_cast:
+//
+//   ImplicitCast_<ToType>(expr)
+//
+// ImplicitCast_ would have been part of the C++ standard library,
+// but the proposal was submitted too late.  It will probably make
+// its way into the language in the future.
+//
+// This relatively ugly name is intentional. It prevents clashes with
+// similar functions users may have (e.g., implicit_cast). The internal
+// namespace alone is not enough because the function can be found by ADL.
+template<typename To>
+inline To ImplicitCast_(To x) { return x; }
+
+// When you upcast (that is, cast a pointer from type Foo to type
+// SuperclassOfFoo), it's fine to use ImplicitCast_<>, since upcasts
+// always succeed.  When you downcast (that is, cast a pointer from
+// type Foo to type SubclassOfFoo), static_cast<> isn't safe, because
+// how do you know the pointer is really of type SubclassOfFoo?  It
+// could be a bare Foo, or of type DifferentSubclassOfFoo.  Thus,
+// when you downcast, you should use this macro.  In debug mode, we
+// use dynamic_cast<> to double-check the downcast is legal (we die
+// if it's not).  In normal mode, we do the efficient static_cast<>
+// instead.  Thus, it's important to test in debug mode to make sure
+// the cast is legal!
+//    This is the only place in the code we should use dynamic_cast<>.
+// In particular, you SHOULDN'T be using dynamic_cast<> in order to
+// do RTTI (eg code like this:
+//    if (dynamic_cast<Subclass1>(foo)) HandleASubclass1Object(foo);
+//    if (dynamic_cast<Subclass2>(foo)) HandleASubclass2Object(foo);
+// You should design the code some other way not to need this.
+//
+// This relatively ugly name is intentional. It prevents clashes with
+// similar functions users may have (e.g., down_cast). The internal
+// namespace alone is not enough because the function can be found by ADL.
+template<typename To, typename From>  // use like this: DownCast_<T*>(foo);
+inline To DownCast_(From* f) {  // so we only accept pointers
+  // Ensures that To is a sub-type of From *.  This test is here only
+  // for compile-time type checking, and has no overhead in an
+  // optimized build at run-time, as it will be optimized away
+  // completely.
+  if (false) {
+    const To to = NULL;
+    ::testing::internal::ImplicitCast_<From*>(to);
+  }
+
+#if GTEST_HAS_RTTI
+  // RTTI: debug mode only!
+  GTEST_CHECK_(f == NULL || dynamic_cast<To>(f) != NULL);
+#endif
+  return static_cast<To>(f);
+}
+
+// Downcasts the pointer of type Base to Derived.
+// Derived must be a subclass of Base. The parameter MUST
+// point to a class of type Derived, not any subclass of it.
+// When RTTI is available, the function performs a runtime
+// check to enforce this.
+template <class Derived, class Base>
+Derived* CheckedDowncastToActualType(Base* base) {
+#if GTEST_HAS_RTTI
+  GTEST_CHECK_(typeid(*base) == typeid(Derived));
+  return dynamic_cast<Derived*>(base);  // NOLINT
+#else
+  return static_cast<Derived*>(base);  // Poor man's downcast.
+#endif
+}
+
+#if GTEST_HAS_STREAM_REDIRECTION
+
+// Defines the stderr capturer:
+//   CaptureStdout     - starts capturing stdout.
+//   GetCapturedStdout - stops capturing stdout and returns the captured string.
+//   CaptureStderr     - starts capturing stderr.
+//   GetCapturedStderr - stops capturing stderr and returns the captured string.
+//
+GTEST_API_ void CaptureStdout();
+GTEST_API_ std::string GetCapturedStdout();
+GTEST_API_ void CaptureStderr();
+GTEST_API_ std::string GetCapturedStderr();
+
+#endif  // GTEST_HAS_STREAM_REDIRECTION
+
+
+#if GTEST_HAS_DEATH_TEST
+
+const ::std::vector<testing::internal::string>& GetInjectableArgvs();
+void SetInjectableArgvs(const ::std::vector<testing::internal::string>*
+                             new_argvs);
+
+// A copy of all command line arguments.  Set by InitGoogleTest().
+extern ::std::vector<testing::internal::string> g_argvs;
+
+#endif  // GTEST_HAS_DEATH_TEST
+
+// Defines synchronization primitives.
+
+#if GTEST_HAS_PTHREAD
+
+// Sleeps for (roughly) n milli-seconds.  This function is only for
+// testing Google Test's own constructs.  Don't use it in user tests,
+// either directly or indirectly.
+inline void SleepMilliseconds(int n) {
+  const timespec time = {
+    0,                  // 0 seconds.
+    n * 1000L * 1000L,  // And n ms.
+  };
+  nanosleep(&time, NULL);
+}
+
+// Allows a controller thread to pause execution of newly created
+// threads until notified.  Instances of this class must be created
+// and destroyed in the controller thread.
+//
+// This class is only for testing Google Test's own constructs. Do not
+// use it in user tests, either directly or indirectly.
+class Notification {
+ public:
+  Notification() : notified_(false) {
+    GTEST_CHECK_POSIX_SUCCESS_(pthread_mutex_init(&mutex_, NULL));
+  }
+  ~Notification() {
+    pthread_mutex_destroy(&mutex_);
+  }
+
+  // Notifies all threads created with this notification to start. Must
+  // be called from the controller thread.
+  void Notify() {
+    pthread_mutex_lock(&mutex_);
+    notified_ = true;
+    pthread_mutex_unlock(&mutex_);
+  }
+
+  // Blocks until the controller thread notifies. Must be called from a test
+  // thread.
+  void WaitForNotification() {
+    for (;;) {
+      pthread_mutex_lock(&mutex_);
+      const bool notified = notified_;
+      pthread_mutex_unlock(&mutex_);
+      if (notified)
+        break;
+      SleepMilliseconds(10);
+    }
+  }
+
+ private:
+  pthread_mutex_t mutex_;
+  bool notified_;
+
+  GTEST_DISALLOW_COPY_AND_ASSIGN_(Notification);
+};
+
+// As a C-function, ThreadFuncWithCLinkage cannot be templated itself.
+// Consequently, it cannot select a correct instantiation of ThreadWithParam
+// in order to call its Run(). Introducing ThreadWithParamBase as a
+// non-templated base class for ThreadWithParam allows us to bypass this
+// problem.
+class ThreadWithParamBase {
+ public:
+  virtual ~ThreadWithParamBase() {}
+  virtual void Run() = 0;
+};
+
+// pthread_create() accepts a pointer to a function type with the C linkage.
+// According to the Standard (7.5/1), function types with different linkages
+// are different even if they are otherwise identical.  Some compilers (for
+// example, SunStudio) treat them as different types.  Since class methods
+// cannot be defined with C-linkage we need to define a free C-function to
+// pass into pthread_create().
+extern "C" inline void* ThreadFuncWithCLinkage(void* thread) {
+  static_cast<ThreadWithParamBase*>(thread)->Run();
+  return NULL;
+}
+
+// Helper class for testing Google Test's multi-threading constructs.
+// To use it, write:
+//
+//   void ThreadFunc(int param) { /* Do things with param */ }
+//   Notification thread_can_start;
+//   ...
+//   // The thread_can_start parameter is optional; you can supply NULL.
+//   ThreadWithParam<int> thread(&ThreadFunc, 5, &thread_can_start);
+//   thread_can_start.Notify();
+//
+// These classes are only for testing Google Test's own constructs. Do
+// not use them in user tests, either directly or indirectly.
+template <typename T>
+class ThreadWithParam : public ThreadWithParamBase {
+ public:
+  typedef void (*UserThreadFunc)(T);
+
+  ThreadWithParam(
+      UserThreadFunc func, T param, Notification* thread_can_start)
+      : func_(func),
+        param_(param),
+        thread_can_start_(thread_can_start),
+        finished_(false) {
+    ThreadWithParamBase* const base = this;
+    // The thread can be created only after all fields except thread_
+    // have been initialized.
+    GTEST_CHECK_POSIX_SUCCESS_(
+        pthread_create(&thread_, 0, &ThreadFuncWithCLinkage, base));
+  }
+  ~ThreadWithParam() { Join(); }
+
+  void Join() {
+    if (!finished_) {
+      GTEST_CHECK_POSIX_SUCCESS_(pthread_join(thread_, 0));
+      finished_ = true;
+    }
+  }
+
+  virtual void Run() {
+    if (thread_can_start_ != NULL)
+      thread_can_start_->WaitForNotification();
+    func_(param_);
+  }
+
+ private:
+  const UserThreadFunc func_;  // User-supplied thread function.
+  const T param_;  // User-supplied parameter to the thread function.
+  // When non-NULL, used to block execution until the controller thread
+  // notifies.
+  Notification* const thread_can_start_;
+  bool finished_;  // true iff we know that the thread function has finished.
+  pthread_t thread_;  // The native thread object.
+
+  GTEST_DISALLOW_COPY_AND_ASSIGN_(ThreadWithParam);
+};
+
+// MutexBase and Mutex implement mutex on pthreads-based platforms. They
+// are used in conjunction with class MutexLock:
+//
+//   Mutex mutex;
+//   ...
+//   MutexLock lock(&mutex);  // Acquires the mutex and releases it at the end
+//                            // of the current scope.
+//
+// MutexBase implements behavior for both statically and dynamically
+// allocated mutexes.  Do not use MutexBase directly.  Instead, write
+// the following to define a static mutex:
+//
+//   GTEST_DEFINE_STATIC_MUTEX_(g_some_mutex);
+//
+// You can forward declare a static mutex like this:
+//
+//   GTEST_DECLARE_STATIC_MUTEX_(g_some_mutex);
+//
+// To create a dynamic mutex, just define an object of type Mutex.
+class MutexBase {
+ public:
+  // Acquires this mutex.
+  void Lock() {
+    GTEST_CHECK_POSIX_SUCCESS_(pthread_mutex_lock(&mutex_));
+    owner_ = pthread_self();
+    has_owner_ = true;
+  }
+
+  // Releases this mutex.
+  void Unlock() {
+    // Since the lock is being released the owner_ field should no longer be
+    // considered valid. We don't protect writing to has_owner_ here, as it's
+    // the caller's responsibility to ensure that the current thread holds the
+    // mutex when this is called.
+    has_owner_ = false;
+    GTEST_CHECK_POSIX_SUCCESS_(pthread_mutex_unlock(&mutex_));
+  }
+
+  // Does nothing if the current thread holds the mutex. Otherwise, crashes
+  // with high probability.
+  void AssertHeld() const {
+    GTEST_CHECK_(has_owner_ && pthread_equal(owner_, pthread_self()))
+        << "The current thread is not holding the mutex @" << this;
+  }
+
+  // A static mutex may be used before main() is entered.  It may even
+  // be used before the dynamic initialization stage.  Therefore we
+  // must be able to initialize a static mutex object at link time.
+  // This means MutexBase has to be a POD and its member variables
+  // have to be public.
+ public:
+  pthread_mutex_t mutex_;  // The underlying pthread mutex.
+  // has_owner_ indicates whether the owner_ field below contains a valid thread
+  // ID and is therefore safe to inspect (e.g., to use in pthread_equal()). All
+  // accesses to the owner_ field should be protected by a check of this field.
+  // An alternative might be to memset() owner_ to all zeros, but there's no
+  // guarantee that a zero'd pthread_t is necessarily invalid or even different
+  // from pthread_self().
+  bool has_owner_;
+  pthread_t owner_;  // The thread holding the mutex.
+};
+
+// Forward-declares a static mutex.
+# define GTEST_DECLARE_STATIC_MUTEX_(mutex) \
+    extern ::testing::internal::MutexBase mutex
+
+// Defines and statically (i.e. at link time) initializes a static mutex.
+// The initialization list here does not explicitly initialize each field,
+// instead relying on default initialization for the unspecified fields. In
+// particular, the owner_ field (a pthread_t) is not explicitly initialized.
+// This allows initialization to work whether pthread_t is a scalar or struct.
+// The flag -Wmissing-field-initializers must not be specified for this to work.
+# define GTEST_DEFINE_STATIC_MUTEX_(mutex) \
+    ::testing::internal::MutexBase mutex = { PTHREAD_MUTEX_INITIALIZER, false }
+
+// The Mutex class can only be used for mutexes created at runtime. It
+// shares its API with MutexBase otherwise.
+class Mutex : public MutexBase {
+ public:
+  Mutex() {
+    GTEST_CHECK_POSIX_SUCCESS_(pthread_mutex_init(&mutex_, NULL));
+    has_owner_ = false;
+  }
+  ~Mutex() {
+    GTEST_CHECK_POSIX_SUCCESS_(pthread_mutex_destroy(&mutex_));
+  }
+
+ private:
+  GTEST_DISALLOW_COPY_AND_ASSIGN_(Mutex);
+};
+
+// We cannot name this class MutexLock as the ctor declaration would
+// conflict with a macro named MutexLock, which is defined on some
+// platforms.  Hence the typedef trick below.
+class GTestMutexLock {
+ public:
+  explicit GTestMutexLock(MutexBase* mutex)
+      : mutex_(mutex) { mutex_->Lock(); }
+
+  ~GTestMutexLock() { mutex_->Unlock(); }
+
+ private:
+  MutexBase* const mutex_;
+
+  GTEST_DISALLOW_COPY_AND_ASSIGN_(GTestMutexLock);
+};
+
+typedef GTestMutexLock MutexLock;
+
+// Helpers for ThreadLocal.
+
+// pthread_key_create() requires DeleteThreadLocalValue() to have
+// C-linkage.  Therefore it cannot be templatized to access
+// ThreadLocal<T>.  Hence the need for class
+// ThreadLocalValueHolderBase.
+class ThreadLocalValueHolderBase {
+ public:
+  virtual ~ThreadLocalValueHolderBase() {}
+};
+
+// Called by pthread to delete thread-local data stored by
+// pthread_setspecific().
+extern "C" inline void DeleteThreadLocalValue(void* value_holder) {
+  delete static_cast<ThreadLocalValueHolderBase*>(value_holder);
+}
+
+// Implements thread-local storage on pthreads-based systems.
+//
+//   // Thread 1
+//   ThreadLocal<int> tl(100);  // 100 is the default value for each thread.
+//
+//   // Thread 2
+//   tl.set(150);  // Changes the value for thread 2 only.
+//   EXPECT_EQ(150, tl.get());
+//
+//   // Thread 1
+//   EXPECT_EQ(100, tl.get());  // In thread 1, tl has the original value.
+//   tl.set(200);
+//   EXPECT_EQ(200, tl.get());
+//
+// The template type argument T must have a public copy constructor.
+// In addition, the default ThreadLocal constructor requires T to have
+// a public default constructor.
+//
+// An object managed for a thread by a ThreadLocal instance is deleted
+// when the thread exits.  Or, if the ThreadLocal instance dies in
+// that thread, when the ThreadLocal dies.  It's the user's
+// responsibility to ensure that all other threads using a ThreadLocal
+// have exited when it dies, or the per-thread objects for those
+// threads will not be deleted.
+//
+// Google Test only uses global ThreadLocal objects.  That means they
+// will die after main() has returned.  Therefore, no per-thread
+// object managed by Google Test will be leaked as long as all threads
+// using Google Test have exited when main() returns.
+template <typename T>
+class ThreadLocal {
+ public:
+  ThreadLocal() : key_(CreateKey()),
+                  default_() {}
+  explicit ThreadLocal(const T& value) : key_(CreateKey()),
+                                         default_(value) {}
+
+  ~ThreadLocal() {
+    // Destroys the managed object for the current thread, if any.
+    DeleteThreadLocalValue(pthread_getspecific(key_));
+
+    // Releases resources associated with the key.  This will *not*
+    // delete managed objects for other threads.
+    GTEST_CHECK_POSIX_SUCCESS_(pthread_key_delete(key_));
+  }
+
+  T* pointer() { return GetOrCreateValue(); }
+  const T* pointer() const { return GetOrCreateValue(); }
+  const T& get() const { return *pointer(); }
+  void set(const T& value) { *pointer() = value; }
+
+ private:
+  // Holds a value of type T.
+  class ValueHolder : public ThreadLocalValueHolderBase {
+   public:
+    explicit ValueHolder(const T& value) : value_(value) {}
+
+    T* pointer() { return &value_; }
+
+   private:
+    T value_;
+    GTEST_DISALLOW_COPY_AND_ASSIGN_(ValueHolder);
+  };
+
+  static pthread_key_t CreateKey() {
+    pthread_key_t key;
+    // When a thread exits, DeleteThreadLocalValue() will be called on
+    // the object managed for that thread.
+    GTEST_CHECK_POSIX_SUCCESS_(
+        pthread_key_create(&key, &DeleteThreadLocalValue));
+    return key;
+  }
+
+  T* GetOrCreateValue() const {
+    ThreadLocalValueHolderBase* const holder =
+        static_cast<ThreadLocalValueHolderBase*>(pthread_getspecific(key_));
+    if (holder != NULL) {
+      return CheckedDowncastToActualType<ValueHolder>(holder)->pointer();
+    }
+
+    ValueHolder* const new_holder = new ValueHolder(default_);
+    ThreadLocalValueHolderBase* const holder_base = new_holder;
+    GTEST_CHECK_POSIX_SUCCESS_(pthread_setspecific(key_, holder_base));
+    return new_holder->pointer();
+  }
+
+  // A key pthreads uses for looking up per-thread values.
+  const pthread_key_t key_;
+  const T default_;  // The default value for each thread.
+
+  GTEST_DISALLOW_COPY_AND_ASSIGN_(ThreadLocal);
+};
+
+# define GTEST_IS_THREADSAFE 1
+
+#else  // GTEST_HAS_PTHREAD
+
+// A dummy implementation of synchronization primitives (mutex, lock,
+// and thread-local variable).  Necessary for compiling Google Test where
+// mutex is not supported - using Google Test in multiple threads is not
+// supported on such platforms.
+
+class Mutex {
+ public:
+  Mutex() {}
+  void Lock() {}
+  void Unlock() {}
+  void AssertHeld() const {}
+};
+
+# define GTEST_DECLARE_STATIC_MUTEX_(mutex) \
+  extern ::testing::internal::Mutex mutex
+
+# define GTEST_DEFINE_STATIC_MUTEX_(mutex) ::testing::internal::Mutex mutex
+
+class GTestMutexLock {
+ public:
+  explicit GTestMutexLock(Mutex*) {}  // NOLINT
+};
+
+typedef GTestMutexLock MutexLock;
+
+template <typename T>
+class ThreadLocal {
+ public:
+  ThreadLocal() : value_() {}
+  explicit ThreadLocal(const T& value) : value_(value) {}
+  T* pointer() { return &value_; }
+  const T* pointer() const { return &value_; }
+  const T& get() const { return value_; }
+  void set(const T& value) { value_ = value; }
+ private:
+  T value_;
+};
+
+// The above synchronization primitives have dummy implementations.
+// Therefore Google Test is not thread-safe.
+# define GTEST_IS_THREADSAFE 0
+
+#endif  // GTEST_HAS_PTHREAD
+
+// Returns the number of threads running in the process, or 0 to indicate that
+// we cannot detect it.
+GTEST_API_ size_t GetThreadCount();
+
+// Passing non-POD classes through ellipsis (...) crashes the ARM
+// compiler and generates a warning in Sun Studio.  The Nokia Symbian
+// and the IBM XL C/C++ compiler try to instantiate a copy constructor
+// for objects passed through ellipsis (...), failing for uncopyable
+// objects.  We define this to ensure that only POD is passed through
+// ellipsis on these systems.
+#if defined(__SYMBIAN32__) || defined(__IBMCPP__) || defined(__SUNPRO_CC)
+// We lose support for NULL detection where the compiler doesn't like
+// passing non-POD classes through ellipsis (...).
+# define GTEST_ELLIPSIS_NEEDS_POD_ 1
+#else
+# define GTEST_CAN_COMPARE_NULL 1
+#endif
+
+// The Nokia Symbian and IBM XL C/C++ compilers cannot decide between
+// const T& and const T* in a function template.  These compilers
+// _can_ decide between class template specializations for T and T*,
+// so a tr1::type_traits-like is_pointer works.
+#if defined(__SYMBIAN32__) || defined(__IBMCPP__)
+# define GTEST_NEEDS_IS_POINTER_ 1
+#endif
+
+template <bool bool_value>
+struct bool_constant {
+  typedef bool_constant<bool_value> type;
+  static const bool value = bool_value;
+};
+template <bool bool_value> const bool bool_constant<bool_value>::value;
+
+typedef bool_constant<false> false_type;
+typedef bool_constant<true> true_type;
+
+template <typename T>
+struct is_pointer : public false_type {};
+
+template <typename T>
+struct is_pointer<T*> : public true_type {};
+
+template <typename Iterator>
+struct IteratorTraits {
+  typedef typename Iterator::value_type value_type;
+};
+
+template <typename T>
+struct IteratorTraits<T*> {
+  typedef T value_type;
+};
+
+template <typename T>
+struct IteratorTraits<const T*> {
+  typedef T value_type;
+};
+
+#if GTEST_OS_WINDOWS
+# define GTEST_PATH_SEP_ "\\"
+# define GTEST_HAS_ALT_PATH_SEP_ 1
+// The biggest signed integer type the compiler supports.
+typedef __int64 BiggestInt;
+#else
+# define GTEST_PATH_SEP_ "/"
+# define GTEST_HAS_ALT_PATH_SEP_ 0
+typedef long long BiggestInt;  // NOLINT
+#endif  // GTEST_OS_WINDOWS
+
+// Utilities for char.
+
+// isspace(int ch) and friends accept an unsigned char or EOF.  char
+// may be signed, depending on the compiler (or compiler flags).
+// Therefore we need to cast a char to unsigned char before calling
+// isspace(), etc.
+
+inline bool IsAlpha(char ch) {
+  return isalpha(static_cast<unsigned char>(ch)) != 0;
+}
+inline bool IsAlNum(char ch) {
+  return isalnum(static_cast<unsigned char>(ch)) != 0;
+}
+inline bool IsDigit(char ch) {
+  return isdigit(static_cast<unsigned char>(ch)) != 0;
+}
+inline bool IsLower(char ch) {
+  return islower(static_cast<unsigned char>(ch)) != 0;
+}
+inline bool IsSpace(char ch) {
+  return isspace(static_cast<unsigned char>(ch)) != 0;
+}
+inline bool IsUpper(char ch) {
+  return isupper(static_cast<unsigned char>(ch)) != 0;
+}
+inline bool IsXDigit(char ch) {
+  return isxdigit(static_cast<unsigned char>(ch)) != 0;
+}
+inline bool IsXDigit(wchar_t ch) {
+  const unsigned char low_byte = static_cast<unsigned char>(ch);
+  return ch == low_byte && isxdigit(low_byte) != 0;
+}
+
+inline char ToLower(char ch) {
+  return static_cast<char>(tolower(static_cast<unsigned char>(ch)));
+}
+inline char ToUpper(char ch) {
+  return static_cast<char>(toupper(static_cast<unsigned char>(ch)));
+}
+
+// The testing::internal::posix namespace holds wrappers for common
+// POSIX functions.  These wrappers hide the differences between
+// Windows/MSVC and POSIX systems.  Since some compilers define these
+// standard functions as macros, the wrapper cannot have the same name
+// as the wrapped function.
+
+namespace posix {
+
+// Functions with a different name on Windows.
+
+#if GTEST_OS_WINDOWS
+
+typedef struct _stat StatStruct;
+
+# ifdef __BORLANDC__
+inline int IsATTY(int fd) { return isatty(fd); }
+inline int StrCaseCmp(const char* s1, const char* s2) {
+  return stricmp(s1, s2);
+}
+inline char* StrDup(const char* src) { return strdup(src); }
+# else  // !__BORLANDC__
+#  if GTEST_OS_WINDOWS_MOBILE
+inline int IsATTY(int /* fd */) { return 0; }
+#  else
+inline int IsATTY(int fd) { return _isatty(fd); }
+#  endif  // GTEST_OS_WINDOWS_MOBILE
+inline int StrCaseCmp(const char* s1, const char* s2) {
+  return _stricmp(s1, s2);
+}
+inline char* StrDup(const char* src) { return _strdup(src); }
+# endif  // __BORLANDC__
+
+# if GTEST_OS_WINDOWS_MOBILE
+inline int FileNo(FILE* file) { return reinterpret_cast<int>(_fileno(file)); }
+// Stat(), RmDir(), and IsDir() are not needed on Windows CE at this
+// time and thus not defined there.
+# else
+inline int FileNo(FILE* file) { return _fileno(file); }
+inline int Stat(const char* path, StatStruct* buf) { return _stat(path, buf); }
+inline int RmDir(const char* dir) { return _rmdir(dir); }
+inline bool IsDir(const StatStruct& st) {
+  return (_S_IFDIR & st.st_mode) != 0;
+}
+# endif  // GTEST_OS_WINDOWS_MOBILE
+
+#else
+
+typedef struct stat StatStruct;
+
+inline int FileNo(FILE* file) { return fileno(file); }
+inline int IsATTY(int fd) { return isatty(fd); }
+inline int Stat(const char* path, StatStruct* buf) { return stat(path, buf); }
+inline int StrCaseCmp(const char* s1, const char* s2) {
+  return strcasecmp(s1, s2);
+}
+inline char* StrDup(const char* src) { return strdup(src); }
+inline int RmDir(const char* dir) { return rmdir(dir); }
+inline bool IsDir(const StatStruct& st) { return S_ISDIR(st.st_mode); }
+
+#endif  // GTEST_OS_WINDOWS
+
+// Functions deprecated by MSVC 8.0.
+
+#ifdef _MSC_VER
+// Temporarily disable warning 4996 (deprecated function).
+# pragma warning(push)
+# pragma warning(disable:4996)
+#endif
+
+inline const char* StrNCpy(char* dest, const char* src, size_t n) {
+  return strncpy(dest, src, n);
+}
+
+// ChDir(), FReopen(), FDOpen(), Read(), Write(), Close(), and
+// StrError() aren't needed on Windows CE at this time and thus not
+// defined there.
+
+#if !GTEST_OS_WINDOWS_MOBILE
+inline int ChDir(const char* dir) { return chdir(dir); }
+#endif
+inline FILE* FOpen(const char* path, const char* mode) {
+  return fopen(path, mode);
+}
+#if !GTEST_OS_WINDOWS_MOBILE
+inline FILE *FReopen(const char* path, const char* mode, FILE* stream) {
+  return freopen(path, mode, stream);
+}
+inline FILE* FDOpen(int fd, const char* mode) { return fdopen(fd, mode); }
+#endif
+inline int FClose(FILE* fp) { return fclose(fp); }
+#if !GTEST_OS_WINDOWS_MOBILE
+inline int Read(int fd, void* buf, unsigned int count) {
+  return static_cast<int>(read(fd, buf, count));
+}
+inline int Write(int fd, const void* buf, unsigned int count) {
+  return static_cast<int>(write(fd, buf, count));
+}
+inline int Close(int fd) { return close(fd); }
+inline const char* StrError(int errnum) { return strerror(errnum); }
+#endif
+inline const char* GetEnv(const char* name) {
+#if GTEST_OS_WINDOWS_MOBILE
+  // We are on Windows CE, which has no environment variables.
+  return NULL;
+#elif defined(__BORLANDC__) || defined(__SunOS_5_8) || defined(__SunOS_5_9)
+  // Environment variables which we programmatically clear will be set to the
+  // empty string rather than unset (NULL).  Handle that case.
+  const char* const env = getenv(name);
+  return (env != NULL && env[0] != '\0') ? env : NULL;
+#else
+  return getenv(name);
+#endif
+}
+
+#ifdef _MSC_VER
+# pragma warning(pop)  // Restores the warning state.
+#endif
+
+#if GTEST_OS_WINDOWS_MOBILE
+// Windows CE has no C library. The abort() function is used in
+// several places in Google Test. This implementation provides a reasonable
+// imitation of standard behaviour.
+void Abort();
+#else
+inline void Abort() { abort(); }
+#endif  // GTEST_OS_WINDOWS_MOBILE
+
+}  // namespace posix
+
+// MSVC "deprecates" snprintf and issues warnings wherever it is used.  In
+// order to avoid these warnings, we need to use _snprintf or _snprintf_s on
+// MSVC-based platforms.  We map the GTEST_SNPRINTF_ macro to the appropriate
+// function in order to achieve that.  We use macro definition here because
+// snprintf is a variadic function.
+#if _MSC_VER >= 1400 && !GTEST_OS_WINDOWS_MOBILE
+// MSVC 2005 and above support variadic macros.
+# define GTEST_SNPRINTF_(buffer, size, format, ...) \
+     _snprintf_s(buffer, size, size, format, __VA_ARGS__)
+#elif defined(_MSC_VER)
+// Windows CE does not define _snprintf_s and MSVC prior to 2005 doesn't
+// complain about _snprintf.
+# define GTEST_SNPRINTF_ _snprintf
+#else
+# define GTEST_SNPRINTF_ snprintf
+#endif
+
+// The maximum number a BiggestInt can represent.  This definition
+// works no matter BiggestInt is represented in one's complement or
+// two's complement.
+//
+// We cannot rely on numeric_limits in STL, as __int64 and long long
+// are not part of standard C++ and numeric_limits doesn't need to be
+// defined for them.
+const BiggestInt kMaxBiggestInt =
+    ~(static_cast<BiggestInt>(1) << (8*sizeof(BiggestInt) - 1));
+
+// This template class serves as a compile-time function from size to
+// type.  It maps a size in bytes to a primitive type with that
+// size. e.g.
+//
+//   TypeWithSize<4>::UInt
+//
+// is typedef-ed to be unsigned int (unsigned integer made up of 4
+// bytes).
+//
+// Such functionality should belong to STL, but I cannot find it
+// there.
+//
+// Google Test uses this class in the implementation of floating-point
+// comparison.
+//
+// For now it only handles UInt (unsigned int) as that's all Google Test
+// needs.  Other types can be easily added in the future if need
+// arises.
+template <size_t size>
+class TypeWithSize {
+ public:
+  // This prevents the user from using TypeWithSize<N> with incorrect
+  // values of N.
+  typedef void UInt;
+};
+
+// The specialization for size 4.
+template <>
+class TypeWithSize<4> {
+ public:
+  // unsigned int has size 4 in both gcc and MSVC.
+  //
+  // As base/basictypes.h doesn't compile on Windows, we cannot use
+  // uint32, uint64, and etc here.
+  typedef int Int;
+  typedef unsigned int UInt;
+};
+
+// The specialization for size 8.
+template <>
+class TypeWithSize<8> {
+ public:
+#if GTEST_OS_WINDOWS
+  typedef __int64 Int;
+  typedef unsigned __int64 UInt;
+#else
+  typedef long long Int;  // NOLINT
+  typedef unsigned long long UInt;  // NOLINT
+#endif  // GTEST_OS_WINDOWS
+};
+
+// Integer types of known sizes.
+typedef TypeWithSize<4>::Int Int32;
+typedef TypeWithSize<4>::UInt UInt32;
+typedef TypeWithSize<8>::Int Int64;
+typedef TypeWithSize<8>::UInt UInt64;
+typedef TypeWithSize<8>::Int TimeInMillis;  // Represents time in milliseconds.
+
+// Utilities for command line flags and environment variables.
+
+// Macro for referencing flags.
+#define GTEST_FLAG(name) FLAGS_gtest_##name
+
+// Macros for declaring flags.
+#define GTEST_DECLARE_bool_(name) GTEST_API_ extern bool GTEST_FLAG(name)
+#define GTEST_DECLARE_int32_(name) \
+    GTEST_API_ extern ::testing::internal::Int32 GTEST_FLAG(name)
+#define GTEST_DECLARE_string_(name) \
+    GTEST_API_ extern ::std::string GTEST_FLAG(name)
+
+// Macros for defining flags.
+#define GTEST_DEFINE_bool_(name, default_val, doc) \
+    GTEST_API_ bool GTEST_FLAG(name) = (default_val)
+#define GTEST_DEFINE_int32_(name, default_val, doc) \
+    GTEST_API_ ::testing::internal::Int32 GTEST_FLAG(name) = (default_val)
+#define GTEST_DEFINE_string_(name, default_val, doc) \
+    GTEST_API_ ::std::string GTEST_FLAG(name) = (default_val)
+
+// Thread annotations
+#define GTEST_EXCLUSIVE_LOCK_REQUIRED_(locks)
+#define GTEST_LOCK_EXCLUDED_(locks)
+
+// Parses 'str' for a 32-bit signed integer.  If successful, writes the result
+// to *value and returns true; otherwise leaves *value unchanged and returns
+// false.
+// TODO(chandlerc): Find a better way to refactor flag and environment parsing
+// out of both gtest-port.cc and gtest.cc to avoid exporting this utility
+// function.
+bool ParseInt32(const Message& src_text, const char* str, Int32* value);
+
+// Parses a bool/Int32/string from the environment variable
+// corresponding to the given Google Test flag.
+bool BoolFromGTestEnv(const char* flag, bool default_val);
+GTEST_API_ Int32 Int32FromGTestEnv(const char* flag, Int32 default_val);
+const char* StringFromGTestEnv(const char* flag, const char* default_val);
+
+}  // namespace internal
+}  // namespace testing
+
+#endif  // GTEST_INCLUDE_GTEST_INTERNAL_GTEST_PORT_H_
diff --git a/test/gtest/include/gtest/internal/gtest-string.h b/test/gtest/include/gtest/internal/gtest-string.h
new file mode 100644
index 0000000..97f1a7f
--- /dev/null
+++ b/test/gtest/include/gtest/internal/gtest-string.h
@@ -0,0 +1,167 @@
+// Copyright 2005, Google Inc.
+// All rights reserved.
+//
+// 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.
+//
+// Authors: wan at google.com (Zhanyong Wan), eefacm at gmail.com (Sean Mcafee)
+//
+// The Google C++ Testing Framework (Google Test)
+//
+// This header file declares the String class and functions used internally by
+// Google Test.  They are subject to change without notice. They should not used
+// by code external to Google Test.
+//
+// This header file is #included by <gtest/internal/gtest-internal.h>.
+// It should not be #included by other files.
+
+#ifndef GTEST_INCLUDE_GTEST_INTERNAL_GTEST_STRING_H_
+#define GTEST_INCLUDE_GTEST_INTERNAL_GTEST_STRING_H_
+
+#ifdef __BORLANDC__
+// string.h is not guaranteed to provide strcpy on C++ Builder.
+# include <mem.h>
+#endif
+
+#include <string.h>
+#include <string>
+
+#include "gtest/internal/gtest-port.h"
+
+namespace testing {
+namespace internal {
+
+// String - an abstract class holding static string utilities.
+class GTEST_API_ String {
+ public:
+  // Static utility methods
+
+  // Clones a 0-terminated C string, allocating memory using new.  The
+  // caller is responsible for deleting the return value using
+  // delete[].  Returns the cloned string, or NULL if the input is
+  // NULL.
+  //
+  // This is different from strdup() in string.h, which allocates
+  // memory using malloc().
+  static const char* CloneCString(const char* c_str);
+
+#if GTEST_OS_WINDOWS_MOBILE
+  // Windows CE does not have the 'ANSI' versions of Win32 APIs. To be
+  // able to pass strings to Win32 APIs on CE we need to convert them
+  // to 'Unicode', UTF-16.
+
+  // Creates a UTF-16 wide string from the given ANSI string, allocating
+  // memory using new. The caller is responsible for deleting the return
+  // value using delete[]. Returns the wide string, or NULL if the
+  // input is NULL.
+  //
+  // The wide string is created using the ANSI codepage (CP_ACP) to
+  // match the behaviour of the ANSI versions of Win32 calls and the
+  // C runtime.
+  static LPCWSTR AnsiToUtf16(const char* c_str);
+
+  // Creates an ANSI string from the given wide string, allocating
+  // memory using new. The caller is responsible for deleting the return
+  // value using delete[]. Returns the ANSI string, or NULL if the
+  // input is NULL.
+  //
+  // The returned string is created using the ANSI codepage (CP_ACP) to
+  // match the behaviour of the ANSI versions of Win32 calls and the
+  // C runtime.
+  static const char* Utf16ToAnsi(LPCWSTR utf16_str);
+#endif
+
+  // Compares two C strings.  Returns true iff they have the same content.
+  //
+  // Unlike strcmp(), this function can handle NULL argument(s).  A
+  // NULL C string is considered different to any non-NULL C string,
+  // including the empty string.
+  static bool CStringEquals(const char* lhs, const char* rhs);
+
+  // Converts a wide C string to a String using the UTF-8 encoding.
+  // NULL will be converted to "(null)".  If an error occurred during
+  // the conversion, "(failed to convert from wide string)" is
+  // returned.
+  static std::string ShowWideCString(const wchar_t* wide_c_str);
+
+  // Compares two wide C strings.  Returns true iff they have the same
+  // content.
+  //
+  // Unlike wcscmp(), this function can handle NULL argument(s).  A
+  // NULL C string is considered different to any non-NULL C string,
+  // including the empty string.
+  static bool WideCStringEquals(const wchar_t* lhs, const wchar_t* rhs);
+
+  // Compares two C strings, ignoring case.  Returns true iff they
+  // have the same content.
+  //
+  // Unlike strcasecmp(), this function can handle NULL argument(s).
+  // A NULL C string is considered different to any non-NULL C string,
+  // including the empty string.
+  static bool CaseInsensitiveCStringEquals(const char* lhs,
+                                           const char* rhs);
+
+  // Compares two wide C strings, ignoring case.  Returns true iff they
+  // have the same content.
+  //
+  // Unlike wcscasecmp(), this function can handle NULL argument(s).
+  // A NULL C string is considered different to any non-NULL wide C string,
+  // including the empty string.
+  // NB: The implementations on different platforms slightly differ.
+  // On windows, this method uses _wcsicmp which compares according to LC_CTYPE
+  // environment variable. On GNU platform this method uses wcscasecmp
+  // which compares according to LC_CTYPE category of the current locale.
+  // On MacOS X, it uses towlower, which also uses LC_CTYPE category of the
+  // current locale.
+  static bool CaseInsensitiveWideCStringEquals(const wchar_t* lhs,
+                                               const wchar_t* rhs);
+
+  // Returns true iff the given string ends with the given suffix, ignoring
+  // case. Any string is considered to end with an empty suffix.
+  static bool EndsWithCaseInsensitive(
+      const std::string& str, const std::string& suffix);
+
+  // Formats an int value as "%02d".
+  static std::string FormatIntWidth2(int value);  // "%02d" for width == 2
+
+  // Formats an int value as "%X".
+  static std::string FormatHexInt(int value);
+
+  // Formats a byte as "%02X".
+  static std::string FormatByte(unsigned char value);
+
+ private:
+  String();  // Not meant to be instantiated.
+};  // class String
+
+// Gets the content of the stringstream's buffer as an std::string.  Each '\0'
+// character in the buffer is replaced with "\\0".
+GTEST_API_ std::string StringStreamToString(::std::stringstream* stream);
+
+}  // namespace internal
+}  // namespace testing
+
+#endif  // GTEST_INCLUDE_GTEST_INTERNAL_GTEST_STRING_H_
diff --git a/test/gtest/include/gtest/internal/gtest-tuple.h b/test/gtest/include/gtest/internal/gtest-tuple.h
new file mode 100644
index 0000000..7b3dfc3
--- /dev/null
+++ b/test/gtest/include/gtest/internal/gtest-tuple.h
@@ -0,0 +1,1012 @@
+// This file was GENERATED by command:
+//     pump.py gtest-tuple.h.pump
+// DO NOT EDIT BY HAND!!!
+
+// Copyright 2009 Google Inc.
+// All Rights Reserved.
+//
+// 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: wan at google.com (Zhanyong Wan)
+
+// Implements a subset of TR1 tuple needed by Google Test and Google Mock.
+
+#ifndef GTEST_INCLUDE_GTEST_INTERNAL_GTEST_TUPLE_H_
+#define GTEST_INCLUDE_GTEST_INTERNAL_GTEST_TUPLE_H_
+
+#include <utility>  // For ::std::pair.
+
+// The compiler used in Symbian has a bug that prevents us from declaring the
+// tuple template as a friend (it complains that tuple is redefined).  This
+// hack bypasses the bug by declaring the members that should otherwise be
+// private as public.
+// Sun Studio versions < 12 also have the above bug.
+#if defined(__SYMBIAN32__) || (defined(__SUNPRO_CC) && __SUNPRO_CC < 0x590)
+# define GTEST_DECLARE_TUPLE_AS_FRIEND_ public:
+#else
+# define GTEST_DECLARE_TUPLE_AS_FRIEND_ \
+    template <GTEST_10_TYPENAMES_(U)> friend class tuple; \
+   private:
+#endif
+
+// GTEST_n_TUPLE_(T) is the type of an n-tuple.
+#define GTEST_0_TUPLE_(T) tuple<>
+#define GTEST_1_TUPLE_(T) tuple<T##0, void, void, void, void, void, void, \
+    void, void, void>
+#define GTEST_2_TUPLE_(T) tuple<T##0, T##1, void, void, void, void, void, \
+    void, void, void>
+#define GTEST_3_TUPLE_(T) tuple<T##0, T##1, T##2, void, void, void, void, \
+    void, void, void>
+#define GTEST_4_TUPLE_(T) tuple<T##0, T##1, T##2, T##3, void, void, void, \
+    void, void, void>
+#define GTEST_5_TUPLE_(T) tuple<T##0, T##1, T##2, T##3, T##4, void, void, \
+    void, void, void>
+#define GTEST_6_TUPLE_(T) tuple<T##0, T##1, T##2, T##3, T##4, T##5, void, \
+    void, void, void>
+#define GTEST_7_TUPLE_(T) tuple<T##0, T##1, T##2, T##3, T##4, T##5, T##6, \
+    void, void, void>
+#define GTEST_8_TUPLE_(T) tuple<T##0, T##1, T##2, T##3, T##4, T##5, T##6, \
+    T##7, void, void>
+#define GTEST_9_TUPLE_(T) tuple<T##0, T##1, T##2, T##3, T##4, T##5, T##6, \
+    T##7, T##8, void>
+#define GTEST_10_TUPLE_(T) tuple<T##0, T##1, T##2, T##3, T##4, T##5, T##6, \
+    T##7, T##8, T##9>
+
+// GTEST_n_TYPENAMES_(T) declares a list of n typenames.
+#define GTEST_0_TYPENAMES_(T)
+#define GTEST_1_TYPENAMES_(T) typename T##0
+#define GTEST_2_TYPENAMES_(T) typename T##0, typename T##1
+#define GTEST_3_TYPENAMES_(T) typename T##0, typename T##1, typename T##2
+#define GTEST_4_TYPENAMES_(T) typename T##0, typename T##1, typename T##2, \
+    typename T##3
+#define GTEST_5_TYPENAMES_(T) typename T##0, typename T##1, typename T##2, \
+    typename T##3, typename T##4
+#define GTEST_6_TYPENAMES_(T) typename T##0, typename T##1, typename T##2, \
+    typename T##3, typename T##4, typename T##5
+#define GTEST_7_TYPENAMES_(T) typename T##0, typename T##1, typename T##2, \
+    typename T##3, typename T##4, typename T##5, typename T##6
+#define GTEST_8_TYPENAMES_(T) typename T##0, typename T##1, typename T##2, \
+    typename T##3, typename T##4, typename T##5, typename T##6, typename T##7
+#define GTEST_9_TYPENAMES_(T) typename T##0, typename T##1, typename T##2, \
+    typename T##3, typename T##4, typename T##5, typename T##6, \
+    typename T##7, typename T##8
+#define GTEST_10_TYPENAMES_(T) typename T##0, typename T##1, typename T##2, \
+    typename T##3, typename T##4, typename T##5, typename T##6, \
+    typename T##7, typename T##8, typename T##9
+
+// In theory, defining stuff in the ::std namespace is undefined
+// behavior.  We can do this as we are playing the role of a standard
+// library vendor.
+namespace std {
+namespace tr1 {
+
+template <typename T0 = void, typename T1 = void, typename T2 = void,
+    typename T3 = void, typename T4 = void, typename T5 = void,
+    typename T6 = void, typename T7 = void, typename T8 = void,
+    typename T9 = void>
+class tuple;
+
+// Anything in namespace gtest_internal is Google Test's INTERNAL
+// IMPLEMENTATION DETAIL and MUST NOT BE USED DIRECTLY in user code.
+namespace gtest_internal {
+
+// ByRef<T>::type is T if T is a reference; otherwise it's const T&.
+template <typename T>
+struct ByRef { typedef const T& type; };  // NOLINT
+template <typename T>
+struct ByRef<T&> { typedef T& type; };  // NOLINT
+
+// A handy wrapper for ByRef.
+#define GTEST_BY_REF_(T) typename ::std::tr1::gtest_internal::ByRef<T>::type
+
+// AddRef<T>::type is T if T is a reference; otherwise it's T&.  This
+// is the same as tr1::add_reference<T>::type.
+template <typename T>
+struct AddRef { typedef T& type; };  // NOLINT
+template <typename T>
+struct AddRef<T&> { typedef T& type; };  // NOLINT
+
+// A handy wrapper for AddRef.
+#define GTEST_ADD_REF_(T) typename ::std::tr1::gtest_internal::AddRef<T>::type
+
+// A helper for implementing get<k>().
+template <int k> class Get;
+
+// A helper for implementing tuple_element<k, T>.  kIndexValid is true
+// iff k < the number of fields in tuple type T.
+template <bool kIndexValid, int kIndex, class Tuple>
+struct TupleElement;
+
+template <GTEST_10_TYPENAMES_(T)>
+struct TupleElement<true, 0, GTEST_10_TUPLE_(T) > {
+  typedef T0 type;
+};
+
+template <GTEST_10_TYPENAMES_(T)>
+struct TupleElement<true, 1, GTEST_10_TUPLE_(T) > {
+  typedef T1 type;
+};
+
+template <GTEST_10_TYPENAMES_(T)>
+struct TupleElement<true, 2, GTEST_10_TUPLE_(T) > {
+  typedef T2 type;
+};
+
+template <GTEST_10_TYPENAMES_(T)>
+struct TupleElement<true, 3, GTEST_10_TUPLE_(T) > {
+  typedef T3 type;
+};
+
+template <GTEST_10_TYPENAMES_(T)>
+struct TupleElement<true, 4, GTEST_10_TUPLE_(T) > {
+  typedef T4 type;
+};
+
+template <GTEST_10_TYPENAMES_(T)>
+struct TupleElement<true, 5, GTEST_10_TUPLE_(T) > {
+  typedef T5 type;
+};
+
+template <GTEST_10_TYPENAMES_(T)>
+struct TupleElement<true, 6, GTEST_10_TUPLE_(T) > {
+  typedef T6 type;
+};
+
+template <GTEST_10_TYPENAMES_(T)>
+struct TupleElement<true, 7, GTEST_10_TUPLE_(T) > {
+  typedef T7 type;
+};
+
+template <GTEST_10_TYPENAMES_(T)>
+struct TupleElement<true, 8, GTEST_10_TUPLE_(T) > {
+  typedef T8 type;
+};
+
+template <GTEST_10_TYPENAMES_(T)>
+struct TupleElement<true, 9, GTEST_10_TUPLE_(T) > {
+  typedef T9 type;
+};
+
+}  // namespace gtest_internal
+
+template <>
+class tuple<> {
+ public:
+  tuple() {}
+  tuple(const tuple& /* t */)  {}
+  tuple& operator=(const tuple& /* t */) { return *this; }
+};
+
+template <GTEST_1_TYPENAMES_(T)>
+class GTEST_1_TUPLE_(T) {
+ public:
+  template <int k> friend class gtest_internal::Get;
+
+  tuple() : f0_() {}
+
+  explicit tuple(GTEST_BY_REF_(T0) f0) : f0_(f0) {}
+
+  tuple(const tuple& t) : f0_(t.f0_) {}
+
+  template <GTEST_1_TYPENAMES_(U)>
+  tuple(const GTEST_1_TUPLE_(U)& t) : f0_(t.f0_) {}
+
+  tuple& operator=(const tuple& t) { return CopyFrom(t); }
+
+  template <GTEST_1_TYPENAMES_(U)>
+  tuple& operator=(const GTEST_1_TUPLE_(U)& t) {
+    return CopyFrom(t);
+  }
+
+  GTEST_DECLARE_TUPLE_AS_FRIEND_
+
+  template <GTEST_1_TYPENAMES_(U)>
+  tuple& CopyFrom(const GTEST_1_TUPLE_(U)& t) {
+    f0_ = t.f0_;
+    return *this;
+  }
+
+  T0 f0_;
+};
+
+template <GTEST_2_TYPENAMES_(T)>
+class GTEST_2_TUPLE_(T) {
+ public:
+  template <int k> friend class gtest_internal::Get;
+
+  tuple() : f0_(), f1_() {}
+
+  explicit tuple(GTEST_BY_REF_(T0) f0, GTEST_BY_REF_(T1) f1) : f0_(f0),
+      f1_(f1) {}
+
+  tuple(const tuple& t) : f0_(t.f0_), f1_(t.f1_) {}
+
+  template <GTEST_2_TYPENAMES_(U)>
+  tuple(const GTEST_2_TUPLE_(U)& t) : f0_(t.f0_), f1_(t.f1_) {}
+  template <typename U0, typename U1>
+  tuple(const ::std::pair<U0, U1>& p) : f0_(p.first), f1_(p.second) {}
+
+  tuple& operator=(const tuple& t) { return CopyFrom(t); }
+
+  template <GTEST_2_TYPENAMES_(U)>
+  tuple& operator=(const GTEST_2_TUPLE_(U)& t) {
+    return CopyFrom(t);
+  }
+  template <typename U0, typename U1>
+  tuple& operator=(const ::std::pair<U0, U1>& p) {
+    f0_ = p.first;
+    f1_ = p.second;
+    return *this;
+  }
+
+  GTEST_DECLARE_TUPLE_AS_FRIEND_
+
+  template <GTEST_2_TYPENAMES_(U)>
+  tuple& CopyFrom(const GTEST_2_TUPLE_(U)& t) {
+    f0_ = t.f0_;
+    f1_ = t.f1_;
+    return *this;
+  }
+
+  T0 f0_;
+  T1 f1_;
+};
+
+template <GTEST_3_TYPENAMES_(T)>
+class GTEST_3_TUPLE_(T) {
+ public:
+  template <int k> friend class gtest_internal::Get;
+
+  tuple() : f0_(), f1_(), f2_() {}
+
+  explicit tuple(GTEST_BY_REF_(T0) f0, GTEST_BY_REF_(T1) f1,
+      GTEST_BY_REF_(T2) f2) : f0_(f0), f1_(f1), f2_(f2) {}
+
+  tuple(const tuple& t) : f0_(t.f0_), f1_(t.f1_), f2_(t.f2_) {}
+
+  template <GTEST_3_TYPENAMES_(U)>
+  tuple(const GTEST_3_TUPLE_(U)& t) : f0_(t.f0_), f1_(t.f1_), f2_(t.f2_) {}
+
+  tuple& operator=(const tuple& t) { return CopyFrom(t); }
+
+  template <GTEST_3_TYPENAMES_(U)>
+  tuple& operator=(const GTEST_3_TUPLE_(U)& t) {
+    return CopyFrom(t);
+  }
+
+  GTEST_DECLARE_TUPLE_AS_FRIEND_
+
+  template <GTEST_3_TYPENAMES_(U)>
+  tuple& CopyFrom(const GTEST_3_TUPLE_(U)& t) {
+    f0_ = t.f0_;
+    f1_ = t.f1_;
+    f2_ = t.f2_;
+    return *this;
+  }
+
+  T0 f0_;
+  T1 f1_;
+  T2 f2_;
+};
+
+template <GTEST_4_TYPENAMES_(T)>
+class GTEST_4_TUPLE_(T) {
+ public:
+  template <int k> friend class gtest_internal::Get;
+
+  tuple() : f0_(), f1_(), f2_(), f3_() {}
+
+  explicit tuple(GTEST_BY_REF_(T0) f0, GTEST_BY_REF_(T1) f1,
+      GTEST_BY_REF_(T2) f2, GTEST_BY_REF_(T3) f3) : f0_(f0), f1_(f1), f2_(f2),
+      f3_(f3) {}
+
+  tuple(const tuple& t) : f0_(t.f0_), f1_(t.f1_), f2_(t.f2_), f3_(t.f3_) {}
+
+  template <GTEST_4_TYPENAMES_(U)>
+  tuple(const GTEST_4_TUPLE_(U)& t) : f0_(t.f0_), f1_(t.f1_), f2_(t.f2_),
+      f3_(t.f3_) {}
+
+  tuple& operator=(const tuple& t) { return CopyFrom(t); }
+
+  template <GTEST_4_TYPENAMES_(U)>
+  tuple& operator=(const GTEST_4_TUPLE_(U)& t) {
+    return CopyFrom(t);
+  }
+
+  GTEST_DECLARE_TUPLE_AS_FRIEND_
+
+  template <GTEST_4_TYPENAMES_(U)>
+  tuple& CopyFrom(const GTEST_4_TUPLE_(U)& t) {
+    f0_ = t.f0_;
+    f1_ = t.f1_;
+    f2_ = t.f2_;
+    f3_ = t.f3_;
+    return *this;
+  }
+
+  T0 f0_;
+  T1 f1_;
+  T2 f2_;
+  T3 f3_;
+};
+
+template <GTEST_5_TYPENAMES_(T)>
+class GTEST_5_TUPLE_(T) {
+ public:
+  template <int k> friend class gtest_internal::Get;
+
+  tuple() : f0_(), f1_(), f2_(), f3_(), f4_() {}
+
+  explicit tuple(GTEST_BY_REF_(T0) f0, GTEST_BY_REF_(T1) f1,
+      GTEST_BY_REF_(T2) f2, GTEST_BY_REF_(T3) f3,
+      GTEST_BY_REF_(T4) f4) : f0_(f0), f1_(f1), f2_(f2), f3_(f3), f4_(f4) {}
+
+  tuple(const tuple& t) : f0_(t.f0_), f1_(t.f1_), f2_(t.f2_), f3_(t.f3_),
+      f4_(t.f4_) {}
+
+  template <GTEST_5_TYPENAMES_(U)>
+  tuple(const GTEST_5_TUPLE_(U)& t) : f0_(t.f0_), f1_(t.f1_), f2_(t.f2_),
+      f3_(t.f3_), f4_(t.f4_) {}
+
+  tuple& operator=(const tuple& t) { return CopyFrom(t); }
+
+  template <GTEST_5_TYPENAMES_(U)>
+  tuple& operator=(const GTEST_5_TUPLE_(U)& t) {
+    return CopyFrom(t);
+  }
+
+  GTEST_DECLARE_TUPLE_AS_FRIEND_
+
+  template <GTEST_5_TYPENAMES_(U)>
+  tuple& CopyFrom(const GTEST_5_TUPLE_(U)& t) {
+    f0_ = t.f0_;
+    f1_ = t.f1_;
+    f2_ = t.f2_;
+    f3_ = t.f3_;
+    f4_ = t.f4_;
+    return *this;
+  }
+
+  T0 f0_;
+  T1 f1_;
+  T2 f2_;
+  T3 f3_;
+  T4 f4_;
+};
+
+template <GTEST_6_TYPENAMES_(T)>
+class GTEST_6_TUPLE_(T) {
+ public:
+  template <int k> friend class gtest_internal::Get;
+
+  tuple() : f0_(), f1_(), f2_(), f3_(), f4_(), f5_() {}
+
+  explicit tuple(GTEST_BY_REF_(T0) f0, GTEST_BY_REF_(T1) f1,
+      GTEST_BY_REF_(T2) f2, GTEST_BY_REF_(T3) f3, GTEST_BY_REF_(T4) f4,
+      GTEST_BY_REF_(T5) f5) : f0_(f0), f1_(f1), f2_(f2), f3_(f3), f4_(f4),
+      f5_(f5) {}
+
+  tuple(const tuple& t) : f0_(t.f0_), f1_(t.f1_), f2_(t.f2_), f3_(t.f3_),
+      f4_(t.f4_), f5_(t.f5_) {}
+
+  template <GTEST_6_TYPENAMES_(U)>
+  tuple(const GTEST_6_TUPLE_(U)& t) : f0_(t.f0_), f1_(t.f1_), f2_(t.f2_),
+      f3_(t.f3_), f4_(t.f4_), f5_(t.f5_) {}
+
+  tuple& operator=(const tuple& t) { return CopyFrom(t); }
+
+  template <GTEST_6_TYPENAMES_(U)>
+  tuple& operator=(const GTEST_6_TUPLE_(U)& t) {
+    return CopyFrom(t);
+  }
+
+  GTEST_DECLARE_TUPLE_AS_FRIEND_
+
+  template <GTEST_6_TYPENAMES_(U)>
+  tuple& CopyFrom(const GTEST_6_TUPLE_(U)& t) {
+    f0_ = t.f0_;
+    f1_ = t.f1_;
+    f2_ = t.f2_;
+    f3_ = t.f3_;
+    f4_ = t.f4_;
+    f5_ = t.f5_;
+    return *this;
+  }
+
+  T0 f0_;
+  T1 f1_;
+  T2 f2_;
+  T3 f3_;
+  T4 f4_;
+  T5 f5_;
+};
+
+template <GTEST_7_TYPENAMES_(T)>
+class GTEST_7_TUPLE_(T) {
+ public:
+  template <int k> friend class gtest_internal::Get;
+
+  tuple() : f0_(), f1_(), f2_(), f3_(), f4_(), f5_(), f6_() {}
+
+  explicit tuple(GTEST_BY_REF_(T0) f0, GTEST_BY_REF_(T1) f1,
+      GTEST_BY_REF_(T2) f2, GTEST_BY_REF_(T3) f3, GTEST_BY_REF_(T4) f4,
+      GTEST_BY_REF_(T5) f5, GTEST_BY_REF_(T6) f6) : f0_(f0), f1_(f1), f2_(f2),
+      f3_(f3), f4_(f4), f5_(f5), f6_(f6) {}
+
+  tuple(const tuple& t) : f0_(t.f0_), f1_(t.f1_), f2_(t.f2_), f3_(t.f3_),
+      f4_(t.f4_), f5_(t.f5_), f6_(t.f6_) {}
+
+  template <GTEST_7_TYPENAMES_(U)>
+  tuple(const GTEST_7_TUPLE_(U)& t) : f0_(t.f0_), f1_(t.f1_), f2_(t.f2_),
+      f3_(t.f3_), f4_(t.f4_), f5_(t.f5_), f6_(t.f6_) {}
+
+  tuple& operator=(const tuple& t) { return CopyFrom(t); }
+
+  template <GTEST_7_TYPENAMES_(U)>
+  tuple& operator=(const GTEST_7_TUPLE_(U)& t) {
+    return CopyFrom(t);
+  }
+
+  GTEST_DECLARE_TUPLE_AS_FRIEND_
+
+  template <GTEST_7_TYPENAMES_(U)>
+  tuple& CopyFrom(const GTEST_7_TUPLE_(U)& t) {
+    f0_ = t.f0_;
+    f1_ = t.f1_;
+    f2_ = t.f2_;
+    f3_ = t.f3_;
+    f4_ = t.f4_;
+    f5_ = t.f5_;
+    f6_ = t.f6_;
+    return *this;
+  }
+
+  T0 f0_;
+  T1 f1_;
+  T2 f2_;
+  T3 f3_;
+  T4 f4_;
+  T5 f5_;
+  T6 f6_;
+};
+
+template <GTEST_8_TYPENAMES_(T)>
+class GTEST_8_TUPLE_(T) {
+ public:
+  template <int k> friend class gtest_internal::Get;
+
+  tuple() : f0_(), f1_(), f2_(), f3_(), f4_(), f5_(), f6_(), f7_() {}
+
+  explicit tuple(GTEST_BY_REF_(T0) f0, GTEST_BY_REF_(T1) f1,
+      GTEST_BY_REF_(T2) f2, GTEST_BY_REF_(T3) f3, GTEST_BY_REF_(T4) f4,
+      GTEST_BY_REF_(T5) f5, GTEST_BY_REF_(T6) f6,
+      GTEST_BY_REF_(T7) f7) : f0_(f0), f1_(f1), f2_(f2), f3_(f3), f4_(f4),
+      f5_(f5), f6_(f6), f7_(f7) {}
+
+  tuple(const tuple& t) : f0_(t.f0_), f1_(t.f1_), f2_(t.f2_), f3_(t.f3_),
+      f4_(t.f4_), f5_(t.f5_), f6_(t.f6_), f7_(t.f7_) {}
+
+  template <GTEST_8_TYPENAMES_(U)>
+  tuple(const GTEST_8_TUPLE_(U)& t) : f0_(t.f0_), f1_(t.f1_), f2_(t.f2_),
+      f3_(t.f3_), f4_(t.f4_), f5_(t.f5_), f6_(t.f6_), f7_(t.f7_) {}
+
+  tuple& operator=(const tuple& t) { return CopyFrom(t); }
+
+  template <GTEST_8_TYPENAMES_(U)>
+  tuple& operator=(const GTEST_8_TUPLE_(U)& t) {
+    return CopyFrom(t);
+  }
+
+  GTEST_DECLARE_TUPLE_AS_FRIEND_
+
+  template <GTEST_8_TYPENAMES_(U)>
+  tuple& CopyFrom(const GTEST_8_TUPLE_(U)& t) {
+    f0_ = t.f0_;
+    f1_ = t.f1_;
+    f2_ = t.f2_;
+    f3_ = t.f3_;
+    f4_ = t.f4_;
+    f5_ = t.f5_;
+    f6_ = t.f6_;
+    f7_ = t.f7_;
+    return *this;
+  }
+
+  T0 f0_;
+  T1 f1_;
+  T2 f2_;
+  T3 f3_;
+  T4 f4_;
+  T5 f5_;
+  T6 f6_;
+  T7 f7_;
+};
+
+template <GTEST_9_TYPENAMES_(T)>
+class GTEST_9_TUPLE_(T) {
+ public:
+  template <int k> friend class gtest_internal::Get;
+
+  tuple() : f0_(), f1_(), f2_(), f3_(), f4_(), f5_(), f6_(), f7_(), f8_() {}
+
+  explicit tuple(GTEST_BY_REF_(T0) f0, GTEST_BY_REF_(T1) f1,
+      GTEST_BY_REF_(T2) f2, GTEST_BY_REF_(T3) f3, GTEST_BY_REF_(T4) f4,
+      GTEST_BY_REF_(T5) f5, GTEST_BY_REF_(T6) f6, GTEST_BY_REF_(T7) f7,
+      GTEST_BY_REF_(T8) f8) : f0_(f0), f1_(f1), f2_(f2), f3_(f3), f4_(f4),
+      f5_(f5), f6_(f6), f7_(f7), f8_(f8) {}
+
+  tuple(const tuple& t) : f0_(t.f0_), f1_(t.f1_), f2_(t.f2_), f3_(t.f3_),
+      f4_(t.f4_), f5_(t.f5_), f6_(t.f6_), f7_(t.f7_), f8_(t.f8_) {}
+
+  template <GTEST_9_TYPENAMES_(U)>
+  tuple(const GTEST_9_TUPLE_(U)& t) : f0_(t.f0_), f1_(t.f1_), f2_(t.f2_),
+      f3_(t.f3_), f4_(t.f4_), f5_(t.f5_), f6_(t.f6_), f7_(t.f7_), f8_(t.f8_) {}
+
+  tuple& operator=(const tuple& t) { return CopyFrom(t); }
+
+  template <GTEST_9_TYPENAMES_(U)>
+  tuple& operator=(const GTEST_9_TUPLE_(U)& t) {
+    return CopyFrom(t);
+  }
+
+  GTEST_DECLARE_TUPLE_AS_FRIEND_
+
+  template <GTEST_9_TYPENAMES_(U)>
+  tuple& CopyFrom(const GTEST_9_TUPLE_(U)& t) {
+    f0_ = t.f0_;
+    f1_ = t.f1_;
+    f2_ = t.f2_;
+    f3_ = t.f3_;
+    f4_ = t.f4_;
+    f5_ = t.f5_;
+    f6_ = t.f6_;
+    f7_ = t.f7_;
+    f8_ = t.f8_;
+    return *this;
+  }
+
+  T0 f0_;
+  T1 f1_;
+  T2 f2_;
+  T3 f3_;
+  T4 f4_;
+  T5 f5_;
+  T6 f6_;
+  T7 f7_;
+  T8 f8_;
+};
+
+template <GTEST_10_TYPENAMES_(T)>
+class tuple {
+ public:
+  template <int k> friend class gtest_internal::Get;
+
+  tuple() : f0_(), f1_(), f2_(), f3_(), f4_(), f5_(), f6_(), f7_(), f8_(),
+      f9_() {}
+
+  explicit tuple(GTEST_BY_REF_(T0) f0, GTEST_BY_REF_(T1) f1,
+      GTEST_BY_REF_(T2) f2, GTEST_BY_REF_(T3) f3, GTEST_BY_REF_(T4) f4,
+      GTEST_BY_REF_(T5) f5, GTEST_BY_REF_(T6) f6, GTEST_BY_REF_(T7) f7,
+      GTEST_BY_REF_(T8) f8, GTEST_BY_REF_(T9) f9) : f0_(f0), f1_(f1), f2_(f2),
+      f3_(f3), f4_(f4), f5_(f5), f6_(f6), f7_(f7), f8_(f8), f9_(f9) {}
+
+  tuple(const tuple& t) : f0_(t.f0_), f1_(t.f1_), f2_(t.f2_), f3_(t.f3_),
+      f4_(t.f4_), f5_(t.f5_), f6_(t.f6_), f7_(t.f7_), f8_(t.f8_), f9_(t.f9_) {}
+
+  template <GTEST_10_TYPENAMES_(U)>
+  tuple(const GTEST_10_TUPLE_(U)& t) : f0_(t.f0_), f1_(t.f1_), f2_(t.f2_),
+      f3_(t.f3_), f4_(t.f4_), f5_(t.f5_), f6_(t.f6_), f7_(t.f7_), f8_(t.f8_),
+      f9_(t.f9_) {}
+
+  tuple& operator=(const tuple& t) { return CopyFrom(t); }
+
+  template <GTEST_10_TYPENAMES_(U)>
+  tuple& operator=(const GTEST_10_TUPLE_(U)& t) {
+    return CopyFrom(t);
+  }
+
+  GTEST_DECLARE_TUPLE_AS_FRIEND_
+
+  template <GTEST_10_TYPENAMES_(U)>
+  tuple& CopyFrom(const GTEST_10_TUPLE_(U)& t) {
+    f0_ = t.f0_;
+    f1_ = t.f1_;
+    f2_ = t.f2_;
+    f3_ = t.f3_;
+    f4_ = t.f4_;
+    f5_ = t.f5_;
+    f6_ = t.f6_;
+    f7_ = t.f7_;
+    f8_ = t.f8_;
+    f9_ = t.f9_;
+    return *this;
+  }
+
+  T0 f0_;
+  T1 f1_;
+  T2 f2_;
+  T3 f3_;
+  T4 f4_;
+  T5 f5_;
+  T6 f6_;
+  T7 f7_;
+  T8 f8_;
+  T9 f9_;
+};
+
+// 6.1.3.2 Tuple creation functions.
+
+// Known limitations: we don't support passing an
+// std::tr1::reference_wrapper<T> to make_tuple().  And we don't
+// implement tie().
+
+inline tuple<> make_tuple() { return tuple<>(); }
+
+template <GTEST_1_TYPENAMES_(T)>
+inline GTEST_1_TUPLE_(T) make_tuple(const T0& f0) {
+  return GTEST_1_TUPLE_(T)(f0);
+}
+
+template <GTEST_2_TYPENAMES_(T)>
+inline GTEST_2_TUPLE_(T) make_tuple(const T0& f0, const T1& f1) {
+  return GTEST_2_TUPLE_(T)(f0, f1);
+}
+
+template <GTEST_3_TYPENAMES_(T)>
+inline GTEST_3_TUPLE_(T) make_tuple(const T0& f0, const T1& f1, const T2& f2) {
+  return GTEST_3_TUPLE_(T)(f0, f1, f2);
+}
+
+template <GTEST_4_TYPENAMES_(T)>
+inline GTEST_4_TUPLE_(T) make_tuple(const T0& f0, const T1& f1, const T2& f2,
+    const T3& f3) {
+  return GTEST_4_TUPLE_(T)(f0, f1, f2, f3);
+}
+
+template <GTEST_5_TYPENAMES_(T)>
+inline GTEST_5_TUPLE_(T) make_tuple(const T0& f0, const T1& f1, const T2& f2,
+    const T3& f3, const T4& f4) {
+  return GTEST_5_TUPLE_(T)(f0, f1, f2, f3, f4);
+}
+
+template <GTEST_6_TYPENAMES_(T)>
+inline GTEST_6_TUPLE_(T) make_tuple(const T0& f0, const T1& f1, const T2& f2,
+    const T3& f3, const T4& f4, const T5& f5) {
+  return GTEST_6_TUPLE_(T)(f0, f1, f2, f3, f4, f5);
+}
+
+template <GTEST_7_TYPENAMES_(T)>
+inline GTEST_7_TUPLE_(T) make_tuple(const T0& f0, const T1& f1, const T2& f2,
+    const T3& f3, const T4& f4, const T5& f5, const T6& f6) {
+  return GTEST_7_TUPLE_(T)(f0, f1, f2, f3, f4, f5, f6);
+}
+
+template <GTEST_8_TYPENAMES_(T)>
+inline GTEST_8_TUPLE_(T) make_tuple(const T0& f0, const T1& f1, const T2& f2,
+    const T3& f3, const T4& f4, const T5& f5, const T6& f6, const T7& f7) {
+  return GTEST_8_TUPLE_(T)(f0, f1, f2, f3, f4, f5, f6, f7);
+}
+
+template <GTEST_9_TYPENAMES_(T)>
+inline GTEST_9_TUPLE_(T) make_tuple(const T0& f0, const T1& f1, const T2& f2,
+    const T3& f3, const T4& f4, const T5& f5, const T6& f6, const T7& f7,
+    const T8& f8) {
+  return GTEST_9_TUPLE_(T)(f0, f1, f2, f3, f4, f5, f6, f7, f8);
+}
+
+template <GTEST_10_TYPENAMES_(T)>
+inline GTEST_10_TUPLE_(T) make_tuple(const T0& f0, const T1& f1, const T2& f2,
+    const T3& f3, const T4& f4, const T5& f5, const T6& f6, const T7& f7,
+    const T8& f8, const T9& f9) {
+  return GTEST_10_TUPLE_(T)(f0, f1, f2, f3, f4, f5, f6, f7, f8, f9);
+}
+
+// 6.1.3.3 Tuple helper classes.
+
+template <typename Tuple> struct tuple_size;
+
+template <GTEST_0_TYPENAMES_(T)>
+struct tuple_size<GTEST_0_TUPLE_(T) > {
+  static const int value = 0;
+};
+
+template <GTEST_1_TYPENAMES_(T)>
+struct tuple_size<GTEST_1_TUPLE_(T) > {
+  static const int value = 1;
+};
+
+template <GTEST_2_TYPENAMES_(T)>
+struct tuple_size<GTEST_2_TUPLE_(T) > {
+  static const int value = 2;
+};
+
+template <GTEST_3_TYPENAMES_(T)>
+struct tuple_size<GTEST_3_TUPLE_(T) > {
+  static const int value = 3;
+};
+
+template <GTEST_4_TYPENAMES_(T)>
+struct tuple_size<GTEST_4_TUPLE_(T) > {
+  static const int value = 4;
+};
+
+template <GTEST_5_TYPENAMES_(T)>
+struct tuple_size<GTEST_5_TUPLE_(T) > {
+  static const int value = 5;
+};
+
+template <GTEST_6_TYPENAMES_(T)>
+struct tuple_size<GTEST_6_TUPLE_(T) > {
+  static const int value = 6;
+};
+
+template <GTEST_7_TYPENAMES_(T)>
+struct tuple_size<GTEST_7_TUPLE_(T) > {
+  static const int value = 7;
+};
+
+template <GTEST_8_TYPENAMES_(T)>
+struct tuple_size<GTEST_8_TUPLE_(T) > {
+  static const int value = 8;
+};
+
+template <GTEST_9_TYPENAMES_(T)>
+struct tuple_size<GTEST_9_TUPLE_(T) > {
+  static const int value = 9;
+};
+
+template <GTEST_10_TYPENAMES_(T)>
+struct tuple_size<GTEST_10_TUPLE_(T) > {
+  static const int value = 10;
+};
+
+template <int k, class Tuple>
+struct tuple_element {
+  typedef typename gtest_internal::TupleElement<
+      k < (tuple_size<Tuple>::value), k, Tuple>::type type;
+};
+
+#define GTEST_TUPLE_ELEMENT_(k, Tuple) typename tuple_element<k, Tuple >::type
+
+// 6.1.3.4 Element access.
+
+namespace gtest_internal {
+
+template <>
+class Get<0> {
+ public:
+  template <class Tuple>
+  static GTEST_ADD_REF_(GTEST_TUPLE_ELEMENT_(0, Tuple))
+  Field(Tuple& t) { return t.f0_; }  // NOLINT
+
+  template <class Tuple>
+  static GTEST_BY_REF_(GTEST_TUPLE_ELEMENT_(0, Tuple))
+  ConstField(const Tuple& t) { return t.f0_; }
+};
+
+template <>
+class Get<1> {
+ public:
+  template <class Tuple>
+  static GTEST_ADD_REF_(GTEST_TUPLE_ELEMENT_(1, Tuple))
+  Field(Tuple& t) { return t.f1_; }  // NOLINT
+
+  template <class Tuple>
+  static GTEST_BY_REF_(GTEST_TUPLE_ELEMENT_(1, Tuple))
+  ConstField(const Tuple& t) { return t.f1_; }
+};
+
+template <>
+class Get<2> {
+ public:
+  template <class Tuple>
+  static GTEST_ADD_REF_(GTEST_TUPLE_ELEMENT_(2, Tuple))
+  Field(Tuple& t) { return t.f2_; }  // NOLINT
+
+  template <class Tuple>
+  static GTEST_BY_REF_(GTEST_TUPLE_ELEMENT_(2, Tuple))
+  ConstField(const Tuple& t) { return t.f2_; }
+};
+
+template <>
+class Get<3> {
+ public:
+  template <class Tuple>
+  static GTEST_ADD_REF_(GTEST_TUPLE_ELEMENT_(3, Tuple))
+  Field(Tuple& t) { return t.f3_; }  // NOLINT
+
+  template <class Tuple>
+  static GTEST_BY_REF_(GTEST_TUPLE_ELEMENT_(3, Tuple))
+  ConstField(const Tuple& t) { return t.f3_; }
+};
+
+template <>
+class Get<4> {
+ public:
+  template <class Tuple>
+  static GTEST_ADD_REF_(GTEST_TUPLE_ELEMENT_(4, Tuple))
+  Field(Tuple& t) { return t.f4_; }  // NOLINT
+
+  template <class Tuple>
+  static GTEST_BY_REF_(GTEST_TUPLE_ELEMENT_(4, Tuple))
+  ConstField(const Tuple& t) { return t.f4_; }
+};
+
+template <>
+class Get<5> {
+ public:
+  template <class Tuple>
+  static GTEST_ADD_REF_(GTEST_TUPLE_ELEMENT_(5, Tuple))
+  Field(Tuple& t) { return t.f5_; }  // NOLINT
+
+  template <class Tuple>
+  static GTEST_BY_REF_(GTEST_TUPLE_ELEMENT_(5, Tuple))
+  ConstField(const Tuple& t) { return t.f5_; }
+};
+
+template <>
+class Get<6> {
+ public:
+  template <class Tuple>
+  static GTEST_ADD_REF_(GTEST_TUPLE_ELEMENT_(6, Tuple))
+  Field(Tuple& t) { return t.f6_; }  // NOLINT
+
+  template <class Tuple>
+  static GTEST_BY_REF_(GTEST_TUPLE_ELEMENT_(6, Tuple))
+  ConstField(const Tuple& t) { return t.f6_; }
+};
+
+template <>
+class Get<7> {
+ public:
+  template <class Tuple>
+  static GTEST_ADD_REF_(GTEST_TUPLE_ELEMENT_(7, Tuple))
+  Field(Tuple& t) { return t.f7_; }  // NOLINT
+
+  template <class Tuple>
+  static GTEST_BY_REF_(GTEST_TUPLE_ELEMENT_(7, Tuple))
+  ConstField(const Tuple& t) { return t.f7_; }
+};
+
+template <>
+class Get<8> {
+ public:
+  template <class Tuple>
+  static GTEST_ADD_REF_(GTEST_TUPLE_ELEMENT_(8, Tuple))
+  Field(Tuple& t) { return t.f8_; }  // NOLINT
+
+  template <class Tuple>
+  static GTEST_BY_REF_(GTEST_TUPLE_ELEMENT_(8, Tuple))
+  ConstField(const Tuple& t) { return t.f8_; }
+};
+
+template <>
+class Get<9> {
+ public:
+  template <class Tuple>
+  static GTEST_ADD_REF_(GTEST_TUPLE_ELEMENT_(9, Tuple))
+  Field(Tuple& t) { return t.f9_; }  // NOLINT
+
+  template <class Tuple>
+  static GTEST_BY_REF_(GTEST_TUPLE_ELEMENT_(9, Tuple))
+  ConstField(const Tuple& t) { return t.f9_; }
+};
+
+}  // namespace gtest_internal
+
+template <int k, GTEST_10_TYPENAMES_(T)>
+GTEST_ADD_REF_(GTEST_TUPLE_ELEMENT_(k, GTEST_10_TUPLE_(T)))
+get(GTEST_10_TUPLE_(T)& t) {
+  return gtest_internal::Get<k>::Field(t);
+}
+
+template <int k, GTEST_10_TYPENAMES_(T)>
+GTEST_BY_REF_(GTEST_TUPLE_ELEMENT_(k,  GTEST_10_TUPLE_(T)))
+get(const GTEST_10_TUPLE_(T)& t) {
+  return gtest_internal::Get<k>::ConstField(t);
+}
+
+// 6.1.3.5 Relational operators
+
+// We only implement == and !=, as we don't have a need for the rest yet.
+
+namespace gtest_internal {
+
+// SameSizeTuplePrefixComparator<k, k>::Eq(t1, t2) returns true if the
+// first k fields of t1 equals the first k fields of t2.
+// SameSizeTuplePrefixComparator(k1, k2) would be a compiler error if
+// k1 != k2.
+template <int kSize1, int kSize2>
+struct SameSizeTuplePrefixComparator;
+
+template <>
+struct SameSizeTuplePrefixComparator<0, 0> {
+  template <class Tuple1, class Tuple2>
+  static bool Eq(const Tuple1& /* t1 */, const Tuple2& /* t2 */) {
+    return true;
+  }
+};
+
+template <int k>
+struct SameSizeTuplePrefixComparator<k, k> {
+  template <class Tuple1, class Tuple2>
+  static bool Eq(const Tuple1& t1, const Tuple2& t2) {
+    return SameSizeTuplePrefixComparator<k - 1, k - 1>::Eq(t1, t2) &&
+        ::std::tr1::get<k - 1>(t1) == ::std::tr1::get<k - 1>(t2);
+  }
+};
+
+}  // namespace gtest_internal
+
+template <GTEST_10_TYPENAMES_(T), GTEST_10_TYPENAMES_(U)>
+inline bool operator==(const GTEST_10_TUPLE_(T)& t,
+                       const GTEST_10_TUPLE_(U)& u) {
+  return gtest_internal::SameSizeTuplePrefixComparator<
+      tuple_size<GTEST_10_TUPLE_(T) >::value,
+      tuple_size<GTEST_10_TUPLE_(U) >::value>::Eq(t, u);
+}
+
+template <GTEST_10_TYPENAMES_(T), GTEST_10_TYPENAMES_(U)>
+inline bool operator!=(const GTEST_10_TUPLE_(T)& t,
+                       const GTEST_10_TUPLE_(U)& u) { return !(t == u); }
+
+// 6.1.4 Pairs.
+// Unimplemented.
+
+}  // namespace tr1
+}  // namespace std
+
+#undef GTEST_0_TUPLE_
+#undef GTEST_1_TUPLE_
+#undef GTEST_2_TUPLE_
+#undef GTEST_3_TUPLE_
+#undef GTEST_4_TUPLE_
+#undef GTEST_5_TUPLE_
+#undef GTEST_6_TUPLE_
+#undef GTEST_7_TUPLE_
+#undef GTEST_8_TUPLE_
+#undef GTEST_9_TUPLE_
+#undef GTEST_10_TUPLE_
+
+#undef GTEST_0_TYPENAMES_
+#undef GTEST_1_TYPENAMES_
+#undef GTEST_2_TYPENAMES_
+#undef GTEST_3_TYPENAMES_
+#undef GTEST_4_TYPENAMES_
+#undef GTEST_5_TYPENAMES_
+#undef GTEST_6_TYPENAMES_
+#undef GTEST_7_TYPENAMES_
+#undef GTEST_8_TYPENAMES_
+#undef GTEST_9_TYPENAMES_
+#undef GTEST_10_TYPENAMES_
+
+#undef GTEST_DECLARE_TUPLE_AS_FRIEND_
+#undef GTEST_BY_REF_
+#undef GTEST_ADD_REF_
+#undef GTEST_TUPLE_ELEMENT_
+
+#endif  // GTEST_INCLUDE_GTEST_INTERNAL_GTEST_TUPLE_H_
diff --git a/test/gtest/include/gtest/internal/gtest-tuple.h.pump b/test/gtest/include/gtest/internal/gtest-tuple.h.pump
new file mode 100644
index 0000000..c7d9e03
--- /dev/null
+++ b/test/gtest/include/gtest/internal/gtest-tuple.h.pump
@@ -0,0 +1,339 @@
+$$ -*- mode: c++; -*-
+$var n = 10  $$ Maximum number of tuple fields we want to support.
+$$ This meta comment fixes auto-indentation in Emacs. }}
+// Copyright 2009 Google Inc.
+// All Rights Reserved.
+//
+// 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: wan at google.com (Zhanyong Wan)
+
+// Implements a subset of TR1 tuple needed by Google Test and Google Mock.
+
+#ifndef GTEST_INCLUDE_GTEST_INTERNAL_GTEST_TUPLE_H_
+#define GTEST_INCLUDE_GTEST_INTERNAL_GTEST_TUPLE_H_
+
+#include <utility>  // For ::std::pair.
+
+// The compiler used in Symbian has a bug that prevents us from declaring the
+// tuple template as a friend (it complains that tuple is redefined).  This
+// hack bypasses the bug by declaring the members that should otherwise be
+// private as public.
+// Sun Studio versions < 12 also have the above bug.
+#if defined(__SYMBIAN32__) || (defined(__SUNPRO_CC) && __SUNPRO_CC < 0x590)
+# define GTEST_DECLARE_TUPLE_AS_FRIEND_ public:
+#else
+# define GTEST_DECLARE_TUPLE_AS_FRIEND_ \
+    template <GTEST_$(n)_TYPENAMES_(U)> friend class tuple; \
+   private:
+#endif
+
+
+$range i 0..n-1
+$range j 0..n
+$range k 1..n
+// GTEST_n_TUPLE_(T) is the type of an n-tuple.
+#define GTEST_0_TUPLE_(T) tuple<>
+
+$for k [[
+$range m 0..k-1
+$range m2 k..n-1
+#define GTEST_$(k)_TUPLE_(T) tuple<$for m, [[T##$m]]$for m2 [[, void]]>
+
+]]
+
+// GTEST_n_TYPENAMES_(T) declares a list of n typenames.
+
+$for j [[
+$range m 0..j-1
+#define GTEST_$(j)_TYPENAMES_(T) $for m, [[typename T##$m]]
+
+
+]]
+
+// In theory, defining stuff in the ::std namespace is undefined
+// behavior.  We can do this as we are playing the role of a standard
+// library vendor.
+namespace std {
+namespace tr1 {
+
+template <$for i, [[typename T$i = void]]>
+class tuple;
+
+// Anything in namespace gtest_internal is Google Test's INTERNAL
+// IMPLEMENTATION DETAIL and MUST NOT BE USED DIRECTLY in user code.
+namespace gtest_internal {
+
+// ByRef<T>::type is T if T is a reference; otherwise it's const T&.
+template <typename T>
+struct ByRef { typedef const T& type; };  // NOLINT
+template <typename T>
+struct ByRef<T&> { typedef T& type; };  // NOLINT
+
+// A handy wrapper for ByRef.
+#define GTEST_BY_REF_(T) typename ::std::tr1::gtest_internal::ByRef<T>::type
+
+// AddRef<T>::type is T if T is a reference; otherwise it's T&.  This
+// is the same as tr1::add_reference<T>::type.
+template <typename T>
+struct AddRef { typedef T& type; };  // NOLINT
+template <typename T>
+struct AddRef<T&> { typedef T& type; };  // NOLINT
+
+// A handy wrapper for AddRef.
+#define GTEST_ADD_REF_(T) typename ::std::tr1::gtest_internal::AddRef<T>::type
+
+// A helper for implementing get<k>().
+template <int k> class Get;
+
+// A helper for implementing tuple_element<k, T>.  kIndexValid is true
+// iff k < the number of fields in tuple type T.
+template <bool kIndexValid, int kIndex, class Tuple>
+struct TupleElement;
+
+
+$for i [[
+template <GTEST_$(n)_TYPENAMES_(T)>
+struct TupleElement<true, $i, GTEST_$(n)_TUPLE_(T) > {
+  typedef T$i type;
+};
+
+
+]]
+}  // namespace gtest_internal
+
+template <>
+class tuple<> {
+ public:
+  tuple() {}
+  tuple(const tuple& /* t */)  {}
+  tuple& operator=(const tuple& /* t */) { return *this; }
+};
+
+
+$for k [[
+$range m 0..k-1
+template <GTEST_$(k)_TYPENAMES_(T)>
+class $if k < n [[GTEST_$(k)_TUPLE_(T)]] $else [[tuple]] {
+ public:
+  template <int k> friend class gtest_internal::Get;
+
+  tuple() : $for m, [[f$(m)_()]] {}
+
+  explicit tuple($for m, [[GTEST_BY_REF_(T$m) f$m]]) : [[]]
+$for m, [[f$(m)_(f$m)]] {}
+
+  tuple(const tuple& t) : $for m, [[f$(m)_(t.f$(m)_)]] {}
+
+  template <GTEST_$(k)_TYPENAMES_(U)>
+  tuple(const GTEST_$(k)_TUPLE_(U)& t) : $for m, [[f$(m)_(t.f$(m)_)]] {}
+
+$if k == 2 [[
+  template <typename U0, typename U1>
+  tuple(const ::std::pair<U0, U1>& p) : f0_(p.first), f1_(p.second) {}
+
+]]
+
+  tuple& operator=(const tuple& t) { return CopyFrom(t); }
+
+  template <GTEST_$(k)_TYPENAMES_(U)>
+  tuple& operator=(const GTEST_$(k)_TUPLE_(U)& t) {
+    return CopyFrom(t);
+  }
+
+$if k == 2 [[
+  template <typename U0, typename U1>
+  tuple& operator=(const ::std::pair<U0, U1>& p) {
+    f0_ = p.first;
+    f1_ = p.second;
+    return *this;
+  }
+
+]]
+
+  GTEST_DECLARE_TUPLE_AS_FRIEND_
+
+  template <GTEST_$(k)_TYPENAMES_(U)>
+  tuple& CopyFrom(const GTEST_$(k)_TUPLE_(U)& t) {
+
+$for m [[
+    f$(m)_ = t.f$(m)_;
+
+]]
+    return *this;
+  }
+
+
+$for m [[
+  T$m f$(m)_;
+
+]]
+};
+
+
+]]
+// 6.1.3.2 Tuple creation functions.
+
+// Known limitations: we don't support passing an
+// std::tr1::reference_wrapper<T> to make_tuple().  And we don't
+// implement tie().
+
+inline tuple<> make_tuple() { return tuple<>(); }
+
+$for k [[
+$range m 0..k-1
+
+template <GTEST_$(k)_TYPENAMES_(T)>
+inline GTEST_$(k)_TUPLE_(T) make_tuple($for m, [[const T$m& f$m]]) {
+  return GTEST_$(k)_TUPLE_(T)($for m, [[f$m]]);
+}
+
+]]
+
+// 6.1.3.3 Tuple helper classes.
+
+template <typename Tuple> struct tuple_size;
+
+
+$for j [[
+template <GTEST_$(j)_TYPENAMES_(T)>
+struct tuple_size<GTEST_$(j)_TUPLE_(T) > {
+  static const int value = $j;
+};
+
+
+]]
+template <int k, class Tuple>
+struct tuple_element {
+  typedef typename gtest_internal::TupleElement<
+      k < (tuple_size<Tuple>::value), k, Tuple>::type type;
+};
+
+#define GTEST_TUPLE_ELEMENT_(k, Tuple) typename tuple_element<k, Tuple >::type
+
+// 6.1.3.4 Element access.
+
+namespace gtest_internal {
+
+
+$for i [[
+template <>
+class Get<$i> {
+ public:
+  template <class Tuple>
+  static GTEST_ADD_REF_(GTEST_TUPLE_ELEMENT_($i, Tuple))
+  Field(Tuple& t) { return t.f$(i)_; }  // NOLINT
+
+  template <class Tuple>
+  static GTEST_BY_REF_(GTEST_TUPLE_ELEMENT_($i, Tuple))
+  ConstField(const Tuple& t) { return t.f$(i)_; }
+};
+
+
+]]
+}  // namespace gtest_internal
+
+template <int k, GTEST_$(n)_TYPENAMES_(T)>
+GTEST_ADD_REF_(GTEST_TUPLE_ELEMENT_(k, GTEST_$(n)_TUPLE_(T)))
+get(GTEST_$(n)_TUPLE_(T)& t) {
+  return gtest_internal::Get<k>::Field(t);
+}
+
+template <int k, GTEST_$(n)_TYPENAMES_(T)>
+GTEST_BY_REF_(GTEST_TUPLE_ELEMENT_(k,  GTEST_$(n)_TUPLE_(T)))
+get(const GTEST_$(n)_TUPLE_(T)& t) {
+  return gtest_internal::Get<k>::ConstField(t);
+}
+
+// 6.1.3.5 Relational operators
+
+// We only implement == and !=, as we don't have a need for the rest yet.
+
+namespace gtest_internal {
+
+// SameSizeTuplePrefixComparator<k, k>::Eq(t1, t2) returns true if the
+// first k fields of t1 equals the first k fields of t2.
+// SameSizeTuplePrefixComparator(k1, k2) would be a compiler error if
+// k1 != k2.
+template <int kSize1, int kSize2>
+struct SameSizeTuplePrefixComparator;
+
+template <>
+struct SameSizeTuplePrefixComparator<0, 0> {
+  template <class Tuple1, class Tuple2>
+  static bool Eq(const Tuple1& /* t1 */, const Tuple2& /* t2 */) {
+    return true;
+  }
+};
+
+template <int k>
+struct SameSizeTuplePrefixComparator<k, k> {
+  template <class Tuple1, class Tuple2>
+  static bool Eq(const Tuple1& t1, const Tuple2& t2) {
+    return SameSizeTuplePrefixComparator<k - 1, k - 1>::Eq(t1, t2) &&
+        ::std::tr1::get<k - 1>(t1) == ::std::tr1::get<k - 1>(t2);
+  }
+};
+
+}  // namespace gtest_internal
+
+template <GTEST_$(n)_TYPENAMES_(T), GTEST_$(n)_TYPENAMES_(U)>
+inline bool operator==(const GTEST_$(n)_TUPLE_(T)& t,
+                       const GTEST_$(n)_TUPLE_(U)& u) {
+  return gtest_internal::SameSizeTuplePrefixComparator<
+      tuple_size<GTEST_$(n)_TUPLE_(T) >::value,
+      tuple_size<GTEST_$(n)_TUPLE_(U) >::value>::Eq(t, u);
+}
+
+template <GTEST_$(n)_TYPENAMES_(T), GTEST_$(n)_TYPENAMES_(U)>
+inline bool operator!=(const GTEST_$(n)_TUPLE_(T)& t,
+                       const GTEST_$(n)_TUPLE_(U)& u) { return !(t == u); }
+
+// 6.1.4 Pairs.
+// Unimplemented.
+
+}  // namespace tr1
+}  // namespace std
+
+
+$for j [[
+#undef GTEST_$(j)_TUPLE_
+
+]]
+
+
+$for j [[
+#undef GTEST_$(j)_TYPENAMES_
+
+]]
+
+#undef GTEST_DECLARE_TUPLE_AS_FRIEND_
+#undef GTEST_BY_REF_
+#undef GTEST_ADD_REF_
+#undef GTEST_TUPLE_ELEMENT_
+
+#endif  // GTEST_INCLUDE_GTEST_INTERNAL_GTEST_TUPLE_H_
diff --git a/test/gtest/include/gtest/internal/gtest-type-util.h b/test/gtest/include/gtest/internal/gtest-type-util.h
new file mode 100644
index 0000000..e46f7cf
--- /dev/null
+++ b/test/gtest/include/gtest/internal/gtest-type-util.h
@@ -0,0 +1,3331 @@
+// This file was GENERATED by command:
+//     pump.py gtest-type-util.h.pump
+// DO NOT EDIT BY HAND!!!
+
+// Copyright 2008 Google Inc.
+// All Rights Reserved.
+//
+// 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: wan at google.com (Zhanyong Wan)
+
+// Type utilities needed for implementing typed and type-parameterized
+// tests.  This file is generated by a SCRIPT.  DO NOT EDIT BY HAND!
+//
+// Currently we support at most 50 types in a list, and at most 50
+// type-parameterized tests in one type-parameterized test case.
+// Please contact googletestframework at googlegroups.com if you need
+// more.
+
+#ifndef GTEST_INCLUDE_GTEST_INTERNAL_GTEST_TYPE_UTIL_H_
+#define GTEST_INCLUDE_GTEST_INTERNAL_GTEST_TYPE_UTIL_H_
+
+#include "gtest/internal/gtest-port.h"
+
+// #ifdef __GNUC__ is too general here.  It is possible to use gcc without using
+// libstdc++ (which is where cxxabi.h comes from).
+# if GTEST_HAS_CXXABI_H_
+#  include <cxxabi.h>
+# elif defined(__HP_aCC)
+#  include <acxx_demangle.h>
+# endif  // GTEST_HASH_CXXABI_H_
+
+namespace testing {
+namespace internal {
+
+// GetTypeName<T>() returns a human-readable name of type T.
+// NB: This function is also used in Google Mock, so don't move it inside of
+// the typed-test-only section below.
+template <typename T>
+std::string GetTypeName() {
+# if GTEST_HAS_RTTI
+
+  const char* const name = typeid(T).name();
+#  if GTEST_HAS_CXXABI_H_ || defined(__HP_aCC)
+  int status = 0;
+  // gcc's implementation of typeid(T).name() mangles the type name,
+  // so we have to demangle it.
+#   if GTEST_HAS_CXXABI_H_
+  using abi::__cxa_demangle;
+#   endif  // GTEST_HAS_CXXABI_H_
+  char* const readable_name = __cxa_demangle(name, 0, 0, &status);
+  const std::string name_str(status == 0 ? readable_name : name);
+  free(readable_name);
+  return name_str;
+#  else
+  return name;
+#  endif  // GTEST_HAS_CXXABI_H_ || __HP_aCC
+
+# else
+
+  return "<type>";
+
+# endif  // GTEST_HAS_RTTI
+}
+
+#if GTEST_HAS_TYPED_TEST || GTEST_HAS_TYPED_TEST_P
+
+// AssertyTypeEq<T1, T2>::type is defined iff T1 and T2 are the same
+// type.  This can be used as a compile-time assertion to ensure that
+// two types are equal.
+
+template <typename T1, typename T2>
+struct AssertTypeEq;
+
+template <typename T>
+struct AssertTypeEq<T, T> {
+  typedef bool type;
+};
+
+// A unique type used as the default value for the arguments of class
+// template Types.  This allows us to simulate variadic templates
+// (e.g. Types<int>, Type<int, double>, and etc), which C++ doesn't
+// support directly.
+struct None {};
+
+// The following family of struct and struct templates are used to
+// represent type lists.  In particular, TypesN<T1, T2, ..., TN>
+// represents a type list with N types (T1, T2, ..., and TN) in it.
+// Except for Types0, every struct in the family has two member types:
+// Head for the first type in the list, and Tail for the rest of the
+// list.
+
+// The empty type list.
+struct Types0 {};
+
+// Type lists of length 1, 2, 3, and so on.
+
+template <typename T1>
+struct Types1 {
+  typedef T1 Head;
+  typedef Types0 Tail;
+};
+template <typename T1, typename T2>
+struct Types2 {
+  typedef T1 Head;
+  typedef Types1<T2> Tail;
+};
+
+template <typename T1, typename T2, typename T3>
+struct Types3 {
+  typedef T1 Head;
+  typedef Types2<T2, T3> Tail;
+};
+
+template <typename T1, typename T2, typename T3, typename T4>
+struct Types4 {
+  typedef T1 Head;
+  typedef Types3<T2, T3, T4> Tail;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5>
+struct Types5 {
+  typedef T1 Head;
+  typedef Types4<T2, T3, T4, T5> Tail;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6>
+struct Types6 {
+  typedef T1 Head;
+  typedef Types5<T2, T3, T4, T5, T6> Tail;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7>
+struct Types7 {
+  typedef T1 Head;
+  typedef Types6<T2, T3, T4, T5, T6, T7> Tail;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8>
+struct Types8 {
+  typedef T1 Head;
+  typedef Types7<T2, T3, T4, T5, T6, T7, T8> Tail;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9>
+struct Types9 {
+  typedef T1 Head;
+  typedef Types8<T2, T3, T4, T5, T6, T7, T8, T9> Tail;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10>
+struct Types10 {
+  typedef T1 Head;
+  typedef Types9<T2, T3, T4, T5, T6, T7, T8, T9, T10> Tail;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11>
+struct Types11 {
+  typedef T1 Head;
+  typedef Types10<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11> Tail;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12>
+struct Types12 {
+  typedef T1 Head;
+  typedef Types11<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12> Tail;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13>
+struct Types13 {
+  typedef T1 Head;
+  typedef Types12<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13> Tail;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14>
+struct Types14 {
+  typedef T1 Head;
+  typedef Types13<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14> Tail;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15>
+struct Types15 {
+  typedef T1 Head;
+  typedef Types14<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+      T15> Tail;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16>
+struct Types16 {
+  typedef T1 Head;
+  typedef Types15<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+      T16> Tail;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17>
+struct Types17 {
+  typedef T1 Head;
+  typedef Types16<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+      T16, T17> Tail;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18>
+struct Types18 {
+  typedef T1 Head;
+  typedef Types17<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+      T16, T17, T18> Tail;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19>
+struct Types19 {
+  typedef T1 Head;
+  typedef Types18<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+      T16, T17, T18, T19> Tail;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20>
+struct Types20 {
+  typedef T1 Head;
+  typedef Types19<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+      T16, T17, T18, T19, T20> Tail;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21>
+struct Types21 {
+  typedef T1 Head;
+  typedef Types20<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+      T16, T17, T18, T19, T20, T21> Tail;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22>
+struct Types22 {
+  typedef T1 Head;
+  typedef Types21<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+      T16, T17, T18, T19, T20, T21, T22> Tail;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23>
+struct Types23 {
+  typedef T1 Head;
+  typedef Types22<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+      T16, T17, T18, T19, T20, T21, T22, T23> Tail;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24>
+struct Types24 {
+  typedef T1 Head;
+  typedef Types23<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+      T16, T17, T18, T19, T20, T21, T22, T23, T24> Tail;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25>
+struct Types25 {
+  typedef T1 Head;
+  typedef Types24<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+      T16, T17, T18, T19, T20, T21, T22, T23, T24, T25> Tail;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26>
+struct Types26 {
+  typedef T1 Head;
+  typedef Types25<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+      T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26> Tail;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27>
+struct Types27 {
+  typedef T1 Head;
+  typedef Types26<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+      T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27> Tail;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28>
+struct Types28 {
+  typedef T1 Head;
+  typedef Types27<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+      T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28> Tail;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29>
+struct Types29 {
+  typedef T1 Head;
+  typedef Types28<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+      T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28,
+      T29> Tail;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30>
+struct Types30 {
+  typedef T1 Head;
+  typedef Types29<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+      T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29,
+      T30> Tail;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31>
+struct Types31 {
+  typedef T1 Head;
+  typedef Types30<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+      T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29,
+      T30, T31> Tail;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32>
+struct Types32 {
+  typedef T1 Head;
+  typedef Types31<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+      T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29,
+      T30, T31, T32> Tail;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32, typename T33>
+struct Types33 {
+  typedef T1 Head;
+  typedef Types32<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+      T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29,
+      T30, T31, T32, T33> Tail;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32, typename T33, typename T34>
+struct Types34 {
+  typedef T1 Head;
+  typedef Types33<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+      T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29,
+      T30, T31, T32, T33, T34> Tail;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32, typename T33, typename T34, typename T35>
+struct Types35 {
+  typedef T1 Head;
+  typedef Types34<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+      T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29,
+      T30, T31, T32, T33, T34, T35> Tail;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32, typename T33, typename T34, typename T35,
+    typename T36>
+struct Types36 {
+  typedef T1 Head;
+  typedef Types35<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+      T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29,
+      T30, T31, T32, T33, T34, T35, T36> Tail;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32, typename T33, typename T34, typename T35,
+    typename T36, typename T37>
+struct Types37 {
+  typedef T1 Head;
+  typedef Types36<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+      T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29,
+      T30, T31, T32, T33, T34, T35, T36, T37> Tail;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32, typename T33, typename T34, typename T35,
+    typename T36, typename T37, typename T38>
+struct Types38 {
+  typedef T1 Head;
+  typedef Types37<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+      T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29,
+      T30, T31, T32, T33, T34, T35, T36, T37, T38> Tail;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32, typename T33, typename T34, typename T35,
+    typename T36, typename T37, typename T38, typename T39>
+struct Types39 {
+  typedef T1 Head;
+  typedef Types38<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+      T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29,
+      T30, T31, T32, T33, T34, T35, T36, T37, T38, T39> Tail;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32, typename T33, typename T34, typename T35,
+    typename T36, typename T37, typename T38, typename T39, typename T40>
+struct Types40 {
+  typedef T1 Head;
+  typedef Types39<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+      T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29,
+      T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40> Tail;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32, typename T33, typename T34, typename T35,
+    typename T36, typename T37, typename T38, typename T39, typename T40,
+    typename T41>
+struct Types41 {
+  typedef T1 Head;
+  typedef Types40<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+      T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29,
+      T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41> Tail;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32, typename T33, typename T34, typename T35,
+    typename T36, typename T37, typename T38, typename T39, typename T40,
+    typename T41, typename T42>
+struct Types42 {
+  typedef T1 Head;
+  typedef Types41<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+      T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29,
+      T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41, T42> Tail;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32, typename T33, typename T34, typename T35,
+    typename T36, typename T37, typename T38, typename T39, typename T40,
+    typename T41, typename T42, typename T43>
+struct Types43 {
+  typedef T1 Head;
+  typedef Types42<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+      T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29,
+      T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41, T42,
+      T43> Tail;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32, typename T33, typename T34, typename T35,
+    typename T36, typename T37, typename T38, typename T39, typename T40,
+    typename T41, typename T42, typename T43, typename T44>
+struct Types44 {
+  typedef T1 Head;
+  typedef Types43<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+      T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29,
+      T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41, T42, T43,
+      T44> Tail;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32, typename T33, typename T34, typename T35,
+    typename T36, typename T37, typename T38, typename T39, typename T40,
+    typename T41, typename T42, typename T43, typename T44, typename T45>
+struct Types45 {
+  typedef T1 Head;
+  typedef Types44<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+      T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29,
+      T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41, T42, T43,
+      T44, T45> Tail;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32, typename T33, typename T34, typename T35,
+    typename T36, typename T37, typename T38, typename T39, typename T40,
+    typename T41, typename T42, typename T43, typename T44, typename T45,
+    typename T46>
+struct Types46 {
+  typedef T1 Head;
+  typedef Types45<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+      T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29,
+      T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41, T42, T43,
+      T44, T45, T46> Tail;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32, typename T33, typename T34, typename T35,
+    typename T36, typename T37, typename T38, typename T39, typename T40,
+    typename T41, typename T42, typename T43, typename T44, typename T45,
+    typename T46, typename T47>
+struct Types47 {
+  typedef T1 Head;
+  typedef Types46<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+      T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29,
+      T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41, T42, T43,
+      T44, T45, T46, T47> Tail;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32, typename T33, typename T34, typename T35,
+    typename T36, typename T37, typename T38, typename T39, typename T40,
+    typename T41, typename T42, typename T43, typename T44, typename T45,
+    typename T46, typename T47, typename T48>
+struct Types48 {
+  typedef T1 Head;
+  typedef Types47<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+      T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29,
+      T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41, T42, T43,
+      T44, T45, T46, T47, T48> Tail;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32, typename T33, typename T34, typename T35,
+    typename T36, typename T37, typename T38, typename T39, typename T40,
+    typename T41, typename T42, typename T43, typename T44, typename T45,
+    typename T46, typename T47, typename T48, typename T49>
+struct Types49 {
+  typedef T1 Head;
+  typedef Types48<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+      T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29,
+      T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41, T42, T43,
+      T44, T45, T46, T47, T48, T49> Tail;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32, typename T33, typename T34, typename T35,
+    typename T36, typename T37, typename T38, typename T39, typename T40,
+    typename T41, typename T42, typename T43, typename T44, typename T45,
+    typename T46, typename T47, typename T48, typename T49, typename T50>
+struct Types50 {
+  typedef T1 Head;
+  typedef Types49<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+      T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29,
+      T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41, T42, T43,
+      T44, T45, T46, T47, T48, T49, T50> Tail;
+};
+
+
+}  // namespace internal
+
+// We don't want to require the users to write TypesN<...> directly,
+// as that would require them to count the length.  Types<...> is much
+// easier to write, but generates horrible messages when there is a
+// compiler error, as gcc insists on printing out each template
+// argument, even if it has the default value (this means Types<int>
+// will appear as Types<int, None, None, ..., None> in the compiler
+// errors).
+//
+// Our solution is to combine the best part of the two approaches: a
+// user would write Types<T1, ..., TN>, and Google Test will translate
+// that to TypesN<T1, ..., TN> internally to make error messages
+// readable.  The translation is done by the 'type' member of the
+// Types template.
+template <typename T1 = internal::None, typename T2 = internal::None,
+    typename T3 = internal::None, typename T4 = internal::None,
+    typename T5 = internal::None, typename T6 = internal::None,
+    typename T7 = internal::None, typename T8 = internal::None,
+    typename T9 = internal::None, typename T10 = internal::None,
+    typename T11 = internal::None, typename T12 = internal::None,
+    typename T13 = internal::None, typename T14 = internal::None,
+    typename T15 = internal::None, typename T16 = internal::None,
+    typename T17 = internal::None, typename T18 = internal::None,
+    typename T19 = internal::None, typename T20 = internal::None,
+    typename T21 = internal::None, typename T22 = internal::None,
+    typename T23 = internal::None, typename T24 = internal::None,
+    typename T25 = internal::None, typename T26 = internal::None,
+    typename T27 = internal::None, typename T28 = internal::None,
+    typename T29 = internal::None, typename T30 = internal::None,
+    typename T31 = internal::None, typename T32 = internal::None,
+    typename T33 = internal::None, typename T34 = internal::None,
+    typename T35 = internal::None, typename T36 = internal::None,
+    typename T37 = internal::None, typename T38 = internal::None,
+    typename T39 = internal::None, typename T40 = internal::None,
+    typename T41 = internal::None, typename T42 = internal::None,
+    typename T43 = internal::None, typename T44 = internal::None,
+    typename T45 = internal::None, typename T46 = internal::None,
+    typename T47 = internal::None, typename T48 = internal::None,
+    typename T49 = internal::None, typename T50 = internal::None>
+struct Types {
+  typedef internal::Types50<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12,
+      T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26,
+      T27, T28, T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40,
+      T41, T42, T43, T44, T45, T46, T47, T48, T49, T50> type;
+};
+
+template <>
+struct Types<internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None> {
+  typedef internal::Types0 type;
+};
+template <typename T1>
+struct Types<T1, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None> {
+  typedef internal::Types1<T1> type;
+};
+template <typename T1, typename T2>
+struct Types<T1, T2, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None> {
+  typedef internal::Types2<T1, T2> type;
+};
+template <typename T1, typename T2, typename T3>
+struct Types<T1, T2, T3, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None> {
+  typedef internal::Types3<T1, T2, T3> type;
+};
+template <typename T1, typename T2, typename T3, typename T4>
+struct Types<T1, T2, T3, T4, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None> {
+  typedef internal::Types4<T1, T2, T3, T4> type;
+};
+template <typename T1, typename T2, typename T3, typename T4, typename T5>
+struct Types<T1, T2, T3, T4, T5, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None> {
+  typedef internal::Types5<T1, T2, T3, T4, T5> type;
+};
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6>
+struct Types<T1, T2, T3, T4, T5, T6, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None> {
+  typedef internal::Types6<T1, T2, T3, T4, T5, T6> type;
+};
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7>
+struct Types<T1, T2, T3, T4, T5, T6, T7, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None> {
+  typedef internal::Types7<T1, T2, T3, T4, T5, T6, T7> type;
+};
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8>
+struct Types<T1, T2, T3, T4, T5, T6, T7, T8, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None> {
+  typedef internal::Types8<T1, T2, T3, T4, T5, T6, T7, T8> type;
+};
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9>
+struct Types<T1, T2, T3, T4, T5, T6, T7, T8, T9, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None> {
+  typedef internal::Types9<T1, T2, T3, T4, T5, T6, T7, T8, T9> type;
+};
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10>
+struct Types<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None> {
+  typedef internal::Types10<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10> type;
+};
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11>
+struct Types<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None> {
+  typedef internal::Types11<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11> type;
+};
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12>
+struct Types<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None> {
+  typedef internal::Types12<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11,
+      T12> type;
+};
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13>
+struct Types<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None> {
+  typedef internal::Types13<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12,
+      T13> type;
+};
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14>
+struct Types<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None> {
+  typedef internal::Types14<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12,
+      T13, T14> type;
+};
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15>
+struct Types<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None> {
+  typedef internal::Types15<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12,
+      T13, T14, T15> type;
+};
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16>
+struct Types<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+    T16, internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None> {
+  typedef internal::Types16<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12,
+      T13, T14, T15, T16> type;
+};
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17>
+struct Types<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+    T16, T17, internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None> {
+  typedef internal::Types17<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12,
+      T13, T14, T15, T16, T17> type;
+};
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18>
+struct Types<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+    T16, T17, T18, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None> {
+  typedef internal::Types18<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12,
+      T13, T14, T15, T16, T17, T18> type;
+};
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19>
+struct Types<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+    T16, T17, T18, T19, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None> {
+  typedef internal::Types19<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12,
+      T13, T14, T15, T16, T17, T18, T19> type;
+};
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20>
+struct Types<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+    T16, T17, T18, T19, T20, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None> {
+  typedef internal::Types20<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12,
+      T13, T14, T15, T16, T17, T18, T19, T20> type;
+};
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21>
+struct Types<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+    T16, T17, T18, T19, T20, T21, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None> {
+  typedef internal::Types21<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12,
+      T13, T14, T15, T16, T17, T18, T19, T20, T21> type;
+};
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22>
+struct Types<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+    T16, T17, T18, T19, T20, T21, T22, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None> {
+  typedef internal::Types22<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12,
+      T13, T14, T15, T16, T17, T18, T19, T20, T21, T22> type;
+};
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23>
+struct Types<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+    T16, T17, T18, T19, T20, T21, T22, T23, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None> {
+  typedef internal::Types23<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12,
+      T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23> type;
+};
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24>
+struct Types<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+    T16, T17, T18, T19, T20, T21, T22, T23, T24, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None> {
+  typedef internal::Types24<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12,
+      T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24> type;
+};
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25>
+struct Types<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+    T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None> {
+  typedef internal::Types25<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12,
+      T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25> type;
+};
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26>
+struct Types<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+    T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None> {
+  typedef internal::Types26<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12,
+      T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25,
+      T26> type;
+};
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27>
+struct Types<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+    T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None> {
+  typedef internal::Types27<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12,
+      T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26,
+      T27> type;
+};
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28>
+struct Types<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+    T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None> {
+  typedef internal::Types28<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12,
+      T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26,
+      T27, T28> type;
+};
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29>
+struct Types<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+    T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None> {
+  typedef internal::Types29<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12,
+      T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26,
+      T27, T28, T29> type;
+};
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30>
+struct Types<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+    T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29, T30,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None> {
+  typedef internal::Types30<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12,
+      T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26,
+      T27, T28, T29, T30> type;
+};
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31>
+struct Types<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+    T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29, T30,
+    T31, internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None> {
+  typedef internal::Types31<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12,
+      T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26,
+      T27, T28, T29, T30, T31> type;
+};
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32>
+struct Types<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+    T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29, T30,
+    T31, T32, internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None> {
+  typedef internal::Types32<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12,
+      T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26,
+      T27, T28, T29, T30, T31, T32> type;
+};
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32, typename T33>
+struct Types<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+    T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29, T30,
+    T31, T32, T33, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None> {
+  typedef internal::Types33<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12,
+      T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26,
+      T27, T28, T29, T30, T31, T32, T33> type;
+};
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32, typename T33, typename T34>
+struct Types<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+    T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29, T30,
+    T31, T32, T33, T34, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None> {
+  typedef internal::Types34<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12,
+      T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26,
+      T27, T28, T29, T30, T31, T32, T33, T34> type;
+};
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32, typename T33, typename T34, typename T35>
+struct Types<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+    T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29, T30,
+    T31, T32, T33, T34, T35, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None> {
+  typedef internal::Types35<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12,
+      T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26,
+      T27, T28, T29, T30, T31, T32, T33, T34, T35> type;
+};
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32, typename T33, typename T34, typename T35,
+    typename T36>
+struct Types<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+    T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29, T30,
+    T31, T32, T33, T34, T35, T36, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None> {
+  typedef internal::Types36<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12,
+      T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26,
+      T27, T28, T29, T30, T31, T32, T33, T34, T35, T36> type;
+};
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32, typename T33, typename T34, typename T35,
+    typename T36, typename T37>
+struct Types<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+    T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29, T30,
+    T31, T32, T33, T34, T35, T36, T37, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None> {
+  typedef internal::Types37<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12,
+      T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26,
+      T27, T28, T29, T30, T31, T32, T33, T34, T35, T36, T37> type;
+};
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32, typename T33, typename T34, typename T35,
+    typename T36, typename T37, typename T38>
+struct Types<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+    T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29, T30,
+    T31, T32, T33, T34, T35, T36, T37, T38, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None> {
+  typedef internal::Types38<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12,
+      T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26,
+      T27, T28, T29, T30, T31, T32, T33, T34, T35, T36, T37, T38> type;
+};
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32, typename T33, typename T34, typename T35,
+    typename T36, typename T37, typename T38, typename T39>
+struct Types<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+    T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29, T30,
+    T31, T32, T33, T34, T35, T36, T37, T38, T39, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None> {
+  typedef internal::Types39<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12,
+      T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26,
+      T27, T28, T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39> type;
+};
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32, typename T33, typename T34, typename T35,
+    typename T36, typename T37, typename T38, typename T39, typename T40>
+struct Types<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+    T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29, T30,
+    T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None> {
+  typedef internal::Types40<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12,
+      T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26,
+      T27, T28, T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39,
+      T40> type;
+};
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32, typename T33, typename T34, typename T35,
+    typename T36, typename T37, typename T38, typename T39, typename T40,
+    typename T41>
+struct Types<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+    T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29, T30,
+    T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None> {
+  typedef internal::Types41<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12,
+      T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26,
+      T27, T28, T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40,
+      T41> type;
+};
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32, typename T33, typename T34, typename T35,
+    typename T36, typename T37, typename T38, typename T39, typename T40,
+    typename T41, typename T42>
+struct Types<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+    T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29, T30,
+    T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41, T42, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None> {
+  typedef internal::Types42<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12,
+      T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26,
+      T27, T28, T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40,
+      T41, T42> type;
+};
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32, typename T33, typename T34, typename T35,
+    typename T36, typename T37, typename T38, typename T39, typename T40,
+    typename T41, typename T42, typename T43>
+struct Types<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+    T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29, T30,
+    T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41, T42, T43,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None> {
+  typedef internal::Types43<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12,
+      T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26,
+      T27, T28, T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40,
+      T41, T42, T43> type;
+};
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32, typename T33, typename T34, typename T35,
+    typename T36, typename T37, typename T38, typename T39, typename T40,
+    typename T41, typename T42, typename T43, typename T44>
+struct Types<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+    T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29, T30,
+    T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41, T42, T43, T44,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None> {
+  typedef internal::Types44<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12,
+      T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26,
+      T27, T28, T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40,
+      T41, T42, T43, T44> type;
+};
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32, typename T33, typename T34, typename T35,
+    typename T36, typename T37, typename T38, typename T39, typename T40,
+    typename T41, typename T42, typename T43, typename T44, typename T45>
+struct Types<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+    T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29, T30,
+    T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41, T42, T43, T44, T45,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None> {
+  typedef internal::Types45<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12,
+      T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26,
+      T27, T28, T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40,
+      T41, T42, T43, T44, T45> type;
+};
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32, typename T33, typename T34, typename T35,
+    typename T36, typename T37, typename T38, typename T39, typename T40,
+    typename T41, typename T42, typename T43, typename T44, typename T45,
+    typename T46>
+struct Types<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+    T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29, T30,
+    T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41, T42, T43, T44, T45,
+    T46, internal::None, internal::None, internal::None, internal::None> {
+  typedef internal::Types46<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12,
+      T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26,
+      T27, T28, T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40,
+      T41, T42, T43, T44, T45, T46> type;
+};
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32, typename T33, typename T34, typename T35,
+    typename T36, typename T37, typename T38, typename T39, typename T40,
+    typename T41, typename T42, typename T43, typename T44, typename T45,
+    typename T46, typename T47>
+struct Types<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+    T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29, T30,
+    T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41, T42, T43, T44, T45,
+    T46, T47, internal::None, internal::None, internal::None> {
+  typedef internal::Types47<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12,
+      T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26,
+      T27, T28, T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40,
+      T41, T42, T43, T44, T45, T46, T47> type;
+};
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32, typename T33, typename T34, typename T35,
+    typename T36, typename T37, typename T38, typename T39, typename T40,
+    typename T41, typename T42, typename T43, typename T44, typename T45,
+    typename T46, typename T47, typename T48>
+struct Types<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+    T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29, T30,
+    T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41, T42, T43, T44, T45,
+    T46, T47, T48, internal::None, internal::None> {
+  typedef internal::Types48<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12,
+      T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26,
+      T27, T28, T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40,
+      T41, T42, T43, T44, T45, T46, T47, T48> type;
+};
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32, typename T33, typename T34, typename T35,
+    typename T36, typename T37, typename T38, typename T39, typename T40,
+    typename T41, typename T42, typename T43, typename T44, typename T45,
+    typename T46, typename T47, typename T48, typename T49>
+struct Types<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+    T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29, T30,
+    T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41, T42, T43, T44, T45,
+    T46, T47, T48, T49, internal::None> {
+  typedef internal::Types49<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12,
+      T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26,
+      T27, T28, T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40,
+      T41, T42, T43, T44, T45, T46, T47, T48, T49> type;
+};
+
+namespace internal {
+
+# define GTEST_TEMPLATE_ template <typename T> class
+
+// The template "selector" struct TemplateSel<Tmpl> is used to
+// represent Tmpl, which must be a class template with one type
+// parameter, as a type.  TemplateSel<Tmpl>::Bind<T>::type is defined
+// as the type Tmpl<T>.  This allows us to actually instantiate the
+// template "selected" by TemplateSel<Tmpl>.
+//
+// This trick is necessary for simulating typedef for class templates,
+// which C++ doesn't support directly.
+template <GTEST_TEMPLATE_ Tmpl>
+struct TemplateSel {
+  template <typename T>
+  struct Bind {
+    typedef Tmpl<T> type;
+  };
+};
+
+# define GTEST_BIND_(TmplSel, T) \
+  TmplSel::template Bind<T>::type
+
+// A unique struct template used as the default value for the
+// arguments of class template Templates.  This allows us to simulate
+// variadic templates (e.g. Templates<int>, Templates<int, double>,
+// and etc), which C++ doesn't support directly.
+template <typename T>
+struct NoneT {};
+
+// The following family of struct and struct templates are used to
+// represent template lists.  In particular, TemplatesN<T1, T2, ...,
+// TN> represents a list of N templates (T1, T2, ..., and TN).  Except
+// for Templates0, every struct in the family has two member types:
+// Head for the selector of the first template in the list, and Tail
+// for the rest of the list.
+
+// The empty template list.
+struct Templates0 {};
+
+// Template lists of length 1, 2, 3, and so on.
+
+template <GTEST_TEMPLATE_ T1>
+struct Templates1 {
+  typedef TemplateSel<T1> Head;
+  typedef Templates0 Tail;
+};
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2>
+struct Templates2 {
+  typedef TemplateSel<T1> Head;
+  typedef Templates1<T2> Tail;
+};
+
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3>
+struct Templates3 {
+  typedef TemplateSel<T1> Head;
+  typedef Templates2<T2, T3> Tail;
+};
+
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4>
+struct Templates4 {
+  typedef TemplateSel<T1> Head;
+  typedef Templates3<T2, T3, T4> Tail;
+};
+
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5>
+struct Templates5 {
+  typedef TemplateSel<T1> Head;
+  typedef Templates4<T2, T3, T4, T5> Tail;
+};
+
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6>
+struct Templates6 {
+  typedef TemplateSel<T1> Head;
+  typedef Templates5<T2, T3, T4, T5, T6> Tail;
+};
+
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7>
+struct Templates7 {
+  typedef TemplateSel<T1> Head;
+  typedef Templates6<T2, T3, T4, T5, T6, T7> Tail;
+};
+
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8>
+struct Templates8 {
+  typedef TemplateSel<T1> Head;
+  typedef Templates7<T2, T3, T4, T5, T6, T7, T8> Tail;
+};
+
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9>
+struct Templates9 {
+  typedef TemplateSel<T1> Head;
+  typedef Templates8<T2, T3, T4, T5, T6, T7, T8, T9> Tail;
+};
+
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10>
+struct Templates10 {
+  typedef TemplateSel<T1> Head;
+  typedef Templates9<T2, T3, T4, T5, T6, T7, T8, T9, T10> Tail;
+};
+
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11>
+struct Templates11 {
+  typedef TemplateSel<T1> Head;
+  typedef Templates10<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11> Tail;
+};
+
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12>
+struct Templates12 {
+  typedef TemplateSel<T1> Head;
+  typedef Templates11<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12> Tail;
+};
+
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13>
+struct Templates13 {
+  typedef TemplateSel<T1> Head;
+  typedef Templates12<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13> Tail;
+};
+
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14>
+struct Templates14 {
+  typedef TemplateSel<T1> Head;
+  typedef Templates13<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+      T14> Tail;
+};
+
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15>
+struct Templates15 {
+  typedef TemplateSel<T1> Head;
+  typedef Templates14<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+      T15> Tail;
+};
+
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+    GTEST_TEMPLATE_ T16>
+struct Templates16 {
+  typedef TemplateSel<T1> Head;
+  typedef Templates15<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+      T15, T16> Tail;
+};
+
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+    GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17>
+struct Templates17 {
+  typedef TemplateSel<T1> Head;
+  typedef Templates16<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+      T15, T16, T17> Tail;
+};
+
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+    GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18>
+struct Templates18 {
+  typedef TemplateSel<T1> Head;
+  typedef Templates17<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+      T15, T16, T17, T18> Tail;
+};
+
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+    GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+    GTEST_TEMPLATE_ T19>
+struct Templates19 {
+  typedef TemplateSel<T1> Head;
+  typedef Templates18<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+      T15, T16, T17, T18, T19> Tail;
+};
+
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+    GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+    GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20>
+struct Templates20 {
+  typedef TemplateSel<T1> Head;
+  typedef Templates19<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+      T15, T16, T17, T18, T19, T20> Tail;
+};
+
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+    GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+    GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21>
+struct Templates21 {
+  typedef TemplateSel<T1> Head;
+  typedef Templates20<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+      T15, T16, T17, T18, T19, T20, T21> Tail;
+};
+
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+    GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+    GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+    GTEST_TEMPLATE_ T22>
+struct Templates22 {
+  typedef TemplateSel<T1> Head;
+  typedef Templates21<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+      T15, T16, T17, T18, T19, T20, T21, T22> Tail;
+};
+
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+    GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+    GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+    GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23>
+struct Templates23 {
+  typedef TemplateSel<T1> Head;
+  typedef Templates22<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+      T15, T16, T17, T18, T19, T20, T21, T22, T23> Tail;
+};
+
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+    GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+    GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+    GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24>
+struct Templates24 {
+  typedef TemplateSel<T1> Head;
+  typedef Templates23<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+      T15, T16, T17, T18, T19, T20, T21, T22, T23, T24> Tail;
+};
+
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+    GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+    GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+    GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
+    GTEST_TEMPLATE_ T25>
+struct Templates25 {
+  typedef TemplateSel<T1> Head;
+  typedef Templates24<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+      T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25> Tail;
+};
+
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+    GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+    GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+    GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
+    GTEST_TEMPLATE_ T25, GTEST_TEMPLATE_ T26>
+struct Templates26 {
+  typedef TemplateSel<T1> Head;
+  typedef Templates25<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+      T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26> Tail;
+};
+
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+    GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+    GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+    GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
+    GTEST_TEMPLATE_ T25, GTEST_TEMPLATE_ T26, GTEST_TEMPLATE_ T27>
+struct Templates27 {
+  typedef TemplateSel<T1> Head;
+  typedef Templates26<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+      T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27> Tail;
+};
+
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+    GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+    GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+    GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
+    GTEST_TEMPLATE_ T25, GTEST_TEMPLATE_ T26, GTEST_TEMPLATE_ T27,
+    GTEST_TEMPLATE_ T28>
+struct Templates28 {
+  typedef TemplateSel<T1> Head;
+  typedef Templates27<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+      T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27,
+      T28> Tail;
+};
+
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+    GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+    GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+    GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
+    GTEST_TEMPLATE_ T25, GTEST_TEMPLATE_ T26, GTEST_TEMPLATE_ T27,
+    GTEST_TEMPLATE_ T28, GTEST_TEMPLATE_ T29>
+struct Templates29 {
+  typedef TemplateSel<T1> Head;
+  typedef Templates28<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+      T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28,
+      T29> Tail;
+};
+
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+    GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+    GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+    GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
+    GTEST_TEMPLATE_ T25, GTEST_TEMPLATE_ T26, GTEST_TEMPLATE_ T27,
+    GTEST_TEMPLATE_ T28, GTEST_TEMPLATE_ T29, GTEST_TEMPLATE_ T30>
+struct Templates30 {
+  typedef TemplateSel<T1> Head;
+  typedef Templates29<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+      T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28,
+      T29, T30> Tail;
+};
+
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+    GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+    GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+    GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
+    GTEST_TEMPLATE_ T25, GTEST_TEMPLATE_ T26, GTEST_TEMPLATE_ T27,
+    GTEST_TEMPLATE_ T28, GTEST_TEMPLATE_ T29, GTEST_TEMPLATE_ T30,
+    GTEST_TEMPLATE_ T31>
+struct Templates31 {
+  typedef TemplateSel<T1> Head;
+  typedef Templates30<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+      T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28,
+      T29, T30, T31> Tail;
+};
+
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+    GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+    GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+    GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
+    GTEST_TEMPLATE_ T25, GTEST_TEMPLATE_ T26, GTEST_TEMPLATE_ T27,
+    GTEST_TEMPLATE_ T28, GTEST_TEMPLATE_ T29, GTEST_TEMPLATE_ T30,
+    GTEST_TEMPLATE_ T31, GTEST_TEMPLATE_ T32>
+struct Templates32 {
+  typedef TemplateSel<T1> Head;
+  typedef Templates31<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+      T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28,
+      T29, T30, T31, T32> Tail;
+};
+
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+    GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+    GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+    GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
+    GTEST_TEMPLATE_ T25, GTEST_TEMPLATE_ T26, GTEST_TEMPLATE_ T27,
+    GTEST_TEMPLATE_ T28, GTEST_TEMPLATE_ T29, GTEST_TEMPLATE_ T30,
+    GTEST_TEMPLATE_ T31, GTEST_TEMPLATE_ T32, GTEST_TEMPLATE_ T33>
+struct Templates33 {
+  typedef TemplateSel<T1> Head;
+  typedef Templates32<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+      T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28,
+      T29, T30, T31, T32, T33> Tail;
+};
+
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+    GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+    GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+    GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
+    GTEST_TEMPLATE_ T25, GTEST_TEMPLATE_ T26, GTEST_TEMPLATE_ T27,
+    GTEST_TEMPLATE_ T28, GTEST_TEMPLATE_ T29, GTEST_TEMPLATE_ T30,
+    GTEST_TEMPLATE_ T31, GTEST_TEMPLATE_ T32, GTEST_TEMPLATE_ T33,
+    GTEST_TEMPLATE_ T34>
+struct Templates34 {
+  typedef TemplateSel<T1> Head;
+  typedef Templates33<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+      T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28,
+      T29, T30, T31, T32, T33, T34> Tail;
+};
+
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+    GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+    GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+    GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
+    GTEST_TEMPLATE_ T25, GTEST_TEMPLATE_ T26, GTEST_TEMPLATE_ T27,
+    GTEST_TEMPLATE_ T28, GTEST_TEMPLATE_ T29, GTEST_TEMPLATE_ T30,
+    GTEST_TEMPLATE_ T31, GTEST_TEMPLATE_ T32, GTEST_TEMPLATE_ T33,
+    GTEST_TEMPLATE_ T34, GTEST_TEMPLATE_ T35>
+struct Templates35 {
+  typedef TemplateSel<T1> Head;
+  typedef Templates34<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+      T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28,
+      T29, T30, T31, T32, T33, T34, T35> Tail;
+};
+
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+    GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+    GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+    GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
+    GTEST_TEMPLATE_ T25, GTEST_TEMPLATE_ T26, GTEST_TEMPLATE_ T27,
+    GTEST_TEMPLATE_ T28, GTEST_TEMPLATE_ T29, GTEST_TEMPLATE_ T30,
+    GTEST_TEMPLATE_ T31, GTEST_TEMPLATE_ T32, GTEST_TEMPLATE_ T33,
+    GTEST_TEMPLATE_ T34, GTEST_TEMPLATE_ T35, GTEST_TEMPLATE_ T36>
+struct Templates36 {
+  typedef TemplateSel<T1> Head;
+  typedef Templates35<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+      T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28,
+      T29, T30, T31, T32, T33, T34, T35, T36> Tail;
+};
+
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+    GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+    GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+    GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
+    GTEST_TEMPLATE_ T25, GTEST_TEMPLATE_ T26, GTEST_TEMPLATE_ T27,
+    GTEST_TEMPLATE_ T28, GTEST_TEMPLATE_ T29, GTEST_TEMPLATE_ T30,
+    GTEST_TEMPLATE_ T31, GTEST_TEMPLATE_ T32, GTEST_TEMPLATE_ T33,
+    GTEST_TEMPLATE_ T34, GTEST_TEMPLATE_ T35, GTEST_TEMPLATE_ T36,
+    GTEST_TEMPLATE_ T37>
+struct Templates37 {
+  typedef TemplateSel<T1> Head;
+  typedef Templates36<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+      T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28,
+      T29, T30, T31, T32, T33, T34, T35, T36, T37> Tail;
+};
+
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+    GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+    GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+    GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
+    GTEST_TEMPLATE_ T25, GTEST_TEMPLATE_ T26, GTEST_TEMPLATE_ T27,
+    GTEST_TEMPLATE_ T28, GTEST_TEMPLATE_ T29, GTEST_TEMPLATE_ T30,
+    GTEST_TEMPLATE_ T31, GTEST_TEMPLATE_ T32, GTEST_TEMPLATE_ T33,
+    GTEST_TEMPLATE_ T34, GTEST_TEMPLATE_ T35, GTEST_TEMPLATE_ T36,
+    GTEST_TEMPLATE_ T37, GTEST_TEMPLATE_ T38>
+struct Templates38 {
+  typedef TemplateSel<T1> Head;
+  typedef Templates37<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+      T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28,
+      T29, T30, T31, T32, T33, T34, T35, T36, T37, T38> Tail;
+};
+
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+    GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+    GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+    GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
+    GTEST_TEMPLATE_ T25, GTEST_TEMPLATE_ T26, GTEST_TEMPLATE_ T27,
+    GTEST_TEMPLATE_ T28, GTEST_TEMPLATE_ T29, GTEST_TEMPLATE_ T30,
+    GTEST_TEMPLATE_ T31, GTEST_TEMPLATE_ T32, GTEST_TEMPLATE_ T33,
+    GTEST_TEMPLATE_ T34, GTEST_TEMPLATE_ T35, GTEST_TEMPLATE_ T36,
+    GTEST_TEMPLATE_ T37, GTEST_TEMPLATE_ T38, GTEST_TEMPLATE_ T39>
+struct Templates39 {
+  typedef TemplateSel<T1> Head;
+  typedef Templates38<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+      T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28,
+      T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39> Tail;
+};
+
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+    GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+    GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+    GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
+    GTEST_TEMPLATE_ T25, GTEST_TEMPLATE_ T26, GTEST_TEMPLATE_ T27,
+    GTEST_TEMPLATE_ T28, GTEST_TEMPLATE_ T29, GTEST_TEMPLATE_ T30,
+    GTEST_TEMPLATE_ T31, GTEST_TEMPLATE_ T32, GTEST_TEMPLATE_ T33,
+    GTEST_TEMPLATE_ T34, GTEST_TEMPLATE_ T35, GTEST_TEMPLATE_ T36,
+    GTEST_TEMPLATE_ T37, GTEST_TEMPLATE_ T38, GTEST_TEMPLATE_ T39,
+    GTEST_TEMPLATE_ T40>
+struct Templates40 {
+  typedef TemplateSel<T1> Head;
+  typedef Templates39<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+      T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28,
+      T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40> Tail;
+};
+
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+    GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+    GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+    GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
+    GTEST_TEMPLATE_ T25, GTEST_TEMPLATE_ T26, GTEST_TEMPLATE_ T27,
+    GTEST_TEMPLATE_ T28, GTEST_TEMPLATE_ T29, GTEST_TEMPLATE_ T30,
+    GTEST_TEMPLATE_ T31, GTEST_TEMPLATE_ T32, GTEST_TEMPLATE_ T33,
+    GTEST_TEMPLATE_ T34, GTEST_TEMPLATE_ T35, GTEST_TEMPLATE_ T36,
+    GTEST_TEMPLATE_ T37, GTEST_TEMPLATE_ T38, GTEST_TEMPLATE_ T39,
+    GTEST_TEMPLATE_ T40, GTEST_TEMPLATE_ T41>
+struct Templates41 {
+  typedef TemplateSel<T1> Head;
+  typedef Templates40<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+      T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28,
+      T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41> Tail;
+};
+
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+    GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+    GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+    GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
+    GTEST_TEMPLATE_ T25, GTEST_TEMPLATE_ T26, GTEST_TEMPLATE_ T27,
+    GTEST_TEMPLATE_ T28, GTEST_TEMPLATE_ T29, GTEST_TEMPLATE_ T30,
+    GTEST_TEMPLATE_ T31, GTEST_TEMPLATE_ T32, GTEST_TEMPLATE_ T33,
+    GTEST_TEMPLATE_ T34, GTEST_TEMPLATE_ T35, GTEST_TEMPLATE_ T36,
+    GTEST_TEMPLATE_ T37, GTEST_TEMPLATE_ T38, GTEST_TEMPLATE_ T39,
+    GTEST_TEMPLATE_ T40, GTEST_TEMPLATE_ T41, GTEST_TEMPLATE_ T42>
+struct Templates42 {
+  typedef TemplateSel<T1> Head;
+  typedef Templates41<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+      T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28,
+      T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41,
+      T42> Tail;
+};
+
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+    GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+    GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+    GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
+    GTEST_TEMPLATE_ T25, GTEST_TEMPLATE_ T26, GTEST_TEMPLATE_ T27,
+    GTEST_TEMPLATE_ T28, GTEST_TEMPLATE_ T29, GTEST_TEMPLATE_ T30,
+    GTEST_TEMPLATE_ T31, GTEST_TEMPLATE_ T32, GTEST_TEMPLATE_ T33,
+    GTEST_TEMPLATE_ T34, GTEST_TEMPLATE_ T35, GTEST_TEMPLATE_ T36,
+    GTEST_TEMPLATE_ T37, GTEST_TEMPLATE_ T38, GTEST_TEMPLATE_ T39,
+    GTEST_TEMPLATE_ T40, GTEST_TEMPLATE_ T41, GTEST_TEMPLATE_ T42,
+    GTEST_TEMPLATE_ T43>
+struct Templates43 {
+  typedef TemplateSel<T1> Head;
+  typedef Templates42<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+      T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28,
+      T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41, T42,
+      T43> Tail;
+};
+
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+    GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+    GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+    GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
+    GTEST_TEMPLATE_ T25, GTEST_TEMPLATE_ T26, GTEST_TEMPLATE_ T27,
+    GTEST_TEMPLATE_ T28, GTEST_TEMPLATE_ T29, GTEST_TEMPLATE_ T30,
+    GTEST_TEMPLATE_ T31, GTEST_TEMPLATE_ T32, GTEST_TEMPLATE_ T33,
+    GTEST_TEMPLATE_ T34, GTEST_TEMPLATE_ T35, GTEST_TEMPLATE_ T36,
+    GTEST_TEMPLATE_ T37, GTEST_TEMPLATE_ T38, GTEST_TEMPLATE_ T39,
+    GTEST_TEMPLATE_ T40, GTEST_TEMPLATE_ T41, GTEST_TEMPLATE_ T42,
+    GTEST_TEMPLATE_ T43, GTEST_TEMPLATE_ T44>
+struct Templates44 {
+  typedef TemplateSel<T1> Head;
+  typedef Templates43<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+      T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28,
+      T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41, T42,
+      T43, T44> Tail;
+};
+
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+    GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+    GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+    GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
+    GTEST_TEMPLATE_ T25, GTEST_TEMPLATE_ T26, GTEST_TEMPLATE_ T27,
+    GTEST_TEMPLATE_ T28, GTEST_TEMPLATE_ T29, GTEST_TEMPLATE_ T30,
+    GTEST_TEMPLATE_ T31, GTEST_TEMPLATE_ T32, GTEST_TEMPLATE_ T33,
+    GTEST_TEMPLATE_ T34, GTEST_TEMPLATE_ T35, GTEST_TEMPLATE_ T36,
+    GTEST_TEMPLATE_ T37, GTEST_TEMPLATE_ T38, GTEST_TEMPLATE_ T39,
+    GTEST_TEMPLATE_ T40, GTEST_TEMPLATE_ T41, GTEST_TEMPLATE_ T42,
+    GTEST_TEMPLATE_ T43, GTEST_TEMPLATE_ T44, GTEST_TEMPLATE_ T45>
+struct Templates45 {
+  typedef TemplateSel<T1> Head;
+  typedef Templates44<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+      T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28,
+      T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41, T42,
+      T43, T44, T45> Tail;
+};
+
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+    GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+    GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+    GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
+    GTEST_TEMPLATE_ T25, GTEST_TEMPLATE_ T26, GTEST_TEMPLATE_ T27,
+    GTEST_TEMPLATE_ T28, GTEST_TEMPLATE_ T29, GTEST_TEMPLATE_ T30,
+    GTEST_TEMPLATE_ T31, GTEST_TEMPLATE_ T32, GTEST_TEMPLATE_ T33,
+    GTEST_TEMPLATE_ T34, GTEST_TEMPLATE_ T35, GTEST_TEMPLATE_ T36,
+    GTEST_TEMPLATE_ T37, GTEST_TEMPLATE_ T38, GTEST_TEMPLATE_ T39,
+    GTEST_TEMPLATE_ T40, GTEST_TEMPLATE_ T41, GTEST_TEMPLATE_ T42,
+    GTEST_TEMPLATE_ T43, GTEST_TEMPLATE_ T44, GTEST_TEMPLATE_ T45,
+    GTEST_TEMPLATE_ T46>
+struct Templates46 {
+  typedef TemplateSel<T1> Head;
+  typedef Templates45<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+      T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28,
+      T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41, T42,
+      T43, T44, T45, T46> Tail;
+};
+
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+    GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+    GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+    GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
+    GTEST_TEMPLATE_ T25, GTEST_TEMPLATE_ T26, GTEST_TEMPLATE_ T27,
+    GTEST_TEMPLATE_ T28, GTEST_TEMPLATE_ T29, GTEST_TEMPLATE_ T30,
+    GTEST_TEMPLATE_ T31, GTEST_TEMPLATE_ T32, GTEST_TEMPLATE_ T33,
+    GTEST_TEMPLATE_ T34, GTEST_TEMPLATE_ T35, GTEST_TEMPLATE_ T36,
+    GTEST_TEMPLATE_ T37, GTEST_TEMPLATE_ T38, GTEST_TEMPLATE_ T39,
+    GTEST_TEMPLATE_ T40, GTEST_TEMPLATE_ T41, GTEST_TEMPLATE_ T42,
+    GTEST_TEMPLATE_ T43, GTEST_TEMPLATE_ T44, GTEST_TEMPLATE_ T45,
+    GTEST_TEMPLATE_ T46, GTEST_TEMPLATE_ T47>
+struct Templates47 {
+  typedef TemplateSel<T1> Head;
+  typedef Templates46<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+      T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28,
+      T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41, T42,
+      T43, T44, T45, T46, T47> Tail;
+};
+
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+    GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+    GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+    GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
+    GTEST_TEMPLATE_ T25, GTEST_TEMPLATE_ T26, GTEST_TEMPLATE_ T27,
+    GTEST_TEMPLATE_ T28, GTEST_TEMPLATE_ T29, GTEST_TEMPLATE_ T30,
+    GTEST_TEMPLATE_ T31, GTEST_TEMPLATE_ T32, GTEST_TEMPLATE_ T33,
+    GTEST_TEMPLATE_ T34, GTEST_TEMPLATE_ T35, GTEST_TEMPLATE_ T36,
+    GTEST_TEMPLATE_ T37, GTEST_TEMPLATE_ T38, GTEST_TEMPLATE_ T39,
+    GTEST_TEMPLATE_ T40, GTEST_TEMPLATE_ T41, GTEST_TEMPLATE_ T42,
+    GTEST_TEMPLATE_ T43, GTEST_TEMPLATE_ T44, GTEST_TEMPLATE_ T45,
+    GTEST_TEMPLATE_ T46, GTEST_TEMPLATE_ T47, GTEST_TEMPLATE_ T48>
+struct Templates48 {
+  typedef TemplateSel<T1> Head;
+  typedef Templates47<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+      T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28,
+      T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41, T42,
+      T43, T44, T45, T46, T47, T48> Tail;
+};
+
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+    GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+    GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+    GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
+    GTEST_TEMPLATE_ T25, GTEST_TEMPLATE_ T26, GTEST_TEMPLATE_ T27,
+    GTEST_TEMPLATE_ T28, GTEST_TEMPLATE_ T29, GTEST_TEMPLATE_ T30,
+    GTEST_TEMPLATE_ T31, GTEST_TEMPLATE_ T32, GTEST_TEMPLATE_ T33,
+    GTEST_TEMPLATE_ T34, GTEST_TEMPLATE_ T35, GTEST_TEMPLATE_ T36,
+    GTEST_TEMPLATE_ T37, GTEST_TEMPLATE_ T38, GTEST_TEMPLATE_ T39,
+    GTEST_TEMPLATE_ T40, GTEST_TEMPLATE_ T41, GTEST_TEMPLATE_ T42,
+    GTEST_TEMPLATE_ T43, GTEST_TEMPLATE_ T44, GTEST_TEMPLATE_ T45,
+    GTEST_TEMPLATE_ T46, GTEST_TEMPLATE_ T47, GTEST_TEMPLATE_ T48,
+    GTEST_TEMPLATE_ T49>
+struct Templates49 {
+  typedef TemplateSel<T1> Head;
+  typedef Templates48<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+      T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28,
+      T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41, T42,
+      T43, T44, T45, T46, T47, T48, T49> Tail;
+};
+
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+    GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+    GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+    GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
+    GTEST_TEMPLATE_ T25, GTEST_TEMPLATE_ T26, GTEST_TEMPLATE_ T27,
+    GTEST_TEMPLATE_ T28, GTEST_TEMPLATE_ T29, GTEST_TEMPLATE_ T30,
+    GTEST_TEMPLATE_ T31, GTEST_TEMPLATE_ T32, GTEST_TEMPLATE_ T33,
+    GTEST_TEMPLATE_ T34, GTEST_TEMPLATE_ T35, GTEST_TEMPLATE_ T36,
+    GTEST_TEMPLATE_ T37, GTEST_TEMPLATE_ T38, GTEST_TEMPLATE_ T39,
+    GTEST_TEMPLATE_ T40, GTEST_TEMPLATE_ T41, GTEST_TEMPLATE_ T42,
+    GTEST_TEMPLATE_ T43, GTEST_TEMPLATE_ T44, GTEST_TEMPLATE_ T45,
+    GTEST_TEMPLATE_ T46, GTEST_TEMPLATE_ T47, GTEST_TEMPLATE_ T48,
+    GTEST_TEMPLATE_ T49, GTEST_TEMPLATE_ T50>
+struct Templates50 {
+  typedef TemplateSel<T1> Head;
+  typedef Templates49<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+      T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28,
+      T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41, T42,
+      T43, T44, T45, T46, T47, T48, T49, T50> Tail;
+};
+
+
+// We don't want to require the users to write TemplatesN<...> directly,
+// as that would require them to count the length.  Templates<...> is much
+// easier to write, but generates horrible messages when there is a
+// compiler error, as gcc insists on printing out each template
+// argument, even if it has the default value (this means Templates<list>
+// will appear as Templates<list, NoneT, NoneT, ..., NoneT> in the compiler
+// errors).
+//
+// Our solution is to combine the best part of the two approaches: a
+// user would write Templates<T1, ..., TN>, and Google Test will translate
+// that to TemplatesN<T1, ..., TN> internally to make error messages
+// readable.  The translation is done by the 'type' member of the
+// Templates template.
+template <GTEST_TEMPLATE_ T1 = NoneT, GTEST_TEMPLATE_ T2 = NoneT,
+    GTEST_TEMPLATE_ T3 = NoneT, GTEST_TEMPLATE_ T4 = NoneT,
+    GTEST_TEMPLATE_ T5 = NoneT, GTEST_TEMPLATE_ T6 = NoneT,
+    GTEST_TEMPLATE_ T7 = NoneT, GTEST_TEMPLATE_ T8 = NoneT,
+    GTEST_TEMPLATE_ T9 = NoneT, GTEST_TEMPLATE_ T10 = NoneT,
+    GTEST_TEMPLATE_ T11 = NoneT, GTEST_TEMPLATE_ T12 = NoneT,
+    GTEST_TEMPLATE_ T13 = NoneT, GTEST_TEMPLATE_ T14 = NoneT,
+    GTEST_TEMPLATE_ T15 = NoneT, GTEST_TEMPLATE_ T16 = NoneT,
+    GTEST_TEMPLATE_ T17 = NoneT, GTEST_TEMPLATE_ T18 = NoneT,
+    GTEST_TEMPLATE_ T19 = NoneT, GTEST_TEMPLATE_ T20 = NoneT,
+    GTEST_TEMPLATE_ T21 = NoneT, GTEST_TEMPLATE_ T22 = NoneT,
+    GTEST_TEMPLATE_ T23 = NoneT, GTEST_TEMPLATE_ T24 = NoneT,
+    GTEST_TEMPLATE_ T25 = NoneT, GTEST_TEMPLATE_ T26 = NoneT,
+    GTEST_TEMPLATE_ T27 = NoneT, GTEST_TEMPLATE_ T28 = NoneT,
+    GTEST_TEMPLATE_ T29 = NoneT, GTEST_TEMPLATE_ T30 = NoneT,
+    GTEST_TEMPLATE_ T31 = NoneT, GTEST_TEMPLATE_ T32 = NoneT,
+    GTEST_TEMPLATE_ T33 = NoneT, GTEST_TEMPLATE_ T34 = NoneT,
+    GTEST_TEMPLATE_ T35 = NoneT, GTEST_TEMPLATE_ T36 = NoneT,
+    GTEST_TEMPLATE_ T37 = NoneT, GTEST_TEMPLATE_ T38 = NoneT,
+    GTEST_TEMPLATE_ T39 = NoneT, GTEST_TEMPLATE_ T40 = NoneT,
+    GTEST_TEMPLATE_ T41 = NoneT, GTEST_TEMPLATE_ T42 = NoneT,
+    GTEST_TEMPLATE_ T43 = NoneT, GTEST_TEMPLATE_ T44 = NoneT,
+    GTEST_TEMPLATE_ T45 = NoneT, GTEST_TEMPLATE_ T46 = NoneT,
+    GTEST_TEMPLATE_ T47 = NoneT, GTEST_TEMPLATE_ T48 = NoneT,
+    GTEST_TEMPLATE_ T49 = NoneT, GTEST_TEMPLATE_ T50 = NoneT>
+struct Templates {
+  typedef Templates50<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+      T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27,
+      T28, T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41,
+      T42, T43, T44, T45, T46, T47, T48, T49, T50> type;
+};
+
+template <>
+struct Templates<NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT> {
+  typedef Templates0 type;
+};
+template <GTEST_TEMPLATE_ T1>
+struct Templates<T1, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT> {
+  typedef Templates1<T1> type;
+};
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2>
+struct Templates<T1, T2, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT> {
+  typedef Templates2<T1, T2> type;
+};
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3>
+struct Templates<T1, T2, T3, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT> {
+  typedef Templates3<T1, T2, T3> type;
+};
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4>
+struct Templates<T1, T2, T3, T4, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT> {
+  typedef Templates4<T1, T2, T3, T4> type;
+};
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5>
+struct Templates<T1, T2, T3, T4, T5, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT> {
+  typedef Templates5<T1, T2, T3, T4, T5> type;
+};
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6>
+struct Templates<T1, T2, T3, T4, T5, T6, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT> {
+  typedef Templates6<T1, T2, T3, T4, T5, T6> type;
+};
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7>
+struct Templates<T1, T2, T3, T4, T5, T6, T7, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT> {
+  typedef Templates7<T1, T2, T3, T4, T5, T6, T7> type;
+};
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8>
+struct Templates<T1, T2, T3, T4, T5, T6, T7, T8, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT> {
+  typedef Templates8<T1, T2, T3, T4, T5, T6, T7, T8> type;
+};
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9>
+struct Templates<T1, T2, T3, T4, T5, T6, T7, T8, T9, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT> {
+  typedef Templates9<T1, T2, T3, T4, T5, T6, T7, T8, T9> type;
+};
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10>
+struct Templates<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT> {
+  typedef Templates10<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10> type;
+};
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11>
+struct Templates<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT> {
+  typedef Templates11<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11> type;
+};
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12>
+struct Templates<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT> {
+  typedef Templates12<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12> type;
+};
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13>
+struct Templates<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT> {
+  typedef Templates13<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12,
+      T13> type;
+};
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14>
+struct Templates<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT> {
+  typedef Templates14<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+      T14> type;
+};
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15>
+struct Templates<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+    T15, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT> {
+  typedef Templates15<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+      T14, T15> type;
+};
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+    GTEST_TEMPLATE_ T16>
+struct Templates<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+    T15, T16, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT> {
+  typedef Templates16<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+      T14, T15, T16> type;
+};
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+    GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17>
+struct Templates<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+    T15, T16, T17, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT> {
+  typedef Templates17<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+      T14, T15, T16, T17> type;
+};
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+    GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18>
+struct Templates<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+    T15, T16, T17, T18, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT> {
+  typedef Templates18<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+      T14, T15, T16, T17, T18> type;
+};
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+    GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+    GTEST_TEMPLATE_ T19>
+struct Templates<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+    T15, T16, T17, T18, T19, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT> {
+  typedef Templates19<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+      T14, T15, T16, T17, T18, T19> type;
+};
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+    GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+    GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20>
+struct Templates<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+    T15, T16, T17, T18, T19, T20, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT> {
+  typedef Templates20<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+      T14, T15, T16, T17, T18, T19, T20> type;
+};
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+    GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+    GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21>
+struct Templates<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+    T15, T16, T17, T18, T19, T20, T21, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT> {
+  typedef Templates21<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+      T14, T15, T16, T17, T18, T19, T20, T21> type;
+};
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+    GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+    GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+    GTEST_TEMPLATE_ T22>
+struct Templates<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+    T15, T16, T17, T18, T19, T20, T21, T22, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT> {
+  typedef Templates22<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+      T14, T15, T16, T17, T18, T19, T20, T21, T22> type;
+};
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+    GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+    GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+    GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23>
+struct Templates<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+    T15, T16, T17, T18, T19, T20, T21, T22, T23, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT> {
+  typedef Templates23<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+      T14, T15, T16, T17, T18, T19, T20, T21, T22, T23> type;
+};
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+    GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+    GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+    GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24>
+struct Templates<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+    T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT> {
+  typedef Templates24<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+      T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24> type;
+};
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+    GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+    GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+    GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
+    GTEST_TEMPLATE_ T25>
+struct Templates<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+    T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT> {
+  typedef Templates25<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+      T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25> type;
+};
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+    GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+    GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+    GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
+    GTEST_TEMPLATE_ T25, GTEST_TEMPLATE_ T26>
+struct Templates<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+    T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT> {
+  typedef Templates26<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+      T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26> type;
+};
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+    GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+    GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+    GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
+    GTEST_TEMPLATE_ T25, GTEST_TEMPLATE_ T26, GTEST_TEMPLATE_ T27>
+struct Templates<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+    T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT> {
+  typedef Templates27<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+      T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26,
+      T27> type;
+};
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+    GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+    GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+    GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
+    GTEST_TEMPLATE_ T25, GTEST_TEMPLATE_ T26, GTEST_TEMPLATE_ T27,
+    GTEST_TEMPLATE_ T28>
+struct Templates<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+    T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT> {
+  typedef Templates28<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+      T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27,
+      T28> type;
+};
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+    GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+    GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+    GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
+    GTEST_TEMPLATE_ T25, GTEST_TEMPLATE_ T26, GTEST_TEMPLATE_ T27,
+    GTEST_TEMPLATE_ T28, GTEST_TEMPLATE_ T29>
+struct Templates<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+    T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT> {
+  typedef Templates29<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+      T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27,
+      T28, T29> type;
+};
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+    GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+    GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+    GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
+    GTEST_TEMPLATE_ T25, GTEST_TEMPLATE_ T26, GTEST_TEMPLATE_ T27,
+    GTEST_TEMPLATE_ T28, GTEST_TEMPLATE_ T29, GTEST_TEMPLATE_ T30>
+struct Templates<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+    T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29,
+    T30, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT> {
+  typedef Templates30<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+      T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27,
+      T28, T29, T30> type;
+};
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+    GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+    GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+    GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
+    GTEST_TEMPLATE_ T25, GTEST_TEMPLATE_ T26, GTEST_TEMPLATE_ T27,
+    GTEST_TEMPLATE_ T28, GTEST_TEMPLATE_ T29, GTEST_TEMPLATE_ T30,
+    GTEST_TEMPLATE_ T31>
+struct Templates<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+    T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29,
+    T30, T31, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT> {
+  typedef Templates31<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+      T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27,
+      T28, T29, T30, T31> type;
+};
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+    GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+    GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+    GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
+    GTEST_TEMPLATE_ T25, GTEST_TEMPLATE_ T26, GTEST_TEMPLATE_ T27,
+    GTEST_TEMPLATE_ T28, GTEST_TEMPLATE_ T29, GTEST_TEMPLATE_ T30,
+    GTEST_TEMPLATE_ T31, GTEST_TEMPLATE_ T32>
+struct Templates<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+    T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29,
+    T30, T31, T32, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT> {
+  typedef Templates32<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+      T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27,
+      T28, T29, T30, T31, T32> type;
+};
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+    GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+    GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+    GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
+    GTEST_TEMPLATE_ T25, GTEST_TEMPLATE_ T26, GTEST_TEMPLATE_ T27,
+    GTEST_TEMPLATE_ T28, GTEST_TEMPLATE_ T29, GTEST_TEMPLATE_ T30,
+    GTEST_TEMPLATE_ T31, GTEST_TEMPLATE_ T32, GTEST_TEMPLATE_ T33>
+struct Templates<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+    T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29,
+    T30, T31, T32, T33, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT> {
+  typedef Templates33<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+      T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27,
+      T28, T29, T30, T31, T32, T33> type;
+};
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+    GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+    GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+    GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
+    GTEST_TEMPLATE_ T25, GTEST_TEMPLATE_ T26, GTEST_TEMPLATE_ T27,
+    GTEST_TEMPLATE_ T28, GTEST_TEMPLATE_ T29, GTEST_TEMPLATE_ T30,
+    GTEST_TEMPLATE_ T31, GTEST_TEMPLATE_ T32, GTEST_TEMPLATE_ T33,
+    GTEST_TEMPLATE_ T34>
+struct Templates<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+    T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29,
+    T30, T31, T32, T33, T34, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT> {
+  typedef Templates34<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+      T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27,
+      T28, T29, T30, T31, T32, T33, T34> type;
+};
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+    GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+    GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+    GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
+    GTEST_TEMPLATE_ T25, GTEST_TEMPLATE_ T26, GTEST_TEMPLATE_ T27,
+    GTEST_TEMPLATE_ T28, GTEST_TEMPLATE_ T29, GTEST_TEMPLATE_ T30,
+    GTEST_TEMPLATE_ T31, GTEST_TEMPLATE_ T32, GTEST_TEMPLATE_ T33,
+    GTEST_TEMPLATE_ T34, GTEST_TEMPLATE_ T35>
+struct Templates<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+    T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29,
+    T30, T31, T32, T33, T34, T35, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT> {
+  typedef Templates35<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+      T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27,
+      T28, T29, T30, T31, T32, T33, T34, T35> type;
+};
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+    GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+    GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+    GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
+    GTEST_TEMPLATE_ T25, GTEST_TEMPLATE_ T26, GTEST_TEMPLATE_ T27,
+    GTEST_TEMPLATE_ T28, GTEST_TEMPLATE_ T29, GTEST_TEMPLATE_ T30,
+    GTEST_TEMPLATE_ T31, GTEST_TEMPLATE_ T32, GTEST_TEMPLATE_ T33,
+    GTEST_TEMPLATE_ T34, GTEST_TEMPLATE_ T35, GTEST_TEMPLATE_ T36>
+struct Templates<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+    T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29,
+    T30, T31, T32, T33, T34, T35, T36, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT> {
+  typedef Templates36<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+      T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27,
+      T28, T29, T30, T31, T32, T33, T34, T35, T36> type;
+};
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+    GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+    GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+    GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
+    GTEST_TEMPLATE_ T25, GTEST_TEMPLATE_ T26, GTEST_TEMPLATE_ T27,
+    GTEST_TEMPLATE_ T28, GTEST_TEMPLATE_ T29, GTEST_TEMPLATE_ T30,
+    GTEST_TEMPLATE_ T31, GTEST_TEMPLATE_ T32, GTEST_TEMPLATE_ T33,
+    GTEST_TEMPLATE_ T34, GTEST_TEMPLATE_ T35, GTEST_TEMPLATE_ T36,
+    GTEST_TEMPLATE_ T37>
+struct Templates<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+    T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29,
+    T30, T31, T32, T33, T34, T35, T36, T37, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT> {
+  typedef Templates37<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+      T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27,
+      T28, T29, T30, T31, T32, T33, T34, T35, T36, T37> type;
+};
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+    GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+    GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+    GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
+    GTEST_TEMPLATE_ T25, GTEST_TEMPLATE_ T26, GTEST_TEMPLATE_ T27,
+    GTEST_TEMPLATE_ T28, GTEST_TEMPLATE_ T29, GTEST_TEMPLATE_ T30,
+    GTEST_TEMPLATE_ T31, GTEST_TEMPLATE_ T32, GTEST_TEMPLATE_ T33,
+    GTEST_TEMPLATE_ T34, GTEST_TEMPLATE_ T35, GTEST_TEMPLATE_ T36,
+    GTEST_TEMPLATE_ T37, GTEST_TEMPLATE_ T38>
+struct Templates<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+    T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29,
+    T30, T31, T32, T33, T34, T35, T36, T37, T38, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT> {
+  typedef Templates38<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+      T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27,
+      T28, T29, T30, T31, T32, T33, T34, T35, T36, T37, T38> type;
+};
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+    GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+    GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+    GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
+    GTEST_TEMPLATE_ T25, GTEST_TEMPLATE_ T26, GTEST_TEMPLATE_ T27,
+    GTEST_TEMPLATE_ T28, GTEST_TEMPLATE_ T29, GTEST_TEMPLATE_ T30,
+    GTEST_TEMPLATE_ T31, GTEST_TEMPLATE_ T32, GTEST_TEMPLATE_ T33,
+    GTEST_TEMPLATE_ T34, GTEST_TEMPLATE_ T35, GTEST_TEMPLATE_ T36,
+    GTEST_TEMPLATE_ T37, GTEST_TEMPLATE_ T38, GTEST_TEMPLATE_ T39>
+struct Templates<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+    T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29,
+    T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT> {
+  typedef Templates39<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+      T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27,
+      T28, T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39> type;
+};
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+    GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+    GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+    GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
+    GTEST_TEMPLATE_ T25, GTEST_TEMPLATE_ T26, GTEST_TEMPLATE_ T27,
+    GTEST_TEMPLATE_ T28, GTEST_TEMPLATE_ T29, GTEST_TEMPLATE_ T30,
+    GTEST_TEMPLATE_ T31, GTEST_TEMPLATE_ T32, GTEST_TEMPLATE_ T33,
+    GTEST_TEMPLATE_ T34, GTEST_TEMPLATE_ T35, GTEST_TEMPLATE_ T36,
+    GTEST_TEMPLATE_ T37, GTEST_TEMPLATE_ T38, GTEST_TEMPLATE_ T39,
+    GTEST_TEMPLATE_ T40>
+struct Templates<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+    T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29,
+    T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT> {
+  typedef Templates40<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+      T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27,
+      T28, T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40> type;
+};
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+    GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+    GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+    GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
+    GTEST_TEMPLATE_ T25, GTEST_TEMPLATE_ T26, GTEST_TEMPLATE_ T27,
+    GTEST_TEMPLATE_ T28, GTEST_TEMPLATE_ T29, GTEST_TEMPLATE_ T30,
+    GTEST_TEMPLATE_ T31, GTEST_TEMPLATE_ T32, GTEST_TEMPLATE_ T33,
+    GTEST_TEMPLATE_ T34, GTEST_TEMPLATE_ T35, GTEST_TEMPLATE_ T36,
+    GTEST_TEMPLATE_ T37, GTEST_TEMPLATE_ T38, GTEST_TEMPLATE_ T39,
+    GTEST_TEMPLATE_ T40, GTEST_TEMPLATE_ T41>
+struct Templates<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+    T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29,
+    T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT> {
+  typedef Templates41<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+      T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27,
+      T28, T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40,
+      T41> type;
+};
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+    GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+    GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+    GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
+    GTEST_TEMPLATE_ T25, GTEST_TEMPLATE_ T26, GTEST_TEMPLATE_ T27,
+    GTEST_TEMPLATE_ T28, GTEST_TEMPLATE_ T29, GTEST_TEMPLATE_ T30,
+    GTEST_TEMPLATE_ T31, GTEST_TEMPLATE_ T32, GTEST_TEMPLATE_ T33,
+    GTEST_TEMPLATE_ T34, GTEST_TEMPLATE_ T35, GTEST_TEMPLATE_ T36,
+    GTEST_TEMPLATE_ T37, GTEST_TEMPLATE_ T38, GTEST_TEMPLATE_ T39,
+    GTEST_TEMPLATE_ T40, GTEST_TEMPLATE_ T41, GTEST_TEMPLATE_ T42>
+struct Templates<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+    T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29,
+    T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41, T42, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT> {
+  typedef Templates42<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+      T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27,
+      T28, T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41,
+      T42> type;
+};
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+    GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+    GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+    GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
+    GTEST_TEMPLATE_ T25, GTEST_TEMPLATE_ T26, GTEST_TEMPLATE_ T27,
+    GTEST_TEMPLATE_ T28, GTEST_TEMPLATE_ T29, GTEST_TEMPLATE_ T30,
+    GTEST_TEMPLATE_ T31, GTEST_TEMPLATE_ T32, GTEST_TEMPLATE_ T33,
+    GTEST_TEMPLATE_ T34, GTEST_TEMPLATE_ T35, GTEST_TEMPLATE_ T36,
+    GTEST_TEMPLATE_ T37, GTEST_TEMPLATE_ T38, GTEST_TEMPLATE_ T39,
+    GTEST_TEMPLATE_ T40, GTEST_TEMPLATE_ T41, GTEST_TEMPLATE_ T42,
+    GTEST_TEMPLATE_ T43>
+struct Templates<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+    T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29,
+    T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41, T42, T43,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT> {
+  typedef Templates43<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+      T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27,
+      T28, T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41,
+      T42, T43> type;
+};
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+    GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+    GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+    GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
+    GTEST_TEMPLATE_ T25, GTEST_TEMPLATE_ T26, GTEST_TEMPLATE_ T27,
+    GTEST_TEMPLATE_ T28, GTEST_TEMPLATE_ T29, GTEST_TEMPLATE_ T30,
+    GTEST_TEMPLATE_ T31, GTEST_TEMPLATE_ T32, GTEST_TEMPLATE_ T33,
+    GTEST_TEMPLATE_ T34, GTEST_TEMPLATE_ T35, GTEST_TEMPLATE_ T36,
+    GTEST_TEMPLATE_ T37, GTEST_TEMPLATE_ T38, GTEST_TEMPLATE_ T39,
+    GTEST_TEMPLATE_ T40, GTEST_TEMPLATE_ T41, GTEST_TEMPLATE_ T42,
+    GTEST_TEMPLATE_ T43, GTEST_TEMPLATE_ T44>
+struct Templates<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+    T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29,
+    T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41, T42, T43, T44,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT> {
+  typedef Templates44<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+      T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27,
+      T28, T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41,
+      T42, T43, T44> type;
+};
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+    GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+    GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+    GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
+    GTEST_TEMPLATE_ T25, GTEST_TEMPLATE_ T26, GTEST_TEMPLATE_ T27,
+    GTEST_TEMPLATE_ T28, GTEST_TEMPLATE_ T29, GTEST_TEMPLATE_ T30,
+    GTEST_TEMPLATE_ T31, GTEST_TEMPLATE_ T32, GTEST_TEMPLATE_ T33,
+    GTEST_TEMPLATE_ T34, GTEST_TEMPLATE_ T35, GTEST_TEMPLATE_ T36,
+    GTEST_TEMPLATE_ T37, GTEST_TEMPLATE_ T38, GTEST_TEMPLATE_ T39,
+    GTEST_TEMPLATE_ T40, GTEST_TEMPLATE_ T41, GTEST_TEMPLATE_ T42,
+    GTEST_TEMPLATE_ T43, GTEST_TEMPLATE_ T44, GTEST_TEMPLATE_ T45>
+struct Templates<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+    T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29,
+    T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41, T42, T43, T44,
+    T45, NoneT, NoneT, NoneT, NoneT, NoneT> {
+  typedef Templates45<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+      T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27,
+      T28, T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41,
+      T42, T43, T44, T45> type;
+};
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+    GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+    GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+    GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
+    GTEST_TEMPLATE_ T25, GTEST_TEMPLATE_ T26, GTEST_TEMPLATE_ T27,
+    GTEST_TEMPLATE_ T28, GTEST_TEMPLATE_ T29, GTEST_TEMPLATE_ T30,
+    GTEST_TEMPLATE_ T31, GTEST_TEMPLATE_ T32, GTEST_TEMPLATE_ T33,
+    GTEST_TEMPLATE_ T34, GTEST_TEMPLATE_ T35, GTEST_TEMPLATE_ T36,
+    GTEST_TEMPLATE_ T37, GTEST_TEMPLATE_ T38, GTEST_TEMPLATE_ T39,
+    GTEST_TEMPLATE_ T40, GTEST_TEMPLATE_ T41, GTEST_TEMPLATE_ T42,
+    GTEST_TEMPLATE_ T43, GTEST_TEMPLATE_ T44, GTEST_TEMPLATE_ T45,
+    GTEST_TEMPLATE_ T46>
+struct Templates<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+    T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29,
+    T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41, T42, T43, T44,
+    T45, T46, NoneT, NoneT, NoneT, NoneT> {
+  typedef Templates46<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+      T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27,
+      T28, T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41,
+      T42, T43, T44, T45, T46> type;
+};
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+    GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+    GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+    GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
+    GTEST_TEMPLATE_ T25, GTEST_TEMPLATE_ T26, GTEST_TEMPLATE_ T27,
+    GTEST_TEMPLATE_ T28, GTEST_TEMPLATE_ T29, GTEST_TEMPLATE_ T30,
+    GTEST_TEMPLATE_ T31, GTEST_TEMPLATE_ T32, GTEST_TEMPLATE_ T33,
+    GTEST_TEMPLATE_ T34, GTEST_TEMPLATE_ T35, GTEST_TEMPLATE_ T36,
+    GTEST_TEMPLATE_ T37, GTEST_TEMPLATE_ T38, GTEST_TEMPLATE_ T39,
+    GTEST_TEMPLATE_ T40, GTEST_TEMPLATE_ T41, GTEST_TEMPLATE_ T42,
+    GTEST_TEMPLATE_ T43, GTEST_TEMPLATE_ T44, GTEST_TEMPLATE_ T45,
+    GTEST_TEMPLATE_ T46, GTEST_TEMPLATE_ T47>
+struct Templates<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+    T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29,
+    T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41, T42, T43, T44,
+    T45, T46, T47, NoneT, NoneT, NoneT> {
+  typedef Templates47<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+      T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27,
+      T28, T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41,
+      T42, T43, T44, T45, T46, T47> type;
+};
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+    GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+    GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+    GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
+    GTEST_TEMPLATE_ T25, GTEST_TEMPLATE_ T26, GTEST_TEMPLATE_ T27,
+    GTEST_TEMPLATE_ T28, GTEST_TEMPLATE_ T29, GTEST_TEMPLATE_ T30,
+    GTEST_TEMPLATE_ T31, GTEST_TEMPLATE_ T32, GTEST_TEMPLATE_ T33,
+    GTEST_TEMPLATE_ T34, GTEST_TEMPLATE_ T35, GTEST_TEMPLATE_ T36,
+    GTEST_TEMPLATE_ T37, GTEST_TEMPLATE_ T38, GTEST_TEMPLATE_ T39,
+    GTEST_TEMPLATE_ T40, GTEST_TEMPLATE_ T41, GTEST_TEMPLATE_ T42,
+    GTEST_TEMPLATE_ T43, GTEST_TEMPLATE_ T44, GTEST_TEMPLATE_ T45,
+    GTEST_TEMPLATE_ T46, GTEST_TEMPLATE_ T47, GTEST_TEMPLATE_ T48>
+struct Templates<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+    T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29,
+    T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41, T42, T43, T44,
+    T45, T46, T47, T48, NoneT, NoneT> {
+  typedef Templates48<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+      T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27,
+      T28, T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41,
+      T42, T43, T44, T45, T46, T47, T48> type;
+};
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+    GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+    GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+    GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
+    GTEST_TEMPLATE_ T25, GTEST_TEMPLATE_ T26, GTEST_TEMPLATE_ T27,
+    GTEST_TEMPLATE_ T28, GTEST_TEMPLATE_ T29, GTEST_TEMPLATE_ T30,
+    GTEST_TEMPLATE_ T31, GTEST_TEMPLATE_ T32, GTEST_TEMPLATE_ T33,
+    GTEST_TEMPLATE_ T34, GTEST_TEMPLATE_ T35, GTEST_TEMPLATE_ T36,
+    GTEST_TEMPLATE_ T37, GTEST_TEMPLATE_ T38, GTEST_TEMPLATE_ T39,
+    GTEST_TEMPLATE_ T40, GTEST_TEMPLATE_ T41, GTEST_TEMPLATE_ T42,
+    GTEST_TEMPLATE_ T43, GTEST_TEMPLATE_ T44, GTEST_TEMPLATE_ T45,
+    GTEST_TEMPLATE_ T46, GTEST_TEMPLATE_ T47, GTEST_TEMPLATE_ T48,
+    GTEST_TEMPLATE_ T49>
+struct Templates<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+    T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29,
+    T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41, T42, T43, T44,
+    T45, T46, T47, T48, T49, NoneT> {
+  typedef Templates49<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+      T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27,
+      T28, T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41,
+      T42, T43, T44, T45, T46, T47, T48, T49> type;
+};
+
+// The TypeList template makes it possible to use either a single type
+// or a Types<...> list in TYPED_TEST_CASE() and
+// INSTANTIATE_TYPED_TEST_CASE_P().
+
+template <typename T>
+struct TypeList {
+  typedef Types1<T> type;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32, typename T33, typename T34, typename T35,
+    typename T36, typename T37, typename T38, typename T39, typename T40,
+    typename T41, typename T42, typename T43, typename T44, typename T45,
+    typename T46, typename T47, typename T48, typename T49, typename T50>
+struct TypeList<Types<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+    T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28,
+    T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41, T42, T43,
+    T44, T45, T46, T47, T48, T49, T50> > {
+  typedef typename Types<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12,
+      T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26,
+      T27, T28, T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40,
+      T41, T42, T43, T44, T45, T46, T47, T48, T49, T50>::type type;
+};
+
+#endif  // GTEST_HAS_TYPED_TEST || GTEST_HAS_TYPED_TEST_P
+
+}  // namespace internal
+}  // namespace testing
+
+#endif  // GTEST_INCLUDE_GTEST_INTERNAL_GTEST_TYPE_UTIL_H_
diff --git a/test/gtest/include/gtest/internal/gtest-type-util.h.pump b/test/gtest/include/gtest/internal/gtest-type-util.h.pump
new file mode 100644
index 0000000..251fdf0
--- /dev/null
+++ b/test/gtest/include/gtest/internal/gtest-type-util.h.pump
@@ -0,0 +1,297 @@
+$$ -*- mode: c++; -*-
+$var n = 50  $$ Maximum length of type lists we want to support.
+// Copyright 2008 Google Inc.
+// All Rights Reserved.
+//
+// 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: wan at google.com (Zhanyong Wan)
+
+// Type utilities needed for implementing typed and type-parameterized
+// tests.  This file is generated by a SCRIPT.  DO NOT EDIT BY HAND!
+//
+// Currently we support at most $n types in a list, and at most $n
+// type-parameterized tests in one type-parameterized test case.
+// Please contact googletestframework at googlegroups.com if you need
+// more.
+
+#ifndef GTEST_INCLUDE_GTEST_INTERNAL_GTEST_TYPE_UTIL_H_
+#define GTEST_INCLUDE_GTEST_INTERNAL_GTEST_TYPE_UTIL_H_
+
+#include "gtest/internal/gtest-port.h"
+
+// #ifdef __GNUC__ is too general here.  It is possible to use gcc without using
+// libstdc++ (which is where cxxabi.h comes from).
+# if GTEST_HAS_CXXABI_H_
+#  include <cxxabi.h>
+# elif defined(__HP_aCC)
+#  include <acxx_demangle.h>
+# endif  // GTEST_HASH_CXXABI_H_
+
+namespace testing {
+namespace internal {
+
+// GetTypeName<T>() returns a human-readable name of type T.
+// NB: This function is also used in Google Mock, so don't move it inside of
+// the typed-test-only section below.
+template <typename T>
+std::string GetTypeName() {
+# if GTEST_HAS_RTTI
+
+  const char* const name = typeid(T).name();
+#  if GTEST_HAS_CXXABI_H_ || defined(__HP_aCC)
+  int status = 0;
+  // gcc's implementation of typeid(T).name() mangles the type name,
+  // so we have to demangle it.
+#   if GTEST_HAS_CXXABI_H_
+  using abi::__cxa_demangle;
+#   endif  // GTEST_HAS_CXXABI_H_
+  char* const readable_name = __cxa_demangle(name, 0, 0, &status);
+  const std::string name_str(status == 0 ? readable_name : name);
+  free(readable_name);
+  return name_str;
+#  else
+  return name;
+#  endif  // GTEST_HAS_CXXABI_H_ || __HP_aCC
+
+# else
+
+  return "<type>";
+
+# endif  // GTEST_HAS_RTTI
+}
+
+#if GTEST_HAS_TYPED_TEST || GTEST_HAS_TYPED_TEST_P
+
+// AssertyTypeEq<T1, T2>::type is defined iff T1 and T2 are the same
+// type.  This can be used as a compile-time assertion to ensure that
+// two types are equal.
+
+template <typename T1, typename T2>
+struct AssertTypeEq;
+
+template <typename T>
+struct AssertTypeEq<T, T> {
+  typedef bool type;
+};
+
+// A unique type used as the default value for the arguments of class
+// template Types.  This allows us to simulate variadic templates
+// (e.g. Types<int>, Type<int, double>, and etc), which C++ doesn't
+// support directly.
+struct None {};
+
+// The following family of struct and struct templates are used to
+// represent type lists.  In particular, TypesN<T1, T2, ..., TN>
+// represents a type list with N types (T1, T2, ..., and TN) in it.
+// Except for Types0, every struct in the family has two member types:
+// Head for the first type in the list, and Tail for the rest of the
+// list.
+
+// The empty type list.
+struct Types0 {};
+
+// Type lists of length 1, 2, 3, and so on.
+
+template <typename T1>
+struct Types1 {
+  typedef T1 Head;
+  typedef Types0 Tail;
+};
+
+$range i 2..n
+
+$for i [[
+$range j 1..i
+$range k 2..i
+template <$for j, [[typename T$j]]>
+struct Types$i {
+  typedef T1 Head;
+  typedef Types$(i-1)<$for k, [[T$k]]> Tail;
+};
+
+
+]]
+
+}  // namespace internal
+
+// We don't want to require the users to write TypesN<...> directly,
+// as that would require them to count the length.  Types<...> is much
+// easier to write, but generates horrible messages when there is a
+// compiler error, as gcc insists on printing out each template
+// argument, even if it has the default value (this means Types<int>
+// will appear as Types<int, None, None, ..., None> in the compiler
+// errors).
+//
+// Our solution is to combine the best part of the two approaches: a
+// user would write Types<T1, ..., TN>, and Google Test will translate
+// that to TypesN<T1, ..., TN> internally to make error messages
+// readable.  The translation is done by the 'type' member of the
+// Types template.
+
+$range i 1..n
+template <$for i, [[typename T$i = internal::None]]>
+struct Types {
+  typedef internal::Types$n<$for i, [[T$i]]> type;
+};
+
+template <>
+struct Types<$for i, [[internal::None]]> {
+  typedef internal::Types0 type;
+};
+
+$range i 1..n-1
+$for i [[
+$range j 1..i
+$range k i+1..n
+template <$for j, [[typename T$j]]>
+struct Types<$for j, [[T$j]]$for k[[, internal::None]]> {
+  typedef internal::Types$i<$for j, [[T$j]]> type;
+};
+
+]]
+
+namespace internal {
+
+# define GTEST_TEMPLATE_ template <typename T> class
+
+// The template "selector" struct TemplateSel<Tmpl> is used to
+// represent Tmpl, which must be a class template with one type
+// parameter, as a type.  TemplateSel<Tmpl>::Bind<T>::type is defined
+// as the type Tmpl<T>.  This allows us to actually instantiate the
+// template "selected" by TemplateSel<Tmpl>.
+//
+// This trick is necessary for simulating typedef for class templates,
+// which C++ doesn't support directly.
+template <GTEST_TEMPLATE_ Tmpl>
+struct TemplateSel {
+  template <typename T>
+  struct Bind {
+    typedef Tmpl<T> type;
+  };
+};
+
+# define GTEST_BIND_(TmplSel, T) \
+  TmplSel::template Bind<T>::type
+
+// A unique struct template used as the default value for the
+// arguments of class template Templates.  This allows us to simulate
+// variadic templates (e.g. Templates<int>, Templates<int, double>,
+// and etc), which C++ doesn't support directly.
+template <typename T>
+struct NoneT {};
+
+// The following family of struct and struct templates are used to
+// represent template lists.  In particular, TemplatesN<T1, T2, ...,
+// TN> represents a list of N templates (T1, T2, ..., and TN).  Except
+// for Templates0, every struct in the family has two member types:
+// Head for the selector of the first template in the list, and Tail
+// for the rest of the list.
+
+// The empty template list.
+struct Templates0 {};
+
+// Template lists of length 1, 2, 3, and so on.
+
+template <GTEST_TEMPLATE_ T1>
+struct Templates1 {
+  typedef TemplateSel<T1> Head;
+  typedef Templates0 Tail;
+};
+
+$range i 2..n
+
+$for i [[
+$range j 1..i
+$range k 2..i
+template <$for j, [[GTEST_TEMPLATE_ T$j]]>
+struct Templates$i {
+  typedef TemplateSel<T1> Head;
+  typedef Templates$(i-1)<$for k, [[T$k]]> Tail;
+};
+
+
+]]
+
+// We don't want to require the users to write TemplatesN<...> directly,
+// as that would require them to count the length.  Templates<...> is much
+// easier to write, but generates horrible messages when there is a
+// compiler error, as gcc insists on printing out each template
+// argument, even if it has the default value (this means Templates<list>
+// will appear as Templates<list, NoneT, NoneT, ..., NoneT> in the compiler
+// errors).
+//
+// Our solution is to combine the best part of the two approaches: a
+// user would write Templates<T1, ..., TN>, and Google Test will translate
+// that to TemplatesN<T1, ..., TN> internally to make error messages
+// readable.  The translation is done by the 'type' member of the
+// Templates template.
+
+$range i 1..n
+template <$for i, [[GTEST_TEMPLATE_ T$i = NoneT]]>
+struct Templates {
+  typedef Templates$n<$for i, [[T$i]]> type;
+};
+
+template <>
+struct Templates<$for i, [[NoneT]]> {
+  typedef Templates0 type;
+};
+
+$range i 1..n-1
+$for i [[
+$range j 1..i
+$range k i+1..n
+template <$for j, [[GTEST_TEMPLATE_ T$j]]>
+struct Templates<$for j, [[T$j]]$for k[[, NoneT]]> {
+  typedef Templates$i<$for j, [[T$j]]> type;
+};
+
+]]
+
+// The TypeList template makes it possible to use either a single type
+// or a Types<...> list in TYPED_TEST_CASE() and
+// INSTANTIATE_TYPED_TEST_CASE_P().
+
+template <typename T>
+struct TypeList {
+  typedef Types1<T> type;
+};
+
+
+$range i 1..n
+template <$for i, [[typename T$i]]>
+struct TypeList<Types<$for i, [[T$i]]> > {
+  typedef typename Types<$for i, [[T$i]]>::type type;
+};
+
+#endif  // GTEST_HAS_TYPED_TEST || GTEST_HAS_TYPED_TEST_P
+
+}  // namespace internal
+}  // namespace testing
+
+#endif  // GTEST_INCLUDE_GTEST_INTERNAL_GTEST_TYPE_UTIL_H_
diff --git a/test/gtest/src/gtest-all.cc b/test/gtest/src/gtest-all.cc
new file mode 100644
index 0000000..0a9cee5
--- /dev/null
+++ b/test/gtest/src/gtest-all.cc
@@ -0,0 +1,48 @@
+// Copyright 2008, Google Inc.
+// All rights reserved.
+//
+// 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: mheule at google.com (Markus Heule)
+//
+// Google C++ Testing Framework (Google Test)
+//
+// Sometimes it's desirable to build Google Test by compiling a single file.
+// This file serves this purpose.
+
+// This line ensures that gtest.h can be compiled on its own, even
+// when it's fused.
+#include "gtest/gtest.h"
+
+// The following lines pull in the real gtest *.cc files.
+#include "src/gtest.cc"
+#include "src/gtest-death-test.cc"
+#include "src/gtest-filepath.cc"
+#include "src/gtest-port.cc"
+#include "src/gtest-printers.cc"
+#include "src/gtest-test-part.cc"
+#include "src/gtest-typed-test.cc"
diff --git a/test/gtest/src/gtest-death-test.cc b/test/gtest/src/gtest-death-test.cc
new file mode 100644
index 0000000..a6023fc
--- /dev/null
+++ b/test/gtest/src/gtest-death-test.cc
@@ -0,0 +1,1344 @@
+// Copyright 2005, Google Inc.
+// All rights reserved.
+//
+// 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: wan at google.com (Zhanyong Wan), vladl at google.com (Vlad Losev)
+//
+// This file implements death tests.
+
+#include "gtest/gtest-death-test.h"
+#include "gtest/internal/gtest-port.h"
+
+#if GTEST_HAS_DEATH_TEST
+
+# if GTEST_OS_MAC
+#  include <crt_externs.h>
+# endif  // GTEST_OS_MAC
+
+# include <errno.h>
+# include <fcntl.h>
+# include <limits.h>
+
+# if GTEST_OS_LINUX
+#  include <signal.h>
+# endif  // GTEST_OS_LINUX
+
+# include <stdarg.h>
+
+# if GTEST_OS_WINDOWS
+#  include <windows.h>
+# else
+#  include <sys/mman.h>
+#  include <sys/wait.h>
+# endif  // GTEST_OS_WINDOWS
+
+# if GTEST_OS_QNX
+#  include <spawn.h>
+# endif  // GTEST_OS_QNX
+
+#endif  // GTEST_HAS_DEATH_TEST
+
+#include "gtest/gtest-message.h"
+#include "gtest/internal/gtest-string.h"
+
+// Indicates that this translation unit is part of Google Test's
+// implementation.  It must come before gtest-internal-inl.h is
+// included, or there will be a compiler error.  This trick is to
+// prevent a user from accidentally including gtest-internal-inl.h in
+// his code.
+#define GTEST_IMPLEMENTATION_ 1
+#include "src/gtest-internal-inl.h"
+#undef GTEST_IMPLEMENTATION_
+
+namespace testing {
+
+// Constants.
+
+// The default death test style.
+static const char kDefaultDeathTestStyle[] = "fast";
+
+GTEST_DEFINE_string_(
+    death_test_style,
+    internal::StringFromGTestEnv("death_test_style", kDefaultDeathTestStyle),
+    "Indicates how to run a death test in a forked child process: "
+    "\"threadsafe\" (child process re-executes the test binary "
+    "from the beginning, running only the specific death test) or "
+    "\"fast\" (child process runs the death test immediately "
+    "after forking).");
+
+GTEST_DEFINE_bool_(
+    death_test_use_fork,
+    internal::BoolFromGTestEnv("death_test_use_fork", false),
+    "Instructs to use fork()/_exit() instead of clone() in death tests. "
+    "Ignored and always uses fork() on POSIX systems where clone() is not "
+    "implemented. Useful when running under valgrind or similar tools if "
+    "those do not support clone(). Valgrind 3.3.1 will just fail if "
+    "it sees an unsupported combination of clone() flags. "
+    "It is not recommended to use this flag w/o valgrind though it will "
+    "work in 99% of the cases. Once valgrind is fixed, this flag will "
+    "most likely be removed.");
+
+namespace internal {
+GTEST_DEFINE_string_(
+    internal_run_death_test, "",
+    "Indicates the file, line number, temporal index of "
+    "the single death test to run, and a file descriptor to "
+    "which a success code may be sent, all separated by "
+    "the '|' characters.  This flag is specified if and only if the current "
+    "process is a sub-process launched for running a thread-safe "
+    "death test.  FOR INTERNAL USE ONLY.");
+}  // namespace internal
+
+#if GTEST_HAS_DEATH_TEST
+
+namespace internal {
+
+// Valid only for fast death tests. Indicates the code is running in the
+// child process of a fast style death test.
+static bool g_in_fast_death_test_child = false;
+
+// Returns a Boolean value indicating whether the caller is currently
+// executing in the context of the death test child process.  Tools such as
+// Valgrind heap checkers may need this to modify their behavior in death
+// tests.  IMPORTANT: This is an internal utility.  Using it may break the
+// implementation of death tests.  User code MUST NOT use it.
+bool InDeathTestChild() {
+# if GTEST_OS_WINDOWS
+
+  // On Windows, death tests are thread-safe regardless of the value of the
+  // death_test_style flag.
+  return !GTEST_FLAG(internal_run_death_test).empty();
+
+# else
+
+  if (GTEST_FLAG(death_test_style) == "threadsafe")
+    return !GTEST_FLAG(internal_run_death_test).empty();
+  else
+    return g_in_fast_death_test_child;
+#endif
+}
+
+}  // namespace internal
+
+// ExitedWithCode constructor.
+ExitedWithCode::ExitedWithCode(int exit_code) : exit_code_(exit_code) {
+}
+
+// ExitedWithCode function-call operator.
+bool ExitedWithCode::operator()(int exit_status) const {
+# if GTEST_OS_WINDOWS
+
+  return exit_status == exit_code_;
+
+# else
+
+  return WIFEXITED(exit_status) && WEXITSTATUS(exit_status) == exit_code_;
+
+# endif  // GTEST_OS_WINDOWS
+}
+
+# if !GTEST_OS_WINDOWS
+// KilledBySignal constructor.
+KilledBySignal::KilledBySignal(int signum) : signum_(signum) {
+}
+
+// KilledBySignal function-call operator.
+bool KilledBySignal::operator()(int exit_status) const {
+  return WIFSIGNALED(exit_status) && WTERMSIG(exit_status) == signum_;
+}
+# endif  // !GTEST_OS_WINDOWS
+
+namespace internal {
+
+// Utilities needed for death tests.
+
+// Generates a textual description of a given exit code, in the format
+// specified by wait(2).
+static std::string ExitSummary(int exit_code) {
+  Message m;
+
+# if GTEST_OS_WINDOWS
+
+  m << "Exited with exit status " << exit_code;
+
+# else
+
+  if (WIFEXITED(exit_code)) {
+    m << "Exited with exit status " << WEXITSTATUS(exit_code);
+  } else if (WIFSIGNALED(exit_code)) {
+    m << "Terminated by signal " << WTERMSIG(exit_code);
+  }
+#  ifdef WCOREDUMP
+  if (WCOREDUMP(exit_code)) {
+    m << " (core dumped)";
+  }
+#  endif
+# endif  // GTEST_OS_WINDOWS
+
+  return m.GetString();
+}
+
+// Returns true if exit_status describes a process that was terminated
+// by a signal, or exited normally with a nonzero exit code.
+bool ExitedUnsuccessfully(int exit_status) {
+  return !ExitedWithCode(0)(exit_status);
+}
+
+# if !GTEST_OS_WINDOWS
+// Generates a textual failure message when a death test finds more than
+// one thread running, or cannot determine the number of threads, prior
+// to executing the given statement.  It is the responsibility of the
+// caller not to pass a thread_count of 1.
+static std::string DeathTestThreadWarning(size_t thread_count) {
+  Message msg;
+  msg << "Death tests use fork(), which is unsafe particularly"
+      << " in a threaded context. For this test, " << GTEST_NAME_ << " ";
+  if (thread_count == 0)
+    msg << "couldn't detect the number of threads.";
+  else
+    msg << "detected " << thread_count << " threads.";
+  return msg.GetString();
+}
+# endif  // !GTEST_OS_WINDOWS
+
+// Flag characters for reporting a death test that did not die.
+static const char kDeathTestLived = 'L';
+static const char kDeathTestReturned = 'R';
+static const char kDeathTestThrew = 'T';
+static const char kDeathTestInternalError = 'I';
+
+// An enumeration describing all of the possible ways that a death test can
+// conclude.  DIED means that the process died while executing the test
+// code; LIVED means that process lived beyond the end of the test code;
+// RETURNED means that the test statement attempted to execute a return
+// statement, which is not allowed; THREW means that the test statement
+// returned control by throwing an exception.  IN_PROGRESS means the test
+// has not yet concluded.
+// TODO(vladl at google.com): Unify names and possibly values for
+// AbortReason, DeathTestOutcome, and flag characters above.
+enum DeathTestOutcome { IN_PROGRESS, DIED, LIVED, RETURNED, THREW };
+
+// Routine for aborting the program which is safe to call from an
+// exec-style death test child process, in which case the error
+// message is propagated back to the parent process.  Otherwise, the
+// message is simply printed to stderr.  In either case, the program
+// then exits with status 1.
+void DeathTestAbort(const std::string& message) {
+  // On a POSIX system, this function may be called from a threadsafe-style
+  // death test child process, which operates on a very small stack.  Use
+  // the heap for any additional non-minuscule memory requirements.
+  const InternalRunDeathTestFlag* const flag =
+      GetUnitTestImpl()->internal_run_death_test_flag();
+  if (flag != NULL) {
+    FILE* parent = posix::FDOpen(flag->write_fd(), "w");
+    fputc(kDeathTestInternalError, parent);
+    fprintf(parent, "%s", message.c_str());
+    fflush(parent);
+    _exit(1);
+  } else {
+    fprintf(stderr, "%s", message.c_str());
+    fflush(stderr);
+    posix::Abort();
+  }
+}
+
+// A replacement for CHECK that calls DeathTestAbort if the assertion
+// fails.
+# define GTEST_DEATH_TEST_CHECK_(expression) \
+  do { \
+    if (!::testing::internal::IsTrue(expression)) { \
+      DeathTestAbort( \
+          ::std::string("CHECK failed: File ") + __FILE__ +  ", line " \
+          + ::testing::internal::StreamableToString(__LINE__) + ": " \
+          + #expression); \
+    } \
+  } while (::testing::internal::AlwaysFalse())
+
+// This macro is similar to GTEST_DEATH_TEST_CHECK_, but it is meant for
+// evaluating any system call that fulfills two conditions: it must return
+// -1 on failure, and set errno to EINTR when it is interrupted and
+// should be tried again.  The macro expands to a loop that repeatedly
+// evaluates the expression as long as it evaluates to -1 and sets
+// errno to EINTR.  If the expression evaluates to -1 but errno is
+// something other than EINTR, DeathTestAbort is called.
+# define GTEST_DEATH_TEST_CHECK_SYSCALL_(expression) \
+  do { \
+    int gtest_retval; \
+    do { \
+      gtest_retval = (expression); \
+    } while (gtest_retval == -1 && errno == EINTR); \
+    if (gtest_retval == -1) { \
+      DeathTestAbort( \
+          ::std::string("CHECK failed: File ") + __FILE__ + ", line " \
+          + ::testing::internal::StreamableToString(__LINE__) + ": " \
+          + #expression + " != -1"); \
+    } \
+  } while (::testing::internal::AlwaysFalse())
+
+// Returns the message describing the last system error in errno.
+std::string GetLastErrnoDescription() {
+    return errno == 0 ? "" : posix::StrError(errno);
+}
+
+// This is called from a death test parent process to read a failure
+// message from the death test child process and log it with the FATAL
+// severity. On Windows, the message is read from a pipe handle. On other
+// platforms, it is read from a file descriptor.
+static void FailFromInternalError(int fd) {
+  Message error;
+  char buffer[256];
+  int num_read;
+
+  do {
+    while ((num_read = posix::Read(fd, buffer, 255)) > 0) {
+      buffer[num_read] = '\0';
+      error << buffer;
+    }
+  } while (num_read == -1 && errno == EINTR);
+
+  if (num_read == 0) {
+    GTEST_LOG_(FATAL) << error.GetString();
+  } else {
+    const int last_error = errno;
+    GTEST_LOG_(FATAL) << "Error while reading death test internal: "
+                      << GetLastErrnoDescription() << " [" << last_error << "]";
+  }
+}
+
+// Death test constructor.  Increments the running death test count
+// for the current test.
+DeathTest::DeathTest() {
+  TestInfo* const info = GetUnitTestImpl()->current_test_info();
+  if (info == NULL) {
+    DeathTestAbort("Cannot run a death test outside of a TEST or "
+                   "TEST_F construct");
+  }
+}
+
+// Creates and returns a death test by dispatching to the current
+// death test factory.
+bool DeathTest::Create(const char* statement, const RE* regex,
+                       const char* file, int line, DeathTest** test) {
+  return GetUnitTestImpl()->death_test_factory()->Create(
+      statement, regex, file, line, test);
+}
+
+const char* DeathTest::LastMessage() {
+  return last_death_test_message_.c_str();
+}
+
+void DeathTest::set_last_death_test_message(const std::string& message) {
+  last_death_test_message_ = message;
+}
+
+std::string DeathTest::last_death_test_message_;
+
+// Provides cross platform implementation for some death functionality.
+class DeathTestImpl : public DeathTest {
+ protected:
+  DeathTestImpl(const char* a_statement, const RE* a_regex)
+      : statement_(a_statement),
+        regex_(a_regex),
+        spawned_(false),
+        status_(-1),
+        outcome_(IN_PROGRESS),
+        read_fd_(-1),
+        write_fd_(-1) {}
+
+  // read_fd_ is expected to be closed and cleared by a derived class.
+  ~DeathTestImpl() { GTEST_DEATH_TEST_CHECK_(read_fd_ == -1); }
+
+  void Abort(AbortReason reason);
+  virtual bool Passed(bool status_ok);
+
+  const char* statement() const { return statement_; }
+  const RE* regex() const { return regex_; }
+  bool spawned() const { return spawned_; }
+  void set_spawned(bool is_spawned) { spawned_ = is_spawned; }
+  int status() const { return status_; }
+  void set_status(int a_status) { status_ = a_status; }
+  DeathTestOutcome outcome() const { return outcome_; }
+  void set_outcome(DeathTestOutcome an_outcome) { outcome_ = an_outcome; }
+  int read_fd() const { return read_fd_; }
+  void set_read_fd(int fd) { read_fd_ = fd; }
+  int write_fd() const { return write_fd_; }
+  void set_write_fd(int fd) { write_fd_ = fd; }
+
+  // Called in the parent process only. Reads the result code of the death
+  // test child process via a pipe, interprets it to set the outcome_
+  // member, and closes read_fd_.  Outputs diagnostics and terminates in
+  // case of unexpected codes.
+  void ReadAndInterpretStatusByte();
+
+ private:
+  // The textual content of the code this object is testing.  This class
+  // doesn't own this string and should not attempt to delete it.
+  const char* const statement_;
+  // The regular expression which test output must match.  DeathTestImpl
+  // doesn't own this object and should not attempt to delete it.
+  const RE* const regex_;
+  // True if the death test child process has been successfully spawned.
+  bool spawned_;
+  // The exit status of the child process.
+  int status_;
+  // How the death test concluded.
+  DeathTestOutcome outcome_;
+  // Descriptor to the read end of the pipe to the child process.  It is
+  // always -1 in the child process.  The child keeps its write end of the
+  // pipe in write_fd_.
+  int read_fd_;
+  // Descriptor to the child's write end of the pipe to the parent process.
+  // It is always -1 in the parent process.  The parent keeps its end of the
+  // pipe in read_fd_.
+  int write_fd_;
+};
+
+// Called in the parent process only. Reads the result code of the death
+// test child process via a pipe, interprets it to set the outcome_
+// member, and closes read_fd_.  Outputs diagnostics and terminates in
+// case of unexpected codes.
+void DeathTestImpl::ReadAndInterpretStatusByte() {
+  char flag;
+  int bytes_read;
+
+  // The read() here blocks until data is available (signifying the
+  // failure of the death test) or until the pipe is closed (signifying
+  // its success), so it's okay to call this in the parent before
+  // the child process has exited.
+  do {
+    bytes_read = posix::Read(read_fd(), &flag, 1);
+  } while (bytes_read == -1 && errno == EINTR);
+
+  if (bytes_read == 0) {
+    set_outcome(DIED);
+  } else if (bytes_read == 1) {
+    switch (flag) {
+      case kDeathTestReturned:
+        set_outcome(RETURNED);
+        break;
+      case kDeathTestThrew:
+        set_outcome(THREW);
+        break;
+      case kDeathTestLived:
+        set_outcome(LIVED);
+        break;
+      case kDeathTestInternalError:
+        FailFromInternalError(read_fd());  // Does not return.
+        break;
+      default:
+        GTEST_LOG_(FATAL) << "Death test child process reported "
+                          << "unexpected status byte ("
+                          << static_cast<unsigned int>(flag) << ")";
+    }
+  } else {
+    GTEST_LOG_(FATAL) << "Read from death test child process failed: "
+                      << GetLastErrnoDescription();
+  }
+  GTEST_DEATH_TEST_CHECK_SYSCALL_(posix::Close(read_fd()));
+  set_read_fd(-1);
+}
+
+// Signals that the death test code which should have exited, didn't.
+// Should be called only in a death test child process.
+// Writes a status byte to the child's status file descriptor, then
+// calls _exit(1).
+void DeathTestImpl::Abort(AbortReason reason) {
+  // The parent process considers the death test to be a failure if
+  // it finds any data in our pipe.  So, here we write a single flag byte
+  // to the pipe, then exit.
+  const char status_ch =
+      reason == TEST_DID_NOT_DIE ? kDeathTestLived :
+      reason == TEST_THREW_EXCEPTION ? kDeathTestThrew : kDeathTestReturned;
+
+  GTEST_DEATH_TEST_CHECK_SYSCALL_(posix::Write(write_fd(), &status_ch, 1));
+  // We are leaking the descriptor here because on some platforms (i.e.,
+  // when built as Windows DLL), destructors of global objects will still
+  // run after calling _exit(). On such systems, write_fd_ will be
+  // indirectly closed from the destructor of UnitTestImpl, causing double
+  // close if it is also closed here. On debug configurations, double close
+  // may assert. As there are no in-process buffers to flush here, we are
+  // relying on the OS to close the descriptor after the process terminates
+  // when the destructors are not run.
+  _exit(1);  // Exits w/o any normal exit hooks (we were supposed to crash)
+}
+
+// Returns an indented copy of stderr output for a death test.
+// This makes distinguishing death test output lines from regular log lines
+// much easier.
+static ::std::string FormatDeathTestOutput(const ::std::string& output) {
+  ::std::string ret;
+  for (size_t at = 0; ; ) {
+    const size_t line_end = output.find('\n', at);
+    ret += "[  DEATH   ] ";
+    if (line_end == ::std::string::npos) {
+      ret += output.substr(at);
+      break;
+    }
+    ret += output.substr(at, line_end + 1 - at);
+    at = line_end + 1;
+  }
+  return ret;
+}
+
+// Assesses the success or failure of a death test, using both private
+// members which have previously been set, and one argument:
+//
+// Private data members:
+//   outcome:  An enumeration describing how the death test
+//             concluded: DIED, LIVED, THREW, or RETURNED.  The death test
+//             fails in the latter three cases.
+//   status:   The exit status of the child process. On *nix, it is in the
+//             in the format specified by wait(2). On Windows, this is the
+//             value supplied to the ExitProcess() API or a numeric code
+//             of the exception that terminated the program.
+//   regex:    A regular expression object to be applied to
+//             the test's captured standard error output; the death test
+//             fails if it does not match.
+//
+// Argument:
+//   status_ok: true if exit_status is acceptable in the context of
+//              this particular death test, which fails if it is false
+//
+// Returns true iff all of the above conditions are met.  Otherwise, the
+// first failing condition, in the order given above, is the one that is
+// reported. Also sets the last death test message string.
+bool DeathTestImpl::Passed(bool status_ok) {
+  if (!spawned())
+    return false;
+
+  const std::string error_message = GetCapturedStderr();
+
+  bool success = false;
+  Message buffer;
+
+  buffer << "Death test: " << statement() << "\n";
+  switch (outcome()) {
+    case LIVED:
+      buffer << "    Result: failed to die.\n"
+             << " Error msg:\n" << FormatDeathTestOutput(error_message);
+      break;
+    case THREW:
+      buffer << "    Result: threw an exception.\n"
+             << " Error msg:\n" << FormatDeathTestOutput(error_message);
+      break;
+    case RETURNED:
+      buffer << "    Result: illegal return in test statement.\n"
+             << " Error msg:\n" << FormatDeathTestOutput(error_message);
+      break;
+    case DIED:
+      if (status_ok) {
+        const bool matched = RE::PartialMatch(error_message.c_str(), *regex());
+        if (matched) {
+          success = true;
+        } else {
+          buffer << "    Result: died but not with expected error.\n"
+                 << "  Expected: " << regex()->pattern() << "\n"
+                 << "Actual msg:\n" << FormatDeathTestOutput(error_message);
+        }
+      } else {
+        buffer << "    Result: died but not with expected exit code:\n"
+               << "            " << ExitSummary(status()) << "\n"
+               << "Actual msg:\n" << FormatDeathTestOutput(error_message);
+      }
+      break;
+    case IN_PROGRESS:
+    default:
+      GTEST_LOG_(FATAL)
+          << "DeathTest::Passed somehow called before conclusion of test";
+  }
+
+  DeathTest::set_last_death_test_message(buffer.GetString());
+  return success;
+}
+
+# if GTEST_OS_WINDOWS
+// WindowsDeathTest implements death tests on Windows. Due to the
+// specifics of starting new processes on Windows, death tests there are
+// always threadsafe, and Google Test considers the
+// --gtest_death_test_style=fast setting to be equivalent to
+// --gtest_death_test_style=threadsafe there.
+//
+// A few implementation notes:  Like the Linux version, the Windows
+// implementation uses pipes for child-to-parent communication. But due to
+// the specifics of pipes on Windows, some extra steps are required:
+//
+// 1. The parent creates a communication pipe and stores handles to both
+//    ends of it.
+// 2. The parent starts the child and provides it with the information
+//    necessary to acquire the handle to the write end of the pipe.
+// 3. The child acquires the write end of the pipe and signals the parent
+//    using a Windows event.
+// 4. Now the parent can release the write end of the pipe on its side. If
+//    this is done before step 3, the object's reference count goes down to
+//    0 and it is destroyed, preventing the child from acquiring it. The
+//    parent now has to release it, or read operations on the read end of
+//    the pipe will not return when the child terminates.
+// 5. The parent reads child's output through the pipe (outcome code and
+//    any possible error messages) from the pipe, and its stderr and then
+//    determines whether to fail the test.
+//
+// Note: to distinguish Win32 API calls from the local method and function
+// calls, the former are explicitly resolved in the global namespace.
+//
+class WindowsDeathTest : public DeathTestImpl {
+ public:
+  WindowsDeathTest(const char* a_statement,
+                   const RE* a_regex,
+                   const char* file,
+                   int line)
+      : DeathTestImpl(a_statement, a_regex), file_(file), line_(line) {}
+
+  // All of these virtual functions are inherited from DeathTest.
+  virtual int Wait();
+  virtual TestRole AssumeRole();
+
+ private:
+  // The name of the file in which the death test is located.
+  const char* const file_;
+  // The line number on which the death test is located.
+  const int line_;
+  // Handle to the write end of the pipe to the child process.
+  AutoHandle write_handle_;
+  // Child process handle.
+  AutoHandle child_handle_;
+  // Event the child process uses to signal the parent that it has
+  // acquired the handle to the write end of the pipe. After seeing this
+  // event the parent can release its own handles to make sure its
+  // ReadFile() calls return when the child terminates.
+  AutoHandle event_handle_;
+};
+
+// Waits for the child in a death test to exit, returning its exit
+// status, or 0 if no child process exists.  As a side effect, sets the
+// outcome data member.
+int WindowsDeathTest::Wait() {
+  if (!spawned())
+    return 0;
+
+  // Wait until the child either signals that it has acquired the write end
+  // of the pipe or it dies.
+  const HANDLE wait_handles[2] = { child_handle_.Get(), event_handle_.Get() };
+  switch (::WaitForMultipleObjects(2,
+                                   wait_handles,
+                                   FALSE,  // Waits for any of the handles.
+                                   INFINITE)) {
+    case WAIT_OBJECT_0:
+    case WAIT_OBJECT_0 + 1:
+      break;
+    default:
+      GTEST_DEATH_TEST_CHECK_(false);  // Should not get here.
+  }
+
+  // The child has acquired the write end of the pipe or exited.
+  // We release the handle on our side and continue.
+  write_handle_.Reset();
+  event_handle_.Reset();
+
+  ReadAndInterpretStatusByte();
+
+  // Waits for the child process to exit if it haven't already. This
+  // returns immediately if the child has already exited, regardless of
+  // whether previous calls to WaitForMultipleObjects synchronized on this
+  // handle or not.
+  GTEST_DEATH_TEST_CHECK_(
+      WAIT_OBJECT_0 == ::WaitForSingleObject(child_handle_.Get(),
+                                             INFINITE));
+  DWORD status_code;
+  GTEST_DEATH_TEST_CHECK_(
+      ::GetExitCodeProcess(child_handle_.Get(), &status_code) != FALSE);
+  child_handle_.Reset();
+  set_status(static_cast<int>(status_code));
+  return status();
+}
+
+// The AssumeRole process for a Windows death test.  It creates a child
+// process with the same executable as the current process to run the
+// death test.  The child process is given the --gtest_filter and
+// --gtest_internal_run_death_test flags such that it knows to run the
+// current death test only.
+DeathTest::TestRole WindowsDeathTest::AssumeRole() {
+  const UnitTestImpl* const impl = GetUnitTestImpl();
+  const InternalRunDeathTestFlag* const flag =
+      impl->internal_run_death_test_flag();
+  const TestInfo* const info = impl->current_test_info();
+  const int death_test_index = info->result()->death_test_count();
+
+  if (flag != NULL) {
+    // ParseInternalRunDeathTestFlag() has performed all the necessary
+    // processing.
+    set_write_fd(flag->write_fd());
+    return EXECUTE_TEST;
+  }
+
+  // WindowsDeathTest uses an anonymous pipe to communicate results of
+  // a death test.
+  SECURITY_ATTRIBUTES handles_are_inheritable = {
+    sizeof(SECURITY_ATTRIBUTES), NULL, TRUE };
+  HANDLE read_handle, write_handle;
+  GTEST_DEATH_TEST_CHECK_(
+      ::CreatePipe(&read_handle, &write_handle, &handles_are_inheritable,
+                   0)  // Default buffer size.
+      != FALSE);
+  set_read_fd(::_open_osfhandle(reinterpret_cast<intptr_t>(read_handle),
+                                O_RDONLY));
+  write_handle_.Reset(write_handle);
+  event_handle_.Reset(::CreateEvent(
+      &handles_are_inheritable,
+      TRUE,    // The event will automatically reset to non-signaled state.
+      FALSE,   // The initial state is non-signalled.
+      NULL));  // The even is unnamed.
+  GTEST_DEATH_TEST_CHECK_(event_handle_.Get() != NULL);
+  const std::string filter_flag =
+      std::string("--") + GTEST_FLAG_PREFIX_ + kFilterFlag + "=" +
+      info->test_case_name() + "." + info->name();
+  const std::string internal_flag =
+      std::string("--") + GTEST_FLAG_PREFIX_ + kInternalRunDeathTestFlag +
+      "=" + file_ + "|" + StreamableToString(line_) + "|" +
+      StreamableToString(death_test_index) + "|" +
+      StreamableToString(static_cast<unsigned int>(::GetCurrentProcessId())) +
+      // size_t has the same width as pointers on both 32-bit and 64-bit
+      // Windows platforms.
+      // See http://msdn.microsoft.com/en-us/library/tcxf1dw6.aspx.
+      "|" + StreamableToString(reinterpret_cast<size_t>(write_handle)) +
+      "|" + StreamableToString(reinterpret_cast<size_t>(event_handle_.Get()));
+
+  char executable_path[_MAX_PATH + 1];  // NOLINT
+  GTEST_DEATH_TEST_CHECK_(
+      _MAX_PATH + 1 != ::GetModuleFileNameA(NULL,
+                                            executable_path,
+                                            _MAX_PATH));
+
+  std::string command_line =
+      std::string(::GetCommandLineA()) + " " + filter_flag + " \"" +
+      internal_flag + "\"";
+
+  DeathTest::set_last_death_test_message("");
+
+  CaptureStderr();
+  // Flush the log buffers since the log streams are shared with the child.
+  FlushInfoLog();
+
+  // The child process will share the standard handles with the parent.
+  STARTUPINFOA startup_info;
+  memset(&startup_info, 0, sizeof(STARTUPINFO));
+  startup_info.dwFlags = STARTF_USESTDHANDLES;
+  startup_info.hStdInput = ::GetStdHandle(STD_INPUT_HANDLE);
+  startup_info.hStdOutput = ::GetStdHandle(STD_OUTPUT_HANDLE);
+  startup_info.hStdError = ::GetStdHandle(STD_ERROR_HANDLE);
+
+  PROCESS_INFORMATION process_info;
+  GTEST_DEATH_TEST_CHECK_(::CreateProcessA(
+      executable_path,
+      const_cast<char*>(command_line.c_str()),
+      NULL,   // Retuned process handle is not inheritable.
+      NULL,   // Retuned thread handle is not inheritable.
+      TRUE,   // Child inherits all inheritable handles (for write_handle_).
+      0x0,    // Default creation flags.
+      NULL,   // Inherit the parent's environment.
+      UnitTest::GetInstance()->original_working_dir(),
+      &startup_info,
+      &process_info) != FALSE);
+  child_handle_.Reset(process_info.hProcess);
+  ::CloseHandle(process_info.hThread);
+  set_spawned(true);
+  return OVERSEE_TEST;
+}
+# else  // We are not on Windows.
+
+// ForkingDeathTest provides implementations for most of the abstract
+// methods of the DeathTest interface.  Only the AssumeRole method is
+// left undefined.
+class ForkingDeathTest : public DeathTestImpl {
+ public:
+  ForkingDeathTest(const char* statement, const RE* regex);
+
+  // All of these virtual functions are inherited from DeathTest.
+  virtual int Wait();
+
+ protected:
+  void set_child_pid(pid_t child_pid) { child_pid_ = child_pid; }
+
+ private:
+  // PID of child process during death test; 0 in the child process itself.
+  pid_t child_pid_;
+};
+
+// Constructs a ForkingDeathTest.
+ForkingDeathTest::ForkingDeathTest(const char* a_statement, const RE* a_regex)
+    : DeathTestImpl(a_statement, a_regex),
+      child_pid_(-1) {}
+
+// Waits for the child in a death test to exit, returning its exit
+// status, or 0 if no child process exists.  As a side effect, sets the
+// outcome data member.
+int ForkingDeathTest::Wait() {
+  if (!spawned())
+    return 0;
+
+  ReadAndInterpretStatusByte();
+
+  int status_value;
+  GTEST_DEATH_TEST_CHECK_SYSCALL_(waitpid(child_pid_, &status_value, 0));
+  set_status(status_value);
+  return status_value;
+}
+
+// A concrete death test class that forks, then immediately runs the test
+// in the child process.
+class NoExecDeathTest : public ForkingDeathTest {
+ public:
+  NoExecDeathTest(const char* a_statement, const RE* a_regex) :
+      ForkingDeathTest(a_statement, a_regex) { }
+  virtual TestRole AssumeRole();
+};
+
+// The AssumeRole process for a fork-and-run death test.  It implements a
+// straightforward fork, with a simple pipe to transmit the status byte.
+DeathTest::TestRole NoExecDeathTest::AssumeRole() {
+  const size_t thread_count = GetThreadCount();
+  if (thread_count != 1) {
+    GTEST_LOG_(WARNING) << DeathTestThreadWarning(thread_count);
+  }
+
+  int pipe_fd[2];
+  GTEST_DEATH_TEST_CHECK_(pipe(pipe_fd) != -1);
+
+  DeathTest::set_last_death_test_message("");
+  CaptureStderr();
+  // When we fork the process below, the log file buffers are copied, but the
+  // file descriptors are shared.  We flush all log files here so that closing
+  // the file descriptors in the child process doesn't throw off the
+  // synchronization between descriptors and buffers in the parent process.
+  // This is as close to the fork as possible to avoid a race condition in case
+  // there are multiple threads running before the death test, and another
+  // thread writes to the log file.
+  FlushInfoLog();
+
+  const pid_t child_pid = fork();
+  GTEST_DEATH_TEST_CHECK_(child_pid != -1);
+  set_child_pid(child_pid);
+  if (child_pid == 0) {
+    GTEST_DEATH_TEST_CHECK_SYSCALL_(close(pipe_fd[0]));
+    set_write_fd(pipe_fd[1]);
+    // Redirects all logging to stderr in the child process to prevent
+    // concurrent writes to the log files.  We capture stderr in the parent
+    // process and append the child process' output to a log.
+    LogToStderr();
+    // Event forwarding to the listeners of event listener API mush be shut
+    // down in death test subprocesses.
+    GetUnitTestImpl()->listeners()->SuppressEventForwarding();
+    g_in_fast_death_test_child = true;
+    return EXECUTE_TEST;
+  } else {
+    GTEST_DEATH_TEST_CHECK_SYSCALL_(close(pipe_fd[1]));
+    set_read_fd(pipe_fd[0]);
+    set_spawned(true);
+    return OVERSEE_TEST;
+  }
+}
+
+// A concrete death test class that forks and re-executes the main
+// program from the beginning, with command-line flags set that cause
+// only this specific death test to be run.
+class ExecDeathTest : public ForkingDeathTest {
+ public:
+  ExecDeathTest(const char* a_statement, const RE* a_regex,
+                const char* file, int line) :
+      ForkingDeathTest(a_statement, a_regex), file_(file), line_(line) { }
+  virtual TestRole AssumeRole();
+ private:
+  static ::std::vector<testing::internal::string>
+  GetArgvsForDeathTestChildProcess() {
+    ::std::vector<testing::internal::string> args = GetInjectableArgvs();
+    return args;
+  }
+  // The name of the file in which the death test is located.
+  const char* const file_;
+  // The line number on which the death test is located.
+  const int line_;
+};
+
+// Utility class for accumulating command-line arguments.
+class Arguments {
+ public:
+  Arguments() {
+    args_.push_back(NULL);
+  }
+
+  ~Arguments() {
+    for (std::vector<char*>::iterator i = args_.begin(); i != args_.end();
+         ++i) {
+      free(*i);
+    }
+  }
+  void AddArgument(const char* argument) {
+    args_.insert(args_.end() - 1, posix::StrDup(argument));
+  }
+
+  template <typename Str>
+  void AddArguments(const ::std::vector<Str>& arguments) {
+    for (typename ::std::vector<Str>::const_iterator i = arguments.begin();
+         i != arguments.end();
+         ++i) {
+      args_.insert(args_.end() - 1, posix::StrDup(i->c_str()));
+    }
+  }
+  char* const* Argv() {
+    return &args_[0];
+  }
+
+ private:
+  std::vector<char*> args_;
+};
+
+// A struct that encompasses the arguments to the child process of a
+// threadsafe-style death test process.
+struct ExecDeathTestArgs {
+  char* const* argv;  // Command-line arguments for the child's call to exec
+  int close_fd;       // File descriptor to close; the read end of a pipe
+};
+
+#  if GTEST_OS_MAC
+inline char** GetEnviron() {
+  // When Google Test is built as a framework on MacOS X, the environ variable
+  // is unavailable. Apple's documentation (man environ) recommends using
+  // _NSGetEnviron() instead.
+  return *_NSGetEnviron();
+}
+#  else
+// Some POSIX platforms expect you to declare environ. extern "C" makes
+// it reside in the global namespace.
+extern "C" char** environ;
+inline char** GetEnviron() { return environ; }
+#  endif  // GTEST_OS_MAC
+
+#  if !GTEST_OS_QNX
+// The main function for a threadsafe-style death test child process.
+// This function is called in a clone()-ed process and thus must avoid
+// any potentially unsafe operations like malloc or libc functions.
+static int ExecDeathTestChildMain(void* child_arg) {
+  ExecDeathTestArgs* const args = static_cast<ExecDeathTestArgs*>(child_arg);
+  GTEST_DEATH_TEST_CHECK_SYSCALL_(close(args->close_fd));
+
+  // We need to execute the test program in the same environment where
+  // it was originally invoked.  Therefore we change to the original
+  // working directory first.
+  const char* const original_dir =
+      UnitTest::GetInstance()->original_working_dir();
+  // We can safely call chdir() as it's a direct system call.
+  if (chdir(original_dir) != 0) {
+    DeathTestAbort(std::string("chdir(\"") + original_dir + "\") failed: " +
+                   GetLastErrnoDescription());
+    return EXIT_FAILURE;
+  }
+
+  // We can safely call execve() as it's a direct system call.  We
+  // cannot use execvp() as it's a libc function and thus potentially
+  // unsafe.  Since execve() doesn't search the PATH, the user must
+  // invoke the test program via a valid path that contains at least
+  // one path separator.
+  execve(args->argv[0], args->argv, GetEnviron());
+  DeathTestAbort(std::string("execve(") + args->argv[0] + ", ...) in " +
+                 original_dir + " failed: " +
+                 GetLastErrnoDescription());
+  return EXIT_FAILURE;
+}
+#  endif  // !GTEST_OS_QNX
+
+// Two utility routines that together determine the direction the stack
+// grows.
+// This could be accomplished more elegantly by a single recursive
+// function, but we want to guard against the unlikely possibility of
+// a smart compiler optimizing the recursion away.
+//
+// GTEST_NO_INLINE_ is required to prevent GCC 4.6 from inlining
+// StackLowerThanAddress into StackGrowsDown, which then doesn't give
+// correct answer.
+void StackLowerThanAddress(const void* ptr, bool* result) GTEST_NO_INLINE_;
+void StackLowerThanAddress(const void* ptr, bool* result) {
+  int dummy;
+  *result = (&dummy < ptr);
+}
+
+bool StackGrowsDown() {
+  int dummy;
+  bool result;
+  StackLowerThanAddress(&dummy, &result);
+  return result;
+}
+
+// Spawns a child process with the same executable as the current process in
+// a thread-safe manner and instructs it to run the death test.  The
+// implementation uses fork(2) + exec.  On systems where clone(2) is
+// available, it is used instead, being slightly more thread-safe.  On QNX,
+// fork supports only single-threaded environments, so this function uses
+// spawn(2) there instead.  The function dies with an error message if
+// anything goes wrong.
+static pid_t ExecDeathTestSpawnChild(char* const* argv, int close_fd) {
+  ExecDeathTestArgs args = { argv, close_fd };
+  pid_t child_pid = -1;
+
+#  if GTEST_OS_QNX
+  // Obtains the current directory and sets it to be closed in the child
+  // process.
+  const int cwd_fd = open(".", O_RDONLY);
+  GTEST_DEATH_TEST_CHECK_(cwd_fd != -1);
+  GTEST_DEATH_TEST_CHECK_SYSCALL_(fcntl(cwd_fd, F_SETFD, FD_CLOEXEC));
+  // We need to execute the test program in the same environment where
+  // it was originally invoked.  Therefore we change to the original
+  // working directory first.
+  const char* const original_dir =
+      UnitTest::GetInstance()->original_working_dir();
+  // We can safely call chdir() as it's a direct system call.
+  if (chdir(original_dir) != 0) {
+    DeathTestAbort(std::string("chdir(\"") + original_dir + "\") failed: " +
+                   GetLastErrnoDescription());
+    return EXIT_FAILURE;
+  }
+
+  int fd_flags;
+  // Set close_fd to be closed after spawn.
+  GTEST_DEATH_TEST_CHECK_SYSCALL_(fd_flags = fcntl(close_fd, F_GETFD));
+  GTEST_DEATH_TEST_CHECK_SYSCALL_(fcntl(close_fd, F_SETFD,
+                                        fd_flags | FD_CLOEXEC));
+  struct inheritance inherit = {0};
+  // spawn is a system call.
+  child_pid = spawn(args.argv[0], 0, NULL, &inherit, args.argv, GetEnviron());
+  // Restores the current working directory.
+  GTEST_DEATH_TEST_CHECK_(fchdir(cwd_fd) != -1);
+  GTEST_DEATH_TEST_CHECK_SYSCALL_(close(cwd_fd));
+
+#  else   // GTEST_OS_QNX
+#   if GTEST_OS_LINUX
+  // When a SIGPROF signal is received while fork() or clone() are executing,
+  // the process may hang. To avoid this, we ignore SIGPROF here and re-enable
+  // it after the call to fork()/clone() is complete.
+  struct sigaction saved_sigprof_action;
+  struct sigaction ignore_sigprof_action;
+  memset(&ignore_sigprof_action, 0, sizeof(ignore_sigprof_action));
+  sigemptyset(&ignore_sigprof_action.sa_mask);
+  ignore_sigprof_action.sa_handler = SIG_IGN;
+  GTEST_DEATH_TEST_CHECK_SYSCALL_(sigaction(
+      SIGPROF, &ignore_sigprof_action, &saved_sigprof_action));
+#   endif  // GTEST_OS_LINUX
+
+#   if GTEST_HAS_CLONE
+  const bool use_fork = GTEST_FLAG(death_test_use_fork);
+
+  if (!use_fork) {
+    static const bool stack_grows_down = StackGrowsDown();
+    const size_t stack_size = getpagesize();
+    // MMAP_ANONYMOUS is not defined on Mac, so we use MAP_ANON instead.
+    void* const stack = mmap(NULL, stack_size, PROT_READ | PROT_WRITE,
+                             MAP_ANON | MAP_PRIVATE, -1, 0);
+    GTEST_DEATH_TEST_CHECK_(stack != MAP_FAILED);
+
+    // Maximum stack alignment in bytes:  For a downward-growing stack, this
+    // amount is subtracted from size of the stack space to get an address
+    // that is within the stack space and is aligned on all systems we care
+    // about.  As far as I know there is no ABI with stack alignment greater
+    // than 64.  We assume stack and stack_size already have alignment of
+    // kMaxStackAlignment.
+    const size_t kMaxStackAlignment = 64;
+    void* const stack_top =
+        static_cast<char*>(stack) +
+            (stack_grows_down ? stack_size - kMaxStackAlignment : 0);
+    GTEST_DEATH_TEST_CHECK_(stack_size > kMaxStackAlignment &&
+        reinterpret_cast<intptr_t>(stack_top) % kMaxStackAlignment == 0);
+
+    child_pid = clone(&ExecDeathTestChildMain, stack_top, SIGCHLD, &args);
+
+    GTEST_DEATH_TEST_CHECK_(munmap(stack, stack_size) != -1);
+  }
+#   else
+  const bool use_fork = true;
+#   endif  // GTEST_HAS_CLONE
+
+  if (use_fork && (child_pid = fork()) == 0) {
+      ExecDeathTestChildMain(&args);
+      _exit(0);
+  }
+#  endif  // GTEST_OS_QNX
+#  if GTEST_OS_LINUX
+  GTEST_DEATH_TEST_CHECK_SYSCALL_(
+      sigaction(SIGPROF, &saved_sigprof_action, NULL));
+#  endif  // GTEST_OS_LINUX
+
+  GTEST_DEATH_TEST_CHECK_(child_pid != -1);
+  return child_pid;
+}
+
+// The AssumeRole process for a fork-and-exec death test.  It re-executes the
+// main program from the beginning, setting the --gtest_filter
+// and --gtest_internal_run_death_test flags to cause only the current
+// death test to be re-run.
+DeathTest::TestRole ExecDeathTest::AssumeRole() {
+  const UnitTestImpl* const impl = GetUnitTestImpl();
+  const InternalRunDeathTestFlag* const flag =
+      impl->internal_run_death_test_flag();
+  const TestInfo* const info = impl->current_test_info();
+  const int death_test_index = info->result()->death_test_count();
+
+  if (flag != NULL) {
+    set_write_fd(flag->write_fd());
+    return EXECUTE_TEST;
+  }
+
+  int pipe_fd[2];
+  GTEST_DEATH_TEST_CHECK_(pipe(pipe_fd) != -1);
+  // Clear the close-on-exec flag on the write end of the pipe, lest
+  // it be closed when the child process does an exec:
+  GTEST_DEATH_TEST_CHECK_(fcntl(pipe_fd[1], F_SETFD, 0) != -1);
+
+  const std::string filter_flag =
+      std::string("--") + GTEST_FLAG_PREFIX_ + kFilterFlag + "="
+      + info->test_case_name() + "." + info->name();
+  const std::string internal_flag =
+      std::string("--") + GTEST_FLAG_PREFIX_ + kInternalRunDeathTestFlag + "="
+      + file_ + "|" + StreamableToString(line_) + "|"
+      + StreamableToString(death_test_index) + "|"
+      + StreamableToString(pipe_fd[1]);
+  Arguments args;
+  args.AddArguments(GetArgvsForDeathTestChildProcess());
+  args.AddArgument(filter_flag.c_str());
+  args.AddArgument(internal_flag.c_str());
+
+  DeathTest::set_last_death_test_message("");
+
+  CaptureStderr();
+  // See the comment in NoExecDeathTest::AssumeRole for why the next line
+  // is necessary.
+  FlushInfoLog();
+
+  const pid_t child_pid = ExecDeathTestSpawnChild(args.Argv(), pipe_fd[0]);
+  GTEST_DEATH_TEST_CHECK_SYSCALL_(close(pipe_fd[1]));
+  set_child_pid(child_pid);
+  set_read_fd(pipe_fd[0]);
+  set_spawned(true);
+  return OVERSEE_TEST;
+}
+
+# endif  // !GTEST_OS_WINDOWS
+
+// Creates a concrete DeathTest-derived class that depends on the
+// --gtest_death_test_style flag, and sets the pointer pointed to
+// by the "test" argument to its address.  If the test should be
+// skipped, sets that pointer to NULL.  Returns true, unless the
+// flag is set to an invalid value.
+bool DefaultDeathTestFactory::Create(const char* statement, const RE* regex,
+                                     const char* file, int line,
+                                     DeathTest** test) {
+  UnitTestImpl* const impl = GetUnitTestImpl();
+  const InternalRunDeathTestFlag* const flag =
+      impl->internal_run_death_test_flag();
+  const int death_test_index = impl->current_test_info()
+      ->increment_death_test_count();
+
+  if (flag != NULL) {
+    if (death_test_index > flag->index()) {
+      DeathTest::set_last_death_test_message(
+          "Death test count (" + StreamableToString(death_test_index)
+          + ") somehow exceeded expected maximum ("
+          + StreamableToString(flag->index()) + ")");
+      return false;
+    }
+
+    if (!(flag->file() == file && flag->line() == line &&
+          flag->index() == death_test_index)) {
+      *test = NULL;
+      return true;
+    }
+  }
+
+# if GTEST_OS_WINDOWS
+
+  if (GTEST_FLAG(death_test_style) == "threadsafe" ||
+      GTEST_FLAG(death_test_style) == "fast") {
+    *test = new WindowsDeathTest(statement, regex, file, line);
+  }
+
+# else
+
+  if (GTEST_FLAG(death_test_style) == "threadsafe") {
+    *test = new ExecDeathTest(statement, regex, file, line);
+  } else if (GTEST_FLAG(death_test_style) == "fast") {
+    *test = new NoExecDeathTest(statement, regex);
+  }
+
+# endif  // GTEST_OS_WINDOWS
+
+  else {  // NOLINT - this is more readable than unbalanced brackets inside #if.
+    DeathTest::set_last_death_test_message(
+        "Unknown death test style \"" + GTEST_FLAG(death_test_style)
+        + "\" encountered");
+    return false;
+  }
+
+  return true;
+}
+
+// Splits a given string on a given delimiter, populating a given
+// vector with the fields.  GTEST_HAS_DEATH_TEST implies that we have
+// ::std::string, so we can use it here.
+static void SplitString(const ::std::string& str, char delimiter,
+                        ::std::vector< ::std::string>* dest) {
+  ::std::vector< ::std::string> parsed;
+  ::std::string::size_type pos = 0;
+  while (::testing::internal::AlwaysTrue()) {
+    const ::std::string::size_type colon = str.find(delimiter, pos);
+    if (colon == ::std::string::npos) {
+      parsed.push_back(str.substr(pos));
+      break;
+    } else {
+      parsed.push_back(str.substr(pos, colon - pos));
+      pos = colon + 1;
+    }
+  }
+  dest->swap(parsed);
+}
+
+# if GTEST_OS_WINDOWS
+// Recreates the pipe and event handles from the provided parameters,
+// signals the event, and returns a file descriptor wrapped around the pipe
+// handle. This function is called in the child process only.
+int GetStatusFileDescriptor(unsigned int parent_process_id,
+                            size_t write_handle_as_size_t,
+                            size_t event_handle_as_size_t) {
+  AutoHandle parent_process_handle(::OpenProcess(PROCESS_DUP_HANDLE,
+                                                   FALSE,  // Non-inheritable.
+                                                   parent_process_id));
+  if (parent_process_handle.Get() == INVALID_HANDLE_VALUE) {
+    DeathTestAbort("Unable to open parent process " +
+                   StreamableToString(parent_process_id));
+  }
+
+  // TODO(vladl at google.com): Replace the following check with a
+  // compile-time assertion when available.
+  GTEST_CHECK_(sizeof(HANDLE) <= sizeof(size_t));
+
+  const HANDLE write_handle =
+      reinterpret_cast<HANDLE>(write_handle_as_size_t);
+  HANDLE dup_write_handle;
+
+  // The newly initialized handle is accessible only in in the parent
+  // process. To obtain one accessible within the child, we need to use
+  // DuplicateHandle.
+  if (!::DuplicateHandle(parent_process_handle.Get(), write_handle,
+                         ::GetCurrentProcess(), &dup_write_handle,
+                         0x0,    // Requested privileges ignored since
+                                 // DUPLICATE_SAME_ACCESS is used.
+                         FALSE,  // Request non-inheritable handler.
+                         DUPLICATE_SAME_ACCESS)) {
+    DeathTestAbort("Unable to duplicate the pipe handle " +
+                   StreamableToString(write_handle_as_size_t) +
+                   " from the parent process " +
+                   StreamableToString(parent_process_id));
+  }
+
+  const HANDLE event_handle = reinterpret_cast<HANDLE>(event_handle_as_size_t);
+  HANDLE dup_event_handle;
+
+  if (!::DuplicateHandle(parent_process_handle.Get(), event_handle,
+                         ::GetCurrentProcess(), &dup_event_handle,
+                         0x0,
+                         FALSE,
+                         DUPLICATE_SAME_ACCESS)) {
+    DeathTestAbort("Unable to duplicate the event handle " +
+                   StreamableToString(event_handle_as_size_t) +
+                   " from the parent process " +
+                   StreamableToString(parent_process_id));
+  }
+
+  const int write_fd =
+      ::_open_osfhandle(reinterpret_cast<intptr_t>(dup_write_handle), O_APPEND);
+  if (write_fd == -1) {
+    DeathTestAbort("Unable to convert pipe handle " +
+                   StreamableToString(write_handle_as_size_t) +
+                   " to a file descriptor");
+  }
+
+  // Signals the parent that the write end of the pipe has been acquired
+  // so the parent can release its own write end.
+  ::SetEvent(dup_event_handle);
+
+  return write_fd;
+}
+# endif  // GTEST_OS_WINDOWS
+
+// Returns a newly created InternalRunDeathTestFlag object with fields
+// initialized from the GTEST_FLAG(internal_run_death_test) flag if
+// the flag is specified; otherwise returns NULL.
+InternalRunDeathTestFlag* ParseInternalRunDeathTestFlag() {
+  if (GTEST_FLAG(internal_run_death_test) == "") return NULL;
+
+  // GTEST_HAS_DEATH_TEST implies that we have ::std::string, so we
+  // can use it here.
+  int line = -1;
+  int index = -1;
+  ::std::vector< ::std::string> fields;
+  SplitString(GTEST_FLAG(internal_run_death_test).c_str(), '|', &fields);
+  int write_fd = -1;
+
+# if GTEST_OS_WINDOWS
+
+  unsigned int parent_process_id = 0;
+  size_t write_handle_as_size_t = 0;
+  size_t event_handle_as_size_t = 0;
+
+  if (fields.size() != 6
+      || !ParseNaturalNumber(fields[1], &line)
+      || !ParseNaturalNumber(fields[2], &index)
+      || !ParseNaturalNumber(fields[3], &parent_process_id)
+      || !ParseNaturalNumber(fields[4], &write_handle_as_size_t)
+      || !ParseNaturalNumber(fields[5], &event_handle_as_size_t)) {
+    DeathTestAbort("Bad --gtest_internal_run_death_test flag: " +
+                   GTEST_FLAG(internal_run_death_test));
+  }
+  write_fd = GetStatusFileDescriptor(parent_process_id,
+                                     write_handle_as_size_t,
+                                     event_handle_as_size_t);
+# else
+
+  if (fields.size() != 4
+      || !ParseNaturalNumber(fields[1], &line)
+      || !ParseNaturalNumber(fields[2], &index)
+      || !ParseNaturalNumber(fields[3], &write_fd)) {
+    DeathTestAbort("Bad --gtest_internal_run_death_test flag: "
+        + GTEST_FLAG(internal_run_death_test));
+  }
+
+# endif  // GTEST_OS_WINDOWS
+
+  return new InternalRunDeathTestFlag(fields[0], line, index, write_fd);
+}
+
+}  // namespace internal
+
+#endif  // GTEST_HAS_DEATH_TEST
+
+}  // namespace testing
diff --git a/test/gtest/src/gtest-filepath.cc b/test/gtest/src/gtest-filepath.cc
new file mode 100644
index 0000000..6be58b6
--- /dev/null
+++ b/test/gtest/src/gtest-filepath.cc
@@ -0,0 +1,382 @@
+// Copyright 2008, Google Inc.
+// All rights reserved.
+//
+// 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.
+//
+// Authors: keith.ray at gmail.com (Keith Ray)
+
+#include "gtest/gtest-message.h"
+#include "gtest/internal/gtest-filepath.h"
+#include "gtest/internal/gtest-port.h"
+
+#include <stdlib.h>
+
+#if GTEST_OS_WINDOWS_MOBILE
+# include <windows.h>
+#elif GTEST_OS_WINDOWS
+# include <direct.h>
+# include <io.h>
+#elif GTEST_OS_SYMBIAN
+// Symbian OpenC has PATH_MAX in sys/syslimits.h
+# include <sys/syslimits.h>
+#else
+# include <limits.h>
+# include <climits>  // Some Linux distributions define PATH_MAX here.
+#endif  // GTEST_OS_WINDOWS_MOBILE
+
+#if GTEST_OS_WINDOWS
+# define GTEST_PATH_MAX_ _MAX_PATH
+#elif defined(PATH_MAX)
+# define GTEST_PATH_MAX_ PATH_MAX
+#elif defined(_XOPEN_PATH_MAX)
+# define GTEST_PATH_MAX_ _XOPEN_PATH_MAX
+#else
+# define GTEST_PATH_MAX_ _POSIX_PATH_MAX
+#endif  // GTEST_OS_WINDOWS
+
+#include "gtest/internal/gtest-string.h"
+
+namespace testing {
+namespace internal {
+
+#if GTEST_OS_WINDOWS
+// On Windows, '\\' is the standard path separator, but many tools and the
+// Windows API also accept '/' as an alternate path separator. Unless otherwise
+// noted, a file path can contain either kind of path separators, or a mixture
+// of them.
+const char kPathSeparator = '\\';
+const char kAlternatePathSeparator = '/';
+const char kPathSeparatorString[] = "\\";
+const char kAlternatePathSeparatorString[] = "/";
+# if GTEST_OS_WINDOWS_MOBILE
+// Windows CE doesn't have a current directory. You should not use
+// the current directory in tests on Windows CE, but this at least
+// provides a reasonable fallback.
+const char kCurrentDirectoryString[] = "\\";
+// Windows CE doesn't define INVALID_FILE_ATTRIBUTES
+const DWORD kInvalidFileAttributes = 0xffffffff;
+# else
+const char kCurrentDirectoryString[] = ".\\";
+# endif  // GTEST_OS_WINDOWS_MOBILE
+#else
+const char kPathSeparator = '/';
+const char kPathSeparatorString[] = "/";
+const char kCurrentDirectoryString[] = "./";
+#endif  // GTEST_OS_WINDOWS
+
+// Returns whether the given character is a valid path separator.
+static bool IsPathSeparator(char c) {
+#if GTEST_HAS_ALT_PATH_SEP_
+  return (c == kPathSeparator) || (c == kAlternatePathSeparator);
+#else
+  return c == kPathSeparator;
+#endif
+}
+
+// Returns the current working directory, or "" if unsuccessful.
+FilePath FilePath::GetCurrentDir() {
+#if GTEST_OS_WINDOWS_MOBILE
+  // Windows CE doesn't have a current directory, so we just return
+  // something reasonable.
+  return FilePath(kCurrentDirectoryString);
+#elif GTEST_OS_WINDOWS
+  char cwd[GTEST_PATH_MAX_ + 1] = { '\0' };
+  return FilePath(_getcwd(cwd, sizeof(cwd)) == NULL ? "" : cwd);
+#else
+  char cwd[GTEST_PATH_MAX_ + 1] = { '\0' };
+  return FilePath(getcwd(cwd, sizeof(cwd)) == NULL ? "" : cwd);
+#endif  // GTEST_OS_WINDOWS_MOBILE
+}
+
+// Returns a copy of the FilePath with the case-insensitive extension removed.
+// Example: FilePath("dir/file.exe").RemoveExtension("EXE") returns
+// FilePath("dir/file"). If a case-insensitive extension is not
+// found, returns a copy of the original FilePath.
+FilePath FilePath::RemoveExtension(const char* extension) const {
+  const std::string dot_extension = std::string(".") + extension;
+  if (String::EndsWithCaseInsensitive(pathname_, dot_extension)) {
+    return FilePath(pathname_.substr(
+        0, pathname_.length() - dot_extension.length()));
+  }
+  return *this;
+}
+
+// Returns a pointer to the last occurence of a valid path separator in
+// the FilePath. On Windows, for example, both '/' and '\' are valid path
+// separators. Returns NULL if no path separator was found.
+const char* FilePath::FindLastPathSeparator() const {
+  const char* const last_sep = strrchr(c_str(), kPathSeparator);
+#if GTEST_HAS_ALT_PATH_SEP_
+  const char* const last_alt_sep = strrchr(c_str(), kAlternatePathSeparator);
+  // Comparing two pointers of which only one is NULL is undefined.
+  if (last_alt_sep != NULL &&
+      (last_sep == NULL || last_alt_sep > last_sep)) {
+    return last_alt_sep;
+  }
+#endif
+  return last_sep;
+}
+
+// Returns a copy of the FilePath with the directory part removed.
+// Example: FilePath("path/to/file").RemoveDirectoryName() returns
+// FilePath("file"). If there is no directory part ("just_a_file"), it returns
+// the FilePath unmodified. If there is no file part ("just_a_dir/") it
+// returns an empty FilePath ("").
+// On Windows platform, '\' is the path separator, otherwise it is '/'.
+FilePath FilePath::RemoveDirectoryName() const {
+  const char* const last_sep = FindLastPathSeparator();
+  return last_sep ? FilePath(last_sep + 1) : *this;
+}
+
+// RemoveFileName returns the directory path with the filename removed.
+// Example: FilePath("path/to/file").RemoveFileName() returns "path/to/".
+// If the FilePath is "a_file" or "/a_file", RemoveFileName returns
+// FilePath("./") or, on Windows, FilePath(".\\"). If the filepath does
+// not have a file, like "just/a/dir/", it returns the FilePath unmodified.
+// On Windows platform, '\' is the path separator, otherwise it is '/'.
+FilePath FilePath::RemoveFileName() const {
+  const char* const last_sep = FindLastPathSeparator();
+  std::string dir;
+  if (last_sep) {
+    dir = std::string(c_str(), last_sep + 1 - c_str());
+  } else {
+    dir = kCurrentDirectoryString;
+  }
+  return FilePath(dir);
+}
+
+// Helper functions for naming files in a directory for xml output.
+
+// Given directory = "dir", base_name = "test", number = 0,
+// extension = "xml", returns "dir/test.xml". If number is greater
+// than zero (e.g., 12), returns "dir/test_12.xml".
+// On Windows platform, uses \ as the separator rather than /.
+FilePath FilePath::MakeFileName(const FilePath& directory,
+                                const FilePath& base_name,
+                                int number,
+                                const char* extension) {
+  std::string file;
+  if (number == 0) {
+    file = base_name.string() + "." + extension;
+  } else {
+    file = base_name.string() + "_" + StreamableToString(number)
+        + "." + extension;
+  }
+  return ConcatPaths(directory, FilePath(file));
+}
+
+// Given directory = "dir", relative_path = "test.xml", returns "dir/test.xml".
+// On Windows, uses \ as the separator rather than /.
+FilePath FilePath::ConcatPaths(const FilePath& directory,
+                               const FilePath& relative_path) {
+  if (directory.IsEmpty())
+    return relative_path;
+  const FilePath dir(directory.RemoveTrailingPathSeparator());
+  return FilePath(dir.string() + kPathSeparator + relative_path.string());
+}
+
+// Returns true if pathname describes something findable in the file-system,
+// either a file, directory, or whatever.
+bool FilePath::FileOrDirectoryExists() const {
+#if GTEST_OS_WINDOWS_MOBILE
+  LPCWSTR unicode = String::AnsiToUtf16(pathname_.c_str());
+  const DWORD attributes = GetFileAttributes(unicode);
+  delete [] unicode;
+  return attributes != kInvalidFileAttributes;
+#else
+  posix::StatStruct file_stat;
+  return posix::Stat(pathname_.c_str(), &file_stat) == 0;
+#endif  // GTEST_OS_WINDOWS_MOBILE
+}
+
+// Returns true if pathname describes a directory in the file-system
+// that exists.
+bool FilePath::DirectoryExists() const {
+  bool result = false;
+#if GTEST_OS_WINDOWS
+  // Don't strip off trailing separator if path is a root directory on
+  // Windows (like "C:\\").
+  const FilePath& path(IsRootDirectory() ? *this :
+                                           RemoveTrailingPathSeparator());
+#else
+  const FilePath& path(*this);
+#endif
+
+#if GTEST_OS_WINDOWS_MOBILE
+  LPCWSTR unicode = String::AnsiToUtf16(path.c_str());
+  const DWORD attributes = GetFileAttributes(unicode);
+  delete [] unicode;
+  if ((attributes != kInvalidFileAttributes) &&
+      (attributes & FILE_ATTRIBUTE_DIRECTORY)) {
+    result = true;
+  }
+#else
+  posix::StatStruct file_stat;
+  result = posix::Stat(path.c_str(), &file_stat) == 0 &&
+      posix::IsDir(file_stat);
+#endif  // GTEST_OS_WINDOWS_MOBILE
+
+  return result;
+}
+
+// Returns true if pathname describes a root directory. (Windows has one
+// root directory per disk drive.)
+bool FilePath::IsRootDirectory() const {
+#if GTEST_OS_WINDOWS
+  // TODO(wan at google.com): on Windows a network share like
+  // \\server\share can be a root directory, although it cannot be the
+  // current directory.  Handle this properly.
+  return pathname_.length() == 3 && IsAbsolutePath();
+#else
+  return pathname_.length() == 1 && IsPathSeparator(pathname_.c_str()[0]);
+#endif
+}
+
+// Returns true if pathname describes an absolute path.
+bool FilePath::IsAbsolutePath() const {
+  const char* const name = pathname_.c_str();
+#if GTEST_OS_WINDOWS
+  return pathname_.length() >= 3 &&
+     ((name[0] >= 'a' && name[0] <= 'z') ||
+      (name[0] >= 'A' && name[0] <= 'Z')) &&
+     name[1] == ':' &&
+     IsPathSeparator(name[2]);
+#else
+  return IsPathSeparator(name[0]);
+#endif
+}
+
+// Returns a pathname for a file that does not currently exist. The pathname
+// will be directory/base_name.extension or
+// directory/base_name_<number>.extension if directory/base_name.extension
+// already exists. The number will be incremented until a pathname is found
+// that does not already exist.
+// Examples: 'dir/foo_test.xml' or 'dir/foo_test_1.xml'.
+// There could be a race condition if two or more processes are calling this
+// function at the same time -- they could both pick the same filename.
+FilePath FilePath::GenerateUniqueFileName(const FilePath& directory,
+                                          const FilePath& base_name,
+                                          const char* extension) {
+  FilePath full_pathname;
+  int number = 0;
+  do {
+    full_pathname.Set(MakeFileName(directory, base_name, number++, extension));
+  } while (full_pathname.FileOrDirectoryExists());
+  return full_pathname;
+}
+
+// Returns true if FilePath ends with a path separator, which indicates that
+// it is intended to represent a directory. Returns false otherwise.
+// This does NOT check that a directory (or file) actually exists.
+bool FilePath::IsDirectory() const {
+  return !pathname_.empty() &&
+         IsPathSeparator(pathname_.c_str()[pathname_.length() - 1]);
+}
+
+// Create directories so that path exists. Returns true if successful or if
+// the directories already exist; returns false if unable to create directories
+// for any reason.
+bool FilePath::CreateDirectoriesRecursively() const {
+  if (!this->IsDirectory()) {
+    return false;
+  }
+
+  if (pathname_.length() == 0 || this->DirectoryExists()) {
+    return true;
+  }
+
+  const FilePath parent(this->RemoveTrailingPathSeparator().RemoveFileName());
+  return parent.CreateDirectoriesRecursively() && this->CreateFolder();
+}
+
+// Create the directory so that path exists. Returns true if successful or
+// if the directory already exists; returns false if unable to create the
+// directory for any reason, including if the parent directory does not
+// exist. Not named "CreateDirectory" because that's a macro on Windows.
+bool FilePath::CreateFolder() const {
+#if GTEST_OS_WINDOWS_MOBILE
+  FilePath removed_sep(this->RemoveTrailingPathSeparator());
+  LPCWSTR unicode = String::AnsiToUtf16(removed_sep.c_str());
+  int result = CreateDirectory(unicode, NULL) ? 0 : -1;
+  delete [] unicode;
+#elif GTEST_OS_WINDOWS
+  int result = _mkdir(pathname_.c_str());
+#else
+  int result = mkdir(pathname_.c_str(), 0777);
+#endif  // GTEST_OS_WINDOWS_MOBILE
+
+  if (result == -1) {
+    return this->DirectoryExists();  // An error is OK if the directory exists.
+  }
+  return true;  // No error.
+}
+
+// If input name has a trailing separator character, remove it and return the
+// name, otherwise return the name string unmodified.
+// On Windows platform, uses \ as the separator, other platforms use /.
+FilePath FilePath::RemoveTrailingPathSeparator() const {
+  return IsDirectory()
+      ? FilePath(pathname_.substr(0, pathname_.length() - 1))
+      : *this;
+}
+
+// Removes any redundant separators that might be in the pathname.
+// For example, "bar///foo" becomes "bar/foo". Does not eliminate other
+// redundancies that might be in a pathname involving "." or "..".
+// TODO(wan at google.com): handle Windows network shares (e.g. \\server\share).
+void FilePath::Normalize() {
+  if (pathname_.c_str() == NULL) {
+    pathname_ = "";
+    return;
+  }
+  const char* src = pathname_.c_str();
+  char* const dest = new char[pathname_.length() + 1];
+  char* dest_ptr = dest;
+  memset(dest_ptr, 0, pathname_.length() + 1);
+
+  while (*src != '\0') {
+    *dest_ptr = *src;
+    if (!IsPathSeparator(*src)) {
+      src++;
+    } else {
+#if GTEST_HAS_ALT_PATH_SEP_
+      if (*dest_ptr == kAlternatePathSeparator) {
+        *dest_ptr = kPathSeparator;
+      }
+#endif
+      while (IsPathSeparator(*src))
+        src++;
+    }
+    dest_ptr++;
+  }
+  *dest_ptr = '\0';
+  pathname_ = dest;
+  delete[] dest;
+}
+
+}  // namespace internal
+}  // namespace testing
diff --git a/test/gtest/src/gtest-internal-inl.h b/test/gtest/src/gtest-internal-inl.h
new file mode 100644
index 0000000..35df303
--- /dev/null
+++ b/test/gtest/src/gtest-internal-inl.h
@@ -0,0 +1,1218 @@
+// Copyright 2005, Google Inc.
+// All rights reserved.
+//
+// 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.
+
+// Utility functions and classes used by the Google C++ testing framework.
+//
+// Author: wan at google.com (Zhanyong Wan)
+//
+// This file contains purely Google Test's internal implementation.  Please
+// DO NOT #INCLUDE IT IN A USER PROGRAM.
+
+#ifndef GTEST_SRC_GTEST_INTERNAL_INL_H_
+#define GTEST_SRC_GTEST_INTERNAL_INL_H_
+
+// GTEST_IMPLEMENTATION_ is defined to 1 iff the current translation unit is
+// part of Google Test's implementation; otherwise it's undefined.
+#if !GTEST_IMPLEMENTATION_
+// A user is trying to include this from his code - just say no.
+# error "gtest-internal-inl.h is part of Google Test's internal implementation."
+# error "It must not be included except by Google Test itself."
+#endif  // GTEST_IMPLEMENTATION_
+
+#ifndef _WIN32_WCE
+# include <errno.h>
+#endif  // !_WIN32_WCE
+#include <stddef.h>
+#include <stdlib.h>  // For strtoll/_strtoul64/malloc/free.
+#include <string.h>  // For memmove.
+
+#include <algorithm>
+#include <string>
+#include <vector>
+
+#include "gtest/internal/gtest-port.h"
+
+#if GTEST_CAN_STREAM_RESULTS_
+# include <arpa/inet.h>  // NOLINT
+# include <netdb.h>  // NOLINT
+#endif
+
+#if GTEST_OS_WINDOWS
+# include <windows.h>  // NOLINT
+#endif  // GTEST_OS_WINDOWS
+
+#include "gtest/gtest.h"  // NOLINT
+#include "gtest/gtest-spi.h"
+
+namespace testing {
+
+// Declares the flags.
+//
+// We don't want the users to modify this flag in the code, but want
+// Google Test's own unit tests to be able to access it. Therefore we
+// declare it here as opposed to in gtest.h.
+GTEST_DECLARE_bool_(death_test_use_fork);
+
+namespace internal {
+
+// The value of GetTestTypeId() as seen from within the Google Test
+// library.  This is solely for testing GetTestTypeId().
+GTEST_API_ extern const TypeId kTestTypeIdInGoogleTest;
+
+// Names of the flags (needed for parsing Google Test flags).
+const char kAlsoRunDisabledTestsFlag[] = "also_run_disabled_tests";
+const char kBreakOnFailureFlag[] = "break_on_failure";
+const char kCatchExceptionsFlag[] = "catch_exceptions";
+const char kColorFlag[] = "color";
+const char kFilterFlag[] = "filter";
+const char kListTestsFlag[] = "list_tests";
+const char kOutputFlag[] = "output";
+const char kPrintTimeFlag[] = "print_time";
+const char kRandomSeedFlag[] = "random_seed";
+const char kRepeatFlag[] = "repeat";
+const char kShuffleFlag[] = "shuffle";
+const char kStackTraceDepthFlag[] = "stack_trace_depth";
+const char kStreamResultToFlag[] = "stream_result_to";
+const char kThrowOnFailureFlag[] = "throw_on_failure";
+
+// A valid random seed must be in [1, kMaxRandomSeed].
+const int kMaxRandomSeed = 99999;
+
+// g_help_flag is true iff the --help flag or an equivalent form is
+// specified on the command line.
+GTEST_API_ extern bool g_help_flag;
+
+// Returns the current time in milliseconds.
+GTEST_API_ TimeInMillis GetTimeInMillis();
+
+// Returns true iff Google Test should use colors in the output.
+GTEST_API_ bool ShouldUseColor(bool stdout_is_tty);
+
+// Formats the given time in milliseconds as seconds.
+GTEST_API_ std::string FormatTimeInMillisAsSeconds(TimeInMillis ms);
+
+// Converts the given time in milliseconds to a date string in the ISO 8601
+// format, without the timezone information.  N.B.: due to the use the
+// non-reentrant localtime() function, this function is not thread safe.  Do
+// not use it in any code that can be called from multiple threads.
+GTEST_API_ std::string FormatEpochTimeInMillisAsIso8601(TimeInMillis ms);
+
+// Parses a string for an Int32 flag, in the form of "--flag=value".
+//
+// On success, stores the value of the flag in *value, and returns
+// true.  On failure, returns false without changing *value.
+GTEST_API_ bool ParseInt32Flag(
+    const char* str, const char* flag, Int32* value);
+
+// Returns a random seed in range [1, kMaxRandomSeed] based on the
+// given --gtest_random_seed flag value.
+inline int GetRandomSeedFromFlag(Int32 random_seed_flag) {
+  const unsigned int raw_seed = (random_seed_flag == 0) ?
+      static_cast<unsigned int>(GetTimeInMillis()) :
+      static_cast<unsigned int>(random_seed_flag);
+
+  // Normalizes the actual seed to range [1, kMaxRandomSeed] such that
+  // it's easy to type.
+  const int normalized_seed =
+      static_cast<int>((raw_seed - 1U) %
+                       static_cast<unsigned int>(kMaxRandomSeed)) + 1;
+  return normalized_seed;
+}
+
+// Returns the first valid random seed after 'seed'.  The behavior is
+// undefined if 'seed' is invalid.  The seed after kMaxRandomSeed is
+// considered to be 1.
+inline int GetNextRandomSeed(int seed) {
+  GTEST_CHECK_(1 <= seed && seed <= kMaxRandomSeed)
+      << "Invalid random seed " << seed << " - must be in [1, "
+      << kMaxRandomSeed << "].";
+  const int next_seed = seed + 1;
+  return (next_seed > kMaxRandomSeed) ? 1 : next_seed;
+}
+
+// This class saves the values of all Google Test flags in its c'tor, and
+// restores them in its d'tor.
+class GTestFlagSaver {
+ public:
+  // The c'tor.
+  GTestFlagSaver() {
+    also_run_disabled_tests_ = GTEST_FLAG(also_run_disabled_tests);
+    break_on_failure_ = GTEST_FLAG(break_on_failure);
+    catch_exceptions_ = GTEST_FLAG(catch_exceptions);
+    color_ = GTEST_FLAG(color);
+    death_test_style_ = GTEST_FLAG(death_test_style);
+    death_test_use_fork_ = GTEST_FLAG(death_test_use_fork);
+    filter_ = GTEST_FLAG(filter);
+    internal_run_death_test_ = GTEST_FLAG(internal_run_death_test);
+    list_tests_ = GTEST_FLAG(list_tests);
+    output_ = GTEST_FLAG(output);
+    print_time_ = GTEST_FLAG(print_time);
+    random_seed_ = GTEST_FLAG(random_seed);
+    repeat_ = GTEST_FLAG(repeat);
+    shuffle_ = GTEST_FLAG(shuffle);
+    stack_trace_depth_ = GTEST_FLAG(stack_trace_depth);
+    stream_result_to_ = GTEST_FLAG(stream_result_to);
+    throw_on_failure_ = GTEST_FLAG(throw_on_failure);
+  }
+
+  // The d'tor is not virtual.  DO NOT INHERIT FROM THIS CLASS.
+  ~GTestFlagSaver() {
+    GTEST_FLAG(also_run_disabled_tests) = also_run_disabled_tests_;
+    GTEST_FLAG(break_on_failure) = break_on_failure_;
+    GTEST_FLAG(catch_exceptions) = catch_exceptions_;
+    GTEST_FLAG(color) = color_;
+    GTEST_FLAG(death_test_style) = death_test_style_;
+    GTEST_FLAG(death_test_use_fork) = death_test_use_fork_;
+    GTEST_FLAG(filter) = filter_;
+    GTEST_FLAG(internal_run_death_test) = internal_run_death_test_;
+    GTEST_FLAG(list_tests) = list_tests_;
+    GTEST_FLAG(output) = output_;
+    GTEST_FLAG(print_time) = print_time_;
+    GTEST_FLAG(random_seed) = random_seed_;
+    GTEST_FLAG(repeat) = repeat_;
+    GTEST_FLAG(shuffle) = shuffle_;
+    GTEST_FLAG(stack_trace_depth) = stack_trace_depth_;
+    GTEST_FLAG(stream_result_to) = stream_result_to_;
+    GTEST_FLAG(throw_on_failure) = throw_on_failure_;
+  }
+
+ private:
+  // Fields for saving the original values of flags.
+  bool also_run_disabled_tests_;
+  bool break_on_failure_;
+  bool catch_exceptions_;
+  std::string color_;
+  std::string death_test_style_;
+  bool death_test_use_fork_;
+  std::string filter_;
+  std::string internal_run_death_test_;
+  bool list_tests_;
+  std::string output_;
+  bool print_time_;
+  internal::Int32 random_seed_;
+  internal::Int32 repeat_;
+  bool shuffle_;
+  internal::Int32 stack_trace_depth_;
+  std::string stream_result_to_;
+  bool throw_on_failure_;
+} GTEST_ATTRIBUTE_UNUSED_;
+
+// Converts a Unicode code point to a narrow string in UTF-8 encoding.
+// code_point parameter is of type UInt32 because wchar_t may not be
+// wide enough to contain a code point.
+// If the code_point is not a valid Unicode code point
+// (i.e. outside of Unicode range U+0 to U+10FFFF) it will be converted
+// to "(Invalid Unicode 0xXXXXXXXX)".
+GTEST_API_ std::string CodePointToUtf8(UInt32 code_point);
+
+// Converts a wide string to a narrow string in UTF-8 encoding.
+// The wide string is assumed to have the following encoding:
+//   UTF-16 if sizeof(wchar_t) == 2 (on Windows, Cygwin, Symbian OS)
+//   UTF-32 if sizeof(wchar_t) == 4 (on Linux)
+// Parameter str points to a null-terminated wide string.
+// Parameter num_chars may additionally limit the number
+// of wchar_t characters processed. -1 is used when the entire string
+// should be processed.
+// If the string contains code points that are not valid Unicode code points
+// (i.e. outside of Unicode range U+0 to U+10FFFF) they will be output
+// as '(Invalid Unicode 0xXXXXXXXX)'. If the string is in UTF16 encoding
+// and contains invalid UTF-16 surrogate pairs, values in those pairs
+// will be encoded as individual Unicode characters from Basic Normal Plane.
+GTEST_API_ std::string WideStringToUtf8(const wchar_t* str, int num_chars);
+
+// Reads the GTEST_SHARD_STATUS_FILE environment variable, and creates the file
+// if the variable is present. If a file already exists at this location, this
+// function will write over it. If the variable is present, but the file cannot
+// be created, prints an error and exits.
+void WriteToShardStatusFileIfNeeded();
+
+// Checks whether sharding is enabled by examining the relevant
+// environment variable values. If the variables are present,
+// but inconsistent (e.g., shard_index >= total_shards), prints
+// an error and exits. If in_subprocess_for_death_test, sharding is
+// disabled because it must only be applied to the original test
+// process. Otherwise, we could filter out death tests we intended to execute.
+GTEST_API_ bool ShouldShard(const char* total_shards_str,
+                            const char* shard_index_str,
+                            bool in_subprocess_for_death_test);
+
+// Parses the environment variable var as an Int32. If it is unset,
+// returns default_val. If it is not an Int32, prints an error and
+// and aborts.
+GTEST_API_ Int32 Int32FromEnvOrDie(const char* env_var, Int32 default_val);
+
+// Given the total number of shards, the shard index, and the test id,
+// returns true iff the test should be run on this shard. The test id is
+// some arbitrary but unique non-negative integer assigned to each test
+// method. Assumes that 0 <= shard_index < total_shards.
+GTEST_API_ bool ShouldRunTestOnShard(
+    int total_shards, int shard_index, int test_id);
+
+// STL container utilities.
+
+// Returns the number of elements in the given container that satisfy
+// the given predicate.
+template <class Container, typename Predicate>
+inline int CountIf(const Container& c, Predicate predicate) {
+  // Implemented as an explicit loop since std::count_if() in libCstd on
+  // Solaris has a non-standard signature.
+  int count = 0;
+  for (typename Container::const_iterator it = c.begin(); it != c.end(); ++it) {
+    if (predicate(*it))
+      ++count;
+  }
+  return count;
+}
+
+// Applies a function/functor to each element in the container.
+template <class Container, typename Functor>
+void ForEach(const Container& c, Functor functor) {
+  std::for_each(c.begin(), c.end(), functor);
+}
+
+// Returns the i-th element of the vector, or default_value if i is not
+// in range [0, v.size()).
+template <typename E>
+inline E GetElementOr(const std::vector<E>& v, int i, E default_value) {
+  return (i < 0 || i >= static_cast<int>(v.size())) ? default_value : v[i];
+}
+
+// Performs an in-place shuffle of a range of the vector's elements.
+// 'begin' and 'end' are element indices as an STL-style range;
+// i.e. [begin, end) are shuffled, where 'end' == size() means to
+// shuffle to the end of the vector.
+template <typename E>
+void ShuffleRange(internal::Random* random, int begin, int end,
+                  std::vector<E>* v) {
+  const int size = static_cast<int>(v->size());
+  GTEST_CHECK_(0 <= begin && begin <= size)
+      << "Invalid shuffle range start " << begin << ": must be in range [0, "
+      << size << "].";
+  GTEST_CHECK_(begin <= end && end <= size)
+      << "Invalid shuffle range finish " << end << ": must be in range ["
+      << begin << ", " << size << "].";
+
+  // Fisher-Yates shuffle, from
+  // http://en.wikipedia.org/wiki/Fisher-Yates_shuffle
+  for (int range_width = end - begin; range_width >= 2; range_width--) {
+    const int last_in_range = begin + range_width - 1;
+    const int selected = begin + random->Generate(range_width);
+    std::swap((*v)[selected], (*v)[last_in_range]);
+  }
+}
+
+// Performs an in-place shuffle of the vector's elements.
+template <typename E>
+inline void Shuffle(internal::Random* random, std::vector<E>* v) {
+  ShuffleRange(random, 0, static_cast<int>(v->size()), v);
+}
+
+// A function for deleting an object.  Handy for being used as a
+// functor.
+template <typename T>
+static void Delete(T* x) {
+  delete x;
+}
+
+// A predicate that checks the key of a TestProperty against a known key.
+//
+// TestPropertyKeyIs is copyable.
+class TestPropertyKeyIs {
+ public:
+  // Constructor.
+  //
+  // TestPropertyKeyIs has NO default constructor.
+  explicit TestPropertyKeyIs(const std::string& key) : key_(key) {}
+
+  // Returns true iff the test name of test property matches on key_.
+  bool operator()(const TestProperty& test_property) const {
+    return test_property.key() == key_;
+  }
+
+ private:
+  std::string key_;
+};
+
+// Class UnitTestOptions.
+//
+// This class contains functions for processing options the user
+// specifies when running the tests.  It has only static members.
+//
+// In most cases, the user can specify an option using either an
+// environment variable or a command line flag.  E.g. you can set the
+// test filter using either GTEST_FILTER or --gtest_filter.  If both
+// the variable and the flag are present, the latter overrides the
+// former.
+class GTEST_API_ UnitTestOptions {
+ public:
+  // Functions for processing the gtest_output flag.
+
+  // Returns the output format, or "" for normal printed output.
+  static std::string GetOutputFormat();
+
+  // Returns the absolute path of the requested output file, or the
+  // default (test_detail.xml in the original working directory) if
+  // none was explicitly specified.
+  static std::string GetAbsolutePathToOutputFile();
+
+  // Functions for processing the gtest_filter flag.
+
+  // Returns true iff the wildcard pattern matches the string.  The
+  // first ':' or '\0' character in pattern marks the end of it.
+  //
+  // This recursive algorithm isn't very efficient, but is clear and
+  // works well enough for matching test names, which are short.
+  static bool PatternMatchesString(const char *pattern, const char *str);
+
+  // Returns true iff the user-specified filter matches the test case
+  // name and the test name.
+  static bool FilterMatchesTest(const std::string &test_case_name,
+                                const std::string &test_name);
+
+#if GTEST_OS_WINDOWS
+  // Function for supporting the gtest_catch_exception flag.
+
+  // Returns EXCEPTION_EXECUTE_HANDLER if Google Test should handle the
+  // given SEH exception, or EXCEPTION_CONTINUE_SEARCH otherwise.
+  // This function is useful as an __except condition.
+  static int GTestShouldProcessSEH(DWORD exception_code);
+#endif  // GTEST_OS_WINDOWS
+
+  // Returns true if "name" matches the ':' separated list of glob-style
+  // filters in "filter".
+  static bool MatchesFilter(const std::string& name, const char* filter);
+};
+
+// Returns the current application's name, removing directory path if that
+// is present.  Used by UnitTestOptions::GetOutputFile.
+GTEST_API_ FilePath GetCurrentExecutableName();
+
+// The role interface for getting the OS stack trace as a string.
+class OsStackTraceGetterInterface {
+ public:
+  OsStackTraceGetterInterface() {}
+  virtual ~OsStackTraceGetterInterface() {}
+
+  // Returns the current OS stack trace as an std::string.  Parameters:
+  //
+  //   max_depth  - the maximum number of stack frames to be included
+  //                in the trace.
+  //   skip_count - the number of top frames to be skipped; doesn't count
+  //                against max_depth.
+  virtual string CurrentStackTrace(int max_depth, int skip_count) = 0;
+
+  // UponLeavingGTest() should be called immediately before Google Test calls
+  // user code. It saves some information about the current stack that
+  // CurrentStackTrace() will use to find and hide Google Test stack frames.
+  virtual void UponLeavingGTest() = 0;
+
+ private:
+  GTEST_DISALLOW_COPY_AND_ASSIGN_(OsStackTraceGetterInterface);
+};
+
+// A working implementation of the OsStackTraceGetterInterface interface.
+class OsStackTraceGetter : public OsStackTraceGetterInterface {
+ public:
+  OsStackTraceGetter() : caller_frame_(NULL) {}
+
+  virtual string CurrentStackTrace(int max_depth, int skip_count)
+      GTEST_LOCK_EXCLUDED_(mutex_);
+
+  virtual void UponLeavingGTest() GTEST_LOCK_EXCLUDED_(mutex_);
+
+  // This string is inserted in place of stack frames that are part of
+  // Google Test's implementation.
+  static const char* const kElidedFramesMarker;
+
+ private:
+  Mutex mutex_;  // protects all internal state
+
+  // We save the stack frame below the frame that calls user code.
+  // We do this because the address of the frame immediately below
+  // the user code changes between the call to UponLeavingGTest()
+  // and any calls to CurrentStackTrace() from within the user code.
+  void* caller_frame_;
+
+  GTEST_DISALLOW_COPY_AND_ASSIGN_(OsStackTraceGetter);
+};
+
+// Information about a Google Test trace point.
+struct TraceInfo {
+  const char* file;
+  int line;
+  std::string message;
+};
+
+// This is the default global test part result reporter used in UnitTestImpl.
+// This class should only be used by UnitTestImpl.
+class DefaultGlobalTestPartResultReporter
+  : public TestPartResultReporterInterface {
+ public:
+  explicit DefaultGlobalTestPartResultReporter(UnitTestImpl* unit_test);
+  // Implements the TestPartResultReporterInterface. Reports the test part
+  // result in the current test.
+  virtual void ReportTestPartResult(const TestPartResult& result);
+
+ private:
+  UnitTestImpl* const unit_test_;
+
+  GTEST_DISALLOW_COPY_AND_ASSIGN_(DefaultGlobalTestPartResultReporter);
+};
+
+// This is the default per thread test part result reporter used in
+// UnitTestImpl. This class should only be used by UnitTestImpl.
+class DefaultPerThreadTestPartResultReporter
+    : public TestPartResultReporterInterface {
+ public:
+  explicit DefaultPerThreadTestPartResultReporter(UnitTestImpl* unit_test);
+  // Implements the TestPartResultReporterInterface. The implementation just
+  // delegates to the current global test part result reporter of *unit_test_.
+  virtual void ReportTestPartResult(const TestPartResult& result);
+
+ private:
+  UnitTestImpl* const unit_test_;
+
+  GTEST_DISALLOW_COPY_AND_ASSIGN_(DefaultPerThreadTestPartResultReporter);
+};
+
+// The private implementation of the UnitTest class.  We don't protect
+// the methods under a mutex, as this class is not accessible by a
+// user and the UnitTest class that delegates work to this class does
+// proper locking.
+class GTEST_API_ UnitTestImpl {
+ public:
+  explicit UnitTestImpl(UnitTest* parent);
+  virtual ~UnitTestImpl();
+
+  // There are two different ways to register your own TestPartResultReporter.
+  // You can register your own repoter to listen either only for test results
+  // from the current thread or for results from all threads.
+  // By default, each per-thread test result repoter just passes a new
+  // TestPartResult to the global test result reporter, which registers the
+  // test part result for the currently running test.
+
+  // Returns the global test part result reporter.
+  TestPartResultReporterInterface* GetGlobalTestPartResultReporter();
+
+  // Sets the global test part result reporter.
+  void SetGlobalTestPartResultReporter(
+      TestPartResultReporterInterface* reporter);
+
+  // Returns the test part result reporter for the current thread.
+  TestPartResultReporterInterface* GetTestPartResultReporterForCurrentThread();
+
+  // Sets the test part result reporter for the current thread.
+  void SetTestPartResultReporterForCurrentThread(
+      TestPartResultReporterInterface* reporter);
+
+  // Gets the number of successful test cases.
+  int successful_test_case_count() const;
+
+  // Gets the number of failed test cases.
+  int failed_test_case_count() const;
+
+  // Gets the number of all test cases.
+  int total_test_case_count() const;
+
+  // Gets the number of all test cases that contain at least one test
+  // that should run.
+  int test_case_to_run_count() const;
+
+  // Gets the number of successful tests.
+  int successful_test_count() const;
+
+  // Gets the number of failed tests.
+  int failed_test_count() const;
+
+  // Gets the number of disabled tests that will be reported in the XML report.
+  int reportable_disabled_test_count() const;
+
+  // Gets the number of disabled tests.
+  int disabled_test_count() const;
+
+  // Gets the number of tests to be printed in the XML report.
+  int reportable_test_count() const;
+
+  // Gets the number of all tests.
+  int total_test_count() const;
+
+  // Gets the number of tests that should run.
+  int test_to_run_count() const;
+
+  // Gets the time of the test program start, in ms from the start of the
+  // UNIX epoch.
+  TimeInMillis start_timestamp() const { return start_timestamp_; }
+
+  // Gets the elapsed time, in milliseconds.
+  TimeInMillis elapsed_time() const { return elapsed_time_; }
+
+  // Returns true iff the unit test passed (i.e. all test cases passed).
+  bool Passed() const { return !Failed(); }
+
+  // Returns true iff the unit test failed (i.e. some test case failed
+  // or something outside of all tests failed).
+  bool Failed() const {
+    return failed_test_case_count() > 0 || ad_hoc_test_result()->Failed();
+  }
+
+  // Gets the i-th test case among all the test cases. i can range from 0 to
+  // total_test_case_count() - 1. If i is not in that range, returns NULL.
+  const TestCase* GetTestCase(int i) const {
+    const int index = GetElementOr(test_case_indices_, i, -1);
+    return index < 0 ? NULL : test_cases_[i];
+  }
+
+  // Gets the i-th test case among all the test cases. i can range from 0 to
+  // total_test_case_count() - 1. If i is not in that range, returns NULL.
+  TestCase* GetMutableTestCase(int i) {
+    const int index = GetElementOr(test_case_indices_, i, -1);
+    return index < 0 ? NULL : test_cases_[index];
+  }
+
+  // Provides access to the event listener list.
+  TestEventListeners* listeners() { return &listeners_; }
+
+  // Returns the TestResult for the test that's currently running, or
+  // the TestResult for the ad hoc test if no test is running.
+  TestResult* current_test_result();
+
+  // Returns the TestResult for the ad hoc test.
+  const TestResult* ad_hoc_test_result() const { return &ad_hoc_test_result_; }
+
+  // Sets the OS stack trace getter.
+  //
+  // Does nothing if the input and the current OS stack trace getter
+  // are the same; otherwise, deletes the old getter and makes the
+  // input the current getter.
+  void set_os_stack_trace_getter(OsStackTraceGetterInterface* getter);
+
+  // Returns the current OS stack trace getter if it is not NULL;
+  // otherwise, creates an OsStackTraceGetter, makes it the current
+  // getter, and returns it.
+  OsStackTraceGetterInterface* os_stack_trace_getter();
+
+  // Returns the current OS stack trace as an std::string.
+  //
+  // The maximum number of stack frames to be included is specified by
+  // the gtest_stack_trace_depth flag.  The skip_count parameter
+  // specifies the number of top frames to be skipped, which doesn't
+  // count against the number of frames to be included.
+  //
+  // For example, if Foo() calls Bar(), which in turn calls
+  // CurrentOsStackTraceExceptTop(1), Foo() will be included in the
+  // trace but Bar() and CurrentOsStackTraceExceptTop() won't.
+  std::string CurrentOsStackTraceExceptTop(int skip_count) GTEST_NO_INLINE_;
+
+  // Finds and returns a TestCase with the given name.  If one doesn't
+  // exist, creates one and returns it.
+  //
+  // Arguments:
+  //
+  //   test_case_name: name of the test case
+  //   type_param:     the name of the test's type parameter, or NULL if
+  //                   this is not a typed or a type-parameterized test.
+  //   set_up_tc:      pointer to the function that sets up the test case
+  //   tear_down_tc:   pointer to the function that tears down the test case
+  TestCase* GetTestCase(const char* test_case_name,
+                        const char* type_param,
+                        Test::SetUpTestCaseFunc set_up_tc,
+                        Test::TearDownTestCaseFunc tear_down_tc);
+
+  // Adds a TestInfo to the unit test.
+  //
+  // Arguments:
+  //
+  //   set_up_tc:    pointer to the function that sets up the test case
+  //   tear_down_tc: pointer to the function that tears down the test case
+  //   test_info:    the TestInfo object
+  void AddTestInfo(Test::SetUpTestCaseFunc set_up_tc,
+                   Test::TearDownTestCaseFunc tear_down_tc,
+                   TestInfo* test_info) {
+    // In order to support thread-safe death tests, we need to
+    // remember the original working directory when the test program
+    // was first invoked.  We cannot do this in RUN_ALL_TESTS(), as
+    // the user may have changed the current directory before calling
+    // RUN_ALL_TESTS().  Therefore we capture the current directory in
+    // AddTestInfo(), which is called to register a TEST or TEST_F
+    // before main() is reached.
+    if (original_working_dir_.IsEmpty()) {
+      original_working_dir_.Set(FilePath::GetCurrentDir());
+      GTEST_CHECK_(!original_working_dir_.IsEmpty())
+          << "Failed to get the current working directory.";
+    }
+
+    GetTestCase(test_info->test_case_name(),
+                test_info->type_param(),
+                set_up_tc,
+                tear_down_tc)->AddTestInfo(test_info);
+  }
+
+#if GTEST_HAS_PARAM_TEST
+  // Returns ParameterizedTestCaseRegistry object used to keep track of
+  // value-parameterized tests and instantiate and register them.
+  internal::ParameterizedTestCaseRegistry& parameterized_test_registry() {
+    return parameterized_test_registry_;
+  }
+#endif  // GTEST_HAS_PARAM_TEST
+
+  // Sets the TestCase object for the test that's currently running.
+  void set_current_test_case(TestCase* a_current_test_case) {
+    current_test_case_ = a_current_test_case;
+  }
+
+  // Sets the TestInfo object for the test that's currently running.  If
+  // current_test_info is NULL, the assertion results will be stored in
+  // ad_hoc_test_result_.
+  void set_current_test_info(TestInfo* a_current_test_info) {
+    current_test_info_ = a_current_test_info;
+  }
+
+  // Registers all parameterized tests defined using TEST_P and
+  // INSTANTIATE_TEST_CASE_P, creating regular tests for each test/parameter
+  // combination. This method can be called more then once; it has guards
+  // protecting from registering the tests more then once.  If
+  // value-parameterized tests are disabled, RegisterParameterizedTests is
+  // present but does nothing.
+  void RegisterParameterizedTests();
+
+  // Runs all tests in this UnitTest object, prints the result, and
+  // returns true if all tests are successful.  If any exception is
+  // thrown during a test, this test is considered to be failed, but
+  // the rest of the tests will still be run.
+  bool RunAllTests();
+
+  // Clears the results of all tests, except the ad hoc tests.
+  void ClearNonAdHocTestResult() {
+    ForEach(test_cases_, TestCase::ClearTestCaseResult);
+  }
+
+  // Clears the results of ad-hoc test assertions.
+  void ClearAdHocTestResult() {
+    ad_hoc_test_result_.Clear();
+  }
+
+  // Adds a TestProperty to the current TestResult object when invoked in a
+  // context of a test or a test case, or to the global property set. If the
+  // result already contains a property with the same key, the value will be
+  // updated.
+  void RecordProperty(const TestProperty& test_property);
+
+  enum ReactionToSharding {
+    HONOR_SHARDING_PROTOCOL,
+    IGNORE_SHARDING_PROTOCOL
+  };
+
+  // Matches the full name of each test against the user-specified
+  // filter to decide whether the test should run, then records the
+  // result in each TestCase and TestInfo object.
+  // If shard_tests == HONOR_SHARDING_PROTOCOL, further filters tests
+  // based on sharding variables in the environment.
+  // Returns the number of tests that should run.
+  int FilterTests(ReactionToSharding shard_tests);
+
+  // Prints the names of the tests matching the user-specified filter flag.
+  void ListTestsMatchingFilter();
+
+  const TestCase* current_test_case() const { return current_test_case_; }
+  TestInfo* current_test_info() { return current_test_info_; }
+  const TestInfo* current_test_info() const { return current_test_info_; }
+
+  // Returns the vector of environments that need to be set-up/torn-down
+  // before/after the tests are run.
+  std::vector<Environment*>& environments() { return environments_; }
+
+  // Getters for the per-thread Google Test trace stack.
+  std::vector<TraceInfo>& gtest_trace_stack() {
+    return *(gtest_trace_stack_.pointer());
+  }
+  const std::vector<TraceInfo>& gtest_trace_stack() const {
+    return gtest_trace_stack_.get();
+  }
+
+#if GTEST_HAS_DEATH_TEST
+  void InitDeathTestSubprocessControlInfo() {
+    internal_run_death_test_flag_.reset(ParseInternalRunDeathTestFlag());
+  }
+  // Returns a pointer to the parsed --gtest_internal_run_death_test
+  // flag, or NULL if that flag was not specified.
+  // This information is useful only in a death test child process.
+  // Must not be called before a call to InitGoogleTest.
+  const InternalRunDeathTestFlag* internal_run_death_test_flag() const {
+    return internal_run_death_test_flag_.get();
+  }
+
+  // Returns a pointer to the current death test factory.
+  internal::DeathTestFactory* death_test_factory() {
+    return death_test_factory_.get();
+  }
+
+  void SuppressTestEventsIfInSubprocess();
+
+  friend class ReplaceDeathTestFactory;
+#endif  // GTEST_HAS_DEATH_TEST
+
+  // Initializes the event listener performing XML output as specified by
+  // UnitTestOptions. Must not be called before InitGoogleTest.
+  void ConfigureXmlOutput();
+
+#if GTEST_CAN_STREAM_RESULTS_
+  // Initializes the event listener for streaming test results to a socket.
+  // Must not be called before InitGoogleTest.
+  void ConfigureStreamingOutput();
+#endif
+
+  // Performs initialization dependent upon flag values obtained in
+  // ParseGoogleTestFlagsOnly.  Is called from InitGoogleTest after the call to
+  // ParseGoogleTestFlagsOnly.  In case a user neglects to call InitGoogleTest
+  // this function is also called from RunAllTests.  Since this function can be
+  // called more than once, it has to be idempotent.
+  void PostFlagParsingInit();
+
+  // Gets the random seed used at the start of the current test iteration.
+  int random_seed() const { return random_seed_; }
+
+  // Gets the random number generator.
+  internal::Random* random() { return &random_; }
+
+  // Shuffles all test cases, and the tests within each test case,
+  // making sure that death tests are still run first.
+  void ShuffleTests();
+
+  // Restores the test cases and tests to their order before the first shuffle.
+  void UnshuffleTests();
+
+  // Returns the value of GTEST_FLAG(catch_exceptions) at the moment
+  // UnitTest::Run() starts.
+  bool catch_exceptions() const { return catch_exceptions_; }
+
+ private:
+  friend class ::testing::UnitTest;
+
+  // Used by UnitTest::Run() to capture the state of
+  // GTEST_FLAG(catch_exceptions) at the moment it starts.
+  void set_catch_exceptions(bool value) { catch_exceptions_ = value; }
+
+  // The UnitTest object that owns this implementation object.
+  UnitTest* const parent_;
+
+  // The working directory when the first TEST() or TEST_F() was
+  // executed.
+  internal::FilePath original_working_dir_;
+
+  // The default test part result reporters.
+  DefaultGlobalTestPartResultReporter default_global_test_part_result_reporter_;
+  DefaultPerThreadTestPartResultReporter
+      default_per_thread_test_part_result_reporter_;
+
+  // Points to (but doesn't own) the global test part result reporter.
+  TestPartResultReporterInterface* global_test_part_result_repoter_;
+
+  // Protects read and write access to global_test_part_result_reporter_.
+  internal::Mutex global_test_part_result_reporter_mutex_;
+
+  // Points to (but doesn't own) the per-thread test part result reporter.
+  internal::ThreadLocal<TestPartResultReporterInterface*>
+      per_thread_test_part_result_reporter_;
+
+  // The vector of environments that need to be set-up/torn-down
+  // before/after the tests are run.
+  std::vector<Environment*> environments_;
+
+  // The vector of TestCases in their original order.  It owns the
+  // elements in the vector.
+  std::vector<TestCase*> test_cases_;
+
+  // Provides a level of indirection for the test case list to allow
+  // easy shuffling and restoring the test case order.  The i-th
+  // element of this vector is the index of the i-th test case in the
+  // shuffled order.
+  std::vector<int> test_case_indices_;
+
+#if GTEST_HAS_PARAM_TEST
+  // ParameterizedTestRegistry object used to register value-parameterized
+  // tests.
+  internal::ParameterizedTestCaseRegistry parameterized_test_registry_;
+
+  // Indicates whether RegisterParameterizedTests() has been called already.
+  bool parameterized_tests_registered_;
+#endif  // GTEST_HAS_PARAM_TEST
+
+  // Index of the last death test case registered.  Initially -1.
+  int last_death_test_case_;
+
+  // This points to the TestCase for the currently running test.  It
+  // changes as Google Test goes through one test case after another.
+  // When no test is running, this is set to NULL and Google Test
+  // stores assertion results in ad_hoc_test_result_.  Initially NULL.
+  TestCase* current_test_case_;
+
+  // This points to the TestInfo for the currently running test.  It
+  // changes as Google Test goes through one test after another.  When
+  // no test is running, this is set to NULL and Google Test stores
+  // assertion results in ad_hoc_test_result_.  Initially NULL.
+  TestInfo* current_test_info_;
+
+  // Normally, a user only writes assertions inside a TEST or TEST_F,
+  // or inside a function called by a TEST or TEST_F.  Since Google
+  // Test keeps track of which test is current running, it can
+  // associate such an assertion with the test it belongs to.
+  //
+  // If an assertion is encountered when no TEST or TEST_F is running,
+  // Google Test attributes the assertion result to an imaginary "ad hoc"
+  // test, and records the result in ad_hoc_test_result_.
+  TestResult ad_hoc_test_result_;
+
+  // The list of event listeners that can be used to track events inside
+  // Google Test.
+  TestEventListeners listeners_;
+
+  // The OS stack trace getter.  Will be deleted when the UnitTest
+  // object is destructed.  By default, an OsStackTraceGetter is used,
+  // but the user can set this field to use a custom getter if that is
+  // desired.
+  OsStackTraceGetterInterface* os_stack_trace_getter_;
+
+  // True iff PostFlagParsingInit() has been called.
+  bool post_flag_parse_init_performed_;
+
+  // The random number seed used at the beginning of the test run.
+  int random_seed_;
+
+  // Our random number generator.
+  internal::Random random_;
+
+  // The time of the test program start, in ms from the start of the
+  // UNIX epoch.
+  TimeInMillis start_timestamp_;
+
+  // How long the test took to run, in milliseconds.
+  TimeInMillis elapsed_time_;
+
+#if GTEST_HAS_DEATH_TEST
+  // The decomposed components of the gtest_internal_run_death_test flag,
+  // parsed when RUN_ALL_TESTS is called.
+  internal::scoped_ptr<InternalRunDeathTestFlag> internal_run_death_test_flag_;
+  internal::scoped_ptr<internal::DeathTestFactory> death_test_factory_;
+#endif  // GTEST_HAS_DEATH_TEST
+
+  // A per-thread stack of traces created by the SCOPED_TRACE() macro.
+  internal::ThreadLocal<std::vector<TraceInfo> > gtest_trace_stack_;
+
+  // The value of GTEST_FLAG(catch_exceptions) at the moment RunAllTests()
+  // starts.
+  bool catch_exceptions_;
+
+  GTEST_DISALLOW_COPY_AND_ASSIGN_(UnitTestImpl);
+};  // class UnitTestImpl
+
+// Convenience function for accessing the global UnitTest
+// implementation object.
+inline UnitTestImpl* GetUnitTestImpl() {
+  return UnitTest::GetInstance()->impl();
+}
+
+#if GTEST_USES_SIMPLE_RE
+
+// Internal helper functions for implementing the simple regular
+// expression matcher.
+GTEST_API_ bool IsInSet(char ch, const char* str);
+GTEST_API_ bool IsAsciiDigit(char ch);
+GTEST_API_ bool IsAsciiPunct(char ch);
+GTEST_API_ bool IsRepeat(char ch);
+GTEST_API_ bool IsAsciiWhiteSpace(char ch);
+GTEST_API_ bool IsAsciiWordChar(char ch);
+GTEST_API_ bool IsValidEscape(char ch);
+GTEST_API_ bool AtomMatchesChar(bool escaped, char pattern, char ch);
+GTEST_API_ bool ValidateRegex(const char* regex);
+GTEST_API_ bool MatchRegexAtHead(const char* regex, const char* str);
+GTEST_API_ bool MatchRepetitionAndRegexAtHead(
+    bool escaped, char ch, char repeat, const char* regex, const char* str);
+GTEST_API_ bool MatchRegexAnywhere(const char* regex, const char* str);
+
+#endif  // GTEST_USES_SIMPLE_RE
+
+// Parses the command line for Google Test flags, without initializing
+// other parts of Google Test.
+GTEST_API_ void ParseGoogleTestFlagsOnly(int* argc, char** argv);
+GTEST_API_ void ParseGoogleTestFlagsOnly(int* argc, wchar_t** argv);
+
+#if GTEST_HAS_DEATH_TEST
+
+// Returns the message describing the last system error, regardless of the
+// platform.
+GTEST_API_ std::string GetLastErrnoDescription();
+
+# if GTEST_OS_WINDOWS
+// Provides leak-safe Windows kernel handle ownership.
+class AutoHandle {
+ public:
+  AutoHandle() : handle_(INVALID_HANDLE_VALUE) {}
+  explicit AutoHandle(HANDLE handle) : handle_(handle) {}
+
+  ~AutoHandle() { Reset(); }
+
+  HANDLE Get() const { return handle_; }
+  void Reset() { Reset(INVALID_HANDLE_VALUE); }
+  void Reset(HANDLE handle) {
+    if (handle != handle_) {
+      if (handle_ != INVALID_HANDLE_VALUE)
+        ::CloseHandle(handle_);
+      handle_ = handle;
+    }
+  }
+
+ private:
+  HANDLE handle_;
+
+  GTEST_DISALLOW_COPY_AND_ASSIGN_(AutoHandle);
+};
+# endif  // GTEST_OS_WINDOWS
+
+// Attempts to parse a string into a positive integer pointed to by the
+// number parameter.  Returns true if that is possible.
+// GTEST_HAS_DEATH_TEST implies that we have ::std::string, so we can use
+// it here.
+template <typename Integer>
+bool ParseNaturalNumber(const ::std::string& str, Integer* number) {
+  // Fail fast if the given string does not begin with a digit;
+  // this bypasses strtoXXX's "optional leading whitespace and plus
+  // or minus sign" semantics, which are undesirable here.
+  if (str.empty() || !IsDigit(str[0])) {
+    return false;
+  }
+  errno = 0;
+
+  char* end;
+  // BiggestConvertible is the largest integer type that system-provided
+  // string-to-number conversion routines can return.
+
+# if GTEST_OS_WINDOWS && !defined(__GNUC__)
+
+  // MSVC and C++ Builder define __int64 instead of the standard long long.
+  typedef unsigned __int64 BiggestConvertible;
+  const BiggestConvertible parsed = _strtoui64(str.c_str(), &end, 10);
+
+# else
+
+  typedef unsigned long long BiggestConvertible;  // NOLINT
+  const BiggestConvertible parsed = strtoull(str.c_str(), &end, 10);
+
+# endif  // GTEST_OS_WINDOWS && !defined(__GNUC__)
+
+  const bool parse_success = *end == '\0' && errno == 0;
+
+  // TODO(vladl at google.com): Convert this to compile time assertion when it is
+  // available.
+  GTEST_CHECK_(sizeof(Integer) <= sizeof(parsed));
+
+  const Integer result = static_cast<Integer>(parsed);
+  if (parse_success && static_cast<BiggestConvertible>(result) == parsed) {
+    *number = result;
+    return true;
+  }
+  return false;
+}
+#endif  // GTEST_HAS_DEATH_TEST
+
+// TestResult contains some private methods that should be hidden from
+// Google Test user but are required for testing. This class allow our tests
+// to access them.
+//
+// This class is supplied only for the purpose of testing Google Test's own
+// constructs. Do not use it in user tests, either directly or indirectly.
+class TestResultAccessor {
+ public:
+  static void RecordProperty(TestResult* test_result,
+                             const std::string& xml_element,
+                             const TestProperty& property) {
+    test_result->RecordProperty(xml_element, property);
+  }
+
+  static void ClearTestPartResults(TestResult* test_result) {
+    test_result->ClearTestPartResults();
+  }
+
+  static const std::vector<testing::TestPartResult>& test_part_results(
+      const TestResult& test_result) {
+    return test_result.test_part_results();
+  }
+};
+
+#if GTEST_CAN_STREAM_RESULTS_
+
+// Streams test results to the given port on the given host machine.
+class StreamingListener : public EmptyTestEventListener {
+ public:
+  // Abstract base class for writing strings to a socket.
+  class AbstractSocketWriter {
+   public:
+    virtual ~AbstractSocketWriter() {}
+
+    // Sends a string to the socket.
+    virtual void Send(const string& message) = 0;
+
+    // Closes the socket.
+    virtual void CloseConnection() {}
+
+    // Sends a string and a newline to the socket.
+    void SendLn(const string& message) {
+      Send(message + "\n");
+    }
+  };
+
+  // Concrete class for actually writing strings to a socket.
+  class SocketWriter : public AbstractSocketWriter {
+   public:
+    SocketWriter(const string& host, const string& port)
+        : sockfd_(-1), host_name_(host), port_num_(port) {
+      MakeConnection();
+    }
+
+    virtual ~SocketWriter() {
+      if (sockfd_ != -1)
+        CloseConnection();
+    }
+
+    // Sends a string to the socket.
+    virtual void Send(const string& message) {
+      GTEST_CHECK_(sockfd_ != -1)
+          << "Send() can be called only when there is a connection.";
+
+      const int len = static_cast<int>(message.length());
+      if (write(sockfd_, message.c_str(), len) != len) {
+        GTEST_LOG_(WARNING)
+            << "stream_result_to: failed to stream to "
+            << host_name_ << ":" << port_num_;
+      }
+    }
+
+   private:
+    // Creates a client socket and connects to the server.
+    void MakeConnection();
+
+    // Closes the socket.
+    void CloseConnection() {
+      GTEST_CHECK_(sockfd_ != -1)
+          << "CloseConnection() can be called only when there is a connection.";
+
+      close(sockfd_);
+      sockfd_ = -1;
+    }
+
+    int sockfd_;  // socket file descriptor
+    const string host_name_;
+    const string port_num_;
+
+    GTEST_DISALLOW_COPY_AND_ASSIGN_(SocketWriter);
+  };  // class SocketWriter
+
+  // Escapes '=', '&', '%', and '\n' characters in str as "%xx".
+  static string UrlEncode(const char* str);
+
+  StreamingListener(const string& host, const string& port)
+      : socket_writer_(new SocketWriter(host, port)) { Start(); }
+
+  explicit StreamingListener(AbstractSocketWriter* socket_writer)
+      : socket_writer_(socket_writer) { Start(); }
+
+  void OnTestProgramStart(const UnitTest& /* unit_test */) {
+    SendLn("event=TestProgramStart");
+  }
+
+  void OnTestProgramEnd(const UnitTest& unit_test) {
+    // Note that Google Test current only report elapsed time for each
+    // test iteration, not for the entire test program.
+    SendLn("event=TestProgramEnd&passed=" + FormatBool(unit_test.Passed()));
+
+    // Notify the streaming server to stop.
+    socket_writer_->CloseConnection();
+  }
+
+  void OnTestIterationStart(const UnitTest& /* unit_test */, int iteration) {
+    SendLn("event=TestIterationStart&iteration=" +
+           StreamableToString(iteration));
+  }
+
+  void OnTestIterationEnd(const UnitTest& unit_test, int /* iteration */) {
+    SendLn("event=TestIterationEnd&passed=" +
+           FormatBool(unit_test.Passed()) + "&elapsed_time=" +
+           StreamableToString(unit_test.elapsed_time()) + "ms");
+  }
+
+  void OnTestCaseStart(const TestCase& test_case) {
+    SendLn(std::string("event=TestCaseStart&name=") + test_case.name());
+  }
+
+  void OnTestCaseEnd(const TestCase& test_case) {
+    SendLn("event=TestCaseEnd&passed=" + FormatBool(test_case.Passed())
+           + "&elapsed_time=" + StreamableToString(test_case.elapsed_time())
+           + "ms");
+  }
+
+  void OnTestStart(const TestInfo& test_info) {
+    SendLn(std::string("event=TestStart&name=") + test_info.name());
+  }
+
+  void OnTestEnd(const TestInfo& test_info) {
+    SendLn("event=TestEnd&passed=" +
+           FormatBool((test_info.result())->Passed()) +
+           "&elapsed_time=" +
+           StreamableToString((test_info.result())->elapsed_time()) + "ms");
+  }
+
+  void OnTestPartResult(const TestPartResult& test_part_result) {
+    const char* file_name = test_part_result.file_name();
+    if (file_name == NULL)
+      file_name = "";
+    SendLn("event=TestPartResult&file=" + UrlEncode(file_name) +
+           "&line=" + StreamableToString(test_part_result.line_number()) +
+           "&message=" + UrlEncode(test_part_result.message()));
+  }
+
+ private:
+  // Sends the given message and a newline to the socket.
+  void SendLn(const string& message) { socket_writer_->SendLn(message); }
+
+  // Called at the start of streaming to notify the receiver what
+  // protocol we are using.
+  void Start() { SendLn("gtest_streaming_protocol_version=1.0"); }
+
+  string FormatBool(bool value) { return value ? "1" : "0"; }
+
+  const scoped_ptr<AbstractSocketWriter> socket_writer_;
+
+  GTEST_DISALLOW_COPY_AND_ASSIGN_(StreamingListener);
+};  // class StreamingListener
+
+#endif  // GTEST_CAN_STREAM_RESULTS_
+
+}  // namespace internal
+}  // namespace testing
+
+#endif  // GTEST_SRC_GTEST_INTERNAL_INL_H_
diff --git a/test/gtest/src/gtest-port.cc b/test/gtest/src/gtest-port.cc
new file mode 100644
index 0000000..0c4df5f
--- /dev/null
+++ b/test/gtest/src/gtest-port.cc
@@ -0,0 +1,805 @@
+// Copyright 2008, Google Inc.
+// All rights reserved.
+//
+// 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: wan at google.com (Zhanyong Wan)
+
+#include "gtest/internal/gtest-port.h"
+
+#include <limits.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+#if GTEST_OS_WINDOWS_MOBILE
+# include <windows.h>  // For TerminateProcess()
+#elif GTEST_OS_WINDOWS
+# include <io.h>
+# include <sys/stat.h>
+#else
+# include <unistd.h>
+#endif  // GTEST_OS_WINDOWS_MOBILE
+
+#if GTEST_OS_MAC
+# include <mach/mach_init.h>
+# include <mach/task.h>
+# include <mach/vm_map.h>
+#endif  // GTEST_OS_MAC
+
+#if GTEST_OS_QNX
+# include <devctl.h>
+# include <sys/procfs.h>
+#endif  // GTEST_OS_QNX
+
+#include "gtest/gtest-spi.h"
+#include "gtest/gtest-message.h"
+#include "gtest/internal/gtest-internal.h"
+#include "gtest/internal/gtest-string.h"
+
+// Indicates that this translation unit is part of Google Test's
+// implementation.  It must come before gtest-internal-inl.h is
+// included, or there will be a compiler error.  This trick is to
+// prevent a user from accidentally including gtest-internal-inl.h in
+// his code.
+#define GTEST_IMPLEMENTATION_ 1
+#include "src/gtest-internal-inl.h"
+#undef GTEST_IMPLEMENTATION_
+
+namespace testing {
+namespace internal {
+
+#if defined(_MSC_VER) || defined(__BORLANDC__)
+// MSVC and C++Builder do not provide a definition of STDERR_FILENO.
+const int kStdOutFileno = 1;
+const int kStdErrFileno = 2;
+#else
+const int kStdOutFileno = STDOUT_FILENO;
+const int kStdErrFileno = STDERR_FILENO;
+#endif  // _MSC_VER
+
+#if GTEST_OS_MAC
+
+// Returns the number of threads running in the process, or 0 to indicate that
+// we cannot detect it.
+size_t GetThreadCount() {
+  const task_t task = mach_task_self();
+  mach_msg_type_number_t thread_count;
+  thread_act_array_t thread_list;
+  const kern_return_t status = task_threads(task, &thread_list, &thread_count);
+  if (status == KERN_SUCCESS) {
+    // task_threads allocates resources in thread_list and we need to free them
+    // to avoid leaks.
+    vm_deallocate(task,
+                  reinterpret_cast<vm_address_t>(thread_list),
+                  sizeof(thread_t) * thread_count);
+    return static_cast<size_t>(thread_count);
+  } else {
+    return 0;
+  }
+}
+
+#elif GTEST_OS_QNX
+
+// Returns the number of threads running in the process, or 0 to indicate that
+// we cannot detect it.
+size_t GetThreadCount() {
+  const int fd = open("/proc/self/as", O_RDONLY);
+  if (fd < 0) {
+    return 0;
+  }
+  procfs_info process_info;
+  const int status =
+      devctl(fd, DCMD_PROC_INFO, &process_info, sizeof(process_info), NULL);
+  close(fd);
+  if (status == EOK) {
+    return static_cast<size_t>(process_info.num_threads);
+  } else {
+    return 0;
+  }
+}
+
+#else
+
+size_t GetThreadCount() {
+  // There's no portable way to detect the number of threads, so we just
+  // return 0 to indicate that we cannot detect it.
+  return 0;
+}
+
+#endif  // GTEST_OS_MAC
+
+#if GTEST_USES_POSIX_RE
+
+// Implements RE.  Currently only needed for death tests.
+
+RE::~RE() {
+  if (is_valid_) {
+    // regfree'ing an invalid regex might crash because the content
+    // of the regex is undefined. Since the regex's are essentially
+    // the same, one cannot be valid (or invalid) without the other
+    // being so too.
+    regfree(&partial_regex_);
+    regfree(&full_regex_);
+  }
+  free(const_cast<char*>(pattern_));
+}
+
+// Returns true iff regular expression re matches the entire str.
+bool RE::FullMatch(const char* str, const RE& re) {
+  if (!re.is_valid_) return false;
+
+  regmatch_t match;
+  return regexec(&re.full_regex_, str, 1, &match, 0) == 0;
+}
+
+// Returns true iff regular expression re matches a substring of str
+// (including str itself).
+bool RE::PartialMatch(const char* str, const RE& re) {
+  if (!re.is_valid_) return false;
+
+  regmatch_t match;
+  return regexec(&re.partial_regex_, str, 1, &match, 0) == 0;
+}
+
+// Initializes an RE from its string representation.
+void RE::Init(const char* regex) {
+  pattern_ = posix::StrDup(regex);
+
+  // Reserves enough bytes to hold the regular expression used for a
+  // full match.
+  const size_t full_regex_len = strlen(regex) + 10;
+  char* const full_pattern = new char[full_regex_len];
+
+  snprintf(full_pattern, full_regex_len, "^(%s)$", regex);
+  is_valid_ = regcomp(&full_regex_, full_pattern, REG_EXTENDED) == 0;
+  // We want to call regcomp(&partial_regex_, ...) even if the
+  // previous expression returns false.  Otherwise partial_regex_ may
+  // not be properly initialized can may cause trouble when it's
+  // freed.
+  //
+  // Some implementation of POSIX regex (e.g. on at least some
+  // versions of Cygwin) doesn't accept the empty string as a valid
+  // regex.  We change it to an equivalent form "()" to be safe.
+  if (is_valid_) {
+    const char* const partial_regex = (*regex == '\0') ? "()" : regex;
+    is_valid_ = regcomp(&partial_regex_, partial_regex, REG_EXTENDED) == 0;
+  }
+  EXPECT_TRUE(is_valid_)
+      << "Regular expression \"" << regex
+      << "\" is not a valid POSIX Extended regular expression.";
+
+  delete[] full_pattern;
+}
+
+#elif GTEST_USES_SIMPLE_RE
+
+// Returns true iff ch appears anywhere in str (excluding the
+// terminating '\0' character).
+bool IsInSet(char ch, const char* str) {
+  return ch != '\0' && strchr(str, ch) != NULL;
+}
+
+// Returns true iff ch belongs to the given classification.  Unlike
+// similar functions in <ctype.h>, these aren't affected by the
+// current locale.
+bool IsAsciiDigit(char ch) { return '0' <= ch && ch <= '9'; }
+bool IsAsciiPunct(char ch) {
+  return IsInSet(ch, "^-!\"#$%&'()*+,./:;<=>?@[\\]_`{|}~");
+}
+bool IsRepeat(char ch) { return IsInSet(ch, "?*+"); }
+bool IsAsciiWhiteSpace(char ch) { return IsInSet(ch, " \f\n\r\t\v"); }
+bool IsAsciiWordChar(char ch) {
+  return ('a' <= ch && ch <= 'z') || ('A' <= ch && ch <= 'Z') ||
+      ('0' <= ch && ch <= '9') || ch == '_';
+}
+
+// Returns true iff "\\c" is a supported escape sequence.
+bool IsValidEscape(char c) {
+  return (IsAsciiPunct(c) || IsInSet(c, "dDfnrsStvwW"));
+}
+
+// Returns true iff the given atom (specified by escaped and pattern)
+// matches ch.  The result is undefined if the atom is invalid.
+bool AtomMatchesChar(bool escaped, char pattern_char, char ch) {
+  if (escaped) {  // "\\p" where p is pattern_char.
+    switch (pattern_char) {
+      case 'd': return IsAsciiDigit(ch);
+      case 'D': return !IsAsciiDigit(ch);
+      case 'f': return ch == '\f';
+      case 'n': return ch == '\n';
+      case 'r': return ch == '\r';
+      case 's': return IsAsciiWhiteSpace(ch);
+      case 'S': return !IsAsciiWhiteSpace(ch);
+      case 't': return ch == '\t';
+      case 'v': return ch == '\v';
+      case 'w': return IsAsciiWordChar(ch);
+      case 'W': return !IsAsciiWordChar(ch);
+    }
+    return IsAsciiPunct(pattern_char) && pattern_char == ch;
+  }
+
+  return (pattern_char == '.' && ch != '\n') || pattern_char == ch;
+}
+
+// Helper function used by ValidateRegex() to format error messages.
+std::string FormatRegexSyntaxError(const char* regex, int index) {
+  return (Message() << "Syntax error at index " << index
+          << " in simple regular expression \"" << regex << "\": ").GetString();
+}
+
+// Generates non-fatal failures and returns false if regex is invalid;
+// otherwise returns true.
+bool ValidateRegex(const char* regex) {
+  if (regex == NULL) {
+    // TODO(wan at google.com): fix the source file location in the
+    // assertion failures to match where the regex is used in user
+    // code.
+    ADD_FAILURE() << "NULL is not a valid simple regular expression.";
+    return false;
+  }
+
+  bool is_valid = true;
+
+  // True iff ?, *, or + can follow the previous atom.
+  bool prev_repeatable = false;
+  for (int i = 0; regex[i]; i++) {
+    if (regex[i] == '\\') {  // An escape sequence
+      i++;
+      if (regex[i] == '\0') {
+        ADD_FAILURE() << FormatRegexSyntaxError(regex, i - 1)
+                      << "'\\' cannot appear at the end.";
+        return false;
+      }
+
+      if (!IsValidEscape(regex[i])) {
+        ADD_FAILURE() << FormatRegexSyntaxError(regex, i - 1)
+                      << "invalid escape sequence \"\\" << regex[i] << "\".";
+        is_valid = false;
+      }
+      prev_repeatable = true;
+    } else {  // Not an escape sequence.
+      const char ch = regex[i];
+
+      if (ch == '^' && i > 0) {
+        ADD_FAILURE() << FormatRegexSyntaxError(regex, i)
+                      << "'^' can only appear at the beginning.";
+        is_valid = false;
+      } else if (ch == '$' && regex[i + 1] != '\0') {
+        ADD_FAILURE() << FormatRegexSyntaxError(regex, i)
+                      << "'$' can only appear at the end.";
+        is_valid = false;
+      } else if (IsInSet(ch, "()[]{}|")) {
+        ADD_FAILURE() << FormatRegexSyntaxError(regex, i)
+                      << "'" << ch << "' is unsupported.";
+        is_valid = false;
+      } else if (IsRepeat(ch) && !prev_repeatable) {
+        ADD_FAILURE() << FormatRegexSyntaxError(regex, i)
+                      << "'" << ch << "' can only follow a repeatable token.";
+        is_valid = false;
+      }
+
+      prev_repeatable = !IsInSet(ch, "^$?*+");
+    }
+  }
+
+  return is_valid;
+}
+
+// Matches a repeated regex atom followed by a valid simple regular
+// expression.  The regex atom is defined as c if escaped is false,
+// or \c otherwise.  repeat is the repetition meta character (?, *,
+// or +).  The behavior is undefined if str contains too many
+// characters to be indexable by size_t, in which case the test will
+// probably time out anyway.  We are fine with this limitation as
+// std::string has it too.
+bool MatchRepetitionAndRegexAtHead(
+    bool escaped, char c, char repeat, const char* regex,
+    const char* str) {
+  const size_t min_count = (repeat == '+') ? 1 : 0;
+  const size_t max_count = (repeat == '?') ? 1 :
+      static_cast<size_t>(-1) - 1;
+  // We cannot call numeric_limits::max() as it conflicts with the
+  // max() macro on Windows.
+
+  for (size_t i = 0; i <= max_count; ++i) {
+    // We know that the atom matches each of the first i characters in str.
+    if (i >= min_count && MatchRegexAtHead(regex, str + i)) {
+      // We have enough matches at the head, and the tail matches too.
+      // Since we only care about *whether* the pattern matches str
+      // (as opposed to *how* it matches), there is no need to find a
+      // greedy match.
+      return true;
+    }
+    if (str[i] == '\0' || !AtomMatchesChar(escaped, c, str[i]))
+      return false;
+  }
+  return false;
+}
+
+// Returns true iff regex matches a prefix of str.  regex must be a
+// valid simple regular expression and not start with "^", or the
+// result is undefined.
+bool MatchRegexAtHead(const char* regex, const char* str) {
+  if (*regex == '\0')  // An empty regex matches a prefix of anything.
+    return true;
+
+  // "$" only matches the end of a string.  Note that regex being
+  // valid guarantees that there's nothing after "$" in it.
+  if (*regex == '$')
+    return *str == '\0';
+
+  // Is the first thing in regex an escape sequence?
+  const bool escaped = *regex == '\\';
+  if (escaped)
+    ++regex;
+  if (IsRepeat(regex[1])) {
+    // MatchRepetitionAndRegexAtHead() calls MatchRegexAtHead(), so
+    // here's an indirect recursion.  It terminates as the regex gets
+    // shorter in each recursion.
+    return MatchRepetitionAndRegexAtHead(
+        escaped, regex[0], regex[1], regex + 2, str);
+  } else {
+    // regex isn't empty, isn't "$", and doesn't start with a
+    // repetition.  We match the first atom of regex with the first
+    // character of str and recurse.
+    return (*str != '\0') && AtomMatchesChar(escaped, *regex, *str) &&
+        MatchRegexAtHead(regex + 1, str + 1);
+  }
+}
+
+// Returns true iff regex matches any substring of str.  regex must be
+// a valid simple regular expression, or the result is undefined.
+//
+// The algorithm is recursive, but the recursion depth doesn't exceed
+// the regex length, so we won't need to worry about running out of
+// stack space normally.  In rare cases the time complexity can be
+// exponential with respect to the regex length + the string length,
+// but usually it's must faster (often close to linear).
+bool MatchRegexAnywhere(const char* regex, const char* str) {
+  if (regex == NULL || str == NULL)
+    return false;
+
+  if (*regex == '^')
+    return MatchRegexAtHead(regex + 1, str);
+
+  // A successful match can be anywhere in str.
+  do {
+    if (MatchRegexAtHead(regex, str))
+      return true;
+  } while (*str++ != '\0');
+  return false;
+}
+
+// Implements the RE class.
+
+RE::~RE() {
+  free(const_cast<char*>(pattern_));
+  free(const_cast<char*>(full_pattern_));
+}
+
+// Returns true iff regular expression re matches the entire str.
+bool RE::FullMatch(const char* str, const RE& re) {
+  return re.is_valid_ && MatchRegexAnywhere(re.full_pattern_, str);
+}
+
+// Returns true iff regular expression re matches a substring of str
+// (including str itself).
+bool RE::PartialMatch(const char* str, const RE& re) {
+  return re.is_valid_ && MatchRegexAnywhere(re.pattern_, str);
+}
+
+// Initializes an RE from its string representation.
+void RE::Init(const char* regex) {
+  pattern_ = full_pattern_ = NULL;
+  if (regex != NULL) {
+    pattern_ = posix::StrDup(regex);
+  }
+
+  is_valid_ = ValidateRegex(regex);
+  if (!is_valid_) {
+    // No need to calculate the full pattern when the regex is invalid.
+    return;
+  }
+
+  const size_t len = strlen(regex);
+  // Reserves enough bytes to hold the regular expression used for a
+  // full match: we need space to prepend a '^', append a '$', and
+  // terminate the string with '\0'.
+  char* buffer = static_cast<char*>(malloc(len + 3));
+  full_pattern_ = buffer;
+
+  if (*regex != '^')
+    *buffer++ = '^';  // Makes sure full_pattern_ starts with '^'.
+
+  // We don't use snprintf or strncpy, as they trigger a warning when
+  // compiled with VC++ 8.0.
+  memcpy(buffer, regex, len);
+  buffer += len;
+
+  if (len == 0 || regex[len - 1] != '$')
+    *buffer++ = '$';  // Makes sure full_pattern_ ends with '$'.
+
+  *buffer = '\0';
+}
+
+#endif  // GTEST_USES_POSIX_RE
+
+const char kUnknownFile[] = "unknown file";
+
+// Formats a source file path and a line number as they would appear
+// in an error message from the compiler used to compile this code.
+GTEST_API_ ::std::string FormatFileLocation(const char* file, int line) {
+  const std::string file_name(file == NULL ? kUnknownFile : file);
+
+  if (line < 0) {
+    return file_name + ":";
+  }
+#ifdef _MSC_VER
+  return file_name + "(" + StreamableToString(line) + "):";
+#else
+  return file_name + ":" + StreamableToString(line) + ":";
+#endif  // _MSC_VER
+}
+
+// Formats a file location for compiler-independent XML output.
+// Although this function is not platform dependent, we put it next to
+// FormatFileLocation in order to contrast the two functions.
+// Note that FormatCompilerIndependentFileLocation() does NOT append colon
+// to the file location it produces, unlike FormatFileLocation().
+GTEST_API_ ::std::string FormatCompilerIndependentFileLocation(
+    const char* file, int line) {
+  const std::string file_name(file == NULL ? kUnknownFile : file);
+
+  if (line < 0)
+    return file_name;
+  else
+    return file_name + ":" + StreamableToString(line);
+}
+
+
+GTestLog::GTestLog(GTestLogSeverity severity, const char* file, int line)
+    : severity_(severity) {
+  const char* const marker =
+      severity == GTEST_INFO ?    "[  INFO ]" :
+      severity == GTEST_WARNING ? "[WARNING]" :
+      severity == GTEST_ERROR ?   "[ ERROR ]" : "[ FATAL ]";
+  GetStream() << ::std::endl << marker << " "
+              << FormatFileLocation(file, line).c_str() << ": ";
+}
+
+// Flushes the buffers and, if severity is GTEST_FATAL, aborts the program.
+GTestLog::~GTestLog() {
+  GetStream() << ::std::endl;
+  if (severity_ == GTEST_FATAL) {
+    fflush(stderr);
+    posix::Abort();
+  }
+}
+// Disable Microsoft deprecation warnings for POSIX functions called from
+// this class (creat, dup, dup2, and close)
+#ifdef _MSC_VER
+# pragma warning(push)
+# pragma warning(disable: 4996)
+#endif  // _MSC_VER
+
+#if GTEST_HAS_STREAM_REDIRECTION
+
+// Object that captures an output stream (stdout/stderr).
+class CapturedStream {
+ public:
+  // The ctor redirects the stream to a temporary file.
+  explicit CapturedStream(int fd) : fd_(fd), uncaptured_fd_(dup(fd)) {
+# if GTEST_OS_WINDOWS
+    char temp_dir_path[MAX_PATH + 1] = { '\0' };  // NOLINT
+    char temp_file_path[MAX_PATH + 1] = { '\0' };  // NOLINT
+
+    ::GetTempPathA(sizeof(temp_dir_path), temp_dir_path);
+    const UINT success = ::GetTempFileNameA(temp_dir_path,
+                                            "gtest_redir",
+                                            0,  // Generate unique file name.
+                                            temp_file_path);
+    GTEST_CHECK_(success != 0)
+        << "Unable to create a temporary file in " << temp_dir_path;
+    const int captured_fd = creat(temp_file_path, _S_IREAD | _S_IWRITE);
+    GTEST_CHECK_(captured_fd != -1) << "Unable to open temporary file "
+                                    << temp_file_path;
+    filename_ = temp_file_path;
+# else
+    // There's no guarantee that a test has write access to the current
+    // directory, so we create the temporary file in the /tmp directory
+    // instead. We use /tmp on most systems, and /sdcard on Android.
+    // That's because Android doesn't have /tmp.
+#  if GTEST_OS_LINUX_ANDROID
+    // Note: Android applications are expected to call the framework's
+    // Context.getExternalStorageDirectory() method through JNI to get
+    // the location of the world-writable SD Card directory. However,
+    // this requires a Context handle, which cannot be retrieved
+    // globally from native code. Doing so also precludes running the
+    // code as part of a regular standalone executable, which doesn't
+    // run in a Dalvik process (e.g. when running it through 'adb shell').
+    //
+    // The location /sdcard is directly accessible from native code
+    // and is the only location (unofficially) supported by the Android
+    // team. It's generally a symlink to the real SD Card mount point
+    // which can be /mnt/sdcard, /mnt/sdcard0, /system/media/sdcard, or
+    // other OEM-customized locations. Never rely on these, and always
+    // use /sdcard.
+    char name_template[] = "/sdcard/gtest_captured_stream.XXXXXX";
+#  else
+    char name_template[] = "/tmp/captured_stream.XXXXXX";
+#  endif  // GTEST_OS_LINUX_ANDROID
+    const int captured_fd = mkstemp(name_template);
+    filename_ = name_template;
+# endif  // GTEST_OS_WINDOWS
+    fflush(NULL);
+    dup2(captured_fd, fd_);
+    close(captured_fd);
+  }
+
+  ~CapturedStream() {
+    remove(filename_.c_str());
+  }
+
+  std::string GetCapturedString() {
+    if (uncaptured_fd_ != -1) {
+      // Restores the original stream.
+      fflush(NULL);
+      dup2(uncaptured_fd_, fd_);
+      close(uncaptured_fd_);
+      uncaptured_fd_ = -1;
+    }
+
+    FILE* const file = posix::FOpen(filename_.c_str(), "r");
+    const std::string content = ReadEntireFile(file);
+    posix::FClose(file);
+    return content;
+  }
+
+ private:
+  // Reads the entire content of a file as an std::string.
+  static std::string ReadEntireFile(FILE* file);
+
+  // Returns the size (in bytes) of a file.
+  static size_t GetFileSize(FILE* file);
+
+  const int fd_;  // A stream to capture.
+  int uncaptured_fd_;
+  // Name of the temporary file holding the stderr output.
+  ::std::string filename_;
+
+  GTEST_DISALLOW_COPY_AND_ASSIGN_(CapturedStream);
+};
+
+// Returns the size (in bytes) of a file.
+size_t CapturedStream::GetFileSize(FILE* file) {
+  fseek(file, 0, SEEK_END);
+  return static_cast<size_t>(ftell(file));
+}
+
+// Reads the entire content of a file as a string.
+std::string CapturedStream::ReadEntireFile(FILE* file) {
+  const size_t file_size = GetFileSize(file);
+  char* const buffer = new char[file_size];
+
+  size_t bytes_last_read = 0;  // # of bytes read in the last fread()
+  size_t bytes_read = 0;       // # of bytes read so far
+
+  fseek(file, 0, SEEK_SET);
+
+  // Keeps reading the file until we cannot read further or the
+  // pre-determined file size is reached.
+  do {
+    bytes_last_read = fread(buffer+bytes_read, 1, file_size-bytes_read, file);
+    bytes_read += bytes_last_read;
+  } while (bytes_last_read > 0 && bytes_read < file_size);
+
+  const std::string content(buffer, bytes_read);
+  delete[] buffer;
+
+  return content;
+}
+
+# ifdef _MSC_VER
+#  pragma warning(pop)
+# endif  // _MSC_VER
+
+static CapturedStream* g_captured_stderr = NULL;
+static CapturedStream* g_captured_stdout = NULL;
+
+// Starts capturing an output stream (stdout/stderr).
+void CaptureStream(int fd, const char* stream_name, CapturedStream** stream) {
+  if (*stream != NULL) {
+    GTEST_LOG_(FATAL) << "Only one " << stream_name
+                      << " capturer can exist at a time.";
+  }
+  *stream = new CapturedStream(fd);
+}
+
+// Stops capturing the output stream and returns the captured string.
+std::string GetCapturedStream(CapturedStream** captured_stream) {
+  const std::string content = (*captured_stream)->GetCapturedString();
+
+  delete *captured_stream;
+  *captured_stream = NULL;
+
+  return content;
+}
+
+// Starts capturing stdout.
+void CaptureStdout() {
+  CaptureStream(kStdOutFileno, "stdout", &g_captured_stdout);
+}
+
+// Starts capturing stderr.
+void CaptureStderr() {
+  CaptureStream(kStdErrFileno, "stderr", &g_captured_stderr);
+}
+
+// Stops capturing stdout and returns the captured string.
+std::string GetCapturedStdout() {
+  return GetCapturedStream(&g_captured_stdout);
+}
+
+// Stops capturing stderr and returns the captured string.
+std::string GetCapturedStderr() {
+  return GetCapturedStream(&g_captured_stderr);
+}
+
+#endif  // GTEST_HAS_STREAM_REDIRECTION
+
+#if GTEST_HAS_DEATH_TEST
+
+// A copy of all command line arguments.  Set by InitGoogleTest().
+::std::vector<testing::internal::string> g_argvs;
+
+static const ::std::vector<testing::internal::string>* g_injected_test_argvs =
+                                        NULL;  // Owned.
+
+void SetInjectableArgvs(const ::std::vector<testing::internal::string>* argvs) {
+  if (g_injected_test_argvs != argvs)
+    delete g_injected_test_argvs;
+  g_injected_test_argvs = argvs;
+}
+
+const ::std::vector<testing::internal::string>& GetInjectableArgvs() {
+  if (g_injected_test_argvs != NULL) {
+    return *g_injected_test_argvs;
+  }
+  return g_argvs;
+}
+#endif  // GTEST_HAS_DEATH_TEST
+
+#if GTEST_OS_WINDOWS_MOBILE
+namespace posix {
+void Abort() {
+  DebugBreak();
+  TerminateProcess(GetCurrentProcess(), 1);
+}
+}  // namespace posix
+#endif  // GTEST_OS_WINDOWS_MOBILE
+
+// Returns the name of the environment variable corresponding to the
+// given flag.  For example, FlagToEnvVar("foo") will return
+// "GTEST_FOO" in the open-source version.
+static std::string FlagToEnvVar(const char* flag) {
+  const std::string full_flag =
+      (Message() << GTEST_FLAG_PREFIX_ << flag).GetString();
+
+  Message env_var;
+  for (size_t i = 0; i != full_flag.length(); i++) {
+    env_var << ToUpper(full_flag.c_str()[i]);
+  }
+
+  return env_var.GetString();
+}
+
+// Parses 'str' for a 32-bit signed integer.  If successful, writes
+// the result to *value and returns true; otherwise leaves *value
+// unchanged and returns false.
+bool ParseInt32(const Message& src_text, const char* str, Int32* value) {
+  // Parses the environment variable as a decimal integer.
+  char* end = NULL;
+  const long long_value = strtol(str, &end, 10);  // NOLINT
+
+  // Has strtol() consumed all characters in the string?
+  if (*end != '\0') {
+    // No - an invalid character was encountered.
+    Message msg;
+    msg << "WARNING: " << src_text
+        << " is expected to be a 32-bit integer, but actually"
+        << " has value \"" << str << "\".\n";
+    printf("%s", msg.GetString().c_str());
+    fflush(stdout);
+    return false;
+  }
+
+  // Is the parsed value in the range of an Int32?
+  const Int32 result = static_cast<Int32>(long_value);
+  if (long_value == LONG_MAX || long_value == LONG_MIN ||
+      // The parsed value overflows as a long.  (strtol() returns
+      // LONG_MAX or LONG_MIN when the input overflows.)
+      result != long_value
+      // The parsed value overflows as an Int32.
+      ) {
+    Message msg;
+    msg << "WARNING: " << src_text
+        << " is expected to be a 32-bit integer, but actually"
+        << " has value " << str << ", which overflows.\n";
+    printf("%s", msg.GetString().c_str());
+    fflush(stdout);
+    return false;
+  }
+
+  *value = result;
+  return true;
+}
+
+// Reads and returns the Boolean environment variable corresponding to
+// the given flag; if it's not set, returns default_value.
+//
+// The value is considered true iff it's not "0".
+bool BoolFromGTestEnv(const char* flag, bool default_value) {
+  const std::string env_var = FlagToEnvVar(flag);
+  const char* const string_value = posix::GetEnv(env_var.c_str());
+  return string_value == NULL ?
+      default_value : strcmp(string_value, "0") != 0;
+}
+
+// Reads and returns a 32-bit integer stored in the environment
+// variable corresponding to the given flag; if it isn't set or
+// doesn't represent a valid 32-bit integer, returns default_value.
+Int32 Int32FromGTestEnv(const char* flag, Int32 default_value) {
+  const std::string env_var = FlagToEnvVar(flag);
+  const char* const string_value = posix::GetEnv(env_var.c_str());
+  if (string_value == NULL) {
+    // The environment variable is not set.
+    return default_value;
+  }
+
+  Int32 result = default_value;
+  if (!ParseInt32(Message() << "Environment variable " << env_var,
+                  string_value, &result)) {
+    printf("The default value %s is used.\n",
+           (Message() << default_value).GetString().c_str());
+    fflush(stdout);
+    return default_value;
+  }
+
+  return result;
+}
+
+// Reads and returns the string environment variable corresponding to
+// the given flag; if it's not set, returns default_value.
+const char* StringFromGTestEnv(const char* flag, const char* default_value) {
+  const std::string env_var = FlagToEnvVar(flag);
+  const char* const value = posix::GetEnv(env_var.c_str());
+  return value == NULL ? default_value : value;
+}
+
+}  // namespace internal
+}  // namespace testing
diff --git a/test/gtest/src/gtest-printers.cc b/test/gtest/src/gtest-printers.cc
new file mode 100644
index 0000000..75fa408
--- /dev/null
+++ b/test/gtest/src/gtest-printers.cc
@@ -0,0 +1,363 @@
+// Copyright 2007, Google Inc.
+// All rights reserved.
+//
+// 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: wan at google.com (Zhanyong Wan)
+
+// Google Test - The Google C++ Testing Framework
+//
+// This file implements a universal value printer that can print a
+// value of any type T:
+//
+//   void ::testing::internal::UniversalPrinter<T>::Print(value, ostream_ptr);
+//
+// It uses the << operator when possible, and prints the bytes in the
+// object otherwise.  A user can override its behavior for a class
+// type Foo by defining either operator<<(::std::ostream&, const Foo&)
+// or void PrintTo(const Foo&, ::std::ostream*) in the namespace that
+// defines Foo.
+
+#include "gtest/gtest-printers.h"
+#include <ctype.h>
+#include <stdio.h>
+#include <ostream>  // NOLINT
+#include <string>
+#include "gtest/internal/gtest-port.h"
+
+namespace testing {
+
+namespace {
+
+using ::std::ostream;
+
+// Prints a segment of bytes in the given object.
+void PrintByteSegmentInObjectTo(const unsigned char* obj_bytes, size_t start,
+                                size_t count, ostream* os) {
+  char text[5] = "";
+  for (size_t i = 0; i != count; i++) {
+    const size_t j = start + i;
+    if (i != 0) {
+      // Organizes the bytes into groups of 2 for easy parsing by
+      // human.
+      if ((j % 2) == 0)
+        *os << ' ';
+      else
+        *os << '-';
+    }
+    GTEST_SNPRINTF_(text, sizeof(text), "%02X", obj_bytes[j]);
+    *os << text;
+  }
+}
+
+// Prints the bytes in the given value to the given ostream.
+void PrintBytesInObjectToImpl(const unsigned char* obj_bytes, size_t count,
+                              ostream* os) {
+  // Tells the user how big the object is.
+  *os << count << "-byte object <";
+
+  const size_t kThreshold = 132;
+  const size_t kChunkSize = 64;
+  // If the object size is bigger than kThreshold, we'll have to omit
+  // some details by printing only the first and the last kChunkSize
+  // bytes.
+  // TODO(wan): let the user control the threshold using a flag.
+  if (count < kThreshold) {
+    PrintByteSegmentInObjectTo(obj_bytes, 0, count, os);
+  } else {
+    PrintByteSegmentInObjectTo(obj_bytes, 0, kChunkSize, os);
+    *os << " ... ";
+    // Rounds up to 2-byte boundary.
+    const size_t resume_pos = (count - kChunkSize + 1)/2*2;
+    PrintByteSegmentInObjectTo(obj_bytes, resume_pos, count - resume_pos, os);
+  }
+  *os << ">";
+}
+
+}  // namespace
+
+namespace internal2 {
+
+// Delegates to PrintBytesInObjectToImpl() to print the bytes in the
+// given object.  The delegation simplifies the implementation, which
+// uses the << operator and thus is easier done outside of the
+// ::testing::internal namespace, which contains a << operator that
+// sometimes conflicts with the one in STL.
+void PrintBytesInObjectTo(const unsigned char* obj_bytes, size_t count,
+                          ostream* os) {
+  PrintBytesInObjectToImpl(obj_bytes, count, os);
+}
+
+}  // namespace internal2
+
+namespace internal {
+
+// Depending on the value of a char (or wchar_t), we print it in one
+// of three formats:
+//   - as is if it's a printable ASCII (e.g. 'a', '2', ' '),
+//   - as a hexidecimal escape sequence (e.g. '\x7F'), or
+//   - as a special escape sequence (e.g. '\r', '\n').
+enum CharFormat {
+  kAsIs,
+  kHexEscape,
+  kSpecialEscape
+};
+
+// Returns true if c is a printable ASCII character.  We test the
+// value of c directly instead of calling isprint(), which is buggy on
+// Windows Mobile.
+inline bool IsPrintableAscii(wchar_t c) {
+  return 0x20 <= c && c <= 0x7E;
+}
+
+// Prints a wide or narrow char c as a character literal without the
+// quotes, escaping it when necessary; returns how c was formatted.
+// The template argument UnsignedChar is the unsigned version of Char,
+// which is the type of c.
+template <typename UnsignedChar, typename Char>
+static CharFormat PrintAsCharLiteralTo(Char c, ostream* os) {
+  switch (static_cast<wchar_t>(c)) {
+    case L'\0':
+      *os << "\\0";
+      break;
+    case L'\'':
+      *os << "\\'";
+      break;
+    case L'\\':
+      *os << "\\\\";
+      break;
+    case L'\a':
+      *os << "\\a";
+      break;
+    case L'\b':
+      *os << "\\b";
+      break;
+    case L'\f':
+      *os << "\\f";
+      break;
+    case L'\n':
+      *os << "\\n";
+      break;
+    case L'\r':
+      *os << "\\r";
+      break;
+    case L'\t':
+      *os << "\\t";
+      break;
+    case L'\v':
+      *os << "\\v";
+      break;
+    default:
+      if (IsPrintableAscii(c)) {
+        *os << static_cast<char>(c);
+        return kAsIs;
+      } else {
+        *os << "\\x" + String::FormatHexInt(static_cast<UnsignedChar>(c));
+        return kHexEscape;
+      }
+  }
+  return kSpecialEscape;
+}
+
+// Prints a wchar_t c as if it's part of a string literal, escaping it when
+// necessary; returns how c was formatted.
+static CharFormat PrintAsStringLiteralTo(wchar_t c, ostream* os) {
+  switch (c) {
+    case L'\'':
+      *os << "'";
+      return kAsIs;
+    case L'"':
+      *os << "\\\"";
+      return kSpecialEscape;
+    default:
+      return PrintAsCharLiteralTo<wchar_t>(c, os);
+  }
+}
+
+// Prints a char c as if it's part of a string literal, escaping it when
+// necessary; returns how c was formatted.
+static CharFormat PrintAsStringLiteralTo(char c, ostream* os) {
+  return PrintAsStringLiteralTo(
+      static_cast<wchar_t>(static_cast<unsigned char>(c)), os);
+}
+
+// Prints a wide or narrow character c and its code.  '\0' is printed
+// as "'\\0'", other unprintable characters are also properly escaped
+// using the standard C++ escape sequence.  The template argument
+// UnsignedChar is the unsigned version of Char, which is the type of c.
+template <typename UnsignedChar, typename Char>
+void PrintCharAndCodeTo(Char c, ostream* os) {
+  // First, print c as a literal in the most readable form we can find.
+  *os << ((sizeof(c) > 1) ? "L'" : "'");
+  const CharFormat format = PrintAsCharLiteralTo<UnsignedChar>(c, os);
+  *os << "'";
+
+  // To aid user debugging, we also print c's code in decimal, unless
+  // it's 0 (in which case c was printed as '\\0', making the code
+  // obvious).
+  if (c == 0)
+    return;
+  *os << " (" << static_cast<int>(c);
+
+  // For more convenience, we print c's code again in hexidecimal,
+  // unless c was already printed in the form '\x##' or the code is in
+  // [1, 9].
+  if (format == kHexEscape || (1 <= c && c <= 9)) {
+    // Do nothing.
+  } else {
+    *os << ", 0x" << String::FormatHexInt(static_cast<UnsignedChar>(c));
+  }
+  *os << ")";
+}
+
+void PrintTo(unsigned char c, ::std::ostream* os) {
+  PrintCharAndCodeTo<unsigned char>(c, os);
+}
+void PrintTo(signed char c, ::std::ostream* os) {
+  PrintCharAndCodeTo<unsigned char>(c, os);
+}
+
+// Prints a wchar_t as a symbol if it is printable or as its internal
+// code otherwise and also as its code.  L'\0' is printed as "L'\\0'".
+void PrintTo(wchar_t wc, ostream* os) {
+  PrintCharAndCodeTo<wchar_t>(wc, os);
+}
+
+// Prints the given array of characters to the ostream.  CharType must be either
+// char or wchar_t.
+// The array starts at begin, the length is len, it may include '\0' characters
+// and may not be NUL-terminated.
+template <typename CharType>
+static void PrintCharsAsStringTo(
+    const CharType* begin, size_t len, ostream* os) {
+  const char* const kQuoteBegin = sizeof(CharType) == 1 ? "\"" : "L\"";
+  *os << kQuoteBegin;
+  bool is_previous_hex = false;
+  for (size_t index = 0; index < len; ++index) {
+    const CharType cur = begin[index];
+    if (is_previous_hex && IsXDigit(cur)) {
+      // Previous character is of '\x..' form and this character can be
+      // interpreted as another hexadecimal digit in its number. Break string to
+      // disambiguate.
+      *os << "\" " << kQuoteBegin;
+    }
+    is_previous_hex = PrintAsStringLiteralTo(cur, os) == kHexEscape;
+  }
+  *os << "\"";
+}
+
+// Prints a (const) char/wchar_t array of 'len' elements, starting at address
+// 'begin'.  CharType must be either char or wchar_t.
+template <typename CharType>
+static void UniversalPrintCharArray(
+    const CharType* begin, size_t len, ostream* os) {
+  // The code
+  //   const char kFoo[] = "foo";
+  // generates an array of 4, not 3, elements, with the last one being '\0'.
+  //
+  // Therefore when printing a char array, we don't print the last element if
+  // it's '\0', such that the output matches the string literal as it's
+  // written in the source code.
+  if (len > 0 && begin[len - 1] == '\0') {
+    PrintCharsAsStringTo(begin, len - 1, os);
+    return;
+  }
+
+  // If, however, the last element in the array is not '\0', e.g.
+  //    const char kFoo[] = { 'f', 'o', 'o' };
+  // we must print the entire array.  We also print a message to indicate
+  // that the array is not NUL-terminated.
+  PrintCharsAsStringTo(begin, len, os);
+  *os << " (no terminating NUL)";
+}
+
+// Prints a (const) char array of 'len' elements, starting at address 'begin'.
+void UniversalPrintArray(const char* begin, size_t len, ostream* os) {
+  UniversalPrintCharArray(begin, len, os);
+}
+
+// Prints a (const) wchar_t array of 'len' elements, starting at address
+// 'begin'.
+void UniversalPrintArray(const wchar_t* begin, size_t len, ostream* os) {
+  UniversalPrintCharArray(begin, len, os);
+}
+
+// Prints the given C string to the ostream.
+void PrintTo(const char* s, ostream* os) {
+  if (s == NULL) {
+    *os << "NULL";
+  } else {
+    *os << ImplicitCast_<const void*>(s) << " pointing to ";
+    PrintCharsAsStringTo(s, strlen(s), os);
+  }
+}
+
+// MSVC compiler can be configured to define whar_t as a typedef
+// of unsigned short. Defining an overload for const wchar_t* in that case
+// would cause pointers to unsigned shorts be printed as wide strings,
+// possibly accessing more memory than intended and causing invalid
+// memory accesses. MSVC defines _NATIVE_WCHAR_T_DEFINED symbol when
+// wchar_t is implemented as a native type.
+#if !defined(_MSC_VER) || defined(_NATIVE_WCHAR_T_DEFINED)
+// Prints the given wide C string to the ostream.
+void PrintTo(const wchar_t* s, ostream* os) {
+  if (s == NULL) {
+    *os << "NULL";
+  } else {
+    *os << ImplicitCast_<const void*>(s) << " pointing to ";
+    PrintCharsAsStringTo(s, wcslen(s), os);
+  }
+}
+#endif  // wchar_t is native
+
+// Prints a ::string object.
+#if GTEST_HAS_GLOBAL_STRING
+void PrintStringTo(const ::string& s, ostream* os) {
+  PrintCharsAsStringTo(s.data(), s.size(), os);
+}
+#endif  // GTEST_HAS_GLOBAL_STRING
+
+void PrintStringTo(const ::std::string& s, ostream* os) {
+  PrintCharsAsStringTo(s.data(), s.size(), os);
+}
+
+// Prints a ::wstring object.
+#if GTEST_HAS_GLOBAL_WSTRING
+void PrintWideStringTo(const ::wstring& s, ostream* os) {
+  PrintCharsAsStringTo(s.data(), s.size(), os);
+}
+#endif  // GTEST_HAS_GLOBAL_WSTRING
+
+#if GTEST_HAS_STD_WSTRING
+void PrintWideStringTo(const ::std::wstring& s, ostream* os) {
+  PrintCharsAsStringTo(s.data(), s.size(), os);
+}
+#endif  // GTEST_HAS_STD_WSTRING
+
+}  // namespace internal
+
+}  // namespace testing
diff --git a/test/gtest/src/gtest-test-part.cc b/test/gtest/src/gtest-test-part.cc
new file mode 100644
index 0000000..c60eef3
--- /dev/null
+++ b/test/gtest/src/gtest-test-part.cc
@@ -0,0 +1,110 @@
+// Copyright 2008, Google Inc.
+// All rights reserved.
+//
+// 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: mheule at google.com (Markus Heule)
+//
+// The Google C++ Testing Framework (Google Test)
+
+#include "gtest/gtest-test-part.h"
+
+// Indicates that this translation unit is part of Google Test's
+// implementation.  It must come before gtest-internal-inl.h is
+// included, or there will be a compiler error.  This trick is to
+// prevent a user from accidentally including gtest-internal-inl.h in
+// his code.
+#define GTEST_IMPLEMENTATION_ 1
+#include "src/gtest-internal-inl.h"
+#undef GTEST_IMPLEMENTATION_
+
+namespace testing {
+
+using internal::GetUnitTestImpl;
+
+// Gets the summary of the failure message by omitting the stack trace
+// in it.
+std::string TestPartResult::ExtractSummary(const char* message) {
+  const char* const stack_trace = strstr(message, internal::kStackTraceMarker);
+  return stack_trace == NULL ? message :
+      std::string(message, stack_trace);
+}
+
+// Prints a TestPartResult object.
+std::ostream& operator<<(std::ostream& os, const TestPartResult& result) {
+  return os
+      << result.file_name() << ":" << result.line_number() << ": "
+      << (result.type() == TestPartResult::kSuccess ? "Success" :
+          result.type() == TestPartResult::kFatalFailure ? "Fatal failure" :
+          "Non-fatal failure") << ":\n"
+      << result.message() << std::endl;
+}
+
+// Appends a TestPartResult to the array.
+void TestPartResultArray::Append(const TestPartResult& result) {
+  array_.push_back(result);
+}
+
+// Returns the TestPartResult at the given index (0-based).
+const TestPartResult& TestPartResultArray::GetTestPartResult(int index) const {
+  if (index < 0 || index >= size()) {
+    printf("\nInvalid index (%d) into TestPartResultArray.\n", index);
+    internal::posix::Abort();
+  }
+
+  return array_[index];
+}
+
+// Returns the number of TestPartResult objects in the array.
+int TestPartResultArray::size() const {
+  return static_cast<int>(array_.size());
+}
+
+namespace internal {
+
+HasNewFatalFailureHelper::HasNewFatalFailureHelper()
+    : has_new_fatal_failure_(false),
+      original_reporter_(GetUnitTestImpl()->
+                         GetTestPartResultReporterForCurrentThread()) {
+  GetUnitTestImpl()->SetTestPartResultReporterForCurrentThread(this);
+}
+
+HasNewFatalFailureHelper::~HasNewFatalFailureHelper() {
+  GetUnitTestImpl()->SetTestPartResultReporterForCurrentThread(
+      original_reporter_);
+}
+
+void HasNewFatalFailureHelper::ReportTestPartResult(
+    const TestPartResult& result) {
+  if (result.fatally_failed())
+    has_new_fatal_failure_ = true;
+  original_reporter_->ReportTestPartResult(result);
+}
+
+}  // namespace internal
+
+}  // namespace testing
diff --git a/test/gtest/src/gtest-typed-test.cc b/test/gtest/src/gtest-typed-test.cc
new file mode 100644
index 0000000..f0079f4
--- /dev/null
+++ b/test/gtest/src/gtest-typed-test.cc
@@ -0,0 +1,110 @@
+// Copyright 2008 Google Inc.
+// All Rights Reserved.
+//
+// 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: wan at google.com (Zhanyong Wan)
+
+#include "gtest/gtest-typed-test.h"
+#include "gtest/gtest.h"
+
+namespace testing {
+namespace internal {
+
+#if GTEST_HAS_TYPED_TEST_P
+
+// Skips to the first non-space char in str. Returns an empty string if str
+// contains only whitespace characters.
+static const char* SkipSpaces(const char* str) {
+  while (IsSpace(*str))
+    str++;
+  return str;
+}
+
+// Verifies that registered_tests match the test names in
+// defined_test_names_; returns registered_tests if successful, or
+// aborts the program otherwise.
+const char* TypedTestCasePState::VerifyRegisteredTestNames(
+    const char* file, int line, const char* registered_tests) {
+  typedef ::std::set<const char*>::const_iterator DefinedTestIter;
+  registered_ = true;
+
+  // Skip initial whitespace in registered_tests since some
+  // preprocessors prefix stringizied literals with whitespace.
+  registered_tests = SkipSpaces(registered_tests);
+
+  Message errors;
+  ::std::set<std::string> tests;
+  for (const char* names = registered_tests; names != NULL;
+       names = SkipComma(names)) {
+    const std::string name = GetPrefixUntilComma(names);
+    if (tests.count(name) != 0) {
+      errors << "Test " << name << " is listed more than once.\n";
+      continue;
+    }
+
+    bool found = false;
+    for (DefinedTestIter it = defined_test_names_.begin();
+         it != defined_test_names_.end();
+         ++it) {
+      if (name == *it) {
+        found = true;
+        break;
+      }
+    }
+
+    if (found) {
+      tests.insert(name);
+    } else {
+      errors << "No test named " << name
+             << " can be found in this test case.\n";
+    }
+  }
+
+  for (DefinedTestIter it = defined_test_names_.begin();
+       it != defined_test_names_.end();
+       ++it) {
+    if (tests.count(*it) == 0) {
+      errors << "You forgot to list test " << *it << ".\n";
+    }
+  }
+
+  const std::string& errors_str = errors.GetString();
+  if (errors_str != "") {
+    fprintf(stderr, "%s %s", FormatFileLocation(file, line).c_str(),
+            errors_str.c_str());
+    fflush(stderr);
+    posix::Abort();
+  }
+
+  return registered_tests;
+}
+
+#endif  // GTEST_HAS_TYPED_TEST_P
+
+}  // namespace internal
+}  // namespace testing
diff --git a/test/gtest/src/gtest.cc b/test/gtest/src/gtest.cc
new file mode 100644
index 0000000..2ab80e2
--- /dev/null
+++ b/test/gtest/src/gtest.cc
@@ -0,0 +1,5019 @@
+// Copyright 2005, Google Inc.
+// All rights reserved.
+//
+// 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: wan at google.com (Zhanyong Wan)
+//
+// The Google C++ Testing Framework (Google Test)
+
+#include "gtest/gtest.h"
+#include "gtest/gtest-spi.h"
+
+#ifndef _WIN32
+#pragma GCC system_header
+#endif
+
+#include <ctype.h>
+#include <math.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <time.h>
+#include <wchar.h>
+#include <wctype.h>
+
+#include <algorithm>
+#include <iomanip>
+#include <limits>
+#include <ostream>  // NOLINT
+#include <sstream>
+#include <vector>
+
+#if GTEST_OS_LINUX
+
+// TODO(kenton at google.com): Use autoconf to detect availability of
+// gettimeofday().
+# define GTEST_HAS_GETTIMEOFDAY_ 1
+
+# include <fcntl.h>  // NOLINT
+# include <limits.h>  // NOLINT
+# include <sched.h>  // NOLINT
+// Declares vsnprintf().  This header is not available on Windows.
+# include <strings.h>  // NOLINT
+# include <sys/mman.h>  // NOLINT
+# include <sys/time.h>  // NOLINT
+# include <unistd.h>  // NOLINT
+# include <string>
+
+#elif GTEST_OS_SYMBIAN
+# define GTEST_HAS_GETTIMEOFDAY_ 1
+# include <sys/time.h>  // NOLINT
+
+#elif GTEST_OS_ZOS
+# define GTEST_HAS_GETTIMEOFDAY_ 1
+# include <sys/time.h>  // NOLINT
+
+// On z/OS we additionally need strings.h for strcasecmp.
+# include <strings.h>  // NOLINT
+
+#elif GTEST_OS_WINDOWS_MOBILE  // We are on Windows CE.
+
+# include <windows.h>  // NOLINT
+
+#elif GTEST_OS_WINDOWS  // We are on Windows proper.
+
+# include <io.h>  // NOLINT
+# include <sys/timeb.h>  // NOLINT
+# include <sys/types.h>  // NOLINT
+# include <sys/stat.h>  // NOLINT
+
+# if GTEST_OS_WINDOWS_MINGW
+// MinGW has gettimeofday() but not _ftime64().
+// TODO(kenton at google.com): Use autoconf to detect availability of
+//   gettimeofday().
+// TODO(kenton at google.com): There are other ways to get the time on
+//   Windows, like GetTickCount() or GetSystemTimeAsFileTime().  MinGW
+//   supports these.  consider using them instead.
+#  define GTEST_HAS_GETTIMEOFDAY_ 1
+#  include <sys/time.h>  // NOLINT
+# endif  // GTEST_OS_WINDOWS_MINGW
+
+// cpplint thinks that the header is already included, so we want to
+// silence it.
+# include <windows.h>  // NOLINT
+
+#else
+
+// Assume other platforms have gettimeofday().
+// TODO(kenton at google.com): Use autoconf to detect availability of
+//   gettimeofday().
+# define GTEST_HAS_GETTIMEOFDAY_ 1
+
+// cpplint thinks that the header is already included, so we want to
+// silence it.
+# include <sys/time.h>  // NOLINT
+# include <unistd.h>  // NOLINT
+
+#endif  // GTEST_OS_LINUX
+
+#if GTEST_HAS_EXCEPTIONS
+# include <stdexcept>
+#endif
+
+#if GTEST_CAN_STREAM_RESULTS_
+# include <arpa/inet.h>  // NOLINT
+# include <netdb.h>  // NOLINT
+#endif
+
+// Indicates that this translation unit is part of Google Test's
+// implementation.  It must come before gtest-internal-inl.h is
+// included, or there will be a compiler error.  This trick is to
+// prevent a user from accidentally including gtest-internal-inl.h in
+// his code.
+#define GTEST_IMPLEMENTATION_ 1
+#include "src/gtest-internal-inl.h"
+#undef GTEST_IMPLEMENTATION_
+
+#if GTEST_OS_WINDOWS
+# define vsnprintf _vsnprintf
+#endif  // GTEST_OS_WINDOWS
+
+namespace testing {
+
+using internal::CountIf;
+using internal::ForEach;
+using internal::GetElementOr;
+using internal::Shuffle;
+
+// Constants.
+
+// A test whose test case name or test name matches this filter is
+// disabled and not run.
+static const char kDisableTestFilter[] = "DISABLED_*:*/DISABLED_*";
+
+// A test case whose name matches this filter is considered a death
+// test case and will be run before test cases whose name doesn't
+// match this filter.
+static const char kDeathTestCaseFilter[] = "*DeathTest:*DeathTest/*";
+
+// A test filter that matches everything.
+static const char kUniversalFilter[] = "*";
+
+// The default output file for XML output.
+static const char kDefaultOutputFile[] = "test_detail.xml";
+
+// The environment variable name for the test shard index.
+static const char kTestShardIndex[] = "GTEST_SHARD_INDEX";
+// The environment variable name for the total number of test shards.
+static const char kTestTotalShards[] = "GTEST_TOTAL_SHARDS";
+// The environment variable name for the test shard status file.
+static const char kTestShardStatusFile[] = "GTEST_SHARD_STATUS_FILE";
+
+namespace internal {
+
+// The text used in failure messages to indicate the start of the
+// stack trace.
+const char kStackTraceMarker[] = "\nStack trace:\n";
+
+// g_help_flag is true iff the --help flag or an equivalent form is
+// specified on the command line.
+bool g_help_flag = false;
+
+}  // namespace internal
+
+static const char* GetDefaultFilter() {
+  return kUniversalFilter;
+}
+
+GTEST_DEFINE_bool_(
+    also_run_disabled_tests,
+    internal::BoolFromGTestEnv("also_run_disabled_tests", false),
+    "Run disabled tests too, in addition to the tests normally being run.");
+
+GTEST_DEFINE_bool_(
+    break_on_failure,
+    internal::BoolFromGTestEnv("break_on_failure", false),
+    "True iff a failed assertion should be a debugger break-point.");
+
+GTEST_DEFINE_bool_(
+    catch_exceptions,
+    internal::BoolFromGTestEnv("catch_exceptions", true),
+    "True iff " GTEST_NAME_
+    " should catch exceptions and treat them as test failures.");
+
+GTEST_DEFINE_string_(
+    color,
+    internal::StringFromGTestEnv("color", "auto"),
+    "Whether to use colors in the output.  Valid values: yes, no, "
+    "and auto.  'auto' means to use colors if the output is "
+    "being sent to a terminal and the TERM environment variable "
+    "is set to a terminal type that supports colors.");
+
+GTEST_DEFINE_string_(
+    filter,
+    internal::StringFromGTestEnv("filter", GetDefaultFilter()),
+    "A colon-separated list of glob (not regex) patterns "
+    "for filtering the tests to run, optionally followed by a "
+    "'-' and a : separated list of negative patterns (tests to "
+    "exclude).  A test is run if it matches one of the positive "
+    "patterns and does not match any of the negative patterns.");
+
+GTEST_DEFINE_bool_(list_tests, false,
+                   "List all tests without running them.");
+
+GTEST_DEFINE_string_(
+    output,
+    internal::StringFromGTestEnv("output", ""),
+    "A format (currently must be \"xml\"), optionally followed "
+    "by a colon and an output file name or directory. A directory "
+    "is indicated by a trailing pathname separator. "
+    "Examples: \"xml:filename.xml\", \"xml::directoryname/\". "
+    "If a directory is specified, output files will be created "
+    "within that directory, with file-names based on the test "
+    "executable's name and, if necessary, made unique by adding "
+    "digits.");
+
+GTEST_DEFINE_bool_(
+    print_time,
+    internal::BoolFromGTestEnv("print_time", true),
+    "True iff " GTEST_NAME_
+    " should display elapsed time in text output.");
+
+GTEST_DEFINE_int32_(
+    random_seed,
+    internal::Int32FromGTestEnv("random_seed", 0),
+    "Random number seed to use when shuffling test orders.  Must be in range "
+    "[1, 99999], or 0 to use a seed based on the current time.");
+
+GTEST_DEFINE_int32_(
+    repeat,
+    internal::Int32FromGTestEnv("repeat", 1),
+    "How many times to repeat each test.  Specify a negative number "
+    "for repeating forever.  Useful for shaking out flaky tests.");
+
+GTEST_DEFINE_bool_(
+    show_internal_stack_frames, false,
+    "True iff " GTEST_NAME_ " should include internal stack frames when "
+    "printing test failure stack traces.");
+
+GTEST_DEFINE_bool_(
+    shuffle,
+    internal::BoolFromGTestEnv("shuffle", false),
+    "True iff " GTEST_NAME_
+    " should randomize tests' order on every run.");
+
+GTEST_DEFINE_int32_(
+    stack_trace_depth,
+    internal::Int32FromGTestEnv("stack_trace_depth", kMaxStackTraceDepth),
+    "The maximum number of stack frames to print when an "
+    "assertion fails.  The valid range is 0 through 100, inclusive.");
+
+GTEST_DEFINE_string_(
+    stream_result_to,
+    internal::StringFromGTestEnv("stream_result_to", ""),
+    "This flag specifies the host name and the port number on which to stream "
+    "test results. Example: \"localhost:555\". The flag is effective only on "
+    "Linux.");
+
+GTEST_DEFINE_bool_(
+    throw_on_failure,
+    internal::BoolFromGTestEnv("throw_on_failure", false),
+    "When this flag is specified, a failed assertion will throw an exception "
+    "if exceptions are enabled or exit the program with a non-zero code "
+    "otherwise.");
+
+namespace internal {
+
+// Generates a random number from [0, range), using a Linear
+// Congruential Generator (LCG).  Crashes if 'range' is 0 or greater
+// than kMaxRange.
+UInt32 Random::Generate(UInt32 range) {
+  // These constants are the same as are used in glibc's rand(3).
+  state_ = (1103515245U*state_ + 12345U) % kMaxRange;
+
+  GTEST_CHECK_(range > 0)
+      << "Cannot generate a number in the range [0, 0).";
+  GTEST_CHECK_(range <= kMaxRange)
+      << "Generation of a number in [0, " << range << ") was requested, "
+      << "but this can only generate numbers in [0, " << kMaxRange << ").";
+
+  // Converting via modulus introduces a bit of downward bias, but
+  // it's simple, and a linear congruential generator isn't too good
+  // to begin with.
+  return state_ % range;
+}
+
+// GTestIsInitialized() returns true iff the user has initialized
+// Google Test.  Useful for catching the user mistake of not initializing
+// Google Test before calling RUN_ALL_TESTS().
+//
+// A user must call testing::InitGoogleTest() to initialize Google
+// Test.  g_init_gtest_count is set to the number of times
+// InitGoogleTest() has been called.  We don't protect this variable
+// under a mutex as it is only accessed in the main thread.
+GTEST_API_ int g_init_gtest_count = 0;
+static bool GTestIsInitialized() { return g_init_gtest_count != 0; }
+
+// Iterates over a vector of TestCases, keeping a running sum of the
+// results of calling a given int-returning method on each.
+// Returns the sum.
+static int SumOverTestCaseList(const std::vector<TestCase*>& case_list,
+                               int (TestCase::*method)() const) {
+  int sum = 0;
+  for (size_t i = 0; i < case_list.size(); i++) {
+    sum += (case_list[i]->*method)();
+  }
+  return sum;
+}
+
+// Returns true iff the test case passed.
+static bool TestCasePassed(const TestCase* test_case) {
+  return test_case->should_run() && test_case->Passed();
+}
+
+// Returns true iff the test case failed.
+static bool TestCaseFailed(const TestCase* test_case) {
+  return test_case->should_run() && test_case->Failed();
+}
+
+// Returns true iff test_case contains at least one test that should
+// run.
+static bool ShouldRunTestCase(const TestCase* test_case) {
+  return test_case->should_run();
+}
+
+// AssertHelper constructor.
+AssertHelper::AssertHelper(TestPartResult::Type type,
+                           const char* file,
+                           int line,
+                           const char* message)
+    : data_(new AssertHelperData(type, file, line, message)) {
+}
+
+AssertHelper::~AssertHelper() {
+  delete data_;
+}
+
+// Message assignment, for assertion streaming support.
+void AssertHelper::operator=(const Message& message) const {
+  UnitTest::GetInstance()->
+    AddTestPartResult(data_->type, data_->file, data_->line,
+                      AppendUserMessage(data_->message, message),
+                      UnitTest::GetInstance()->impl()
+                      ->CurrentOsStackTraceExceptTop(1)
+                      // Skips the stack frame for this function itself.
+                      );  // NOLINT
+}
+
+// Mutex for linked pointers.
+GTEST_API_ GTEST_DEFINE_STATIC_MUTEX_(g_linked_ptr_mutex);
+
+// Application pathname gotten in InitGoogleTest.
+std::string g_executable_path;
+
+// Returns the current application's name, removing directory path if that
+// is present.
+FilePath GetCurrentExecutableName() {
+  FilePath result;
+
+#if GTEST_OS_WINDOWS
+  result.Set(FilePath(g_executable_path).RemoveExtension("exe"));
+#else
+  result.Set(FilePath(g_executable_path));
+#endif  // GTEST_OS_WINDOWS
+
+  return result.RemoveDirectoryName();
+}
+
+// Functions for processing the gtest_output flag.
+
+// Returns the output format, or "" for normal printed output.
+std::string UnitTestOptions::GetOutputFormat() {
+  const char* const gtest_output_flag = GTEST_FLAG(output).c_str();
+  if (gtest_output_flag == NULL) return std::string("");
+
+  const char* const colon = strchr(gtest_output_flag, ':');
+  return (colon == NULL) ?
+      std::string(gtest_output_flag) :
+      std::string(gtest_output_flag, colon - gtest_output_flag);
+}
+
+// Returns the name of the requested output file, or the default if none
+// was explicitly specified.
+std::string UnitTestOptions::GetAbsolutePathToOutputFile() {
+  const char* const gtest_output_flag = GTEST_FLAG(output).c_str();
+  if (gtest_output_flag == NULL)
+    return "";
+
+  const char* const colon = strchr(gtest_output_flag, ':');
+  if (colon == NULL)
+    return internal::FilePath::ConcatPaths(
+        internal::FilePath(
+            UnitTest::GetInstance()->original_working_dir()),
+        internal::FilePath(kDefaultOutputFile)).string();
+
+  internal::FilePath output_name(colon + 1);
+  if (!output_name.IsAbsolutePath())
+    // TODO(wan at google.com): on Windows \some\path is not an absolute
+    // path (as its meaning depends on the current drive), yet the
+    // following logic for turning it into an absolute path is wrong.
+    // Fix it.
+    output_name = internal::FilePath::ConcatPaths(
+        internal::FilePath(UnitTest::GetInstance()->original_working_dir()),
+        internal::FilePath(colon + 1));
+
+  if (!output_name.IsDirectory())
+    return output_name.string();
+
+  internal::FilePath result(internal::FilePath::GenerateUniqueFileName(
+      output_name, internal::GetCurrentExecutableName(),
+      GetOutputFormat().c_str()));
+  return result.string();
+}
+
+// Returns true iff the wildcard pattern matches the string.  The
+// first ':' or '\0' character in pattern marks the end of it.
+//
+// This recursive algorithm isn't very efficient, but is clear and
+// works well enough for matching test names, which are short.
+bool UnitTestOptions::PatternMatchesString(const char *pattern,
+                                           const char *str) {
+  switch (*pattern) {
+    case '\0':
+    case ':':  // Either ':' or '\0' marks the end of the pattern.
+      return *str == '\0';
+    case '?':  // Matches any single character.
+      return *str != '\0' && PatternMatchesString(pattern + 1, str + 1);
+    case '*':  // Matches any string (possibly empty) of characters.
+      return (*str != '\0' && PatternMatchesString(pattern, str + 1)) ||
+          PatternMatchesString(pattern + 1, str);
+    default:  // Non-special character.  Matches itself.
+      return *pattern == *str &&
+          PatternMatchesString(pattern + 1, str + 1);
+  }
+}
+
+bool UnitTestOptions::MatchesFilter(
+    const std::string& name, const char* filter) {
+  const char *cur_pattern = filter;
+  for (;;) {
+    if (PatternMatchesString(cur_pattern, name.c_str())) {
+      return true;
+    }
+
+    // Finds the next pattern in the filter.
+    cur_pattern = strchr(cur_pattern, ':');
+
+    // Returns if no more pattern can be found.
+    if (cur_pattern == NULL) {
+      return false;
+    }
+
+    // Skips the pattern separater (the ':' character).
+    cur_pattern++;
+  }
+}
+
+// Returns true iff the user-specified filter matches the test case
+// name and the test name.
+bool UnitTestOptions::FilterMatchesTest(const std::string &test_case_name,
+                                        const std::string &test_name) {
+  const std::string& full_name = test_case_name + "." + test_name.c_str();
+
+  // Split --gtest_filter at '-', if there is one, to separate into
+  // positive filter and negative filter portions
+  const char* const p = GTEST_FLAG(filter).c_str();
+  const char* const dash = strchr(p, '-');
+  std::string positive;
+  std::string negative;
+  if (dash == NULL) {
+    positive = GTEST_FLAG(filter).c_str();  // Whole string is a positive filter
+    negative = "";
+  } else {
+    positive = std::string(p, dash);   // Everything up to the dash
+    negative = std::string(dash + 1);  // Everything after the dash
+    if (positive.empty()) {
+      // Treat '-test1' as the same as '*-test1'
+      positive = kUniversalFilter;
+    }
+  }
+
+  // A filter is a colon-separated list of patterns.  It matches a
+  // test if any pattern in it matches the test.
+  return (MatchesFilter(full_name, positive.c_str()) &&
+          !MatchesFilter(full_name, negative.c_str()));
+}
+
+#if GTEST_HAS_SEH
+// Returns EXCEPTION_EXECUTE_HANDLER if Google Test should handle the
+// given SEH exception, or EXCEPTION_CONTINUE_SEARCH otherwise.
+// This function is useful as an __except condition.
+int UnitTestOptions::GTestShouldProcessSEH(DWORD exception_code) {
+  // Google Test should handle a SEH exception if:
+  //   1. the user wants it to, AND
+  //   2. this is not a breakpoint exception, AND
+  //   3. this is not a C++ exception (VC++ implements them via SEH,
+  //      apparently).
+  //
+  // SEH exception code for C++ exceptions.
+  // (see http://support.microsoft.com/kb/185294 for more information).
+  const DWORD kCxxExceptionCode = 0xe06d7363;
+
+  bool should_handle = true;
+
+  if (!GTEST_FLAG(catch_exceptions))
+    should_handle = false;
+  else if (exception_code == EXCEPTION_BREAKPOINT)
+    should_handle = false;
+  else if (exception_code == kCxxExceptionCode)
+    should_handle = false;
+
+  return should_handle ? EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH;
+}
+#endif  // GTEST_HAS_SEH
+
+}  // namespace internal
+
+// The c'tor sets this object as the test part result reporter used by
+// Google Test.  The 'result' parameter specifies where to report the
+// results. Intercepts only failures from the current thread.
+ScopedFakeTestPartResultReporter::ScopedFakeTestPartResultReporter(
+    TestPartResultArray* result)
+    : intercept_mode_(INTERCEPT_ONLY_CURRENT_THREAD),
+      result_(result) {
+  Init();
+}
+
+// The c'tor sets this object as the test part result reporter used by
+// Google Test.  The 'result' parameter specifies where to report the
+// results.
+ScopedFakeTestPartResultReporter::ScopedFakeTestPartResultReporter(
+    InterceptMode intercept_mode, TestPartResultArray* result)
+    : intercept_mode_(intercept_mode),
+      result_(result) {
+  Init();
+}
+
+void ScopedFakeTestPartResultReporter::Init() {
+  internal::UnitTestImpl* const impl = internal::GetUnitTestImpl();
+  if (intercept_mode_ == INTERCEPT_ALL_THREADS) {
+    old_reporter_ = impl->GetGlobalTestPartResultReporter();
+    impl->SetGlobalTestPartResultReporter(this);
+  } else {
+    old_reporter_ = impl->GetTestPartResultReporterForCurrentThread();
+    impl->SetTestPartResultReporterForCurrentThread(this);
+  }
+}
+
+// The d'tor restores the test part result reporter used by Google Test
+// before.
+ScopedFakeTestPartResultReporter::~ScopedFakeTestPartResultReporter() {
+  internal::UnitTestImpl* const impl = internal::GetUnitTestImpl();
+  if (intercept_mode_ == INTERCEPT_ALL_THREADS) {
+    impl->SetGlobalTestPartResultReporter(old_reporter_);
+  } else {
+    impl->SetTestPartResultReporterForCurrentThread(old_reporter_);
+  }
+}
+
+// Increments the test part result count and remembers the result.
+// This method is from the TestPartResultReporterInterface interface.
+void ScopedFakeTestPartResultReporter::ReportTestPartResult(
+    const TestPartResult& result) {
+  result_->Append(result);
+}
+
+namespace internal {
+
+// Returns the type ID of ::testing::Test.  We should always call this
+// instead of GetTypeId< ::testing::Test>() to get the type ID of
+// testing::Test.  This is to work around a suspected linker bug when
+// using Google Test as a framework on Mac OS X.  The bug causes
+// GetTypeId< ::testing::Test>() to return different values depending
+// on whether the call is from the Google Test framework itself or
+// from user test code.  GetTestTypeId() is guaranteed to always
+// return the same value, as it always calls GetTypeId<>() from the
+// gtest.cc, which is within the Google Test framework.
+TypeId GetTestTypeId() {
+  return GetTypeId<Test>();
+}
+
+// The value of GetTestTypeId() as seen from within the Google Test
+// library.  This is solely for testing GetTestTypeId().
+extern const TypeId kTestTypeIdInGoogleTest = GetTestTypeId();
+
+// This predicate-formatter checks that 'results' contains a test part
+// failure of the given type and that the failure message contains the
+// given substring.
+AssertionResult HasOneFailure(const char* /* results_expr */,
+                              const char* /* type_expr */,
+                              const char* /* substr_expr */,
+                              const TestPartResultArray& results,
+                              TestPartResult::Type type,
+                              const string& substr) {
+  const std::string expected(type == TestPartResult::kFatalFailure ?
+                        "1 fatal failure" :
+                        "1 non-fatal failure");
+  Message msg;
+  if (results.size() != 1) {
+    msg << "Expected: " << expected << "\n"
+        << "  Actual: " << results.size() << " failures";
+    for (int i = 0; i < results.size(); i++) {
+      msg << "\n" << results.GetTestPartResult(i);
+    }
+    return AssertionFailure() << msg;
+  }
+
+  const TestPartResult& r = results.GetTestPartResult(0);
+  if (r.type() != type) {
+    return AssertionFailure() << "Expected: " << expected << "\n"
+                              << "  Actual:\n"
+                              << r;
+  }
+
+  if (strstr(r.message(), substr.c_str()) == NULL) {
+    return AssertionFailure() << "Expected: " << expected << " containing \""
+                              << substr << "\"\n"
+                              << "  Actual:\n"
+                              << r;
+  }
+
+  return AssertionSuccess();
+}
+
+// The constructor of SingleFailureChecker remembers where to look up
+// test part results, what type of failure we expect, and what
+// substring the failure message should contain.
+SingleFailureChecker:: SingleFailureChecker(
+    const TestPartResultArray* results,
+    TestPartResult::Type type,
+    const string& substr)
+    : results_(results),
+      type_(type),
+      substr_(substr) {}
+
+// The destructor of SingleFailureChecker verifies that the given
+// TestPartResultArray contains exactly one failure that has the given
+// type and contains the given substring.  If that's not the case, a
+// non-fatal failure will be generated.
+SingleFailureChecker::~SingleFailureChecker() {
+  EXPECT_PRED_FORMAT3(HasOneFailure, *results_, type_, substr_);
+}
+
+DefaultGlobalTestPartResultReporter::DefaultGlobalTestPartResultReporter(
+    UnitTestImpl* unit_test) : unit_test_(unit_test) {}
+
+void DefaultGlobalTestPartResultReporter::ReportTestPartResult(
+    const TestPartResult& result) {
+  unit_test_->current_test_result()->AddTestPartResult(result);
+  unit_test_->listeners()->repeater()->OnTestPartResult(result);
+}
+
+DefaultPerThreadTestPartResultReporter::DefaultPerThreadTestPartResultReporter(
+    UnitTestImpl* unit_test) : unit_test_(unit_test) {}
+
+void DefaultPerThreadTestPartResultReporter::ReportTestPartResult(
+    const TestPartResult& result) {
+  unit_test_->GetGlobalTestPartResultReporter()->ReportTestPartResult(result);
+}
+
+// Returns the global test part result reporter.
+TestPartResultReporterInterface*
+UnitTestImpl::GetGlobalTestPartResultReporter() {
+  internal::MutexLock lock(&global_test_part_result_reporter_mutex_);
+  return global_test_part_result_repoter_;
+}
+
+// Sets the global test part result reporter.
+void UnitTestImpl::SetGlobalTestPartResultReporter(
+    TestPartResultReporterInterface* reporter) {
+  internal::MutexLock lock(&global_test_part_result_reporter_mutex_);
+  global_test_part_result_repoter_ = reporter;
+}
+
+// Returns the test part result reporter for the current thread.
+TestPartResultReporterInterface*
+UnitTestImpl::GetTestPartResultReporterForCurrentThread() {
+  return per_thread_test_part_result_reporter_.get();
+}
+
+// Sets the test part result reporter for the current thread.
+void UnitTestImpl::SetTestPartResultReporterForCurrentThread(
+    TestPartResultReporterInterface* reporter) {
+  per_thread_test_part_result_reporter_.set(reporter);
+}
+
+// Gets the number of successful test cases.
+int UnitTestImpl::successful_test_case_count() const {
+  return CountIf(test_cases_, TestCasePassed);
+}
+
+// Gets the number of failed test cases.
+int UnitTestImpl::failed_test_case_count() const {
+  return CountIf(test_cases_, TestCaseFailed);
+}
+
+// Gets the number of all test cases.
+int UnitTestImpl::total_test_case_count() const {
+  return static_cast<int>(test_cases_.size());
+}
+
+// Gets the number of all test cases that contain at least one test
+// that should run.
+int UnitTestImpl::test_case_to_run_count() const {
+  return CountIf(test_cases_, ShouldRunTestCase);
+}
+
+// Gets the number of successful tests.
+int UnitTestImpl::successful_test_count() const {
+  return SumOverTestCaseList(test_cases_, &TestCase::successful_test_count);
+}
+
+// Gets the number of failed tests.
+int UnitTestImpl::failed_test_count() const {
+  return SumOverTestCaseList(test_cases_, &TestCase::failed_test_count);
+}
+
+// Gets the number of disabled tests that will be reported in the XML report.
+int UnitTestImpl::reportable_disabled_test_count() const {
+  return SumOverTestCaseList(test_cases_,
+                             &TestCase::reportable_disabled_test_count);
+}
+
+// Gets the number of disabled tests.
+int UnitTestImpl::disabled_test_count() const {
+  return SumOverTestCaseList(test_cases_, &TestCase::disabled_test_count);
+}
+
+// Gets the number of tests to be printed in the XML report.
+int UnitTestImpl::reportable_test_count() const {
+  return SumOverTestCaseList(test_cases_, &TestCase::reportable_test_count);
+}
+
+// Gets the number of all tests.
+int UnitTestImpl::total_test_count() const {
+  return SumOverTestCaseList(test_cases_, &TestCase::total_test_count);
+}
+
+// Gets the number of tests that should run.
+int UnitTestImpl::test_to_run_count() const {
+  return SumOverTestCaseList(test_cases_, &TestCase::test_to_run_count);
+}
+
+// Returns the current OS stack trace as an std::string.
+//
+// The maximum number of stack frames to be included is specified by
+// the gtest_stack_trace_depth flag.  The skip_count parameter
+// specifies the number of top frames to be skipped, which doesn't
+// count against the number of frames to be included.
+//
+// For example, if Foo() calls Bar(), which in turn calls
+// CurrentOsStackTraceExceptTop(1), Foo() will be included in the
+// trace but Bar() and CurrentOsStackTraceExceptTop() won't.
+std::string UnitTestImpl::CurrentOsStackTraceExceptTop(int skip_count) {
+  (void)skip_count;
+  return "";
+}
+
+// Returns the current time in milliseconds.
+TimeInMillis GetTimeInMillis() {
+#if GTEST_OS_WINDOWS_MOBILE || defined(__BORLANDC__)
+  // Difference between 1970-01-01 and 1601-01-01 in milliseconds.
+  // http://analogous.blogspot.com/2005/04/epoch.html
+  const TimeInMillis kJavaEpochToWinFileTimeDelta =
+    static_cast<TimeInMillis>(116444736UL) * 100000UL;
+  const DWORD kTenthMicrosInMilliSecond = 10000;
+
+  SYSTEMTIME now_systime;
+  FILETIME now_filetime;
+  ULARGE_INTEGER now_int64;
+  // TODO(kenton at google.com): Shouldn't this just use
+  //   GetSystemTimeAsFileTime()?
+  GetSystemTime(&now_systime);
+  if (SystemTimeToFileTime(&now_systime, &now_filetime)) {
+    now_int64.LowPart = now_filetime.dwLowDateTime;
+    now_int64.HighPart = now_filetime.dwHighDateTime;
+    now_int64.QuadPart = (now_int64.QuadPart / kTenthMicrosInMilliSecond) -
+      kJavaEpochToWinFileTimeDelta;
+    return now_int64.QuadPart;
+  }
+  return 0;
+#elif GTEST_OS_WINDOWS && !GTEST_HAS_GETTIMEOFDAY_
+  __timeb64 now;
+
+# ifdef _MSC_VER
+
+  // MSVC 8 deprecates _ftime64(), so we want to suppress warning 4996
+  // (deprecated function) there.
+  // TODO(kenton at google.com): Use GetTickCount()?  Or use
+  //   SystemTimeToFileTime()
+#  pragma warning(push)          // Saves the current warning state.
+#  pragma warning(disable:4996)  // Temporarily disables warning 4996.
+  _ftime64(&now);
+#  pragma warning(pop)           // Restores the warning state.
+# else
+
+  _ftime64(&now);
+
+# endif  // _MSC_VER
+
+  return static_cast<TimeInMillis>(now.time) * 1000 + now.millitm;
+#elif GTEST_HAS_GETTIMEOFDAY_
+  struct timeval now;
+  gettimeofday(&now, NULL);
+  return static_cast<TimeInMillis>(now.tv_sec) * 1000 + now.tv_usec / 1000;
+#else
+# error "Don't know how to get the current time on your system."
+#endif
+}
+
+// Utilities
+
+// class String.
+
+#if GTEST_OS_WINDOWS_MOBILE
+// Creates a UTF-16 wide string from the given ANSI string, allocating
+// memory using new. The caller is responsible for deleting the return
+// value using delete[]. Returns the wide string, or NULL if the
+// input is NULL.
+LPCWSTR String::AnsiToUtf16(const char* ansi) {
+  if (!ansi) return NULL;
+  const int length = strlen(ansi);
+  const int unicode_length =
+      MultiByteToWideChar(CP_ACP, 0, ansi, length,
+                          NULL, 0);
+  WCHAR* unicode = new WCHAR[unicode_length + 1];
+  MultiByteToWideChar(CP_ACP, 0, ansi, length,
+                      unicode, unicode_length);
+  unicode[unicode_length] = 0;
+  return unicode;
+}
+
+// Creates an ANSI string from the given wide string, allocating
+// memory using new. The caller is responsible for deleting the return
+// value using delete[]. Returns the ANSI string, or NULL if the
+// input is NULL.
+const char* String::Utf16ToAnsi(LPCWSTR utf16_str)  {
+  if (!utf16_str) return NULL;
+  const int ansi_length =
+      WideCharToMultiByte(CP_ACP, 0, utf16_str, -1,
+                          NULL, 0, NULL, NULL);
+  char* ansi = new char[ansi_length + 1];
+  WideCharToMultiByte(CP_ACP, 0, utf16_str, -1,
+                      ansi, ansi_length, NULL, NULL);
+  ansi[ansi_length] = 0;
+  return ansi;
+}
+
+#endif  // GTEST_OS_WINDOWS_MOBILE
+
+// Compares two C strings.  Returns true iff they have the same content.
+//
+// Unlike strcmp(), this function can handle NULL argument(s).  A NULL
+// C string is considered different to any non-NULL C string,
+// including the empty string.
+bool String::CStringEquals(const char * lhs, const char * rhs) {
+  if ( lhs == NULL ) return rhs == NULL;
+
+  if ( rhs == NULL ) return false;
+
+  return strcmp(lhs, rhs) == 0;
+}
+
+#if GTEST_HAS_STD_WSTRING || GTEST_HAS_GLOBAL_WSTRING
+
+// Converts an array of wide chars to a narrow string using the UTF-8
+// encoding, and streams the result to the given Message object.
+static void StreamWideCharsToMessage(const wchar_t* wstr, size_t length,
+                                     Message* msg) {
+  for (size_t i = 0; i != length; ) {  // NOLINT
+    if (wstr[i] != L'\0') {
+      *msg << WideStringToUtf8(wstr + i, static_cast<int>(length - i));
+      while (i != length && wstr[i] != L'\0')
+        i++;
+    } else {
+      *msg << '\0';
+      i++;
+    }
+  }
+}
+
+#endif  // GTEST_HAS_STD_WSTRING || GTEST_HAS_GLOBAL_WSTRING
+
+}  // namespace internal
+
+// Constructs an empty Message.
+// We allocate the stringstream separately because otherwise each use of
+// ASSERT/EXPECT in a procedure adds over 200 bytes to the procedure's
+// stack frame leading to huge stack frames in some cases; gcc does not reuse
+// the stack space.
+Message::Message() : ss_(new ::std::stringstream) {
+  // By default, we want there to be enough precision when printing
+  // a double to a Message.
+  *ss_ << std::setprecision(std::numeric_limits<double>::digits10 + 2);
+}
+
+// These two overloads allow streaming a wide C string to a Message
+// using the UTF-8 encoding.
+Message& Message::operator <<(const wchar_t* wide_c_str) {
+  return *this << internal::String::ShowWideCString(wide_c_str);
+}
+Message& Message::operator <<(wchar_t* wide_c_str) {
+  return *this << internal::String::ShowWideCString(wide_c_str);
+}
+
+#if GTEST_HAS_STD_WSTRING
+// Converts the given wide string to a narrow string using the UTF-8
+// encoding, and streams the result to this Message object.
+Message& Message::operator <<(const ::std::wstring& wstr) {
+  internal::StreamWideCharsToMessage(wstr.c_str(), wstr.length(), this);
+  return *this;
+}
+#endif  // GTEST_HAS_STD_WSTRING
+
+#if GTEST_HAS_GLOBAL_WSTRING
+// Converts the given wide string to a narrow string using the UTF-8
+// encoding, and streams the result to this Message object.
+Message& Message::operator <<(const ::wstring& wstr) {
+  internal::StreamWideCharsToMessage(wstr.c_str(), wstr.length(), this);
+  return *this;
+}
+#endif  // GTEST_HAS_GLOBAL_WSTRING
+
+// Gets the text streamed to this object so far as an std::string.
+// Each '\0' character in the buffer is replaced with "\\0".
+std::string Message::GetString() const {
+  return internal::StringStreamToString(ss_.get());
+}
+
+// AssertionResult constructors.
+// Used in EXPECT_TRUE/FALSE(assertion_result).
+AssertionResult::AssertionResult(const AssertionResult& other)
+    : success_(other.success_),
+      message_(other.message_.get() != NULL ?
+               new ::std::string(*other.message_) :
+               static_cast< ::std::string*>(NULL)) {
+}
+
+// Returns the assertion's negation. Used with EXPECT/ASSERT_FALSE.
+AssertionResult AssertionResult::operator!() const {
+  AssertionResult negation(!success_);
+  if (message_.get() != NULL)
+    negation << *message_;
+  return negation;
+}
+
+// Makes a successful assertion result.
+AssertionResult AssertionSuccess() {
+  return AssertionResult(true);
+}
+
+// Makes a failed assertion result.
+AssertionResult AssertionFailure() {
+  return AssertionResult(false);
+}
+
+// Makes a failed assertion result with the given failure message.
+// Deprecated; use AssertionFailure() << message.
+AssertionResult AssertionFailure(const Message& message) {
+  return AssertionFailure() << message;
+}
+
+namespace internal {
+
+// Constructs and returns the message for an equality assertion
+// (e.g. ASSERT_EQ, EXPECT_STREQ, etc) failure.
+//
+// The first four parameters are the expressions used in the assertion
+// and their values, as strings.  For example, for ASSERT_EQ(foo, bar)
+// where foo is 5 and bar is 6, we have:
+//
+//   expected_expression: "foo"
+//   actual_expression:   "bar"
+//   expected_value:      "5"
+//   actual_value:        "6"
+//
+// The ignoring_case parameter is true iff the assertion is a
+// *_STRCASEEQ*.  When it's true, the string " (ignoring case)" will
+// be inserted into the message.
+AssertionResult EqFailure(const char* expected_expression,
+                          const char* actual_expression,
+                          const std::string& expected_value,
+                          const std::string& actual_value,
+                          bool ignoring_case) {
+  Message msg;
+  msg << "Value of: " << actual_expression;
+  if (actual_value != actual_expression) {
+    msg << "\n  Actual: " << actual_value;
+  }
+
+  msg << "\nExpected: " << expected_expression;
+  if (ignoring_case) {
+    msg << " (ignoring case)";
+  }
+  if (expected_value != expected_expression) {
+    msg << "\nWhich is: " << expected_value;
+  }
+
+  return AssertionFailure() << msg;
+}
+
+// Constructs a failure message for Boolean assertions such as EXPECT_TRUE.
+std::string GetBoolAssertionFailureMessage(
+    const AssertionResult& assertion_result,
+    const char* expression_text,
+    const char* actual_predicate_value,
+    const char* expected_predicate_value) {
+  const char* actual_message = assertion_result.message();
+  Message msg;
+  msg << "Value of: " << expression_text
+      << "\n  Actual: " << actual_predicate_value;
+  if (actual_message[0] != '\0')
+    msg << " (" << actual_message << ")";
+  msg << "\nExpected: " << expected_predicate_value;
+  return msg.GetString();
+}
+
+// Helper function for implementing ASSERT_NEAR.
+AssertionResult DoubleNearPredFormat(const char* expr1,
+                                     const char* expr2,
+                                     const char* abs_error_expr,
+                                     double val1,
+                                     double val2,
+                                     double abs_error) {
+  const double diff = fabs(val1 - val2);
+  if (diff <= abs_error) return AssertionSuccess();
+
+  // TODO(wan): do not print the value of an expression if it's
+  // already a literal.
+  return AssertionFailure()
+      << "The difference between " << expr1 << " and " << expr2
+      << " is " << diff << ", which exceeds " << abs_error_expr << ", where\n"
+      << expr1 << " evaluates to " << val1 << ",\n"
+      << expr2 << " evaluates to " << val2 << ", and\n"
+      << abs_error_expr << " evaluates to " << abs_error << ".";
+}
+
+
+// Helper template for implementing FloatLE() and DoubleLE().
+template <typename RawType>
+AssertionResult FloatingPointLE(const char* expr1,
+                                const char* expr2,
+                                RawType val1,
+                                RawType val2) {
+  // Returns success if val1 is less than val2,
+  if (val1 < val2) {
+    return AssertionSuccess();
+  }
+
+  // or if val1 is almost equal to val2.
+  const FloatingPoint<RawType> lhs(val1), rhs(val2);
+  if (lhs.AlmostEquals(rhs)) {
+    return AssertionSuccess();
+  }
+
+  // Note that the above two checks will both fail if either val1 or
+  // val2 is NaN, as the IEEE floating-point standard requires that
+  // any predicate involving a NaN must return false.
+
+  ::std::stringstream val1_ss;
+  val1_ss << std::setprecision(std::numeric_limits<RawType>::digits10 + 2)
+          << val1;
+
+  ::std::stringstream val2_ss;
+  val2_ss << std::setprecision(std::numeric_limits<RawType>::digits10 + 2)
+          << val2;
+
+  return AssertionFailure()
+      << "Expected: (" << expr1 << ") <= (" << expr2 << ")\n"
+      << "  Actual: " << StringStreamToString(&val1_ss) << " vs "
+      << StringStreamToString(&val2_ss);
+}
+
+}  // namespace internal
+
+// Asserts that val1 is less than, or almost equal to, val2.  Fails
+// otherwise.  In particular, it fails if either val1 or val2 is NaN.
+AssertionResult FloatLE(const char* expr1, const char* expr2,
+                        float val1, float val2) {
+  return internal::FloatingPointLE<float>(expr1, expr2, val1, val2);
+}
+
+// Asserts that val1 is less than, or almost equal to, val2.  Fails
+// otherwise.  In particular, it fails if either val1 or val2 is NaN.
+AssertionResult DoubleLE(const char* expr1, const char* expr2,
+                         double val1, double val2) {
+  return internal::FloatingPointLE<double>(expr1, expr2, val1, val2);
+}
+
+namespace internal {
+
+// The helper function for {ASSERT|EXPECT}_EQ with int or enum
+// arguments.
+AssertionResult CmpHelperEQ(const char* expected_expression,
+                            const char* actual_expression,
+                            BiggestInt expected,
+                            BiggestInt actual) {
+  if (expected == actual) {
+    return AssertionSuccess();
+  }
+
+  return EqFailure(expected_expression,
+                   actual_expression,
+                   FormatForComparisonFailureMessage(expected, actual),
+                   FormatForComparisonFailureMessage(actual, expected),
+                   false);
+}
+
+// A macro for implementing the helper functions needed to implement
+// ASSERT_?? and EXPECT_?? with integer or enum arguments.  It is here
+// just to avoid copy-and-paste of similar code.
+#define GTEST_IMPL_CMP_HELPER_(op_name, op)\
+AssertionResult CmpHelper##op_name(const char* expr1, const char* expr2, \
+                                   BiggestInt val1, BiggestInt val2) {\
+  if (val1 op val2) {\
+    return AssertionSuccess();\
+  } else {\
+    return AssertionFailure() \
+        << "Expected: (" << expr1 << ") " #op " (" << expr2\
+        << "), actual: " << FormatForComparisonFailureMessage(val1, val2)\
+        << " vs " << FormatForComparisonFailureMessage(val2, val1);\
+  }\
+}
+
+// Implements the helper function for {ASSERT|EXPECT}_NE with int or
+// enum arguments.
+GTEST_IMPL_CMP_HELPER_(NE, !=)
+// Implements the helper function for {ASSERT|EXPECT}_LE with int or
+// enum arguments.
+GTEST_IMPL_CMP_HELPER_(LE, <=)
+// Implements the helper function for {ASSERT|EXPECT}_LT with int or
+// enum arguments.
+GTEST_IMPL_CMP_HELPER_(LT, < )
+// Implements the helper function for {ASSERT|EXPECT}_GE with int or
+// enum arguments.
+GTEST_IMPL_CMP_HELPER_(GE, >=)
+// Implements the helper function for {ASSERT|EXPECT}_GT with int or
+// enum arguments.
+GTEST_IMPL_CMP_HELPER_(GT, > )
+
+#undef GTEST_IMPL_CMP_HELPER_
+
+// The helper function for {ASSERT|EXPECT}_STREQ.
+AssertionResult CmpHelperSTREQ(const char* expected_expression,
+                               const char* actual_expression,
+                               const char* expected,
+                               const char* actual) {
+  if (String::CStringEquals(expected, actual)) {
+    return AssertionSuccess();
+  }
+
+  return EqFailure(expected_expression,
+                   actual_expression,
+                   PrintToString(expected),
+                   PrintToString(actual),
+                   false);
+}
+
+// The helper function for {ASSERT|EXPECT}_STRCASEEQ.
+AssertionResult CmpHelperSTRCASEEQ(const char* expected_expression,
+                                   const char* actual_expression,
+                                   const char* expected,
+                                   const char* actual) {
+  if (String::CaseInsensitiveCStringEquals(expected, actual)) {
+    return AssertionSuccess();
+  }
+
+  return EqFailure(expected_expression,
+                   actual_expression,
+                   PrintToString(expected),
+                   PrintToString(actual),
+                   true);
+}
+
+// The helper function for {ASSERT|EXPECT}_STRNE.
+AssertionResult CmpHelperSTRNE(const char* s1_expression,
+                               const char* s2_expression,
+                               const char* s1,
+                               const char* s2) {
+  if (!String::CStringEquals(s1, s2)) {
+    return AssertionSuccess();
+  } else {
+    return AssertionFailure() << "Expected: (" << s1_expression << ") != ("
+                              << s2_expression << "), actual: \""
+                              << s1 << "\" vs \"" << s2 << "\"";
+  }
+}
+
+// The helper function for {ASSERT|EXPECT}_STRCASENE.
+AssertionResult CmpHelperSTRCASENE(const char* s1_expression,
+                                   const char* s2_expression,
+                                   const char* s1,
+                                   const char* s2) {
+  if (!String::CaseInsensitiveCStringEquals(s1, s2)) {
+    return AssertionSuccess();
+  } else {
+    return AssertionFailure()
+        << "Expected: (" << s1_expression << ") != ("
+        << s2_expression << ") (ignoring case), actual: \""
+        << s1 << "\" vs \"" << s2 << "\"";
+  }
+}
+
+}  // namespace internal
+
+namespace {
+
+// Helper functions for implementing IsSubString() and IsNotSubstring().
+
+// This group of overloaded functions return true iff needle is a
+// substring of haystack.  NULL is considered a substring of itself
+// only.
+
+bool IsSubstringPred(const char* needle, const char* haystack) {
+  if (needle == NULL || haystack == NULL)
+    return needle == haystack;
+
+  return strstr(haystack, needle) != NULL;
+}
+
+bool IsSubstringPred(const wchar_t* needle, const wchar_t* haystack) {
+  if (needle == NULL || haystack == NULL)
+    return needle == haystack;
+
+  return wcsstr(haystack, needle) != NULL;
+}
+
+// StringType here can be either ::std::string or ::std::wstring.
+template <typename StringType>
+bool IsSubstringPred(const StringType& needle,
+                     const StringType& haystack) {
+  return haystack.find(needle) != StringType::npos;
+}
+
+// This function implements either IsSubstring() or IsNotSubstring(),
+// depending on the value of the expected_to_be_substring parameter.
+// StringType here can be const char*, const wchar_t*, ::std::string,
+// or ::std::wstring.
+template <typename StringType>
+AssertionResult IsSubstringImpl(
+    bool expected_to_be_substring,
+    const char* needle_expr, const char* haystack_expr,
+    const StringType& needle, const StringType& haystack) {
+  if (IsSubstringPred(needle, haystack) == expected_to_be_substring)
+    return AssertionSuccess();
+
+  const bool is_wide_string = sizeof(needle[0]) > 1;
+  const char* const begin_string_quote = is_wide_string ? "L\"" : "\"";
+  return AssertionFailure()
+      << "Value of: " << needle_expr << "\n"
+      << "  Actual: " << begin_string_quote << needle << "\"\n"
+      << "Expected: " << (expected_to_be_substring ? "" : "not ")
+      << "a substring of " << haystack_expr << "\n"
+      << "Which is: " << begin_string_quote << haystack << "\"";
+}
+
+}  // namespace
+
+// IsSubstring() and IsNotSubstring() check whether needle is a
+// substring of haystack (NULL is considered a substring of itself
+// only), and return an appropriate error message when they fail.
+
+AssertionResult IsSubstring(
+    const char* needle_expr, const char* haystack_expr,
+    const char* needle, const char* haystack) {
+  return IsSubstringImpl(true, needle_expr, haystack_expr, needle, haystack);
+}
+
+AssertionResult IsSubstring(
+    const char* needle_expr, const char* haystack_expr,
+    const wchar_t* needle, const wchar_t* haystack) {
+  return IsSubstringImpl(true, needle_expr, haystack_expr, needle, haystack);
+}
+
+AssertionResult IsNotSubstring(
+    const char* needle_expr, const char* haystack_expr,
+    const char* needle, const char* haystack) {
+  return IsSubstringImpl(false, needle_expr, haystack_expr, needle, haystack);
+}
+
+AssertionResult IsNotSubstring(
+    const char* needle_expr, const char* haystack_expr,
+    const wchar_t* needle, const wchar_t* haystack) {
+  return IsSubstringImpl(false, needle_expr, haystack_expr, needle, haystack);
+}
+
+AssertionResult IsSubstring(
+    const char* needle_expr, const char* haystack_expr,
+    const ::std::string& needle, const ::std::string& haystack) {
+  return IsSubstringImpl(true, needle_expr, haystack_expr, needle, haystack);
+}
+
+AssertionResult IsNotSubstring(
+    const char* needle_expr, const char* haystack_expr,
+    const ::std::string& needle, const ::std::string& haystack) {
+  return IsSubstringImpl(false, needle_expr, haystack_expr, needle, haystack);
+}
+
+#if GTEST_HAS_STD_WSTRING
+AssertionResult IsSubstring(
+    const char* needle_expr, const char* haystack_expr,
+    const ::std::wstring& needle, const ::std::wstring& haystack) {
+  return IsSubstringImpl(true, needle_expr, haystack_expr, needle, haystack);
+}
+
+AssertionResult IsNotSubstring(
+    const char* needle_expr, const char* haystack_expr,
+    const ::std::wstring& needle, const ::std::wstring& haystack) {
+  return IsSubstringImpl(false, needle_expr, haystack_expr, needle, haystack);
+}
+#endif  // GTEST_HAS_STD_WSTRING
+
+namespace internal {
+
+#if GTEST_OS_WINDOWS
+
+namespace {
+
+// Helper function for IsHRESULT{SuccessFailure} predicates
+AssertionResult HRESULTFailureHelper(const char* expr,
+                                     const char* expected,
+                                     long hr) {  // NOLINT
+# if GTEST_OS_WINDOWS_MOBILE
+
+  // Windows CE doesn't support FormatMessage.
+  const char error_text[] = "";
+
+# else
+
+  // Looks up the human-readable system message for the HRESULT code
+  // and since we're not passing any params to FormatMessage, we don't
+  // want inserts expanded.
+  const DWORD kFlags = FORMAT_MESSAGE_FROM_SYSTEM |
+                       FORMAT_MESSAGE_IGNORE_INSERTS;
+  const DWORD kBufSize = 4096;
+  // Gets the system's human readable message string for this HRESULT.
+  char error_text[kBufSize] = { '\0' };
+  DWORD message_length = ::FormatMessageA(kFlags,
+                                          0,  // no source, we're asking system
+                                          hr,  // the error
+                                          0,  // no line width restrictions
+                                          error_text,  // output buffer
+                                          kBufSize,  // buf size
+                                          NULL);  // no arguments for inserts
+  // Trims tailing white space (FormatMessage leaves a trailing CR-LF)
+  for (; message_length && IsSpace(error_text[message_length - 1]);
+          --message_length) {
+    error_text[message_length - 1] = '\0';
+  }
+
+# endif  // GTEST_OS_WINDOWS_MOBILE
+
+  const std::string error_hex("0x" + String::FormatHexInt(hr));
+  return ::testing::AssertionFailure()
+      << "Expected: " << expr << " " << expected << ".\n"
+      << "  Actual: " << error_hex << " " << error_text << "\n";
+}
+
+}  // namespace
+
+AssertionResult IsHRESULTSuccess(const char* expr, long hr) {  // NOLINT
+  if (SUCCEEDED(hr)) {
+    return AssertionSuccess();
+  }
+  return HRESULTFailureHelper(expr, "succeeds", hr);
+}
+
+AssertionResult IsHRESULTFailure(const char* expr, long hr) {  // NOLINT
+  if (FAILED(hr)) {
+    return AssertionSuccess();
+  }
+  return HRESULTFailureHelper(expr, "fails", hr);
+}
+
+#endif  // GTEST_OS_WINDOWS
+
+// Utility functions for encoding Unicode text (wide strings) in
+// UTF-8.
+
+// A Unicode code-point can have upto 21 bits, and is encoded in UTF-8
+// like this:
+//
+// Code-point length   Encoding
+//   0 -  7 bits       0xxxxxxx
+//   8 - 11 bits       110xxxxx 10xxxxxx
+//  12 - 16 bits       1110xxxx 10xxxxxx 10xxxxxx
+//  17 - 21 bits       11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
+
+// The maximum code-point a one-byte UTF-8 sequence can represent.
+const UInt32 kMaxCodePoint1 = (static_cast<UInt32>(1) <<  7) - 1;
+
+// The maximum code-point a two-byte UTF-8 sequence can represent.
+const UInt32 kMaxCodePoint2 = (static_cast<UInt32>(1) << (5 + 6)) - 1;
+
+// The maximum code-point a three-byte UTF-8 sequence can represent.
+const UInt32 kMaxCodePoint3 = (static_cast<UInt32>(1) << (4 + 2*6)) - 1;
+
+// The maximum code-point a four-byte UTF-8 sequence can represent.
+const UInt32 kMaxCodePoint4 = (static_cast<UInt32>(1) << (3 + 3*6)) - 1;
+
+// Chops off the n lowest bits from a bit pattern.  Returns the n
+// lowest bits.  As a side effect, the original bit pattern will be
+// shifted to the right by n bits.
+inline UInt32 ChopLowBits(UInt32* bits, int n) {
+  const UInt32 low_bits = *bits & ((static_cast<UInt32>(1) << n) - 1);
+  *bits >>= n;
+  return low_bits;
+}
+
+// Converts a Unicode code point to a narrow string in UTF-8 encoding.
+// code_point parameter is of type UInt32 because wchar_t may not be
+// wide enough to contain a code point.
+// If the code_point is not a valid Unicode code point
+// (i.e. outside of Unicode range U+0 to U+10FFFF) it will be converted
+// to "(Invalid Unicode 0xXXXXXXXX)".
+std::string CodePointToUtf8(UInt32 code_point) {
+  if (code_point > kMaxCodePoint4) {
+    return "(Invalid Unicode 0x" + String::FormatHexInt(code_point) + ")";
+  }
+
+  char str[5];  // Big enough for the largest valid code point.
+  if (code_point <= kMaxCodePoint1) {
+    str[1] = '\0';
+    str[0] = static_cast<char>(code_point);                          // 0xxxxxxx
+  } else if (code_point <= kMaxCodePoint2) {
+    str[2] = '\0';
+    str[1] = static_cast<char>(0x80 | ChopLowBits(&code_point, 6));  // 10xxxxxx
+    str[0] = static_cast<char>(0xC0 | code_point);                   // 110xxxxx
+  } else if (code_point <= kMaxCodePoint3) {
+    str[3] = '\0';
+    str[2] = static_cast<char>(0x80 | ChopLowBits(&code_point, 6));  // 10xxxxxx
+    str[1] = static_cast<char>(0x80 | ChopLowBits(&code_point, 6));  // 10xxxxxx
+    str[0] = static_cast<char>(0xE0 | code_point);                   // 1110xxxx
+  } else {  // code_point <= kMaxCodePoint4
+    str[4] = '\0';
+    str[3] = static_cast<char>(0x80 | ChopLowBits(&code_point, 6));  // 10xxxxxx
+    str[2] = static_cast<char>(0x80 | ChopLowBits(&code_point, 6));  // 10xxxxxx
+    str[1] = static_cast<char>(0x80 | ChopLowBits(&code_point, 6));  // 10xxxxxx
+    str[0] = static_cast<char>(0xF0 | code_point);                   // 11110xxx
+  }
+  return str;
+}
+
+// The following two functions only make sense if the the system
+// uses UTF-16 for wide string encoding. All supported systems
+// with 16 bit wchar_t (Windows, Cygwin, Symbian OS) do use UTF-16.
+
+// Determines if the arguments constitute UTF-16 surrogate pair
+// and thus should be combined into a single Unicode code point
+// using CreateCodePointFromUtf16SurrogatePair.
+inline bool IsUtf16SurrogatePair(wchar_t first, wchar_t second) {
+  return sizeof(wchar_t) == 2 &&
+      (first & 0xFC00) == 0xD800 && (second & 0xFC00) == 0xDC00;
+}
+
+// Creates a Unicode code point from UTF16 surrogate pair.
+inline UInt32 CreateCodePointFromUtf16SurrogatePair(wchar_t first,
+                                                    wchar_t second) {
+  const UInt32 mask = (1 << 10) - 1;
+  return (sizeof(wchar_t) == 2) ?
+      (((first & mask) << 10) | (second & mask)) + 0x10000 :
+      // This function should not be called when the condition is
+      // false, but we provide a sensible default in case it is.
+      static_cast<UInt32>(first);
+}
+
+// Converts a wide string to a narrow string in UTF-8 encoding.
+// The wide string is assumed to have the following encoding:
+//   UTF-16 if sizeof(wchar_t) == 2 (on Windows, Cygwin, Symbian OS)
+//   UTF-32 if sizeof(wchar_t) == 4 (on Linux)
+// Parameter str points to a null-terminated wide string.
+// Parameter num_chars may additionally limit the number
+// of wchar_t characters processed. -1 is used when the entire string
+// should be processed.
+// If the string contains code points that are not valid Unicode code points
+// (i.e. outside of Unicode range U+0 to U+10FFFF) they will be output
+// as '(Invalid Unicode 0xXXXXXXXX)'. If the string is in UTF16 encoding
+// and contains invalid UTF-16 surrogate pairs, values in those pairs
+// will be encoded as individual Unicode characters from Basic Normal Plane.
+std::string WideStringToUtf8(const wchar_t* str, int num_chars) {
+  if (num_chars == -1)
+    num_chars = static_cast<int>(wcslen(str));
+
+  ::std::stringstream stream;
+  for (int i = 0; i < num_chars; ++i) {
+    UInt32 unicode_code_point;
+
+    if (str[i] == L'\0') {
+      break;
+    } else if (i + 1 < num_chars && IsUtf16SurrogatePair(str[i], str[i + 1])) {
+      unicode_code_point = CreateCodePointFromUtf16SurrogatePair(str[i],
+                                                                 str[i + 1]);
+      i++;
+    } else {
+      unicode_code_point = static_cast<UInt32>(str[i]);
+    }
+
+    stream << CodePointToUtf8(unicode_code_point);
+  }
+  return StringStreamToString(&stream);
+}
+
+// Converts a wide C string to an std::string using the UTF-8 encoding.
+// NULL will be converted to "(null)".
+std::string String::ShowWideCString(const wchar_t * wide_c_str) {
+  if (wide_c_str == NULL)  return "(null)";
+
+  return internal::WideStringToUtf8(wide_c_str, -1);
+}
+
+// Compares two wide C strings.  Returns true iff they have the same
+// content.
+//
+// Unlike wcscmp(), this function can handle NULL argument(s).  A NULL
+// C string is considered different to any non-NULL C string,
+// including the empty string.
+bool String::WideCStringEquals(const wchar_t * lhs, const wchar_t * rhs) {
+  if (lhs == NULL) return rhs == NULL;
+
+  if (rhs == NULL) return false;
+
+  return wcscmp(lhs, rhs) == 0;
+}
+
+// Helper function for *_STREQ on wide strings.
+AssertionResult CmpHelperSTREQ(const char* expected_expression,
+                               const char* actual_expression,
+                               const wchar_t* expected,
+                               const wchar_t* actual) {
+  if (String::WideCStringEquals(expected, actual)) {
+    return AssertionSuccess();
+  }
+
+  return EqFailure(expected_expression,
+                   actual_expression,
+                   PrintToString(expected),
+                   PrintToString(actual),
+                   false);
+}
+
+// Helper function for *_STRNE on wide strings.
+AssertionResult CmpHelperSTRNE(const char* s1_expression,
+                               const char* s2_expression,
+                               const wchar_t* s1,
+                               const wchar_t* s2) {
+  if (!String::WideCStringEquals(s1, s2)) {
+    return AssertionSuccess();
+  }
+
+  return AssertionFailure() << "Expected: (" << s1_expression << ") != ("
+                            << s2_expression << "), actual: "
+                            << PrintToString(s1)
+                            << " vs " << PrintToString(s2);
+}
+
+// Compares two C strings, ignoring case.  Returns true iff they have
+// the same content.
+//
+// Unlike strcasecmp(), this function can handle NULL argument(s).  A
+// NULL C string is considered different to any non-NULL C string,
+// including the empty string.
+bool String::CaseInsensitiveCStringEquals(const char * lhs, const char * rhs) {
+  if (lhs == NULL)
+    return rhs == NULL;
+  if (rhs == NULL)
+    return false;
+  return posix::StrCaseCmp(lhs, rhs) == 0;
+}
+
+  // Compares two wide C strings, ignoring case.  Returns true iff they
+  // have the same content.
+  //
+  // Unlike wcscasecmp(), this function can handle NULL argument(s).
+  // A NULL C string is considered different to any non-NULL wide C string,
+  // including the empty string.
+  // NB: The implementations on different platforms slightly differ.
+  // On windows, this method uses _wcsicmp which compares according to LC_CTYPE
+  // environment variable. On GNU platform this method uses wcscasecmp
+  // which compares according to LC_CTYPE category of the current locale.
+  // On MacOS X, it uses towlower, which also uses LC_CTYPE category of the
+  // current locale.
+bool String::CaseInsensitiveWideCStringEquals(const wchar_t* lhs,
+                                              const wchar_t* rhs) {
+  if (lhs == NULL) return rhs == NULL;
+
+  if (rhs == NULL) return false;
+
+#if GTEST_OS_WINDOWS
+  return _wcsicmp(lhs, rhs) == 0;
+#elif GTEST_OS_LINUX && !GTEST_OS_LINUX_ANDROID
+  return wcscasecmp(lhs, rhs) == 0;
+#else
+  // Android, Mac OS X and Cygwin don't define wcscasecmp.
+  // Other unknown OSes may not define it either.
+  wint_t left, right;
+  do {
+    left = towlower(*lhs++);
+    right = towlower(*rhs++);
+  } while (left && left == right);
+  return left == right;
+#endif  // OS selector
+}
+
+// Returns true iff str ends with the given suffix, ignoring case.
+// Any string is considered to end with an empty suffix.
+bool String::EndsWithCaseInsensitive(
+    const std::string& str, const std::string& suffix) {
+  const size_t str_len = str.length();
+  const size_t suffix_len = suffix.length();
+  return (str_len >= suffix_len) &&
+         CaseInsensitiveCStringEquals(str.c_str() + str_len - suffix_len,
+                                      suffix.c_str());
+}
+
+// Formats an int value as "%02d".
+std::string String::FormatIntWidth2(int value) {
+  std::stringstream ss;
+  ss << std::setfill('0') << std::setw(2) << value;
+  return ss.str();
+}
+
+// Formats an int value as "%X".
+std::string String::FormatHexInt(int value) {
+  std::stringstream ss;
+  ss << std::hex << std::uppercase << value;
+  return ss.str();
+}
+
+// Formats a byte as "%02X".
+std::string String::FormatByte(unsigned char value) {
+  std::stringstream ss;
+  ss << std::setfill('0') << std::setw(2) << std::hex << std::uppercase
+     << static_cast<unsigned int>(value);
+  return ss.str();
+}
+
+// Converts the buffer in a stringstream to an std::string, converting NUL
+// bytes to "\\0" along the way.
+std::string StringStreamToString(::std::stringstream* ss) {
+  const ::std::string& str = ss->str();
+  const char* const start = str.c_str();
+  const char* const end = start + str.length();
+
+  std::string result;
+  result.reserve(2 * (end - start));
+  for (const char* ch = start; ch != end; ++ch) {
+    if (*ch == '\0') {
+      result += "\\0";  // Replaces NUL with "\\0";
+    } else {
+      result += *ch;
+    }
+  }
+
+  return result;
+}
+
+// Appends the user-supplied message to the Google-Test-generated message.
+std::string AppendUserMessage(const std::string& gtest_msg,
+                              const Message& user_msg) {
+  // Appends the user message if it's non-empty.
+  const std::string user_msg_string = user_msg.GetString();
+  if (user_msg_string.empty()) {
+    return gtest_msg;
+  }
+
+  return gtest_msg + "\n" + user_msg_string;
+}
+
+}  // namespace internal
+
+// class TestResult
+
+// Creates an empty TestResult.
+TestResult::TestResult()
+    : death_test_count_(0),
+      elapsed_time_(0) {
+}
+
+// D'tor.
+TestResult::~TestResult() {
+}
+
+// Returns the i-th test part result among all the results. i can
+// range from 0 to total_part_count() - 1. If i is not in that range,
+// aborts the program.
+const TestPartResult& TestResult::GetTestPartResult(int i) const {
+  if (i < 0 || i >= total_part_count())
+    internal::posix::Abort();
+  return test_part_results_.at(i);
+}
+
+// Returns the i-th test property. i can range from 0 to
+// test_property_count() - 1. If i is not in that range, aborts the
+// program.
+const TestProperty& TestResult::GetTestProperty(int i) const {
+  if (i < 0 || i >= test_property_count())
+    internal::posix::Abort();
+  return test_properties_.at(i);
+}
+
+// Clears the test part results.
+void TestResult::ClearTestPartResults() {
+  test_part_results_.clear();
+}
+
+// Adds a test part result to the list.
+void TestResult::AddTestPartResult(const TestPartResult& test_part_result) {
+  test_part_results_.push_back(test_part_result);
+}
+
+// Adds a test property to the list. If a property with the same key as the
+// supplied property is already represented, the value of this test_property
+// replaces the old value for that key.
+void TestResult::RecordProperty(const std::string& xml_element,
+                                const TestProperty& test_property) {
+  if (!ValidateTestProperty(xml_element, test_property)) {
+    return;
+  }
+  internal::MutexLock lock(&test_properites_mutex_);
+  const std::vector<TestProperty>::iterator property_with_matching_key =
+      std::find_if(test_properties_.begin(), test_properties_.end(),
+                   internal::TestPropertyKeyIs(test_property.key()));
+  if (property_with_matching_key == test_properties_.end()) {
+    test_properties_.push_back(test_property);
+    return;
+  }
+  property_with_matching_key->SetValue(test_property.value());
+}
+
+// The list of reserved attributes used in the <testsuites> element of XML
+// output.
+static const char* const kReservedTestSuitesAttributes[] = {
+  "disabled",
+  "errors",
+  "failures",
+  "name",
+  "random_seed",
+  "tests",
+  "time",
+  "timestamp"
+};
+
+// The list of reserved attributes used in the <testsuite> element of XML
+// output.
+static const char* const kReservedTestSuiteAttributes[] = {
+  "disabled",
+  "errors",
+  "failures",
+  "name",
+  "tests",
+  "time"
+};
+
+// The list of reserved attributes used in the <testcase> element of XML output.
+static const char* const kReservedTestCaseAttributes[] = {
+  "classname",
+  "name",
+  "status",
+  "time",
+  "type_param",
+  "value_param"
+};
+
+template <int kSize>
+std::vector<std::string> ArrayAsVector(const char* const (&array)[kSize]) {
+  return std::vector<std::string>(array, array + kSize);
+}
+
+static std::vector<std::string> GetReservedAttributesForElement(
+    const std::string& xml_element) {
+  if (xml_element == "testsuites") {
+    return ArrayAsVector(kReservedTestSuitesAttributes);
+  } else if (xml_element == "testsuite") {
+    return ArrayAsVector(kReservedTestSuiteAttributes);
+  } else if (xml_element == "testcase") {
+    return ArrayAsVector(kReservedTestCaseAttributes);
+  } else {
+    GTEST_CHECK_(false) << "Unrecognized xml_element provided: " << xml_element;
+  }
+  // This code is unreachable but some compilers may not realizes that.
+  return std::vector<std::string>();
+}
+
+static std::string FormatWordList(const std::vector<std::string>& words) {
+  Message word_list;
+  for (size_t i = 0; i < words.size(); ++i) {
+    if (i > 0 && words.size() > 2) {
+      word_list << ", ";
+    }
+    if (i == words.size() - 1) {
+      word_list << "and ";
+    }
+    word_list << "'" << words[i] << "'";
+  }
+  return word_list.GetString();
+}
+
+bool ValidateTestPropertyName(const std::string& property_name,
+                              const std::vector<std::string>& reserved_names) {
+  if (std::find(reserved_names.begin(), reserved_names.end(), property_name) !=
+          reserved_names.end()) {
+    ADD_FAILURE() << "Reserved key used in RecordProperty(): " << property_name
+                  << " (" << FormatWordList(reserved_names)
+                  << " are reserved by " << GTEST_NAME_ << ")";
+    return false;
+  }
+  return true;
+}
+
+// Adds a failure if the key is a reserved attribute of the element named
+// xml_element.  Returns true if the property is valid.
+bool TestResult::ValidateTestProperty(const std::string& xml_element,
+                                      const TestProperty& test_property) {
+  return ValidateTestPropertyName(test_property.key(),
+                                  GetReservedAttributesForElement(xml_element));
+}
+
+// Clears the object.
+void TestResult::Clear() {
+  test_part_results_.clear();
+  test_properties_.clear();
+  death_test_count_ = 0;
+  elapsed_time_ = 0;
+}
+
+// Returns true iff the test failed.
+bool TestResult::Failed() const {
+  for (int i = 0; i < total_part_count(); ++i) {
+    if (GetTestPartResult(i).failed())
+      return true;
+  }
+  return false;
+}
+
+// Returns true iff the test part fatally failed.
+static bool TestPartFatallyFailed(const TestPartResult& result) {
+  return result.fatally_failed();
+}
+
+// Returns true iff the test fatally failed.
+bool TestResult::HasFatalFailure() const {
+  return CountIf(test_part_results_, TestPartFatallyFailed) > 0;
+}
+
+// Returns true iff the test part non-fatally failed.
+static bool TestPartNonfatallyFailed(const TestPartResult& result) {
+  return result.nonfatally_failed();
+}
+
+// Returns true iff the test has a non-fatal failure.
+bool TestResult::HasNonfatalFailure() const {
+  return CountIf(test_part_results_, TestPartNonfatallyFailed) > 0;
+}
+
+// Gets the number of all test parts.  This is the sum of the number
+// of successful test parts and the number of failed test parts.
+int TestResult::total_part_count() const {
+  return static_cast<int>(test_part_results_.size());
+}
+
+// Returns the number of the test properties.
+int TestResult::test_property_count() const {
+  return static_cast<int>(test_properties_.size());
+}
+
+// class Test
+
+// Creates a Test object.
+
+// The c'tor saves the values of all Google Test flags.
+Test::Test()
+    : gtest_flag_saver_(new internal::GTestFlagSaver) {
+}
+
+// The d'tor restores the values of all Google Test flags.
+Test::~Test() {
+  delete gtest_flag_saver_;
+}
+
+// Sets up the test fixture.
+//
+// A sub-class may override this.
+void Test::SetUp() {
+}
+
+// Tears down the test fixture.
+//
+// A sub-class may override this.
+void Test::TearDown() {
+}
+
+// Allows user supplied key value pairs to be recorded for later output.
+void Test::RecordProperty(const std::string& key, const std::string& value) {
+  UnitTest::GetInstance()->RecordProperty(key, value);
+}
+
+// Allows user supplied key value pairs to be recorded for later output.
+void Test::RecordProperty(const std::string& key, int value) {
+  Message value_message;
+  value_message << value;
+  RecordProperty(key, value_message.GetString().c_str());
+}
+
+namespace internal {
+
+void ReportFailureInUnknownLocation(TestPartResult::Type result_type,
+                                    const std::string& message) {
+  // This function is a friend of UnitTest and as such has access to
+  // AddTestPartResult.
+  UnitTest::GetInstance()->AddTestPartResult(
+      result_type,
+      NULL,  // No info about the source file where the exception occurred.
+      -1,    // We have no info on which line caused the exception.
+      message,
+      "");   // No stack trace, either.
+}
+
+}  // namespace internal
+
+// Google Test requires all tests in the same test case to use the same test
+// fixture class.  This function checks if the current test has the
+// same fixture class as the first test in the current test case.  If
+// yes, it returns true; otherwise it generates a Google Test failure and
+// returns false.
+bool Test::HasSameFixtureClass() {
+  internal::UnitTestImpl* const impl = internal::GetUnitTestImpl();
+  const TestCase* const test_case = impl->current_test_case();
+
+  // Info about the first test in the current test case.
+  const TestInfo* const first_test_info = test_case->test_info_list()[0];
+  const internal::TypeId first_fixture_id = first_test_info->fixture_class_id_;
+  const char* const first_test_name = first_test_info->name();
+
+  // Info about the current test.
+  const TestInfo* const this_test_info = impl->current_test_info();
+  const internal::TypeId this_fixture_id = this_test_info->fixture_class_id_;
+  const char* const this_test_name = this_test_info->name();
+
+  if (this_fixture_id != first_fixture_id) {
+    // Is the first test defined using TEST?
+    const bool first_is_TEST = first_fixture_id == internal::GetTestTypeId();
+    // Is this test defined using TEST?
+    const bool this_is_TEST = this_fixture_id == internal::GetTestTypeId();
+
+    if (first_is_TEST || this_is_TEST) {
+      // The user mixed TEST and TEST_F in this test case - we'll tell
+      // him/her how to fix it.
+
+      // Gets the name of the TEST and the name of the TEST_F.  Note
+      // that first_is_TEST and this_is_TEST cannot both be true, as
+      // the fixture IDs are different for the two tests.
+      const char* const TEST_name =
+          first_is_TEST ? first_test_name : this_test_name;
+      const char* const TEST_F_name =
+          first_is_TEST ? this_test_name : first_test_name;
+
+      ADD_FAILURE()
+          << "All tests in the same test case must use the same test fixture\n"
+          << "class, so mixing TEST_F and TEST in the same test case is\n"
+          << "illegal.  In test case " << this_test_info->test_case_name()
+          << ",\n"
+          << "test " << TEST_F_name << " is defined using TEST_F but\n"
+          << "test " << TEST_name << " is defined using TEST.  You probably\n"
+          << "want to change the TEST to TEST_F or move it to another test\n"
+          << "case.";
+    } else {
+      // The user defined two fixture classes with the same name in
+      // two namespaces - we'll tell him/her how to fix it.
+      ADD_FAILURE()
+          << "All tests in the same test case must use the same test fixture\n"
+          << "class.  However, in test case "
+          << this_test_info->test_case_name() << ",\n"
+          << "you defined test " << first_test_name
+          << " and test " << this_test_name << "\n"
+          << "using two different test fixture classes.  This can happen if\n"
+          << "the two classes are from different namespaces or translation\n"
+          << "units and have the same name.  You should probably rename one\n"
+          << "of the classes to put the tests into different test cases.";
+    }
+    return false;
+  }
+
+  return true;
+}
+
+#if GTEST_HAS_SEH
+
+// Adds an "exception thrown" fatal failure to the current test.  This
+// function returns its result via an output parameter pointer because VC++
+// prohibits creation of objects with destructors on stack in functions
+// using __try (see error C2712).
+static std::string* FormatSehExceptionMessage(DWORD exception_code,
+                                              const char* location) {
+  Message message;
+  message << "SEH exception with code 0x" << std::setbase(16) <<
+    exception_code << std::setbase(10) << " thrown in " << location << ".";
+
+  return new std::string(message.GetString());
+}
+
+#endif  // GTEST_HAS_SEH
+
+namespace internal {
+
+#if GTEST_HAS_EXCEPTIONS
+
+// Adds an "exception thrown" fatal failure to the current test.
+static std::string FormatCxxExceptionMessage(const char* description,
+                                             const char* location) {
+  Message message;
+  if (description != NULL) {
+    message << "C++ exception with description \"" << description << "\"";
+  } else {
+    message << "Unknown C++ exception";
+  }
+  message << " thrown in " << location << ".";
+
+  return message.GetString();
+}
+
+static std::string PrintTestPartResultToString(
+    const TestPartResult& test_part_result);
+
+GoogleTestFailureException::GoogleTestFailureException(
+    const TestPartResult& failure)
+    : ::std::runtime_error(PrintTestPartResultToString(failure).c_str()) {}
+
+#endif  // GTEST_HAS_EXCEPTIONS
+
+// We put these helper functions in the internal namespace as IBM's xlC
+// compiler rejects the code if they were declared static.
+
+// Runs the given method and handles SEH exceptions it throws, when
+// SEH is supported; returns the 0-value for type Result in case of an
+// SEH exception.  (Microsoft compilers cannot handle SEH and C++
+// exceptions in the same function.  Therefore, we provide a separate
+// wrapper function for handling SEH exceptions.)
+template <class T, typename Result>
+Result HandleSehExceptionsInMethodIfSupported(
+    T* object, Result (T::*method)(), const char* location) {
+#if GTEST_HAS_SEH
+  __try {
+    return (object->*method)();
+  } __except (internal::UnitTestOptions::GTestShouldProcessSEH(  // NOLINT
+      GetExceptionCode())) {
+    // We create the exception message on the heap because VC++ prohibits
+    // creation of objects with destructors on stack in functions using __try
+    // (see error C2712).
+    std::string* exception_message = FormatSehExceptionMessage(
+        GetExceptionCode(), location);
+    internal::ReportFailureInUnknownLocation(TestPartResult::kFatalFailure,
+                                             *exception_message);
+    delete exception_message;
+    return static_cast<Result>(0);
+  }
+#else
+  (void)location;
+  return (object->*method)();
+#endif  // GTEST_HAS_SEH
+}
+
+// Runs the given method and catches and reports C++ and/or SEH-style
+// exceptions, if they are supported; returns the 0-value for type
+// Result in case of an SEH exception.
+template <class T, typename Result>
+Result HandleExceptionsInMethodIfSupported(
+    T* object, Result (T::*method)(), const char* location) {
+  // NOTE: The user code can affect the way in which Google Test handles
+  // exceptions by setting GTEST_FLAG(catch_exceptions), but only before
+  // RUN_ALL_TESTS() starts. It is technically possible to check the flag
+  // after the exception is caught and either report or re-throw the
+  // exception based on the flag's value:
+  //
+  // try {
+  //   // Perform the test method.
+  // } catch (...) {
+  //   if (GTEST_FLAG(catch_exceptions))
+  //     // Report the exception as failure.
+  //   else
+  //     throw;  // Re-throws the original exception.
+  // }
+  //
+  // However, the purpose of this flag is to allow the program to drop into
+  // the debugger when the exception is thrown. On most platforms, once the
+  // control enters the catch block, the exception origin information is
+  // lost and the debugger will stop the program at the point of the
+  // re-throw in this function -- instead of at the point of the original
+  // throw statement in the code under test.  For this reason, we perform
+  // the check early, sacrificing the ability to affect Google Test's
+  // exception handling in the method where the exception is thrown.
+  if (internal::GetUnitTestImpl()->catch_exceptions()) {
+#if GTEST_HAS_EXCEPTIONS
+    try {
+      return HandleSehExceptionsInMethodIfSupported(object, method, location);
+    } catch (const internal::GoogleTestFailureException&) {  // NOLINT
+      // This exception type can only be thrown by a failed Google
+      // Test assertion with the intention of letting another testing
+      // framework catch it.  Therefore we just re-throw it.
+      throw;
+    } catch (const std::exception& e) {  // NOLINT
+      internal::ReportFailureInUnknownLocation(
+          TestPartResult::kFatalFailure,
+          FormatCxxExceptionMessage(e.what(), location));
+    } catch (...) {  // NOLINT
+      internal::ReportFailureInUnknownLocation(
+          TestPartResult::kFatalFailure,
+          FormatCxxExceptionMessage(NULL, location));
+    }
+    return static_cast<Result>(0);
+#else
+    return HandleSehExceptionsInMethodIfSupported(object, method, location);
+#endif  // GTEST_HAS_EXCEPTIONS
+  } else {
+    return (object->*method)();
+  }
+}
+
+}  // namespace internal
+
+// Runs the test and updates the test result.
+void Test::Run() {
+  if (!HasSameFixtureClass()) return;
+
+  internal::UnitTestImpl* const impl = internal::GetUnitTestImpl();
+  impl->os_stack_trace_getter()->UponLeavingGTest();
+  internal::HandleExceptionsInMethodIfSupported(this, &Test::SetUp, "SetUp()");
+  // We will run the test only if SetUp() was successful.
+  if (!HasFatalFailure()) {
+    impl->os_stack_trace_getter()->UponLeavingGTest();
+    internal::HandleExceptionsInMethodIfSupported(
+        this, &Test::TestBody, "the test body");
+  }
+
+  // However, we want to clean up as much as possible.  Hence we will
+  // always call TearDown(), even if SetUp() or the test body has
+  // failed.
+  impl->os_stack_trace_getter()->UponLeavingGTest();
+  internal::HandleExceptionsInMethodIfSupported(
+      this, &Test::TearDown, "TearDown()");
+}
+
+// Returns true iff the current test has a fatal failure.
+bool Test::HasFatalFailure() {
+  return internal::GetUnitTestImpl()->current_test_result()->HasFatalFailure();
+}
+
+// Returns true iff the current test has a non-fatal failure.
+bool Test::HasNonfatalFailure() {
+  return internal::GetUnitTestImpl()->current_test_result()->
+      HasNonfatalFailure();
+}
+
+// class TestInfo
+
+// Constructs a TestInfo object. It assumes ownership of the test factory
+// object.
+TestInfo::TestInfo(const std::string& a_test_case_name,
+                   const std::string& a_name,
+                   const char* a_type_param,
+                   const char* a_value_param,
+                   internal::TypeId fixture_class_id,
+                   internal::TestFactoryBase* factory)
+    : test_case_name_(a_test_case_name),
+      name_(a_name),
+      type_param_(a_type_param ? new std::string(a_type_param) : NULL),
+      value_param_(a_value_param ? new std::string(a_value_param) : NULL),
+      fixture_class_id_(fixture_class_id),
+      should_run_(false),
+      is_disabled_(false),
+      matches_filter_(false),
+      factory_(factory),
+      result_() {}
+
+// Destructs a TestInfo object.
+TestInfo::~TestInfo() { delete factory_; }
+
+namespace internal {
+
+// Creates a new TestInfo object and registers it with Google Test;
+// returns the created object.
+//
+// Arguments:
+//
+//   test_case_name:   name of the test case
+//   name:             name of the test
+//   type_param:       the name of the test's type parameter, or NULL if
+//                     this is not a typed or a type-parameterized test.
+//   value_param:      text representation of the test's value parameter,
+//                     or NULL if this is not a value-parameterized test.
+//   fixture_class_id: ID of the test fixture class
+//   set_up_tc:        pointer to the function that sets up the test case
+//   tear_down_tc:     pointer to the function that tears down the test case
+//   factory:          pointer to the factory that creates a test object.
+//                     The newly created TestInfo instance will assume
+//                     ownership of the factory object.
+TestInfo* MakeAndRegisterTestInfo(
+    const char* test_case_name,
+    const char* name,
+    const char* type_param,
+    const char* value_param,
+    TypeId fixture_class_id,
+    SetUpTestCaseFunc set_up_tc,
+    TearDownTestCaseFunc tear_down_tc,
+    TestFactoryBase* factory) {
+  TestInfo* const test_info =
+      new TestInfo(test_case_name, name, type_param, value_param,
+                   fixture_class_id, factory);
+  GetUnitTestImpl()->AddTestInfo(set_up_tc, tear_down_tc, test_info);
+  return test_info;
+}
+
+#if GTEST_HAS_PARAM_TEST
+void ReportInvalidTestCaseType(const char* test_case_name,
+                               const char* file, int line) {
+  Message errors;
+  errors
+      << "Attempted redefinition of test case " << test_case_name << ".\n"
+      << "All tests in the same test case must use the same test fixture\n"
+      << "class.  However, in test case " << test_case_name << ", you tried\n"
+      << "to define a test using a fixture class different from the one\n"
+      << "used earlier. This can happen if the two fixture classes are\n"
+      << "from different namespaces and have the same name. You should\n"
+      << "probably rename one of the classes to put the tests into different\n"
+      << "test cases.";
+
+  fprintf(stderr, "%s %s", FormatFileLocation(file, line).c_str(),
+          errors.GetString().c_str());
+}
+#endif  // GTEST_HAS_PARAM_TEST
+
+}  // namespace internal
+
+namespace {
+
+// A predicate that checks the test name of a TestInfo against a known
+// value.
+//
+// This is used for implementation of the TestCase class only.  We put
+// it in the anonymous namespace to prevent polluting the outer
+// namespace.
+//
+// TestNameIs is copyable.
+class TestNameIs {
+ public:
+  // Constructor.
+  //
+  // TestNameIs has NO default constructor.
+  explicit TestNameIs(const char* name)
+      : name_(name) {}
+
+  // Returns true iff the test name of test_info matches name_.
+  bool operator()(const TestInfo * test_info) const {
+    return test_info && test_info->name() == name_;
+  }
+
+ private:
+  std::string name_;
+};
+
+}  // namespace
+
+namespace internal {
+
+// This method expands all parameterized tests registered with macros TEST_P
+// and INSTANTIATE_TEST_CASE_P into regular tests and registers those.
+// This will be done just once during the program runtime.
+void UnitTestImpl::RegisterParameterizedTests() {
+#if GTEST_HAS_PARAM_TEST
+  if (!parameterized_tests_registered_) {
+    parameterized_test_registry_.RegisterTests();
+    parameterized_tests_registered_ = true;
+  }
+#endif
+}
+
+}  // namespace internal
+
+// Creates the test object, runs it, records its result, and then
+// deletes it.
+void TestInfo::Run() {
+  if (!should_run_) return;
+
+  // Tells UnitTest where to store test result.
+  internal::UnitTestImpl* const impl = internal::GetUnitTestImpl();
+  impl->set_current_test_info(this);
+
+  TestEventListener* repeater = UnitTest::GetInstance()->listeners().repeater();
+
+  // Notifies the unit test event listeners that a test is about to start.
+  repeater->OnTestStart(*this);
+
+  const TimeInMillis start = internal::GetTimeInMillis();
+
+  impl->os_stack_trace_getter()->UponLeavingGTest();
+
+  // Creates the test object.
+  Test* const test = internal::HandleExceptionsInMethodIfSupported(
+      factory_, &internal::TestFactoryBase::CreateTest,
+      "the test fixture's constructor");
+
+  // Runs the test only if the test object was created and its
+  // constructor didn't generate a fatal failure.
+  if ((test != NULL) && !Test::HasFatalFailure()) {
+    // This doesn't throw as all user code that can throw are wrapped into
+    // exception handling code.
+    test->Run();
+  }
+
+  // Deletes the test object.
+  impl->os_stack_trace_getter()->UponLeavingGTest();
+  internal::HandleExceptionsInMethodIfSupported(
+      test, &Test::DeleteSelf_, "the test fixture's destructor");
+
+  result_.set_elapsed_time(internal::GetTimeInMillis() - start);
+
+  // Notifies the unit test event listener that a test has just finished.
+  repeater->OnTestEnd(*this);
+
+  // Tells UnitTest to stop associating assertion results to this
+  // test.
+  impl->set_current_test_info(NULL);
+}
+
+// class TestCase
+
+// Gets the number of successful tests in this test case.
+int TestCase::successful_test_count() const {
+  return CountIf(test_info_list_, TestPassed);
+}
+
+// Gets the number of failed tests in this test case.
+int TestCase::failed_test_count() const {
+  return CountIf(test_info_list_, TestFailed);
+}
+
+// Gets the number of disabled tests that will be reported in the XML report.
+int TestCase::reportable_disabled_test_count() const {
+  return CountIf(test_info_list_, TestReportableDisabled);
+}
+
+// Gets the number of disabled tests in this test case.
+int TestCase::disabled_test_count() const {
+  return CountIf(test_info_list_, TestDisabled);
+}
+
+// Gets the number of tests to be printed in the XML report.
+int TestCase::reportable_test_count() const {
+  return CountIf(test_info_list_, TestReportable);
+}
+
+// Get the number of tests in this test case that should run.
+int TestCase::test_to_run_count() const {
+  return CountIf(test_info_list_, ShouldRunTest);
+}
+
+// Gets the number of all tests.
+int TestCase::total_test_count() const {
+  return static_cast<int>(test_info_list_.size());
+}
+
+// Creates a TestCase with the given name.
+//
+// Arguments:
+//
+//   name:         name of the test case
+//   a_type_param: the name of the test case's type parameter, or NULL if
+//                 this is not a typed or a type-parameterized test case.
+//   set_up_tc:    pointer to the function that sets up the test case
+//   tear_down_tc: pointer to the function that tears down the test case
+TestCase::TestCase(const char* a_name, const char* a_type_param,
+                   Test::SetUpTestCaseFunc set_up_tc,
+                   Test::TearDownTestCaseFunc tear_down_tc)
+    : name_(a_name),
+      type_param_(a_type_param ? new std::string(a_type_param) : NULL),
+      set_up_tc_(set_up_tc),
+      tear_down_tc_(tear_down_tc),
+      should_run_(false),
+      elapsed_time_(0) {
+}
+
+// Destructor of TestCase.
+TestCase::~TestCase() {
+  // Deletes every Test in the collection.
+  ForEach(test_info_list_, internal::Delete<TestInfo>);
+}
+
+// Returns the i-th test among all the tests. i can range from 0 to
+// total_test_count() - 1. If i is not in that range, returns NULL.
+const TestInfo* TestCase::GetTestInfo(int i) const {
+  const int index = GetElementOr(test_indices_, i, -1);
+  return index < 0 ? NULL : test_info_list_[index];
+}
+
+// Returns the i-th test among all the tests. i can range from 0 to
+// total_test_count() - 1. If i is not in that range, returns NULL.
+TestInfo* TestCase::GetMutableTestInfo(int i) {
+  const int index = GetElementOr(test_indices_, i, -1);
+  return index < 0 ? NULL : test_info_list_[index];
+}
+
+// Adds a test to this test case.  Will delete the test upon
+// destruction of the TestCase object.
+void TestCase::AddTestInfo(TestInfo * test_info) {
+  test_info_list_.push_back(test_info);
+  test_indices_.push_back(static_cast<int>(test_indices_.size()));
+}
+
+// Runs every test in this TestCase.
+void TestCase::Run() {
+  if (!should_run_) return;
+
+  internal::UnitTestImpl* const impl = internal::GetUnitTestImpl();
+  impl->set_current_test_case(this);
+
+  TestEventListener* repeater = UnitTest::GetInstance()->listeners().repeater();
+
+  repeater->OnTestCaseStart(*this);
+  impl->os_stack_trace_getter()->UponLeavingGTest();
+  internal::HandleExceptionsInMethodIfSupported(
+      this, &TestCase::RunSetUpTestCase, "SetUpTestCase()");
+
+  const internal::TimeInMillis start = internal::GetTimeInMillis();
+  for (int i = 0; i < total_test_count(); i++) {
+    GetMutableTestInfo(i)->Run();
+  }
+  elapsed_time_ = internal::GetTimeInMillis() - start;
+
+  impl->os_stack_trace_getter()->UponLeavingGTest();
+  internal::HandleExceptionsInMethodIfSupported(
+      this, &TestCase::RunTearDownTestCase, "TearDownTestCase()");
+
+  repeater->OnTestCaseEnd(*this);
+  impl->set_current_test_case(NULL);
+}
+
+// Clears the results of all tests in this test case.
+void TestCase::ClearResult() {
+  ad_hoc_test_result_.Clear();
+  ForEach(test_info_list_, TestInfo::ClearTestResult);
+}
+
+// Shuffles the tests in this test case.
+void TestCase::ShuffleTests(internal::Random* random) {
+  Shuffle(random, &test_indices_);
+}
+
+// Restores the test order to before the first shuffle.
+void TestCase::UnshuffleTests() {
+  for (size_t i = 0; i < test_indices_.size(); i++) {
+    test_indices_[i] = static_cast<int>(i);
+  }
+}
+
+// Formats a countable noun.  Depending on its quantity, either the
+// singular form or the plural form is used. e.g.
+//
+// FormatCountableNoun(1, "formula", "formuli") returns "1 formula".
+// FormatCountableNoun(5, "book", "books") returns "5 books".
+static std::string FormatCountableNoun(int count,
+                                       const char * singular_form,
+                                       const char * plural_form) {
+  return internal::StreamableToString(count) + " " +
+      (count == 1 ? singular_form : plural_form);
+}
+
+// Formats the count of tests.
+static std::string FormatTestCount(int test_count) {
+  return FormatCountableNoun(test_count, "test", "tests");
+}
+
+// Formats the count of test cases.
+static std::string FormatTestCaseCount(int test_case_count) {
+  return FormatCountableNoun(test_case_count, "test case", "test cases");
+}
+
+// Converts a TestPartResult::Type enum to human-friendly string
+// representation.  Both kNonFatalFailure and kFatalFailure are translated
+// to "Failure", as the user usually doesn't care about the difference
+// between the two when viewing the test result.
+static const char * TestPartResultTypeToString(TestPartResult::Type type) {
+  switch (type) {
+    case TestPartResult::kSuccess:
+      return "Success";
+
+    case TestPartResult::kNonFatalFailure:
+    case TestPartResult::kFatalFailure:
+#ifdef _MSC_VER
+      return "error: ";
+#else
+      return "Failure\n";
+#endif
+    default:
+      return "Unknown result type";
+  }
+}
+
+namespace internal {
+
+// Prints a TestPartResult to an std::string.
+static std::string PrintTestPartResultToString(
+    const TestPartResult& test_part_result) {
+  return (Message()
+          << internal::FormatFileLocation(test_part_result.file_name(),
+                                          test_part_result.line_number())
+          << " " << TestPartResultTypeToString(test_part_result.type())
+          << test_part_result.message()).GetString();
+}
+
+// Prints a TestPartResult.
+static void PrintTestPartResult(const TestPartResult& test_part_result) {
+  const std::string& result =
+      PrintTestPartResultToString(test_part_result);
+  printf("%s\n", result.c_str());
+  fflush(stdout);
+  // If the test program runs in Visual Studio or a debugger, the
+  // following statements add the test part result message to the Output
+  // window such that the user can double-click on it to jump to the
+  // corresponding source code location; otherwise they do nothing.
+#if GTEST_OS_WINDOWS && !GTEST_OS_WINDOWS_MOBILE
+  // We don't call OutputDebugString*() on Windows Mobile, as printing
+  // to stdout is done by OutputDebugString() there already - we don't
+  // want the same message printed twice.
+  ::OutputDebugStringA(result.c_str());
+  ::OutputDebugStringA("\n");
+#endif
+}
+
+// class PrettyUnitTestResultPrinter
+
+enum GTestColor {
+  COLOR_DEFAULT,
+  COLOR_RED,
+  COLOR_GREEN,
+  COLOR_YELLOW
+};
+
+#if GTEST_OS_WINDOWS && !GTEST_OS_WINDOWS_MOBILE
+
+// Returns the character attribute for the given color.
+WORD GetColorAttribute(GTestColor color) {
+  switch (color) {
+    case COLOR_RED:    return FOREGROUND_RED;
+    case COLOR_GREEN:  return FOREGROUND_GREEN;
+    case COLOR_YELLOW: return FOREGROUND_RED | FOREGROUND_GREEN;
+    default:           return 0;
+  }
+}
+
+#else
+
+// Returns the ANSI color code for the given color.  COLOR_DEFAULT is
+// an invalid input.
+const char* GetAnsiColorCode(GTestColor color) {
+  switch (color) {
+    case COLOR_RED:     return "1";
+    case COLOR_GREEN:   return "2";
+    case COLOR_YELLOW:  return "3";
+    default:            return NULL;
+  };
+}
+
+#endif  // GTEST_OS_WINDOWS && !GTEST_OS_WINDOWS_MOBILE
+
+// Returns true iff Google Test should use colors in the output.
+bool ShouldUseColor(bool stdout_is_tty) {
+  const char* const gtest_color = GTEST_FLAG(color).c_str();
+
+  if (String::CaseInsensitiveCStringEquals(gtest_color, "auto")) {
+#if GTEST_OS_WINDOWS
+    // On Windows the TERM variable is usually not set, but the
+    // console there does support colors.
+    return stdout_is_tty;
+#else
+    // On non-Windows platforms, we rely on the TERM variable.
+    const char* const term = posix::GetEnv("TERM");
+    const bool term_supports_color =
+        String::CStringEquals(term, "xterm") ||
+        String::CStringEquals(term, "xterm-color") ||
+        String::CStringEquals(term, "xterm-256color") ||
+        String::CStringEquals(term, "screen") ||
+        String::CStringEquals(term, "screen-256color") ||
+        String::CStringEquals(term, "linux") ||
+        String::CStringEquals(term, "cygwin");
+    return stdout_is_tty && term_supports_color;
+#endif  // GTEST_OS_WINDOWS
+  }
+
+  return String::CaseInsensitiveCStringEquals(gtest_color, "yes") ||
+      String::CaseInsensitiveCStringEquals(gtest_color, "true") ||
+      String::CaseInsensitiveCStringEquals(gtest_color, "t") ||
+      String::CStringEquals(gtest_color, "1");
+  // We take "yes", "true", "t", and "1" as meaning "yes".  If the
+  // value is neither one of these nor "auto", we treat it as "no" to
+  // be conservative.
+}
+
+// Helpers for printing colored strings to stdout. Note that on Windows, we
+// cannot simply emit special characters and have the terminal change colors.
+// This routine must actually emit the characters rather than return a string
+// that would be colored when printed, as can be done on Linux.
+void ColoredPrintf(GTestColor color, const char* fmt, ...) {
+  va_list args;
+  va_start(args, fmt);
+
+#if GTEST_OS_WINDOWS_MOBILE || GTEST_OS_SYMBIAN || GTEST_OS_ZOS || GTEST_OS_IOS
+  const bool use_color = false;
+#else
+  static const bool in_color_mode =
+      ShouldUseColor(posix::IsATTY(posix::FileNo(stdout)) != 0);
+  const bool use_color = in_color_mode && (color != COLOR_DEFAULT);
+#endif  // GTEST_OS_WINDOWS_MOBILE || GTEST_OS_SYMBIAN || GTEST_OS_ZOS
+  // The '!= 0' comparison is necessary to satisfy MSVC 7.1.
+
+  if (!use_color) {
+    vprintf(fmt, args);
+    va_end(args);
+    return;
+  }
+
+#if GTEST_OS_WINDOWS && !GTEST_OS_WINDOWS_MOBILE
+  const HANDLE stdout_handle = GetStdHandle(STD_OUTPUT_HANDLE);
+
+  // Gets the current text color.
+  CONSOLE_SCREEN_BUFFER_INFO buffer_info;
+  GetConsoleScreenBufferInfo(stdout_handle, &buffer_info);
+  const WORD old_color_attrs = buffer_info.wAttributes;
+
+  // We need to flush the stream buffers into the console before each
+  // SetConsoleTextAttribute call lest it affect the text that is already
+  // printed but has not yet reached the console.
+  fflush(stdout);
+  SetConsoleTextAttribute(stdout_handle,
+                          GetColorAttribute(color) | FOREGROUND_INTENSITY);
+  vprintf(fmt, args);
+
+  fflush(stdout);
+  // Restores the text color.
+  SetConsoleTextAttribute(stdout_handle, old_color_attrs);
+#else
+  printf("\033[0;3%sm", GetAnsiColorCode(color));
+  vprintf(fmt, args);
+  printf("\033[m");  // Resets the terminal to default.
+#endif  // GTEST_OS_WINDOWS && !GTEST_OS_WINDOWS_MOBILE
+  va_end(args);
+}
+
+// Text printed in Google Test's text output and --gunit_list_tests
+// output to label the type parameter and value parameter for a test.
+static const char kTypeParamLabel[] = "TypeParam";
+static const char kValueParamLabel[] = "GetParam()";
+
+void PrintFullTestCommentIfPresent(const TestInfo& test_info) {
+  const char* const type_param = test_info.type_param();
+  const char* const value_param = test_info.value_param();
+
+  if (type_param != NULL || value_param != NULL) {
+    printf(", where ");
+    if (type_param != NULL) {
+      printf("%s = %s", kTypeParamLabel, type_param);
+      if (value_param != NULL)
+        printf(" and ");
+    }
+    if (value_param != NULL) {
+      printf("%s = %s", kValueParamLabel, value_param);
+    }
+  }
+}
+
+// This class implements the TestEventListener interface.
+//
+// Class PrettyUnitTestResultPrinter is copyable.
+class PrettyUnitTestResultPrinter : public TestEventListener {
+ public:
+  PrettyUnitTestResultPrinter() {}
+  static void PrintTestName(const char * test_case, const char * test) {
+    printf("%s.%s", test_case, test);
+  }
+
+  // The following methods override what's in the TestEventListener class.
+  virtual void OnTestProgramStart(const UnitTest& /*unit_test*/) {}
+  virtual void OnTestIterationStart(const UnitTest& unit_test, int iteration);
+  virtual void OnEnvironmentsSetUpStart(const UnitTest& unit_test);
+  virtual void OnEnvironmentsSetUpEnd(const UnitTest& /*unit_test*/) {}
+  virtual void OnTestCaseStart(const TestCase& test_case);
+  virtual void OnTestStart(const TestInfo& test_info);
+  virtual void OnTestPartResult(const TestPartResult& result);
+  virtual void OnTestEnd(const TestInfo& test_info);
+  virtual void OnTestCaseEnd(const TestCase& test_case);
+  virtual void OnEnvironmentsTearDownStart(const UnitTest& unit_test);
+  virtual void OnEnvironmentsTearDownEnd(const UnitTest& /*unit_test*/) {}
+  virtual void OnTestIterationEnd(const UnitTest& unit_test, int iteration);
+  virtual void OnTestProgramEnd(const UnitTest& /*unit_test*/) {}
+
+ private:
+  static void PrintFailedTests(const UnitTest& unit_test);
+};
+
+  // Fired before each iteration of tests starts.
+void PrettyUnitTestResultPrinter::OnTestIterationStart(
+    const UnitTest& unit_test, int iteration) {
+  if (GTEST_FLAG(repeat) != 1)
+    printf("\nRepeating all tests (iteration %d) . . .\n\n", iteration + 1);
+
+  const char* const filter = GTEST_FLAG(filter).c_str();
+
+  // Prints the filter if it's not *.  This reminds the user that some
+  // tests may be skipped.
+  if (!String::CStringEquals(filter, kUniversalFilter)) {
+    ColoredPrintf(COLOR_YELLOW,
+                  "Note: %s filter = %s\n", GTEST_NAME_, filter);
+  }
+
+  if (internal::ShouldShard(kTestTotalShards, kTestShardIndex, false)) {
+    const Int32 shard_index = Int32FromEnvOrDie(kTestShardIndex, -1);
+    ColoredPrintf(COLOR_YELLOW,
+                  "Note: This is test shard %d of %s.\n",
+                  static_cast<int>(shard_index) + 1,
+                  internal::posix::GetEnv(kTestTotalShards));
+  }
+
+  if (GTEST_FLAG(shuffle)) {
+    ColoredPrintf(COLOR_YELLOW,
+                  "Note: Randomizing tests' orders with a seed of %d .\n",
+                  unit_test.random_seed());
+  }
+
+  ColoredPrintf(COLOR_GREEN,  "[==========] ");
+  printf("Running %s from %s.\n",
+         FormatTestCount(unit_test.test_to_run_count()).c_str(),
+         FormatTestCaseCount(unit_test.test_case_to_run_count()).c_str());
+  fflush(stdout);
+}
+
+void PrettyUnitTestResultPrinter::OnEnvironmentsSetUpStart(
+    const UnitTest& /*unit_test*/) {
+  ColoredPrintf(COLOR_GREEN,  "[----------] ");
+  printf("Global test environment set-up.\n");
+  fflush(stdout);
+}
+
+void PrettyUnitTestResultPrinter::OnTestCaseStart(const TestCase& test_case) {
+  const std::string counts =
+      FormatCountableNoun(test_case.test_to_run_count(), "test", "tests");
+  ColoredPrintf(COLOR_GREEN, "[----------] ");
+  printf("%s from %s", counts.c_str(), test_case.name());
+  if (test_case.type_param() == NULL) {
+    printf("\n");
+  } else {
+    printf(", where %s = %s\n", kTypeParamLabel, test_case.type_param());
+  }
+  fflush(stdout);
+}
+
+void PrettyUnitTestResultPrinter::OnTestStart(const TestInfo& test_info) {
+  ColoredPrintf(COLOR_GREEN,  "[ RUN      ] ");
+  PrintTestName(test_info.test_case_name(), test_info.name());
+  printf("\n");
+  fflush(stdout);
+}
+
+// Called after an assertion failure.
+void PrettyUnitTestResultPrinter::OnTestPartResult(
+    const TestPartResult& result) {
+  // If the test part succeeded, we don't need to do anything.
+  if (result.type() == TestPartResult::kSuccess)
+    return;
+
+  // Print failure message from the assertion (e.g. expected this and got that).
+  PrintTestPartResult(result);
+  fflush(stdout);
+}
+
+void PrettyUnitTestResultPrinter::OnTestEnd(const TestInfo& test_info) {
+  if (test_info.result()->Passed()) {
+    ColoredPrintf(COLOR_GREEN, "[       OK ] ");
+  } else {
+    ColoredPrintf(COLOR_RED, "[  FAILED  ] ");
+  }
+  PrintTestName(test_info.test_case_name(), test_info.name());
+  if (test_info.result()->Failed())
+    PrintFullTestCommentIfPresent(test_info);
+
+  if (GTEST_FLAG(print_time)) {
+    printf(" (%s ms)\n", internal::StreamableToString(
+           test_info.result()->elapsed_time()).c_str());
+  } else {
+    printf("\n");
+  }
+  fflush(stdout);
+}
+
+void PrettyUnitTestResultPrinter::OnTestCaseEnd(const TestCase& test_case) {
+  if (!GTEST_FLAG(print_time)) return;
+
+  const std::string counts =
+      FormatCountableNoun(test_case.test_to_run_count(), "test", "tests");
+  ColoredPrintf(COLOR_GREEN, "[----------] ");
+  printf("%s from %s (%s ms total)\n\n",
+         counts.c_str(), test_case.name(),
+         internal::StreamableToString(test_case.elapsed_time()).c_str());
+  fflush(stdout);
+}
+
+void PrettyUnitTestResultPrinter::OnEnvironmentsTearDownStart(
+    const UnitTest& /*unit_test*/) {
+  ColoredPrintf(COLOR_GREEN,  "[----------] ");
+  printf("Global test environment tear-down\n");
+  fflush(stdout);
+}
+
+// Internal helper for printing the list of failed tests.
+void PrettyUnitTestResultPrinter::PrintFailedTests(const UnitTest& unit_test) {
+  const int failed_test_count = unit_test.failed_test_count();
+  if (failed_test_count == 0) {
+    return;
+  }
+
+  for (int i = 0; i < unit_test.total_test_case_count(); ++i) {
+    const TestCase& test_case = *unit_test.GetTestCase(i);
+    if (!test_case.should_run() || (test_case.failed_test_count() == 0)) {
+      continue;
+    }
+    for (int j = 0; j < test_case.total_test_count(); ++j) {
+      const TestInfo& test_info = *test_case.GetTestInfo(j);
+      if (!test_info.should_run() || test_info.result()->Passed()) {
+        continue;
+      }
+      ColoredPrintf(COLOR_RED, "[  FAILED  ] ");
+      printf("%s.%s", test_case.name(), test_info.name());
+      PrintFullTestCommentIfPresent(test_info);
+      printf("\n");
+    }
+  }
+}
+
+void PrettyUnitTestResultPrinter::OnTestIterationEnd(const UnitTest& unit_test,
+                                                     int /*iteration*/) {
+  ColoredPrintf(COLOR_GREEN,  "[==========] ");
+  printf("%s from %s ran.",
+         FormatTestCount(unit_test.test_to_run_count()).c_str(),
+         FormatTestCaseCount(unit_test.test_case_to_run_count()).c_str());
+  if (GTEST_FLAG(print_time)) {
+    printf(" (%s ms total)",
+           internal::StreamableToString(unit_test.elapsed_time()).c_str());
+  }
+  printf("\n");
+  ColoredPrintf(COLOR_GREEN,  "[  PASSED  ] ");
+  printf("%s.\n", FormatTestCount(unit_test.successful_test_count()).c_str());
+
+  int num_failures = unit_test.failed_test_count();
+  if (!unit_test.Passed()) {
+    const int failed_test_count = unit_test.failed_test_count();
+    ColoredPrintf(COLOR_RED,  "[  FAILED  ] ");
+    printf("%s, listed below:\n", FormatTestCount(failed_test_count).c_str());
+    PrintFailedTests(unit_test);
+    printf("\n%2d FAILED %s\n", num_failures,
+                        num_failures == 1 ? "TEST" : "TESTS");
+  }
+
+  int num_disabled = unit_test.reportable_disabled_test_count();
+  if (num_disabled && !GTEST_FLAG(also_run_disabled_tests)) {
+    if (!num_failures) {
+      printf("\n");  // Add a spacer if no FAILURE banner is displayed.
+    }
+    ColoredPrintf(COLOR_YELLOW,
+                  "  YOU HAVE %d DISABLED %s\n\n",
+                  num_disabled,
+                  num_disabled == 1 ? "TEST" : "TESTS");
+  }
+  // Ensure that Google Test output is printed before, e.g., heapchecker output.
+  fflush(stdout);
+}
+
+// End PrettyUnitTestResultPrinter
+
+// class TestEventRepeater
+//
+// This class forwards events to other event listeners.
+class TestEventRepeater : public TestEventListener {
+ public:
+  TestEventRepeater() : forwarding_enabled_(true) {}
+  virtual ~TestEventRepeater();
+  void Append(TestEventListener *listener);
+  TestEventListener* Release(TestEventListener* listener);
+
+  // Controls whether events will be forwarded to listeners_. Set to false
+  // in death test child processes.
+  bool forwarding_enabled() const { return forwarding_enabled_; }
+  void set_forwarding_enabled(bool enable) { forwarding_enabled_ = enable; }
+
+  virtual void OnTestProgramStart(const UnitTest& unit_test);
+  virtual void OnTestIterationStart(const UnitTest& unit_test, int iteration);
+  virtual void OnEnvironmentsSetUpStart(const UnitTest& unit_test);
+  virtual void OnEnvironmentsSetUpEnd(const UnitTest& unit_test);
+  virtual void OnTestCaseStart(const TestCase& test_case);
+  virtual void OnTestStart(const TestInfo& test_info);
+  virtual void OnTestPartResult(const TestPartResult& result);
+  virtual void OnTestEnd(const TestInfo& test_info);
+  virtual void OnTestCaseEnd(const TestCase& test_case);
+  virtual void OnEnvironmentsTearDownStart(const UnitTest& unit_test);
+  virtual void OnEnvironmentsTearDownEnd(const UnitTest& unit_test);
+  virtual void OnTestIterationEnd(const UnitTest& unit_test, int iteration);
+  virtual void OnTestProgramEnd(const UnitTest& unit_test);
+
+ private:
+  // Controls whether events will be forwarded to listeners_. Set to false
+  // in death test child processes.
+  bool forwarding_enabled_;
+  // The list of listeners that receive events.
+  std::vector<TestEventListener*> listeners_;
+
+  GTEST_DISALLOW_COPY_AND_ASSIGN_(TestEventRepeater);
+};
+
+TestEventRepeater::~TestEventRepeater() {
+  ForEach(listeners_, Delete<TestEventListener>);
+}
+
+void TestEventRepeater::Append(TestEventListener *listener) {
+  listeners_.push_back(listener);
+}
+
+// TODO(vladl at google.com): Factor the search functionality into Vector::Find.
+TestEventListener* TestEventRepeater::Release(TestEventListener *listener) {
+  for (size_t i = 0; i < listeners_.size(); ++i) {
+    if (listeners_[i] == listener) {
+      listeners_.erase(listeners_.begin() + i);
+      return listener;
+    }
+  }
+
+  return NULL;
+}
+
+// Since most methods are very similar, use macros to reduce boilerplate.
+// This defines a member that forwards the call to all listeners.
+#define GTEST_REPEATER_METHOD_(Name, Type) \
+void TestEventRepeater::Name(const Type& parameter) { \
+  if (forwarding_enabled_) { \
+    for (size_t i = 0; i < listeners_.size(); i++) { \
+      listeners_[i]->Name(parameter); \
+    } \
+  } \
+}
+// This defines a member that forwards the call to all listeners in reverse
+// order.
+#define GTEST_REVERSE_REPEATER_METHOD_(Name, Type) \
+void TestEventRepeater::Name(const Type& parameter) { \
+  if (forwarding_enabled_) { \
+    for (int i = static_cast<int>(listeners_.size()) - 1; i >= 0; i--) { \
+      listeners_[i]->Name(parameter); \
+    } \
+  } \
+}
+
+GTEST_REPEATER_METHOD_(OnTestProgramStart, UnitTest)
+GTEST_REPEATER_METHOD_(OnEnvironmentsSetUpStart, UnitTest)
+GTEST_REPEATER_METHOD_(OnTestCaseStart, TestCase)
+GTEST_REPEATER_METHOD_(OnTestStart, TestInfo)
+GTEST_REPEATER_METHOD_(OnTestPartResult, TestPartResult)
+GTEST_REPEATER_METHOD_(OnEnvironmentsTearDownStart, UnitTest)
+GTEST_REVERSE_REPEATER_METHOD_(OnEnvironmentsSetUpEnd, UnitTest)
+GTEST_REVERSE_REPEATER_METHOD_(OnEnvironmentsTearDownEnd, UnitTest)
+GTEST_REVERSE_REPEATER_METHOD_(OnTestEnd, TestInfo)
+GTEST_REVERSE_REPEATER_METHOD_(OnTestCaseEnd, TestCase)
+GTEST_REVERSE_REPEATER_METHOD_(OnTestProgramEnd, UnitTest)
+
+#undef GTEST_REPEATER_METHOD_
+#undef GTEST_REVERSE_REPEATER_METHOD_
+
+void TestEventRepeater::OnTestIterationStart(const UnitTest& unit_test,
+                                             int iteration) {
+  if (forwarding_enabled_) {
+    for (size_t i = 0; i < listeners_.size(); i++) {
+      listeners_[i]->OnTestIterationStart(unit_test, iteration);
+    }
+  }
+}
+
+void TestEventRepeater::OnTestIterationEnd(const UnitTest& unit_test,
+                                           int iteration) {
+  if (forwarding_enabled_) {
+    for (int i = static_cast<int>(listeners_.size()) - 1; i >= 0; i--) {
+      listeners_[i]->OnTestIterationEnd(unit_test, iteration);
+    }
+  }
+}
+
+// End TestEventRepeater
+
+// This class generates an XML output file.
+class XmlUnitTestResultPrinter : public EmptyTestEventListener {
+ public:
+  explicit XmlUnitTestResultPrinter(const char* output_file);
+
+  virtual void OnTestIterationEnd(const UnitTest& unit_test, int iteration);
+
+ private:
+  // Is c a whitespace character that is normalized to a space character
+  // when it appears in an XML attribute value?
+  static bool IsNormalizableWhitespace(char c) {
+    return c == 0x9 || c == 0xA || c == 0xD;
+  }
+
+  // May c appear in a well-formed XML document?
+  static bool IsValidXmlCharacter(char c) {
+    return IsNormalizableWhitespace(c) || c >= 0x20;
+  }
+
+  // Returns an XML-escaped copy of the input string str.  If
+  // is_attribute is true, the text is meant to appear as an attribute
+  // value, and normalizable whitespace is preserved by replacing it
+  // with character references.
+  static std::string EscapeXml(const std::string& str, bool is_attribute);
+
+  // Returns the given string with all characters invalid in XML removed.
+  static std::string RemoveInvalidXmlCharacters(const std::string& str);
+
+  // Convenience wrapper around EscapeXml when str is an attribute value.
+  static std::string EscapeXmlAttribute(const std::string& str) {
+    return EscapeXml(str, true);
+  }
+
+  // Convenience wrapper around EscapeXml when str is not an attribute value.
+  static std::string EscapeXmlText(const char* str) {
+    return EscapeXml(str, false);
+  }
+
+  // Verifies that the given attribute belongs to the given element and
+  // streams the attribute as XML.
+  static void OutputXmlAttribute(std::ostream* stream,
+                                 const std::string& element_name,
+                                 const std::string& name,
+                                 const std::string& value);
+
+  // Streams an XML CDATA section, escaping invalid CDATA sequences as needed.
+  static void OutputXmlCDataSection(::std::ostream* stream, const char* data);
+
+  // Streams an XML representation of a TestInfo object.
+  static void OutputXmlTestInfo(::std::ostream* stream,
+                                const char* test_case_name,
+                                const TestInfo& test_info);
+
+  // Prints an XML representation of a TestCase object
+  static void PrintXmlTestCase(::std::ostream* stream,
+                               const TestCase& test_case);
+
+  // Prints an XML summary of unit_test to output stream out.
+  static void PrintXmlUnitTest(::std::ostream* stream,
+                               const UnitTest& unit_test);
+
+  // Produces a string representing the test properties in a result as space
+  // delimited XML attributes based on the property key="value" pairs.
+  // When the std::string is not empty, it includes a space at the beginning,
+  // to delimit this attribute from prior attributes.
+  static std::string TestPropertiesAsXmlAttributes(const TestResult& result);
+
+  // The output file.
+  const std::string output_file_;
+
+  GTEST_DISALLOW_COPY_AND_ASSIGN_(XmlUnitTestResultPrinter);
+};
+
+// Creates a new XmlUnitTestResultPrinter.
+XmlUnitTestResultPrinter::XmlUnitTestResultPrinter(const char* output_file)
+    : output_file_(output_file) {
+  if (output_file_.c_str() == NULL || output_file_.empty()) {
+    fprintf(stderr, "XML output file may not be null\n");
+    fflush(stderr);
+    exit(EXIT_FAILURE);
+  }
+}
+
+// Called after the unit test ends.
+void XmlUnitTestResultPrinter::OnTestIterationEnd(const UnitTest& unit_test,
+                                                  int /*iteration*/) {
+  FILE* xmlout = NULL;
+  FilePath output_file(output_file_);
+  FilePath output_dir(output_file.RemoveFileName());
+
+  if (output_dir.CreateDirectoriesRecursively()) {
+    xmlout = posix::FOpen(output_file_.c_str(), "w");
+  }
+  if (xmlout == NULL) {
+    // TODO(wan): report the reason of the failure.
+    //
+    // We don't do it for now as:
+    //
+    //   1. There is no urgent need for it.
+    //   2. It's a bit involved to make the errno variable thread-safe on
+    //      all three operating systems (Linux, Windows, and Mac OS).
+    //   3. To interpret the meaning of errno in a thread-safe way,
+    //      we need the strerror_r() function, which is not available on
+    //      Windows.
+    fprintf(stderr,
+            "Unable to open file \"%s\"\n",
+            output_file_.c_str());
+    fflush(stderr);
+    exit(EXIT_FAILURE);
+  }
+  std::stringstream stream;
+  PrintXmlUnitTest(&stream, unit_test);
+  fprintf(xmlout, "%s", StringStreamToString(&stream).c_str());
+  fclose(xmlout);
+}
+
+// Returns an XML-escaped copy of the input string str.  If is_attribute
+// is true, the text is meant to appear as an attribute value, and
+// normalizable whitespace is preserved by replacing it with character
+// references.
+//
+// Invalid XML characters in str, if any, are stripped from the output.
+// It is expected that most, if not all, of the text processed by this
+// module will consist of ordinary English text.
+// If this module is ever modified to produce version 1.1 XML output,
+// most invalid characters can be retained using character references.
+// TODO(wan): It might be nice to have a minimally invasive, human-readable
+// escaping scheme for invalid characters, rather than dropping them.
+std::string XmlUnitTestResultPrinter::EscapeXml(
+    const std::string& str, bool is_attribute) {
+  Message m;
+
+  for (size_t i = 0; i < str.size(); ++i) {
+    const char ch = str[i];
+    switch (ch) {
+      case '<':
+        m << "<";
+        break;
+      case '>':
+        m << ">";
+        break;
+      case '&':
+        m << "&";
+        break;
+      case '\'':
+        if (is_attribute)
+          m << "'";
+        else
+          m << '\'';
+        break;
+      case '"':
+        if (is_attribute)
+          m << """;
+        else
+          m << '"';
+        break;
+      default:
+        if (IsValidXmlCharacter(ch)) {
+          if (is_attribute && IsNormalizableWhitespace(ch))
+            m << "&#x" << String::FormatByte(static_cast<unsigned char>(ch))
+              << ";";
+          else
+            m << ch;
+        }
+        break;
+    }
+  }
+
+  return m.GetString();
+}
+
+// Returns the given string with all characters invalid in XML removed.
+// Currently invalid characters are dropped from the string. An
+// alternative is to replace them with certain characters such as . or ?.
+std::string XmlUnitTestResultPrinter::RemoveInvalidXmlCharacters(
+    const std::string& str) {
+  std::string output;
+  output.reserve(str.size());
+  for (std::string::const_iterator it = str.begin(); it != str.end(); ++it)
+    if (IsValidXmlCharacter(*it))
+      output.push_back(*it);
+
+  return output;
+}
+
+// The following routines generate an XML representation of a UnitTest
+// object.
+//
+// This is how Google Test concepts map to the DTD:
+//
+// <testsuites name="AllTests">        <-- corresponds to a UnitTest object
+//   <testsuite name="testcase-name">  <-- corresponds to a TestCase object
+//     <testcase name="test-name">     <-- corresponds to a TestInfo object
+//       <failure message="...">...</failure>
+//       <failure message="...">...</failure>
+//       <failure message="...">...</failure>
+//                                     <-- individual assertion failures
+//     </testcase>
+//   </testsuite>
+// </testsuites>
+
+// Formats the given time in milliseconds as seconds.
+std::string FormatTimeInMillisAsSeconds(TimeInMillis ms) {
+  ::std::stringstream ss;
+  ss << ms/1000.0;
+  return ss.str();
+}
+
+// Converts the given epoch time in milliseconds to a date string in the ISO
+// 8601 format, without the timezone information.
+std::string FormatEpochTimeInMillisAsIso8601(TimeInMillis ms) {
+  // Using non-reentrant version as localtime_r is not portable.
+  time_t seconds = static_cast<time_t>(ms / 1000);
+#ifdef _MSC_VER
+# pragma warning(push)          // Saves the current warning state.
+# pragma warning(disable:4996)  // Temporarily disables warning 4996
+                                // (function or variable may be unsafe).
+  const struct tm* const time_struct = localtime(&seconds);  // NOLINT
+# pragma warning(pop)           // Restores the warning state again.
+#else
+  const struct tm* const time_struct = localtime(&seconds);  // NOLINT
+#endif
+  if (time_struct == NULL)
+    return "";  // Invalid ms value
+
+  // YYYY-MM-DDThh:mm:ss
+  return StreamableToString(time_struct->tm_year + 1900) + "-" +
+      String::FormatIntWidth2(time_struct->tm_mon + 1) + "-" +
+      String::FormatIntWidth2(time_struct->tm_mday) + "T" +
+      String::FormatIntWidth2(time_struct->tm_hour) + ":" +
+      String::FormatIntWidth2(time_struct->tm_min) + ":" +
+      String::FormatIntWidth2(time_struct->tm_sec);
+}
+
+// Streams an XML CDATA section, escaping invalid CDATA sequences as needed.
+void XmlUnitTestResultPrinter::OutputXmlCDataSection(::std::ostream* stream,
+                                                     const char* data) {
+  const char* segment = data;
+  *stream << "<![CDATA[";
+  for (;;) {
+    const char* const next_segment = strstr(segment, "]]>");
+    if (next_segment != NULL) {
+      stream->write(
+          segment, static_cast<std::streamsize>(next_segment - segment));
+      *stream << "]]>]]><![CDATA[";
+      segment = next_segment + strlen("]]>");
+    } else {
+      *stream << segment;
+      break;
+    }
+  }
+  *stream << "]]>";
+}
+
+void XmlUnitTestResultPrinter::OutputXmlAttribute(
+    std::ostream* stream,
+    const std::string& element_name,
+    const std::string& name,
+    const std::string& value) {
+  const std::vector<std::string>& allowed_names =
+      GetReservedAttributesForElement(element_name);
+
+  GTEST_CHECK_(std::find(allowed_names.begin(), allowed_names.end(), name) !=
+                   allowed_names.end())
+      << "Attribute " << name << " is not allowed for element <" << element_name
+      << ">.";
+
+  *stream << " " << name << "=\"" << EscapeXmlAttribute(value) << "\"";
+}
+
+// Prints an XML representation of a TestInfo object.
+// TODO(wan): There is also value in printing properties with the plain printer.
+void XmlUnitTestResultPrinter::OutputXmlTestInfo(::std::ostream* stream,
+                                                 const char* test_case_name,
+                                                 const TestInfo& test_info) {
+  const TestResult& result = *test_info.result();
+  const std::string kTestcase = "testcase";
+
+  *stream << "    <testcase";
+  OutputXmlAttribute(stream, kTestcase, "name", test_info.name());
+
+  if (test_info.value_param() != NULL) {
+    OutputXmlAttribute(stream, kTestcase, "value_param",
+                       test_info.value_param());
+  }
+  if (test_info.type_param() != NULL) {
+    OutputXmlAttribute(stream, kTestcase, "type_param", test_info.type_param());
+  }
+
+  OutputXmlAttribute(stream, kTestcase, "status",
+                     test_info.should_run() ? "run" : "notrun");
+  OutputXmlAttribute(stream, kTestcase, "time",
+                     FormatTimeInMillisAsSeconds(result.elapsed_time()));
+  OutputXmlAttribute(stream, kTestcase, "classname", test_case_name);
+  *stream << TestPropertiesAsXmlAttributes(result);
+
+  int failures = 0;
+  for (int i = 0; i < result.total_part_count(); ++i) {
+    const TestPartResult& part = result.GetTestPartResult(i);
+    if (part.failed()) {
+      if (++failures == 1) {
+        *stream << ">\n";
+      }
+      const string location = internal::FormatCompilerIndependentFileLocation(
+          part.file_name(), part.line_number());
+      const string summary = location + "\n" + part.summary();
+      *stream << "      <failure message=\""
+              << EscapeXmlAttribute(summary.c_str())
+              << "\" type=\"\">";
+      const string detail = location + "\n" + part.message();
+      OutputXmlCDataSection(stream, RemoveInvalidXmlCharacters(detail).c_str());
+      *stream << "</failure>\n";
+    }
+  }
+
+  if (failures == 0)
+    *stream << " />\n";
+  else
+    *stream << "    </testcase>\n";
+}
+
+// Prints an XML representation of a TestCase object
+void XmlUnitTestResultPrinter::PrintXmlTestCase(std::ostream* stream,
+                                                const TestCase& test_case) {
+  const std::string kTestsuite = "testsuite";
+  *stream << "  <" << kTestsuite;
+  OutputXmlAttribute(stream, kTestsuite, "name", test_case.name());
+  OutputXmlAttribute(stream, kTestsuite, "tests",
+                     StreamableToString(test_case.reportable_test_count()));
+  OutputXmlAttribute(stream, kTestsuite, "failures",
+                     StreamableToString(test_case.failed_test_count()));
+  OutputXmlAttribute(
+      stream, kTestsuite, "disabled",
+      StreamableToString(test_case.reportable_disabled_test_count()));
+  OutputXmlAttribute(stream, kTestsuite, "errors", "0");
+  OutputXmlAttribute(stream, kTestsuite, "time",
+                     FormatTimeInMillisAsSeconds(test_case.elapsed_time()));
+  *stream << TestPropertiesAsXmlAttributes(test_case.ad_hoc_test_result())
+          << ">\n";
+
+  for (int i = 0; i < test_case.total_test_count(); ++i) {
+    if (test_case.GetTestInfo(i)->is_reportable())
+      OutputXmlTestInfo(stream, test_case.name(), *test_case.GetTestInfo(i));
+  }
+  *stream << "  </" << kTestsuite << ">\n";
+}
+
+// Prints an XML summary of unit_test to output stream out.
+void XmlUnitTestResultPrinter::PrintXmlUnitTest(std::ostream* stream,
+                                                const UnitTest& unit_test) {
+  const std::string kTestsuites = "testsuites";
+
+  *stream << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n";
+  *stream << "<" << kTestsuites;
+
+  OutputXmlAttribute(stream, kTestsuites, "tests",
+                     StreamableToString(unit_test.reportable_test_count()));
+  OutputXmlAttribute(stream, kTestsuites, "failures",
+                     StreamableToString(unit_test.failed_test_count()));
+  OutputXmlAttribute(
+      stream, kTestsuites, "disabled",
+      StreamableToString(unit_test.reportable_disabled_test_count()));
+  OutputXmlAttribute(stream, kTestsuites, "errors", "0");
+  OutputXmlAttribute(
+      stream, kTestsuites, "timestamp",
+      FormatEpochTimeInMillisAsIso8601(unit_test.start_timestamp()));
+  OutputXmlAttribute(stream, kTestsuites, "time",
+                     FormatTimeInMillisAsSeconds(unit_test.elapsed_time()));
+
+  if (GTEST_FLAG(shuffle)) {
+    OutputXmlAttribute(stream, kTestsuites, "random_seed",
+                       StreamableToString(unit_test.random_seed()));
+  }
+
+  *stream << TestPropertiesAsXmlAttributes(unit_test.ad_hoc_test_result());
+
+  OutputXmlAttribute(stream, kTestsuites, "name", "AllTests");
+  *stream << ">\n";
+
+  for (int i = 0; i < unit_test.total_test_case_count(); ++i) {
+    if (unit_test.GetTestCase(i)->reportable_test_count() > 0)
+      PrintXmlTestCase(stream, *unit_test.GetTestCase(i));
+  }
+  *stream << "</" << kTestsuites << ">\n";
+}
+
+// Produces a string representing the test properties in a result as space
+// delimited XML attributes based on the property key="value" pairs.
+std::string XmlUnitTestResultPrinter::TestPropertiesAsXmlAttributes(
+    const TestResult& result) {
+  Message attributes;
+  for (int i = 0; i < result.test_property_count(); ++i) {
+    const TestProperty& property = result.GetTestProperty(i);
+    attributes << " " << property.key() << "="
+        << "\"" << EscapeXmlAttribute(property.value()) << "\"";
+  }
+  return attributes.GetString();
+}
+
+// End XmlUnitTestResultPrinter
+
+#if GTEST_CAN_STREAM_RESULTS_
+
+// Checks if str contains '=', '&', '%' or '\n' characters. If yes,
+// replaces them by "%xx" where xx is their hexadecimal value. For
+// example, replaces "=" with "%3D".  This algorithm is O(strlen(str))
+// in both time and space -- important as the input str may contain an
+// arbitrarily long test failure message and stack trace.
+string StreamingListener::UrlEncode(const char* str) {
+  string result;
+  result.reserve(strlen(str) + 1);
+  for (char ch = *str; ch != '\0'; ch = *++str) {
+    switch (ch) {
+      case '%':
+      case '=':
+      case '&':
+      case '\n':
+        result.append("%" + String::FormatByte(static_cast<unsigned char>(ch)));
+        break;
+      default:
+        result.push_back(ch);
+        break;
+    }
+  }
+  return result;
+}
+
+void StreamingListener::SocketWriter::MakeConnection() {
+  GTEST_CHECK_(sockfd_ == -1)
+      << "MakeConnection() can't be called when there is already a connection.";
+
+  addrinfo hints;
+  memset(&hints, 0, sizeof(hints));
+  hints.ai_family = AF_UNSPEC;    // To allow both IPv4 and IPv6 addresses.
+  hints.ai_socktype = SOCK_STREAM;
+  addrinfo* servinfo = NULL;
+
+  // Use the getaddrinfo() to get a linked list of IP addresses for
+  // the given host name.
+  const int error_num = getaddrinfo(
+      host_name_.c_str(), port_num_.c_str(), &hints, &servinfo);
+  if (error_num != 0) {
+    GTEST_LOG_(WARNING) << "stream_result_to: getaddrinfo() failed: "
+                        << gai_strerror(error_num);
+  }
+
+  // Loop through all the results and connect to the first we can.
+  for (addrinfo* cur_addr = servinfo; sockfd_ == -1 && cur_addr != NULL;
+       cur_addr = cur_addr->ai_next) {
+    sockfd_ = socket(
+        cur_addr->ai_family, cur_addr->ai_socktype, cur_addr->ai_protocol);
+    if (sockfd_ != -1) {
+      // Connect the client socket to the server socket.
+      if (connect(sockfd_, cur_addr->ai_addr, cur_addr->ai_addrlen) == -1) {
+        close(sockfd_);
+        sockfd_ = -1;
+      }
+    }
+  }
+
+  freeaddrinfo(servinfo);  // all done with this structure
+
+  if (sockfd_ == -1) {
+    GTEST_LOG_(WARNING) << "stream_result_to: failed to connect to "
+                        << host_name_ << ":" << port_num_;
+  }
+}
+
+// End of class Streaming Listener
+#endif  // GTEST_CAN_STREAM_RESULTS__
+
+// Class ScopedTrace
+
+// Pushes the given source file location and message onto a per-thread
+// trace stack maintained by Google Test.
+ScopedTrace::ScopedTrace(const char* file, int line, const Message& message)
+    GTEST_LOCK_EXCLUDED_(&UnitTest::mutex_) {
+  TraceInfo trace;
+  trace.file = file;
+  trace.line = line;
+  trace.message = message.GetString();
+
+  UnitTest::GetInstance()->PushGTestTrace(trace);
+}
+
+// Pops the info pushed by the c'tor.
+ScopedTrace::~ScopedTrace()
+    GTEST_LOCK_EXCLUDED_(&UnitTest::mutex_) {
+  UnitTest::GetInstance()->PopGTestTrace();
+}
+
+
+// class OsStackTraceGetter
+
+// Returns the current OS stack trace as an std::string.  Parameters:
+//
+//   max_depth  - the maximum number of stack frames to be included
+//                in the trace.
+//   skip_count - the number of top frames to be skipped; doesn't count
+//                against max_depth.
+//
+string OsStackTraceGetter::CurrentStackTrace(int /* max_depth */,
+                                             int /* skip_count */)
+    GTEST_LOCK_EXCLUDED_(mutex_) {
+  return "";
+}
+
+void OsStackTraceGetter::UponLeavingGTest()
+    GTEST_LOCK_EXCLUDED_(mutex_) {
+}
+
+const char* const
+OsStackTraceGetter::kElidedFramesMarker =
+    "... " GTEST_NAME_ " internal frames ...";
+
+// A helper class that creates the premature-exit file in its
+// constructor and deletes the file in its destructor.
+class ScopedPrematureExitFile {
+ public:
+  explicit ScopedPrematureExitFile(const char* premature_exit_filepath)
+      : premature_exit_filepath_(premature_exit_filepath) {
+    // If a path to the premature-exit file is specified...
+    if (premature_exit_filepath != NULL && *premature_exit_filepath != '\0') {
+      // create the file with a single "0" character in it.  I/O
+      // errors are ignored as there's nothing better we can do and we
+      // don't want to fail the test because of this.
+      FILE* pfile = posix::FOpen(premature_exit_filepath, "w");
+      fwrite("0", 1, 1, pfile);
+      fclose(pfile);
+    }
+  }
+
+  ~ScopedPrematureExitFile() {
+    if (premature_exit_filepath_ != NULL && *premature_exit_filepath_ != '\0') {
+      remove(premature_exit_filepath_);
+    }
+  }
+
+ private:
+  const char* const premature_exit_filepath_;
+
+  GTEST_DISALLOW_COPY_AND_ASSIGN_(ScopedPrematureExitFile);
+};
+
+}  // namespace internal
+
+// class TestEventListeners
+
+TestEventListeners::TestEventListeners()
+    : repeater_(new internal::TestEventRepeater()),
+      default_result_printer_(NULL),
+      default_xml_generator_(NULL) {
+}
+
+TestEventListeners::~TestEventListeners() { delete repeater_; }
+
+// Returns the standard listener responsible for the default console
+// output.  Can be removed from the listeners list to shut down default
+// console output.  Note that removing this object from the listener list
+// with Release transfers its ownership to the user.
+void TestEventListeners::Append(TestEventListener* listener) {
+  repeater_->Append(listener);
+}
+
+// Removes the given event listener from the list and returns it.  It then
+// becomes the caller's responsibility to delete the listener. Returns
+// NULL if the listener is not found in the list.
+TestEventListener* TestEventListeners::Release(TestEventListener* listener) {
+  if (listener == default_result_printer_)
+    default_result_printer_ = NULL;
+  else if (listener == default_xml_generator_)
+    default_xml_generator_ = NULL;
+  return repeater_->Release(listener);
+}
+
+// Returns repeater that broadcasts the TestEventListener events to all
+// subscribers.
+TestEventListener* TestEventListeners::repeater() { return repeater_; }
+
+// Sets the default_result_printer attribute to the provided listener.
+// The listener is also added to the listener list and previous
+// default_result_printer is removed from it and deleted. The listener can
+// also be NULL in which case it will not be added to the list. Does
+// nothing if the previous and the current listener objects are the same.
+void TestEventListeners::SetDefaultResultPrinter(TestEventListener* listener) {
+  if (default_result_printer_ != listener) {
+    // It is an error to pass this method a listener that is already in the
+    // list.
+    delete Release(default_result_printer_);
+    default_result_printer_ = listener;
+    if (listener != NULL)
+      Append(listener);
+  }
+}
+
+// Sets the default_xml_generator attribute to the provided listener.  The
+// listener is also added to the listener list and previous
+// default_xml_generator is removed from it and deleted. The listener can
+// also be NULL in which case it will not be added to the list. Does
+// nothing if the previous and the current listener objects are the same.
+void TestEventListeners::SetDefaultXmlGenerator(TestEventListener* listener) {
+  if (default_xml_generator_ != listener) {
+    // It is an error to pass this method a listener that is already in the
+    // list.
+    delete Release(default_xml_generator_);
+    default_xml_generator_ = listener;
+    if (listener != NULL)
+      Append(listener);
+  }
+}
+
+// Controls whether events will be forwarded by the repeater to the
+// listeners in the list.
+bool TestEventListeners::EventForwardingEnabled() const {
+  return repeater_->forwarding_enabled();
+}
+
+void TestEventListeners::SuppressEventForwarding() {
+  repeater_->set_forwarding_enabled(false);
+}
+
+// class UnitTest
+
+// Gets the singleton UnitTest object.  The first time this method is
+// called, a UnitTest object is constructed and returned.  Consecutive
+// calls will return the same object.
+//
+// We don't protect this under mutex_ as a user is not supposed to
+// call this before main() starts, from which point on the return
+// value will never change.
+UnitTest* UnitTest::GetInstance() {
+  // When compiled with MSVC 7.1 in optimized mode, destroying the
+  // UnitTest object upon exiting the program messes up the exit code,
+  // causing successful tests to appear failed.  We have to use a
+  // different implementation in this case to bypass the compiler bug.
+  // This implementation makes the compiler happy, at the cost of
+  // leaking the UnitTest object.
+
+  // CodeGear C++Builder insists on a public destructor for the
+  // default implementation.  Use this implementation to keep good OO
+  // design with private destructor.
+
+#if (_MSC_VER == 1310 && !defined(_DEBUG)) || defined(__BORLANDC__)
+  static UnitTest* const instance = new UnitTest;
+  return instance;
+#else
+  static UnitTest instance;
+  return &instance;
+#endif  // (_MSC_VER == 1310 && !defined(_DEBUG)) || defined(__BORLANDC__)
+}
+
+// Gets the number of successful test cases.
+int UnitTest::successful_test_case_count() const {
+  return impl()->successful_test_case_count();
+}
+
+// Gets the number of failed test cases.
+int UnitTest::failed_test_case_count() const {
+  return impl()->failed_test_case_count();
+}
+
+// Gets the number of all test cases.
+int UnitTest::total_test_case_count() const {
+  return impl()->total_test_case_count();
+}
+
+// Gets the number of all test cases that contain at least one test
+// that should run.
+int UnitTest::test_case_to_run_count() const {
+  return impl()->test_case_to_run_count();
+}
+
+// Gets the number of successful tests.
+int UnitTest::successful_test_count() const {
+  return impl()->successful_test_count();
+}
+
+// Gets the number of failed tests.
+int UnitTest::failed_test_count() const { return impl()->failed_test_count(); }
+
+// Gets the number of disabled tests that will be reported in the XML report.
+int UnitTest::reportable_disabled_test_count() const {
+  return impl()->reportable_disabled_test_count();
+}
+
+// Gets the number of disabled tests.
+int UnitTest::disabled_test_count() const {
+  return impl()->disabled_test_count();
+}
+
+// Gets the number of tests to be printed in the XML report.
+int UnitTest::reportable_test_count() const {
+  return impl()->reportable_test_count();
+}
+
+// Gets the number of all tests.
+int UnitTest::total_test_count() const { return impl()->total_test_count(); }
+
+// Gets the number of tests that should run.
+int UnitTest::test_to_run_count() const { return impl()->test_to_run_count(); }
+
+// Gets the time of the test program start, in ms from the start of the
+// UNIX epoch.
+internal::TimeInMillis UnitTest::start_timestamp() const {
+    return impl()->start_timestamp();
+}
+
+// Gets the elapsed time, in milliseconds.
+internal::TimeInMillis UnitTest::elapsed_time() const {
+  return impl()->elapsed_time();
+}
+
+// Returns true iff the unit test passed (i.e. all test cases passed).
+bool UnitTest::Passed() const { return impl()->Passed(); }
+
+// Returns true iff the unit test failed (i.e. some test case failed
+// or something outside of all tests failed).
+bool UnitTest::Failed() const { return impl()->Failed(); }
+
+// Gets the i-th test case among all the test cases. i can range from 0 to
+// total_test_case_count() - 1. If i is not in that range, returns NULL.
+const TestCase* UnitTest::GetTestCase(int i) const {
+  return impl()->GetTestCase(i);
+}
+
+// Returns the TestResult containing information on test failures and
+// properties logged outside of individual test cases.
+const TestResult& UnitTest::ad_hoc_test_result() const {
+  return *impl()->ad_hoc_test_result();
+}
+
+// Gets the i-th test case among all the test cases. i can range from 0 to
+// total_test_case_count() - 1. If i is not in that range, returns NULL.
+TestCase* UnitTest::GetMutableTestCase(int i) {
+  return impl()->GetMutableTestCase(i);
+}
+
+// Returns the list of event listeners that can be used to track events
+// inside Google Test.
+TestEventListeners& UnitTest::listeners() {
+  return *impl()->listeners();
+}
+
+// Registers and returns a global test environment.  When a test
+// program is run, all global test environments will be set-up in the
+// order they were registered.  After all tests in the program have
+// finished, all global test environments will be torn-down in the
+// *reverse* order they were registered.
+//
+// The UnitTest object takes ownership of the given environment.
+//
+// We don't protect this under mutex_, as we only support calling it
+// from the main thread.
+Environment* UnitTest::AddEnvironment(Environment* env) {
+  if (env == NULL) {
+    return NULL;
+  }
+
+  impl_->environments().push_back(env);
+  return env;
+}
+
+// Adds a TestPartResult to the current TestResult object.  All Google Test
+// assertion macros (e.g. ASSERT_TRUE, EXPECT_EQ, etc) eventually call
+// this to report their results.  The user code should use the
+// assertion macros instead of calling this directly.
+void UnitTest::AddTestPartResult(
+    TestPartResult::Type result_type,
+    const char* file_name,
+    int line_number,
+    const std::string& message,
+    const std::string& os_stack_trace) GTEST_LOCK_EXCLUDED_(mutex_) {
+  Message msg;
+  msg << message;
+
+  internal::MutexLock lock(&mutex_);
+  if (impl_->gtest_trace_stack().size() > 0) {
+    msg << "\n" << GTEST_NAME_ << " trace:";
+
+    for (int i = static_cast<int>(impl_->gtest_trace_stack().size());
+         i > 0; --i) {
+      const internal::TraceInfo& trace = impl_->gtest_trace_stack()[i - 1];
+      msg << "\n" << internal::FormatFileLocation(trace.file, trace.line)
+          << " " << trace.message;
+    }
+  }
+
+  if (os_stack_trace.c_str() != NULL && !os_stack_trace.empty()) {
+    msg << internal::kStackTraceMarker << os_stack_trace;
+  }
+
+  const TestPartResult result =
+    TestPartResult(result_type, file_name, line_number,
+                   msg.GetString().c_str());
+  impl_->GetTestPartResultReporterForCurrentThread()->
+      ReportTestPartResult(result);
+
+  if (result_type != TestPartResult::kSuccess) {
+    // gtest_break_on_failure takes precedence over
+    // gtest_throw_on_failure.  This allows a user to set the latter
+    // in the code (perhaps in order to use Google Test assertions
+    // with another testing framework) and specify the former on the
+    // command line for debugging.
+    if (GTEST_FLAG(break_on_failure)) {
+#if GTEST_OS_WINDOWS
+      // Using DebugBreak on Windows allows gtest to still break into a debugger
+      // when a failure happens and both the --gtest_break_on_failure and
+      // the --gtest_catch_exceptions flags are specified.
+      DebugBreak();
+#else
+      // Dereference NULL through a volatile pointer to prevent the compiler
+      // from removing. We use this rather than abort() or __builtin_trap() for
+      // portability: Symbian doesn't implement abort() well, and some debuggers
+      // don't correctly trap abort().
+      *static_cast<volatile int*>(NULL) = 1;
+#endif  // GTEST_OS_WINDOWS
+    } else if (GTEST_FLAG(throw_on_failure)) {
+#if GTEST_HAS_EXCEPTIONS
+      throw internal::GoogleTestFailureException(result);
+#else
+      // We cannot call abort() as it generates a pop-up in debug mode
+      // that cannot be suppressed in VC 7.1 or below.
+      exit(1);
+#endif
+    }
+  }
+}
+
+// Adds a TestProperty to the current TestResult object when invoked from
+// inside a test, to current TestCase's ad_hoc_test_result_ when invoked
+// from SetUpTestCase or TearDownTestCase, or to the global property set
+// when invoked elsewhere.  If the result already contains a property with
+// the same key, the value will be updated.
+void UnitTest::RecordProperty(const std::string& key,
+                              const std::string& value) {
+  impl_->RecordProperty(TestProperty(key, value));
+}
+
+// Runs all tests in this UnitTest object and prints the result.
+// Returns 0 if successful, or 1 otherwise.
+//
+// We don't protect this under mutex_, as we only support calling it
+// from the main thread.
+int UnitTest::Run() {
+  const bool in_death_test_child_process =
+      internal::GTEST_FLAG(internal_run_death_test).length() > 0;
+
+  // Google Test implements this protocol for catching that a test
+  // program exits before returning control to Google Test:
+  //
+  //   1. Upon start, Google Test creates a file whose absolute path
+  //      is specified by the environment variable
+  //      TEST_PREMATURE_EXIT_FILE.
+  //   2. When Google Test has finished its work, it deletes the file.
+  //
+  // This allows a test runner to set TEST_PREMATURE_EXIT_FILE before
+  // running a Google-Test-based test program and check the existence
+  // of the file at the end of the test execution to see if it has
+  // exited prematurely.
+
+  // If we are in the child process of a death test, don't
+  // create/delete the premature exit file, as doing so is unnecessary
+  // and will confuse the parent process.  Otherwise, create/delete
+  // the file upon entering/leaving this function.  If the program
+  // somehow exits before this function has a chance to return, the
+  // premature-exit file will be left undeleted, causing a test runner
+  // that understands the premature-exit-file protocol to report the
+  // test as having failed.
+  const internal::ScopedPrematureExitFile premature_exit_file(
+      in_death_test_child_process ?
+      NULL : internal::posix::GetEnv("TEST_PREMATURE_EXIT_FILE"));
+
+  // Captures the value of GTEST_FLAG(catch_exceptions).  This value will be
+  // used for the duration of the program.
+  impl()->set_catch_exceptions(GTEST_FLAG(catch_exceptions));
+
+#if GTEST_HAS_SEH
+  // Either the user wants Google Test to catch exceptions thrown by the
+  // tests or this is executing in the context of death test child
+  // process. In either case the user does not want to see pop-up dialogs
+  // about crashes - they are expected.
+  if (impl()->catch_exceptions() || in_death_test_child_process) {
+# if !GTEST_OS_WINDOWS_MOBILE
+    // SetErrorMode doesn't exist on CE.
+    SetErrorMode(SEM_FAILCRITICALERRORS | SEM_NOALIGNMENTFAULTEXCEPT |
+                 SEM_NOGPFAULTERRORBOX | SEM_NOOPENFILEERRORBOX);
+# endif  // !GTEST_OS_WINDOWS_MOBILE
+
+# if (defined(_MSC_VER) || GTEST_OS_WINDOWS_MINGW) && !GTEST_OS_WINDOWS_MOBILE
+    // Death test children can be terminated with _abort().  On Windows,
+    // _abort() can show a dialog with a warning message.  This forces the
+    // abort message to go to stderr instead.
+    _set_error_mode(_OUT_TO_STDERR);
+# endif
+
+# if _MSC_VER >= 1400 && !GTEST_OS_WINDOWS_MOBILE
+    // In the debug version, Visual Studio pops up a separate dialog
+    // offering a choice to debug the aborted program. We need to suppress
+    // this dialog or it will pop up for every EXPECT/ASSERT_DEATH statement
+    // executed. Google Test will notify the user of any unexpected
+    // failure via stderr.
+    //
+    // VC++ doesn't define _set_abort_behavior() prior to the version 8.0.
+    // Users of prior VC versions shall suffer the agony and pain of
+    // clicking through the countless debug dialogs.
+    // TODO(vladl at google.com): find a way to suppress the abort dialog() in the
+    // debug mode when compiled with VC 7.1 or lower.
+    if (!GTEST_FLAG(break_on_failure))
+      _set_abort_behavior(
+          0x0,                                    // Clear the following flags:
+          _WRITE_ABORT_MSG | _CALL_REPORTFAULT);  // pop-up window, core dump.
+# endif
+  }
+#endif  // GTEST_HAS_SEH
+
+  return internal::HandleExceptionsInMethodIfSupported(
+      impl(),
+      &internal::UnitTestImpl::RunAllTests,
+      "auxiliary test code (environments or event listeners)") ? 0 : 1;
+}
+
+// Returns the working directory when the first TEST() or TEST_F() was
+// executed.
+const char* UnitTest::original_working_dir() const {
+  return impl_->original_working_dir_.c_str();
+}
+
+// Returns the TestCase object for the test that's currently running,
+// or NULL if no test is running.
+const TestCase* UnitTest::current_test_case() const
+    GTEST_LOCK_EXCLUDED_(mutex_) {
+  internal::MutexLock lock(&mutex_);
+  return impl_->current_test_case();
+}
+
+// Returns the TestInfo object for the test that's currently running,
+// or NULL if no test is running.
+const TestInfo* UnitTest::current_test_info() const
+    GTEST_LOCK_EXCLUDED_(mutex_) {
+  internal::MutexLock lock(&mutex_);
+  return impl_->current_test_info();
+}
+
+// Returns the random seed used at the start of the current test run.
+int UnitTest::random_seed() const { return impl_->random_seed(); }
+
+#if GTEST_HAS_PARAM_TEST
+// Returns ParameterizedTestCaseRegistry object used to keep track of
+// value-parameterized tests and instantiate and register them.
+internal::ParameterizedTestCaseRegistry&
+    UnitTest::parameterized_test_registry()
+        GTEST_LOCK_EXCLUDED_(mutex_) {
+  return impl_->parameterized_test_registry();
+}
+#endif  // GTEST_HAS_PARAM_TEST
+
+// Creates an empty UnitTest.
+UnitTest::UnitTest() {
+  impl_ = new internal::UnitTestImpl(this);
+}
+
+// Destructor of UnitTest.
+UnitTest::~UnitTest() {
+  delete impl_;
+}
+
+// Pushes a trace defined by SCOPED_TRACE() on to the per-thread
+// Google Test trace stack.
+void UnitTest::PushGTestTrace(const internal::TraceInfo& trace)
+    GTEST_LOCK_EXCLUDED_(mutex_) {
+  internal::MutexLock lock(&mutex_);
+  impl_->gtest_trace_stack().push_back(trace);
+}
+
+// Pops a trace from the per-thread Google Test trace stack.
+void UnitTest::PopGTestTrace()
+    GTEST_LOCK_EXCLUDED_(mutex_) {
+  internal::MutexLock lock(&mutex_);
+  impl_->gtest_trace_stack().pop_back();
+}
+
+namespace internal {
+
+UnitTestImpl::UnitTestImpl(UnitTest* parent)
+    : parent_(parent),
+#ifdef _MSC_VER
+# pragma warning(push)                    // Saves the current warning state.
+# pragma warning(disable:4355)            // Temporarily disables warning 4355
+                                         // (using this in initializer).
+      default_global_test_part_result_reporter_(this),
+      default_per_thread_test_part_result_reporter_(this),
+# pragma warning(pop)                     // Restores the warning state again.
+#else
+      default_global_test_part_result_reporter_(this),
+      default_per_thread_test_part_result_reporter_(this),
+#endif  // _MSC_VER
+      global_test_part_result_repoter_(
+          &default_global_test_part_result_reporter_),
+      per_thread_test_part_result_reporter_(
+          &default_per_thread_test_part_result_reporter_),
+#if GTEST_HAS_PARAM_TEST
+      parameterized_test_registry_(),
+      parameterized_tests_registered_(false),
+#endif  // GTEST_HAS_PARAM_TEST
+      last_death_test_case_(-1),
+      current_test_case_(NULL),
+      current_test_info_(NULL),
+      ad_hoc_test_result_(),
+      os_stack_trace_getter_(NULL),
+      post_flag_parse_init_performed_(false),
+      random_seed_(0),  // Will be overridden by the flag before first use.
+      random_(0),  // Will be reseeded before first use.
+      start_timestamp_(0),
+      elapsed_time_(0),
+#if GTEST_HAS_DEATH_TEST
+      death_test_factory_(new DefaultDeathTestFactory),
+#endif
+      // Will be overridden by the flag before first use.
+      catch_exceptions_(false) {
+  listeners()->SetDefaultResultPrinter(new PrettyUnitTestResultPrinter);
+}
+
+UnitTestImpl::~UnitTestImpl() {
+  // Deletes every TestCase.
+  ForEach(test_cases_, internal::Delete<TestCase>);
+
+  // Deletes every Environment.
+  ForEach(environments_, internal::Delete<Environment>);
+
+  delete os_stack_trace_getter_;
+}
+
+// Adds a TestProperty to the current TestResult object when invoked in a
+// context of a test, to current test case's ad_hoc_test_result when invoke
+// from SetUpTestCase/TearDownTestCase, or to the global property set
+// otherwise.  If the result already contains a property with the same key,
+// the value will be updated.
+void UnitTestImpl::RecordProperty(const TestProperty& test_property) {
+  std::string xml_element;
+  TestResult* test_result;  // TestResult appropriate for property recording.
+
+  if (current_test_info_ != NULL) {
+    xml_element = "testcase";
+    test_result = &(current_test_info_->result_);
+  } else if (current_test_case_ != NULL) {
+    xml_element = "testsuite";
+    test_result = &(current_test_case_->ad_hoc_test_result_);
+  } else {
+    xml_element = "testsuites";
+    test_result = &ad_hoc_test_result_;
+  }
+  test_result->RecordProperty(xml_element, test_property);
+}
+
+#if GTEST_HAS_DEATH_TEST
+// Disables event forwarding if the control is currently in a death test
+// subprocess. Must not be called before InitGoogleTest.
+void UnitTestImpl::SuppressTestEventsIfInSubprocess() {
+  if (internal_run_death_test_flag_.get() != NULL)
+    listeners()->SuppressEventForwarding();
+}
+#endif  // GTEST_HAS_DEATH_TEST
+
+// Initializes event listeners performing XML output as specified by
+// UnitTestOptions. Must not be called before InitGoogleTest.
+void UnitTestImpl::ConfigureXmlOutput() {
+  const std::string& output_format = UnitTestOptions::GetOutputFormat();
+  if (output_format == "xml") {
+    listeners()->SetDefaultXmlGenerator(new XmlUnitTestResultPrinter(
+        UnitTestOptions::GetAbsolutePathToOutputFile().c_str()));
+  } else if (output_format != "") {
+    printf("WARNING: unrecognized output format \"%s\" ignored.\n",
+           output_format.c_str());
+    fflush(stdout);
+  }
+}
+
+#if GTEST_CAN_STREAM_RESULTS_
+// Initializes event listeners for streaming test results in string form.
+// Must not be called before InitGoogleTest.
+void UnitTestImpl::ConfigureStreamingOutput() {
+  const std::string& target = GTEST_FLAG(stream_result_to);
+  if (!target.empty()) {
+    const size_t pos = target.find(':');
+    if (pos != std::string::npos) {
+      listeners()->Append(new StreamingListener(target.substr(0, pos),
+                                                target.substr(pos+1)));
+    } else {
+      printf("WARNING: unrecognized streaming target \"%s\" ignored.\n",
+             target.c_str());
+      fflush(stdout);
+    }
+  }
+}
+#endif  // GTEST_CAN_STREAM_RESULTS_
+
+// Performs initialization dependent upon flag values obtained in
+// ParseGoogleTestFlagsOnly.  Is called from InitGoogleTest after the call to
+// ParseGoogleTestFlagsOnly.  In case a user neglects to call InitGoogleTest
+// this function is also called from RunAllTests.  Since this function can be
+// called more than once, it has to be idempotent.
+void UnitTestImpl::PostFlagParsingInit() {
+  // Ensures that this function does not execute more than once.
+  if (!post_flag_parse_init_performed_) {
+    post_flag_parse_init_performed_ = true;
+
+#if GTEST_HAS_DEATH_TEST
+    InitDeathTestSubprocessControlInfo();
+    SuppressTestEventsIfInSubprocess();
+#endif  // GTEST_HAS_DEATH_TEST
+
+    // Registers parameterized tests. This makes parameterized tests
+    // available to the UnitTest reflection API without running
+    // RUN_ALL_TESTS.
+    RegisterParameterizedTests();
+
+    // Configures listeners for XML output. This makes it possible for users
+    // to shut down the default XML output before invoking RUN_ALL_TESTS.
+    ConfigureXmlOutput();
+
+#if GTEST_CAN_STREAM_RESULTS_
+    // Configures listeners for streaming test results to the specified server.
+    ConfigureStreamingOutput();
+#endif  // GTEST_CAN_STREAM_RESULTS_
+  }
+}
+
+// A predicate that checks the name of a TestCase against a known
+// value.
+//
+// This is used for implementation of the UnitTest class only.  We put
+// it in the anonymous namespace to prevent polluting the outer
+// namespace.
+//
+// TestCaseNameIs is copyable.
+class TestCaseNameIs {
+ public:
+  // Constructor.
+  explicit TestCaseNameIs(const std::string& name)
+      : name_(name) {}
+
+  // Returns true iff the name of test_case matches name_.
+  bool operator()(const TestCase* test_case) const {
+    return test_case != NULL && strcmp(test_case->name(), name_.c_str()) == 0;
+  }
+
+ private:
+  std::string name_;
+};
+
+// Finds and returns a TestCase with the given name.  If one doesn't
+// exist, creates one and returns it.  It's the CALLER'S
+// RESPONSIBILITY to ensure that this function is only called WHEN THE
+// TESTS ARE NOT SHUFFLED.
+//
+// Arguments:
+//
+//   test_case_name: name of the test case
+//   type_param:     the name of the test case's type parameter, or NULL if
+//                   this is not a typed or a type-parameterized test case.
+//   set_up_tc:      pointer to the function that sets up the test case
+//   tear_down_tc:   pointer to the function that tears down the test case
+TestCase* UnitTestImpl::GetTestCase(const char* test_case_name,
+                                    const char* type_param,
+                                    Test::SetUpTestCaseFunc set_up_tc,
+                                    Test::TearDownTestCaseFunc tear_down_tc) {
+  // Can we find a TestCase with the given name?
+  const std::vector<TestCase*>::const_iterator test_case =
+      std::find_if(test_cases_.begin(), test_cases_.end(),
+                   TestCaseNameIs(test_case_name));
+
+  if (test_case != test_cases_.end())
+    return *test_case;
+
+  // No.  Let's create one.
+  TestCase* const new_test_case =
+      new TestCase(test_case_name, type_param, set_up_tc, tear_down_tc);
+
+  // Is this a death test case?
+  if (internal::UnitTestOptions::MatchesFilter(test_case_name,
+                                               kDeathTestCaseFilter)) {
+    // Yes.  Inserts the test case after the last death test case
+    // defined so far.  This only works when the test cases haven't
+    // been shuffled.  Otherwise we may end up running a death test
+    // after a non-death test.
+    ++last_death_test_case_;
+    test_cases_.insert(test_cases_.begin() + last_death_test_case_,
+                       new_test_case);
+  } else {
+    // No.  Appends to the end of the list.
+    test_cases_.push_back(new_test_case);
+  }
+
+  test_case_indices_.push_back(static_cast<int>(test_case_indices_.size()));
+  return new_test_case;
+}
+
+// Helpers for setting up / tearing down the given environment.  They
+// are for use in the ForEach() function.
+static void SetUpEnvironment(Environment* env) { env->SetUp(); }
+static void TearDownEnvironment(Environment* env) { env->TearDown(); }
+
+// Runs all tests in this UnitTest object, prints the result, and
+// returns true if all tests are successful.  If any exception is
+// thrown during a test, the test is considered to be failed, but the
+// rest of the tests will still be run.
+//
+// When parameterized tests are enabled, it expands and registers
+// parameterized tests first in RegisterParameterizedTests().
+// All other functions called from RunAllTests() may safely assume that
+// parameterized tests are ready to be counted and run.
+bool UnitTestImpl::RunAllTests() {
+  // Makes sure InitGoogleTest() was called.
+  if (!GTestIsInitialized()) {
+    printf("%s",
+           "\nThis test program did NOT call ::testing::InitGoogleTest "
+           "before calling RUN_ALL_TESTS().  Please fix it.\n");
+    return false;
+  }
+
+  // Do not run any test if the --help flag was specified.
+  if (g_help_flag)
+    return true;
+
+  // Repeats the call to the post-flag parsing initialization in case the
+  // user didn't call InitGoogleTest.
+  PostFlagParsingInit();
+
+  // Even if sharding is not on, test runners may want to use the
+  // GTEST_SHARD_STATUS_FILE to query whether the test supports the sharding
+  // protocol.
+  internal::WriteToShardStatusFileIfNeeded();
+
+  // True iff we are in a subprocess for running a thread-safe-style
+  // death test.
+  bool in_subprocess_for_death_test = false;
+
+#if GTEST_HAS_DEATH_TEST
+  in_subprocess_for_death_test = (internal_run_death_test_flag_.get() != NULL);
+#endif  // GTEST_HAS_DEATH_TEST
+
+  const bool should_shard = ShouldShard(kTestTotalShards, kTestShardIndex,
+                                        in_subprocess_for_death_test);
+
+  // Compares the full test names with the filter to decide which
+  // tests to run.
+  const bool has_tests_to_run = FilterTests(should_shard
+                                              ? HONOR_SHARDING_PROTOCOL
+                                              : IGNORE_SHARDING_PROTOCOL) > 0;
+
+  // Lists the tests and exits if the --gtest_list_tests flag was specified.
+  if (GTEST_FLAG(list_tests)) {
+    // This must be called *after* FilterTests() has been called.
+    ListTestsMatchingFilter();
+    return true;
+  }
+
+  random_seed_ = GTEST_FLAG(shuffle) ?
+      GetRandomSeedFromFlag(GTEST_FLAG(random_seed)) : 0;
+
+  // True iff at least one test has failed.
+  bool failed = false;
+
+  TestEventListener* repeater = listeners()->repeater();
+
+  start_timestamp_ = GetTimeInMillis();
+  repeater->OnTestProgramStart(*parent_);
+
+  // How many times to repeat the tests?  We don't want to repeat them
+  // when we are inside the subprocess of a death test.
+  const int repeat = in_subprocess_for_death_test ? 1 : GTEST_FLAG(repeat);
+  // Repeats forever if the repeat count is negative.
+  const bool forever = repeat < 0;
+  for (int i = 0; forever || i != repeat; i++) {
+    // We want to preserve failures generated by ad-hoc test
+    // assertions executed before RUN_ALL_TESTS().
+    ClearNonAdHocTestResult();
+
+    const TimeInMillis start = GetTimeInMillis();
+
+    // Shuffles test cases and tests if requested.
+    if (has_tests_to_run && GTEST_FLAG(shuffle)) {
+      random()->Reseed(random_seed_);
+      // This should be done before calling OnTestIterationStart(),
+      // such that a test event listener can see the actual test order
+      // in the event.
+      ShuffleTests();
+    }
+
+    // Tells the unit test event listeners that the tests are about to start.
+    repeater->OnTestIterationStart(*parent_, i);
+
+    // Runs each test case if there is at least one test to run.
+    if (has_tests_to_run) {
+      // Sets up all environments beforehand.
+      repeater->OnEnvironmentsSetUpStart(*parent_);
+      ForEach(environments_, SetUpEnvironment);
+      repeater->OnEnvironmentsSetUpEnd(*parent_);
+
+      // Runs the tests only if there was no fatal failure during global
+      // set-up.
+      if (!Test::HasFatalFailure()) {
+        for (int test_index = 0; test_index < total_test_case_count();
+             test_index++) {
+          GetMutableTestCase(test_index)->Run();
+        }
+      }
+
+      // Tears down all environments in reverse order afterwards.
+      repeater->OnEnvironmentsTearDownStart(*parent_);
+      std::for_each(environments_.rbegin(), environments_.rend(),
+                    TearDownEnvironment);
+      repeater->OnEnvironmentsTearDownEnd(*parent_);
+    }
+
+    elapsed_time_ = GetTimeInMillis() - start;
+
+    // Tells the unit test event listener that the tests have just finished.
+    repeater->OnTestIterationEnd(*parent_, i);
+
+    // Gets the result and clears it.
+    if (!Passed()) {
+      failed = true;
+    }
+
+    // Restores the original test order after the iteration.  This
+    // allows the user to quickly repro a failure that happens in the
+    // N-th iteration without repeating the first (N - 1) iterations.
+    // This is not enclosed in "if (GTEST_FLAG(shuffle)) { ... }", in
+    // case the user somehow changes the value of the flag somewhere
+    // (it's always safe to unshuffle the tests).
+    UnshuffleTests();
+
+    if (GTEST_FLAG(shuffle)) {
+      // Picks a new random seed for each iteration.
+      random_seed_ = GetNextRandomSeed(random_seed_);
+    }
+  }
+
+  repeater->OnTestProgramEnd(*parent_);
+
+  return !failed;
+}
+
+// Reads the GTEST_SHARD_STATUS_FILE environment variable, and creates the file
+// if the variable is present. If a file already exists at this location, this
+// function will write over it. If the variable is present, but the file cannot
+// be created, prints an error and exits.
+void WriteToShardStatusFileIfNeeded() {
+  const char* const test_shard_file = posix::GetEnv(kTestShardStatusFile);
+  if (test_shard_file != NULL) {
+    FILE* const file = posix::FOpen(test_shard_file, "w");
+    if (file == NULL) {
+      ColoredPrintf(COLOR_RED,
+                    "Could not write to the test shard status file \"%s\" "
+                    "specified by the %s environment variable.\n",
+                    test_shard_file, kTestShardStatusFile);
+      fflush(stdout);
+      exit(EXIT_FAILURE);
+    }
+    fclose(file);
+  }
+}
+
+// Checks whether sharding is enabled by examining the relevant
+// environment variable values. If the variables are present,
+// but inconsistent (i.e., shard_index >= total_shards), prints
+// an error and exits. If in_subprocess_for_death_test, sharding is
+// disabled because it must only be applied to the original test
+// process. Otherwise, we could filter out death tests we intended to execute.
+bool ShouldShard(const char* total_shards_env,
+                 const char* shard_index_env,
+                 bool in_subprocess_for_death_test) {
+  if (in_subprocess_for_death_test) {
+    return false;
+  }
+
+  const Int32 total_shards = Int32FromEnvOrDie(total_shards_env, -1);
+  const Int32 shard_index = Int32FromEnvOrDie(shard_index_env, -1);
+
+  if (total_shards == -1 && shard_index == -1) {
+    return false;
+  } else if (total_shards == -1 && shard_index != -1) {
+    const Message msg = Message()
+      << "Invalid environment variables: you have "
+      << kTestShardIndex << " = " << shard_index
+      << ", but have left " << kTestTotalShards << " unset.\n";
+    ColoredPrintf(COLOR_RED, msg.GetString().c_str());
+    fflush(stdout);
+    exit(EXIT_FAILURE);
+  } else if (total_shards != -1 && shard_index == -1) {
+    const Message msg = Message()
+      << "Invalid environment variables: you have "
+      << kTestTotalShards << " = " << total_shards
+      << ", but have left " << kTestShardIndex << " unset.\n";
+    ColoredPrintf(COLOR_RED, msg.GetString().c_str());
+    fflush(stdout);
+    exit(EXIT_FAILURE);
+  } else if (shard_index < 0 || shard_index >= total_shards) {
+    const Message msg = Message()
+      << "Invalid environment variables: we require 0 <= "
+      << kTestShardIndex << " < " << kTestTotalShards
+      << ", but you have " << kTestShardIndex << "=" << shard_index
+      << ", " << kTestTotalShards << "=" << total_shards << ".\n";
+    ColoredPrintf(COLOR_RED, msg.GetString().c_str());
+    fflush(stdout);
+    exit(EXIT_FAILURE);
+  }
+
+  return total_shards > 1;
+}
+
+// Parses the environment variable var as an Int32. If it is unset,
+// returns default_val. If it is not an Int32, prints an error
+// and aborts.
+Int32 Int32FromEnvOrDie(const char* var, Int32 default_val) {
+  const char* str_val = posix::GetEnv(var);
+  if (str_val == NULL) {
+    return default_val;
+  }
+
+  Int32 result;
+  if (!ParseInt32(Message() << "The value of environment variable " << var,
+                  str_val, &result)) {
+    exit(EXIT_FAILURE);
+  }
+  return result;
+}
+
+// Given the total number of shards, the shard index, and the test id,
+// returns true iff the test should be run on this shard. The test id is
+// some arbitrary but unique non-negative integer assigned to each test
+// method. Assumes that 0 <= shard_index < total_shards.
+bool ShouldRunTestOnShard(int total_shards, int shard_index, int test_id) {
+  return (test_id % total_shards) == shard_index;
+}
+
+// Compares the name of each test with the user-specified filter to
+// decide whether the test should be run, then records the result in
+// each TestCase and TestInfo object.
+// If shard_tests == true, further filters tests based on sharding
+// variables in the environment - see
+// http://code.google.com/p/googletest/wiki/GoogleTestAdvancedGuide.
+// Returns the number of tests that should run.
+int UnitTestImpl::FilterTests(ReactionToSharding shard_tests) {
+  const Int32 total_shards = shard_tests == HONOR_SHARDING_PROTOCOL ?
+      Int32FromEnvOrDie(kTestTotalShards, -1) : -1;
+  const Int32 shard_index = shard_tests == HONOR_SHARDING_PROTOCOL ?
+      Int32FromEnvOrDie(kTestShardIndex, -1) : -1;
+
+  // num_runnable_tests are the number of tests that will
+  // run across all shards (i.e., match filter and are not disabled).
+  // num_selected_tests are the number of tests to be run on
+  // this shard.
+  int num_runnable_tests = 0;
+  int num_selected_tests = 0;
+  for (size_t i = 0; i < test_cases_.size(); i++) {
+    TestCase* const test_case = test_cases_[i];
+    const std::string &test_case_name = test_case->name();
+    test_case->set_should_run(false);
+
+    for (size_t j = 0; j < test_case->test_info_list().size(); j++) {
+      TestInfo* const test_info = test_case->test_info_list()[j];
+      const std::string test_name(test_info->name());
+      // A test is disabled if test case name or test name matches
+      // kDisableTestFilter.
+      const bool is_disabled =
+          internal::UnitTestOptions::MatchesFilter(test_case_name,
+                                                   kDisableTestFilter) ||
+          internal::UnitTestOptions::MatchesFilter(test_name,
+                                                   kDisableTestFilter);
+      test_info->is_disabled_ = is_disabled;
+
+      const bool matches_filter =
+          internal::UnitTestOptions::FilterMatchesTest(test_case_name,
+                                                       test_name);
+      test_info->matches_filter_ = matches_filter;
+
+      const bool is_runnable =
+          (GTEST_FLAG(also_run_disabled_tests) || !is_disabled) &&
+          matches_filter;
+
+      const bool is_selected = is_runnable &&
+          (shard_tests == IGNORE_SHARDING_PROTOCOL ||
+           ShouldRunTestOnShard(total_shards, shard_index,
+                                num_runnable_tests));
+
+      num_runnable_tests += is_runnable;
+      num_selected_tests += is_selected;
+
+      test_info->should_run_ = is_selected;
+      test_case->set_should_run(test_case->should_run() || is_selected);
+    }
+  }
+  return num_selected_tests;
+}
+
+// Prints the given C-string on a single line by replacing all '\n'
+// characters with string "\\n".  If the output takes more than
+// max_length characters, only prints the first max_length characters
+// and "...".
+static void PrintOnOneLine(const char* str, int max_length) {
+  if (str != NULL) {
+    for (int i = 0; *str != '\0'; ++str) {
+      if (i >= max_length) {
+        printf("...");
+        break;
+      }
+      if (*str == '\n') {
+        printf("\\n");
+        i += 2;
+      } else {
+        printf("%c", *str);
+        ++i;
+      }
+    }
+  }
+}
+
+// Prints the names of the tests matching the user-specified filter flag.
+void UnitTestImpl::ListTestsMatchingFilter() {
+  // Print at most this many characters for each type/value parameter.
+  const int kMaxParamLength = 250;
+
+  for (size_t i = 0; i < test_cases_.size(); i++) {
+    const TestCase* const test_case = test_cases_[i];
+    bool printed_test_case_name = false;
+
+    for (size_t j = 0; j < test_case->test_info_list().size(); j++) {
+      const TestInfo* const test_info =
+          test_case->test_info_list()[j];
+      if (test_info->matches_filter_) {
+        if (!printed_test_case_name) {
+          printed_test_case_name = true;
+          printf("%s.", test_case->name());
+          if (test_case->type_param() != NULL) {
+            printf("  # %s = ", kTypeParamLabel);
+            // We print the type parameter on a single line to make
+            // the output easy to parse by a program.
+            PrintOnOneLine(test_case->type_param(), kMaxParamLength);
+          }
+          printf("\n");
+        }
+        printf("  %s", test_info->name());
+        if (test_info->value_param() != NULL) {
+          printf("  # %s = ", kValueParamLabel);
+          // We print the value parameter on a single line to make the
+          // output easy to parse by a program.
+          PrintOnOneLine(test_info->value_param(), kMaxParamLength);
+        }
+        printf("\n");
+      }
+    }
+  }
+  fflush(stdout);
+}
+
+// Sets the OS stack trace getter.
+//
+// Does nothing if the input and the current OS stack trace getter are
+// the same; otherwise, deletes the old getter and makes the input the
+// current getter.
+void UnitTestImpl::set_os_stack_trace_getter(
+    OsStackTraceGetterInterface* getter) {
+  if (os_stack_trace_getter_ != getter) {
+    delete os_stack_trace_getter_;
+    os_stack_trace_getter_ = getter;
+  }
+}
+
+// Returns the current OS stack trace getter if it is not NULL;
+// otherwise, creates an OsStackTraceGetter, makes it the current
+// getter, and returns it.
+OsStackTraceGetterInterface* UnitTestImpl::os_stack_trace_getter() {
+  if (os_stack_trace_getter_ == NULL) {
+    os_stack_trace_getter_ = new OsStackTraceGetter;
+  }
+
+  return os_stack_trace_getter_;
+}
+
+// Returns the TestResult for the test that's currently running, or
+// the TestResult for the ad hoc test if no test is running.
+TestResult* UnitTestImpl::current_test_result() {
+  return current_test_info_ ?
+      &(current_test_info_->result_) : &ad_hoc_test_result_;
+}
+
+// Shuffles all test cases, and the tests within each test case,
+// making sure that death tests are still run first.
+void UnitTestImpl::ShuffleTests() {
+  // Shuffles the death test cases.
+  ShuffleRange(random(), 0, last_death_test_case_ + 1, &test_case_indices_);
+
+  // Shuffles the non-death test cases.
+  ShuffleRange(random(), last_death_test_case_ + 1,
+               static_cast<int>(test_cases_.size()), &test_case_indices_);
+
+  // Shuffles the tests inside each test case.
+  for (size_t i = 0; i < test_cases_.size(); i++) {
+    test_cases_[i]->ShuffleTests(random());
+  }
+}
+
+// Restores the test cases and tests to their order before the first shuffle.
+void UnitTestImpl::UnshuffleTests() {
+  for (size_t i = 0; i < test_cases_.size(); i++) {
+    // Unshuffles the tests in each test case.
+    test_cases_[i]->UnshuffleTests();
+    // Resets the index of each test case.
+    test_case_indices_[i] = static_cast<int>(i);
+  }
+}
+
+// Returns the current OS stack trace as an std::string.
+//
+// The maximum number of stack frames to be included is specified by
+// the gtest_stack_trace_depth flag.  The skip_count parameter
+// specifies the number of top frames to be skipped, which doesn't
+// count against the number of frames to be included.
+//
+// For example, if Foo() calls Bar(), which in turn calls
+// GetCurrentOsStackTraceExceptTop(..., 1), Foo() will be included in
+// the trace but Bar() and GetCurrentOsStackTraceExceptTop() won't.
+std::string GetCurrentOsStackTraceExceptTop(UnitTest* /*unit_test*/,
+                                            int skip_count) {
+  // We pass skip_count + 1 to skip this wrapper function in addition
+  // to what the user really wants to skip.
+  return GetUnitTestImpl()->CurrentOsStackTraceExceptTop(skip_count + 1);
+}
+
+// Used by the GTEST_SUPPRESS_UNREACHABLE_CODE_WARNING_BELOW_ macro to
+// suppress unreachable code warnings.
+namespace {
+class ClassUniqueToAlwaysTrue {};
+}
+
+bool IsTrue(bool condition) { return condition; }
+
+bool AlwaysTrue() {
+#if GTEST_HAS_EXCEPTIONS
+  // This condition is always false so AlwaysTrue() never actually throws,
+  // but it makes the compiler think that it may throw.
+  if (IsTrue(false))
+    throw ClassUniqueToAlwaysTrue();
+#endif  // GTEST_HAS_EXCEPTIONS
+  return true;
+}
+
+// If *pstr starts with the given prefix, modifies *pstr to be right
+// past the prefix and returns true; otherwise leaves *pstr unchanged
+// and returns false.  None of pstr, *pstr, and prefix can be NULL.
+bool SkipPrefix(const char* prefix, const char** pstr) {
+  const size_t prefix_len = strlen(prefix);
+  if (strncmp(*pstr, prefix, prefix_len) == 0) {
+    *pstr += prefix_len;
+    return true;
+  }
+  return false;
+}
+
+// Parses a string as a command line flag.  The string should have
+// the format "--flag=value".  When def_optional is true, the "=value"
+// part can be omitted.
+//
+// Returns the value of the flag, or NULL if the parsing failed.
+const char* ParseFlagValue(const char* str,
+                           const char* flag,
+                           bool def_optional) {
+  // str and flag must not be NULL.
+  if (str == NULL || flag == NULL) return NULL;
+
+  // The flag must start with "--" followed by GTEST_FLAG_PREFIX_.
+  const std::string flag_str = std::string("--") + GTEST_FLAG_PREFIX_ + flag;
+  const size_t flag_len = flag_str.length();
+  if (strncmp(str, flag_str.c_str(), flag_len) != 0) return NULL;
+
+  // Skips the flag name.
+  const char* flag_end = str + flag_len;
+
+  // When def_optional is true, it's OK to not have a "=value" part.
+  if (def_optional && (flag_end[0] == '\0')) {
+    return flag_end;
+  }
+
+  // If def_optional is true and there are more characters after the
+  // flag name, or if def_optional is false, there must be a '=' after
+  // the flag name.
+  if (flag_end[0] != '=') return NULL;
+
+  // Returns the string after "=".
+  return flag_end + 1;
+}
+
+// Parses a string for a bool flag, in the form of either
+// "--flag=value" or "--flag".
+//
+// In the former case, the value is taken as true as long as it does
+// not start with '0', 'f', or 'F'.
+//
+// In the latter case, the value is taken as true.
+//
+// On success, stores the value of the flag in *value, and returns
+// true.  On failure, returns false without changing *value.
+bool ParseBoolFlag(const char* str, const char* flag, bool* value) {
+  // Gets the value of the flag as a string.
+  const char* const value_str = ParseFlagValue(str, flag, true);
+
+  // Aborts if the parsing failed.
+  if (value_str == NULL) return false;
+
+  // Converts the string value to a bool.
+  *value = !(*value_str == '0' || *value_str == 'f' || *value_str == 'F');
+  return true;
+}
+
+// Parses a string for an Int32 flag, in the form of
+// "--flag=value".
+//
+// On success, stores the value of the flag in *value, and returns
+// true.  On failure, returns false without changing *value.
+bool ParseInt32Flag(const char* str, const char* flag, Int32* value) {
+  // Gets the value of the flag as a string.
+  const char* const value_str = ParseFlagValue(str, flag, false);
+
+  // Aborts if the parsing failed.
+  if (value_str == NULL) return false;
+
+  // Sets *value to the value of the flag.
+  return ParseInt32(Message() << "The value of flag --" << flag,
+                    value_str, value);
+}
+
+// Parses a string for a string flag, in the form of
+// "--flag=value".
+//
+// On success, stores the value of the flag in *value, and returns
+// true.  On failure, returns false without changing *value.
+bool ParseStringFlag(const char* str, const char* flag, std::string* value) {
+  // Gets the value of the flag as a string.
+  const char* const value_str = ParseFlagValue(str, flag, false);
+
+  // Aborts if the parsing failed.
+  if (value_str == NULL) return false;
+
+  // Sets *value to the value of the flag.
+  *value = value_str;
+  return true;
+}
+
+// Determines whether a string has a prefix that Google Test uses for its
+// flags, i.e., starts with GTEST_FLAG_PREFIX_ or GTEST_FLAG_PREFIX_DASH_.
+// If Google Test detects that a command line flag has its prefix but is not
+// recognized, it will print its help message. Flags starting with
+// GTEST_INTERNAL_PREFIX_ followed by "internal_" are considered Google Test
+// internal flags and do not trigger the help message.
+static bool HasGoogleTestFlagPrefix(const char* str) {
+  return (SkipPrefix("--", &str) ||
+          SkipPrefix("-", &str) ||
+          SkipPrefix("/", &str)) &&
+         !SkipPrefix(GTEST_FLAG_PREFIX_ "internal_", &str) &&
+         (SkipPrefix(GTEST_FLAG_PREFIX_, &str) ||
+          SkipPrefix(GTEST_FLAG_PREFIX_DASH_, &str));
+}
+
+// Prints a string containing code-encoded text.  The following escape
+// sequences can be used in the string to control the text color:
+//
+//   @@    prints a single '@' character.
+//   @R    changes the color to red.
+//   @G    changes the color to green.
+//   @Y    changes the color to yellow.
+//   @D    changes to the default terminal text color.
+//
+// TODO(wan at google.com): Write tests for this once we add stdout
+// capturing to Google Test.
+static void PrintColorEncoded(const char* str) {
+  GTestColor color = COLOR_DEFAULT;  // The current color.
+
+  // Conceptually, we split the string into segments divided by escape
+  // sequences.  Then we print one segment at a time.  At the end of
+  // each iteration, the str pointer advances to the beginning of the
+  // next segment.
+  for (;;) {
+    const char* p = strchr(str, '@');
+    if (p == NULL) {
+      ColoredPrintf(color, "%s", str);
+      return;
+    }
+
+    ColoredPrintf(color, "%s", std::string(str, p).c_str());
+
+    const char ch = p[1];
+    str = p + 2;
+    if (ch == '@') {
+      ColoredPrintf(color, "@");
+    } else if (ch == 'D') {
+      color = COLOR_DEFAULT;
+    } else if (ch == 'R') {
+      color = COLOR_RED;
+    } else if (ch == 'G') {
+      color = COLOR_GREEN;
+    } else if (ch == 'Y') {
+      color = COLOR_YELLOW;
+    } else {
+      --str;
+    }
+  }
+}
+
+static const char kColorEncodedHelpMessage[] =
+"This program contains tests written using " GTEST_NAME_ ". You can use the\n"
+"following command line flags to control its behavior:\n"
+"\n"
+"Test Selection:\n"
+"  @G--" GTEST_FLAG_PREFIX_ "list_tests at D\n"
+"      List the names of all tests instead of running them. The name of\n"
+"      TEST(Foo, Bar) is \"Foo.Bar\".\n"
+"  @G--" GTEST_FLAG_PREFIX_ "filter=@YPOSTIVE_PATTERNS"
+    "[@G- at YNEGATIVE_PATTERNS]@D\n"
+"      Run only the tests whose name matches one of the positive patterns but\n"
+"      none of the negative patterns. '?' matches any single character; '*'\n"
+"      matches any substring; ':' separates two patterns.\n"
+"  @G--" GTEST_FLAG_PREFIX_ "also_run_disabled_tests at D\n"
+"      Run all disabled tests too.\n"
+"\n"
+"Test Execution:\n"
+"  @G--" GTEST_FLAG_PREFIX_ "repeat=@Y[COUNT]@D\n"
+"      Run the tests repeatedly; use a negative count to repeat forever.\n"
+"  @G--" GTEST_FLAG_PREFIX_ "shuffle at D\n"
+"      Randomize tests' orders on every iteration.\n"
+"  @G--" GTEST_FLAG_PREFIX_ "random_seed=@Y[NUMBER]@D\n"
+"      Random number seed to use for shuffling test orders (between 1 and\n"
+"      99999, or 0 to use a seed based on the current time).\n"
+"\n"
+"Test Output:\n"
+"  @G--" GTEST_FLAG_PREFIX_ "color=@Y(@Gyes at Y|@Gno at Y|@Gauto at Y)@D\n"
+"      Enable/disable colored output. The default is @Gauto at D.\n"
+"  - at G-" GTEST_FLAG_PREFIX_ "print_time=0 at D\n"
+"      Don't print the elapsed time of each test.\n"
+"  @G--" GTEST_FLAG_PREFIX_ "output=xml at Y[@G:@YDIRECTORY_PATH at G"
+    GTEST_PATH_SEP_ "@Y|@G:@YFILE_PATH]@D\n"
+"      Generate an XML report in the given directory or with the given file\n"
+"      name. @YFILE_PATH at D defaults to @Gtest_details.xml at D.\n"
+#if GTEST_CAN_STREAM_RESULTS_
+"  @G--" GTEST_FLAG_PREFIX_ "stream_result_to=@YHOST at G:@YPORT at D\n"
+"      Stream test results to the given server.\n"
+#endif  // GTEST_CAN_STREAM_RESULTS_
+"\n"
+"Assertion Behavior:\n"
+#if GTEST_HAS_DEATH_TEST && !GTEST_OS_WINDOWS
+"  @G--" GTEST_FLAG_PREFIX_ "death_test_style=@Y(@Gfast at Y|@Gthreadsafe at Y)@D\n"
+"      Set the default death test style.\n"
+#endif  // GTEST_HAS_DEATH_TEST && !GTEST_OS_WINDOWS
+"  @G--" GTEST_FLAG_PREFIX_ "break_on_failure at D\n"
+"      Turn assertion failures into debugger break-points.\n"
+"  @G--" GTEST_FLAG_PREFIX_ "throw_on_failure at D\n"
+"      Turn assertion failures into C++ exceptions.\n"
+"  @G--" GTEST_FLAG_PREFIX_ "catch_exceptions=0 at D\n"
+"      Do not report exceptions as test failures. Instead, allow them\n"
+"      to crash the program or throw a pop-up (on Windows).\n"
+"\n"
+"Except for @G--" GTEST_FLAG_PREFIX_ "list_tests at D, you can alternatively set "
+    "the corresponding\n"
+"environment variable of a flag (all letters in upper-case). For example, to\n"
+"disable colored text output, you can either specify @G--" GTEST_FLAG_PREFIX_
+    "color=no at D or set\n"
+"the @G" GTEST_FLAG_PREFIX_UPPER_ "COLOR at D environment variable to @Gno at D.\n"
+"\n"
+"For more information, please read the " GTEST_NAME_ " documentation at\n"
+"@G" GTEST_PROJECT_URL_ "@D. If you find a bug in " GTEST_NAME_ "\n"
+"(not one in your own code or tests), please report it to\n"
+"@G<" GTEST_DEV_EMAIL_ ">@D.\n";
+
+// Parses the command line for Google Test flags, without initializing
+// other parts of Google Test.  The type parameter CharType can be
+// instantiated to either char or wchar_t.
+template <typename CharType>
+void ParseGoogleTestFlagsOnlyImpl(int* argc, CharType** argv) {
+  for (int i = 1; i < *argc; i++) {
+    const std::string arg_string = StreamableToString(argv[i]);
+    const char* const arg = arg_string.c_str();
+
+    using internal::ParseBoolFlag;
+    using internal::ParseInt32Flag;
+    using internal::ParseStringFlag;
+
+    // Do we see a Google Test flag?
+    if (ParseBoolFlag(arg, kAlsoRunDisabledTestsFlag,
+                      &GTEST_FLAG(also_run_disabled_tests)) ||
+        ParseBoolFlag(arg, kBreakOnFailureFlag,
+                      &GTEST_FLAG(break_on_failure)) ||
+        ParseBoolFlag(arg, kCatchExceptionsFlag,
+                      &GTEST_FLAG(catch_exceptions)) ||
+        ParseStringFlag(arg, kColorFlag, &GTEST_FLAG(color)) ||
+        ParseStringFlag(arg, kDeathTestStyleFlag,
+                        &GTEST_FLAG(death_test_style)) ||
+        ParseBoolFlag(arg, kDeathTestUseFork,
+                      &GTEST_FLAG(death_test_use_fork)) ||
+        ParseStringFlag(arg, kFilterFlag, &GTEST_FLAG(filter)) ||
+        ParseStringFlag(arg, kInternalRunDeathTestFlag,
+                        &GTEST_FLAG(internal_run_death_test)) ||
+        ParseBoolFlag(arg, kListTestsFlag, &GTEST_FLAG(list_tests)) ||
+        ParseStringFlag(arg, kOutputFlag, &GTEST_FLAG(output)) ||
+        ParseBoolFlag(arg, kPrintTimeFlag, &GTEST_FLAG(print_time)) ||
+        ParseInt32Flag(arg, kRandomSeedFlag, &GTEST_FLAG(random_seed)) ||
+        ParseInt32Flag(arg, kRepeatFlag, &GTEST_FLAG(repeat)) ||
+        ParseBoolFlag(arg, kShuffleFlag, &GTEST_FLAG(shuffle)) ||
+        ParseInt32Flag(arg, kStackTraceDepthFlag,
+                       &GTEST_FLAG(stack_trace_depth)) ||
+        ParseStringFlag(arg, kStreamResultToFlag,
+                        &GTEST_FLAG(stream_result_to)) ||
+        ParseBoolFlag(arg, kThrowOnFailureFlag,
+                      &GTEST_FLAG(throw_on_failure))
+        ) {
+      // Yes.  Shift the remainder of the argv list left by one.  Note
+      // that argv has (*argc + 1) elements, the last one always being
+      // NULL.  The following loop moves the trailing NULL element as
+      // well.
+      for (int j = i; j != *argc; j++) {
+        argv[j] = argv[j + 1];
+      }
+
+      // Decrements the argument count.
+      (*argc)--;
+
+      // We also need to decrement the iterator as we just removed
+      // an element.
+      i--;
+    } else if (arg_string == "--help" || arg_string == "-h" ||
+               arg_string == "-?" || arg_string == "/?" ||
+               HasGoogleTestFlagPrefix(arg)) {
+      // Both help flag and unrecognized Google Test flags (excluding
+      // internal ones) trigger help display.
+      g_help_flag = true;
+    }
+  }
+
+  if (g_help_flag) {
+    // We print the help here instead of in RUN_ALL_TESTS(), as the
+    // latter may not be called at all if the user is using Google
+    // Test with another testing framework.
+    PrintColorEncoded(kColorEncodedHelpMessage);
+  }
+}
+
+// Parses the command line for Google Test flags, without initializing
+// other parts of Google Test.
+void ParseGoogleTestFlagsOnly(int* argc, char** argv) {
+  ParseGoogleTestFlagsOnlyImpl(argc, argv);
+}
+void ParseGoogleTestFlagsOnly(int* argc, wchar_t** argv) {
+  ParseGoogleTestFlagsOnlyImpl(argc, argv);
+}
+
+// The internal implementation of InitGoogleTest().
+//
+// The type parameter CharType can be instantiated to either char or
+// wchar_t.
+template <typename CharType>
+void InitGoogleTestImpl(int* argc, CharType** argv) {
+  g_init_gtest_count++;
+
+  // We don't want to run the initialization code twice.
+  if (g_init_gtest_count != 1) return;
+
+  if (*argc <= 0) return;
+
+  internal::g_executable_path = internal::StreamableToString(argv[0]);
+
+#if GTEST_HAS_DEATH_TEST
+
+  g_argvs.clear();
+  for (int i = 0; i != *argc; i++) {
+    g_argvs.push_back(StreamableToString(argv[i]));
+  }
+
+#endif  // GTEST_HAS_DEATH_TEST
+
+  ParseGoogleTestFlagsOnly(argc, argv);
+  GetUnitTestImpl()->PostFlagParsingInit();
+}
+
+}  // namespace internal
+
+// Initializes Google Test.  This must be called before calling
+// RUN_ALL_TESTS().  In particular, it parses a command line for the
+// flags that Google Test recognizes.  Whenever a Google Test flag is
+// seen, it is removed from argv, and *argc is decremented.
+//
+// No value is returned.  Instead, the Google Test flag variables are
+// updated.
+//
+// Calling the function for the second time has no user-visible effect.
+void InitGoogleTest(int* argc, char** argv) {
+  internal::InitGoogleTestImpl(argc, argv);
+}
+
+// This overloaded version can be used in Windows programs compiled in
+// UNICODE mode.
+void InitGoogleTest(int* argc, wchar_t** argv) {
+  internal::InitGoogleTestImpl(argc, argv);
+}
+
+}  // namespace testing
diff --git a/test/gtest/src/gtest_main.cc b/test/gtest/src/gtest_main.cc
new file mode 100644
index 0000000..f302822
--- /dev/null
+++ b/test/gtest/src/gtest_main.cc
@@ -0,0 +1,38 @@
+// Copyright 2006, Google Inc.
+// All rights reserved.
+//
+// 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.
+
+#include <stdio.h>
+
+#include "gtest/gtest.h"
+
+GTEST_API_ int main(int argc, char **argv) {
+  printf("Running main() from gtest_main.cc\n");
+  testing::InitGoogleTest(&argc, argv);
+  return RUN_ALL_TESTS();
+}
diff --git a/test/integration/CMakeLists.txt b/test/integration/CMakeLists.txt
new file mode 100644
index 0000000..ba38c2d
--- /dev/null
+++ b/test/integration/CMakeLists.txt
@@ -0,0 +1,8 @@
+set(TEST_TYPE "INTEGRATION")
+
+set(tests
+)
+
+link_directories(${PROJECT_BINARY_DIR}/test)
+
+ign_build_tests(TYPE INTEGRATION SOURCES ${tests})
diff --git a/test/performance/CMakeLists.txt b/test/performance/CMakeLists.txt
new file mode 100644
index 0000000..7cf00db
--- /dev/null
+++ b/test/performance/CMakeLists.txt
@@ -0,0 +1,8 @@
+set(TEST_TYPE "PERFORMANCE")
+
+set(tests
+)
+
+link_directories(${PROJECT_BINARY_DIR}/test)
+
+ign_build_tests(TYPE PERFORMANCE SOURCES ${tests})
diff --git a/test/regression/CMakeLists.txt b/test/regression/CMakeLists.txt
new file mode 100644
index 0000000..ebbc7da
--- /dev/null
+++ b/test/regression/CMakeLists.txt
@@ -0,0 +1,8 @@
+set(TEST_TYPE "REGRESSION")
+
+set(tests
+)
+
+link_directories(${PROJECT_BINARY_DIR}/test)
+
+ign_build_tests(TYPE REGRESSION SOURCES ${tests})
diff --git a/test/test_config.h.in b/test/test_config.h.in
new file mode 100644
index 0000000..b6ba74a
--- /dev/null
+++ b/test/test_config.h.in
@@ -0,0 +1 @@
+#define PROJECT_SOURCE_PATH "${PROJECT_SOURCE_DIR}"
diff --git a/tools/check_test_ran.py b/tools/check_test_ran.py
new file mode 100755
index 0000000..4b64fc7
--- /dev/null
+++ b/tools/check_test_ran.py
@@ -0,0 +1,79 @@
+#!/usr/bin/env python
+# Software License Agreement (BSD License)
+#
+# Copyright (c) 2008, Willow Garage, Inc.
+# All rights reserved.
+#
+# 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 Willow Garage, 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.
+#
+# Revision $Id: check_test_ran.py 16671 2012-04-27 16:15:28Z dthomas $
+
+"""
+Writes a test failure out to test file if it doesn't exist.
+"""
+
+# Adapted from rosunit/check_test_ran.py
+
+from __future__ import print_function
+NAME="check_test_ran.py"
+
+import os
+import sys
+
+def usage():
+    print("""Usage:
+\t%s test-file.xml
+"""%(NAME), file=sys.stderr)
+    print(sys.argv)
+    sys.exit(getattr(os, 'EX_USAGE', 1))
+
+def check_main():
+    if len(sys.argv) < 2:
+        usage()
+    test_file = sys.argv[1]
+        
+    print("Checking for test results in %s"%test_file)
+    
+    if not os.path.exists(test_file):
+        if not os.path.exists(os.path.dirname(test_file)):
+            os.makedirs(os.path.dirname(test_file))
+            
+        print("Cannot find results, writing failure results to", test_file)
+        
+        with open(test_file, 'w') as f:
+            test_name = os.path.basename(test_file)
+            d = {'test': test_name, 'test_file': test_file }
+            f.write("""<?xml version="1.0" encoding="UTF-8"?>
+<testsuite tests="1" failures="1" time="1" errors="0" name="%(test)s">
+  <testcase name="test_ran" status="run" time="1" classname="Results">
+    <failure message="Unable to find test results for %(test)s, test did not run.\nExpected results in %(test_file)s" type=""/>
+  </testcase>
+</testsuite>"""%d)
+
+if __name__ == '__main__':
+    check_main()
diff --git a/tools/code_check.sh b/tools/code_check.sh
new file mode 100644
index 0000000..42b03e3
--- /dev/null
+++ b/tools/code_check.sh
@@ -0,0 +1,150 @@
+#!/bin/sh
+
+# Jenkins will pass -xml, in which case we want to generate XML output
+xmlout=0
+if test "$1" = "-xmldir" -a -n "$2"; then
+  xmlout=1
+  xmldir=$2
+  mkdir -p $xmldir
+  rm -rf $xmldir/*.xml
+  # Assuming that Jenkins called, the `build` directory is sibling to src dir
+  builddir=../build
+else
+  # This is a heuristic guess; not everyone puts the `build` dir in the src dir
+  builddir=./build
+fi
+
+# Identify cppcheck version
+CPPCHECK_VERSION=`cppcheck --version | sed -e 's at Cppcheck @@'`
+CPPCHECK_LT_157=`echo "$CPPCHECK_VERSION 1.57" | \
+                 awk '{if ($1 < $2) print 1; else print 0}'`
+
+QUICK_CHECK=0
+if test "$1" = "--quick"
+then
+  QUICK_CHECK=1
+  QUICK_SOURCE=$2
+  hg_root=`hg root`
+  if [ "$?" -ne "0" ] ; then
+    echo This is not an hg repository
+    exit
+  fi
+  cd $hg_root
+  hg log -r $QUICK_SOURCE > /dev/null
+  if [ "$?" -ne "0" ] ; then
+    echo $QUICK_SOURCE is not a valid changeset hash
+    exit
+  fi
+  CHECK_FILES=""
+  while read line; do
+    for f in $line; do
+      CHECK_FILES="$CHECK_FILES `echo $f | grep '\.[ch][ch]*$' | grep -v '^deps'`"
+    done
+  done
+  CPPCHECK_FILES="$CHECK_FILES"
+  CPPLINT_FILES="$CHECK_FILES"
+  QUICK_TMP=`mktemp -t asdfXXXXXXXXXX`
+else
+  CHECK_DIRS="./src ./include ./test/integration ./test/regression ./test/performance"
+  if [ $CPPCHECK_LT_157 -eq 1 ]; then
+    # cppcheck is older than 1.57, so don't check header files (issue #907)
+    CPPCHECK_FILES=`find $CHECK_DIRS -name "*.cc"`
+  else
+    CPPCHECK_FILES=`find $CHECK_DIRS -name "*.cc" -o -name "*.hh"`
+  fi
+  CPPLINT_FILES=`\
+    find $CHECK_DIRS -name "*.cc" -o -name "*.hh" -o -name "*.c" -o -name "*.h"`
+fi
+
+SUPPRESS=/tmp/cpp_check.suppress
+
+# The follow suppression is useful when checking for missing includes.
+# It's disable for now because checking for missing includes is very
+# time consuming. See CPPCHECK_CMD3.
+SUPPRESS=/tmp/gazebo_cpp_check.suppress
+# false positives related to explicit constructors where there is no
+# constructor declared
+echo "*:include/ignition/math/Vector2.hh:230" > $SUPPRESS
+echo "*:include/ignition/math/Vector3.hh:372" >> $SUPPRESS
+echo "*:include/ignition/math/Vector3.hh:433" >> $SUPPRESS
+echo "*:include/ignition/math/Vector3.hh:536" >> $SUPPRESS
+echo "*:include/ignition/math/Vector4.hh:257" >> $SUPPRESS
+echo "*:include/ignition/math/Vector4.hh:258" >> $SUPPRESS	
+
+#cppcheck
+CPPCHECK_BASE="cppcheck -q --suppressions-list=$SUPPRESS --inline-suppr"
+if [ $CPPCHECK_LT_157 -eq 0 ]; then
+  # use --language argument if 1.57 or greater (issue #907)
+  CPPCHECK_BASE="$CPPCHECK_BASE --language=c++"
+fi
+CPPCHECK_INCLUDES="-I ./include -I $builddir -I test -I ./include/ignition/math"
+CPPCHECK_RULES="-DIGNITION_MATH_VISIBLE"\
+" --rule-file=./tools/cppcheck_rules/header_guard.rule"\
+" --rule-file=./tools/cppcheck_rules/namespace_AZ.rule"
+CPPCHECK_CMD1A="-j 4 --enable=style,performance,portability,information"
+CPPCHECK_CMD1B="$CPPCHECK_RULES $CPPCHECK_FILES"
+CPPCHECK_CMD1="$CPPCHECK_CMD1A $CPPCHECK_CMD1B"
+CPPCHECK_CMD2="--enable=unusedFunction $CPPCHECK_FILES"
+
+# Checking for missing includes is very time consuming. This is disabled
+# for now
+CPPCHECK_CMD3="-j 4 --enable=missingInclude $CPPCHECK_FILES $CPPCHECK_INCLUDES"
+# CPPCHECK_CMD3=""
+
+if [ $xmlout -eq 1 ]; then
+  # Performance, style, portability, and information
+  ($CPPCHECK_BASE --xml $CPPCHECK_CMD1) 2> $xmldir/cppcheck.xml
+
+  # Check the configuration
+  ($CPPCHECK_BASE --xml $CPPCHECK_CMD3) 2> $xmldir/cppcheck-configuration.xml
+elif [ $QUICK_CHECK -eq 1 ]; then
+  for f in $CHECK_FILES; do
+    prefix=`basename $f | sed -e 's@\..*$@@'`
+    ext=`echo $f | sed -e 's@^.*\.@@'`
+    tmp2="$QUICK_TMP"."$ext"
+    tmp2base=`basename "$QUICK_TMP"`
+    hg cat -r $QUICK_SOURCE $hg_root/$f > $tmp2
+
+    # Fix suppressions for tmp files
+    sed -i -e "s@$f@$tmp2@" $SUPPRESS
+
+    # Skip cppcheck for header files if cppcheck is old
+    DO_CPPCHECK=0
+    if [ $ext = 'cc' ]; then
+      DO_CPPCHECK=1
+    elif [ $CPPCHECK_LT_157 -eq 0 ]; then
+      DO_CPPCHECK=1
+    fi 
+
+    if [ $DO_CPPCHECK -eq 1 ]; then
+      $CPPCHECK_BASE $CPPCHECK_CMD1A $CPPCHECK_RULES $tmp2 2>&1 \
+        | sed -e "s@$tmp2@$f at g" \
+        | grep -v 'use --check-config for details' \
+        | grep -v 'Include file: .*not found'
+    fi
+
+    # Undo changes to suppression file
+    sed -i -e "s@$tmp2@$f@" $SUPPRESS
+
+    python $hg_root/tools/cpplint.py $tmp2 2>&1 \
+      | sed -e "s@$tmp2@$f at g" -e "s@$tmp2base@$prefix at g" \
+      | grep -v 'Total errors found: 0'
+
+    rm $tmp2
+  done
+  rm $QUICK_TMP
+else
+  # Performance, style, portability, and information
+  $CPPCHECK_BASE $CPPCHECK_INCLUDES $CPPCHECK_CMD1 2>&1
+
+  # Check the configuration
+  $CPPCHECK_BASE $CPPCHECK_CMD3 2>&1
+fi
+
+# cpplint
+if [ $xmlout -eq 1 ]; then
+  (echo $CPPLINT_FILES | xargs python tools/cpplint.p --extensions=cc,hhy 2>&1) \
+    | python tools/cpplint_to_cppcheckxml.py 2> $xmldir/cpplint.xml
+elif [ $QUICK_CHECK -eq 0 ]; then
+  echo $CPPLINT_FILES | xargs python tools/cpplint.py --extensions=cc,hh 2>&1
+fi
diff --git a/tools/cppcheck_rules/header_guard.rule b/tools/cppcheck_rules/header_guard.rule
new file mode 100644
index 0000000..6607951
--- /dev/null
+++ b/tools/cppcheck_rules/header_guard.rule
@@ -0,0 +1,10 @@
+<?xml version="1.0"?>
+<rule version="1">
+  <tokenlist>define</tokenlist>
+  <pattern>#define _[A-Z]</pattern>
+  <message>
+    <id>_AZdefine</id>
+    <severity>warning</severity>
+    <summary>Definitions should not start with underscore and then a capital letter.</summary>
+  </message>
+</rule>
diff --git a/tools/cppcheck_rules/namespace_AZ.rule b/tools/cppcheck_rules/namespace_AZ.rule
new file mode 100644
index 0000000..75250d7
--- /dev/null
+++ b/tools/cppcheck_rules/namespace_AZ.rule
@@ -0,0 +1,9 @@
+<?xml version="1.0"?>
+<rule version="1">
+  <pattern>:: _[A-Z]</pattern>
+  <message>
+    <id>_AZnaming</id>
+    <severity>warning</severity>
+    <summary>Identifier that starts with underscore and then a capital letter is reserved.</summary>
+  </message>
+</rule>
diff --git a/tools/cpplint.py b/tools/cpplint.py
new file mode 100644
index 0000000..1b1e4cf
--- /dev/null
+++ b/tools/cpplint.py
@@ -0,0 +1,5622 @@
+#!/usr/bin/python
+#
+# Copyright (c) 2009 Google Inc. All rights reserved.
+#
+# 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.
+
+"""Does google-lint on c++ files.
+
+The goal of this script is to identify places in the code that *may*
+be in non-compliance with google style.  It does not attempt to fix
+up these problems -- the point is to educate.  It does also not
+attempt to find all problems, or to ensure that everything it does
+find is legitimately a problem.
+
+In particular, we can get very confused by /* and // inside strings!
+We do a small hack, which is to ignore //'s with "'s after them on the
+same line, but it is far from perfect (in either direction).
+"""
+
+import codecs
+import copy
+import getopt
+import math  # for log
+import os
+import re
+import sre_compile
+import string
+import sys
+import unicodedata
+
+
+_USAGE = """
+Syntax: cpplint.py [--verbose=#] [--output=vs7] [--filter=-x,+y,...]
+                   [--counting=total|toplevel|detailed] [--root=subdir]
+                   [--linelength=digits]
+        <file> [file] ...
+
+  The style guidelines this tries to follow are those in
+    http://google-styleguide.googlecode.com/svn/trunk/cppguide.xml
+
+  Every problem is given a confidence score from 1-5, with 5 meaning we are
+  certain of the problem, and 1 meaning it could be a legitimate construct.
+  This will miss some errors, and is not a substitute for a code review.
+
+  To suppress false-positive errors of a certain category, add a
+  'NOLINT(category)' comment to the line.  NOLINT or NOLINT(*)
+  suppresses errors of all categories on that line.
+
+  The files passed in will be linted; at least one file must be provided.
+  Default linted extensions are .cc, .cpp, .cu, .cuh and .h.  Change the
+  extensions with the --extensions flag.
+
+  Flags:
+
+    output=vs7
+      By default, the output is formatted to ease emacs parsing.  Visual Studio
+      compatible output (vs7) may also be used.  Other formats are unsupported.
+
+    verbose=#
+      Specify a number 0-5 to restrict errors to certain verbosity levels.
+
+    filter=-x,+y,...
+      Specify a comma-separated list of category-filters to apply: only
+      error messages whose category names pass the filters will be printed.
+      (Category names are printed with the message and look like
+      "[whitespace/indent]".)  Filters are evaluated left to right.
+      "-FOO" and "FOO" means "do not print categories that start with FOO".
+      "+FOO" means "do print categories that start with FOO".
+
+      Examples: --filter=-whitespace,+whitespace/braces
+                --filter=whitespace,runtime/printf,+runtime/printf_format
+                --filter=-,+build/include_what_you_use
+
+      To see a list of all the categories used in cpplint, pass no arg:
+         --filter=
+
+    counting=total|toplevel|detailed
+      The total number of errors found is always printed. If
+      'toplevel' is provided, then the count of errors in each of
+      the top-level categories like 'build' and 'whitespace' will
+      also be printed. If 'detailed' is provided, then a count
+      is provided for each category like 'build/class'.
+
+    root=subdir
+      The root directory used for deriving header guard CPP variable.
+      By default, the header guard CPP variable is calculated as the relative
+      path to the directory that contains .git, .hg, or .svn.  When this flag
+      is specified, the relative path is calculated from the specified
+      directory. If the specified directory does not exist, this flag is
+      ignored.
+
+      Examples:
+        Assuming that src/.git exists, the header guard CPP variables for
+        src/chrome/browser/ui/browser.h are:
+
+        No flag => CHROME_BROWSER_UI_BROWSER_H_
+        --root=chrome => BROWSER_UI_BROWSER_H_
+        --root=chrome/browser => UI_BROWSER_H_
+
+    linelength=digits
+      This is the allowed line length for the project. The default value is
+      80 characters.
+
+      Examples:
+        --linelength=120
+
+    extensions=extension,extension,...
+      The allowed file extensions that cpplint will check
+
+      Examples:
+        --extensions=hpp,cpp
+"""
+
+# We categorize each error message we print.  Here are the categories.
+# We want an explicit list so we can list them all in cpplint --filter=.
+# If you add a new error message with a new category, add it to the list
+# here!  cpplint_unittest.py should tell you if you forget to do this.
+_ERROR_CATEGORIES = [
+  'build/class',
+  'build/c++11',
+  'build/deprecated',
+  'build/endif_comment',
+  'build/explicit_make_pair',
+  'build/forward_decl',
+  'build/header_guard',
+  'build/include',
+  'build/include_alpha',
+  'build/include_order',
+  'build/include_what_you_use',
+  'build/namespaces',
+  'build/printf_format',
+  'build/storage_class',
+  'legal/copyright',
+  'readability/alt_tokens',
+  'readability/braces',
+  'readability/casting',
+  'readability/check',
+  'readability/constructors',
+  'readability/fn_size',
+  'readability/function',
+  'readability/multiline_comment',
+  'readability/multiline_string',
+  'readability/namespace',
+  'readability/nolint',
+  'readability/nul',
+  'readability/streams',
+  'readability/todo',
+  'readability/utf8',
+  'runtime/arrays',
+  'runtime/casting',
+  'runtime/explicit',
+  'runtime/int',
+  'runtime/init',
+  'runtime/invalid_increment',
+  'runtime/member_string_references',
+  'runtime/memset',
+  'runtime/operator',
+  'runtime/printf',
+  'runtime/printf_format',
+  'runtime/references',
+  'runtime/string',
+  'runtime/threadsafe_fn',
+  'runtime/vlog',
+  'whitespace/blank_line',
+  'whitespace/braces',
+  'whitespace/comma',
+  'whitespace/comments',
+  'whitespace/empty_conditional_body',
+  'whitespace/empty_loop_body',
+  'whitespace/end_of_line',
+  'whitespace/ending_newline',
+  'whitespace/forcolon',
+  'whitespace/indent',
+  'whitespace/line_length',
+  'whitespace/newline',
+  'whitespace/operators',
+  'whitespace/parens',
+  'whitespace/semicolon',
+  'whitespace/tab',
+  'whitespace/todo'
+  ]
+
+# The default state of the category filter. This is overridden by the --filter=
+# flag. By default all errors are on, so only add here categories that should be
+# off by default (i.e., categories that must be enabled by the --filter= flags).
+# All entries here should start with a '-' or '+', as in the --filter= flag.
+_DEFAULT_FILTERS = ['-build/include_alpha']
+
+# We used to check for high-bit characters, but after much discussion we
+# decided those were OK, as long as they were in UTF-8 and didn't represent
+# hard-coded international strings, which belong in a separate i18n file.
+
+# C++ headers
+_CPP_HEADERS = frozenset([
+    # Legacy
+    'algobase.h',
+    'algo.h',
+    'alloc.h',
+    'builtinbuf.h',
+    'bvector.h',
+    'complex.h',
+    'defalloc.h',
+    'deque.h',
+    'editbuf.h',
+    'fstream.h',
+    'function.h',
+    'hash_map',
+    'hash_map.h',
+    'hash_set',
+    'hash_set.h',
+    'hashtable.h',
+    'heap.h',
+    'indstream.h',
+    'iomanip.h',
+    'iostream.h',
+    'istream.h',
+    'iterator.h',
+    'list.h',
+    'map.h',
+    'multimap.h',
+    'multiset.h',
+    'ostream.h',
+    'pair.h',
+    'parsestream.h',
+    'pfstream.h',
+    'procbuf.h',
+    'pthread_alloc',
+    'pthread_alloc.h',
+    'rope',
+    'rope.h',
+    'ropeimpl.h',
+    'set.h',
+    'slist',
+    'slist.h',
+    'stack.h',
+    'stdiostream.h',
+    'stl_alloc.h',
+    'stl_relops.h',
+    'streambuf.h',
+    'stream.h',
+    'strfile.h',
+    'strstream.h',
+    'tempbuf.h',
+    'tree.h',
+    'type_traits.h',
+    'vector.h',
+    # 17.6.1.2 C++ library headers
+    'algorithm',
+    'array',
+    'atomic',
+    'bitset',
+    'chrono',
+    'codecvt',
+    'complex',
+    'condition_variable',
+    'deque',
+    'exception',
+    'forward_list',
+    'fstream',
+    'functional',
+    'future',
+    'initializer_list',
+    'iomanip',
+    'ios',
+    'iosfwd',
+    'iostream',
+    'istream',
+    'iterator',
+    'limits',
+    'list',
+    'locale',
+    'map',
+    'memory',
+    'mutex',
+    'new',
+    'numeric',
+    'ostream',
+    'queue',
+    'random',
+    'ratio',
+    'regex',
+    'set',
+    'sstream',
+    'stack',
+    'stdexcept',
+    'streambuf',
+    'string',
+    'strstream',
+    'system_error',
+    'thread',
+    'tuple',
+    'typeindex',
+    'typeinfo',
+    'type_traits',
+    'unordered_map',
+    'unordered_set',
+    'utility',
+    'valarray',
+    'vector',
+    # 17.6.1.2 C++ headers for C library facilities
+    'cassert',
+    'ccomplex',
+    'cctype',
+    'cerrno',
+    'cfenv',
+    'cfloat',
+    'cinttypes',
+    'ciso646',
+    'climits',
+    'clocale',
+    'cmath',
+    'csetjmp',
+    'csignal',
+    'cstdalign',
+    'cstdarg',
+    'cstdbool',
+    'cstddef',
+    'cstdint',
+    'cstdio',
+    'cstdlib',
+    'cstring',
+    'ctgmath',
+    'ctime',
+    'cuchar',
+    'cwchar',
+    'cwctype',
+    ])
+
+
+# Assertion macros.  These are defined in base/logging.h and
+# testing/base/gunit.h.  Note that the _M versions need to come first
+# for substring matching to work.
+_CHECK_MACROS = [
+    'DCHECK', 'CHECK',
+    'EXPECT_TRUE_M', 'EXPECT_TRUE',
+    'ASSERT_TRUE_M', 'ASSERT_TRUE',
+    'EXPECT_FALSE_M', 'EXPECT_FALSE',
+    'ASSERT_FALSE_M', 'ASSERT_FALSE',
+    ]
+
+# Replacement macros for CHECK/DCHECK/EXPECT_TRUE/EXPECT_FALSE
+_CHECK_REPLACEMENT = dict([(m, {}) for m in _CHECK_MACROS])
+
+for op, replacement in [('==', 'EQ'), ('!=', 'NE'),
+                        ('>=', 'GE'), ('>', 'GT'),
+                        ('<=', 'LE'), ('<', 'LT')]:
+  _CHECK_REPLACEMENT['DCHECK'][op] = 'DCHECK_%s' % replacement
+  _CHECK_REPLACEMENT['CHECK'][op] = 'CHECK_%s' % replacement
+  _CHECK_REPLACEMENT['EXPECT_TRUE'][op] = 'EXPECT_%s' % replacement
+  _CHECK_REPLACEMENT['ASSERT_TRUE'][op] = 'ASSERT_%s' % replacement
+  _CHECK_REPLACEMENT['EXPECT_TRUE_M'][op] = 'EXPECT_%s_M' % replacement
+  _CHECK_REPLACEMENT['ASSERT_TRUE_M'][op] = 'ASSERT_%s_M' % replacement
+
+for op, inv_replacement in [('==', 'NE'), ('!=', 'EQ'),
+                            ('>=', 'LT'), ('>', 'LE'),
+                            ('<=', 'GT'), ('<', 'GE')]:
+  _CHECK_REPLACEMENT['EXPECT_FALSE'][op] = 'EXPECT_%s' % inv_replacement
+  _CHECK_REPLACEMENT['ASSERT_FALSE'][op] = 'ASSERT_%s' % inv_replacement
+  _CHECK_REPLACEMENT['EXPECT_FALSE_M'][op] = 'EXPECT_%s_M' % inv_replacement
+  _CHECK_REPLACEMENT['ASSERT_FALSE_M'][op] = 'ASSERT_%s_M' % inv_replacement
+
+# Alternative tokens and their replacements.  For full list, see section 2.5
+# Alternative tokens [lex.digraph] in the C++ standard.
+#
+# Digraphs (such as '%:') are not included here since it's a mess to
+# match those on a word boundary.
+_ALT_TOKEN_REPLACEMENT = {
+    'and': '&&',
+    'bitor': '|',
+    'or': '||',
+    'xor': '^',
+    'compl': '~',
+    'bitand': '&',
+    'and_eq': '&=',
+    'or_eq': '|=',
+    'xor_eq': '^=',
+    'not': '!',
+    'not_eq': '!='
+    }
+
+# Compile regular expression that matches all the above keywords.  The "[ =()]"
+# bit is meant to avoid matching these keywords outside of boolean expressions.
+#
+# False positives include C-style multi-line comments and multi-line strings
+# but those have always been troublesome for cpplint.
+_ALT_TOKEN_REPLACEMENT_PATTERN = re.compile(
+    r'[ =()](' + ('|'.join(_ALT_TOKEN_REPLACEMENT.keys())) + r')(?=[ (]|$)')
+
+
+# These constants define types of headers for use with
+# _IncludeState.CheckNextIncludeOrder().
+_C_SYS_HEADER = 1
+_CPP_SYS_HEADER = 2
+_LIKELY_MY_HEADER = 3
+_POSSIBLE_MY_HEADER = 4
+_OTHER_HEADER = 5
+
+# These constants define the current inline assembly state
+_NO_ASM = 0       # Outside of inline assembly block
+_INSIDE_ASM = 1   # Inside inline assembly block
+_END_ASM = 2      # Last line of inline assembly block
+_BLOCK_ASM = 3    # The whole block is an inline assembly block
+
+# Match start of assembly blocks
+_MATCH_ASM = re.compile(r'^\s*(?:asm|_asm|__asm|__asm__)'
+                        r'(?:\s+(volatile|__volatile__))?'
+                        r'\s*[{(]')
+
+
+_regexp_compile_cache = {}
+
+# Finds occurrences of NOLINT or NOLINT(...).
+_RE_SUPPRESSION = re.compile(r'\bNOLINT\b(\([^)]*\))?')
+
+# {str, set(int)}: a map from error categories to sets of linenumbers
+# on which those errors are expected and should be suppressed.
+_error_suppressions = {}
+
+# The root directory used for deriving header guard CPP variable.
+# This is set by --root flag.
+_root = None
+
+# The allowed line length of files.
+# This is set by --linelength flag.
+_line_length = 80
+
+# The allowed extensions for file names
+# This is set by --extensions flag.
+_valid_extensions = set(['cc', 'hh', 'h', 'cpp', 'cu', 'cuh'])
+
+def ParseNolintSuppressions(filename, raw_line, linenum, error):
+  """Updates the global list of error-suppressions.
+
+  Parses any NOLINT comments on the current line, updating the global
+  error_suppressions store.  Reports an error if the NOLINT comment
+  was malformed.
+
+  Args:
+    filename: str, the name of the input file.
+    raw_line: str, the line of input text, with comments.
+    linenum: int, the number of the current line.
+    error: function, an error handler.
+  """
+  # FIXME(adonovan): "NOLINT(" is misparsed as NOLINT(*).
+  matched = _RE_SUPPRESSION.search(raw_line)
+  if matched:
+    category = matched.group(1)
+    if category in (None, '(*)'):  # => "suppress all"
+      _error_suppressions.setdefault(None, set()).add(linenum)
+    else:
+      if category.startswith('(') and category.endswith(')'):
+        category = category[1:-1]
+        if category in _ERROR_CATEGORIES:
+          _error_suppressions.setdefault(category, set()).add(linenum)
+        else:
+          error(filename, linenum, 'readability/nolint', 5,
+                'Unknown NOLINT error category: %s' % category)
+
+
+def ResetNolintSuppressions():
+  "Resets the set of NOLINT suppressions to empty."
+  _error_suppressions.clear()
+
+
+def IsErrorSuppressedByNolint(category, linenum):
+  """Returns true if the specified error category is suppressed on this line.
+
+  Consults the global error_suppressions map populated by
+  ParseNolintSuppressions/ResetNolintSuppressions.
+
+  Args:
+    category: str, the category of the error.
+    linenum: int, the current line number.
+  Returns:
+    bool, True iff the error should be suppressed due to a NOLINT comment.
+  """
+  return (linenum in _error_suppressions.get(category, set()) or
+          linenum in _error_suppressions.get(None, set()))
+
+
+def Match(pattern, s):
+  """Matches the string with the pattern, caching the compiled regexp."""
+  # The regexp compilation caching is inlined in both Match and Search for
+  # performance reasons; factoring it out into a separate function turns out
+  # to be noticeably expensive.
+  if pattern not in _regexp_compile_cache:
+    _regexp_compile_cache[pattern] = sre_compile.compile(pattern)
+  return _regexp_compile_cache[pattern].match(s)
+
+
+def ReplaceAll(pattern, rep, s):
+  """Replaces instances of pattern in a string with a replacement.
+
+  The compiled regex is kept in a cache shared by Match and Search.
+
+  Args:
+    pattern: regex pattern
+    rep: replacement text
+    s: search string
+
+  Returns:
+    string with replacements made (or original string if no replacements)
+  """
+  if pattern not in _regexp_compile_cache:
+    _regexp_compile_cache[pattern] = sre_compile.compile(pattern)
+  return _regexp_compile_cache[pattern].sub(rep, s)
+
+
+def Search(pattern, s):
+  """Searches the string for the pattern, caching the compiled regexp."""
+  if pattern not in _regexp_compile_cache:
+    _regexp_compile_cache[pattern] = sre_compile.compile(pattern)
+  return _regexp_compile_cache[pattern].search(s)
+
+
+class _IncludeState(dict):
+  """Tracks line numbers for includes, and the order in which includes appear.
+
+  As a dict, an _IncludeState object serves as a mapping between include
+  filename and line number on which that file was included.
+
+  Call CheckNextIncludeOrder() once for each header in the file, passing
+  in the type constants defined above. Calls in an illegal order will
+  raise an _IncludeError with an appropriate error message.
+
+  """
+  # self._section will move monotonically through this set. If it ever
+  # needs to move backwards, CheckNextIncludeOrder will raise an error.
+  _INITIAL_SECTION = 0
+  _MY_H_SECTION = 1
+  _C_SECTION = 2
+  _CPP_SECTION = 3
+  _OTHER_H_SECTION = 4
+
+  _TYPE_NAMES = {
+      _C_SYS_HEADER: 'C system header',
+      _CPP_SYS_HEADER: 'C++ system header',
+      _LIKELY_MY_HEADER: 'header this file implements',
+      _POSSIBLE_MY_HEADER: 'header this file may implement',
+      _OTHER_HEADER: 'other header',
+      }
+  _SECTION_NAMES = {
+      _INITIAL_SECTION: "... nothing. (This can't be an error.)",
+      _MY_H_SECTION: 'a header this file implements',
+      _C_SECTION: 'C system header',
+      _CPP_SECTION: 'C++ system header',
+      _OTHER_H_SECTION: 'other header',
+      }
+
+  def __init__(self):
+    dict.__init__(self)
+    self.ResetSection()
+
+  def ResetSection(self):
+    # The name of the current section.
+    self._section = self._INITIAL_SECTION
+    # The path of last found header.
+    self._last_header = ''
+
+  def SetLastHeader(self, header_path):
+    self._last_header = header_path
+
+  def CanonicalizeAlphabeticalOrder(self, header_path):
+    """Returns a path canonicalized for alphabetical comparison.
+
+    - replaces "-" with "_" so they both cmp the same.
+    - removes '-inl' since we don't require them to be after the main header.
+    - lowercase everything, just in case.
+
+    Args:
+      header_path: Path to be canonicalized.
+
+    Returns:
+      Canonicalized path.
+    """
+    return header_path.replace('-inl.h', '.h').replace('-', '_').lower()
+
+  def IsInAlphabeticalOrder(self, clean_lines, linenum, header_path):
+    """Check if a header is in alphabetical order with the previous header.
+
+    Args:
+      clean_lines: A CleansedLines instance containing the file.
+      linenum: The number of the line to check.
+      header_path: Canonicalized header to be checked.
+
+    Returns:
+      Returns true if the header is in alphabetical order.
+    """
+    # If previous section is different from current section, _last_header will
+    # be reset to empty string, so it's always less than current header.
+    #
+    # If previous line was a blank line, assume that the headers are
+    # intentionally sorted the way they are.
+    if (self._last_header > header_path and
+        not Match(r'^\s*$', clean_lines.elided[linenum - 1])):
+      return False
+    return True
+
+  def CheckNextIncludeOrder(self, header_type):
+    """Returns a non-empty error message if the next header is out of order.
+
+    This function also updates the internal state to be ready to check
+    the next include.
+
+    Args:
+      header_type: One of the _XXX_HEADER constants defined above.
+
+    Returns:
+      The empty string if the header is in the right order, or an
+      error message describing what's wrong.
+
+    """
+    error_message = ('Found %s after %s' %
+                     (self._TYPE_NAMES[header_type],
+                      self._SECTION_NAMES[self._section]))
+
+    last_section = self._section
+
+    if header_type == _C_SYS_HEADER:
+      if self._section <= self._C_SECTION:
+        self._section = self._C_SECTION
+      else:
+        self._last_header = ''
+        return error_message
+    elif header_type == _CPP_SYS_HEADER:
+      if self._section <= self._CPP_SECTION:
+        self._section = self._CPP_SECTION
+      else:
+        self._last_header = ''
+        return error_message
+    elif header_type == _LIKELY_MY_HEADER:
+      if self._section <= self._MY_H_SECTION:
+        self._section = self._MY_H_SECTION
+      else:
+        self._section = self._OTHER_H_SECTION
+    elif header_type == _POSSIBLE_MY_HEADER:
+      if self._section <= self._MY_H_SECTION:
+        self._section = self._MY_H_SECTION
+      else:
+        # This will always be the fallback because we're not sure
+        # enough that the header is associated with this file.
+        self._section = self._OTHER_H_SECTION
+    else:
+      assert header_type == _OTHER_HEADER
+      self._section = self._OTHER_H_SECTION
+
+    if last_section != self._section:
+      self._last_header = ''
+
+    return ''
+
+
+class _CppLintState(object):
+  """Maintains module-wide state.."""
+
+  def __init__(self):
+    self.verbose_level = 1  # global setting.
+    self.error_count = 0    # global count of reported errors
+    # filters to apply when emitting error messages
+    self.filters = _DEFAULT_FILTERS[:]
+    self.counting = 'total'  # In what way are we counting errors?
+    self.errors_by_category = {}  # string to int dict storing error counts
+
+    # output format:
+    # "emacs" - format that emacs can parse (default)
+    # "vs7" - format that Microsoft Visual Studio 7 can parse
+    self.output_format = 'emacs'
+
+  def SetOutputFormat(self, output_format):
+    """Sets the output format for errors."""
+    self.output_format = output_format
+
+  def SetVerboseLevel(self, level):
+    """Sets the module's verbosity, and returns the previous setting."""
+    last_verbose_level = self.verbose_level
+    self.verbose_level = level
+    return last_verbose_level
+
+  def SetCountingStyle(self, counting_style):
+    """Sets the module's counting options."""
+    self.counting = counting_style
+
+  def SetFilters(self, filters):
+    """Sets the error-message filters.
+
+    These filters are applied when deciding whether to emit a given
+    error message.
+
+    Args:
+      filters: A string of comma-separated filters (eg "+whitespace/indent").
+               Each filter should start with + or -; else we die.
+
+    Raises:
+      ValueError: The comma-separated filters did not all start with '+' or '-'.
+                  E.g. "-,+whitespace,-whitespace/indent,whitespace/badfilter"
+    """
+    # Default filters always have less priority than the flag ones.
+    self.filters = _DEFAULT_FILTERS[:]
+    for filt in filters.split(','):
+      clean_filt = filt.strip()
+      if clean_filt:
+        self.filters.append(clean_filt)
+    for filt in self.filters:
+      if not (filt.startswith('+') or filt.startswith('-')):
+        raise ValueError('Every filter in --filters must start with + or -'
+                         ' (%s does not)' % filt)
+
+  def ResetErrorCounts(self):
+    """Sets the module's error statistic back to zero."""
+    self.error_count = 0
+    self.errors_by_category = {}
+
+  def IncrementErrorCount(self, category):
+    """Bumps the module's error statistic."""
+    self.error_count += 1
+    if self.counting in ('toplevel', 'detailed'):
+      if self.counting != 'detailed':
+        category = category.split('/')[0]
+      if category not in self.errors_by_category:
+        self.errors_by_category[category] = 0
+      self.errors_by_category[category] += 1
+
+  def PrintErrorCounts(self):
+    """Print a summary of errors by category, and the total."""
+    for category, count in self.errors_by_category.iteritems():
+      sys.stderr.write('Category \'%s\' errors found: %d\n' %
+                       (category, count))
+    sys.stderr.write('Total errors found: %d\n' % self.error_count)
+
+_cpplint_state = _CppLintState()
+
+
+def _OutputFormat():
+  """Gets the module's output format."""
+  return _cpplint_state.output_format
+
+
+def _SetOutputFormat(output_format):
+  """Sets the module's output format."""
+  _cpplint_state.SetOutputFormat(output_format)
+
+
+def _VerboseLevel():
+  """Returns the module's verbosity setting."""
+  return _cpplint_state.verbose_level
+
+
+def _SetVerboseLevel(level):
+  """Sets the module's verbosity, and returns the previous setting."""
+  return _cpplint_state.SetVerboseLevel(level)
+
+
+def _SetCountingStyle(level):
+  """Sets the module's counting options."""
+  _cpplint_state.SetCountingStyle(level)
+
+
+def _Filters():
+  """Returns the module's list of output filters, as a list."""
+  return _cpplint_state.filters
+
+
+def _SetFilters(filters):
+  """Sets the module's error-message filters.
+
+  These filters are applied when deciding whether to emit a given
+  error message.
+
+  Args:
+    filters: A string of comma-separated filters (eg "whitespace/indent").
+             Each filter should start with + or -; else we die.
+  """
+  _cpplint_state.SetFilters(filters)
+
+
+class _FunctionState(object):
+  """Tracks current function name and the number of lines in its body."""
+
+  _NORMAL_TRIGGER = 250  # for --v=0, 500 for --v=1, etc.
+  _TEST_TRIGGER = 400    # about 50% more than _NORMAL_TRIGGER.
+
+  def __init__(self):
+    self.in_a_function = False
+    self.lines_in_function = 0
+    self.current_function = ''
+
+  def Begin(self, function_name):
+    """Start analyzing function body.
+
+    Args:
+      function_name: The name of the function being tracked.
+    """
+    self.in_a_function = True
+    self.lines_in_function = 0
+    self.current_function = function_name
+
+  def Count(self):
+    """Count line in current function body."""
+    if self.in_a_function:
+      self.lines_in_function += 1
+
+  def Check(self, error, filename, linenum):
+    """Report if too many lines in function body.
+
+    Args:
+      error: The function to call with any errors found.
+      filename: The name of the current file.
+      linenum: The number of the line to check.
+    """
+    if Match(r'T(EST|est)', self.current_function):
+      base_trigger = self._TEST_TRIGGER
+    else:
+      base_trigger = self._NORMAL_TRIGGER
+    trigger = base_trigger * 2**_VerboseLevel()
+
+    if self.lines_in_function > trigger:
+      error_level = int(math.log(self.lines_in_function / base_trigger, 2))
+      # 50 => 0, 100 => 1, 200 => 2, 400 => 3, 800 => 4, 1600 => 5, ...
+      if error_level > 5:
+        error_level = 5
+      error(filename, linenum, 'readability/fn_size', error_level,
+            'Small and focused functions are preferred:'
+            ' %s has %d non-comment lines'
+            ' (error triggered by exceeding %d lines).'  % (
+                self.current_function, self.lines_in_function, trigger))
+
+  def End(self):
+    """Stop analyzing function body."""
+    self.in_a_function = False
+
+
+class _IncludeError(Exception):
+  """Indicates a problem with the include order in a file."""
+  pass
+
+
+class FileInfo:
+  """Provides utility functions for filenames.
+
+  FileInfo provides easy access to the components of a file's path
+  relative to the project root.
+  """
+
+  def __init__(self, filename):
+    self._filename = filename
+
+  def FullName(self):
+    """Make Windows paths like Unix."""
+    return os.path.abspath(self._filename).replace('\\', '/')
+
+  def RepositoryName(self):
+    """FullName after removing the local path to the repository.
+
+    If we have a real absolute path name here we can try to do something smart:
+    detecting the root of the checkout and truncating /path/to/checkout from
+    the name so that we get header guards that don't include things like
+    "C:\Documents and Settings\..." or "/home/username/..." in them and thus
+    people on different computers who have checked the source out to different
+    locations won't see bogus errors.
+    """
+    fullname = self.FullName()
+
+    if os.path.exists(fullname):
+      project_dir = os.path.dirname(fullname)
+
+      if os.path.exists(os.path.join(project_dir, ".svn")):
+        # If there's a .svn file in the current directory, we recursively look
+        # up the directory tree for the top of the SVN checkout
+        root_dir = project_dir
+        one_up_dir = os.path.dirname(root_dir)
+        while os.path.exists(os.path.join(one_up_dir, ".svn")):
+          root_dir = os.path.dirname(root_dir)
+          one_up_dir = os.path.dirname(one_up_dir)
+
+        prefix = os.path.commonprefix([root_dir, project_dir])
+        return fullname[len(prefix) + 1:]
+
+      # Not SVN <= 1.6? Try to find a git, hg, or svn top level directory by
+      # searching up from the current path.
+      root_dir = os.path.dirname(fullname)
+      while (root_dir != os.path.dirname(root_dir) and
+             not os.path.exists(os.path.join(root_dir, ".git")) and
+             not os.path.exists(os.path.join(root_dir, ".hg")) and
+             not os.path.exists(os.path.join(root_dir, ".svn"))):
+        root_dir = os.path.dirname(root_dir)
+
+      if (os.path.exists(os.path.join(root_dir, ".git")) or
+          os.path.exists(os.path.join(root_dir, ".hg")) or
+          os.path.exists(os.path.join(root_dir, ".svn"))):
+        prefix = os.path.commonprefix([root_dir, project_dir])
+        return fullname[len(prefix) + 1:]
+
+    # Don't know what to do; header guard warnings may be wrong...
+    return fullname
+
+  def Split(self):
+    """Splits the file into the directory, basename, and extension.
+
+    For 'chrome/browser/browser.cc', Split() would
+    return ('chrome/browser', 'browser', '.cc')
+
+    Returns:
+      A tuple of (directory, basename, extension).
+    """
+
+    googlename = self.RepositoryName()
+    project, rest = os.path.split(googlename)
+    return (project,) + os.path.splitext(rest)
+
+  def BaseName(self):
+    """File base name - text after the final slash, before the final period."""
+    return self.Split()[1]
+
+  def Extension(self):
+    """File extension - text following the final period."""
+    return self.Split()[2]
+
+  def NoExtension(self):
+    """File has no source file extension."""
+    return '/'.join(self.Split()[0:2])
+
+  def IsSource(self):
+    """File has a source file extension."""
+    return self.Extension()[1:] in ('c', 'cc', 'cpp', 'cxx')
+
+
+def _ShouldPrintError(category, confidence, linenum):
+  """If confidence >= verbose, category passes filter and is not suppressed."""
+
+  # There are three ways we might decide not to print an error message:
+  # a "NOLINT(category)" comment appears in the source,
+  # the verbosity level isn't high enough, or the filters filter it out.
+  if IsErrorSuppressedByNolint(category, linenum):
+    return False
+
+  if confidence < _cpplint_state.verbose_level:
+    return False
+
+  is_filtered = False
+  for one_filter in _Filters():
+    if one_filter.startswith('-'):
+      if category.startswith(one_filter[1:]):
+        is_filtered = True
+    elif one_filter.startswith('+'):
+      if category.startswith(one_filter[1:]):
+        is_filtered = False
+    else:
+      assert False  # should have been checked for in SetFilter.
+  if is_filtered:
+    return False
+
+  return True
+
+
+def Error(filename, linenum, category, confidence, message):
+  """Logs the fact we've found a lint error.
+
+  We log where the error was found, and also our confidence in the error,
+  that is, how certain we are this is a legitimate style regression, and
+  not a misidentification or a use that's sometimes justified.
+
+  False positives can be suppressed by the use of
+  "cpplint(category)"  comments on the offending line.  These are
+  parsed into _error_suppressions.
+
+  Args:
+    filename: The name of the file containing the error.
+    linenum: The number of the line containing the error.
+    category: A string used to describe the "category" this bug
+      falls under: "whitespace", say, or "runtime".  Categories
+      may have a hierarchy separated by slashes: "whitespace/indent".
+    confidence: A number from 1-5 representing a confidence score for
+      the error, with 5 meaning that we are certain of the problem,
+      and 1 meaning that it could be a legitimate construct.
+    message: The error message.
+  """
+  if _ShouldPrintError(category, confidence, linenum):
+    _cpplint_state.IncrementErrorCount(category)
+    if _cpplint_state.output_format == 'vs7':
+      sys.stderr.write('%s(%s):  %s  [%s] [%d]\n' % (
+          filename, linenum, message, category, confidence))
+    elif _cpplint_state.output_format == 'eclipse':
+      sys.stderr.write('%s:%s: warning: %s  [%s] [%d]\n' % (
+          filename, linenum, message, category, confidence))
+    else:
+      sys.stderr.write('%s:%s:  %s  [%s] [%d]\n' % (
+          filename, linenum, message, category, confidence))
+
+
+# Matches standard C++ escape sequences per 2.13.2.3 of the C++ standard.
+_RE_PATTERN_CLEANSE_LINE_ESCAPES = re.compile(
+    r'\\([abfnrtv?"\\\']|\d+|x[0-9a-fA-F]+)')
+# Match a single C style comment on the same line.
+_RE_PATTERN_C_COMMENTS = r'/\*(?:[^*]|\*(?!/))*\*/'
+# Matches multi-line C style comments.
+# This RE is a little bit more complicated than one might expect, because we
+# have to take care of space removals tools so we can handle comments inside
+# statements better.
+# The current rule is: We only clear spaces from both sides when we're at the
+# end of the line. Otherwise, we try to remove spaces from the right side,
+# if this doesn't work we try on left side but only if there's a non-character
+# on the right.
+_RE_PATTERN_CLEANSE_LINE_C_COMMENTS = re.compile(
+    r'(\s*' + _RE_PATTERN_C_COMMENTS + r'\s*$|' +
+    _RE_PATTERN_C_COMMENTS + r'\s+|' +
+    r'\s+' + _RE_PATTERN_C_COMMENTS + r'(?=\W)|' +
+    _RE_PATTERN_C_COMMENTS + r')')
+
+
+def IsCppString(line):
+  """Does line terminate so, that the next symbol is in string constant.
+
+  This function does not consider single-line nor multi-line comments.
+
+  Args:
+    line: is a partial line of code starting from the 0..n.
+
+  Returns:
+    True, if next character appended to 'line' is inside a
+    string constant.
+  """
+
+  line = line.replace(r'\\', 'XX')  # after this, \\" does not match to \"
+  return ((line.count('"') - line.count(r'\"') - line.count("'\"'")) & 1) == 1
+
+
+def CleanseRawStrings(raw_lines):
+  """Removes C++11 raw strings from lines.
+
+    Before:
+      static const char kData[] = R"(
+          multi-line string
+          )";
+
+    After:
+      static const char kData[] = ""
+          (replaced by blank line)
+          "";
+
+  Args:
+    raw_lines: list of raw lines.
+
+  Returns:
+    list of lines with C++11 raw strings replaced by empty strings.
+  """
+
+  delimiter = None
+  lines_without_raw_strings = []
+  for line in raw_lines:
+    if delimiter:
+      # Inside a raw string, look for the end
+      end = line.find(delimiter)
+      if end >= 0:
+        # Found the end of the string, match leading space for this
+        # line and resume copying the original lines, and also insert
+        # a "" on the last line.
+        leading_space = Match(r'^(\s*)\S', line)
+        line = leading_space.group(1) + '""' + line[end + len(delimiter):]
+        delimiter = None
+      else:
+        # Haven't found the end yet, append a blank line.
+        line = '""'
+
+    # Look for beginning of a raw string, and replace them with
+    # empty strings.  This is done in a loop to handle multiple raw
+    # strings on the same line.
+    while delimiter is None:
+      # Look for beginning of a raw string.
+      # See 2.14.15 [lex.string] for syntax.
+      matched = Match(r'^(.*)\b(?:R|u8R|uR|UR|LR)"([^\s\\()]*)\((.*)$', line)
+      if matched:
+        delimiter = ')' + matched.group(2) + '"'
+
+        end = matched.group(3).find(delimiter)
+        if end >= 0:
+          # Raw string ended on same line
+          line = (matched.group(1) + '""' +
+                  matched.group(3)[end + len(delimiter):])
+          delimiter = None
+        else:
+          # Start of a multi-line raw string
+          line = matched.group(1) + '""'
+      else:
+        break
+
+    lines_without_raw_strings.append(line)
+
+  # TODO(unknown): if delimiter is not None here, we might want to
+  # emit a warning for unterminated string.
+  return lines_without_raw_strings
+
+
+def FindNextMultiLineCommentStart(lines, lineix):
+  """Find the beginning marker for a multiline comment."""
+  while lineix < len(lines):
+    if lines[lineix].strip().startswith('/*'):
+      # Only return this marker if the comment goes beyond this line
+      if lines[lineix].strip().find('*/', 2) < 0:
+        return lineix
+    lineix += 1
+  return len(lines)
+
+
+def FindNextMultiLineCommentEnd(lines, lineix):
+  """We are inside a comment, find the end marker."""
+  while lineix < len(lines):
+    if lines[lineix].strip().endswith('*/'):
+      return lineix
+    lineix += 1
+  return len(lines)
+
+
+def RemoveMultiLineCommentsFromRange(lines, begin, end):
+  """Clears a range of lines for multi-line comments."""
+  # Having // dummy comments makes the lines non-empty, so we will not get
+  # unnecessary blank line warnings later in the code.
+  for i in range(begin, end):
+    lines[i] = '// dummy'
+
+
+def RemoveMultiLineComments(filename, lines, error):
+  """Removes multiline (c-style) comments from lines."""
+  lineix = 0
+  while lineix < len(lines):
+    lineix_begin = FindNextMultiLineCommentStart(lines, lineix)
+    if lineix_begin >= len(lines):
+      return
+    lineix_end = FindNextMultiLineCommentEnd(lines, lineix_begin)
+    if lineix_end >= len(lines):
+      error(filename, lineix_begin + 1, 'readability/multiline_comment', 5,
+            'Could not find end of multi-line comment')
+      return
+    RemoveMultiLineCommentsFromRange(lines, lineix_begin, lineix_end + 1)
+    lineix = lineix_end + 1
+
+
+def CleanseComments(line):
+  """Removes //-comments and single-line C-style /* */ comments.
+
+  Args:
+    line: A line of C++ source.
+
+  Returns:
+    The line with single-line comments removed.
+  """
+  commentpos = line.find('//')
+  if commentpos != -1 and not IsCppString(line[:commentpos]):
+    line = line[:commentpos].rstrip()
+  # get rid of /* ... */
+  return _RE_PATTERN_CLEANSE_LINE_C_COMMENTS.sub('', line)
+
+
+class CleansedLines(object):
+  """Holds 3 copies of all lines with different preprocessing applied to them.
+
+  1) elided member contains lines without strings and comments,
+  2) lines member contains lines without comments, and
+  3) raw_lines member contains all the lines without processing.
+  All these three members are of <type 'list'>, and of the same length.
+  """
+
+  def __init__(self, lines):
+    self.elided = []
+    self.lines = []
+    self.raw_lines = lines
+    self.num_lines = len(lines)
+    self.lines_without_raw_strings = CleanseRawStrings(lines)
+    for linenum in range(len(self.lines_without_raw_strings)):
+      self.lines.append(CleanseComments(
+          self.lines_without_raw_strings[linenum]))
+      elided = self._CollapseStrings(self.lines_without_raw_strings[linenum])
+      self.elided.append(CleanseComments(elided))
+
+  def NumLines(self):
+    """Returns the number of lines represented."""
+    return self.num_lines
+
+  @staticmethod
+  def _CollapseStrings(elided):
+    """Collapses strings and chars on a line to simple "" or '' blocks.
+
+    We nix strings first so we're not fooled by text like '"http://"'
+
+    Args:
+      elided: The line being processed.
+
+    Returns:
+      The line with collapsed strings.
+    """
+    if _RE_PATTERN_INCLUDE.match(elided):
+      return elided
+
+    # Remove escaped characters first to make quote/single quote collapsing
+    # basic.  Things that look like escaped characters shouldn't occur
+    # outside of strings and chars.
+    elided = _RE_PATTERN_CLEANSE_LINE_ESCAPES.sub('', elided)
+
+    # Replace quoted strings and digit separators.  Both single quotes
+    # and double quotes are processed in the same loop, otherwise
+    # nested quotes wouldn't work.
+    collapsed = ''
+    while True:
+      # Find the first quote character
+      match = Match(r'^([^\'"]*)([\'"])(.*)$', elided)
+      if not match:
+        collapsed += elided
+        break
+      head, quote, tail = match.groups()
+
+      if quote == '"':
+        # Collapse double quoted strings
+        second_quote = tail.find('"')
+        if second_quote >= 0:
+          collapsed += head + '""'
+          elided = tail[second_quote + 1:]
+        else:
+          # Unmatched double quote, don't bother processing the rest
+          # of the line since this is probably a multiline string.
+          collapsed += elided
+          break
+      else:
+        # Found single quote, check nearby text to eliminate digit separators.
+        #
+        # There is no special handling for floating point here, because
+        # the integer/fractional/exponent parts would all be parsed
+        # correctly as long as there are digits on both sides of the
+        # separator.  So we are fine as long as we don't see something
+        # like "0.'3" (gcc 4.9.0 will not allow this literal).
+        if Search(r'\b(?:0[bBxX]?|[1-9])[0-9a-fA-F]*$', head):
+          match_literal = Match(r'^((?:\'?[0-9a-zA-Z_])*)(.*)$', "'" + tail)
+          collapsed += head + match_literal.group(1).replace("'", '')
+          elided = match_literal.group(2)
+        else:
+          second_quote = tail.find('\'')
+          if second_quote >= 0:
+            collapsed += head + "''"
+            elided = tail[second_quote + 1:]
+          else:
+            # Unmatched single quote
+            collapsed += elided
+            break
+
+    return collapsed
+
+
+def FindEndOfExpressionInLine(line, startpos, stack):
+  """Find the position just after the end of current parenthesized expression.
+
+  Args:
+    line: a CleansedLines line.
+    startpos: start searching at this position.
+    stack: nesting stack at startpos.
+
+  Returns:
+    On finding matching end: (index just after matching end, None)
+    On finding an unclosed expression: (-1, None)
+    Otherwise: (-1, new stack at end of this line)
+  """
+  for i in xrange(startpos, len(line)):
+    char = line[i]
+    if char in '([{':
+      # Found start of parenthesized expression, push to expression stack
+      stack.append(char)
+    elif char == '<':
+      # Found potential start of template argument list
+      if i > 0 and line[i - 1] == '<':
+        # Left shift operator
+        if stack and stack[-1] == '<':
+          stack.pop()
+          if not stack:
+            return (-1, None)
+      elif i > 0 and Search(r'\boperator\s*$', line[0:i]):
+        # operator<, don't add to stack
+        continue
+      else:
+        # Tentative start of template argument list
+        stack.append('<')
+    elif char in ')]}':
+      # Found end of parenthesized expression.
+      #
+      # If we are currently expecting a matching '>', the pending '<'
+      # must have been an operator.  Remove them from expression stack.
+      while stack and stack[-1] == '<':
+        stack.pop()
+      if not stack:
+        return (-1, None)
+      if ((stack[-1] == '(' and char == ')') or
+          (stack[-1] == '[' and char == ']') or
+          (stack[-1] == '{' and char == '}')):
+        stack.pop()
+        if not stack:
+          return (i + 1, None)
+      else:
+        # Mismatched parentheses
+        return (-1, None)
+    elif char == '>':
+      # Found potential end of template argument list.
+
+      # Ignore "->" and operator functions
+      if (i > 0 and
+          (line[i - 1] == '-' or Search(r'\boperator\s*$', line[0:i - 1]))):
+        continue
+
+      # Pop the stack if there is a matching '<'.  Otherwise, ignore
+      # this '>' since it must be an operator.
+      if stack:
+        if stack[-1] == '<':
+          stack.pop()
+          if not stack:
+            return (i + 1, None)
+    elif char == ';':
+      # Found something that look like end of statements.  If we are currently
+      # expecting a '>', the matching '<' must have been an operator, since
+      # template argument list should not contain statements.
+      while stack and stack[-1] == '<':
+        stack.pop()
+      if not stack:
+        return (-1, None)
+
+  # Did not find end of expression or unbalanced parentheses on this line
+  return (-1, stack)
+
+
+def CloseExpression(clean_lines, linenum, pos):
+  """If input points to ( or { or [ or <, finds the position that closes it.
+
+  If lines[linenum][pos] points to a '(' or '{' or '[' or '<', finds the
+  linenum/pos that correspond to the closing of the expression.
+
+  TODO(unknown): cpplint spends a fair bit of time matching parentheses.
+  Ideally we would want to index all opening and closing parentheses once
+  and have CloseExpression be just a simple lookup, but due to preprocessor
+  tricks, this is not so easy.
+
+  Args:
+    clean_lines: A CleansedLines instance containing the file.
+    linenum: The number of the line to check.
+    pos: A position on the line.
+
+  Returns:
+    A tuple (line, linenum, pos) pointer *past* the closing brace, or
+    (line, len(lines), -1) if we never find a close.  Note we ignore
+    strings and comments when matching; and the line we return is the
+    'cleansed' line at linenum.
+  """
+
+  line = clean_lines.elided[linenum]
+  if (line[pos] not in '({[<') or Match(r'<[<=]', line[pos:]):
+    return (line, clean_lines.NumLines(), -1)
+
+  # Check first line
+  (end_pos, stack) = FindEndOfExpressionInLine(line, pos, [])
+  if end_pos > -1:
+    return (line, linenum, end_pos)
+
+  # Continue scanning forward
+  while stack and linenum < clean_lines.NumLines() - 1:
+    linenum += 1
+    line = clean_lines.elided[linenum]
+    (end_pos, stack) = FindEndOfExpressionInLine(line, 0, stack)
+    if end_pos > -1:
+      return (line, linenum, end_pos)
+
+  # Did not find end of expression before end of file, give up
+  return (line, clean_lines.NumLines(), -1)
+
+
+def FindStartOfExpressionInLine(line, endpos, stack):
+  """Find position at the matching start of current expression.
+
+  This is almost the reverse of FindEndOfExpressionInLine, but note
+  that the input position and returned position differs by 1.
+
+  Args:
+    line: a CleansedLines line.
+    endpos: start searching at this position.
+    stack: nesting stack at endpos.
+
+  Returns:
+    On finding matching start: (index at matching start, None)
+    On finding an unclosed expression: (-1, None)
+    Otherwise: (-1, new stack at beginning of this line)
+  """
+  i = endpos
+  while i >= 0:
+    char = line[i]
+    if char in ')]}':
+      # Found end of expression, push to expression stack
+      stack.append(char)
+    elif char == '>':
+      # Found potential end of template argument list.
+      #
+      # Ignore it if it's a "->" or ">=" or "operator>"
+      if (i > 0 and
+          (line[i - 1] == '-' or
+           Match(r'\s>=\s', line[i - 1:]) or
+           Search(r'\boperator\s*$', line[0:i]))):
+        i -= 1
+      else:
+        stack.append('>')
+    elif char == '<':
+      # Found potential start of template argument list
+      if i > 0 and line[i - 1] == '<':
+        # Left shift operator
+        i -= 1
+      else:
+        # If there is a matching '>', we can pop the expression stack.
+        # Otherwise, ignore this '<' since it must be an operator.
+        if stack and stack[-1] == '>':
+          stack.pop()
+          if not stack:
+            return (i, None)
+    elif char in '([{':
+      # Found start of expression.
+      #
+      # If there are any unmatched '>' on the stack, they must be
+      # operators.  Remove those.
+      while stack and stack[-1] == '>':
+        stack.pop()
+      if not stack:
+        return (-1, None)
+      if ((char == '(' and stack[-1] == ')') or
+          (char == '[' and stack[-1] == ']') or
+          (char == '{' and stack[-1] == '}')):
+        stack.pop()
+        if not stack:
+          return (i, None)
+      else:
+        # Mismatched parentheses
+        return (-1, None)
+    elif char == ';':
+      # Found something that look like end of statements.  If we are currently
+      # expecting a '<', the matching '>' must have been an operator, since
+      # template argument list should not contain statements.
+      while stack and stack[-1] == '>':
+        stack.pop()
+      if not stack:
+        return (-1, None)
+
+    i -= 1
+
+  return (-1, stack)
+
+
+def ReverseCloseExpression(clean_lines, linenum, pos):
+  """If input points to ) or } or ] or >, finds the position that opens it.
+
+  If lines[linenum][pos] points to a ')' or '}' or ']' or '>', finds the
+  linenum/pos that correspond to the opening of the expression.
+
+  Args:
+    clean_lines: A CleansedLines instance containing the file.
+    linenum: The number of the line to check.
+    pos: A position on the line.
+
+  Returns:
+    A tuple (line, linenum, pos) pointer *at* the opening brace, or
+    (line, 0, -1) if we never find the matching opening brace.  Note
+    we ignore strings and comments when matching; and the line we
+    return is the 'cleansed' line at linenum.
+  """
+  line = clean_lines.elided[linenum]
+  if line[pos] not in ')}]>':
+    return (line, 0, -1)
+
+  # Check last line
+  (start_pos, stack) = FindStartOfExpressionInLine(line, pos, [])
+  if start_pos > -1:
+    return (line, linenum, start_pos)
+
+  # Continue scanning backward
+  while stack and linenum > 0:
+    linenum -= 1
+    line = clean_lines.elided[linenum]
+    (start_pos, stack) = FindStartOfExpressionInLine(line, len(line) - 1, stack)
+    if start_pos > -1:
+      return (line, linenum, start_pos)
+
+  # Did not find start of expression before beginning of file, give up
+  return (line, 0, -1)
+
+
+def CheckForCopyright(filename, lines, error):
+  """Logs an error if no Copyright message appears at the top of the file."""
+
+  # We'll say it should occur by line 10. Don't forget there's a
+  # dummy line at the front.
+  for line in xrange(1, min(len(lines), 11)):
+    if re.search(r'Copyright', lines[line], re.I): break
+  else:                       # means no copyright line was found
+    error(filename, 0, 'legal/copyright', 5,
+          'No copyright message found.  '
+          'You should have a line: "Copyright [year] <Copyright Owner>"')
+
+
+def GetIndentLevel(line):
+  """Return the number of leading spaces in line.
+
+  Args:
+    line: A string to check.
+
+  Returns:
+    An integer count of leading spaces, possibly zero.
+  """
+  indent = Match(r'^( *)\S', line)
+  if indent:
+    return len(indent.group(1))
+  else:
+    return 0
+
+
+def GetHeaderGuardCPPVariable(filename):
+  """Returns the CPP variable that should be used as a header guard.
+
+  Args:
+    filename: The name of a C++ header file.
+
+  Returns:
+    The CPP variable that should be used as a header guard in the
+    named file.
+
+  """
+
+  # Restores original filename in case that cpplint is invoked from Emacs's
+  # flymake.
+  filename = re.sub(r'_flymake\.h$', '.h', filename)
+  filename = re.sub(r'/\.flymake/([^/]*)$', r'/\1', filename)
+
+  fileinfo = FileInfo(filename)
+  file_path_from_root = fileinfo.RepositoryName()
+  if _root:
+    file_path_from_root = re.sub('^' + _root + os.sep, '', file_path_from_root)
+  return re.sub(r'[-./\s]', '_', file_path_from_root).upper() + '_'
+
+
+def CheckForHeaderGuard(filename, lines, error):
+  """Checks that the file contains a header guard.
+
+  Logs an error if no #ifndef header guard is present.  For other
+  headers, checks that the full pathname is used.
+
+  Args:
+    filename: The name of the C++ header file.
+    lines: An array of strings, each representing a line of the file.
+    error: The function to call with any errors found.
+  """
+
+  cppvar = GetHeaderGuardCPPVariable(filename)
+
+  ifndef = None
+  ifndef_linenum = 0
+  define = None
+  endif = None
+  endif_linenum = 0
+  for linenum, line in enumerate(lines):
+    linesplit = line.split()
+    if len(linesplit) >= 2:
+      # find the first occurrence of #ifndef and #define, save arg
+      if not ifndef and linesplit[0] == '#ifndef':
+        # set ifndef to the header guard presented on the #ifndef line.
+        ifndef = linesplit[1]
+        ifndef_linenum = linenum
+      if not define and linesplit[0] == '#define':
+        define = linesplit[1]
+    # find the last occurrence of #endif, save entire line
+    if line.startswith('#endif'):
+      endif = line
+      endif_linenum = linenum
+
+  if not ifndef:
+    error(filename, 0, 'build/header_guard', 5,
+          'No #ifndef header guard found, suggested CPP variable is: %s' %
+          cppvar)
+    return
+
+  if not define:
+    error(filename, 0, 'build/header_guard', 5,
+          'No #define header guard found, suggested CPP variable is: %s' %
+          cppvar)
+    return
+
+  # The guard should be PATH_FILE_H_, but we also allow PATH_FILE_H__
+  # for backward compatibility.
+  if ifndef != cppvar:
+    error_level = 0
+    if ifndef != cppvar + '_':
+      error_level = 5
+
+    ParseNolintSuppressions(filename, lines[ifndef_linenum], ifndef_linenum,
+                            error)
+    error(filename, ifndef_linenum, 'build/header_guard', error_level,
+          '#ifndef header guard has wrong style, please use: %s' % cppvar)
+
+  if define != ifndef:
+    error(filename, 0, 'build/header_guard', 5,
+          '#ifndef and #define don\'t match, suggested CPP variable is: %s' %
+          cppvar)
+    return
+
+  if endif != ('#endif  // %s' % cppvar):
+    error_level = 0
+    if endif != ('#endif  // %s' % (cppvar + '_')):
+      error_level = 5
+
+    ParseNolintSuppressions(filename, lines[endif_linenum], endif_linenum,
+                            error)
+    error(filename, endif_linenum, 'build/header_guard', error_level,
+          '#endif line should be "#endif  // %s"' % cppvar)
+
+
+def CheckForBadCharacters(filename, lines, error):
+  """Logs an error for each line containing bad characters.
+
+  Two kinds of bad characters:
+
+  1. Unicode replacement characters: These indicate that either the file
+  contained invalid UTF-8 (likely) or Unicode replacement characters (which
+  it shouldn't).  Note that it's possible for this to throw off line
+  numbering if the invalid UTF-8 occurred adjacent to a newline.
+
+  2. NUL bytes.  These are problematic for some tools.
+
+  Args:
+    filename: The name of the current file.
+    lines: An array of strings, each representing a line of the file.
+    error: The function to call with any errors found.
+  """
+  for linenum, line in enumerate(lines):
+    if u'\ufffd' in line:
+      error(filename, linenum, 'readability/utf8', 5,
+            'Line contains invalid UTF-8 (or Unicode replacement character).')
+    if '\0' in line:
+      error(filename, linenum, 'readability/nul', 5, 'Line contains NUL byte.')
+
+
+def CheckForNewlineAtEOF(filename, lines, error):
+  """Logs an error if there is no newline char at the end of the file.
+
+  Args:
+    filename: The name of the current file.
+    lines: An array of strings, each representing a line of the file.
+    error: The function to call with any errors found.
+  """
+
+  # The array lines() was created by adding two newlines to the
+  # original file (go figure), then splitting on \n.
+  # To verify that the file ends in \n, we just have to make sure the
+  # last-but-two element of lines() exists and is empty.
+  if len(lines) < 3 or lines[-2]:
+    error(filename, len(lines) - 2, 'whitespace/ending_newline', 5,
+          'Could not find a newline character at the end of the file.')
+
+
+def CheckForMultilineCommentsAndStrings(filename, clean_lines, linenum, error):
+  """Logs an error if we see /* ... */ or "..." that extend past one line.
+
+  /* ... */ comments are legit inside macros, for one line.
+  Otherwise, we prefer // comments, so it's ok to warn about the
+  other.  Likewise, it's ok for strings to extend across multiple
+  lines, as long as a line continuation character (backslash)
+  terminates each line. Although not currently prohibited by the C++
+  style guide, it's ugly and unnecessary. We don't do well with either
+  in this lint program, so we warn about both.
+
+  Args:
+    filename: The name of the current file.
+    clean_lines: A CleansedLines instance containing the file.
+    linenum: The number of the line to check.
+    error: The function to call with any errors found.
+  """
+  line = clean_lines.elided[linenum]
+
+  # Remove all \\ (escaped backslashes) from the line. They are OK, and the
+  # second (escaped) slash may trigger later \" detection erroneously.
+  line = line.replace('\\\\', '')
+
+  if line.count('/*') > line.count('*/'):
+    error(filename, linenum, 'readability/multiline_comment', 5,
+          'Complex multi-line /*...*/-style comment found. '
+          'Lint may give bogus warnings.  '
+          'Consider replacing these with //-style comments, '
+          'with #if 0...#endif, '
+          'or with more clearly structured multi-line comments.')
+
+  if (line.count('"') - line.count('\\"')) % 2:
+    error(filename, linenum, 'readability/multiline_string', 5,
+          'Multi-line string ("...") found.  This lint script doesn\'t '
+          'do well with such strings, and may give bogus warnings.  '
+          'Use C++11 raw strings or concatenation instead.')
+
+
+# (non-threadsafe name, thread-safe alternative, validation pattern)
+#
+# The validation pattern is used to eliminate false positives such as:
+#  _rand();               // false positive due to substring match.
+#  ->rand();              // some member function rand().
+#  ACMRandom rand(seed);  // some variable named rand.
+#  ISAACRandom rand();    // another variable named rand.
+#
+# Basically we require the return value of these functions to be used
+# in some expression context on the same line by matching on some
+# operator before the function name.  This eliminates constructors and
+# member function calls.
+_UNSAFE_FUNC_PREFIX = r'(?:[-+*/=%^&|(<]\s*|>\s+)'
+_THREADING_LIST = (
+    ('asctime(', 'asctime_r(', _UNSAFE_FUNC_PREFIX + r'asctime\([^)]+\)'),
+    ('ctime(', 'ctime_r(', _UNSAFE_FUNC_PREFIX + r'ctime\([^)]+\)'),
+    ('getgrgid(', 'getgrgid_r(', _UNSAFE_FUNC_PREFIX + r'getgrgid\([^)]+\)'),
+    ('getgrnam(', 'getgrnam_r(', _UNSAFE_FUNC_PREFIX + r'getgrnam\([^)]+\)'),
+    ('getlogin(', 'getlogin_r(', _UNSAFE_FUNC_PREFIX + r'getlogin\(\)'),
+    ('getpwnam(', 'getpwnam_r(', _UNSAFE_FUNC_PREFIX + r'getpwnam\([^)]+\)'),
+    ('getpwuid(', 'getpwuid_r(', _UNSAFE_FUNC_PREFIX + r'getpwuid\([^)]+\)'),
+    ('gmtime(', 'gmtime_r(', _UNSAFE_FUNC_PREFIX + r'gmtime\([^)]+\)'),
+    ('localtime(', 'localtime_r(', _UNSAFE_FUNC_PREFIX + r'localtime\([^)]+\)'),
+    ('rand(', 'rand_r(', _UNSAFE_FUNC_PREFIX + r'rand\(\)'),
+    ('strtok(', 'strtok_r(',
+     _UNSAFE_FUNC_PREFIX + r'strtok\([^)]+\)'),
+    ('ttyname(', 'ttyname_r(', _UNSAFE_FUNC_PREFIX + r'ttyname\([^)]+\)'),
+    )
+
+
+def CheckPosixThreading(filename, clean_lines, linenum, error):
+  """Checks for calls to thread-unsafe functions.
+
+  Much code has been originally written without consideration of
+  multi-threading. Also, engineers are relying on their old experience;
+  they have learned posix before threading extensions were added. These
+  tests guide the engineers to use thread-safe functions (when using
+  posix directly).
+
+  Args:
+    filename: The name of the current file.
+    clean_lines: A CleansedLines instance containing the file.
+    linenum: The number of the line to check.
+    error: The function to call with any errors found.
+  """
+  line = clean_lines.elided[linenum]
+  for single_thread_func, multithread_safe_func, pattern in _THREADING_LIST:
+    # Additional pattern matching check to confirm that this is the
+    # function we are looking for
+    if Search(pattern, line):
+      error(filename, linenum, 'runtime/threadsafe_fn', 2,
+            'Consider using ' + multithread_safe_func +
+            '...) instead of ' + single_thread_func +
+            '...) for improved thread safety.')
+
+
+def CheckVlogArguments(filename, clean_lines, linenum, error):
+  """Checks that VLOG() is only used for defining a logging level.
+
+  For example, VLOG(2) is correct. VLOG(INFO), VLOG(WARNING), VLOG(ERROR), and
+  VLOG(FATAL) are not.
+
+  Args:
+    filename: The name of the current file.
+    clean_lines: A CleansedLines instance containing the file.
+    linenum: The number of the line to check.
+    error: The function to call with any errors found.
+  """
+  line = clean_lines.elided[linenum]
+  if Search(r'\bVLOG\((INFO|ERROR|WARNING|DFATAL|FATAL)\)', line):
+    error(filename, linenum, 'runtime/vlog', 5,
+          'VLOG() should be used with numeric verbosity level.  '
+          'Use LOG() if you want symbolic severity levels.')
+
+# Matches invalid increment: *count++, which moves pointer instead of
+# incrementing a value.
+_RE_PATTERN_INVALID_INCREMENT = re.compile(
+    r'^\s*\*\w+(\+\+|--);')
+
+
+def CheckInvalidIncrement(filename, clean_lines, linenum, error):
+  """Checks for invalid increment *count++.
+
+  For example following function:
+  void increment_counter(int* count) {
+    *count++;
+  }
+  is invalid, because it effectively does count++, moving pointer, and should
+  be replaced with ++*count, (*count)++ or *count += 1.
+
+  Args:
+    filename: The name of the current file.
+    clean_lines: A CleansedLines instance containing the file.
+    linenum: The number of the line to check.
+    error: The function to call with any errors found.
+  """
+  line = clean_lines.elided[linenum]
+  if _RE_PATTERN_INVALID_INCREMENT.match(line):
+    error(filename, linenum, 'runtime/invalid_increment', 5,
+          'Changing pointer instead of value (or unused value of operator*).')
+
+
+class _BlockInfo(object):
+  """Stores information about a generic block of code."""
+
+  def __init__(self, seen_open_brace):
+    self.seen_open_brace = seen_open_brace
+    self.open_parentheses = 0
+    self.inline_asm = _NO_ASM
+
+  def CheckBegin(self, filename, clean_lines, linenum, error):
+    """Run checks that applies to text up to the opening brace.
+
+    This is mostly for checking the text after the class identifier
+    and the "{", usually where the base class is specified.  For other
+    blocks, there isn't much to check, so we always pass.
+
+    Args:
+      filename: The name of the current file.
+      clean_lines: A CleansedLines instance containing the file.
+      linenum: The number of the line to check.
+      error: The function to call with any errors found.
+    """
+    pass
+
+  def CheckEnd(self, filename, clean_lines, linenum, error):
+    """Run checks that applies to text after the closing brace.
+
+    This is mostly used for checking end of namespace comments.
+
+    Args:
+      filename: The name of the current file.
+      clean_lines: A CleansedLines instance containing the file.
+      linenum: The number of the line to check.
+      error: The function to call with any errors found.
+    """
+    pass
+
+  def IsBlockInfo(self):
+    """Returns true if this block is a _BlockInfo.
+
+    This is convenient for verifying that an object is an instance of
+    a _BlockInfo, but not an instance of any of the derived classes.
+
+    Returns:
+      True for this class, False for derived classes.
+    """
+    return self.__class__ == _BlockInfo
+
+
+class _ExternCInfo(_BlockInfo):
+  """Stores information about an 'extern "C"' block."""
+
+  def __init__(self):
+    _BlockInfo.__init__(self, True)
+
+
+class _ClassInfo(_BlockInfo):
+  """Stores information about a class."""
+
+  def __init__(self, name, class_or_struct, clean_lines, linenum):
+    _BlockInfo.__init__(self, False)
+    self.name = name
+    self.starting_linenum = linenum
+    self.is_derived = False
+    if class_or_struct == 'struct':
+      self.access = 'public'
+      self.is_struct = True
+    else:
+      self.access = 'private'
+      self.is_struct = False
+
+    # Remember initial indentation level for this class.  Using raw_lines here
+    # instead of elided to account for leading comments.
+    self.class_indent = GetIndentLevel(clean_lines.raw_lines[linenum])
+
+    # Try to find the end of the class.  This will be confused by things like:
+    #   class A {
+    #   } *x = { ...
+    #
+    # But it's still good enough for CheckSectionSpacing.
+    self.last_line = 0
+    depth = 0
+    for i in range(linenum, clean_lines.NumLines()):
+      line = clean_lines.elided[i]
+      depth += line.count('{') - line.count('}')
+      if not depth:
+        self.last_line = i
+        break
+
+  def CheckBegin(self, filename, clean_lines, linenum, error):
+    # Look for a bare ':'
+    if Search('(^|[^:]):($|[^:])', clean_lines.elided[linenum]):
+      self.is_derived = True
+
+  def CheckEnd(self, filename, clean_lines, linenum, error):
+    # Check that closing brace is aligned with beginning of the class.
+    # Only do this if the closing brace is indented by only whitespaces.
+    # This means we will not check single-line class definitions.
+    indent = Match(r'^( *)\}', clean_lines.elided[linenum])
+    if indent and len(indent.group(1)) != self.class_indent:
+      if self.is_struct:
+        parent = 'struct ' + self.name
+      else:
+        parent = 'class ' + self.name
+      error(filename, linenum, 'whitespace/indent', 3,
+            'Closing brace should be aligned with beginning of %s' % parent)
+
+
+class _NamespaceInfo(_BlockInfo):
+  """Stores information about a namespace."""
+
+  def __init__(self, name, linenum):
+    _BlockInfo.__init__(self, False)
+    self.name = name or ''
+    self.starting_linenum = linenum
+
+  def CheckEnd(self, filename, clean_lines, linenum, error):
+    """Check end of namespace comments."""
+    line = clean_lines.raw_lines[linenum]
+
+    # Check how many lines is enclosed in this namespace.  Don't issue
+    # warning for missing namespace comments if there aren't enough
+    # lines.  However, do apply checks if there is already an end of
+    # namespace comment and it's incorrect.
+    #
+    # TODO(unknown): We always want to check end of namespace comments
+    # if a namespace is large, but sometimes we also want to apply the
+    # check if a short namespace contained nontrivial things (something
+    # other than forward declarations).  There is currently no logic on
+    # deciding what these nontrivial things are, so this check is
+    # triggered by namespace size only, which works most of the time.
+    if (linenum - self.starting_linenum < 10
+        and not Match(r'};*\s*(//|/\*).*\bnamespace\b', line)):
+      return
+
+    # Look for matching comment at end of namespace.
+    #
+    # Note that we accept C style "/* */" comments for terminating
+    # namespaces, so that code that terminate namespaces inside
+    # preprocessor macros can be cpplint clean.
+    #
+    # We also accept stuff like "// end of namespace <name>." with the
+    # period at the end.
+    #
+    # Besides these, we don't accept anything else, otherwise we might
+    # get false negatives when existing comment is a substring of the
+    # expected namespace.
+    if self.name:
+      # Named namespace
+      if Match((r'};*\s*(//|/\*).*\bnamespace\s+' + re.escape(self.name) +
+                     r'[\*/\.\\\s]*$'),
+                    line):
+         error(filename, linenum, 'readability/namespace', 5,
+               'Namespace should not be terminated with "// namespace %s"' %
+               self.name)
+    else:
+      # Anonymous namespace
+      if not Match(r'};*\s*(//|/\*).*\bnamespace[\*/\.\\\s]*$', line):
+        # If "// namespace anonymous" or "// anonymous namespace (more text)",
+        # mention "// anonymous namespace" as an acceptable form
+        if Match(r'}.*\b(namespace anonymous|anonymous namespace)\b', line):
+          error(filename, linenum, 'readability/namespace', 5,
+                'Anonymous namespace should be terminated with "// namespace"'
+                ' or "// anonymous namespace"')
+        else:
+          error(filename, linenum, 'readability/namespace', 5,
+                'Anonymous namespace should be terminated with "// namespace"')
+
+
+class _PreprocessorInfo(object):
+  """Stores checkpoints of nesting stacks when #if/#else is seen."""
+
+  def __init__(self, stack_before_if):
+    # The entire nesting stack before #if
+    self.stack_before_if = stack_before_if
+
+    # The entire nesting stack up to #else
+    self.stack_before_else = []
+
+    # Whether we have already seen #else or #elif
+    self.seen_else = False
+
+
+class NestingState(object):
+  """Holds states related to parsing braces."""
+
+  def __init__(self):
+    # Stack for tracking all braces.  An object is pushed whenever we
+    # see a "{", and popped when we see a "}".  Only 3 types of
+    # objects are possible:
+    # - _ClassInfo: a class or struct.
+    # - _NamespaceInfo: a namespace.
+    # - _BlockInfo: some other type of block.
+    self.stack = []
+
+    # Top of the previous stack before each Update().
+    #
+    # Because the nesting_stack is updated at the end of each line, we
+    # had to do some convoluted checks to find out what is the current
+    # scope at the beginning of the line.  This check is simplified by
+    # saving the previous top of nesting stack.
+    #
+    # We could save the full stack, but we only need the top.  Copying
+    # the full nesting stack would slow down cpplint by ~10%.
+    self.previous_stack_top = []
+
+    # Stack of _PreprocessorInfo objects.
+    self.pp_stack = []
+
+  def SeenOpenBrace(self):
+    """Check if we have seen the opening brace for the innermost block.
+
+    Returns:
+      True if we have seen the opening brace, False if the innermost
+      block is still expecting an opening brace.
+    """
+    return (not self.stack) or self.stack[-1].seen_open_brace
+
+  def InNamespaceBody(self):
+    """Check if we are currently one level inside a namespace body.
+
+    Returns:
+      True if top of the stack is a namespace block, False otherwise.
+    """
+    return self.stack and isinstance(self.stack[-1], _NamespaceInfo)
+
+  def InExternC(self):
+    """Check if we are currently one level inside an 'extern "C"' block.
+
+    Returns:
+      True if top of the stack is an extern block, False otherwise.
+    """
+    return self.stack and isinstance(self.stack[-1], _ExternCInfo)
+
+  def InClassDeclaration(self):
+    """Check if we are currently one level inside a class or struct declaration.
+
+    Returns:
+      True if top of the stack is a class/struct, False otherwise.
+    """
+    return self.stack and isinstance(self.stack[-1], _ClassInfo)
+
+  def InAsmBlock(self):
+    """Check if we are currently one level inside an inline ASM block.
+
+    Returns:
+      True if the top of the stack is a block containing inline ASM.
+    """
+    return self.stack and self.stack[-1].inline_asm != _NO_ASM
+
+  def InTemplateArgumentList(self, clean_lines, linenum, pos):
+    """Check if current position is inside template argument list.
+
+    Args:
+      clean_lines: A CleansedLines instance containing the file.
+      linenum: The number of the line to check.
+      pos: position just after the suspected template argument.
+    Returns:
+      True if (linenum, pos) is inside template arguments.
+    """
+    while linenum < clean_lines.NumLines():
+      # Find the earliest character that might indicate a template argument
+      line = clean_lines.elided[linenum]
+      match = Match(r'^[^{};=\[\]\.<>]*(.)', line[pos:])
+      if not match:
+        linenum += 1
+        pos = 0
+        continue
+      token = match.group(1)
+      pos += len(match.group(0))
+
+      # These things do not look like template argument list:
+      #   class Suspect {
+      #   class Suspect x; }
+      if token in ('{', '}', ';'): return False
+
+      # These things look like template argument list:
+      #   template <class Suspect>
+      #   template <class Suspect = default_value>
+      #   template <class Suspect[]>
+      #   template <class Suspect...>
+      if token in ('>', '=', '[', ']', '.'): return True
+
+      # Check if token is an unmatched '<'.
+      # If not, move on to the next character.
+      if token != '<':
+        pos += 1
+        if pos >= len(line):
+          linenum += 1
+          pos = 0
+        continue
+
+      # We can't be sure if we just find a single '<', and need to
+      # find the matching '>'.
+      (_, end_line, end_pos) = CloseExpression(clean_lines, linenum, pos - 1)
+      if end_pos < 0:
+        # Not sure if template argument list or syntax error in file
+        return False
+      linenum = end_line
+      pos = end_pos
+    return False
+
+  def UpdatePreprocessor(self, line):
+    """Update preprocessor stack.
+
+    We need to handle preprocessors due to classes like this:
+      #ifdef SWIG
+      struct ResultDetailsPageElementExtensionPoint {
+      #else
+      struct ResultDetailsPageElementExtensionPoint : public Extension {
+      #endif
+
+    We make the following assumptions (good enough for most files):
+    - Preprocessor condition evaluates to true from #if up to first
+      #else/#elif/#endif.
+
+    - Preprocessor condition evaluates to false from #else/#elif up
+      to #endif.  We still perform lint checks on these lines, but
+      these do not affect nesting stack.
+
+    Args:
+      line: current line to check.
+    """
+    if Match(r'^\s*#\s*(if|ifdef|ifndef)\b', line):
+      # Beginning of #if block, save the nesting stack here.  The saved
+      # stack will allow us to restore the parsing state in the #else case.
+      self.pp_stack.append(_PreprocessorInfo(copy.deepcopy(self.stack)))
+    elif Match(r'^\s*#\s*(else|elif)\b', line):
+      # Beginning of #else block
+      if self.pp_stack:
+        if not self.pp_stack[-1].seen_else:
+          # This is the first #else or #elif block.  Remember the
+          # whole nesting stack up to this point.  This is what we
+          # keep after the #endif.
+          self.pp_stack[-1].seen_else = True
+          self.pp_stack[-1].stack_before_else = copy.deepcopy(self.stack)
+
+        # Restore the stack to how it was before the #if
+        self.stack = copy.deepcopy(self.pp_stack[-1].stack_before_if)
+      else:
+        # TODO(unknown): unexpected #else, issue warning?
+        pass
+    elif Match(r'^\s*#\s*endif\b', line):
+      # End of #if or #else blocks.
+      if self.pp_stack:
+        # If we saw an #else, we will need to restore the nesting
+        # stack to its former state before the #else, otherwise we
+        # will just continue from where we left off.
+        if self.pp_stack[-1].seen_else:
+          # Here we can just use a shallow copy since we are the last
+          # reference to it.
+          self.stack = self.pp_stack[-1].stack_before_else
+        # Drop the corresponding #if
+        self.pp_stack.pop()
+      else:
+        # TODO(unknown): unexpected #endif, issue warning?
+        pass
+
+  # TODO(unknown): Update() is too long, but we will refactor later.
+  def Update(self, filename, clean_lines, linenum, error):
+    """Update nesting state with current line.
+
+    Args:
+      filename: The name of the current file.
+      clean_lines: A CleansedLines instance containing the file.
+      linenum: The number of the line to check.
+      error: The function to call with any errors found.
+    """
+    line = clean_lines.elided[linenum]
+
+    # Remember top of the previous nesting stack.
+    #
+    # The stack is always pushed/popped and not modified in place, so
+    # we can just do a shallow copy instead of copy.deepcopy.  Using
+    # deepcopy would slow down cpplint by ~28%.
+    if self.stack:
+      self.previous_stack_top = self.stack[-1]
+    else:
+      self.previous_stack_top = None
+
+    # Update pp_stack
+    self.UpdatePreprocessor(line)
+
+    # Count parentheses.  This is to avoid adding struct arguments to
+    # the nesting stack.
+    if self.stack:
+      inner_block = self.stack[-1]
+      depth_change = line.count('(') - line.count(')')
+      inner_block.open_parentheses += depth_change
+
+      # Also check if we are starting or ending an inline assembly block.
+      if inner_block.inline_asm in (_NO_ASM, _END_ASM):
+        if (depth_change != 0 and
+            inner_block.open_parentheses == 1 and
+            _MATCH_ASM.match(line)):
+          # Enter assembly block
+          inner_block.inline_asm = _INSIDE_ASM
+        else:
+          # Not entering assembly block.  If previous line was _END_ASM,
+          # we will now shift to _NO_ASM state.
+          inner_block.inline_asm = _NO_ASM
+      elif (inner_block.inline_asm == _INSIDE_ASM and
+            inner_block.open_parentheses == 0):
+        # Exit assembly block
+        inner_block.inline_asm = _END_ASM
+
+    # Consume namespace declaration at the beginning of the line.  Do
+    # this in a loop so that we catch same line declarations like this:
+    #   namespace proto2 { namespace bridge { class MessageSet; } }
+    while True:
+      # Match start of namespace.  The "\b\s*" below catches namespace
+      # declarations even if it weren't followed by a whitespace, this
+      # is so that we don't confuse our namespace checker.  The
+      # missing spaces will be flagged by CheckSpacing.
+      namespace_decl_match = Match(r'^\s*namespace\b\s*([:\w]+)?(.*)$', line)
+      if not namespace_decl_match:
+        break
+
+      new_namespace = _NamespaceInfo(namespace_decl_match.group(1), linenum)
+      self.stack.append(new_namespace)
+
+      line = namespace_decl_match.group(2)
+      if line.find('{') != -1:
+        new_namespace.seen_open_brace = True
+        line = line[line.find('{') + 1:]
+
+    # Look for a class declaration in whatever is left of the line
+    # after parsing namespaces.  The regexp accounts for decorated classes
+    # such as in:
+    #   class LOCKABLE API Object {
+    #   };
+    class_decl_match = Match(
+        r'^(\s*(?:template\s*<[\w\s<>,:]*>\s*)?'
+        r'(class|struct)\s+(?:[A-Z_]+\s+)*(\w+(?:::\w+)*))'
+        r'(.*)$', line)
+    if (class_decl_match and
+        (not self.stack or self.stack[-1].open_parentheses == 0)):
+      # We do not want to accept classes that are actually template arguments:
+      #   template <class Ignore1,
+      #             class Ignore2 = Default<Args>,
+      #             template <Args> class Ignore3>
+      #   void Function() {};
+      #
+      # To avoid template argument cases, we scan forward and look for
+      # an unmatched '>'.  If we see one, assume we are inside a
+      # template argument list.
+      end_declaration = len(class_decl_match.group(1))
+      if not self.InTemplateArgumentList(clean_lines, linenum, end_declaration):
+        self.stack.append(_ClassInfo(
+            class_decl_match.group(3), class_decl_match.group(2),
+            clean_lines, linenum))
+        line = class_decl_match.group(4)
+
+    # If we have not yet seen the opening brace for the innermost block,
+    # run checks here.
+    if not self.SeenOpenBrace():
+      self.stack[-1].CheckBegin(filename, clean_lines, linenum, error)
+
+    # Update access control if we are inside a class/struct
+    if self.stack and isinstance(self.stack[-1], _ClassInfo):
+      classinfo = self.stack[-1]
+      access_match = Match(
+          r'^(.*)\b(public|private|protected|signals)(\s+(?:slots\s*)?)?'
+          r':(?:[^:]|$)',
+          line)
+      if access_match:
+        classinfo.access = access_match.group(2)
+
+        # Check that access keywords are indented +1 space.  Skip this
+        # check if the keywords are not preceded by whitespaces.
+        indent = access_match.group(1)
+        if (len(indent) != classinfo.class_indent + 2 and
+            Match(r'^\s*$', indent)):
+          if classinfo.is_struct:
+            parent = 'struct ' + classinfo.name
+          else:
+            parent = 'class ' + classinfo.name
+          slots = ''
+          if access_match.group(3):
+            slots = access_match.group(3)
+          error(filename, linenum, 'whitespace/indent', 3,
+                '%s%s: should be indented +2 space inside %s' % (
+                    access_match.group(2), slots, parent))
+
+    # Consume braces or semicolons from what's left of the line
+    while True:
+      # Match first brace, semicolon, or closed parenthesis.
+      matched = Match(r'^[^{;)}]*([{;)}])(.*)$', line)
+      if not matched:
+        break
+
+      token = matched.group(1)
+      if token == '{':
+        # If namespace or class hasn't seen a opening brace yet, mark
+        # namespace/class head as complete.  Push a new block onto the
+        # stack otherwise.
+        if not self.SeenOpenBrace():
+          self.stack[-1].seen_open_brace = True
+        elif Match(r'^extern\s*"[^"]*"\s*\{', line):
+          self.stack.append(_ExternCInfo())
+        else:
+          self.stack.append(_BlockInfo(True))
+          if _MATCH_ASM.match(line):
+            self.stack[-1].inline_asm = _BLOCK_ASM
+
+      elif token == ';' or token == ')':
+        # If we haven't seen an opening brace yet, but we already saw
+        # a semicolon, this is probably a forward declaration.  Pop
+        # the stack for these.
+        #
+        # Similarly, if we haven't seen an opening brace yet, but we
+        # already saw a closing parenthesis, then these are probably
+        # function arguments with extra "class" or "struct" keywords.
+        # Also pop these stack for these.
+        if not self.SeenOpenBrace():
+          self.stack.pop()
+      else:  # token == '}'
+        # Perform end of block checks and pop the stack.
+        if self.stack:
+          self.stack[-1].CheckEnd(filename, clean_lines, linenum, error)
+          self.stack.pop()
+      line = matched.group(2)
+
+  def InnermostClass(self):
+    """Get class info on the top of the stack.
+
+    Returns:
+      A _ClassInfo object if we are inside a class, or None otherwise.
+    """
+    for i in range(len(self.stack), 0, -1):
+      classinfo = self.stack[i - 1]
+      if isinstance(classinfo, _ClassInfo):
+        return classinfo
+    return None
+
+  def CheckCompletedBlocks(self, filename, error):
+    """Checks that all classes and namespaces have been completely parsed.
+
+    Call this when all lines in a file have been processed.
+    Args:
+      filename: The name of the current file.
+      error: The function to call with any errors found.
+    """
+    # Note: This test can result in false positives if #ifdef constructs
+    # get in the way of brace matching. See the testBuildClass test in
+    # cpplint_unittest.py for an example of this.
+    for obj in self.stack:
+      if isinstance(obj, _ClassInfo):
+        error(filename, obj.starting_linenum, 'build/class', 5,
+              'Failed to find complete declaration of class %s' %
+              obj.name)
+      elif isinstance(obj, _NamespaceInfo):
+        error(filename, obj.starting_linenum, 'build/namespaces', 5,
+              'Failed to find complete declaration of namespace %s' %
+              obj.name)
+
+
+def CheckForNonStandardConstructs(filename, clean_lines, linenum,
+                                  nesting_state, error):
+  r"""Logs an error if we see certain non-ANSI constructs ignored by gcc-2.
+
+  Complain about several constructs which gcc-2 accepts, but which are
+  not standard C++.  Warning about these in lint is one way to ease the
+  transition to new compilers.
+  - put storage class first (e.g. "static const" instead of "const static").
+  - "%lld" instead of %qd" in printf-type functions.
+  - "%1$d" is non-standard in printf-type functions.
+  - "\%" is an undefined character escape sequence.
+  - text after #endif is not allowed.
+  - invalid inner-style forward declaration.
+  - >? and <? operators, and their >?= and <?= cousins.
+
+  Additionally, check for constructor/destructor style violations and reference
+  members, as it is very convenient to do so while checking for
+  gcc-2 compliance.
+
+  Args:
+    filename: The name of the current file.
+    clean_lines: A CleansedLines instance containing the file.
+    linenum: The number of the line to check.
+    nesting_state: A NestingState instance which maintains information about
+                   the current stack of nested blocks being parsed.
+    error: A callable to which errors are reported, which takes 4 arguments:
+           filename, line number, error level, and message
+  """
+
+  # Remove comments from the line, but leave in strings for now.
+  line = clean_lines.lines[linenum]
+
+  if Search(r'printf\s*\(.*".*%[-+ ]?\d*q', line):
+    error(filename, linenum, 'runtime/printf_format', 3,
+          '%q in format strings is deprecated.  Use %ll instead.')
+
+  if Search(r'printf\s*\(.*".*%\d+\$', line):
+    error(filename, linenum, 'runtime/printf_format', 2,
+          '%N$ formats are unconventional.  Try rewriting to avoid them.')
+
+  # Remove escaped backslashes before looking for undefined escapes.
+  line = line.replace('\\\\', '')
+
+  if Search(r'("|\').*\\(%|\[|\(|{)', line):
+    error(filename, linenum, 'build/printf_format', 3,
+          '%, [, (, and { are undefined character escapes.  Unescape them.')
+
+  # For the rest, work with both comments and strings removed.
+  line = clean_lines.elided[linenum]
+
+  if Search(r'\b(const|volatile|void|char|short|int|long'
+            r'|float|double|signed|unsigned'
+            r'|schar|u?int8|u?int16|u?int32|u?int64)'
+            r'\s+(register|static|extern|typedef)\b',
+            line):
+    error(filename, linenum, 'build/storage_class', 5,
+          'Storage class (static, extern, typedef, etc) should be first.')
+
+  if Match(r'\s*#\s*endif\s*[^/\s]+', line):
+    error(filename, linenum, 'build/endif_comment', 5,
+          'Uncommented text after #endif is non-standard.  Use a comment.')
+
+  if Match(r'\s*class\s+(\w+\s*::\s*)+\w+\s*;', line):
+    error(filename, linenum, 'build/forward_decl', 5,
+          'Inner-style forward declarations are invalid.  Remove this line.')
+
+  if Search(r'(\w+|[+-]?\d+(\.\d*)?)\s*(<|>)\?=?\s*(\w+|[+-]?\d+)(\.\d*)?',
+            line):
+    error(filename, linenum, 'build/deprecated', 3,
+          '>? and <? (max and min) operators are non-standard and deprecated.')
+
+  if Search(r'^\s*const\s*string\s*&\s*\w+\s*;', line):
+    # TODO(unknown): Could it be expanded safely to arbitrary references,
+    # without triggering too many false positives? The first
+    # attempt triggered 5 warnings for mostly benign code in the regtest, hence
+    # the restriction.
+    # Here's the original regexp, for the reference:
+    # type_name = r'\w+((\s*::\s*\w+)|(\s*<\s*\w+?\s*>))?'
+    # r'\s*const\s*' + type_name + '\s*&\s*\w+\s*;'
+    error(filename, linenum, 'runtime/member_string_references', 2,
+          'const string& members are dangerous. It is much better to use '
+          'alternatives, such as pointers or simple constants.')
+
+  # Everything else in this function operates on class declarations.
+  # Return early if the top of the nesting stack is not a class, or if
+  # the class head is not completed yet.
+  classinfo = nesting_state.InnermostClass()
+  if not classinfo or not classinfo.seen_open_brace:
+    return
+
+  # The class may have been declared with namespace or classname qualifiers.
+  # The constructor and destructor will not have those qualifiers.
+  base_classname = classinfo.name.split('::')[-1]
+
+  # Look for single-argument constructors that aren't marked explicit.
+  # Technically a valid construct, but against style.
+  args = Match(r'\s+(?:inline\s+)?%s\s*\(([^,()]+)\)'
+               % re.escape(base_classname),
+               line)
+  if (args and
+      args.group(1) != 'void' and
+      not Search(r'\bstd::initializer_list\b', args.group(1)) and
+      not Match(r'(const\s+)?%s(\s+const)?\s*(?:<\w+>\s*)?&'
+                % re.escape(base_classname), args.group(1).strip())):
+    error(filename, linenum, 'runtime/explicit', 5,
+          'Single-argument constructors should be marked explicit.')
+
+
+def CheckSpacingForFunctionCall(filename, clean_lines, linenum, error):
+  """Checks for the correctness of various spacing around function calls.
+
+  Args:
+    filename: The name of the current file.
+    clean_lines: A CleansedLines instance containing the file.
+    linenum: The number of the line to check.
+    error: The function to call with any errors found.
+  """
+  line = clean_lines.elided[linenum]
+
+  # Since function calls often occur inside if/for/while/switch
+  # expressions - which have their own, more liberal conventions - we
+  # first see if we should be looking inside such an expression for a
+  # function call, to which we can apply more strict standards.
+  fncall = line    # if there's no control flow construct, look at whole line
+  for pattern in (r'\bif\s*\((.*)\)\s*{',
+                  r'\bfor\s*\((.*)\)\s*{',
+                  r'\bwhile\s*\((.*)\)\s*[{;]',
+                  r'\bswitch\s*\((.*)\)\s*{'):
+    match = Search(pattern, line)
+    if match:
+      fncall = match.group(1)    # look inside the parens for function calls
+      break
+
+  # Except in if/for/while/switch, there should never be space
+  # immediately inside parens (eg "f( 3, 4 )").  We make an exception
+  # for nested parens ( (a+b) + c ).  Likewise, there should never be
+  # a space before a ( when it's a function argument.  I assume it's a
+  # function argument when the char before the whitespace is legal in
+  # a function name (alnum + _) and we're not starting a macro. Also ignore
+  # pointers and references to arrays and functions coz they're too tricky:
+  # we use a very simple way to recognize these:
+  # " (something)(maybe-something)" or
+  # " (something)(maybe-something," or
+  # " (something)[something]"
+  # Note that we assume the contents of [] to be short enough that
+  # they'll never need to wrap.
+  if (  # Ignore control structures.
+      not Search(r'\b(if|for|while|switch|return|new|delete|catch|sizeof)\b',
+                 fncall) and
+      # Ignore pointers/references to functions.
+      not Search(r' \([^)]+\)\([^)]*(\)|,$)', fncall) and
+      # Ignore pointers/references to arrays.
+      not Search(r' \([^)]+\)\[[^\]]+\]', fncall)):
+    if Search(r'\w\s*\(\s(?!\s*\\$)', fncall):      # a ( used for a fn call
+      error(filename, linenum, 'whitespace/parens', 4,
+            'Extra space after ( in function call')
+    elif Search(r'\(\s+(?!(\s*\\)|\()', fncall):
+      error(filename, linenum, 'whitespace/parens', 2,
+            'Extra space after (')
+    if (Search(r'\w\s+\(', fncall) and
+        not Search(r'#\s*define|typedef|using\s+\w+\s*=', fncall) and
+        not Search(r'\w\s+\((\w+::)*\*\w+\)\(', fncall)):
+      # TODO(unknown): Space after an operator function seem to be a common
+      # error, silence those for now by restricting them to highest verbosity.
+      if Search(r'\boperator_*\b', line):
+        error(filename, linenum, 'whitespace/parens', 0,
+              'Extra space before ( in function call')
+      else:
+        error(filename, linenum, 'whitespace/parens', 4,
+              'Extra space before ( in function call')
+    # If the ) is followed only by a newline or a { + newline, assume it's
+    # part of a control statement (if/while/etc), and don't complain
+    if Search(r'[^)]\s+\)\s*[^{\s]', fncall):
+      # If the closing parenthesis is preceded by only whitespaces,
+      # try to give a more descriptive error message.
+      if Search(r'^\s+\)', fncall):
+        error(filename, linenum, 'whitespace/parens', 2,
+              'Closing ) should be moved to the previous line')
+      else:
+        error(filename, linenum, 'whitespace/parens', 2,
+              'Extra space before )')
+
+
+def IsBlankLine(line):
+  """Returns true if the given line is blank.
+
+  We consider a line to be blank if the line is empty or consists of
+  only white spaces.
+
+  Args:
+    line: A line of a string.
+
+  Returns:
+    True, if the given line is blank.
+  """
+  return not line or line.isspace()
+
+
+def CheckForFunctionLengths(filename, clean_lines, linenum,
+                            function_state, error):
+  """Reports for long function bodies.
+
+  For an overview why this is done, see:
+  http://google-styleguide.googlecode.com/svn/trunk/cppguide.xml#Write_Short_Functions
+
+  Uses a simplistic algorithm assuming other style guidelines
+  (especially spacing) are followed.
+  Only checks unindented functions, so class members are unchecked.
+  Trivial bodies are unchecked, so constructors with huge initializer lists
+  may be missed.
+  Blank/comment lines are not counted so as to avoid encouraging the removal
+  of vertical space and comments just to get through a lint check.
+  NOLINT *on the last line of a function* disables this check.
+
+  Args:
+    filename: The name of the current file.
+    clean_lines: A CleansedLines instance containing the file.
+    linenum: The number of the line to check.
+    function_state: Current function name and lines in body so far.
+    error: The function to call with any errors found.
+  """
+  lines = clean_lines.lines
+  line = lines[linenum]
+  joined_line = ''
+
+  starting_func = False
+  regexp = r'(\w(\w|::|\*|\&|\s)*)\('  # decls * & space::name( ...
+  match_result = Match(regexp, line)
+  if match_result:
+    # If the name is all caps and underscores, figure it's a macro and
+    # ignore it, unless it's TEST or TEST_F.
+    function_name = match_result.group(1).split()[-1]
+    if function_name == 'TEST' or function_name == 'TEST_F' or (
+        not Match(r'[A-Z_]+$', function_name)):
+      starting_func = True
+
+  if starting_func:
+    body_found = False
+    for start_linenum in xrange(linenum, clean_lines.NumLines()):
+      start_line = lines[start_linenum]
+      joined_line += ' ' + start_line.lstrip()
+      if Search(r'(;|})', start_line):  # Declarations and trivial functions
+        body_found = True
+        break                              # ... ignore
+      elif Search(r'{', start_line):
+        body_found = True
+        function = Search(r'((\w|:)*)\(', line).group(1)
+        if Match(r'TEST', function):    # Handle TEST... macros
+          parameter_regexp = Search(r'(\(.*\))', joined_line)
+          if parameter_regexp:             # Ignore bad syntax
+            function += parameter_regexp.group(1)
+        else:
+          function += '()'
+        function_state.Begin(function)
+        break
+    if not body_found:
+      # No body for the function (or evidence of a non-function) was found.
+      error(filename, linenum, 'readability/fn_size', 5,
+            'Lint failed to find start of function body.')
+  elif Match(r'^\}\s*$', line):  # function end
+    function_state.Check(error, filename, linenum)
+    function_state.End()
+  elif not Match(r'^\s*$', line):
+    function_state.Count()  # Count non-blank/non-comment lines.
+
+
+_RE_PATTERN_TODO = re.compile(r'^//(\s*)TODO(\(.+?\))?:?(\s|$)?')
+
+
+def CheckComment(line, filename, linenum, next_line_start, error):
+  """Checks for common mistakes in comments.
+
+  Args:
+    line: The line in question.
+    filename: The name of the current file.
+    linenum: The number of the line to check.
+    next_line_start: The first non-whitespace column of the next line.
+    error: The function to call with any errors found.
+  """
+  commentpos = line.find('//')
+  if commentpos != -1:
+    # Check if the // may be in quotes.  If so, ignore it
+    # Comparisons made explicit for clarity -- pylint: disable=g-explicit-bool-comparison
+    if (line.count('"', 0, commentpos) -
+        line.count('\\"', 0, commentpos)) % 2 == 0:   # not in quotes
+      # Allow one space for new scopes, two spaces otherwise:
+      if (not (Match(r'^.*{ *//', line) and next_line_start == commentpos) and
+          ((commentpos >= 1 and
+            line[commentpos-1] not in string.whitespace) or
+           (commentpos >= 2 and
+            line[commentpos-2] not in string.whitespace))):
+        error(filename, linenum, 'whitespace/comments', 2,
+              'At least two spaces is best between code and comments')
+
+      # Checks for common mistakes in TODO comments.
+      comment = line[commentpos:]
+      match = _RE_PATTERN_TODO.match(comment)
+      if match:
+        # One whitespace is correct; zero whitespace is handled elsewhere.
+        leading_whitespace = match.group(1)
+        if len(leading_whitespace) > 1:
+          error(filename, linenum, 'whitespace/todo', 2,
+                'Too many spaces before TODO')
+
+        username = match.group(2)
+        # if not username:
+        #   error(filename, linenum, 'readability/todo', 2,
+        #         'Missing username in TODO; it should look like '
+        #         '"// TODO(my_username): Stuff."')
+
+        middle_whitespace = match.group(3)
+        # Comparisons made explicit for correctness -- pylint: disable=g-explicit-bool-comparison
+        if middle_whitespace != ' ' and middle_whitespace != '':
+          error(filename, linenum, 'whitespace/todo', 2,
+                'TODO(my_username) should be followed by a space')
+
+      # If the comment contains an alphanumeric character, there
+      # should be a space somewhere between it and the //.
+      if Match(r'//[^ ]*\w', comment):
+        error(filename, linenum, 'whitespace/comments', 4,
+              'Should have a space between // and comment')
+
+def CheckAccess(filename, clean_lines, linenum, nesting_state, error):
+  """Checks for improper use of DISALLOW* macros.
+
+  Args:
+    filename: The name of the current file.
+    clean_lines: A CleansedLines instance containing the file.
+    linenum: The number of the line to check.
+    nesting_state: A NestingState instance which maintains information about
+                   the current stack of nested blocks being parsed.
+    error: The function to call with any errors found.
+  """
+  line = clean_lines.elided[linenum]  # get rid of comments and strings
+
+  matched = Match((r'\s*(DISALLOW_COPY_AND_ASSIGN|'
+                   r'DISALLOW_EVIL_CONSTRUCTORS|'
+                   r'DISALLOW_IMPLICIT_CONSTRUCTORS)'), line)
+  if not matched:
+    return
+  if nesting_state.stack and isinstance(nesting_state.stack[-1], _ClassInfo):
+    if nesting_state.stack[-1].access != 'private':
+      error(filename, linenum, 'readability/constructors', 3,
+            '%s must be in the private: section' % matched.group(1))
+
+  else:
+    # Found DISALLOW* macro outside a class declaration, or perhaps it
+    # was used inside a function when it should have been part of the
+    # class declaration.  We could issue a warning here, but it
+    # probably resulted in a compiler error already.
+    pass
+
+
+def CheckSpacing(filename, clean_lines, linenum, nesting_state, error):
+  """Checks for the correctness of various spacing issues in the code.
+
+  Things we check for: spaces around operators, spaces after
+  if/for/while/switch, no spaces around parens in function calls, two
+  spaces between code and comment, don't start a block with a blank
+  line, don't end a function with a blank line, don't add a blank line
+  after public/protected/private, don't have too many blank lines in a row.
+
+  Args:
+    filename: The name of the current file.
+    clean_lines: A CleansedLines instance containing the file.
+    linenum: The number of the line to check.
+    nesting_state: A NestingState instance which maintains information about
+                   the current stack of nested blocks being parsed.
+    error: The function to call with any errors found.
+  """
+
+  # Don't use "elided" lines here, otherwise we can't check commented lines.
+  # Don't want to use "raw" either, because we don't want to check inside C++11
+  # raw strings,
+  raw = clean_lines.lines_without_raw_strings
+  line = raw[linenum]
+
+  # Before nixing comments, check if the line is blank for no good
+  # reason.  This includes the first line after a block is opened, and
+  # blank lines at the end of a function (ie, right before a line like '}'
+  #
+  # Skip all the blank line checks if we are immediately inside a
+  # namespace body.  In other words, don't issue blank line warnings
+  # for this block:
+  #   namespace {
+  #
+  #   }
+  #
+  # A warning about missing end of namespace comments will be issued instead.
+  #
+  # Also skip blank line checks for 'extern "C"' blocks, which are formatted
+  # like namespaces.
+  if (IsBlankLine(line) and
+      not nesting_state.InNamespaceBody() and
+      not nesting_state.InExternC()):
+    elided = clean_lines.elided
+    prev_line = elided[linenum - 1]
+    prevbrace = prev_line.rfind('{')
+    # TODO(unknown): Don't complain if line before blank line, and line after,
+    #                both start with alnums and are indented the same amount.
+    #                This ignores whitespace at the start of a namespace block
+    #                because those are not usually indented.
+    if prevbrace != -1 and prev_line[prevbrace:].find('}') == -1:
+      # OK, we have a blank line at the start of a code block.  Before we
+      # complain, we check if it is an exception to the rule: The previous
+      # non-empty line has the parameters of a function header that are indented
+      # 4 spaces (because they did not fit in a 80 column line when placed on
+      # the same line as the function name).  We also check for the case where
+      # the previous line is indented 6 spaces, which may happen when the
+      # initializers of a constructor do not fit into a 80 column line.
+      exception = False
+      if Match(r' {6}\w', prev_line):  # Initializer list?
+        # We are looking for the opening column of initializer list, which
+        # should be indented 4 spaces to cause 6 space indentation afterwards.
+        search_position = linenum-2
+        while (search_position >= 0
+               and Match(r' {6}\w', elided[search_position])):
+          search_position -= 1
+        exception = (search_position >= 0
+                     and elided[search_position][:5] == '    :')
+      else:
+        # Search for the function arguments or an initializer list.  We use a
+        # simple heuristic here: If the line is indented 4 spaces; and we have a
+        # closing paren, without the opening paren, followed by an opening brace
+        # or colon (for initializer lists) we assume that it is the last line of
+        # a function header.  If we have a colon indented 4 spaces, it is an
+        # initializer list.
+        exception = (Match(r' {4}\w[^\(]*\)\s*(const\s*)?(\{\s*$|:)',
+                           prev_line)
+                     or Match(r' {4}:', prev_line))
+
+      if not exception:
+        error(filename, linenum, 'whitespace/blank_line', 2,
+              'Redundant blank line at the start of a code block '
+              'should be deleted.')
+    # Ignore blank lines at the end of a block in a long if-else
+    # chain, like this:
+    #   if (condition1) {
+    #     // Something followed by a blank line
+    #
+    #   } else if (condition2) {
+    #     // Something else
+    #   }
+    if linenum + 1 < clean_lines.NumLines():
+      next_line = raw[linenum + 1]
+      if (next_line
+          and Match(r'\s*}', next_line)
+          and next_line.find('} else ') == -1):
+        error(filename, linenum, 'whitespace/blank_line', 3,
+              'Redundant blank line at the end of a code block '
+              'should be deleted.')
+
+    # matched = Match(r'\s*(public|protected|private):', prev_line)
+    # if matched:
+    #   error(filename, linenum, 'whitespace/blank_line', 3,
+    #         'Do not leave a blank line after "%s:"' % matched.group(1))
+
+  # Next, check comments
+  next_line_start = 0
+  if linenum + 1 < clean_lines.NumLines():
+    next_line = raw[linenum + 1]
+    next_line_start = len(next_line) - len(next_line.lstrip())
+  CheckComment(line, filename, linenum, next_line_start, error)
+
+  # get rid of comments and strings
+  line = clean_lines.elided[linenum]
+
+  # You shouldn't have spaces before your brackets, except maybe after
+  # 'delete []' or 'return []() {};'
+  if Search(r'\w\s+\[', line) and not Search(r'(?:delete|return)\s+\[', line):
+    error(filename, linenum, 'whitespace/braces', 5,
+          'Extra space before [')
+
+  # In range-based for, we wanted spaces before and after the colon, but
+  # not around "::" tokens that might appear.
+  if (Search(r'for *\(.*[^:]:[^: ]', line) or
+      Search(r'for *\(.*[^: ]:[^:]', line)):
+    error(filename, linenum, 'whitespace/forcolon', 2,
+          'Missing space around colon in range-based for loop')
+
+
+def CheckOperatorSpacing(filename, clean_lines, linenum, error):
+  """Checks for horizontal spacing around operators.
+
+  Args:
+    filename: The name of the current file.
+    clean_lines: A CleansedLines instance containing the file.
+    linenum: The number of the line to check.
+    error: The function to call with any errors found.
+  """
+  line = clean_lines.elided[linenum]
+
+  # Don't try to do spacing checks for operator methods.  Do this by
+  # replacing the troublesome characters with something else,
+  # preserving column position for all other characters.
+  #
+  # The replacement is done repeatedly to avoid false positives from
+  # operators that call operators.
+  while True:
+    match = Match(r'^(.*\boperator\b)(\S+)(\s*\(.*)$', line)
+    if match:
+      line = match.group(1) + ('_' * len(match.group(2))) + match.group(3)
+    else:
+      break
+
+  # We allow no-spaces around = within an if: "if ( (a=Foo()) == 0 )".
+  # Otherwise not.  Note we only check for non-spaces on *both* sides;
+  # sometimes people put non-spaces on one side when aligning ='s among
+  # many lines (not that this is behavior that I approve of...)
+  if Search(r'[\w.]=[\w.]', line) and not Search(r'\b(if|while) ', line):
+    error(filename, linenum, 'whitespace/operators', 4,
+          'Missing spaces around =')
+
+  # It's ok not to have spaces around binary operators like + - * /, but if
+  # there's too little whitespace, we get concerned.  It's hard to tell,
+  # though, so we punt on this one for now.  TODO.
+
+  # You should always have whitespace around binary operators.
+  #
+  # Check <= and >= first to avoid false positives with < and >, then
+  # check non-include lines for spacing around < and >.
+  #
+  # If the operator is followed by a comma, assume it's be used in a
+  # macro context and don't do any checks.  This avoids false
+  # positives.
+  #
+  # Note that && is not included here.  Those are checked separately
+  # in CheckRValueReference
+  match = Search(r'[^<>=!\s](==|!=|<=|>=|\|\|)[^<>=!\s,;\)]', line)
+  if match:
+    error(filename, linenum, 'whitespace/operators', 3,
+          'Missing spaces around %s' % match.group(1))
+  elif not Match(r'#.*include', line):
+    # Look for < that is not surrounded by spaces.  This is only
+    # triggered if both sides are missing spaces, even though
+    # technically should should flag if at least one side is missing a
+    # space.  This is done to avoid some false positives with shifts.
+    match = Match(r'^(.*[^\s<])<[^\s=<,]', line)
+    if match:
+      (_, _, end_pos) = CloseExpression(
+          clean_lines, linenum, len(match.group(1)))
+      if end_pos <= -1:
+        error(filename, linenum, 'whitespace/operators', 3,
+              'Missing spaces around <')
+
+    # Look for > that is not surrounded by spaces.  Similar to the
+    # above, we only trigger if both sides are missing spaces to avoid
+    # false positives with shifts.
+    match = Match(r'^(.*[^-\s>])>[^\s=>,]', line)
+    if match:
+      (_, _, start_pos) = ReverseCloseExpression(
+          clean_lines, linenum, len(match.group(1)))
+      if start_pos <= -1:
+        error(filename, linenum, 'whitespace/operators', 3,
+              'Missing spaces around >')
+
+  # We allow no-spaces around << when used like this: 10<<20, but
+  # not otherwise (particularly, not when used as streams)
+  # We also allow operators following an opening parenthesis, since
+  # those tend to be macros that deal with operators.
+  match = Search(r'(operator|\S)(?:L|UL|ULL|l|ul|ull)?<<([^\s,=])', line)
+  if (match and match.group(1) != '(' and
+      not (match.group(1).isdigit() and match.group(2).isdigit()) and
+      not (match.group(1) == 'operator' and match.group(2) == ';')):
+    error(filename, linenum, 'whitespace/operators', 3,
+          'Missing spaces around <<')
+
+  # We allow no-spaces around >> for almost anything.  This is because
+  # C++11 allows ">>" to close nested templates, which accounts for
+  # most cases when ">>" is not followed by a space.
+  #
+  # We still warn on ">>" followed by alpha character, because that is
+  # likely due to ">>" being used for right shifts, e.g.:
+  #   value >> alpha
+  #
+  # When ">>" is used to close templates, the alphanumeric letter that
+  # follows would be part of an identifier, and there should still be
+  # a space separating the template type and the identifier.
+  #   type<type<type>> alpha
+  match = Search(r'>>[a-zA-Z_]', line)
+  if match:
+    error(filename, linenum, 'whitespace/operators', 3,
+          'Missing spaces around >>')
+
+  # There shouldn't be space around unary operators
+  match = Search(r'(!\s|~\s|[\s]--[\s;]|[\s]\+\+[\s;])', line)
+  if match:
+    error(filename, linenum, 'whitespace/operators', 4,
+          'Extra space for operator %s' % match.group(1))
+
+
+def CheckParenthesisSpacing(filename, clean_lines, linenum, error):
+  """Checks for horizontal spacing around parentheses.
+
+  Args:
+    filename: The name of the current file.
+    clean_lines: A CleansedLines instance containing the file.
+    linenum: The number of the line to check.
+    error: The function to call with any errors found.
+  """
+  line = clean_lines.elided[linenum]
+
+  # No spaces after an if, while, switch, or for
+  match = Search(r' (if\(|for\(|while\(|switch\()', line)
+  if match:
+    error(filename, linenum, 'whitespace/parens', 5,
+          'Missing space before ( in %s' % match.group(1))
+
+  # For if/for/while/switch, the left and right parens should be
+  # consistent about how many spaces are inside the parens, and
+  # there should either be zero or one spaces inside the parens.
+  # We don't want: "if ( foo)" or "if ( foo   )".
+  # Exception: "for ( ; foo; bar)" and "for (foo; bar; )" are allowed.
+  match = Search(r'\b(if|for|while|switch)\s*'
+                 r'\(([ ]*)(.).*[^ ]+([ ]*)\)\s*{\s*$',
+                 line)
+  if match:
+    if len(match.group(2)) != len(match.group(4)):
+      if not (match.group(3) == ';' and
+              len(match.group(2)) == 1 + len(match.group(4)) or
+              not match.group(2) and Search(r'\bfor\s*\(.*; \)', line)):
+        error(filename, linenum, 'whitespace/parens', 5,
+              'Mismatching spaces inside () in %s' % match.group(1))
+    if len(match.group(2)) not in [0, 1]:
+      error(filename, linenum, 'whitespace/parens', 5,
+            'Should have zero or one spaces inside ( and ) in %s' %
+            match.group(1))
+
+
+def CheckCommaSpacing(filename, clean_lines, linenum, error):
+  """Checks for horizontal spacing near commas and semicolons.
+
+  Args:
+    filename: The name of the current file.
+    clean_lines: A CleansedLines instance containing the file.
+    linenum: The number of the line to check.
+    error: The function to call with any errors found.
+  """
+  raw = clean_lines.lines_without_raw_strings
+  line = clean_lines.elided[linenum]
+
+  # You should always have a space after a comma (either as fn arg or operator)
+  #
+  # This does not apply when the non-space character following the
+  # comma is another comma, since the only time when that happens is
+  # for empty macro arguments.
+  #
+  # We run this check in two passes: first pass on elided lines to
+  # verify that lines contain missing whitespaces, second pass on raw
+  # lines to confirm that those missing whitespaces are not due to
+  # elided comments.
+  if Search(r',[^,\s]', line) and Search(r',[^,\s]', raw[linenum]):
+    error(filename, linenum, 'whitespace/comma', 3,
+          'Missing space after ,')
+
+  # You should always have a space after a semicolon
+  # except for few corner cases
+  # TODO(unknown): clarify if 'if (1) { return 1;}' is requires one more
+  # space after ;
+  if Search(r';[^\s};\\)/]', line):
+    error(filename, linenum, 'whitespace/semicolon', 3,
+          'Missing space after ;')
+
+
+def CheckBracesSpacing(filename, clean_lines, linenum, error):
+  """Checks for horizontal spacing near commas.
+
+  Args:
+    filename: The name of the current file.
+    clean_lines: A CleansedLines instance containing the file.
+    linenum: The number of the line to check.
+    error: The function to call with any errors found.
+  """
+  line = clean_lines.elided[linenum]
+
+  # Except after an opening paren, or after another opening brace (in case of
+  # an initializer list, for instance), you should have spaces before your
+  # braces. And since you should never have braces at the beginning of a line,
+  # this is an easy test.
+  match = Match(r'^(.*[^ ({]){', line)
+  if match:
+    # Try a bit harder to check for brace initialization.  This
+    # happens in one of the following forms:
+    #   Constructor() : initializer_list_{} { ... }
+    #   Constructor{}.MemberFunction()
+    #   Type variable{};
+    #   FunctionCall(type{}, ...);
+    #   LastArgument(..., type{});
+    #   LOG(INFO) << type{} << " ...";
+    #   map_of_type[{...}] = ...;
+    #   ternary = expr ? new type{} : nullptr;
+    #   OuterTemplate<InnerTemplateConstructor<Type>{}>
+    #
+    # We check for the character following the closing brace, and
+    # silence the warning if it's one of those listed above, i.e.
+    # "{.;,)<>]:".
+    #
+    # To account for nested initializer list, we allow any number of
+    # closing braces up to "{;,)<".  We can't simply silence the
+    # warning on first sight of closing brace, because that would
+    # cause false negatives for things that are not initializer lists.
+    #   Silence this:         But not this:
+    #     Outer{                if (...) {
+    #       Inner{...}            if (...){  // Missing space before {
+    #     };                    }
+    #
+    # There is a false negative with this approach if people inserted
+    # spurious semicolons, e.g. "if (cond){};", but we will catch the
+    # spurious semicolon with a separate check.
+    (endline, endlinenum, endpos) = CloseExpression(
+        clean_lines, linenum, len(match.group(1)))
+    trailing_text = ''
+    if endpos > -1:
+      trailing_text = endline[endpos:]
+    for offset in xrange(endlinenum + 1,
+                         min(endlinenum + 3, clean_lines.NumLines() - 1)):
+      trailing_text += clean_lines.elided[offset]
+    if not Match(r'^[\s}]*[{.;,)<>\]:]', trailing_text):
+      error(filename, linenum, 'whitespace/braces', 5,
+            'Missing space before {')
+
+  # Make sure '} else {' has spaces.
+  if Search(r'}else', line):
+    error(filename, linenum, 'whitespace/braces', 5,
+          'Missing space before else')
+
+  # You shouldn't have a space before a semicolon at the end of the line.
+  # There's a special case for "for" since the style guide allows space before
+  # the semicolon there.
+  if Search(r':\s*;\s*$', line):
+    error(filename, linenum, 'whitespace/semicolon', 5,
+          'Semicolon defining empty statement. Use {} instead.')
+  elif Search(r'^\s*;\s*$', line):
+    error(filename, linenum, 'whitespace/semicolon', 5,
+          'Line contains only semicolon. If this should be an empty statement, '
+          'use {} instead.')
+  elif (Search(r'\s+;\s*$', line) and
+        not Search(r'\bfor\b', line)):
+    error(filename, linenum, 'whitespace/semicolon', 5,
+          'Extra space before last semicolon. If this should be an empty '
+          'statement, use {} instead.')
+
+
+def IsDecltype(clean_lines, linenum, column):
+  """Check if the token ending on (linenum, column) is decltype().
+
+  Args:
+    clean_lines: A CleansedLines instance containing the file.
+    linenum: the number of the line to check.
+    column: end column of the token to check.
+  Returns:
+    True if this token is decltype() expression, False otherwise.
+  """
+  (text, _, start_col) = ReverseCloseExpression(clean_lines, linenum, column)
+  if start_col < 0:
+    return False
+  if Search(r'\bdecltype\s*$', text[0:start_col]):
+    return True
+  return False
+
+
+def IsTemplateParameterList(clean_lines, linenum, column):
+  """Check if the token ending on (linenum, column) is the end of template<>.
+
+  Args:
+    clean_lines: A CleansedLines instance containing the file.
+    linenum: the number of the line to check.
+    column: end column of the token to check.
+  Returns:
+    True if this token is end of a template parameter list, False otherwise.
+  """
+  (_, startline, startpos) = ReverseCloseExpression(
+      clean_lines, linenum, column)
+  if (startpos > -1 and
+      Search(r'\btemplate\s*$', clean_lines.elided[startline][0:startpos])):
+    return True
+  return False
+
+
+def IsRValueType(clean_lines, nesting_state, linenum, column):
+  """Check if the token ending on (linenum, column) is a type.
+
+  Assumes that text to the right of the column is "&&" or a function
+  name.
+
+  Args:
+    clean_lines: A CleansedLines instance containing the file.
+    nesting_state: A NestingState instance which maintains information about
+                   the current stack of nested blocks being parsed.
+    linenum: the number of the line to check.
+    column: end column of the token to check.
+  Returns:
+    True if this token is a type, False if we are not sure.
+  """
+  prefix = clean_lines.elided[linenum][0:column]
+
+  # Get one word to the left.  If we failed to do so, this is most
+  # likely not a type, since it's unlikely that the type name and "&&"
+  # would be split across multiple lines.
+  match = Match(r'^(.*)(\b\w+|[>*)&])\s*$', prefix)
+  if not match:
+    return False
+
+  # Check text following the token.  If it's "&&>" or "&&," or "&&...", it's
+  # most likely a rvalue reference used inside a template.
+  suffix = clean_lines.elided[linenum][column:]
+  if Match(r'&&\s*(?:[>,]|\.\.\.)', suffix):
+    return True
+
+  # Check for simple type and end of templates:
+  #   int&& variable
+  #   vector<int>&& variable
+  #
+  # Because this function is called recursively, we also need to
+  # recognize pointer and reference types:
+  #   int* Function()
+  #   int& Function()
+  if match.group(2) in ['char', 'char16_t', 'char32_t', 'wchar_t', 'bool',
+                        'short', 'int', 'long', 'signed', 'unsigned',
+                        'float', 'double', 'void', 'auto', '>', '*', '&']:
+    return True
+
+  # If we see a close parenthesis, look for decltype on the other side.
+  # decltype would unambiguously identify a type, anything else is
+  # probably a parenthesized expression and not a type.
+  if match.group(2) == ')':
+    return IsDecltype(
+        clean_lines, linenum, len(match.group(1)) + len(match.group(2)) - 1)
+
+  # Check for casts and cv-qualifiers.
+  #   match.group(1)  remainder
+  #   --------------  ---------
+  #   const_cast<     type&&
+  #   const           type&&
+  #   type            const&&
+  if Search(r'\b(?:const_cast\s*<|static_cast\s*<|dynamic_cast\s*<|'
+            r'reinterpret_cast\s*<|\w+\s)\s*$',
+            match.group(1)):
+    return True
+
+  # Look for a preceding symbol that might help differentiate the context.
+  # These are the cases that would be ambiguous:
+  #   match.group(1)  remainder
+  #   --------------  ---------
+  #   Call         (   expression &&
+  #   Declaration  (   type&&
+  #   sizeof       (   type&&
+  #   if           (   expression &&
+  #   while        (   expression &&
+  #   for          (   type&&
+  #   for(         ;   expression &&
+  #   statement    ;   type&&
+  #   block        {   type&&
+  #   constructor  {   expression &&
+  start = linenum
+  line = match.group(1)
+  match_symbol = None
+  while start >= 0:
+    # We want to skip over identifiers and commas to get to a symbol.
+    # Commas are skipped so that we can find the opening parenthesis
+    # for function parameter lists.
+    match_symbol = Match(r'^(.*)([^\w\s,])[\w\s,]*$', line)
+    if match_symbol:
+      break
+    start -= 1
+    line = clean_lines.elided[start]
+
+  if not match_symbol:
+    # Probably the first statement in the file is an rvalue reference
+    return True
+
+  if match_symbol.group(2) == '}':
+    # Found closing brace, probably an indicate of this:
+    #   block{} type&&
+    return True
+
+  if match_symbol.group(2) == ';':
+    # Found semicolon, probably one of these:
+    #   for(; expression &&
+    #   statement; type&&
+
+    # Look for the previous 'for(' in the previous lines.
+    before_text = match_symbol.group(1)
+    for i in xrange(start - 1, max(start - 6, 0), -1):
+      before_text = clean_lines.elided[i] + before_text
+    if Search(r'for\s*\([^{};]*$', before_text):
+      # This is the condition inside a for-loop
+      return False
+
+    # Did not find a for-init-statement before this semicolon, so this
+    # is probably a new statement and not a condition.
+    return True
+
+  if match_symbol.group(2) == '{':
+    # Found opening brace, probably one of these:
+    #   block{ type&& = ... ; }
+    #   constructor{ expression && expression }
+
+    # Look for a closing brace or a semicolon.  If we see a semicolon
+    # first, this is probably a rvalue reference.
+    line = clean_lines.elided[start][0:len(match_symbol.group(1)) + 1]
+    end = start
+    depth = 1
+    while True:
+      for ch in line:
+        if ch == ';':
+          return True
+        elif ch == '{':
+          depth += 1
+        elif ch == '}':
+          depth -= 1
+          if depth == 0:
+            return False
+      end += 1
+      if end >= clean_lines.NumLines():
+        break
+      line = clean_lines.elided[end]
+    # Incomplete program?
+    return False
+
+  if match_symbol.group(2) == '(':
+    # Opening parenthesis.  Need to check what's to the left of the
+    # parenthesis.  Look back one extra line for additional context.
+    before_text = match_symbol.group(1)
+    if linenum > 1:
+      before_text = clean_lines.elided[linenum - 1] + before_text
+    before_text = match_symbol.group(1)
+
+    # Patterns that are likely to be types:
+    #   [](type&&
+    #   for (type&&
+    #   sizeof(type&&
+    #   operator=(type&&
+    #
+    if Search(r'(?:\]|\bfor|\bsizeof|\boperator\s*\S+\s*)\s*$', before_text):
+      return True
+
+    # Patterns that are likely to be expressions:
+    #   if (expression &&
+    #   while (expression &&
+    #   : initializer(expression &&
+    #   , initializer(expression &&
+    #   ( FunctionCall(expression &&
+    #   + FunctionCall(expression &&
+    #   + (expression &&
+    #
+    # The last '+' represents operators such as '+' and '-'.
+    if Search(r'(?:\bif|\bwhile|[-+=%^(<!?:,&*]\s*)$', before_text):
+      return False
+
+    # Something else.  Check that tokens to the left look like
+    #   return_type function_name
+    match_func = Match(r'^(.*)\s+\w(?:\w|::)*(?:<[^<>]*>)?\s*$',
+                       match_symbol.group(1))
+    if match_func:
+      # Check for constructors, which don't have return types.
+      if Search(r'\bexplicit$', match_func.group(1)):
+        return True
+      implicit_constructor = Match(r'\s*(\w+)\((?:const\s+)?(\w+)', prefix)
+      if (implicit_constructor and
+          implicit_constructor.group(1) == implicit_constructor.group(2)):
+        return True
+      return IsRValueType(clean_lines, nesting_state, linenum,
+                          len(match_func.group(1)))
+
+    # Nothing before the function name.  If this is inside a block scope,
+    # this is probably a function call.
+    return not (nesting_state.previous_stack_top and
+                nesting_state.previous_stack_top.IsBlockInfo())
+
+  if match_symbol.group(2) == '>':
+    # Possibly a closing bracket, check that what's on the other side
+    # looks like the start of a template.
+    return IsTemplateParameterList(
+        clean_lines, start, len(match_symbol.group(1)))
+
+  # Some other symbol, usually something like "a=b&&c".  This is most
+  # likely not a type.
+  return False
+
+
+def IsRValueAllowed(clean_lines, linenum):
+  """Check if RValue reference is allowed within some range of lines.
+
+  Args:
+    clean_lines: A CleansedLines instance containing the file.
+    linenum: The number of the line to check.
+  Returns:
+    True if line is within the region where RValue references are allowed.
+  """
+  for i in xrange(linenum, 0, -1):
+    line = clean_lines.elided[i]
+    if Match(r'GOOGLE_ALLOW_RVALUE_REFERENCES_(?:PUSH|POP)', line):
+      if not line.endswith('PUSH'):
+        return False
+      for j in xrange(linenum, clean_lines.NumLines(), 1):
+        line = clean_lines.elided[j]
+        if Match(r'GOOGLE_ALLOW_RVALUE_REFERENCES_(?:PUSH|POP)', line):
+          return line.endswith('POP')
+  return False
+
+
+def CheckRValueReference(filename, clean_lines, linenum, nesting_state, error):
+  """Check for rvalue references.
+
+  Args:
+    filename: The name of the current file.
+    clean_lines: A CleansedLines instance containing the file.
+    linenum: The number of the line to check.
+    nesting_state: A NestingState instance which maintains information about
+                   the current stack of nested blocks being parsed.
+    error: The function to call with any errors found.
+  """
+  # Find lines missing spaces around &&.
+  # TODO(unknown): currently we don't check for rvalue references
+  # with spaces surrounding the && to avoid false positives with
+  # boolean expressions.
+  line = clean_lines.elided[linenum]
+  match = Match(r'^(.*\S)&&', line)
+  if not match:
+    match = Match(r'(.*)&&\S', line)
+  if (not match) or '(&&)' in line or Search(r'\boperator\s*$', match.group(1)):
+    return
+
+  # Either poorly formed && or an rvalue reference, check the context
+  # to get a more accurate error message.  Mostly we want to determine
+  # if what's to the left of "&&" is a type or not.
+  and_pos = len(match.group(1))
+  if IsRValueType(clean_lines, nesting_state, linenum, and_pos):
+    if not IsRValueAllowed(clean_lines, linenum):
+      error(filename, linenum, 'build/c++11', 3,
+            'RValue references are an unapproved C++ feature.')
+  else:
+    error(filename, linenum, 'whitespace/operators', 3,
+          'Missing spaces around &&')
+
+
+def CheckSectionSpacing(filename, clean_lines, class_info, linenum, error):
+  """Checks for additional blank line issues related to sections.
+
+  Currently the only thing checked here is blank line before protected/private.
+
+  Args:
+    filename: The name of the current file.
+    clean_lines: A CleansedLines instance containing the file.
+    class_info: A _ClassInfo objects.
+    linenum: The number of the line to check.
+    error: The function to call with any errors found.
+  """
+  # Skip checks if the class is small, where small means 25 lines or less.
+  # 25 lines seems like a good cutoff since that's the usual height of
+  # terminals, and any class that can't fit in one screen can't really
+  # be considered "small".
+  #
+  # Also skip checks if we are on the first line.  This accounts for
+  # classes that look like
+  #   class Foo { public: ... };
+  #
+  # If we didn't find the end of the class, last_line would be zero,
+  # and the check will be skipped by the first condition.
+  if (class_info.last_line - class_info.starting_linenum <= 24 or
+      linenum <= class_info.starting_linenum):
+    return
+
+  matched = Match(r'\s*(public|protected|private):', clean_lines.lines[linenum])
+  if matched:
+    # Issue warning if the line before public/protected/private was
+    # not a blank line, but don't do this if the previous line contains
+    # "class" or "struct".  This can happen two ways:
+    #  - We are at the beginning of the class.
+    #  - We are forward-declaring an inner class that is semantically
+    #    private, but needed to be public for implementation reasons.
+    # Also ignores cases where the previous line ends with a backslash as can be
+    # common when defining classes in C macros.
+    prev_line = clean_lines.lines[linenum - 1]
+    if (not IsBlankLine(prev_line) and
+        not Search(r'\b(class|struct)\b', prev_line) and
+        not Search(r'\\$', prev_line)):
+      # Try a bit harder to find the beginning of the class.  This is to
+      # account for multi-line base-specifier lists, e.g.:
+      #   class Derived
+      #       : public Base {
+      end_class_head = class_info.starting_linenum
+      for i in range(class_info.starting_linenum, linenum):
+        if Search(r'\{\s*$', clean_lines.lines[i]):
+          end_class_head = i
+          break
+      if end_class_head < linenum - 1:
+        error(filename, linenum, 'whitespace/blank_line', 3,
+              '"%s:" should be preceded by a blank line' % matched.group(1))
+
+
+def GetPreviousNonBlankLine(clean_lines, linenum):
+  """Return the most recent non-blank line and its line number.
+
+  Args:
+    clean_lines: A CleansedLines instance containing the file contents.
+    linenum: The number of the line to check.
+
+  Returns:
+    A tuple with two elements.  The first element is the contents of the last
+    non-blank line before the current line, or the empty string if this is the
+    first non-blank line.  The second is the line number of that line, or -1
+    if this is the first non-blank line.
+  """
+
+  prevlinenum = linenum - 1
+  while prevlinenum >= 0:
+    prevline = clean_lines.elided[prevlinenum]
+    if not IsBlankLine(prevline):     # if not a blank line...
+      return (prevline, prevlinenum)
+    prevlinenum -= 1
+  return ('', -1)
+
+
+def CheckBraces(filename, clean_lines, linenum, error):
+  """Looks for misplaced braces (e.g. at the end of line).
+
+  Args:
+    filename: The name of the current file.
+    clean_lines: A CleansedLines instance containing the file.
+    linenum: The number of the line to check.
+    error: The function to call with any errors found.
+  """
+
+  line = clean_lines.elided[linenum]        # get rid of comments and strings
+
+  #if Match(r'\s*{\s*$', line):
+  #  # We allow an open brace to start a line in the case where someone is using
+  #  # braces in a block to explicitly create a new scope, which is commonly used
+  #  # to control the lifetime of stack-allocated variables.  Braces are also
+  #  # used for brace initializers inside function calls.  We don't detect this
+  #  # perfectly: we just don't complain if the last non-whitespace character on
+  #  # the previous non-blank line is ',', ';', ':', '(', '{', or '}', or if the
+  #  # previous line starts a preprocessor block.
+  #  prevline = GetPreviousNonBlankLine(clean_lines, linenum)[0]
+  #  if (not Search(r'[,;:}{()]\s*$', prevline) and
+  #      not Match(r'\s*#', prevline) and
+  #      os.path.splitext(filename)[1] != ".hh"):
+  #      #not Match(r'\s*}\s*', prevline) and
+  #      #not Match(r'^\s*{\s*&', prevline)):
+  #    error(filename, linenum, 'whitespace/braces', 4,
+  #          '{ should never be at the end of the previous line')
+
+  # An else clause should not be on the same line as the preceding closing brace.
+  if Match(r'\s*}\s*else\b\s*(?:if\b|\{|$)', line):
+    # prevline = GetPreviousNonBlankLine(clean_lines, linenum)[0]
+    #if Match(r'\s*}\s*$', line):
+    error(filename, linenum, 'whitespace/newline', 4,
+          'An else should not appear on the same line as the preceding }')
+  if Match(r'\s*else.*{$', line):
+    error(filename, linenum, 'whitespace/newline', 4,
+          'An else should not appear on the same line as the next {')
+
+  # If braces come on one side of an else, they should be on both.
+  # However, we have to worry about "else if" that spans multiple lines!
+  # if Search(r'else if\s*\(', line):       # could be multi-line if
+  #   brace_on_left = bool(Search(r'}\s*else if\s*\(', line))
+  #   # find the ( after the if
+  #   pos = line.find('else if')
+  #   pos = line.find('(', pos)
+  #   if pos > 0:
+  #     (endline, _, endpos) = CloseExpression(clean_lines, linenum, pos)
+  #     brace_on_right = endline[endpos:].find('{') != -1
+  #     if brace_on_left != brace_on_right:    # must be brace after if
+  #       error(filename, linenum, 'readability/braces', 5,
+  #             'If an else has a brace on one side, it should have it on both')
+  # elif Search(r'}\s*else[^{]*$', line) or Match(r'[^}]*else\s*{', line):
+  #   error(filename, linenum, 'readability/braces', 5,
+  #         'If an else has a brace on one side, it should have it on both')
+
+  # Likewise, an else should never have the else clause on the same line
+  if Search(r'\belse [^\s{]', line) and not Search(r'\belse if\b', line):
+    error(filename, linenum, 'whitespace/newline', 4,
+          'Else clause should never be on same line as else (use 2 lines)')
+
+  # In the same way, a do/while should never be on one line
+  if Match(r'\s*do [^\s{]', line):
+    error(filename, linenum, 'whitespace/newline', 4,
+          'do/while clauses should not be on a single line')
+
+  # Check single-line if/else bodies. The style guide says 'curly braces are not
+  # required for single-line statements'. We additionally allow multi-line,
+  # single statements, but we reject anything with more than one semicolon in
+  # it. This means that the first semicolon after the if should be at the end of
+  # its line, and the line after that should have an indent level equal to or
+  # lower than the if. We also check for ambiguous if/else nesting without
+  # braces.
+  if_else_match = Search(r'\b(if\s*\(|else\b)', line)
+  if if_else_match and not Match(r'\s*#', line):
+    if_indent = GetIndentLevel(line)
+    endline, endlinenum, endpos = line, linenum, if_else_match.end()
+    if_match = Search(r'\bif\s*\(', line)
+    if if_match:
+      # This could be a multiline if condition, so find the end first.
+      pos = if_match.end() - 1
+      (endline, endlinenum, endpos) = CloseExpression(clean_lines, linenum, pos)
+    # Check for an opening brace, either directly after the if or on the next
+    # line. If found, this isn't a single-statement conditional.
+    if (not Match(r'\s*{', endline[endpos:])
+        and not (Match(r'\s*$', endline[endpos:])
+                 and endlinenum < (len(clean_lines.elided) - 1)
+                 and Match(r'\s*{', clean_lines.elided[endlinenum + 1]))):
+      while (endlinenum < len(clean_lines.elided)
+             and ';' not in clean_lines.elided[endlinenum][endpos:]):
+        endlinenum += 1
+        endpos = 0
+      if endlinenum < len(clean_lines.elided):
+        endline = clean_lines.elided[endlinenum]
+        # We allow a mix of whitespace and closing braces (e.g. for one-liner
+        # methods) and a single \ after the semicolon (for macros)
+        endpos = endline.find(';')
+        if not Match(r';[\s}]*(\\?)$', endline[endpos:]):
+          # Semicolon isn't the last character, there's something trailing
+          error(filename, linenum, 'readability/braces', 4,
+                'If/else bodies with multiple statements require braces')
+        elif endlinenum < len(clean_lines.elided) - 1:
+          # Make sure the next line is dedented
+          next_line = clean_lines.elided[endlinenum + 1]
+          next_indent = GetIndentLevel(next_line)
+          # With ambiguous nested if statements, this will error out on the
+          # if that *doesn't* match the else, regardless of whether it's the
+          # inner one or outer one.
+          if (if_match and Match(r'\s*else\b', next_line)
+              and next_indent != if_indent):
+            error(filename, linenum, 'readability/braces', 4,
+                  'Else clause should be indented at the same level as if. '
+                  'Ambiguous nested if/else chains require braces.')
+          elif next_indent > if_indent:
+            error(filename, linenum, 'readability/braces', 4,
+                  'If/else bodies with multiple statements require braces')
+
+
+def CheckTrailingSemicolon(filename, clean_lines, linenum, error):
+  """Looks for redundant trailing semicolon.
+
+  Args:
+    filename: The name of the current file.
+    clean_lines: A CleansedLines instance containing the file.
+    linenum: The number of the line to check.
+    error: The function to call with any errors found.
+  """
+
+  line = clean_lines.elided[linenum]
+
+  # Block bodies should not be followed by a semicolon.  Due to C++11
+  # brace initialization, there are more places where semicolons are
+  # required than not, so we use a whitelist approach to check these
+  # rather than a blacklist.  These are the places where "};" should
+  # be replaced by just "}":
+  # 1. Some flavor of block following closing parenthesis:
+  #    for (;;) {};
+  #    while (...) {};
+  #    switch (...) {};
+  #    Function(...) {};
+  #    if (...) {};
+  #    if (...) else if (...) {};
+  #
+  # 2. else block:
+  #    if (...) else {};
+  #
+  # 3. const member function:
+  #    Function(...) const {};
+  #
+  # 4. Block following some statement:
+  #    x = 42;
+  #    {};
+  #
+  # 5. Block at the beginning of a function:
+  #    Function(...) {
+  #      {};
+  #    }
+  #
+  #    Note that naively checking for the preceding "{" will also match
+  #    braces inside multi-dimensional arrays, but this is fine since
+  #    that expression will not contain semicolons.
+  #
+  # 6. Block following another block:
+  #    while (true) {}
+  #    {};
+  #
+  # 7. End of namespaces:
+  #    namespace {};
+  #
+  #    These semicolons seems far more common than other kinds of
+  #    redundant semicolons, possibly due to people converting classes
+  #    to namespaces.  For now we do not warn for this case.
+  #
+  # Try matching case 1 first.
+  match = Match(r'^(.*\)\s*)\{', line)
+  if match:
+    # Matched closing parenthesis (case 1).  Check the token before the
+    # matching opening parenthesis, and don't warn if it looks like a
+    # macro.  This avoids these false positives:
+    #  - macro that defines a base class
+    #  - multi-line macro that defines a base class
+    #  - macro that defines the whole class-head
+    #
+    # But we still issue warnings for macros that we know are safe to
+    # warn, specifically:
+    #  - TEST, TEST_F, TEST_P, MATCHER, MATCHER_P
+    #  - TYPED_TEST
+    #  - INTERFACE_DEF
+    #  - EXCLUSIVE_LOCKS_REQUIRED, SHARED_LOCKS_REQUIRED, LOCKS_EXCLUDED:
+    #
+    # We implement a whitelist of safe macros instead of a blacklist of
+    # unsafe macros, even though the latter appears less frequently in
+    # google code and would have been easier to implement.  This is because
+    # the downside for getting the whitelist wrong means some extra
+    # semicolons, while the downside for getting the blacklist wrong
+    # would result in compile errors.
+    #
+    # In addition to macros, we also don't want to warn on compound
+    # literals and lambdas.
+    closing_brace_pos = match.group(1).rfind(')')
+    opening_parenthesis = ReverseCloseExpression(
+        clean_lines, linenum, closing_brace_pos)
+    if opening_parenthesis[2] > -1:
+      line_prefix = opening_parenthesis[0][0:opening_parenthesis[2]]
+      macro = Search(r'\b([A-Z_]+)\s*$', line_prefix)
+      func = Match(r'^(.*\])\s*$', line_prefix)
+      if ((macro and
+           macro.group(1) not in (
+               'TEST', 'TEST_F', 'MATCHER', 'MATCHER_P', 'TYPED_TEST',
+               'EXCLUSIVE_LOCKS_REQUIRED', 'SHARED_LOCKS_REQUIRED',
+               'LOCKS_EXCLUDED', 'INTERFACE_DEF')) or
+          (func and not Search(r'\boperator\s*\[\s*\]', func.group(1))) or
+          Search(r'\s+=\s*$', line_prefix)):
+        match = None
+    if (match and
+        opening_parenthesis[1] > 1 and
+        Search(r'\]\s*$', clean_lines.elided[opening_parenthesis[1] - 1])):
+      # Multi-line lambda-expression
+      match = None
+
+  else:
+    # Try matching cases 2-3.
+    match = Match(r'^(.*(?:else|\)\s*const)\s*)\{', line)
+    if not match:
+      # Try matching cases 4-6.  These are always matched on separate lines.
+      #
+      # Note that we can't simply concatenate the previous line to the
+      # current line and do a single match, otherwise we may output
+      # duplicate warnings for the blank line case:
+      #   if (cond) {
+      #     // blank line
+      #   }
+      prevline = GetPreviousNonBlankLine(clean_lines, linenum)[0]
+      if prevline and Search(r'[;{}]\s*$', prevline):
+        match = Match(r'^(\s*)\{', line)
+
+  # Check matching closing brace
+  if match:
+    (endline, endlinenum, endpos) = CloseExpression(
+        clean_lines, linenum, len(match.group(1)))
+    if endpos > -1 and Match(r'^\s*;', endline[endpos:]):
+      # Current {} pair is eligible for semicolon check, and we have found
+      # the redundant semicolon, output warning here.
+      #
+      # Note: because we are scanning forward for opening braces, and
+      # outputting warnings for the matching closing brace, if there are
+      # nested blocks with trailing semicolons, we will get the error
+      # messages in reversed order.
+      error(filename, endlinenum, 'readability/braces', 4,
+            "You don't need a ; after a }")
+
+
+def CheckEmptyBlockBody(filename, clean_lines, linenum, error):
+  """Look for empty loop/conditional body with only a single semicolon.
+
+  Args:
+    filename: The name of the current file.
+    clean_lines: A CleansedLines instance containing the file.
+    linenum: The number of the line to check.
+    error: The function to call with any errors found.
+  """
+
+  # Search for loop keywords at the beginning of the line.  Because only
+  # whitespaces are allowed before the keywords, this will also ignore most
+  # do-while-loops, since those lines should start with closing brace.
+  #
+  # We also check "if" blocks here, since an empty conditional block
+  # is likely an error.
+  line = clean_lines.elided[linenum]
+  matched = Match(r'\s*(for|while|if)\s*\(', line)
+  if matched:
+    # Find the end of the conditional expression
+    (end_line, end_linenum, end_pos) = CloseExpression(
+        clean_lines, linenum, line.find('('))
+
+    # Output warning if what follows the condition expression is a semicolon.
+    # No warning for all other cases, including whitespace or newline, since we
+    # have a separate check for semicolons preceded by whitespace.
+    if end_pos >= 0 and Match(r';', end_line[end_pos:]):
+      if matched.group(1) == 'if':
+        error(filename, end_linenum, 'whitespace/empty_conditional_body', 5,
+              'Empty conditional bodies should use {}')
+      elif matched.group(1) != "while":
+        error(filename, end_linenum, 'whitespace/empty_loop_body', 5,
+              'Empty loop bodies should use {} or continue')
+
+
+def FindCheckMacro(line):
+  """Find a replaceable CHECK-like macro.
+
+  Args:
+    line: line to search on.
+  Returns:
+    (macro name, start position), or (None, -1) if no replaceable
+    macro is found.
+  """
+  for macro in _CHECK_MACROS:
+    i = line.find(macro)
+    if i >= 0:
+      # Find opening parenthesis.  Do a regular expression match here
+      # to make sure that we are matching the expected CHECK macro, as
+      # opposed to some other macro that happens to contain the CHECK
+      # substring.
+      matched = Match(r'^(.*\b' + macro + r'\s*)\(', line)
+      if not matched:
+        continue
+      return (macro, len(matched.group(1)))
+  return (None, -1)
+
+
+def CheckCheck(filename, clean_lines, linenum, error):
+  """Checks the use of CHECK and EXPECT macros.
+
+  Args:
+    filename: The name of the current file.
+    clean_lines: A CleansedLines instance containing the file.
+    linenum: The number of the line to check.
+    error: The function to call with any errors found.
+  """
+
+  # Decide the set of replacement macros that should be suggested
+  lines = clean_lines.elided
+  (check_macro, start_pos) = FindCheckMacro(lines[linenum])
+  if not check_macro:
+    return
+
+  # Find end of the boolean expression by matching parentheses
+  (last_line, end_line, end_pos) = CloseExpression(
+      clean_lines, linenum, start_pos)
+  if end_pos < 0:
+    return
+  if linenum == end_line:
+    expression = lines[linenum][start_pos + 1:end_pos - 1]
+  else:
+    expression = lines[linenum][start_pos + 1:]
+    for i in xrange(linenum + 1, end_line):
+      expression += lines[i]
+    expression += last_line[0:end_pos - 1]
+
+  # Parse expression so that we can take parentheses into account.
+  # This avoids false positives for inputs like "CHECK((a < 4) == b)",
+  # which is not replaceable by CHECK_LE.
+  lhs = ''
+  rhs = ''
+  operator = None
+  while expression:
+    matched = Match(r'^\s*(<<|<<=|>>|>>=|->\*|->|&&|\|\||'
+                    r'==|!=|>=|>|<=|<|\()(.*)$', expression)
+    if matched:
+      token = matched.group(1)
+      if token == '(':
+        # Parenthesized operand
+        expression = matched.group(2)
+        (end, _) = FindEndOfExpressionInLine(expression, 0, ['('])
+        if end < 0:
+          return  # Unmatched parenthesis
+        lhs += '(' + expression[0:end]
+        expression = expression[end:]
+      elif token in ('&&', '||'):
+        # Logical and/or operators.  This means the expression
+        # contains more than one term, for example:
+        #   CHECK(42 < a && a < b);
+        #
+        # These are not replaceable with CHECK_LE, so bail out early.
+        return
+      elif token in ('<<', '<<=', '>>', '>>=', '->*', '->'):
+        # Non-relational operator
+        lhs += token
+        expression = matched.group(2)
+      else:
+        # Relational operator
+        operator = token
+        rhs = matched.group(2)
+        break
+    else:
+      # Unparenthesized operand.  Instead of appending to lhs one character
+      # at a time, we do another regular expression match to consume several
+      # characters at once if possible.  Trivial benchmark shows that this
+      # is more efficient when the operands are longer than a single
+      # character, which is generally the case.
+      matched = Match(r'^([^-=!<>()&|]+)(.*)$', expression)
+      if not matched:
+        matched = Match(r'^(\s*\S)(.*)$', expression)
+        if not matched:
+          break
+      lhs += matched.group(1)
+      expression = matched.group(2)
+
+  # Only apply checks if we got all parts of the boolean expression
+  if not (lhs and operator and rhs):
+    return
+
+  # Check that rhs do not contain logical operators.  We already know
+  # that lhs is fine since the loop above parses out && and ||.
+  if rhs.find('&&') > -1 or rhs.find('||') > -1:
+    return
+
+  # At least one of the operands must be a constant literal.  This is
+  # to avoid suggesting replacements for unprintable things like
+  # CHECK(variable != iterator)
+  #
+  # The following pattern matches decimal, hex integers, strings, and
+  # characters (in that order).
+  lhs = lhs.strip()
+  rhs = rhs.strip()
+  match_constant = r'^([-+]?(\d+|0[xX][0-9a-fA-F]+)[lLuU]{0,3}|".*"|\'.*\')$'
+  if Match(match_constant, lhs) or Match(match_constant, rhs):
+    # Note: since we know both lhs and rhs, we can provide a more
+    # descriptive error message like:
+    #   Consider using CHECK_EQ(x, 42) instead of CHECK(x == 42)
+    # Instead of:
+    #   Consider using CHECK_EQ instead of CHECK(a == b)
+    #
+    # We are still keeping the less descriptive message because if lhs
+    # or rhs gets long, the error message might become unreadable.
+    error(filename, linenum, 'readability/check', 2,
+          'Consider using %s instead of %s(a %s b)' % (
+              _CHECK_REPLACEMENT[check_macro][operator],
+              check_macro, operator))
+
+
+def CheckAltTokens(filename, clean_lines, linenum, error):
+  """Check alternative keywords being used in boolean expressions.
+
+  Args:
+    filename: The name of the current file.
+    clean_lines: A CleansedLines instance containing the file.
+    linenum: The number of the line to check.
+    error: The function to call with any errors found.
+  """
+  line = clean_lines.elided[linenum]
+
+  # Avoid preprocessor lines
+  if Match(r'^\s*#', line):
+    return
+
+  # Last ditch effort to avoid multi-line comments.  This will not help
+  # if the comment started before the current line or ended after the
+  # current line, but it catches most of the false positives.  At least,
+  # it provides a way to workaround this warning for people who use
+  # multi-line comments in preprocessor macros.
+  #
+  # TODO(unknown): remove this once cpplint has better support for
+  # multi-line comments.
+  if line.find('/*') >= 0 or line.find('*/') >= 0:
+    return
+
+  for match in _ALT_TOKEN_REPLACEMENT_PATTERN.finditer(line):
+    error(filename, linenum, 'readability/alt_tokens', 2,
+          'Use operator %s instead of %s' % (
+              _ALT_TOKEN_REPLACEMENT[match.group(1)], match.group(1)))
+
+
+def GetLineWidth(line):
+  """Determines the width of the line in column positions.
+
+  Args:
+    line: A string, which may be a Unicode string.
+
+  Returns:
+    The width of the line in column positions, accounting for Unicode
+    combining characters and wide characters.
+  """
+  if isinstance(line, unicode):
+    width = 0
+    for uc in unicodedata.normalize('NFC', line):
+      if unicodedata.east_asian_width(uc) in ('W', 'F'):
+        width += 2
+      elif not unicodedata.combining(uc):
+        width += 1
+    return width
+  else:
+    return len(line)
+
+
+def CheckStyle(filename, clean_lines, linenum, file_extension, nesting_state,
+               error):
+  """Checks rules from the 'C++ style rules' section of cppguide.html.
+
+  Most of these rules are hard to test (naming, comment style), but we
+  do what we can.  In particular we check for 2-space indents, line lengths,
+  tab usage, spaces inside code, etc.
+
+  Args:
+    filename: The name of the current file.
+    clean_lines: A CleansedLines instance containing the file.
+    linenum: The number of the line to check.
+    file_extension: The extension (without the dot) of the filename.
+    nesting_state: A NestingState instance which maintains information about
+                   the current stack of nested blocks being parsed.
+    error: The function to call with any errors found.
+  """
+
+  # Don't use "elided" lines here, otherwise we can't check commented lines.
+  # Don't want to use "raw" either, because we don't want to check inside C++11
+  # raw strings,
+  raw_lines = clean_lines.lines_without_raw_strings
+  line = raw_lines[linenum]
+
+  if line.find('\t') != -1:
+    error(filename, linenum, 'whitespace/tab', 1,
+          'Tab found; better to use spaces')
+
+  # One or three blank spaces at the beginning of the line is weird; it's
+  # hard to reconcile that with 2-space indents.
+  # NOTE: here are the conditions rob pike used for his tests.  Mine aren't
+  # as sophisticated, but it may be worth becoming so:  RLENGTH==initial_spaces
+  # if(RLENGTH > 20) complain = 0;
+  # if(match($0, " +(error|private|public|protected):")) complain = 0;
+  # if(match(prev, "&& *$")) complain = 0;
+  # if(match(prev, "\\|\\| *$")) complain = 0;
+  # if(match(prev, "[\",=><] *$")) complain = 0;
+  # if(match($0, " <<")) complain = 0;
+  # if(match(prev, " +for \\(")) complain = 0;
+  # if(prevodd && match(prevprev, " +for \\(")) complain = 0;
+  scope_or_label_pattern = r'\s*\w+\s*:\s*\\?$'
+  classinfo = nesting_state.InnermostClass()
+  initial_spaces = 0
+  cleansed_line = clean_lines.elided[linenum]
+  while initial_spaces < len(line) and line[initial_spaces] == ' ':
+    initial_spaces += 1
+  if line and line[-1].isspace():
+    error(filename, linenum, 'whitespace/end_of_line', 4,
+          'Line ends in whitespace.  Consider deleting these extra spaces.')
+  # There are certain situations we allow one space, notably for
+  # section labels, and also lines containing multi-line raw strings.
+  elif ((initial_spaces == 1 or initial_spaces == 3) and
+        not Match(scope_or_label_pattern, cleansed_line) and
+        not (clean_lines.raw_lines[linenum] != line and
+             Match(r'^\s*""', line))):
+    error(filename, linenum, 'whitespace/indent', 3,
+          'Weird number of spaces at line-start.  '
+          'Are you using a 2-space indent?')
+
+  # Check if the line is a header guard.
+  is_header_guard = False
+  if file_extension == 'h':
+    cppvar = GetHeaderGuardCPPVariable(filename)
+    if (line.startswith('#ifndef %s' % cppvar) or
+        line.startswith('#define %s' % cppvar) or
+        line.startswith('#endif  // %s' % cppvar)):
+      is_header_guard = True
+  # #include lines and header guards can be long, since there's no clean way to
+  # split them.
+  #
+  # URLs can be long too.  It's possible to split these, but it makes them
+  # harder to cut&paste.
+  #
+  # The "$Id:...$" comment may also get very long without it being the
+  # developers fault.
+  if (not line.startswith('#include') and not is_header_guard and
+      not Match(r'^\s*//.*http(s?)://\S*$', line) and
+      not Match(r'^// \$Id:.*#[0-9]+ \$$', line)):
+    line_width = GetLineWidth(line)
+    extended_length = int((_line_length * 1.25))
+    if line_width > extended_length:
+      error(filename, linenum, 'whitespace/line_length', 4,
+            'Lines should very rarely be longer than %i characters' %
+            extended_length)
+    elif line_width > _line_length:
+      error(filename, linenum, 'whitespace/line_length', 2,
+            'Lines should be <= %i characters long' % _line_length)
+
+  if (cleansed_line.count(';') > 1 and
+      # for loops are allowed two ;'s (and may run over two lines).
+      cleansed_line.find('for') == -1 and
+      (GetPreviousNonBlankLine(clean_lines, linenum)[0].find('for') == -1 or
+       GetPreviousNonBlankLine(clean_lines, linenum)[0].find(';') != -1) and
+      # It's ok to have many commands in a switch case that fits in 1 line
+      not ((cleansed_line.find('case ') != -1 or
+            cleansed_line.find('default:') != -1) and
+           cleansed_line.find('break;') != -1)):
+    error(filename, linenum, 'whitespace/newline', 0,
+          'More than one command on the same line')
+
+  # Some more style checks
+  CheckBraces(filename, clean_lines, linenum, error)
+  CheckTrailingSemicolon(filename, clean_lines, linenum, error)
+  CheckEmptyBlockBody(filename, clean_lines, linenum, error)
+  CheckAccess(filename, clean_lines, linenum, nesting_state, error)
+  CheckSpacing(filename, clean_lines, linenum, nesting_state, error)
+  CheckOperatorSpacing(filename, clean_lines, linenum, error)
+  CheckParenthesisSpacing(filename, clean_lines, linenum, error)
+  CheckCommaSpacing(filename, clean_lines, linenum, error)
+  CheckBracesSpacing(filename, clean_lines, linenum, error)
+  CheckSpacingForFunctionCall(filename, clean_lines, linenum, error)
+  CheckRValueReference(filename, clean_lines, linenum, nesting_state, error)
+  CheckCheck(filename, clean_lines, linenum, error)
+  CheckAltTokens(filename, clean_lines, linenum, error)
+  classinfo = nesting_state.InnermostClass()
+  if classinfo:
+    CheckSectionSpacing(filename, clean_lines, classinfo, linenum, error)
+
+
+_RE_PATTERN_INCLUDE_NEW_STYLE = re.compile(r'#include +"[^/]+\.h"')
+_RE_PATTERN_INCLUDE = re.compile(r'^\s*#\s*include\s*([<"])([^>"]*)[>"].*$')
+# Matches the first component of a filename delimited by -s and _s. That is:
+#  _RE_FIRST_COMPONENT.match('foo').group(0) == 'foo'
+#  _RE_FIRST_COMPONENT.match('foo.cc').group(0) == 'foo'
+#  _RE_FIRST_COMPONENT.match('foo-bar_baz.cc').group(0) == 'foo'
+#  _RE_FIRST_COMPONENT.match('foo_bar-baz.cc').group(0) == 'foo'
+_RE_FIRST_COMPONENT = re.compile(r'^[^-_.]+')
+
+
+def _DropCommonSuffixes(filename):
+  """Drops common suffixes like _test.cc or -inl.h from filename.
+
+  For example:
+    >>> _DropCommonSuffixes('foo/foo-inl.h')
+    'foo/foo'
+    >>> _DropCommonSuffixes('foo/bar/foo.cc')
+    'foo/bar/foo'
+    >>> _DropCommonSuffixes('foo/foo_internal.h')
+    'foo/foo'
+    >>> _DropCommonSuffixes('foo/foo_unusualinternal.h')
+    'foo/foo_unusualinternal'
+
+  Args:
+    filename: The input filename.
+
+  Returns:
+    The filename with the common suffix removed.
+  """
+  for suffix in ('test.cc', 'regtest.cc', 'unittest.cc',
+                 'inl.h', 'impl.h', 'internal.h'):
+    if (filename.endswith(suffix) and len(filename) > len(suffix) and
+        filename[-len(suffix) - 1] in ('-', '_')):
+      return filename[:-len(suffix) - 1]
+  return os.path.splitext(filename)[0]
+
+
+def _IsTestFilename(filename):
+  """Determines if the given filename has a suffix that identifies it as a test.
+
+  Args:
+    filename: The input filename.
+
+  Returns:
+    True if 'filename' looks like a test, False otherwise.
+  """
+  if (filename.endswith('_test.cc') or
+      filename.endswith('_unittest.cc') or
+      filename.endswith('_regtest.cc')):
+    return True
+  else:
+    return False
+
+
+def _ClassifyInclude(fileinfo, include, is_system):
+  """Figures out what kind of header 'include' is.
+
+  Args:
+    fileinfo: The current file cpplint is running over. A FileInfo instance.
+    include: The path to a #included file.
+    is_system: True if the #include used <> rather than "".
+
+  Returns:
+    One of the _XXX_HEADER constants.
+
+  For example:
+    >>> _ClassifyInclude(FileInfo('foo/foo.cc'), 'stdio.h', True)
+    _C_SYS_HEADER
+    >>> _ClassifyInclude(FileInfo('foo/foo.cc'), 'string', True)
+    _CPP_SYS_HEADER
+    >>> _ClassifyInclude(FileInfo('foo/foo.cc'), 'foo/foo.h', False)
+    _LIKELY_MY_HEADER
+    >>> _ClassifyInclude(FileInfo('foo/foo_unknown_extension.cc'),
+    ...                  'bar/foo_other_ext.h', False)
+    _POSSIBLE_MY_HEADER
+    >>> _ClassifyInclude(FileInfo('foo/foo.cc'), 'foo/bar.h', False)
+    _OTHER_HEADER
+  """
+  # This is a list of all standard c++ header files, except
+  # those already checked for above.
+  is_cpp_h = include in _CPP_HEADERS or include.find(".hh") > 0
+
+  if is_system:
+    if is_cpp_h:
+      return _CPP_SYS_HEADER
+    else:
+      return _C_SYS_HEADER
+
+  # If the target file and the include we're checking share a
+  # basename when we drop common extensions, and the include
+  # lives in . , then it's likely to be owned by the target file.
+  target_dir, target_base = (
+      os.path.split(_DropCommonSuffixes(fileinfo.RepositoryName())))
+  include_dir, include_base = os.path.split(_DropCommonSuffixes(include))
+  if target_base == include_base and (
+      include_dir == target_dir or
+      include_dir == os.path.normpath(target_dir + '/../public')):
+    return _LIKELY_MY_HEADER
+
+  # If the target and include share some initial basename
+  # component, it's possible the target is implementing the
+  # include, so it's allowed to be first, but we'll never
+  # complain if it's not there.
+  target_first_component = _RE_FIRST_COMPONENT.match(target_base)
+  include_first_component = _RE_FIRST_COMPONENT.match(include_base)
+  if (target_first_component and include_first_component and
+      target_first_component.group(0) ==
+      include_first_component.group(0)):
+    return _POSSIBLE_MY_HEADER
+
+  return _OTHER_HEADER
+
+
+
+def CheckIncludeLine(filename, clean_lines, linenum, include_state, error):
+  """Check rules that are applicable to #include lines.
+
+  Strings on #include lines are NOT removed from elided line, to make
+  certain tasks easier. However, to prevent false positives, checks
+  applicable to #include lines in CheckLanguage must be put here.
+
+  Args:
+    filename: The name of the current file.
+    clean_lines: A CleansedLines instance containing the file.
+    linenum: The number of the line to check.
+    include_state: An _IncludeState instance in which the headers are inserted.
+    error: The function to call with any errors found.
+  """
+  fileinfo = FileInfo(filename)
+  line = clean_lines.lines[linenum]
+
+  # "include" should use the new style "foo/bar.h" instead of just "bar.h"
+  if _RE_PATTERN_INCLUDE_NEW_STYLE.search(line):
+    error(filename, linenum, 'build/include', 4,
+          'Include the directory when naming .h files')
+
+  # we shouldn't include a file more than once. actually, there are a
+  # handful of instances where doing so is okay, but in general it's
+  # not.
+  match = _RE_PATTERN_INCLUDE.search(line)
+  if match:
+    include = match.group(2)
+    is_system = (match.group(1) == '<')
+    if include in include_state:
+      error(filename, linenum, 'build/include', 4,
+            '"%s" already included at %s:%s' %
+            (include, filename, include_state[include]))
+    else:
+      include_state[include] = linenum
+
+      # We want to ensure that headers appear in the right order:
+      # 1) for foo.cc, foo.h  (preferred location)
+      # 2) c system files
+      # 3) cpp system files
+      # 4) for foo.cc, foo.h  (deprecated location)
+      # 5) other google headers
+      #
+      # We classify each include statement as one of those 5 types
+      # using a number of techniques. The include_state object keeps
+      # track of the highest type seen, and complains if we see a
+      # lower type after that.
+      error_message = include_state.CheckNextIncludeOrder(
+          _ClassifyInclude(fileinfo, include, is_system))
+      if error_message:
+        error(filename, linenum, 'build/include_order', 4,
+              '%s. Should be: %s.h, c system, c++ system, other.' %
+              (error_message, fileinfo.BaseName()))
+      canonical_include = include_state.CanonicalizeAlphabeticalOrder(include)
+      if not include_state.IsInAlphabeticalOrder(
+          clean_lines, linenum, canonical_include):
+        error(filename, linenum, 'build/include_alpha', 4,
+              'Include "%s" not in alphabetical order' % include)
+      include_state.SetLastHeader(canonical_include)
+
+  # Look for any of the stream classes that are part of standard C++.
+  match = _RE_PATTERN_INCLUDE.match(line)
+  if match:
+    include = match.group(2)
+    if Match(r'(f|ind|io|i|o|parse|pf|stdio|str|)?stream$', include):
+      # Many unit tests use cout, so we exempt them.
+      if not _IsTestFilename(filename):
+        # Suggest a different header for ostream
+        if include == 'ostream':
+          error(filename, linenum, 'readability/streams', 3,
+                'For logging, include "base/logging.h" instead of <ostream>.')
+        # else:
+        #   error(filename, linenum, 'readability/streams', 3,
+        #         'Streams are highly discouraged.')
+
+
+def _GetTextInside(text, start_pattern):
+  r"""Retrieves all the text between matching open and close parentheses.
+
+  Given a string of lines and a regular expression string, retrieve all the text
+  following the expression and between opening punctuation symbols like
+  (, [, or {, and the matching close-punctuation symbol. This properly nested
+  occurrences of the punctuations, so for the text like
+    printf(a(), b(c()));
+  a call to _GetTextInside(text, r'printf\(') will return 'a(), b(c())'.
+  start_pattern must match string having an open punctuation symbol at the end.
+
+  Args:
+    text: The lines to extract text. Its comments and strings must be elided.
+           It can be single line and can span multiple lines.
+    start_pattern: The regexp string indicating where to start extracting
+                   the text.
+  Returns:
+    The extracted text.
+    None if either the opening string or ending punctuation could not be found.
+  """
+  # TODO(unknown): Audit cpplint.py to see what places could be profitably
+  # rewritten to use _GetTextInside (and use inferior regexp matching today).
+
+  # Give opening punctuations to get the matching close-punctuations.
+  matching_punctuation = {'(': ')', '{': '}', '[': ']'}
+  closing_punctuation = set(matching_punctuation.itervalues())
+
+  # Find the position to start extracting text.
+  match = re.search(start_pattern, text, re.M)
+  if not match:  # start_pattern not found in text.
+    return None
+  start_position = match.end(0)
+
+  assert start_position > 0, (
+      'start_pattern must ends with an opening punctuation.')
+  assert text[start_position - 1] in matching_punctuation, (
+      'start_pattern must ends with an opening punctuation.')
+  # Stack of closing punctuations we expect to have in text after position.
+  punctuation_stack = [matching_punctuation[text[start_position - 1]]]
+  position = start_position
+  while punctuation_stack and position < len(text):
+    if text[position] == punctuation_stack[-1]:
+      punctuation_stack.pop()
+    elif text[position] in closing_punctuation:
+      # A closing punctuation without matching opening punctuations.
+      return None
+    elif text[position] in matching_punctuation:
+      punctuation_stack.append(matching_punctuation[text[position]])
+    position += 1
+  if punctuation_stack:
+    # Opening punctuations left without matching close-punctuations.
+    return None
+  # punctuations match.
+  return text[start_position:position - 1]
+
+
+# Patterns for matching call-by-reference parameters.
+#
+# Supports nested templates up to 2 levels deep using this messy pattern:
+#   < (?: < (?: < [^<>]*
+#               >
+#           |   [^<>] )*
+#         >
+#     |   [^<>] )*
+#   >
+_RE_PATTERN_IDENT = r'[_a-zA-Z]\w*'  # =~ [[:alpha:]][[:alnum:]]*
+_RE_PATTERN_TYPE = (
+    r'(?:const\s+)?(?:typename\s+|class\s+|struct\s+|union\s+|enum\s+)?'
+    r'(?:\w|'
+    r'\s*<(?:<(?:<[^<>]*>|[^<>])*>|[^<>])*>|'
+    r'::)+')
+# A call-by-reference parameter ends with '& identifier'.
+_RE_PATTERN_REF_PARAM = re.compile(
+    r'(' + _RE_PATTERN_TYPE + r'(?:\s*(?:\bconst\b|[*]))*\s*'
+    r'&\s*' + _RE_PATTERN_IDENT + r')\s*(?:=[^,()]+)?[,)]')
+# A call-by-const-reference parameter either ends with 'const& identifier'
+# or looks like 'const type& identifier' when 'type' is atomic.
+_RE_PATTERN_CONST_REF_PARAM = (
+    r'(?:.*\s*\bconst\s*&\s*' + _RE_PATTERN_IDENT +
+    r'|const\s+' + _RE_PATTERN_TYPE + r'\s*&\s*' + _RE_PATTERN_IDENT + r')')
+
+
+def CheckLanguage(filename, clean_lines, linenum, file_extension,
+                  include_state, nesting_state, error):
+  """Checks rules from the 'C++ language rules' section of cppguide.html.
+
+  Some of these rules are hard to test (function overloading, using
+  uint32 inappropriately), but we do the best we can.
+
+  Args:
+    filename: The name of the current file.
+    clean_lines: A CleansedLines instance containing the file.
+    linenum: The number of the line to check.
+    file_extension: The extension (without the dot) of the filename.
+    include_state: An _IncludeState instance in which the headers are inserted.
+    nesting_state: A NestingState instance which maintains information about
+                   the current stack of nested blocks being parsed.
+    error: The function to call with any errors found.
+  """
+  # If the line is empty or consists of entirely a comment, no need to
+  # check it.
+  line = clean_lines.elided[linenum]
+  if not line:
+    return
+
+  match = _RE_PATTERN_INCLUDE.search(line)
+  if match:
+    CheckIncludeLine(filename, clean_lines, linenum, include_state, error)
+    return
+
+  # Reset include state across preprocessor directives.  This is meant
+  # to silence warnings for conditional includes.
+  if Match(r'^\s*#\s*(?:ifdef|elif|else|endif)\b', line):
+    include_state.ResetSection()
+
+  # Make Windows paths like Unix.
+  fullname = os.path.abspath(filename).replace('\\', '/')
+  
+  # Perform other checks now that we are sure that this is not an include line
+  CheckCasts(filename, clean_lines, linenum, error)
+  CheckGlobalStatic(filename, clean_lines, linenum, error)
+  CheckPrintf(filename, clean_lines, linenum, error)
+
+  if file_extension == 'h':
+    # TODO(unknown): check that 1-arg constructors are explicit.
+    #                How to tell it's a constructor?
+    #                (handled in CheckForNonStandardConstructs for now)
+    # TODO(unknown): check that classes have DISALLOW_EVIL_CONSTRUCTORS
+    #                (level 1 error)
+    pass
+
+  # Check if people are using the verboten C basic types.  The only exception
+  # we regularly allow is "unsigned short port" for port.
+  if Search(r'\bshort port\b', line):
+    if not Search(r'\bunsigned short port\b', line):
+      error(filename, linenum, 'runtime/int', 4,
+            'Use "unsigned short" for ports, not "short"')
+  else:
+    match = Search(r'\b(short|long(?! +double)|long long)\b', line)
+    if match:
+      error(filename, linenum, 'runtime/int', 4,
+            'Use int16/int64/etc, rather than the C type %s' % match.group(1))
+
+  # Check if some verboten operator overloading is going on
+  # TODO(unknown): catch out-of-line unary operator&:
+  #   class X {};
+  #   int operator&(const X& x) { return 42; }  // unary operator&
+  # The trick is it's hard to tell apart from binary operator&:
+  #   class Y { int operator&(const Y& x) { return 23; } }; // binary operator&
+  if Search(r'\boperator\s*&\s*\(\s*\)', line):
+    error(filename, linenum, 'runtime/operator', 4,
+          'Unary operator& is dangerous.  Do not use it.')
+
+  # Check for suspicious usage of "if" like
+  # } if (a == b) {
+  if Search(r'\}\s*if\s*\(', line):
+    error(filename, linenum, 'readability/braces', 4,
+          'Did you mean "else if"? If not, start a new line for "if".')
+
+  # Check for potential format string bugs like printf(foo).
+  # We constrain the pattern not to pick things like DocidForPrintf(foo).
+  # Not perfect but it can catch printf(foo.c_str()) and printf(foo->c_str())
+  # TODO(unknown): Catch the following case. Need to change the calling
+  # convention of the whole function to process multiple line to handle it.
+  #   printf(
+  #       boy_this_is_a_really_long_variable_that_cannot_fit_on_the_prev_line);
+  printf_args = _GetTextInside(line, r'(?i)\b(string)?printf\s*\(')
+  if printf_args:
+    match = Match(r'([\w.\->()]+)$', printf_args)
+    if match and match.group(1) != '__VA_ARGS__':
+      function_name = re.search(r'\b((?:string)?printf)\s*\(',
+                                line, re.I).group(1)
+      error(filename, linenum, 'runtime/printf', 4,
+            'Potential format string bug. Do %s("%%s", %s) instead.'
+            % (function_name, match.group(1)))
+
+  # Check for potential memset bugs like memset(buf, sizeof(buf), 0).
+  match = Search(r'memset\s*\(([^,]*),\s*([^,]*),\s*0\s*\)', line)
+  if match and not Match(r"^''|-?[0-9]+|0x[0-9A-Fa-f]$", match.group(2)):
+    error(filename, linenum, 'runtime/memset', 4,
+          'Did you mean "memset(%s, 0, %s)"?'
+          % (match.group(1), match.group(2)))
+
+  # if Search(r'\busing namespace\b', line):
+  #   error(filename, linenum, 'build/namespaces', 5,
+  #         'Do not use namespace using-directives.  '
+  #         'Use using-declarations instead.')
+
+  # Detect variable-length arrays.
+  match = Match(r'\s*(.+::)?(\w+) [a-z]\w*\[(.+)];', line)
+  if (match and match.group(2) != 'return' and match.group(2) != 'delete' and
+      match.group(3).find(']') == -1):
+    # Split the size using space and arithmetic operators as delimiters.
+    # If any of the resulting tokens are not compile time constants then
+    # report the error.
+    tokens = re.split(r'\s|\+|\-|\*|\/|<<|>>]', match.group(3))
+    is_const = True
+    skip_next = False
+    for tok in tokens:
+      if skip_next:
+        skip_next = False
+        continue
+
+      if Search(r'sizeof\(.+\)', tok): continue
+      if Search(r'arraysize\(\w+\)', tok): continue
+
+      tok = tok.lstrip('(')
+      tok = tok.rstrip(')')
+      if not tok: continue
+      if Match(r'\d+', tok): continue
+      if Match(r'0[xX][0-9a-fA-F]+', tok): continue
+      if Match(r'k[A-Z0-9]\w*', tok): continue
+      if Match(r'(.+::)?k[A-Z0-9]\w*', tok): continue
+      if Match(r'(.+::)?[A-Z][A-Z0-9_]*', tok): continue
+      # A catch all for tricky sizeof cases, including 'sizeof expression',
+      # 'sizeof(*type)', 'sizeof(const type)', 'sizeof(struct StructName)'
+      # requires skipping the next token because we split on ' ' and '*'.
+      if tok.startswith('sizeof'):
+        skip_next = True
+        continue
+      is_const = False
+      break
+    if not is_const:
+      error(filename, linenum, 'runtime/arrays', 1,
+            'Do not use variable-length arrays.  Use an appropriately named '
+            "('k' followed by CamelCase) compile-time constant for the size.")
+
+  # If DISALLOW_EVIL_CONSTRUCTORS, DISALLOW_COPY_AND_ASSIGN, or
+  # DISALLOW_IMPLICIT_CONSTRUCTORS is present, then it should be the last thing
+  # in the class declaration.
+  match = Match(
+      (r'\s*'
+       r'(DISALLOW_(EVIL_CONSTRUCTORS|COPY_AND_ASSIGN|IMPLICIT_CONSTRUCTORS))'
+       r'\(.*\);$'),
+      line)
+  if match and linenum + 1 < clean_lines.NumLines():
+    next_line = clean_lines.elided[linenum + 1]
+    # We allow some, but not all, declarations of variables to be present
+    # in the statement that defines the class.  The [\w\*,\s]* fragment of
+    # the regular expression below allows users to declare instances of
+    # the class or pointers to instances, but not less common types such
+    # as function pointers or arrays.  It's a tradeoff between allowing
+    # reasonable code and avoiding trying to parse more C++ using regexps.
+    if not Search(r'^\s*}[\w\*,\s]*;', next_line):
+      error(filename, linenum, 'readability/constructors', 3,
+            match.group(1) + ' should be the last thing in the class')
+
+  # Check for use of unnamed namespaces in header files.  Registration
+  # macros are typically OK, so we allow use of "namespace {" on lines
+  # that end with backslashes.
+  if (file_extension == 'h'
+      and Search(r'\bnamespace\s*{', line)
+      and line[-1] != '\\'):
+    error(filename, linenum, 'build/namespaces', 4,
+          'Do not use unnamed namespaces in header files.  See '
+          'http://google-styleguide.googlecode.com/svn/trunk/cppguide.xml#Namespaces'
+          ' for more information.')
+
+
+def CheckGlobalStatic(filename, clean_lines, linenum, error):
+  """Check for unsafe global or static objects.
+
+  Args:
+    filename: The name of the current file.
+    clean_lines: A CleansedLines instance containing the file.
+    linenum: The number of the line to check.
+    error: The function to call with any errors found.
+  """
+  line = clean_lines.elided[linenum]
+
+  # Check for people declaring static/global STL strings at the top level.
+  # This is dangerous because the C++ language does not guarantee that
+  # globals with constructors are initialized before the first access.
+  match = Match(
+      r'((?:|static +)(?:|const +))string +([a-zA-Z0-9_:]+)\b(.*)',
+      line)
+  # Remove false positives:
+  # - String pointers (as opposed to values).
+  #    string *pointer
+  #    const string *pointer
+  #    string const *pointer
+  #    string *const pointer
+  #
+  # - Functions and template specializations.
+  #    string Function<Type>(...
+  #    string Class<Type>::Method(...
+  #
+  # - Operators.  These are matched separately because operator names
+  #   cross non-word boundaries, and trying to match both operators
+  #   and functions at the same time would decrease accuracy of
+  #   matching identifiers.
+  #    string Class::operator*()
+  if (match and
+      not Search(r'\bstring\b(\s+const)?\s*\*\s*(const\s+)?\w', line) and
+      not Search(r'\boperator\W', line) and
+      not Match(r'\s*(<.*>)?(::[a-zA-Z0-9_]+)?\s*\(([^"]|$)', match.group(3))):
+    error(filename, linenum, 'runtime/string', 4,
+          'For a static/global string constant, use a C style string instead: '
+          '"%schar %s[]".' %
+          (match.group(1), match.group(2)))
+
+  if Search(r'\b([A-Za-z0-9_]*_)\(\1\)', line):
+    error(filename, linenum, 'runtime/init', 4,
+          'You seem to be initializing a member variable with itself.')
+
+
+def CheckPrintf(filename, clean_lines, linenum, error):
+  """Check for printf related issues.
+
+  Args:
+    filename: The name of the current file.
+    clean_lines: A CleansedLines instance containing the file.
+    linenum: The number of the line to check.
+    error: The function to call with any errors found.
+  """
+  line = clean_lines.elided[linenum]
+
+  # When snprintf is used, the second argument shouldn't be a literal.
+  match = Search(r'snprintf\s*\(([^,]*),\s*([0-9]*)\s*,', line)
+  if match and match.group(2) != '0':
+    # If 2nd arg is zero, snprintf is used to calculate size.
+    error(filename, linenum, 'runtime/printf', 3,
+          'If you can, use sizeof(%s) instead of %s as the 2nd arg '
+          'to snprintf.' % (match.group(1), match.group(2)))
+
+  # Check if some verboten C functions are being used.
+  if Search(r'\bsprintf\b', line):
+    error(filename, linenum, 'runtime/printf', 5,
+          'Never use sprintf. Use snprintf instead.')
+  match = Search(r'\b(strcpy|strcat)\b', line)
+  if match:
+    error(filename, linenum, 'runtime/printf', 4,
+          'Almost always, snprintf is better than %s' % match.group(1))
+
+
+def IsDerivedFunction(clean_lines, linenum):
+  """Check if current line contains an inherited function.
+
+  Args:
+    clean_lines: A CleansedLines instance containing the file.
+    linenum: The number of the line to check.
+  Returns:
+    True if current line contains a function with "override"
+    virt-specifier.
+  """
+  # Look for leftmost opening parenthesis on current line
+  opening_paren = clean_lines.elided[linenum].find('(')
+  if opening_paren < 0: return False
+
+  # Look for "override" after the matching closing parenthesis
+  line, _, closing_paren = CloseExpression(clean_lines, linenum, opening_paren)
+  return closing_paren >= 0 and Search(r'\boverride\b', line[closing_paren:])
+
+
+def IsInitializerList(clean_lines, linenum):
+  """Check if current line is inside constructor initializer list.
+
+  Args:
+    clean_lines: A CleansedLines instance containing the file.
+    linenum: The number of the line to check.
+  Returns:
+    True if current line appears to be inside constructor initializer
+    list, False otherwise.
+  """
+  for i in xrange(linenum, 1, -1):
+    line = clean_lines.elided[i]
+    if i == linenum:
+      remove_function_body = Match(r'^(.*)\{\s*$', line)
+      if remove_function_body:
+        line = remove_function_body.group(1)
+
+    if Search(r'\s:\s*\w+[({]', line):
+      # A lone colon tend to indicate the start of a constructor
+      # initializer list.  It could also be a ternary operator, which
+      # also tend to appear in constructor initializer lists as
+      # opposed to parameter lists.
+      return True
+    if Search(r'\}\s*,\s*$', line):
+      # A closing brace followed by a comma is probably the end of a
+      # brace-initialized member in constructor initializer list.
+      return True
+    if Search(r'[{};]\s*$', line):
+      # Found one of the following:
+      # - A closing brace or semicolon, probably the end of the previous
+      #   function.
+      # - An opening brace, probably the start of current class or namespace.
+      #
+      # Current line is probably not inside an initializer list since
+      # we saw one of those things without seeing the starting colon.
+      return False
+
+  # Got to the beginning of the file without seeing the start of
+  # constructor initializer list.
+  return False
+
+
+def CheckForNonConstReference(filename, clean_lines, linenum,
+                              nesting_state, error):
+  """Check for non-const references.
+
+  Separate from CheckLanguage since it scans backwards from current
+  line, instead of scanning forward.
+
+  Args:
+    filename: The name of the current file.
+    clean_lines: A CleansedLines instance containing the file.
+    linenum: The number of the line to check.
+    nesting_state: A NestingState instance which maintains information about
+                   the current stack of nested blocks being parsed.
+    error: The function to call with any errors found.
+  """
+  # Do nothing if there is no '&' on current line.
+  line = clean_lines.elided[linenum]
+  if '&' not in line:
+    return
+
+  # If a function is inherited, current function doesn't have much of
+  # a choice, so any non-const references should not be blamed on
+  # derived function.
+  if IsDerivedFunction(clean_lines, linenum):
+    return
+
+  # Long type names may be broken across multiple lines, usually in one
+  # of these forms:
+  #   LongType
+  #       ::LongTypeContinued &identifier
+  #   LongType::
+  #       LongTypeContinued &identifier
+  #   LongType<
+  #       ...>::LongTypeContinued &identifier
+  #
+  # If we detected a type split across two lines, join the previous
+  # line to current line so that we can match const references
+  # accordingly.
+  #
+  # Note that this only scans back one line, since scanning back
+  # arbitrary number of lines would be expensive.  If you have a type
+  # that spans more than 2 lines, please use a typedef.
+  if linenum > 1:
+    previous = None
+    if Match(r'\s*::(?:[\w<>]|::)+\s*&\s*\S', line):
+      # previous_line\n + ::current_line
+      previous = Search(r'\b((?:const\s*)?(?:[\w<>]|::)+[\w<>])\s*$',
+                        clean_lines.elided[linenum - 1])
+    elif Match(r'\s*[a-zA-Z_]([\w<>]|::)+\s*&\s*\S', line):
+      # previous_line::\n + current_line
+      previous = Search(r'\b((?:const\s*)?(?:[\w<>]|::)+::)\s*$',
+                        clean_lines.elided[linenum - 1])
+    if previous:
+      line = previous.group(1) + line.lstrip()
+    else:
+      # Check for templated parameter that is split across multiple lines
+      endpos = line.rfind('>')
+      if endpos > -1:
+        (_, startline, startpos) = ReverseCloseExpression(
+            clean_lines, linenum, endpos)
+        if startpos > -1 and startline < linenum:
+          # Found the matching < on an earlier line, collect all
+          # pieces up to current line.
+          line = ''
+          for i in xrange(startline, linenum + 1):
+            line += clean_lines.elided[i].strip()
+
+  # Check for non-const references in function parameters.  A single '&' may
+  # found in the following places:
+  #   inside expression: binary & for bitwise AND
+  #   inside expression: unary & for taking the address of something
+  #   inside declarators: reference parameter
+  # We will exclude the first two cases by checking that we are not inside a
+  # function body, including one that was just introduced by a trailing '{'.
+  # TODO(unknown): Doesn't account for 'catch(Exception& e)' [rare].
+  if (nesting_state.previous_stack_top and
+      not (isinstance(nesting_state.previous_stack_top, _ClassInfo) or
+           isinstance(nesting_state.previous_stack_top, _NamespaceInfo))):
+    # Not at toplevel, not within a class, and not within a namespace
+    return
+
+  # Avoid preprocessors
+  if Search(r'\\\s*$', line):
+    return
+
+  # Avoid constructor initializer lists
+  if IsInitializerList(clean_lines, linenum):
+    return
+
+  # We allow non-const references in a few standard places, like functions
+  # called "swap()" or iostream operators like "<<" or ">>".  Do not check
+  # those function parameters.
+  #
+  # We also accept & in static_assert, which looks like a function but
+  # it's actually a declaration expression.
+  whitelisted_functions = (r'(?:[sS]wap(?:<\w:+>)?|'
+                           r'operator\s*[<>][<>]|'
+                           r'static_assert|COMPILE_ASSERT'
+                           r')\s*\(')
+  if Search(whitelisted_functions, line):
+    return
+  elif not Search(r'\S+\([^)]*$', line):
+    # Don't see a whitelisted function on this line.  Actually we
+    # didn't see any function name on this line, so this is likely a
+    # multi-line parameter list.  Try a bit harder to catch this case.
+    for i in xrange(2):
+      if (linenum > i and
+          Search(whitelisted_functions, clean_lines.elided[linenum - i - 1])):
+        return
+
+  decls = ReplaceAll(r'{[^}]*}', ' ', line)  # exclude function body
+  # for parameter in re.findall(_RE_PATTERN_REF_PARAM, decls):
+  #   if not Match(_RE_PATTERN_CONST_REF_PARAM, parameter):
+  #     error(filename, linenum, 'runtime/references', 2,
+  #           'Is this a non-const reference? '
+  #           'If so, make const or use a pointer: ' +
+  #           ReplaceAll(' *<', '<', parameter))
+
+
+def CheckCasts(filename, clean_lines, linenum, error):
+  """Various cast related checks.
+
+  Args:
+    filename: The name of the current file.
+    clean_lines: A CleansedLines instance containing the file.
+    linenum: The number of the line to check.
+    error: The function to call with any errors found.
+  """
+  line = clean_lines.elided[linenum]
+
+  # Check to see if they're using an conversion function cast.
+  # I just try to capture the most common basic types, though there are more.
+  # Parameterless conversion functions, such as bool(), are allowed as they are
+  # probably a member operator declaration or default constructor.
+  match = Search(
+      r'(\bnew\s+|\S<\s*(?:const\s+)?)?\b'
+      r'(int|float|double|bool|char|int32|uint32|int64|uint64)'
+      r'(\([^)].*)', line)
+  expecting_function = ExpectingFunctionArgs(clean_lines, linenum)
+  if match and not expecting_function:
+    matched_type = match.group(2)
+
+    # matched_new_or_template is used to silence two false positives:
+    # - New operators
+    # - Template arguments with function types
+    #
+    # For template arguments, we match on types immediately following
+    # an opening bracket without any spaces.  This is a fast way to
+    # silence the common case where the function type is the first
+    # template argument.  False negative with less-than comparison is
+    # avoided because those operators are usually followed by a space.
+    #
+    #   function<double(double)>   // bracket + no space = false positive
+    #   value < double(42)         // bracket + space = true positive
+    matched_new_or_template = match.group(1)
+
+    # Other things to ignore:
+    # - Function pointers
+    # - Casts to pointer types
+    # - Placement new
+    # - Alias declarations
+    matched_funcptr = match.group(3)
+    if (matched_new_or_template is None and
+        not (matched_funcptr and
+             (Match(r'\((?:[^() ]+::\s*\*\s*)?[^() ]+\)\s*\(',
+                    matched_funcptr) or
+              matched_funcptr.startswith('(*)'))) and
+        not Match(r'\s*using\s+\S+\s*=\s*' + matched_type, line) and
+        not Search(r'new\(\S+\)\s*' + matched_type, line)):
+      error(filename, linenum, 'readability/casting', 4,
+            'Using deprecated casting style.  '
+            'Use static_cast<%s>(...) instead' %
+            matched_type)
+
+  if not expecting_function:
+    CheckCStyleCast(filename, linenum, line, clean_lines.raw_lines[linenum],
+                    'static_cast',
+                    r'\((int|float|double|bool|char|u?int(16|32|64))\)', error)
+
+  # This doesn't catch all cases. Consider (const char * const)"hello".
+  #
+  # (char *) "foo" should always be a const_cast (reinterpret_cast won't
+  # compile).
+  if CheckCStyleCast(filename, linenum, line, clean_lines.raw_lines[linenum],
+                     'const_cast', r'\((char\s?\*+\s?)\)\s*"', error):
+    pass
+  else:
+    # Check pointer casts for other than string constants
+    CheckCStyleCast(filename, linenum, line, clean_lines.raw_lines[linenum],
+                    'reinterpret_cast', r'\((\w+\s?\*+\s?)\)', error)
+
+  # In addition, we look for people taking the address of a cast.  This
+  # is dangerous -- casts can assign to temporaries, so the pointer doesn't
+  # point where you think.
+  match = Search(
+      r'(?:&\(([^)]+)\)[\w(])|'
+      r'(?:&(static|dynamic|down|reinterpret)_cast\b)', line)
+  if match and match.group(1) != '*':
+    # Try a better error message when the & is bound to something
+    # dereferenced by the casted pointer, as opposed to the casted
+    # pointer itself.
+    parenthesis_error = False
+    match = Match(r'^(.*&(?:static|dynamic|down|reinterpret)_cast\b)<', line)
+    if match:
+      _, y1, x1 = CloseExpression(clean_lines, linenum, len(match.group(1)))
+      if x1 >= 0 and clean_lines.elided[y1][x1] == '(':
+        _, y2, x2 = CloseExpression(clean_lines, y1, x1)
+        if x2 >= 0:
+          extended_line = clean_lines.elided[y2][x2:]
+          if y2 < clean_lines.NumLines() - 1:
+            extended_line += clean_lines.elided[y2 + 1]
+          if Match(r'\s*(?:->|\[)', extended_line):
+            parenthesis_error = True
+
+    if parenthesis_error:
+      error(filename, linenum, 'readability/casting', 4,
+            ('Are you taking an address of something dereferenced '
+             'from a cast?  Wrapping the dereferenced expression in '
+             'parentheses will make the binding more obvious'))
+    else:
+      error(filename, linenum, 'runtime/casting', 4,
+            ('Are you taking an address of a cast?  '
+             'This is dangerous: could be a temp var.  '
+             'Take the address before doing the cast, rather than after'))
+
+
+def CheckCStyleCast(filename, linenum, line, raw_line, cast_type, pattern,
+                    error):
+  """Checks for a C-style cast by looking for the pattern.
+
+  Args:
+    filename: The name of the current file.
+    linenum: The number of the line to check.
+    line: The line of code to check.
+    raw_line: The raw line of code to check, with comments.
+    cast_type: The string for the C++ cast to recommend.  This is either
+      reinterpret_cast, static_cast, or const_cast, depending.
+    pattern: The regular expression used to find C-style casts.
+    error: The function to call with any errors found.
+
+  Returns:
+    True if an error was emitted.
+    False otherwise.
+  """
+  match = Search(pattern, line)
+  if not match:
+    return False
+
+  # Exclude lines with keywords that tend to look like casts, and also
+  # macros which are generally troublesome.
+  if Match(r'.*\b(?:sizeof|alignof|alignas|[A-Z_]+)\s*$',
+           line[0:match.start(1) - 1]):
+    return False
+
+  # operator++(int) and operator--(int)
+  if (line[0:match.start(1) - 1].endswith(' operator++') or
+      line[0:match.start(1) - 1].endswith(' operator--')):
+    return False
+
+  # A single unnamed argument for a function tends to look like old
+  # style cast.  If we see those, don't issue warnings for deprecated
+  # casts, instead issue warnings for unnamed arguments where
+  # appropriate.
+  #
+  # These are things that we want warnings for, since the style guide
+  # explicitly require all parameters to be named:
+  #   Function(int);
+  #   Function(int) {
+  #   ConstMember(int) const;
+  #   ConstMember(int) const {
+  #   ExceptionMember(int) throw (...);
+  #   ExceptionMember(int) throw (...) {
+  #   PureVirtual(int) = 0;
+  #
+  # These are functions of some sort, where the compiler would be fine
+  # if they had named parameters, but people often omit those
+  # identifiers to reduce clutter:
+  #   (FunctionPointer)(int);
+  #   (FunctionPointer)(int) = value;
+  #   Function((function_pointer_arg)(int))
+  #   <TemplateArgument(int)>;
+  #   <(FunctionPointerTemplateArgument)(int)>;
+  remainder = line[match.end(0):]
+  if Match(r'^\s*(?:;|const\b|throw\b|final\b|override\b|=|>|\{|\))',
+           remainder):
+    # Looks like an unnamed parameter.
+
+    # Don't warn on any kind of template arguments.
+    if Match(r'^\s*>', remainder):
+      return False
+
+    # Don't warn on assignments to function pointers, but keep warnings for
+    # unnamed parameters to pure virtual functions.  Note that this pattern
+    # will also pass on assignments of "0" to function pointers, but the
+    # preferred values for those would be "nullptr" or "NULL".
+    matched_zero = Match(r'^\s=\s*(\S+)\s*;', remainder)
+    if matched_zero and matched_zero.group(1) != '0':
+      return False
+
+    # Don't warn on function pointer declarations.  For this we need
+    # to check what came before the "(type)" string.
+    if Match(r'.*\)\s*$', line[0:match.start(0)]):
+      return False
+
+    # Don't warn if the parameter is named with block comments, e.g.:
+    #  Function(int /*unused_param*/);
+    if '/*' in raw_line:
+      return False
+
+    # Passed all filters, issue warning here.
+    error(filename, linenum, 'readability/function', 3,
+          'All parameters should be named in a function')
+    return True
+
+  # At this point, all that should be left is actual casts.
+  error(filename, linenum, 'readability/casting', 4,
+        'Using C-style cast.  Use %s<%s>(...) instead' %
+        (cast_type, match.group(1)))
+
+  return True
+
+
+def ExpectingFunctionArgs(clean_lines, linenum):
+  """Checks whether where function type arguments are expected.
+
+  Args:
+    clean_lines: A CleansedLines instance containing the file.
+    linenum: The number of the line to check.
+
+  Returns:
+    True if the line at 'linenum' is inside something that expects arguments
+    of function types.
+  """
+  line = clean_lines.elided[linenum]
+  return (Match(r'^\s*MOCK_(CONST_)?METHOD\d+(_T)?\(', line) or
+          (linenum >= 2 and
+           (Match(r'^\s*MOCK_(?:CONST_)?METHOD\d+(?:_T)?\((?:\S+,)?\s*$',
+                  clean_lines.elided[linenum - 1]) or
+            Match(r'^\s*MOCK_(?:CONST_)?METHOD\d+(?:_T)?\(\s*$',
+                  clean_lines.elided[linenum - 2]) or
+            Search(r'\bstd::m?function\s*\<\s*$',
+                   clean_lines.elided[linenum - 1]))))
+
+
+_HEADERS_CONTAINING_TEMPLATES = (
+    ('<deque>', ('deque',)),
+    ('<functional>', ('unary_function', 'binary_function',
+                      'plus', 'minus', 'multiplies', 'divides', 'modulus',
+                      'negate',
+                      'equal_to', 'not_equal_to', 'greater', 'less',
+                      'greater_equal', 'less_equal',
+                      'logical_and', 'logical_or', 'logical_not',
+                      'unary_negate', 'not1', 'binary_negate', 'not2',
+                      'bind1st', 'bind2nd',
+                      'pointer_to_unary_function',
+                      'pointer_to_binary_function',
+                      'ptr_fun',
+                      'mem_fun_t', 'mem_fun', 'mem_fun1_t', 'mem_fun1_ref_t',
+                      'mem_fun_ref_t',
+                      'const_mem_fun_t', 'const_mem_fun1_t',
+                      'const_mem_fun_ref_t', 'const_mem_fun1_ref_t',
+                      'mem_fun_ref',
+                     )),
+    ('<limits>', ('numeric_limits',)),
+    ('<list>', ('list',)),
+    ('<map>', ('map', 'multimap',)),
+    ('<memory>', ('allocator',)),
+    ('<queue>', ('queue', 'priority_queue',)),
+    ('<set>', ('set', 'multiset',)),
+    ('<stack>', ('stack',)),
+    ('<string>', ('char_traits', 'basic_string',)),
+    ('<utility>', ('pair',)),
+    ('<vector>', ('vector',)),
+
+    # gcc extensions.
+    # Note: std::hash is their hash, ::hash is our hash
+    ('<hash_map>', ('hash_map', 'hash_multimap',)),
+    ('<hash_set>', ('hash_set', 'hash_multiset',)),
+    ('<slist>', ('slist',)),
+    )
+
+_RE_PATTERN_STRING = re.compile(r'\bstring\b')
+
+_re_pattern_algorithm_header = []
+for _template in ('copy', 'max', 'min', 'min_element', 'sort', 'swap',
+                  'transform'):
+  # Match max<type>(..., ...), max(..., ...), but not foo->max, foo.max or
+  # type::max().
+  _re_pattern_algorithm_header.append(
+      (re.compile(r'[^>.]\b' + _template + r'(<.*?>)?\([^\)]'),
+       _template,
+       '<algorithm>'))
+
+_re_pattern_templates = []
+for _header, _templates in _HEADERS_CONTAINING_TEMPLATES:
+  for _template in _templates:
+    _re_pattern_templates.append(
+        (re.compile(r'(\<|\b)' + _template + r'\s*\<'),
+         _template + '<>',
+         _header))
+
+
+def FilesBelongToSameModule(filename_cc, filename_h):
+  """Check if these two filenames belong to the same module.
+
+  The concept of a 'module' here is a as follows:
+  foo.h, foo-inl.h, foo.cc, foo_test.cc and foo_unittest.cc belong to the
+  same 'module' if they are in the same directory.
+  some/path/public/xyzzy and some/path/internal/xyzzy are also considered
+  to belong to the same module here.
+
+  If the filename_cc contains a longer path than the filename_h, for example,
+  '/absolute/path/to/base/sysinfo.cc', and this file would include
+  'base/sysinfo.h', this function also produces the prefix needed to open the
+  header. This is used by the caller of this function to more robustly open the
+  header file. We don't have access to the real include paths in this context,
+  so we need this guesswork here.
+
+  Known bugs: tools/base/bar.cc and base/bar.h belong to the same module
+  according to this implementation. Because of this, this function gives
+  some false positives. This should be sufficiently rare in practice.
+
+  Args:
+    filename_cc: is the path for the .cc file
+    filename_h: is the path for the header path
+
+  Returns:
+    Tuple with a bool and a string:
+    bool: True if filename_cc and filename_h belong to the same module.
+    string: the additional prefix needed to open the header file.
+  """
+
+  if not filename_cc.endswith('.cc'):
+    return (False, '')
+  filename_cc = filename_cc[:-len('.cc')]
+  if filename_cc.endswith('_unittest'):
+    filename_cc = filename_cc[:-len('_unittest')]
+  elif filename_cc.endswith('_test'):
+    filename_cc = filename_cc[:-len('_test')]
+  filename_cc = filename_cc.replace('/public/', '/')
+  filename_cc = filename_cc.replace('/internal/', '/')
+
+  if not filename_h.endswith('.h'):
+    return (False, '')
+  filename_h = filename_h[:-len('.h')]
+  if filename_h.endswith('-inl'):
+    filename_h = filename_h[:-len('-inl')]
+  filename_h = filename_h.replace('/public/', '/')
+  filename_h = filename_h.replace('/internal/', '/')
+
+  files_belong_to_same_module = filename_cc.endswith(filename_h)
+  common_path = ''
+  if files_belong_to_same_module:
+    common_path = filename_cc[:-len(filename_h)]
+  return files_belong_to_same_module, common_path
+
+
+def UpdateIncludeState(filename, include_state, io=codecs):
+  """Fill up the include_state with new includes found from the file.
+
+  Args:
+    filename: the name of the header to read.
+    include_state: an _IncludeState instance in which the headers are inserted.
+    io: The io factory to use to read the file. Provided for testability.
+
+  Returns:
+    True if a header was succesfully added. False otherwise.
+  """
+  headerfile = None
+  try:
+    headerfile = io.open(filename, 'r', 'utf8', 'replace')
+  except IOError:
+    return False
+  linenum = 0
+  for line in headerfile:
+    linenum += 1
+    clean_line = CleanseComments(line)
+    match = _RE_PATTERN_INCLUDE.search(clean_line)
+    if match:
+      include = match.group(2)
+      # The value formatting is cute, but not really used right now.
+      # What matters here is that the key is in include_state.
+      include_state.setdefault(include, '%s:%d' % (filename, linenum))
+  return True
+
+
+def CheckForIncludeWhatYouUse(filename, clean_lines, include_state, error,
+                              io=codecs):
+  """Reports for missing stl includes.
+
+  This function will output warnings to make sure you are including the headers
+  necessary for the stl containers and functions that you use. We only give one
+  reason to include a header. For example, if you use both equal_to<> and
+  less<> in a .h file, only one (the latter in the file) of these will be
+  reported as a reason to include the <functional>.
+
+  Args:
+    filename: The name of the current file.
+    clean_lines: A CleansedLines instance containing the file.
+    include_state: An _IncludeState instance.
+    error: The function to call with any errors found.
+    io: The IO factory to use to read the header file. Provided for unittest
+        injection.
+  """
+  required = {}  # A map of header name to linenumber and the template entity.
+                 # Example of required: { '<functional>': (1219, 'less<>') }
+
+  for linenum in xrange(clean_lines.NumLines()):
+    line = clean_lines.elided[linenum]
+    if not line or line[0] == '#':
+      continue
+
+    # String is special -- it is a non-templatized type in STL.
+    matched = _RE_PATTERN_STRING.search(line)
+    if matched:
+      # Don't warn about strings in non-STL namespaces:
+      # (We check only the first match per line; good enough.)
+      prefix = line[:matched.start()]
+      if prefix.endswith('std::') or not prefix.endswith('::'):
+        required['<string>'] = (linenum, 'string')
+
+    for pattern, template, header in _re_pattern_algorithm_header:
+      if pattern.search(line):
+        required[header] = (linenum, template)
+
+    # The following function is just a speed up, no semantics are changed.
+    if not '<' in line:  # Reduces the cpu time usage by skipping lines.
+      continue
+
+    for pattern, template, header in _re_pattern_templates:
+      if pattern.search(line):
+        required[header] = (linenum, template)
+
+  # The policy is that if you #include something in foo.h you don't need to
+  # include it again in foo.cc. Here, we will look at possible includes.
+  # Let's copy the include_state so it is only messed up within this function.
+  include_state = include_state.copy()
+
+  # Did we find the header for this file (if any) and succesfully load it?
+  header_found = False
+
+  # Use the absolute path so that matching works properly.
+  abs_filename = FileInfo(filename).FullName()
+
+  # For Emacs's flymake.
+  # If cpplint is invoked from Emacs's flymake, a temporary file is generated
+  # by flymake and that file name might end with '_flymake.cc'. In that case,
+  # restore original file name here so that the corresponding header file can be
+  # found.
+  # e.g. If the file name is 'foo_flymake.cc', we should search for 'foo.h'
+  # instead of 'foo_flymake.h'
+  abs_filename = re.sub(r'_flymake\.cc$', '.cc', abs_filename)
+
+  # include_state is modified during iteration, so we iterate over a copy of
+  # the keys.
+  header_keys = include_state.keys()
+  for header in header_keys:
+    (same_module, common_path) = FilesBelongToSameModule(abs_filename, header)
+    fullpath = common_path + header
+    if same_module and UpdateIncludeState(fullpath, include_state, io):
+      header_found = True
+
+  # If we can't find the header file for a .cc, assume it's because we don't
+  # know where to look. In that case we'll give up as we're not sure they
+  # didn't include it in the .h file.
+  # TODO(unknown): Do a better job of finding .h files so we are confident that
+  # not having the .h file means there isn't one.
+  if filename.endswith('.cc') and not header_found:
+    return
+
+  # All the lines have been processed, report the errors found.
+  for required_header_unstripped in required:
+    template = required[required_header_unstripped][1]
+    if required_header_unstripped.strip('<>"') not in include_state:
+      error(filename, required[required_header_unstripped][0],
+            'build/include_what_you_use', 4,
+            'Add #include ' + required_header_unstripped + ' for ' + template)
+
+
+_RE_PATTERN_EXPLICIT_MAKEPAIR = re.compile(r'\bmake_pair\s*<')
+
+
+def CheckMakePairUsesDeduction(filename, clean_lines, linenum, error):
+  """Check that make_pair's template arguments are deduced.
+
+  G++ 4.6 in C++11 mode fails badly if make_pair's template arguments are
+  specified explicitly, and such use isn't intended in any case.
+
+  Args:
+    filename: The name of the current file.
+    clean_lines: A CleansedLines instance containing the file.
+    linenum: The number of the line to check.
+    error: The function to call with any errors found.
+  """
+  line = clean_lines.elided[linenum]
+  match = _RE_PATTERN_EXPLICIT_MAKEPAIR.search(line)
+  if match:
+    error(filename, linenum, 'build/explicit_make_pair',
+          4,  # 4 = high confidence
+          'For C++11-compatibility, omit template arguments from make_pair'
+          ' OR use pair directly OR if appropriate, construct a pair directly')
+def CheckDefaultLambdaCaptures(filename, clean_lines, linenum, error):
+  """Check that default lambda captures are not used.
+
+  Args:
+    filename: The name of the current file.
+    clean_lines: A CleansedLines instance containing the file.
+    linenum: The number of the line to check.
+    error: The function to call with any errors found.
+  """
+  line = clean_lines.elided[linenum]
+
+  # A lambda introducer specifies a default capture if it starts with "[="
+  # or if it starts with "[&" _not_ followed by an identifier.
+  match = Match(r'^(.*)\[\s*(?:=|&[^\w])', line)
+  if match:
+    # Found a potential error, check what comes after the lambda-introducer.
+    # If it's not open parenthesis (for lambda-declarator) or open brace
+    # (for compound-statement), it's not a lambda.
+    line, _, pos = CloseExpression(clean_lines, linenum, len(match.group(1)))
+    if pos >= 0 and Match(r'^\s*[{(]', line[pos:]):
+      error(filename, linenum, 'build/c++11',
+            4,  # 4 = high confidence
+            'Default lambda captures are an unapproved C++ feature.')
+
+
+
+
+def ProcessLine(filename, file_extension, clean_lines, line,
+                include_state, function_state, nesting_state, error,
+                extra_check_functions=[]):
+  """Processes a single line in the file.
+
+  Args:
+    filename: Filename of the file that is being processed.
+    file_extension: The extension (dot not included) of the file.
+    clean_lines: An array of strings, each representing a line of the file,
+                 with comments stripped.
+    line: Number of line being processed.
+    include_state: An _IncludeState instance in which the headers are inserted.
+    function_state: A _FunctionState instance which counts function lines, etc.
+    nesting_state: A NestingState instance which maintains information about
+                   the current stack of nested blocks being parsed.
+    error: A callable to which errors are reported, which takes 4 arguments:
+           filename, line number, error level, and message
+    extra_check_functions: An array of additional check functions that will be
+                           run on each source line. Each function takes 4
+                           arguments: filename, clean_lines, line, error
+  """
+  raw_lines = clean_lines.raw_lines
+  ParseNolintSuppressions(filename, raw_lines[line], line, error)
+  nesting_state.Update(filename, clean_lines, line, error)
+  if nesting_state.InAsmBlock(): return
+  CheckForFunctionLengths(filename, clean_lines, line, function_state, error)
+  CheckForMultilineCommentsAndStrings(filename, clean_lines, line, error)
+  CheckStyle(filename, clean_lines, line, file_extension, nesting_state, error)
+  CheckLanguage(filename, clean_lines, line, file_extension, include_state,
+                nesting_state, error)
+  CheckForNonConstReference(filename, clean_lines, line, nesting_state, error)
+  CheckForNonStandardConstructs(filename, clean_lines, line,
+                                nesting_state, error)
+  CheckVlogArguments(filename, clean_lines, line, error)
+  CheckPosixThreading(filename, clean_lines, line, error)
+  CheckInvalidIncrement(filename, clean_lines, line, error)
+  CheckMakePairUsesDeduction(filename, clean_lines, line, error)
+  # CheckDefaultLambdaCaptures(filename, clean_lines, line, error)
+  for check_fn in extra_check_functions:
+    check_fn(filename, clean_lines, line, error)
+	
+def FlagCxx11Features(filename, clean_lines, linenum, error):
+  """Flag those c++11 features that we only allow in certain places.
+
+  Args:
+    filename: The name of the current file.
+    clean_lines: A CleansedLines instance containing the file.
+    linenum: The number of the line to check.
+    error: The function to call with any errors found.
+  """
+  line = clean_lines.elided[linenum]
+
+  # Flag unapproved C++11 headers.
+  include = Match(r'\s*#\s*include\s+[<"]([^<"]+)[">]', line)
+  # if include and include.group(1) in ('cfenv',
+  #                                     'condition_variable',
+  #                                     'fenv.h',
+  #                                     'ratio',
+  #                                     'regex',
+  #                                     'system_error',
+  #                                    ):
+  #   error(filename, linenum, 'build/c++11', 5,
+  #         ('<%s> is an unapproved C++11 header.') % include.group(1))
+
+  # The only place where we need to worry about C++11 keywords and library
+  # features in preprocessor directives is in macro definitions.
+  if Match(r'\s*#', line) and not Match(r'\s*#\s*define\b', line): return
+
+  # These are classes and free functions.  The classes are always
+  # mentioned as std::*, but we only catch the free functions if
+  # they're not found by ADL.  They're alphabetical by header.
+  for top_name in (
+      # type_traits
+      'alignment_of',
+      'aligned_union',
+
+      # utility
+      'forward',
+      ):
+    if Search(r'\bstd::%s\b' % top_name, line):
+      error(filename, linenum, 'build/c++11', 5,
+            ('std::%s is an unapproved C++11 class or function.  Send c-style '
+             'an example of where it would make your code more readable, and '
+             'they may let you use it.') % top_name)
+
+
+def ProcessFileData(filename, file_extension, lines, error,
+                    extra_check_functions=[]):
+  """Performs lint checks and reports any errors to the given error function.
+
+  Args:
+    filename: Filename of the file that is being processed.
+    file_extension: The extension (dot not included) of the file.
+    lines: An array of strings, each representing a line of the file, with the
+           last element being empty if the file is terminated with a newline.
+    error: A callable to which errors are reported, which takes 4 arguments:
+           filename, line number, error level, and message
+    extra_check_functions: An array of additional check functions that will be
+                           run on each source line. Each function takes 4
+                           arguments: filename, clean_lines, line, error
+  """
+  lines = (['// marker so line numbers and indices both start at 1'] + lines +
+           ['// marker so line numbers end in a known way'])
+
+  include_state = _IncludeState()
+  function_state = _FunctionState()
+  nesting_state = NestingState()
+
+  ResetNolintSuppressions()
+
+  CheckForCopyright(filename, lines, error)
+
+  if file_extension == 'h':
+    CheckForHeaderGuard(filename, lines, error)
+
+  RemoveMultiLineComments(filename, lines, error)
+  clean_lines = CleansedLines(lines)
+  for line in xrange(clean_lines.NumLines()):
+    ProcessLine(filename, file_extension, clean_lines, line,
+                include_state, function_state, nesting_state, error,
+                extra_check_functions)
+    FlagCxx11Features(filename, clean_lines, line, error)
+  nesting_state.CheckCompletedBlocks(filename, error)
+
+  CheckForIncludeWhatYouUse(filename, clean_lines, include_state, error)
+
+  # We check here rather than inside ProcessLine so that we see raw
+  # lines rather than "cleaned" lines.
+  CheckForBadCharacters(filename, lines, error)
+
+  CheckForNewlineAtEOF(filename, lines, error)
+
+
+def ProcessFile(filename, vlevel, extra_check_functions=[]):
+  """Does google-lint on a single file.
+
+  Args:
+    filename: The name of the file to parse.
+
+    vlevel: The level of errors to report.  Every error of confidence
+    >= verbose_level will be reported.  0 is a good default.
+
+    extra_check_functions: An array of additional check functions that will be
+                           run on each source line. Each function takes 4
+                           arguments: filename, clean_lines, line, error
+  """
+
+  _SetVerboseLevel(vlevel)
+
+  lf_lines = []
+  crlf_lines = []
+  try:
+    # Support the UNIX convention of using "-" for stdin.  Note that
+    # we are not opening the file with universal newline support
+    # (which codecs doesn't support anyway), so the resulting lines do
+    # contain trailing '\r' characters if we are reading a file that
+    # has CRLF endings.
+    # If after the split a trailing '\r' is present, it is removed
+    # below.
+    if filename == '-':
+      lines = codecs.StreamReaderWriter(sys.stdin,
+                                        codecs.getreader('utf8'),
+                                        codecs.getwriter('utf8'),
+                                        'replace').read().split('\n')
+    else:
+      lines = codecs.open(filename, 'r', 'utf8', 'replace').read().split('\n')
+
+    # Remove trailing '\r'.
+    # The -1 accounts for the extra trailing blank line we get from split()
+    for linenum in range(len(lines) - 1):
+      if lines[linenum].endswith('\r'):
+        lines[linenum] = lines[linenum].rstrip('\r')
+        crlf_lines.append(linenum + 1)
+      else:
+        lf_lines.append(linenum + 1)
+
+  except IOError:
+    sys.stderr.write(
+        "Skipping input '%s': Can't open for reading\n" % filename)
+    return
+
+  # Note, if no dot is found, this will give the entire filename as the ext.
+  file_extension = filename[filename.rfind('.') + 1:]
+
+  # When reading from stdin, the extension is unknown, so no cpplint tests
+  # should rely on the extension.
+  if filename != '-' and file_extension not in _valid_extensions:
+    sys.stderr.write('Ignoring %s; not a valid file name '
+                     '(%s)\n' % (filename, ', '.join(_valid_extensions)))
+  else:
+    ProcessFileData(filename, file_extension, lines, Error,
+                    extra_check_functions)
+
+    # If end-of-line sequences are a mix of LF and CR-LF, issue
+    # warnings on the lines with CR.
+    #
+    # Don't issue any warnings if all lines are uniformly LF or CR-LF,
+    # since critique can handle these just fine, and the style guide
+    # doesn't dictate a particular end of line sequence.
+    #
+    # We can't depend on os.linesep to determine what the desired
+    # end-of-line sequence should be, since that will return the
+    # server-side end-of-line sequence.
+    if lf_lines and crlf_lines:
+      # Warn on every line with CR.  An alternative approach might be to
+      # check whether the file is mostly CRLF or just LF, and warn on the
+      # minority, we bias toward LF here since most tools prefer LF.
+      for linenum in crlf_lines:
+        Error(filename, linenum, 'whitespace/newline', 1,
+              'Unexpected \\r (^M) found; better to use only \\n')
+
+  # sys.stderr.write('Done processing %s\n' % filename)
+
+
+def PrintUsage(message):
+  """Prints a brief usage string and exits, optionally with an error message.
+
+  Args:
+    message: The optional error message.
+  """
+  sys.stderr.write(_USAGE)
+  if message:
+    sys.exit('\nFATAL ERROR: ' + message)
+  else:
+    sys.exit(1)
+
+
+def PrintCategories():
+  """Prints a list of all the error-categories used by error messages.
+
+  These are the categories used to filter messages via --filter.
+  """
+  sys.stderr.write(''.join('  %s\n' % cat for cat in _ERROR_CATEGORIES))
+  sys.exit(0)
+
+
+def ParseArguments(args):
+  """Parses the command line arguments.
+
+  This may set the output format and verbosity level as side-effects.
+
+  Args:
+    args: The command line arguments:
+
+  Returns:
+    The list of filenames to lint.
+  """
+  try:
+    (opts, filenames) = getopt.getopt(args, '', ['help', 'output=', 'verbose=',
+                                                 'counting=',
+                                                 'filter=',
+                                                 'root=',
+                                                 'linelength=',
+                                                 'extensions='])
+  except getopt.GetoptError:
+    PrintUsage('Invalid arguments.')
+
+  verbosity = _VerboseLevel()
+  output_format = _OutputFormat()
+  filters = ''
+  counting_style = ''
+
+  for (opt, val) in opts:
+    if opt == '--help':
+      PrintUsage(None)
+    elif opt == '--output':
+      if val not in ('emacs', 'vs7', 'eclipse'):
+        PrintUsage('The only allowed output formats are emacs, vs7 and eclipse.')
+      output_format = val
+    elif opt == '--verbose':
+      verbosity = int(val)
+    elif opt == '--filter':
+      filters = val
+      if not filters:
+        PrintCategories()
+    elif opt == '--counting':
+      if val not in ('total', 'toplevel', 'detailed'):
+        PrintUsage('Valid counting options are total, toplevel, and detailed')
+      counting_style = val
+    elif opt == '--root':
+      global _root
+      _root = val
+    elif opt == '--linelength':
+      global _line_length
+      try:
+          _line_length = int(val)
+      except ValueError:
+          PrintUsage('Line length must be digits.')
+    elif opt == '--extensions':
+      global _valid_extensions
+      try:
+          _valid_extensions = set(val.split(','))
+      except ValueError:
+          PrintUsage('Extensions must be comma seperated list.')
+
+  if not filenames:
+    PrintUsage('No files were specified.')
+
+  _SetOutputFormat(output_format)
+  _SetVerboseLevel(verbosity)
+  _SetFilters(filters)
+  _SetCountingStyle(counting_style)
+
+  return filenames
+
+
+def main():
+  filenames = ParseArguments(sys.argv[1:])
+
+  # Change stderr to write with replacement characters so we don't die
+  # if we try to print something containing non-ASCII characters.
+  sys.stderr = codecs.StreamReaderWriter(sys.stderr,
+                                         codecs.getreader('utf8'),
+                                         codecs.getwriter('utf8'),
+                                         'replace')
+
+  _cpplint_state.ResetErrorCounts()
+  for filename in filenames:
+    ProcessFile(filename, _cpplint_state.verbose_level)
+  _cpplint_state.PrintErrorCounts()
+
+  sys.exit(_cpplint_state.error_count > 0)
+
+
+if __name__ == '__main__':
+  main()

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/debian-science/packages/ignition-math4.git



More information about the debian-science-commits mailing list