From 60e238e5728cbd4591ab5bd61b1e3182e346a8b1 Mon Sep 17 00:00:00 2001 From: Ben Goodrich Date: Sun, 8 Oct 2017 13:58:56 -0400 Subject: [PATCH 1/7] add var dummy constructors in the complex case --- stan/math/rev/core/var.hpp | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/stan/math/rev/core/var.hpp b/stan/math/rev/core/var.hpp index f5be5a4f946..652f85f2309 100644 --- a/stan/math/rev/core/var.hpp +++ b/stan/math/rev/core/var.hpp @@ -7,6 +7,9 @@ #include #include #include +#include +#include +#include namespace stan { namespace math { @@ -181,6 +184,30 @@ namespace stan { // NOLINTNEXTLINE var(unsigned long x) : vi_(new vari(static_cast(x))) { } // NOLINT + /** + * Construct a variable from the specified arithmetic argument + * by constructing a new vari with the argument + * cast to double, and a zero adjoint. Only works + * if the imaginary part is zero. + * + * @param x Value of the variable. + */ + explicit var(std::complex x) { + assert(imag(x) == 0); + vi_ = new vari(std::numeric_limits::quiet_NaN()); + } + + /** + * This constructor does not work and really only exists to + * ensure that such a var is not created accidentally in + * testing. + * + * @param x Value of the variable. + */ + explicit var(std::complex x) { + assert(false); + } + #ifdef _WIN64 // these two ctors are for Win64 to enable 64-bit signed From f90037a3d2b5681d0fc9c4e9bee8bdb556a22c5d Mon Sep 17 00:00:00 2001 From: Ben Goodrich Date: Sun, 8 Oct 2017 14:35:18 -0400 Subject: [PATCH 2/7] add and test a few more cases --- stan/math/rev/core/var.hpp | 28 +++++++++++++++++++++++++++- test/unit/math/rev/core/var_test.cpp | 4 ++++ 2 files changed, 31 insertions(+), 1 deletion(-) diff --git a/stan/math/rev/core/var.hpp b/stan/math/rev/core/var.hpp index 652f85f2309..297715be390 100644 --- a/stan/math/rev/core/var.hpp +++ b/stan/math/rev/core/var.hpp @@ -194,7 +194,33 @@ namespace stan { */ explicit var(std::complex x) { assert(imag(x) == 0); - vi_ = new vari(std::numeric_limits::quiet_NaN()); + vi_ = new vari(real(x)); + } + + /** + * Construct a variable from the specified arithmetic argument + * by constructing a new vari with the argument + * cast to double, and a zero adjoint. Only works + * if the imaginary part is zero. + * + * @param x Value of the variable. + */ + explicit var(std::complex x) { + assert(imag(x) == 0); + vi_ = new vari(static_cast(real(x))); + } + + /** + * Construct a variable from the specified arithmetic argument + * by constructing a new vari with the argument + * cast to double, and a zero adjoint. Only works + * if the imaginary part is zero. + * + * @param x Value of the variable. + */ + explicit var(std::complex x) { + assert(imag(x) == 0); + vi_ = new vari(static_cast(real(x))); } /** diff --git a/test/unit/math/rev/core/var_test.cpp b/test/unit/math/rev/core/var_test.cpp index 9818dbc4141..25499bae61a 100644 --- a/test/unit/math/rev/core/var_test.cpp +++ b/test/unit/math/rev/core/var_test.cpp @@ -69,6 +69,10 @@ TEST_F(AgradRev, ctorOverloads) { EXPECT_FLOAT_EQ(37, var(static_cast(37)).val()); EXPECT_FLOAT_EQ(0, var(static_cast(0)).val()); + // complex but with zero imaginary part + EXPECT_FLOAT_EQ(37, var(std::complex(37,0)).val()); + EXPECT_FLOAT_EQ(37, var(std::complex(37,0)).val()); + EXPECT_FLOAT_EQ(37, var(std::complex(37,0)).val()); } TEST_F(AgradRev,a_eq_x) { From 867663525443427884c0cb52b5c761e92438c12c Mon Sep 17 00:00:00 2001 From: Ben Goodrich Date: Sat, 14 Oct 2017 14:06:47 -0400 Subject: [PATCH 3/7] make suggested changes still does not prevent segfault --- stan/math/rev/core/var.hpp | 53 +++++++++++++++++++++------- test/unit/math/rev/core/var_test.cpp | 5 +++ 2 files changed, 45 insertions(+), 13 deletions(-) diff --git a/stan/math/rev/core/var.hpp b/stan/math/rev/core/var.hpp index 297715be390..bfa21aeaaf7 100644 --- a/stan/math/rev/core/var.hpp +++ b/stan/math/rev/core/var.hpp @@ -8,8 +8,7 @@ #include #include #include -#include -#include +#include namespace stan { namespace math { @@ -192,9 +191,17 @@ namespace stan { * * @param x Value of the variable. */ - explicit var(std::complex x) { - assert(imag(x) == 0); - vi_ = new vari(real(x)); + explicit var(const std::complex& x) { + if (imag(x) == 0) { + vi_ = new vari(real(x)); + } else { + std::stringstream ss; + ss << "Imaginary part of std::complex used to construct var" + << " must be zero. Found real part = " << real(x) << " and " + << " found imaginary part = " << imag(x) << std::endl; + std::string msg = ss.str(); + throw std::invalid_argument(msg); + } } /** @@ -205,9 +212,17 @@ namespace stan { * * @param x Value of the variable. */ - explicit var(std::complex x) { - assert(imag(x) == 0); - vi_ = new vari(static_cast(real(x))); + explicit var(const std::complex& x) { + if (imag(x) == 0) { + vi_ = new vari(static_cast(real(x))); + } else { + std::stringstream ss; + ss << "Imaginary part of std::complex used to construct var" + << " must be zero. Found real part = " << real(x) << " and " + << " found imaginary part = " << imag(x) << std::endl; + std::string msg = ss.str(); + throw std::invalid_argument(msg); + } } /** @@ -218,9 +233,18 @@ namespace stan { * * @param x Value of the variable. */ - explicit var(std::complex x) { - assert(imag(x) == 0); - vi_ = new vari(static_cast(real(x))); + explicit var(const std::complex& x) { + if (imag(x) == 0) { + vi_ = new vari(static_cast(real(x))); + } else { + std::stringstream ss; + ss << "Imaginary part of std::complex used to construct var" + << " must be zero. Found real part = " << real(x) << " and " + << " found imaginary part = " << imag(x) << std::endl; + std::string msg = ss.str(); + throw std::invalid_argument(msg); + } + } /** @@ -230,8 +254,11 @@ namespace stan { * * @param x Value of the variable. */ - explicit var(std::complex x) { - assert(false); + explicit var(const std::complex& x) { + std::stringstream ss; + ss << "Stan does not support vars with complex numbers."; + std::string msg = ss.str(); + throw std::invalid_argument(msg); } #ifdef _WIN64 diff --git a/test/unit/math/rev/core/var_test.cpp b/test/unit/math/rev/core/var_test.cpp index 25499bae61a..f757808c8ed 100644 --- a/test/unit/math/rev/core/var_test.cpp +++ b/test/unit/math/rev/core/var_test.cpp @@ -73,6 +73,11 @@ TEST_F(AgradRev, ctorOverloads) { EXPECT_FLOAT_EQ(37, var(std::complex(37,0)).val()); EXPECT_FLOAT_EQ(37, var(std::complex(37,0)).val()); EXPECT_FLOAT_EQ(37, var(std::complex(37,0)).val()); + + // complex but with non-zero imaginary part + EXPECT_THROW(var(std::complex(37,10)), std::invalid_argument); + EXPECT_THROW(var(std::complex(37,10)), std::invalid_argument); + EXPECT_THROW(var(std::complex(37,10)), std::invalid_argument); } TEST_F(AgradRev,a_eq_x) { From fceed9bdaed94703682f911090b4137ca72f26e6 Mon Sep 17 00:00:00 2001 From: Ben Goodrich Date: Sat, 14 Oct 2017 14:09:37 -0400 Subject: [PATCH 4/7] remove blank line --- stan/math/rev/core/var.hpp | 1 - 1 file changed, 1 deletion(-) diff --git a/stan/math/rev/core/var.hpp b/stan/math/rev/core/var.hpp index bfa21aeaaf7..54ba5ed754c 100644 --- a/stan/math/rev/core/var.hpp +++ b/stan/math/rev/core/var.hpp @@ -244,7 +244,6 @@ namespace stan { std::string msg = ss.str(); throw std::invalid_argument(msg); } - } /** From 5d99ffb2b4e4a1c8f8afa665c2d1ed2f16c5457a Mon Sep 17 00:00:00 2001 From: Ben Goodrich Date: Wed, 18 Oct 2017 15:42:25 -0400 Subject: [PATCH 5/7] eliminate constructor --- stan/math/rev/core/var.hpp | 14 -------------- 1 file changed, 14 deletions(-) diff --git a/stan/math/rev/core/var.hpp b/stan/math/rev/core/var.hpp index 54ba5ed754c..52c21f9c7ee 100644 --- a/stan/math/rev/core/var.hpp +++ b/stan/math/rev/core/var.hpp @@ -246,20 +246,6 @@ namespace stan { } } - /** - * This constructor does not work and really only exists to - * ensure that such a var is not created accidentally in - * testing. - * - * @param x Value of the variable. - */ - explicit var(const std::complex& x) { - std::stringstream ss; - ss << "Stan does not support vars with complex numbers."; - std::string msg = ss.str(); - throw std::invalid_argument(msg); - } - #ifdef _WIN64 // these two ctors are for Win64 to enable 64-bit signed From 30d608de4fb6c90267f6b0df9b309d8726ea2497 Mon Sep 17 00:00:00 2001 From: Ben Goodrich Date: Sat, 21 Oct 2017 13:07:30 -0400 Subject: [PATCH 6/7] add exception header --- stan/math/rev/core/var.hpp | 1 + 1 file changed, 1 insertion(+) diff --git a/stan/math/rev/core/var.hpp b/stan/math/rev/core/var.hpp index 52c21f9c7ee..5c4077eaf3f 100644 --- a/stan/math/rev/core/var.hpp +++ b/stan/math/rev/core/var.hpp @@ -9,6 +9,7 @@ #include #include #include +#include namespace stan { namespace math { From 820006503415677e922d76304761fb424635a469 Mon Sep 17 00:00:00 2001 From: Stan Jenkins Date: Wed, 31 Jan 2018 09:14:50 -0500 Subject: [PATCH 7/7] [Jenkins] auto-formatting by clang-format version 5.0.1 (tags/RELEASE_501/final) --- stan/math/rev/core/var.hpp | 124 +++++++++++++-------------- test/unit/math/rev/core/var_test.cpp | 14 +-- 2 files changed, 69 insertions(+), 69 deletions(-) diff --git a/stan/math/rev/core/var.hpp b/stan/math/rev/core/var.hpp index 79848f89f75..5bfd61fda72 100644 --- a/stan/math/rev/core/var.hpp +++ b/stan/math/rev/core/var.hpp @@ -182,68 +182,68 @@ class var { // NOLINTNEXTLINE var(unsigned long x) : vi_(new vari(static_cast(x))) {} // NOLINT - /** - * Construct a variable from the specified arithmetic argument - * by constructing a new vari with the argument - * cast to double, and a zero adjoint. Only works - * if the imaginary part is zero. - * - * @param x Value of the variable. - */ - explicit var(const std::complex& x) { - if (imag(x) == 0) { - vi_ = new vari(real(x)); - } else { - std::stringstream ss; - ss << "Imaginary part of std::complex used to construct var" - << " must be zero. Found real part = " << real(x) << " and " - << " found imaginary part = " << imag(x) << std::endl; - std::string msg = ss.str(); - throw std::invalid_argument(msg); - } - } - - /** - * Construct a variable from the specified arithmetic argument - * by constructing a new vari with the argument - * cast to double, and a zero adjoint. Only works - * if the imaginary part is zero. - * - * @param x Value of the variable. - */ - explicit var(const std::complex& x) { - if (imag(x) == 0) { - vi_ = new vari(static_cast(real(x))); - } else { - std::stringstream ss; - ss << "Imaginary part of std::complex used to construct var" - << " must be zero. Found real part = " << real(x) << " and " - << " found imaginary part = " << imag(x) << std::endl; - std::string msg = ss.str(); - throw std::invalid_argument(msg); - } - } - - /** - * Construct a variable from the specified arithmetic argument - * by constructing a new vari with the argument - * cast to double, and a zero adjoint. Only works - * if the imaginary part is zero. - * - * @param x Value of the variable. - */ - explicit var(const std::complex& x) { - if (imag(x) == 0) { - vi_ = new vari(static_cast(real(x))); - } else { - std::stringstream ss; - ss << "Imaginary part of std::complex used to construct var" - << " must be zero. Found real part = " << real(x) << " and " - << " found imaginary part = " << imag(x) << std::endl; - std::string msg = ss.str(); - throw std::invalid_argument(msg); - } - } + /** + * Construct a variable from the specified arithmetic argument + * by constructing a new vari with the argument + * cast to double, and a zero adjoint. Only works + * if the imaginary part is zero. + * + * @param x Value of the variable. + */ + explicit var(const std::complex& x) { + if (imag(x) == 0) { + vi_ = new vari(real(x)); + } else { + std::stringstream ss; + ss << "Imaginary part of std::complex used to construct var" + << " must be zero. Found real part = " << real(x) << " and " + << " found imaginary part = " << imag(x) << std::endl; + std::string msg = ss.str(); + throw std::invalid_argument(msg); + } + } + + /** + * Construct a variable from the specified arithmetic argument + * by constructing a new vari with the argument + * cast to double, and a zero adjoint. Only works + * if the imaginary part is zero. + * + * @param x Value of the variable. + */ + explicit var(const std::complex& x) { + if (imag(x) == 0) { + vi_ = new vari(static_cast(real(x))); + } else { + std::stringstream ss; + ss << "Imaginary part of std::complex used to construct var" + << " must be zero. Found real part = " << real(x) << " and " + << " found imaginary part = " << imag(x) << std::endl; + std::string msg = ss.str(); + throw std::invalid_argument(msg); + } + } + + /** + * Construct a variable from the specified arithmetic argument + * by constructing a new vari with the argument + * cast to double, and a zero adjoint. Only works + * if the imaginary part is zero. + * + * @param x Value of the variable. + */ + explicit var(const std::complex& x) { + if (imag(x) == 0) { + vi_ = new vari(static_cast(real(x))); + } else { + std::stringstream ss; + ss << "Imaginary part of std::complex used to construct var" + << " must be zero. Found real part = " << real(x) << " and " + << " found imaginary part = " << imag(x) << std::endl; + std::string msg = ss.str(); + throw std::invalid_argument(msg); + } + } #ifdef _WIN64 diff --git a/test/unit/math/rev/core/var_test.cpp b/test/unit/math/rev/core/var_test.cpp index 9c9c0b65516..dd174f64e6e 100644 --- a/test/unit/math/rev/core/var_test.cpp +++ b/test/unit/math/rev/core/var_test.cpp @@ -69,16 +69,16 @@ TEST_F(AgradRev, ctorOverloads) { // ptrdiff_t EXPECT_FLOAT_EQ(37, var(static_cast(37)).val()); EXPECT_FLOAT_EQ(0, var(static_cast(0)).val()); - + // complex but with zero imaginary part - EXPECT_FLOAT_EQ(37, var(std::complex(37,0)).val()); - EXPECT_FLOAT_EQ(37, var(std::complex(37,0)).val()); - EXPECT_FLOAT_EQ(37, var(std::complex(37,0)).val()); + EXPECT_FLOAT_EQ(37, var(std::complex(37, 0)).val()); + EXPECT_FLOAT_EQ(37, var(std::complex(37, 0)).val()); + EXPECT_FLOAT_EQ(37, var(std::complex(37, 0)).val()); // complex but with non-zero imaginary part - EXPECT_THROW(var(std::complex(37,10)), std::invalid_argument); - EXPECT_THROW(var(std::complex(37,10)), std::invalid_argument); - EXPECT_THROW(var(std::complex(37,10)), std::invalid_argument); + EXPECT_THROW(var(std::complex(37, 10)), std::invalid_argument); + EXPECT_THROW(var(std::complex(37, 10)), std::invalid_argument); + EXPECT_THROW(var(std::complex(37, 10)), std::invalid_argument); } TEST_F(AgradRev, a_eq_x) {