diff --git a/include/ignition/math/Vector2.hh b/include/ignition/math/Vector2.hh index dc8530a92..717fba2eb 100644 --- a/include/ignition/math/Vector2.hh +++ b/include/ignition/math/Vector2.hh @@ -18,6 +18,7 @@ #define IGNITION_MATH_VECTOR2_HH_ #include +#include #include #include @@ -40,6 +41,9 @@ namespace ignition /// \brief math::Vector2(1, 1) public: static const Vector2 One; + /// \brief math::Vector2(NaN, NaN, NaN) + public: static const Vector2 NaN; + /// \brief Default Constructor public: Vector2() { @@ -579,6 +583,11 @@ namespace ignition template const Vector2 Vector2::One(1, 1); + template + const Vector2 Vector2::NaN( + std::numeric_limits::quiet_NaN(), + std::numeric_limits::quiet_NaN()); + typedef Vector2 Vector2i; typedef Vector2 Vector2d; typedef Vector2 Vector2f; diff --git a/include/ignition/math/Vector3.hh b/include/ignition/math/Vector3.hh index 4d5622374..af1dc71a0 100644 --- a/include/ignition/math/Vector3.hh +++ b/include/ignition/math/Vector3.hh @@ -17,10 +17,11 @@ #ifndef IGNITION_MATH_VECTOR3_HH_ #define IGNITION_MATH_VECTOR3_HH_ -#include -#include -#include #include +#include +#include +#include +#include #include #include @@ -54,6 +55,9 @@ namespace ignition /// \brief math::Vector3(0, 0, 1) public: static const Vector3 UnitZ; + /// \brief math::Vector3(NaN, NaN, NaN) + public: static const Vector3 NaN; + /// \brief Constructor public: Vector3() { @@ -757,6 +761,10 @@ namespace ignition template const Vector3 Vector3::UnitX(1, 0, 0); template const Vector3 Vector3::UnitY(0, 1, 0); template const Vector3 Vector3::UnitZ(0, 0, 1); + template const Vector3 Vector3::NaN( + std::numeric_limits::quiet_NaN(), + std::numeric_limits::quiet_NaN(), + std::numeric_limits::quiet_NaN()); typedef Vector3 Vector3i; typedef Vector3 Vector3d; diff --git a/include/ignition/math/Vector4.hh b/include/ignition/math/Vector4.hh index 0403f1cca..9d27b4b87 100644 --- a/include/ignition/math/Vector4.hh +++ b/include/ignition/math/Vector4.hh @@ -18,6 +18,7 @@ #define IGNITION_MATH_VECTOR4_HH_ #include +#include #include #include @@ -41,6 +42,9 @@ namespace ignition /// \brief math::Vector4(1, 1, 1, 1) public: static const Vector4 One; + /// \brief math::Vector4(NaN, NaN, NaN, NaN) + public: static const Vector4 NaN; + /// \brief Constructor public: Vector4() { @@ -735,6 +739,12 @@ namespace ignition template const Vector4 Vector4::One(1, 1, 1, 1); + template const Vector4 Vector4::NaN( + std::numeric_limits::quiet_NaN(), + std::numeric_limits::quiet_NaN(), + std::numeric_limits::quiet_NaN(), + std::numeric_limits::quiet_NaN()); + typedef Vector4 Vector4i; typedef Vector4 Vector4d; typedef Vector4 Vector4f; diff --git a/src/Vector2_TEST.cc b/src/Vector2_TEST.cc index 7a289fe97..3e6e95f75 100644 --- a/src/Vector2_TEST.cc +++ b/src/Vector2_TEST.cc @@ -443,3 +443,25 @@ TEST(Vector2Test, Length) EXPECT_EQ(vi.SquaredLength(), 25); } +///////////////////////////////////////////////// +TEST(Vector2Test, NaN) +{ + auto nanVec = math::Vector2d::NaN; + EXPECT_FALSE(nanVec.IsFinite()); + EXPECT_TRUE(math::isnan(nanVec.X())); + EXPECT_TRUE(math::isnan(nanVec.Y())); + + nanVec.Correct(); + EXPECT_EQ(math::Vector2d::Zero, nanVec); + EXPECT_TRUE(nanVec.IsFinite()); + + auto nanVecF = math::Vector2f::NaN; + EXPECT_FALSE(nanVecF.IsFinite()); + EXPECT_TRUE(math::isnan(nanVecF.X())); + EXPECT_TRUE(math::isnan(nanVecF.Y())); + + nanVecF.Correct(); + EXPECT_EQ(math::Vector2f::Zero, nanVecF); + EXPECT_TRUE(nanVecF.IsFinite()); +} + diff --git a/src/Vector3_TEST.cc b/src/Vector3_TEST.cc index c6207a8b2..9076b1099 100644 --- a/src/Vector3_TEST.cc +++ b/src/Vector3_TEST.cc @@ -125,11 +125,25 @@ TEST(Vector3dTest, Vector3d) 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)); + EXPECT_EQ(math::Vector3d::Zero, math::Vector3d(0, 0, 0)); + EXPECT_EQ(math::Vector3f::Zero, math::Vector3f(0, 0, 0)); + EXPECT_EQ(math::Vector3i::Zero, math::Vector3i(0, 0, 0)); + + EXPECT_EQ(math::Vector3d::One, math::Vector3d(1, 1, 1)); + EXPECT_EQ(math::Vector3f::One, math::Vector3f(1, 1, 1)); + EXPECT_EQ(math::Vector3i::One, math::Vector3i(1, 1, 1)); + + EXPECT_EQ(math::Vector3d::UnitX, math::Vector3d(1, 0, 0)); + EXPECT_EQ(math::Vector3f::UnitX, math::Vector3f(1, 0, 0)); + EXPECT_EQ(math::Vector3i::UnitX, math::Vector3i(1, 0, 0)); + + EXPECT_EQ(math::Vector3d::UnitY, math::Vector3d(0, 1, 0)); + EXPECT_EQ(math::Vector3f::UnitY, math::Vector3f(0, 1, 0)); + EXPECT_EQ(math::Vector3i::UnitY, math::Vector3i(0, 1, 0)); + + EXPECT_EQ(math::Vector3d::UnitZ, math::Vector3d(0, 0, 1)); + EXPECT_EQ(math::Vector3f::UnitZ, math::Vector3f(0, 0, 1)); + EXPECT_EQ(math::Vector3i::UnitZ, math::Vector3i(0, 0, 1)); } ///////////////////////////////////////////////// @@ -467,3 +481,26 @@ TEST(Vector3dTest, NoException) EXPECT_NO_THROW(ss << vInf); } +///////////////////////////////////////////////// +TEST(Vector3dTest, NaN) +{ + auto nanVec = math::Vector3d::NaN; + EXPECT_FALSE(nanVec.IsFinite()); + EXPECT_TRUE(math::isnan(nanVec.X())); + EXPECT_TRUE(math::isnan(nanVec.Y())); + EXPECT_TRUE(math::isnan(nanVec.Z())); + + nanVec.Correct(); + EXPECT_EQ(math::Vector3d::Zero, nanVec); + EXPECT_TRUE(nanVec.IsFinite()); + + auto nanVecF = math::Vector3f::NaN; + EXPECT_FALSE(nanVecF.IsFinite()); + EXPECT_TRUE(math::isnan(nanVecF.X())); + EXPECT_TRUE(math::isnan(nanVecF.Y())); + EXPECT_TRUE(math::isnan(nanVecF.Z())); + + nanVecF.Correct(); + EXPECT_EQ(math::Vector3f::Zero, nanVecF); + EXPECT_TRUE(nanVecF.IsFinite()); +} diff --git a/src/Vector4_TEST.cc b/src/Vector4_TEST.cc index 5d99f2402..400a1f90c 100644 --- a/src/Vector4_TEST.cc +++ b/src/Vector4_TEST.cc @@ -443,3 +443,28 @@ TEST(Vector4dTest, Length) EXPECT_EQ(math::Vector4i::One.SquaredLength(), 4); } +///////////////////////////////////////////////// +TEST(Vector4Test, NaN) +{ + auto nanVec = math::Vector4d::NaN; + EXPECT_FALSE(nanVec.IsFinite()); + EXPECT_TRUE(math::isnan(nanVec.X())); + EXPECT_TRUE(math::isnan(nanVec.Y())); + EXPECT_TRUE(math::isnan(nanVec.Z())); + EXPECT_TRUE(math::isnan(nanVec.W())); + + nanVec.Correct(); + EXPECT_EQ(math::Vector4d::Zero, nanVec); + EXPECT_TRUE(nanVec.IsFinite()); + + auto nanVecF = math::Vector4f::NaN; + EXPECT_FALSE(nanVecF.IsFinite()); + EXPECT_TRUE(math::isnan(nanVecF.X())); + EXPECT_TRUE(math::isnan(nanVecF.Y())); + EXPECT_TRUE(math::isnan(nanVecF.Z())); + EXPECT_TRUE(math::isnan(nanVecF.W())); + + nanVecF.Correct(); + EXPECT_EQ(math::Vector4f::Zero, nanVecF); + EXPECT_TRUE(nanVecF.IsFinite()); +} diff --git a/src/python/Vector2.i b/src/python/Vector2.i index ff2f80098..6ff486814 100644 --- a/src/python/Vector2.i +++ b/src/python/Vector2.i @@ -37,6 +37,7 @@ namespace ignition %rename("%(uppercase)s", %$isstatic, %$isvariable) ""; public: static const Vector2 Zero; public: static const Vector2 One; + public: static const Vector2 NaN; public: Vector2(); public: Vector2(const T &_x, const T &_y); diff --git a/src/python/Vector2_TEST.py b/src/python/Vector2_TEST.py index 7bcac078f..6043f0f0c 100644 --- a/src/python/Vector2_TEST.py +++ b/src/python/Vector2_TEST.py @@ -15,6 +15,7 @@ import unittest import math from ignition.math import Vector2d +from ignition.math import Vector2f class TestVector2(unittest.TestCase): @@ -295,6 +296,24 @@ def test_lenght(self): self.assertAlmostEqual(v.length(), 5) self.assertAlmostEqual(v.squared_length(), 25) + def test_nan(self): + nanVec = Vector2d.NAN + self.assertFalse(nanVec.is_finite()) + self.assertTrue(math.isnan(nanVec.x())) + self.assertTrue(math.isnan(nanVec.y())) + + nanVec.correct() + self.assertEqual(Vector2d.ZERO, nanVec) + self.assertTrue(nanVec.is_finite()) + + nanVecF = Vector2f.NAN + self.assertFalse(nanVecF.is_finite()) + self.assertTrue(math.isnan(nanVecF.x())) + self.assertTrue(math.isnan(nanVecF.y())) + + nanVecF.correct() + self.assertEqual(Vector2f.ZERO, nanVecF) + self.assertTrue(nanVecF.is_finite()) if __name__ == '__main__': unittest.main() diff --git a/src/python/Vector3.i b/src/python/Vector3.i index 12b48ced9..751350fb7 100644 --- a/src/python/Vector3.i +++ b/src/python/Vector3.i @@ -43,6 +43,7 @@ namespace ignition public: static const Vector3 UnitY; %rename(UNIT_Z) UnitZ; public: static const Vector3 UnitZ; + public: static const Vector3 NaN; public: Vector3(); public: Vector3(const T &_x, const T &_y, const T &_z); public: Vector3(const Vector3 &_v); diff --git a/src/python/Vector3_TEST.py b/src/python/Vector3_TEST.py index 2ac6ab18e..0c3b7e610 100644 --- a/src/python/Vector3_TEST.py +++ b/src/python/Vector3_TEST.py @@ -15,6 +15,7 @@ import unittest import math from ignition.math import Vector3d +from ignition.math import Vector3f class TestVector3(unittest.TestCase): @@ -350,6 +351,26 @@ def test_finite(self): self.assertTrue(vec1.is_finite()) + def test_nan(self): + nanVec = Vector3d.NAN + self.assertFalse(nanVec.is_finite()) + self.assertTrue(math.isnan(nanVec.x())) + self.assertTrue(math.isnan(nanVec.y())) + self.assertTrue(math.isnan(nanVec.z())) + + nanVec.correct() + self.assertEqual(Vector3d.ZERO, nanVec) + self.assertTrue(nanVec.is_finite()) + + nanVecF = Vector3f.NAN + self.assertFalse(nanVecF.is_finite()) + self.assertTrue(math.isnan(nanVecF.x())) + self.assertTrue(math.isnan(nanVecF.y())) + self.assertTrue(math.isnan(nanVecF.z())) + + nanVecF.correct() + self.assertEqual(Vector3f.ZERO, nanVecF) + self.assertTrue(nanVecF.is_finite()) if __name__ == '__main__': unittest.main() diff --git a/src/python/Vector4.i b/src/python/Vector4.i index 1608bce03..aaea4dbc6 100644 --- a/src/python/Vector4.i +++ b/src/python/Vector4.i @@ -37,6 +37,7 @@ namespace ignition %rename("%(uppercase)s", %$isstatic, %$isvariable) ""; public: static const Vector4 Zero; public: static const Vector4 One; + public: static const Vector4 NaN; public: Vector4(); public: Vector4(const T &_x, const T &_y, const T &_z, const T &_w); public: Vector4(const Vector4 &_v); @@ -58,6 +59,7 @@ namespace ignition public: bool operator==(const Vector4 &_v) const; public: bool Equal(const Vector4 &_v, const T &_tol) const; public: bool IsFinite() const; + public: inline void Correct(); public: inline T X() const; public: inline T Y() const; public: inline T Z() const; diff --git a/src/python/Vector4_TEST.py b/src/python/Vector4_TEST.py index b85ecf9cd..854050277 100644 --- a/src/python/Vector4_TEST.py +++ b/src/python/Vector4_TEST.py @@ -16,6 +16,7 @@ import unittest import math from ignition.math import Vector4d +from ignition.math import Vector4f class TestVector4(unittest.TestCase): @@ -256,6 +257,28 @@ def test_finite(self): vec1 = Vector4d(0.1, 0.2, 0.3, 0.4) self.assertTrue(vec1.is_finite()) + def test_nan(self): + nanVec = Vector4d.NAN + self.assertFalse(nanVec.is_finite()) + self.assertTrue(math.isnan(nanVec.x())) + self.assertTrue(math.isnan(nanVec.y())) + self.assertTrue(math.isnan(nanVec.z())) + self.assertTrue(math.isnan(nanVec.w())) + + nanVec.correct() + self.assertEqual(Vector4d.ZERO, nanVec) + self.assertTrue(nanVec.is_finite()) + + nanVecF = Vector4f.NAN + self.assertFalse(nanVecF.is_finite()) + self.assertTrue(math.isnan(nanVecF.x())) + self.assertTrue(math.isnan(nanVecF.y())) + self.assertTrue(math.isnan(nanVecF.z())) + self.assertTrue(math.isnan(nanVecF.w())) + + nanVecF.correct() + self.assertEqual(Vector4f.ZERO, nanVecF) + self.assertTrue(nanVecF.is_finite()) if __name__ == '__main__': unittest.main() diff --git a/src/ruby/Vector2.i b/src/ruby/Vector2.i index 63ae8adee..cad4128ea 100644 --- a/src/ruby/Vector2.i +++ b/src/ruby/Vector2.i @@ -35,6 +35,7 @@ namespace ignition { public: static const Vector2 Zero; public: static const Vector2 One; + public: static const Vector2 NaN; public: Vector2(); public: Vector2(const T &_x, const T &_y); diff --git a/src/ruby/Vector2_TEST.rb b/src/ruby/Vector2_TEST.rb index 653a47d86..cdc350e2c 100644 --- a/src/ruby/Vector2_TEST.rb +++ b/src/ruby/Vector2_TEST.rb @@ -257,6 +257,28 @@ def test_length assert((v.SquaredLength() - 17.65).abs < 1e-8, "Squared length of v should be near 17.65") end + + def test_nan + nanVec = Ignition::Math::Vector2d.NaN + assert(!nanVec.IsFinite(), + "NaN vector shouldn't be finite") + assert(nanVec.X().nan?, "X should be NaN") + assert(nanVec.Y().nan?, "Y should be NaN") + + nanVec.Correct() + assert(Ignition::Math::Vector2d.Zero == nanVec, + "Corrected vector should equal zero") + + nanVecF = Ignition::Math::Vector2f.NaN + assert(!nanVecF.IsFinite(), + "NaN vector shouldn't be finite") + assert(nanVecF.X().nan?, "X should be NaN") + assert(nanVecF.Y().nan?, "Y should be NaN") + + nanVecF.Correct() + assert(Ignition::Math::Vector2f.Zero == nanVecF, + "Corrected vector should equal zero") + end end exit Test::Unit::UI::Console::TestRunner.run(Vector2_TEST).passed? ? 0 : -1 diff --git a/src/ruby/Vector3.i b/src/ruby/Vector3.i index 0d8508d3c..0acf12da5 100644 --- a/src/ruby/Vector3.i +++ b/src/ruby/Vector3.i @@ -38,6 +38,7 @@ namespace ignition public: static const Vector3 UnitX; public: static const Vector3 UnitY; public: static const Vector3 UnitZ; + public: static const Vector3 NaN; public: Vector3(); public: Vector3(const T &_x, const T &_y, const T &_z); public: Vector3(const Vector3 &_v); diff --git a/src/ruby/Vector3_TEST.rb b/src/ruby/Vector3_TEST.rb index 1448cdf4e..d698b06d7 100755 --- a/src/ruby/Vector3_TEST.rb +++ b/src/ruby/Vector3_TEST.rb @@ -425,6 +425,29 @@ def test_finite assert(vec1.IsFinite(), "Vector3 vec1 should be be finite") end + def test_nan + nanVec = Ignition::Math::Vector3d.NaN + assert(!nanVec.IsFinite(), + "NaN vector shouldn't be finite") + assert(nanVec.X().nan?, "X should be NaN") + assert(nanVec.Y().nan?, "Y should be NaN") + assert(nanVec.Z().nan?, "Z should be NaN") + + nanVec.Correct() + assert(Ignition::Math::Vector3d.Zero == nanVec, + "Corrected vector should equal zero") + + nanVecF = Ignition::Math::Vector3f.NaN + assert(!nanVecF.IsFinite(), + "NaN vector shouldn't be finite") + assert(nanVecF.X().nan?, "X should be NaN") + assert(nanVecF.Y().nan?, "Y should be NaN") + assert(nanVecF.Z().nan?, "Z should be NaN") + + nanVecF.Correct() + assert(Ignition::Math::Vector3f.Zero == nanVecF, + "Corrected vector should equal zero") + end end exit Test::Unit::UI::Console::TestRunner.run(Vector3_TEST).passed? ? 0 : -1 diff --git a/src/ruby/Vector4.i b/src/ruby/Vector4.i index d5f2bbf7b..a9235cae3 100644 --- a/src/ruby/Vector4.i +++ b/src/ruby/Vector4.i @@ -35,6 +35,7 @@ namespace ignition { public: static const Vector4 Zero; public: static const Vector4 One; + public: static const Vector4 NaN; public: Vector4(); public: Vector4(const T &_x, const T &_y, const T &_z, const T &_w); public: Vector4(const Vector4 &_v); @@ -56,6 +57,7 @@ namespace ignition public: bool operator==(const Vector4 &_v) const; public: bool Equal(const Vector4 &_v, const T &_tol) const; public: bool IsFinite() const; + public: inline void Correct(); public: inline T X() const; public: inline T Y() const; public: inline T Z() const; diff --git a/src/ruby/Vector4_TEST.rb b/src/ruby/Vector4_TEST.rb index 1d750133d..c594bcc16 100644 --- a/src/ruby/Vector4_TEST.rb +++ b/src/ruby/Vector4_TEST.rb @@ -295,6 +295,32 @@ def test_finite assert(vec1.IsFinite(), "Vector4 vec1 should be be finite") end + + def test_nan + nanVec = Ignition::Math::Vector4d.NaN + assert(!nanVec.IsFinite(), + "NaN vector shouldn't be finite") + assert(nanVec.X().nan?, "X should be NaN") + assert(nanVec.Y().nan?, "Y should be NaN") + assert(nanVec.Z().nan?, "Z should be NaN") + assert(nanVec.W().nan?, "W should be NaN") + + nanVec.Correct() + assert(Ignition::Math::Vector4d.Zero == nanVec, + "Corrected vector should equal zero") + + nanVecF = Ignition::Math::Vector4f.NaN + assert(!nanVecF.IsFinite(), + "NaN vector shouldn't be finite") + assert(nanVecF.X().nan?, "X should be NaN") + assert(nanVecF.Y().nan?, "Y should be NaN") + assert(nanVecF.Z().nan?, "Z should be NaN") + assert(nanVecF.W().nan?, "W should be NaN") + + nanVecF.Correct() + assert(Ignition::Math::Vector4f.Zero == nanVecF, + "Corrected vector should equal zero") + end end exit Test::Unit::UI::Console::TestRunner.run(Vector4_TEST).passed? ? 0 : -1