Skip to content

Commit

Permalink
Merge pull request #643 from stan-dev/issue-123
Browse files Browse the repository at this point in the history
Issue 123
  • Loading branch information
seantalts authored Feb 8, 2018
2 parents a4c9203 + 8200065 commit 5ea9efa
Show file tree
Hide file tree
Showing 2 changed files with 76 additions and 0 deletions.
66 changes: 66 additions & 0 deletions stan/math/rev/core/var.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,9 @@
#include <boost/math/tools/config.hpp>
#include <ostream>
#include <vector>
#include <complex>
#include <string>
#include <exception>

namespace stan {
namespace math {
Expand Down Expand Up @@ -179,6 +182,69 @@ class var {
// NOLINTNEXTLINE
var(unsigned long x) : vi_(new vari(static_cast<double>(x))) {} // NOLINT

/**
* Construct a variable from the specified arithmetic argument
* by constructing a new <code>vari</code> with the argument
* cast to <code>double</code>, and a zero adjoint. Only works
* if the imaginary part is zero.
*
* @param x Value of the variable.
*/
explicit var(const std::complex<double>& 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 <code>vari</code> with the argument
* cast to <code>double</code>, and a zero adjoint. Only works
* if the imaginary part is zero.
*
* @param x Value of the variable.
*/
explicit var(const std::complex<float>& x) {
if (imag(x) == 0) {
vi_ = new vari(static_cast<double>(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 <code>vari</code> with the argument
* cast to <code>double</code>, and a zero adjoint. Only works
* if the imaginary part is zero.
*
* @param x Value of the variable.
*/
explicit var(const std::complex<long double>& x) {
if (imag(x) == 0) {
vi_ = new vari(static_cast<double>(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

// these two ctors are for Win64 to enable 64-bit signed
Expand Down
10 changes: 10 additions & 0 deletions test/unit/math/rev/core/var_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,16 @@ TEST_F(AgradRev, ctorOverloads) {
// ptrdiff_t
EXPECT_FLOAT_EQ(37, var(static_cast<ptrdiff_t>(37)).val());
EXPECT_FLOAT_EQ(0, var(static_cast<ptrdiff_t>(0)).val());

// complex but with zero imaginary part
EXPECT_FLOAT_EQ(37, var(std::complex<double>(37, 0)).val());
EXPECT_FLOAT_EQ(37, var(std::complex<float>(37, 0)).val());
EXPECT_FLOAT_EQ(37, var(std::complex<long double>(37, 0)).val());

// complex but with non-zero imaginary part
EXPECT_THROW(var(std::complex<double>(37, 10)), std::invalid_argument);
EXPECT_THROW(var(std::complex<float>(37, 10)), std::invalid_argument);
EXPECT_THROW(var(std::complex<long double>(37, 10)), std::invalid_argument);
}

TEST_F(AgradRev, a_eq_x) {
Expand Down

0 comments on commit 5ea9efa

Please sign in to comment.