-
-
Notifications
You must be signed in to change notification settings - Fork 187
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Feature/issue 123 complex numbers with vars #789
Changes from all commits
788edbc
0695ca1
a271bdc
41f9d0b
ed33827
e65748b
ab66802
6fd81ba
99bd2f0
523cbe1
4a15c4c
accf844
941595d
a978a08
67f0b73
59df90d
9ed85e6
9fd648d
51e9381
eb7a775
6616c0a
c6cca98
ea3a2b8
73bdbda
09cf3c9
5fb41d0
3ef68c5
f86a6a5
9cbdc14
59fbd80
cbc12fd
5778b3d
1805f7f
2bd02fe
83adf5a
d371f2d
dc1870f
b433c27
ebf8ac1
da6876f
27a45b7
98087fb
23b454f
dbd4faa
99081b8
b6419ee
9a9d404
e78930e
c8121ba
c6bffc7
8239d09
fe010fd
ca32ef3
62dd118
73d2074
fa8d852
68cf52e
00a1bfa
ab0ad61
85c2d42
d7df296
efb2721
99035c1
4ca9f02
72dbc12
f7baf67
f68d54f
6ea194d
c3be260
b7c4600
35675ef
30e243a
9dc41a9
13e30a2
1d6c004
fde62be
519ede2
023a700
f3bd995
26f4558
31b9347
42b1912
1a98267
5cfefd9
acaf423
e7150d4
90d9965
8277554
15240fc
768c843
35e439a
ba17f31
cc4e47e
3cd4345
f3e098b
4d1f473
258ae51
fe12a30
67b0dc2
5094cc2
dc5f2c2
36a58ab
0908396
57c6d9b
3384667
1370b5f
912d8b3
e82360f
52805bc
1317c09
be5b3c0
7ac48a5
e69fa68
ee59e70
e2d1162
dfc52ff
f5ac5f5
8c9c261
eb70e6d
aea814d
319bf6d
814c8f4
c24546a
7aa5315
09f9019
ee002ff
5322bfa
ab9278d
5fd2b1c
c6415b6
ca6c740
4d88872
cfc82ad
f4de40a
56797be
e65c975
0f10cea
152ec31
12a09bf
7f3d34c
07ffd6c
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
#ifndef STAN_MATH_FWD_CPLX_HPP | ||
#define STAN_MATH_FWD_CPLX_HPP | ||
|
||
#include <stan/math/fwd/cplx/fvar.hpp> | ||
#include <stan/math/fwd/cplx/operator_division.hpp> | ||
|
||
#endif |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
#ifndef STAN_MATH_FWD_CPLX_FVAR_HPP | ||
#define STAN_MATH_FWD_CPLX_FVAR_HPP | ||
|
||
#include <stan/math/fwd/scal/meta/ad_promotable.hpp> | ||
#include <stan/math/fwd/scal/meta/is_fvar.hpp> | ||
#include <stan/math/fwd/core/fvar.hpp> | ||
#include <stan/math/prim/cplx/complex.hpp> | ||
|
||
namespace std { | ||
|
||
/** | ||
* std::complex<fvar> inherits from stan::math::complex. Details | ||
* are provided there. | ||
*/ | ||
template <class T> | ||
struct complex<stan::math::fvar<T>> : stan::math::complex<stan::math::fvar<T>> { | ||
using stan::math::complex<stan::math::fvar<T>>::complex; | ||
}; | ||
|
||
} // namespace std | ||
#endif |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
#ifndef STAN_MATH_FWD_CPLX_OPERATOR_DIVISION_HPP | ||
#define STAN_MATH_FWD_CPLX_OPERATOR_DIVISION_HPP | ||
|
||
#include <stan/math/fwd/cplx/fvar.hpp> | ||
#include <stan/math/fwd/scal/fun/pow.hpp> | ||
#include <stan/math/prim/cplx/operator_division.hpp> | ||
|
||
namespace stan { | ||
namespace math { | ||
|
||
/** | ||
* Return the result of dividing the first argument by the second. | ||
* This overload exists because libc++ uses logb and scalbn for | ||
* complex division, which aren't defined for fvars. | ||
* | ||
* @tparam T type of complex fvar value and tangent | ||
* @param t first argument | ||
* @param u second argument | ||
* @return first argument divided by second argument | ||
*/ | ||
template <class T> | ||
inline std::complex<fvar<T>> operator/(std::complex<fvar<T>> const& t, | ||
std::complex<fvar<T>> const& u) { | ||
return stan::math::operator_division(t, u); // no recursion | ||
} | ||
|
||
} // namespace math | ||
} // namespace stan | ||
#endif |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
#ifndef STAN_MATH_FWD_SCAL_FUN_PROJ_HPP | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. just following our (not very good) convention, can you rename this file |
||
#define STAN_MATH_FWD_SCAL_FUN_PROJ_HPP | ||
|
||
#include <stan/math/fwd/cplx.hpp> | ||
#include <stan/math/fwd/scal/fun/is_inf.hpp> | ||
#include <stan/math/prim/scal/fun/proj.hpp> | ||
|
||
namespace std { | ||
|
||
/** | ||
* Return a projection of a complex number onto | ||
* the Riemann sphere. | ||
* | ||
* This overloads an erroneous definition in | ||
* libstdc++ for general types. | ||
* | ||
* @tparam T auto diff variable type | ||
* @param[in] t Variable input. | ||
* @return projection onto Riemann sphere | ||
*/ | ||
template <class T> | ||
inline std::complex<stan::math::fvar<T>> proj( | ||
std::complex<stan::math::fvar<T>> const& t) { | ||
return stan::math::proj(t); | ||
} | ||
|
||
} // namespace std | ||
#endif |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
#ifndef STAN_MATH_PRIM_CPLX_HPP | ||
#define STAN_MATH_PRIM_CPLX_HPP | ||
|
||
#include <stan/math/prim/cplx/complex.hpp> | ||
#include <stan/math/prim/cplx/operator_addition.hpp> | ||
#include <stan/math/prim/cplx/operator_division.hpp> | ||
#include <stan/math/prim/cplx/operator_multiplication.hpp> | ||
#include <stan/math/prim/cplx/operator_subtraction.hpp> | ||
#include <stan/math/prim/cplx/zeroing.hpp> | ||
|
||
#endif |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,57 @@ | ||
#ifndef STAN_MATH_PRIM_CPLX_COMPLEX_HPP | ||
#define STAN_MATH_PRIM_CPLX_COMPLEX_HPP | ||
|
||
#include <stan/math/prim/cplx/zeroing.hpp> | ||
#include <complex> | ||
|
||
namespace stan { | ||
namespace math { | ||
|
||
/** | ||
* Complex class that forwards the interface of std::complex, brining | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. what is meant here? I still don't understand what "forwards" means in the way it's used here. |
||
* stan::math's namespace into ADL for functions called on data types | ||
* that inherit from this class, as well as allowing template | ||
* specializations of std::complex to indirectly work with different | ||
* underlying data types. For example, std::complex<var> specializes | ||
* the std::complex<T> template to inherit from | ||
* stan::math::complex<T>, which in turn inherits from | ||
* std::complex<zeroing<T>>. This causes stan::math to be pulled into | ||
* ADL on operations involving std::complex<var>, to handle, e.g. | ||
* division operations that the base std::complex doesn't have | ||
* defined usably for var, and, since stan::math::zeroing<var> zero | ||
* initializes itself, will also correctly work with the remaining | ||
* algorithms in std::complex<T> that require the expression T() to | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Clarification? The algorithms expect |
||
* be 0. | ||
*/ | ||
template <class T> | ||
struct complex : std::complex<zeroing<T>> { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. What's the motivation for having There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. If we did that, we would create an inheritance loop. The way we force things to work is by making a template specialization for |
||
using std::complex<zeroing<T>>::complex; | ||
// NOLINTNEXTLINE(runtime/explicit) | ||
complex(const std::complex<zeroing<T>>& t) | ||
: std::complex<zeroing<T>>(t) {} ///< allow promotion | ||
/** | ||
* Without this converting ctor, copy initialization of | ||
* std::complex<zeroing<(f)var>>> from an (f)var fails, because the | ||
* default implementation in the std::complex template requires the | ||
* argument type to match the template type. This is the same reason | ||
* why std::complex<double> can't be multiplied by an int. | ||
* | ||
* tparam R type of real argument. Won't fire on non-arithmetic types. | ||
* tparam I type of imaginary argument. | ||
* param[in] real, the pure real component of the complex number. | ||
* param[in] imag, the pure imaginary component of the complex number | ||
*/ | ||
template <class R = double, class I = R, | ||
std::enable_if_t<is_arith_like<R>::value>* = nullptr> | ||
// NOLINTNEXTLINE(runtime/explicit) | ||
complex(R const& real = 0, I const& imag = 0) | ||
: std::complex<zeroing<T>>(zeroing<T>(real), zeroing<T>(imag)) {} | ||
// downcast | ||
operator std::complex<T>() const { | ||
return *static_cast<std::complex<T> const*>(this); | ||
} | ||
}; | ||
|
||
} // namespace math | ||
} // namespace stan | ||
#endif |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,50 @@ | ||
#ifndef STAN_MATH_PRIM_CPLX_OPERATOR_ADDITION_HPP | ||
#define STAN_MATH_PRIM_CPLX_OPERATOR_ADDITION_HPP | ||
|
||
#include <stan/math/prim/scal/fun/copysign.hpp> | ||
#include <stan/math/prim/scal/fun/complex_promote.hpp> | ||
#include <stan/math/prim/scal/fun/isfinite.hpp> | ||
#include <stan/math/prim/scal/meta/is_arith_like.hpp> | ||
#include <stan/math/prim/scal/meta/is_complex.hpp> | ||
#include <stan/math/prim/scal/meta/is_fr_var.hpp> | ||
#include <complex> | ||
|
||
namespace stan { | ||
namespace math { | ||
|
||
/** | ||
* Return the sum of the specified arguments | ||
* | ||
* @tparam T type of complex first argument | ||
* @tparam U type of second argument | ||
* @param t complex first argument | ||
* @param u second argument | ||
* @return sum | ||
*/ | ||
template <class T, class U, | ||
std::enable_if_t<is_fr_var<T, U>::value | ||
&& (is_complex<U>::value | ||
|| is_arith_like<U>::value)>* = nullptr> | ||
inline auto operator+(std::complex<T> const& t, U const& u) { | ||
return complex_promote<U>(t) += u; | ||
} | ||
|
||
/** | ||
* Return the sum of the specified arguments | ||
* | ||
* @tparam T type of first argument | ||
* @tparam U type of complex second argument | ||
* @param t first argument | ||
* @param u complex second argument | ||
* @return sum | ||
*/ | ||
template <class T, class U, | ||
std::enable_if_t<is_fr_var<T, U>::value | ||
&& is_arith_like<T>::value>* = nullptr> | ||
inline auto operator+(T const& t, std::complex<U> const& u) { | ||
return complex_promote<U>(t) += u; | ||
} | ||
|
||
} // namespace math | ||
} // namespace stan | ||
#endif |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A bunch of questions:
isinf
and notis_inf
)isinf
in thestan::math
namespace? I'm guessing you need it in thestd
namespace?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I see how we've handled it elsewhere. Is there a reason we can't do the same here? By that, I mean specialize
isnan
andisinf
forstan::math::fvar<T>
and include it in its own header file calledstan/math/fwd/core/std_isnan.hpp
andstd_isinf
?See:
stan/math/fwd/core/std_numeric_limits.hpp
stan/math/rev/core/std_isnan.hpp
stan/math/rev/core/std_numeric_limits.hpp
stan/math/rev/core/std_isinf.hpp
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you clarify? What other packages? I didn't see anywhere in this pull request that this is meant to work with other packages.
(I just found a stackoverflow post on isnan outside of any namespace; is this something you've run into or is this hypothetical?)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we're way past that;
std::complex
for our types are unspecified. We should do what we can verify is correct, is maintainable, and makes sense.