From 4727ac706803fc9eedf29cd0bcc28555421f9334 Mon Sep 17 00:00:00 2001 From: Nicusor Serban <48496524+serban-nicusor-toptal@users.noreply.github.com> Date: Thu, 18 Jul 2019 23:24:46 +0200 Subject: [PATCH 001/355] Fixed typo in release notes --- RELEASE-NOTES.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/RELEASE-NOTES.txt b/RELEASE-NOTES.txt index b378bfecdae..1f0b2660ae0 100644 --- a/RELEASE-NOTES.txt +++ b/RELEASE-NOTES.txt @@ -1,7 +1,7 @@ Stan Math Library Release Notes ====================================================================== -v2.19.2 (18 July 2019) +v2.20.0 (18 July 2019) ====================================================================== New Features From a7070395b70198647ae5e80a7417a9523f4655af Mon Sep 17 00:00:00 2001 From: Nicusor Serban Date: Fri, 18 Oct 2019 21:49:02 +0200 Subject: [PATCH 002/355] Revert "release/v2.21.0: updating version numbers" This reverts commit a50deb9f6dbc35ba221e3685b9d8a19202a80fd9. --- .github/ISSUE_TEMPLATE.md | 2 +- RELEASE-NOTES.txt | 84 --------------------------------------- doxygen/doxygen.cfg | 2 +- stan/math/version.hpp | 2 +- 4 files changed, 3 insertions(+), 87 deletions(-) diff --git a/.github/ISSUE_TEMPLATE.md b/.github/ISSUE_TEMPLATE.md index 963186bcf5d..6127caf2694 100644 --- a/.github/ISSUE_TEMPLATE.md +++ b/.github/ISSUE_TEMPLATE.md @@ -25,4 +25,4 @@ If this is a **feature request**, show what you expect to happen if the feature #### Current Version: -v2.21.0 +v2.20.0 diff --git a/RELEASE-NOTES.txt b/RELEASE-NOTES.txt index 8351a003dfc..1f0b2660ae0 100644 --- a/RELEASE-NOTES.txt +++ b/RELEASE-NOTES.txt @@ -1,89 +1,5 @@ Stan Math Library Release Notes -====================================================================== -v2.21.0 (18 October 2019) -====================================================================== - -## Features - -PR [#1180](https://github.com/stan-dev/math/pull/1180) brought the [Intel TBB](https://github.com/intel/tbb) into Stan as a dependency, which we will be using in the future for CPU parallelism all across Stan! The TBB is an excellent framework that will let Stan utilize nested parallelism across the algorithms and gradient evaluations. The licensing for the Intel TBB library is under the Apache 2.0 license. This dependency implies an additional restriction as compared to the new BSD license alone. The Apache 2.0 license is incompatible with GPL-2 licensed code if the software if distributing the software as a unitary binary. Refer to the Apache 2.0 evaluation page on the Stan Math [wiki](https://github.com/stan-dev/math/wiki/Apache-2.0-License-Evaluation). - -With @t4c1's large contributions, we now have GPU/OpenCL support for many of our glm functions! @rok-cesnovar added an OpenCL reverse mode specialization for `multiplication` and `mdivide_left_tri` while @t4c1 added the OpenCL specialization for `gp_exp_quad_cov`. - -Some other nice features include @andrjohns vectorizing the Dirichlet distribution, @IvanYashchuk implementing a reverse mode specialization for inverse, and @yizhang-yiz with @charlesm93 adding fixed point algebra solvers based on Sundial's KINSOL scheme. - -Internally, @bob-carpenter added a new AD testing framework, which both replaced 18,539 of code with 2,500 and simultaneously increased our test coverage! @Stevebronder added a type traits metaprogramming scheme so that we can make use of more generic templating in a lot of our code. Last but not least, @andrjohns standardized a lot of our code to use standard library functions instead of our hand-rolled methods. - -## Fixes - -@wds15 patched the way we use `lgamma` so that it's faster in concurrent settings. A speedy patch came in from @t4c1 when @jgabry reported intercept only glm specializations with size zero matrices could give the wrong output. We had several patches and code cleanups in the OpenCL code, mostly testing and improving the type trait system around the OpenCL methods. @nhuurre patched `log_sum_exp` and `log_diff_exp` so that the methods respected boundary conditions a bit better. Stan also now uses `clang-tidy,` which gives us an automated way to keep the code base standardized. - -## Features List - -|Contributor |Title | -|:---------------------------------------------------------------------------------------------------------|:----------------------------------------------------------------------------------------------| -|[bob-carpenter](https://github.com/bob-carpenter) : ([#1384](https://github.com/stan-dev/math/pull/1384)) |Feature/1382 remove fvar nan checks | -|[wds15](https://github.com/wds15) : ([#1376](https://github.com/stan-dev/math/pull/1376)) |integrate Intel TBB | -|[yizhang-yiz](https://github.com/yizhang-yiz) : ([#1371](https://github.com/stan-dev/math/pull/1371)) |Feature fp solver | -|[t4c1](https://github.com/t4c1) : ([#1366](https://github.com/stan-dev/math/pull/1366)) |Gpu ordered_logistic_glm_lpmf and categorical_logit_glm_lpmf | -|[t4c1](https://github.com/t4c1) : ([#1365](https://github.com/stan-dev/math/pull/1365)) |Gpu neg_binomial_2_log_glm | -|[andrjohns](https://github.com/andrjohns) : ([#1363](https://github.com/stan-dev/math/pull/1363)) |Issue 1362 - Vectorised Dirichlet distribution | -|[rok-cesnovar](https://github.com/rok-cesnovar) : ([#1355](https://github.com/stan-dev/math/pull/1355)) |Feature/issue 1354 Implement matrix_cl overloads for rep_vector, rep_row_vector and rep_matrix | -|[rok-cesnovar](https://github.com/rok-cesnovar) : ([#1353](https://github.com/stan-dev/math/pull/1353)) |Revert GPU caching | -|[t4c1](https://github.com/t4c1) : ([#1350](https://github.com/stan-dev/math/pull/1350)) |Gpu poisson bernoulli glms | -|[SteveBronder](https://github.com/SteveBronder) : ([#1344](https://github.com/stan-dev/math/pull/1344)) |Adds require_* template type traits | -|[charlesm93](https://github.com/charlesm93) : ([#1339](https://github.com/stan-dev/math/pull/1339)) |Feature/issue 1115 newton solver | -|[IvanYashchuk](https://github.com/IvanYashchuk) : ([#1334](https://github.com/stan-dev/math/pull/1334)) |Implemented reverse mode for inverse | -|[t4c1](https://github.com/t4c1) : ([#1333](https://github.com/stan-dev/math/pull/1333)) |Implement normal_id_glm_lpdf in OpenCL | -|[rok-cesnovar](https://github.com/rok-cesnovar) : ([#1329](https://github.com/stan-dev/math/pull/1329)) |Feature/Issue 1294 Rewrite the test-math-dependencies script in Python | -|[SteveBronder](https://github.com/SteveBronder) : ([#1323](https://github.com/stan-dev/math/pull/1323)) |Adds const ref and ref returns for to_var/fvar methods | -|[andrjohns](https://github.com/andrjohns) : ([#1318](https://github.com/stan-dev/math/pull/1318)) |Issue 1010 - Replace hand-coded math with standard library c++11 functions | -|[rok-cesnovar](https://github.com/rok-cesnovar) : ([#1303](https://github.com/stan-dev/math/pull/1303)) |Feature/issue 1221 Use OpenCL in rev/mdivide_left_tri | -|[andrjohns](https://github.com/andrjohns) : ([#1296](https://github.com/stan-dev/math/pull/1296)) |issue 1279 - Remove deprecated Eigen content from math headers | -|[t4c1](https://github.com/t4c1) : ([#1293](https://github.com/stan-dev/math/pull/1293)) |OpenCL matrix multiplication optimizations | -|[andrjohns](https://github.com/andrjohns) : ([#1283](https://github.com/stan-dev/math/pull/1283)) |Refactor rev/mat with eigen plugin methods | -|[SteveBronder](https://github.com/SteveBronder) : ([#1281](https://github.com/stan-dev/math/pull/1281)) |Add a double template to matrix_cl | -|[bob-carpenter](https://github.com/bob-carpenter) : ([#1262](https://github.com/stan-dev/math/pull/1262)) |Feature/1258 ad test core | -|[t4c1](https://github.com/t4c1) : ([#1252](https://github.com/stan-dev/math/pull/1252)) |Implement ordinal regression GLM (ordered_logistic_glm_lpmf) | -|[t4c1](https://github.com/t4c1) : ([#1206](https://github.com/stan-dev/math/pull/1206)) |opencl prim gp_exp_quad_cov | -|[rok-cesnovar](https://github.com/rok-cesnovar) : ([#1305](https://github.com/stan-dev/math/pull/1305)) |Feature/issue 1221 Use OpenCL in rev/multiply | -|[rok-cesnovar](https://github.com/rok-cesnovar) : ([#1278](https://github.com/stan-dev/math/pull/1278)) |Feature/1221 OpenCL primitive multiply | -|[t4c1](https://github.com/t4c1) : ([#1299](https://github.com/stan-dev/math/pull/1299)) |mdivide_right_tri can use OpenCL | -|[wds15](https://github.com/wds15) : ([#1180](https://github.com/stan-dev/math/pull/1180)) |Feature/intel tbb lib | - -## Fixes - -|Contributor |Title | -|:-------------------------------------------------------------------------------------------------------|:-------------------------------------------------------------------------------| -|[wds15](https://github.com/wds15) : ([#1401](https://github.com/stan-dev/math/pull/1401)) |Bugfix/tbb cleanup | -|[t4c1](https://github.com/t4c1) : ([#1399](https://github.com/stan-dev/math/pull/1399)) |bugfix intercept only GLMs | -|[wds15](https://github.com/wds15) : ([#1395](https://github.com/stan-dev/math/pull/1395)) |allow spaces in path leading to stan-directory in makefiles | -|[SteveBronder](https://github.com/SteveBronder) : ([#1392](https://github.com/stan-dev/math/pull/1392)) |Add /lib/tbb/** to the .gitignore | -|[rok-cesnovar](https://github.com/rok-cesnovar) : ([#1375](https://github.com/stan-dev/math/pull/1375)) |Fix bug in stack_alloc_test | -|[rok-cesnovar](https://github.com/rok-cesnovar) : ([#1369](https://github.com/stan-dev/math/pull/1369)) |Bugfix/remove unused vectorize test | -|[rok-cesnovar](https://github.com/rok-cesnovar) : ([#1364](https://github.com/stan-dev/math/pull/1364)) |Reorganize /opencl and add missing matrix_cl overloads | -|[rok-cesnovar](https://github.com/rok-cesnovar) : ([#1361](https://github.com/stan-dev/math/pull/1361)) |Remove const qualifier from matrix_cl rows & cols | -|[t4c1](https://github.com/t4c1) : ([#1358](https://github.com/stan-dev/math/pull/1358)) |Split opencl glm function | -|[SteveBronder](https://github.com/SteveBronder) : ([#1356](https://github.com/stan-dev/math/pull/1356)) |Bugfix for making matrix_cls from temporaries | -|[SteveBronder](https://github.com/SteveBronder) : ([#1341](https://github.com/stan-dev/math/pull/1341)) |Refactor Type Traits | -|[SteveBronder](https://github.com/SteveBronder) : ([#1340](https://github.com/stan-dev/math/pull/1340)) |Refactor/clang tidy cleanup | -|[SteveBronder](https://github.com/SteveBronder) : ([#1337](https://github.com/stan-dev/math/pull/1337)) |Update OpenCL Headers | -|[SteveBronder](https://github.com/SteveBronder) : ([#1331](https://github.com/stan-dev/math/pull/1331)) |Moves if statements for scal/prob/beta-binomial out of for loops | -|[rok-cesnovar](https://github.com/rok-cesnovar) : ([#1330](https://github.com/stan-dev/math/pull/1330)) |Remove EXPECT_DEATH unit tests that fail when -NDEBUG is set | -|[SteveBronder](https://github.com/SteveBronder) : ([#1327](https://github.com/stan-dev/math/pull/1327)) |Adds clang-tidy to makefile | -|[t4c1](https://github.com/t4c1) : ([#1314](https://github.com/stan-dev/math/pull/1314)) |fix matrix_cl_view test | -|[t4c1](https://github.com/t4c1) : ([#1311](https://github.com/stan-dev/math/pull/1311)) |Fixed matrix_cl copying and moving | -|[rok-cesnovar](https://github.com/rok-cesnovar) : ([#1310](https://github.com/stan-dev/math/pull/1310)) |Cleanup/issue #1301 remove unnecessary Boost and other compiler flags | -|[rok-cesnovar](https://github.com/rok-cesnovar) : ([#1304](https://github.com/stan-dev/math/pull/1304)) |Re-apply #1278 OpenCL prim multiply | -|[SteveBronder](https://github.com/SteveBronder) : ([#1298](https://github.com/stan-dev/math/pull/1298)) |make key of map for opencl kernel options into a string | -|[SteveBronder](https://github.com/SteveBronder) : ([#1291](https://github.com/stan-dev/math/pull/1291)) |Changes all prim files to use *_return_type_t instead of typename *_return_type | -|[nhuurre](https://github.com/nhuurre) : ([#1290](https://github.com/stan-dev/math/pull/1290)) |Bugfix/646 log_sum_exp and log_diff_exp boundaries | -|[SteveBronder](https://github.com/SteveBronder) : ([#1289](https://github.com/stan-dev/math/pull/1289)) |Refactor for enable_if functions | -|[SteveBronder](https://github.com/SteveBronder) : ([#1286](https://github.com/stan-dev/math/pull/1286)) |Removes extra loops in Jacobian calculations | -|[t4c1](https://github.com/t4c1) : ([#1266](https://github.com/stan-dev/math/pull/1266)) |Added triangularity attribute to matrix_cl | -|[t4c1](https://github.com/t4c1) : ([#1261](https://github.com/stan-dev/math/pull/1261)) |GLM tests improvements | -|[wds15](https://github.com/wds15) : ([#1255](https://github.com/stan-dev/math/pull/1255)) |Bugfix/issue 1250 lgamma | - ====================================================================== v2.20.0 (18 July 2019) ====================================================================== diff --git a/doxygen/doxygen.cfg b/doxygen/doxygen.cfg index be71ec3b7fc..9ac53d0280e 100644 --- a/doxygen/doxygen.cfg +++ b/doxygen/doxygen.cfg @@ -38,7 +38,7 @@ PROJECT_NAME = "Stan Math Library" # could be handy for archiving the generated documentation or if some version # control system is used. -PROJECT_NUMBER = 2.21.0 +PROJECT_NUMBER = 2.20.0 # 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 diff --git a/stan/math/version.hpp b/stan/math/version.hpp index d70c4badca3..b64aff29ae8 100644 --- a/stan/math/version.hpp +++ b/stan/math/version.hpp @@ -12,7 +12,7 @@ #endif #define STAN_MATH_MAJOR 2 -#define STAN_MATH_MINOR 21 +#define STAN_MATH_MINOR 20 #define STAN_MATH_PATCH 0 namespace stan { From d4e4f15aea1b2883efe700048e216bac68b225d9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rok=20=C4=8Ce=C5=A1novar?= Date: Wed, 29 Jan 2020 19:05:54 +0100 Subject: [PATCH 003/355] Fixed conflict in stan/math/prim/fun/log_softmax.hpp --- stan/math/prim/fun/acos.hpp | 2 +- stan/math/prim/fun/asin.hpp | 2 +- stan/math/prim/fun/atan.hpp | 2 +- stan/math/prim/fun/ceil.hpp | 2 +- stan/math/prim/fun/cos.hpp | 2 +- stan/math/prim/fun/cosh.hpp | 2 +- stan/math/prim/fun/exp.hpp | 2 +- stan/math/prim/fun/fabs.hpp | 4 ++-- stan/math/prim/fun/floor.hpp | 2 +- stan/math/prim/fun/inv.hpp | 4 ++-- stan/math/prim/fun/inv_cloglog.hpp | 4 ++-- stan/math/prim/fun/inv_sqrt.hpp | 4 ++-- stan/math/prim/fun/log.hpp | 2 +- stan/math/prim/fun/log10.hpp | 2 +- stan/math/prim/fun/log_softmax.hpp | 11 ++++++----- stan/math/prim/fun/minus.hpp | 4 +++- stan/math/prim/fun/round.hpp | 2 +- stan/math/prim/fun/sin.hpp | 2 +- stan/math/prim/fun/sinh.hpp | 4 ++-- stan/math/prim/fun/sqrt.hpp | 2 +- stan/math/prim/fun/tan.hpp | 2 +- stan/math/prim/fun/tanh.hpp | 2 +- stan/math/prim/vectorize/apply_scalar_unary.hpp | 7 +++++-- test/unit/math/prim/fun/Phi_approx_test.cpp | 8 ++++++++ test/unit/math/prim/fun/Phi_test.cpp | 8 ++++++++ test/unit/math/prim/fun/acos_test.cpp | 8 ++++++++ test/unit/math/prim/fun/acosh_test.cpp | 8 ++++++++ test/unit/math/prim/fun/asin_test.cpp | 8 ++++++++ test/unit/math/prim/fun/asinh_test.cpp | 8 ++++++++ test/unit/math/prim/fun/atan_test.cpp | 8 ++++++++ test/unit/math/prim/fun/atanh_test.cpp | 8 ++++++++ test/unit/math/prim/fun/cbrt_test.cpp | 8 ++++++++ test/unit/math/prim/fun/ceil_test.cpp | 8 ++++++++ test/unit/math/prim/fun/cos_test.cpp | 8 ++++++++ test/unit/math/prim/fun/cosh_test.cpp | 10 ++++++++++ test/unit/math/prim/fun/digamma_test.cpp | 8 ++++++++ test/unit/math/prim/fun/erf_test.cpp | 8 ++++++++ test/unit/math/prim/fun/erfc_test.cpp | 8 ++++++++ test/unit/math/prim/fun/exp2_test.cpp | 8 ++++++++ test/unit/math/prim/fun/exp_test.cpp | 8 ++++++++ test/unit/math/prim/fun/expm1_test.cpp | 8 ++++++++ test/unit/math/prim/fun/fabs_test.cpp | 8 ++++++++ test/unit/math/prim/fun/floor_test.cpp | 8 ++++++++ test/unit/math/prim/fun/inv_Phi_test.cpp | 8 ++++++++ test/unit/math/prim/fun/inv_cloglog_test.cpp | 8 ++++++++ test/unit/math/prim/fun/inv_logit_test.cpp | 8 ++++++++ test/unit/math/prim/fun/inv_sqrt_test.cpp | 8 ++++++++ test/unit/math/prim/fun/inv_square_test.cpp | 8 ++++++++ test/unit/math/prim/fun/inv_test.cpp | 8 ++++++++ test/unit/math/prim/fun/lgamma_test.cpp | 8 ++++++++ test/unit/math/prim/fun/log10_test.cpp | 8 ++++++++ test/unit/math/prim/fun/log1m_test.cpp | 8 ++++++++ test/unit/math/prim/fun/log1p_exp_test.cpp | 8 ++++++++ test/unit/math/prim/fun/log1p_test.cpp | 8 ++++++++ test/unit/math/prim/fun/log2_test.cpp | 8 ++++++++ test/unit/math/prim/fun/log_inv_logit_test.cpp | 8 ++++++++ test/unit/math/prim/fun/log_softmax_test.cpp | 8 ++++++++ test/unit/math/prim/fun/log_test.cpp | 8 ++++++++ test/unit/math/prim/fun/logit_test.cpp | 8 ++++++++ test/unit/math/prim/fun/minus_test.cpp | 8 ++++++++ test/unit/math/prim/fun/round_test.cpp | 8 ++++++++ test/unit/math/prim/fun/sin_test.cpp | 8 ++++++++ test/unit/math/prim/fun/sinh_test.cpp | 8 ++++++++ test/unit/math/prim/fun/sqrt_test.cpp | 8 ++++++++ test/unit/math/prim/fun/square_test.cpp | 10 +++++++++- test/unit/math/prim/fun/tan_test.cpp | 10 ++++++++++ test/unit/math/prim/fun/tanh_test.cpp | 8 ++++++++ test/unit/math/prim/fun/tgamma_test.cpp | 8 ++++++++ test/unit/math/prim/fun/trigamma_test.cpp | 8 ++++++++ test/unit/math/prim/fun/trunc_test.cpp | 8 ++++++++ 70 files changed, 420 insertions(+), 34 deletions(-) create mode 100644 test/unit/math/prim/fun/cosh_test.cpp create mode 100644 test/unit/math/prim/fun/tan_test.cpp diff --git a/stan/math/prim/fun/acos.hpp b/stan/math/prim/fun/acos.hpp index 709864e1db6..e5960f1b758 100644 --- a/stan/math/prim/fun/acos.hpp +++ b/stan/math/prim/fun/acos.hpp @@ -45,7 +45,7 @@ inline auto acos(const T& x) { template > inline auto acos(const Eigen::MatrixBase& x) { - return x.derived().array().acos().matrix(); + return x.derived().array().acos().matrix().eval(); } } // namespace math diff --git a/stan/math/prim/fun/asin.hpp b/stan/math/prim/fun/asin.hpp index 81a22dcf60b..0f5d172a29b 100644 --- a/stan/math/prim/fun/asin.hpp +++ b/stan/math/prim/fun/asin.hpp @@ -45,7 +45,7 @@ inline auto asin(const T& x) { template > inline auto asin(const Eigen::MatrixBase& x) { - return x.derived().array().asin().matrix(); + return x.derived().array().asin().matrix().eval(); } } // namespace math diff --git a/stan/math/prim/fun/atan.hpp b/stan/math/prim/fun/atan.hpp index 28a05b08d6a..9576c99240a 100644 --- a/stan/math/prim/fun/atan.hpp +++ b/stan/math/prim/fun/atan.hpp @@ -45,7 +45,7 @@ inline typename apply_scalar_unary::return_t atan(const T& x) { template > inline auto atan(const Eigen::MatrixBase& x) { - return x.derived().array().atan().matrix(); + return x.derived().array().atan().matrix().eval(); } } // namespace math diff --git a/stan/math/prim/fun/ceil.hpp b/stan/math/prim/fun/ceil.hpp index 7a78566ac1d..2de0ddb72e7 100644 --- a/stan/math/prim/fun/ceil.hpp +++ b/stan/math/prim/fun/ceil.hpp @@ -45,7 +45,7 @@ inline auto ceil(const T& x) { template > inline auto ceil(const Eigen::MatrixBase& x) { - return x.derived().array().ceil().matrix(); + return x.derived().array().ceil().matrix().eval(); } } // namespace math diff --git a/stan/math/prim/fun/cos.hpp b/stan/math/prim/fun/cos.hpp index 0c20e53f935..bf9761ace9f 100644 --- a/stan/math/prim/fun/cos.hpp +++ b/stan/math/prim/fun/cos.hpp @@ -45,7 +45,7 @@ inline auto cos(const T& x) { template > inline auto cos(const Eigen::MatrixBase& x) { - return x.derived().array().cos().matrix(); + return x.derived().array().cos().matrix().eval(); } } // namespace math diff --git a/stan/math/prim/fun/cosh.hpp b/stan/math/prim/fun/cosh.hpp index 3dee3eae2a3..2a0402fe9c2 100644 --- a/stan/math/prim/fun/cosh.hpp +++ b/stan/math/prim/fun/cosh.hpp @@ -45,7 +45,7 @@ inline typename apply_scalar_unary::return_t cosh(const T& x) { template > inline auto cosh(const Eigen::MatrixBase& x) { - return x.derived().array().cosh().matrix(); + return x.derived().array().cosh().matrix().eval(); } } // namespace math diff --git a/stan/math/prim/fun/exp.hpp b/stan/math/prim/fun/exp.hpp index 4d60b4c04b5..54486d9e394 100644 --- a/stan/math/prim/fun/exp.hpp +++ b/stan/math/prim/fun/exp.hpp @@ -60,7 +60,7 @@ inline auto exp(const T& x) { template > inline auto exp(const Eigen::MatrixBase& x) { - return x.derived().array().exp().matrix(); + return x.derived().array().exp().matrix().eval(); } } // namespace math diff --git a/stan/math/prim/fun/fabs.hpp b/stan/math/prim/fun/fabs.hpp index 1dc51b0ee3c..2bfc97071d2 100644 --- a/stan/math/prim/fun/fabs.hpp +++ b/stan/math/prim/fun/fabs.hpp @@ -45,7 +45,7 @@ inline typename apply_scalar_unary::return_t fabs(const T& x) { template > inline auto fabs(const Eigen::MatrixBase& x) { - return x.derived().array().abs().matrix(); + return x.derived().array().abs().matrix().eval(); } /** @@ -57,7 +57,7 @@ inline auto fabs(const Eigen::MatrixBase& x) { template > inline auto fabs(const Eigen::ArrayBase& x) { - return x.derived().abs(); + return x.derived().abs().eval(); } } // namespace math diff --git a/stan/math/prim/fun/floor.hpp b/stan/math/prim/fun/floor.hpp index 7f1f37317cd..c53433cf356 100644 --- a/stan/math/prim/fun/floor.hpp +++ b/stan/math/prim/fun/floor.hpp @@ -45,7 +45,7 @@ inline auto floor(const T& x) { template > inline auto floor(const Eigen::MatrixBase& x) { - return x.derived().array().floor().matrix(); + return x.derived().array().floor().matrix().eval(); } } // namespace math diff --git a/stan/math/prim/fun/inv.hpp b/stan/math/prim/fun/inv.hpp index f50f17f784c..439dc962778 100644 --- a/stan/math/prim/fun/inv.hpp +++ b/stan/math/prim/fun/inv.hpp @@ -45,7 +45,7 @@ inline auto inv(const T& x) { template > inline auto inv(const Eigen::MatrixBase& x) { - return x.derived().array().inverse().matrix(); + return x.derived().array().inverse().matrix().eval(); } /** @@ -57,7 +57,7 @@ inline auto inv(const Eigen::MatrixBase& x) { template > inline auto inv(const Eigen::ArrayBase& x) { - return x.derived().inverse(); + return x.derived().inverse().eval(); } } // namespace math diff --git a/stan/math/prim/fun/inv_cloglog.hpp b/stan/math/prim/fun/inv_cloglog.hpp index 945417aa0f9..44c6dfdc8d7 100644 --- a/stan/math/prim/fun/inv_cloglog.hpp +++ b/stan/math/prim/fun/inv_cloglog.hpp @@ -87,7 +87,7 @@ inline auto inv_cloglog(const T& x) { template > inline auto inv_cloglog(const Eigen::MatrixBase& x) { - return (1 - exp(-exp(x.derived().array()))).matrix(); + return (1 - exp(-exp(x.derived().array()))).matrix().eval(); } /** @@ -99,7 +99,7 @@ inline auto inv_cloglog(const Eigen::MatrixBase& x) { template > inline auto inv_cloglog(const Eigen::ArrayBase& x) { - return 1 - exp(-exp(x.derived())); + return (1 - exp(-exp(x.derived()))).eval(); } } // namespace math diff --git a/stan/math/prim/fun/inv_sqrt.hpp b/stan/math/prim/fun/inv_sqrt.hpp index aa6e0d7ffdf..66b41ee7138 100644 --- a/stan/math/prim/fun/inv_sqrt.hpp +++ b/stan/math/prim/fun/inv_sqrt.hpp @@ -50,7 +50,7 @@ inline auto inv_sqrt(const T& x) { template > inline auto inv_sqrt(const Eigen::MatrixBase& x) { - return x.derived().array().rsqrt().matrix(); + return x.derived().array().rsqrt().matrix().eval(); } /** @@ -62,7 +62,7 @@ inline auto inv_sqrt(const Eigen::MatrixBase& x) { template > inline auto inv_sqrt(const Eigen::ArrayBase& x) { - return x.derived().rsqrt(); + return x.derived().rsqrt().eval(); } } // namespace math diff --git a/stan/math/prim/fun/log.hpp b/stan/math/prim/fun/log.hpp index 2e32bc5aa4b..3814d0a5ae5 100644 --- a/stan/math/prim/fun/log.hpp +++ b/stan/math/prim/fun/log.hpp @@ -60,7 +60,7 @@ inline auto log(const T& x) { template > inline auto log(const Eigen::MatrixBase& x) { - return x.derived().array().log().matrix(); + return x.derived().array().log().matrix().eval(); } } // namespace math diff --git a/stan/math/prim/fun/log10.hpp b/stan/math/prim/fun/log10.hpp index 808bdb85bad..10b7b0fa1b0 100644 --- a/stan/math/prim/fun/log10.hpp +++ b/stan/math/prim/fun/log10.hpp @@ -45,7 +45,7 @@ inline auto log10(const T& x) { template > inline auto log10(const Eigen::MatrixBase& x) { - return x.derived().array().log10().matrix(); + return x.derived().array().log10().matrix().eval(); } } // namespace math diff --git a/stan/math/prim/fun/log_softmax.hpp b/stan/math/prim/fun/log_softmax.hpp index a51370d0b1a..8c4951df779 100644 --- a/stan/math/prim/fun/log_softmax.hpp +++ b/stan/math/prim/fun/log_softmax.hpp @@ -36,11 +36,12 @@ namespace math { * @param[in] v Vector to transform. * @return Unit simplex result of the softmax transform of the vector. */ -template -inline Eigen::Matrix log_softmax( - const Eigen::Matrix& v) { - check_nonzero_size("log_softmax", "v", v); - return v.array() - log_sum_exp(v); +template >>...> +inline auto log_softmax(const T& x) { + return apply_vector_unary::apply(x, [&](const auto& v) { + check_nonzero_size("log_softmax", "v", v); + return (v.array() - log_sum_exp(v)).matrix().eval(); + }); } } // namespace math diff --git a/stan/math/prim/fun/minus.hpp b/stan/math/prim/fun/minus.hpp index 7f374462fc0..13fe7d090ed 100644 --- a/stan/math/prim/fun/minus.hpp +++ b/stan/math/prim/fun/minus.hpp @@ -1,6 +1,8 @@ #ifndef STAN_MATH_PRIM_FUN_MINUS_HPP #define STAN_MATH_PRIM_FUN_MINUS_HPP +#include + namespace stan { namespace math { @@ -12,7 +14,7 @@ namespace math { * @return Negation of subtrahend. */ template -inline auto minus(const T& x) { +inline plain_type_t minus(const T& x) { return -x; } diff --git a/stan/math/prim/fun/round.hpp b/stan/math/prim/fun/round.hpp index 66b2d6a428c..e5cc48efd18 100644 --- a/stan/math/prim/fun/round.hpp +++ b/stan/math/prim/fun/round.hpp @@ -62,7 +62,7 @@ inline auto round(const T& x) { template > inline auto round(const Eigen::MatrixBase& x) { - return x.derived().array().round().matrix(); + return x.derived().array().round().matrix().eval(); } } // namespace math diff --git a/stan/math/prim/fun/sin.hpp b/stan/math/prim/fun/sin.hpp index f2ed9102f97..0b783ffeb20 100644 --- a/stan/math/prim/fun/sin.hpp +++ b/stan/math/prim/fun/sin.hpp @@ -45,7 +45,7 @@ inline auto sin(const T& x) { template > inline auto sin(const Eigen::MatrixBase& x) { - return x.derived().array().sin().matrix(); + return x.derived().array().sin().matrix().eval(); } } // namespace math diff --git a/stan/math/prim/fun/sinh.hpp b/stan/math/prim/fun/sinh.hpp index 5e13a03993e..e4d1252295d 100644 --- a/stan/math/prim/fun/sinh.hpp +++ b/stan/math/prim/fun/sinh.hpp @@ -45,7 +45,7 @@ inline auto sinh(const T& x) { template > inline auto sinh(const Eigen::MatrixBase& x) { - return x.derived().array().sinh().matrix(); + return x.derived().array().sinh().matrix().eval(); } /** @@ -57,7 +57,7 @@ inline auto sinh(const Eigen::MatrixBase& x) { template > inline auto sinh(const Eigen::ArrayBase& x) { - return x.derived().sinh(); + return x.derived().sinh().eval(); } } // namespace math diff --git a/stan/math/prim/fun/sqrt.hpp b/stan/math/prim/fun/sqrt.hpp index ae1b6dace93..fe81fcf75b6 100644 --- a/stan/math/prim/fun/sqrt.hpp +++ b/stan/math/prim/fun/sqrt.hpp @@ -54,7 +54,7 @@ inline auto sqrt(const T& x) { template > inline auto sqrt(const Eigen::MatrixBase& x) { - return x.derived().array().sqrt().matrix(); + return x.derived().array().sqrt().matrix().eval(); } } // namespace math diff --git a/stan/math/prim/fun/tan.hpp b/stan/math/prim/fun/tan.hpp index 7064300e695..efc03beb94b 100644 --- a/stan/math/prim/fun/tan.hpp +++ b/stan/math/prim/fun/tan.hpp @@ -45,7 +45,7 @@ inline auto tan(const T& x) { template > inline auto tan(const Eigen::MatrixBase& x) { - return x.derived().array().tan().matrix(); + return x.derived().array().tan().matrix().eval(); } } // namespace math diff --git a/stan/math/prim/fun/tanh.hpp b/stan/math/prim/fun/tanh.hpp index 60c4d405fb2..2fe9f4c5a25 100644 --- a/stan/math/prim/fun/tanh.hpp +++ b/stan/math/prim/fun/tanh.hpp @@ -45,7 +45,7 @@ inline auto tanh(const T& x) { template > inline auto tanh(const Eigen::MatrixBase& x) { - return x.derived().array().tanh().matrix(); + return x.derived().array().tanh().matrix().eval(); } } // namespace math diff --git a/stan/math/prim/vectorize/apply_scalar_unary.hpp b/stan/math/prim/vectorize/apply_scalar_unary.hpp index ed31037a207..8cc283cd4ac 100644 --- a/stan/math/prim/vectorize/apply_scalar_unary.hpp +++ b/stan/math/prim/vectorize/apply_scalar_unary.hpp @@ -59,8 +59,11 @@ struct apply_scalar_unary> { * by F to the specified matrix. */ static inline auto apply(const T& x) { - return x.unaryExpr( - [](scalar_t x) { return apply_scalar_unary::apply(x); }); + return x + .unaryExpr([](scalar_t x) { + return apply_scalar_unary::apply(x); + }) + .eval(); } /** diff --git a/test/unit/math/prim/fun/Phi_approx_test.cpp b/test/unit/math/prim/fun/Phi_approx_test.cpp index dbc4078352d..4a29923c572 100644 --- a/test/unit/math/prim/fun/Phi_approx_test.cpp +++ b/test/unit/math/prim/fun/Phi_approx_test.cpp @@ -14,3 +14,11 @@ TEST(MathFunctions, Phi_approx_nan) { EXPECT_TRUE(std::isnan(stan::math::Phi_approx(nan))); } + +TEST(MathFunctions, Phi_approx__works_with_other_functions) { + Eigen::VectorXd a(5); + a << 1.1, 1.2, 1.3, 1.4, 1.5; + Eigen::RowVectorXd b(5); + b << 1.1, 1.2, 1.3, 1.4, 1.5; + stan::math::multiply(a, stan::math::Phi_approx(b)); +} diff --git a/test/unit/math/prim/fun/Phi_test.cpp b/test/unit/math/prim/fun/Phi_test.cpp index c43e260bf88..1273ad24628 100644 --- a/test/unit/math/prim/fun/Phi_test.cpp +++ b/test/unit/math/prim/fun/Phi_test.cpp @@ -118,3 +118,11 @@ TEST(MathFunctions, Phi_nan) { double nan = std::numeric_limits::quiet_NaN(); EXPECT_THROW(stan::math::Phi(nan), std::domain_error); } + +TEST(MathFunctions, Phi_works_with_other_functions) { + Eigen::VectorXd a(5); + a << 1.1, 1.2, 1.3, 1.4, 1.5; + Eigen::RowVectorXd b(5); + b << 1.1, 1.2, 1.3, 1.4, 1.5; + stan::math::multiply(a, stan::math::Phi(b)); +} diff --git a/test/unit/math/prim/fun/acos_test.cpp b/test/unit/math/prim/fun/acos_test.cpp index c66c4c49a02..7570f52cc71 100644 --- a/test/unit/math/prim/fun/acos_test.cpp +++ b/test/unit/math/prim/fun/acos_test.cpp @@ -5,3 +5,11 @@ TEST(primScalFun, acos) { stan::test::expect_common_prim([](auto x) { return std::acos(x); }, [](auto x) { return stan::math::acos(x); }); } + +TEST(MathFunctions, acos_works_with_other_functions) { + Eigen::VectorXd a(5); + a << 0.1, 0.2, 0.3, 0.4, 0.5; + Eigen::RowVectorXd b(5); + b << 0.1, 0.2, 0.3, 0.4, 0.5; + stan::math::multiply(a, stan::math::acos(b)); +} diff --git a/test/unit/math/prim/fun/acosh_test.cpp b/test/unit/math/prim/fun/acosh_test.cpp index 2d5bc742d3c..1f9e8ab7bb5 100644 --- a/test/unit/math/prim/fun/acosh_test.cpp +++ b/test/unit/math/prim/fun/acosh_test.cpp @@ -26,3 +26,11 @@ TEST(MathFunctions, acosh_nan) { double nan = std::numeric_limits::quiet_NaN(); EXPECT_TRUE(std::isnan(stan::math::acosh(nan))); } + +TEST(MathFunctions, acosh_works_with_other_functions) { + Eigen::VectorXd a(5); + a << 1.1, 1.2, 1.3, 1.4, 1.5; + Eigen::RowVectorXd b(5); + b << 1.1, 1.2, 1.3, 1.4, 1.5; + stan::math::multiply(a, stan::math::acosh(b)); +} diff --git a/test/unit/math/prim/fun/asin_test.cpp b/test/unit/math/prim/fun/asin_test.cpp index a14245b58c2..858be5fbbbd 100644 --- a/test/unit/math/prim/fun/asin_test.cpp +++ b/test/unit/math/prim/fun/asin_test.cpp @@ -5,3 +5,11 @@ TEST(primScalFun, asin) { stan::test::expect_common_prim([](auto x) { return std::asin(x); }, [](auto x) { return stan::math::asin(x); }); } + +TEST(MathFunctions, asin_works_with_other_functions) { + Eigen::VectorXd a(5); + a << 0.1, 0.2, 0.3, 0.4, 0.5; + Eigen::RowVectorXd b(5); + b << 0.1, 0.2, 0.3, 0.4, 0.5; + stan::math::multiply(a, stan::math::asin(b)); +} diff --git a/test/unit/math/prim/fun/asinh_test.cpp b/test/unit/math/prim/fun/asinh_test.cpp index 151afc2b3ef..e10228b0af0 100644 --- a/test/unit/math/prim/fun/asinh_test.cpp +++ b/test/unit/math/prim/fun/asinh_test.cpp @@ -22,3 +22,11 @@ TEST(MathFunctions, asinh_nan) { double nan = std::numeric_limits::quiet_NaN(); EXPECT_TRUE(std::isnan(stan::math::asinh(nan))); } + +TEST(MathFunctions, asinh_works_with_other_functions) { + Eigen::VectorXd a(5); + a << 1.1, 1.2, 1.3, 1.4, 1.5; + Eigen::RowVectorXd b(5); + b << 1.1, 1.2, 1.3, 1.4, 1.5; + stan::math::multiply(a, stan::math::asinh(b)); +} diff --git a/test/unit/math/prim/fun/atan_test.cpp b/test/unit/math/prim/fun/atan_test.cpp index 467ceefff7d..54861be5151 100644 --- a/test/unit/math/prim/fun/atan_test.cpp +++ b/test/unit/math/prim/fun/atan_test.cpp @@ -5,3 +5,11 @@ TEST(primScalFun, atan) { stan::test::expect_common_prim([](auto x) { return std::atan(x); }, [](auto x) { return stan::math::atan(x); }); } + +TEST(MathFunctions, atan_works_with_other_functions) { + Eigen::VectorXd a(5); + a << 1.1, 1.2, 1.3, 1.4, 1.5; + Eigen::RowVectorXd b(5); + b << 1.1, 1.2, 1.3, 1.4, 1.5; + stan::math::multiply(a, stan::math::atan(b)); +} diff --git a/test/unit/math/prim/fun/atanh_test.cpp b/test/unit/math/prim/fun/atanh_test.cpp index ca60e585e86..18ae151e23c 100644 --- a/test/unit/math/prim/fun/atanh_test.cpp +++ b/test/unit/math/prim/fun/atanh_test.cpp @@ -27,3 +27,11 @@ TEST(MathFunctions, atanh_nan) { double nan = std::numeric_limits::quiet_NaN(); EXPECT_TRUE(std::isnan(stan::math::atanh(nan))); } + +TEST(MathFunctions, atanh_works_with_other_functions) { + Eigen::VectorXd a(5); + a << 0.1, 0.2, 0.3, 0.4, 0.5; + Eigen::RowVectorXd b(5); + b << 0.1, 0.2, 0.3, 0.4, 0.5; + stan::math::multiply(a, stan::math::atanh(b)); +} diff --git a/test/unit/math/prim/fun/cbrt_test.cpp b/test/unit/math/prim/fun/cbrt_test.cpp index 2ca66bbde53..854853943a6 100644 --- a/test/unit/math/prim/fun/cbrt_test.cpp +++ b/test/unit/math/prim/fun/cbrt_test.cpp @@ -24,3 +24,11 @@ TEST(MathFunctions, cbrt_nan) { double nan = std::numeric_limits::quiet_NaN(); EXPECT_TRUE(std::isnan(stan::math::cbrt(nan))); } + +TEST(MathFunctions, cbrt_works_with_other_functions) { + Eigen::VectorXd a(5); + a << 1.1, 1.2, 1.3, 1.4, 1.5; + Eigen::RowVectorXd b(5); + b << 1.1, 1.2, 1.3, 1.4, 1.5; + stan::math::multiply(a, stan::math::cbrt(b)); +} diff --git a/test/unit/math/prim/fun/ceil_test.cpp b/test/unit/math/prim/fun/ceil_test.cpp index f26f0068eb1..57a7dce8c41 100644 --- a/test/unit/math/prim/fun/ceil_test.cpp +++ b/test/unit/math/prim/fun/ceil_test.cpp @@ -4,3 +4,11 @@ TEST(primScalFun, ceil) { stan::test::expect_common_prim([](auto x) { return std::ceil(x); }, [](auto x) { return stan::math::ceil(x); }); } + +TEST(MathFunctions, ceil_works_with_other_functions) { + Eigen::VectorXd a(5); + a << 1.1, 1.2, 1.3, 1.4, 1.5; + Eigen::RowVectorXd b(5); + b << 1.1, 1.2, 1.3, 1.4, 1.5; + stan::math::multiply(a, stan::math::ceil(b)); +} diff --git a/test/unit/math/prim/fun/cos_test.cpp b/test/unit/math/prim/fun/cos_test.cpp index 53daaa398de..94989f9703f 100644 --- a/test/unit/math/prim/fun/cos_test.cpp +++ b/test/unit/math/prim/fun/cos_test.cpp @@ -5,3 +5,11 @@ TEST(primScalFun, cos) { stan::test::expect_common_prim([](auto x) { return std::cos(x); }, [](auto x) { return stan::math::cos(x); }); } + +TEST(MathFunctions, cos_works_with_other_functions) { + Eigen::VectorXd a(5); + a << 1.1, 1.2, 1.3, 1.4, 1.5; + Eigen::RowVectorXd b(5); + b << 1.1, 1.2, 1.3, 1.4, 1.5; + stan::math::multiply(a, stan::math::cos(b)); +} diff --git a/test/unit/math/prim/fun/cosh_test.cpp b/test/unit/math/prim/fun/cosh_test.cpp new file mode 100644 index 00000000000..d1433637b36 --- /dev/null +++ b/test/unit/math/prim/fun/cosh_test.cpp @@ -0,0 +1,10 @@ +#include +#include + +TEST(MathFunctions, cosh_works_with_other_functions) { + Eigen::VectorXd a(5); + a << 1.1, 1.2, 1.3, 1.4, 1.5; + Eigen::RowVectorXd b(5); + b << 1.1, 1.2, 1.3, 1.4, 1.5; + stan::math::multiply(a, stan::math::cosh(b)); +} diff --git a/test/unit/math/prim/fun/digamma_test.cpp b/test/unit/math/prim/fun/digamma_test.cpp index 2a3a7ea150b..b0d37f98b7e 100644 --- a/test/unit/math/prim/fun/digamma_test.cpp +++ b/test/unit/math/prim/fun/digamma_test.cpp @@ -18,3 +18,11 @@ TEST(MathFunctions, digamma_nan) { EXPECT_TRUE(std::isnormal(stan::math::digamma(1.0E50))); } + +TEST(MathFunctions, digamma_works_with_other_functions) { + Eigen::VectorXd a(5); + a << 1.1, 1.2, 1.3, 1.4, 1.5; + Eigen::RowVectorXd b(5); + b << 1.1, 1.2, 1.3, 1.4, 1.5; + stan::math::multiply(a, stan::math::digamma(b)); +} diff --git a/test/unit/math/prim/fun/erf_test.cpp b/test/unit/math/prim/fun/erf_test.cpp index f01b192b8be..0c06057587c 100644 --- a/test/unit/math/prim/fun/erf_test.cpp +++ b/test/unit/math/prim/fun/erf_test.cpp @@ -20,3 +20,11 @@ TEST(MathFunctions, erfNan) { double nan = std::numeric_limits::quiet_NaN(); EXPECT_TRUE(std::isnan(stan::math::erf(nan))); } + +TEST(MathFunctions, erf_works_with_other_functions) { + Eigen::VectorXd a(5); + a << 1.1, 1.2, 1.3, 1.4, 1.5; + Eigen::RowVectorXd b(5); + b << 1.1, 1.2, 1.3, 1.4, 1.5; + stan::math::multiply(a, stan::math::erf(b)); +} diff --git a/test/unit/math/prim/fun/erfc_test.cpp b/test/unit/math/prim/fun/erfc_test.cpp index aad40784135..2e19d0fe333 100644 --- a/test/unit/math/prim/fun/erfc_test.cpp +++ b/test/unit/math/prim/fun/erfc_test.cpp @@ -21,3 +21,11 @@ TEST(MathFunctions, erfcNan) { double nan = std::numeric_limits::quiet_NaN(); EXPECT_TRUE(std::isnan(stan::math::erfc(nan))); } + +TEST(MathFunctions, erfc_works_with_other_functions) { + Eigen::VectorXd a(5); + a << 1.1, 1.2, 1.3, 1.4, 1.5; + Eigen::RowVectorXd b(5); + b << 1.1, 1.2, 1.3, 1.4, 1.5; + stan::math::multiply(a, stan::math::erfc(b)); +} diff --git a/test/unit/math/prim/fun/exp2_test.cpp b/test/unit/math/prim/fun/exp2_test.cpp index ae1c93c1e22..b5c8f356425 100644 --- a/test/unit/math/prim/fun/exp2_test.cpp +++ b/test/unit/math/prim/fun/exp2_test.cpp @@ -35,3 +35,11 @@ TEST(MathFunctions, exp2_nan) { EXPECT_TRUE(std::isnan(stan::math::exp2(nan))); } + +TEST(MathFunctions, exp2_works_with_other_functions) { + Eigen::VectorXd a(5); + a << 1.1, 1.2, 1.3, 1.4, 1.5; + Eigen::RowVectorXd b(5); + b << 1.1, 1.2, 1.3, 1.4, 1.5; + stan::math::multiply(a, stan::math::exp2(b)); +} diff --git a/test/unit/math/prim/fun/exp_test.cpp b/test/unit/math/prim/fun/exp_test.cpp index a19d8643a9f..292f72baf10 100644 --- a/test/unit/math/prim/fun/exp_test.cpp +++ b/test/unit/math/prim/fun/exp_test.cpp @@ -7,3 +7,11 @@ TEST(MathFunctions, expInt) { EXPECT_FLOAT_EQ(std::exp(3), exp(3)); EXPECT_FLOAT_EQ(std::exp(3.0), exp(3.0)); } + +TEST(MathFunctions, exp_works_with_other_functions) { + Eigen::VectorXd a(5); + a << 1.1, 1.2, 1.3, 1.4, 1.5; + Eigen::RowVectorXd b(5); + b << 1.1, 1.2, 1.3, 1.4, 1.5; + stan::math::multiply(a, stan::math::exp(b)); +} diff --git a/test/unit/math/prim/fun/expm1_test.cpp b/test/unit/math/prim/fun/expm1_test.cpp index 3e35d9873c1..a92bbc91f45 100644 --- a/test/unit/math/prim/fun/expm1_test.cpp +++ b/test/unit/math/prim/fun/expm1_test.cpp @@ -23,3 +23,11 @@ TEST(MathFunctions, expm1_nan) { double nan = std::numeric_limits::quiet_NaN(); EXPECT_TRUE(std::isnan(stan::math::expm1(nan))); } + +TEST(MathFunctions, expm1_works_with_other_functions) { + Eigen::VectorXd a(5); + a << 1.1, 1.2, 1.3, 1.4, 1.5; + Eigen::RowVectorXd b(5); + b << 1.1, 1.2, 1.3, 1.4, 1.5; + stan::math::multiply(a, stan::math::expm1(b)); +} diff --git a/test/unit/math/prim/fun/fabs_test.cpp b/test/unit/math/prim/fun/fabs_test.cpp index 985f1426eda..e4450169d0a 100644 --- a/test/unit/math/prim/fun/fabs_test.cpp +++ b/test/unit/math/prim/fun/fabs_test.cpp @@ -5,3 +5,11 @@ TEST(primScalFun, fabs) { stan::test::expect_common_prim([](auto x) { return std::fabs(x); }, [](auto x) { return stan::math::fabs(x); }); } + +TEST(MathFunctions, fabs_works_with_other_functions) { + Eigen::VectorXd a(5); + a << 1.1, 1.2, 1.3, 1.4, 1.5; + Eigen::RowVectorXd b(5); + b << 1.1, 1.2, 1.3, 1.4, 1.5; + stan::math::multiply(a, stan::math::fabs(b)); +} diff --git a/test/unit/math/prim/fun/floor_test.cpp b/test/unit/math/prim/fun/floor_test.cpp index 6c283c47dbc..90c6dca6090 100644 --- a/test/unit/math/prim/fun/floor_test.cpp +++ b/test/unit/math/prim/fun/floor_test.cpp @@ -4,3 +4,11 @@ TEST(primScalFun, floor) { stan::test::expect_common_prim([](auto x) { return std::floor(x); }, [](auto x) { return stan::math::floor(x); }); } + +TEST(MathFunctions, floor_works_with_other_functions) { + Eigen::VectorXd a(5); + a << 1.1, 1.2, 1.3, 1.4, 1.5; + Eigen::RowVectorXd b(5); + b << 1.1, 1.2, 1.3, 1.4, 1.5; + stan::math::multiply(a, stan::math::floor(b)); +} diff --git a/test/unit/math/prim/fun/inv_Phi_test.cpp b/test/unit/math/prim/fun/inv_Phi_test.cpp index 13d81adbb7f..9538f7151d6 100644 --- a/test/unit/math/prim/fun/inv_Phi_test.cpp +++ b/test/unit/math/prim/fun/inv_Phi_test.cpp @@ -34,3 +34,11 @@ TEST(MathFunctions, inv_Phi_nan) { EXPECT_THROW(inv_Phi(-2.0), std::domain_error); EXPECT_THROW(inv_Phi(2.0), std::domain_error); } + +TEST(MathFunctions, inv_Phi_works_with_other_functions) { + Eigen::VectorXd a(5); + a << 0.1, 0.2, 0.3, 0.4, 0.5; + Eigen::RowVectorXd b(5); + b << 0.1, 0.2, 0.3, 0.4, 0.5; + stan::math::multiply(a, stan::math::inv_Phi(b)); +} diff --git a/test/unit/math/prim/fun/inv_cloglog_test.cpp b/test/unit/math/prim/fun/inv_cloglog_test.cpp index 67118b3b9e6..3f8c3fa6c7b 100644 --- a/test/unit/math/prim/fun/inv_cloglog_test.cpp +++ b/test/unit/math/prim/fun/inv_cloglog_test.cpp @@ -14,3 +14,11 @@ TEST(MathFunctions, inv_cloglog_nan) { EXPECT_TRUE(std::isnan(stan::math::inv_cloglog(nan))); } + +TEST(MathFunctions, inv_cloglog_works_with_other_functions) { + Eigen::VectorXd a(5); + a << 1.1, 1.2, 1.3, 1.4, 1.5; + Eigen::RowVectorXd b(5); + b << 1.1, 1.2, 1.3, 1.4, 1.5; + stan::math::multiply(a, stan::math::inv_cloglog(b)); +} diff --git a/test/unit/math/prim/fun/inv_logit_test.cpp b/test/unit/math/prim/fun/inv_logit_test.cpp index b1e0de78766..a7e272f19b5 100644 --- a/test/unit/math/prim/fun/inv_logit_test.cpp +++ b/test/unit/math/prim/fun/inv_logit_test.cpp @@ -14,3 +14,11 @@ TEST(MathFunctions, inv_logit_nan) { EXPECT_TRUE(std::isnan(stan::math::inv_logit(nan))); } + +TEST(MathFunctions, inv_logit_works_with_other_functions) { + Eigen::VectorXd a(5); + a << 1.1, 1.2, 1.3, 1.4, 1.5; + Eigen::RowVectorXd b(5); + b << 1.1, 1.2, 1.3, 1.4, 1.5; + stan::math::multiply(a, stan::math::inv_logit(b)); +} diff --git a/test/unit/math/prim/fun/inv_sqrt_test.cpp b/test/unit/math/prim/fun/inv_sqrt_test.cpp index 645957931a2..1a7deb94def 100644 --- a/test/unit/math/prim/fun/inv_sqrt_test.cpp +++ b/test/unit/math/prim/fun/inv_sqrt_test.cpp @@ -22,3 +22,11 @@ TEST(MathFunctions, inv_sqrt_nan) { EXPECT_TRUE(std::isnan(stan::math::inv_sqrt(nan))); } + +TEST(MathFunctions, inv_sqrt_works_with_other_functions) { + Eigen::VectorXd a(5); + a << 1.1, 1.2, 1.3, 1.4, 1.5; + Eigen::RowVectorXd b(5); + b << 1.1, 1.2, 1.3, 1.4, 1.5; + stan::math::multiply(a, stan::math::inv_sqrt(b)); +} diff --git a/test/unit/math/prim/fun/inv_square_test.cpp b/test/unit/math/prim/fun/inv_square_test.cpp index 32c17c48cf2..a3cb3588a07 100644 --- a/test/unit/math/prim/fun/inv_square_test.cpp +++ b/test/unit/math/prim/fun/inv_square_test.cpp @@ -19,3 +19,11 @@ TEST(MathFunctions, inv_square_nan) { EXPECT_TRUE(std::isnan(stan::math::inv_square(nan))); } + +TEST(MathFunctions, inv_square_works_with_other_functions) { + Eigen::VectorXd a(5); + a << 1.1, 1.2, 1.3, 1.4, 1.5; + Eigen::RowVectorXd b(5); + b << 1.1, 1.2, 1.3, 1.4, 1.5; + stan::math::multiply(a, stan::math::inv_square(b)); +} diff --git a/test/unit/math/prim/fun/inv_test.cpp b/test/unit/math/prim/fun/inv_test.cpp index f418be35db1..99f9d21a969 100644 --- a/test/unit/math/prim/fun/inv_test.cpp +++ b/test/unit/math/prim/fun/inv_test.cpp @@ -19,3 +19,11 @@ TEST(MathFunctions, inv_nan) { EXPECT_TRUE(std::isnan(stan::math::inv(nan))); } + +TEST(MathFunctions, inv_works_with_other_functions) { + Eigen::VectorXd a(5); + a << 1.1, 1.2, 1.3, 1.4, 1.5; + Eigen::RowVectorXd b(5); + b << 1.1, 1.2, 1.3, 1.4, 1.5; + stan::math::multiply(a, stan::math::inv(b)); +} diff --git a/test/unit/math/prim/fun/lgamma_test.cpp b/test/unit/math/prim/fun/lgamma_test.cpp index d252006d5d5..77e52134c33 100644 --- a/test/unit/math/prim/fun/lgamma_test.cpp +++ b/test/unit/math/prim/fun/lgamma_test.cpp @@ -26,3 +26,11 @@ TEST(MathFunctions, lgamma_nan) { EXPECT_TRUE( std::isnormal(boost::math::lgamma(1.0E50, stan::math::boost_policy_t()))); } + +TEST(MathFunctions, lgamma_works_with_other_functions) { + Eigen::VectorXd a(5); + a << 1.1, 1.2, 1.3, 1.4, 1.5; + Eigen::RowVectorXd b(5); + b << 1.1, 1.2, 1.3, 1.4, 1.5; + stan::math::multiply(a, stan::math::lgamma(b)); +} diff --git a/test/unit/math/prim/fun/log10_test.cpp b/test/unit/math/prim/fun/log10_test.cpp index 1a67f75a75c..4e3e79e94fc 100644 --- a/test/unit/math/prim/fun/log10_test.cpp +++ b/test/unit/math/prim/fun/log10_test.cpp @@ -5,3 +5,11 @@ TEST(primScalFun, log10) { stan::test::expect_common_prim([](auto x) { return std::log10(x); }, [](auto x) { return stan::math::log10(x); }); } + +TEST(MathFunctions, log10_works_with_other_functions) { + Eigen::VectorXd a(5); + a << 1.1, 1.2, 1.3, 1.4, 1.5; + Eigen::RowVectorXd b(5); + b << 1.1, 1.2, 1.3, 1.4, 1.5; + stan::math::multiply(a, stan::math::log10(b)); +} diff --git a/test/unit/math/prim/fun/log1m_test.cpp b/test/unit/math/prim/fun/log1m_test.cpp index a0cf248f987..2c68c5a825e 100644 --- a/test/unit/math/prim/fun/log1m_test.cpp +++ b/test/unit/math/prim/fun/log1m_test.cpp @@ -22,3 +22,11 @@ TEST(MathFunctions, log1m_nan) { double nan = std::numeric_limits::quiet_NaN(); EXPECT_TRUE(std::isnan(stan::math::log1m(nan))); } + +TEST(MathFunctions, log1m_works_with_other_functions) { + Eigen::VectorXd a(5); + a << 0.1, 0.2, 0.3, 0.4, 0.5; + Eigen::RowVectorXd b(5); + b << 0.1, 0.2, 0.3, 0.4, 0.5; + stan::math::multiply(a, stan::math::log1m(b)); +} diff --git a/test/unit/math/prim/fun/log1p_exp_test.cpp b/test/unit/math/prim/fun/log1p_exp_test.cpp index 6930db3a1eb..aa4b3fd0303 100644 --- a/test/unit/math/prim/fun/log1p_exp_test.cpp +++ b/test/unit/math/prim/fun/log1p_exp_test.cpp @@ -16,3 +16,11 @@ TEST(MathFunctions, log1p_exp_nan) { EXPECT_TRUE(std::isnan(stan::math::log1p_exp(nan))); } + +TEST(MathFunctions, log1p_exp_works_with_other_functions) { + Eigen::VectorXd a(5); + a << 1.1, 1.2, 1.3, 1.4, 1.5; + Eigen::RowVectorXd b(5); + b << 1.1, 1.2, 1.3, 1.4, 1.5; + stan::math::multiply(a, stan::math::log1p_exp(b)); +} diff --git a/test/unit/math/prim/fun/log1p_test.cpp b/test/unit/math/prim/fun/log1p_test.cpp index 35f90f46452..714958a1745 100644 --- a/test/unit/math/prim/fun/log1p_test.cpp +++ b/test/unit/math/prim/fun/log1p_test.cpp @@ -40,3 +40,11 @@ TEST(MathFunctions, log1p_nan) { double nan = std::numeric_limits::quiet_NaN(); EXPECT_TRUE(std::isnan(stan::math::log1p(nan))); } + +TEST(MathFunctions, log1p_works_with_other_functions) { + Eigen::VectorXd a(5); + a << 1.1, 1.2, 1.3, 1.4, 1.5; + Eigen::RowVectorXd b(5); + b << 1.1, 1.2, 1.3, 1.4, 1.5; + stan::math::multiply(a, stan::math::log1p(b)); +} diff --git a/test/unit/math/prim/fun/log2_test.cpp b/test/unit/math/prim/fun/log2_test.cpp index 031a50afa97..cf726f78ceb 100644 --- a/test/unit/math/prim/fun/log2_test.cpp +++ b/test/unit/math/prim/fun/log2_test.cpp @@ -22,3 +22,11 @@ TEST(MathFunctions, log2_nan) { EXPECT_TRUE(std::isnan(stan::math::log2(nan))); } + +TEST(MathFunctions, log2_works_with_other_functions) { + Eigen::VectorXd a(5); + a << 1.1, 1.2, 1.3, 1.4, 1.5; + Eigen::RowVectorXd b(5); + b << 1.1, 1.2, 1.3, 1.4, 1.5; + stan::math::multiply(a, stan::math::log2(b)); +} diff --git a/test/unit/math/prim/fun/log_inv_logit_test.cpp b/test/unit/math/prim/fun/log_inv_logit_test.cpp index 774d044a4dd..bb13d370b2a 100644 --- a/test/unit/math/prim/fun/log_inv_logit_test.cpp +++ b/test/unit/math/prim/fun/log_inv_logit_test.cpp @@ -18,3 +18,11 @@ TEST(MathFunctions, log_inv_logit_nan) { EXPECT_TRUE(std::isnan(stan::math::log_inv_logit(nan))); } + +TEST(MathFunctions, log_inv_logit_works_with_other_functions) { + Eigen::VectorXd a(5); + a << 1.1, 1.2, 1.3, 1.4, 1.5; + Eigen::RowVectorXd b(5); + b << 1.1, 1.2, 1.3, 1.4, 1.5; + stan::math::multiply(a, stan::math::log_inv_logit(b)); +} diff --git a/test/unit/math/prim/fun/log_softmax_test.cpp b/test/unit/math/prim/fun/log_softmax_test.cpp index ba26ba1ce20..eff97db3cd9 100644 --- a/test/unit/math/prim/fun/log_softmax_test.cpp +++ b/test/unit/math/prim/fun/log_softmax_test.cpp @@ -47,3 +47,11 @@ TEST(MathMatrixPrimMat, log_softmax_exception) { EXPECT_THROW(log_softmax(v0), std::invalid_argument); } + +TEST(MathFunctions, log_softmax_works_with_other_functions) { + Eigen::VectorXd a(5); + a << 1.1, 1.2, 1.3, 1.4, 1.5; + Eigen::RowVectorXd b(5); + b << 1.1, 1.2, 1.3, 1.4, 1.5; + stan::math::multiply(a, stan::math::log_softmax(b)); +} diff --git a/test/unit/math/prim/fun/log_test.cpp b/test/unit/math/prim/fun/log_test.cpp index 77563092631..f7163dbcf1a 100644 --- a/test/unit/math/prim/fun/log_test.cpp +++ b/test/unit/math/prim/fun/log_test.cpp @@ -7,3 +7,11 @@ TEST(MathFunctions, logInt) { EXPECT_FLOAT_EQ(std::log(3), log(3)); EXPECT_FLOAT_EQ(std::log(3.0), log(3.0)); } + +TEST(MathFunctions, log_works_with_other_functions) { + Eigen::VectorXd a(5); + a << 1.1, 1.2, 1.3, 1.4, 1.5; + Eigen::RowVectorXd b(5); + b << 1.1, 1.2, 1.3, 1.4, 1.5; + stan::math::multiply(a, stan::math::log(b)); +} diff --git a/test/unit/math/prim/fun/logit_test.cpp b/test/unit/math/prim/fun/logit_test.cpp index b6820aa4b7f..566cbcd88ad 100644 --- a/test/unit/math/prim/fun/logit_test.cpp +++ b/test/unit/math/prim/fun/logit_test.cpp @@ -14,3 +14,11 @@ TEST(MathFunctions, logit_nan) { EXPECT_TRUE(std::isnan(stan::math::logit(nan))); } + +TEST(MathFunctions, logit_works_with_other_functions) { + Eigen::VectorXd a(5); + a << 1.1, 1.2, 1.3, 1.4, 1.5; + Eigen::RowVectorXd b(5); + b << 1.1, 1.2, 1.3, 1.4, 1.5; + stan::math::multiply(a, stan::math::logit(b)); +} diff --git a/test/unit/math/prim/fun/minus_test.cpp b/test/unit/math/prim/fun/minus_test.cpp index e9535ca4781..d3dd9bdad85 100644 --- a/test/unit/math/prim/fun/minus_test.cpp +++ b/test/unit/math/prim/fun/minus_test.cpp @@ -10,3 +10,11 @@ TEST(MathMatrixPrimMat, minus) { EXPECT_EQ(0, stan::math::minus(rv0).size()); EXPECT_EQ(0, stan::math::minus(m0).size()); } + +TEST(MathFunctions, minus_works_with_other_functions) { + Eigen::VectorXd a(5); + a << 1.1, 1.2, 1.3, 1.4, 1.5; + Eigen::RowVectorXd b(5); + b << 1.1, 1.2, 1.3, 1.4, 1.5; + stan::math::multiply(a, stan::math::minus(b)); +} diff --git a/test/unit/math/prim/fun/round_test.cpp b/test/unit/math/prim/fun/round_test.cpp index 40cc1a8334f..3cabf152e67 100644 --- a/test/unit/math/prim/fun/round_test.cpp +++ b/test/unit/math/prim/fun/round_test.cpp @@ -17,3 +17,11 @@ TEST(MathFunctions, roundNaN) { double nan = std::numeric_limits::quiet_NaN(); EXPECT_TRUE(std::isnan(stan::math::round(nan))); } + +TEST(MathFunctions, round_works_with_other_functions) { + Eigen::VectorXd a(5); + a << 1.1, 1.2, 1.3, 1.4, 1.5; + Eigen::RowVectorXd b(5); + b << 1.1, 1.2, 1.3, 1.4, 1.5; + stan::math::multiply(a, stan::math::round(b)); +} diff --git a/test/unit/math/prim/fun/sin_test.cpp b/test/unit/math/prim/fun/sin_test.cpp index 3a564bfea3b..4125f5e22f8 100644 --- a/test/unit/math/prim/fun/sin_test.cpp +++ b/test/unit/math/prim/fun/sin_test.cpp @@ -5,3 +5,11 @@ TEST(primScalFun, sin) { stan::test::expect_common_prim([](auto x) { return std::sin(x); }, [](auto x) { return stan::math::sin(x); }); } + +TEST(MathFunctions, sin_works_with_other_functions) { + Eigen::VectorXd a(5); + a << 1.1, 1.2, 1.3, 1.4, 1.5; + Eigen::RowVectorXd b(5); + b << 1.1, 1.2, 1.3, 1.4, 1.5; + stan::math::multiply(a, stan::math::sin(b)); +} diff --git a/test/unit/math/prim/fun/sinh_test.cpp b/test/unit/math/prim/fun/sinh_test.cpp index 72b18d36f94..72e3f143e5d 100644 --- a/test/unit/math/prim/fun/sinh_test.cpp +++ b/test/unit/math/prim/fun/sinh_test.cpp @@ -5,3 +5,11 @@ TEST(primScalFun, sinh) { stan::test::expect_common_prim([](auto x) { return std::sinh(x); }, [](auto x) { return stan::math::sinh(x); }); } + +TEST(MathFunctions, sinh_works_with_other_functions) { + Eigen::VectorXd a(5); + a << 1.1, 1.2, 1.3, 1.4, 1.5; + Eigen::RowVectorXd b(5); + b << 1.1, 1.2, 1.3, 1.4, 1.5; + stan::math::multiply(a, stan::math::sinh(b)); +} diff --git a/test/unit/math/prim/fun/sqrt_test.cpp b/test/unit/math/prim/fun/sqrt_test.cpp index 43c362d0cc9..9896911dbf5 100644 --- a/test/unit/math/prim/fun/sqrt_test.cpp +++ b/test/unit/math/prim/fun/sqrt_test.cpp @@ -7,3 +7,11 @@ TEST(MathFunctions, sqrtInt) { EXPECT_FLOAT_EQ(std::sqrt(3.0), sqrt(3)); EXPECT_TRUE(stan::math::is_nan(sqrt(-2))); } + +TEST(MathFunctions, sqrt_works_with_other_functions) { + Eigen::VectorXd a(5); + a << 1.1, 1.2, 1.3, 1.4, 1.5; + Eigen::RowVectorXd b(5); + b << 1.1, 1.2, 1.3, 1.4, 1.5; + stan::math::multiply(a, stan::math::sqrt(b)); +} diff --git a/test/unit/math/prim/fun/square_test.cpp b/test/unit/math/prim/fun/square_test.cpp index aadd3009906..13b66189bcf 100644 --- a/test/unit/math/prim/fun/square_test.cpp +++ b/test/unit/math/prim/fun/square_test.cpp @@ -3,7 +3,7 @@ #include #include -TEST(MathsFunctions, square) { +TEST(MathFunctions, square) { double y = 2.0; EXPECT_FLOAT_EQ(y * y, stan::math::square(y)); @@ -19,3 +19,11 @@ TEST(MathFunctions, square_nan) { EXPECT_TRUE(std::isnan(stan::math::square(nan))); } + +TEST(MathFunctions, square_works_with_other_functions) { + Eigen::VectorXd a(5); + a << 1.1, 1.2, 1.3, 1.4, 1.5; + Eigen::RowVectorXd b(5); + b << 1.1, 1.2, 1.3, 1.4, 1.5; + stan::math::multiply(a, stan::math::square(b)); +} diff --git a/test/unit/math/prim/fun/tan_test.cpp b/test/unit/math/prim/fun/tan_test.cpp new file mode 100644 index 00000000000..5b9e861cabc --- /dev/null +++ b/test/unit/math/prim/fun/tan_test.cpp @@ -0,0 +1,10 @@ +#include +#include + +TEST(MathFunctions, tan_works_with_other_functions) { + Eigen::VectorXd a(5); + a << 1.1, 1.2, 1.3, 1.4, 1.5; + Eigen::RowVectorXd b(5); + b << 1.1, 1.2, 1.3, 1.4, 1.5; + stan::math::multiply(a, stan::math::tan(b)); +} diff --git a/test/unit/math/prim/fun/tanh_test.cpp b/test/unit/math/prim/fun/tanh_test.cpp index bd4da5755c9..594d0e37ed5 100644 --- a/test/unit/math/prim/fun/tanh_test.cpp +++ b/test/unit/math/prim/fun/tanh_test.cpp @@ -5,3 +5,11 @@ TEST(primScalFun, tanh) { stan::test::expect_common_prim([](auto x) { return std::tanh(x); }, [](auto x) { return stan::math::tanh(x); }); } + +TEST(MathFunctions, tanh_works_with_other_functions) { + Eigen::VectorXd a(5); + a << 1.1, 1.2, 1.3, 1.4, 1.5; + Eigen::RowVectorXd b(5); + b << 1.1, 1.2, 1.3, 1.4, 1.5; + stan::math::multiply(a, stan::math::tanh(b)); +} diff --git a/test/unit/math/prim/fun/tgamma_test.cpp b/test/unit/math/prim/fun/tgamma_test.cpp index 51e5b84261c..2ecb0bd51cc 100644 --- a/test/unit/math/prim/fun/tgamma_test.cpp +++ b/test/unit/math/prim/fun/tgamma_test.cpp @@ -20,3 +20,11 @@ TEST(MathFunctions, tgamma_nan) { double nan = std::numeric_limits::quiet_NaN(); EXPECT_TRUE(std::isnan(stan::math::tgamma(nan))); } + +TEST(MathFunctions, tgamma_works_with_other_functions) { + Eigen::VectorXd a(5); + a << 1.1, 1.2, 1.3, 1.4, 1.5; + Eigen::RowVectorXd b(5); + b << 1.1, 1.2, 1.3, 1.4, 1.5; + stan::math::multiply(a, stan::math::tgamma(b)); +} diff --git a/test/unit/math/prim/fun/trigamma_test.cpp b/test/unit/math/prim/fun/trigamma_test.cpp index d2066598d32..c2d4484d1f0 100644 --- a/test/unit/math/prim/fun/trigamma_test.cpp +++ b/test/unit/math/prim/fun/trigamma_test.cpp @@ -17,3 +17,11 @@ TEST(MathFunctions, trigamma_nan) { EXPECT_TRUE(std::isnan(stan::math::trigamma(nan))); } + +TEST(MathFunctions, trigamma_works_with_other_functions) { + Eigen::VectorXd a(5); + a << 1.1, 1.2, 1.3, 1.4, 1.5; + Eigen::RowVectorXd b(5); + b << 1.1, 1.2, 1.3, 1.4, 1.5; + stan::math::multiply(a, stan::math::trigamma(b)); +} diff --git a/test/unit/math/prim/fun/trunc_test.cpp b/test/unit/math/prim/fun/trunc_test.cpp index 8aa3a7c6a00..2f64da18b03 100644 --- a/test/unit/math/prim/fun/trunc_test.cpp +++ b/test/unit/math/prim/fun/trunc_test.cpp @@ -17,3 +17,11 @@ TEST(MathFunctions, truncNaN) { double nan = std::numeric_limits::quiet_NaN(); EXPECT_TRUE(std::isnan(stan::math::trunc(nan))); } + +TEST(MathFunctions, trunc_works_with_other_functions) { + Eigen::VectorXd a(5); + a << 1.1, 1.2, 1.3, 1.4, 1.5; + Eigen::RowVectorXd b(5); + b << 1.1, 1.2, 1.3, 1.4, 1.5; + stan::math::multiply(a, stan::math::trunc(b)); +} From 3f8fae424ff1e1252f4aed2080d4c2d7b86e24c3 Mon Sep 17 00:00:00 2001 From: Nicusor Serban Date: Wed, 29 Jan 2020 22:31:53 +0200 Subject: [PATCH 004/355] Updated math version --- .github/ISSUE_TEMPLATE.md | 2 +- doxygen/contributor_help_pages/windows_devnotes.md | 6 +++--- doxygen/doxygen.cfg | 2 +- stan/math/version.hpp | 2 +- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/.github/ISSUE_TEMPLATE.md b/.github/ISSUE_TEMPLATE.md index 0e35de62263..8f112ab89d3 100644 --- a/.github/ISSUE_TEMPLATE.md +++ b/.github/ISSUE_TEMPLATE.md @@ -25,4 +25,4 @@ If this is a **feature request**, show what you expect to happen if the feature #### Current Version: -v3.1.0 +v3.1.1 diff --git a/doxygen/contributor_help_pages/windows_devnotes.md b/doxygen/contributor_help_pages/windows_devnotes.md index 1082a514b7e..2c8e7137315 100644 --- a/doxygen/contributor_help_pages/windows_devnotes.md +++ b/doxygen/contributor_help_pages/windows_devnotes.md @@ -51,7 +51,7 @@ BIT=32 ``` If the test suite isn't built first, client code using numerical integration routines such as `integrate_ode_bdf` may fail to link because the libraries haven't been built yet. Obviously these files and directories would need to be added to the downstream project makefile's LDLIBS variable, or equivalent. ``` -$ make lib/sundials_3.1.0/lib/libsundials_cvodes.a lib/sundials_3.1.0/lib/libsundials_nvecserial.a -make: 'lib/sundials_3.1.0/lib/libsundials_cvodes.a' is up to date. -make: 'lib/sundials_3.1.0/lib/libsundials_nvecserial.a' is up to date. +$ make lib/sundials_3.1.1/lib/libsundials_cvodes.a lib/sundials_3.1.1/lib/libsundials_nvecserial.a +make: 'lib/sundials_3.1.1/lib/libsundials_cvodes.a' is up to date. +make: 'lib/sundials_3.1.1/lib/libsundials_nvecserial.a' is up to date. ``` diff --git a/doxygen/doxygen.cfg b/doxygen/doxygen.cfg index 8fee6f17d59..e4b5060f7d0 100644 --- a/doxygen/doxygen.cfg +++ b/doxygen/doxygen.cfg @@ -38,7 +38,7 @@ PROJECT_NAME = "Stan Math Library" # could be handy for archiving the generated documentation or if some version # control system is used. -PROJECT_NUMBER = 3.1.0 +PROJECT_NUMBER = 3.1.1 # 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 diff --git a/stan/math/version.hpp b/stan/math/version.hpp index bf8599edc07..d5ba5648855 100644 --- a/stan/math/version.hpp +++ b/stan/math/version.hpp @@ -13,7 +13,7 @@ #define STAN_MATH_MAJOR 3 #define STAN_MATH_MINOR 1 -#define STAN_MATH_PATCH 0 +#define STAN_MATH_PATCH 1 namespace stan { namespace math { From 067add1de9793d0647c17c7f65fcd5b0ad18ed8a Mon Sep 17 00:00:00 2001 From: Nicusor Serban Date: Wed, 29 Jan 2020 22:49:18 +0200 Subject: [PATCH 005/355] Reverted release of 3.1.1 --- .github/ISSUE_TEMPLATE.md | 2 +- doxygen/contributor_help_pages/windows_devnotes.md | 6 +++--- doxygen/doxygen.cfg | 2 +- stan/math/prim/fun/acos.hpp | 2 +- stan/math/prim/fun/asin.hpp | 2 +- stan/math/prim/fun/atan.hpp | 2 +- stan/math/prim/fun/ceil.hpp | 2 +- stan/math/prim/fun/cos.hpp | 2 +- stan/math/prim/fun/cosh.hpp | 2 +- stan/math/prim/fun/exp.hpp | 2 +- stan/math/prim/fun/fabs.hpp | 4 ++-- stan/math/prim/fun/floor.hpp | 2 +- stan/math/prim/fun/inv.hpp | 4 ++-- stan/math/prim/fun/inv_cloglog.hpp | 4 ++-- stan/math/prim/fun/inv_sqrt.hpp | 4 ++-- stan/math/prim/fun/log.hpp | 2 +- stan/math/prim/fun/log10.hpp | 2 +- stan/math/prim/fun/log_softmax.hpp | 11 +++++------ stan/math/prim/fun/minus.hpp | 4 +--- stan/math/prim/fun/round.hpp | 2 +- stan/math/prim/fun/sin.hpp | 2 +- stan/math/prim/fun/sinh.hpp | 4 ++-- stan/math/prim/fun/sqrt.hpp | 2 +- stan/math/prim/fun/tan.hpp | 2 +- stan/math/prim/fun/tanh.hpp | 2 +- stan/math/prim/vectorize/apply_scalar_unary.hpp | 7 ++----- stan/math/version.hpp | 2 +- test/unit/math/prim/fun/Phi_approx_test.cpp | 8 -------- test/unit/math/prim/fun/Phi_test.cpp | 8 -------- test/unit/math/prim/fun/acos_test.cpp | 8 -------- test/unit/math/prim/fun/acosh_test.cpp | 8 -------- test/unit/math/prim/fun/asin_test.cpp | 8 -------- test/unit/math/prim/fun/asinh_test.cpp | 8 -------- test/unit/math/prim/fun/atan_test.cpp | 8 -------- test/unit/math/prim/fun/atanh_test.cpp | 8 -------- test/unit/math/prim/fun/cbrt_test.cpp | 8 -------- test/unit/math/prim/fun/ceil_test.cpp | 8 -------- test/unit/math/prim/fun/cos_test.cpp | 8 -------- test/unit/math/prim/fun/cosh_test.cpp | 10 ---------- test/unit/math/prim/fun/digamma_test.cpp | 8 -------- test/unit/math/prim/fun/erf_test.cpp | 8 -------- test/unit/math/prim/fun/erfc_test.cpp | 8 -------- test/unit/math/prim/fun/exp2_test.cpp | 8 -------- test/unit/math/prim/fun/exp_test.cpp | 8 -------- test/unit/math/prim/fun/expm1_test.cpp | 8 -------- test/unit/math/prim/fun/fabs_test.cpp | 8 -------- test/unit/math/prim/fun/floor_test.cpp | 8 -------- test/unit/math/prim/fun/inv_Phi_test.cpp | 8 -------- test/unit/math/prim/fun/inv_cloglog_test.cpp | 8 -------- test/unit/math/prim/fun/inv_logit_test.cpp | 8 -------- test/unit/math/prim/fun/inv_sqrt_test.cpp | 8 -------- test/unit/math/prim/fun/inv_square_test.cpp | 8 -------- test/unit/math/prim/fun/inv_test.cpp | 8 -------- test/unit/math/prim/fun/lgamma_test.cpp | 8 -------- test/unit/math/prim/fun/log10_test.cpp | 8 -------- test/unit/math/prim/fun/log1m_test.cpp | 8 -------- test/unit/math/prim/fun/log1p_exp_test.cpp | 8 -------- test/unit/math/prim/fun/log1p_test.cpp | 8 -------- test/unit/math/prim/fun/log2_test.cpp | 8 -------- test/unit/math/prim/fun/log_inv_logit_test.cpp | 8 -------- test/unit/math/prim/fun/log_softmax_test.cpp | 8 -------- test/unit/math/prim/fun/log_test.cpp | 8 -------- test/unit/math/prim/fun/logit_test.cpp | 8 -------- test/unit/math/prim/fun/minus_test.cpp | 8 -------- test/unit/math/prim/fun/round_test.cpp | 8 -------- test/unit/math/prim/fun/sin_test.cpp | 8 -------- test/unit/math/prim/fun/sinh_test.cpp | 8 -------- test/unit/math/prim/fun/sqrt_test.cpp | 8 -------- test/unit/math/prim/fun/square_test.cpp | 10 +--------- test/unit/math/prim/fun/tan_test.cpp | 10 ---------- test/unit/math/prim/fun/tanh_test.cpp | 8 -------- test/unit/math/prim/fun/tgamma_test.cpp | 8 -------- test/unit/math/prim/fun/trigamma_test.cpp | 8 -------- test/unit/math/prim/fun/trunc_test.cpp | 8 -------- 74 files changed, 40 insertions(+), 426 deletions(-) delete mode 100644 test/unit/math/prim/fun/cosh_test.cpp delete mode 100644 test/unit/math/prim/fun/tan_test.cpp diff --git a/.github/ISSUE_TEMPLATE.md b/.github/ISSUE_TEMPLATE.md index 8f112ab89d3..0e35de62263 100644 --- a/.github/ISSUE_TEMPLATE.md +++ b/.github/ISSUE_TEMPLATE.md @@ -25,4 +25,4 @@ If this is a **feature request**, show what you expect to happen if the feature #### Current Version: -v3.1.1 +v3.1.0 diff --git a/doxygen/contributor_help_pages/windows_devnotes.md b/doxygen/contributor_help_pages/windows_devnotes.md index 2c8e7137315..1082a514b7e 100644 --- a/doxygen/contributor_help_pages/windows_devnotes.md +++ b/doxygen/contributor_help_pages/windows_devnotes.md @@ -51,7 +51,7 @@ BIT=32 ``` If the test suite isn't built first, client code using numerical integration routines such as `integrate_ode_bdf` may fail to link because the libraries haven't been built yet. Obviously these files and directories would need to be added to the downstream project makefile's LDLIBS variable, or equivalent. ``` -$ make lib/sundials_3.1.1/lib/libsundials_cvodes.a lib/sundials_3.1.1/lib/libsundials_nvecserial.a -make: 'lib/sundials_3.1.1/lib/libsundials_cvodes.a' is up to date. -make: 'lib/sundials_3.1.1/lib/libsundials_nvecserial.a' is up to date. +$ make lib/sundials_3.1.0/lib/libsundials_cvodes.a lib/sundials_3.1.0/lib/libsundials_nvecserial.a +make: 'lib/sundials_3.1.0/lib/libsundials_cvodes.a' is up to date. +make: 'lib/sundials_3.1.0/lib/libsundials_nvecserial.a' is up to date. ``` diff --git a/doxygen/doxygen.cfg b/doxygen/doxygen.cfg index e4b5060f7d0..8fee6f17d59 100644 --- a/doxygen/doxygen.cfg +++ b/doxygen/doxygen.cfg @@ -38,7 +38,7 @@ PROJECT_NAME = "Stan Math Library" # could be handy for archiving the generated documentation or if some version # control system is used. -PROJECT_NUMBER = 3.1.1 +PROJECT_NUMBER = 3.1.0 # 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 diff --git a/stan/math/prim/fun/acos.hpp b/stan/math/prim/fun/acos.hpp index e5960f1b758..709864e1db6 100644 --- a/stan/math/prim/fun/acos.hpp +++ b/stan/math/prim/fun/acos.hpp @@ -45,7 +45,7 @@ inline auto acos(const T& x) { template > inline auto acos(const Eigen::MatrixBase& x) { - return x.derived().array().acos().matrix().eval(); + return x.derived().array().acos().matrix(); } } // namespace math diff --git a/stan/math/prim/fun/asin.hpp b/stan/math/prim/fun/asin.hpp index 0f5d172a29b..81a22dcf60b 100644 --- a/stan/math/prim/fun/asin.hpp +++ b/stan/math/prim/fun/asin.hpp @@ -45,7 +45,7 @@ inline auto asin(const T& x) { template > inline auto asin(const Eigen::MatrixBase& x) { - return x.derived().array().asin().matrix().eval(); + return x.derived().array().asin().matrix(); } } // namespace math diff --git a/stan/math/prim/fun/atan.hpp b/stan/math/prim/fun/atan.hpp index 9576c99240a..28a05b08d6a 100644 --- a/stan/math/prim/fun/atan.hpp +++ b/stan/math/prim/fun/atan.hpp @@ -45,7 +45,7 @@ inline typename apply_scalar_unary::return_t atan(const T& x) { template > inline auto atan(const Eigen::MatrixBase& x) { - return x.derived().array().atan().matrix().eval(); + return x.derived().array().atan().matrix(); } } // namespace math diff --git a/stan/math/prim/fun/ceil.hpp b/stan/math/prim/fun/ceil.hpp index 2de0ddb72e7..7a78566ac1d 100644 --- a/stan/math/prim/fun/ceil.hpp +++ b/stan/math/prim/fun/ceil.hpp @@ -45,7 +45,7 @@ inline auto ceil(const T& x) { template > inline auto ceil(const Eigen::MatrixBase& x) { - return x.derived().array().ceil().matrix().eval(); + return x.derived().array().ceil().matrix(); } } // namespace math diff --git a/stan/math/prim/fun/cos.hpp b/stan/math/prim/fun/cos.hpp index bf9761ace9f..0c20e53f935 100644 --- a/stan/math/prim/fun/cos.hpp +++ b/stan/math/prim/fun/cos.hpp @@ -45,7 +45,7 @@ inline auto cos(const T& x) { template > inline auto cos(const Eigen::MatrixBase& x) { - return x.derived().array().cos().matrix().eval(); + return x.derived().array().cos().matrix(); } } // namespace math diff --git a/stan/math/prim/fun/cosh.hpp b/stan/math/prim/fun/cosh.hpp index 2a0402fe9c2..3dee3eae2a3 100644 --- a/stan/math/prim/fun/cosh.hpp +++ b/stan/math/prim/fun/cosh.hpp @@ -45,7 +45,7 @@ inline typename apply_scalar_unary::return_t cosh(const T& x) { template > inline auto cosh(const Eigen::MatrixBase& x) { - return x.derived().array().cosh().matrix().eval(); + return x.derived().array().cosh().matrix(); } } // namespace math diff --git a/stan/math/prim/fun/exp.hpp b/stan/math/prim/fun/exp.hpp index 54486d9e394..4d60b4c04b5 100644 --- a/stan/math/prim/fun/exp.hpp +++ b/stan/math/prim/fun/exp.hpp @@ -60,7 +60,7 @@ inline auto exp(const T& x) { template > inline auto exp(const Eigen::MatrixBase& x) { - return x.derived().array().exp().matrix().eval(); + return x.derived().array().exp().matrix(); } } // namespace math diff --git a/stan/math/prim/fun/fabs.hpp b/stan/math/prim/fun/fabs.hpp index 2bfc97071d2..1dc51b0ee3c 100644 --- a/stan/math/prim/fun/fabs.hpp +++ b/stan/math/prim/fun/fabs.hpp @@ -45,7 +45,7 @@ inline typename apply_scalar_unary::return_t fabs(const T& x) { template > inline auto fabs(const Eigen::MatrixBase& x) { - return x.derived().array().abs().matrix().eval(); + return x.derived().array().abs().matrix(); } /** @@ -57,7 +57,7 @@ inline auto fabs(const Eigen::MatrixBase& x) { template > inline auto fabs(const Eigen::ArrayBase& x) { - return x.derived().abs().eval(); + return x.derived().abs(); } } // namespace math diff --git a/stan/math/prim/fun/floor.hpp b/stan/math/prim/fun/floor.hpp index c53433cf356..7f1f37317cd 100644 --- a/stan/math/prim/fun/floor.hpp +++ b/stan/math/prim/fun/floor.hpp @@ -45,7 +45,7 @@ inline auto floor(const T& x) { template > inline auto floor(const Eigen::MatrixBase& x) { - return x.derived().array().floor().matrix().eval(); + return x.derived().array().floor().matrix(); } } // namespace math diff --git a/stan/math/prim/fun/inv.hpp b/stan/math/prim/fun/inv.hpp index 439dc962778..f50f17f784c 100644 --- a/stan/math/prim/fun/inv.hpp +++ b/stan/math/prim/fun/inv.hpp @@ -45,7 +45,7 @@ inline auto inv(const T& x) { template > inline auto inv(const Eigen::MatrixBase& x) { - return x.derived().array().inverse().matrix().eval(); + return x.derived().array().inverse().matrix(); } /** @@ -57,7 +57,7 @@ inline auto inv(const Eigen::MatrixBase& x) { template > inline auto inv(const Eigen::ArrayBase& x) { - return x.derived().inverse().eval(); + return x.derived().inverse(); } } // namespace math diff --git a/stan/math/prim/fun/inv_cloglog.hpp b/stan/math/prim/fun/inv_cloglog.hpp index 44c6dfdc8d7..945417aa0f9 100644 --- a/stan/math/prim/fun/inv_cloglog.hpp +++ b/stan/math/prim/fun/inv_cloglog.hpp @@ -87,7 +87,7 @@ inline auto inv_cloglog(const T& x) { template > inline auto inv_cloglog(const Eigen::MatrixBase& x) { - return (1 - exp(-exp(x.derived().array()))).matrix().eval(); + return (1 - exp(-exp(x.derived().array()))).matrix(); } /** @@ -99,7 +99,7 @@ inline auto inv_cloglog(const Eigen::MatrixBase& x) { template > inline auto inv_cloglog(const Eigen::ArrayBase& x) { - return (1 - exp(-exp(x.derived()))).eval(); + return 1 - exp(-exp(x.derived())); } } // namespace math diff --git a/stan/math/prim/fun/inv_sqrt.hpp b/stan/math/prim/fun/inv_sqrt.hpp index 66b41ee7138..aa6e0d7ffdf 100644 --- a/stan/math/prim/fun/inv_sqrt.hpp +++ b/stan/math/prim/fun/inv_sqrt.hpp @@ -50,7 +50,7 @@ inline auto inv_sqrt(const T& x) { template > inline auto inv_sqrt(const Eigen::MatrixBase& x) { - return x.derived().array().rsqrt().matrix().eval(); + return x.derived().array().rsqrt().matrix(); } /** @@ -62,7 +62,7 @@ inline auto inv_sqrt(const Eigen::MatrixBase& x) { template > inline auto inv_sqrt(const Eigen::ArrayBase& x) { - return x.derived().rsqrt().eval(); + return x.derived().rsqrt(); } } // namespace math diff --git a/stan/math/prim/fun/log.hpp b/stan/math/prim/fun/log.hpp index 3814d0a5ae5..2e32bc5aa4b 100644 --- a/stan/math/prim/fun/log.hpp +++ b/stan/math/prim/fun/log.hpp @@ -60,7 +60,7 @@ inline auto log(const T& x) { template > inline auto log(const Eigen::MatrixBase& x) { - return x.derived().array().log().matrix().eval(); + return x.derived().array().log().matrix(); } } // namespace math diff --git a/stan/math/prim/fun/log10.hpp b/stan/math/prim/fun/log10.hpp index 10b7b0fa1b0..808bdb85bad 100644 --- a/stan/math/prim/fun/log10.hpp +++ b/stan/math/prim/fun/log10.hpp @@ -45,7 +45,7 @@ inline auto log10(const T& x) { template > inline auto log10(const Eigen::MatrixBase& x) { - return x.derived().array().log10().matrix().eval(); + return x.derived().array().log10().matrix(); } } // namespace math diff --git a/stan/math/prim/fun/log_softmax.hpp b/stan/math/prim/fun/log_softmax.hpp index 8c4951df779..a51370d0b1a 100644 --- a/stan/math/prim/fun/log_softmax.hpp +++ b/stan/math/prim/fun/log_softmax.hpp @@ -36,12 +36,11 @@ namespace math { * @param[in] v Vector to transform. * @return Unit simplex result of the softmax transform of the vector. */ -template >>...> -inline auto log_softmax(const T& x) { - return apply_vector_unary::apply(x, [&](const auto& v) { - check_nonzero_size("log_softmax", "v", v); - return (v.array() - log_sum_exp(v)).matrix().eval(); - }); +template +inline Eigen::Matrix log_softmax( + const Eigen::Matrix& v) { + check_nonzero_size("log_softmax", "v", v); + return v.array() - log_sum_exp(v); } } // namespace math diff --git a/stan/math/prim/fun/minus.hpp b/stan/math/prim/fun/minus.hpp index 13fe7d090ed..7f374462fc0 100644 --- a/stan/math/prim/fun/minus.hpp +++ b/stan/math/prim/fun/minus.hpp @@ -1,8 +1,6 @@ #ifndef STAN_MATH_PRIM_FUN_MINUS_HPP #define STAN_MATH_PRIM_FUN_MINUS_HPP -#include - namespace stan { namespace math { @@ -14,7 +12,7 @@ namespace math { * @return Negation of subtrahend. */ template -inline plain_type_t minus(const T& x) { +inline auto minus(const T& x) { return -x; } diff --git a/stan/math/prim/fun/round.hpp b/stan/math/prim/fun/round.hpp index e5cc48efd18..66b2d6a428c 100644 --- a/stan/math/prim/fun/round.hpp +++ b/stan/math/prim/fun/round.hpp @@ -62,7 +62,7 @@ inline auto round(const T& x) { template > inline auto round(const Eigen::MatrixBase& x) { - return x.derived().array().round().matrix().eval(); + return x.derived().array().round().matrix(); } } // namespace math diff --git a/stan/math/prim/fun/sin.hpp b/stan/math/prim/fun/sin.hpp index 0b783ffeb20..f2ed9102f97 100644 --- a/stan/math/prim/fun/sin.hpp +++ b/stan/math/prim/fun/sin.hpp @@ -45,7 +45,7 @@ inline auto sin(const T& x) { template > inline auto sin(const Eigen::MatrixBase& x) { - return x.derived().array().sin().matrix().eval(); + return x.derived().array().sin().matrix(); } } // namespace math diff --git a/stan/math/prim/fun/sinh.hpp b/stan/math/prim/fun/sinh.hpp index e4d1252295d..5e13a03993e 100644 --- a/stan/math/prim/fun/sinh.hpp +++ b/stan/math/prim/fun/sinh.hpp @@ -45,7 +45,7 @@ inline auto sinh(const T& x) { template > inline auto sinh(const Eigen::MatrixBase& x) { - return x.derived().array().sinh().matrix().eval(); + return x.derived().array().sinh().matrix(); } /** @@ -57,7 +57,7 @@ inline auto sinh(const Eigen::MatrixBase& x) { template > inline auto sinh(const Eigen::ArrayBase& x) { - return x.derived().sinh().eval(); + return x.derived().sinh(); } } // namespace math diff --git a/stan/math/prim/fun/sqrt.hpp b/stan/math/prim/fun/sqrt.hpp index fe81fcf75b6..ae1b6dace93 100644 --- a/stan/math/prim/fun/sqrt.hpp +++ b/stan/math/prim/fun/sqrt.hpp @@ -54,7 +54,7 @@ inline auto sqrt(const T& x) { template > inline auto sqrt(const Eigen::MatrixBase& x) { - return x.derived().array().sqrt().matrix().eval(); + return x.derived().array().sqrt().matrix(); } } // namespace math diff --git a/stan/math/prim/fun/tan.hpp b/stan/math/prim/fun/tan.hpp index efc03beb94b..7064300e695 100644 --- a/stan/math/prim/fun/tan.hpp +++ b/stan/math/prim/fun/tan.hpp @@ -45,7 +45,7 @@ inline auto tan(const T& x) { template > inline auto tan(const Eigen::MatrixBase& x) { - return x.derived().array().tan().matrix().eval(); + return x.derived().array().tan().matrix(); } } // namespace math diff --git a/stan/math/prim/fun/tanh.hpp b/stan/math/prim/fun/tanh.hpp index 2fe9f4c5a25..60c4d405fb2 100644 --- a/stan/math/prim/fun/tanh.hpp +++ b/stan/math/prim/fun/tanh.hpp @@ -45,7 +45,7 @@ inline auto tanh(const T& x) { template > inline auto tanh(const Eigen::MatrixBase& x) { - return x.derived().array().tanh().matrix().eval(); + return x.derived().array().tanh().matrix(); } } // namespace math diff --git a/stan/math/prim/vectorize/apply_scalar_unary.hpp b/stan/math/prim/vectorize/apply_scalar_unary.hpp index 8cc283cd4ac..ed31037a207 100644 --- a/stan/math/prim/vectorize/apply_scalar_unary.hpp +++ b/stan/math/prim/vectorize/apply_scalar_unary.hpp @@ -59,11 +59,8 @@ struct apply_scalar_unary> { * by F to the specified matrix. */ static inline auto apply(const T& x) { - return x - .unaryExpr([](scalar_t x) { - return apply_scalar_unary::apply(x); - }) - .eval(); + return x.unaryExpr( + [](scalar_t x) { return apply_scalar_unary::apply(x); }); } /** diff --git a/stan/math/version.hpp b/stan/math/version.hpp index d5ba5648855..bf8599edc07 100644 --- a/stan/math/version.hpp +++ b/stan/math/version.hpp @@ -13,7 +13,7 @@ #define STAN_MATH_MAJOR 3 #define STAN_MATH_MINOR 1 -#define STAN_MATH_PATCH 1 +#define STAN_MATH_PATCH 0 namespace stan { namespace math { diff --git a/test/unit/math/prim/fun/Phi_approx_test.cpp b/test/unit/math/prim/fun/Phi_approx_test.cpp index 4a29923c572..dbc4078352d 100644 --- a/test/unit/math/prim/fun/Phi_approx_test.cpp +++ b/test/unit/math/prim/fun/Phi_approx_test.cpp @@ -14,11 +14,3 @@ TEST(MathFunctions, Phi_approx_nan) { EXPECT_TRUE(std::isnan(stan::math::Phi_approx(nan))); } - -TEST(MathFunctions, Phi_approx__works_with_other_functions) { - Eigen::VectorXd a(5); - a << 1.1, 1.2, 1.3, 1.4, 1.5; - Eigen::RowVectorXd b(5); - b << 1.1, 1.2, 1.3, 1.4, 1.5; - stan::math::multiply(a, stan::math::Phi_approx(b)); -} diff --git a/test/unit/math/prim/fun/Phi_test.cpp b/test/unit/math/prim/fun/Phi_test.cpp index 1273ad24628..c43e260bf88 100644 --- a/test/unit/math/prim/fun/Phi_test.cpp +++ b/test/unit/math/prim/fun/Phi_test.cpp @@ -118,11 +118,3 @@ TEST(MathFunctions, Phi_nan) { double nan = std::numeric_limits::quiet_NaN(); EXPECT_THROW(stan::math::Phi(nan), std::domain_error); } - -TEST(MathFunctions, Phi_works_with_other_functions) { - Eigen::VectorXd a(5); - a << 1.1, 1.2, 1.3, 1.4, 1.5; - Eigen::RowVectorXd b(5); - b << 1.1, 1.2, 1.3, 1.4, 1.5; - stan::math::multiply(a, stan::math::Phi(b)); -} diff --git a/test/unit/math/prim/fun/acos_test.cpp b/test/unit/math/prim/fun/acos_test.cpp index 7570f52cc71..c66c4c49a02 100644 --- a/test/unit/math/prim/fun/acos_test.cpp +++ b/test/unit/math/prim/fun/acos_test.cpp @@ -5,11 +5,3 @@ TEST(primScalFun, acos) { stan::test::expect_common_prim([](auto x) { return std::acos(x); }, [](auto x) { return stan::math::acos(x); }); } - -TEST(MathFunctions, acos_works_with_other_functions) { - Eigen::VectorXd a(5); - a << 0.1, 0.2, 0.3, 0.4, 0.5; - Eigen::RowVectorXd b(5); - b << 0.1, 0.2, 0.3, 0.4, 0.5; - stan::math::multiply(a, stan::math::acos(b)); -} diff --git a/test/unit/math/prim/fun/acosh_test.cpp b/test/unit/math/prim/fun/acosh_test.cpp index 1f9e8ab7bb5..2d5bc742d3c 100644 --- a/test/unit/math/prim/fun/acosh_test.cpp +++ b/test/unit/math/prim/fun/acosh_test.cpp @@ -26,11 +26,3 @@ TEST(MathFunctions, acosh_nan) { double nan = std::numeric_limits::quiet_NaN(); EXPECT_TRUE(std::isnan(stan::math::acosh(nan))); } - -TEST(MathFunctions, acosh_works_with_other_functions) { - Eigen::VectorXd a(5); - a << 1.1, 1.2, 1.3, 1.4, 1.5; - Eigen::RowVectorXd b(5); - b << 1.1, 1.2, 1.3, 1.4, 1.5; - stan::math::multiply(a, stan::math::acosh(b)); -} diff --git a/test/unit/math/prim/fun/asin_test.cpp b/test/unit/math/prim/fun/asin_test.cpp index 858be5fbbbd..a14245b58c2 100644 --- a/test/unit/math/prim/fun/asin_test.cpp +++ b/test/unit/math/prim/fun/asin_test.cpp @@ -5,11 +5,3 @@ TEST(primScalFun, asin) { stan::test::expect_common_prim([](auto x) { return std::asin(x); }, [](auto x) { return stan::math::asin(x); }); } - -TEST(MathFunctions, asin_works_with_other_functions) { - Eigen::VectorXd a(5); - a << 0.1, 0.2, 0.3, 0.4, 0.5; - Eigen::RowVectorXd b(5); - b << 0.1, 0.2, 0.3, 0.4, 0.5; - stan::math::multiply(a, stan::math::asin(b)); -} diff --git a/test/unit/math/prim/fun/asinh_test.cpp b/test/unit/math/prim/fun/asinh_test.cpp index e10228b0af0..151afc2b3ef 100644 --- a/test/unit/math/prim/fun/asinh_test.cpp +++ b/test/unit/math/prim/fun/asinh_test.cpp @@ -22,11 +22,3 @@ TEST(MathFunctions, asinh_nan) { double nan = std::numeric_limits::quiet_NaN(); EXPECT_TRUE(std::isnan(stan::math::asinh(nan))); } - -TEST(MathFunctions, asinh_works_with_other_functions) { - Eigen::VectorXd a(5); - a << 1.1, 1.2, 1.3, 1.4, 1.5; - Eigen::RowVectorXd b(5); - b << 1.1, 1.2, 1.3, 1.4, 1.5; - stan::math::multiply(a, stan::math::asinh(b)); -} diff --git a/test/unit/math/prim/fun/atan_test.cpp b/test/unit/math/prim/fun/atan_test.cpp index 54861be5151..467ceefff7d 100644 --- a/test/unit/math/prim/fun/atan_test.cpp +++ b/test/unit/math/prim/fun/atan_test.cpp @@ -5,11 +5,3 @@ TEST(primScalFun, atan) { stan::test::expect_common_prim([](auto x) { return std::atan(x); }, [](auto x) { return stan::math::atan(x); }); } - -TEST(MathFunctions, atan_works_with_other_functions) { - Eigen::VectorXd a(5); - a << 1.1, 1.2, 1.3, 1.4, 1.5; - Eigen::RowVectorXd b(5); - b << 1.1, 1.2, 1.3, 1.4, 1.5; - stan::math::multiply(a, stan::math::atan(b)); -} diff --git a/test/unit/math/prim/fun/atanh_test.cpp b/test/unit/math/prim/fun/atanh_test.cpp index 18ae151e23c..ca60e585e86 100644 --- a/test/unit/math/prim/fun/atanh_test.cpp +++ b/test/unit/math/prim/fun/atanh_test.cpp @@ -27,11 +27,3 @@ TEST(MathFunctions, atanh_nan) { double nan = std::numeric_limits::quiet_NaN(); EXPECT_TRUE(std::isnan(stan::math::atanh(nan))); } - -TEST(MathFunctions, atanh_works_with_other_functions) { - Eigen::VectorXd a(5); - a << 0.1, 0.2, 0.3, 0.4, 0.5; - Eigen::RowVectorXd b(5); - b << 0.1, 0.2, 0.3, 0.4, 0.5; - stan::math::multiply(a, stan::math::atanh(b)); -} diff --git a/test/unit/math/prim/fun/cbrt_test.cpp b/test/unit/math/prim/fun/cbrt_test.cpp index 854853943a6..2ca66bbde53 100644 --- a/test/unit/math/prim/fun/cbrt_test.cpp +++ b/test/unit/math/prim/fun/cbrt_test.cpp @@ -24,11 +24,3 @@ TEST(MathFunctions, cbrt_nan) { double nan = std::numeric_limits::quiet_NaN(); EXPECT_TRUE(std::isnan(stan::math::cbrt(nan))); } - -TEST(MathFunctions, cbrt_works_with_other_functions) { - Eigen::VectorXd a(5); - a << 1.1, 1.2, 1.3, 1.4, 1.5; - Eigen::RowVectorXd b(5); - b << 1.1, 1.2, 1.3, 1.4, 1.5; - stan::math::multiply(a, stan::math::cbrt(b)); -} diff --git a/test/unit/math/prim/fun/ceil_test.cpp b/test/unit/math/prim/fun/ceil_test.cpp index 57a7dce8c41..f26f0068eb1 100644 --- a/test/unit/math/prim/fun/ceil_test.cpp +++ b/test/unit/math/prim/fun/ceil_test.cpp @@ -4,11 +4,3 @@ TEST(primScalFun, ceil) { stan::test::expect_common_prim([](auto x) { return std::ceil(x); }, [](auto x) { return stan::math::ceil(x); }); } - -TEST(MathFunctions, ceil_works_with_other_functions) { - Eigen::VectorXd a(5); - a << 1.1, 1.2, 1.3, 1.4, 1.5; - Eigen::RowVectorXd b(5); - b << 1.1, 1.2, 1.3, 1.4, 1.5; - stan::math::multiply(a, stan::math::ceil(b)); -} diff --git a/test/unit/math/prim/fun/cos_test.cpp b/test/unit/math/prim/fun/cos_test.cpp index 94989f9703f..53daaa398de 100644 --- a/test/unit/math/prim/fun/cos_test.cpp +++ b/test/unit/math/prim/fun/cos_test.cpp @@ -5,11 +5,3 @@ TEST(primScalFun, cos) { stan::test::expect_common_prim([](auto x) { return std::cos(x); }, [](auto x) { return stan::math::cos(x); }); } - -TEST(MathFunctions, cos_works_with_other_functions) { - Eigen::VectorXd a(5); - a << 1.1, 1.2, 1.3, 1.4, 1.5; - Eigen::RowVectorXd b(5); - b << 1.1, 1.2, 1.3, 1.4, 1.5; - stan::math::multiply(a, stan::math::cos(b)); -} diff --git a/test/unit/math/prim/fun/cosh_test.cpp b/test/unit/math/prim/fun/cosh_test.cpp deleted file mode 100644 index d1433637b36..00000000000 --- a/test/unit/math/prim/fun/cosh_test.cpp +++ /dev/null @@ -1,10 +0,0 @@ -#include -#include - -TEST(MathFunctions, cosh_works_with_other_functions) { - Eigen::VectorXd a(5); - a << 1.1, 1.2, 1.3, 1.4, 1.5; - Eigen::RowVectorXd b(5); - b << 1.1, 1.2, 1.3, 1.4, 1.5; - stan::math::multiply(a, stan::math::cosh(b)); -} diff --git a/test/unit/math/prim/fun/digamma_test.cpp b/test/unit/math/prim/fun/digamma_test.cpp index b0d37f98b7e..2a3a7ea150b 100644 --- a/test/unit/math/prim/fun/digamma_test.cpp +++ b/test/unit/math/prim/fun/digamma_test.cpp @@ -18,11 +18,3 @@ TEST(MathFunctions, digamma_nan) { EXPECT_TRUE(std::isnormal(stan::math::digamma(1.0E50))); } - -TEST(MathFunctions, digamma_works_with_other_functions) { - Eigen::VectorXd a(5); - a << 1.1, 1.2, 1.3, 1.4, 1.5; - Eigen::RowVectorXd b(5); - b << 1.1, 1.2, 1.3, 1.4, 1.5; - stan::math::multiply(a, stan::math::digamma(b)); -} diff --git a/test/unit/math/prim/fun/erf_test.cpp b/test/unit/math/prim/fun/erf_test.cpp index 0c06057587c..f01b192b8be 100644 --- a/test/unit/math/prim/fun/erf_test.cpp +++ b/test/unit/math/prim/fun/erf_test.cpp @@ -20,11 +20,3 @@ TEST(MathFunctions, erfNan) { double nan = std::numeric_limits::quiet_NaN(); EXPECT_TRUE(std::isnan(stan::math::erf(nan))); } - -TEST(MathFunctions, erf_works_with_other_functions) { - Eigen::VectorXd a(5); - a << 1.1, 1.2, 1.3, 1.4, 1.5; - Eigen::RowVectorXd b(5); - b << 1.1, 1.2, 1.3, 1.4, 1.5; - stan::math::multiply(a, stan::math::erf(b)); -} diff --git a/test/unit/math/prim/fun/erfc_test.cpp b/test/unit/math/prim/fun/erfc_test.cpp index 2e19d0fe333..aad40784135 100644 --- a/test/unit/math/prim/fun/erfc_test.cpp +++ b/test/unit/math/prim/fun/erfc_test.cpp @@ -21,11 +21,3 @@ TEST(MathFunctions, erfcNan) { double nan = std::numeric_limits::quiet_NaN(); EXPECT_TRUE(std::isnan(stan::math::erfc(nan))); } - -TEST(MathFunctions, erfc_works_with_other_functions) { - Eigen::VectorXd a(5); - a << 1.1, 1.2, 1.3, 1.4, 1.5; - Eigen::RowVectorXd b(5); - b << 1.1, 1.2, 1.3, 1.4, 1.5; - stan::math::multiply(a, stan::math::erfc(b)); -} diff --git a/test/unit/math/prim/fun/exp2_test.cpp b/test/unit/math/prim/fun/exp2_test.cpp index b5c8f356425..ae1c93c1e22 100644 --- a/test/unit/math/prim/fun/exp2_test.cpp +++ b/test/unit/math/prim/fun/exp2_test.cpp @@ -35,11 +35,3 @@ TEST(MathFunctions, exp2_nan) { EXPECT_TRUE(std::isnan(stan::math::exp2(nan))); } - -TEST(MathFunctions, exp2_works_with_other_functions) { - Eigen::VectorXd a(5); - a << 1.1, 1.2, 1.3, 1.4, 1.5; - Eigen::RowVectorXd b(5); - b << 1.1, 1.2, 1.3, 1.4, 1.5; - stan::math::multiply(a, stan::math::exp2(b)); -} diff --git a/test/unit/math/prim/fun/exp_test.cpp b/test/unit/math/prim/fun/exp_test.cpp index 292f72baf10..a19d8643a9f 100644 --- a/test/unit/math/prim/fun/exp_test.cpp +++ b/test/unit/math/prim/fun/exp_test.cpp @@ -7,11 +7,3 @@ TEST(MathFunctions, expInt) { EXPECT_FLOAT_EQ(std::exp(3), exp(3)); EXPECT_FLOAT_EQ(std::exp(3.0), exp(3.0)); } - -TEST(MathFunctions, exp_works_with_other_functions) { - Eigen::VectorXd a(5); - a << 1.1, 1.2, 1.3, 1.4, 1.5; - Eigen::RowVectorXd b(5); - b << 1.1, 1.2, 1.3, 1.4, 1.5; - stan::math::multiply(a, stan::math::exp(b)); -} diff --git a/test/unit/math/prim/fun/expm1_test.cpp b/test/unit/math/prim/fun/expm1_test.cpp index a92bbc91f45..3e35d9873c1 100644 --- a/test/unit/math/prim/fun/expm1_test.cpp +++ b/test/unit/math/prim/fun/expm1_test.cpp @@ -23,11 +23,3 @@ TEST(MathFunctions, expm1_nan) { double nan = std::numeric_limits::quiet_NaN(); EXPECT_TRUE(std::isnan(stan::math::expm1(nan))); } - -TEST(MathFunctions, expm1_works_with_other_functions) { - Eigen::VectorXd a(5); - a << 1.1, 1.2, 1.3, 1.4, 1.5; - Eigen::RowVectorXd b(5); - b << 1.1, 1.2, 1.3, 1.4, 1.5; - stan::math::multiply(a, stan::math::expm1(b)); -} diff --git a/test/unit/math/prim/fun/fabs_test.cpp b/test/unit/math/prim/fun/fabs_test.cpp index e4450169d0a..985f1426eda 100644 --- a/test/unit/math/prim/fun/fabs_test.cpp +++ b/test/unit/math/prim/fun/fabs_test.cpp @@ -5,11 +5,3 @@ TEST(primScalFun, fabs) { stan::test::expect_common_prim([](auto x) { return std::fabs(x); }, [](auto x) { return stan::math::fabs(x); }); } - -TEST(MathFunctions, fabs_works_with_other_functions) { - Eigen::VectorXd a(5); - a << 1.1, 1.2, 1.3, 1.4, 1.5; - Eigen::RowVectorXd b(5); - b << 1.1, 1.2, 1.3, 1.4, 1.5; - stan::math::multiply(a, stan::math::fabs(b)); -} diff --git a/test/unit/math/prim/fun/floor_test.cpp b/test/unit/math/prim/fun/floor_test.cpp index 90c6dca6090..6c283c47dbc 100644 --- a/test/unit/math/prim/fun/floor_test.cpp +++ b/test/unit/math/prim/fun/floor_test.cpp @@ -4,11 +4,3 @@ TEST(primScalFun, floor) { stan::test::expect_common_prim([](auto x) { return std::floor(x); }, [](auto x) { return stan::math::floor(x); }); } - -TEST(MathFunctions, floor_works_with_other_functions) { - Eigen::VectorXd a(5); - a << 1.1, 1.2, 1.3, 1.4, 1.5; - Eigen::RowVectorXd b(5); - b << 1.1, 1.2, 1.3, 1.4, 1.5; - stan::math::multiply(a, stan::math::floor(b)); -} diff --git a/test/unit/math/prim/fun/inv_Phi_test.cpp b/test/unit/math/prim/fun/inv_Phi_test.cpp index 9538f7151d6..13d81adbb7f 100644 --- a/test/unit/math/prim/fun/inv_Phi_test.cpp +++ b/test/unit/math/prim/fun/inv_Phi_test.cpp @@ -34,11 +34,3 @@ TEST(MathFunctions, inv_Phi_nan) { EXPECT_THROW(inv_Phi(-2.0), std::domain_error); EXPECT_THROW(inv_Phi(2.0), std::domain_error); } - -TEST(MathFunctions, inv_Phi_works_with_other_functions) { - Eigen::VectorXd a(5); - a << 0.1, 0.2, 0.3, 0.4, 0.5; - Eigen::RowVectorXd b(5); - b << 0.1, 0.2, 0.3, 0.4, 0.5; - stan::math::multiply(a, stan::math::inv_Phi(b)); -} diff --git a/test/unit/math/prim/fun/inv_cloglog_test.cpp b/test/unit/math/prim/fun/inv_cloglog_test.cpp index 3f8c3fa6c7b..67118b3b9e6 100644 --- a/test/unit/math/prim/fun/inv_cloglog_test.cpp +++ b/test/unit/math/prim/fun/inv_cloglog_test.cpp @@ -14,11 +14,3 @@ TEST(MathFunctions, inv_cloglog_nan) { EXPECT_TRUE(std::isnan(stan::math::inv_cloglog(nan))); } - -TEST(MathFunctions, inv_cloglog_works_with_other_functions) { - Eigen::VectorXd a(5); - a << 1.1, 1.2, 1.3, 1.4, 1.5; - Eigen::RowVectorXd b(5); - b << 1.1, 1.2, 1.3, 1.4, 1.5; - stan::math::multiply(a, stan::math::inv_cloglog(b)); -} diff --git a/test/unit/math/prim/fun/inv_logit_test.cpp b/test/unit/math/prim/fun/inv_logit_test.cpp index a7e272f19b5..b1e0de78766 100644 --- a/test/unit/math/prim/fun/inv_logit_test.cpp +++ b/test/unit/math/prim/fun/inv_logit_test.cpp @@ -14,11 +14,3 @@ TEST(MathFunctions, inv_logit_nan) { EXPECT_TRUE(std::isnan(stan::math::inv_logit(nan))); } - -TEST(MathFunctions, inv_logit_works_with_other_functions) { - Eigen::VectorXd a(5); - a << 1.1, 1.2, 1.3, 1.4, 1.5; - Eigen::RowVectorXd b(5); - b << 1.1, 1.2, 1.3, 1.4, 1.5; - stan::math::multiply(a, stan::math::inv_logit(b)); -} diff --git a/test/unit/math/prim/fun/inv_sqrt_test.cpp b/test/unit/math/prim/fun/inv_sqrt_test.cpp index 1a7deb94def..645957931a2 100644 --- a/test/unit/math/prim/fun/inv_sqrt_test.cpp +++ b/test/unit/math/prim/fun/inv_sqrt_test.cpp @@ -22,11 +22,3 @@ TEST(MathFunctions, inv_sqrt_nan) { EXPECT_TRUE(std::isnan(stan::math::inv_sqrt(nan))); } - -TEST(MathFunctions, inv_sqrt_works_with_other_functions) { - Eigen::VectorXd a(5); - a << 1.1, 1.2, 1.3, 1.4, 1.5; - Eigen::RowVectorXd b(5); - b << 1.1, 1.2, 1.3, 1.4, 1.5; - stan::math::multiply(a, stan::math::inv_sqrt(b)); -} diff --git a/test/unit/math/prim/fun/inv_square_test.cpp b/test/unit/math/prim/fun/inv_square_test.cpp index a3cb3588a07..32c17c48cf2 100644 --- a/test/unit/math/prim/fun/inv_square_test.cpp +++ b/test/unit/math/prim/fun/inv_square_test.cpp @@ -19,11 +19,3 @@ TEST(MathFunctions, inv_square_nan) { EXPECT_TRUE(std::isnan(stan::math::inv_square(nan))); } - -TEST(MathFunctions, inv_square_works_with_other_functions) { - Eigen::VectorXd a(5); - a << 1.1, 1.2, 1.3, 1.4, 1.5; - Eigen::RowVectorXd b(5); - b << 1.1, 1.2, 1.3, 1.4, 1.5; - stan::math::multiply(a, stan::math::inv_square(b)); -} diff --git a/test/unit/math/prim/fun/inv_test.cpp b/test/unit/math/prim/fun/inv_test.cpp index 99f9d21a969..f418be35db1 100644 --- a/test/unit/math/prim/fun/inv_test.cpp +++ b/test/unit/math/prim/fun/inv_test.cpp @@ -19,11 +19,3 @@ TEST(MathFunctions, inv_nan) { EXPECT_TRUE(std::isnan(stan::math::inv(nan))); } - -TEST(MathFunctions, inv_works_with_other_functions) { - Eigen::VectorXd a(5); - a << 1.1, 1.2, 1.3, 1.4, 1.5; - Eigen::RowVectorXd b(5); - b << 1.1, 1.2, 1.3, 1.4, 1.5; - stan::math::multiply(a, stan::math::inv(b)); -} diff --git a/test/unit/math/prim/fun/lgamma_test.cpp b/test/unit/math/prim/fun/lgamma_test.cpp index 77e52134c33..d252006d5d5 100644 --- a/test/unit/math/prim/fun/lgamma_test.cpp +++ b/test/unit/math/prim/fun/lgamma_test.cpp @@ -26,11 +26,3 @@ TEST(MathFunctions, lgamma_nan) { EXPECT_TRUE( std::isnormal(boost::math::lgamma(1.0E50, stan::math::boost_policy_t()))); } - -TEST(MathFunctions, lgamma_works_with_other_functions) { - Eigen::VectorXd a(5); - a << 1.1, 1.2, 1.3, 1.4, 1.5; - Eigen::RowVectorXd b(5); - b << 1.1, 1.2, 1.3, 1.4, 1.5; - stan::math::multiply(a, stan::math::lgamma(b)); -} diff --git a/test/unit/math/prim/fun/log10_test.cpp b/test/unit/math/prim/fun/log10_test.cpp index 4e3e79e94fc..1a67f75a75c 100644 --- a/test/unit/math/prim/fun/log10_test.cpp +++ b/test/unit/math/prim/fun/log10_test.cpp @@ -5,11 +5,3 @@ TEST(primScalFun, log10) { stan::test::expect_common_prim([](auto x) { return std::log10(x); }, [](auto x) { return stan::math::log10(x); }); } - -TEST(MathFunctions, log10_works_with_other_functions) { - Eigen::VectorXd a(5); - a << 1.1, 1.2, 1.3, 1.4, 1.5; - Eigen::RowVectorXd b(5); - b << 1.1, 1.2, 1.3, 1.4, 1.5; - stan::math::multiply(a, stan::math::log10(b)); -} diff --git a/test/unit/math/prim/fun/log1m_test.cpp b/test/unit/math/prim/fun/log1m_test.cpp index 2c68c5a825e..a0cf248f987 100644 --- a/test/unit/math/prim/fun/log1m_test.cpp +++ b/test/unit/math/prim/fun/log1m_test.cpp @@ -22,11 +22,3 @@ TEST(MathFunctions, log1m_nan) { double nan = std::numeric_limits::quiet_NaN(); EXPECT_TRUE(std::isnan(stan::math::log1m(nan))); } - -TEST(MathFunctions, log1m_works_with_other_functions) { - Eigen::VectorXd a(5); - a << 0.1, 0.2, 0.3, 0.4, 0.5; - Eigen::RowVectorXd b(5); - b << 0.1, 0.2, 0.3, 0.4, 0.5; - stan::math::multiply(a, stan::math::log1m(b)); -} diff --git a/test/unit/math/prim/fun/log1p_exp_test.cpp b/test/unit/math/prim/fun/log1p_exp_test.cpp index aa4b3fd0303..6930db3a1eb 100644 --- a/test/unit/math/prim/fun/log1p_exp_test.cpp +++ b/test/unit/math/prim/fun/log1p_exp_test.cpp @@ -16,11 +16,3 @@ TEST(MathFunctions, log1p_exp_nan) { EXPECT_TRUE(std::isnan(stan::math::log1p_exp(nan))); } - -TEST(MathFunctions, log1p_exp_works_with_other_functions) { - Eigen::VectorXd a(5); - a << 1.1, 1.2, 1.3, 1.4, 1.5; - Eigen::RowVectorXd b(5); - b << 1.1, 1.2, 1.3, 1.4, 1.5; - stan::math::multiply(a, stan::math::log1p_exp(b)); -} diff --git a/test/unit/math/prim/fun/log1p_test.cpp b/test/unit/math/prim/fun/log1p_test.cpp index 714958a1745..35f90f46452 100644 --- a/test/unit/math/prim/fun/log1p_test.cpp +++ b/test/unit/math/prim/fun/log1p_test.cpp @@ -40,11 +40,3 @@ TEST(MathFunctions, log1p_nan) { double nan = std::numeric_limits::quiet_NaN(); EXPECT_TRUE(std::isnan(stan::math::log1p(nan))); } - -TEST(MathFunctions, log1p_works_with_other_functions) { - Eigen::VectorXd a(5); - a << 1.1, 1.2, 1.3, 1.4, 1.5; - Eigen::RowVectorXd b(5); - b << 1.1, 1.2, 1.3, 1.4, 1.5; - stan::math::multiply(a, stan::math::log1p(b)); -} diff --git a/test/unit/math/prim/fun/log2_test.cpp b/test/unit/math/prim/fun/log2_test.cpp index cf726f78ceb..031a50afa97 100644 --- a/test/unit/math/prim/fun/log2_test.cpp +++ b/test/unit/math/prim/fun/log2_test.cpp @@ -22,11 +22,3 @@ TEST(MathFunctions, log2_nan) { EXPECT_TRUE(std::isnan(stan::math::log2(nan))); } - -TEST(MathFunctions, log2_works_with_other_functions) { - Eigen::VectorXd a(5); - a << 1.1, 1.2, 1.3, 1.4, 1.5; - Eigen::RowVectorXd b(5); - b << 1.1, 1.2, 1.3, 1.4, 1.5; - stan::math::multiply(a, stan::math::log2(b)); -} diff --git a/test/unit/math/prim/fun/log_inv_logit_test.cpp b/test/unit/math/prim/fun/log_inv_logit_test.cpp index bb13d370b2a..774d044a4dd 100644 --- a/test/unit/math/prim/fun/log_inv_logit_test.cpp +++ b/test/unit/math/prim/fun/log_inv_logit_test.cpp @@ -18,11 +18,3 @@ TEST(MathFunctions, log_inv_logit_nan) { EXPECT_TRUE(std::isnan(stan::math::log_inv_logit(nan))); } - -TEST(MathFunctions, log_inv_logit_works_with_other_functions) { - Eigen::VectorXd a(5); - a << 1.1, 1.2, 1.3, 1.4, 1.5; - Eigen::RowVectorXd b(5); - b << 1.1, 1.2, 1.3, 1.4, 1.5; - stan::math::multiply(a, stan::math::log_inv_logit(b)); -} diff --git a/test/unit/math/prim/fun/log_softmax_test.cpp b/test/unit/math/prim/fun/log_softmax_test.cpp index eff97db3cd9..ba26ba1ce20 100644 --- a/test/unit/math/prim/fun/log_softmax_test.cpp +++ b/test/unit/math/prim/fun/log_softmax_test.cpp @@ -47,11 +47,3 @@ TEST(MathMatrixPrimMat, log_softmax_exception) { EXPECT_THROW(log_softmax(v0), std::invalid_argument); } - -TEST(MathFunctions, log_softmax_works_with_other_functions) { - Eigen::VectorXd a(5); - a << 1.1, 1.2, 1.3, 1.4, 1.5; - Eigen::RowVectorXd b(5); - b << 1.1, 1.2, 1.3, 1.4, 1.5; - stan::math::multiply(a, stan::math::log_softmax(b)); -} diff --git a/test/unit/math/prim/fun/log_test.cpp b/test/unit/math/prim/fun/log_test.cpp index f7163dbcf1a..77563092631 100644 --- a/test/unit/math/prim/fun/log_test.cpp +++ b/test/unit/math/prim/fun/log_test.cpp @@ -7,11 +7,3 @@ TEST(MathFunctions, logInt) { EXPECT_FLOAT_EQ(std::log(3), log(3)); EXPECT_FLOAT_EQ(std::log(3.0), log(3.0)); } - -TEST(MathFunctions, log_works_with_other_functions) { - Eigen::VectorXd a(5); - a << 1.1, 1.2, 1.3, 1.4, 1.5; - Eigen::RowVectorXd b(5); - b << 1.1, 1.2, 1.3, 1.4, 1.5; - stan::math::multiply(a, stan::math::log(b)); -} diff --git a/test/unit/math/prim/fun/logit_test.cpp b/test/unit/math/prim/fun/logit_test.cpp index 566cbcd88ad..b6820aa4b7f 100644 --- a/test/unit/math/prim/fun/logit_test.cpp +++ b/test/unit/math/prim/fun/logit_test.cpp @@ -14,11 +14,3 @@ TEST(MathFunctions, logit_nan) { EXPECT_TRUE(std::isnan(stan::math::logit(nan))); } - -TEST(MathFunctions, logit_works_with_other_functions) { - Eigen::VectorXd a(5); - a << 1.1, 1.2, 1.3, 1.4, 1.5; - Eigen::RowVectorXd b(5); - b << 1.1, 1.2, 1.3, 1.4, 1.5; - stan::math::multiply(a, stan::math::logit(b)); -} diff --git a/test/unit/math/prim/fun/minus_test.cpp b/test/unit/math/prim/fun/minus_test.cpp index d3dd9bdad85..e9535ca4781 100644 --- a/test/unit/math/prim/fun/minus_test.cpp +++ b/test/unit/math/prim/fun/minus_test.cpp @@ -10,11 +10,3 @@ TEST(MathMatrixPrimMat, minus) { EXPECT_EQ(0, stan::math::minus(rv0).size()); EXPECT_EQ(0, stan::math::minus(m0).size()); } - -TEST(MathFunctions, minus_works_with_other_functions) { - Eigen::VectorXd a(5); - a << 1.1, 1.2, 1.3, 1.4, 1.5; - Eigen::RowVectorXd b(5); - b << 1.1, 1.2, 1.3, 1.4, 1.5; - stan::math::multiply(a, stan::math::minus(b)); -} diff --git a/test/unit/math/prim/fun/round_test.cpp b/test/unit/math/prim/fun/round_test.cpp index 3cabf152e67..40cc1a8334f 100644 --- a/test/unit/math/prim/fun/round_test.cpp +++ b/test/unit/math/prim/fun/round_test.cpp @@ -17,11 +17,3 @@ TEST(MathFunctions, roundNaN) { double nan = std::numeric_limits::quiet_NaN(); EXPECT_TRUE(std::isnan(stan::math::round(nan))); } - -TEST(MathFunctions, round_works_with_other_functions) { - Eigen::VectorXd a(5); - a << 1.1, 1.2, 1.3, 1.4, 1.5; - Eigen::RowVectorXd b(5); - b << 1.1, 1.2, 1.3, 1.4, 1.5; - stan::math::multiply(a, stan::math::round(b)); -} diff --git a/test/unit/math/prim/fun/sin_test.cpp b/test/unit/math/prim/fun/sin_test.cpp index 4125f5e22f8..3a564bfea3b 100644 --- a/test/unit/math/prim/fun/sin_test.cpp +++ b/test/unit/math/prim/fun/sin_test.cpp @@ -5,11 +5,3 @@ TEST(primScalFun, sin) { stan::test::expect_common_prim([](auto x) { return std::sin(x); }, [](auto x) { return stan::math::sin(x); }); } - -TEST(MathFunctions, sin_works_with_other_functions) { - Eigen::VectorXd a(5); - a << 1.1, 1.2, 1.3, 1.4, 1.5; - Eigen::RowVectorXd b(5); - b << 1.1, 1.2, 1.3, 1.4, 1.5; - stan::math::multiply(a, stan::math::sin(b)); -} diff --git a/test/unit/math/prim/fun/sinh_test.cpp b/test/unit/math/prim/fun/sinh_test.cpp index 72e3f143e5d..72b18d36f94 100644 --- a/test/unit/math/prim/fun/sinh_test.cpp +++ b/test/unit/math/prim/fun/sinh_test.cpp @@ -5,11 +5,3 @@ TEST(primScalFun, sinh) { stan::test::expect_common_prim([](auto x) { return std::sinh(x); }, [](auto x) { return stan::math::sinh(x); }); } - -TEST(MathFunctions, sinh_works_with_other_functions) { - Eigen::VectorXd a(5); - a << 1.1, 1.2, 1.3, 1.4, 1.5; - Eigen::RowVectorXd b(5); - b << 1.1, 1.2, 1.3, 1.4, 1.5; - stan::math::multiply(a, stan::math::sinh(b)); -} diff --git a/test/unit/math/prim/fun/sqrt_test.cpp b/test/unit/math/prim/fun/sqrt_test.cpp index 9896911dbf5..43c362d0cc9 100644 --- a/test/unit/math/prim/fun/sqrt_test.cpp +++ b/test/unit/math/prim/fun/sqrt_test.cpp @@ -7,11 +7,3 @@ TEST(MathFunctions, sqrtInt) { EXPECT_FLOAT_EQ(std::sqrt(3.0), sqrt(3)); EXPECT_TRUE(stan::math::is_nan(sqrt(-2))); } - -TEST(MathFunctions, sqrt_works_with_other_functions) { - Eigen::VectorXd a(5); - a << 1.1, 1.2, 1.3, 1.4, 1.5; - Eigen::RowVectorXd b(5); - b << 1.1, 1.2, 1.3, 1.4, 1.5; - stan::math::multiply(a, stan::math::sqrt(b)); -} diff --git a/test/unit/math/prim/fun/square_test.cpp b/test/unit/math/prim/fun/square_test.cpp index 13b66189bcf..aadd3009906 100644 --- a/test/unit/math/prim/fun/square_test.cpp +++ b/test/unit/math/prim/fun/square_test.cpp @@ -3,7 +3,7 @@ #include #include -TEST(MathFunctions, square) { +TEST(MathsFunctions, square) { double y = 2.0; EXPECT_FLOAT_EQ(y * y, stan::math::square(y)); @@ -19,11 +19,3 @@ TEST(MathFunctions, square_nan) { EXPECT_TRUE(std::isnan(stan::math::square(nan))); } - -TEST(MathFunctions, square_works_with_other_functions) { - Eigen::VectorXd a(5); - a << 1.1, 1.2, 1.3, 1.4, 1.5; - Eigen::RowVectorXd b(5); - b << 1.1, 1.2, 1.3, 1.4, 1.5; - stan::math::multiply(a, stan::math::square(b)); -} diff --git a/test/unit/math/prim/fun/tan_test.cpp b/test/unit/math/prim/fun/tan_test.cpp deleted file mode 100644 index 5b9e861cabc..00000000000 --- a/test/unit/math/prim/fun/tan_test.cpp +++ /dev/null @@ -1,10 +0,0 @@ -#include -#include - -TEST(MathFunctions, tan_works_with_other_functions) { - Eigen::VectorXd a(5); - a << 1.1, 1.2, 1.3, 1.4, 1.5; - Eigen::RowVectorXd b(5); - b << 1.1, 1.2, 1.3, 1.4, 1.5; - stan::math::multiply(a, stan::math::tan(b)); -} diff --git a/test/unit/math/prim/fun/tanh_test.cpp b/test/unit/math/prim/fun/tanh_test.cpp index 594d0e37ed5..bd4da5755c9 100644 --- a/test/unit/math/prim/fun/tanh_test.cpp +++ b/test/unit/math/prim/fun/tanh_test.cpp @@ -5,11 +5,3 @@ TEST(primScalFun, tanh) { stan::test::expect_common_prim([](auto x) { return std::tanh(x); }, [](auto x) { return stan::math::tanh(x); }); } - -TEST(MathFunctions, tanh_works_with_other_functions) { - Eigen::VectorXd a(5); - a << 1.1, 1.2, 1.3, 1.4, 1.5; - Eigen::RowVectorXd b(5); - b << 1.1, 1.2, 1.3, 1.4, 1.5; - stan::math::multiply(a, stan::math::tanh(b)); -} diff --git a/test/unit/math/prim/fun/tgamma_test.cpp b/test/unit/math/prim/fun/tgamma_test.cpp index 2ecb0bd51cc..51e5b84261c 100644 --- a/test/unit/math/prim/fun/tgamma_test.cpp +++ b/test/unit/math/prim/fun/tgamma_test.cpp @@ -20,11 +20,3 @@ TEST(MathFunctions, tgamma_nan) { double nan = std::numeric_limits::quiet_NaN(); EXPECT_TRUE(std::isnan(stan::math::tgamma(nan))); } - -TEST(MathFunctions, tgamma_works_with_other_functions) { - Eigen::VectorXd a(5); - a << 1.1, 1.2, 1.3, 1.4, 1.5; - Eigen::RowVectorXd b(5); - b << 1.1, 1.2, 1.3, 1.4, 1.5; - stan::math::multiply(a, stan::math::tgamma(b)); -} diff --git a/test/unit/math/prim/fun/trigamma_test.cpp b/test/unit/math/prim/fun/trigamma_test.cpp index c2d4484d1f0..d2066598d32 100644 --- a/test/unit/math/prim/fun/trigamma_test.cpp +++ b/test/unit/math/prim/fun/trigamma_test.cpp @@ -17,11 +17,3 @@ TEST(MathFunctions, trigamma_nan) { EXPECT_TRUE(std::isnan(stan::math::trigamma(nan))); } - -TEST(MathFunctions, trigamma_works_with_other_functions) { - Eigen::VectorXd a(5); - a << 1.1, 1.2, 1.3, 1.4, 1.5; - Eigen::RowVectorXd b(5); - b << 1.1, 1.2, 1.3, 1.4, 1.5; - stan::math::multiply(a, stan::math::trigamma(b)); -} diff --git a/test/unit/math/prim/fun/trunc_test.cpp b/test/unit/math/prim/fun/trunc_test.cpp index 2f64da18b03..8aa3a7c6a00 100644 --- a/test/unit/math/prim/fun/trunc_test.cpp +++ b/test/unit/math/prim/fun/trunc_test.cpp @@ -17,11 +17,3 @@ TEST(MathFunctions, truncNaN) { double nan = std::numeric_limits::quiet_NaN(); EXPECT_TRUE(std::isnan(stan::math::trunc(nan))); } - -TEST(MathFunctions, trunc_works_with_other_functions) { - Eigen::VectorXd a(5); - a << 1.1, 1.2, 1.3, 1.4, 1.5; - Eigen::RowVectorXd b(5); - b << 1.1, 1.2, 1.3, 1.4, 1.5; - stan::math::multiply(a, stan::math::trunc(b)); -} From b96e4018df7438f93ac19c0851a030fb5c7a73cd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rok=20=C4=8Ce=C5=A1novar?= Date: Wed, 29 Jan 2020 19:05:54 +0100 Subject: [PATCH 006/355] Fixed conflict in stan/math/prim/fun/log_softmax.hpp --- stan/math/prim/fun/acos.hpp | 2 +- stan/math/prim/fun/asin.hpp | 2 +- stan/math/prim/fun/atan.hpp | 2 +- stan/math/prim/fun/ceil.hpp | 2 +- stan/math/prim/fun/cos.hpp | 2 +- stan/math/prim/fun/cosh.hpp | 2 +- stan/math/prim/fun/exp.hpp | 2 +- stan/math/prim/fun/fabs.hpp | 4 ++-- stan/math/prim/fun/floor.hpp | 2 +- stan/math/prim/fun/inv.hpp | 4 ++-- stan/math/prim/fun/inv_cloglog.hpp | 4 ++-- stan/math/prim/fun/inv_sqrt.hpp | 4 ++-- stan/math/prim/fun/log.hpp | 2 +- stan/math/prim/fun/log10.hpp | 2 +- stan/math/prim/fun/log_softmax.hpp | 11 ++++++----- stan/math/prim/fun/minus.hpp | 4 +++- stan/math/prim/fun/round.hpp | 2 +- stan/math/prim/fun/sin.hpp | 2 +- stan/math/prim/fun/sinh.hpp | 4 ++-- stan/math/prim/fun/sqrt.hpp | 2 +- stan/math/prim/fun/tan.hpp | 2 +- stan/math/prim/fun/tanh.hpp | 2 +- stan/math/prim/vectorize/apply_scalar_unary.hpp | 7 +++++-- test/unit/math/prim/fun/Phi_approx_test.cpp | 8 ++++++++ test/unit/math/prim/fun/Phi_test.cpp | 8 ++++++++ test/unit/math/prim/fun/acos_test.cpp | 8 ++++++++ test/unit/math/prim/fun/acosh_test.cpp | 8 ++++++++ test/unit/math/prim/fun/asin_test.cpp | 8 ++++++++ test/unit/math/prim/fun/asinh_test.cpp | 8 ++++++++ test/unit/math/prim/fun/atan_test.cpp | 8 ++++++++ test/unit/math/prim/fun/atanh_test.cpp | 8 ++++++++ test/unit/math/prim/fun/cbrt_test.cpp | 8 ++++++++ test/unit/math/prim/fun/ceil_test.cpp | 8 ++++++++ test/unit/math/prim/fun/cos_test.cpp | 8 ++++++++ test/unit/math/prim/fun/cosh_test.cpp | 10 ++++++++++ test/unit/math/prim/fun/digamma_test.cpp | 8 ++++++++ test/unit/math/prim/fun/erf_test.cpp | 8 ++++++++ test/unit/math/prim/fun/erfc_test.cpp | 8 ++++++++ test/unit/math/prim/fun/exp2_test.cpp | 8 ++++++++ test/unit/math/prim/fun/exp_test.cpp | 8 ++++++++ test/unit/math/prim/fun/expm1_test.cpp | 8 ++++++++ test/unit/math/prim/fun/fabs_test.cpp | 8 ++++++++ test/unit/math/prim/fun/floor_test.cpp | 8 ++++++++ test/unit/math/prim/fun/inv_Phi_test.cpp | 8 ++++++++ test/unit/math/prim/fun/inv_cloglog_test.cpp | 8 ++++++++ test/unit/math/prim/fun/inv_logit_test.cpp | 8 ++++++++ test/unit/math/prim/fun/inv_sqrt_test.cpp | 8 ++++++++ test/unit/math/prim/fun/inv_square_test.cpp | 8 ++++++++ test/unit/math/prim/fun/inv_test.cpp | 8 ++++++++ test/unit/math/prim/fun/lgamma_test.cpp | 8 ++++++++ test/unit/math/prim/fun/log10_test.cpp | 8 ++++++++ test/unit/math/prim/fun/log1m_test.cpp | 8 ++++++++ test/unit/math/prim/fun/log1p_exp_test.cpp | 8 ++++++++ test/unit/math/prim/fun/log1p_test.cpp | 8 ++++++++ test/unit/math/prim/fun/log2_test.cpp | 8 ++++++++ test/unit/math/prim/fun/log_inv_logit_test.cpp | 8 ++++++++ test/unit/math/prim/fun/log_softmax_test.cpp | 8 ++++++++ test/unit/math/prim/fun/log_test.cpp | 8 ++++++++ test/unit/math/prim/fun/logit_test.cpp | 8 ++++++++ test/unit/math/prim/fun/minus_test.cpp | 8 ++++++++ test/unit/math/prim/fun/round_test.cpp | 8 ++++++++ test/unit/math/prim/fun/sin_test.cpp | 8 ++++++++ test/unit/math/prim/fun/sinh_test.cpp | 8 ++++++++ test/unit/math/prim/fun/sqrt_test.cpp | 8 ++++++++ test/unit/math/prim/fun/square_test.cpp | 10 +++++++++- test/unit/math/prim/fun/tan_test.cpp | 10 ++++++++++ test/unit/math/prim/fun/tanh_test.cpp | 8 ++++++++ test/unit/math/prim/fun/tgamma_test.cpp | 8 ++++++++ test/unit/math/prim/fun/trigamma_test.cpp | 8 ++++++++ test/unit/math/prim/fun/trunc_test.cpp | 8 ++++++++ 70 files changed, 420 insertions(+), 34 deletions(-) create mode 100644 test/unit/math/prim/fun/cosh_test.cpp create mode 100644 test/unit/math/prim/fun/tan_test.cpp diff --git a/stan/math/prim/fun/acos.hpp b/stan/math/prim/fun/acos.hpp index 709864e1db6..e5960f1b758 100644 --- a/stan/math/prim/fun/acos.hpp +++ b/stan/math/prim/fun/acos.hpp @@ -45,7 +45,7 @@ inline auto acos(const T& x) { template > inline auto acos(const Eigen::MatrixBase& x) { - return x.derived().array().acos().matrix(); + return x.derived().array().acos().matrix().eval(); } } // namespace math diff --git a/stan/math/prim/fun/asin.hpp b/stan/math/prim/fun/asin.hpp index 81a22dcf60b..0f5d172a29b 100644 --- a/stan/math/prim/fun/asin.hpp +++ b/stan/math/prim/fun/asin.hpp @@ -45,7 +45,7 @@ inline auto asin(const T& x) { template > inline auto asin(const Eigen::MatrixBase& x) { - return x.derived().array().asin().matrix(); + return x.derived().array().asin().matrix().eval(); } } // namespace math diff --git a/stan/math/prim/fun/atan.hpp b/stan/math/prim/fun/atan.hpp index 28a05b08d6a..9576c99240a 100644 --- a/stan/math/prim/fun/atan.hpp +++ b/stan/math/prim/fun/atan.hpp @@ -45,7 +45,7 @@ inline typename apply_scalar_unary::return_t atan(const T& x) { template > inline auto atan(const Eigen::MatrixBase& x) { - return x.derived().array().atan().matrix(); + return x.derived().array().atan().matrix().eval(); } } // namespace math diff --git a/stan/math/prim/fun/ceil.hpp b/stan/math/prim/fun/ceil.hpp index 7a78566ac1d..2de0ddb72e7 100644 --- a/stan/math/prim/fun/ceil.hpp +++ b/stan/math/prim/fun/ceil.hpp @@ -45,7 +45,7 @@ inline auto ceil(const T& x) { template > inline auto ceil(const Eigen::MatrixBase& x) { - return x.derived().array().ceil().matrix(); + return x.derived().array().ceil().matrix().eval(); } } // namespace math diff --git a/stan/math/prim/fun/cos.hpp b/stan/math/prim/fun/cos.hpp index 0c20e53f935..bf9761ace9f 100644 --- a/stan/math/prim/fun/cos.hpp +++ b/stan/math/prim/fun/cos.hpp @@ -45,7 +45,7 @@ inline auto cos(const T& x) { template > inline auto cos(const Eigen::MatrixBase& x) { - return x.derived().array().cos().matrix(); + return x.derived().array().cos().matrix().eval(); } } // namespace math diff --git a/stan/math/prim/fun/cosh.hpp b/stan/math/prim/fun/cosh.hpp index 3dee3eae2a3..2a0402fe9c2 100644 --- a/stan/math/prim/fun/cosh.hpp +++ b/stan/math/prim/fun/cosh.hpp @@ -45,7 +45,7 @@ inline typename apply_scalar_unary::return_t cosh(const T& x) { template > inline auto cosh(const Eigen::MatrixBase& x) { - return x.derived().array().cosh().matrix(); + return x.derived().array().cosh().matrix().eval(); } } // namespace math diff --git a/stan/math/prim/fun/exp.hpp b/stan/math/prim/fun/exp.hpp index 4d60b4c04b5..54486d9e394 100644 --- a/stan/math/prim/fun/exp.hpp +++ b/stan/math/prim/fun/exp.hpp @@ -60,7 +60,7 @@ inline auto exp(const T& x) { template > inline auto exp(const Eigen::MatrixBase& x) { - return x.derived().array().exp().matrix(); + return x.derived().array().exp().matrix().eval(); } } // namespace math diff --git a/stan/math/prim/fun/fabs.hpp b/stan/math/prim/fun/fabs.hpp index 1dc51b0ee3c..2bfc97071d2 100644 --- a/stan/math/prim/fun/fabs.hpp +++ b/stan/math/prim/fun/fabs.hpp @@ -45,7 +45,7 @@ inline typename apply_scalar_unary::return_t fabs(const T& x) { template > inline auto fabs(const Eigen::MatrixBase& x) { - return x.derived().array().abs().matrix(); + return x.derived().array().abs().matrix().eval(); } /** @@ -57,7 +57,7 @@ inline auto fabs(const Eigen::MatrixBase& x) { template > inline auto fabs(const Eigen::ArrayBase& x) { - return x.derived().abs(); + return x.derived().abs().eval(); } } // namespace math diff --git a/stan/math/prim/fun/floor.hpp b/stan/math/prim/fun/floor.hpp index 7f1f37317cd..c53433cf356 100644 --- a/stan/math/prim/fun/floor.hpp +++ b/stan/math/prim/fun/floor.hpp @@ -45,7 +45,7 @@ inline auto floor(const T& x) { template > inline auto floor(const Eigen::MatrixBase& x) { - return x.derived().array().floor().matrix(); + return x.derived().array().floor().matrix().eval(); } } // namespace math diff --git a/stan/math/prim/fun/inv.hpp b/stan/math/prim/fun/inv.hpp index f50f17f784c..439dc962778 100644 --- a/stan/math/prim/fun/inv.hpp +++ b/stan/math/prim/fun/inv.hpp @@ -45,7 +45,7 @@ inline auto inv(const T& x) { template > inline auto inv(const Eigen::MatrixBase& x) { - return x.derived().array().inverse().matrix(); + return x.derived().array().inverse().matrix().eval(); } /** @@ -57,7 +57,7 @@ inline auto inv(const Eigen::MatrixBase& x) { template > inline auto inv(const Eigen::ArrayBase& x) { - return x.derived().inverse(); + return x.derived().inverse().eval(); } } // namespace math diff --git a/stan/math/prim/fun/inv_cloglog.hpp b/stan/math/prim/fun/inv_cloglog.hpp index 945417aa0f9..44c6dfdc8d7 100644 --- a/stan/math/prim/fun/inv_cloglog.hpp +++ b/stan/math/prim/fun/inv_cloglog.hpp @@ -87,7 +87,7 @@ inline auto inv_cloglog(const T& x) { template > inline auto inv_cloglog(const Eigen::MatrixBase& x) { - return (1 - exp(-exp(x.derived().array()))).matrix(); + return (1 - exp(-exp(x.derived().array()))).matrix().eval(); } /** @@ -99,7 +99,7 @@ inline auto inv_cloglog(const Eigen::MatrixBase& x) { template > inline auto inv_cloglog(const Eigen::ArrayBase& x) { - return 1 - exp(-exp(x.derived())); + return (1 - exp(-exp(x.derived()))).eval(); } } // namespace math diff --git a/stan/math/prim/fun/inv_sqrt.hpp b/stan/math/prim/fun/inv_sqrt.hpp index aa6e0d7ffdf..66b41ee7138 100644 --- a/stan/math/prim/fun/inv_sqrt.hpp +++ b/stan/math/prim/fun/inv_sqrt.hpp @@ -50,7 +50,7 @@ inline auto inv_sqrt(const T& x) { template > inline auto inv_sqrt(const Eigen::MatrixBase& x) { - return x.derived().array().rsqrt().matrix(); + return x.derived().array().rsqrt().matrix().eval(); } /** @@ -62,7 +62,7 @@ inline auto inv_sqrt(const Eigen::MatrixBase& x) { template > inline auto inv_sqrt(const Eigen::ArrayBase& x) { - return x.derived().rsqrt(); + return x.derived().rsqrt().eval(); } } // namespace math diff --git a/stan/math/prim/fun/log.hpp b/stan/math/prim/fun/log.hpp index 2e32bc5aa4b..3814d0a5ae5 100644 --- a/stan/math/prim/fun/log.hpp +++ b/stan/math/prim/fun/log.hpp @@ -60,7 +60,7 @@ inline auto log(const T& x) { template > inline auto log(const Eigen::MatrixBase& x) { - return x.derived().array().log().matrix(); + return x.derived().array().log().matrix().eval(); } } // namespace math diff --git a/stan/math/prim/fun/log10.hpp b/stan/math/prim/fun/log10.hpp index 808bdb85bad..10b7b0fa1b0 100644 --- a/stan/math/prim/fun/log10.hpp +++ b/stan/math/prim/fun/log10.hpp @@ -45,7 +45,7 @@ inline auto log10(const T& x) { template > inline auto log10(const Eigen::MatrixBase& x) { - return x.derived().array().log10().matrix(); + return x.derived().array().log10().matrix().eval(); } } // namespace math diff --git a/stan/math/prim/fun/log_softmax.hpp b/stan/math/prim/fun/log_softmax.hpp index a51370d0b1a..8c4951df779 100644 --- a/stan/math/prim/fun/log_softmax.hpp +++ b/stan/math/prim/fun/log_softmax.hpp @@ -36,11 +36,12 @@ namespace math { * @param[in] v Vector to transform. * @return Unit simplex result of the softmax transform of the vector. */ -template -inline Eigen::Matrix log_softmax( - const Eigen::Matrix& v) { - check_nonzero_size("log_softmax", "v", v); - return v.array() - log_sum_exp(v); +template >>...> +inline auto log_softmax(const T& x) { + return apply_vector_unary::apply(x, [&](const auto& v) { + check_nonzero_size("log_softmax", "v", v); + return (v.array() - log_sum_exp(v)).matrix().eval(); + }); } } // namespace math diff --git a/stan/math/prim/fun/minus.hpp b/stan/math/prim/fun/minus.hpp index 7f374462fc0..13fe7d090ed 100644 --- a/stan/math/prim/fun/minus.hpp +++ b/stan/math/prim/fun/minus.hpp @@ -1,6 +1,8 @@ #ifndef STAN_MATH_PRIM_FUN_MINUS_HPP #define STAN_MATH_PRIM_FUN_MINUS_HPP +#include + namespace stan { namespace math { @@ -12,7 +14,7 @@ namespace math { * @return Negation of subtrahend. */ template -inline auto minus(const T& x) { +inline plain_type_t minus(const T& x) { return -x; } diff --git a/stan/math/prim/fun/round.hpp b/stan/math/prim/fun/round.hpp index 66b2d6a428c..e5cc48efd18 100644 --- a/stan/math/prim/fun/round.hpp +++ b/stan/math/prim/fun/round.hpp @@ -62,7 +62,7 @@ inline auto round(const T& x) { template > inline auto round(const Eigen::MatrixBase& x) { - return x.derived().array().round().matrix(); + return x.derived().array().round().matrix().eval(); } } // namespace math diff --git a/stan/math/prim/fun/sin.hpp b/stan/math/prim/fun/sin.hpp index f2ed9102f97..0b783ffeb20 100644 --- a/stan/math/prim/fun/sin.hpp +++ b/stan/math/prim/fun/sin.hpp @@ -45,7 +45,7 @@ inline auto sin(const T& x) { template > inline auto sin(const Eigen::MatrixBase& x) { - return x.derived().array().sin().matrix(); + return x.derived().array().sin().matrix().eval(); } } // namespace math diff --git a/stan/math/prim/fun/sinh.hpp b/stan/math/prim/fun/sinh.hpp index 5e13a03993e..e4d1252295d 100644 --- a/stan/math/prim/fun/sinh.hpp +++ b/stan/math/prim/fun/sinh.hpp @@ -45,7 +45,7 @@ inline auto sinh(const T& x) { template > inline auto sinh(const Eigen::MatrixBase& x) { - return x.derived().array().sinh().matrix(); + return x.derived().array().sinh().matrix().eval(); } /** @@ -57,7 +57,7 @@ inline auto sinh(const Eigen::MatrixBase& x) { template > inline auto sinh(const Eigen::ArrayBase& x) { - return x.derived().sinh(); + return x.derived().sinh().eval(); } } // namespace math diff --git a/stan/math/prim/fun/sqrt.hpp b/stan/math/prim/fun/sqrt.hpp index ae1b6dace93..fe81fcf75b6 100644 --- a/stan/math/prim/fun/sqrt.hpp +++ b/stan/math/prim/fun/sqrt.hpp @@ -54,7 +54,7 @@ inline auto sqrt(const T& x) { template > inline auto sqrt(const Eigen::MatrixBase& x) { - return x.derived().array().sqrt().matrix(); + return x.derived().array().sqrt().matrix().eval(); } } // namespace math diff --git a/stan/math/prim/fun/tan.hpp b/stan/math/prim/fun/tan.hpp index 7064300e695..efc03beb94b 100644 --- a/stan/math/prim/fun/tan.hpp +++ b/stan/math/prim/fun/tan.hpp @@ -45,7 +45,7 @@ inline auto tan(const T& x) { template > inline auto tan(const Eigen::MatrixBase& x) { - return x.derived().array().tan().matrix(); + return x.derived().array().tan().matrix().eval(); } } // namespace math diff --git a/stan/math/prim/fun/tanh.hpp b/stan/math/prim/fun/tanh.hpp index 60c4d405fb2..2fe9f4c5a25 100644 --- a/stan/math/prim/fun/tanh.hpp +++ b/stan/math/prim/fun/tanh.hpp @@ -45,7 +45,7 @@ inline auto tanh(const T& x) { template > inline auto tanh(const Eigen::MatrixBase& x) { - return x.derived().array().tanh().matrix(); + return x.derived().array().tanh().matrix().eval(); } } // namespace math diff --git a/stan/math/prim/vectorize/apply_scalar_unary.hpp b/stan/math/prim/vectorize/apply_scalar_unary.hpp index ed31037a207..8cc283cd4ac 100644 --- a/stan/math/prim/vectorize/apply_scalar_unary.hpp +++ b/stan/math/prim/vectorize/apply_scalar_unary.hpp @@ -59,8 +59,11 @@ struct apply_scalar_unary> { * by F to the specified matrix. */ static inline auto apply(const T& x) { - return x.unaryExpr( - [](scalar_t x) { return apply_scalar_unary::apply(x); }); + return x + .unaryExpr([](scalar_t x) { + return apply_scalar_unary::apply(x); + }) + .eval(); } /** diff --git a/test/unit/math/prim/fun/Phi_approx_test.cpp b/test/unit/math/prim/fun/Phi_approx_test.cpp index dbc4078352d..4a29923c572 100644 --- a/test/unit/math/prim/fun/Phi_approx_test.cpp +++ b/test/unit/math/prim/fun/Phi_approx_test.cpp @@ -14,3 +14,11 @@ TEST(MathFunctions, Phi_approx_nan) { EXPECT_TRUE(std::isnan(stan::math::Phi_approx(nan))); } + +TEST(MathFunctions, Phi_approx__works_with_other_functions) { + Eigen::VectorXd a(5); + a << 1.1, 1.2, 1.3, 1.4, 1.5; + Eigen::RowVectorXd b(5); + b << 1.1, 1.2, 1.3, 1.4, 1.5; + stan::math::multiply(a, stan::math::Phi_approx(b)); +} diff --git a/test/unit/math/prim/fun/Phi_test.cpp b/test/unit/math/prim/fun/Phi_test.cpp index c43e260bf88..1273ad24628 100644 --- a/test/unit/math/prim/fun/Phi_test.cpp +++ b/test/unit/math/prim/fun/Phi_test.cpp @@ -118,3 +118,11 @@ TEST(MathFunctions, Phi_nan) { double nan = std::numeric_limits::quiet_NaN(); EXPECT_THROW(stan::math::Phi(nan), std::domain_error); } + +TEST(MathFunctions, Phi_works_with_other_functions) { + Eigen::VectorXd a(5); + a << 1.1, 1.2, 1.3, 1.4, 1.5; + Eigen::RowVectorXd b(5); + b << 1.1, 1.2, 1.3, 1.4, 1.5; + stan::math::multiply(a, stan::math::Phi(b)); +} diff --git a/test/unit/math/prim/fun/acos_test.cpp b/test/unit/math/prim/fun/acos_test.cpp index c66c4c49a02..7570f52cc71 100644 --- a/test/unit/math/prim/fun/acos_test.cpp +++ b/test/unit/math/prim/fun/acos_test.cpp @@ -5,3 +5,11 @@ TEST(primScalFun, acos) { stan::test::expect_common_prim([](auto x) { return std::acos(x); }, [](auto x) { return stan::math::acos(x); }); } + +TEST(MathFunctions, acos_works_with_other_functions) { + Eigen::VectorXd a(5); + a << 0.1, 0.2, 0.3, 0.4, 0.5; + Eigen::RowVectorXd b(5); + b << 0.1, 0.2, 0.3, 0.4, 0.5; + stan::math::multiply(a, stan::math::acos(b)); +} diff --git a/test/unit/math/prim/fun/acosh_test.cpp b/test/unit/math/prim/fun/acosh_test.cpp index 2d5bc742d3c..1f9e8ab7bb5 100644 --- a/test/unit/math/prim/fun/acosh_test.cpp +++ b/test/unit/math/prim/fun/acosh_test.cpp @@ -26,3 +26,11 @@ TEST(MathFunctions, acosh_nan) { double nan = std::numeric_limits::quiet_NaN(); EXPECT_TRUE(std::isnan(stan::math::acosh(nan))); } + +TEST(MathFunctions, acosh_works_with_other_functions) { + Eigen::VectorXd a(5); + a << 1.1, 1.2, 1.3, 1.4, 1.5; + Eigen::RowVectorXd b(5); + b << 1.1, 1.2, 1.3, 1.4, 1.5; + stan::math::multiply(a, stan::math::acosh(b)); +} diff --git a/test/unit/math/prim/fun/asin_test.cpp b/test/unit/math/prim/fun/asin_test.cpp index a14245b58c2..858be5fbbbd 100644 --- a/test/unit/math/prim/fun/asin_test.cpp +++ b/test/unit/math/prim/fun/asin_test.cpp @@ -5,3 +5,11 @@ TEST(primScalFun, asin) { stan::test::expect_common_prim([](auto x) { return std::asin(x); }, [](auto x) { return stan::math::asin(x); }); } + +TEST(MathFunctions, asin_works_with_other_functions) { + Eigen::VectorXd a(5); + a << 0.1, 0.2, 0.3, 0.4, 0.5; + Eigen::RowVectorXd b(5); + b << 0.1, 0.2, 0.3, 0.4, 0.5; + stan::math::multiply(a, stan::math::asin(b)); +} diff --git a/test/unit/math/prim/fun/asinh_test.cpp b/test/unit/math/prim/fun/asinh_test.cpp index 151afc2b3ef..e10228b0af0 100644 --- a/test/unit/math/prim/fun/asinh_test.cpp +++ b/test/unit/math/prim/fun/asinh_test.cpp @@ -22,3 +22,11 @@ TEST(MathFunctions, asinh_nan) { double nan = std::numeric_limits::quiet_NaN(); EXPECT_TRUE(std::isnan(stan::math::asinh(nan))); } + +TEST(MathFunctions, asinh_works_with_other_functions) { + Eigen::VectorXd a(5); + a << 1.1, 1.2, 1.3, 1.4, 1.5; + Eigen::RowVectorXd b(5); + b << 1.1, 1.2, 1.3, 1.4, 1.5; + stan::math::multiply(a, stan::math::asinh(b)); +} diff --git a/test/unit/math/prim/fun/atan_test.cpp b/test/unit/math/prim/fun/atan_test.cpp index 467ceefff7d..54861be5151 100644 --- a/test/unit/math/prim/fun/atan_test.cpp +++ b/test/unit/math/prim/fun/atan_test.cpp @@ -5,3 +5,11 @@ TEST(primScalFun, atan) { stan::test::expect_common_prim([](auto x) { return std::atan(x); }, [](auto x) { return stan::math::atan(x); }); } + +TEST(MathFunctions, atan_works_with_other_functions) { + Eigen::VectorXd a(5); + a << 1.1, 1.2, 1.3, 1.4, 1.5; + Eigen::RowVectorXd b(5); + b << 1.1, 1.2, 1.3, 1.4, 1.5; + stan::math::multiply(a, stan::math::atan(b)); +} diff --git a/test/unit/math/prim/fun/atanh_test.cpp b/test/unit/math/prim/fun/atanh_test.cpp index ca60e585e86..18ae151e23c 100644 --- a/test/unit/math/prim/fun/atanh_test.cpp +++ b/test/unit/math/prim/fun/atanh_test.cpp @@ -27,3 +27,11 @@ TEST(MathFunctions, atanh_nan) { double nan = std::numeric_limits::quiet_NaN(); EXPECT_TRUE(std::isnan(stan::math::atanh(nan))); } + +TEST(MathFunctions, atanh_works_with_other_functions) { + Eigen::VectorXd a(5); + a << 0.1, 0.2, 0.3, 0.4, 0.5; + Eigen::RowVectorXd b(5); + b << 0.1, 0.2, 0.3, 0.4, 0.5; + stan::math::multiply(a, stan::math::atanh(b)); +} diff --git a/test/unit/math/prim/fun/cbrt_test.cpp b/test/unit/math/prim/fun/cbrt_test.cpp index 2ca66bbde53..854853943a6 100644 --- a/test/unit/math/prim/fun/cbrt_test.cpp +++ b/test/unit/math/prim/fun/cbrt_test.cpp @@ -24,3 +24,11 @@ TEST(MathFunctions, cbrt_nan) { double nan = std::numeric_limits::quiet_NaN(); EXPECT_TRUE(std::isnan(stan::math::cbrt(nan))); } + +TEST(MathFunctions, cbrt_works_with_other_functions) { + Eigen::VectorXd a(5); + a << 1.1, 1.2, 1.3, 1.4, 1.5; + Eigen::RowVectorXd b(5); + b << 1.1, 1.2, 1.3, 1.4, 1.5; + stan::math::multiply(a, stan::math::cbrt(b)); +} diff --git a/test/unit/math/prim/fun/ceil_test.cpp b/test/unit/math/prim/fun/ceil_test.cpp index f26f0068eb1..57a7dce8c41 100644 --- a/test/unit/math/prim/fun/ceil_test.cpp +++ b/test/unit/math/prim/fun/ceil_test.cpp @@ -4,3 +4,11 @@ TEST(primScalFun, ceil) { stan::test::expect_common_prim([](auto x) { return std::ceil(x); }, [](auto x) { return stan::math::ceil(x); }); } + +TEST(MathFunctions, ceil_works_with_other_functions) { + Eigen::VectorXd a(5); + a << 1.1, 1.2, 1.3, 1.4, 1.5; + Eigen::RowVectorXd b(5); + b << 1.1, 1.2, 1.3, 1.4, 1.5; + stan::math::multiply(a, stan::math::ceil(b)); +} diff --git a/test/unit/math/prim/fun/cos_test.cpp b/test/unit/math/prim/fun/cos_test.cpp index 53daaa398de..94989f9703f 100644 --- a/test/unit/math/prim/fun/cos_test.cpp +++ b/test/unit/math/prim/fun/cos_test.cpp @@ -5,3 +5,11 @@ TEST(primScalFun, cos) { stan::test::expect_common_prim([](auto x) { return std::cos(x); }, [](auto x) { return stan::math::cos(x); }); } + +TEST(MathFunctions, cos_works_with_other_functions) { + Eigen::VectorXd a(5); + a << 1.1, 1.2, 1.3, 1.4, 1.5; + Eigen::RowVectorXd b(5); + b << 1.1, 1.2, 1.3, 1.4, 1.5; + stan::math::multiply(a, stan::math::cos(b)); +} diff --git a/test/unit/math/prim/fun/cosh_test.cpp b/test/unit/math/prim/fun/cosh_test.cpp new file mode 100644 index 00000000000..d1433637b36 --- /dev/null +++ b/test/unit/math/prim/fun/cosh_test.cpp @@ -0,0 +1,10 @@ +#include +#include + +TEST(MathFunctions, cosh_works_with_other_functions) { + Eigen::VectorXd a(5); + a << 1.1, 1.2, 1.3, 1.4, 1.5; + Eigen::RowVectorXd b(5); + b << 1.1, 1.2, 1.3, 1.4, 1.5; + stan::math::multiply(a, stan::math::cosh(b)); +} diff --git a/test/unit/math/prim/fun/digamma_test.cpp b/test/unit/math/prim/fun/digamma_test.cpp index 2a3a7ea150b..b0d37f98b7e 100644 --- a/test/unit/math/prim/fun/digamma_test.cpp +++ b/test/unit/math/prim/fun/digamma_test.cpp @@ -18,3 +18,11 @@ TEST(MathFunctions, digamma_nan) { EXPECT_TRUE(std::isnormal(stan::math::digamma(1.0E50))); } + +TEST(MathFunctions, digamma_works_with_other_functions) { + Eigen::VectorXd a(5); + a << 1.1, 1.2, 1.3, 1.4, 1.5; + Eigen::RowVectorXd b(5); + b << 1.1, 1.2, 1.3, 1.4, 1.5; + stan::math::multiply(a, stan::math::digamma(b)); +} diff --git a/test/unit/math/prim/fun/erf_test.cpp b/test/unit/math/prim/fun/erf_test.cpp index f01b192b8be..0c06057587c 100644 --- a/test/unit/math/prim/fun/erf_test.cpp +++ b/test/unit/math/prim/fun/erf_test.cpp @@ -20,3 +20,11 @@ TEST(MathFunctions, erfNan) { double nan = std::numeric_limits::quiet_NaN(); EXPECT_TRUE(std::isnan(stan::math::erf(nan))); } + +TEST(MathFunctions, erf_works_with_other_functions) { + Eigen::VectorXd a(5); + a << 1.1, 1.2, 1.3, 1.4, 1.5; + Eigen::RowVectorXd b(5); + b << 1.1, 1.2, 1.3, 1.4, 1.5; + stan::math::multiply(a, stan::math::erf(b)); +} diff --git a/test/unit/math/prim/fun/erfc_test.cpp b/test/unit/math/prim/fun/erfc_test.cpp index aad40784135..2e19d0fe333 100644 --- a/test/unit/math/prim/fun/erfc_test.cpp +++ b/test/unit/math/prim/fun/erfc_test.cpp @@ -21,3 +21,11 @@ TEST(MathFunctions, erfcNan) { double nan = std::numeric_limits::quiet_NaN(); EXPECT_TRUE(std::isnan(stan::math::erfc(nan))); } + +TEST(MathFunctions, erfc_works_with_other_functions) { + Eigen::VectorXd a(5); + a << 1.1, 1.2, 1.3, 1.4, 1.5; + Eigen::RowVectorXd b(5); + b << 1.1, 1.2, 1.3, 1.4, 1.5; + stan::math::multiply(a, stan::math::erfc(b)); +} diff --git a/test/unit/math/prim/fun/exp2_test.cpp b/test/unit/math/prim/fun/exp2_test.cpp index ae1c93c1e22..b5c8f356425 100644 --- a/test/unit/math/prim/fun/exp2_test.cpp +++ b/test/unit/math/prim/fun/exp2_test.cpp @@ -35,3 +35,11 @@ TEST(MathFunctions, exp2_nan) { EXPECT_TRUE(std::isnan(stan::math::exp2(nan))); } + +TEST(MathFunctions, exp2_works_with_other_functions) { + Eigen::VectorXd a(5); + a << 1.1, 1.2, 1.3, 1.4, 1.5; + Eigen::RowVectorXd b(5); + b << 1.1, 1.2, 1.3, 1.4, 1.5; + stan::math::multiply(a, stan::math::exp2(b)); +} diff --git a/test/unit/math/prim/fun/exp_test.cpp b/test/unit/math/prim/fun/exp_test.cpp index a19d8643a9f..292f72baf10 100644 --- a/test/unit/math/prim/fun/exp_test.cpp +++ b/test/unit/math/prim/fun/exp_test.cpp @@ -7,3 +7,11 @@ TEST(MathFunctions, expInt) { EXPECT_FLOAT_EQ(std::exp(3), exp(3)); EXPECT_FLOAT_EQ(std::exp(3.0), exp(3.0)); } + +TEST(MathFunctions, exp_works_with_other_functions) { + Eigen::VectorXd a(5); + a << 1.1, 1.2, 1.3, 1.4, 1.5; + Eigen::RowVectorXd b(5); + b << 1.1, 1.2, 1.3, 1.4, 1.5; + stan::math::multiply(a, stan::math::exp(b)); +} diff --git a/test/unit/math/prim/fun/expm1_test.cpp b/test/unit/math/prim/fun/expm1_test.cpp index 3e35d9873c1..a92bbc91f45 100644 --- a/test/unit/math/prim/fun/expm1_test.cpp +++ b/test/unit/math/prim/fun/expm1_test.cpp @@ -23,3 +23,11 @@ TEST(MathFunctions, expm1_nan) { double nan = std::numeric_limits::quiet_NaN(); EXPECT_TRUE(std::isnan(stan::math::expm1(nan))); } + +TEST(MathFunctions, expm1_works_with_other_functions) { + Eigen::VectorXd a(5); + a << 1.1, 1.2, 1.3, 1.4, 1.5; + Eigen::RowVectorXd b(5); + b << 1.1, 1.2, 1.3, 1.4, 1.5; + stan::math::multiply(a, stan::math::expm1(b)); +} diff --git a/test/unit/math/prim/fun/fabs_test.cpp b/test/unit/math/prim/fun/fabs_test.cpp index 985f1426eda..e4450169d0a 100644 --- a/test/unit/math/prim/fun/fabs_test.cpp +++ b/test/unit/math/prim/fun/fabs_test.cpp @@ -5,3 +5,11 @@ TEST(primScalFun, fabs) { stan::test::expect_common_prim([](auto x) { return std::fabs(x); }, [](auto x) { return stan::math::fabs(x); }); } + +TEST(MathFunctions, fabs_works_with_other_functions) { + Eigen::VectorXd a(5); + a << 1.1, 1.2, 1.3, 1.4, 1.5; + Eigen::RowVectorXd b(5); + b << 1.1, 1.2, 1.3, 1.4, 1.5; + stan::math::multiply(a, stan::math::fabs(b)); +} diff --git a/test/unit/math/prim/fun/floor_test.cpp b/test/unit/math/prim/fun/floor_test.cpp index 6c283c47dbc..90c6dca6090 100644 --- a/test/unit/math/prim/fun/floor_test.cpp +++ b/test/unit/math/prim/fun/floor_test.cpp @@ -4,3 +4,11 @@ TEST(primScalFun, floor) { stan::test::expect_common_prim([](auto x) { return std::floor(x); }, [](auto x) { return stan::math::floor(x); }); } + +TEST(MathFunctions, floor_works_with_other_functions) { + Eigen::VectorXd a(5); + a << 1.1, 1.2, 1.3, 1.4, 1.5; + Eigen::RowVectorXd b(5); + b << 1.1, 1.2, 1.3, 1.4, 1.5; + stan::math::multiply(a, stan::math::floor(b)); +} diff --git a/test/unit/math/prim/fun/inv_Phi_test.cpp b/test/unit/math/prim/fun/inv_Phi_test.cpp index 13d81adbb7f..9538f7151d6 100644 --- a/test/unit/math/prim/fun/inv_Phi_test.cpp +++ b/test/unit/math/prim/fun/inv_Phi_test.cpp @@ -34,3 +34,11 @@ TEST(MathFunctions, inv_Phi_nan) { EXPECT_THROW(inv_Phi(-2.0), std::domain_error); EXPECT_THROW(inv_Phi(2.0), std::domain_error); } + +TEST(MathFunctions, inv_Phi_works_with_other_functions) { + Eigen::VectorXd a(5); + a << 0.1, 0.2, 0.3, 0.4, 0.5; + Eigen::RowVectorXd b(5); + b << 0.1, 0.2, 0.3, 0.4, 0.5; + stan::math::multiply(a, stan::math::inv_Phi(b)); +} diff --git a/test/unit/math/prim/fun/inv_cloglog_test.cpp b/test/unit/math/prim/fun/inv_cloglog_test.cpp index 67118b3b9e6..3f8c3fa6c7b 100644 --- a/test/unit/math/prim/fun/inv_cloglog_test.cpp +++ b/test/unit/math/prim/fun/inv_cloglog_test.cpp @@ -14,3 +14,11 @@ TEST(MathFunctions, inv_cloglog_nan) { EXPECT_TRUE(std::isnan(stan::math::inv_cloglog(nan))); } + +TEST(MathFunctions, inv_cloglog_works_with_other_functions) { + Eigen::VectorXd a(5); + a << 1.1, 1.2, 1.3, 1.4, 1.5; + Eigen::RowVectorXd b(5); + b << 1.1, 1.2, 1.3, 1.4, 1.5; + stan::math::multiply(a, stan::math::inv_cloglog(b)); +} diff --git a/test/unit/math/prim/fun/inv_logit_test.cpp b/test/unit/math/prim/fun/inv_logit_test.cpp index b1e0de78766..a7e272f19b5 100644 --- a/test/unit/math/prim/fun/inv_logit_test.cpp +++ b/test/unit/math/prim/fun/inv_logit_test.cpp @@ -14,3 +14,11 @@ TEST(MathFunctions, inv_logit_nan) { EXPECT_TRUE(std::isnan(stan::math::inv_logit(nan))); } + +TEST(MathFunctions, inv_logit_works_with_other_functions) { + Eigen::VectorXd a(5); + a << 1.1, 1.2, 1.3, 1.4, 1.5; + Eigen::RowVectorXd b(5); + b << 1.1, 1.2, 1.3, 1.4, 1.5; + stan::math::multiply(a, stan::math::inv_logit(b)); +} diff --git a/test/unit/math/prim/fun/inv_sqrt_test.cpp b/test/unit/math/prim/fun/inv_sqrt_test.cpp index 645957931a2..1a7deb94def 100644 --- a/test/unit/math/prim/fun/inv_sqrt_test.cpp +++ b/test/unit/math/prim/fun/inv_sqrt_test.cpp @@ -22,3 +22,11 @@ TEST(MathFunctions, inv_sqrt_nan) { EXPECT_TRUE(std::isnan(stan::math::inv_sqrt(nan))); } + +TEST(MathFunctions, inv_sqrt_works_with_other_functions) { + Eigen::VectorXd a(5); + a << 1.1, 1.2, 1.3, 1.4, 1.5; + Eigen::RowVectorXd b(5); + b << 1.1, 1.2, 1.3, 1.4, 1.5; + stan::math::multiply(a, stan::math::inv_sqrt(b)); +} diff --git a/test/unit/math/prim/fun/inv_square_test.cpp b/test/unit/math/prim/fun/inv_square_test.cpp index 32c17c48cf2..a3cb3588a07 100644 --- a/test/unit/math/prim/fun/inv_square_test.cpp +++ b/test/unit/math/prim/fun/inv_square_test.cpp @@ -19,3 +19,11 @@ TEST(MathFunctions, inv_square_nan) { EXPECT_TRUE(std::isnan(stan::math::inv_square(nan))); } + +TEST(MathFunctions, inv_square_works_with_other_functions) { + Eigen::VectorXd a(5); + a << 1.1, 1.2, 1.3, 1.4, 1.5; + Eigen::RowVectorXd b(5); + b << 1.1, 1.2, 1.3, 1.4, 1.5; + stan::math::multiply(a, stan::math::inv_square(b)); +} diff --git a/test/unit/math/prim/fun/inv_test.cpp b/test/unit/math/prim/fun/inv_test.cpp index f418be35db1..99f9d21a969 100644 --- a/test/unit/math/prim/fun/inv_test.cpp +++ b/test/unit/math/prim/fun/inv_test.cpp @@ -19,3 +19,11 @@ TEST(MathFunctions, inv_nan) { EXPECT_TRUE(std::isnan(stan::math::inv(nan))); } + +TEST(MathFunctions, inv_works_with_other_functions) { + Eigen::VectorXd a(5); + a << 1.1, 1.2, 1.3, 1.4, 1.5; + Eigen::RowVectorXd b(5); + b << 1.1, 1.2, 1.3, 1.4, 1.5; + stan::math::multiply(a, stan::math::inv(b)); +} diff --git a/test/unit/math/prim/fun/lgamma_test.cpp b/test/unit/math/prim/fun/lgamma_test.cpp index d252006d5d5..77e52134c33 100644 --- a/test/unit/math/prim/fun/lgamma_test.cpp +++ b/test/unit/math/prim/fun/lgamma_test.cpp @@ -26,3 +26,11 @@ TEST(MathFunctions, lgamma_nan) { EXPECT_TRUE( std::isnormal(boost::math::lgamma(1.0E50, stan::math::boost_policy_t()))); } + +TEST(MathFunctions, lgamma_works_with_other_functions) { + Eigen::VectorXd a(5); + a << 1.1, 1.2, 1.3, 1.4, 1.5; + Eigen::RowVectorXd b(5); + b << 1.1, 1.2, 1.3, 1.4, 1.5; + stan::math::multiply(a, stan::math::lgamma(b)); +} diff --git a/test/unit/math/prim/fun/log10_test.cpp b/test/unit/math/prim/fun/log10_test.cpp index 1a67f75a75c..4e3e79e94fc 100644 --- a/test/unit/math/prim/fun/log10_test.cpp +++ b/test/unit/math/prim/fun/log10_test.cpp @@ -5,3 +5,11 @@ TEST(primScalFun, log10) { stan::test::expect_common_prim([](auto x) { return std::log10(x); }, [](auto x) { return stan::math::log10(x); }); } + +TEST(MathFunctions, log10_works_with_other_functions) { + Eigen::VectorXd a(5); + a << 1.1, 1.2, 1.3, 1.4, 1.5; + Eigen::RowVectorXd b(5); + b << 1.1, 1.2, 1.3, 1.4, 1.5; + stan::math::multiply(a, stan::math::log10(b)); +} diff --git a/test/unit/math/prim/fun/log1m_test.cpp b/test/unit/math/prim/fun/log1m_test.cpp index a0cf248f987..2c68c5a825e 100644 --- a/test/unit/math/prim/fun/log1m_test.cpp +++ b/test/unit/math/prim/fun/log1m_test.cpp @@ -22,3 +22,11 @@ TEST(MathFunctions, log1m_nan) { double nan = std::numeric_limits::quiet_NaN(); EXPECT_TRUE(std::isnan(stan::math::log1m(nan))); } + +TEST(MathFunctions, log1m_works_with_other_functions) { + Eigen::VectorXd a(5); + a << 0.1, 0.2, 0.3, 0.4, 0.5; + Eigen::RowVectorXd b(5); + b << 0.1, 0.2, 0.3, 0.4, 0.5; + stan::math::multiply(a, stan::math::log1m(b)); +} diff --git a/test/unit/math/prim/fun/log1p_exp_test.cpp b/test/unit/math/prim/fun/log1p_exp_test.cpp index 6930db3a1eb..aa4b3fd0303 100644 --- a/test/unit/math/prim/fun/log1p_exp_test.cpp +++ b/test/unit/math/prim/fun/log1p_exp_test.cpp @@ -16,3 +16,11 @@ TEST(MathFunctions, log1p_exp_nan) { EXPECT_TRUE(std::isnan(stan::math::log1p_exp(nan))); } + +TEST(MathFunctions, log1p_exp_works_with_other_functions) { + Eigen::VectorXd a(5); + a << 1.1, 1.2, 1.3, 1.4, 1.5; + Eigen::RowVectorXd b(5); + b << 1.1, 1.2, 1.3, 1.4, 1.5; + stan::math::multiply(a, stan::math::log1p_exp(b)); +} diff --git a/test/unit/math/prim/fun/log1p_test.cpp b/test/unit/math/prim/fun/log1p_test.cpp index 35f90f46452..714958a1745 100644 --- a/test/unit/math/prim/fun/log1p_test.cpp +++ b/test/unit/math/prim/fun/log1p_test.cpp @@ -40,3 +40,11 @@ TEST(MathFunctions, log1p_nan) { double nan = std::numeric_limits::quiet_NaN(); EXPECT_TRUE(std::isnan(stan::math::log1p(nan))); } + +TEST(MathFunctions, log1p_works_with_other_functions) { + Eigen::VectorXd a(5); + a << 1.1, 1.2, 1.3, 1.4, 1.5; + Eigen::RowVectorXd b(5); + b << 1.1, 1.2, 1.3, 1.4, 1.5; + stan::math::multiply(a, stan::math::log1p(b)); +} diff --git a/test/unit/math/prim/fun/log2_test.cpp b/test/unit/math/prim/fun/log2_test.cpp index 031a50afa97..cf726f78ceb 100644 --- a/test/unit/math/prim/fun/log2_test.cpp +++ b/test/unit/math/prim/fun/log2_test.cpp @@ -22,3 +22,11 @@ TEST(MathFunctions, log2_nan) { EXPECT_TRUE(std::isnan(stan::math::log2(nan))); } + +TEST(MathFunctions, log2_works_with_other_functions) { + Eigen::VectorXd a(5); + a << 1.1, 1.2, 1.3, 1.4, 1.5; + Eigen::RowVectorXd b(5); + b << 1.1, 1.2, 1.3, 1.4, 1.5; + stan::math::multiply(a, stan::math::log2(b)); +} diff --git a/test/unit/math/prim/fun/log_inv_logit_test.cpp b/test/unit/math/prim/fun/log_inv_logit_test.cpp index 774d044a4dd..bb13d370b2a 100644 --- a/test/unit/math/prim/fun/log_inv_logit_test.cpp +++ b/test/unit/math/prim/fun/log_inv_logit_test.cpp @@ -18,3 +18,11 @@ TEST(MathFunctions, log_inv_logit_nan) { EXPECT_TRUE(std::isnan(stan::math::log_inv_logit(nan))); } + +TEST(MathFunctions, log_inv_logit_works_with_other_functions) { + Eigen::VectorXd a(5); + a << 1.1, 1.2, 1.3, 1.4, 1.5; + Eigen::RowVectorXd b(5); + b << 1.1, 1.2, 1.3, 1.4, 1.5; + stan::math::multiply(a, stan::math::log_inv_logit(b)); +} diff --git a/test/unit/math/prim/fun/log_softmax_test.cpp b/test/unit/math/prim/fun/log_softmax_test.cpp index ba26ba1ce20..eff97db3cd9 100644 --- a/test/unit/math/prim/fun/log_softmax_test.cpp +++ b/test/unit/math/prim/fun/log_softmax_test.cpp @@ -47,3 +47,11 @@ TEST(MathMatrixPrimMat, log_softmax_exception) { EXPECT_THROW(log_softmax(v0), std::invalid_argument); } + +TEST(MathFunctions, log_softmax_works_with_other_functions) { + Eigen::VectorXd a(5); + a << 1.1, 1.2, 1.3, 1.4, 1.5; + Eigen::RowVectorXd b(5); + b << 1.1, 1.2, 1.3, 1.4, 1.5; + stan::math::multiply(a, stan::math::log_softmax(b)); +} diff --git a/test/unit/math/prim/fun/log_test.cpp b/test/unit/math/prim/fun/log_test.cpp index 77563092631..f7163dbcf1a 100644 --- a/test/unit/math/prim/fun/log_test.cpp +++ b/test/unit/math/prim/fun/log_test.cpp @@ -7,3 +7,11 @@ TEST(MathFunctions, logInt) { EXPECT_FLOAT_EQ(std::log(3), log(3)); EXPECT_FLOAT_EQ(std::log(3.0), log(3.0)); } + +TEST(MathFunctions, log_works_with_other_functions) { + Eigen::VectorXd a(5); + a << 1.1, 1.2, 1.3, 1.4, 1.5; + Eigen::RowVectorXd b(5); + b << 1.1, 1.2, 1.3, 1.4, 1.5; + stan::math::multiply(a, stan::math::log(b)); +} diff --git a/test/unit/math/prim/fun/logit_test.cpp b/test/unit/math/prim/fun/logit_test.cpp index b6820aa4b7f..566cbcd88ad 100644 --- a/test/unit/math/prim/fun/logit_test.cpp +++ b/test/unit/math/prim/fun/logit_test.cpp @@ -14,3 +14,11 @@ TEST(MathFunctions, logit_nan) { EXPECT_TRUE(std::isnan(stan::math::logit(nan))); } + +TEST(MathFunctions, logit_works_with_other_functions) { + Eigen::VectorXd a(5); + a << 1.1, 1.2, 1.3, 1.4, 1.5; + Eigen::RowVectorXd b(5); + b << 1.1, 1.2, 1.3, 1.4, 1.5; + stan::math::multiply(a, stan::math::logit(b)); +} diff --git a/test/unit/math/prim/fun/minus_test.cpp b/test/unit/math/prim/fun/minus_test.cpp index e9535ca4781..d3dd9bdad85 100644 --- a/test/unit/math/prim/fun/minus_test.cpp +++ b/test/unit/math/prim/fun/minus_test.cpp @@ -10,3 +10,11 @@ TEST(MathMatrixPrimMat, minus) { EXPECT_EQ(0, stan::math::minus(rv0).size()); EXPECT_EQ(0, stan::math::minus(m0).size()); } + +TEST(MathFunctions, minus_works_with_other_functions) { + Eigen::VectorXd a(5); + a << 1.1, 1.2, 1.3, 1.4, 1.5; + Eigen::RowVectorXd b(5); + b << 1.1, 1.2, 1.3, 1.4, 1.5; + stan::math::multiply(a, stan::math::minus(b)); +} diff --git a/test/unit/math/prim/fun/round_test.cpp b/test/unit/math/prim/fun/round_test.cpp index 40cc1a8334f..3cabf152e67 100644 --- a/test/unit/math/prim/fun/round_test.cpp +++ b/test/unit/math/prim/fun/round_test.cpp @@ -17,3 +17,11 @@ TEST(MathFunctions, roundNaN) { double nan = std::numeric_limits::quiet_NaN(); EXPECT_TRUE(std::isnan(stan::math::round(nan))); } + +TEST(MathFunctions, round_works_with_other_functions) { + Eigen::VectorXd a(5); + a << 1.1, 1.2, 1.3, 1.4, 1.5; + Eigen::RowVectorXd b(5); + b << 1.1, 1.2, 1.3, 1.4, 1.5; + stan::math::multiply(a, stan::math::round(b)); +} diff --git a/test/unit/math/prim/fun/sin_test.cpp b/test/unit/math/prim/fun/sin_test.cpp index 3a564bfea3b..4125f5e22f8 100644 --- a/test/unit/math/prim/fun/sin_test.cpp +++ b/test/unit/math/prim/fun/sin_test.cpp @@ -5,3 +5,11 @@ TEST(primScalFun, sin) { stan::test::expect_common_prim([](auto x) { return std::sin(x); }, [](auto x) { return stan::math::sin(x); }); } + +TEST(MathFunctions, sin_works_with_other_functions) { + Eigen::VectorXd a(5); + a << 1.1, 1.2, 1.3, 1.4, 1.5; + Eigen::RowVectorXd b(5); + b << 1.1, 1.2, 1.3, 1.4, 1.5; + stan::math::multiply(a, stan::math::sin(b)); +} diff --git a/test/unit/math/prim/fun/sinh_test.cpp b/test/unit/math/prim/fun/sinh_test.cpp index 72b18d36f94..72e3f143e5d 100644 --- a/test/unit/math/prim/fun/sinh_test.cpp +++ b/test/unit/math/prim/fun/sinh_test.cpp @@ -5,3 +5,11 @@ TEST(primScalFun, sinh) { stan::test::expect_common_prim([](auto x) { return std::sinh(x); }, [](auto x) { return stan::math::sinh(x); }); } + +TEST(MathFunctions, sinh_works_with_other_functions) { + Eigen::VectorXd a(5); + a << 1.1, 1.2, 1.3, 1.4, 1.5; + Eigen::RowVectorXd b(5); + b << 1.1, 1.2, 1.3, 1.4, 1.5; + stan::math::multiply(a, stan::math::sinh(b)); +} diff --git a/test/unit/math/prim/fun/sqrt_test.cpp b/test/unit/math/prim/fun/sqrt_test.cpp index 43c362d0cc9..9896911dbf5 100644 --- a/test/unit/math/prim/fun/sqrt_test.cpp +++ b/test/unit/math/prim/fun/sqrt_test.cpp @@ -7,3 +7,11 @@ TEST(MathFunctions, sqrtInt) { EXPECT_FLOAT_EQ(std::sqrt(3.0), sqrt(3)); EXPECT_TRUE(stan::math::is_nan(sqrt(-2))); } + +TEST(MathFunctions, sqrt_works_with_other_functions) { + Eigen::VectorXd a(5); + a << 1.1, 1.2, 1.3, 1.4, 1.5; + Eigen::RowVectorXd b(5); + b << 1.1, 1.2, 1.3, 1.4, 1.5; + stan::math::multiply(a, stan::math::sqrt(b)); +} diff --git a/test/unit/math/prim/fun/square_test.cpp b/test/unit/math/prim/fun/square_test.cpp index aadd3009906..13b66189bcf 100644 --- a/test/unit/math/prim/fun/square_test.cpp +++ b/test/unit/math/prim/fun/square_test.cpp @@ -3,7 +3,7 @@ #include #include -TEST(MathsFunctions, square) { +TEST(MathFunctions, square) { double y = 2.0; EXPECT_FLOAT_EQ(y * y, stan::math::square(y)); @@ -19,3 +19,11 @@ TEST(MathFunctions, square_nan) { EXPECT_TRUE(std::isnan(stan::math::square(nan))); } + +TEST(MathFunctions, square_works_with_other_functions) { + Eigen::VectorXd a(5); + a << 1.1, 1.2, 1.3, 1.4, 1.5; + Eigen::RowVectorXd b(5); + b << 1.1, 1.2, 1.3, 1.4, 1.5; + stan::math::multiply(a, stan::math::square(b)); +} diff --git a/test/unit/math/prim/fun/tan_test.cpp b/test/unit/math/prim/fun/tan_test.cpp new file mode 100644 index 00000000000..5b9e861cabc --- /dev/null +++ b/test/unit/math/prim/fun/tan_test.cpp @@ -0,0 +1,10 @@ +#include +#include + +TEST(MathFunctions, tan_works_with_other_functions) { + Eigen::VectorXd a(5); + a << 1.1, 1.2, 1.3, 1.4, 1.5; + Eigen::RowVectorXd b(5); + b << 1.1, 1.2, 1.3, 1.4, 1.5; + stan::math::multiply(a, stan::math::tan(b)); +} diff --git a/test/unit/math/prim/fun/tanh_test.cpp b/test/unit/math/prim/fun/tanh_test.cpp index bd4da5755c9..594d0e37ed5 100644 --- a/test/unit/math/prim/fun/tanh_test.cpp +++ b/test/unit/math/prim/fun/tanh_test.cpp @@ -5,3 +5,11 @@ TEST(primScalFun, tanh) { stan::test::expect_common_prim([](auto x) { return std::tanh(x); }, [](auto x) { return stan::math::tanh(x); }); } + +TEST(MathFunctions, tanh_works_with_other_functions) { + Eigen::VectorXd a(5); + a << 1.1, 1.2, 1.3, 1.4, 1.5; + Eigen::RowVectorXd b(5); + b << 1.1, 1.2, 1.3, 1.4, 1.5; + stan::math::multiply(a, stan::math::tanh(b)); +} diff --git a/test/unit/math/prim/fun/tgamma_test.cpp b/test/unit/math/prim/fun/tgamma_test.cpp index 51e5b84261c..2ecb0bd51cc 100644 --- a/test/unit/math/prim/fun/tgamma_test.cpp +++ b/test/unit/math/prim/fun/tgamma_test.cpp @@ -20,3 +20,11 @@ TEST(MathFunctions, tgamma_nan) { double nan = std::numeric_limits::quiet_NaN(); EXPECT_TRUE(std::isnan(stan::math::tgamma(nan))); } + +TEST(MathFunctions, tgamma_works_with_other_functions) { + Eigen::VectorXd a(5); + a << 1.1, 1.2, 1.3, 1.4, 1.5; + Eigen::RowVectorXd b(5); + b << 1.1, 1.2, 1.3, 1.4, 1.5; + stan::math::multiply(a, stan::math::tgamma(b)); +} diff --git a/test/unit/math/prim/fun/trigamma_test.cpp b/test/unit/math/prim/fun/trigamma_test.cpp index d2066598d32..c2d4484d1f0 100644 --- a/test/unit/math/prim/fun/trigamma_test.cpp +++ b/test/unit/math/prim/fun/trigamma_test.cpp @@ -17,3 +17,11 @@ TEST(MathFunctions, trigamma_nan) { EXPECT_TRUE(std::isnan(stan::math::trigamma(nan))); } + +TEST(MathFunctions, trigamma_works_with_other_functions) { + Eigen::VectorXd a(5); + a << 1.1, 1.2, 1.3, 1.4, 1.5; + Eigen::RowVectorXd b(5); + b << 1.1, 1.2, 1.3, 1.4, 1.5; + stan::math::multiply(a, stan::math::trigamma(b)); +} diff --git a/test/unit/math/prim/fun/trunc_test.cpp b/test/unit/math/prim/fun/trunc_test.cpp index 8aa3a7c6a00..2f64da18b03 100644 --- a/test/unit/math/prim/fun/trunc_test.cpp +++ b/test/unit/math/prim/fun/trunc_test.cpp @@ -17,3 +17,11 @@ TEST(MathFunctions, truncNaN) { double nan = std::numeric_limits::quiet_NaN(); EXPECT_TRUE(std::isnan(stan::math::trunc(nan))); } + +TEST(MathFunctions, trunc_works_with_other_functions) { + Eigen::VectorXd a(5); + a << 1.1, 1.2, 1.3, 1.4, 1.5; + Eigen::RowVectorXd b(5); + b << 1.1, 1.2, 1.3, 1.4, 1.5; + stan::math::multiply(a, stan::math::trunc(b)); +} From ab50cb5e0bf6cccf19511a8341ead4763683c0f2 Mon Sep 17 00:00:00 2001 From: rok-cesnovar Date: Wed, 29 Jan 2020 21:50:31 +0100 Subject: [PATCH 007/355] Fixed conflict in stan/math/prim/fun/log_softmax.hpp --- stan/math/prim/fun/log_softmax.hpp | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/stan/math/prim/fun/log_softmax.hpp b/stan/math/prim/fun/log_softmax.hpp index 8c4951df779..a51370d0b1a 100644 --- a/stan/math/prim/fun/log_softmax.hpp +++ b/stan/math/prim/fun/log_softmax.hpp @@ -36,12 +36,11 @@ namespace math { * @param[in] v Vector to transform. * @return Unit simplex result of the softmax transform of the vector. */ -template >>...> -inline auto log_softmax(const T& x) { - return apply_vector_unary::apply(x, [&](const auto& v) { - check_nonzero_size("log_softmax", "v", v); - return (v.array() - log_sum_exp(v)).matrix().eval(); - }); +template +inline Eigen::Matrix log_softmax( + const Eigen::Matrix& v) { + check_nonzero_size("log_softmax", "v", v); + return v.array() - log_sum_exp(v); } } // namespace math From ba8e315d1b0317ef4e9c3cba31c69a8d38891ec8 Mon Sep 17 00:00:00 2001 From: Nicusor Serban Date: Wed, 29 Jan 2020 22:58:08 +0200 Subject: [PATCH 008/355] Updated math to v3.1.1 --- .github/ISSUE_TEMPLATE.md | 2 +- doxygen/doxygen.cfg | 2 +- stan/math/version.hpp | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/ISSUE_TEMPLATE.md b/.github/ISSUE_TEMPLATE.md index 0e35de62263..8f112ab89d3 100644 --- a/.github/ISSUE_TEMPLATE.md +++ b/.github/ISSUE_TEMPLATE.md @@ -25,4 +25,4 @@ If this is a **feature request**, show what you expect to happen if the feature #### Current Version: -v3.1.0 +v3.1.1 diff --git a/doxygen/doxygen.cfg b/doxygen/doxygen.cfg index 8fee6f17d59..e4b5060f7d0 100644 --- a/doxygen/doxygen.cfg +++ b/doxygen/doxygen.cfg @@ -38,7 +38,7 @@ PROJECT_NAME = "Stan Math Library" # could be handy for archiving the generated documentation or if some version # control system is used. -PROJECT_NUMBER = 3.1.0 +PROJECT_NUMBER = 3.1.1 # 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 diff --git a/stan/math/version.hpp b/stan/math/version.hpp index bf8599edc07..d5ba5648855 100644 --- a/stan/math/version.hpp +++ b/stan/math/version.hpp @@ -13,7 +13,7 @@ #define STAN_MATH_MAJOR 3 #define STAN_MATH_MINOR 1 -#define STAN_MATH_PATCH 0 +#define STAN_MATH_PATCH 1 namespace stan { namespace math { From ea955b842553cc9b19b10b2f5ead3276530ed54d Mon Sep 17 00:00:00 2001 From: Nicusor Serban Date: Thu, 30 Jan 2020 01:54:02 +0200 Subject: [PATCH 009/355] Reverted release 3.1.1 --- .github/ISSUE_TEMPLATE.md | 2 +- doxygen/doxygen.cfg | 2 +- stan/math/prim/fun/acos.hpp | 2 +- stan/math/prim/fun/asin.hpp | 2 +- stan/math/prim/fun/atan.hpp | 2 +- stan/math/prim/fun/ceil.hpp | 2 +- stan/math/prim/fun/cos.hpp | 2 +- stan/math/prim/fun/cosh.hpp | 2 +- stan/math/prim/fun/exp.hpp | 2 +- stan/math/prim/fun/fabs.hpp | 4 ++-- stan/math/prim/fun/floor.hpp | 2 +- stan/math/prim/fun/inv.hpp | 4 ++-- stan/math/prim/fun/inv_cloglog.hpp | 4 ++-- stan/math/prim/fun/inv_sqrt.hpp | 4 ++-- stan/math/prim/fun/log.hpp | 2 +- stan/math/prim/fun/log10.hpp | 2 +- stan/math/prim/fun/minus.hpp | 4 +--- stan/math/prim/fun/round.hpp | 2 +- stan/math/prim/fun/sin.hpp | 2 +- stan/math/prim/fun/sinh.hpp | 4 ++-- stan/math/prim/fun/sqrt.hpp | 2 +- stan/math/prim/fun/tan.hpp | 2 +- stan/math/prim/fun/tanh.hpp | 2 +- stan/math/prim/vectorize/apply_scalar_unary.hpp | 7 ++----- stan/math/version.hpp | 2 +- test/unit/math/prim/fun/Phi_approx_test.cpp | 8 -------- test/unit/math/prim/fun/Phi_test.cpp | 8 -------- test/unit/math/prim/fun/acos_test.cpp | 8 -------- test/unit/math/prim/fun/acosh_test.cpp | 8 -------- test/unit/math/prim/fun/asin_test.cpp | 8 -------- test/unit/math/prim/fun/asinh_test.cpp | 8 -------- test/unit/math/prim/fun/atan_test.cpp | 8 -------- test/unit/math/prim/fun/atanh_test.cpp | 8 -------- test/unit/math/prim/fun/cbrt_test.cpp | 8 -------- test/unit/math/prim/fun/ceil_test.cpp | 8 -------- test/unit/math/prim/fun/cos_test.cpp | 8 -------- test/unit/math/prim/fun/cosh_test.cpp | 10 ---------- test/unit/math/prim/fun/digamma_test.cpp | 8 -------- test/unit/math/prim/fun/erf_test.cpp | 8 -------- test/unit/math/prim/fun/erfc_test.cpp | 8 -------- test/unit/math/prim/fun/exp2_test.cpp | 8 -------- test/unit/math/prim/fun/exp_test.cpp | 8 -------- test/unit/math/prim/fun/expm1_test.cpp | 8 -------- test/unit/math/prim/fun/fabs_test.cpp | 8 -------- test/unit/math/prim/fun/floor_test.cpp | 8 -------- test/unit/math/prim/fun/inv_Phi_test.cpp | 8 -------- test/unit/math/prim/fun/inv_cloglog_test.cpp | 8 -------- test/unit/math/prim/fun/inv_logit_test.cpp | 8 -------- test/unit/math/prim/fun/inv_sqrt_test.cpp | 8 -------- test/unit/math/prim/fun/inv_square_test.cpp | 8 -------- test/unit/math/prim/fun/inv_test.cpp | 8 -------- test/unit/math/prim/fun/lgamma_test.cpp | 8 -------- test/unit/math/prim/fun/log10_test.cpp | 8 -------- test/unit/math/prim/fun/log1m_test.cpp | 8 -------- test/unit/math/prim/fun/log1p_exp_test.cpp | 8 -------- test/unit/math/prim/fun/log1p_test.cpp | 8 -------- test/unit/math/prim/fun/log2_test.cpp | 8 -------- test/unit/math/prim/fun/log_inv_logit_test.cpp | 8 -------- test/unit/math/prim/fun/log_softmax_test.cpp | 8 -------- test/unit/math/prim/fun/log_test.cpp | 8 -------- test/unit/math/prim/fun/logit_test.cpp | 8 -------- test/unit/math/prim/fun/minus_test.cpp | 8 -------- test/unit/math/prim/fun/round_test.cpp | 8 -------- test/unit/math/prim/fun/sin_test.cpp | 8 -------- test/unit/math/prim/fun/sinh_test.cpp | 8 -------- test/unit/math/prim/fun/sqrt_test.cpp | 8 -------- test/unit/math/prim/fun/square_test.cpp | 10 +--------- test/unit/math/prim/fun/tan_test.cpp | 10 ---------- test/unit/math/prim/fun/tanh_test.cpp | 8 -------- test/unit/math/prim/fun/tgamma_test.cpp | 8 -------- test/unit/math/prim/fun/trigamma_test.cpp | 8 -------- test/unit/math/prim/fun/trunc_test.cpp | 8 -------- 72 files changed, 32 insertions(+), 417 deletions(-) delete mode 100644 test/unit/math/prim/fun/cosh_test.cpp delete mode 100644 test/unit/math/prim/fun/tan_test.cpp diff --git a/.github/ISSUE_TEMPLATE.md b/.github/ISSUE_TEMPLATE.md index 8f112ab89d3..0e35de62263 100644 --- a/.github/ISSUE_TEMPLATE.md +++ b/.github/ISSUE_TEMPLATE.md @@ -25,4 +25,4 @@ If this is a **feature request**, show what you expect to happen if the feature #### Current Version: -v3.1.1 +v3.1.0 diff --git a/doxygen/doxygen.cfg b/doxygen/doxygen.cfg index e4b5060f7d0..8fee6f17d59 100644 --- a/doxygen/doxygen.cfg +++ b/doxygen/doxygen.cfg @@ -38,7 +38,7 @@ PROJECT_NAME = "Stan Math Library" # could be handy for archiving the generated documentation or if some version # control system is used. -PROJECT_NUMBER = 3.1.1 +PROJECT_NUMBER = 3.1.0 # 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 diff --git a/stan/math/prim/fun/acos.hpp b/stan/math/prim/fun/acos.hpp index e5960f1b758..709864e1db6 100644 --- a/stan/math/prim/fun/acos.hpp +++ b/stan/math/prim/fun/acos.hpp @@ -45,7 +45,7 @@ inline auto acos(const T& x) { template > inline auto acos(const Eigen::MatrixBase& x) { - return x.derived().array().acos().matrix().eval(); + return x.derived().array().acos().matrix(); } } // namespace math diff --git a/stan/math/prim/fun/asin.hpp b/stan/math/prim/fun/asin.hpp index 0f5d172a29b..81a22dcf60b 100644 --- a/stan/math/prim/fun/asin.hpp +++ b/stan/math/prim/fun/asin.hpp @@ -45,7 +45,7 @@ inline auto asin(const T& x) { template > inline auto asin(const Eigen::MatrixBase& x) { - return x.derived().array().asin().matrix().eval(); + return x.derived().array().asin().matrix(); } } // namespace math diff --git a/stan/math/prim/fun/atan.hpp b/stan/math/prim/fun/atan.hpp index 9576c99240a..28a05b08d6a 100644 --- a/stan/math/prim/fun/atan.hpp +++ b/stan/math/prim/fun/atan.hpp @@ -45,7 +45,7 @@ inline typename apply_scalar_unary::return_t atan(const T& x) { template > inline auto atan(const Eigen::MatrixBase& x) { - return x.derived().array().atan().matrix().eval(); + return x.derived().array().atan().matrix(); } } // namespace math diff --git a/stan/math/prim/fun/ceil.hpp b/stan/math/prim/fun/ceil.hpp index 2de0ddb72e7..7a78566ac1d 100644 --- a/stan/math/prim/fun/ceil.hpp +++ b/stan/math/prim/fun/ceil.hpp @@ -45,7 +45,7 @@ inline auto ceil(const T& x) { template > inline auto ceil(const Eigen::MatrixBase& x) { - return x.derived().array().ceil().matrix().eval(); + return x.derived().array().ceil().matrix(); } } // namespace math diff --git a/stan/math/prim/fun/cos.hpp b/stan/math/prim/fun/cos.hpp index bf9761ace9f..0c20e53f935 100644 --- a/stan/math/prim/fun/cos.hpp +++ b/stan/math/prim/fun/cos.hpp @@ -45,7 +45,7 @@ inline auto cos(const T& x) { template > inline auto cos(const Eigen::MatrixBase& x) { - return x.derived().array().cos().matrix().eval(); + return x.derived().array().cos().matrix(); } } // namespace math diff --git a/stan/math/prim/fun/cosh.hpp b/stan/math/prim/fun/cosh.hpp index 2a0402fe9c2..3dee3eae2a3 100644 --- a/stan/math/prim/fun/cosh.hpp +++ b/stan/math/prim/fun/cosh.hpp @@ -45,7 +45,7 @@ inline typename apply_scalar_unary::return_t cosh(const T& x) { template > inline auto cosh(const Eigen::MatrixBase& x) { - return x.derived().array().cosh().matrix().eval(); + return x.derived().array().cosh().matrix(); } } // namespace math diff --git a/stan/math/prim/fun/exp.hpp b/stan/math/prim/fun/exp.hpp index 54486d9e394..4d60b4c04b5 100644 --- a/stan/math/prim/fun/exp.hpp +++ b/stan/math/prim/fun/exp.hpp @@ -60,7 +60,7 @@ inline auto exp(const T& x) { template > inline auto exp(const Eigen::MatrixBase& x) { - return x.derived().array().exp().matrix().eval(); + return x.derived().array().exp().matrix(); } } // namespace math diff --git a/stan/math/prim/fun/fabs.hpp b/stan/math/prim/fun/fabs.hpp index 2bfc97071d2..1dc51b0ee3c 100644 --- a/stan/math/prim/fun/fabs.hpp +++ b/stan/math/prim/fun/fabs.hpp @@ -45,7 +45,7 @@ inline typename apply_scalar_unary::return_t fabs(const T& x) { template > inline auto fabs(const Eigen::MatrixBase& x) { - return x.derived().array().abs().matrix().eval(); + return x.derived().array().abs().matrix(); } /** @@ -57,7 +57,7 @@ inline auto fabs(const Eigen::MatrixBase& x) { template > inline auto fabs(const Eigen::ArrayBase& x) { - return x.derived().abs().eval(); + return x.derived().abs(); } } // namespace math diff --git a/stan/math/prim/fun/floor.hpp b/stan/math/prim/fun/floor.hpp index c53433cf356..7f1f37317cd 100644 --- a/stan/math/prim/fun/floor.hpp +++ b/stan/math/prim/fun/floor.hpp @@ -45,7 +45,7 @@ inline auto floor(const T& x) { template > inline auto floor(const Eigen::MatrixBase& x) { - return x.derived().array().floor().matrix().eval(); + return x.derived().array().floor().matrix(); } } // namespace math diff --git a/stan/math/prim/fun/inv.hpp b/stan/math/prim/fun/inv.hpp index 439dc962778..f50f17f784c 100644 --- a/stan/math/prim/fun/inv.hpp +++ b/stan/math/prim/fun/inv.hpp @@ -45,7 +45,7 @@ inline auto inv(const T& x) { template > inline auto inv(const Eigen::MatrixBase& x) { - return x.derived().array().inverse().matrix().eval(); + return x.derived().array().inverse().matrix(); } /** @@ -57,7 +57,7 @@ inline auto inv(const Eigen::MatrixBase& x) { template > inline auto inv(const Eigen::ArrayBase& x) { - return x.derived().inverse().eval(); + return x.derived().inverse(); } } // namespace math diff --git a/stan/math/prim/fun/inv_cloglog.hpp b/stan/math/prim/fun/inv_cloglog.hpp index 44c6dfdc8d7..945417aa0f9 100644 --- a/stan/math/prim/fun/inv_cloglog.hpp +++ b/stan/math/prim/fun/inv_cloglog.hpp @@ -87,7 +87,7 @@ inline auto inv_cloglog(const T& x) { template > inline auto inv_cloglog(const Eigen::MatrixBase& x) { - return (1 - exp(-exp(x.derived().array()))).matrix().eval(); + return (1 - exp(-exp(x.derived().array()))).matrix(); } /** @@ -99,7 +99,7 @@ inline auto inv_cloglog(const Eigen::MatrixBase& x) { template > inline auto inv_cloglog(const Eigen::ArrayBase& x) { - return (1 - exp(-exp(x.derived()))).eval(); + return 1 - exp(-exp(x.derived())); } } // namespace math diff --git a/stan/math/prim/fun/inv_sqrt.hpp b/stan/math/prim/fun/inv_sqrt.hpp index 66b41ee7138..aa6e0d7ffdf 100644 --- a/stan/math/prim/fun/inv_sqrt.hpp +++ b/stan/math/prim/fun/inv_sqrt.hpp @@ -50,7 +50,7 @@ inline auto inv_sqrt(const T& x) { template > inline auto inv_sqrt(const Eigen::MatrixBase& x) { - return x.derived().array().rsqrt().matrix().eval(); + return x.derived().array().rsqrt().matrix(); } /** @@ -62,7 +62,7 @@ inline auto inv_sqrt(const Eigen::MatrixBase& x) { template > inline auto inv_sqrt(const Eigen::ArrayBase& x) { - return x.derived().rsqrt().eval(); + return x.derived().rsqrt(); } } // namespace math diff --git a/stan/math/prim/fun/log.hpp b/stan/math/prim/fun/log.hpp index 3814d0a5ae5..2e32bc5aa4b 100644 --- a/stan/math/prim/fun/log.hpp +++ b/stan/math/prim/fun/log.hpp @@ -60,7 +60,7 @@ inline auto log(const T& x) { template > inline auto log(const Eigen::MatrixBase& x) { - return x.derived().array().log().matrix().eval(); + return x.derived().array().log().matrix(); } } // namespace math diff --git a/stan/math/prim/fun/log10.hpp b/stan/math/prim/fun/log10.hpp index 10b7b0fa1b0..808bdb85bad 100644 --- a/stan/math/prim/fun/log10.hpp +++ b/stan/math/prim/fun/log10.hpp @@ -45,7 +45,7 @@ inline auto log10(const T& x) { template > inline auto log10(const Eigen::MatrixBase& x) { - return x.derived().array().log10().matrix().eval(); + return x.derived().array().log10().matrix(); } } // namespace math diff --git a/stan/math/prim/fun/minus.hpp b/stan/math/prim/fun/minus.hpp index 13fe7d090ed..7f374462fc0 100644 --- a/stan/math/prim/fun/minus.hpp +++ b/stan/math/prim/fun/minus.hpp @@ -1,8 +1,6 @@ #ifndef STAN_MATH_PRIM_FUN_MINUS_HPP #define STAN_MATH_PRIM_FUN_MINUS_HPP -#include - namespace stan { namespace math { @@ -14,7 +12,7 @@ namespace math { * @return Negation of subtrahend. */ template -inline plain_type_t minus(const T& x) { +inline auto minus(const T& x) { return -x; } diff --git a/stan/math/prim/fun/round.hpp b/stan/math/prim/fun/round.hpp index e5cc48efd18..66b2d6a428c 100644 --- a/stan/math/prim/fun/round.hpp +++ b/stan/math/prim/fun/round.hpp @@ -62,7 +62,7 @@ inline auto round(const T& x) { template > inline auto round(const Eigen::MatrixBase& x) { - return x.derived().array().round().matrix().eval(); + return x.derived().array().round().matrix(); } } // namespace math diff --git a/stan/math/prim/fun/sin.hpp b/stan/math/prim/fun/sin.hpp index 0b783ffeb20..f2ed9102f97 100644 --- a/stan/math/prim/fun/sin.hpp +++ b/stan/math/prim/fun/sin.hpp @@ -45,7 +45,7 @@ inline auto sin(const T& x) { template > inline auto sin(const Eigen::MatrixBase& x) { - return x.derived().array().sin().matrix().eval(); + return x.derived().array().sin().matrix(); } } // namespace math diff --git a/stan/math/prim/fun/sinh.hpp b/stan/math/prim/fun/sinh.hpp index e4d1252295d..5e13a03993e 100644 --- a/stan/math/prim/fun/sinh.hpp +++ b/stan/math/prim/fun/sinh.hpp @@ -45,7 +45,7 @@ inline auto sinh(const T& x) { template > inline auto sinh(const Eigen::MatrixBase& x) { - return x.derived().array().sinh().matrix().eval(); + return x.derived().array().sinh().matrix(); } /** @@ -57,7 +57,7 @@ inline auto sinh(const Eigen::MatrixBase& x) { template > inline auto sinh(const Eigen::ArrayBase& x) { - return x.derived().sinh().eval(); + return x.derived().sinh(); } } // namespace math diff --git a/stan/math/prim/fun/sqrt.hpp b/stan/math/prim/fun/sqrt.hpp index fe81fcf75b6..ae1b6dace93 100644 --- a/stan/math/prim/fun/sqrt.hpp +++ b/stan/math/prim/fun/sqrt.hpp @@ -54,7 +54,7 @@ inline auto sqrt(const T& x) { template > inline auto sqrt(const Eigen::MatrixBase& x) { - return x.derived().array().sqrt().matrix().eval(); + return x.derived().array().sqrt().matrix(); } } // namespace math diff --git a/stan/math/prim/fun/tan.hpp b/stan/math/prim/fun/tan.hpp index efc03beb94b..7064300e695 100644 --- a/stan/math/prim/fun/tan.hpp +++ b/stan/math/prim/fun/tan.hpp @@ -45,7 +45,7 @@ inline auto tan(const T& x) { template > inline auto tan(const Eigen::MatrixBase& x) { - return x.derived().array().tan().matrix().eval(); + return x.derived().array().tan().matrix(); } } // namespace math diff --git a/stan/math/prim/fun/tanh.hpp b/stan/math/prim/fun/tanh.hpp index 2fe9f4c5a25..60c4d405fb2 100644 --- a/stan/math/prim/fun/tanh.hpp +++ b/stan/math/prim/fun/tanh.hpp @@ -45,7 +45,7 @@ inline auto tanh(const T& x) { template > inline auto tanh(const Eigen::MatrixBase& x) { - return x.derived().array().tanh().matrix().eval(); + return x.derived().array().tanh().matrix(); } } // namespace math diff --git a/stan/math/prim/vectorize/apply_scalar_unary.hpp b/stan/math/prim/vectorize/apply_scalar_unary.hpp index 8cc283cd4ac..ed31037a207 100644 --- a/stan/math/prim/vectorize/apply_scalar_unary.hpp +++ b/stan/math/prim/vectorize/apply_scalar_unary.hpp @@ -59,11 +59,8 @@ struct apply_scalar_unary> { * by F to the specified matrix. */ static inline auto apply(const T& x) { - return x - .unaryExpr([](scalar_t x) { - return apply_scalar_unary::apply(x); - }) - .eval(); + return x.unaryExpr( + [](scalar_t x) { return apply_scalar_unary::apply(x); }); } /** diff --git a/stan/math/version.hpp b/stan/math/version.hpp index d5ba5648855..bf8599edc07 100644 --- a/stan/math/version.hpp +++ b/stan/math/version.hpp @@ -13,7 +13,7 @@ #define STAN_MATH_MAJOR 3 #define STAN_MATH_MINOR 1 -#define STAN_MATH_PATCH 1 +#define STAN_MATH_PATCH 0 namespace stan { namespace math { diff --git a/test/unit/math/prim/fun/Phi_approx_test.cpp b/test/unit/math/prim/fun/Phi_approx_test.cpp index 4a29923c572..dbc4078352d 100644 --- a/test/unit/math/prim/fun/Phi_approx_test.cpp +++ b/test/unit/math/prim/fun/Phi_approx_test.cpp @@ -14,11 +14,3 @@ TEST(MathFunctions, Phi_approx_nan) { EXPECT_TRUE(std::isnan(stan::math::Phi_approx(nan))); } - -TEST(MathFunctions, Phi_approx__works_with_other_functions) { - Eigen::VectorXd a(5); - a << 1.1, 1.2, 1.3, 1.4, 1.5; - Eigen::RowVectorXd b(5); - b << 1.1, 1.2, 1.3, 1.4, 1.5; - stan::math::multiply(a, stan::math::Phi_approx(b)); -} diff --git a/test/unit/math/prim/fun/Phi_test.cpp b/test/unit/math/prim/fun/Phi_test.cpp index 1273ad24628..c43e260bf88 100644 --- a/test/unit/math/prim/fun/Phi_test.cpp +++ b/test/unit/math/prim/fun/Phi_test.cpp @@ -118,11 +118,3 @@ TEST(MathFunctions, Phi_nan) { double nan = std::numeric_limits::quiet_NaN(); EXPECT_THROW(stan::math::Phi(nan), std::domain_error); } - -TEST(MathFunctions, Phi_works_with_other_functions) { - Eigen::VectorXd a(5); - a << 1.1, 1.2, 1.3, 1.4, 1.5; - Eigen::RowVectorXd b(5); - b << 1.1, 1.2, 1.3, 1.4, 1.5; - stan::math::multiply(a, stan::math::Phi(b)); -} diff --git a/test/unit/math/prim/fun/acos_test.cpp b/test/unit/math/prim/fun/acos_test.cpp index 7570f52cc71..c66c4c49a02 100644 --- a/test/unit/math/prim/fun/acos_test.cpp +++ b/test/unit/math/prim/fun/acos_test.cpp @@ -5,11 +5,3 @@ TEST(primScalFun, acos) { stan::test::expect_common_prim([](auto x) { return std::acos(x); }, [](auto x) { return stan::math::acos(x); }); } - -TEST(MathFunctions, acos_works_with_other_functions) { - Eigen::VectorXd a(5); - a << 0.1, 0.2, 0.3, 0.4, 0.5; - Eigen::RowVectorXd b(5); - b << 0.1, 0.2, 0.3, 0.4, 0.5; - stan::math::multiply(a, stan::math::acos(b)); -} diff --git a/test/unit/math/prim/fun/acosh_test.cpp b/test/unit/math/prim/fun/acosh_test.cpp index 1f9e8ab7bb5..2d5bc742d3c 100644 --- a/test/unit/math/prim/fun/acosh_test.cpp +++ b/test/unit/math/prim/fun/acosh_test.cpp @@ -26,11 +26,3 @@ TEST(MathFunctions, acosh_nan) { double nan = std::numeric_limits::quiet_NaN(); EXPECT_TRUE(std::isnan(stan::math::acosh(nan))); } - -TEST(MathFunctions, acosh_works_with_other_functions) { - Eigen::VectorXd a(5); - a << 1.1, 1.2, 1.3, 1.4, 1.5; - Eigen::RowVectorXd b(5); - b << 1.1, 1.2, 1.3, 1.4, 1.5; - stan::math::multiply(a, stan::math::acosh(b)); -} diff --git a/test/unit/math/prim/fun/asin_test.cpp b/test/unit/math/prim/fun/asin_test.cpp index 858be5fbbbd..a14245b58c2 100644 --- a/test/unit/math/prim/fun/asin_test.cpp +++ b/test/unit/math/prim/fun/asin_test.cpp @@ -5,11 +5,3 @@ TEST(primScalFun, asin) { stan::test::expect_common_prim([](auto x) { return std::asin(x); }, [](auto x) { return stan::math::asin(x); }); } - -TEST(MathFunctions, asin_works_with_other_functions) { - Eigen::VectorXd a(5); - a << 0.1, 0.2, 0.3, 0.4, 0.5; - Eigen::RowVectorXd b(5); - b << 0.1, 0.2, 0.3, 0.4, 0.5; - stan::math::multiply(a, stan::math::asin(b)); -} diff --git a/test/unit/math/prim/fun/asinh_test.cpp b/test/unit/math/prim/fun/asinh_test.cpp index e10228b0af0..151afc2b3ef 100644 --- a/test/unit/math/prim/fun/asinh_test.cpp +++ b/test/unit/math/prim/fun/asinh_test.cpp @@ -22,11 +22,3 @@ TEST(MathFunctions, asinh_nan) { double nan = std::numeric_limits::quiet_NaN(); EXPECT_TRUE(std::isnan(stan::math::asinh(nan))); } - -TEST(MathFunctions, asinh_works_with_other_functions) { - Eigen::VectorXd a(5); - a << 1.1, 1.2, 1.3, 1.4, 1.5; - Eigen::RowVectorXd b(5); - b << 1.1, 1.2, 1.3, 1.4, 1.5; - stan::math::multiply(a, stan::math::asinh(b)); -} diff --git a/test/unit/math/prim/fun/atan_test.cpp b/test/unit/math/prim/fun/atan_test.cpp index 54861be5151..467ceefff7d 100644 --- a/test/unit/math/prim/fun/atan_test.cpp +++ b/test/unit/math/prim/fun/atan_test.cpp @@ -5,11 +5,3 @@ TEST(primScalFun, atan) { stan::test::expect_common_prim([](auto x) { return std::atan(x); }, [](auto x) { return stan::math::atan(x); }); } - -TEST(MathFunctions, atan_works_with_other_functions) { - Eigen::VectorXd a(5); - a << 1.1, 1.2, 1.3, 1.4, 1.5; - Eigen::RowVectorXd b(5); - b << 1.1, 1.2, 1.3, 1.4, 1.5; - stan::math::multiply(a, stan::math::atan(b)); -} diff --git a/test/unit/math/prim/fun/atanh_test.cpp b/test/unit/math/prim/fun/atanh_test.cpp index 18ae151e23c..ca60e585e86 100644 --- a/test/unit/math/prim/fun/atanh_test.cpp +++ b/test/unit/math/prim/fun/atanh_test.cpp @@ -27,11 +27,3 @@ TEST(MathFunctions, atanh_nan) { double nan = std::numeric_limits::quiet_NaN(); EXPECT_TRUE(std::isnan(stan::math::atanh(nan))); } - -TEST(MathFunctions, atanh_works_with_other_functions) { - Eigen::VectorXd a(5); - a << 0.1, 0.2, 0.3, 0.4, 0.5; - Eigen::RowVectorXd b(5); - b << 0.1, 0.2, 0.3, 0.4, 0.5; - stan::math::multiply(a, stan::math::atanh(b)); -} diff --git a/test/unit/math/prim/fun/cbrt_test.cpp b/test/unit/math/prim/fun/cbrt_test.cpp index 854853943a6..2ca66bbde53 100644 --- a/test/unit/math/prim/fun/cbrt_test.cpp +++ b/test/unit/math/prim/fun/cbrt_test.cpp @@ -24,11 +24,3 @@ TEST(MathFunctions, cbrt_nan) { double nan = std::numeric_limits::quiet_NaN(); EXPECT_TRUE(std::isnan(stan::math::cbrt(nan))); } - -TEST(MathFunctions, cbrt_works_with_other_functions) { - Eigen::VectorXd a(5); - a << 1.1, 1.2, 1.3, 1.4, 1.5; - Eigen::RowVectorXd b(5); - b << 1.1, 1.2, 1.3, 1.4, 1.5; - stan::math::multiply(a, stan::math::cbrt(b)); -} diff --git a/test/unit/math/prim/fun/ceil_test.cpp b/test/unit/math/prim/fun/ceil_test.cpp index 57a7dce8c41..f26f0068eb1 100644 --- a/test/unit/math/prim/fun/ceil_test.cpp +++ b/test/unit/math/prim/fun/ceil_test.cpp @@ -4,11 +4,3 @@ TEST(primScalFun, ceil) { stan::test::expect_common_prim([](auto x) { return std::ceil(x); }, [](auto x) { return stan::math::ceil(x); }); } - -TEST(MathFunctions, ceil_works_with_other_functions) { - Eigen::VectorXd a(5); - a << 1.1, 1.2, 1.3, 1.4, 1.5; - Eigen::RowVectorXd b(5); - b << 1.1, 1.2, 1.3, 1.4, 1.5; - stan::math::multiply(a, stan::math::ceil(b)); -} diff --git a/test/unit/math/prim/fun/cos_test.cpp b/test/unit/math/prim/fun/cos_test.cpp index 94989f9703f..53daaa398de 100644 --- a/test/unit/math/prim/fun/cos_test.cpp +++ b/test/unit/math/prim/fun/cos_test.cpp @@ -5,11 +5,3 @@ TEST(primScalFun, cos) { stan::test::expect_common_prim([](auto x) { return std::cos(x); }, [](auto x) { return stan::math::cos(x); }); } - -TEST(MathFunctions, cos_works_with_other_functions) { - Eigen::VectorXd a(5); - a << 1.1, 1.2, 1.3, 1.4, 1.5; - Eigen::RowVectorXd b(5); - b << 1.1, 1.2, 1.3, 1.4, 1.5; - stan::math::multiply(a, stan::math::cos(b)); -} diff --git a/test/unit/math/prim/fun/cosh_test.cpp b/test/unit/math/prim/fun/cosh_test.cpp deleted file mode 100644 index d1433637b36..00000000000 --- a/test/unit/math/prim/fun/cosh_test.cpp +++ /dev/null @@ -1,10 +0,0 @@ -#include -#include - -TEST(MathFunctions, cosh_works_with_other_functions) { - Eigen::VectorXd a(5); - a << 1.1, 1.2, 1.3, 1.4, 1.5; - Eigen::RowVectorXd b(5); - b << 1.1, 1.2, 1.3, 1.4, 1.5; - stan::math::multiply(a, stan::math::cosh(b)); -} diff --git a/test/unit/math/prim/fun/digamma_test.cpp b/test/unit/math/prim/fun/digamma_test.cpp index b0d37f98b7e..2a3a7ea150b 100644 --- a/test/unit/math/prim/fun/digamma_test.cpp +++ b/test/unit/math/prim/fun/digamma_test.cpp @@ -18,11 +18,3 @@ TEST(MathFunctions, digamma_nan) { EXPECT_TRUE(std::isnormal(stan::math::digamma(1.0E50))); } - -TEST(MathFunctions, digamma_works_with_other_functions) { - Eigen::VectorXd a(5); - a << 1.1, 1.2, 1.3, 1.4, 1.5; - Eigen::RowVectorXd b(5); - b << 1.1, 1.2, 1.3, 1.4, 1.5; - stan::math::multiply(a, stan::math::digamma(b)); -} diff --git a/test/unit/math/prim/fun/erf_test.cpp b/test/unit/math/prim/fun/erf_test.cpp index 0c06057587c..f01b192b8be 100644 --- a/test/unit/math/prim/fun/erf_test.cpp +++ b/test/unit/math/prim/fun/erf_test.cpp @@ -20,11 +20,3 @@ TEST(MathFunctions, erfNan) { double nan = std::numeric_limits::quiet_NaN(); EXPECT_TRUE(std::isnan(stan::math::erf(nan))); } - -TEST(MathFunctions, erf_works_with_other_functions) { - Eigen::VectorXd a(5); - a << 1.1, 1.2, 1.3, 1.4, 1.5; - Eigen::RowVectorXd b(5); - b << 1.1, 1.2, 1.3, 1.4, 1.5; - stan::math::multiply(a, stan::math::erf(b)); -} diff --git a/test/unit/math/prim/fun/erfc_test.cpp b/test/unit/math/prim/fun/erfc_test.cpp index 2e19d0fe333..aad40784135 100644 --- a/test/unit/math/prim/fun/erfc_test.cpp +++ b/test/unit/math/prim/fun/erfc_test.cpp @@ -21,11 +21,3 @@ TEST(MathFunctions, erfcNan) { double nan = std::numeric_limits::quiet_NaN(); EXPECT_TRUE(std::isnan(stan::math::erfc(nan))); } - -TEST(MathFunctions, erfc_works_with_other_functions) { - Eigen::VectorXd a(5); - a << 1.1, 1.2, 1.3, 1.4, 1.5; - Eigen::RowVectorXd b(5); - b << 1.1, 1.2, 1.3, 1.4, 1.5; - stan::math::multiply(a, stan::math::erfc(b)); -} diff --git a/test/unit/math/prim/fun/exp2_test.cpp b/test/unit/math/prim/fun/exp2_test.cpp index b5c8f356425..ae1c93c1e22 100644 --- a/test/unit/math/prim/fun/exp2_test.cpp +++ b/test/unit/math/prim/fun/exp2_test.cpp @@ -35,11 +35,3 @@ TEST(MathFunctions, exp2_nan) { EXPECT_TRUE(std::isnan(stan::math::exp2(nan))); } - -TEST(MathFunctions, exp2_works_with_other_functions) { - Eigen::VectorXd a(5); - a << 1.1, 1.2, 1.3, 1.4, 1.5; - Eigen::RowVectorXd b(5); - b << 1.1, 1.2, 1.3, 1.4, 1.5; - stan::math::multiply(a, stan::math::exp2(b)); -} diff --git a/test/unit/math/prim/fun/exp_test.cpp b/test/unit/math/prim/fun/exp_test.cpp index 292f72baf10..a19d8643a9f 100644 --- a/test/unit/math/prim/fun/exp_test.cpp +++ b/test/unit/math/prim/fun/exp_test.cpp @@ -7,11 +7,3 @@ TEST(MathFunctions, expInt) { EXPECT_FLOAT_EQ(std::exp(3), exp(3)); EXPECT_FLOAT_EQ(std::exp(3.0), exp(3.0)); } - -TEST(MathFunctions, exp_works_with_other_functions) { - Eigen::VectorXd a(5); - a << 1.1, 1.2, 1.3, 1.4, 1.5; - Eigen::RowVectorXd b(5); - b << 1.1, 1.2, 1.3, 1.4, 1.5; - stan::math::multiply(a, stan::math::exp(b)); -} diff --git a/test/unit/math/prim/fun/expm1_test.cpp b/test/unit/math/prim/fun/expm1_test.cpp index a92bbc91f45..3e35d9873c1 100644 --- a/test/unit/math/prim/fun/expm1_test.cpp +++ b/test/unit/math/prim/fun/expm1_test.cpp @@ -23,11 +23,3 @@ TEST(MathFunctions, expm1_nan) { double nan = std::numeric_limits::quiet_NaN(); EXPECT_TRUE(std::isnan(stan::math::expm1(nan))); } - -TEST(MathFunctions, expm1_works_with_other_functions) { - Eigen::VectorXd a(5); - a << 1.1, 1.2, 1.3, 1.4, 1.5; - Eigen::RowVectorXd b(5); - b << 1.1, 1.2, 1.3, 1.4, 1.5; - stan::math::multiply(a, stan::math::expm1(b)); -} diff --git a/test/unit/math/prim/fun/fabs_test.cpp b/test/unit/math/prim/fun/fabs_test.cpp index e4450169d0a..985f1426eda 100644 --- a/test/unit/math/prim/fun/fabs_test.cpp +++ b/test/unit/math/prim/fun/fabs_test.cpp @@ -5,11 +5,3 @@ TEST(primScalFun, fabs) { stan::test::expect_common_prim([](auto x) { return std::fabs(x); }, [](auto x) { return stan::math::fabs(x); }); } - -TEST(MathFunctions, fabs_works_with_other_functions) { - Eigen::VectorXd a(5); - a << 1.1, 1.2, 1.3, 1.4, 1.5; - Eigen::RowVectorXd b(5); - b << 1.1, 1.2, 1.3, 1.4, 1.5; - stan::math::multiply(a, stan::math::fabs(b)); -} diff --git a/test/unit/math/prim/fun/floor_test.cpp b/test/unit/math/prim/fun/floor_test.cpp index 90c6dca6090..6c283c47dbc 100644 --- a/test/unit/math/prim/fun/floor_test.cpp +++ b/test/unit/math/prim/fun/floor_test.cpp @@ -4,11 +4,3 @@ TEST(primScalFun, floor) { stan::test::expect_common_prim([](auto x) { return std::floor(x); }, [](auto x) { return stan::math::floor(x); }); } - -TEST(MathFunctions, floor_works_with_other_functions) { - Eigen::VectorXd a(5); - a << 1.1, 1.2, 1.3, 1.4, 1.5; - Eigen::RowVectorXd b(5); - b << 1.1, 1.2, 1.3, 1.4, 1.5; - stan::math::multiply(a, stan::math::floor(b)); -} diff --git a/test/unit/math/prim/fun/inv_Phi_test.cpp b/test/unit/math/prim/fun/inv_Phi_test.cpp index 9538f7151d6..13d81adbb7f 100644 --- a/test/unit/math/prim/fun/inv_Phi_test.cpp +++ b/test/unit/math/prim/fun/inv_Phi_test.cpp @@ -34,11 +34,3 @@ TEST(MathFunctions, inv_Phi_nan) { EXPECT_THROW(inv_Phi(-2.0), std::domain_error); EXPECT_THROW(inv_Phi(2.0), std::domain_error); } - -TEST(MathFunctions, inv_Phi_works_with_other_functions) { - Eigen::VectorXd a(5); - a << 0.1, 0.2, 0.3, 0.4, 0.5; - Eigen::RowVectorXd b(5); - b << 0.1, 0.2, 0.3, 0.4, 0.5; - stan::math::multiply(a, stan::math::inv_Phi(b)); -} diff --git a/test/unit/math/prim/fun/inv_cloglog_test.cpp b/test/unit/math/prim/fun/inv_cloglog_test.cpp index 3f8c3fa6c7b..67118b3b9e6 100644 --- a/test/unit/math/prim/fun/inv_cloglog_test.cpp +++ b/test/unit/math/prim/fun/inv_cloglog_test.cpp @@ -14,11 +14,3 @@ TEST(MathFunctions, inv_cloglog_nan) { EXPECT_TRUE(std::isnan(stan::math::inv_cloglog(nan))); } - -TEST(MathFunctions, inv_cloglog_works_with_other_functions) { - Eigen::VectorXd a(5); - a << 1.1, 1.2, 1.3, 1.4, 1.5; - Eigen::RowVectorXd b(5); - b << 1.1, 1.2, 1.3, 1.4, 1.5; - stan::math::multiply(a, stan::math::inv_cloglog(b)); -} diff --git a/test/unit/math/prim/fun/inv_logit_test.cpp b/test/unit/math/prim/fun/inv_logit_test.cpp index a7e272f19b5..b1e0de78766 100644 --- a/test/unit/math/prim/fun/inv_logit_test.cpp +++ b/test/unit/math/prim/fun/inv_logit_test.cpp @@ -14,11 +14,3 @@ TEST(MathFunctions, inv_logit_nan) { EXPECT_TRUE(std::isnan(stan::math::inv_logit(nan))); } - -TEST(MathFunctions, inv_logit_works_with_other_functions) { - Eigen::VectorXd a(5); - a << 1.1, 1.2, 1.3, 1.4, 1.5; - Eigen::RowVectorXd b(5); - b << 1.1, 1.2, 1.3, 1.4, 1.5; - stan::math::multiply(a, stan::math::inv_logit(b)); -} diff --git a/test/unit/math/prim/fun/inv_sqrt_test.cpp b/test/unit/math/prim/fun/inv_sqrt_test.cpp index 1a7deb94def..645957931a2 100644 --- a/test/unit/math/prim/fun/inv_sqrt_test.cpp +++ b/test/unit/math/prim/fun/inv_sqrt_test.cpp @@ -22,11 +22,3 @@ TEST(MathFunctions, inv_sqrt_nan) { EXPECT_TRUE(std::isnan(stan::math::inv_sqrt(nan))); } - -TEST(MathFunctions, inv_sqrt_works_with_other_functions) { - Eigen::VectorXd a(5); - a << 1.1, 1.2, 1.3, 1.4, 1.5; - Eigen::RowVectorXd b(5); - b << 1.1, 1.2, 1.3, 1.4, 1.5; - stan::math::multiply(a, stan::math::inv_sqrt(b)); -} diff --git a/test/unit/math/prim/fun/inv_square_test.cpp b/test/unit/math/prim/fun/inv_square_test.cpp index a3cb3588a07..32c17c48cf2 100644 --- a/test/unit/math/prim/fun/inv_square_test.cpp +++ b/test/unit/math/prim/fun/inv_square_test.cpp @@ -19,11 +19,3 @@ TEST(MathFunctions, inv_square_nan) { EXPECT_TRUE(std::isnan(stan::math::inv_square(nan))); } - -TEST(MathFunctions, inv_square_works_with_other_functions) { - Eigen::VectorXd a(5); - a << 1.1, 1.2, 1.3, 1.4, 1.5; - Eigen::RowVectorXd b(5); - b << 1.1, 1.2, 1.3, 1.4, 1.5; - stan::math::multiply(a, stan::math::inv_square(b)); -} diff --git a/test/unit/math/prim/fun/inv_test.cpp b/test/unit/math/prim/fun/inv_test.cpp index 99f9d21a969..f418be35db1 100644 --- a/test/unit/math/prim/fun/inv_test.cpp +++ b/test/unit/math/prim/fun/inv_test.cpp @@ -19,11 +19,3 @@ TEST(MathFunctions, inv_nan) { EXPECT_TRUE(std::isnan(stan::math::inv(nan))); } - -TEST(MathFunctions, inv_works_with_other_functions) { - Eigen::VectorXd a(5); - a << 1.1, 1.2, 1.3, 1.4, 1.5; - Eigen::RowVectorXd b(5); - b << 1.1, 1.2, 1.3, 1.4, 1.5; - stan::math::multiply(a, stan::math::inv(b)); -} diff --git a/test/unit/math/prim/fun/lgamma_test.cpp b/test/unit/math/prim/fun/lgamma_test.cpp index 77e52134c33..d252006d5d5 100644 --- a/test/unit/math/prim/fun/lgamma_test.cpp +++ b/test/unit/math/prim/fun/lgamma_test.cpp @@ -26,11 +26,3 @@ TEST(MathFunctions, lgamma_nan) { EXPECT_TRUE( std::isnormal(boost::math::lgamma(1.0E50, stan::math::boost_policy_t()))); } - -TEST(MathFunctions, lgamma_works_with_other_functions) { - Eigen::VectorXd a(5); - a << 1.1, 1.2, 1.3, 1.4, 1.5; - Eigen::RowVectorXd b(5); - b << 1.1, 1.2, 1.3, 1.4, 1.5; - stan::math::multiply(a, stan::math::lgamma(b)); -} diff --git a/test/unit/math/prim/fun/log10_test.cpp b/test/unit/math/prim/fun/log10_test.cpp index 4e3e79e94fc..1a67f75a75c 100644 --- a/test/unit/math/prim/fun/log10_test.cpp +++ b/test/unit/math/prim/fun/log10_test.cpp @@ -5,11 +5,3 @@ TEST(primScalFun, log10) { stan::test::expect_common_prim([](auto x) { return std::log10(x); }, [](auto x) { return stan::math::log10(x); }); } - -TEST(MathFunctions, log10_works_with_other_functions) { - Eigen::VectorXd a(5); - a << 1.1, 1.2, 1.3, 1.4, 1.5; - Eigen::RowVectorXd b(5); - b << 1.1, 1.2, 1.3, 1.4, 1.5; - stan::math::multiply(a, stan::math::log10(b)); -} diff --git a/test/unit/math/prim/fun/log1m_test.cpp b/test/unit/math/prim/fun/log1m_test.cpp index 2c68c5a825e..a0cf248f987 100644 --- a/test/unit/math/prim/fun/log1m_test.cpp +++ b/test/unit/math/prim/fun/log1m_test.cpp @@ -22,11 +22,3 @@ TEST(MathFunctions, log1m_nan) { double nan = std::numeric_limits::quiet_NaN(); EXPECT_TRUE(std::isnan(stan::math::log1m(nan))); } - -TEST(MathFunctions, log1m_works_with_other_functions) { - Eigen::VectorXd a(5); - a << 0.1, 0.2, 0.3, 0.4, 0.5; - Eigen::RowVectorXd b(5); - b << 0.1, 0.2, 0.3, 0.4, 0.5; - stan::math::multiply(a, stan::math::log1m(b)); -} diff --git a/test/unit/math/prim/fun/log1p_exp_test.cpp b/test/unit/math/prim/fun/log1p_exp_test.cpp index aa4b3fd0303..6930db3a1eb 100644 --- a/test/unit/math/prim/fun/log1p_exp_test.cpp +++ b/test/unit/math/prim/fun/log1p_exp_test.cpp @@ -16,11 +16,3 @@ TEST(MathFunctions, log1p_exp_nan) { EXPECT_TRUE(std::isnan(stan::math::log1p_exp(nan))); } - -TEST(MathFunctions, log1p_exp_works_with_other_functions) { - Eigen::VectorXd a(5); - a << 1.1, 1.2, 1.3, 1.4, 1.5; - Eigen::RowVectorXd b(5); - b << 1.1, 1.2, 1.3, 1.4, 1.5; - stan::math::multiply(a, stan::math::log1p_exp(b)); -} diff --git a/test/unit/math/prim/fun/log1p_test.cpp b/test/unit/math/prim/fun/log1p_test.cpp index 714958a1745..35f90f46452 100644 --- a/test/unit/math/prim/fun/log1p_test.cpp +++ b/test/unit/math/prim/fun/log1p_test.cpp @@ -40,11 +40,3 @@ TEST(MathFunctions, log1p_nan) { double nan = std::numeric_limits::quiet_NaN(); EXPECT_TRUE(std::isnan(stan::math::log1p(nan))); } - -TEST(MathFunctions, log1p_works_with_other_functions) { - Eigen::VectorXd a(5); - a << 1.1, 1.2, 1.3, 1.4, 1.5; - Eigen::RowVectorXd b(5); - b << 1.1, 1.2, 1.3, 1.4, 1.5; - stan::math::multiply(a, stan::math::log1p(b)); -} diff --git a/test/unit/math/prim/fun/log2_test.cpp b/test/unit/math/prim/fun/log2_test.cpp index cf726f78ceb..031a50afa97 100644 --- a/test/unit/math/prim/fun/log2_test.cpp +++ b/test/unit/math/prim/fun/log2_test.cpp @@ -22,11 +22,3 @@ TEST(MathFunctions, log2_nan) { EXPECT_TRUE(std::isnan(stan::math::log2(nan))); } - -TEST(MathFunctions, log2_works_with_other_functions) { - Eigen::VectorXd a(5); - a << 1.1, 1.2, 1.3, 1.4, 1.5; - Eigen::RowVectorXd b(5); - b << 1.1, 1.2, 1.3, 1.4, 1.5; - stan::math::multiply(a, stan::math::log2(b)); -} diff --git a/test/unit/math/prim/fun/log_inv_logit_test.cpp b/test/unit/math/prim/fun/log_inv_logit_test.cpp index bb13d370b2a..774d044a4dd 100644 --- a/test/unit/math/prim/fun/log_inv_logit_test.cpp +++ b/test/unit/math/prim/fun/log_inv_logit_test.cpp @@ -18,11 +18,3 @@ TEST(MathFunctions, log_inv_logit_nan) { EXPECT_TRUE(std::isnan(stan::math::log_inv_logit(nan))); } - -TEST(MathFunctions, log_inv_logit_works_with_other_functions) { - Eigen::VectorXd a(5); - a << 1.1, 1.2, 1.3, 1.4, 1.5; - Eigen::RowVectorXd b(5); - b << 1.1, 1.2, 1.3, 1.4, 1.5; - stan::math::multiply(a, stan::math::log_inv_logit(b)); -} diff --git a/test/unit/math/prim/fun/log_softmax_test.cpp b/test/unit/math/prim/fun/log_softmax_test.cpp index eff97db3cd9..ba26ba1ce20 100644 --- a/test/unit/math/prim/fun/log_softmax_test.cpp +++ b/test/unit/math/prim/fun/log_softmax_test.cpp @@ -47,11 +47,3 @@ TEST(MathMatrixPrimMat, log_softmax_exception) { EXPECT_THROW(log_softmax(v0), std::invalid_argument); } - -TEST(MathFunctions, log_softmax_works_with_other_functions) { - Eigen::VectorXd a(5); - a << 1.1, 1.2, 1.3, 1.4, 1.5; - Eigen::RowVectorXd b(5); - b << 1.1, 1.2, 1.3, 1.4, 1.5; - stan::math::multiply(a, stan::math::log_softmax(b)); -} diff --git a/test/unit/math/prim/fun/log_test.cpp b/test/unit/math/prim/fun/log_test.cpp index f7163dbcf1a..77563092631 100644 --- a/test/unit/math/prim/fun/log_test.cpp +++ b/test/unit/math/prim/fun/log_test.cpp @@ -7,11 +7,3 @@ TEST(MathFunctions, logInt) { EXPECT_FLOAT_EQ(std::log(3), log(3)); EXPECT_FLOAT_EQ(std::log(3.0), log(3.0)); } - -TEST(MathFunctions, log_works_with_other_functions) { - Eigen::VectorXd a(5); - a << 1.1, 1.2, 1.3, 1.4, 1.5; - Eigen::RowVectorXd b(5); - b << 1.1, 1.2, 1.3, 1.4, 1.5; - stan::math::multiply(a, stan::math::log(b)); -} diff --git a/test/unit/math/prim/fun/logit_test.cpp b/test/unit/math/prim/fun/logit_test.cpp index 566cbcd88ad..b6820aa4b7f 100644 --- a/test/unit/math/prim/fun/logit_test.cpp +++ b/test/unit/math/prim/fun/logit_test.cpp @@ -14,11 +14,3 @@ TEST(MathFunctions, logit_nan) { EXPECT_TRUE(std::isnan(stan::math::logit(nan))); } - -TEST(MathFunctions, logit_works_with_other_functions) { - Eigen::VectorXd a(5); - a << 1.1, 1.2, 1.3, 1.4, 1.5; - Eigen::RowVectorXd b(5); - b << 1.1, 1.2, 1.3, 1.4, 1.5; - stan::math::multiply(a, stan::math::logit(b)); -} diff --git a/test/unit/math/prim/fun/minus_test.cpp b/test/unit/math/prim/fun/minus_test.cpp index d3dd9bdad85..e9535ca4781 100644 --- a/test/unit/math/prim/fun/minus_test.cpp +++ b/test/unit/math/prim/fun/minus_test.cpp @@ -10,11 +10,3 @@ TEST(MathMatrixPrimMat, minus) { EXPECT_EQ(0, stan::math::minus(rv0).size()); EXPECT_EQ(0, stan::math::minus(m0).size()); } - -TEST(MathFunctions, minus_works_with_other_functions) { - Eigen::VectorXd a(5); - a << 1.1, 1.2, 1.3, 1.4, 1.5; - Eigen::RowVectorXd b(5); - b << 1.1, 1.2, 1.3, 1.4, 1.5; - stan::math::multiply(a, stan::math::minus(b)); -} diff --git a/test/unit/math/prim/fun/round_test.cpp b/test/unit/math/prim/fun/round_test.cpp index 3cabf152e67..40cc1a8334f 100644 --- a/test/unit/math/prim/fun/round_test.cpp +++ b/test/unit/math/prim/fun/round_test.cpp @@ -17,11 +17,3 @@ TEST(MathFunctions, roundNaN) { double nan = std::numeric_limits::quiet_NaN(); EXPECT_TRUE(std::isnan(stan::math::round(nan))); } - -TEST(MathFunctions, round_works_with_other_functions) { - Eigen::VectorXd a(5); - a << 1.1, 1.2, 1.3, 1.4, 1.5; - Eigen::RowVectorXd b(5); - b << 1.1, 1.2, 1.3, 1.4, 1.5; - stan::math::multiply(a, stan::math::round(b)); -} diff --git a/test/unit/math/prim/fun/sin_test.cpp b/test/unit/math/prim/fun/sin_test.cpp index 4125f5e22f8..3a564bfea3b 100644 --- a/test/unit/math/prim/fun/sin_test.cpp +++ b/test/unit/math/prim/fun/sin_test.cpp @@ -5,11 +5,3 @@ TEST(primScalFun, sin) { stan::test::expect_common_prim([](auto x) { return std::sin(x); }, [](auto x) { return stan::math::sin(x); }); } - -TEST(MathFunctions, sin_works_with_other_functions) { - Eigen::VectorXd a(5); - a << 1.1, 1.2, 1.3, 1.4, 1.5; - Eigen::RowVectorXd b(5); - b << 1.1, 1.2, 1.3, 1.4, 1.5; - stan::math::multiply(a, stan::math::sin(b)); -} diff --git a/test/unit/math/prim/fun/sinh_test.cpp b/test/unit/math/prim/fun/sinh_test.cpp index 72e3f143e5d..72b18d36f94 100644 --- a/test/unit/math/prim/fun/sinh_test.cpp +++ b/test/unit/math/prim/fun/sinh_test.cpp @@ -5,11 +5,3 @@ TEST(primScalFun, sinh) { stan::test::expect_common_prim([](auto x) { return std::sinh(x); }, [](auto x) { return stan::math::sinh(x); }); } - -TEST(MathFunctions, sinh_works_with_other_functions) { - Eigen::VectorXd a(5); - a << 1.1, 1.2, 1.3, 1.4, 1.5; - Eigen::RowVectorXd b(5); - b << 1.1, 1.2, 1.3, 1.4, 1.5; - stan::math::multiply(a, stan::math::sinh(b)); -} diff --git a/test/unit/math/prim/fun/sqrt_test.cpp b/test/unit/math/prim/fun/sqrt_test.cpp index 9896911dbf5..43c362d0cc9 100644 --- a/test/unit/math/prim/fun/sqrt_test.cpp +++ b/test/unit/math/prim/fun/sqrt_test.cpp @@ -7,11 +7,3 @@ TEST(MathFunctions, sqrtInt) { EXPECT_FLOAT_EQ(std::sqrt(3.0), sqrt(3)); EXPECT_TRUE(stan::math::is_nan(sqrt(-2))); } - -TEST(MathFunctions, sqrt_works_with_other_functions) { - Eigen::VectorXd a(5); - a << 1.1, 1.2, 1.3, 1.4, 1.5; - Eigen::RowVectorXd b(5); - b << 1.1, 1.2, 1.3, 1.4, 1.5; - stan::math::multiply(a, stan::math::sqrt(b)); -} diff --git a/test/unit/math/prim/fun/square_test.cpp b/test/unit/math/prim/fun/square_test.cpp index 13b66189bcf..aadd3009906 100644 --- a/test/unit/math/prim/fun/square_test.cpp +++ b/test/unit/math/prim/fun/square_test.cpp @@ -3,7 +3,7 @@ #include #include -TEST(MathFunctions, square) { +TEST(MathsFunctions, square) { double y = 2.0; EXPECT_FLOAT_EQ(y * y, stan::math::square(y)); @@ -19,11 +19,3 @@ TEST(MathFunctions, square_nan) { EXPECT_TRUE(std::isnan(stan::math::square(nan))); } - -TEST(MathFunctions, square_works_with_other_functions) { - Eigen::VectorXd a(5); - a << 1.1, 1.2, 1.3, 1.4, 1.5; - Eigen::RowVectorXd b(5); - b << 1.1, 1.2, 1.3, 1.4, 1.5; - stan::math::multiply(a, stan::math::square(b)); -} diff --git a/test/unit/math/prim/fun/tan_test.cpp b/test/unit/math/prim/fun/tan_test.cpp deleted file mode 100644 index 5b9e861cabc..00000000000 --- a/test/unit/math/prim/fun/tan_test.cpp +++ /dev/null @@ -1,10 +0,0 @@ -#include -#include - -TEST(MathFunctions, tan_works_with_other_functions) { - Eigen::VectorXd a(5); - a << 1.1, 1.2, 1.3, 1.4, 1.5; - Eigen::RowVectorXd b(5); - b << 1.1, 1.2, 1.3, 1.4, 1.5; - stan::math::multiply(a, stan::math::tan(b)); -} diff --git a/test/unit/math/prim/fun/tanh_test.cpp b/test/unit/math/prim/fun/tanh_test.cpp index 594d0e37ed5..bd4da5755c9 100644 --- a/test/unit/math/prim/fun/tanh_test.cpp +++ b/test/unit/math/prim/fun/tanh_test.cpp @@ -5,11 +5,3 @@ TEST(primScalFun, tanh) { stan::test::expect_common_prim([](auto x) { return std::tanh(x); }, [](auto x) { return stan::math::tanh(x); }); } - -TEST(MathFunctions, tanh_works_with_other_functions) { - Eigen::VectorXd a(5); - a << 1.1, 1.2, 1.3, 1.4, 1.5; - Eigen::RowVectorXd b(5); - b << 1.1, 1.2, 1.3, 1.4, 1.5; - stan::math::multiply(a, stan::math::tanh(b)); -} diff --git a/test/unit/math/prim/fun/tgamma_test.cpp b/test/unit/math/prim/fun/tgamma_test.cpp index 2ecb0bd51cc..51e5b84261c 100644 --- a/test/unit/math/prim/fun/tgamma_test.cpp +++ b/test/unit/math/prim/fun/tgamma_test.cpp @@ -20,11 +20,3 @@ TEST(MathFunctions, tgamma_nan) { double nan = std::numeric_limits::quiet_NaN(); EXPECT_TRUE(std::isnan(stan::math::tgamma(nan))); } - -TEST(MathFunctions, tgamma_works_with_other_functions) { - Eigen::VectorXd a(5); - a << 1.1, 1.2, 1.3, 1.4, 1.5; - Eigen::RowVectorXd b(5); - b << 1.1, 1.2, 1.3, 1.4, 1.5; - stan::math::multiply(a, stan::math::tgamma(b)); -} diff --git a/test/unit/math/prim/fun/trigamma_test.cpp b/test/unit/math/prim/fun/trigamma_test.cpp index c2d4484d1f0..d2066598d32 100644 --- a/test/unit/math/prim/fun/trigamma_test.cpp +++ b/test/unit/math/prim/fun/trigamma_test.cpp @@ -17,11 +17,3 @@ TEST(MathFunctions, trigamma_nan) { EXPECT_TRUE(std::isnan(stan::math::trigamma(nan))); } - -TEST(MathFunctions, trigamma_works_with_other_functions) { - Eigen::VectorXd a(5); - a << 1.1, 1.2, 1.3, 1.4, 1.5; - Eigen::RowVectorXd b(5); - b << 1.1, 1.2, 1.3, 1.4, 1.5; - stan::math::multiply(a, stan::math::trigamma(b)); -} diff --git a/test/unit/math/prim/fun/trunc_test.cpp b/test/unit/math/prim/fun/trunc_test.cpp index 2f64da18b03..8aa3a7c6a00 100644 --- a/test/unit/math/prim/fun/trunc_test.cpp +++ b/test/unit/math/prim/fun/trunc_test.cpp @@ -17,11 +17,3 @@ TEST(MathFunctions, truncNaN) { double nan = std::numeric_limits::quiet_NaN(); EXPECT_TRUE(std::isnan(stan::math::trunc(nan))); } - -TEST(MathFunctions, trunc_works_with_other_functions) { - Eigen::VectorXd a(5); - a << 1.1, 1.2, 1.3, 1.4, 1.5; - Eigen::RowVectorXd b(5); - b << 1.1, 1.2, 1.3, 1.4, 1.5; - stan::math::multiply(a, stan::math::trunc(b)); -} From f899a98480800c889e0b36e81a2a928a5a77a8fa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rok=20=C4=8Ce=C5=A1novar?= Date: Wed, 29 Jan 2020 19:05:54 +0100 Subject: [PATCH 010/355] Fixed conflict in stan/math/prim/fun/log_softmax.hpp --- stan/math/prim/fun/acos.hpp | 2 +- stan/math/prim/fun/asin.hpp | 2 +- stan/math/prim/fun/atan.hpp | 2 +- stan/math/prim/fun/ceil.hpp | 2 +- stan/math/prim/fun/cos.hpp | 2 +- stan/math/prim/fun/cosh.hpp | 2 +- stan/math/prim/fun/exp.hpp | 2 +- stan/math/prim/fun/fabs.hpp | 4 ++-- stan/math/prim/fun/floor.hpp | 2 +- stan/math/prim/fun/inv.hpp | 4 ++-- stan/math/prim/fun/inv_cloglog.hpp | 4 ++-- stan/math/prim/fun/inv_sqrt.hpp | 4 ++-- stan/math/prim/fun/log.hpp | 2 +- stan/math/prim/fun/log10.hpp | 2 +- stan/math/prim/fun/log_softmax.hpp | 11 ++++++----- stan/math/prim/fun/minus.hpp | 4 +++- stan/math/prim/fun/round.hpp | 2 +- stan/math/prim/fun/sin.hpp | 2 +- stan/math/prim/fun/sinh.hpp | 4 ++-- stan/math/prim/fun/sqrt.hpp | 2 +- stan/math/prim/fun/tan.hpp | 2 +- stan/math/prim/fun/tanh.hpp | 2 +- stan/math/prim/vectorize/apply_scalar_unary.hpp | 7 +++++-- test/unit/math/prim/fun/Phi_approx_test.cpp | 8 ++++++++ test/unit/math/prim/fun/Phi_test.cpp | 8 ++++++++ test/unit/math/prim/fun/acos_test.cpp | 8 ++++++++ test/unit/math/prim/fun/acosh_test.cpp | 8 ++++++++ test/unit/math/prim/fun/asin_test.cpp | 8 ++++++++ test/unit/math/prim/fun/asinh_test.cpp | 8 ++++++++ test/unit/math/prim/fun/atan_test.cpp | 8 ++++++++ test/unit/math/prim/fun/atanh_test.cpp | 8 ++++++++ test/unit/math/prim/fun/cbrt_test.cpp | 8 ++++++++ test/unit/math/prim/fun/ceil_test.cpp | 8 ++++++++ test/unit/math/prim/fun/cos_test.cpp | 8 ++++++++ test/unit/math/prim/fun/cosh_test.cpp | 10 ++++++++++ test/unit/math/prim/fun/digamma_test.cpp | 8 ++++++++ test/unit/math/prim/fun/erf_test.cpp | 8 ++++++++ test/unit/math/prim/fun/erfc_test.cpp | 8 ++++++++ test/unit/math/prim/fun/exp2_test.cpp | 8 ++++++++ test/unit/math/prim/fun/exp_test.cpp | 8 ++++++++ test/unit/math/prim/fun/expm1_test.cpp | 8 ++++++++ test/unit/math/prim/fun/fabs_test.cpp | 8 ++++++++ test/unit/math/prim/fun/floor_test.cpp | 8 ++++++++ test/unit/math/prim/fun/inv_Phi_test.cpp | 8 ++++++++ test/unit/math/prim/fun/inv_cloglog_test.cpp | 8 ++++++++ test/unit/math/prim/fun/inv_logit_test.cpp | 8 ++++++++ test/unit/math/prim/fun/inv_sqrt_test.cpp | 8 ++++++++ test/unit/math/prim/fun/inv_square_test.cpp | 8 ++++++++ test/unit/math/prim/fun/inv_test.cpp | 8 ++++++++ test/unit/math/prim/fun/lgamma_test.cpp | 8 ++++++++ test/unit/math/prim/fun/log10_test.cpp | 8 ++++++++ test/unit/math/prim/fun/log1m_test.cpp | 8 ++++++++ test/unit/math/prim/fun/log1p_exp_test.cpp | 8 ++++++++ test/unit/math/prim/fun/log1p_test.cpp | 8 ++++++++ test/unit/math/prim/fun/log2_test.cpp | 8 ++++++++ test/unit/math/prim/fun/log_inv_logit_test.cpp | 8 ++++++++ test/unit/math/prim/fun/log_softmax_test.cpp | 8 ++++++++ test/unit/math/prim/fun/log_test.cpp | 8 ++++++++ test/unit/math/prim/fun/logit_test.cpp | 8 ++++++++ test/unit/math/prim/fun/minus_test.cpp | 8 ++++++++ test/unit/math/prim/fun/round_test.cpp | 8 ++++++++ test/unit/math/prim/fun/sin_test.cpp | 8 ++++++++ test/unit/math/prim/fun/sinh_test.cpp | 8 ++++++++ test/unit/math/prim/fun/sqrt_test.cpp | 8 ++++++++ test/unit/math/prim/fun/square_test.cpp | 10 +++++++++- test/unit/math/prim/fun/tan_test.cpp | 10 ++++++++++ test/unit/math/prim/fun/tanh_test.cpp | 8 ++++++++ test/unit/math/prim/fun/tgamma_test.cpp | 8 ++++++++ test/unit/math/prim/fun/trigamma_test.cpp | 8 ++++++++ test/unit/math/prim/fun/trunc_test.cpp | 8 ++++++++ 70 files changed, 420 insertions(+), 34 deletions(-) create mode 100644 test/unit/math/prim/fun/cosh_test.cpp create mode 100644 test/unit/math/prim/fun/tan_test.cpp diff --git a/stan/math/prim/fun/acos.hpp b/stan/math/prim/fun/acos.hpp index 709864e1db6..e5960f1b758 100644 --- a/stan/math/prim/fun/acos.hpp +++ b/stan/math/prim/fun/acos.hpp @@ -45,7 +45,7 @@ inline auto acos(const T& x) { template > inline auto acos(const Eigen::MatrixBase& x) { - return x.derived().array().acos().matrix(); + return x.derived().array().acos().matrix().eval(); } } // namespace math diff --git a/stan/math/prim/fun/asin.hpp b/stan/math/prim/fun/asin.hpp index 81a22dcf60b..0f5d172a29b 100644 --- a/stan/math/prim/fun/asin.hpp +++ b/stan/math/prim/fun/asin.hpp @@ -45,7 +45,7 @@ inline auto asin(const T& x) { template > inline auto asin(const Eigen::MatrixBase& x) { - return x.derived().array().asin().matrix(); + return x.derived().array().asin().matrix().eval(); } } // namespace math diff --git a/stan/math/prim/fun/atan.hpp b/stan/math/prim/fun/atan.hpp index 28a05b08d6a..9576c99240a 100644 --- a/stan/math/prim/fun/atan.hpp +++ b/stan/math/prim/fun/atan.hpp @@ -45,7 +45,7 @@ inline typename apply_scalar_unary::return_t atan(const T& x) { template > inline auto atan(const Eigen::MatrixBase& x) { - return x.derived().array().atan().matrix(); + return x.derived().array().atan().matrix().eval(); } } // namespace math diff --git a/stan/math/prim/fun/ceil.hpp b/stan/math/prim/fun/ceil.hpp index 7a78566ac1d..2de0ddb72e7 100644 --- a/stan/math/prim/fun/ceil.hpp +++ b/stan/math/prim/fun/ceil.hpp @@ -45,7 +45,7 @@ inline auto ceil(const T& x) { template > inline auto ceil(const Eigen::MatrixBase& x) { - return x.derived().array().ceil().matrix(); + return x.derived().array().ceil().matrix().eval(); } } // namespace math diff --git a/stan/math/prim/fun/cos.hpp b/stan/math/prim/fun/cos.hpp index 0c20e53f935..bf9761ace9f 100644 --- a/stan/math/prim/fun/cos.hpp +++ b/stan/math/prim/fun/cos.hpp @@ -45,7 +45,7 @@ inline auto cos(const T& x) { template > inline auto cos(const Eigen::MatrixBase& x) { - return x.derived().array().cos().matrix(); + return x.derived().array().cos().matrix().eval(); } } // namespace math diff --git a/stan/math/prim/fun/cosh.hpp b/stan/math/prim/fun/cosh.hpp index 3dee3eae2a3..2a0402fe9c2 100644 --- a/stan/math/prim/fun/cosh.hpp +++ b/stan/math/prim/fun/cosh.hpp @@ -45,7 +45,7 @@ inline typename apply_scalar_unary::return_t cosh(const T& x) { template > inline auto cosh(const Eigen::MatrixBase& x) { - return x.derived().array().cosh().matrix(); + return x.derived().array().cosh().matrix().eval(); } } // namespace math diff --git a/stan/math/prim/fun/exp.hpp b/stan/math/prim/fun/exp.hpp index 4d60b4c04b5..54486d9e394 100644 --- a/stan/math/prim/fun/exp.hpp +++ b/stan/math/prim/fun/exp.hpp @@ -60,7 +60,7 @@ inline auto exp(const T& x) { template > inline auto exp(const Eigen::MatrixBase& x) { - return x.derived().array().exp().matrix(); + return x.derived().array().exp().matrix().eval(); } } // namespace math diff --git a/stan/math/prim/fun/fabs.hpp b/stan/math/prim/fun/fabs.hpp index 1dc51b0ee3c..2bfc97071d2 100644 --- a/stan/math/prim/fun/fabs.hpp +++ b/stan/math/prim/fun/fabs.hpp @@ -45,7 +45,7 @@ inline typename apply_scalar_unary::return_t fabs(const T& x) { template > inline auto fabs(const Eigen::MatrixBase& x) { - return x.derived().array().abs().matrix(); + return x.derived().array().abs().matrix().eval(); } /** @@ -57,7 +57,7 @@ inline auto fabs(const Eigen::MatrixBase& x) { template > inline auto fabs(const Eigen::ArrayBase& x) { - return x.derived().abs(); + return x.derived().abs().eval(); } } // namespace math diff --git a/stan/math/prim/fun/floor.hpp b/stan/math/prim/fun/floor.hpp index 7f1f37317cd..c53433cf356 100644 --- a/stan/math/prim/fun/floor.hpp +++ b/stan/math/prim/fun/floor.hpp @@ -45,7 +45,7 @@ inline auto floor(const T& x) { template > inline auto floor(const Eigen::MatrixBase& x) { - return x.derived().array().floor().matrix(); + return x.derived().array().floor().matrix().eval(); } } // namespace math diff --git a/stan/math/prim/fun/inv.hpp b/stan/math/prim/fun/inv.hpp index f50f17f784c..439dc962778 100644 --- a/stan/math/prim/fun/inv.hpp +++ b/stan/math/prim/fun/inv.hpp @@ -45,7 +45,7 @@ inline auto inv(const T& x) { template > inline auto inv(const Eigen::MatrixBase& x) { - return x.derived().array().inverse().matrix(); + return x.derived().array().inverse().matrix().eval(); } /** @@ -57,7 +57,7 @@ inline auto inv(const Eigen::MatrixBase& x) { template > inline auto inv(const Eigen::ArrayBase& x) { - return x.derived().inverse(); + return x.derived().inverse().eval(); } } // namespace math diff --git a/stan/math/prim/fun/inv_cloglog.hpp b/stan/math/prim/fun/inv_cloglog.hpp index 945417aa0f9..44c6dfdc8d7 100644 --- a/stan/math/prim/fun/inv_cloglog.hpp +++ b/stan/math/prim/fun/inv_cloglog.hpp @@ -87,7 +87,7 @@ inline auto inv_cloglog(const T& x) { template > inline auto inv_cloglog(const Eigen::MatrixBase& x) { - return (1 - exp(-exp(x.derived().array()))).matrix(); + return (1 - exp(-exp(x.derived().array()))).matrix().eval(); } /** @@ -99,7 +99,7 @@ inline auto inv_cloglog(const Eigen::MatrixBase& x) { template > inline auto inv_cloglog(const Eigen::ArrayBase& x) { - return 1 - exp(-exp(x.derived())); + return (1 - exp(-exp(x.derived()))).eval(); } } // namespace math diff --git a/stan/math/prim/fun/inv_sqrt.hpp b/stan/math/prim/fun/inv_sqrt.hpp index aa6e0d7ffdf..66b41ee7138 100644 --- a/stan/math/prim/fun/inv_sqrt.hpp +++ b/stan/math/prim/fun/inv_sqrt.hpp @@ -50,7 +50,7 @@ inline auto inv_sqrt(const T& x) { template > inline auto inv_sqrt(const Eigen::MatrixBase& x) { - return x.derived().array().rsqrt().matrix(); + return x.derived().array().rsqrt().matrix().eval(); } /** @@ -62,7 +62,7 @@ inline auto inv_sqrt(const Eigen::MatrixBase& x) { template > inline auto inv_sqrt(const Eigen::ArrayBase& x) { - return x.derived().rsqrt(); + return x.derived().rsqrt().eval(); } } // namespace math diff --git a/stan/math/prim/fun/log.hpp b/stan/math/prim/fun/log.hpp index 2e32bc5aa4b..3814d0a5ae5 100644 --- a/stan/math/prim/fun/log.hpp +++ b/stan/math/prim/fun/log.hpp @@ -60,7 +60,7 @@ inline auto log(const T& x) { template > inline auto log(const Eigen::MatrixBase& x) { - return x.derived().array().log().matrix(); + return x.derived().array().log().matrix().eval(); } } // namespace math diff --git a/stan/math/prim/fun/log10.hpp b/stan/math/prim/fun/log10.hpp index 808bdb85bad..10b7b0fa1b0 100644 --- a/stan/math/prim/fun/log10.hpp +++ b/stan/math/prim/fun/log10.hpp @@ -45,7 +45,7 @@ inline auto log10(const T& x) { template > inline auto log10(const Eigen::MatrixBase& x) { - return x.derived().array().log10().matrix(); + return x.derived().array().log10().matrix().eval(); } } // namespace math diff --git a/stan/math/prim/fun/log_softmax.hpp b/stan/math/prim/fun/log_softmax.hpp index a51370d0b1a..8c4951df779 100644 --- a/stan/math/prim/fun/log_softmax.hpp +++ b/stan/math/prim/fun/log_softmax.hpp @@ -36,11 +36,12 @@ namespace math { * @param[in] v Vector to transform. * @return Unit simplex result of the softmax transform of the vector. */ -template -inline Eigen::Matrix log_softmax( - const Eigen::Matrix& v) { - check_nonzero_size("log_softmax", "v", v); - return v.array() - log_sum_exp(v); +template >>...> +inline auto log_softmax(const T& x) { + return apply_vector_unary::apply(x, [&](const auto& v) { + check_nonzero_size("log_softmax", "v", v); + return (v.array() - log_sum_exp(v)).matrix().eval(); + }); } } // namespace math diff --git a/stan/math/prim/fun/minus.hpp b/stan/math/prim/fun/minus.hpp index 7f374462fc0..13fe7d090ed 100644 --- a/stan/math/prim/fun/minus.hpp +++ b/stan/math/prim/fun/minus.hpp @@ -1,6 +1,8 @@ #ifndef STAN_MATH_PRIM_FUN_MINUS_HPP #define STAN_MATH_PRIM_FUN_MINUS_HPP +#include + namespace stan { namespace math { @@ -12,7 +14,7 @@ namespace math { * @return Negation of subtrahend. */ template -inline auto minus(const T& x) { +inline plain_type_t minus(const T& x) { return -x; } diff --git a/stan/math/prim/fun/round.hpp b/stan/math/prim/fun/round.hpp index 66b2d6a428c..e5cc48efd18 100644 --- a/stan/math/prim/fun/round.hpp +++ b/stan/math/prim/fun/round.hpp @@ -62,7 +62,7 @@ inline auto round(const T& x) { template > inline auto round(const Eigen::MatrixBase& x) { - return x.derived().array().round().matrix(); + return x.derived().array().round().matrix().eval(); } } // namespace math diff --git a/stan/math/prim/fun/sin.hpp b/stan/math/prim/fun/sin.hpp index f2ed9102f97..0b783ffeb20 100644 --- a/stan/math/prim/fun/sin.hpp +++ b/stan/math/prim/fun/sin.hpp @@ -45,7 +45,7 @@ inline auto sin(const T& x) { template > inline auto sin(const Eigen::MatrixBase& x) { - return x.derived().array().sin().matrix(); + return x.derived().array().sin().matrix().eval(); } } // namespace math diff --git a/stan/math/prim/fun/sinh.hpp b/stan/math/prim/fun/sinh.hpp index 5e13a03993e..e4d1252295d 100644 --- a/stan/math/prim/fun/sinh.hpp +++ b/stan/math/prim/fun/sinh.hpp @@ -45,7 +45,7 @@ inline auto sinh(const T& x) { template > inline auto sinh(const Eigen::MatrixBase& x) { - return x.derived().array().sinh().matrix(); + return x.derived().array().sinh().matrix().eval(); } /** @@ -57,7 +57,7 @@ inline auto sinh(const Eigen::MatrixBase& x) { template > inline auto sinh(const Eigen::ArrayBase& x) { - return x.derived().sinh(); + return x.derived().sinh().eval(); } } // namespace math diff --git a/stan/math/prim/fun/sqrt.hpp b/stan/math/prim/fun/sqrt.hpp index ae1b6dace93..fe81fcf75b6 100644 --- a/stan/math/prim/fun/sqrt.hpp +++ b/stan/math/prim/fun/sqrt.hpp @@ -54,7 +54,7 @@ inline auto sqrt(const T& x) { template > inline auto sqrt(const Eigen::MatrixBase& x) { - return x.derived().array().sqrt().matrix(); + return x.derived().array().sqrt().matrix().eval(); } } // namespace math diff --git a/stan/math/prim/fun/tan.hpp b/stan/math/prim/fun/tan.hpp index 7064300e695..efc03beb94b 100644 --- a/stan/math/prim/fun/tan.hpp +++ b/stan/math/prim/fun/tan.hpp @@ -45,7 +45,7 @@ inline auto tan(const T& x) { template > inline auto tan(const Eigen::MatrixBase& x) { - return x.derived().array().tan().matrix(); + return x.derived().array().tan().matrix().eval(); } } // namespace math diff --git a/stan/math/prim/fun/tanh.hpp b/stan/math/prim/fun/tanh.hpp index 60c4d405fb2..2fe9f4c5a25 100644 --- a/stan/math/prim/fun/tanh.hpp +++ b/stan/math/prim/fun/tanh.hpp @@ -45,7 +45,7 @@ inline auto tanh(const T& x) { template > inline auto tanh(const Eigen::MatrixBase& x) { - return x.derived().array().tanh().matrix(); + return x.derived().array().tanh().matrix().eval(); } } // namespace math diff --git a/stan/math/prim/vectorize/apply_scalar_unary.hpp b/stan/math/prim/vectorize/apply_scalar_unary.hpp index ed31037a207..8cc283cd4ac 100644 --- a/stan/math/prim/vectorize/apply_scalar_unary.hpp +++ b/stan/math/prim/vectorize/apply_scalar_unary.hpp @@ -59,8 +59,11 @@ struct apply_scalar_unary> { * by F to the specified matrix. */ static inline auto apply(const T& x) { - return x.unaryExpr( - [](scalar_t x) { return apply_scalar_unary::apply(x); }); + return x + .unaryExpr([](scalar_t x) { + return apply_scalar_unary::apply(x); + }) + .eval(); } /** diff --git a/test/unit/math/prim/fun/Phi_approx_test.cpp b/test/unit/math/prim/fun/Phi_approx_test.cpp index dbc4078352d..4a29923c572 100644 --- a/test/unit/math/prim/fun/Phi_approx_test.cpp +++ b/test/unit/math/prim/fun/Phi_approx_test.cpp @@ -14,3 +14,11 @@ TEST(MathFunctions, Phi_approx_nan) { EXPECT_TRUE(std::isnan(stan::math::Phi_approx(nan))); } + +TEST(MathFunctions, Phi_approx__works_with_other_functions) { + Eigen::VectorXd a(5); + a << 1.1, 1.2, 1.3, 1.4, 1.5; + Eigen::RowVectorXd b(5); + b << 1.1, 1.2, 1.3, 1.4, 1.5; + stan::math::multiply(a, stan::math::Phi_approx(b)); +} diff --git a/test/unit/math/prim/fun/Phi_test.cpp b/test/unit/math/prim/fun/Phi_test.cpp index c43e260bf88..1273ad24628 100644 --- a/test/unit/math/prim/fun/Phi_test.cpp +++ b/test/unit/math/prim/fun/Phi_test.cpp @@ -118,3 +118,11 @@ TEST(MathFunctions, Phi_nan) { double nan = std::numeric_limits::quiet_NaN(); EXPECT_THROW(stan::math::Phi(nan), std::domain_error); } + +TEST(MathFunctions, Phi_works_with_other_functions) { + Eigen::VectorXd a(5); + a << 1.1, 1.2, 1.3, 1.4, 1.5; + Eigen::RowVectorXd b(5); + b << 1.1, 1.2, 1.3, 1.4, 1.5; + stan::math::multiply(a, stan::math::Phi(b)); +} diff --git a/test/unit/math/prim/fun/acos_test.cpp b/test/unit/math/prim/fun/acos_test.cpp index c66c4c49a02..7570f52cc71 100644 --- a/test/unit/math/prim/fun/acos_test.cpp +++ b/test/unit/math/prim/fun/acos_test.cpp @@ -5,3 +5,11 @@ TEST(primScalFun, acos) { stan::test::expect_common_prim([](auto x) { return std::acos(x); }, [](auto x) { return stan::math::acos(x); }); } + +TEST(MathFunctions, acos_works_with_other_functions) { + Eigen::VectorXd a(5); + a << 0.1, 0.2, 0.3, 0.4, 0.5; + Eigen::RowVectorXd b(5); + b << 0.1, 0.2, 0.3, 0.4, 0.5; + stan::math::multiply(a, stan::math::acos(b)); +} diff --git a/test/unit/math/prim/fun/acosh_test.cpp b/test/unit/math/prim/fun/acosh_test.cpp index 2d5bc742d3c..1f9e8ab7bb5 100644 --- a/test/unit/math/prim/fun/acosh_test.cpp +++ b/test/unit/math/prim/fun/acosh_test.cpp @@ -26,3 +26,11 @@ TEST(MathFunctions, acosh_nan) { double nan = std::numeric_limits::quiet_NaN(); EXPECT_TRUE(std::isnan(stan::math::acosh(nan))); } + +TEST(MathFunctions, acosh_works_with_other_functions) { + Eigen::VectorXd a(5); + a << 1.1, 1.2, 1.3, 1.4, 1.5; + Eigen::RowVectorXd b(5); + b << 1.1, 1.2, 1.3, 1.4, 1.5; + stan::math::multiply(a, stan::math::acosh(b)); +} diff --git a/test/unit/math/prim/fun/asin_test.cpp b/test/unit/math/prim/fun/asin_test.cpp index a14245b58c2..858be5fbbbd 100644 --- a/test/unit/math/prim/fun/asin_test.cpp +++ b/test/unit/math/prim/fun/asin_test.cpp @@ -5,3 +5,11 @@ TEST(primScalFun, asin) { stan::test::expect_common_prim([](auto x) { return std::asin(x); }, [](auto x) { return stan::math::asin(x); }); } + +TEST(MathFunctions, asin_works_with_other_functions) { + Eigen::VectorXd a(5); + a << 0.1, 0.2, 0.3, 0.4, 0.5; + Eigen::RowVectorXd b(5); + b << 0.1, 0.2, 0.3, 0.4, 0.5; + stan::math::multiply(a, stan::math::asin(b)); +} diff --git a/test/unit/math/prim/fun/asinh_test.cpp b/test/unit/math/prim/fun/asinh_test.cpp index 151afc2b3ef..e10228b0af0 100644 --- a/test/unit/math/prim/fun/asinh_test.cpp +++ b/test/unit/math/prim/fun/asinh_test.cpp @@ -22,3 +22,11 @@ TEST(MathFunctions, asinh_nan) { double nan = std::numeric_limits::quiet_NaN(); EXPECT_TRUE(std::isnan(stan::math::asinh(nan))); } + +TEST(MathFunctions, asinh_works_with_other_functions) { + Eigen::VectorXd a(5); + a << 1.1, 1.2, 1.3, 1.4, 1.5; + Eigen::RowVectorXd b(5); + b << 1.1, 1.2, 1.3, 1.4, 1.5; + stan::math::multiply(a, stan::math::asinh(b)); +} diff --git a/test/unit/math/prim/fun/atan_test.cpp b/test/unit/math/prim/fun/atan_test.cpp index 467ceefff7d..54861be5151 100644 --- a/test/unit/math/prim/fun/atan_test.cpp +++ b/test/unit/math/prim/fun/atan_test.cpp @@ -5,3 +5,11 @@ TEST(primScalFun, atan) { stan::test::expect_common_prim([](auto x) { return std::atan(x); }, [](auto x) { return stan::math::atan(x); }); } + +TEST(MathFunctions, atan_works_with_other_functions) { + Eigen::VectorXd a(5); + a << 1.1, 1.2, 1.3, 1.4, 1.5; + Eigen::RowVectorXd b(5); + b << 1.1, 1.2, 1.3, 1.4, 1.5; + stan::math::multiply(a, stan::math::atan(b)); +} diff --git a/test/unit/math/prim/fun/atanh_test.cpp b/test/unit/math/prim/fun/atanh_test.cpp index ca60e585e86..18ae151e23c 100644 --- a/test/unit/math/prim/fun/atanh_test.cpp +++ b/test/unit/math/prim/fun/atanh_test.cpp @@ -27,3 +27,11 @@ TEST(MathFunctions, atanh_nan) { double nan = std::numeric_limits::quiet_NaN(); EXPECT_TRUE(std::isnan(stan::math::atanh(nan))); } + +TEST(MathFunctions, atanh_works_with_other_functions) { + Eigen::VectorXd a(5); + a << 0.1, 0.2, 0.3, 0.4, 0.5; + Eigen::RowVectorXd b(5); + b << 0.1, 0.2, 0.3, 0.4, 0.5; + stan::math::multiply(a, stan::math::atanh(b)); +} diff --git a/test/unit/math/prim/fun/cbrt_test.cpp b/test/unit/math/prim/fun/cbrt_test.cpp index 2ca66bbde53..854853943a6 100644 --- a/test/unit/math/prim/fun/cbrt_test.cpp +++ b/test/unit/math/prim/fun/cbrt_test.cpp @@ -24,3 +24,11 @@ TEST(MathFunctions, cbrt_nan) { double nan = std::numeric_limits::quiet_NaN(); EXPECT_TRUE(std::isnan(stan::math::cbrt(nan))); } + +TEST(MathFunctions, cbrt_works_with_other_functions) { + Eigen::VectorXd a(5); + a << 1.1, 1.2, 1.3, 1.4, 1.5; + Eigen::RowVectorXd b(5); + b << 1.1, 1.2, 1.3, 1.4, 1.5; + stan::math::multiply(a, stan::math::cbrt(b)); +} diff --git a/test/unit/math/prim/fun/ceil_test.cpp b/test/unit/math/prim/fun/ceil_test.cpp index f26f0068eb1..57a7dce8c41 100644 --- a/test/unit/math/prim/fun/ceil_test.cpp +++ b/test/unit/math/prim/fun/ceil_test.cpp @@ -4,3 +4,11 @@ TEST(primScalFun, ceil) { stan::test::expect_common_prim([](auto x) { return std::ceil(x); }, [](auto x) { return stan::math::ceil(x); }); } + +TEST(MathFunctions, ceil_works_with_other_functions) { + Eigen::VectorXd a(5); + a << 1.1, 1.2, 1.3, 1.4, 1.5; + Eigen::RowVectorXd b(5); + b << 1.1, 1.2, 1.3, 1.4, 1.5; + stan::math::multiply(a, stan::math::ceil(b)); +} diff --git a/test/unit/math/prim/fun/cos_test.cpp b/test/unit/math/prim/fun/cos_test.cpp index 53daaa398de..94989f9703f 100644 --- a/test/unit/math/prim/fun/cos_test.cpp +++ b/test/unit/math/prim/fun/cos_test.cpp @@ -5,3 +5,11 @@ TEST(primScalFun, cos) { stan::test::expect_common_prim([](auto x) { return std::cos(x); }, [](auto x) { return stan::math::cos(x); }); } + +TEST(MathFunctions, cos_works_with_other_functions) { + Eigen::VectorXd a(5); + a << 1.1, 1.2, 1.3, 1.4, 1.5; + Eigen::RowVectorXd b(5); + b << 1.1, 1.2, 1.3, 1.4, 1.5; + stan::math::multiply(a, stan::math::cos(b)); +} diff --git a/test/unit/math/prim/fun/cosh_test.cpp b/test/unit/math/prim/fun/cosh_test.cpp new file mode 100644 index 00000000000..d1433637b36 --- /dev/null +++ b/test/unit/math/prim/fun/cosh_test.cpp @@ -0,0 +1,10 @@ +#include +#include + +TEST(MathFunctions, cosh_works_with_other_functions) { + Eigen::VectorXd a(5); + a << 1.1, 1.2, 1.3, 1.4, 1.5; + Eigen::RowVectorXd b(5); + b << 1.1, 1.2, 1.3, 1.4, 1.5; + stan::math::multiply(a, stan::math::cosh(b)); +} diff --git a/test/unit/math/prim/fun/digamma_test.cpp b/test/unit/math/prim/fun/digamma_test.cpp index 2a3a7ea150b..b0d37f98b7e 100644 --- a/test/unit/math/prim/fun/digamma_test.cpp +++ b/test/unit/math/prim/fun/digamma_test.cpp @@ -18,3 +18,11 @@ TEST(MathFunctions, digamma_nan) { EXPECT_TRUE(std::isnormal(stan::math::digamma(1.0E50))); } + +TEST(MathFunctions, digamma_works_with_other_functions) { + Eigen::VectorXd a(5); + a << 1.1, 1.2, 1.3, 1.4, 1.5; + Eigen::RowVectorXd b(5); + b << 1.1, 1.2, 1.3, 1.4, 1.5; + stan::math::multiply(a, stan::math::digamma(b)); +} diff --git a/test/unit/math/prim/fun/erf_test.cpp b/test/unit/math/prim/fun/erf_test.cpp index f01b192b8be..0c06057587c 100644 --- a/test/unit/math/prim/fun/erf_test.cpp +++ b/test/unit/math/prim/fun/erf_test.cpp @@ -20,3 +20,11 @@ TEST(MathFunctions, erfNan) { double nan = std::numeric_limits::quiet_NaN(); EXPECT_TRUE(std::isnan(stan::math::erf(nan))); } + +TEST(MathFunctions, erf_works_with_other_functions) { + Eigen::VectorXd a(5); + a << 1.1, 1.2, 1.3, 1.4, 1.5; + Eigen::RowVectorXd b(5); + b << 1.1, 1.2, 1.3, 1.4, 1.5; + stan::math::multiply(a, stan::math::erf(b)); +} diff --git a/test/unit/math/prim/fun/erfc_test.cpp b/test/unit/math/prim/fun/erfc_test.cpp index aad40784135..2e19d0fe333 100644 --- a/test/unit/math/prim/fun/erfc_test.cpp +++ b/test/unit/math/prim/fun/erfc_test.cpp @@ -21,3 +21,11 @@ TEST(MathFunctions, erfcNan) { double nan = std::numeric_limits::quiet_NaN(); EXPECT_TRUE(std::isnan(stan::math::erfc(nan))); } + +TEST(MathFunctions, erfc_works_with_other_functions) { + Eigen::VectorXd a(5); + a << 1.1, 1.2, 1.3, 1.4, 1.5; + Eigen::RowVectorXd b(5); + b << 1.1, 1.2, 1.3, 1.4, 1.5; + stan::math::multiply(a, stan::math::erfc(b)); +} diff --git a/test/unit/math/prim/fun/exp2_test.cpp b/test/unit/math/prim/fun/exp2_test.cpp index ae1c93c1e22..b5c8f356425 100644 --- a/test/unit/math/prim/fun/exp2_test.cpp +++ b/test/unit/math/prim/fun/exp2_test.cpp @@ -35,3 +35,11 @@ TEST(MathFunctions, exp2_nan) { EXPECT_TRUE(std::isnan(stan::math::exp2(nan))); } + +TEST(MathFunctions, exp2_works_with_other_functions) { + Eigen::VectorXd a(5); + a << 1.1, 1.2, 1.3, 1.4, 1.5; + Eigen::RowVectorXd b(5); + b << 1.1, 1.2, 1.3, 1.4, 1.5; + stan::math::multiply(a, stan::math::exp2(b)); +} diff --git a/test/unit/math/prim/fun/exp_test.cpp b/test/unit/math/prim/fun/exp_test.cpp index a19d8643a9f..292f72baf10 100644 --- a/test/unit/math/prim/fun/exp_test.cpp +++ b/test/unit/math/prim/fun/exp_test.cpp @@ -7,3 +7,11 @@ TEST(MathFunctions, expInt) { EXPECT_FLOAT_EQ(std::exp(3), exp(3)); EXPECT_FLOAT_EQ(std::exp(3.0), exp(3.0)); } + +TEST(MathFunctions, exp_works_with_other_functions) { + Eigen::VectorXd a(5); + a << 1.1, 1.2, 1.3, 1.4, 1.5; + Eigen::RowVectorXd b(5); + b << 1.1, 1.2, 1.3, 1.4, 1.5; + stan::math::multiply(a, stan::math::exp(b)); +} diff --git a/test/unit/math/prim/fun/expm1_test.cpp b/test/unit/math/prim/fun/expm1_test.cpp index 3e35d9873c1..a92bbc91f45 100644 --- a/test/unit/math/prim/fun/expm1_test.cpp +++ b/test/unit/math/prim/fun/expm1_test.cpp @@ -23,3 +23,11 @@ TEST(MathFunctions, expm1_nan) { double nan = std::numeric_limits::quiet_NaN(); EXPECT_TRUE(std::isnan(stan::math::expm1(nan))); } + +TEST(MathFunctions, expm1_works_with_other_functions) { + Eigen::VectorXd a(5); + a << 1.1, 1.2, 1.3, 1.4, 1.5; + Eigen::RowVectorXd b(5); + b << 1.1, 1.2, 1.3, 1.4, 1.5; + stan::math::multiply(a, stan::math::expm1(b)); +} diff --git a/test/unit/math/prim/fun/fabs_test.cpp b/test/unit/math/prim/fun/fabs_test.cpp index 985f1426eda..e4450169d0a 100644 --- a/test/unit/math/prim/fun/fabs_test.cpp +++ b/test/unit/math/prim/fun/fabs_test.cpp @@ -5,3 +5,11 @@ TEST(primScalFun, fabs) { stan::test::expect_common_prim([](auto x) { return std::fabs(x); }, [](auto x) { return stan::math::fabs(x); }); } + +TEST(MathFunctions, fabs_works_with_other_functions) { + Eigen::VectorXd a(5); + a << 1.1, 1.2, 1.3, 1.4, 1.5; + Eigen::RowVectorXd b(5); + b << 1.1, 1.2, 1.3, 1.4, 1.5; + stan::math::multiply(a, stan::math::fabs(b)); +} diff --git a/test/unit/math/prim/fun/floor_test.cpp b/test/unit/math/prim/fun/floor_test.cpp index 6c283c47dbc..90c6dca6090 100644 --- a/test/unit/math/prim/fun/floor_test.cpp +++ b/test/unit/math/prim/fun/floor_test.cpp @@ -4,3 +4,11 @@ TEST(primScalFun, floor) { stan::test::expect_common_prim([](auto x) { return std::floor(x); }, [](auto x) { return stan::math::floor(x); }); } + +TEST(MathFunctions, floor_works_with_other_functions) { + Eigen::VectorXd a(5); + a << 1.1, 1.2, 1.3, 1.4, 1.5; + Eigen::RowVectorXd b(5); + b << 1.1, 1.2, 1.3, 1.4, 1.5; + stan::math::multiply(a, stan::math::floor(b)); +} diff --git a/test/unit/math/prim/fun/inv_Phi_test.cpp b/test/unit/math/prim/fun/inv_Phi_test.cpp index 13d81adbb7f..9538f7151d6 100644 --- a/test/unit/math/prim/fun/inv_Phi_test.cpp +++ b/test/unit/math/prim/fun/inv_Phi_test.cpp @@ -34,3 +34,11 @@ TEST(MathFunctions, inv_Phi_nan) { EXPECT_THROW(inv_Phi(-2.0), std::domain_error); EXPECT_THROW(inv_Phi(2.0), std::domain_error); } + +TEST(MathFunctions, inv_Phi_works_with_other_functions) { + Eigen::VectorXd a(5); + a << 0.1, 0.2, 0.3, 0.4, 0.5; + Eigen::RowVectorXd b(5); + b << 0.1, 0.2, 0.3, 0.4, 0.5; + stan::math::multiply(a, stan::math::inv_Phi(b)); +} diff --git a/test/unit/math/prim/fun/inv_cloglog_test.cpp b/test/unit/math/prim/fun/inv_cloglog_test.cpp index 67118b3b9e6..3f8c3fa6c7b 100644 --- a/test/unit/math/prim/fun/inv_cloglog_test.cpp +++ b/test/unit/math/prim/fun/inv_cloglog_test.cpp @@ -14,3 +14,11 @@ TEST(MathFunctions, inv_cloglog_nan) { EXPECT_TRUE(std::isnan(stan::math::inv_cloglog(nan))); } + +TEST(MathFunctions, inv_cloglog_works_with_other_functions) { + Eigen::VectorXd a(5); + a << 1.1, 1.2, 1.3, 1.4, 1.5; + Eigen::RowVectorXd b(5); + b << 1.1, 1.2, 1.3, 1.4, 1.5; + stan::math::multiply(a, stan::math::inv_cloglog(b)); +} diff --git a/test/unit/math/prim/fun/inv_logit_test.cpp b/test/unit/math/prim/fun/inv_logit_test.cpp index b1e0de78766..a7e272f19b5 100644 --- a/test/unit/math/prim/fun/inv_logit_test.cpp +++ b/test/unit/math/prim/fun/inv_logit_test.cpp @@ -14,3 +14,11 @@ TEST(MathFunctions, inv_logit_nan) { EXPECT_TRUE(std::isnan(stan::math::inv_logit(nan))); } + +TEST(MathFunctions, inv_logit_works_with_other_functions) { + Eigen::VectorXd a(5); + a << 1.1, 1.2, 1.3, 1.4, 1.5; + Eigen::RowVectorXd b(5); + b << 1.1, 1.2, 1.3, 1.4, 1.5; + stan::math::multiply(a, stan::math::inv_logit(b)); +} diff --git a/test/unit/math/prim/fun/inv_sqrt_test.cpp b/test/unit/math/prim/fun/inv_sqrt_test.cpp index 645957931a2..1a7deb94def 100644 --- a/test/unit/math/prim/fun/inv_sqrt_test.cpp +++ b/test/unit/math/prim/fun/inv_sqrt_test.cpp @@ -22,3 +22,11 @@ TEST(MathFunctions, inv_sqrt_nan) { EXPECT_TRUE(std::isnan(stan::math::inv_sqrt(nan))); } + +TEST(MathFunctions, inv_sqrt_works_with_other_functions) { + Eigen::VectorXd a(5); + a << 1.1, 1.2, 1.3, 1.4, 1.5; + Eigen::RowVectorXd b(5); + b << 1.1, 1.2, 1.3, 1.4, 1.5; + stan::math::multiply(a, stan::math::inv_sqrt(b)); +} diff --git a/test/unit/math/prim/fun/inv_square_test.cpp b/test/unit/math/prim/fun/inv_square_test.cpp index 32c17c48cf2..a3cb3588a07 100644 --- a/test/unit/math/prim/fun/inv_square_test.cpp +++ b/test/unit/math/prim/fun/inv_square_test.cpp @@ -19,3 +19,11 @@ TEST(MathFunctions, inv_square_nan) { EXPECT_TRUE(std::isnan(stan::math::inv_square(nan))); } + +TEST(MathFunctions, inv_square_works_with_other_functions) { + Eigen::VectorXd a(5); + a << 1.1, 1.2, 1.3, 1.4, 1.5; + Eigen::RowVectorXd b(5); + b << 1.1, 1.2, 1.3, 1.4, 1.5; + stan::math::multiply(a, stan::math::inv_square(b)); +} diff --git a/test/unit/math/prim/fun/inv_test.cpp b/test/unit/math/prim/fun/inv_test.cpp index f418be35db1..99f9d21a969 100644 --- a/test/unit/math/prim/fun/inv_test.cpp +++ b/test/unit/math/prim/fun/inv_test.cpp @@ -19,3 +19,11 @@ TEST(MathFunctions, inv_nan) { EXPECT_TRUE(std::isnan(stan::math::inv(nan))); } + +TEST(MathFunctions, inv_works_with_other_functions) { + Eigen::VectorXd a(5); + a << 1.1, 1.2, 1.3, 1.4, 1.5; + Eigen::RowVectorXd b(5); + b << 1.1, 1.2, 1.3, 1.4, 1.5; + stan::math::multiply(a, stan::math::inv(b)); +} diff --git a/test/unit/math/prim/fun/lgamma_test.cpp b/test/unit/math/prim/fun/lgamma_test.cpp index d252006d5d5..77e52134c33 100644 --- a/test/unit/math/prim/fun/lgamma_test.cpp +++ b/test/unit/math/prim/fun/lgamma_test.cpp @@ -26,3 +26,11 @@ TEST(MathFunctions, lgamma_nan) { EXPECT_TRUE( std::isnormal(boost::math::lgamma(1.0E50, stan::math::boost_policy_t()))); } + +TEST(MathFunctions, lgamma_works_with_other_functions) { + Eigen::VectorXd a(5); + a << 1.1, 1.2, 1.3, 1.4, 1.5; + Eigen::RowVectorXd b(5); + b << 1.1, 1.2, 1.3, 1.4, 1.5; + stan::math::multiply(a, stan::math::lgamma(b)); +} diff --git a/test/unit/math/prim/fun/log10_test.cpp b/test/unit/math/prim/fun/log10_test.cpp index 1a67f75a75c..4e3e79e94fc 100644 --- a/test/unit/math/prim/fun/log10_test.cpp +++ b/test/unit/math/prim/fun/log10_test.cpp @@ -5,3 +5,11 @@ TEST(primScalFun, log10) { stan::test::expect_common_prim([](auto x) { return std::log10(x); }, [](auto x) { return stan::math::log10(x); }); } + +TEST(MathFunctions, log10_works_with_other_functions) { + Eigen::VectorXd a(5); + a << 1.1, 1.2, 1.3, 1.4, 1.5; + Eigen::RowVectorXd b(5); + b << 1.1, 1.2, 1.3, 1.4, 1.5; + stan::math::multiply(a, stan::math::log10(b)); +} diff --git a/test/unit/math/prim/fun/log1m_test.cpp b/test/unit/math/prim/fun/log1m_test.cpp index a0cf248f987..2c68c5a825e 100644 --- a/test/unit/math/prim/fun/log1m_test.cpp +++ b/test/unit/math/prim/fun/log1m_test.cpp @@ -22,3 +22,11 @@ TEST(MathFunctions, log1m_nan) { double nan = std::numeric_limits::quiet_NaN(); EXPECT_TRUE(std::isnan(stan::math::log1m(nan))); } + +TEST(MathFunctions, log1m_works_with_other_functions) { + Eigen::VectorXd a(5); + a << 0.1, 0.2, 0.3, 0.4, 0.5; + Eigen::RowVectorXd b(5); + b << 0.1, 0.2, 0.3, 0.4, 0.5; + stan::math::multiply(a, stan::math::log1m(b)); +} diff --git a/test/unit/math/prim/fun/log1p_exp_test.cpp b/test/unit/math/prim/fun/log1p_exp_test.cpp index 6930db3a1eb..aa4b3fd0303 100644 --- a/test/unit/math/prim/fun/log1p_exp_test.cpp +++ b/test/unit/math/prim/fun/log1p_exp_test.cpp @@ -16,3 +16,11 @@ TEST(MathFunctions, log1p_exp_nan) { EXPECT_TRUE(std::isnan(stan::math::log1p_exp(nan))); } + +TEST(MathFunctions, log1p_exp_works_with_other_functions) { + Eigen::VectorXd a(5); + a << 1.1, 1.2, 1.3, 1.4, 1.5; + Eigen::RowVectorXd b(5); + b << 1.1, 1.2, 1.3, 1.4, 1.5; + stan::math::multiply(a, stan::math::log1p_exp(b)); +} diff --git a/test/unit/math/prim/fun/log1p_test.cpp b/test/unit/math/prim/fun/log1p_test.cpp index 35f90f46452..714958a1745 100644 --- a/test/unit/math/prim/fun/log1p_test.cpp +++ b/test/unit/math/prim/fun/log1p_test.cpp @@ -40,3 +40,11 @@ TEST(MathFunctions, log1p_nan) { double nan = std::numeric_limits::quiet_NaN(); EXPECT_TRUE(std::isnan(stan::math::log1p(nan))); } + +TEST(MathFunctions, log1p_works_with_other_functions) { + Eigen::VectorXd a(5); + a << 1.1, 1.2, 1.3, 1.4, 1.5; + Eigen::RowVectorXd b(5); + b << 1.1, 1.2, 1.3, 1.4, 1.5; + stan::math::multiply(a, stan::math::log1p(b)); +} diff --git a/test/unit/math/prim/fun/log2_test.cpp b/test/unit/math/prim/fun/log2_test.cpp index 031a50afa97..cf726f78ceb 100644 --- a/test/unit/math/prim/fun/log2_test.cpp +++ b/test/unit/math/prim/fun/log2_test.cpp @@ -22,3 +22,11 @@ TEST(MathFunctions, log2_nan) { EXPECT_TRUE(std::isnan(stan::math::log2(nan))); } + +TEST(MathFunctions, log2_works_with_other_functions) { + Eigen::VectorXd a(5); + a << 1.1, 1.2, 1.3, 1.4, 1.5; + Eigen::RowVectorXd b(5); + b << 1.1, 1.2, 1.3, 1.4, 1.5; + stan::math::multiply(a, stan::math::log2(b)); +} diff --git a/test/unit/math/prim/fun/log_inv_logit_test.cpp b/test/unit/math/prim/fun/log_inv_logit_test.cpp index 774d044a4dd..bb13d370b2a 100644 --- a/test/unit/math/prim/fun/log_inv_logit_test.cpp +++ b/test/unit/math/prim/fun/log_inv_logit_test.cpp @@ -18,3 +18,11 @@ TEST(MathFunctions, log_inv_logit_nan) { EXPECT_TRUE(std::isnan(stan::math::log_inv_logit(nan))); } + +TEST(MathFunctions, log_inv_logit_works_with_other_functions) { + Eigen::VectorXd a(5); + a << 1.1, 1.2, 1.3, 1.4, 1.5; + Eigen::RowVectorXd b(5); + b << 1.1, 1.2, 1.3, 1.4, 1.5; + stan::math::multiply(a, stan::math::log_inv_logit(b)); +} diff --git a/test/unit/math/prim/fun/log_softmax_test.cpp b/test/unit/math/prim/fun/log_softmax_test.cpp index ba26ba1ce20..eff97db3cd9 100644 --- a/test/unit/math/prim/fun/log_softmax_test.cpp +++ b/test/unit/math/prim/fun/log_softmax_test.cpp @@ -47,3 +47,11 @@ TEST(MathMatrixPrimMat, log_softmax_exception) { EXPECT_THROW(log_softmax(v0), std::invalid_argument); } + +TEST(MathFunctions, log_softmax_works_with_other_functions) { + Eigen::VectorXd a(5); + a << 1.1, 1.2, 1.3, 1.4, 1.5; + Eigen::RowVectorXd b(5); + b << 1.1, 1.2, 1.3, 1.4, 1.5; + stan::math::multiply(a, stan::math::log_softmax(b)); +} diff --git a/test/unit/math/prim/fun/log_test.cpp b/test/unit/math/prim/fun/log_test.cpp index 77563092631..f7163dbcf1a 100644 --- a/test/unit/math/prim/fun/log_test.cpp +++ b/test/unit/math/prim/fun/log_test.cpp @@ -7,3 +7,11 @@ TEST(MathFunctions, logInt) { EXPECT_FLOAT_EQ(std::log(3), log(3)); EXPECT_FLOAT_EQ(std::log(3.0), log(3.0)); } + +TEST(MathFunctions, log_works_with_other_functions) { + Eigen::VectorXd a(5); + a << 1.1, 1.2, 1.3, 1.4, 1.5; + Eigen::RowVectorXd b(5); + b << 1.1, 1.2, 1.3, 1.4, 1.5; + stan::math::multiply(a, stan::math::log(b)); +} diff --git a/test/unit/math/prim/fun/logit_test.cpp b/test/unit/math/prim/fun/logit_test.cpp index b6820aa4b7f..566cbcd88ad 100644 --- a/test/unit/math/prim/fun/logit_test.cpp +++ b/test/unit/math/prim/fun/logit_test.cpp @@ -14,3 +14,11 @@ TEST(MathFunctions, logit_nan) { EXPECT_TRUE(std::isnan(stan::math::logit(nan))); } + +TEST(MathFunctions, logit_works_with_other_functions) { + Eigen::VectorXd a(5); + a << 1.1, 1.2, 1.3, 1.4, 1.5; + Eigen::RowVectorXd b(5); + b << 1.1, 1.2, 1.3, 1.4, 1.5; + stan::math::multiply(a, stan::math::logit(b)); +} diff --git a/test/unit/math/prim/fun/minus_test.cpp b/test/unit/math/prim/fun/minus_test.cpp index e9535ca4781..d3dd9bdad85 100644 --- a/test/unit/math/prim/fun/minus_test.cpp +++ b/test/unit/math/prim/fun/minus_test.cpp @@ -10,3 +10,11 @@ TEST(MathMatrixPrimMat, minus) { EXPECT_EQ(0, stan::math::minus(rv0).size()); EXPECT_EQ(0, stan::math::minus(m0).size()); } + +TEST(MathFunctions, minus_works_with_other_functions) { + Eigen::VectorXd a(5); + a << 1.1, 1.2, 1.3, 1.4, 1.5; + Eigen::RowVectorXd b(5); + b << 1.1, 1.2, 1.3, 1.4, 1.5; + stan::math::multiply(a, stan::math::minus(b)); +} diff --git a/test/unit/math/prim/fun/round_test.cpp b/test/unit/math/prim/fun/round_test.cpp index 40cc1a8334f..3cabf152e67 100644 --- a/test/unit/math/prim/fun/round_test.cpp +++ b/test/unit/math/prim/fun/round_test.cpp @@ -17,3 +17,11 @@ TEST(MathFunctions, roundNaN) { double nan = std::numeric_limits::quiet_NaN(); EXPECT_TRUE(std::isnan(stan::math::round(nan))); } + +TEST(MathFunctions, round_works_with_other_functions) { + Eigen::VectorXd a(5); + a << 1.1, 1.2, 1.3, 1.4, 1.5; + Eigen::RowVectorXd b(5); + b << 1.1, 1.2, 1.3, 1.4, 1.5; + stan::math::multiply(a, stan::math::round(b)); +} diff --git a/test/unit/math/prim/fun/sin_test.cpp b/test/unit/math/prim/fun/sin_test.cpp index 3a564bfea3b..4125f5e22f8 100644 --- a/test/unit/math/prim/fun/sin_test.cpp +++ b/test/unit/math/prim/fun/sin_test.cpp @@ -5,3 +5,11 @@ TEST(primScalFun, sin) { stan::test::expect_common_prim([](auto x) { return std::sin(x); }, [](auto x) { return stan::math::sin(x); }); } + +TEST(MathFunctions, sin_works_with_other_functions) { + Eigen::VectorXd a(5); + a << 1.1, 1.2, 1.3, 1.4, 1.5; + Eigen::RowVectorXd b(5); + b << 1.1, 1.2, 1.3, 1.4, 1.5; + stan::math::multiply(a, stan::math::sin(b)); +} diff --git a/test/unit/math/prim/fun/sinh_test.cpp b/test/unit/math/prim/fun/sinh_test.cpp index 72b18d36f94..72e3f143e5d 100644 --- a/test/unit/math/prim/fun/sinh_test.cpp +++ b/test/unit/math/prim/fun/sinh_test.cpp @@ -5,3 +5,11 @@ TEST(primScalFun, sinh) { stan::test::expect_common_prim([](auto x) { return std::sinh(x); }, [](auto x) { return stan::math::sinh(x); }); } + +TEST(MathFunctions, sinh_works_with_other_functions) { + Eigen::VectorXd a(5); + a << 1.1, 1.2, 1.3, 1.4, 1.5; + Eigen::RowVectorXd b(5); + b << 1.1, 1.2, 1.3, 1.4, 1.5; + stan::math::multiply(a, stan::math::sinh(b)); +} diff --git a/test/unit/math/prim/fun/sqrt_test.cpp b/test/unit/math/prim/fun/sqrt_test.cpp index 43c362d0cc9..9896911dbf5 100644 --- a/test/unit/math/prim/fun/sqrt_test.cpp +++ b/test/unit/math/prim/fun/sqrt_test.cpp @@ -7,3 +7,11 @@ TEST(MathFunctions, sqrtInt) { EXPECT_FLOAT_EQ(std::sqrt(3.0), sqrt(3)); EXPECT_TRUE(stan::math::is_nan(sqrt(-2))); } + +TEST(MathFunctions, sqrt_works_with_other_functions) { + Eigen::VectorXd a(5); + a << 1.1, 1.2, 1.3, 1.4, 1.5; + Eigen::RowVectorXd b(5); + b << 1.1, 1.2, 1.3, 1.4, 1.5; + stan::math::multiply(a, stan::math::sqrt(b)); +} diff --git a/test/unit/math/prim/fun/square_test.cpp b/test/unit/math/prim/fun/square_test.cpp index aadd3009906..13b66189bcf 100644 --- a/test/unit/math/prim/fun/square_test.cpp +++ b/test/unit/math/prim/fun/square_test.cpp @@ -3,7 +3,7 @@ #include #include -TEST(MathsFunctions, square) { +TEST(MathFunctions, square) { double y = 2.0; EXPECT_FLOAT_EQ(y * y, stan::math::square(y)); @@ -19,3 +19,11 @@ TEST(MathFunctions, square_nan) { EXPECT_TRUE(std::isnan(stan::math::square(nan))); } + +TEST(MathFunctions, square_works_with_other_functions) { + Eigen::VectorXd a(5); + a << 1.1, 1.2, 1.3, 1.4, 1.5; + Eigen::RowVectorXd b(5); + b << 1.1, 1.2, 1.3, 1.4, 1.5; + stan::math::multiply(a, stan::math::square(b)); +} diff --git a/test/unit/math/prim/fun/tan_test.cpp b/test/unit/math/prim/fun/tan_test.cpp new file mode 100644 index 00000000000..5b9e861cabc --- /dev/null +++ b/test/unit/math/prim/fun/tan_test.cpp @@ -0,0 +1,10 @@ +#include +#include + +TEST(MathFunctions, tan_works_with_other_functions) { + Eigen::VectorXd a(5); + a << 1.1, 1.2, 1.3, 1.4, 1.5; + Eigen::RowVectorXd b(5); + b << 1.1, 1.2, 1.3, 1.4, 1.5; + stan::math::multiply(a, stan::math::tan(b)); +} diff --git a/test/unit/math/prim/fun/tanh_test.cpp b/test/unit/math/prim/fun/tanh_test.cpp index bd4da5755c9..594d0e37ed5 100644 --- a/test/unit/math/prim/fun/tanh_test.cpp +++ b/test/unit/math/prim/fun/tanh_test.cpp @@ -5,3 +5,11 @@ TEST(primScalFun, tanh) { stan::test::expect_common_prim([](auto x) { return std::tanh(x); }, [](auto x) { return stan::math::tanh(x); }); } + +TEST(MathFunctions, tanh_works_with_other_functions) { + Eigen::VectorXd a(5); + a << 1.1, 1.2, 1.3, 1.4, 1.5; + Eigen::RowVectorXd b(5); + b << 1.1, 1.2, 1.3, 1.4, 1.5; + stan::math::multiply(a, stan::math::tanh(b)); +} diff --git a/test/unit/math/prim/fun/tgamma_test.cpp b/test/unit/math/prim/fun/tgamma_test.cpp index 51e5b84261c..2ecb0bd51cc 100644 --- a/test/unit/math/prim/fun/tgamma_test.cpp +++ b/test/unit/math/prim/fun/tgamma_test.cpp @@ -20,3 +20,11 @@ TEST(MathFunctions, tgamma_nan) { double nan = std::numeric_limits::quiet_NaN(); EXPECT_TRUE(std::isnan(stan::math::tgamma(nan))); } + +TEST(MathFunctions, tgamma_works_with_other_functions) { + Eigen::VectorXd a(5); + a << 1.1, 1.2, 1.3, 1.4, 1.5; + Eigen::RowVectorXd b(5); + b << 1.1, 1.2, 1.3, 1.4, 1.5; + stan::math::multiply(a, stan::math::tgamma(b)); +} diff --git a/test/unit/math/prim/fun/trigamma_test.cpp b/test/unit/math/prim/fun/trigamma_test.cpp index d2066598d32..c2d4484d1f0 100644 --- a/test/unit/math/prim/fun/trigamma_test.cpp +++ b/test/unit/math/prim/fun/trigamma_test.cpp @@ -17,3 +17,11 @@ TEST(MathFunctions, trigamma_nan) { EXPECT_TRUE(std::isnan(stan::math::trigamma(nan))); } + +TEST(MathFunctions, trigamma_works_with_other_functions) { + Eigen::VectorXd a(5); + a << 1.1, 1.2, 1.3, 1.4, 1.5; + Eigen::RowVectorXd b(5); + b << 1.1, 1.2, 1.3, 1.4, 1.5; + stan::math::multiply(a, stan::math::trigamma(b)); +} diff --git a/test/unit/math/prim/fun/trunc_test.cpp b/test/unit/math/prim/fun/trunc_test.cpp index 8aa3a7c6a00..2f64da18b03 100644 --- a/test/unit/math/prim/fun/trunc_test.cpp +++ b/test/unit/math/prim/fun/trunc_test.cpp @@ -17,3 +17,11 @@ TEST(MathFunctions, truncNaN) { double nan = std::numeric_limits::quiet_NaN(); EXPECT_TRUE(std::isnan(stan::math::trunc(nan))); } + +TEST(MathFunctions, trunc_works_with_other_functions) { + Eigen::VectorXd a(5); + a << 1.1, 1.2, 1.3, 1.4, 1.5; + Eigen::RowVectorXd b(5); + b << 1.1, 1.2, 1.3, 1.4, 1.5; + stan::math::multiply(a, stan::math::trunc(b)); +} From a5d71b29fea3a93256cbec1312d4400eb535b9a9 Mon Sep 17 00:00:00 2001 From: rok-cesnovar Date: Thu, 30 Jan 2020 08:25:03 +0100 Subject: [PATCH 011/355] Fixed conflict in stan/math/prim/fun/log_softmax.hpp --- stan/math/prim/fun/log_softmax.hpp | 11 +++++------ test/unit/math/prim/fun/log_softmax_test.cpp | 8 -------- 2 files changed, 5 insertions(+), 14 deletions(-) diff --git a/stan/math/prim/fun/log_softmax.hpp b/stan/math/prim/fun/log_softmax.hpp index 8c4951df779..a51370d0b1a 100644 --- a/stan/math/prim/fun/log_softmax.hpp +++ b/stan/math/prim/fun/log_softmax.hpp @@ -36,12 +36,11 @@ namespace math { * @param[in] v Vector to transform. * @return Unit simplex result of the softmax transform of the vector. */ -template >>...> -inline auto log_softmax(const T& x) { - return apply_vector_unary::apply(x, [&](const auto& v) { - check_nonzero_size("log_softmax", "v", v); - return (v.array() - log_sum_exp(v)).matrix().eval(); - }); +template +inline Eigen::Matrix log_softmax( + const Eigen::Matrix& v) { + check_nonzero_size("log_softmax", "v", v); + return v.array() - log_sum_exp(v); } } // namespace math diff --git a/test/unit/math/prim/fun/log_softmax_test.cpp b/test/unit/math/prim/fun/log_softmax_test.cpp index eff97db3cd9..ba26ba1ce20 100644 --- a/test/unit/math/prim/fun/log_softmax_test.cpp +++ b/test/unit/math/prim/fun/log_softmax_test.cpp @@ -47,11 +47,3 @@ TEST(MathMatrixPrimMat, log_softmax_exception) { EXPECT_THROW(log_softmax(v0), std::invalid_argument); } - -TEST(MathFunctions, log_softmax_works_with_other_functions) { - Eigen::VectorXd a(5); - a << 1.1, 1.2, 1.3, 1.4, 1.5; - Eigen::RowVectorXd b(5); - b << 1.1, 1.2, 1.3, 1.4, 1.5; - stan::math::multiply(a, stan::math::log_softmax(b)); -} From e081b4ee12f00f21b99eaeee36d9c72f6f4540fa Mon Sep 17 00:00:00 2001 From: Nicusor Serban Date: Thu, 30 Jan 2020 10:33:34 +0200 Subject: [PATCH 012/355] Release v3.1.1 --- .github/ISSUE_TEMPLATE.md | 2 +- doxygen/doxygen.cfg | 2 +- stan/math/version.hpp | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/ISSUE_TEMPLATE.md b/.github/ISSUE_TEMPLATE.md index 0e35de62263..8f112ab89d3 100644 --- a/.github/ISSUE_TEMPLATE.md +++ b/.github/ISSUE_TEMPLATE.md @@ -25,4 +25,4 @@ If this is a **feature request**, show what you expect to happen if the feature #### Current Version: -v3.1.0 +v3.1.1 diff --git a/doxygen/doxygen.cfg b/doxygen/doxygen.cfg index 8fee6f17d59..e4b5060f7d0 100644 --- a/doxygen/doxygen.cfg +++ b/doxygen/doxygen.cfg @@ -38,7 +38,7 @@ PROJECT_NAME = "Stan Math Library" # could be handy for archiving the generated documentation or if some version # control system is used. -PROJECT_NUMBER = 3.1.0 +PROJECT_NUMBER = 3.1.1 # 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 diff --git a/stan/math/version.hpp b/stan/math/version.hpp index bf8599edc07..d5ba5648855 100644 --- a/stan/math/version.hpp +++ b/stan/math/version.hpp @@ -13,7 +13,7 @@ #define STAN_MATH_MAJOR 3 #define STAN_MATH_MINOR 1 -#define STAN_MATH_PATCH 0 +#define STAN_MATH_PATCH 1 namespace stan { namespace math { From ebbfeb8eb6f25223396733bcd3a58bbdfd7517d5 Mon Sep 17 00:00:00 2001 From: Steve Bronder Date: Wed, 27 May 2020 23:12:27 -0400 Subject: [PATCH 013/355] Adds templates to vari and var as well as the var operators. Fixes std::numeric_limits so that it conforms to the C++11 definition --- .gitignore | 3 + stan/math/prim/fun/mdivide_right_ldlt.hpp | 11 +- .../prim/fun/scale_matrix_exp_multiply.hpp | 4 +- stan/math/prim/meta.hpp | 1 + stan/math/prim/meta/is_var.hpp | 7 + stan/math/prim/meta/is_vari.hpp | 19 ++ stan/math/rev/core/chainablestack.hpp | 4 +- stan/math/rev/core/grad.hpp | 4 +- stan/math/rev/core/matrix_vari.hpp | 2 +- stan/math/rev/core/operator_addition.hpp | 10 +- stan/math/rev/core/operator_divide_equal.hpp | 9 +- stan/math/rev/core/operator_division.hpp | 8 +- stan/math/rev/core/operator_equal.hpp | 10 +- stan/math/rev/core/operator_greater_than.hpp | 10 +- .../core/operator_greater_than_or_equal.hpp | 10 +- stan/math/rev/core/operator_less_than.hpp | 10 +- .../rev/core/operator_less_than_or_equal.hpp | 10 +- stan/math/rev/core/operator_logical_and.hpp | 10 +- stan/math/rev/core/operator_logical_or.hpp | 10 +- stan/math/rev/core/operator_minus_equal.hpp | 9 +- .../math/rev/core/operator_multiplication.hpp | 10 +- .../math/rev/core/operator_multiply_equal.hpp | 9 +- stan/math/rev/core/operator_not_equal.hpp | 10 +- stan/math/rev/core/operator_plus_equal.hpp | 9 +- stan/math/rev/core/operator_subtraction.hpp | 10 +- .../math/rev/core/operator_unary_negative.hpp | 2 +- stan/math/rev/core/operator_unary_not.hpp | 2 +- stan/math/rev/core/operator_unary_plus.hpp | 2 +- stan/math/rev/core/std_iterator_traits.hpp | 11 +- stan/math/rev/core/std_numeric_limits.hpp | 87 +++--- stan/math/rev/core/var.hpp | 277 +++++++----------- stan/math/rev/core/vari.hpp | 119 ++++++-- stan/math/rev/core/vector_vari.hpp | 4 +- stan/math/rev/fun/value_of.hpp | 3 +- stan/math/rev/fun/value_of_rec.hpp | 3 +- stan/math/rev/meta.hpp | 1 + stan/math/rev/meta/is_var.hpp | 14 +- stan/math/rev/meta/is_vari.hpp | 21 ++ stan/math/rev/meta/partials_type.hpp | 2 +- test/unit/math/rev/core/var_test.cpp | 110 +++---- test/unit/math/rev/core/vari_test.cpp | 7 + test/unit/pretty_print_types.hpp | 4 +- 42 files changed, 481 insertions(+), 397 deletions(-) create mode 100644 stan/math/prim/meta/is_vari.hpp create mode 100644 stan/math/rev/meta/is_vari.hpp diff --git a/.gitignore b/.gitignore index 70b24de41cb..4e157904b86 100644 --- a/.gitignore +++ b/.gitignore @@ -89,3 +89,6 @@ compile_commands.json # Ignore things made with tbb lib/tbb/** + +# gdb +.gdb_history diff --git a/stan/math/prim/fun/mdivide_right_ldlt.hpp b/stan/math/prim/fun/mdivide_right_ldlt.hpp index ec801f9c4b6..422f41321a5 100644 --- a/stan/math/prim/fun/mdivide_right_ldlt.hpp +++ b/stan/math/prim/fun/mdivide_right_ldlt.hpp @@ -25,7 +25,7 @@ namespace math { */ template * = nullptr, - require_any_not_vt_same* = nullptr> + require_any_not_arithmetic_t, T>* = nullptr> inline Eigen::Matrix, EigMat::RowsAtCompileTime, C> mdivide_right_ldlt(const EigMat& b, const LDLT_factor& A) { check_multiplicable("mdivide_right_ldlt", "b", b, "A", A); @@ -36,10 +36,11 @@ mdivide_right_ldlt(const EigMat& b, const LDLT_factor& A) { return transpose(mdivide_left_ldlt(A, transpose(b))); } -template * = nullptr, - require_vt_same* = nullptr> -inline Eigen::Matrix mdivide_right_ldlt( - const EigMat& b, const LDLT_factor& A) { +template * = nullptr, + require_all_arithmetic_t, T>* = nullptr> +inline Eigen::Matrix mdivide_right_ldlt( + const EigMat& b, const LDLT_factor& A) { check_multiplicable("mdivide_right_ldlt", "b", b, "A", A); if (A.rows() == 0) { return {b.rows(), 0}; diff --git a/stan/math/prim/fun/scale_matrix_exp_multiply.hpp b/stan/math/prim/fun/scale_matrix_exp_multiply.hpp index 1c025d7d47d..577248b9b05 100644 --- a/stan/math/prim/fun/scale_matrix_exp_multiply.hpp +++ b/stan/math/prim/fun/scale_matrix_exp_multiply.hpp @@ -26,7 +26,7 @@ namespace math { */ template * = nullptr, - require_all_vt_same* = nullptr> + require_all_same_t, value_type_t>* = nullptr> inline Eigen::Matrix scale_matrix_exp_multiply(const double& t, const EigMat1& A, const EigMat2& B) { check_square("scale_matrix_exp_multiply", "input matrix", A); @@ -54,7 +54,7 @@ scale_matrix_exp_multiply(const double& t, const EigMat1& A, const EigMat2& B) { */ template * = nullptr, - require_any_not_vt_same* = nullptr> + require_any_not_same_t, value_type_t>* = nullptr> inline Eigen::Matrix, Eigen::Dynamic, EigMat2::ColsAtCompileTime> scale_matrix_exp_multiply(const Tt& t, const EigMat1& A, const EigMat2& B) { diff --git a/stan/math/prim/meta.hpp b/stan/math/prim/meta.hpp index 25a3baca8de..4e0f966f848 100644 --- a/stan/math/prim/meta.hpp +++ b/stan/math/prim/meta.hpp @@ -193,6 +193,7 @@ #include #include #include +#include #include #include #include diff --git a/stan/math/prim/meta/is_var.hpp b/stan/math/prim/meta/is_var.hpp index e9315a5ffb3..db87cc9e2ee 100644 --- a/stan/math/prim/meta/is_var.hpp +++ b/stan/math/prim/meta/is_var.hpp @@ -14,7 +14,14 @@ template struct is_var : std::false_type {}; STAN_ADD_REQUIRE_UNARY(var, is_var, require_stan_scalar_real); +STAN_ADD_REQUIRE_CONTAINER(var, is_var, require_stan_scalar_real); STAN_ADD_REQUIRE_UNARY_INNER(var, is_var, require_stan_scalar_real); + +template +struct value_type::value>> { + using type = typename std::decay_t::value_type; +}; + } // namespace stan #endif diff --git a/stan/math/prim/meta/is_vari.hpp b/stan/math/prim/meta/is_vari.hpp new file mode 100644 index 00000000000..db82abbf9a9 --- /dev/null +++ b/stan/math/prim/meta/is_vari.hpp @@ -0,0 +1,19 @@ +#ifndef STAN_MATH_PRIM_META_IS_VARI_HPP +#define STAN_MATH_PRIM_META_IS_VARI_HPP + +#include + +namespace stan { +/** \ingroup type_trait + * Specialization for checking if value of T minus cv qualifier and pointer is a + * vari. + */ +template +struct is_vari : std::false_type {}; + +STAN_ADD_REQUIRE_UNARY(vari, is_vari, require_stan_scalar_real); +STAN_ADD_REQUIRE_CONTAINER(vari, is_vari, require_stan_scalar_real); + + +} // namespace stan +#endif diff --git a/stan/math/rev/core/chainablestack.hpp b/stan/math/rev/core/chainablestack.hpp index 92b18fe023e..57d49da3dbc 100644 --- a/stan/math/rev/core/chainablestack.hpp +++ b/stan/math/rev/core/chainablestack.hpp @@ -6,10 +6,10 @@ namespace stan { namespace math { -class vari; +class vari_base; class chainable_alloc; -using ChainableStack = AutodiffStackSingleton; +using ChainableStack = AutodiffStackSingleton; } // namespace math } // namespace stan diff --git a/stan/math/rev/core/grad.hpp b/stan/math/rev/core/grad.hpp index 01b3b153fcc..6e5f56c2287 100644 --- a/stan/math/rev/core/grad.hpp +++ b/stan/math/rev/core/grad.hpp @@ -27,9 +27,9 @@ namespace math { * @param vi Variable implementation for root of partial * derivative propagation. */ -static void grad(vari* vi) { +static void grad(vari_base* vi) { vi->init_dependent(); - std::vector& var_stack = ChainableStack::instance_->var_stack_; + std::vector& var_stack = ChainableStack::instance_->var_stack_; size_t end = var_stack.size(); size_t beginning = empty_nested() ? 0 : end - nested_size(); for (size_t i = end; i-- > beginning;) { diff --git a/stan/math/rev/core/matrix_vari.hpp b/stan/math/rev/core/matrix_vari.hpp index c9dcc4eb54b..69aa4a96068 100644 --- a/stan/math/rev/core/matrix_vari.hpp +++ b/stan/math/rev/core/matrix_vari.hpp @@ -17,7 +17,7 @@ class op_matrix_vari : public vari { vari** vis_; public: - template ...> + template * = nullptr> op_matrix_vari(double f, const T& vs) : vari(f), size_(vs.size()) { vis_ = ChainableStack::instance_->memalloc_.alloc_array(size_); Eigen::Map>(vis_, vs.rows(), vs.cols()) diff --git a/stan/math/rev/core/operator_addition.hpp b/stan/math/rev/core/operator_addition.hpp index 67b595a192b..190958f8301 100644 --- a/stan/math/rev/core/operator_addition.hpp +++ b/stan/math/rev/core/operator_addition.hpp @@ -78,7 +78,7 @@ class add_vd_vari : public op_vd_vari { * @param b Second variable operand. * @return Variable result of adding two variables. */ -inline var operator+(var a, var b) { +inline var operator+(const var& a, const var& b) { return {new internal::add_vv_vari(a.vi_, b.vi_)}; } @@ -94,8 +94,8 @@ inline var operator+(var a, var b) { * @param b Second scalar operand. * @return Result of adding variable and scalar. */ -template ...> -inline var operator+(var a, Arith b) { +template * = nullptr> +inline var operator+(const var& a, Arith b) { if (b == 0.0) { return a; } @@ -114,8 +114,8 @@ inline var operator+(var a, Arith b) { * @param b Second variable operand. * @return Result of adding variable and scalar. */ -template ...> -inline var operator+(Arith a, var b) { +template * = nullptr> +inline var operator+(Arith a, const var& b) { if (a == 0.0) { return b; } diff --git a/stan/math/rev/core/operator_divide_equal.hpp b/stan/math/rev/core/operator_divide_equal.hpp index 88289b8ce67..531ee676004 100644 --- a/stan/math/rev/core/operator_divide_equal.hpp +++ b/stan/math/rev/core/operator_divide_equal.hpp @@ -7,13 +7,16 @@ namespace stan { namespace math { -inline var& var::operator/=(var b) { +template +template >*> +inline var_value& var_value::operator/=(const var_value& b) { vi_ = new internal::divide_vv_vari(vi_, b.vi_); return *this; } -template ...> -inline var& var::operator/=(Arith b) { +template +template *> +inline var_value& var_value::operator/=(Arith b) { if (b == 1.0) { return *this; } diff --git a/stan/math/rev/core/operator_division.hpp b/stan/math/rev/core/operator_division.hpp index 420ec04d07d..69770cb15cc 100644 --- a/stan/math/rev/core/operator_division.hpp +++ b/stan/math/rev/core/operator_division.hpp @@ -115,8 +115,8 @@ inline var operator/(var dividend, var divisor) { * @param divisor Scalar operand. * @return Variable result of dividing the variable by the scalar. */ -template ...> -inline var operator/(var dividend, Arith divisor) { +template * = nullptr> +inline var operator/(const var& dividend, Arith divisor) { if (divisor == 1.0) { return dividend; } @@ -135,8 +135,8 @@ inline var operator/(var dividend, Arith divisor) { * @param divisor Variable operand. * @return Quotient of the dividend and divisor. */ -template ...> -inline var operator/(Arith dividend, var divisor) { +template * = nullptr> +inline var operator/(Arith dividend, const var& divisor) { return {new internal::divide_dv_vari(dividend, divisor.vi_)}; } diff --git a/stan/math/rev/core/operator_equal.hpp b/stan/math/rev/core/operator_equal.hpp index 1f123ac1da4..28140c8b484 100644 --- a/stan/math/rev/core/operator_equal.hpp +++ b/stan/math/rev/core/operator_equal.hpp @@ -24,7 +24,7 @@ namespace math { * @return True if the first variable's value is the same as the * second's. */ -inline bool operator==(var a, var b) { return a.val() == b.val(); } +inline bool operator==(const var& a, const var& b) { return a.val() == b.val(); } /** * Equality operator comparing a variable's value and a double @@ -36,8 +36,8 @@ inline bool operator==(var a, var b) { return a.val() == b.val(); } * @return True if the first variable's value is the same as the * second value. */ -template ...> -inline bool operator==(var a, Arith b) { +template * = nullptr> +inline bool operator==(const var& a, Arith b) { return a.val() == b; } @@ -50,8 +50,8 @@ inline bool operator==(var a, Arith b) { * @param b Second variable. * @return True if the variable's value is equal to the scalar. */ -template ...> -inline bool operator==(Arith a, var b) { +template * = nullptr> +inline bool operator==(Arith a, const var& b) { return a == b.val(); } diff --git a/stan/math/rev/core/operator_greater_than.hpp b/stan/math/rev/core/operator_greater_than.hpp index c0e07372562..bbffa4f4948 100644 --- a/stan/math/rev/core/operator_greater_than.hpp +++ b/stan/math/rev/core/operator_greater_than.hpp @@ -23,7 +23,7 @@ namespace math { * @param b Second variable. * @return True if first variable's value is greater than second's. */ -inline bool operator>(var a, var b) { return a.val() > b.val(); } +inline bool operator>(const var& a, const var& b) { return a.val() > b.val(); } /** * Greater than operator comparing variable's value and double @@ -34,8 +34,8 @@ inline bool operator>(var a, var b) { return a.val() > b.val(); } * @param b Second value. * @return True if first variable's value is greater than second value. */ -template ...> -inline bool operator>(var a, Arith b) { +template * = nullptr> +inline bool operator>(const var& a, Arith b) { return a.val() > b; } @@ -48,8 +48,8 @@ inline bool operator>(var a, Arith b) { * @param b Second variable. * @return True if first value is greater than second variable's value. */ -template ...> -inline bool operator>(Arith a, var b) { +template * = nullptr> +inline bool operator>(Arith a, const var& b) { return a > b.val(); } diff --git a/stan/math/rev/core/operator_greater_than_or_equal.hpp b/stan/math/rev/core/operator_greater_than_or_equal.hpp index d8c1a4619b2..356816f84c1 100644 --- a/stan/math/rev/core/operator_greater_than_or_equal.hpp +++ b/stan/math/rev/core/operator_greater_than_or_equal.hpp @@ -25,7 +25,7 @@ namespace math { * @return True if first variable's value is greater than or equal * to the second's. */ -inline bool operator>=(var a, var b) { return a.val() >= b.val(); } +inline bool operator>=(const var& a, const var& b) { return a.val() >= b.val(); } /** * Greater than or equal operator comparing variable's value and @@ -37,8 +37,8 @@ inline bool operator>=(var a, var b) { return a.val() >= b.val(); } * @return True if first variable's value is greater than or equal * to second value. */ -template ...> -inline bool operator>=(var a, Arith b) { +template * = nullptr> +inline bool operator>=(const var& a, Arith b) { return a.val() >= b; } @@ -52,8 +52,8 @@ inline bool operator>=(var a, Arith b) { * @return True if the first value is greater than or equal to the * second variable's value. */ -template ...> -inline bool operator>=(Arith a, var b) { +template * = nullptr> +inline bool operator>=(Arith a, const var& b) { return a >= b.val(); } diff --git a/stan/math/rev/core/operator_less_than.hpp b/stan/math/rev/core/operator_less_than.hpp index 7157c504759..387ec114f0c 100644 --- a/stan/math/rev/core/operator_less_than.hpp +++ b/stan/math/rev/core/operator_less_than.hpp @@ -22,7 +22,7 @@ namespace math { * @param b Second variable. * @return True if first variable's value is less than second's. */ -inline bool operator<(var a, var b) { return a.val() < b.val(); } +inline bool operator<(const var& a, const var& b) { return a.val() < b.val(); } /** * Less than operator comparing variable's value and a double @@ -33,8 +33,8 @@ inline bool operator<(var a, var b) { return a.val() < b.val(); } * @param b Second value. * @return True if first variable's value is less than second value. */ -template ...> -inline bool operator<(var a, Arith b) { +template * = nullptr> +inline bool operator<(const var& a, Arith b) { return a.val() < b; } @@ -47,8 +47,8 @@ inline bool operator<(var a, Arith b) { * @param b Second variable. * @return True if first value is less than second variable's value. */ -template ...> -inline bool operator<(Arith a, var b) { +template * = nullptr> +inline bool operator<(Arith a, const var& b) { return a < b.val(); } diff --git a/stan/math/rev/core/operator_less_than_or_equal.hpp b/stan/math/rev/core/operator_less_than_or_equal.hpp index e45c6e022b4..a5a50f8975c 100644 --- a/stan/math/rev/core/operator_less_than_or_equal.hpp +++ b/stan/math/rev/core/operator_less_than_or_equal.hpp @@ -24,7 +24,7 @@ namespace math { * @return True if first variable's value is less than or equal to * the second's. */ -inline bool operator<=(var a, var b) { return a.val() <= b.val(); } +inline bool operator<=(const var& a, const var& b) { return a.val() <= b.val(); } /** * Less than or equal operator comparing a variable's value and a @@ -36,8 +36,8 @@ inline bool operator<=(var a, var b) { return a.val() <= b.val(); } * @return True if first variable's value is less than or equal to * the second value. */ -template ...> -inline bool operator<=(var a, Arith b) { +template * = nullptr> +inline bool operator<=(const var& a, Arith b) { return a.val() <= b; } @@ -51,8 +51,8 @@ inline bool operator<=(var a, Arith b) { * @return True if first value is less than or equal to the second * variable's value. */ -template ...> -inline bool operator<=(Arith a, var b) { +template * = nullptr> +inline bool operator<=(Arith a, const var& b) { return a <= b.val(); } diff --git a/stan/math/rev/core/operator_logical_and.hpp b/stan/math/rev/core/operator_logical_and.hpp index 66360dd19ea..80cf247186d 100644 --- a/stan/math/rev/core/operator_logical_and.hpp +++ b/stan/math/rev/core/operator_logical_and.hpp @@ -15,7 +15,7 @@ namespace math { * @param[in] y second argument * @return conjunction of the arguments' values */ -inline bool operator&&(var x, var y) { return x.val() && y.val(); } +inline bool operator&&(const var& x, const var& y) { return x.val() && y.val(); } /** * Return the logical conjunction of the values of the two @@ -28,8 +28,8 @@ inline bool operator&&(var x, var y) { return x.val() && y.val(); } * @return conjunction of first argument's value and second * argument */ -template ...> -inline bool operator&&(var x, Arith y) { +template * = nullptr> +inline bool operator&&(const var& x, Arith y) { return x.val() && y; } @@ -44,8 +44,8 @@ inline bool operator&&(var x, Arith y) { * @return conjunction of first argument and second argument's * value */ -template ...> -inline bool operator&&(Arith x, var y) { +template * = nullptr> +inline bool operator&&(Arith x, const var& y) { return x && y.val(); } diff --git a/stan/math/rev/core/operator_logical_or.hpp b/stan/math/rev/core/operator_logical_or.hpp index 6aaf35b31df..a4f1f8ab14c 100644 --- a/stan/math/rev/core/operator_logical_or.hpp +++ b/stan/math/rev/core/operator_logical_or.hpp @@ -15,7 +15,7 @@ namespace math { * @param[in] y second argument * @return disjunction of the arguments' values */ -inline bool operator||(var x, var y) { return x.val() || y.val(); } +inline bool operator||(const var& x, const var& y) { return x.val() || y.val(); } /** * Return the logical disjunction of the values of the two @@ -27,8 +27,8 @@ inline bool operator||(var x, var y) { return x.val() || y.val(); } * @return disjunction of first argument's value and second * argument */ -template ...> -inline bool operator||(var x, Arith y) { +template * = nullptr> +inline bool operator||(const var& x, Arith y) { return x.val() || y; } @@ -42,8 +42,8 @@ inline bool operator||(var x, Arith y) { * @return disjunction of first argument and the second * argument's value */ -template ...> -inline bool operator||(Arith x, var y) { +template * = nullptr> +inline bool operator||(Arith x, const var& y) { return x || y.val(); } diff --git a/stan/math/rev/core/operator_minus_equal.hpp b/stan/math/rev/core/operator_minus_equal.hpp index 30cd5f2b299..3990c103f8b 100644 --- a/stan/math/rev/core/operator_minus_equal.hpp +++ b/stan/math/rev/core/operator_minus_equal.hpp @@ -8,13 +8,16 @@ namespace stan { namespace math { -inline var& var::operator-=(var b) { +template +template >*> +inline var_value& var_value::operator-=(const var_value& b) { vi_ = new internal::subtract_vv_vari(vi_, b.vi_); return *this; } -template ...> -inline var& var::operator-=(Arith b) { +template +template *> +inline var_value& var_value::operator-=(Arith b) { if (b == 0.0) { return *this; } diff --git a/stan/math/rev/core/operator_multiplication.hpp b/stan/math/rev/core/operator_multiplication.hpp index 080e0831feb..12744038693 100644 --- a/stan/math/rev/core/operator_multiplication.hpp +++ b/stan/math/rev/core/operator_multiplication.hpp @@ -79,7 +79,7 @@ class multiply_vd_vari : public op_vd_vari { * @param b Second variable operand. * @return Variable result of multiplying operands. */ -inline var operator*(var a, var b) { +inline var operator*(const var& a, const var& b) { return {new internal::multiply_vv_vari(a.vi_, b.vi_)}; } @@ -95,8 +95,8 @@ inline var operator*(var a, var b) { * @param b Scalar operand. * @return Variable result of multiplying operands. */ -template ...> -inline var operator*(var a, Arith b) { +template * = nullptr> +inline var operator*(const var& a, Arith b) { if (b == 1.0) { return a; } @@ -115,8 +115,8 @@ inline var operator*(var a, Arith b) { * @param b Variable operand. * @return Variable result of multiplying the operands. */ -template ...> -inline var operator*(Arith a, var b) { +template * = nullptr> +inline var operator*(Arith a, const var& b) { if (a == 1.0) { return b; } diff --git a/stan/math/rev/core/operator_multiply_equal.hpp b/stan/math/rev/core/operator_multiply_equal.hpp index 3426d203040..302af7d612f 100644 --- a/stan/math/rev/core/operator_multiply_equal.hpp +++ b/stan/math/rev/core/operator_multiply_equal.hpp @@ -8,13 +8,16 @@ namespace stan { namespace math { -inline var& var::operator*=(var b) { +template +template >*> +inline var_value& var_value::operator*=(const var_value& b) { vi_ = new internal::multiply_vv_vari(vi_, b.vi_); return *this; } -template ...> -inline var& var::operator*=(Arith b) { +template +template *> +inline var_value& var_value::operator*=(Arith b) { if (b == 1.0) { return *this; } diff --git a/stan/math/rev/core/operator_not_equal.hpp b/stan/math/rev/core/operator_not_equal.hpp index 9a5148294fe..d7591eacfbb 100644 --- a/stan/math/rev/core/operator_not_equal.hpp +++ b/stan/math/rev/core/operator_not_equal.hpp @@ -27,7 +27,7 @@ namespace math { * @return True if the first variable's value is not the same as the * second's. */ -inline bool operator!=(var a, var b) { return a.val() != b.val(); } +inline bool operator!=(const var& a, const var& b) { return a.val() != b.val(); } /** * Inequality operator comparing a variable's value and a double @@ -39,8 +39,8 @@ inline bool operator!=(var a, var b) { return a.val() != b.val(); } * @return True if the first variable's value is not the same as the * second value. */ -template ...> -inline bool operator!=(var a, Arith b) { +template * = nullptr> +inline bool operator!=(const var& a, Arith b) { return a.val() != b; } @@ -54,8 +54,8 @@ inline bool operator!=(var a, Arith b) { * @return True if the first value is not the same as the * second variable's value. */ -template ...> -inline bool operator!=(Arith a, var b) { +template * = nullptr> +inline bool operator!=(Arith a, const var& b) { return a != b.val(); } diff --git a/stan/math/rev/core/operator_plus_equal.hpp b/stan/math/rev/core/operator_plus_equal.hpp index cd629637bdd..85d91100d78 100644 --- a/stan/math/rev/core/operator_plus_equal.hpp +++ b/stan/math/rev/core/operator_plus_equal.hpp @@ -8,13 +8,16 @@ namespace stan { namespace math { -inline var& var::operator+=(var b) { +template +template >*> +inline var_value& var_value::operator+=(const var_value& b) { vi_ = new internal::add_vv_vari(vi_, b.vi_); return *this; } -template ...> -inline var& var::operator+=(Arith b) { +template +template *> +inline var_value& var_value::operator+=(Arith b) { if (b == 0.0) { return *this; } diff --git a/stan/math/rev/core/operator_subtraction.hpp b/stan/math/rev/core/operator_subtraction.hpp index 6eb66f4f690..eb4319e5f03 100644 --- a/stan/math/rev/core/operator_subtraction.hpp +++ b/stan/math/rev/core/operator_subtraction.hpp @@ -93,7 +93,7 @@ class subtract_dv_vari : public op_dv_vari { * @return Variable result of subtracting the second variable from * the first. */ -inline var operator-(var a, var b) { +inline var operator-(const var& a, const var& b) { return {new internal::subtract_vv_vari(a.vi_, b.vi_)}; } @@ -110,8 +110,8 @@ inline var operator-(var a, var b) { * @param b Second scalar operand. * @return Result of subtracting the scalar from the variable. */ -template ...> -inline var operator-(var a, Arith b) { +template * = nullptr> +inline var operator-(const var& a, Arith b) { if (b == 0.0) { return a; } @@ -131,8 +131,8 @@ inline var operator-(var a, Arith b) { * @param b Second variable operand. * @return Result of subtracting a variable from a scalar. */ -template ...> -inline var operator-(Arith a, var b) { +template * = nullptr> +inline var operator-(Arith a, const var& b) { return {new internal::subtract_dv_vari(a, b.vi_)}; } diff --git a/stan/math/rev/core/operator_unary_negative.hpp b/stan/math/rev/core/operator_unary_negative.hpp index 250ccc0f5a9..3b294f2250d 100644 --- a/stan/math/rev/core/operator_unary_negative.hpp +++ b/stan/math/rev/core/operator_unary_negative.hpp @@ -48,7 +48,7 @@ class neg_vari : public op_v_vari { * @param a Argument variable. * @return Negation of variable. */ -inline var operator-(var a) { return {new internal::neg_vari(a.vi_)}; } +inline var operator-(const var& a) { return {new internal::neg_vari(a.vi_)}; } } // namespace math } // namespace stan diff --git a/stan/math/rev/core/operator_unary_not.hpp b/stan/math/rev/core/operator_unary_not.hpp index 6a1f58d59c0..aa0234504ee 100644 --- a/stan/math/rev/core/operator_unary_not.hpp +++ b/stan/math/rev/core/operator_unary_not.hpp @@ -14,7 +14,7 @@ namespace math { * @param[in] x argument * @return negation of argument value */ -inline bool operator!(var x) { return !x.val(); } +inline bool operator!(const var& x) { return !x.val(); } } // namespace math } // namespace stan diff --git a/stan/math/rev/core/operator_unary_plus.hpp b/stan/math/rev/core/operator_unary_plus.hpp index e48685f4965..f2a1fe8e45b 100644 --- a/stan/math/rev/core/operator_unary_plus.hpp +++ b/stan/math/rev/core/operator_unary_plus.hpp @@ -41,7 +41,7 @@ namespace math { * @param a Argument variable. * @return The input reference. */ -inline var operator+(var a) { +inline var operator+(const var& a) { if (unlikely(is_nan(a.vi_->val_))) { return {new precomp_v_vari(NOT_A_NUMBER, a.vi_, NOT_A_NUMBER)}; } diff --git a/stan/math/rev/core/std_iterator_traits.hpp b/stan/math/rev/core/std_iterator_traits.hpp index 2bcda5ad91f..9194128965c 100644 --- a/stan/math/rev/core/std_iterator_traits.hpp +++ b/stan/math/rev/core/std_iterator_traits.hpp @@ -10,8 +10,8 @@ namespace std { * Specialization of iterator traits for Stan math. These all take * the form of typedefs. */ -template <> -struct iterator_traits { +template +struct iterator_traits> { /** * Iterator category for traits. */ @@ -25,17 +25,18 @@ struct iterator_traits { /** * Type for value of pointer to values. */ - typedef stan::math::var value_type; + typedef stan::math::var_value value_type; /** * Type of pointer to variables. */ - typedef stan::math::var* pointer; + typedef stan::math::var_value* pointer; /** * Type of reference to variables. */ - typedef stan::math::var& reference; + typedef stan::math::var_value& reference; + }; } // namespace std diff --git a/stan/math/rev/core/std_numeric_limits.hpp b/stan/math/rev/core/std_numeric_limits.hpp index a218696cca8..79fe01fc701 100644 --- a/stan/math/rev/core/std_numeric_limits.hpp +++ b/stan/math/rev/core/std_numeric_limits.hpp @@ -10,57 +10,62 @@ namespace std { * Specialization of numeric limits for var objects. * * This implementation of std::numeric_limits - * is used to treat var objects like doubles. + * is used to treat var objects like value_types. */ -template <> -struct numeric_limits { - static const bool is_specialized = true; - static stan::math::var min() { return numeric_limits::min(); } - static stan::math::var max() { return numeric_limits::max(); } - static const int digits = numeric_limits::digits; - static const int digits10 = numeric_limits::digits10; - static const bool is_signed = numeric_limits::is_signed; - static const bool is_integer = numeric_limits::is_integer; - static const bool is_exact = numeric_limits::is_exact; - static const int radix = numeric_limits::radix; - static stan::math::var epsilon() { return numeric_limits::epsilon(); } - static stan::math::var round_error() { - return numeric_limits::round_error(); +template +struct numeric_limits> { + typedef stan::math::internal::floating_point_promoter value_type; + static constexpr bool is_specialized = true; + static constexpr stan::math::var_value min() noexcept { return numeric_limits::min(); } + static constexpr stan::math::var_value max() noexcept { return numeric_limits::max(); } + static constexpr int digits = numeric_limits::digits; + static constexpr int digits10 = numeric_limits::digits10; + static constexpr int max_digits10 = numeric_limits::max_digits10; + static constexpr bool is_signed = numeric_limits::is_signed; + static constexpr bool is_integer = numeric_limits::is_integer; + static constexpr bool is_exact = numeric_limits::is_exact; + static constexpr int radix = numeric_limits::radix; + static constexpr stan::math::var_value epsilon() noexcept { return numeric_limits::epsilon(); } + static constexpr stan::math::var_value round_error() noexcept { + return numeric_limits::round_error(); } + static constexpr T lowest() noexcept { + return numeric_limits::lowest(); + }; - static const int min_exponent = numeric_limits::min_exponent; - static const int min_exponent10 = numeric_limits::min_exponent10; - static const int max_exponent = numeric_limits::max_exponent; - static const int max_exponent10 = numeric_limits::max_exponent10; + static constexpr int min_exponent = numeric_limits::min_exponent; + static constexpr int min_exponent10 = numeric_limits::min_exponent10; + static constexpr int max_exponent = numeric_limits::max_exponent; + static constexpr int max_exponent10 = numeric_limits::max_exponent10; - static const bool has_infinity = numeric_limits::has_infinity; - static const bool has_quiet_NaN = numeric_limits::has_quiet_NaN; - static const bool has_signaling_NaN - = numeric_limits::has_signaling_NaN; - static const float_denorm_style has_denorm - = numeric_limits::has_denorm; - static const bool has_denorm_loss = numeric_limits::has_denorm_loss; - static stan::math::var infinity() { - return numeric_limits::infinity(); + static constexpr bool has_infinity = numeric_limits::has_infinity; + static constexpr bool has_quiet_NaN = numeric_limits::has_quiet_NaN; + static constexpr bool has_signaling_NaN + = numeric_limits::has_signaling_NaN; + static constexpr float_denorm_style has_denorm + = numeric_limits::has_denorm; + static constexpr bool has_denorm_loss = numeric_limits::has_denorm_loss; + static constexpr stan::math::var_value infinity() noexcept { + return numeric_limits::infinity(); } - static stan::math::var quiet_NaN() { - return numeric_limits::quiet_NaN(); + static constexpr stan::math::var_value quiet_NaN() noexcept { + return numeric_limits::quiet_NaN(); } - static stan::math::var signaling_NaN() { - return numeric_limits::signaling_NaN(); + static constexpr stan::math::var_value signaling_NaN() noexcept { + return numeric_limits::signaling_NaN(); } - static stan::math::var denorm_min() { - return numeric_limits::denorm_min(); + static constexpr stan::math::var_value denorm_min() noexcept { + return numeric_limits::denorm_min(); } - static const bool is_iec559 = numeric_limits::is_iec559; - static const bool is_bounded = numeric_limits::is_bounded; - static const bool is_modulo = numeric_limits::is_modulo; + static constexpr bool is_iec559 = numeric_limits::is_iec559; + static constexpr bool is_bounded = numeric_limits::is_bounded; + static constexpr bool is_modulo = numeric_limits::is_modulo; - static const bool traps = numeric_limits::traps; - static const bool tinyness_before = numeric_limits::tinyness_before; - static const float_round_style round_style - = numeric_limits::round_style; + static constexpr bool traps = numeric_limits::traps; + static constexpr bool tinyness_before = numeric_limits::tinyness_before; + static constexpr float_round_style round_style + = numeric_limits::round_style; }; } // namespace std diff --git a/stan/math/rev/core/var.hpp b/stan/math/rev/core/var.hpp index 1f9cb114000..6aae6529e66 100644 --- a/stan/math/rev/core/var.hpp +++ b/stan/math/rev/core/var.hpp @@ -5,18 +5,14 @@ #include #include #include -#include #include #include -#include -#include -#include namespace stan { namespace math { // forward declare -static void grad(vari* vi); +static void grad(vari_base* vi); /** * Independent (input) and dependent (output) variables for gradients. @@ -30,23 +26,31 @@ static void grad(vari* vi); * and subtraction, as well as a range of mathematical functions * like exponentiation and powers are overridden to operate on * var values objects. + * @tparam T An Arithmetic type. */ -class var { - public: - // FIXME: doc what this is for - using Scalar = double; +template +class var_value { + public: + /** FIXME: This changes integral (int etc) types to double and leaves the type + * untouched otherwise. Since this can be an Eigen matrix it's a pretty + * dumb name. Just for the purposes of readability it may be better to + * use SFINAE on var_value and have a scalar and eigen representation. + * that would also get rid of some of the weirder requires here. + */ + using value_type = internal::floating_point_promoter; + using vari_type = vari_value; /** * Pointer to the implementation of this variable. * * This value should not be modified, but may be accessed in - * var operators to construct vari + * var operators to construct `vari_value` * instances. */ - vari* vi_; + vari_type* vi_; /** - * Return true if this variable has been + * Return `true` if this variable has been * declared, but not been defined. Any attempt to use an * undefined variable's value or adjoint will result in a * segmentation fault. @@ -54,7 +58,9 @@ class var { * @return true if this variable does not yet have * a defined variable. */ - bool is_uninitialized() { return (vi_ == static_cast(nullptr)); } + bool is_uninitialized() { + return (vi_ == static_cast(nullptr)); + } /** * Construct a variable for later assignment. @@ -63,185 +69,94 @@ class var { * dangling. Before an assignment, the behavior is thus undefined just * as for a basic double. */ - var() : vi_(static_cast(nullptr)) {} + var_value() : vi_(static_cast(nullptr)) {} /** * Construct a variable from a pointer to a variable implementation. - * - * @param vi Variable implementation. - */ - var(vari* vi) : vi_(vi) {} // NOLINT - - /** - * Construct a variable from the specified arithmetic argument - * by constructing a new vari with the argument - * cast to double, and a zero adjoint. - * - * @param x Value of the variable. - */ - var(float x) : vi_(new vari(static_cast(x), false)) {} // NOLINT - - /** - * Construct a variable from the specified arithmetic argument - * by constructing a new vari with the argument as - * a value and a zero adjoint. - * - * @param x Value of the variable. - */ - var(double x) : vi_(new vari(x, false)) {} // NOLINT - - /** - * Construct a variable from the specified arithmetic argument - * by constructing a new vari with the argument - * cast to double, and a zero adjoint. - * - * @param x Value of the variable. + * @tparam VariValue A vari_value whose pointer can be implicitly converted + * to vari_value*. + * @param vi Vari type. */ - var(long double x) : vi_(new vari(x, false)) {} // NOLINT + template * = nullptr> + var_value(vari_value* vi) : vi_(vi) {} // NOLINT /** - * Construct a variable from the specified arithmetic argument - * by constructing a new vari with the argument - * cast to double, and a zero adjoint. - * - * @param x Value of the variable. - */ - var(bool x) : vi_(new vari(static_cast(x), false)) {} // NOLINT - - /** - * Construct a variable from the specified arithmetic argument - * by constructing a new vari with the argument - * cast to double, and a zero adjoint. - * - * @param x Value of the variable. - */ - var(char x) : vi_(new vari(static_cast(x), false)) {} // NOLINT - - /** - * Construct a variable from the specified arithmetic argument - * by constructing a new vari with the argument - * cast to double, and a zero adjoint. - * - * @param x Value of the variable. - */ - var(short x) : vi_(new vari(static_cast(x), false)) {} // NOLINT - - /** - * Construct a variable from the specified arithmetic argument - * by constructing a new vari with the argument - * cast to double, and a zero adjoint. - * - * @param x Value of the variable. - */ - var(int x) : vi_(new vari(static_cast(x), false)) {} // NOLINT - - /** - * Construct a variable from the specified arithmetic argument - * by constructing a new vari with the argument - * cast to double, and a zero adjoint. - * - * @param x Value of the variable. - */ - var(long x) : vi_(new vari(static_cast(x), false)) {} // NOLINT - - /** - * Construct a variable from the specified arithmetic argument - * by constructing a new vari with the argument - * cast to double, and a zero adjoint. - * - * @param x Value of the variable. - */ - var(unsigned char x) // NOLINT(runtime/explicit) - : vi_(new vari(static_cast(x), false)) {} - - /** - * Construct a variable from the specified arithmetic argument - * by constructing a new vari with the argument - * cast to double, and a zero adjoint. - * - * @param x Value of the variable. - */ - // NOLINTNEXTLINE - var(unsigned short x) : vi_(new vari(static_cast(x), false)) {} - - /** - * Construct a variable from the specified arithmetic argument - * by constructing a new vari with the argument - * cast to double, and a zero adjoint. - * - * @param x Value of the variable. - */ - // NOLINTNEXTLINE - var(unsigned int x) - : vi_(new vari(static_cast(x), false)) {} // NOLINT + * Construct a variable from a pointer to a variable implementation. + * @tparam VariValue A vari_value whose pointer can be implicitly converted + * to vari_value*. + * @param vi Vari type. + */ + template * = nullptr, + require_not_same_t* = nullptr> + var_value(vari_value* vi) : vi_(new vari_type(vi->val_, false)) { // NOLINT + this->vi_->adj_ = vi->adj_; + } /** - * Construct a variable from the specified arithmetic argument - * by constructing a new vari with the argument - * cast to double, and a zero adjoint. - * + * Construct a variable from the specified integral type argument + * by constructing a new `vari_value`. For integral types the + * `vari_value` will hold doubles. This constructor is only valid when + * `T` is arithmetic. + * @tparam IntegralT Integral type such as `int` + * @tparam T1 A dummy template whose value will always be `T` * @param x Value of the variable. */ - // NOLINTNEXTLINE - var(unsigned long x) - : vi_(new vari(static_cast(x), false)) {} // NOLINT - -#ifdef _WIN64 - // these two ctors are for Win64 to enable 64-bit signed - // and unsigned integers, because long and unsigned long - // are still 32-bit + template * = nullptr> + var_value(S x) : vi_(new vari_type(x, false)) {} // NOLINT /** - * Construct a variable from the specified arithmetic argument - * by constructing a new vari with the argument - * cast to double, and a zero adjoint. - * - * @param x Value of the variable. + * Construct from a var_value whose underlying value_type differs in type + * to this class's value_type. + * `var_value a(var_value(b));`` + * @tparam S An arithmetic type that is convertible to `T` but is not the + * same as the underlying value_type. + * param x a `var_value` whose underlying vari_type can be dynamically cast + * to `this::vari_value``. */ - var(size_t x) : vi_(new vari(static_cast(x), false)) {} // NOLINT - + template , + require_not_same_t* = nullptr> + var_value(var_value& x) : vi_(new vari_type(x.val(), false)) { // NOLINT + this->vi_->adj_ = x.adj(); + } /** - * Construct a variable from the specified arithmetic argument - * by constructing a new vari with the argument - * cast to double, and a zero adjoint. - * - * @param x Value of the variable. + * Same as the floating point */ - var(ptrdiff_t x) : vi_(new vari(static_cast(x), false)) {} // NOLINT -#endif - -#ifdef BOOST_MATH_USE_FLOAT128 - - // this ctor is for later GCCs that have the __float128 - // type enabled, because it gets enabled by boost + template , + require_not_same_t* = nullptr> + var_value(var_value&& x) : vi_(new vari_type(x.val(), false)) { // NOLINT + this->vi_->adj_ = x.adj(); + } /** - * Construct a variable from the specified arithmetic argument - * by constructing a new vari with the argument - * cast to double, and a zero adjoint. - * - * @param x Value of the variable. + * Constructor from `var_value` whose value_type is the same as this class's + * `value_type`. This is used in cases such as + * `var_value(var_value(4.0))` since the `value_type` for a + * `var_value` with an arithmetic type is a double. */ - var(__float128 x) : vi_(new vari(static_cast(x), false)) {} // NOLINT + template , + require_same_t* = nullptr> + var_value(var_value& x) : vi_(x.vi_) {} // NOLINT -#endif + template , + require_same_t* = nullptr> + var_value(var_value&& x) : vi_(x.vi_) {} // NOLINT /** * Return the value of this variable. * * @return The value of this variable. */ - inline double val() const { return vi_->val_; } + inline auto val() const { return vi_->val_; } /** * Return the derivative of the root expression with * respect to this expression. This method only works - * after one of the grad() methods has been + * after one of the `grad()` methods has been * called. * * @return Adjoint for this variable. */ - inline double adj() const { return vi_->adj_; } + inline auto adj() const { return vi_->adj_; } /** * Compute the gradient of this (dependent) variable with respect to @@ -255,7 +170,7 @@ class var { * @param g Gradient vector of partial derivatives of this * variable with respect to x. */ - void grad(std::vector& x, std::vector& g) { + inline void grad(std::vector>& x, std::vector& g) { stan::math::grad(vi_); g.resize(x.size()); for (size_t i = 0; i < x.size(); ++i) { @@ -285,7 +200,7 @@ class var { * * @return variable */ - inline vari& operator*() { return *vi_; } + inline vari_type& operator*() { return *vi_; } /** * Return a pointer to the underlying implementation of this variable. @@ -297,7 +212,7 @@ class var { * Warning: The returned result does not track changes to * this variable. */ - inline vari* operator->() { return vi_; } + inline vari_type* operator->() { return vi_; } // COMPOUND ASSIGNMENT OPERATORS @@ -308,10 +223,12 @@ class var { * then (a += b) behaves exactly the same way as (a = a + b), * creating an intermediate variable representing (a + b). * + * @tparam S a type that is convertible to `T` * @param b The variable to add to this variable. * @return The result of adding the specified variable to this variable. */ - inline var& operator+=(var b); + template >* = nullptr> + inline var_value& operator+=(const var_value& b); /** * The compound add/assignment operator for scalars (C++). @@ -323,8 +240,8 @@ class var { * @param b The scalar to add to this variable. * @return The result of adding the specified variable to this variable. */ - template ...> - inline var& operator+=(Arith b); + template * = nullptr> + inline var_value& operator+=(Arith b); /** * The compound subtract/assignment operator for variables (C++). @@ -333,11 +250,13 @@ class var { * then (a -= b) behaves exactly the same way as (a = a - b). * Note that the result is an assignable lvalue. * + * @tparam S a type that is convertible to `T` * @param b The variable to subtract from this variable. * @return The result of subtracting the specified variable from * this variable. */ - inline var& operator-=(var b); + template >* = nullptr> + inline var_value& operator-=(const var_value& b); /** * The compound subtract/assignment operator for scalars (C++). @@ -350,8 +269,8 @@ class var { * @return The result of subtracting the specified variable from this * variable. */ - template ...> - inline var& operator-=(Arith b); + template * = nullptr> + inline var_value& operator-=(Arith b); /** * The compound multiply/assignment operator for variables (C++). @@ -360,11 +279,13 @@ class var { * then (a *= b) behaves exactly the same way as (a = a * b). * Note that the result is an assignable lvalue. * + * @tparam S a type that is convertible to `T` * @param b The variable to multiply this variable by. * @return The result of multiplying this variable by the * specified variable. */ - inline var& operator*=(var b); + template >* = nullptr> + inline var_value& operator*=(const var_value& b); /** * The compound multiply/assignment operator for scalars (C++). @@ -377,8 +298,8 @@ class var { * @return The result of multiplying this variable by the specified * variable. */ - template ...> - inline var& operator*=(Arith b); + template * = nullptr> + inline var_value& operator*=(Arith b); /** * The compound divide/assignment operator for variables (C++). If this @@ -386,11 +307,13 @@ class var { * behaves exactly the same way as (a = a / b). Note that the * result is an assignable lvalue. * + * @tparam S a type that is convertible to `T` * @param b The variable to divide this variable by. * @return The result of dividing this variable by the * specified variable. */ - inline var& operator/=(var b); + template >* = nullptr> + inline var_value& operator/=(const var_value& b); /** * The compound divide/assignment operator for scalars (C++). @@ -403,8 +326,8 @@ class var { * @return The result of dividing this variable by the specified * variable. */ - template ...> - inline var& operator/=(Arith b); + template * = nullptr> + inline var_value& operator/=(Arith b); /** * Write the value of this autodiff variable and its adjoint to @@ -414,14 +337,18 @@ class var { * @param v Variable to write. * @return Reference to the specified output stream. */ - friend std::ostream& operator<<(std::ostream& os, const var& v) { + friend std::ostream& operator<<(std::ostream& os, const var_value& v) { if (v.vi_ == nullptr) { return os << "uninitialized"; } return os << v.val(); } + }; +// For backwards compatability the default value is double +using var = var_value; + } // namespace math } // namespace stan #endif diff --git a/stan/math/rev/core/vari.hpp b/stan/math/rev/core/vari.hpp index ababd029097..28092db0c63 100644 --- a/stan/math/rev/core/vari.hpp +++ b/stan/math/rev/core/vari.hpp @@ -4,12 +4,61 @@ #include #include #include +#include namespace stan { namespace math { // forward declaration of var -class var; +template +class var_value; + +/** + * Pure virtual class that all `vari_value` and it's derived classes inherit. + */ +class vari_base { + public: + /** + * Apply the chain rule to this variable based on the variables + * on which it depends. + */ + virtual void chain() {} + + /** + * Initialize the adjoint for this (dependent) variable to 1. + * This operation is applied to the dependent variable before + * propagating derivatives, setting the derivative of the + * result with respect to itself to be 1. + */ + virtual void init_dependent() {} + + /** + * Set the adjoint value of this variable to 0. This is used to + * reset adjoints before propagating derivatives again (for + * example in a Jacobian calculation). + */ + virtual void set_zero_adjoint() {} + + /** + * Throw an illegal argument exception. + * + * Warning: Destructors should never called for var objects. + * + * @throw Logic exception always. + */ + virtual ~vari_base() {} +}; + +namespace internal { + /** + * Promote integral types to double + * @tparam Val Any type + */ + template + using floating_point_promoter + = std::conditional_t>::value, double, + std::decay_t>; +} /** * The variable implementation base class. @@ -27,21 +76,28 @@ class var; * classes will store operand variables and propagate derivative * information via an implementation of chain(). */ -class vari { - private: - friend class var; +template +class vari_value; +template +class vari_value::value>> + : public vari_base { + private: + template + friend class var_value; public: + using Scalar = internal::floating_point_promoter; + using value_type = Scalar; /** * The value of this variable. */ - const double val_; + const Scalar val_; /** * The adjoint of this variable, which is the partial derivative * of this variable with respect to the root variable. */ - double adj_; + Scalar adj_; /** * Construct a variable implementation from a value. The @@ -53,13 +109,33 @@ class vari { * derivative propagation, the chain() method of each variable * will be called in the reverse order of construction. * + * @tparam S an Arithmetic type. * @param x Value of the constructed variable. */ - explicit vari(double x) : val_(x), adj_(0.0) { + template ::value>* = nullptr> + vari_value(S x) : val_(x), adj_(0.0) { ChainableStack::instance_->var_stack_.push_back(this); } - vari(double x, bool stacked) : val_(x), adj_(0.0) { + /** + * Construct a variable implementation from a value. The + * adjoint is initialized to zero and if `stacked` is `false` this vari + * will be moved to the nochain stack s.t. it's chain method will not be + * called when calling `grad()`. + * + * All constructed variables are added to the stack. Variables + * should be constructed before variables on which they depend + * to insure proper partial derivative propagation. During + * derivative propagation, the chain() method of each variable + * will be called in the reverse order of construction. + * + * @tparam S an Arithmetic type. + * @param x Value of the constructed variable. + * @param stacked If true will put this this vari on the nochain stack so that + * it's `chain()` method is not called. + */ + template ::value>* = nullptr> + vari_value(S x, bool stacked) : val_(x), adj_(0.0) { if (stacked) { ChainableStack::instance_->var_stack_.push_back(this); } else { @@ -67,38 +143,20 @@ class vari { } } - /** - * Throw an illegal argument exception. - * - * Warning: Destructors should never called for var objects. - * - * @throw Logic exception always. - */ - virtual ~vari() { - // this will never get called - } - - /** - * Apply the chain rule to this variable based on the variables - * on which it depends. The base implementation in this class - * is a no-op. - */ - virtual void chain() {} - /** * Initialize the adjoint for this (dependent) variable to 1. * This operation is applied to the dependent variable before * propagating derivatives, setting the derivative of the * result with respect to itself to be 1. */ - void init_dependent() { adj_ = 1.0; } + void init_dependent() final { adj_ = 1.0; } /** * Set the adjoint value of this variable to 0. This is used to * reset adjoints before propagating derivatives again (for * example in a Jacobian calculation). */ - void set_zero_adjoint() { adj_ = 0.0; } + void set_zero_adjoint() final { adj_ = 0.0; } /** * Insertion operator for vari. Prints the current value and @@ -109,7 +167,7 @@ class vari { * * @return The modified ostream. */ - friend std::ostream& operator<<(std::ostream& os, const vari* v) { + friend std::ostream& operator<<(std::ostream& os, const vari_value* v) { return os << v->val_ << ":" << v->adj_; } @@ -142,6 +200,9 @@ class vari { } }; +// For backwards compatability the default is double +using vari = vari_value; + } // namespace math } // namespace stan #endif diff --git a/stan/math/rev/core/vector_vari.hpp b/stan/math/rev/core/vector_vari.hpp index 7e06bb91f27..55de53af4a8 100644 --- a/stan/math/rev/core/vector_vari.hpp +++ b/stan/math/rev/core/vector_vari.hpp @@ -15,8 +15,8 @@ class op_vector_vari : public vari { vari** vis_; public: - template ..., - require_vector_like_vt...> + template * = nullptr, + require_vector_like_vt* = nullptr> op_vector_vari(Arith f, VecVar&& vs) : vari(f), size_(vs.size()) { vis_ = reinterpret_cast(operator new(sizeof(vari*) * vs.size())); for (size_t i = 0; i < vs.size(); ++i) { diff --git a/stan/math/rev/fun/value_of.hpp b/stan/math/rev/fun/value_of.hpp index f3361cdf72c..162a9834618 100644 --- a/stan/math/rev/fun/value_of.hpp +++ b/stan/math/rev/fun/value_of.hpp @@ -20,7 +20,8 @@ namespace math { * @param v Variable. * @return Value of variable. */ -inline double value_of(const var& v) { return v.vi_->val_; } +template +inline auto value_of(const var_value& v) { return v.vi_->val_; } } // namespace math } // namespace stan diff --git a/stan/math/rev/fun/value_of_rec.hpp b/stan/math/rev/fun/value_of_rec.hpp index c75d7a2e931..5f6a477d86b 100644 --- a/stan/math/rev/fun/value_of_rec.hpp +++ b/stan/math/rev/fun/value_of_rec.hpp @@ -14,7 +14,8 @@ namespace math { * @param v Variable. * @return Value of variable. */ -inline double value_of_rec(const var& v) { return v.vi_->val_; } +template +inline auto value_of_rec(const var_value& v) { return v.vi_->val_; } } // namespace math } // namespace stan diff --git a/stan/math/rev/meta.hpp b/stan/math/rev/meta.hpp index e97380c2e1b..de7740d931e 100644 --- a/stan/math/rev/meta.hpp +++ b/stan/math/rev/meta.hpp @@ -3,6 +3,7 @@ #include #include +#include #include #include #include diff --git a/stan/math/rev/meta/is_var.hpp b/stan/math/rev/meta/is_var.hpp index 40cb61cf8d7..a44745393c9 100644 --- a/stan/math/rev/meta/is_var.hpp +++ b/stan/math/rev/meta/is_var.hpp @@ -6,13 +6,19 @@ #include namespace stan { + +namespace internal { + template + struct is_var_impl : std::false_type {}; + + template + struct is_var_impl> : std::true_type {}; +} /** \ingroup type_trait - * Specialization for checking if value of T minus cv qualifier is a var. + * Specialization for checking if value of T minus cv qualifier is a var_value. */ template -struct is_var>::value>> - : std::true_type {}; +struct is_var>::value>> : std::true_type {}; } // namespace stan #endif diff --git a/stan/math/rev/meta/is_vari.hpp b/stan/math/rev/meta/is_vari.hpp new file mode 100644 index 00000000000..84c5d79cb85 --- /dev/null +++ b/stan/math/rev/meta/is_vari.hpp @@ -0,0 +1,21 @@ +#ifndef STAN_MATH_REV_META_IS_VARI_HPP +#define STAN_MATH_REV_META_IS_VARI_HPP + +#include +#include +#include + +namespace stan { +/** \ingroup type_trait + * Specialization for checking if value of T minus cv qualifier and pointer is a + * vari_value. + */ +template +struct is_vari< + T, std::enable_if_t>>::value>> + : std::true_type {}; + + +} // namespace stan +#endif diff --git a/stan/math/rev/meta/partials_type.hpp b/stan/math/rev/meta/partials_type.hpp index 51c10e928a9..823117fe062 100644 --- a/stan/math/rev/meta/partials_type.hpp +++ b/stan/math/rev/meta/partials_type.hpp @@ -13,7 +13,7 @@ namespace stan { */ template struct partials_type> { - using type = typename std::decay_t::Scalar; + using type = typename std::decay_t::value_type; }; } // namespace stan diff --git a/test/unit/math/rev/core/var_test.cpp b/test/unit/math/rev/core/var_test.cpp index 54d66f75db0..6284ce983bd 100644 --- a/test/unit/math/rev/core/var_test.cpp +++ b/test/unit/math/rev/core/var_test.cpp @@ -1,5 +1,6 @@ #include #include +#include #include #include #include @@ -13,62 +14,63 @@ struct AgradRev : public testing::Test { } }; -TEST_F(AgradRev, ctorOverloads) { - using stan::math::var; - using stan::math::vari; - +template +void ctor_overloads_impl() { + using stan::math::var_value; + using stan::math::vari_value; + using stan::math::test::type_name; // make sure copy ctor is used rather than casting vari* to unsigned int - EXPECT_FLOAT_EQ(12.3, var(new vari(12.3)).val()); + EXPECT_FLOAT_EQ(12.3, var_value(new vari_value(12.3)).val()) << + "Failed For T: " << type_name() << " and S: " << type_name() << "\n"; - // double - EXPECT_FLOAT_EQ(3.7, var(3.7).val()); + EXPECT_FLOAT_EQ(12.3, var_value(var_value(12.3)).val()) << + "Failed For T: " << type_name() << " and S: " << type_name() << "\n"; + EXPECT_FLOAT_EQ(static_cast(3.7), var_value(static_cast(3.7)).val()) << + "Failed For T: " << type_name() << " and S: " << type_name() << "\n"; + // double + EXPECT_FLOAT_EQ(3.7, var_value(3.7).val()) << + "Failed For T: " << type_name() << " and S: " << type_name() << "\n"; // long double - EXPECT_FLOAT_EQ(3.7, var(static_cast(3.7)).val()); - - // float - EXPECT_FLOAT_EQ(3.7, var(static_cast(3.7)).val()); - - // bool - EXPECT_FLOAT_EQ(1, var(static_cast(true)).val()); - - // char - EXPECT_FLOAT_EQ(3, var(static_cast(3)).val()); - - // short - EXPECT_FLOAT_EQ(1, var(static_cast(1)).val()); - - // int - EXPECT_FLOAT_EQ(37, var(static_cast(37)).val()); - - // long - EXPECT_FLOAT_EQ(37, var(static_cast(37)).val()); - - // unsigned char - EXPECT_FLOAT_EQ(37, var(static_cast(37)).val()); + EXPECT_FLOAT_EQ(static_cast(3.7), var_value(static_cast(3.7)).val()) << + "Failed For T: " << type_name() << " and S: " << type_name() << "\n"; + EXPECT_FLOAT_EQ(0, var_value(static_cast(0)).val()) << + "Failed For T: " << type_name() << " and S:" << type_name() << "\n"; - // unsigned short - EXPECT_FLOAT_EQ(37, var(static_cast(37)).val()); - - // unsigned int - EXPECT_FLOAT_EQ(37, var(static_cast(37)).val()); - - // unsigned int (test conflict with null pointer) - EXPECT_FLOAT_EQ(0, var(static_cast(0)).val()); - - // unsigned long - EXPECT_FLOAT_EQ(37, var(static_cast(37)).val()); - - // unsigned long (test for conflict with pointer) - EXPECT_FLOAT_EQ(0, var(static_cast(0)).val()); - - // size_t - EXPECT_FLOAT_EQ(37, var(static_cast(37)).val()); - EXPECT_FLOAT_EQ(0, var(static_cast(0)).val()); +} - // ptrdiff_t - EXPECT_FLOAT_EQ(37, var(static_cast(37)).val()); - EXPECT_FLOAT_EQ(0, var(static_cast(0)).val()); +template +void ctor_overloads() { + ctor_overloads_impl(); + ctor_overloads_impl(); + ctor_overloads_impl(); + ctor_overloads_impl(); + ctor_overloads_impl(); + ctor_overloads_impl(); + ctor_overloads_impl(); + ctor_overloads_impl(); + ctor_overloads_impl(); + ctor_overloads_impl(); + ctor_overloads_impl(); + ctor_overloads_impl(); + ctor_overloads_impl(); +} +TEST_F(AgradRev, ctorOverloads) { + using stan::math::var; + using stan::math::vari; + ctor_overloads(); + ctor_overloads(); + ctor_overloads(); + ctor_overloads(); + ctor_overloads(); + ctor_overloads(); + ctor_overloads(); + ctor_overloads(); + ctor_overloads(); + ctor_overloads(); + ctor_overloads(); + ctor_overloads(); + ctor_overloads(); } TEST_F(AgradRev, a_eq_x) { @@ -281,3 +283,11 @@ TEST_F(AgradRev, grad) { EXPECT_FLOAT_EQ(11.0, a.adj()); EXPECT_FLOAT_EQ(5.0, b.adj()); } + +TEST_F(AgradRev, type_convs) { + using stan::math::var_value; + var_value a(1); + var_value b(a); + var_value c(a); + var_value d(a); +} diff --git a/test/unit/math/rev/core/vari_test.cpp b/test/unit/math/rev/core/vari_test.cpp index 0da07b91486..b0e72a07230 100644 --- a/test/unit/math/rev/core/vari_test.cpp +++ b/test/unit/math/rev/core/vari_test.cpp @@ -8,3 +8,10 @@ TEST(AgradRev, insertion_operator) { ss << &v; EXPECT_EQ("5:0", ss.str()); } + +TEST(AgradRev, insertion_operator) { + stan::math::vari_value v(5); + std::stringstream ss; + ss << &v; + EXPECT_EQ("5:0", ss.str()); +} diff --git a/test/unit/pretty_print_types.hpp b/test/unit/pretty_print_types.hpp index f468590de26..893e92b59a5 100644 --- a/test/unit/pretty_print_types.hpp +++ b/test/unit/pretty_print_types.hpp @@ -74,7 +74,7 @@ inline std::ostream& operator<<(std::ostream& os, static_string const& s) { * Prints out an input type. * @tparam T The type to print out. */ -template +template CONSTEXPR14_TN static_string type_name() { #ifdef __clang__ static_string p = __PRETTY_FUNCTION__; @@ -84,7 +84,7 @@ CONSTEXPR14_TN static_string type_name() { #if __cplusplus < 201402 return static_string(p.data() + 36, p.size() - 36 - 1); #else - return static_string(p.data() + 46, p.size() - 46 - 1); + return static_string(p.data() + 83, p.size() - 83 - 1); #endif #elif defined(_MSC_VER) static_string p = __FUNCSIG__; From d7e1d84bd90ac50dc1f00dc12df3f8eebb411d00 Mon Sep 17 00:00:00 2001 From: Steve Bronder Date: Thu, 28 May 2020 13:05:39 -0400 Subject: [PATCH 014/355] Add a template to grad so that init_dependent can be non-virtual, make vari_base a pure virtual base class --- stan/math/rev/core/grad.hpp | 3 ++- stan/math/rev/core/vari.hpp | 14 +++----------- stan/math/rev/functor/coupled_ode_system.hpp | 4 ++-- test/unit/math/rev/core/vari_test.cpp | 2 +- 4 files changed, 8 insertions(+), 15 deletions(-) diff --git a/stan/math/rev/core/grad.hpp b/stan/math/rev/core/grad.hpp index 6e5f56c2287..cb62d333772 100644 --- a/stan/math/rev/core/grad.hpp +++ b/stan/math/rev/core/grad.hpp @@ -27,7 +27,8 @@ namespace math { * @param vi Variable implementation for root of partial * derivative propagation. */ -static void grad(vari_base* vi) { +template * = nullptr> +static void grad(Vari* vi) { vi->init_dependent(); std::vector& var_stack = ChainableStack::instance_->var_stack_; size_t end = var_stack.size(); diff --git a/stan/math/rev/core/vari.hpp b/stan/math/rev/core/vari.hpp index 28092db0c63..4e4bd589465 100644 --- a/stan/math/rev/core/vari.hpp +++ b/stan/math/rev/core/vari.hpp @@ -22,22 +22,14 @@ class vari_base { * Apply the chain rule to this variable based on the variables * on which it depends. */ - virtual void chain() {} - - /** - * Initialize the adjoint for this (dependent) variable to 1. - * This operation is applied to the dependent variable before - * propagating derivatives, setting the derivative of the - * result with respect to itself to be 1. - */ - virtual void init_dependent() {} + virtual void chain() {}; /** * Set the adjoint value of this variable to 0. This is used to * reset adjoints before propagating derivatives again (for * example in a Jacobian calculation). */ - virtual void set_zero_adjoint() {} + virtual void set_zero_adjoint() = 0; /** * Throw an illegal argument exception. @@ -149,7 +141,7 @@ class vari_value::value>> * propagating derivatives, setting the derivative of the * result with respect to itself to be 1. */ - void init_dependent() final { adj_ = 1.0; } + void init_dependent() { adj_ = 1.0; } /** * Set the adjoint value of this variable to 0. This is used to diff --git a/stan/math/rev/functor/coupled_ode_system.hpp b/stan/math/rev/functor/coupled_ode_system.hpp index 22669207494..0ec42273374 100644 --- a/stan/math/rev/functor/coupled_ode_system.hpp +++ b/stan/math/rev/functor/coupled_ode_system.hpp @@ -149,7 +149,7 @@ struct coupled_ode_system { // See efficiency note above on template specialization for more details // on this. for (size_t j = 0; j < M_; ++j) { - theta_nochain_[j].vi_->set_zero_adjoint(); + theta_nochain_[j].vi_->adj_ = 0.0; } } } @@ -484,7 +484,7 @@ struct coupled_ode_system { // See efficiency note above on template specialization for more details // on this. for (size_t j = 0; j < M_; ++j) { - theta_nochain_[j].vi_->set_zero_adjoint(); + theta_nochain_[j].vi_->adj_ = 0.0; } } } diff --git a/test/unit/math/rev/core/vari_test.cpp b/test/unit/math/rev/core/vari_test.cpp index b0e72a07230..d9d0fb6648f 100644 --- a/test/unit/math/rev/core/vari_test.cpp +++ b/test/unit/math/rev/core/vari_test.cpp @@ -9,7 +9,7 @@ TEST(AgradRev, insertion_operator) { EXPECT_EQ("5:0", ss.str()); } -TEST(AgradRev, insertion_operator) { +TEST(AgradRev, int_test) { stan::math::vari_value v(5); std::stringstream ss; ss << &v; From ba930da00d3768094c2b5d7435929c783a5a1909 Mon Sep 17 00:00:00 2001 From: Steve Bronder Date: Thu, 28 May 2020 14:51:47 -0400 Subject: [PATCH 015/355] add final to classes inheriting op_varis so flto can more aggressivly devirtualize --- stan/math/rev/core/operator_addition.hpp | 4 ++-- stan/math/rev/core/operator_division.hpp | 6 +++--- stan/math/rev/core/operator_multiplication.hpp | 4 ++-- stan/math/rev/core/operator_subtraction.hpp | 6 +++--- stan/math/rev/core/operator_unary_decrement.hpp | 2 +- stan/math/rev/core/operator_unary_increment.hpp | 2 +- stan/math/rev/core/operator_unary_negative.hpp | 2 +- stan/math/rev/core/precomp_v_vari.hpp | 2 +- stan/math/rev/core/precomp_vvv_vari.hpp | 2 +- 9 files changed, 15 insertions(+), 15 deletions(-) diff --git a/stan/math/rev/core/operator_addition.hpp b/stan/math/rev/core/operator_addition.hpp index 190958f8301..6832d0a75c2 100644 --- a/stan/math/rev/core/operator_addition.hpp +++ b/stan/math/rev/core/operator_addition.hpp @@ -12,7 +12,7 @@ namespace stan { namespace math { namespace internal { -class add_vv_vari : public op_vv_vari { +class add_vv_vari final : public op_vv_vari { public: add_vv_vari(vari* avi, vari* bvi) : op_vv_vari(avi->val_ + bvi->val_, avi, bvi) {} @@ -27,7 +27,7 @@ class add_vv_vari : public op_vv_vari { } }; -class add_vd_vari : public op_vd_vari { +class add_vd_vari final : public op_vd_vari { public: add_vd_vari(vari* avi, double b) : op_vd_vari(avi->val_ + b, avi, b) {} void chain() { diff --git a/stan/math/rev/core/operator_division.hpp b/stan/math/rev/core/operator_division.hpp index 69770cb15cc..892ec27fb4d 100644 --- a/stan/math/rev/core/operator_division.hpp +++ b/stan/math/rev/core/operator_division.hpp @@ -23,7 +23,7 @@ namespace math { namespace internal { // (dividend/divisor)' = dividend' * (1 / divisor) - divisor' * (dividend / // [divisor * divisor]) -class divide_vv_vari : public op_vv_vari { +class divide_vv_vari final : public op_vv_vari { public: divide_vv_vari(vari* dividend_vi, vari* divisor_vi) : op_vv_vari(dividend_vi->val_ / divisor_vi->val_, dividend_vi, @@ -39,7 +39,7 @@ class divide_vv_vari : public op_vv_vari { } }; -class divide_vd_vari : public op_vd_vari { +class divide_vd_vari final : public op_vd_vari { public: divide_vd_vari(vari* dividend_vi, double divisor) : op_vd_vari(dividend_vi->val_ / divisor, dividend_vi, divisor) {} @@ -52,7 +52,7 @@ class divide_vd_vari : public op_vd_vari { } }; -class divide_dv_vari : public op_dv_vari { +class divide_dv_vari final : public op_dv_vari { public: divide_dv_vari(double dividend, vari* divisor_vi) : op_dv_vari(dividend / divisor_vi->val_, dividend, divisor_vi) {} diff --git a/stan/math/rev/core/operator_multiplication.hpp b/stan/math/rev/core/operator_multiplication.hpp index 12744038693..2d360d5a7f4 100644 --- a/stan/math/rev/core/operator_multiplication.hpp +++ b/stan/math/rev/core/operator_multiplication.hpp @@ -14,7 +14,7 @@ namespace stan { namespace math { namespace internal { -class multiply_vv_vari : public op_vv_vari { +class multiply_vv_vari final : public op_vv_vari { public: multiply_vv_vari(vari* avi, vari* bvi) : op_vv_vari(avi->val_ * bvi->val_, avi, bvi) {} @@ -29,7 +29,7 @@ class multiply_vv_vari : public op_vv_vari { } }; -class multiply_vd_vari : public op_vd_vari { +class multiply_vd_vari final : public op_vd_vari { public: multiply_vd_vari(vari* avi, double b) : op_vd_vari(avi->val_ * b, avi, b) {} void chain() { diff --git a/stan/math/rev/core/operator_subtraction.hpp b/stan/math/rev/core/operator_subtraction.hpp index eb4319e5f03..20a825c7383 100644 --- a/stan/math/rev/core/operator_subtraction.hpp +++ b/stan/math/rev/core/operator_subtraction.hpp @@ -13,7 +13,7 @@ namespace stan { namespace math { namespace internal { -class subtract_vv_vari : public op_vv_vari { +class subtract_vv_vari final : public op_vv_vari { public: subtract_vv_vari(vari* avi, vari* bvi) : op_vv_vari(avi->val_ - bvi->val_, avi, bvi) {} @@ -28,7 +28,7 @@ class subtract_vv_vari : public op_vv_vari { } }; -class subtract_vd_vari : public op_vd_vari { +class subtract_vd_vari final : public op_vd_vari { public: subtract_vd_vari(vari* avi, double b) : op_vd_vari(avi->val_ - b, avi, b) {} void chain() { @@ -40,7 +40,7 @@ class subtract_vd_vari : public op_vd_vari { } }; -class subtract_dv_vari : public op_dv_vari { +class subtract_dv_vari final : public op_dv_vari { public: subtract_dv_vari(double a, vari* bvi) : op_dv_vari(a - bvi->val_, a, bvi) {} void chain() { diff --git a/stan/math/rev/core/operator_unary_decrement.hpp b/stan/math/rev/core/operator_unary_decrement.hpp index df79c750674..bca1358792b 100644 --- a/stan/math/rev/core/operator_unary_decrement.hpp +++ b/stan/math/rev/core/operator_unary_decrement.hpp @@ -11,7 +11,7 @@ namespace stan { namespace math { namespace internal { -class decrement_vari : public op_v_vari { +class decrement_vari final : public op_v_vari { public: explicit decrement_vari(vari* avi) : op_v_vari(avi->val_ - 1.0, avi) {} void chain() { diff --git a/stan/math/rev/core/operator_unary_increment.hpp b/stan/math/rev/core/operator_unary_increment.hpp index 6c3e818f088..cb904cd3780 100644 --- a/stan/math/rev/core/operator_unary_increment.hpp +++ b/stan/math/rev/core/operator_unary_increment.hpp @@ -11,7 +11,7 @@ namespace stan { namespace math { namespace internal { -class increment_vari : public op_v_vari { +class increment_vari final : public op_v_vari { public: explicit increment_vari(vari* avi) : op_v_vari(avi->val_ + 1.0, avi) {} void chain() { diff --git a/stan/math/rev/core/operator_unary_negative.hpp b/stan/math/rev/core/operator_unary_negative.hpp index 3b294f2250d..4c5b9a40b49 100644 --- a/stan/math/rev/core/operator_unary_negative.hpp +++ b/stan/math/rev/core/operator_unary_negative.hpp @@ -11,7 +11,7 @@ namespace stan { namespace math { namespace internal { -class neg_vari : public op_v_vari { +class neg_vari final : public op_v_vari { public: explicit neg_vari(vari* avi) : op_v_vari(-(avi->val_), avi) {} void chain() { diff --git a/stan/math/rev/core/precomp_v_vari.hpp b/stan/math/rev/core/precomp_v_vari.hpp index a8fb5ecd0de..6da15f81796 100644 --- a/stan/math/rev/core/precomp_v_vari.hpp +++ b/stan/math/rev/core/precomp_v_vari.hpp @@ -8,7 +8,7 @@ namespace stan { namespace math { // use for single precomputed partials -class precomp_v_vari : public op_v_vari { +class precomp_v_vari final : public op_v_vari { protected: double da_; diff --git a/stan/math/rev/core/precomp_vvv_vari.hpp b/stan/math/rev/core/precomp_vvv_vari.hpp index 69af6ce4a61..e6c2d8a9ba6 100644 --- a/stan/math/rev/core/precomp_vvv_vari.hpp +++ b/stan/math/rev/core/precomp_vvv_vari.hpp @@ -8,7 +8,7 @@ namespace stan { namespace math { // use for single precomputed partials -class precomp_vvv_vari : public op_vvv_vari { +class precomp_vvv_vari final : public op_vvv_vari { protected: double da_; double db_; From 244620a6a98f819a0de6d6f3d692bc4e679c60f6 Mon Sep 17 00:00:00 2001 From: Steve Bronder Date: Fri, 29 May 2020 17:56:10 -0400 Subject: [PATCH 016/355] cleanup templates in var and vari, clang-format, tests for is_var, is_vari, and avoiding copies for integral type vari_value --- .../prim/fun/scale_matrix_exp_multiply.hpp | 6 +- stan/math/rev/core/grad.hpp | 2 +- stan/math/rev/core/operator_divide_equal.hpp | 3 +- stan/math/rev/core/operator_equal.hpp | 4 +- .../core/operator_greater_than_or_equal.hpp | 4 +- .../rev/core/operator_less_than_or_equal.hpp | 4 +- stan/math/rev/core/operator_logical_and.hpp | 4 +- stan/math/rev/core/operator_logical_or.hpp | 4 +- stan/math/rev/core/operator_minus_equal.hpp | 3 +- .../math/rev/core/operator_multiply_equal.hpp | 3 +- stan/math/rev/core/operator_not_equal.hpp | 4 +- stan/math/rev/core/operator_plus_equal.hpp | 3 +- stan/math/rev/core/precomp_vv_vari.hpp | 2 +- stan/math/rev/core/std_iterator_traits.hpp | 1 - stan/math/rev/core/std_numeric_limits.hpp | 27 +++- stan/math/rev/core/var.hpp | 143 +++++++++--------- stan/math/rev/core/vari.hpp | 48 ++++-- stan/math/rev/core/vector_vari.hpp | 3 +- stan/math/rev/meta/is_var.hpp | 14 +- test/unit/math/rev/core/var_test.cpp | 36 ++--- test/unit/math/rev/meta/is_var_test.cpp | 7 + test/unit/math/rev/meta/is_vari_test.cpp | 14 ++ 22 files changed, 210 insertions(+), 129 deletions(-) create mode 100644 test/unit/math/rev/meta/is_vari_test.cpp diff --git a/stan/math/prim/fun/scale_matrix_exp_multiply.hpp b/stan/math/prim/fun/scale_matrix_exp_multiply.hpp index 577248b9b05..217c7c8b6a2 100644 --- a/stan/math/prim/fun/scale_matrix_exp_multiply.hpp +++ b/stan/math/prim/fun/scale_matrix_exp_multiply.hpp @@ -26,7 +26,8 @@ namespace math { */ template * = nullptr, - require_all_same_t, value_type_t>* = nullptr> + require_all_same_t, + value_type_t>* = nullptr> inline Eigen::Matrix scale_matrix_exp_multiply(const double& t, const EigMat1& A, const EigMat2& B) { check_square("scale_matrix_exp_multiply", "input matrix", A); @@ -54,7 +55,8 @@ scale_matrix_exp_multiply(const double& t, const EigMat1& A, const EigMat2& B) { */ template * = nullptr, - require_any_not_same_t, value_type_t>* = nullptr> + require_any_not_same_t, + value_type_t>* = nullptr> inline Eigen::Matrix, Eigen::Dynamic, EigMat2::ColsAtCompileTime> scale_matrix_exp_multiply(const Tt& t, const EigMat1& A, const EigMat2& B) { diff --git a/stan/math/rev/core/grad.hpp b/stan/math/rev/core/grad.hpp index cb62d333772..cd22f8c9a04 100644 --- a/stan/math/rev/core/grad.hpp +++ b/stan/math/rev/core/grad.hpp @@ -27,7 +27,7 @@ namespace math { * @param vi Variable implementation for root of partial * derivative propagation. */ -template * = nullptr> +template static void grad(Vari* vi) { vi->init_dependent(); std::vector& var_stack = ChainableStack::instance_->var_stack_; diff --git a/stan/math/rev/core/operator_divide_equal.hpp b/stan/math/rev/core/operator_divide_equal.hpp index 531ee676004..25d0ae082bd 100644 --- a/stan/math/rev/core/operator_divide_equal.hpp +++ b/stan/math/rev/core/operator_divide_equal.hpp @@ -8,7 +8,8 @@ namespace stan { namespace math { template -template >*> +template >*> inline var_value& var_value::operator/=(const var_value& b) { vi_ = new internal::divide_vv_vari(vi_, b.vi_); return *this; diff --git a/stan/math/rev/core/operator_equal.hpp b/stan/math/rev/core/operator_equal.hpp index 28140c8b484..d47ea6f473a 100644 --- a/stan/math/rev/core/operator_equal.hpp +++ b/stan/math/rev/core/operator_equal.hpp @@ -24,7 +24,9 @@ namespace math { * @return True if the first variable's value is the same as the * second's. */ -inline bool operator==(const var& a, const var& b) { return a.val() == b.val(); } +inline bool operator==(const var& a, const var& b) { + return a.val() == b.val(); +} /** * Equality operator comparing a variable's value and a double diff --git a/stan/math/rev/core/operator_greater_than_or_equal.hpp b/stan/math/rev/core/operator_greater_than_or_equal.hpp index 356816f84c1..10607dba3ed 100644 --- a/stan/math/rev/core/operator_greater_than_or_equal.hpp +++ b/stan/math/rev/core/operator_greater_than_or_equal.hpp @@ -25,7 +25,9 @@ namespace math { * @return True if first variable's value is greater than or equal * to the second's. */ -inline bool operator>=(const var& a, const var& b) { return a.val() >= b.val(); } +inline bool operator>=(const var& a, const var& b) { + return a.val() >= b.val(); +} /** * Greater than or equal operator comparing variable's value and diff --git a/stan/math/rev/core/operator_less_than_or_equal.hpp b/stan/math/rev/core/operator_less_than_or_equal.hpp index a5a50f8975c..026af410cff 100644 --- a/stan/math/rev/core/operator_less_than_or_equal.hpp +++ b/stan/math/rev/core/operator_less_than_or_equal.hpp @@ -24,7 +24,9 @@ namespace math { * @return True if first variable's value is less than or equal to * the second's. */ -inline bool operator<=(const var& a, const var& b) { return a.val() <= b.val(); } +inline bool operator<=(const var& a, const var& b) { + return a.val() <= b.val(); +} /** * Less than or equal operator comparing a variable's value and a diff --git a/stan/math/rev/core/operator_logical_and.hpp b/stan/math/rev/core/operator_logical_and.hpp index 80cf247186d..02be3386298 100644 --- a/stan/math/rev/core/operator_logical_and.hpp +++ b/stan/math/rev/core/operator_logical_and.hpp @@ -15,7 +15,9 @@ namespace math { * @param[in] y second argument * @return conjunction of the arguments' values */ -inline bool operator&&(const var& x, const var& y) { return x.val() && y.val(); } +inline bool operator&&(const var& x, const var& y) { + return x.val() && y.val(); +} /** * Return the logical conjunction of the values of the two diff --git a/stan/math/rev/core/operator_logical_or.hpp b/stan/math/rev/core/operator_logical_or.hpp index a4f1f8ab14c..ee8b4e85f0a 100644 --- a/stan/math/rev/core/operator_logical_or.hpp +++ b/stan/math/rev/core/operator_logical_or.hpp @@ -15,7 +15,9 @@ namespace math { * @param[in] y second argument * @return disjunction of the arguments' values */ -inline bool operator||(const var& x, const var& y) { return x.val() || y.val(); } +inline bool operator||(const var& x, const var& y) { + return x.val() || y.val(); +} /** * Return the logical disjunction of the values of the two diff --git a/stan/math/rev/core/operator_minus_equal.hpp b/stan/math/rev/core/operator_minus_equal.hpp index 3990c103f8b..23f6ef74bc7 100644 --- a/stan/math/rev/core/operator_minus_equal.hpp +++ b/stan/math/rev/core/operator_minus_equal.hpp @@ -9,7 +9,8 @@ namespace stan { namespace math { template -template >*> +template >*> inline var_value& var_value::operator-=(const var_value& b) { vi_ = new internal::subtract_vv_vari(vi_, b.vi_); return *this; diff --git a/stan/math/rev/core/operator_multiply_equal.hpp b/stan/math/rev/core/operator_multiply_equal.hpp index 302af7d612f..b8abd44df25 100644 --- a/stan/math/rev/core/operator_multiply_equal.hpp +++ b/stan/math/rev/core/operator_multiply_equal.hpp @@ -9,7 +9,8 @@ namespace stan { namespace math { template -template >*> +template >*> inline var_value& var_value::operator*=(const var_value& b) { vi_ = new internal::multiply_vv_vari(vi_, b.vi_); return *this; diff --git a/stan/math/rev/core/operator_not_equal.hpp b/stan/math/rev/core/operator_not_equal.hpp index d7591eacfbb..b4f41b576d8 100644 --- a/stan/math/rev/core/operator_not_equal.hpp +++ b/stan/math/rev/core/operator_not_equal.hpp @@ -27,7 +27,9 @@ namespace math { * @return True if the first variable's value is not the same as the * second's. */ -inline bool operator!=(const var& a, const var& b) { return a.val() != b.val(); } +inline bool operator!=(const var& a, const var& b) { + return a.val() != b.val(); +} /** * Inequality operator comparing a variable's value and a double diff --git a/stan/math/rev/core/operator_plus_equal.hpp b/stan/math/rev/core/operator_plus_equal.hpp index 85d91100d78..e9c38129c40 100644 --- a/stan/math/rev/core/operator_plus_equal.hpp +++ b/stan/math/rev/core/operator_plus_equal.hpp @@ -9,7 +9,8 @@ namespace stan { namespace math { template -template >*> +template >*> inline var_value& var_value::operator+=(const var_value& b) { vi_ = new internal::add_vv_vari(vi_, b.vi_); return *this; diff --git a/stan/math/rev/core/precomp_vv_vari.hpp b/stan/math/rev/core/precomp_vv_vari.hpp index b5d2e512bee..f65e41605be 100644 --- a/stan/math/rev/core/precomp_vv_vari.hpp +++ b/stan/math/rev/core/precomp_vv_vari.hpp @@ -8,7 +8,7 @@ namespace stan { namespace math { // use for single precomputed partials -class precomp_vv_vari : public op_vv_vari { +class precomp_vv_vari final : public op_vv_vari { protected: double da_; double db_; diff --git a/stan/math/rev/core/std_iterator_traits.hpp b/stan/math/rev/core/std_iterator_traits.hpp index 9194128965c..09560538e88 100644 --- a/stan/math/rev/core/std_iterator_traits.hpp +++ b/stan/math/rev/core/std_iterator_traits.hpp @@ -36,7 +36,6 @@ struct iterator_traits> { * Type of reference to variables. */ typedef stan::math::var_value& reference; - }; } // namespace std diff --git a/stan/math/rev/core/std_numeric_limits.hpp b/stan/math/rev/core/std_numeric_limits.hpp index 79fe01fc701..6e3ba21ead7 100644 --- a/stan/math/rev/core/std_numeric_limits.hpp +++ b/stan/math/rev/core/std_numeric_limits.hpp @@ -16,8 +16,12 @@ template struct numeric_limits> { typedef stan::math::internal::floating_point_promoter value_type; static constexpr bool is_specialized = true; - static constexpr stan::math::var_value min() noexcept { return numeric_limits::min(); } - static constexpr stan::math::var_value max() noexcept { return numeric_limits::max(); } + static constexpr stan::math::var_value min() noexcept { + return numeric_limits::min(); + } + static constexpr stan::math::var_value max() noexcept { + return numeric_limits::max(); + } static constexpr int digits = numeric_limits::digits; static constexpr int digits10 = numeric_limits::digits10; static constexpr int max_digits10 = numeric_limits::max_digits10; @@ -25,7 +29,9 @@ struct numeric_limits> { static constexpr bool is_integer = numeric_limits::is_integer; static constexpr bool is_exact = numeric_limits::is_exact; static constexpr int radix = numeric_limits::radix; - static constexpr stan::math::var_value epsilon() noexcept { return numeric_limits::epsilon(); } + static constexpr stan::math::var_value epsilon() noexcept { + return numeric_limits::epsilon(); + } static constexpr stan::math::var_value round_error() noexcept { return numeric_limits::round_error(); } @@ -34,17 +40,21 @@ struct numeric_limits> { }; static constexpr int min_exponent = numeric_limits::min_exponent; - static constexpr int min_exponent10 = numeric_limits::min_exponent10; + static constexpr int min_exponent10 + = numeric_limits::min_exponent10; static constexpr int max_exponent = numeric_limits::max_exponent; - static constexpr int max_exponent10 = numeric_limits::max_exponent10; + static constexpr int max_exponent10 + = numeric_limits::max_exponent10; static constexpr bool has_infinity = numeric_limits::has_infinity; - static constexpr bool has_quiet_NaN = numeric_limits::has_quiet_NaN; + static constexpr bool has_quiet_NaN + = numeric_limits::has_quiet_NaN; static constexpr bool has_signaling_NaN = numeric_limits::has_signaling_NaN; static constexpr float_denorm_style has_denorm = numeric_limits::has_denorm; - static constexpr bool has_denorm_loss = numeric_limits::has_denorm_loss; + static constexpr bool has_denorm_loss + = numeric_limits::has_denorm_loss; static constexpr stan::math::var_value infinity() noexcept { return numeric_limits::infinity(); } @@ -63,7 +73,8 @@ struct numeric_limits> { static constexpr bool is_modulo = numeric_limits::is_modulo; static constexpr bool traps = numeric_limits::traps; - static constexpr bool tinyness_before = numeric_limits::tinyness_before; + static constexpr bool tinyness_before + = numeric_limits::tinyness_before; static constexpr float_round_style round_style = numeric_limits::round_style; }; diff --git a/stan/math/rev/core/var.hpp b/stan/math/rev/core/var.hpp index 6aae6529e66..76b18cd5497 100644 --- a/stan/math/rev/core/var.hpp +++ b/stan/math/rev/core/var.hpp @@ -5,6 +5,7 @@ #include #include #include +#include #include #include @@ -12,7 +13,8 @@ namespace stan { namespace math { // forward declare -static void grad(vari_base* vi); +template +static void grad(Vari* vi); /** * Independent (input) and dependent (output) variables for gradients. @@ -21,7 +23,7 @@ static void grad(vari_base* vi); * an arena-based memory manager scoped to a single gradient * calculation. * - * A var is constructed with a double and used like any + * A var is constructed with a type `T` and used like any * other scalar. Arithmetical functions like negation, addition, * and subtraction, as well as a range of mathematical functions * like exponentiation and powers are overridden to operate on @@ -30,16 +32,18 @@ static void grad(vari_base* vi); */ template class var_value { - public: - /** FIXME: This changes integral (int etc) types to double and leaves the type - * untouched otherwise. Since this can be an Eigen matrix it's a pretty - * dumb name. Just for the purposes of readability it may be better to - * use SFINAE on var_value and have a scalar and eigen representation. - * that would also get rid of some of the weirder requires here. - */ + // The internal value_type is always a floating point type using value_type = internal::floating_point_promoter; using vari_type = vari_value; + + template + using require_vari_convertible_t + = require_t*, vari_type*>>; + template + using require_not_vari_convertible_t = require_t< + bool_constant*, vari_type*>::value>>; + /** * Pointer to the implementation of this variable. * @@ -58,9 +62,7 @@ class var_value { * @return true if this variable does not yet have * a defined variable. */ - bool is_uninitialized() { - return (vi_ == static_cast(nullptr)); - } + bool is_uninitialized() { return (vi_ == static_cast(nullptr)); } /** * Construct a variable for later assignment. @@ -72,74 +74,68 @@ class var_value { var_value() : vi_(static_cast(nullptr)) {} /** - * Construct a variable from a pointer to a variable implementation. - * @tparam VariValue A vari_value whose pointer can be implicitly converted - * to vari_value*. - * @param vi Vari type. + * Construct a variable from the specified arithmetic type argument + * by constructing a new `vari_value`. For integral types the + * `vari_value` will hold doubles. This constructor is only valid + * when `S` is convertible to this `vari_value`'s `value_type`. + * @tparam S A type that is convertible to `value_type`. + * @param x Value of the variable. */ - template * = nullptr> - var_value(vari_value* vi) : vi_(vi) {} // NOLINT + template * = nullptr> + var_value(S x) : vi_(new vari_type(x, false)) {} // NOLINT /** * Construct a variable from a pointer to a variable implementation. - * @tparam VariValue A vari_value whose pointer can be implicitly converted - * to vari_value*. - * @param vi Vari type. + * @tparam S The type in the vari_value pointer that has the same `value_type` + * as this `var_value`. For integral types a `vari_value` is the + * same as `vari_value` so can be `reinterpret_cast` without a copy. + * @param vi A vari_value pointer. */ - template * = nullptr, - require_not_same_t* = nullptr> - var_value(vari_value* vi) : vi_(new vari_type(vi->val_, false)) { // NOLINT - this->vi_->adj_ = vi->adj_; - } + template , + require_vari_convertible_t* = nullptr> + var_value(vari_value* vi) // NOLINT + : vi_(reinterpret_cast(vi)) {} /** - * Construct a variable from the specified integral type argument - * by constructing a new `vari_value`. For integral types the - * `vari_value` will hold doubles. This constructor is only valid when - * `T` is arithmetic. - * @tparam IntegralT Integral type such as `int` - * @tparam T1 A dummy template whose value will always be `T` - * @param x Value of the variable. + * Construct a variable from a pointer to a variable implementation when. + * the `value_type`s differ. This forces a copy of the vari + * @tparam S the type in the vari_value* that does not have the same type + * as the `value_type` of this `var_value`. + * @param vi A `vari_value`. */ - template * = nullptr> - var_value(S x) : vi_(new vari_type(x, false)) {} // NOLINT + template , + require_not_vari_convertible_t* = nullptr> + var_value(vari_value* vi) : vi_(new vari_type(*vi)) {} // NOLINT /** * Construct from a var_value whose underlying value_type differs in type - * to this class's value_type. - * `var_value a(var_value(b));`` - * @tparam S An arithmetic type that is convertible to `T` but is not the + * to this class's value_type. This is for cases such as + * `var_value a(5.0); var_value b(a);` + * @tparam S A type that is not the same as the underlying value type. * same as the underlying value_type. * param x a `var_value` whose underlying vari_type can be dynamically cast * to `this::vari_value``. */ - template , - require_not_same_t* = nullptr> - var_value(var_value& x) : vi_(new vari_type(x.val(), false)) { // NOLINT - this->vi_->adj_ = x.adj(); - } - /** - * Same as the floating point - */ - template , - require_not_same_t* = nullptr> - var_value(var_value&& x) : vi_(new vari_type(x.val(), false)) { // NOLINT - this->vi_->adj_ = x.adj(); - } + template , + require_not_vari_convertible_t* = nullptr> + var_value(var_value& x) : vi_(new vari_type(*x.vi_)) {} // NOLINT + + template , + require_not_vari_convertible_t* = nullptr> + var_value(var_value&& x) : vi_(new vari_type(*x.vi_)) {} // NOLINT /** * Constructor from `var_value` whose value_type is the same as this class's * `value_type`. This is used in cases such as - * `var_value(var_value(4.0))` since the `value_type` for a - * `var_value` with an arithmetic type is a double. + * `var_value a(4.0); var_value b(a)` since the `value_type` for + * a `var_value` with an integral type is a double. */ - template , - require_same_t* = nullptr> + template , + require_vari_convertible_t* = nullptr> var_value(var_value& x) : vi_(x.vi_) {} // NOLINT - - template , - require_same_t* = nullptr> - var_value(var_value&& x) : vi_(x.vi_) {} // NOLINT + template , + require_vari_convertible_t* = nullptr> + var_value(var_value&& x) : vi_(x.vi_) {} // NOLINT /** * Return the value of this variable. @@ -223,11 +219,13 @@ class var_value { * then (a += b) behaves exactly the same way as (a = a + b), * creating an intermediate variable representing (a + b). * - * @tparam S a type that is convertible to `T` + * @tparam S a type that is convertible to `value_type` * @param b The variable to add to this variable. * @return The result of adding the specified variable to this variable. */ - template >* = nullptr> + template >* = nullptr> inline var_value& operator+=(const var_value& b); /** @@ -237,6 +235,7 @@ class var_value { * (a += b) behaves exactly the same way as (a = a + b). Note * that the result is an assignable lvalue. * + * @tparam Arith An arithmetic type * @param b The scalar to add to this variable. * @return The result of adding the specified variable to this variable. */ @@ -250,12 +249,14 @@ class var_value { * then (a -= b) behaves exactly the same way as (a = a - b). * Note that the result is an assignable lvalue. * - * @tparam S a type that is convertible to `T` + * @tparam S a type that is convertible to `value_type` * @param b The variable to subtract from this variable. * @return The result of subtracting the specified variable from * this variable. */ - template >* = nullptr> + template >* = nullptr> inline var_value& operator-=(const var_value& b); /** @@ -265,6 +266,7 @@ class var_value { * (a -= b) behaves exactly the same way as (a = a - b). Note * that the result is an assignable lvalue. * + * @tparam Arith An arithmetic type * @param b The scalar to subtract from this variable. * @return The result of subtracting the specified variable from this * variable. @@ -279,12 +281,14 @@ class var_value { * then (a *= b) behaves exactly the same way as (a = a * b). * Note that the result is an assignable lvalue. * - * @tparam S a type that is convertible to `T` + * @tparam S a type that is convertible to `value_type` * @param b The variable to multiply this variable by. * @return The result of multiplying this variable by the * specified variable. */ - template >* = nullptr> + template >* = nullptr> inline var_value& operator*=(const var_value& b); /** @@ -294,6 +298,7 @@ class var_value { * (a *= b) behaves exactly the same way as (a = a * b). Note * that the result is an assignable lvalue. * + * @tparam Arith An arithmetic type * @param b The scalar to multiply this variable by. * @return The result of multiplying this variable by the specified * variable. @@ -307,12 +312,14 @@ class var_value { * behaves exactly the same way as (a = a / b). Note that the * result is an assignable lvalue. * - * @tparam S a type that is convertible to `T` + * @tparam S a type that is convertible to `value_type` * @param b The variable to divide this variable by. * @return The result of dividing this variable by the * specified variable. */ - template >* = nullptr> + template >* = nullptr> inline var_value& operator/=(const var_value& b); /** @@ -322,6 +329,7 @@ class var_value { * (a /= b) behaves exactly the same way as (a = a / b). Note * that the result is an assignable lvalue. * + * @tparam Arith An arithmetic type * @param b The scalar to divide this variable by. * @return The result of dividing this variable by the specified * variable. @@ -343,7 +351,6 @@ class var_value { } return os << v.val(); } - }; // For backwards compatability the default value is double diff --git a/stan/math/rev/core/vari.hpp b/stan/math/rev/core/vari.hpp index 4e4bd589465..9720d7b8132 100644 --- a/stan/math/rev/core/vari.hpp +++ b/stan/math/rev/core/vari.hpp @@ -22,7 +22,7 @@ class vari_base { * Apply the chain rule to this variable based on the variables * on which it depends. */ - virtual void chain() {}; + virtual void chain() {} /** * Set the adjoint value of this variable to 0. This is used to @@ -42,15 +42,15 @@ class vari_base { }; namespace internal { - /** - * Promote integral types to double - * @tparam Val Any type - */ - template - using floating_point_promoter - = std::conditional_t>::value, double, - std::decay_t>; -} +/** + * Promote integral types to double + * @tparam Val Any type + */ +template +using floating_point_promoter + = std::conditional_t>::value, double, + std::decay_t>; +} // namespace internal /** * The variable implementation base class. @@ -77,6 +77,7 @@ class vari_value::value>> private: template friend class var_value; + public: using Scalar = internal::floating_point_promoter; using value_type = Scalar; @@ -104,8 +105,9 @@ class vari_value::value>> * @tparam S an Arithmetic type. * @param x Value of the constructed variable. */ - template ::value>* = nullptr> - vari_value(S x) : val_(x), adj_(0.0) { + template ::value>* = nullptr> + vari_value(S x) : val_(x), adj_(0.0) { // NOLINT ChainableStack::instance_->var_stack_.push_back(this); } @@ -126,8 +128,9 @@ class vari_value::value>> * @param stacked If true will put this this vari on the nochain stack so that * it's `chain()` method is not called. */ - template ::value>* = nullptr> - vari_value(S x, bool stacked) : val_(x), adj_(0.0) { + template ::value>* = nullptr> + vari_value(S x, bool stacked) : val_(x), adj_(0.0) { if (stacked) { ChainableStack::instance_->var_stack_.push_back(this); } else { @@ -135,6 +138,23 @@ class vari_value::value>> } } + /** + * Constructor from vari_value + * @tparam S An arithmetic type + * @param x A vari_value + */ + template ::value>* = nullptr> + vari_value(vari_value& x) : val_(x.val_), adj_(x.adj_) { + ChainableStack::instance_->var_stack_.push_back(this); + } + + template ::value>* = nullptr> + vari_value(vari_value&& x) : val_(x.val_), adj_(x.adj_) { + ChainableStack::instance_->var_stack_.push_back(this); + } + /** * Initialize the adjoint for this (dependent) variable to 1. * This operation is applied to the dependent variable before diff --git a/stan/math/rev/core/vector_vari.hpp b/stan/math/rev/core/vector_vari.hpp index 55de53af4a8..57f7ebed6c6 100644 --- a/stan/math/rev/core/vector_vari.hpp +++ b/stan/math/rev/core/vector_vari.hpp @@ -15,7 +15,8 @@ class op_vector_vari : public vari { vari** vis_; public: - template * = nullptr, + template * = nullptr, require_vector_like_vt* = nullptr> op_vector_vari(Arith f, VecVar&& vs) : vari(f), size_(vs.size()) { vis_ = reinterpret_cast(operator new(sizeof(vari*) * vs.size())); diff --git a/stan/math/rev/meta/is_var.hpp b/stan/math/rev/meta/is_var.hpp index a44745393c9..e4d9fa54fed 100644 --- a/stan/math/rev/meta/is_var.hpp +++ b/stan/math/rev/meta/is_var.hpp @@ -8,17 +8,19 @@ namespace stan { namespace internal { - template - struct is_var_impl : std::false_type {}; +template +struct is_var_impl : std::false_type {}; - template - struct is_var_impl> : std::true_type {}; -} +template +struct is_var_impl> : std::true_type {}; +} // namespace internal /** \ingroup type_trait * Specialization for checking if value of T minus cv qualifier is a var_value. */ template -struct is_var>::value>> : std::true_type {}; +struct is_var>::value>> + : std::true_type {}; } // namespace stan #endif diff --git a/test/unit/math/rev/core/var_test.cpp b/test/unit/math/rev/core/var_test.cpp index 6284ce983bd..b33361cbd37 100644 --- a/test/unit/math/rev/core/var_test.cpp +++ b/test/unit/math/rev/core/var_test.cpp @@ -19,24 +19,26 @@ void ctor_overloads_impl() { using stan::math::var_value; using stan::math::vari_value; using stan::math::test::type_name; + // standard constructor + EXPECT_FLOAT_EQ(3.7, var_value(3.7).val()) + << "Failed For T: " << type_name() << " and S: " << type_name() + << "\n"; // make sure copy ctor is used rather than casting vari* to unsigned int - EXPECT_FLOAT_EQ(12.3, var_value(new vari_value(12.3)).val()) << - "Failed For T: " << type_name() << " and S: " << type_name() << "\n"; - - EXPECT_FLOAT_EQ(12.3, var_value(var_value(12.3)).val()) << - "Failed For T: " << type_name() << " and S: " << type_name() << "\n"; - - EXPECT_FLOAT_EQ(static_cast(3.7), var_value(static_cast(3.7)).val()) << - "Failed For T: " << type_name() << " and S: " << type_name() << "\n"; - // double - EXPECT_FLOAT_EQ(3.7, var_value(3.7).val()) << - "Failed For T: " << type_name() << " and S: " << type_name() << "\n"; - // long double - EXPECT_FLOAT_EQ(static_cast(3.7), var_value(static_cast(3.7)).val()) << - "Failed For T: " << type_name() << " and S: " << type_name() << "\n"; - EXPECT_FLOAT_EQ(0, var_value(static_cast(0)).val()) << - "Failed For T: " << type_name() << " and S:" << type_name() << "\n"; - + EXPECT_FLOAT_EQ(12.3, var_value(new vari_value(12.3)).val()) + << "Failed For T: " << type_name() << " and S: " << type_name() + << "\n"; + // make sure rvalue var_value can be accepted + EXPECT_FLOAT_EQ(12.3, var_value(var_value(12.3)).val()) + << "Failed For T: " << type_name() << " and S: " << type_name() + << "\n"; + // S type is preserved + EXPECT_FLOAT_EQ(static_cast(3.7), var_value(static_cast(3.7)).val()) + << "Failed For T: " << type_name() << " and S: " << type_name() + << "\n"; + // Make sure integral types don't hold a nullptr instead of zero. + EXPECT_FLOAT_EQ(0, var_value(static_cast(0)).val()) + << "Failed For T: " << type_name() << " and S:" << type_name() + << "\n"; } template diff --git a/test/unit/math/rev/meta/is_var_test.cpp b/test/unit/math/rev/meta/is_var_test.cpp index 2a3f4e19a79..fd74125efa7 100644 --- a/test/unit/math/rev/meta/is_var_test.cpp +++ b/test/unit/math/rev/meta/is_var_test.cpp @@ -3,5 +3,12 @@ TEST(MetaTraitsRevScal, is_var) { using stan::is_var; + using stan::math::var_value; + using stan::math::var; EXPECT_TRUE(is_var::value); + EXPECT_TRUE((is_var>::value)); + EXPECT_TRUE((is_var>::value)); + EXPECT_FALSE(is_var::value); + EXPECT_FALSE((is_var::value)); + EXPECT_FALSE((is_var>::value)); } diff --git a/test/unit/math/rev/meta/is_vari_test.cpp b/test/unit/math/rev/meta/is_vari_test.cpp new file mode 100644 index 00000000000..14574c32a14 --- /dev/null +++ b/test/unit/math/rev/meta/is_vari_test.cpp @@ -0,0 +1,14 @@ +#include +#include + +TEST(MetaTraitsRevScal, is_vari) { + using stan::is_vari; + using stan::math::vari_value; + using stan::math::vari; + EXPECT_TRUE(is_vari::value); + EXPECT_TRUE((is_vari>::value)); + EXPECT_TRUE((is_vari>::value)); + EXPECT_FALSE(is_vari::value); + EXPECT_FALSE((is_vari::value)); + EXPECT_FALSE((is_vari>::value)); +} From 92630dd3d5dedc6696ca902c433fe73aa821e469 Mon Sep 17 00:00:00 2001 From: Steve Bronder Date: Fri, 29 May 2020 17:58:42 -0400 Subject: [PATCH 017/355] add ref to require_convertible check in vari constructors --- stan/math/rev/core/vari.hpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/stan/math/rev/core/vari.hpp b/stan/math/rev/core/vari.hpp index 9720d7b8132..2f9ed9b56fc 100644 --- a/stan/math/rev/core/vari.hpp +++ b/stan/math/rev/core/vari.hpp @@ -106,7 +106,7 @@ class vari_value::value>> * @param x Value of the constructed variable. */ template ::value>* = nullptr> + std::enable_if_t::value>* = nullptr> vari_value(S x) : val_(x), adj_(0.0) { // NOLINT ChainableStack::instance_->var_stack_.push_back(this); } @@ -129,7 +129,7 @@ class vari_value::value>> * it's `chain()` method is not called. */ template ::value>* = nullptr> + std::enable_if_t::value>* = nullptr> vari_value(S x, bool stacked) : val_(x), adj_(0.0) { if (stacked) { ChainableStack::instance_->var_stack_.push_back(this); From 2dfa329a9cd29fdf153966dc970788c791e52dea Mon Sep 17 00:00:00 2001 From: Stan Jenkins Date: Fri, 29 May 2020 22:45:11 -0400 Subject: [PATCH 018/355] [Jenkins] auto-formatting by clang-format version 6.0.0-1ubuntu2 (tags/RELEASE_600/final) --- stan/math/prim/fun/scale_matrix_exp_multiply.hpp | 4 ++-- stan/math/prim/meta/is_var.hpp | 1 - stan/math/prim/meta/is_vari.hpp | 1 - stan/math/rev/core/var.hpp | 2 +- stan/math/rev/core/vari.hpp | 2 +- stan/math/rev/fun/value_of.hpp | 4 +++- stan/math/rev/fun/value_of_rec.hpp | 4 +++- stan/math/rev/meta/is_vari.hpp | 1 - test/unit/math/rev/meta/is_var_test.cpp | 2 +- test/unit/math/rev/meta/is_vari_test.cpp | 2 +- 10 files changed, 12 insertions(+), 11 deletions(-) diff --git a/stan/math/prim/fun/scale_matrix_exp_multiply.hpp b/stan/math/prim/fun/scale_matrix_exp_multiply.hpp index 217c7c8b6a2..5b21af83058 100644 --- a/stan/math/prim/fun/scale_matrix_exp_multiply.hpp +++ b/stan/math/prim/fun/scale_matrix_exp_multiply.hpp @@ -27,7 +27,7 @@ namespace math { template * = nullptr, require_all_same_t, - value_type_t>* = nullptr> + value_type_t>* = nullptr> inline Eigen::Matrix scale_matrix_exp_multiply(const double& t, const EigMat1& A, const EigMat2& B) { check_square("scale_matrix_exp_multiply", "input matrix", A); @@ -56,7 +56,7 @@ scale_matrix_exp_multiply(const double& t, const EigMat1& A, const EigMat2& B) { template * = nullptr, require_any_not_same_t, - value_type_t>* = nullptr> + value_type_t>* = nullptr> inline Eigen::Matrix, Eigen::Dynamic, EigMat2::ColsAtCompileTime> scale_matrix_exp_multiply(const Tt& t, const EigMat1& A, const EigMat2& B) { diff --git a/stan/math/prim/meta/is_var.hpp b/stan/math/prim/meta/is_var.hpp index db87cc9e2ee..d9264d0afeb 100644 --- a/stan/math/prim/meta/is_var.hpp +++ b/stan/math/prim/meta/is_var.hpp @@ -17,7 +17,6 @@ STAN_ADD_REQUIRE_UNARY(var, is_var, require_stan_scalar_real); STAN_ADD_REQUIRE_CONTAINER(var, is_var, require_stan_scalar_real); STAN_ADD_REQUIRE_UNARY_INNER(var, is_var, require_stan_scalar_real); - template struct value_type::value>> { using type = typename std::decay_t::value_type; diff --git a/stan/math/prim/meta/is_vari.hpp b/stan/math/prim/meta/is_vari.hpp index db82abbf9a9..4ee384a303c 100644 --- a/stan/math/prim/meta/is_vari.hpp +++ b/stan/math/prim/meta/is_vari.hpp @@ -14,6 +14,5 @@ struct is_vari : std::false_type {}; STAN_ADD_REQUIRE_UNARY(vari, is_vari, require_stan_scalar_real); STAN_ADD_REQUIRE_CONTAINER(vari, is_vari, require_stan_scalar_real); - } // namespace stan #endif diff --git a/stan/math/rev/core/var.hpp b/stan/math/rev/core/var.hpp index 76b18cd5497..564deb7b606 100644 --- a/stan/math/rev/core/var.hpp +++ b/stan/math/rev/core/var.hpp @@ -93,7 +93,7 @@ class var_value { */ template , require_vari_convertible_t* = nullptr> - var_value(vari_value* vi) // NOLINT + var_value(vari_value* vi) // NOLINT : vi_(reinterpret_cast(vi)) {} /** diff --git a/stan/math/rev/core/vari.hpp b/stan/math/rev/core/vari.hpp index 2f9ed9b56fc..edfd0672a47 100644 --- a/stan/math/rev/core/vari.hpp +++ b/stan/math/rev/core/vari.hpp @@ -107,7 +107,7 @@ class vari_value::value>> */ template ::value>* = nullptr> - vari_value(S x) : val_(x), adj_(0.0) { // NOLINT + vari_value(S x) : val_(x), adj_(0.0) { // NOLINT ChainableStack::instance_->var_stack_.push_back(this); } diff --git a/stan/math/rev/fun/value_of.hpp b/stan/math/rev/fun/value_of.hpp index 162a9834618..b44578eb955 100644 --- a/stan/math/rev/fun/value_of.hpp +++ b/stan/math/rev/fun/value_of.hpp @@ -21,7 +21,9 @@ namespace math { * @return Value of variable. */ template -inline auto value_of(const var_value& v) { return v.vi_->val_; } +inline auto value_of(const var_value& v) { + return v.vi_->val_; +} } // namespace math } // namespace stan diff --git a/stan/math/rev/fun/value_of_rec.hpp b/stan/math/rev/fun/value_of_rec.hpp index 5f6a477d86b..e02ff980afe 100644 --- a/stan/math/rev/fun/value_of_rec.hpp +++ b/stan/math/rev/fun/value_of_rec.hpp @@ -15,7 +15,9 @@ namespace math { * @return Value of variable. */ template -inline auto value_of_rec(const var_value& v) { return v.vi_->val_; } +inline auto value_of_rec(const var_value& v) { + return v.vi_->val_; +} } // namespace math } // namespace stan diff --git a/stan/math/rev/meta/is_vari.hpp b/stan/math/rev/meta/is_vari.hpp index 84c5d79cb85..c91364bbe3c 100644 --- a/stan/math/rev/meta/is_vari.hpp +++ b/stan/math/rev/meta/is_vari.hpp @@ -16,6 +16,5 @@ struct is_vari< math::vari_base, std::remove_pointer_t>>::value>> : std::true_type {}; - } // namespace stan #endif diff --git a/test/unit/math/rev/meta/is_var_test.cpp b/test/unit/math/rev/meta/is_var_test.cpp index fd74125efa7..75ef61d9596 100644 --- a/test/unit/math/rev/meta/is_var_test.cpp +++ b/test/unit/math/rev/meta/is_var_test.cpp @@ -3,8 +3,8 @@ TEST(MetaTraitsRevScal, is_var) { using stan::is_var; - using stan::math::var_value; using stan::math::var; + using stan::math::var_value; EXPECT_TRUE(is_var::value); EXPECT_TRUE((is_var>::value)); EXPECT_TRUE((is_var>::value)); diff --git a/test/unit/math/rev/meta/is_vari_test.cpp b/test/unit/math/rev/meta/is_vari_test.cpp index 14574c32a14..9b5ab9e90c5 100644 --- a/test/unit/math/rev/meta/is_vari_test.cpp +++ b/test/unit/math/rev/meta/is_vari_test.cpp @@ -3,8 +3,8 @@ TEST(MetaTraitsRevScal, is_vari) { using stan::is_vari; - using stan::math::vari_value; using stan::math::vari; + using stan::math::vari_value; EXPECT_TRUE(is_vari::value); EXPECT_TRUE((is_vari>::value)); EXPECT_TRUE((is_vari>::value)); From f04527225d41a5f4ae3c79a0868651cdcf394df0 Mon Sep 17 00:00:00 2001 From: Steve Bronder Date: Fri, 29 May 2020 23:44:09 -0400 Subject: [PATCH 019/355] fix header check --- stan/math/prim/meta/is_vari.hpp | 1 + 1 file changed, 1 insertion(+) diff --git a/stan/math/prim/meta/is_vari.hpp b/stan/math/prim/meta/is_vari.hpp index 4ee384a303c..b2f31cd27b3 100644 --- a/stan/math/prim/meta/is_vari.hpp +++ b/stan/math/prim/meta/is_vari.hpp @@ -1,6 +1,7 @@ #ifndef STAN_MATH_PRIM_META_IS_VARI_HPP #define STAN_MATH_PRIM_META_IS_VARI_HPP +#include #include namespace stan { From 4b5fc677510e76e1cc43ebeacf765eb8717271f3 Mon Sep 17 00:00:00 2001 From: Steve Bronder Date: Sat, 30 May 2020 00:44:22 -0400 Subject: [PATCH 020/355] Fix templates for hmm --- stan/math/prim/prob/hmm_marginal_lpdf.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stan/math/prim/prob/hmm_marginal_lpdf.hpp b/stan/math/prim/prob/hmm_marginal_lpdf.hpp index 67968c6d9b9..90076649d30 100644 --- a/stan/math/prim/prob/hmm_marginal_lpdf.hpp +++ b/stan/math/prim/prob/hmm_marginal_lpdf.hpp @@ -20,7 +20,7 @@ template * = nullptr, require_all_eigen_col_vector_t* = nullptr, require_stan_scalar_t* = nullptr, - require_all_vt_same* = nullptr> + require_all_same_t, value_type_t, T_norm>* = nullptr> inline auto hmm_marginal_lpdf_val(const T_omega& omegas, const T_Gamma& Gamma_val, const T_rho& rho_val, T_alphas& alphas, From 1fe6e2b85abeb46e1227debdd418c8d2270a5267 Mon Sep 17 00:00:00 2001 From: Stan Jenkins Date: Sat, 30 May 2020 00:45:08 -0400 Subject: [PATCH 021/355] [Jenkins] auto-formatting by clang-format version 6.0.0-1ubuntu2 (tags/RELEASE_600/final) --- stan/math/prim/prob/hmm_marginal_lpdf.hpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/stan/math/prim/prob/hmm_marginal_lpdf.hpp b/stan/math/prim/prob/hmm_marginal_lpdf.hpp index 90076649d30..7166f524e34 100644 --- a/stan/math/prim/prob/hmm_marginal_lpdf.hpp +++ b/stan/math/prim/prob/hmm_marginal_lpdf.hpp @@ -20,7 +20,8 @@ template * = nullptr, require_all_eigen_col_vector_t* = nullptr, require_stan_scalar_t* = nullptr, - require_all_same_t, value_type_t, T_norm>* = nullptr> + require_all_same_t, + value_type_t, T_norm>* = nullptr> inline auto hmm_marginal_lpdf_val(const T_omega& omegas, const T_Gamma& Gamma_val, const T_rho& rho_val, T_alphas& alphas, From b63acdc3e535db419f4d0d4e2d0d668cd80a33b3 Mon Sep 17 00:00:00 2001 From: Steve Bronder Date: Sat, 30 May 2020 02:47:23 -0400 Subject: [PATCH 022/355] add template to lp value in in positive_constrain --- stan/math/prim/fun/positive_constrain.hpp | 4 ++-- stan/math/rev/fun/mdivide_left_tri.hpp | 6 ++---- 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/stan/math/prim/fun/positive_constrain.hpp b/stan/math/prim/fun/positive_constrain.hpp index 87059c835af..8f4ad86965a 100644 --- a/stan/math/prim/fun/positive_constrain.hpp +++ b/stan/math/prim/fun/positive_constrain.hpp @@ -40,8 +40,8 @@ inline auto positive_constrain(const T& x) { * @param lp log density reference. * @return positive constrained version of unconstrained value(s) */ -template -inline auto positive_constrain(const T& x, value_type_t& lp) { +template +inline auto positive_constrain(const T& x, S& lp) { lp += sum(x); return exp(x); } diff --git a/stan/math/rev/fun/mdivide_left_tri.hpp b/stan/math/rev/fun/mdivide_left_tri.hpp index a0c6319a8d1..5858cace163 100644 --- a/stan/math/rev/fun/mdivide_left_tri.hpp +++ b/stan/math/rev/fun/mdivide_left_tri.hpp @@ -337,8 +337,7 @@ mdivide_left_tri(const T1 &A, const T2 &b) { return res; } template * = nullptr, - require_vt_same * = nullptr, + require_eigen_vt * = nullptr, require_eigen_vt * = nullptr> inline Eigen::Matrix mdivide_left_tri(const T1 &A, const T2 &b) { @@ -365,8 +364,7 @@ mdivide_left_tri(const T1 &A, const T2 &b) { } template * = nullptr, - require_eigen_t * = nullptr, - require_vt_same * = nullptr> + require_eigen_vt * = nullptr> inline Eigen::Matrix mdivide_left_tri(const T1 &A, const T2 &b) { check_square("mdivide_left_tri", "A", A); From f20d98aaa047ee64ee32586af763d1cf62771fb9 Mon Sep 17 00:00:00 2001 From: Steve Bronder Date: Sat, 30 May 2020 17:16:46 -0400 Subject: [PATCH 023/355] replace vector func value types in apply_scalar_binary with return type of function --- stan/math/prim/fun/cholesky_decompose.hpp | 14 ++++++-------- stan/math/prim/meta/apply_scalar_binary.hpp | 6 +++--- 2 files changed, 9 insertions(+), 11 deletions(-) diff --git a/stan/math/prim/fun/cholesky_decompose.hpp b/stan/math/prim/fun/cholesky_decompose.hpp index 571fa106f8c..e9e0fd5a3e7 100644 --- a/stan/math/prim/fun/cholesky_decompose.hpp +++ b/stan/math/prim/fun/cholesky_decompose.hpp @@ -29,9 +29,7 @@ namespace math { * @throw std::domain_error if m is not a symmetric matrix or * if m is not positive definite (if m has more than 0 elements) */ -template * = nullptr, - require_not_vt_same* = nullptr, - require_not_eigen_vt* = nullptr> +template * = nullptr> inline Eigen::Matrix, EigMat::RowsAtCompileTime, EigMat::ColsAtCompileTime> cholesky_decompose(const EigMat& m) { @@ -61,11 +59,11 @@ cholesky_decompose(const EigMat& m) { * @throw std::domain_error if m is not a symmetric matrix or * if m is not positive definite (if m has more than 0 elements) */ -template * = nullptr, - require_vt_same* = nullptr> -inline Eigen::Matrix* = nullptr> +inline Eigen::Matrix, EigMat::RowsAtCompileTime, EigMat::ColsAtCompileTime> cholesky_decompose(const EigMat& m) { + using eig_val = value_type_t; eval_return_type_t& m_eval = m.eval(); check_not_nan("cholesky_decompose", "m", m_eval); #ifdef STAN_OPENCL @@ -74,7 +72,7 @@ cholesky_decompose(const EigMat& m) { return from_matrix_cl(cholesky_decompose(m_cl)); } else { check_symmetric("cholesky_decompose", "m", m_eval); - Eigen::LLT> llt = m_eval.llt(); check_pos_definite("cholesky_decompose", "m", llt); @@ -82,7 +80,7 @@ cholesky_decompose(const EigMat& m) { } #else check_symmetric("cholesky_decompose", "m", m_eval); - Eigen::LLT> llt = m_eval.llt(); check_pos_definite("cholesky_decompose", "m", llt); diff --git a/stan/math/prim/meta/apply_scalar_binary.hpp b/stan/math/prim/meta/apply_scalar_binary.hpp index 8e755beb1df..0768fd9b29e 100644 --- a/stan/math/prim/meta/apply_scalar_binary.hpp +++ b/stan/math/prim/meta/apply_scalar_binary.hpp @@ -124,7 +124,7 @@ template ; + using T_return = std::decay_t; std::vector result(x.size()); Eigen::Map>(result.data(), result.size()) = x_vec.binaryExpr(y_vec, f); @@ -154,7 +154,7 @@ template * = nullptr> inline auto apply_scalar_binary(const T1& x, const T2& y, const F& f) { decltype(auto) x_vec = as_column_vector_or_scalar(x); - using T_return = value_type_t; + using T_return = std::decay_t; std::vector result(x.size()); Eigen::Map>(result.data(), result.size()) = x_vec.unaryExpr([&f, &y](const auto& v) { return f(v, y); }); @@ -184,7 +184,7 @@ template * = nullptr> inline auto apply_scalar_binary(const T1& x, const T2& y, const F& f) { decltype(auto) y_vec = as_column_vector_or_scalar(y); - using T_return = value_type_t; + using T_return = std::decay_t; std::vector result(y.size()); Eigen::Map>(result.data(), result.size()) = y_vec.unaryExpr([&f, &x](const auto& v) { return f(x, v); }); From 16db81b55989c118fa02e98a887515d2b0dc664b Mon Sep 17 00:00:00 2001 From: Stan Jenkins Date: Sat, 30 May 2020 17:17:34 -0400 Subject: [PATCH 024/355] [Jenkins] auto-formatting by clang-format version 6.0.0-1ubuntu2 (tags/RELEASE_600/final) --- stan/math/prim/fun/cholesky_decompose.hpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/stan/math/prim/fun/cholesky_decompose.hpp b/stan/math/prim/fun/cholesky_decompose.hpp index e9e0fd5a3e7..aff4ad50235 100644 --- a/stan/math/prim/fun/cholesky_decompose.hpp +++ b/stan/math/prim/fun/cholesky_decompose.hpp @@ -59,7 +59,8 @@ cholesky_decompose(const EigMat& m) { * @throw std::domain_error if m is not a symmetric matrix or * if m is not positive definite (if m has more than 0 elements) */ -template * = nullptr> +template * = nullptr> inline Eigen::Matrix, EigMat::RowsAtCompileTime, EigMat::ColsAtCompileTime> cholesky_decompose(const EigMat& m) { From 4cc404e424e0a6ef358a1967f86d274d7d570beb Mon Sep 17 00:00:00 2001 From: Steve Bronder Date: Mon, 1 Jun 2020 18:51:30 -0400 Subject: [PATCH 025/355] var and vari can only be templated with floating point types. Remove double_promoter and use promote_args instead. Add flto compiler flags for gcc and clang --- make/compiler_flags | 9 +-- stan/math/prim/fun/cholesky_decompose.hpp | 2 +- .../prim/fun/scale_matrix_exp_multiply.hpp | 7 +- stan/math/rev/core/operator_divide_equal.hpp | 6 +- stan/math/rev/core/operator_minus_equal.hpp | 6 +- .../math/rev/core/operator_multiply_equal.hpp | 6 +- stan/math/rev/core/operator_plus_equal.hpp | 6 +- stan/math/rev/core/std_numeric_limits.hpp | 2 +- stan/math/rev/core/var.hpp | 52 +++++++-------- stan/math/rev/core/vari.hpp | 32 +++------- test/unit/math/rev/core/var_test.cpp | 64 ++++++++----------- 11 files changed, 79 insertions(+), 113 deletions(-) diff --git a/make/compiler_flags b/make/compiler_flags index de486bffc43..e64fa6f474f 100644 --- a/make/compiler_flags +++ b/make/compiler_flags @@ -28,7 +28,7 @@ ifeq ($(OS),Linux) LIBRARY_SUFFIX ?= .so endif -## Set default compiler +## Set default compiler and flto compiler flags ifeq (default,$(origin CXX)) ifeq ($(OS),Darwin) ## Darwin is Mac OS X CXX := clang++ @@ -47,15 +47,18 @@ endif # - CXX_MINOR: minor version of CXX ifneq (,$(findstring clang,$(CXX))) CXX_TYPE ?= clang + CXXFLAGS_FLTO := -flto -fwhole-program-vtables -fstrict-vtable-pointers endif ifneq (,$(findstring mingw32-g,$(CXX))) CXX_TYPE ?= mingw32-gcc endif ifneq (,$(findstring gcc,$(CXX))) CXX_TYPE ?= gcc + CXXFLAGS_FLTO := -flto -fuse-linker-plugin -fdevirtualize-at-ltrans -fipa-pta endif ifneq (,$(findstring g++,$(CXX))) CXX_TYPE ?= gcc + CXXFLAGS_FLTO := -flto -fuse-linker-plugin -fdevirtualize-at-ltrans -fipa-pta endif CXX_TYPE ?= other CXX_MAJOR := $(shell $(CXX) -dumpversion 2>&1 | cut -d'.' -f1) @@ -254,9 +257,7 @@ ifdef STAN_MPI CXXFLAGS_MPI ?= -Wno-delete-non-virtual-dtor endif - - -CXXFLAGS += $(CXXFLAGS_LANG) $(CXXFLAGS_OS) $(CXXFLAGS_WARNINGS) $(CXXFLAGS_BOOST) $(CXXFLAGS_EIGEN) $(CXXFLAGS_OPENCL) $(CXXFLAGS_MPI) $(CXXFLAGS_THREADS) $(CXXFLAGS_TBB) -O$(O) $(INC) +CXXFLAGS += $(CXXFLAGS_LANG) $(CXXFLAGS_OS) $(CXXFLAGS_FLTO) $(CXXFLAGS_WARNINGS) $(CXXFLAGS_BOOST) $(CXXFLAGS_EIGEN) $(CXXFLAGS_OPENCL) $(CXXFLAGS_MPI) $(CXXFLAGS_THREADS) $(CXXFLAGS_TBB) -O$(O) $(INC) CPPFLAGS += $(CPPFLAGS_LANG) $(CPPFLAGS_OS) $(CPPFLAGS_WARNINGS) $(CPPFLAGS_BOOST) $(CPPFLAGS_EIGEN) $(CPPFLAGS_OPENCL) $(CPPFLAGS_MPI) $(CPPFLAGS_TBB) LDFLAGS += $(LDFLAGS_LANG) $(LDFLAGS_OS) $(LDFLAGS_WARNINGS) $(LDFLAGS_BOOST) $(LDFLAGS_EIGEN) $(LDFLAGS_OPENCL) $(LDFLAGS_MPI) $(LDFLAGS_TBB) LDLIBS += $(LDLIBS_LANG) $(LDLIBS_OS) $(LDLIBS_WARNINGS) $(LDLIBS_BOOST) $(LDLIBS_EIGEN) $(LDLIBS_OPENCL) $(LDLIBS_MPI) $(LDLIBS_TBB) diff --git a/stan/math/prim/fun/cholesky_decompose.hpp b/stan/math/prim/fun/cholesky_decompose.hpp index aff4ad50235..e227d604eaa 100644 --- a/stan/math/prim/fun/cholesky_decompose.hpp +++ b/stan/math/prim/fun/cholesky_decompose.hpp @@ -68,7 +68,7 @@ cholesky_decompose(const EigMat& m) { eval_return_type_t& m_eval = m.eval(); check_not_nan("cholesky_decompose", "m", m_eval); #ifdef STAN_OPENCL - if (m.rows() >= opencl_context.tuning_opts().cholesky_size_worth_transfer) { + if (std::is_same::value && m.rows() >= opencl_context.tuning_opts().cholesky_size_worth_transfer) { matrix_cl m_cl(m_eval); return from_matrix_cl(cholesky_decompose(m_cl)); } else { diff --git a/stan/math/prim/fun/scale_matrix_exp_multiply.hpp b/stan/math/prim/fun/scale_matrix_exp_multiply.hpp index 5b21af83058..f59aadbd816 100644 --- a/stan/math/prim/fun/scale_matrix_exp_multiply.hpp +++ b/stan/math/prim/fun/scale_matrix_exp_multiply.hpp @@ -25,9 +25,7 @@ namespace math { * @return exponential of At multiplied by B */ template * = nullptr, - require_all_same_t, - value_type_t>* = nullptr> + require_all_eigen_vt* = nullptr> inline Eigen::Matrix scale_matrix_exp_multiply(const double& t, const EigMat1& A, const EigMat2& B) { check_square("scale_matrix_exp_multiply", "input matrix", A); @@ -55,8 +53,7 @@ scale_matrix_exp_multiply(const double& t, const EigMat1& A, const EigMat2& B) { */ template * = nullptr, - require_any_not_same_t, - value_type_t>* = nullptr> + require_any_autodiff_t, value_type_t>* = nullptr> inline Eigen::Matrix, Eigen::Dynamic, EigMat2::ColsAtCompileTime> scale_matrix_exp_multiply(const Tt& t, const EigMat1& A, const EigMat2& B) { diff --git a/stan/math/rev/core/operator_divide_equal.hpp b/stan/math/rev/core/operator_divide_equal.hpp index 25d0ae082bd..0a82b3c0e91 100644 --- a/stan/math/rev/core/operator_divide_equal.hpp +++ b/stan/math/rev/core/operator_divide_equal.hpp @@ -9,15 +9,15 @@ namespace stan { namespace math { template template >*> -inline var_value& var_value::operator/=(const var_value& b) { + require_convertible_t>*> +inline var_value>& var_value>::operator/=(const var_value& b) { vi_ = new internal::divide_vv_vari(vi_, b.vi_); return *this; } template template *> -inline var_value& var_value::operator/=(Arith b) { +inline var_value>& var_value>::operator/=(Arith b) { if (b == 1.0) { return *this; } diff --git a/stan/math/rev/core/operator_minus_equal.hpp b/stan/math/rev/core/operator_minus_equal.hpp index 23f6ef74bc7..fee058d7e9d 100644 --- a/stan/math/rev/core/operator_minus_equal.hpp +++ b/stan/math/rev/core/operator_minus_equal.hpp @@ -10,15 +10,15 @@ namespace math { template template >*> -inline var_value& var_value::operator-=(const var_value& b) { + require_convertible_t>*> +inline var_value>& var_value>::operator-=(const var_value& b) { vi_ = new internal::subtract_vv_vari(vi_, b.vi_); return *this; } template template *> -inline var_value& var_value::operator-=(Arith b) { +inline var_value>& var_value>::operator-=(Arith b) { if (b == 0.0) { return *this; } diff --git a/stan/math/rev/core/operator_multiply_equal.hpp b/stan/math/rev/core/operator_multiply_equal.hpp index b8abd44df25..95176df2ab2 100644 --- a/stan/math/rev/core/operator_multiply_equal.hpp +++ b/stan/math/rev/core/operator_multiply_equal.hpp @@ -10,15 +10,15 @@ namespace math { template template >*> -inline var_value& var_value::operator*=(const var_value& b) { + require_convertible_t>*> +inline var_value>& var_value>::operator*=(const var_value& b) { vi_ = new internal::multiply_vv_vari(vi_, b.vi_); return *this; } template template *> -inline var_value& var_value::operator*=(Arith b) { +inline var_value>& var_value>::operator*=(Arith b) { if (b == 1.0) { return *this; } diff --git a/stan/math/rev/core/operator_plus_equal.hpp b/stan/math/rev/core/operator_plus_equal.hpp index e9c38129c40..5edda2b3d88 100644 --- a/stan/math/rev/core/operator_plus_equal.hpp +++ b/stan/math/rev/core/operator_plus_equal.hpp @@ -10,15 +10,15 @@ namespace math { template template >*> -inline var_value& var_value::operator+=(const var_value& b) { + require_convertible_t>*> +inline var_value>& var_value>::operator+=(const var_value& b) { vi_ = new internal::add_vv_vari(vi_, b.vi_); return *this; } template template *> -inline var_value& var_value::operator+=(Arith b) { +inline var_value>& var_value>::operator+=(Arith b) { if (b == 0.0) { return *this; } diff --git a/stan/math/rev/core/std_numeric_limits.hpp b/stan/math/rev/core/std_numeric_limits.hpp index 6e3ba21ead7..f7cf545f4e7 100644 --- a/stan/math/rev/core/std_numeric_limits.hpp +++ b/stan/math/rev/core/std_numeric_limits.hpp @@ -14,7 +14,7 @@ namespace std { */ template struct numeric_limits> { - typedef stan::math::internal::floating_point_promoter value_type; + typedef stan::promote_args_t value_type; static constexpr bool is_specialized = true; static constexpr stan::math::var_value min() noexcept { return numeric_limits::min(); diff --git a/stan/math/rev/core/var.hpp b/stan/math/rev/core/var.hpp index 564deb7b606..c2fb3b1dc19 100644 --- a/stan/math/rev/core/var.hpp +++ b/stan/math/rev/core/var.hpp @@ -30,11 +30,14 @@ static void grad(Vari* vi); * var values objects. * @tparam T An Arithmetic type. */ +template +class var_value {}; + template -class var_value { +class var_value> { public: // The internal value_type is always a floating point type - using value_type = internal::floating_point_promoter; + using value_type = std::decay_t; using vari_type = vari_value; template @@ -91,10 +94,10 @@ class var_value { * same as `vari_value` so can be `reinterpret_cast` without a copy. * @param vi A vari_value pointer. */ - template , + template , require_vari_convertible_t* = nullptr> var_value(vari_value* vi) // NOLINT - : vi_(reinterpret_cast(vi)) {} + : vi_(vi) {} /** * Construct a variable from a pointer to a variable implementation when. @@ -103,7 +106,7 @@ class var_value { * as the `value_type` of this `var_value`. * @param vi A `vari_value`. */ - template , + template , require_not_vari_convertible_t* = nullptr> var_value(vari_value* vi) : vi_(new vari_type(*vi)) {} // NOLINT @@ -116,13 +119,9 @@ class var_value { * param x a `var_value` whose underlying vari_type can be dynamically cast * to `this::vari_value``. */ - template , - require_not_vari_convertible_t* = nullptr> - var_value(var_value& x) : vi_(new vari_type(*x.vi_)) {} // NOLINT - - template , + template , require_not_vari_convertible_t* = nullptr> - var_value(var_value&& x) : vi_(new vari_type(*x.vi_)) {} // NOLINT + var_value(const var_value& x) : vi_(new vari_type(*x.vi_)) {} // NOLINT /** * Constructor from `var_value` whose value_type is the same as this class's @@ -130,12 +129,9 @@ class var_value { * `var_value a(4.0); var_value b(a)` since the `value_type` for * a `var_value` with an integral type is a double. */ - template , - require_vari_convertible_t* = nullptr> - var_value(var_value& x) : vi_(x.vi_) {} // NOLINT - template , + template , require_vari_convertible_t* = nullptr> - var_value(var_value&& x) : vi_(x.vi_) {} // NOLINT + var_value(const var_value& x) : vi_(x.vi_) {} // NOLINT /** * Return the value of this variable. @@ -225,8 +221,8 @@ class var_value { */ template >* = nullptr> - inline var_value& operator+=(const var_value& b); + S&, promote_args_t>* = nullptr> + inline var_value>& operator+=(const var_value& b); /** * The compound add/assignment operator for scalars (C++). @@ -240,7 +236,7 @@ class var_value { * @return The result of adding the specified variable to this variable. */ template * = nullptr> - inline var_value& operator+=(Arith b); + inline var_value>& operator+=(Arith b); /** * The compound subtract/assignment operator for variables (C++). @@ -256,8 +252,8 @@ class var_value { */ template >* = nullptr> - inline var_value& operator-=(const var_value& b); + S&, promote_args_t>* = nullptr> + inline var_value>& operator-=(const var_value& b); /** * The compound subtract/assignment operator for scalars (C++). @@ -272,7 +268,7 @@ class var_value { * variable. */ template * = nullptr> - inline var_value& operator-=(Arith b); + inline var_value>& operator-=(Arith b); /** * The compound multiply/assignment operator for variables (C++). @@ -288,8 +284,8 @@ class var_value { */ template >* = nullptr> - inline var_value& operator*=(const var_value& b); + S&, promote_args_t>* = nullptr> + inline var_value>& operator*=(const var_value& b); /** * The compound multiply/assignment operator for scalars (C++). @@ -304,7 +300,7 @@ class var_value { * variable. */ template * = nullptr> - inline var_value& operator*=(Arith b); + inline var_value>& operator*=(Arith b); /** * The compound divide/assignment operator for variables (C++). If this @@ -319,8 +315,8 @@ class var_value { */ template >* = nullptr> - inline var_value& operator/=(const var_value& b); + S&, promote_args_t>* = nullptr> + inline var_value>& operator/=(const var_value& b); /** * The compound divide/assignment operator for scalars (C++). @@ -335,7 +331,7 @@ class var_value { * variable. */ template * = nullptr> - inline var_value& operator/=(Arith b); + inline var_value>& operator/=(Arith b); /** * Write the value of this autodiff variable and its adjoint to diff --git a/stan/math/rev/core/vari.hpp b/stan/math/rev/core/vari.hpp index edfd0672a47..726e785ba12 100644 --- a/stan/math/rev/core/vari.hpp +++ b/stan/math/rev/core/vari.hpp @@ -3,6 +3,7 @@ #include #include +#include #include #include @@ -10,11 +11,11 @@ namespace stan { namespace math { // forward declaration of var -template +template class var_value; /** - * Pure virtual class that all `vari_value` and it's derived classes inherit. + * Abstract class that all `vari_value` and it's derived classes inherit. */ class vari_base { public: @@ -41,17 +42,6 @@ class vari_base { virtual ~vari_base() {} }; -namespace internal { -/** - * Promote integral types to double - * @tparam Val Any type - */ -template -using floating_point_promoter - = std::conditional_t>::value, double, - std::decay_t>; -} // namespace internal - /** * The variable implementation base class. * @@ -72,14 +62,14 @@ template class vari_value; template -class vari_value::value>> +class vari_value::value>> : public vari_base { private: - template + template friend class var_value; public: - using Scalar = internal::floating_point_promoter; + using Scalar = T; using value_type = Scalar; /** * The value of this variable. @@ -125,7 +115,7 @@ class vari_value::value>> * * @tparam S an Arithmetic type. * @param x Value of the constructed variable. - * @param stacked If true will put this this vari on the nochain stack so that + * @param stacked If false will put this this vari on the nochain stack so that * it's `chain()` method is not called. */ template ::value>> */ template ::value>* = nullptr> - vari_value(vari_value& x) : val_(x.val_), adj_(x.adj_) { - ChainableStack::instance_->var_stack_.push_back(this); - } - - template ::value>* = nullptr> - vari_value(vari_value&& x) : val_(x.val_), adj_(x.adj_) { + vari_value(const vari_value& x) : val_(x.val_), adj_(x.adj_) { ChainableStack::instance_->var_stack_.push_back(this); } diff --git a/test/unit/math/rev/core/var_test.cpp b/test/unit/math/rev/core/var_test.cpp index b33361cbd37..74567e4aa73 100644 --- a/test/unit/math/rev/core/var_test.cpp +++ b/test/unit/math/rev/core/var_test.cpp @@ -14,22 +14,21 @@ struct AgradRev : public testing::Test { } }; -template -void ctor_overloads_impl() { +template +void ctor_overloads_impl_impl() { using stan::math::var_value; using stan::math::vari_value; using stan::math::test::type_name; // standard constructor EXPECT_FLOAT_EQ(3.7, var_value(3.7).val()) - << "Failed For T: " << type_name() << " and S: " << type_name() - << "\n"; + << "Failed For T: " << type_name() << "\n"; // make sure copy ctor is used rather than casting vari* to unsigned int - EXPECT_FLOAT_EQ(12.3, var_value(new vari_value(12.3)).val()) - << "Failed For T: " << type_name() << " and S: " << type_name() + EXPECT_FLOAT_EQ(12.3, var_value(new vari_value(12.3)).val()) + << "Failed For T: " << type_name() << " and K: " << type_name() << "\n"; // make sure rvalue var_value can be accepted - EXPECT_FLOAT_EQ(12.3, var_value(var_value(12.3)).val()) - << "Failed For T: " << type_name() << " and S: " << type_name() + EXPECT_FLOAT_EQ(12.3, var_value(var_value(12.3)).val()) + << "Failed For T: " << type_name() << " and K: " << type_name() << "\n"; // S type is preserved EXPECT_FLOAT_EQ(static_cast(3.7), var_value(static_cast(3.7)).val()) @@ -41,38 +40,35 @@ void ctor_overloads_impl() { << "\n"; } +template +void ctor_overloads_impl() { + ctor_overloads_impl_impl(); + ctor_overloads_impl_impl(); + ctor_overloads_impl_impl(); + ctor_overloads_impl_impl(); + ctor_overloads_impl_impl(); + ctor_overloads_impl_impl(); + ctor_overloads_impl_impl(); + ctor_overloads_impl_impl(); + ctor_overloads_impl_impl(); + ctor_overloads_impl_impl(); + ctor_overloads_impl_impl(); + ctor_overloads_impl_impl(); + ctor_overloads_impl_impl(); +} template void ctor_overloads() { + ctor_overloads_impl(); ctor_overloads_impl(); ctor_overloads_impl(); - ctor_overloads_impl(); - ctor_overloads_impl(); - ctor_overloads_impl(); - ctor_overloads_impl(); - ctor_overloads_impl(); - ctor_overloads_impl(); - ctor_overloads_impl(); - ctor_overloads_impl(); - ctor_overloads_impl(); - ctor_overloads_impl(); - ctor_overloads_impl(); } + TEST_F(AgradRev, ctorOverloads) { using stan::math::var; using stan::math::vari; + ctor_overloads(); ctor_overloads(); ctor_overloads(); - ctor_overloads(); - ctor_overloads(); - ctor_overloads(); - ctor_overloads(); - ctor_overloads(); - ctor_overloads(); - ctor_overloads(); - ctor_overloads(); - ctor_overloads(); - ctor_overloads(); - ctor_overloads(); } TEST_F(AgradRev, a_eq_x) { @@ -285,11 +281,3 @@ TEST_F(AgradRev, grad) { EXPECT_FLOAT_EQ(11.0, a.adj()); EXPECT_FLOAT_EQ(5.0, b.adj()); } - -TEST_F(AgradRev, type_convs) { - using stan::math::var_value; - var_value a(1); - var_value b(a); - var_value c(a); - var_value d(a); -} From 75910a11cf854851023d8a429bc4596ae3e92089 Mon Sep 17 00:00:00 2001 From: Stan Jenkins Date: Wed, 3 Jun 2020 13:01:15 -0400 Subject: [PATCH 026/355] [Jenkins] auto-formatting by clang-format version 6.0.0-1ubuntu2 (tags/RELEASE_600/final) --- stan/math/prim/fun/cholesky_decompose.hpp | 4 ++- .../prim/fun/scale_matrix_exp_multiply.hpp | 3 +- stan/math/rev/core/operator_divide_equal.hpp | 9 +++--- stan/math/rev/core/operator_minus_equal.hpp | 9 +++--- .../math/rev/core/operator_multiply_equal.hpp | 9 +++--- stan/math/rev/core/operator_plus_equal.hpp | 9 +++--- stan/math/rev/core/var.hpp | 28 ++++++++----------- stan/math/rev/core/vari.hpp | 4 +-- 8 files changed, 39 insertions(+), 36 deletions(-) diff --git a/stan/math/prim/fun/cholesky_decompose.hpp b/stan/math/prim/fun/cholesky_decompose.hpp index e227d604eaa..fe64e168b81 100644 --- a/stan/math/prim/fun/cholesky_decompose.hpp +++ b/stan/math/prim/fun/cholesky_decompose.hpp @@ -68,7 +68,9 @@ cholesky_decompose(const EigMat& m) { eval_return_type_t& m_eval = m.eval(); check_not_nan("cholesky_decompose", "m", m_eval); #ifdef STAN_OPENCL - if (std::is_same::value && m.rows() >= opencl_context.tuning_opts().cholesky_size_worth_transfer) { + if (std::is_same::value + && m.rows() + >= opencl_context.tuning_opts().cholesky_size_worth_transfer) { matrix_cl m_cl(m_eval); return from_matrix_cl(cholesky_decompose(m_cl)); } else { diff --git a/stan/math/prim/fun/scale_matrix_exp_multiply.hpp b/stan/math/prim/fun/scale_matrix_exp_multiply.hpp index f59aadbd816..7901aafc80e 100644 --- a/stan/math/prim/fun/scale_matrix_exp_multiply.hpp +++ b/stan/math/prim/fun/scale_matrix_exp_multiply.hpp @@ -53,7 +53,8 @@ scale_matrix_exp_multiply(const double& t, const EigMat1& A, const EigMat2& B) { */ template * = nullptr, - require_any_autodiff_t, value_type_t>* = nullptr> + require_any_autodiff_t, + value_type_t>* = nullptr> inline Eigen::Matrix, Eigen::Dynamic, EigMat2::ColsAtCompileTime> scale_matrix_exp_multiply(const Tt& t, const EigMat1& A, const EigMat2& B) { diff --git a/stan/math/rev/core/operator_divide_equal.hpp b/stan/math/rev/core/operator_divide_equal.hpp index 0a82b3c0e91..3b158118805 100644 --- a/stan/math/rev/core/operator_divide_equal.hpp +++ b/stan/math/rev/core/operator_divide_equal.hpp @@ -8,16 +8,17 @@ namespace stan { namespace math { template -template >*> -inline var_value>& var_value>::operator/=(const var_value& b) { +template >*> +inline var_value>& +var_value>::operator/=(const var_value& b) { vi_ = new internal::divide_vv_vari(vi_, b.vi_); return *this; } template template *> -inline var_value>& var_value>::operator/=(Arith b) { +inline var_value>& +var_value>::operator/=(Arith b) { if (b == 1.0) { return *this; } diff --git a/stan/math/rev/core/operator_minus_equal.hpp b/stan/math/rev/core/operator_minus_equal.hpp index fee058d7e9d..2792d11fbdb 100644 --- a/stan/math/rev/core/operator_minus_equal.hpp +++ b/stan/math/rev/core/operator_minus_equal.hpp @@ -9,16 +9,17 @@ namespace stan { namespace math { template -template >*> -inline var_value>& var_value>::operator-=(const var_value& b) { +template >*> +inline var_value>& +var_value>::operator-=(const var_value& b) { vi_ = new internal::subtract_vv_vari(vi_, b.vi_); return *this; } template template *> -inline var_value>& var_value>::operator-=(Arith b) { +inline var_value>& +var_value>::operator-=(Arith b) { if (b == 0.0) { return *this; } diff --git a/stan/math/rev/core/operator_multiply_equal.hpp b/stan/math/rev/core/operator_multiply_equal.hpp index 95176df2ab2..876ec9c8372 100644 --- a/stan/math/rev/core/operator_multiply_equal.hpp +++ b/stan/math/rev/core/operator_multiply_equal.hpp @@ -9,16 +9,17 @@ namespace stan { namespace math { template -template >*> -inline var_value>& var_value>::operator*=(const var_value& b) { +template >*> +inline var_value>& +var_value>::operator*=(const var_value& b) { vi_ = new internal::multiply_vv_vari(vi_, b.vi_); return *this; } template template *> -inline var_value>& var_value>::operator*=(Arith b) { +inline var_value>& +var_value>::operator*=(Arith b) { if (b == 1.0) { return *this; } diff --git a/stan/math/rev/core/operator_plus_equal.hpp b/stan/math/rev/core/operator_plus_equal.hpp index 5edda2b3d88..12c4ddf2d72 100644 --- a/stan/math/rev/core/operator_plus_equal.hpp +++ b/stan/math/rev/core/operator_plus_equal.hpp @@ -9,16 +9,17 @@ namespace stan { namespace math { template -template >*> -inline var_value>& var_value>::operator+=(const var_value& b) { +template >*> +inline var_value>& +var_value>::operator+=(const var_value& b) { vi_ = new internal::add_vv_vari(vi_, b.vi_); return *this; } template template *> -inline var_value>& var_value>::operator+=(Arith b) { +inline var_value>& +var_value>::operator+=(Arith b) { if (b == 0.0) { return *this; } diff --git a/stan/math/rev/core/var.hpp b/stan/math/rev/core/var.hpp index c2fb3b1dc19..b74b7d35fc1 100644 --- a/stan/math/rev/core/var.hpp +++ b/stan/math/rev/core/var.hpp @@ -219,10 +219,9 @@ class var_value> { * @param b The variable to add to this variable. * @return The result of adding the specified variable to this variable. */ - template >* = nullptr> - inline var_value>& operator+=(const var_value& b); + template >* = nullptr> + inline var_value>& operator+=( + const var_value& b); /** * The compound add/assignment operator for scalars (C++). @@ -250,10 +249,9 @@ class var_value> { * @return The result of subtracting the specified variable from * this variable. */ - template >* = nullptr> - inline var_value>& operator-=(const var_value& b); + template >* = nullptr> + inline var_value>& operator-=( + const var_value& b); /** * The compound subtract/assignment operator for scalars (C++). @@ -282,10 +280,9 @@ class var_value> { * @return The result of multiplying this variable by the * specified variable. */ - template >* = nullptr> - inline var_value>& operator*=(const var_value& b); + template >* = nullptr> + inline var_value>& operator*=( + const var_value& b); /** * The compound multiply/assignment operator for scalars (C++). @@ -313,10 +310,9 @@ class var_value> { * @return The result of dividing this variable by the * specified variable. */ - template >* = nullptr> - inline var_value>& operator/=(const var_value& b); + template >* = nullptr> + inline var_value>& operator/=( + const var_value& b); /** * The compound divide/assignment operator for scalars (C++). diff --git a/stan/math/rev/core/vari.hpp b/stan/math/rev/core/vari.hpp index 726e785ba12..2690ccbac3b 100644 --- a/stan/math/rev/core/vari.hpp +++ b/stan/math/rev/core/vari.hpp @@ -115,8 +115,8 @@ class vari_value::value>> * * @tparam S an Arithmetic type. * @param x Value of the constructed variable. - * @param stacked If false will put this this vari on the nochain stack so that - * it's `chain()` method is not called. + * @param stacked If false will put this this vari on the nochain stack so + * that it's `chain()` method is not called. */ template ::value>* = nullptr> From de2b7c5ffbef042df1863791acb5be7c56f9ac86 Mon Sep 17 00:00:00 2001 From: Steve Bronder Date: Wed, 3 Jun 2020 14:48:12 -0400 Subject: [PATCH 027/355] add flto flag for mac --- make/compiler_flags | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/make/compiler_flags b/make/compiler_flags index e64fa6f474f..36729e0ff9e 100644 --- a/make/compiler_flags +++ b/make/compiler_flags @@ -64,6 +64,14 @@ CXX_TYPE ?= other CXX_MAJOR := $(shell $(CXX) -dumpversion 2>&1 | cut -d'.' -f1) CXX_MINOR := $(shell $(CXX) -dumpversion 2>&1 | cut -d'.' -f2) +ifeq (default,$(origin CXX)) + ifeq ($(OS),Darwin) ## Darwin is Mac OS X + # gcc on mac actually calls clang + CXXFLAGS_FLTO := -flto -fwhole-program-vtables -fstrict-vtable-pointers + endif +endif + + ################################################################################ # Set default compiler flags # From df7e0891d26f5108234b6f1488b8a4535f775eae Mon Sep 17 00:00:00 2001 From: Steve Bronder Date: Wed, 3 Jun 2020 15:00:03 -0400 Subject: [PATCH 028/355] use ? instead of : for flto flags --- make/compiler_flags | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) diff --git a/make/compiler_flags b/make/compiler_flags index 36729e0ff9e..f802ff3b797 100644 --- a/make/compiler_flags +++ b/make/compiler_flags @@ -47,29 +47,23 @@ endif # - CXX_MINOR: minor version of CXX ifneq (,$(findstring clang,$(CXX))) CXX_TYPE ?= clang - CXXFLAGS_FLTO := -flto -fwhole-program-vtables -fstrict-vtable-pointers + CXXFLAGS_FLTO ?= -flto -fwhole-program-vtables -fstrict-vtable-pointers endif ifneq (,$(findstring mingw32-g,$(CXX))) CXX_TYPE ?= mingw32-gcc endif ifneq (,$(findstring gcc,$(CXX))) CXX_TYPE ?= gcc - CXXFLAGS_FLTO := -flto -fuse-linker-plugin -fdevirtualize-at-ltrans -fipa-pta + CXXFLAGS_FLTO ?= -flto -fuse-linker-plugin -fdevirtualize-at-ltrans -fipa-pta endif ifneq (,$(findstring g++,$(CXX))) CXX_TYPE ?= gcc - CXXFLAGS_FLTO := -flto -fuse-linker-plugin -fdevirtualize-at-ltrans -fipa-pta + CXXFLAGS_FLTO ?= -flto -fuse-linker-plugin -fdevirtualize-at-ltrans -fipa-pta endif CXX_TYPE ?= other CXX_MAJOR := $(shell $(CXX) -dumpversion 2>&1 | cut -d'.' -f1) CXX_MINOR := $(shell $(CXX) -dumpversion 2>&1 | cut -d'.' -f2) -ifeq (default,$(origin CXX)) - ifeq ($(OS),Darwin) ## Darwin is Mac OS X - # gcc on mac actually calls clang - CXXFLAGS_FLTO := -flto -fwhole-program-vtables -fstrict-vtable-pointers - endif -endif ################################################################################ From b510337fd2245c008844db2c400aef1c1a9890ba Mon Sep 17 00:00:00 2001 From: Steve Bronder Date: Wed, 3 Jun 2020 15:44:34 -0400 Subject: [PATCH 029/355] update vari test since integral template types are no longer allowed --- test/unit/math/rev/meta/is_vari_test.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/unit/math/rev/meta/is_vari_test.cpp b/test/unit/math/rev/meta/is_vari_test.cpp index 9b5ab9e90c5..818d6c3b4d7 100644 --- a/test/unit/math/rev/meta/is_vari_test.cpp +++ b/test/unit/math/rev/meta/is_vari_test.cpp @@ -7,8 +7,8 @@ TEST(MetaTraitsRevScal, is_vari) { using stan::math::vari_value; EXPECT_TRUE(is_vari::value); EXPECT_TRUE((is_vari>::value)); - EXPECT_TRUE((is_vari>::value)); + EXPECT_TRUE((is_vari>::value)); EXPECT_FALSE(is_vari::value); EXPECT_FALSE((is_vari::value)); - EXPECT_FALSE((is_vari>::value)); + EXPECT_FALSE((is_vari>::value)); } From 4424dc3cc001b8cb89acf766f6fa71c933b41625 Mon Sep 17 00:00:00 2001 From: Steve Bronder Date: Wed, 3 Jun 2020 17:22:05 -0400 Subject: [PATCH 030/355] remove whole program vtable clang optimization --- make/compiler_flags | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/make/compiler_flags b/make/compiler_flags index f802ff3b797..c43cfd458b2 100644 --- a/make/compiler_flags +++ b/make/compiler_flags @@ -47,7 +47,7 @@ endif # - CXX_MINOR: minor version of CXX ifneq (,$(findstring clang,$(CXX))) CXX_TYPE ?= clang - CXXFLAGS_FLTO ?= -flto -fwhole-program-vtables -fstrict-vtable-pointers + CXXFLAGS_FLTO ?= -flto -fstrict-vtable-pointers endif ifneq (,$(findstring mingw32-g,$(CXX))) CXX_TYPE ?= mingw32-gcc From 8ce09f4b1245c5bd0e0e0d6d7c72541d2fe5ac3e Mon Sep 17 00:00:00 2001 From: Steve Bronder Date: Wed, 3 Jun 2020 18:02:22 -0400 Subject: [PATCH 031/355] remove -fstrict-vtable-pointers from clang --- make/compiler_flags | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/make/compiler_flags b/make/compiler_flags index c43cfd458b2..dafdafb82aa 100644 --- a/make/compiler_flags +++ b/make/compiler_flags @@ -47,7 +47,7 @@ endif # - CXX_MINOR: minor version of CXX ifneq (,$(findstring clang,$(CXX))) CXX_TYPE ?= clang - CXXFLAGS_FLTO ?= -flto -fstrict-vtable-pointers + CXXFLAGS_FLTO ?= -flto endif ifneq (,$(findstring mingw32-g,$(CXX))) CXX_TYPE ?= mingw32-gcc From b8de65f5978ac8769291cedcac72d9c07df84546 Mon Sep 17 00:00:00 2001 From: Steve Bronder Date: Thu, 4 Jun 2020 09:30:05 -0400 Subject: [PATCH 032/355] fix is_var test --- test/unit/math/rev/meta/is_var_test.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/unit/math/rev/meta/is_var_test.cpp b/test/unit/math/rev/meta/is_var_test.cpp index 75ef61d9596..cb225ff7d1c 100644 --- a/test/unit/math/rev/meta/is_var_test.cpp +++ b/test/unit/math/rev/meta/is_var_test.cpp @@ -7,8 +7,8 @@ TEST(MetaTraitsRevScal, is_var) { using stan::math::var_value; EXPECT_TRUE(is_var::value); EXPECT_TRUE((is_var>::value)); - EXPECT_TRUE((is_var>::value)); + EXPECT_TRUE((is_var>::value)); EXPECT_FALSE(is_var::value); EXPECT_FALSE((is_var::value)); - EXPECT_FALSE((is_var>::value)); + EXPECT_FALSE((is_var>::value)); } From 8cf3bcc3d872e98d6018226d86d46ef205b1680b Mon Sep 17 00:00:00 2001 From: Steve Bronder Date: Thu, 4 Jun 2020 10:16:09 -0400 Subject: [PATCH 033/355] remove unneeded templating in var_value operators --- stan/math/rev/core/operator_divide_equal.hpp | 6 ++---- stan/math/rev/core/operator_minus_equal.hpp | 6 ++---- .../math/rev/core/operator_multiply_equal.hpp | 6 ++---- stan/math/rev/core/operator_plus_equal.hpp | 6 ++---- stan/math/rev/core/var.hpp | 20 ++++++++----------- 5 files changed, 16 insertions(+), 28 deletions(-) diff --git a/stan/math/rev/core/operator_divide_equal.hpp b/stan/math/rev/core/operator_divide_equal.hpp index 3b158118805..e4e2507cc31 100644 --- a/stan/math/rev/core/operator_divide_equal.hpp +++ b/stan/math/rev/core/operator_divide_equal.hpp @@ -9,16 +9,14 @@ namespace stan { namespace math { template template >*> -inline var_value>& -var_value>::operator/=(const var_value& b) { +inline var_value& var_value>::operator/=(const var_value& b) { vi_ = new internal::divide_vv_vari(vi_, b.vi_); return *this; } template template *> -inline var_value>& -var_value>::operator/=(Arith b) { +inline var_value& var_value>::operator/=(Arith b) { if (b == 1.0) { return *this; } diff --git a/stan/math/rev/core/operator_minus_equal.hpp b/stan/math/rev/core/operator_minus_equal.hpp index 2792d11fbdb..c5a888504d7 100644 --- a/stan/math/rev/core/operator_minus_equal.hpp +++ b/stan/math/rev/core/operator_minus_equal.hpp @@ -10,16 +10,14 @@ namespace math { template template >*> -inline var_value>& -var_value>::operator-=(const var_value& b) { +inline var_value& var_value>::operator-=(const var_value& b) { vi_ = new internal::subtract_vv_vari(vi_, b.vi_); return *this; } template template *> -inline var_value>& -var_value>::operator-=(Arith b) { +inline var_value& var_value>::operator-=(Arith b) { if (b == 0.0) { return *this; } diff --git a/stan/math/rev/core/operator_multiply_equal.hpp b/stan/math/rev/core/operator_multiply_equal.hpp index 876ec9c8372..ec2936539e3 100644 --- a/stan/math/rev/core/operator_multiply_equal.hpp +++ b/stan/math/rev/core/operator_multiply_equal.hpp @@ -10,16 +10,14 @@ namespace math { template template >*> -inline var_value>& -var_value>::operator*=(const var_value& b) { +inline var_value& var_value>::operator*=(const var_value& b) { vi_ = new internal::multiply_vv_vari(vi_, b.vi_); return *this; } template template *> -inline var_value>& -var_value>::operator*=(Arith b) { +inline var_value& var_value>::operator*=(Arith b) { if (b == 1.0) { return *this; } diff --git a/stan/math/rev/core/operator_plus_equal.hpp b/stan/math/rev/core/operator_plus_equal.hpp index 12c4ddf2d72..e74e440dfd7 100644 --- a/stan/math/rev/core/operator_plus_equal.hpp +++ b/stan/math/rev/core/operator_plus_equal.hpp @@ -10,16 +10,14 @@ namespace math { template template >*> -inline var_value>& -var_value>::operator+=(const var_value& b) { +inline var_value& var_value>::operator+=(const var_value& b) { vi_ = new internal::add_vv_vari(vi_, b.vi_); return *this; } template template *> -inline var_value>& -var_value>::operator+=(Arith b) { +inline var_value& var_value>::operator+=(Arith b) { if (b == 0.0) { return *this; } diff --git a/stan/math/rev/core/var.hpp b/stan/math/rev/core/var.hpp index b74b7d35fc1..0889712d782 100644 --- a/stan/math/rev/core/var.hpp +++ b/stan/math/rev/core/var.hpp @@ -220,8 +220,7 @@ class var_value> { * @return The result of adding the specified variable to this variable. */ template >* = nullptr> - inline var_value>& operator+=( - const var_value& b); + inline var_value& operator+=(const var_value& b); /** * The compound add/assignment operator for scalars (C++). @@ -235,7 +234,7 @@ class var_value> { * @return The result of adding the specified variable to this variable. */ template * = nullptr> - inline var_value>& operator+=(Arith b); + inline var_value& operator+=(Arith b); /** * The compound subtract/assignment operator for variables (C++). @@ -250,8 +249,7 @@ class var_value> { * this variable. */ template >* = nullptr> - inline var_value>& operator-=( - const var_value& b); + inline var_value& operator-=(const var_value& b); /** * The compound subtract/assignment operator for scalars (C++). @@ -266,7 +264,7 @@ class var_value> { * variable. */ template * = nullptr> - inline var_value>& operator-=(Arith b); + inline var_value& operator-=(Arith b); /** * The compound multiply/assignment operator for variables (C++). @@ -281,8 +279,7 @@ class var_value> { * specified variable. */ template >* = nullptr> - inline var_value>& operator*=( - const var_value& b); + inline var_value& operator*=(const var_value& b); /** * The compound multiply/assignment operator for scalars (C++). @@ -297,7 +294,7 @@ class var_value> { * variable. */ template * = nullptr> - inline var_value>& operator*=(Arith b); + inline var_value& operator*=(Arith b); /** * The compound divide/assignment operator for variables (C++). If this @@ -311,8 +308,7 @@ class var_value> { * specified variable. */ template >* = nullptr> - inline var_value>& operator/=( - const var_value& b); + inline var_value& operator/=(const var_value& b); /** * The compound divide/assignment operator for scalars (C++). @@ -327,7 +323,7 @@ class var_value> { * variable. */ template * = nullptr> - inline var_value>& operator/=(Arith b); + inline var_value& operator/=(Arith b); /** * Write the value of this autodiff variable and its adjoint to From a07140c371481b548a932abf78618dd40031b63d Mon Sep 17 00:00:00 2001 From: Stan Jenkins Date: Thu, 4 Jun 2020 10:35:12 -0400 Subject: [PATCH 034/355] [Jenkins] auto-formatting by clang-format version 6.0.0-1ubuntu2 (tags/RELEASE_600/final) --- stan/math/rev/core/operator_divide_equal.hpp | 6 ++++-- stan/math/rev/core/operator_minus_equal.hpp | 6 ++++-- stan/math/rev/core/operator_multiply_equal.hpp | 6 ++++-- stan/math/rev/core/operator_plus_equal.hpp | 6 ++++-- 4 files changed, 16 insertions(+), 8 deletions(-) diff --git a/stan/math/rev/core/operator_divide_equal.hpp b/stan/math/rev/core/operator_divide_equal.hpp index e4e2507cc31..a3ed35bbd3b 100644 --- a/stan/math/rev/core/operator_divide_equal.hpp +++ b/stan/math/rev/core/operator_divide_equal.hpp @@ -9,14 +9,16 @@ namespace stan { namespace math { template template >*> -inline var_value& var_value>::operator/=(const var_value& b) { +inline var_value& var_value>::operator/=( + const var_value& b) { vi_ = new internal::divide_vv_vari(vi_, b.vi_); return *this; } template template *> -inline var_value& var_value>::operator/=(Arith b) { +inline var_value& var_value>::operator/=( + Arith b) { if (b == 1.0) { return *this; } diff --git a/stan/math/rev/core/operator_minus_equal.hpp b/stan/math/rev/core/operator_minus_equal.hpp index c5a888504d7..9c89c2578f4 100644 --- a/stan/math/rev/core/operator_minus_equal.hpp +++ b/stan/math/rev/core/operator_minus_equal.hpp @@ -10,14 +10,16 @@ namespace math { template template >*> -inline var_value& var_value>::operator-=(const var_value& b) { +inline var_value& var_value>::operator-=( + const var_value& b) { vi_ = new internal::subtract_vv_vari(vi_, b.vi_); return *this; } template template *> -inline var_value& var_value>::operator-=(Arith b) { +inline var_value& var_value>::operator-=( + Arith b) { if (b == 0.0) { return *this; } diff --git a/stan/math/rev/core/operator_multiply_equal.hpp b/stan/math/rev/core/operator_multiply_equal.hpp index ec2936539e3..fa74c2f543d 100644 --- a/stan/math/rev/core/operator_multiply_equal.hpp +++ b/stan/math/rev/core/operator_multiply_equal.hpp @@ -10,14 +10,16 @@ namespace math { template template >*> -inline var_value& var_value>::operator*=(const var_value& b) { +inline var_value& var_value>::operator*=( + const var_value& b) { vi_ = new internal::multiply_vv_vari(vi_, b.vi_); return *this; } template template *> -inline var_value& var_value>::operator*=(Arith b) { +inline var_value& var_value>::operator*=( + Arith b) { if (b == 1.0) { return *this; } diff --git a/stan/math/rev/core/operator_plus_equal.hpp b/stan/math/rev/core/operator_plus_equal.hpp index e74e440dfd7..c22bccd71d3 100644 --- a/stan/math/rev/core/operator_plus_equal.hpp +++ b/stan/math/rev/core/operator_plus_equal.hpp @@ -10,14 +10,16 @@ namespace math { template template >*> -inline var_value& var_value>::operator+=(const var_value& b) { +inline var_value& var_value>::operator+=( + const var_value& b) { vi_ = new internal::add_vv_vari(vi_, b.vi_); return *this; } template template *> -inline var_value& var_value>::operator+=(Arith b) { +inline var_value& var_value>::operator+=( + Arith b) { if (b == 0.0) { return *this; } From 7ed5d9973c609a18a44ea4878de649062d66dcc8 Mon Sep 17 00:00:00 2001 From: Steve Bronder Date: Thu, 4 Jun 2020 13:18:42 -0400 Subject: [PATCH 035/355] remove flto flag --- make/compiler_flags | 5 +- stan/math/rev/core/autodiffstackstorage.hpp | 4 +- stan/math/rev/core/chainablestack.hpp | 8 ++- stan/math/rev/core/grad.hpp | 4 +- stan/math/rev/core/print_stack.hpp | 6 +- stan/math/rev/core/set_zero_all_adjoints.hpp | 4 +- .../rev/core/set_zero_all_adjoints_nested.hpp | 4 +- stan/math/rev/core/vari.hpp | 60 +++++++++++++++---- 8 files changed, 63 insertions(+), 32 deletions(-) diff --git a/make/compiler_flags b/make/compiler_flags index dafdafb82aa..5d20960a48a 100644 --- a/make/compiler_flags +++ b/make/compiler_flags @@ -47,18 +47,15 @@ endif # - CXX_MINOR: minor version of CXX ifneq (,$(findstring clang,$(CXX))) CXX_TYPE ?= clang - CXXFLAGS_FLTO ?= -flto endif ifneq (,$(findstring mingw32-g,$(CXX))) CXX_TYPE ?= mingw32-gcc endif ifneq (,$(findstring gcc,$(CXX))) CXX_TYPE ?= gcc - CXXFLAGS_FLTO ?= -flto -fuse-linker-plugin -fdevirtualize-at-ltrans -fipa-pta endif ifneq (,$(findstring g++,$(CXX))) CXX_TYPE ?= gcc - CXXFLAGS_FLTO ?= -flto -fuse-linker-plugin -fdevirtualize-at-ltrans -fipa-pta endif CXX_TYPE ?= other CXX_MAJOR := $(shell $(CXX) -dumpversion 2>&1 | cut -d'.' -f1) @@ -259,7 +256,7 @@ ifdef STAN_MPI CXXFLAGS_MPI ?= -Wno-delete-non-virtual-dtor endif -CXXFLAGS += $(CXXFLAGS_LANG) $(CXXFLAGS_OS) $(CXXFLAGS_FLTO) $(CXXFLAGS_WARNINGS) $(CXXFLAGS_BOOST) $(CXXFLAGS_EIGEN) $(CXXFLAGS_OPENCL) $(CXXFLAGS_MPI) $(CXXFLAGS_THREADS) $(CXXFLAGS_TBB) -O$(O) $(INC) +CXXFLAGS += $(CXXFLAGS_LANG) $(CXXFLAGS_OS) $(CXXFLAGS_WARNINGS) $(CXXFLAGS_BOOST) $(CXXFLAGS_EIGEN) $(CXXFLAGS_OPENCL) $(CXXFLAGS_MPI) $(CXXFLAGS_THREADS) $(CXXFLAGS_TBB) -O$(O) $(INC) CPPFLAGS += $(CPPFLAGS_LANG) $(CPPFLAGS_OS) $(CPPFLAGS_WARNINGS) $(CPPFLAGS_BOOST) $(CPPFLAGS_EIGEN) $(CPPFLAGS_OPENCL) $(CPPFLAGS_MPI) $(CPPFLAGS_TBB) LDFLAGS += $(LDFLAGS_LANG) $(LDFLAGS_OS) $(LDFLAGS_WARNINGS) $(LDFLAGS_BOOST) $(LDFLAGS_EIGEN) $(LDFLAGS_OPENCL) $(LDFLAGS_MPI) $(LDFLAGS_TBB) LDLIBS += $(LDLIBS_LANG) $(LDLIBS_OS) $(LDLIBS_WARNINGS) $(LDLIBS_BOOST) $(LDLIBS_EIGEN) $(LDLIBS_OPENCL) $(LDLIBS_MPI) $(LDLIBS_TBB) diff --git a/stan/math/rev/core/autodiffstackstorage.hpp b/stan/math/rev/core/autodiffstackstorage.hpp index fecdab186b5..9b2dc106fdf 100644 --- a/stan/math/rev/core/autodiffstackstorage.hpp +++ b/stan/math/rev/core/autodiffstackstorage.hpp @@ -101,8 +101,8 @@ struct AutodiffStackSingleton { struct AutodiffStackStorage { AutodiffStackStorage &operator=(const AutodiffStackStorage &) = delete; - std::vector var_stack_; - std::vector var_nochain_stack_; + std::vector var_stack_; + std::vector var_nochain_stack_; std::vector var_alloc_stack_; stack_alloc memalloc_; diff --git a/stan/math/rev/core/chainablestack.hpp b/stan/math/rev/core/chainablestack.hpp index 57d49da3dbc..c6e2c424c41 100644 --- a/stan/math/rev/core/chainablestack.hpp +++ b/stan/math/rev/core/chainablestack.hpp @@ -2,14 +2,18 @@ #define STAN_MATH_REV_CORE_CHAINABLESTACK_HPP #include - +#include namespace stan { namespace math { +template +class vari_value; class vari_base; class chainable_alloc; -using ChainableStack = AutodiffStackSingleton; +using vari_variant = boost::variant*, vari_value*, vari_value*>; + +using ChainableStack = AutodiffStackSingleton; } // namespace math } // namespace stan diff --git a/stan/math/rev/core/grad.hpp b/stan/math/rev/core/grad.hpp index cd22f8c9a04..00d9ef669f0 100644 --- a/stan/math/rev/core/grad.hpp +++ b/stan/math/rev/core/grad.hpp @@ -30,11 +30,11 @@ namespace math { template static void grad(Vari* vi) { vi->init_dependent(); - std::vector& var_stack = ChainableStack::instance_->var_stack_; + std::vector& var_stack = ChainableStack::instance_->var_stack_; size_t end = var_stack.size(); size_t beginning = empty_nested() ? 0 : end - nested_size(); for (size_t i = end; i-- > beginning;) { - var_stack[i]->chain(); + boost::apply_visitor(vari_chainer(), var_stack[i]); } } diff --git a/stan/math/rev/core/print_stack.hpp b/stan/math/rev/core/print_stack.hpp index 70f12b759b8..4f394e13663 100644 --- a/stan/math/rev/core/print_stack.hpp +++ b/stan/math/rev/core/print_stack.hpp @@ -22,11 +22,7 @@ inline void print_stack(std::ostream& o) { << std::endl; // TODO(carpenter): this shouldn't need to be cast any more for (size_t i = 0; i < ChainableStack::instance_->var_stack_.size(); ++i) { - o << i << " " << ChainableStack::instance_->var_stack_[i] << " " - << (static_cast(ChainableStack::instance_->var_stack_[i]))->val_ - << " : " - << (static_cast(ChainableStack::instance_->var_stack_[i]))->adj_ - << std::endl; + boost::apply_visitor(vari_printer(o, i), ChainableStack::instance_->var_stack_[i]); } } diff --git a/stan/math/rev/core/set_zero_all_adjoints.hpp b/stan/math/rev/core/set_zero_all_adjoints.hpp index 841ef6d5c60..55ea7f7ed45 100644 --- a/stan/math/rev/core/set_zero_all_adjoints.hpp +++ b/stan/math/rev/core/set_zero_all_adjoints.hpp @@ -13,10 +13,10 @@ namespace math { */ static void set_zero_all_adjoints() { for (auto &x : ChainableStack::instance_->var_stack_) { - x->set_zero_adjoint(); + boost::apply_visitor(vari_zero_adj(), x); } for (auto &x : ChainableStack::instance_->var_nochain_stack_) { - x->set_zero_adjoint(); + boost::apply_visitor(vari_zero_adj(), x); } } diff --git a/stan/math/rev/core/set_zero_all_adjoints_nested.hpp b/stan/math/rev/core/set_zero_all_adjoints_nested.hpp index 34dc367556c..0cf1591721d 100644 --- a/stan/math/rev/core/set_zero_all_adjoints_nested.hpp +++ b/stan/math/rev/core/set_zero_all_adjoints_nested.hpp @@ -27,14 +27,14 @@ static void set_zero_all_adjoints_nested() { // avoid wrap with unsigned when start1 == 0 for (size_t i = (start1 == 0U) ? 0U : (start1 - 1); i < ChainableStack::instance_->var_stack_.size(); ++i) { - ChainableStack::instance_->var_stack_[i]->set_zero_adjoint(); + boost::apply_visitor(vari_zero_adj(), ChainableStack::instance_->var_stack_[i]); } size_t start2 = ChainableStack::instance_->nested_var_nochain_stack_sizes_.back(); for (size_t i = (start2 == 0U) ? 0U : (start2 - 1); i < ChainableStack::instance_->var_nochain_stack_.size(); ++i) { - ChainableStack::instance_->var_nochain_stack_[i]->set_zero_adjoint(); + boost::apply_visitor(vari_zero_adj(), ChainableStack::instance_->var_nochain_stack_[i]); } } diff --git a/stan/math/rev/core/vari.hpp b/stan/math/rev/core/vari.hpp index 2690ccbac3b..0b3d86ec168 100644 --- a/stan/math/rev/core/vari.hpp +++ b/stan/math/rev/core/vari.hpp @@ -25,13 +25,6 @@ class vari_base { */ virtual void chain() {} - /** - * Set the adjoint value of this variable to 0. This is used to - * reset adjoints before propagating derivatives again (for - * example in a Jacobian calculation). - */ - virtual void set_zero_adjoint() = 0; - /** * Throw an illegal argument exception. * @@ -58,7 +51,7 @@ class vari_base { * classes will store operand variables and propagate derivative * information via an implementation of chain(). */ -template +template class vari_value; template @@ -98,7 +91,7 @@ class vari_value::value>> template ::value>* = nullptr> vari_value(S x) : val_(x), adj_(0.0) { // NOLINT - ChainableStack::instance_->var_stack_.push_back(this); + ChainableStack::instance_->var_stack_.emplace_back(this); } /** @@ -122,9 +115,9 @@ class vari_value::value>> std::enable_if_t::value>* = nullptr> vari_value(S x, bool stacked) : val_(x), adj_(0.0) { if (stacked) { - ChainableStack::instance_->var_stack_.push_back(this); + ChainableStack::instance_->var_stack_.emplace_back(this); } else { - ChainableStack::instance_->var_nochain_stack_.push_back(this); + ChainableStack::instance_->var_nochain_stack_.emplace_back(this); } } @@ -136,7 +129,7 @@ class vari_value::value>> template ::value>* = nullptr> vari_value(const vari_value& x) : val_(x.val_), adj_(x.adj_) { - ChainableStack::instance_->var_stack_.push_back(this); + ChainableStack::instance_->var_stack_.emplace_back(this); } /** @@ -152,7 +145,7 @@ class vari_value::value>> * reset adjoints before propagating derivatives again (for * example in a Jacobian calculation). */ - void set_zero_adjoint() final { adj_ = 0.0; } + void set_zero_adjoint() { adj_ = 0.0; } /** * Insertion operator for vari. Prints the current value and @@ -199,6 +192,47 @@ class vari_value::value>> // For backwards compatability the default is double using vari = vari_value; +class vari_zero_adj : public boost::static_visitor<> { + public: + void operator()(vari_value*& x) const { + x->adj_ = 0.0; + } + void operator()(vari_value*& x) const { + x->adj_ = 0.0; + } + void operator()(vari_value*& x) const { + x->adj_ = 0.0; + } +}; + +class vari_chainer : public boost::static_visitor<> { + public: + void operator()(vari_value*& x) const { + x->chain(); + } + void operator()(vari_value*& x) const { + x->chain(); + } + void operator()(vari_value*& x) const { + x->chain(); + } +}; + +class vari_printer : public boost::static_visitor<> { +public: + int i_{0}; + std::ostream& o_; + vari_printer(std::ostream& o, int i) : o_(o), i_(i) {} + template + void operator()(T*& x) const { + // TODO(carpenter): this shouldn't need to be cast any more + o_ << i_ << " " << x << " " + << x->val_ + << " : " + << x->adj_ + << std::endl; + } +}; } // namespace math } // namespace stan #endif From 52de946350aa3cd3923bff949dfa61f09421c0b3 Mon Sep 17 00:00:00 2001 From: Steve Bronder Date: Thu, 4 Jun 2020 13:57:27 -0400 Subject: [PATCH 036/355] use lambda instead of visitor pattern --- stan/math/rev/core/grad.hpp | 5 ++--- stan/math/rev/core/set_zero_all_adjoints.hpp | 4 ++-- .../rev/core/set_zero_all_adjoints_nested.hpp | 4 ++-- stan/math/rev/core/vari.hpp | 20 +++++++++---------- 4 files changed, 16 insertions(+), 17 deletions(-) diff --git a/stan/math/rev/core/grad.hpp b/stan/math/rev/core/grad.hpp index 00d9ef669f0..b45768e42dd 100644 --- a/stan/math/rev/core/grad.hpp +++ b/stan/math/rev/core/grad.hpp @@ -30,11 +30,10 @@ namespace math { template static void grad(Vari* vi) { vi->init_dependent(); - std::vector& var_stack = ChainableStack::instance_->var_stack_; - size_t end = var_stack.size(); + size_t end = ChainableStack::instance_->var_stack_.size(); size_t beginning = empty_nested() ? 0 : end - nested_size(); for (size_t i = end; i-- > beginning;) { - boost::apply_visitor(vari_chainer(), var_stack[i]); + boost::apply_visitor([](auto*& x) { x->chain();}, ChainableStack::instance_->var_stack_[i]); } } diff --git a/stan/math/rev/core/set_zero_all_adjoints.hpp b/stan/math/rev/core/set_zero_all_adjoints.hpp index 55ea7f7ed45..08e000b51f5 100644 --- a/stan/math/rev/core/set_zero_all_adjoints.hpp +++ b/stan/math/rev/core/set_zero_all_adjoints.hpp @@ -13,10 +13,10 @@ namespace math { */ static void set_zero_all_adjoints() { for (auto &x : ChainableStack::instance_->var_stack_) { - boost::apply_visitor(vari_zero_adj(), x); + boost::apply_visitor([](auto*& x) { x->adj_ = 0.0;}, x); } for (auto &x : ChainableStack::instance_->var_nochain_stack_) { - boost::apply_visitor(vari_zero_adj(), x); + boost::apply_visitor([](auto*& x) { x->adj_ = 0.0;}, x); } } diff --git a/stan/math/rev/core/set_zero_all_adjoints_nested.hpp b/stan/math/rev/core/set_zero_all_adjoints_nested.hpp index 0cf1591721d..169fdfd0653 100644 --- a/stan/math/rev/core/set_zero_all_adjoints_nested.hpp +++ b/stan/math/rev/core/set_zero_all_adjoints_nested.hpp @@ -27,14 +27,14 @@ static void set_zero_all_adjoints_nested() { // avoid wrap with unsigned when start1 == 0 for (size_t i = (start1 == 0U) ? 0U : (start1 - 1); i < ChainableStack::instance_->var_stack_.size(); ++i) { - boost::apply_visitor(vari_zero_adj(), ChainableStack::instance_->var_stack_[i]); + boost::apply_visitor([](auto*& x) { x->adj_ = 0.0;}, ChainableStack::instance_->var_stack_[i]); } size_t start2 = ChainableStack::instance_->nested_var_nochain_stack_sizes_.back(); for (size_t i = (start2 == 0U) ? 0U : (start2 - 1); i < ChainableStack::instance_->var_nochain_stack_.size(); ++i) { - boost::apply_visitor(vari_zero_adj(), ChainableStack::instance_->var_nochain_stack_[i]); + boost::apply_visitor([](auto*& x) { x->adj_ = 0.0;}, ChainableStack::instance_->var_nochain_stack_[i]); } } diff --git a/stan/math/rev/core/vari.hpp b/stan/math/rev/core/vari.hpp index 0b3d86ec168..15323397781 100644 --- a/stan/math/rev/core/vari.hpp +++ b/stan/math/rev/core/vari.hpp @@ -91,7 +91,7 @@ class vari_value::value>> template ::value>* = nullptr> vari_value(S x) : val_(x), adj_(0.0) { // NOLINT - ChainableStack::instance_->var_stack_.emplace_back(this); + ChainableStack::instance_->var_stack_.push_back(this); } /** @@ -115,9 +115,9 @@ class vari_value::value>> std::enable_if_t::value>* = nullptr> vari_value(S x, bool stacked) : val_(x), adj_(0.0) { if (stacked) { - ChainableStack::instance_->var_stack_.emplace_back(this); + ChainableStack::instance_->var_stack_.push_back(this); } else { - ChainableStack::instance_->var_nochain_stack_.emplace_back(this); + ChainableStack::instance_->var_nochain_stack_.push_back(this); } } @@ -129,7 +129,7 @@ class vari_value::value>> template ::value>* = nullptr> vari_value(const vari_value& x) : val_(x.val_), adj_(x.adj_) { - ChainableStack::instance_->var_stack_.emplace_back(this); + ChainableStack::instance_->var_stack_.push_back(this); } /** @@ -194,26 +194,26 @@ using vari = vari_value; class vari_zero_adj : public boost::static_visitor<> { public: - void operator()(vari_value*& x) const { + inline void operator()(vari_value*& x) const { x->adj_ = 0.0; } - void operator()(vari_value*& x) const { + inline void operator()(vari_value*& x) const { x->adj_ = 0.0; } - void operator()(vari_value*& x) const { + inline void operator()(vari_value*& x) const { x->adj_ = 0.0; } }; class vari_chainer : public boost::static_visitor<> { public: - void operator()(vari_value*& x) const { + inline void operator()(vari_value*& x) const { x->chain(); } - void operator()(vari_value*& x) const { + inline void operator()(vari_value*& x) const { x->chain(); } - void operator()(vari_value*& x) const { + inline void operator()(vari_value*& x) const { x->chain(); } }; From 6585a89cb355fc01900fd70fe4a923c7b0c92c07 Mon Sep 17 00:00:00 2001 From: Steve Bronder Date: Thu, 4 Jun 2020 14:08:27 -0400 Subject: [PATCH 037/355] fix vari_test --- test/unit/math/rev/core/vari_test.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/unit/math/rev/core/vari_test.cpp b/test/unit/math/rev/core/vari_test.cpp index d9d0fb6648f..fc5a6e34ab5 100644 --- a/test/unit/math/rev/core/vari_test.cpp +++ b/test/unit/math/rev/core/vari_test.cpp @@ -9,8 +9,8 @@ TEST(AgradRev, insertion_operator) { EXPECT_EQ("5:0", ss.str()); } -TEST(AgradRev, int_test) { - stan::math::vari_value v(5); +TEST(AgradRev, long_double_test) { + stan::math::vari_value v(5); std::stringstream ss; ss << &v; EXPECT_EQ("5:0", ss.str()); From f42756c65b6c49e6010a98c9a77de273150db5e5 Mon Sep 17 00:00:00 2001 From: Steve Bronder Date: Thu, 4 Jun 2020 17:17:55 -0400 Subject: [PATCH 038/355] only use fdevirtualize-at-ltrans for linux gcc --- make/compiler_flags | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/make/compiler_flags b/make/compiler_flags index dafdafb82aa..f5ef6127406 100644 --- a/make/compiler_flags +++ b/make/compiler_flags @@ -54,11 +54,17 @@ ifneq (,$(findstring mingw32-g,$(CXX))) endif ifneq (,$(findstring gcc,$(CXX))) CXX_TYPE ?= gcc - CXXFLAGS_FLTO ?= -flto -fuse-linker-plugin -fdevirtualize-at-ltrans -fipa-pta + CXXFLAGS_FLTO ?= -flto -fuse-linker-plugin -fipa-pta + ifneq ($(OS),Windows_NT) + CXXFLAGS_FLTO += -fdevirtualize-at-ltrans + endif endif ifneq (,$(findstring g++,$(CXX))) CXX_TYPE ?= gcc - CXXFLAGS_FLTO ?= -flto -fuse-linker-plugin -fdevirtualize-at-ltrans -fipa-pta + CXXFLAGS_FLTO ?= -flto -fuse-linker-plugin -fipa-pta + ifneq ($(OS),Windows_NT) + CXXFLAGS_FLTO += -fdevirtualize-at-ltrans + endif endif CXX_TYPE ?= other CXX_MAJOR := $(shell $(CXX) -dumpversion 2>&1 | cut -d'.' -f1) From 12f9cafde02c9c11c911908b68900abebcba2f40 Mon Sep 17 00:00:00 2001 From: Steve Bronder Date: Thu, 4 Jun 2020 17:26:41 -0400 Subject: [PATCH 039/355] use filter instead of findstring when matching on g++ in makefile --- make/compiler_flags | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/make/compiler_flags b/make/compiler_flags index f5ef6127406..7fd2304369d 100644 --- a/make/compiler_flags +++ b/make/compiler_flags @@ -52,14 +52,14 @@ endif ifneq (,$(findstring mingw32-g,$(CXX))) CXX_TYPE ?= mingw32-gcc endif -ifneq (,$(findstring gcc,$(CXX))) +ifneq ($(filter gcc,$(CXX)),) CXX_TYPE ?= gcc CXXFLAGS_FLTO ?= -flto -fuse-linker-plugin -fipa-pta ifneq ($(OS),Windows_NT) CXXFLAGS_FLTO += -fdevirtualize-at-ltrans endif endif -ifneq (,$(findstring g++,$(CXX))) +ifneq ($(filter g++,$(CXX)),) CXX_TYPE ?= gcc CXXFLAGS_FLTO ?= -flto -fuse-linker-plugin -fipa-pta ifneq ($(OS),Windows_NT) From 2c41d98ce45dbca951a7751c697165410d5e8653 Mon Sep 17 00:00:00 2001 From: Steve Bronder Date: Sun, 7 Jun 2020 17:20:12 -0400 Subject: [PATCH 040/355] do not use flto for windows --- make/compiler_flags | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/make/compiler_flags b/make/compiler_flags index 7fd2304369d..65d29413135 100644 --- a/make/compiler_flags +++ b/make/compiler_flags @@ -52,18 +52,16 @@ endif ifneq (,$(findstring mingw32-g,$(CXX))) CXX_TYPE ?= mingw32-gcc endif -ifneq ($(filter gcc,$(CXX)),) +ifneq ($(filter gcc,$(CXX)),) CXX_TYPE ?= gcc - CXXFLAGS_FLTO ?= -flto -fuse-linker-plugin -fipa-pta ifneq ($(OS),Windows_NT) - CXXFLAGS_FLTO += -fdevirtualize-at-ltrans + CXXFLAGS_FLTO ?= -fdevirtualize-at-ltrans -flto -fuse-linker-plugin -fipa-pta endif endif ifneq ($(filter g++,$(CXX)),) CXX_TYPE ?= gcc - CXXFLAGS_FLTO ?= -flto -fuse-linker-plugin -fipa-pta ifneq ($(OS),Windows_NT) - CXXFLAGS_FLTO += -fdevirtualize-at-ltrans + CXXFLAGS_FLTO ?= -fdevirtualize-at-ltrans -flto -fuse-linker-plugin -fipa-pta endif endif CXX_TYPE ?= other @@ -292,6 +290,7 @@ print-compiler-flags: @echo ' - CXXFLAGS_WARNINGS ' $(CXXFLAGS_WARNINGS) @echo ' - CXXFLAGS_BOOST ' $(CXXFLAGS_BOOST) @echo ' - CXXFLAGS_EIGEN ' $(CXXFLAGS_EIGEN) + @echo ' - CXXFLAGS_FLTO ' $(CXXFLAGS_FLTO) @echo ' - CXXFLAGS_OS ' $(CXXFLAGS_OS) @echo ' - CXXFLAGS_GTEST ' $(CXXFLAGS_GTEST) @echo ' - CXXFLAGS_THREADS ' $(CXXFLAGS_THREADS) From 77f10598b9b05403fef0495cd57e6c2752a1f418 Mon Sep 17 00:00:00 2001 From: Steve Bronder Date: Sun, 7 Jun 2020 17:44:06 -0400 Subject: [PATCH 041/355] fix compile_flags missing tab --- make/compiler_flags | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/make/compiler_flags b/make/compiler_flags index 65d29413135..77d4fbc40c9 100644 --- a/make/compiler_flags +++ b/make/compiler_flags @@ -290,7 +290,7 @@ print-compiler-flags: @echo ' - CXXFLAGS_WARNINGS ' $(CXXFLAGS_WARNINGS) @echo ' - CXXFLAGS_BOOST ' $(CXXFLAGS_BOOST) @echo ' - CXXFLAGS_EIGEN ' $(CXXFLAGS_EIGEN) - @echo ' - CXXFLAGS_FLTO ' $(CXXFLAGS_FLTO) + @echo ' - CXXFLAGS_FLTO ' $(CXXFLAGS_FLTO) @echo ' - CXXFLAGS_OS ' $(CXXFLAGS_OS) @echo ' - CXXFLAGS_GTEST ' $(CXXFLAGS_GTEST) @echo ' - CXXFLAGS_THREADS ' $(CXXFLAGS_THREADS) From e1f6af33891a83946b986e53348dd30c5baf3af7 Mon Sep 17 00:00:00 2001 From: Steve Bronder Date: Mon, 8 Jun 2020 14:00:35 -0400 Subject: [PATCH 042/355] add flto flags to library flags --- make/compiler_flags | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/make/compiler_flags b/make/compiler_flags index 77d4fbc40c9..ae88fce48de 100644 --- a/make/compiler_flags +++ b/make/compiler_flags @@ -265,7 +265,7 @@ endif CXXFLAGS += $(CXXFLAGS_LANG) $(CXXFLAGS_OS) $(CXXFLAGS_FLTO) $(CXXFLAGS_WARNINGS) $(CXXFLAGS_BOOST) $(CXXFLAGS_EIGEN) $(CXXFLAGS_OPENCL) $(CXXFLAGS_MPI) $(CXXFLAGS_THREADS) $(CXXFLAGS_TBB) -O$(O) $(INC) CPPFLAGS += $(CPPFLAGS_LANG) $(CPPFLAGS_OS) $(CPPFLAGS_WARNINGS) $(CPPFLAGS_BOOST) $(CPPFLAGS_EIGEN) $(CPPFLAGS_OPENCL) $(CPPFLAGS_MPI) $(CPPFLAGS_TBB) -LDFLAGS += $(LDFLAGS_LANG) $(LDFLAGS_OS) $(LDFLAGS_WARNINGS) $(LDFLAGS_BOOST) $(LDFLAGS_EIGEN) $(LDFLAGS_OPENCL) $(LDFLAGS_MPI) $(LDFLAGS_TBB) +LDFLAGS += $(LDFLAGS_LANG) $(LDFLAGS_OS) $(CXXFLAGS_FLTO) $(LDFLAGS_WARNINGS) $(LDFLAGS_BOOST) $(LDFLAGS_EIGEN) $(LDFLAGS_OPENCL) $(LDFLAGS_MPI) $(LDFLAGS_TBB) LDLIBS += $(LDLIBS_LANG) $(LDLIBS_OS) $(LDLIBS_WARNINGS) $(LDLIBS_BOOST) $(LDLIBS_EIGEN) $(LDLIBS_OPENCL) $(LDLIBS_MPI) $(LDLIBS_TBB) .PHONY: print-compiler-flags From fdae56f2cb4aad72bdb64a93434a19514921422a Mon Sep 17 00:00:00 2001 From: Steve Bronder Date: Tue, 9 Jun 2020 02:11:46 -0400 Subject: [PATCH 043/355] remove flto changes --- make/compiler_flags | 22 +++++++--------------- 1 file changed, 7 insertions(+), 15 deletions(-) diff --git a/make/compiler_flags b/make/compiler_flags index ae88fce48de..de486bffc43 100644 --- a/make/compiler_flags +++ b/make/compiler_flags @@ -28,7 +28,7 @@ ifeq ($(OS),Linux) LIBRARY_SUFFIX ?= .so endif -## Set default compiler and flto compiler flags +## Set default compiler ifeq (default,$(origin CXX)) ifeq ($(OS),Darwin) ## Darwin is Mac OS X CXX := clang++ @@ -47,29 +47,20 @@ endif # - CXX_MINOR: minor version of CXX ifneq (,$(findstring clang,$(CXX))) CXX_TYPE ?= clang - CXXFLAGS_FLTO ?= -flto endif ifneq (,$(findstring mingw32-g,$(CXX))) CXX_TYPE ?= mingw32-gcc endif -ifneq ($(filter gcc,$(CXX)),) +ifneq (,$(findstring gcc,$(CXX))) CXX_TYPE ?= gcc - ifneq ($(OS),Windows_NT) - CXXFLAGS_FLTO ?= -fdevirtualize-at-ltrans -flto -fuse-linker-plugin -fipa-pta - endif endif -ifneq ($(filter g++,$(CXX)),) +ifneq (,$(findstring g++,$(CXX))) CXX_TYPE ?= gcc - ifneq ($(OS),Windows_NT) - CXXFLAGS_FLTO ?= -fdevirtualize-at-ltrans -flto -fuse-linker-plugin -fipa-pta - endif endif CXX_TYPE ?= other CXX_MAJOR := $(shell $(CXX) -dumpversion 2>&1 | cut -d'.' -f1) CXX_MINOR := $(shell $(CXX) -dumpversion 2>&1 | cut -d'.' -f2) - - ################################################################################ # Set default compiler flags # @@ -263,9 +254,11 @@ ifdef STAN_MPI CXXFLAGS_MPI ?= -Wno-delete-non-virtual-dtor endif -CXXFLAGS += $(CXXFLAGS_LANG) $(CXXFLAGS_OS) $(CXXFLAGS_FLTO) $(CXXFLAGS_WARNINGS) $(CXXFLAGS_BOOST) $(CXXFLAGS_EIGEN) $(CXXFLAGS_OPENCL) $(CXXFLAGS_MPI) $(CXXFLAGS_THREADS) $(CXXFLAGS_TBB) -O$(O) $(INC) + + +CXXFLAGS += $(CXXFLAGS_LANG) $(CXXFLAGS_OS) $(CXXFLAGS_WARNINGS) $(CXXFLAGS_BOOST) $(CXXFLAGS_EIGEN) $(CXXFLAGS_OPENCL) $(CXXFLAGS_MPI) $(CXXFLAGS_THREADS) $(CXXFLAGS_TBB) -O$(O) $(INC) CPPFLAGS += $(CPPFLAGS_LANG) $(CPPFLAGS_OS) $(CPPFLAGS_WARNINGS) $(CPPFLAGS_BOOST) $(CPPFLAGS_EIGEN) $(CPPFLAGS_OPENCL) $(CPPFLAGS_MPI) $(CPPFLAGS_TBB) -LDFLAGS += $(LDFLAGS_LANG) $(LDFLAGS_OS) $(CXXFLAGS_FLTO) $(LDFLAGS_WARNINGS) $(LDFLAGS_BOOST) $(LDFLAGS_EIGEN) $(LDFLAGS_OPENCL) $(LDFLAGS_MPI) $(LDFLAGS_TBB) +LDFLAGS += $(LDFLAGS_LANG) $(LDFLAGS_OS) $(LDFLAGS_WARNINGS) $(LDFLAGS_BOOST) $(LDFLAGS_EIGEN) $(LDFLAGS_OPENCL) $(LDFLAGS_MPI) $(LDFLAGS_TBB) LDLIBS += $(LDLIBS_LANG) $(LDLIBS_OS) $(LDLIBS_WARNINGS) $(LDLIBS_BOOST) $(LDLIBS_EIGEN) $(LDLIBS_OPENCL) $(LDLIBS_MPI) $(LDLIBS_TBB) .PHONY: print-compiler-flags @@ -290,7 +283,6 @@ print-compiler-flags: @echo ' - CXXFLAGS_WARNINGS ' $(CXXFLAGS_WARNINGS) @echo ' - CXXFLAGS_BOOST ' $(CXXFLAGS_BOOST) @echo ' - CXXFLAGS_EIGEN ' $(CXXFLAGS_EIGEN) - @echo ' - CXXFLAGS_FLTO ' $(CXXFLAGS_FLTO) @echo ' - CXXFLAGS_OS ' $(CXXFLAGS_OS) @echo ' - CXXFLAGS_GTEST ' $(CXXFLAGS_GTEST) @echo ' - CXXFLAGS_THREADS ' $(CXXFLAGS_THREADS) From cc702da7e7f97fdbe73398d1c9dcb16ca3d73f77 Mon Sep 17 00:00:00 2001 From: Steve Bronder Date: Tue, 9 Jun 2020 16:32:21 -0400 Subject: [PATCH 044/355] add back flto flag for mac and linux --- make/compiler_flags | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/make/compiler_flags b/make/compiler_flags index de486bffc43..9c191bfaa22 100644 --- a/make/compiler_flags +++ b/make/compiler_flags @@ -141,11 +141,15 @@ ifeq ($(OS),Darwin) ifeq (clang,$(CXX_TYPE)) CXXFLAGS_OS ?= -Wno-unknown-warning-option -Wno-tautological-compare -Wno-sign-compare endif + CXXFLAGS_FLTO ?= -flto + LDFLAGS_FLTO ?= -flto endif ifeq ($(OS),Linux) CPPFLAGS_GTEST ?= -DGTEST_HAS_PTHREAD=0 CXXFLAGS_WARNINGS ?= -Wno-sign-compare + CXXFLAGS_FLTO ?= -flto + LDFLAGS_FLTO ?= -flto ifeq (gcc,$(CXX_TYPE)) CXXFLAGS_OS ?= -pthread endif @@ -256,9 +260,9 @@ endif -CXXFLAGS += $(CXXFLAGS_LANG) $(CXXFLAGS_OS) $(CXXFLAGS_WARNINGS) $(CXXFLAGS_BOOST) $(CXXFLAGS_EIGEN) $(CXXFLAGS_OPENCL) $(CXXFLAGS_MPI) $(CXXFLAGS_THREADS) $(CXXFLAGS_TBB) -O$(O) $(INC) +CXXFLAGS += $(CXXFLAGS_LANG) $(CXXFLAGS_OS) $(CXXFLAGS_FLTO) $(CXXFLAGS_WARNINGS) $(CXXFLAGS_BOOST) $(CXXFLAGS_EIGEN) $(CXXFLAGS_OPENCL) $(CXXFLAGS_MPI) $(CXXFLAGS_THREADS) $(CXXFLAGS_TBB) -O$(O) $(INC) CPPFLAGS += $(CPPFLAGS_LANG) $(CPPFLAGS_OS) $(CPPFLAGS_WARNINGS) $(CPPFLAGS_BOOST) $(CPPFLAGS_EIGEN) $(CPPFLAGS_OPENCL) $(CPPFLAGS_MPI) $(CPPFLAGS_TBB) -LDFLAGS += $(LDFLAGS_LANG) $(LDFLAGS_OS) $(LDFLAGS_WARNINGS) $(LDFLAGS_BOOST) $(LDFLAGS_EIGEN) $(LDFLAGS_OPENCL) $(LDFLAGS_MPI) $(LDFLAGS_TBB) +LDFLAGS += $(LDFLAGS_LANG) $(LDFLAGS_OS) $(CXXFLAGS_FLTO) $(LDFLAGS_WARNINGS) $(LDFLAGS_BOOST) $(LDFLAGS_EIGEN) $(LDFLAGS_OPENCL) $(LDFLAGS_MPI) $(LDFLAGS_TBB) LDLIBS += $(LDLIBS_LANG) $(LDLIBS_OS) $(LDLIBS_WARNINGS) $(LDLIBS_BOOST) $(LDLIBS_EIGEN) $(LDLIBS_OPENCL) $(LDLIBS_MPI) $(LDLIBS_TBB) .PHONY: print-compiler-flags From c8b5eea0f52ab7b0e8d7f2e8cbf59a9c8f899c35 Mon Sep 17 00:00:00 2001 From: Steve Bronder Date: Tue, 9 Jun 2020 16:35:29 -0400 Subject: [PATCH 045/355] add flto to cppflags --- make/compiler_flags | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/make/compiler_flags b/make/compiler_flags index 9c191bfaa22..18439d3d09e 100644 --- a/make/compiler_flags +++ b/make/compiler_flags @@ -261,7 +261,7 @@ endif CXXFLAGS += $(CXXFLAGS_LANG) $(CXXFLAGS_OS) $(CXXFLAGS_FLTO) $(CXXFLAGS_WARNINGS) $(CXXFLAGS_BOOST) $(CXXFLAGS_EIGEN) $(CXXFLAGS_OPENCL) $(CXXFLAGS_MPI) $(CXXFLAGS_THREADS) $(CXXFLAGS_TBB) -O$(O) $(INC) -CPPFLAGS += $(CPPFLAGS_LANG) $(CPPFLAGS_OS) $(CPPFLAGS_WARNINGS) $(CPPFLAGS_BOOST) $(CPPFLAGS_EIGEN) $(CPPFLAGS_OPENCL) $(CPPFLAGS_MPI) $(CPPFLAGS_TBB) +CPPFLAGS += $(CPPFLAGS_LANG) $(CPPFLAGS_OS) $(CXXFLAGS_FLTO) $(CPPFLAGS_WARNINGS) $(CPPFLAGS_BOOST) $(CPPFLAGS_EIGEN) $(CPPFLAGS_OPENCL) $(CPPFLAGS_MPI) $(CPPFLAGS_TBB) LDFLAGS += $(LDFLAGS_LANG) $(LDFLAGS_OS) $(CXXFLAGS_FLTO) $(LDFLAGS_WARNINGS) $(LDFLAGS_BOOST) $(LDFLAGS_EIGEN) $(LDFLAGS_OPENCL) $(LDFLAGS_MPI) $(LDFLAGS_TBB) LDLIBS += $(LDLIBS_LANG) $(LDLIBS_OS) $(LDLIBS_WARNINGS) $(LDLIBS_BOOST) $(LDLIBS_EIGEN) $(LDLIBS_OPENCL) $(LDLIBS_MPI) $(LDLIBS_TBB) From 8726f4c6565811345d1cf796548a8eb756d9979b Mon Sep 17 00:00:00 2001 From: Steve Bronder Date: Tue, 9 Jun 2020 22:06:38 -0400 Subject: [PATCH 046/355] set ar by clang or gcc cxx_type --- make/compiler_flags | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/make/compiler_flags b/make/compiler_flags index 18439d3d09e..5c8d5e18210 100644 --- a/make/compiler_flags +++ b/make/compiler_flags @@ -61,6 +61,16 @@ CXX_TYPE ?= other CXX_MAJOR := $(shell $(CXX) -dumpversion 2>&1 | cut -d'.' -f1) CXX_MINOR := $(shell $(CXX) -dumpversion 2>&1 | cut -d'.' -f2) +# Set the ar to use +ifneq ($(OS),Windows_NT) + ifneq (,$(findstring clang,$(CXX_TYPE))) + AR := llvm-ar + endif + ifneq (,$(findstring gcc,$(CXX_TYPE))) + AR := gcc-ar + endif +endif + ################################################################################ # Set default compiler flags # From cba8d24b79585f60172308f5837b3191e957a647 Mon Sep 17 00:00:00 2001 From: Steve Bronder Date: Wed, 10 Jun 2020 14:22:03 -0400 Subject: [PATCH 047/355] remove vari_base --- stan/math/rev/core/vari.hpp | 30 +++++------------------------- stan/math/rev/meta/is_vari.hpp | 12 +++++++++--- 2 files changed, 14 insertions(+), 28 deletions(-) diff --git a/stan/math/rev/core/vari.hpp b/stan/math/rev/core/vari.hpp index 15323397781..790f8aeecff 100644 --- a/stan/math/rev/core/vari.hpp +++ b/stan/math/rev/core/vari.hpp @@ -14,27 +14,6 @@ namespace math { template class var_value; -/** - * Abstract class that all `vari_value` and it's derived classes inherit. - */ -class vari_base { - public: - /** - * Apply the chain rule to this variable based on the variables - * on which it depends. - */ - virtual void chain() {} - - /** - * Throw an illegal argument exception. - * - * Warning: Destructors should never called for var objects. - * - * @throw Logic exception always. - */ - virtual ~vari_base() {} -}; - /** * The variable implementation base class. * @@ -55,8 +34,7 @@ template class vari_value; template -class vari_value::value>> - : public vari_base { +class vari_value::value>> { private: template friend class var_value; @@ -138,14 +116,16 @@ class vari_value::value>> * propagating derivatives, setting the derivative of the * result with respect to itself to be 1. */ - void init_dependent() { adj_ = 1.0; } + inline void init_dependent() { adj_ = 1.0; } /** * Set the adjoint value of this variable to 0. This is used to * reset adjoints before propagating derivatives again (for * example in a Jacobian calculation). */ - void set_zero_adjoint() { adj_ = 0.0; } + inline void set_zero_adjoint() { adj_ = 0.0; } + + virtual void chain() {} /** * Insertion operator for vari. Prints the current value and diff --git a/stan/math/rev/meta/is_vari.hpp b/stan/math/rev/meta/is_vari.hpp index c91364bbe3c..9ba8b5e6e08 100644 --- a/stan/math/rev/meta/is_vari.hpp +++ b/stan/math/rev/meta/is_vari.hpp @@ -6,14 +6,20 @@ #include namespace stan { + +namespace internal { + template + struct is_vari_impl : std::false_type {}; + + template + struct is_vari_impl> : std::true_type {}; +} /** \ingroup type_trait * Specialization for checking if value of T minus cv qualifier and pointer is a * vari_value. */ template -struct is_vari< - T, std::enable_if_t>>::value>> +struct is_vari>::value>> : std::true_type {}; } // namespace stan From 4c671e127bd208d73f469a6a5596bbcf55fd950c Mon Sep 17 00:00:00 2001 From: Steve Bronder Date: Wed, 10 Jun 2020 14:49:55 -0400 Subject: [PATCH 048/355] use functors instead of lambdas --- make/compiler_flags | 2 +- stan/math/rev/core/grad.hpp | 2 +- stan/math/rev/core/set_zero_all_adjoints.hpp | 4 ++-- stan/math/rev/core/set_zero_all_adjoints_nested.hpp | 4 ++-- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/make/compiler_flags b/make/compiler_flags index 5d20960a48a..ac4df8907b2 100644 --- a/make/compiler_flags +++ b/make/compiler_flags @@ -28,7 +28,7 @@ ifeq ($(OS),Linux) LIBRARY_SUFFIX ?= .so endif -## Set default compiler and flto compiler flags +## Set default compiler ifeq (default,$(origin CXX)) ifeq ($(OS),Darwin) ## Darwin is Mac OS X CXX := clang++ diff --git a/stan/math/rev/core/grad.hpp b/stan/math/rev/core/grad.hpp index b45768e42dd..890f01bb983 100644 --- a/stan/math/rev/core/grad.hpp +++ b/stan/math/rev/core/grad.hpp @@ -33,7 +33,7 @@ static void grad(Vari* vi) { size_t end = ChainableStack::instance_->var_stack_.size(); size_t beginning = empty_nested() ? 0 : end - nested_size(); for (size_t i = end; i-- > beginning;) { - boost::apply_visitor([](auto*& x) { x->chain();}, ChainableStack::instance_->var_stack_[i]); + boost::apply_visitor(vari_chainer(), ChainableStack::instance_->var_stack_[i]); } } diff --git a/stan/math/rev/core/set_zero_all_adjoints.hpp b/stan/math/rev/core/set_zero_all_adjoints.hpp index 08e000b51f5..55ea7f7ed45 100644 --- a/stan/math/rev/core/set_zero_all_adjoints.hpp +++ b/stan/math/rev/core/set_zero_all_adjoints.hpp @@ -13,10 +13,10 @@ namespace math { */ static void set_zero_all_adjoints() { for (auto &x : ChainableStack::instance_->var_stack_) { - boost::apply_visitor([](auto*& x) { x->adj_ = 0.0;}, x); + boost::apply_visitor(vari_zero_adj(), x); } for (auto &x : ChainableStack::instance_->var_nochain_stack_) { - boost::apply_visitor([](auto*& x) { x->adj_ = 0.0;}, x); + boost::apply_visitor(vari_zero_adj(), x); } } diff --git a/stan/math/rev/core/set_zero_all_adjoints_nested.hpp b/stan/math/rev/core/set_zero_all_adjoints_nested.hpp index 169fdfd0653..0cf1591721d 100644 --- a/stan/math/rev/core/set_zero_all_adjoints_nested.hpp +++ b/stan/math/rev/core/set_zero_all_adjoints_nested.hpp @@ -27,14 +27,14 @@ static void set_zero_all_adjoints_nested() { // avoid wrap with unsigned when start1 == 0 for (size_t i = (start1 == 0U) ? 0U : (start1 - 1); i < ChainableStack::instance_->var_stack_.size(); ++i) { - boost::apply_visitor([](auto*& x) { x->adj_ = 0.0;}, ChainableStack::instance_->var_stack_[i]); + boost::apply_visitor(vari_zero_adj(), ChainableStack::instance_->var_stack_[i]); } size_t start2 = ChainableStack::instance_->nested_var_nochain_stack_sizes_.back(); for (size_t i = (start2 == 0U) ? 0U : (start2 - 1); i < ChainableStack::instance_->var_nochain_stack_.size(); ++i) { - boost::apply_visitor([](auto*& x) { x->adj_ = 0.0;}, ChainableStack::instance_->var_nochain_stack_[i]); + boost::apply_visitor(vari_zero_adj(), ChainableStack::instance_->var_nochain_stack_[i]); } } From e4581ca2ac5ae001b85428dea87f109c0298a542 Mon Sep 17 00:00:00 2001 From: Steve Bronder Date: Wed, 10 Jun 2020 15:08:33 -0400 Subject: [PATCH 049/355] remove flto from compiler_flags --- make/compiler_flags | 14 +------------- 1 file changed, 1 insertion(+), 13 deletions(-) diff --git a/make/compiler_flags b/make/compiler_flags index 9c79acdd5d5..20a490c7fda 100644 --- a/make/compiler_flags +++ b/make/compiler_flags @@ -28,11 +28,7 @@ ifeq ($(OS),Linux) LIBRARY_SUFFIX ?= .so endif -<<<<<<< HEAD ## Set default compiler -======= -## Set default compiler ->>>>>>> feature/vari-template-variant ifeq (default,$(origin CXX)) ifeq ($(OS),Darwin) ## Darwin is Mac OS X CXX := clang++ @@ -65,15 +61,7 @@ CXX_TYPE ?= other CXX_MAJOR := $(shell $(CXX) -dumpversion 2>&1 | cut -d'.' -f1) CXX_MINOR := $(shell $(CXX) -dumpversion 2>&1 | cut -d'.' -f2) -# Set the ar to use -ifneq ($(OS),Windows_NT) - ifneq (,$(findstring clang,$(CXX_TYPE))) - AR := llvm-ar - endif - ifneq (,$(findstring gcc,$(CXX_TYPE))) - AR := gcc-ar - endif -endif + ################################################################################ # Set default compiler flags From 52ae3b420ec7c88c37655530a588de777be5f9fc Mon Sep 17 00:00:00 2001 From: Stan Jenkins Date: Wed, 10 Jun 2020 19:15:02 +0000 Subject: [PATCH 050/355] [Jenkins] auto-formatting by clang-format version 6.0.0-1ubuntu2~16.04.1 (tags/RELEASE_600/final) --- stan/math/rev/core/chainablestack.hpp | 3 +- stan/math/rev/core/grad.hpp | 3 +- stan/math/rev/core/print_stack.hpp | 3 +- .../rev/core/set_zero_all_adjoints_nested.hpp | 6 ++- stan/math/rev/core/vari.hpp | 50 +++++++------------ stan/math/rev/meta/is_vari.hpp | 13 ++--- 6 files changed, 34 insertions(+), 44 deletions(-) diff --git a/stan/math/rev/core/chainablestack.hpp b/stan/math/rev/core/chainablestack.hpp index c6e2c424c41..e77bfd51e1d 100644 --- a/stan/math/rev/core/chainablestack.hpp +++ b/stan/math/rev/core/chainablestack.hpp @@ -11,7 +11,8 @@ class vari_value; class vari_base; class chainable_alloc; -using vari_variant = boost::variant*, vari_value*, vari_value*>; +using vari_variant = boost::variant*, vari_value*, + vari_value*>; using ChainableStack = AutodiffStackSingleton; diff --git a/stan/math/rev/core/grad.hpp b/stan/math/rev/core/grad.hpp index 890f01bb983..2201794c91c 100644 --- a/stan/math/rev/core/grad.hpp +++ b/stan/math/rev/core/grad.hpp @@ -33,7 +33,8 @@ static void grad(Vari* vi) { size_t end = ChainableStack::instance_->var_stack_.size(); size_t beginning = empty_nested() ? 0 : end - nested_size(); for (size_t i = end; i-- > beginning;) { - boost::apply_visitor(vari_chainer(), ChainableStack::instance_->var_stack_[i]); + boost::apply_visitor(vari_chainer(), + ChainableStack::instance_->var_stack_[i]); } } diff --git a/stan/math/rev/core/print_stack.hpp b/stan/math/rev/core/print_stack.hpp index 4f394e13663..d7dc55d185e 100644 --- a/stan/math/rev/core/print_stack.hpp +++ b/stan/math/rev/core/print_stack.hpp @@ -22,7 +22,8 @@ inline void print_stack(std::ostream& o) { << std::endl; // TODO(carpenter): this shouldn't need to be cast any more for (size_t i = 0; i < ChainableStack::instance_->var_stack_.size(); ++i) { - boost::apply_visitor(vari_printer(o, i), ChainableStack::instance_->var_stack_[i]); + boost::apply_visitor(vari_printer(o, i), + ChainableStack::instance_->var_stack_[i]); } } diff --git a/stan/math/rev/core/set_zero_all_adjoints_nested.hpp b/stan/math/rev/core/set_zero_all_adjoints_nested.hpp index 0cf1591721d..f94fa618722 100644 --- a/stan/math/rev/core/set_zero_all_adjoints_nested.hpp +++ b/stan/math/rev/core/set_zero_all_adjoints_nested.hpp @@ -27,14 +27,16 @@ static void set_zero_all_adjoints_nested() { // avoid wrap with unsigned when start1 == 0 for (size_t i = (start1 == 0U) ? 0U : (start1 - 1); i < ChainableStack::instance_->var_stack_.size(); ++i) { - boost::apply_visitor(vari_zero_adj(), ChainableStack::instance_->var_stack_[i]); + boost::apply_visitor(vari_zero_adj(), + ChainableStack::instance_->var_stack_[i]); } size_t start2 = ChainableStack::instance_->nested_var_nochain_stack_sizes_.back(); for (size_t i = (start2 == 0U) ? 0U : (start2 - 1); i < ChainableStack::instance_->var_nochain_stack_.size(); ++i) { - boost::apply_visitor(vari_zero_adj(), ChainableStack::instance_->var_nochain_stack_[i]); + boost::apply_visitor(vari_zero_adj(), + ChainableStack::instance_->var_nochain_stack_[i]); } } diff --git a/stan/math/rev/core/vari.hpp b/stan/math/rev/core/vari.hpp index 790f8aeecff..b90bb794c16 100644 --- a/stan/math/rev/core/vari.hpp +++ b/stan/math/rev/core/vari.hpp @@ -173,45 +173,29 @@ class vari_value::value>> { using vari = vari_value; class vari_zero_adj : public boost::static_visitor<> { - public: - inline void operator()(vari_value*& x) const { - x->adj_ = 0.0; - } - inline void operator()(vari_value*& x) const { - x->adj_ = 0.0; - } - inline void operator()(vari_value*& x) const { - x->adj_ = 0.0; - } + public: + inline void operator()(vari_value*& x) const { x->adj_ = 0.0; } + inline void operator()(vari_value*& x) const { x->adj_ = 0.0; } + inline void operator()(vari_value*& x) const { x->adj_ = 0.0; } }; class vari_chainer : public boost::static_visitor<> { - public: - inline void operator()(vari_value*& x) const { - x->chain(); - } - inline void operator()(vari_value*& x) const { - x->chain(); - } - inline void operator()(vari_value*& x) const { - x->chain(); - } + public: + inline void operator()(vari_value*& x) const { x->chain(); } + inline void operator()(vari_value*& x) const { x->chain(); } + inline void operator()(vari_value*& x) const { x->chain(); } }; class vari_printer : public boost::static_visitor<> { -public: - int i_{0}; - std::ostream& o_; - vari_printer(std::ostream& o, int i) : o_(o), i_(i) {} - template - void operator()(T*& x) const { - // TODO(carpenter): this shouldn't need to be cast any more - o_ << i_ << " " << x << " " - << x->val_ - << " : " - << x->adj_ - << std::endl; - } + public: + int i_{0}; + std::ostream& o_; + vari_printer(std::ostream& o, int i) : o_(o), i_(i) {} + template + void operator()(T*& x) const { + // TODO(carpenter): this shouldn't need to be cast any more + o_ << i_ << " " << x << " " << x->val_ << " : " << x->adj_ << std::endl; + } }; } // namespace math } // namespace stan diff --git a/stan/math/rev/meta/is_vari.hpp b/stan/math/rev/meta/is_vari.hpp index 9ba8b5e6e08..39fb79cb767 100644 --- a/stan/math/rev/meta/is_vari.hpp +++ b/stan/math/rev/meta/is_vari.hpp @@ -8,18 +8,19 @@ namespace stan { namespace internal { - template - struct is_vari_impl : std::false_type {}; +template +struct is_vari_impl : std::false_type {}; - template - struct is_vari_impl> : std::true_type {}; -} +template +struct is_vari_impl> : std::true_type {}; +} // namespace internal /** \ingroup type_trait * Specialization for checking if value of T minus cv qualifier and pointer is a * vari_value. */ template -struct is_vari>::value>> +struct is_vari>::value>> : std::true_type {}; } // namespace stan From 9358df7922731a9c558fcbe3400f83550b5bb2b3 Mon Sep 17 00:00:00 2001 From: Steve Bronder Date: Wed, 10 Jun 2020 20:56:27 -0400 Subject: [PATCH 051/355] remove promote_args_t in var member function templates --- stan/math/rev/core/operator_divide_equal.hpp | 2 +- stan/math/rev/core/operator_minus_equal.hpp | 2 +- .../math/rev/core/operator_multiply_equal.hpp | 2 +- stan/math/rev/core/operator_plus_equal.hpp | 2 +- stan/math/rev/core/var.hpp | 26 ++++++++----------- 5 files changed, 15 insertions(+), 19 deletions(-) diff --git a/stan/math/rev/core/operator_divide_equal.hpp b/stan/math/rev/core/operator_divide_equal.hpp index a3ed35bbd3b..3dae0cc79cb 100644 --- a/stan/math/rev/core/operator_divide_equal.hpp +++ b/stan/math/rev/core/operator_divide_equal.hpp @@ -8,7 +8,7 @@ namespace stan { namespace math { template -template >*> +template *> inline var_value& var_value>::operator/=( const var_value& b) { vi_ = new internal::divide_vv_vari(vi_, b.vi_); diff --git a/stan/math/rev/core/operator_minus_equal.hpp b/stan/math/rev/core/operator_minus_equal.hpp index 9c89c2578f4..e70a03bf69b 100644 --- a/stan/math/rev/core/operator_minus_equal.hpp +++ b/stan/math/rev/core/operator_minus_equal.hpp @@ -9,7 +9,7 @@ namespace stan { namespace math { template -template >*> +template *> inline var_value& var_value>::operator-=( const var_value& b) { vi_ = new internal::subtract_vv_vari(vi_, b.vi_); diff --git a/stan/math/rev/core/operator_multiply_equal.hpp b/stan/math/rev/core/operator_multiply_equal.hpp index fa74c2f543d..c995b6fa905 100644 --- a/stan/math/rev/core/operator_multiply_equal.hpp +++ b/stan/math/rev/core/operator_multiply_equal.hpp @@ -9,7 +9,7 @@ namespace stan { namespace math { template -template >*> +template *> inline var_value& var_value>::operator*=( const var_value& b) { vi_ = new internal::multiply_vv_vari(vi_, b.vi_); diff --git a/stan/math/rev/core/operator_plus_equal.hpp b/stan/math/rev/core/operator_plus_equal.hpp index c22bccd71d3..0da8b734b22 100644 --- a/stan/math/rev/core/operator_plus_equal.hpp +++ b/stan/math/rev/core/operator_plus_equal.hpp @@ -9,7 +9,7 @@ namespace stan { namespace math { template -template >*> +template *> inline var_value& var_value>::operator+=( const var_value& b) { vi_ = new internal::add_vv_vari(vi_, b.vi_); diff --git a/stan/math/rev/core/var.hpp b/stan/math/rev/core/var.hpp index 0889712d782..23353733b0a 100644 --- a/stan/math/rev/core/var.hpp +++ b/stan/math/rev/core/var.hpp @@ -39,13 +39,13 @@ class var_value> { // The internal value_type is always a floating point type using value_type = std::decay_t; using vari_type = vari_value; - + using vari_pointer = vari_type*; template using require_vari_convertible_t - = require_t*, vari_type*>>; + = require_t*, vari_pointer>>; template using require_not_vari_convertible_t = require_t< - bool_constant*, vari_type*>::value>>; + bool_constant*, vari_pointer>::value>>; /** * Pointer to the implementation of this variable. @@ -94,8 +94,7 @@ class var_value> { * same as `vari_value` so can be `reinterpret_cast` without a copy. * @param vi A vari_value pointer. */ - template , - require_vari_convertible_t* = nullptr> + template * = nullptr> var_value(vari_value* vi) // NOLINT : vi_(vi) {} @@ -106,8 +105,7 @@ class var_value> { * as the `value_type` of this `var_value`. * @param vi A `vari_value`. */ - template , - require_not_vari_convertible_t* = nullptr> + template * = nullptr> var_value(vari_value* vi) : vi_(new vari_type(*vi)) {} // NOLINT /** @@ -119,8 +117,7 @@ class var_value> { * param x a `var_value` whose underlying vari_type can be dynamically cast * to `this::vari_value``. */ - template , - require_not_vari_convertible_t* = nullptr> + template * = nullptr> var_value(const var_value& x) : vi_(new vari_type(*x.vi_)) {} // NOLINT /** @@ -129,8 +126,7 @@ class var_value> { * `var_value a(4.0); var_value b(a)` since the `value_type` for * a `var_value` with an integral type is a double. */ - template , - require_vari_convertible_t* = nullptr> + template * = nullptr> var_value(const var_value& x) : vi_(x.vi_) {} // NOLINT /** @@ -219,7 +215,7 @@ class var_value> { * @param b The variable to add to this variable. * @return The result of adding the specified variable to this variable. */ - template >* = nullptr> + template * = nullptr> inline var_value& operator+=(const var_value& b); /** @@ -248,7 +244,7 @@ class var_value> { * @return The result of subtracting the specified variable from * this variable. */ - template >* = nullptr> + template * = nullptr> inline var_value& operator-=(const var_value& b); /** @@ -278,7 +274,7 @@ class var_value> { * @return The result of multiplying this variable by the * specified variable. */ - template >* = nullptr> + template * = nullptr> inline var_value& operator*=(const var_value& b); /** @@ -307,7 +303,7 @@ class var_value> { * @return The result of dividing this variable by the * specified variable. */ - template >* = nullptr> + template * = nullptr> inline var_value& operator/=(const var_value& b); /** From eb18a98f4c99b262ddbb3f918e11cb75b2b5be31 Mon Sep 17 00:00:00 2001 From: Steve Bronder Date: Thu, 11 Jun 2020 12:56:35 -0400 Subject: [PATCH 052/355] remove TODO comment and fix grammar --- stan/math/rev/core/vari.hpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/stan/math/rev/core/vari.hpp b/stan/math/rev/core/vari.hpp index b90bb794c16..da31f91c90c 100644 --- a/stan/math/rev/core/vari.hpp +++ b/stan/math/rev/core/vari.hpp @@ -87,7 +87,7 @@ class vari_value::value>> { * @tparam S an Arithmetic type. * @param x Value of the constructed variable. * @param stacked If false will put this this vari on the nochain stack so - * that it's `chain()` method is not called. + * that its `chain()` method is not called. */ template ::value>* = nullptr> @@ -181,6 +181,7 @@ class vari_zero_adj : public boost::static_visitor<> { class vari_chainer : public boost::static_visitor<> { public: + template inline void operator()(vari_value*& x) const { x->chain(); } inline void operator()(vari_value*& x) const { x->chain(); } inline void operator()(vari_value*& x) const { x->chain(); } @@ -193,7 +194,6 @@ class vari_printer : public boost::static_visitor<> { vari_printer(std::ostream& o, int i) : o_(o), i_(i) {} template void operator()(T*& x) const { - // TODO(carpenter): this shouldn't need to be cast any more o_ << i_ << " " << x << " " << x->val_ << " : " << x->adj_ << std::endl; } }; From 3a711018a12953cb5f6d4806950e2883102e78a0 Mon Sep 17 00:00:00 2001 From: Stan Jenkins Date: Thu, 11 Jun 2020 13:11:29 -0400 Subject: [PATCH 053/355] [Jenkins] auto-formatting by clang-format version 6.0.0-1ubuntu2 (tags/RELEASE_600/final) --- stan/math/rev/core/vari.hpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/stan/math/rev/core/vari.hpp b/stan/math/rev/core/vari.hpp index da31f91c90c..cd663001de0 100644 --- a/stan/math/rev/core/vari.hpp +++ b/stan/math/rev/core/vari.hpp @@ -182,7 +182,9 @@ class vari_zero_adj : public boost::static_visitor<> { class vari_chainer : public boost::static_visitor<> { public: template - inline void operator()(vari_value*& x) const { x->chain(); } + inline void operator()(vari_value*& x) const { + x->chain(); + } inline void operator()(vari_value*& x) const { x->chain(); } inline void operator()(vari_value*& x) const { x->chain(); } }; From 944134648aa3f1010cfb53580b833e63bdb79c3f Mon Sep 17 00:00:00 2001 From: Steve Bronder Date: Thu, 11 Jun 2020 13:20:26 -0400 Subject: [PATCH 054/355] make visitor classes more generic --- stan/math/rev/core/vari.hpp | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/stan/math/rev/core/vari.hpp b/stan/math/rev/core/vari.hpp index da31f91c90c..134328fcaf5 100644 --- a/stan/math/rev/core/vari.hpp +++ b/stan/math/rev/core/vari.hpp @@ -174,17 +174,14 @@ using vari = vari_value; class vari_zero_adj : public boost::static_visitor<> { public: - inline void operator()(vari_value*& x) const { x->adj_ = 0.0; } - inline void operator()(vari_value*& x) const { x->adj_ = 0.0; } - inline void operator()(vari_value*& x) const { x->adj_ = 0.0; } + template * = nullptr> + inline void operator()(vari_value*& x) const { x->adj_ = 0.0; } }; class vari_chainer : public boost::static_visitor<> { public: template - inline void operator()(vari_value*& x) const { x->chain(); } - inline void operator()(vari_value*& x) const { x->chain(); } - inline void operator()(vari_value*& x) const { x->chain(); } + inline void operator()(vari_value*& x) const { x->chain(); } }; class vari_printer : public boost::static_visitor<> { From 30be7d221a06117c629b17faec769f1f5a33b377 Mon Sep 17 00:00:00 2001 From: Stan Jenkins Date: Thu, 11 Jun 2020 13:27:09 -0400 Subject: [PATCH 055/355] [Jenkins] auto-formatting by clang-format version 6.0.0-1ubuntu2 (tags/RELEASE_600/final) --- stan/math/rev/core/vari.hpp | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/stan/math/rev/core/vari.hpp b/stan/math/rev/core/vari.hpp index 134328fcaf5..1198b6247cd 100644 --- a/stan/math/rev/core/vari.hpp +++ b/stan/math/rev/core/vari.hpp @@ -175,13 +175,17 @@ using vari = vari_value; class vari_zero_adj : public boost::static_visitor<> { public: template * = nullptr> - inline void operator()(vari_value*& x) const { x->adj_ = 0.0; } + inline void operator()(vari_value*& x) const { + x->adj_ = 0.0; + } }; class vari_chainer : public boost::static_visitor<> { public: template - inline void operator()(vari_value*& x) const { x->chain(); } + inline void operator()(vari_value*& x) const { + x->chain(); + } }; class vari_printer : public boost::static_visitor<> { From 78b73b99f921fb7405d13b2e005a6b7e904921f3 Mon Sep 17 00:00:00 2001 From: Steve Bronder Date: Thu, 11 Jun 2020 13:46:59 -0400 Subject: [PATCH 056/355] add const correct stuff for vari value accessors in var --- stan/math/rev/core/var.hpp | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/stan/math/rev/core/var.hpp b/stan/math/rev/core/var.hpp index 23353733b0a..bcd3cb6f720 100644 --- a/stan/math/rev/core/var.hpp +++ b/stan/math/rev/core/var.hpp @@ -130,21 +130,31 @@ class var_value> { var_value(const var_value& x) : vi_(x.vi_) {} // NOLINT /** - * Return the value of this variable. + * Return a constant reference to the value of this variable. * * @return The value of this variable. */ - inline auto val() const { return vi_->val_; } + inline const auto& val() const { return vi_->val_; } /** - * Return the derivative of the root expression with + * Return a const reference of the derivative of the root expression with * respect to this expression. This method only works * after one of the `grad()` methods has been * called. * * @return Adjoint for this variable. */ - inline auto adj() const { return vi_->adj_; } + inline const auto& adj() const { return vi_->adj_; } + + /** + * Return a reference to the derivative of the root expression with + * respect to this expression. This method only works + * after one of the `grad()` methods has been + * called. + * + * @return Adjoint for this variable. + */ + inline auto& adj() { return vi_->adj_; } /** * Compute the gradient of this (dependent) variable with respect to From 5c69ed02ef8dee14ebe2c5a6efc08e8ee6843e09 Mon Sep 17 00:00:00 2001 From: Steve Bronder Date: Fri, 12 Jun 2020 12:39:29 -0400 Subject: [PATCH 057/355] remove constructors for mixed floating point types --- nohup.out | 8 +++++ stan/math/rev/core/var.hpp | 22 -------------- test/unit/math/rev/core/var_test.cpp | 44 +++++++++++----------------- 3 files changed, 25 insertions(+), 49 deletions(-) create mode 100644 nohup.out diff --git a/nohup.out b/nohup.out new file mode 100644 index 00000000000..c0b074fb927 --- /dev/null +++ b/nohup.out @@ -0,0 +1,8 @@ +../../3rdparty/chromium/sandbox/linux/seccomp-bpf-helpers/sigsys_handlers.cc:**CRASHING**:seccomp-bpf failure in syscall 0230 +The X11 connection broke (error 1). Did the X11 server die? +Gdk-Message: 14:16:34.225: rstudio: Fatal IO error 11 (Resource temporarily unavailable) on X server :1. + +../../3rdparty/chromium/sandbox/linux/seccomp-bpf-helpers/sigsys_handlers.cc:**CRASHING**:seccomp-bpf failure in syscall 0230 +The X11 connection broke (error 1). Did the X11 server die? +Gdk-Message: 14:16:54.082: rstudio: Fatal IO error 11 (Resource temporarily unavailable) on X server :1. + diff --git a/stan/math/rev/core/var.hpp b/stan/math/rev/core/var.hpp index bcd3cb6f720..e7de6b0a820 100644 --- a/stan/math/rev/core/var.hpp +++ b/stan/math/rev/core/var.hpp @@ -98,28 +98,6 @@ class var_value> { var_value(vari_value* vi) // NOLINT : vi_(vi) {} - /** - * Construct a variable from a pointer to a variable implementation when. - * the `value_type`s differ. This forces a copy of the vari - * @tparam S the type in the vari_value* that does not have the same type - * as the `value_type` of this `var_value`. - * @param vi A `vari_value`. - */ - template * = nullptr> - var_value(vari_value* vi) : vi_(new vari_type(*vi)) {} // NOLINT - - /** - * Construct from a var_value whose underlying value_type differs in type - * to this class's value_type. This is for cases such as - * `var_value a(5.0); var_value b(a);` - * @tparam S A type that is not the same as the underlying value type. - * same as the underlying value_type. - * param x a `var_value` whose underlying vari_type can be dynamically cast - * to `this::vari_value``. - */ - template * = nullptr> - var_value(const var_value& x) : vi_(new vari_type(*x.vi_)) {} // NOLINT - /** * Constructor from `var_value` whose value_type is the same as this class's * `value_type`. This is used in cases such as diff --git a/test/unit/math/rev/core/var_test.cpp b/test/unit/math/rev/core/var_test.cpp index 74567e4aa73..2b792ac41cd 100644 --- a/test/unit/math/rev/core/var_test.cpp +++ b/test/unit/math/rev/core/var_test.cpp @@ -14,8 +14,8 @@ struct AgradRev : public testing::Test { } }; -template -void ctor_overloads_impl_impl() { +template +void ctor_overloads_impl() { using stan::math::var_value; using stan::math::vari_value; using stan::math::test::type_name; @@ -23,13 +23,11 @@ void ctor_overloads_impl_impl() { EXPECT_FLOAT_EQ(3.7, var_value(3.7).val()) << "Failed For T: " << type_name() << "\n"; // make sure copy ctor is used rather than casting vari* to unsigned int - EXPECT_FLOAT_EQ(12.3, var_value(new vari_value(12.3)).val()) - << "Failed For T: " << type_name() << " and K: " << type_name() - << "\n"; + EXPECT_FLOAT_EQ(12.3, var_value(new vari_value(12.3)).val()) + << "Failed For T: " << type_name() << std::endl; // make sure rvalue var_value can be accepted - EXPECT_FLOAT_EQ(12.3, var_value(var_value(12.3)).val()) - << "Failed For T: " << type_name() << " and K: " << type_name() - << "\n"; + EXPECT_FLOAT_EQ(12.3, var_value(var_value(12.3)).val()) + << "Failed For T: " << type_name() << std::endl; // S type is preserved EXPECT_FLOAT_EQ(static_cast(3.7), var_value(static_cast(3.7)).val()) << "Failed For T: " << type_name() << " and S: " << type_name() @@ -40,32 +38,24 @@ void ctor_overloads_impl_impl() { << "\n"; } -template -void ctor_overloads_impl() { - ctor_overloads_impl_impl(); - ctor_overloads_impl_impl(); - ctor_overloads_impl_impl(); - ctor_overloads_impl_impl(); - ctor_overloads_impl_impl(); - ctor_overloads_impl_impl(); - ctor_overloads_impl_impl(); - ctor_overloads_impl_impl(); - ctor_overloads_impl_impl(); - ctor_overloads_impl_impl(); - ctor_overloads_impl_impl(); - ctor_overloads_impl_impl(); - ctor_overloads_impl_impl(); -} template void ctor_overloads() { - ctor_overloads_impl(); ctor_overloads_impl(); ctor_overloads_impl(); + ctor_overloads_impl(); + ctor_overloads_impl(); + ctor_overloads_impl(); + ctor_overloads_impl(); + ctor_overloads_impl(); + ctor_overloads_impl(); + ctor_overloads_impl(); + ctor_overloads_impl(); + ctor_overloads_impl(); + ctor_overloads_impl(); + ctor_overloads_impl(); } TEST_F(AgradRev, ctorOverloads) { - using stan::math::var; - using stan::math::vari; ctor_overloads(); ctor_overloads(); ctor_overloads(); From 917800ab6d081b51d36b418d9a7e6c065ca4050b Mon Sep 17 00:00:00 2001 From: Steve Bronder Date: Fri, 12 Jun 2020 12:39:45 -0400 Subject: [PATCH 058/355] remove nohup --- nohup.out | 8 -------- 1 file changed, 8 deletions(-) delete mode 100644 nohup.out diff --git a/nohup.out b/nohup.out deleted file mode 100644 index c0b074fb927..00000000000 --- a/nohup.out +++ /dev/null @@ -1,8 +0,0 @@ -../../3rdparty/chromium/sandbox/linux/seccomp-bpf-helpers/sigsys_handlers.cc:**CRASHING**:seccomp-bpf failure in syscall 0230 -The X11 connection broke (error 1). Did the X11 server die? -Gdk-Message: 14:16:34.225: rstudio: Fatal IO error 11 (Resource temporarily unavailable) on X server :1. - -../../3rdparty/chromium/sandbox/linux/seccomp-bpf-helpers/sigsys_handlers.cc:**CRASHING**:seccomp-bpf failure in syscall 0230 -The X11 connection broke (error 1). Did the X11 server die? -Gdk-Message: 14:16:54.082: rstudio: Fatal IO error 11 (Resource temporarily unavailable) on X server :1. - From ac7076cf0b4cbe7080dc7f4ed78a2d5751ebb74f Mon Sep 17 00:00:00 2001 From: Steve Bronder Date: Fri, 12 Jun 2020 19:51:31 -0400 Subject: [PATCH 059/355] switch order of members in vari_printer for order warning on windows --- stan/math/rev/core/vari.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stan/math/rev/core/vari.hpp b/stan/math/rev/core/vari.hpp index 1198b6247cd..0866099f9d9 100644 --- a/stan/math/rev/core/vari.hpp +++ b/stan/math/rev/core/vari.hpp @@ -190,8 +190,8 @@ class vari_chainer : public boost::static_visitor<> { class vari_printer : public boost::static_visitor<> { public: - int i_{0}; std::ostream& o_; + int i_{0}; vari_printer(std::ostream& o, int i) : o_(o), i_(i) {} template void operator()(T*& x) const { From 1cd05a8730d08384279061c343d7de070dc8d244 Mon Sep 17 00:00:00 2001 From: Steve Bronder Date: Fri, 12 Jun 2020 19:52:13 -0400 Subject: [PATCH 060/355] switch order of members in vari_printer for order warning on windows --- stan/math/rev/core/vari.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stan/math/rev/core/vari.hpp b/stan/math/rev/core/vari.hpp index 0866099f9d9..6fc4b62767b 100644 --- a/stan/math/rev/core/vari.hpp +++ b/stan/math/rev/core/vari.hpp @@ -194,7 +194,7 @@ class vari_printer : public boost::static_visitor<> { int i_{0}; vari_printer(std::ostream& o, int i) : o_(o), i_(i) {} template - void operator()(T*& x) const { + inline void operator()(T*& x) const { o_ << i_ << " " << x << " " << x->val_ << " : " << x->adj_ << std::endl; } }; From 276352461c244054b772f662376382d33e261cf4 Mon Sep 17 00:00:00 2001 From: Steve Bronder Date: Sat, 13 Jun 2020 19:15:04 -0400 Subject: [PATCH 061/355] call set_zero_adjoint_nested directly --- stan/math/rev/core/nested_rev_autodiff.hpp | 2 +- stan/math/rev/core/set_zero_all_adjoints.hpp | 2 +- stan/math/rev/core/set_zero_all_adjoints_nested.hpp | 10 +++++----- stan/math/rev/core/vari.hpp | 6 +++--- stan/math/rev/functor/coupled_ode_system.hpp | 2 +- test/unit/math/rev/core/var_test.cpp | 1 + 6 files changed, 12 insertions(+), 11 deletions(-) diff --git a/stan/math/rev/core/nested_rev_autodiff.hpp b/stan/math/rev/core/nested_rev_autodiff.hpp index a8f71d21c4a..2e44ca29850 100644 --- a/stan/math/rev/core/nested_rev_autodiff.hpp +++ b/stan/math/rev/core/nested_rev_autodiff.hpp @@ -39,7 +39,7 @@ class nested_rev_autodiff { * Reset all adjoint values in this nested stack * to zero. **/ - void set_zero_all_adjoints() { set_zero_all_adjoints_nested(); } + inline void set_zero_all_adjoints() { set_zero_all_adjoints_nested(); } }; } // namespace math diff --git a/stan/math/rev/core/set_zero_all_adjoints.hpp b/stan/math/rev/core/set_zero_all_adjoints.hpp index 55ea7f7ed45..f5664b7f80b 100644 --- a/stan/math/rev/core/set_zero_all_adjoints.hpp +++ b/stan/math/rev/core/set_zero_all_adjoints.hpp @@ -11,7 +11,7 @@ namespace math { /** * Reset all adjoint values in the stack to zero. */ -static void set_zero_all_adjoints() { +inline void set_zero_all_adjoints() { for (auto &x : ChainableStack::instance_->var_stack_) { boost::apply_visitor(vari_zero_adj(), x); } diff --git a/stan/math/rev/core/set_zero_all_adjoints_nested.hpp b/stan/math/rev/core/set_zero_all_adjoints_nested.hpp index f94fa618722..290786ab1a0 100644 --- a/stan/math/rev/core/set_zero_all_adjoints_nested.hpp +++ b/stan/math/rev/core/set_zero_all_adjoints_nested.hpp @@ -17,24 +17,24 @@ namespace math { * It is preferred to use the nested_rev_autodiff class for * nested autodiff class as it handles recovery of memory automatically. */ -static void set_zero_all_adjoints_nested() { +inline void set_zero_all_adjoints_nested() { if (empty_nested()) { throw std::logic_error( "empty_nested() must be false before calling" " set_zero_all_adjoints_nested()"); } size_t start1 = ChainableStack::instance_->nested_var_stack_sizes_.back(); + const auto stack_size = ChainableStack::instance_->var_stack_.size(); // avoid wrap with unsigned when start1 == 0 - for (size_t i = (start1 == 0U) ? 0U : (start1 - 1); - i < ChainableStack::instance_->var_stack_.size(); ++i) { + for (size_t i = (start1 == 0U) ? 0U : (start1 - 1); i < stack_size; ++i) { boost::apply_visitor(vari_zero_adj(), ChainableStack::instance_->var_stack_[i]); } size_t start2 = ChainableStack::instance_->nested_var_nochain_stack_sizes_.back(); - for (size_t i = (start2 == 0U) ? 0U : (start2 - 1); - i < ChainableStack::instance_->var_nochain_stack_.size(); ++i) { + const auto nochain_stack_size = ChainableStack::instance_->var_nochain_stack_.size(); + for (size_t i = (start2 == 0U) ? 0U : (start2 - 1); i < nochain_stack_size; ++i) { boost::apply_visitor(vari_zero_adj(), ChainableStack::instance_->var_nochain_stack_[i]); } diff --git a/stan/math/rev/core/vari.hpp b/stan/math/rev/core/vari.hpp index 6fc4b62767b..154b1daab26 100644 --- a/stan/math/rev/core/vari.hpp +++ b/stan/math/rev/core/vari.hpp @@ -172,7 +172,7 @@ class vari_value::value>> { // For backwards compatability the default is double using vari = vari_value; -class vari_zero_adj : public boost::static_visitor<> { +class vari_zero_adj final : public boost::static_visitor<> { public: template * = nullptr> inline void operator()(vari_value*& x) const { @@ -180,7 +180,7 @@ class vari_zero_adj : public boost::static_visitor<> { } }; -class vari_chainer : public boost::static_visitor<> { +class vari_chainer final : public boost::static_visitor<> { public: template inline void operator()(vari_value*& x) const { @@ -188,7 +188,7 @@ class vari_chainer : public boost::static_visitor<> { } }; -class vari_printer : public boost::static_visitor<> { +class vari_printer final : public boost::static_visitor<> { public: std::ostream& o_; int i_{0}; diff --git a/stan/math/rev/functor/coupled_ode_system.hpp b/stan/math/rev/functor/coupled_ode_system.hpp index 0ec42273374..12f47c5729c 100644 --- a/stan/math/rev/functor/coupled_ode_system.hpp +++ b/stan/math/rev/functor/coupled_ode_system.hpp @@ -478,7 +478,7 @@ struct coupled_ode_system { dz_dt[offset + i] = temp_deriv; } - nested.set_zero_all_adjoints(); + set_zero_all_adjoints_nested(); // Parameters stored on the outer (non-nested) nochain stack are not // reset to zero by the last call. This is done as a separate step here. // See efficiency note above on template specialization for more details diff --git a/test/unit/math/rev/core/var_test.cpp b/test/unit/math/rev/core/var_test.cpp index 2b792ac41cd..303d00a3ec6 100644 --- a/test/unit/math/rev/core/var_test.cpp +++ b/test/unit/math/rev/core/var_test.cpp @@ -1,5 +1,6 @@ #include #include +#include #include #include #include From ed1d828ab4efced3b48f76a1120ec55a108aacc2 Mon Sep 17 00:00:00 2001 From: Steve Bronder Date: Sat, 13 Jun 2020 19:17:40 -0400 Subject: [PATCH 062/355] call set_zero_adjoint_nested directly --- stan/math/rev/functor/coupled_ode_system.hpp | 4 ++-- stan/math/rev/functor/jacobian.hpp | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/stan/math/rev/functor/coupled_ode_system.hpp b/stan/math/rev/functor/coupled_ode_system.hpp index 12f47c5729c..773aebe625e 100644 --- a/stan/math/rev/functor/coupled_ode_system.hpp +++ b/stan/math/rev/functor/coupled_ode_system.hpp @@ -143,7 +143,7 @@ struct coupled_ode_system { dz_dt[offset + i] = temp_deriv; } - nested.set_zero_all_adjoints(); + set_zero_all_adjoints_nested(); // Parameters stored on the outer (non-nested) nochain stack are not // reset to zero by the last call. This is done as a separate step here. // See efficiency note above on template specialization for more details @@ -296,7 +296,7 @@ struct coupled_ode_system { dz_dt[offset + i] = temp_deriv; } - nested.set_zero_all_adjoints(); + set_zero_all_adjoints_nested(); } } diff --git a/stan/math/rev/functor/jacobian.hpp b/stan/math/rev/functor/jacobian.hpp index 75692b06911..c388a8bcccb 100644 --- a/stan/math/rev/functor/jacobian.hpp +++ b/stan/math/rev/functor/jacobian.hpp @@ -27,7 +27,7 @@ void jacobian(const F& f, const Eigen::Matrix& x, grad(fx_var(0).vi_); J.col(0) = x_var.adj(); for (int i = 1; i < fx_var.size(); ++i) { - nested.set_zero_all_adjoints(); + set_zero_all_adjoints_nested(); grad(fx_var(i).vi_); J.col(i) = x_var.adj(); } From 22f90a17d9b25c3b9569ec0efe6da598386cb53e Mon Sep 17 00:00:00 2001 From: Stan Jenkins Date: Sat, 13 Jun 2020 19:18:34 -0400 Subject: [PATCH 063/355] [Jenkins] auto-formatting by clang-format version 6.0.0-1ubuntu2 (tags/RELEASE_600/final) --- stan/math/rev/core/set_zero_all_adjoints_nested.hpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/stan/math/rev/core/set_zero_all_adjoints_nested.hpp b/stan/math/rev/core/set_zero_all_adjoints_nested.hpp index 290786ab1a0..342bb562c15 100644 --- a/stan/math/rev/core/set_zero_all_adjoints_nested.hpp +++ b/stan/math/rev/core/set_zero_all_adjoints_nested.hpp @@ -33,8 +33,10 @@ inline void set_zero_all_adjoints_nested() { size_t start2 = ChainableStack::instance_->nested_var_nochain_stack_sizes_.back(); - const auto nochain_stack_size = ChainableStack::instance_->var_nochain_stack_.size(); - for (size_t i = (start2 == 0U) ? 0U : (start2 - 1); i < nochain_stack_size; ++i) { + const auto nochain_stack_size + = ChainableStack::instance_->var_nochain_stack_.size(); + for (size_t i = (start2 == 0U) ? 0U : (start2 - 1); i < nochain_stack_size; + ++i) { boost::apply_visitor(vari_zero_adj(), ChainableStack::instance_->var_nochain_stack_[i]); } From d15494d81e9e9e1fbd6dff8df5dae3bfea9818ad Mon Sep 17 00:00:00 2001 From: Steve Bronder Date: Sat, 13 Jun 2020 20:55:04 -0400 Subject: [PATCH 064/355] try variant2 --- stan/math/rev/core/chainablestack.hpp | 4 +-- stan/math/rev/core/grad.hpp | 2 +- stan/math/rev/core/print_stack.hpp | 2 +- stan/math/rev/core/set_zero_all_adjoints.hpp | 4 +-- .../rev/core/set_zero_all_adjoints_nested.hpp | 4 +-- stan/math/rev/core/vari.hpp | 27 ++++++++++++------- 6 files changed, 25 insertions(+), 18 deletions(-) diff --git a/stan/math/rev/core/chainablestack.hpp b/stan/math/rev/core/chainablestack.hpp index e77bfd51e1d..bc35c3179b9 100644 --- a/stan/math/rev/core/chainablestack.hpp +++ b/stan/math/rev/core/chainablestack.hpp @@ -2,7 +2,7 @@ #define STAN_MATH_REV_CORE_CHAINABLESTACK_HPP #include -#include +#include namespace stan { namespace math { @@ -11,7 +11,7 @@ class vari_value; class vari_base; class chainable_alloc; -using vari_variant = boost::variant*, vari_value*, +using vari_variant = boost::variant2::variant*, vari_value*, vari_value*>; using ChainableStack = AutodiffStackSingleton; diff --git a/stan/math/rev/core/grad.hpp b/stan/math/rev/core/grad.hpp index 2201794c91c..8c06e6351d2 100644 --- a/stan/math/rev/core/grad.hpp +++ b/stan/math/rev/core/grad.hpp @@ -33,7 +33,7 @@ static void grad(Vari* vi) { size_t end = ChainableStack::instance_->var_stack_.size(); size_t beginning = empty_nested() ? 0 : end - nested_size(); for (size_t i = end; i-- > beginning;) { - boost::apply_visitor(vari_chainer(), + boost::variant2::visit([&](auto& x) {x->chain();}, ChainableStack::instance_->var_stack_[i]); } } diff --git a/stan/math/rev/core/print_stack.hpp b/stan/math/rev/core/print_stack.hpp index d7dc55d185e..3af1193a1c9 100644 --- a/stan/math/rev/core/print_stack.hpp +++ b/stan/math/rev/core/print_stack.hpp @@ -22,7 +22,7 @@ inline void print_stack(std::ostream& o) { << std::endl; // TODO(carpenter): this shouldn't need to be cast any more for (size_t i = 0; i < ChainableStack::instance_->var_stack_.size(); ++i) { - boost::apply_visitor(vari_printer(o, i), + boost::variant2::visit(vari_printer(o, i), ChainableStack::instance_->var_stack_[i]); } } diff --git a/stan/math/rev/core/set_zero_all_adjoints.hpp b/stan/math/rev/core/set_zero_all_adjoints.hpp index f5664b7f80b..a9a952157f4 100644 --- a/stan/math/rev/core/set_zero_all_adjoints.hpp +++ b/stan/math/rev/core/set_zero_all_adjoints.hpp @@ -13,10 +13,10 @@ namespace math { */ inline void set_zero_all_adjoints() { for (auto &x : ChainableStack::instance_->var_stack_) { - boost::apply_visitor(vari_zero_adj(), x); + boost::variant2::visit([&](auto& x) {x->adj_ = 0.0;}, x); } for (auto &x : ChainableStack::instance_->var_nochain_stack_) { - boost::apply_visitor(vari_zero_adj(), x); + boost::variant2::visit([&](auto& x) {x->adj_ = 0.0;}, x); } } diff --git a/stan/math/rev/core/set_zero_all_adjoints_nested.hpp b/stan/math/rev/core/set_zero_all_adjoints_nested.hpp index 290786ab1a0..6695fb7a2ba 100644 --- a/stan/math/rev/core/set_zero_all_adjoints_nested.hpp +++ b/stan/math/rev/core/set_zero_all_adjoints_nested.hpp @@ -27,7 +27,7 @@ inline void set_zero_all_adjoints_nested() { const auto stack_size = ChainableStack::instance_->var_stack_.size(); // avoid wrap with unsigned when start1 == 0 for (size_t i = (start1 == 0U) ? 0U : (start1 - 1); i < stack_size; ++i) { - boost::apply_visitor(vari_zero_adj(), + boost::variant2::visit([&](auto& x) {x->adj_ = 0.0;}, ChainableStack::instance_->var_stack_[i]); } @@ -35,7 +35,7 @@ inline void set_zero_all_adjoints_nested() { = ChainableStack::instance_->nested_var_nochain_stack_sizes_.back(); const auto nochain_stack_size = ChainableStack::instance_->var_nochain_stack_.size(); for (size_t i = (start2 == 0U) ? 0U : (start2 - 1); i < nochain_stack_size; ++i) { - boost::apply_visitor(vari_zero_adj(), + boost::variant2::visit([&](auto& x) {x->adj_ = 0.0;}, ChainableStack::instance_->var_nochain_stack_[i]); } } diff --git a/stan/math/rev/core/vari.hpp b/stan/math/rev/core/vari.hpp index 154b1daab26..d2c77c53bec 100644 --- a/stan/math/rev/core/vari.hpp +++ b/stan/math/rev/core/vari.hpp @@ -106,7 +106,17 @@ class vari_value::value>> { */ template ::value>* = nullptr> - vari_value(const vari_value& x) : val_(x.val_), adj_(x.adj_) { + vari_value(const vari_value& x) noexcept : val_(x.val_), adj_(x.adj_) { + ChainableStack::instance_->var_stack_.push_back(this); + } + /** + * Constructor from vari_value + * @tparam S An arithmetic type + * @param x A vari_value + */ + template ::value>* = nullptr> + vari_value(vari_value&& x) noexcept : val_(x.val_), adj_(x.adj_) { ChainableStack::instance_->var_stack_.push_back(this); } @@ -172,24 +182,21 @@ class vari_value::value>> { // For backwards compatability the default is double using vari = vari_value; -class vari_zero_adj final : public boost::static_visitor<> { - public: - template * = nullptr> - inline void operator()(vari_value*& x) const { +struct vari_zero_adj { + template + inline void operator()(T&& x) const { x->adj_ = 0.0; } }; -class vari_chainer final : public boost::static_visitor<> { - public: +struct vari_chainer { template - inline void operator()(vari_value*& x) const { + inline void operator()(T&& x) const { x->chain(); } }; -class vari_printer final : public boost::static_visitor<> { - public: +struct vari_printer { std::ostream& o_; int i_{0}; vari_printer(std::ostream& o, int i) : o_(o), i_(i) {} From 5c6836bcba648c0d28cd4d8bd07fcc50fa17be75 Mon Sep 17 00:00:00 2001 From: Steve Bronder Date: Sat, 13 Jun 2020 21:30:53 -0400 Subject: [PATCH 065/355] add noexcept to member functions that will not throw --- stan/math/rev/core/vari.hpp | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/stan/math/rev/core/vari.hpp b/stan/math/rev/core/vari.hpp index d2c77c53bec..49adc896fbc 100644 --- a/stan/math/rev/core/vari.hpp +++ b/stan/math/rev/core/vari.hpp @@ -68,8 +68,8 @@ class vari_value::value>> { */ template ::value>* = nullptr> - vari_value(S x) : val_(x), adj_(0.0) { // NOLINT - ChainableStack::instance_->var_stack_.push_back(this); + vari_value(S x) noexcept : val_(x), adj_(0.0) { // NOLINT + ChainableStack::instance_->var_stack_.emplace_back(this); } /** @@ -91,11 +91,11 @@ class vari_value::value>> { */ template ::value>* = nullptr> - vari_value(S x, bool stacked) : val_(x), adj_(0.0) { + vari_value(S x, bool stacked) noexcept : val_(x), adj_(0.0) { if (stacked) { - ChainableStack::instance_->var_stack_.push_back(this); + ChainableStack::instance_->var_stack_.emplace_back(this); } else { - ChainableStack::instance_->var_nochain_stack_.push_back(this); + ChainableStack::instance_->var_nochain_stack_.emplace_back(this); } } @@ -107,7 +107,7 @@ class vari_value::value>> { template ::value>* = nullptr> vari_value(const vari_value& x) noexcept : val_(x.val_), adj_(x.adj_) { - ChainableStack::instance_->var_stack_.push_back(this); + ChainableStack::instance_->var_stack_.emplace_back(this); } /** * Constructor from vari_value @@ -117,7 +117,7 @@ class vari_value::value>> { template ::value>* = nullptr> vari_value(vari_value&& x) noexcept : val_(x.val_), adj_(x.adj_) { - ChainableStack::instance_->var_stack_.push_back(this); + ChainableStack::instance_->var_stack_.emplace_back(this); } /** @@ -126,14 +126,14 @@ class vari_value::value>> { * propagating derivatives, setting the derivative of the * result with respect to itself to be 1. */ - inline void init_dependent() { adj_ = 1.0; } + inline void init_dependent() noexcept { adj_ = 1.0; } /** * Set the adjoint value of this variable to 0. This is used to * reset adjoints before propagating derivatives again (for * example in a Jacobian calculation). */ - inline void set_zero_adjoint() { adj_ = 0.0; } + inline void set_zero_adjoint() noexcept { adj_ = 0.0; } virtual void chain() {} @@ -160,7 +160,7 @@ class vari_value::value>> { * @param nbytes Number of bytes to allocate. * @return Pointer to allocated bytes. */ - static inline void* operator new(size_t nbytes) { + static inline void* operator new(size_t nbytes) noexcept { return ChainableStack::instance_->memalloc_.alloc(nbytes); } @@ -175,7 +175,7 @@ class vari_value::value>> { * See the discussion of "plugging the memory leak" in: * http://www.parashift.com/c++-faq/memory-pools.html */ - static inline void operator delete(void* /* ignore arg */) { /* no op */ + static inline void operator delete(void* /* ignore arg */) noexcept { /* no op */ } }; From d8bb2ac5353a93ceb73e682b4623498d2a44ac17 Mon Sep 17 00:00:00 2001 From: Steve Bronder Date: Sat, 13 Jun 2020 21:41:16 -0400 Subject: [PATCH 066/355] use lambda for print_stack --- stan/math/rev/core/print_stack.hpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/stan/math/rev/core/print_stack.hpp b/stan/math/rev/core/print_stack.hpp index 3af1193a1c9..97f09da10cc 100644 --- a/stan/math/rev/core/print_stack.hpp +++ b/stan/math/rev/core/print_stack.hpp @@ -22,8 +22,9 @@ inline void print_stack(std::ostream& o) { << std::endl; // TODO(carpenter): this shouldn't need to be cast any more for (size_t i = 0; i < ChainableStack::instance_->var_stack_.size(); ++i) { - boost::variant2::visit(vari_printer(o, i), - ChainableStack::instance_->var_stack_[i]); + boost::variant2::visit([&o, &i](auto x) { + o << i << " " << x << " " << x->val_ << " : " << x->adj_ << std::endl; + }, ChainableStack::instance_->var_stack_[i]); } } From cd1b3c4f9b7df45d5b5dca39881853c219424e47 Mon Sep 17 00:00:00 2001 From: Stan Jenkins Date: Sun, 14 Jun 2020 01:46:34 +0000 Subject: [PATCH 067/355] [Jenkins] auto-formatting by clang-format version 6.0.0-1ubuntu2~16.04.1 (tags/RELEASE_600/final) --- stan/math/rev/core/chainablestack.hpp | 5 +++-- stan/math/rev/core/grad.hpp | 4 ++-- stan/math/rev/core/print_stack.hpp | 9 ++++++--- stan/math/rev/core/set_zero_all_adjoints.hpp | 8 ++++---- .../math/rev/core/set_zero_all_adjoints_nested.hpp | 14 ++++++++------ stan/math/rev/core/vari.hpp | 3 ++- 6 files changed, 25 insertions(+), 18 deletions(-) diff --git a/stan/math/rev/core/chainablestack.hpp b/stan/math/rev/core/chainablestack.hpp index bc35c3179b9..6dd314a84c6 100644 --- a/stan/math/rev/core/chainablestack.hpp +++ b/stan/math/rev/core/chainablestack.hpp @@ -11,8 +11,9 @@ class vari_value; class vari_base; class chainable_alloc; -using vari_variant = boost::variant2::variant*, vari_value*, - vari_value*>; +using vari_variant + = boost::variant2::variant*, vari_value*, + vari_value*>; using ChainableStack = AutodiffStackSingleton; diff --git a/stan/math/rev/core/grad.hpp b/stan/math/rev/core/grad.hpp index 8c06e6351d2..4aa2d6fc66f 100644 --- a/stan/math/rev/core/grad.hpp +++ b/stan/math/rev/core/grad.hpp @@ -33,8 +33,8 @@ static void grad(Vari* vi) { size_t end = ChainableStack::instance_->var_stack_.size(); size_t beginning = empty_nested() ? 0 : end - nested_size(); for (size_t i = end; i-- > beginning;) { - boost::variant2::visit([&](auto& x) {x->chain();}, - ChainableStack::instance_->var_stack_[i]); + boost::variant2::visit([&](auto& x) { x->chain(); }, + ChainableStack::instance_->var_stack_[i]); } } diff --git a/stan/math/rev/core/print_stack.hpp b/stan/math/rev/core/print_stack.hpp index 97f09da10cc..7718dbefa26 100644 --- a/stan/math/rev/core/print_stack.hpp +++ b/stan/math/rev/core/print_stack.hpp @@ -22,9 +22,12 @@ inline void print_stack(std::ostream& o) { << std::endl; // TODO(carpenter): this shouldn't need to be cast any more for (size_t i = 0; i < ChainableStack::instance_->var_stack_.size(); ++i) { - boost::variant2::visit([&o, &i](auto x) { - o << i << " " << x << " " << x->val_ << " : " << x->adj_ << std::endl; - }, ChainableStack::instance_->var_stack_[i]); + boost::variant2::visit( + [&o, &i](auto x) { + o << i << " " << x << " " << x->val_ << " : " << x->adj_ + << std::endl; + }, + ChainableStack::instance_->var_stack_[i]); } } diff --git a/stan/math/rev/core/set_zero_all_adjoints.hpp b/stan/math/rev/core/set_zero_all_adjoints.hpp index a9a952157f4..7b5714ede0a 100644 --- a/stan/math/rev/core/set_zero_all_adjoints.hpp +++ b/stan/math/rev/core/set_zero_all_adjoints.hpp @@ -12,11 +12,11 @@ namespace math { * Reset all adjoint values in the stack to zero. */ inline void set_zero_all_adjoints() { - for (auto &x : ChainableStack::instance_->var_stack_) { - boost::variant2::visit([&](auto& x) {x->adj_ = 0.0;}, x); + for (auto& x : ChainableStack::instance_->var_stack_) { + boost::variant2::visit([&](auto& x) { x->adj_ = 0.0; }, x); } - for (auto &x : ChainableStack::instance_->var_nochain_stack_) { - boost::variant2::visit([&](auto& x) {x->adj_ = 0.0;}, x); + for (auto& x : ChainableStack::instance_->var_nochain_stack_) { + boost::variant2::visit([&](auto& x) { x->adj_ = 0.0; }, x); } } diff --git a/stan/math/rev/core/set_zero_all_adjoints_nested.hpp b/stan/math/rev/core/set_zero_all_adjoints_nested.hpp index 6695fb7a2ba..d128bf88bc1 100644 --- a/stan/math/rev/core/set_zero_all_adjoints_nested.hpp +++ b/stan/math/rev/core/set_zero_all_adjoints_nested.hpp @@ -27,16 +27,18 @@ inline void set_zero_all_adjoints_nested() { const auto stack_size = ChainableStack::instance_->var_stack_.size(); // avoid wrap with unsigned when start1 == 0 for (size_t i = (start1 == 0U) ? 0U : (start1 - 1); i < stack_size; ++i) { - boost::variant2::visit([&](auto& x) {x->adj_ = 0.0;}, - ChainableStack::instance_->var_stack_[i]); + boost::variant2::visit([&](auto& x) { x->adj_ = 0.0; }, + ChainableStack::instance_->var_stack_[i]); } size_t start2 = ChainableStack::instance_->nested_var_nochain_stack_sizes_.back(); - const auto nochain_stack_size = ChainableStack::instance_->var_nochain_stack_.size(); - for (size_t i = (start2 == 0U) ? 0U : (start2 - 1); i < nochain_stack_size; ++i) { - boost::variant2::visit([&](auto& x) {x->adj_ = 0.0;}, - ChainableStack::instance_->var_nochain_stack_[i]); + const auto nochain_stack_size + = ChainableStack::instance_->var_nochain_stack_.size(); + for (size_t i = (start2 == 0U) ? 0U : (start2 - 1); i < nochain_stack_size; + ++i) { + boost::variant2::visit([&](auto& x) { x->adj_ = 0.0; }, + ChainableStack::instance_->var_nochain_stack_[i]); } } diff --git a/stan/math/rev/core/vari.hpp b/stan/math/rev/core/vari.hpp index 49adc896fbc..dca9da48a19 100644 --- a/stan/math/rev/core/vari.hpp +++ b/stan/math/rev/core/vari.hpp @@ -175,7 +175,8 @@ class vari_value::value>> { * See the discussion of "plugging the memory leak" in: * http://www.parashift.com/c++-faq/memory-pools.html */ - static inline void operator delete(void* /* ignore arg */) noexcept { /* no op */ + static inline void operator delete( + void* /* ignore arg */) noexcept { /* no op */ } }; From 5630a65d73c9e4f511a4dcf8439a9d71f4909f8d Mon Sep 17 00:00:00 2001 From: Steve Bronder Date: Sun, 14 Jun 2020 16:10:20 -0400 Subject: [PATCH 068/355] use eigen strong inline and static on set_zero_adj() --- stan/math/rev/core/chainablestack.hpp | 3 +-- stan/math/rev/core/set_zero_all_adjoints.hpp | 6 +++--- stan/math/rev/core/set_zero_all_adjoints_nested.hpp | 6 +++--- test/unit/math/rev/core/var_test.cpp | 1 - test/unit/math/rev/core/vari_test.cpp | 2 +- 5 files changed, 8 insertions(+), 10 deletions(-) diff --git a/stan/math/rev/core/chainablestack.hpp b/stan/math/rev/core/chainablestack.hpp index 6dd314a84c6..0eb6aada190 100644 --- a/stan/math/rev/core/chainablestack.hpp +++ b/stan/math/rev/core/chainablestack.hpp @@ -12,8 +12,7 @@ class vari_base; class chainable_alloc; using vari_variant - = boost::variant2::variant*, vari_value*, - vari_value*>; + = boost::variant2::variant*, vari_value*>; using ChainableStack = AutodiffStackSingleton; diff --git a/stan/math/rev/core/set_zero_all_adjoints.hpp b/stan/math/rev/core/set_zero_all_adjoints.hpp index 7b5714ede0a..5cb59f39c26 100644 --- a/stan/math/rev/core/set_zero_all_adjoints.hpp +++ b/stan/math/rev/core/set_zero_all_adjoints.hpp @@ -11,12 +11,12 @@ namespace math { /** * Reset all adjoint values in the stack to zero. */ -inline void set_zero_all_adjoints() { + static EIGEN_STRONG_INLINE void set_zero_all_adjoints() { for (auto& x : ChainableStack::instance_->var_stack_) { - boost::variant2::visit([&](auto& x) { x->adj_ = 0.0; }, x); + boost::variant2::visit([](auto& x) { x->adj_ = 0.0; }, x); } for (auto& x : ChainableStack::instance_->var_nochain_stack_) { - boost::variant2::visit([&](auto& x) { x->adj_ = 0.0; }, x); + boost::variant2::visit([](auto& x) { x->adj_ = 0.0; }, x); } } diff --git a/stan/math/rev/core/set_zero_all_adjoints_nested.hpp b/stan/math/rev/core/set_zero_all_adjoints_nested.hpp index d128bf88bc1..0b7fc446a62 100644 --- a/stan/math/rev/core/set_zero_all_adjoints_nested.hpp +++ b/stan/math/rev/core/set_zero_all_adjoints_nested.hpp @@ -17,7 +17,7 @@ namespace math { * It is preferred to use the nested_rev_autodiff class for * nested autodiff class as it handles recovery of memory automatically. */ -inline void set_zero_all_adjoints_nested() { +static EIGEN_STRONG_INLINE void set_zero_all_adjoints_nested() { if (empty_nested()) { throw std::logic_error( "empty_nested() must be false before calling" @@ -27,7 +27,7 @@ inline void set_zero_all_adjoints_nested() { const auto stack_size = ChainableStack::instance_->var_stack_.size(); // avoid wrap with unsigned when start1 == 0 for (size_t i = (start1 == 0U) ? 0U : (start1 - 1); i < stack_size; ++i) { - boost::variant2::visit([&](auto& x) { x->adj_ = 0.0; }, + boost::variant2::visit([](auto& x) { x->adj_ = 0.0; }, ChainableStack::instance_->var_stack_[i]); } @@ -37,7 +37,7 @@ inline void set_zero_all_adjoints_nested() { = ChainableStack::instance_->var_nochain_stack_.size(); for (size_t i = (start2 == 0U) ? 0U : (start2 - 1); i < nochain_stack_size; ++i) { - boost::variant2::visit([&](auto& x) { x->adj_ = 0.0; }, + boost::variant2::visit([](auto& x) { x->adj_ = 0.0; }, ChainableStack::instance_->var_nochain_stack_[i]); } } diff --git a/test/unit/math/rev/core/var_test.cpp b/test/unit/math/rev/core/var_test.cpp index 303d00a3ec6..e9c744d6e22 100644 --- a/test/unit/math/rev/core/var_test.cpp +++ b/test/unit/math/rev/core/var_test.cpp @@ -59,7 +59,6 @@ void ctor_overloads() { TEST_F(AgradRev, ctorOverloads) { ctor_overloads(); ctor_overloads(); - ctor_overloads(); } TEST_F(AgradRev, a_eq_x) { diff --git a/test/unit/math/rev/core/vari_test.cpp b/test/unit/math/rev/core/vari_test.cpp index fc5a6e34ab5..355d74a6769 100644 --- a/test/unit/math/rev/core/vari_test.cpp +++ b/test/unit/math/rev/core/vari_test.cpp @@ -10,7 +10,7 @@ TEST(AgradRev, insertion_operator) { } TEST(AgradRev, long_double_test) { - stan::math::vari_value v(5); + stan::math::vari_value v(5); std::stringstream ss; ss << &v; EXPECT_EQ("5:0", ss.str()); From 5285fdd7899db5faf9d5d8a36c098c2c09915167 Mon Sep 17 00:00:00 2001 From: Stan Jenkins Date: Sun, 14 Jun 2020 16:11:13 -0400 Subject: [PATCH 069/355] [Jenkins] auto-formatting by clang-format version 6.0.0-1ubuntu2 (tags/RELEASE_600/final) --- stan/math/rev/core/set_zero_all_adjoints.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stan/math/rev/core/set_zero_all_adjoints.hpp b/stan/math/rev/core/set_zero_all_adjoints.hpp index 5cb59f39c26..cfd1edb83ec 100644 --- a/stan/math/rev/core/set_zero_all_adjoints.hpp +++ b/stan/math/rev/core/set_zero_all_adjoints.hpp @@ -11,7 +11,7 @@ namespace math { /** * Reset all adjoint values in the stack to zero. */ - static EIGEN_STRONG_INLINE void set_zero_all_adjoints() { +static EIGEN_STRONG_INLINE void set_zero_all_adjoints() { for (auto& x : ChainableStack::instance_->var_stack_) { boost::variant2::visit([](auto& x) { x->adj_ = 0.0; }, x); } From 006fbf60bfd9a3ec9e2030408a7b81c9479c197c Mon Sep 17 00:00:00 2001 From: Steve Bronder Date: Sun, 14 Jun 2020 16:20:18 -0400 Subject: [PATCH 070/355] testing if vari long slows us down --- stan/math/rev/core/chainablestack.hpp | 2 +- stan/math/rev/core/vari.hpp | 17 +---------------- 2 files changed, 2 insertions(+), 17 deletions(-) diff --git a/stan/math/rev/core/chainablestack.hpp b/stan/math/rev/core/chainablestack.hpp index 0eb6aada190..730dbb40b98 100644 --- a/stan/math/rev/core/chainablestack.hpp +++ b/stan/math/rev/core/chainablestack.hpp @@ -12,7 +12,7 @@ class vari_base; class chainable_alloc; using vari_variant - = boost::variant2::variant*, vari_value*>; + = boost::variant2::variant*, vari_value*, vari_value*>; using ChainableStack = AutodiffStackSingleton; diff --git a/stan/math/rev/core/vari.hpp b/stan/math/rev/core/vari.hpp index dca9da48a19..50782d730b0 100644 --- a/stan/math/rev/core/vari.hpp +++ b/stan/math/rev/core/vari.hpp @@ -175,28 +175,13 @@ class vari_value::value>> { * See the discussion of "plugging the memory leak" in: * http://www.parashift.com/c++-faq/memory-pools.html */ - static inline void operator delete( - void* /* ignore arg */) noexcept { /* no op */ + static inline void operator delete(void* /* ignore arg */) noexcept { /* no op */ } }; // For backwards compatability the default is double using vari = vari_value; -struct vari_zero_adj { - template - inline void operator()(T&& x) const { - x->adj_ = 0.0; - } -}; - -struct vari_chainer { - template - inline void operator()(T&& x) const { - x->chain(); - } -}; - struct vari_printer { std::ostream& o_; int i_{0}; From 538b0118d2c05378cac09a1866b29077387045a8 Mon Sep 17 00:00:00 2001 From: Steve Bronder Date: Sun, 14 Jun 2020 16:27:12 -0400 Subject: [PATCH 071/355] add back tests for vari long double --- test/unit/math/rev/core/var_test.cpp | 1 + test/unit/math/rev/core/vari_test.cpp | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/test/unit/math/rev/core/var_test.cpp b/test/unit/math/rev/core/var_test.cpp index e9c744d6e22..303d00a3ec6 100644 --- a/test/unit/math/rev/core/var_test.cpp +++ b/test/unit/math/rev/core/var_test.cpp @@ -59,6 +59,7 @@ void ctor_overloads() { TEST_F(AgradRev, ctorOverloads) { ctor_overloads(); ctor_overloads(); + ctor_overloads(); } TEST_F(AgradRev, a_eq_x) { diff --git a/test/unit/math/rev/core/vari_test.cpp b/test/unit/math/rev/core/vari_test.cpp index 355d74a6769..fc5a6e34ab5 100644 --- a/test/unit/math/rev/core/vari_test.cpp +++ b/test/unit/math/rev/core/vari_test.cpp @@ -10,7 +10,7 @@ TEST(AgradRev, insertion_operator) { } TEST(AgradRev, long_double_test) { - stan::math::vari_value v(5); + stan::math::vari_value v(5); std::stringstream ss; ss << &v; EXPECT_EQ("5:0", ss.str()); From ad2d15f2a80a264fc3fcb3cf13e4b4e266da8db2 Mon Sep 17 00:00:00 2001 From: Stan Jenkins Date: Sun, 14 Jun 2020 16:28:38 -0400 Subject: [PATCH 072/355] [Jenkins] auto-formatting by clang-format version 6.0.0-1ubuntu2 (tags/RELEASE_600/final) --- stan/math/rev/core/chainablestack.hpp | 3 ++- stan/math/rev/core/vari.hpp | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/stan/math/rev/core/chainablestack.hpp b/stan/math/rev/core/chainablestack.hpp index 730dbb40b98..6dd314a84c6 100644 --- a/stan/math/rev/core/chainablestack.hpp +++ b/stan/math/rev/core/chainablestack.hpp @@ -12,7 +12,8 @@ class vari_base; class chainable_alloc; using vari_variant - = boost::variant2::variant*, vari_value*, vari_value*>; + = boost::variant2::variant*, vari_value*, + vari_value*>; using ChainableStack = AutodiffStackSingleton; diff --git a/stan/math/rev/core/vari.hpp b/stan/math/rev/core/vari.hpp index 50782d730b0..d5749507323 100644 --- a/stan/math/rev/core/vari.hpp +++ b/stan/math/rev/core/vari.hpp @@ -175,7 +175,8 @@ class vari_value::value>> { * See the discussion of "plugging the memory leak" in: * http://www.parashift.com/c++-faq/memory-pools.html */ - static inline void operator delete(void* /* ignore arg */) noexcept { /* no op */ + static inline void operator delete( + void* /* ignore arg */) noexcept { /* no op */ } }; From 28f3373d6eeaeababf2e6e6d11d8d2d1e9568b68 Mon Sep 17 00:00:00 2001 From: Steve Bronder Date: Mon, 15 Jun 2020 17:50:43 -0400 Subject: [PATCH 073/355] remove templates from operators --- stan/math/rev/core/operator_divide_equal.hpp | 7 ++-- stan/math/rev/core/operator_minus_equal.hpp | 7 ++-- .../math/rev/core/operator_multiply_equal.hpp | 7 ++-- stan/math/rev/core/operator_plus_equal.hpp | 7 ++-- stan/math/rev/core/var.hpp | 34 +++++++------------ stan/math/rev/core/vari.hpp | 22 +++++------- 6 files changed, 29 insertions(+), 55 deletions(-) diff --git a/stan/math/rev/core/operator_divide_equal.hpp b/stan/math/rev/core/operator_divide_equal.hpp index 3dae0cc79cb..d3a432b9ed3 100644 --- a/stan/math/rev/core/operator_divide_equal.hpp +++ b/stan/math/rev/core/operator_divide_equal.hpp @@ -8,17 +8,14 @@ namespace stan { namespace math { template -template *> inline var_value& var_value>::operator/=( - const var_value& b) { + const var_value& b) { vi_ = new internal::divide_vv_vari(vi_, b.vi_); return *this; } template -template *> -inline var_value& var_value>::operator/=( - Arith b) { +inline var_value& var_value>::operator/=(T b) { if (b == 1.0) { return *this; } diff --git a/stan/math/rev/core/operator_minus_equal.hpp b/stan/math/rev/core/operator_minus_equal.hpp index e70a03bf69b..3a9513a024f 100644 --- a/stan/math/rev/core/operator_minus_equal.hpp +++ b/stan/math/rev/core/operator_minus_equal.hpp @@ -9,17 +9,14 @@ namespace stan { namespace math { template -template *> inline var_value& var_value>::operator-=( - const var_value& b) { + const var_value& b) { vi_ = new internal::subtract_vv_vari(vi_, b.vi_); return *this; } template -template *> -inline var_value& var_value>::operator-=( - Arith b) { +inline var_value& var_value>::operator-=(T b) { if (b == 0.0) { return *this; } diff --git a/stan/math/rev/core/operator_multiply_equal.hpp b/stan/math/rev/core/operator_multiply_equal.hpp index c995b6fa905..69b09cdc4fa 100644 --- a/stan/math/rev/core/operator_multiply_equal.hpp +++ b/stan/math/rev/core/operator_multiply_equal.hpp @@ -9,17 +9,14 @@ namespace stan { namespace math { template -template *> inline var_value& var_value>::operator*=( - const var_value& b) { + const var_value& b) { vi_ = new internal::multiply_vv_vari(vi_, b.vi_); return *this; } template -template *> -inline var_value& var_value>::operator*=( - Arith b) { +inline var_value& var_value>::operator*=(T b) { if (b == 1.0) { return *this; } diff --git a/stan/math/rev/core/operator_plus_equal.hpp b/stan/math/rev/core/operator_plus_equal.hpp index 0da8b734b22..864d5f45d19 100644 --- a/stan/math/rev/core/operator_plus_equal.hpp +++ b/stan/math/rev/core/operator_plus_equal.hpp @@ -9,17 +9,14 @@ namespace stan { namespace math { template -template *> inline var_value& var_value>::operator+=( - const var_value& b) { + const var_value& b) { vi_ = new internal::add_vv_vari(vi_, b.vi_); return *this; } template -template *> -inline var_value& var_value>::operator+=( - Arith b) { +inline var_value& var_value>::operator+=(T b) { if (b == 0.0) { return *this; } diff --git a/stan/math/rev/core/var.hpp b/stan/math/rev/core/var.hpp index e7de6b0a820..eed077e0fe5 100644 --- a/stan/math/rev/core/var.hpp +++ b/stan/math/rev/core/var.hpp @@ -84,8 +84,8 @@ class var_value> { * @tparam S A type that is convertible to `value_type`. * @param x Value of the variable. */ - template * = nullptr> - var_value(S x) : vi_(new vari_type(x, false)) {} // NOLINT + template * = nullptr> + var_value(const S& x) : vi_(new vari_type(x, false)) {} // NOLINT /** * Construct a variable from a pointer to a variable implementation. @@ -94,8 +94,7 @@ class var_value> { * same as `vari_value` so can be `reinterpret_cast` without a copy. * @param vi A vari_value pointer. */ - template * = nullptr> - var_value(vari_value* vi) // NOLINT + var_value(vari_value* vi) // NOLINT : vi_(vi) {} /** @@ -104,8 +103,7 @@ class var_value> { * `var_value a(4.0); var_value b(a)` since the `value_type` for * a `var_value` with an integral type is a double. */ - template * = nullptr> - var_value(const var_value& x) : vi_(x.vi_) {} // NOLINT + var_value(const var_value& x) : vi_(x.vi_) {} // NOLINT /** * Return a constant reference to the value of this variable. @@ -203,8 +201,7 @@ class var_value> { * @param b The variable to add to this variable. * @return The result of adding the specified variable to this variable. */ - template * = nullptr> - inline var_value& operator+=(const var_value& b); + inline var_value& operator+=(const var_value& b); /** * The compound add/assignment operator for scalars (C++). @@ -217,8 +214,7 @@ class var_value> { * @param b The scalar to add to this variable. * @return The result of adding the specified variable to this variable. */ - template * = nullptr> - inline var_value& operator+=(Arith b); + inline var_value& operator+=(T b); /** * The compound subtract/assignment operator for variables (C++). @@ -232,8 +228,7 @@ class var_value> { * @return The result of subtracting the specified variable from * this variable. */ - template * = nullptr> - inline var_value& operator-=(const var_value& b); + inline var_value& operator-=(const var_value& b); /** * The compound subtract/assignment operator for scalars (C++). @@ -247,8 +242,7 @@ class var_value> { * @return The result of subtracting the specified variable from this * variable. */ - template * = nullptr> - inline var_value& operator-=(Arith b); + inline var_value& operator-=(T b); /** * The compound multiply/assignment operator for variables (C++). @@ -262,8 +256,7 @@ class var_value> { * @return The result of multiplying this variable by the * specified variable. */ - template * = nullptr> - inline var_value& operator*=(const var_value& b); + inline var_value& operator*=(const var_value& b); /** * The compound multiply/assignment operator for scalars (C++). @@ -277,8 +270,7 @@ class var_value> { * @return The result of multiplying this variable by the specified * variable. */ - template * = nullptr> - inline var_value& operator*=(Arith b); + inline var_value& operator*=(T b); /** * The compound divide/assignment operator for variables (C++). If this @@ -291,8 +283,7 @@ class var_value> { * @return The result of dividing this variable by the * specified variable. */ - template * = nullptr> - inline var_value& operator/=(const var_value& b); + inline var_value& operator/=(const var_value& b); /** * The compound divide/assignment operator for scalars (C++). @@ -306,8 +297,7 @@ class var_value> { * @return The result of dividing this variable by the specified * variable. */ - template * = nullptr> - inline var_value& operator/=(Arith b); + inline var_value& operator/=(T b); /** * Write the value of this autodiff variable and its adjoint to diff --git a/stan/math/rev/core/vari.hpp b/stan/math/rev/core/vari.hpp index d5749507323..f105e7f8c51 100644 --- a/stan/math/rev/core/vari.hpp +++ b/stan/math/rev/core/vari.hpp @@ -66,11 +66,11 @@ class vari_value::value>> { * @tparam S an Arithmetic type. * @param x Value of the constructed variable. */ - template ::value>* = nullptr> - vari_value(S x) noexcept : val_(x), adj_(0.0) { // NOLINT - ChainableStack::instance_->var_stack_.emplace_back(this); - } + template ::value>* = nullptr> + vari_value(S x) noexcept : val_(x), adj_(0.0) { // NOLINT + ChainableStack::instance_->var_stack_.emplace_back(this); + } /** * Construct a variable implementation from a value. The @@ -89,8 +89,8 @@ class vari_value::value>> { * @param stacked If false will put this this vari on the nochain stack so * that its `chain()` method is not called. */ - template ::value>* = nullptr> + template ::value>* = nullptr> vari_value(S x, bool stacked) noexcept : val_(x), adj_(0.0) { if (stacked) { ChainableStack::instance_->var_stack_.emplace_back(this); @@ -104,9 +104,7 @@ class vari_value::value>> { * @tparam S An arithmetic type * @param x A vari_value */ - template ::value>* = nullptr> - vari_value(const vari_value& x) noexcept : val_(x.val_), adj_(x.adj_) { + vari_value(const vari_value& x) noexcept : val_(x.val_), adj_(x.adj_) { ChainableStack::instance_->var_stack_.emplace_back(this); } /** @@ -114,9 +112,7 @@ class vari_value::value>> { * @tparam S An arithmetic type * @param x A vari_value */ - template ::value>* = nullptr> - vari_value(vari_value&& x) noexcept : val_(x.val_), adj_(x.adj_) { + vari_value(vari_value&& x) noexcept : val_(x.val_), adj_(x.adj_) { ChainableStack::instance_->var_stack_.emplace_back(this); } From 0324c82f4b9cd7095c4bbe93c6681cfc48e8d846 Mon Sep 17 00:00:00 2001 From: Stan Jenkins Date: Mon, 15 Jun 2020 17:51:37 -0400 Subject: [PATCH 074/355] [Jenkins] auto-formatting by clang-format version 6.0.0-1ubuntu2 (tags/RELEASE_600/final) --- stan/math/rev/core/operator_divide_equal.hpp | 3 ++- stan/math/rev/core/operator_minus_equal.hpp | 3 ++- stan/math/rev/core/operator_multiply_equal.hpp | 3 ++- stan/math/rev/core/operator_plus_equal.hpp | 3 ++- stan/math/rev/core/var.hpp | 4 ++-- stan/math/rev/core/vari.hpp | 14 +++++++------- 6 files changed, 17 insertions(+), 13 deletions(-) diff --git a/stan/math/rev/core/operator_divide_equal.hpp b/stan/math/rev/core/operator_divide_equal.hpp index d3a432b9ed3..23687c7011e 100644 --- a/stan/math/rev/core/operator_divide_equal.hpp +++ b/stan/math/rev/core/operator_divide_equal.hpp @@ -15,7 +15,8 @@ inline var_value& var_value>::operator/=( } template -inline var_value& var_value>::operator/=(T b) { +inline var_value& var_value>::operator/=( + T b) { if (b == 1.0) { return *this; } diff --git a/stan/math/rev/core/operator_minus_equal.hpp b/stan/math/rev/core/operator_minus_equal.hpp index 3a9513a024f..f72f7d7412d 100644 --- a/stan/math/rev/core/operator_minus_equal.hpp +++ b/stan/math/rev/core/operator_minus_equal.hpp @@ -16,7 +16,8 @@ inline var_value& var_value>::operator-=( } template -inline var_value& var_value>::operator-=(T b) { +inline var_value& var_value>::operator-=( + T b) { if (b == 0.0) { return *this; } diff --git a/stan/math/rev/core/operator_multiply_equal.hpp b/stan/math/rev/core/operator_multiply_equal.hpp index 69b09cdc4fa..61c13263c19 100644 --- a/stan/math/rev/core/operator_multiply_equal.hpp +++ b/stan/math/rev/core/operator_multiply_equal.hpp @@ -16,7 +16,8 @@ inline var_value& var_value>::operator*=( } template -inline var_value& var_value>::operator*=(T b) { +inline var_value& var_value>::operator*=( + T b) { if (b == 1.0) { return *this; } diff --git a/stan/math/rev/core/operator_plus_equal.hpp b/stan/math/rev/core/operator_plus_equal.hpp index 864d5f45d19..32d41b30772 100644 --- a/stan/math/rev/core/operator_plus_equal.hpp +++ b/stan/math/rev/core/operator_plus_equal.hpp @@ -16,7 +16,8 @@ inline var_value& var_value>::operator+=( } template -inline var_value& var_value>::operator+=(T b) { +inline var_value& var_value>::operator+=( + T b) { if (b == 0.0) { return *this; } diff --git a/stan/math/rev/core/var.hpp b/stan/math/rev/core/var.hpp index eed077e0fe5..c8001d28963 100644 --- a/stan/math/rev/core/var.hpp +++ b/stan/math/rev/core/var.hpp @@ -84,8 +84,8 @@ class var_value> { * @tparam S A type that is convertible to `value_type`. * @param x Value of the variable. */ - template * = nullptr> - var_value(const S& x) : vi_(new vari_type(x, false)) {} // NOLINT + template * = nullptr> + var_value(const S& x) : vi_(new vari_type(x, false)) {} // NOLINT /** * Construct a variable from a pointer to a variable implementation. diff --git a/stan/math/rev/core/vari.hpp b/stan/math/rev/core/vari.hpp index f105e7f8c51..e6ba6ce1579 100644 --- a/stan/math/rev/core/vari.hpp +++ b/stan/math/rev/core/vari.hpp @@ -66,11 +66,11 @@ class vari_value::value>> { * @tparam S an Arithmetic type. * @param x Value of the constructed variable. */ - template ::value>* = nullptr> - vari_value(S x) noexcept : val_(x), adj_(0.0) { // NOLINT - ChainableStack::instance_->var_stack_.emplace_back(this); - } + template ::value>* = nullptr> + vari_value(S x) noexcept : val_(x), adj_(0.0) { // NOLINT + ChainableStack::instance_->var_stack_.emplace_back(this); + } /** * Construct a variable implementation from a value. The @@ -89,8 +89,8 @@ class vari_value::value>> { * @param stacked If false will put this this vari on the nochain stack so * that its `chain()` method is not called. */ - template ::value>* = nullptr> + template ::value>* = nullptr> vari_value(S x, bool stacked) noexcept : val_(x), adj_(0.0) { if (stacked) { ChainableStack::instance_->var_stack_.emplace_back(this); From e30e11121efd520cc9dace588bca52c3399b5491 Mon Sep 17 00:00:00 2001 From: Steve Bronder Date: Tue, 16 Jun 2020 14:54:49 -0400 Subject: [PATCH 075/355] add dense eigen vari type --- stan/math/prim/meta.hpp | 2 + stan/math/prim/meta/is_eigen_dense_base.hpp | 32 ++++ stan/math/prim/meta/is_eigen_sparse_base.hpp | 32 ++++ stan/math/rev/core/chainablestack.hpp | 10 +- stan/math/rev/core/make_vari_variadic.hpp | 107 ++++++++++++++ stan/math/rev/core/set_zero_all_adjoints.hpp | 4 +- .../rev/core/set_zero_all_adjoints_nested.hpp | 4 +- stan/math/rev/core/vari.hpp | 139 ++++++++++++++++++ 8 files changed, 317 insertions(+), 13 deletions(-) create mode 100644 stan/math/prim/meta/is_eigen_dense_base.hpp create mode 100644 stan/math/prim/meta/is_eigen_sparse_base.hpp create mode 100644 stan/math/rev/core/make_vari_variadic.hpp diff --git a/stan/math/prim/meta.hpp b/stan/math/prim/meta.hpp index 0de5dc8f17a..5ef0611c798 100644 --- a/stan/math/prim/meta.hpp +++ b/stan/math/prim/meta.hpp @@ -189,8 +189,10 @@ #include #include #include +#include #include #include +#include #include #include #include diff --git a/stan/math/prim/meta/is_eigen_dense_base.hpp b/stan/math/prim/meta/is_eigen_dense_base.hpp new file mode 100644 index 00000000000..d838d83af90 --- /dev/null +++ b/stan/math/prim/meta/is_eigen_dense_base.hpp @@ -0,0 +1,32 @@ +#ifndef STAN_MATH_PRIM_META_IS_EIGEN_DENSE_BASE_HPP +#define STAN_MATH_PRIM_META_IS_EIGEN_DENSE_BASE_HPP + +#include +#include +#include +#include +#include + +namespace stan { + +/** + * Checks whether type T is derived from Eigen::MatrixBase. + * If true this will have a static member function named value with a type + * of true, else value is false. + * @tparam T Type to check if it is derived from `EigenBase` + * @tparam Enable used for SFINAE deduction. + * @ingroup type_trait + */ +template +struct is_eigen_dense_base + : bool_constant::value> { +}; + +STAN_ADD_REQUIRE_UNARY(eigen_dense_base, is_eigen_dense_base, + require_eigens_types); +STAN_ADD_REQUIRE_CONTAINER(eigen_dense_base, is_eigen_dense_base, + require_eigens_types); + +} // namespace stan + +#endif diff --git a/stan/math/prim/meta/is_eigen_sparse_base.hpp b/stan/math/prim/meta/is_eigen_sparse_base.hpp new file mode 100644 index 00000000000..0628b3dce66 --- /dev/null +++ b/stan/math/prim/meta/is_eigen_sparse_base.hpp @@ -0,0 +1,32 @@ +#ifndef STAN_MATH_PRIM_META_IS_EIGEN_SPARSE_BASE_HPP +#define STAN_MATH_PRIM_META_IS_EIGEN_SPARSE_BASE_HPP + +#include +#include +#include +#include +#include + +namespace stan { + +/** + * Checks whether type T is derived from Eigen::MatrixBase. + * If true this will have a static member function named value with a type + * of true, else value is false. + * @tparam T Type to check if it is derived from `EigenBase` + * @tparam Enable used for SFINAE deduction. + * @ingroup type_trait + */ +template +struct is_eigen_sparse_base + : bool_constant::value> { +}; + +STAN_ADD_REQUIRE_UNARY(eigen_sparse_base, is_eigen_sparse_base, + require_eigens_types); +STAN_ADD_REQUIRE_CONTAINER(eigen_sparse_base, is_eigen_sparse_base, + require_eigens_types); + +} // namespace stan + +#endif diff --git a/stan/math/rev/core/chainablestack.hpp b/stan/math/rev/core/chainablestack.hpp index 6dd314a84c6..9855405f13f 100644 --- a/stan/math/rev/core/chainablestack.hpp +++ b/stan/math/rev/core/chainablestack.hpp @@ -2,19 +2,11 @@ #define STAN_MATH_REV_CORE_CHAINABLESTACK_HPP #include +#include #include namespace stan { namespace math { - -template -class vari_value; -class vari_base; class chainable_alloc; - -using vari_variant - = boost::variant2::variant*, vari_value*, - vari_value*>; - using ChainableStack = AutodiffStackSingleton; } // namespace math diff --git a/stan/math/rev/core/make_vari_variadic.hpp b/stan/math/rev/core/make_vari_variadic.hpp new file mode 100644 index 00000000000..27cb8d94397 --- /dev/null +++ b/stan/math/rev/core/make_vari_variadic.hpp @@ -0,0 +1,107 @@ +#ifndef STAN_MATH_REV_CORE_MAKE_VARI_VARIANT_HPP +#define STAN_MATH_REV_CORE_MAKE_VARI_VARIANT_HPP + +#include +#include +#include + +namespace stan { +namespace math { +template +class vari_value; + +namespace internal { +// Make one tuple out of N tuples +template +struct concat_tuple { + using type = decltype(std::tuple_cat(std::declval()...)); +}; +// helper +template +using concat_tuple_t = typename concat_tuple::type; + +// All the vari_value Matrix types +template +struct vari_eigen_mat_tuple { + using type = std::tuple< + vari_value>, + vari_value>, + vari_value>, + vari_value>>; +}; + +template +using vari_eigen_mat_tuple_t = typename vari_eigen_mat_tuple::type; + +template +struct vari_eigen_arr_tuple { + using type = std::tuple< + vari_value>, + vari_value>, + vari_value>, + vari_value>>; +}; + +template +using vari_eigen_arr_tuple_t = typename vari_eigen_arr_tuple::type; + +template +struct vari_eigen_sparsemat_tuple { + using type = std::tuple< + vari_value>, + vari_value>>; +}; + +template +using vari_eigen_sparsemat_tuple_t = typename vari_eigen_sparsemat_tuple::type; + +// All of the vari_value mixes +template +struct vari_combinations { + using type = concat_tuple_t< + vari_eigen_mat_tuple_t, + vari_eigen_arr_tuple_t, +// vari_eigen_sparsemat_tuple_t, + std::tuple>>; +}; + +template +using vari_combinations_t = typename vari_combinations::type; + + +template +struct make_vari_types; + + // break condition on default type which ends the recursion +template <> +struct make_vari_types { + using type = std::tuple<>; +}; + +// alias template +template +using make_vari_types_t = typename make_vari_types::type; + +// Take all the base types T and make their vari_value equivalents +template +struct make_vari_types { + using type = concat_tuple_t, make_vari_types_t>; +}; + +template +struct make_vari_variadic {}; + +// Take the tuple of all the types and place them in boost::variant +template +struct make_vari_variadic> { + using type = boost::variant2::variant; +}; +} +// Create boost variant holding pointers to all the vari_value types +template +using make_vari_variadic_t = typename internal::make_vari_variadic>::type; + +using vari_variant = make_vari_variadic_t; +} +} +#endif diff --git a/stan/math/rev/core/set_zero_all_adjoints.hpp b/stan/math/rev/core/set_zero_all_adjoints.hpp index cfd1edb83ec..1d706b096bb 100644 --- a/stan/math/rev/core/set_zero_all_adjoints.hpp +++ b/stan/math/rev/core/set_zero_all_adjoints.hpp @@ -13,10 +13,10 @@ namespace math { */ static EIGEN_STRONG_INLINE void set_zero_all_adjoints() { for (auto& x : ChainableStack::instance_->var_stack_) { - boost::variant2::visit([](auto& x) { x->adj_ = 0.0; }, x); + boost::variant2::visit([](auto& x) { x->set_zero_adjoint(); }, x); } for (auto& x : ChainableStack::instance_->var_nochain_stack_) { - boost::variant2::visit([](auto& x) { x->adj_ = 0.0; }, x); + boost::variant2::visit([](auto& x) { x->set_zero_adjoint(); }, x); } } diff --git a/stan/math/rev/core/set_zero_all_adjoints_nested.hpp b/stan/math/rev/core/set_zero_all_adjoints_nested.hpp index 0b7fc446a62..09aa3cd6559 100644 --- a/stan/math/rev/core/set_zero_all_adjoints_nested.hpp +++ b/stan/math/rev/core/set_zero_all_adjoints_nested.hpp @@ -27,7 +27,7 @@ static EIGEN_STRONG_INLINE void set_zero_all_adjoints_nested() { const auto stack_size = ChainableStack::instance_->var_stack_.size(); // avoid wrap with unsigned when start1 == 0 for (size_t i = (start1 == 0U) ? 0U : (start1 - 1); i < stack_size; ++i) { - boost::variant2::visit([](auto& x) { x->adj_ = 0.0; }, + boost::variant2::visit([](auto& x) { x->set_zero_adjoint(); }, ChainableStack::instance_->var_stack_[i]); } @@ -37,7 +37,7 @@ static EIGEN_STRONG_INLINE void set_zero_all_adjoints_nested() { = ChainableStack::instance_->var_nochain_stack_.size(); for (size_t i = (start2 == 0U) ? 0U : (start2 - 1); i < nochain_stack_size; ++i) { - boost::variant2::visit([](auto& x) { x->adj_ = 0.0; }, + boost::variant2::visit([](auto& x) { x->set_zero_adjoint(); }, ChainableStack::instance_->var_nochain_stack_[i]); } } diff --git a/stan/math/rev/core/vari.hpp b/stan/math/rev/core/vari.hpp index e6ba6ce1579..f0e6ffc6bb2 100644 --- a/stan/math/rev/core/vari.hpp +++ b/stan/math/rev/core/vari.hpp @@ -179,6 +179,145 @@ class vari_value::value>> { // For backwards compatability the default is double using vari = vari_value; + + +template +class vari_value::value>> { + private: + template + friend class var_value; + using eigen_scalar = value_type_t; + value_type_t* val_mem_; + value_type_t* adj_mem_; + + public: + using Scalar = T; + using value_type = T; + using PlainObject = typename T::PlainObject; + using eigen_map = Eigen::Map; + const Eigen::Index rows_; + const Eigen::Index cols_; + const Eigen::Index size_; + const Eigen::Index RowsAtCompileTime = T::RowsAtCompileTime; + const Eigen::Index ColsAtCompileTime = T::ColsAtCompileTime; + /** + * The value of this variable. + */ + eigen_map val_; + + /** + * The adjoint of this variable, which is the partial derivative + * of this variable with respect to the root variable. + */ + eigen_map adj_; + + /** + * Construct a variable implementation from a value. The + * adjoint is initialized to zero. + * + * All constructed variables are added to the stack. Variables + * should be constructed before variables on which they depend + * to insure proper partial derivative propagation. During + * derivative propagation, the chain() method of each variable + * will be called in the reverse order of construction. + * + * @param x Value of the constructed variable. + */ + explicit vari_value(const T& x) + : val_mem_(ChainableStack::instance_->memalloc_.alloc_array( + x.size())), + adj_mem_(ChainableStack::instance_->memalloc_.alloc_array( + x.size())), + rows_(x.rows()), + cols_(x.cols()), + size_(x.size()), + val_(val_mem_, x.rows(), x.cols()), + adj_(adj_mem_, x.rows(), x.cols()) { + val_ = x; + adj_.setZero(); + ChainableStack::instance_->var_stack_.push_back(this); + } + + vari_value(const T& x, bool stacked) + : val_mem_(ChainableStack::instance_->memalloc_.alloc_array( + x.size())), + adj_mem_(ChainableStack::instance_->memalloc_.alloc_array( + x.size())), + rows_(x.rows()), + cols_(x.cols()), + size_(x.size()), + val_(val_mem_, x.rows(), x.cols()), + adj_(adj_mem_, x.rows(), x.cols()) { + val_ = x; + adj_.setZero(); + if (stacked) { + ChainableStack::instance_->var_stack_.push_back(this); + } else { + ChainableStack::instance_->var_nochain_stack_.push_back(this); + } + } + + const Eigen::Index rows() const { return rows_; } + const Eigen::Index cols() const { return cols_; } + const Eigen::Index size() const { return size_; } + virtual void chain() {} + /** + * Initialize the adjoint for this (dependent) variable to 1. + * This operation is applied to the dependent variable before + * propagating derivatives, setting the derivative of the + * result with respect to itself to be 1. + */ + void init_dependent() { adj_.setOnes(); } + + /** + * Set the adjoint value of this variable to 0. This is used to + * reset adjoints before propagating derivatives again (for + * example in a Jacobian calculation). + */ + void set_zero_adjoint() { adj_.setZero(); } + + /** + * Insertion operator for vari. Prints the current value and + * the adjoint value. + * + * @param os [in, out] ostream to modify + * @param v [in] vari object to print. + * + * @return The modified ostream. + */ + friend std::ostream& operator<<(std::ostream& os, const vari_value* v) { + return os << v->val_ << ":" << v->adj_; + } + + /** + * Allocate memory from the underlying memory pool. This memory is + * is managed as a whole externally. + * + * Warning: Classes should not be allocated with this operator + * if they have non-trivial destructors. + * + * @param nbytes Number of bytes to allocate. + * @return Pointer to allocated bytes. + */ + static inline void* operator new(size_t nbytes) { + return ChainableStack::instance_->memalloc_.alloc(nbytes); + } + + /** + * Delete a pointer from the underlying memory pool. + * + * This no-op implementation enables a subclass to throw + * exceptions in its constructor. An exception thrown in the + * constructor of a subclass will result in an error being + * raised, which is in turn caught and calls delete(). + * + * See the discussion of "plugging the memory leak" in: + * http://www.parashift.com/c++-faq/memory-pools.html + */ + static inline void operator delete(void* /* ignore arg */) { /* no op */ + } +}; + struct vari_printer { std::ostream& o_; int i_{0}; From 3f8833589f94c17eab19711da8df8f9b05ac33ba Mon Sep 17 00:00:00 2001 From: Steve Bronder Date: Tue, 16 Jun 2020 16:24:34 -0400 Subject: [PATCH 076/355] try custom visitor --- stan/math/rev/core/grad.hpp | 4 +- .../rev/core/set_zero_all_adjoints_nested.hpp | 11 ++--- stan/math/rev/core/vari_visitor.hpp | 47 +++++++++++++++++++ 3 files changed, 54 insertions(+), 8 deletions(-) create mode 100644 stan/math/rev/core/vari_visitor.hpp diff --git a/stan/math/rev/core/grad.hpp b/stan/math/rev/core/grad.hpp index 4aa2d6fc66f..4c4eaabaf04 100644 --- a/stan/math/rev/core/grad.hpp +++ b/stan/math/rev/core/grad.hpp @@ -6,6 +6,7 @@ #include #include #include +#include #include namespace stan { @@ -33,8 +34,7 @@ static void grad(Vari* vi) { size_t end = ChainableStack::instance_->var_stack_.size(); size_t beginning = empty_nested() ? 0 : end - nested_size(); for (size_t i = end; i-- > beginning;) { - boost::variant2::visit([&](auto& x) { x->chain(); }, - ChainableStack::instance_->var_stack_[i]); + vari_visitor(ChainableStack::instance_->var_stack_[i], [&](auto& x) { x->chain(); }); } } diff --git a/stan/math/rev/core/set_zero_all_adjoints_nested.hpp b/stan/math/rev/core/set_zero_all_adjoints_nested.hpp index 09aa3cd6559..9339682a8e5 100644 --- a/stan/math/rev/core/set_zero_all_adjoints_nested.hpp +++ b/stan/math/rev/core/set_zero_all_adjoints_nested.hpp @@ -5,6 +5,7 @@ #include #include #include +#include #include namespace stan { @@ -27,18 +28,16 @@ static EIGEN_STRONG_INLINE void set_zero_all_adjoints_nested() { const auto stack_size = ChainableStack::instance_->var_stack_.size(); // avoid wrap with unsigned when start1 == 0 for (size_t i = (start1 == 0U) ? 0U : (start1 - 1); i < stack_size; ++i) { - boost::variant2::visit([](auto& x) { x->set_zero_adjoint(); }, - ChainableStack::instance_->var_stack_[i]); + vari_visitor(ChainableStack::instance_->var_stack_[i], [](auto& x) { x->set_zero_adjoint(); }); } size_t start2 = ChainableStack::instance_->nested_var_nochain_stack_sizes_.back(); const auto nochain_stack_size = ChainableStack::instance_->var_nochain_stack_.size(); - for (size_t i = (start2 == 0U) ? 0U : (start2 - 1); i < nochain_stack_size; - ++i) { - boost::variant2::visit([](auto& x) { x->set_zero_adjoint(); }, - ChainableStack::instance_->var_nochain_stack_[i]); + for (size_t i = (start2 == 0U) ? 0U : (start2 - 1); i < nochain_stack_size; ++i) { + vari_visitor(ChainableStack::instance_->var_nochain_stack_[i], + [](auto& x) { x->set_zero_adjoint(); }); } } diff --git a/stan/math/rev/core/vari_visitor.hpp b/stan/math/rev/core/vari_visitor.hpp new file mode 100644 index 00000000000..f8ae7a65804 --- /dev/null +++ b/stan/math/rev/core/vari_visitor.hpp @@ -0,0 +1,47 @@ +#ifndef STAN_MATH_REV_CORE_VARI_VISITOR_HPP +#define STAN_MATH_REV_CORE_VARI_VISITOR_HPP + +#include +#include + +namespace stan { +namespace math { + +template +struct visit_nt_impl; + +template +struct visit_nt_impl>> { + template + inline static constexpr auto apply(Variant &&var, Visitor &&vis) noexcept { + if (N == var.index()) { + // If this check isnt there the compiler will generate + // exception code, this stops that + return std::forward(vis)( + boost::variant2::get(std::forward(var))); + } + } +}; +template +struct visit_nt_impl 0)>>> { + template + inline static constexpr auto apply(Variant &&var, Visitor &&vis) noexcept { + if (likely(var.index() == N)) { + return std::forward(vis)( + *boost::variant2::get_if*>(&std::forward(var))); + } else { + return visit_nt_impl::apply(std::forward(var), + std::forward(vis)); + } + } +}; + +template +constexpr auto vari_visitor(Variant&& var, Visitor&& vis) noexcept { + constexpr auto sizer = boost::variant2::variant_size::value; + return visit_nt_impl::apply(std::forward(var), std::forward(vis)); +} + +} +} +#endif From 4104696e50b46e9eed88ddad9a9ed0df57422c82 Mon Sep 17 00:00:00 2001 From: Steve Bronder Date: Tue, 16 Jun 2020 16:46:40 -0400 Subject: [PATCH 077/355] switching back to virtual --- stan/math/rev/core/autodiffstackstorage.hpp | 4 ++-- stan/math/rev/core/chainable_alloc.hpp | 1 - stan/math/rev/core/chainablestack.hpp | 7 +------ stan/math/rev/core/grad.hpp | 3 +-- stan/math/rev/core/print_stack.hpp | 9 --------- stan/math/rev/core/set_zero_all_adjoints.hpp | 4 ++-- .../rev/core/set_zero_all_adjoints_nested.hpp | 6 ++---- stan/math/rev/core/vari.hpp | 20 +++++++------------ 8 files changed, 15 insertions(+), 39 deletions(-) diff --git a/stan/math/rev/core/autodiffstackstorage.hpp b/stan/math/rev/core/autodiffstackstorage.hpp index 9b2dc106fdf..e0b993081c5 100644 --- a/stan/math/rev/core/autodiffstackstorage.hpp +++ b/stan/math/rev/core/autodiffstackstorage.hpp @@ -101,8 +101,8 @@ struct AutodiffStackSingleton { struct AutodiffStackStorage { AutodiffStackStorage &operator=(const AutodiffStackStorage &) = delete; - std::vector var_stack_; - std::vector var_nochain_stack_; + std::vector var_stack_; + std::vector var_nochain_stack_; std::vector var_alloc_stack_; stack_alloc memalloc_; diff --git a/stan/math/rev/core/chainable_alloc.hpp b/stan/math/rev/core/chainable_alloc.hpp index 3541e88aee6..6ff43fd0e43 100644 --- a/stan/math/rev/core/chainable_alloc.hpp +++ b/stan/math/rev/core/chainable_alloc.hpp @@ -18,7 +18,6 @@ class chainable_alloc { chainable_alloc() { ChainableStack::instance_->var_alloc_stack_.push_back(this); } - virtual ~chainable_alloc() {} }; } // namespace math diff --git a/stan/math/rev/core/chainablestack.hpp b/stan/math/rev/core/chainablestack.hpp index 6dd314a84c6..ecbf61a7c43 100644 --- a/stan/math/rev/core/chainablestack.hpp +++ b/stan/math/rev/core/chainablestack.hpp @@ -10,12 +10,7 @@ template class vari_value; class vari_base; class chainable_alloc; - -using vari_variant - = boost::variant2::variant*, vari_value*, - vari_value*>; - -using ChainableStack = AutodiffStackSingleton; +using ChainableStack = AutodiffStackSingleton; } // namespace math } // namespace stan diff --git a/stan/math/rev/core/grad.hpp b/stan/math/rev/core/grad.hpp index 4aa2d6fc66f..efe8fee1e87 100644 --- a/stan/math/rev/core/grad.hpp +++ b/stan/math/rev/core/grad.hpp @@ -33,8 +33,7 @@ static void grad(Vari* vi) { size_t end = ChainableStack::instance_->var_stack_.size(); size_t beginning = empty_nested() ? 0 : end - nested_size(); for (size_t i = end; i-- > beginning;) { - boost::variant2::visit([&](auto& x) { x->chain(); }, - ChainableStack::instance_->var_stack_[i]); + ChainableStack::instance_->var_stack_[i]->chain(); } } diff --git a/stan/math/rev/core/print_stack.hpp b/stan/math/rev/core/print_stack.hpp index 7718dbefa26..a81b03cc51e 100644 --- a/stan/math/rev/core/print_stack.hpp +++ b/stan/math/rev/core/print_stack.hpp @@ -20,15 +20,6 @@ namespace math { inline void print_stack(std::ostream& o) { o << "STACK, size=" << ChainableStack::instance_->var_stack_.size() << std::endl; - // TODO(carpenter): this shouldn't need to be cast any more - for (size_t i = 0; i < ChainableStack::instance_->var_stack_.size(); ++i) { - boost::variant2::visit( - [&o, &i](auto x) { - o << i << " " << x << " " << x->val_ << " : " << x->adj_ - << std::endl; - }, - ChainableStack::instance_->var_stack_[i]); - } } } // namespace math diff --git a/stan/math/rev/core/set_zero_all_adjoints.hpp b/stan/math/rev/core/set_zero_all_adjoints.hpp index cfd1edb83ec..27a730f8d3c 100644 --- a/stan/math/rev/core/set_zero_all_adjoints.hpp +++ b/stan/math/rev/core/set_zero_all_adjoints.hpp @@ -13,10 +13,10 @@ namespace math { */ static EIGEN_STRONG_INLINE void set_zero_all_adjoints() { for (auto& x : ChainableStack::instance_->var_stack_) { - boost::variant2::visit([](auto& x) { x->adj_ = 0.0; }, x); + x->set_zero_adjoint(); } for (auto& x : ChainableStack::instance_->var_nochain_stack_) { - boost::variant2::visit([](auto& x) { x->adj_ = 0.0; }, x); + x->set_zero_adjoint(); } } diff --git a/stan/math/rev/core/set_zero_all_adjoints_nested.hpp b/stan/math/rev/core/set_zero_all_adjoints_nested.hpp index 0b7fc446a62..1fc4c88eaef 100644 --- a/stan/math/rev/core/set_zero_all_adjoints_nested.hpp +++ b/stan/math/rev/core/set_zero_all_adjoints_nested.hpp @@ -27,8 +27,7 @@ static EIGEN_STRONG_INLINE void set_zero_all_adjoints_nested() { const auto stack_size = ChainableStack::instance_->var_stack_.size(); // avoid wrap with unsigned when start1 == 0 for (size_t i = (start1 == 0U) ? 0U : (start1 - 1); i < stack_size; ++i) { - boost::variant2::visit([](auto& x) { x->adj_ = 0.0; }, - ChainableStack::instance_->var_stack_[i]); + ChainableStack::instance_->var_stack_[i]->set_zero_adjoint(); } size_t start2 @@ -37,8 +36,7 @@ static EIGEN_STRONG_INLINE void set_zero_all_adjoints_nested() { = ChainableStack::instance_->var_nochain_stack_.size(); for (size_t i = (start2 == 0U) ? 0U : (start2 - 1); i < nochain_stack_size; ++i) { - boost::variant2::visit([](auto& x) { x->adj_ = 0.0; }, - ChainableStack::instance_->var_nochain_stack_[i]); + ChainableStack::instance_->var_nochain_stack_[i]->set_zero_adjoint(); } } diff --git a/stan/math/rev/core/vari.hpp b/stan/math/rev/core/vari.hpp index e6ba6ce1579..81066ffbeaf 100644 --- a/stan/math/rev/core/vari.hpp +++ b/stan/math/rev/core/vari.hpp @@ -14,6 +14,11 @@ namespace math { template class var_value; +class vari_base { +public: + virtual void chain() {} + virtual void set_zero_adjoint() noexcept {} +}; /** * The variable implementation base class. * @@ -34,7 +39,7 @@ template class vari_value; template -class vari_value::value>> { +class vari_value::value>> : public vari_base { private: template friend class var_value; @@ -129,9 +134,7 @@ class vari_value::value>> { * reset adjoints before propagating derivatives again (for * example in a Jacobian calculation). */ - inline void set_zero_adjoint() noexcept { adj_ = 0.0; } - - virtual void chain() {} + void set_zero_adjoint() noexcept final { adj_ = 0.0; } /** * Insertion operator for vari. Prints the current value and @@ -179,15 +182,6 @@ class vari_value::value>> { // For backwards compatability the default is double using vari = vari_value; -struct vari_printer { - std::ostream& o_; - int i_{0}; - vari_printer(std::ostream& o, int i) : o_(o), i_(i) {} - template - inline void operator()(T*& x) const { - o_ << i_ << " " << x << " " << x->val_ << " : " << x->adj_ << std::endl; - } -}; } // namespace math } // namespace stan #endif From ce718a88afba8743bba568ad583f6d10e555c092 Mon Sep 17 00:00:00 2001 From: Steve Bronder Date: Tue, 16 Jun 2020 17:53:50 -0400 Subject: [PATCH 078/355] Trying multi stack method --- stan/math/rev/core/autodiffstackstorage.hpp | 4 ++++ stan/math/rev/core/chainablestack.hpp | 2 +- stan/math/rev/core/set_zero_all_adjoints.hpp | 5 +---- stan/math/rev/core/set_zero_all_adjoints_nested.hpp | 13 ++----------- stan/math/rev/core/vari.hpp | 3 +-- 5 files changed, 9 insertions(+), 18 deletions(-) diff --git a/stan/math/rev/core/autodiffstackstorage.hpp b/stan/math/rev/core/autodiffstackstorage.hpp index e0b993081c5..847aab7d1ac 100644 --- a/stan/math/rev/core/autodiffstackstorage.hpp +++ b/stan/math/rev/core/autodiffstackstorage.hpp @@ -24,6 +24,9 @@ namespace math { #define STAN_THREADS_DEF #endif +template +class vari_value; + /** * This struct always provides access to the autodiff stack using * the singleton pattern. Read warnings below! @@ -103,6 +106,7 @@ struct AutodiffStackSingleton { std::vector var_stack_; std::vector var_nochain_stack_; + std::vector*> var_dbl_stack_; std::vector var_alloc_stack_; stack_alloc memalloc_; diff --git a/stan/math/rev/core/chainablestack.hpp b/stan/math/rev/core/chainablestack.hpp index ecbf61a7c43..47d94983ca6 100644 --- a/stan/math/rev/core/chainablestack.hpp +++ b/stan/math/rev/core/chainablestack.hpp @@ -6,7 +6,7 @@ namespace stan { namespace math { -template +template class vari_value; class vari_base; class chainable_alloc; diff --git a/stan/math/rev/core/set_zero_all_adjoints.hpp b/stan/math/rev/core/set_zero_all_adjoints.hpp index 27a730f8d3c..abd4f87d2e0 100644 --- a/stan/math/rev/core/set_zero_all_adjoints.hpp +++ b/stan/math/rev/core/set_zero_all_adjoints.hpp @@ -12,10 +12,7 @@ namespace math { * Reset all adjoint values in the stack to zero. */ static EIGEN_STRONG_INLINE void set_zero_all_adjoints() { - for (auto& x : ChainableStack::instance_->var_stack_) { - x->set_zero_adjoint(); - } - for (auto& x : ChainableStack::instance_->var_nochain_stack_) { + for (auto& x : ChainableStack::instance_->var_dbl_stack_) { x->set_zero_adjoint(); } } diff --git a/stan/math/rev/core/set_zero_all_adjoints_nested.hpp b/stan/math/rev/core/set_zero_all_adjoints_nested.hpp index 1fc4c88eaef..26c0afc3e60 100644 --- a/stan/math/rev/core/set_zero_all_adjoints_nested.hpp +++ b/stan/math/rev/core/set_zero_all_adjoints_nested.hpp @@ -24,19 +24,10 @@ static EIGEN_STRONG_INLINE void set_zero_all_adjoints_nested() { " set_zero_all_adjoints_nested()"); } size_t start1 = ChainableStack::instance_->nested_var_stack_sizes_.back(); - const auto stack_size = ChainableStack::instance_->var_stack_.size(); + const auto stack_size = ChainableStack::instance_->var_dbl_stack_.size(); // avoid wrap with unsigned when start1 == 0 for (size_t i = (start1 == 0U) ? 0U : (start1 - 1); i < stack_size; ++i) { - ChainableStack::instance_->var_stack_[i]->set_zero_adjoint(); - } - - size_t start2 - = ChainableStack::instance_->nested_var_nochain_stack_sizes_.back(); - const auto nochain_stack_size - = ChainableStack::instance_->var_nochain_stack_.size(); - for (size_t i = (start2 == 0U) ? 0U : (start2 - 1); i < nochain_stack_size; - ++i) { - ChainableStack::instance_->var_nochain_stack_[i]->set_zero_adjoint(); + ChainableStack::instance_->var_dbl_stack_[i]->set_zero_adjoint(); } } diff --git a/stan/math/rev/core/vari.hpp b/stan/math/rev/core/vari.hpp index 81066ffbeaf..7cae2c77f06 100644 --- a/stan/math/rev/core/vari.hpp +++ b/stan/math/rev/core/vari.hpp @@ -17,7 +17,6 @@ class var_value; class vari_base { public: virtual void chain() {} - virtual void set_zero_adjoint() noexcept {} }; /** * The variable implementation base class. @@ -134,7 +133,7 @@ class vari_value::value>> : public * reset adjoints before propagating derivatives again (for * example in a Jacobian calculation). */ - void set_zero_adjoint() noexcept final { adj_ = 0.0; } + void set_zero_adjoint() noexcept { adj_ = 0.0; } /** * Insertion operator for vari. Prints the current value and From 85a44b78090974e164369fd2159a83fd661edc82 Mon Sep 17 00:00:00 2001 From: Steve Bronder Date: Tue, 16 Jun 2020 18:04:37 -0400 Subject: [PATCH 079/355] add var_dbl_stack to vari --- stan/math/rev/core/vari.hpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/stan/math/rev/core/vari.hpp b/stan/math/rev/core/vari.hpp index 7cae2c77f06..b1be4f555b7 100644 --- a/stan/math/rev/core/vari.hpp +++ b/stan/math/rev/core/vari.hpp @@ -73,6 +73,7 @@ class vari_value::value>> : public template ::value>* = nullptr> vari_value(S x) noexcept : val_(x), adj_(0.0) { // NOLINT + ChainableStack::instance_->var_dbl_stack_.emplace_back(this); ChainableStack::instance_->var_stack_.emplace_back(this); } @@ -96,6 +97,7 @@ class vari_value::value>> : public template ::value>* = nullptr> vari_value(S x, bool stacked) noexcept : val_(x), adj_(0.0) { + ChainableStack::instance_->var_dbl_stack_.emplace_back(this); if (stacked) { ChainableStack::instance_->var_stack_.emplace_back(this); } else { @@ -109,6 +111,7 @@ class vari_value::value>> : public * @param x A vari_value */ vari_value(const vari_value& x) noexcept : val_(x.val_), adj_(x.adj_) { + ChainableStack::instance_->var_dbl_stack_.emplace_back(this); ChainableStack::instance_->var_stack_.emplace_back(this); } /** @@ -117,6 +120,7 @@ class vari_value::value>> : public * @param x A vari_value */ vari_value(vari_value&& x) noexcept : val_(x.val_), adj_(x.adj_) { + ChainableStack::instance_->var_dbl_stack_.emplace_back(this); ChainableStack::instance_->var_stack_.emplace_back(this); } From ac6e99a4f43d3d9c7dc551e687f208f1228f2cc5 Mon Sep 17 00:00:00 2001 From: Steve Bronder Date: Tue, 16 Jun 2020 18:05:23 -0400 Subject: [PATCH 080/355] add var_dbl_stack to vari --- stan/math/rev/core/vari.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stan/math/rev/core/vari.hpp b/stan/math/rev/core/vari.hpp index b1be4f555b7..f740247d0b3 100644 --- a/stan/math/rev/core/vari.hpp +++ b/stan/math/rev/core/vari.hpp @@ -137,7 +137,7 @@ class vari_value::value>> : public * reset adjoints before propagating derivatives again (for * example in a Jacobian calculation). */ - void set_zero_adjoint() noexcept { adj_ = 0.0; } + inline void set_zero_adjoint() noexcept { adj_ = 0.0; } /** * Insertion operator for vari. Prints the current value and From f9af05505bc70f3cde1b936b39a535f0fcd1af9e Mon Sep 17 00:00:00 2001 From: Steve Bronder Date: Tue, 16 Jun 2020 18:28:03 -0400 Subject: [PATCH 081/355] add var_dbl_stack to vari --- stan/math/rev/core/vari.hpp | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/stan/math/rev/core/vari.hpp b/stan/math/rev/core/vari.hpp index f740247d0b3..f797346e033 100644 --- a/stan/math/rev/core/vari.hpp +++ b/stan/math/rev/core/vari.hpp @@ -100,9 +100,7 @@ class vari_value::value>> : public ChainableStack::instance_->var_dbl_stack_.emplace_back(this); if (stacked) { ChainableStack::instance_->var_stack_.emplace_back(this); - } else { - ChainableStack::instance_->var_nochain_stack_.emplace_back(this); - } + } } /** From 82c03323d262b87c6d2283164f9b5c13056d19b3 Mon Sep 17 00:00:00 2001 From: Steve Bronder Date: Tue, 16 Jun 2020 21:51:17 -0400 Subject: [PATCH 082/355] remove nochain stack and use dbl stack --- stan/math/rev/core/autodiffstackstorage.hpp | 3 +-- stan/math/rev/core/recover_memory.hpp | 2 +- stan/math/rev/core/recover_memory_nested.hpp | 6 +++--- stan/math/rev/core/start_nested.hpp | 4 ++-- 4 files changed, 7 insertions(+), 8 deletions(-) diff --git a/stan/math/rev/core/autodiffstackstorage.hpp b/stan/math/rev/core/autodiffstackstorage.hpp index 847aab7d1ac..4734e09cdb7 100644 --- a/stan/math/rev/core/autodiffstackstorage.hpp +++ b/stan/math/rev/core/autodiffstackstorage.hpp @@ -105,14 +105,13 @@ struct AutodiffStackSingleton { AutodiffStackStorage &operator=(const AutodiffStackStorage &) = delete; std::vector var_stack_; - std::vector var_nochain_stack_; std::vector*> var_dbl_stack_; std::vector var_alloc_stack_; stack_alloc memalloc_; // nested positions std::vector nested_var_stack_sizes_; - std::vector nested_var_nochain_stack_sizes_; + std::vector nested_var_dbl_stack_sizes_; std::vector nested_var_alloc_stack_starts_; }; diff --git a/stan/math/rev/core/recover_memory.hpp b/stan/math/rev/core/recover_memory.hpp index c8ec7e92b66..116d9befcc2 100644 --- a/stan/math/rev/core/recover_memory.hpp +++ b/stan/math/rev/core/recover_memory.hpp @@ -22,7 +22,7 @@ static inline void recover_memory() { " before calling recover_memory()"); } ChainableStack::instance_->var_stack_.clear(); - ChainableStack::instance_->var_nochain_stack_.clear(); + ChainableStack::instance_->var_dbl_stack_.clear(); for (auto &x : ChainableStack::instance_->var_alloc_stack_) { delete x; } diff --git a/stan/math/rev/core/recover_memory_nested.hpp b/stan/math/rev/core/recover_memory_nested.hpp index 1cd493a1a11..0e34aaee8ed 100644 --- a/stan/math/rev/core/recover_memory_nested.hpp +++ b/stan/math/rev/core/recover_memory_nested.hpp @@ -31,9 +31,9 @@ static inline void recover_memory_nested() { ChainableStack::instance_->nested_var_stack_sizes_.back()); ChainableStack::instance_->nested_var_stack_sizes_.pop_back(); - ChainableStack::instance_->var_nochain_stack_.resize( - ChainableStack::instance_->nested_var_nochain_stack_sizes_.back()); - ChainableStack::instance_->nested_var_nochain_stack_sizes_.pop_back(); + ChainableStack::instance_->var_dbl_stack_.resize( + ChainableStack::instance_->nested_var_dbl_stack_sizes_.back()); + ChainableStack::instance_->nested_var_dbl_stack_sizes_.pop_back(); for (size_t i = ChainableStack::instance_->nested_var_alloc_stack_starts_.back(); diff --git a/stan/math/rev/core/start_nested.hpp b/stan/math/rev/core/start_nested.hpp index d17ff7e153b..bb0f0a7cec8 100644 --- a/stan/math/rev/core/start_nested.hpp +++ b/stan/math/rev/core/start_nested.hpp @@ -16,8 +16,8 @@ namespace math { static inline void start_nested() { ChainableStack::instance_->nested_var_stack_sizes_.push_back( ChainableStack::instance_->var_stack_.size()); - ChainableStack::instance_->nested_var_nochain_stack_sizes_.push_back( - ChainableStack::instance_->var_nochain_stack_.size()); + ChainableStack::instance_->nested_var_dbl_stack_sizes_.push_back( + ChainableStack::instance_->var_dbl_stack_.size()); ChainableStack::instance_->nested_var_alloc_stack_starts_.push_back( ChainableStack::instance_->var_alloc_stack_.size()); ChainableStack::instance_->memalloc_.start_nested(); From 346e6cab07b46f0d560be437182f06ab04bfdac7 Mon Sep 17 00:00:00 2001 From: Steve Bronder Date: Wed, 17 Jun 2020 01:13:33 -0400 Subject: [PATCH 083/355] add tuple of stacks to zero out --- make/compiler_flags | 2 +- stan/math/prim/functor.hpp | 1 + stan/math/prim/functor/for_each_tuple.hpp | 37 +++++++++++++++++++ stan/math/rev/core/autodiffstackstorage.hpp | 14 +++---- stan/math/rev/core/chainablestack.hpp | 8 +++- stan/math/rev/core/recover_memory.hpp | 6 ++- stan/math/rev/core/recover_memory_nested.hpp | 12 +++--- stan/math/rev/core/set_zero_all_adjoints.hpp | 10 +++-- .../rev/core/set_zero_all_adjoints_nested.hpp | 14 +++++-- stan/math/rev/core/start_nested.hpp | 7 +++- stan/math/rev/core/vari.hpp | 11 +++--- 11 files changed, 91 insertions(+), 31 deletions(-) create mode 100644 stan/math/prim/functor/for_each_tuple.hpp diff --git a/make/compiler_flags b/make/compiler_flags index 20a490c7fda..0649b6bea2a 100644 --- a/make/compiler_flags +++ b/make/compiler_flags @@ -256,7 +256,7 @@ ifdef STAN_MPI CXXFLAGS_MPI ?= -Wno-delete-non-virtual-dtor endif -CXXFLAGS += $(CXXFLAGS_LANG) $(CXXFLAGS_OS) $(CXXFLAGS_WARNINGS) $(CXXFLAGS_BOOST) $(CXXFLAGS_EIGEN) $(CXXFLAGS_OPENCL) $(CXXFLAGS_MPI) $(CXXFLAGS_THREADS) $(CXXFLAGS_TBB) -O$(O) $(INC) +CXXFLAGS += $(CXXFLAGS_LANG) $(CXXFLAGS_OS) $(CXXFLAGS_WARNINGS) $(CXXFLAGS_BOOST) $(CXXFLAGS_EIGEN) $(CXXFLAGS_OPENCL) $(CXXFLAGS_MPI) $(CXXFLAGS_THREADS) $(CXXFLAGS_TBB) -O$(O) $(INC) -g -O0 CPPFLAGS += $(CPPFLAGS_LANG) $(CPPFLAGS_OS) $(CPPFLAGS_WARNINGS) $(CPPFLAGS_BOOST) $(CPPFLAGS_EIGEN) $(CPPFLAGS_OPENCL) $(CPPFLAGS_MPI) $(CPPFLAGS_TBB) LDFLAGS += $(LDFLAGS_LANG) $(LDFLAGS_OS) $(LDFLAGS_WARNINGS) $(LDFLAGS_BOOST) $(LDFLAGS_EIGEN) $(LDFLAGS_OPENCL) $(LDFLAGS_MPI) $(LDFLAGS_TBB) LDLIBS += $(LDLIBS_LANG) $(LDLIBS_OS) $(LDLIBS_WARNINGS) $(LDLIBS_BOOST) $(LDLIBS_EIGEN) $(LDLIBS_OPENCL) $(LDLIBS_MPI) $(LDLIBS_TBB) diff --git a/stan/math/prim/functor.hpp b/stan/math/prim/functor.hpp index f33209dcac3..a11d7dacbb4 100644 --- a/stan/math/prim/functor.hpp +++ b/stan/math/prim/functor.hpp @@ -9,6 +9,7 @@ #include #include #include +#include #include #include #include diff --git a/stan/math/prim/functor/for_each_tuple.hpp b/stan/math/prim/functor/for_each_tuple.hpp new file mode 100644 index 00000000000..e6884e5083e --- /dev/null +++ b/stan/math/prim/functor/for_each_tuple.hpp @@ -0,0 +1,37 @@ +#ifndef STAN_MATH_PRIM_FUNCTOR_FOR_EACH_TUPLE_HPP +#define STAN_MATH_PRIM_FUNCTOR_FOR_EACH_TUPLE_HPP + +#include +#include +#include +#include + +namespace stan { +namespace math { +namespace internal { +template +inline auto for_each(F&& f, T&& t, std::index_sequence) { + using tuple_ret = std::tuple(std::declval())))>...>; + return tuple_ret{ std::forward(f)(std::get(t))... }; +} +template +inline auto for_each(F&& f, T1&& t1, T2&& t2, std::index_sequence) { + using tuple_ret = std::tuple(std::declval())), + decltype(std::get(std::declval())))>...>; + return tuple_ret{ std::forward(f)(std::get(t1), std::get(t2))... }; +} +} +template +inline auto for_each_tuple(F&& f, T&& t) { + return internal::for_each(std::forward(f), std::forward(t), + std::make_index_sequence>::value>()); +} +template +inline auto for_each_tuple(F&& f, T1&& t1, T2&& t2) { + return internal::for_each(std::forward(f), std::forward(t1), std::forward(t2), + std::make_index_sequence>::value>()); +} + +} +} +#endif diff --git a/stan/math/rev/core/autodiffstackstorage.hpp b/stan/math/rev/core/autodiffstackstorage.hpp index 4734e09cdb7..79dc4c52f57 100644 --- a/stan/math/rev/core/autodiffstackstorage.hpp +++ b/stan/math/rev/core/autodiffstackstorage.hpp @@ -88,10 +88,10 @@ class vari_value; * [3] * http://discourse.mc-stan.org/t/potentially-dropping-support-for-older-versions-of-apples-version-of-clang/3780/ */ -template +template struct AutodiffStackSingleton { using AutodiffStackSingleton_t - = AutodiffStackSingleton; + = AutodiffStackSingleton; AutodiffStackSingleton() : own_instance_(init()) {} ~AutodiffStackSingleton() { @@ -105,13 +105,13 @@ struct AutodiffStackSingleton { AutodiffStackStorage &operator=(const AutodiffStackStorage &) = delete; std::vector var_stack_; - std::vector*> var_dbl_stack_; + ZeroingT var_zeroing_stacks_; std::vector var_alloc_stack_; stack_alloc memalloc_; // nested positions std::vector nested_var_stack_sizes_; - std::vector nested_var_dbl_stack_sizes_; + NumZeroingT nested_var_zeroing_stack_sizes_; std::vector nested_var_alloc_stack_starts_; }; @@ -139,11 +139,11 @@ struct AutodiffStackSingleton { bool own_instance_; }; -template +template STAN_THREADS_DEF typename AutodiffStackSingleton::AutodiffStackStorage - *AutodiffStackSingleton::instance_; + ChainableAllocT, ZeroingT, NumZeroingT>::AutodiffStackStorage + *AutodiffStackSingleton::instance_; } // namespace math } // namespace stan diff --git a/stan/math/rev/core/chainablestack.hpp b/stan/math/rev/core/chainablestack.hpp index 47d94983ca6..eeaf0334d3f 100644 --- a/stan/math/rev/core/chainablestack.hpp +++ b/stan/math/rev/core/chainablestack.hpp @@ -2,7 +2,7 @@ #define STAN_MATH_REV_CORE_CHAINABLESTACK_HPP #include -#include +#include namespace stan { namespace math { @@ -10,7 +10,11 @@ template class vari_value; class vari_base; class chainable_alloc; -using ChainableStack = AutodiffStackSingleton; +using zeroing_stacks = std::tuple*>, + std::vector*>, + std::vector*>>; +using zeroing_stacks_sizes = std::tuple, std::vector, std::vector>; +using ChainableStack = AutodiffStackSingleton; } // namespace math } // namespace stan diff --git a/stan/math/rev/core/recover_memory.hpp b/stan/math/rev/core/recover_memory.hpp index 116d9befcc2..e589455ba58 100644 --- a/stan/math/rev/core/recover_memory.hpp +++ b/stan/math/rev/core/recover_memory.hpp @@ -1,6 +1,7 @@ #ifndef STAN_MATH_REV_CORE_RECOVER_MEMORY_HPP #define STAN_MATH_REV_CORE_RECOVER_MEMORY_HPP +#include #include #include #include @@ -22,7 +23,10 @@ static inline void recover_memory() { " before calling recover_memory()"); } ChainableStack::instance_->var_stack_.clear(); - ChainableStack::instance_->var_dbl_stack_.clear(); + for_each_tuple([](auto& x) { + x.clear(); + return 0; + }, ChainableStack::instance_->var_zeroing_stacks_); for (auto &x : ChainableStack::instance_->var_alloc_stack_) { delete x; } diff --git a/stan/math/rev/core/recover_memory_nested.hpp b/stan/math/rev/core/recover_memory_nested.hpp index 0e34aaee8ed..c9ba7a2bf3e 100644 --- a/stan/math/rev/core/recover_memory_nested.hpp +++ b/stan/math/rev/core/recover_memory_nested.hpp @@ -1,6 +1,7 @@ #ifndef STAN_MATH_REV_CORE_RECOVER_MEMORY_NESTED_HPP #define STAN_MATH_REV_CORE_RECOVER_MEMORY_NESTED_HPP +#include #include #include #include @@ -30,11 +31,12 @@ static inline void recover_memory_nested() { ChainableStack::instance_->var_stack_.resize( ChainableStack::instance_->nested_var_stack_sizes_.back()); ChainableStack::instance_->nested_var_stack_sizes_.pop_back(); - - ChainableStack::instance_->var_dbl_stack_.resize( - ChainableStack::instance_->nested_var_dbl_stack_sizes_.back()); - ChainableStack::instance_->nested_var_dbl_stack_sizes_.pop_back(); - + for_each_tuple([](auto& x, auto& y) { + x.resize(y.back()); + y.pop_back(); + return 0; + }, ChainableStack::instance_->var_zeroing_stacks_, + ChainableStack::instance_->nested_var_zeroing_stack_sizes_); for (size_t i = ChainableStack::instance_->nested_var_alloc_stack_starts_.back(); i < ChainableStack::instance_->var_alloc_stack_.size(); ++i) { diff --git a/stan/math/rev/core/set_zero_all_adjoints.hpp b/stan/math/rev/core/set_zero_all_adjoints.hpp index abd4f87d2e0..b68268a255d 100644 --- a/stan/math/rev/core/set_zero_all_adjoints.hpp +++ b/stan/math/rev/core/set_zero_all_adjoints.hpp @@ -1,6 +1,7 @@ #ifndef STAN_MATH_REV_CORE_SET_ZERO_ALL_ADJOINTS_HPP #define STAN_MATH_REV_CORE_SET_ZERO_ALL_ADJOINTS_HPP +#include #include #include #include @@ -12,9 +13,12 @@ namespace math { * Reset all adjoint values in the stack to zero. */ static EIGEN_STRONG_INLINE void set_zero_all_adjoints() { - for (auto& x : ChainableStack::instance_->var_dbl_stack_) { - x->set_zero_adjoint(); - } + for_each_tuple([](auto& x) { + for (auto& xx : x) { + xx->set_zero_adjoint(); + } + return 0; + }, ChainableStack::instance_->var_zeroing_stacks_); } } // namespace math diff --git a/stan/math/rev/core/set_zero_all_adjoints_nested.hpp b/stan/math/rev/core/set_zero_all_adjoints_nested.hpp index 26c0afc3e60..8779e825cc3 100644 --- a/stan/math/rev/core/set_zero_all_adjoints_nested.hpp +++ b/stan/math/rev/core/set_zero_all_adjoints_nested.hpp @@ -1,6 +1,7 @@ #ifndef STAN_MATH_REV_CORE_SET_ZERO_ALL_ADJOINTS_NESTED_HPP #define STAN_MATH_REV_CORE_SET_ZERO_ALL_ADJOINTS_NESTED_HPP +#include #include #include #include @@ -24,11 +25,16 @@ static EIGEN_STRONG_INLINE void set_zero_all_adjoints_nested() { " set_zero_all_adjoints_nested()"); } size_t start1 = ChainableStack::instance_->nested_var_stack_sizes_.back(); - const auto stack_size = ChainableStack::instance_->var_dbl_stack_.size(); + for_each_tuple([&start1](auto& x, auto& x_size) { + const auto stack_size = x.size(); + if (stack_size > 0) { + for (size_t i = (start1 == 0U) ? 0U : (start1 - 1); i < stack_size; ++i) { + x[i]->set_zero_adjoint(); + } + } + return 0; + }, ChainableStack::instance_->var_zeroing_stacks_, ChainableStack::instance_->nested_var_zeroing_stack_sizes_); // avoid wrap with unsigned when start1 == 0 - for (size_t i = (start1 == 0U) ? 0U : (start1 - 1); i < stack_size; ++i) { - ChainableStack::instance_->var_dbl_stack_[i]->set_zero_adjoint(); - } } } // namespace math diff --git a/stan/math/rev/core/start_nested.hpp b/stan/math/rev/core/start_nested.hpp index bb0f0a7cec8..dc1aa6b924d 100644 --- a/stan/math/rev/core/start_nested.hpp +++ b/stan/math/rev/core/start_nested.hpp @@ -16,8 +16,11 @@ namespace math { static inline void start_nested() { ChainableStack::instance_->nested_var_stack_sizes_.push_back( ChainableStack::instance_->var_stack_.size()); - ChainableStack::instance_->nested_var_dbl_stack_sizes_.push_back( - ChainableStack::instance_->var_dbl_stack_.size()); + for_each_tuple([](auto& x, auto& y) { + x.push_back(y.size()); + return 0; + }, ChainableStack::instance_->nested_var_zeroing_stack_sizes_, + ChainableStack::instance_->var_zeroing_stacks_); ChainableStack::instance_->nested_var_alloc_stack_starts_.push_back( ChainableStack::instance_->var_alloc_stack_.size()); ChainableStack::instance_->memalloc_.start_nested(); diff --git a/stan/math/rev/core/vari.hpp b/stan/math/rev/core/vari.hpp index f797346e033..d2b339e7fcf 100644 --- a/stan/math/rev/core/vari.hpp +++ b/stan/math/rev/core/vari.hpp @@ -50,7 +50,6 @@ class vari_value::value>> : public * The value of this variable. */ const Scalar val_; - /** * The adjoint of this variable, which is the partial derivative * of this variable with respect to the root variable. @@ -73,7 +72,7 @@ class vari_value::value>> : public template ::value>* = nullptr> vari_value(S x) noexcept : val_(x), adj_(0.0) { // NOLINT - ChainableStack::instance_->var_dbl_stack_.emplace_back(this); + std::get*>>(ChainableStack::instance_->var_zeroing_stacks_).emplace_back(this); ChainableStack::instance_->var_stack_.emplace_back(this); } @@ -97,10 +96,10 @@ class vari_value::value>> : public template ::value>* = nullptr> vari_value(S x, bool stacked) noexcept : val_(x), adj_(0.0) { - ChainableStack::instance_->var_dbl_stack_.emplace_back(this); + std::get*>>(ChainableStack::instance_->var_zeroing_stacks_).emplace_back(this); if (stacked) { ChainableStack::instance_->var_stack_.emplace_back(this); - } + } } /** @@ -109,7 +108,7 @@ class vari_value::value>> : public * @param x A vari_value */ vari_value(const vari_value& x) noexcept : val_(x.val_), adj_(x.adj_) { - ChainableStack::instance_->var_dbl_stack_.emplace_back(this); + std::get*>>(ChainableStack::instance_->var_zeroing_stacks_).emplace_back(this); ChainableStack::instance_->var_stack_.emplace_back(this); } /** @@ -118,7 +117,7 @@ class vari_value::value>> : public * @param x A vari_value */ vari_value(vari_value&& x) noexcept : val_(x.val_), adj_(x.adj_) { - ChainableStack::instance_->var_dbl_stack_.emplace_back(this); + std::get*>>(ChainableStack::instance_->var_zeroing_stacks_).emplace_back(this); ChainableStack::instance_->var_stack_.emplace_back(this); } From 2f7d37c506c6cffc1cb733bb24a1992fd96e1663 Mon Sep 17 00:00:00 2001 From: Steve Bronder Date: Wed, 17 Jun 2020 02:03:00 -0400 Subject: [PATCH 084/355] debugs for nested sizes --- stan/math/prim/functor/for_each_tuple.hpp | 7 ++----- stan/math/rev/core/recover_memory.hpp | 3 +-- stan/math/rev/core/recover_memory_nested.hpp | 12 +++++++++--- stan/math/rev/core/set_zero_all_adjoints.hpp | 7 ++++--- stan/math/rev/core/set_zero_all_adjoints_nested.hpp | 1 - stan/math/rev/core/start_nested.hpp | 9 +++++++-- 6 files changed, 23 insertions(+), 16 deletions(-) diff --git a/stan/math/prim/functor/for_each_tuple.hpp b/stan/math/prim/functor/for_each_tuple.hpp index e6884e5083e..f0a515cc7a2 100644 --- a/stan/math/prim/functor/for_each_tuple.hpp +++ b/stan/math/prim/functor/for_each_tuple.hpp @@ -11,14 +11,11 @@ namespace math { namespace internal { template inline auto for_each(F&& f, T&& t, std::index_sequence) { - using tuple_ret = std::tuple(std::declval())))>...>; - return tuple_ret{ std::forward(f)(std::get(t))... }; + auto l = { (std::forward(f)(std::get(t)), 0)...}; } template inline auto for_each(F&& f, T1&& t1, T2&& t2, std::index_sequence) { - using tuple_ret = std::tuple(std::declval())), - decltype(std::get(std::declval())))>...>; - return tuple_ret{ std::forward(f)(std::get(t1), std::get(t2))... }; + auto l = { (std::forward(f)(std::get(t1), std::get(t2)), 0)...}; } } template diff --git a/stan/math/rev/core/recover_memory.hpp b/stan/math/rev/core/recover_memory.hpp index e589455ba58..0d5ef1c0eab 100644 --- a/stan/math/rev/core/recover_memory.hpp +++ b/stan/math/rev/core/recover_memory.hpp @@ -24,8 +24,7 @@ static inline void recover_memory() { } ChainableStack::instance_->var_stack_.clear(); for_each_tuple([](auto& x) { - x.clear(); - return 0; + x.clear(); }, ChainableStack::instance_->var_zeroing_stacks_); for (auto &x : ChainableStack::instance_->var_alloc_stack_) { delete x; diff --git a/stan/math/rev/core/recover_memory_nested.hpp b/stan/math/rev/core/recover_memory_nested.hpp index c9ba7a2bf3e..17caae7fddc 100644 --- a/stan/math/rev/core/recover_memory_nested.hpp +++ b/stan/math/rev/core/recover_memory_nested.hpp @@ -32,11 +32,17 @@ static inline void recover_memory_nested() { ChainableStack::instance_->nested_var_stack_sizes_.back()); ChainableStack::instance_->nested_var_stack_sizes_.pop_back(); for_each_tuple([](auto& x, auto& y) { - x.resize(y.back()); - y.pop_back(); - return 0; + if (std::is_same, vari_value*>::value) { + std::cout << "zero_stack size : " << x.size() << " nested_zero_stack size: " << y.size() << std::endl; + if(y.size() > 0) { + std::cout << "nested_zero_end : " << *(y.end()-1) << std::endl; + x.resize(y.back()); + y.pop_back(); + } + } }, ChainableStack::instance_->var_zeroing_stacks_, ChainableStack::instance_->nested_var_zeroing_stack_sizes_); + for (size_t i = ChainableStack::instance_->nested_var_alloc_stack_starts_.back(); i < ChainableStack::instance_->var_alloc_stack_.size(); ++i) { diff --git a/stan/math/rev/core/set_zero_all_adjoints.hpp b/stan/math/rev/core/set_zero_all_adjoints.hpp index b68268a255d..c38475da99d 100644 --- a/stan/math/rev/core/set_zero_all_adjoints.hpp +++ b/stan/math/rev/core/set_zero_all_adjoints.hpp @@ -14,10 +14,11 @@ namespace math { */ static EIGEN_STRONG_INLINE void set_zero_all_adjoints() { for_each_tuple([](auto& x) { - for (auto& xx : x) { - xx->set_zero_adjoint(); + if (x.size() > 0) { + for (auto& xx : x) { + xx->set_zero_adjoint(); + } } - return 0; }, ChainableStack::instance_->var_zeroing_stacks_); } diff --git a/stan/math/rev/core/set_zero_all_adjoints_nested.hpp b/stan/math/rev/core/set_zero_all_adjoints_nested.hpp index 8779e825cc3..2daee965418 100644 --- a/stan/math/rev/core/set_zero_all_adjoints_nested.hpp +++ b/stan/math/rev/core/set_zero_all_adjoints_nested.hpp @@ -32,7 +32,6 @@ static EIGEN_STRONG_INLINE void set_zero_all_adjoints_nested() { x[i]->set_zero_adjoint(); } } - return 0; }, ChainableStack::instance_->var_zeroing_stacks_, ChainableStack::instance_->nested_var_zeroing_stack_sizes_); // avoid wrap with unsigned when start1 == 0 } diff --git a/stan/math/rev/core/start_nested.hpp b/stan/math/rev/core/start_nested.hpp index dc1aa6b924d..7cdb17f1d31 100644 --- a/stan/math/rev/core/start_nested.hpp +++ b/stan/math/rev/core/start_nested.hpp @@ -17,8 +17,13 @@ static inline void start_nested() { ChainableStack::instance_->nested_var_stack_sizes_.push_back( ChainableStack::instance_->var_stack_.size()); for_each_tuple([](auto& x, auto& y) { - x.push_back(y.size()); - return 0; + if (std::is_same, vari_value*>::value) { + std::cout << "1 size : " << x.size() << " 2 size: " << y.size() << std::endl; + } + if (y.size() > 0) { + x.push_back(y.size()); + } + }, ChainableStack::instance_->nested_var_zeroing_stack_sizes_, ChainableStack::instance_->var_zeroing_stacks_); ChainableStack::instance_->nested_var_alloc_stack_starts_.push_back( From e3e2d7e40167f7b57646b0b00b337bbd19537e33 Mon Sep 17 00:00:00 2001 From: Steve Bronder Date: Wed, 17 Jun 2020 02:43:57 -0400 Subject: [PATCH 085/355] multi-stack nested --- make/compiler_flags | 2 +- stan/math/prim/functor/for_each_tuple.hpp | 8 ++++---- stan/math/rev/core/recover_memory_nested.hpp | 8 ++------ stan/math/rev/core/set_zero_all_adjoints.hpp | 2 -- stan/math/rev/core/set_zero_all_adjoints_nested.hpp | 2 -- stan/math/rev/core/start_nested.hpp | 6 ------ 6 files changed, 7 insertions(+), 21 deletions(-) diff --git a/make/compiler_flags b/make/compiler_flags index 0649b6bea2a..20a490c7fda 100644 --- a/make/compiler_flags +++ b/make/compiler_flags @@ -256,7 +256,7 @@ ifdef STAN_MPI CXXFLAGS_MPI ?= -Wno-delete-non-virtual-dtor endif -CXXFLAGS += $(CXXFLAGS_LANG) $(CXXFLAGS_OS) $(CXXFLAGS_WARNINGS) $(CXXFLAGS_BOOST) $(CXXFLAGS_EIGEN) $(CXXFLAGS_OPENCL) $(CXXFLAGS_MPI) $(CXXFLAGS_THREADS) $(CXXFLAGS_TBB) -O$(O) $(INC) -g -O0 +CXXFLAGS += $(CXXFLAGS_LANG) $(CXXFLAGS_OS) $(CXXFLAGS_WARNINGS) $(CXXFLAGS_BOOST) $(CXXFLAGS_EIGEN) $(CXXFLAGS_OPENCL) $(CXXFLAGS_MPI) $(CXXFLAGS_THREADS) $(CXXFLAGS_TBB) -O$(O) $(INC) CPPFLAGS += $(CPPFLAGS_LANG) $(CPPFLAGS_OS) $(CPPFLAGS_WARNINGS) $(CPPFLAGS_BOOST) $(CPPFLAGS_EIGEN) $(CPPFLAGS_OPENCL) $(CPPFLAGS_MPI) $(CPPFLAGS_TBB) LDFLAGS += $(LDFLAGS_LANG) $(LDFLAGS_OS) $(LDFLAGS_WARNINGS) $(LDFLAGS_BOOST) $(LDFLAGS_EIGEN) $(LDFLAGS_OPENCL) $(LDFLAGS_MPI) $(LDFLAGS_TBB) LDLIBS += $(LDLIBS_LANG) $(LDLIBS_OS) $(LDLIBS_WARNINGS) $(LDLIBS_BOOST) $(LDLIBS_EIGEN) $(LDLIBS_OPENCL) $(LDLIBS_MPI) $(LDLIBS_TBB) diff --git a/stan/math/prim/functor/for_each_tuple.hpp b/stan/math/prim/functor/for_each_tuple.hpp index f0a515cc7a2..8245d69a1b4 100644 --- a/stan/math/prim/functor/for_each_tuple.hpp +++ b/stan/math/prim/functor/for_each_tuple.hpp @@ -10,21 +10,21 @@ namespace stan { namespace math { namespace internal { template -inline auto for_each(F&& f, T&& t, std::index_sequence) { +static inline auto for_each(F&& f, T&& t, std::index_sequence) { auto l = { (std::forward(f)(std::get(t)), 0)...}; } template -inline auto for_each(F&& f, T1&& t1, T2&& t2, std::index_sequence) { +static inline auto for_each(F&& f, T1&& t1, T2&& t2, std::index_sequence) { auto l = { (std::forward(f)(std::get(t1), std::get(t2)), 0)...}; } } template -inline auto for_each_tuple(F&& f, T&& t) { +static inline auto for_each_tuple(F&& f, T&& t) { return internal::for_each(std::forward(f), std::forward(t), std::make_index_sequence>::value>()); } template -inline auto for_each_tuple(F&& f, T1&& t1, T2&& t2) { +static inline auto for_each_tuple(F&& f, T1&& t1, T2&& t2) { return internal::for_each(std::forward(f), std::forward(t1), std::forward(t2), std::make_index_sequence>::value>()); } diff --git a/stan/math/rev/core/recover_memory_nested.hpp b/stan/math/rev/core/recover_memory_nested.hpp index 17caae7fddc..9d7ff79125a 100644 --- a/stan/math/rev/core/recover_memory_nested.hpp +++ b/stan/math/rev/core/recover_memory_nested.hpp @@ -32,14 +32,10 @@ static inline void recover_memory_nested() { ChainableStack::instance_->nested_var_stack_sizes_.back()); ChainableStack::instance_->nested_var_stack_sizes_.pop_back(); for_each_tuple([](auto& x, auto& y) { - if (std::is_same, vari_value*>::value) { - std::cout << "zero_stack size : " << x.size() << " nested_zero_stack size: " << y.size() << std::endl; - if(y.size() > 0) { - std::cout << "nested_zero_end : " << *(y.end()-1) << std::endl; + if (y.size() > 0) { x.resize(y.back()); - y.pop_back(); + y.pop_back(); } - } }, ChainableStack::instance_->var_zeroing_stacks_, ChainableStack::instance_->nested_var_zeroing_stack_sizes_); diff --git a/stan/math/rev/core/set_zero_all_adjoints.hpp b/stan/math/rev/core/set_zero_all_adjoints.hpp index c38475da99d..2049c95192a 100644 --- a/stan/math/rev/core/set_zero_all_adjoints.hpp +++ b/stan/math/rev/core/set_zero_all_adjoints.hpp @@ -14,11 +14,9 @@ namespace math { */ static EIGEN_STRONG_INLINE void set_zero_all_adjoints() { for_each_tuple([](auto& x) { - if (x.size() > 0) { for (auto& xx : x) { xx->set_zero_adjoint(); } - } }, ChainableStack::instance_->var_zeroing_stacks_); } diff --git a/stan/math/rev/core/set_zero_all_adjoints_nested.hpp b/stan/math/rev/core/set_zero_all_adjoints_nested.hpp index 2daee965418..28e5f1200e1 100644 --- a/stan/math/rev/core/set_zero_all_adjoints_nested.hpp +++ b/stan/math/rev/core/set_zero_all_adjoints_nested.hpp @@ -27,11 +27,9 @@ static EIGEN_STRONG_INLINE void set_zero_all_adjoints_nested() { size_t start1 = ChainableStack::instance_->nested_var_stack_sizes_.back(); for_each_tuple([&start1](auto& x, auto& x_size) { const auto stack_size = x.size(); - if (stack_size > 0) { for (size_t i = (start1 == 0U) ? 0U : (start1 - 1); i < stack_size; ++i) { x[i]->set_zero_adjoint(); } - } }, ChainableStack::instance_->var_zeroing_stacks_, ChainableStack::instance_->nested_var_zeroing_stack_sizes_); // avoid wrap with unsigned when start1 == 0 } diff --git a/stan/math/rev/core/start_nested.hpp b/stan/math/rev/core/start_nested.hpp index 7cdb17f1d31..697bb5405f0 100644 --- a/stan/math/rev/core/start_nested.hpp +++ b/stan/math/rev/core/start_nested.hpp @@ -17,13 +17,7 @@ static inline void start_nested() { ChainableStack::instance_->nested_var_stack_sizes_.push_back( ChainableStack::instance_->var_stack_.size()); for_each_tuple([](auto& x, auto& y) { - if (std::is_same, vari_value*>::value) { - std::cout << "1 size : " << x.size() << " 2 size: " << y.size() << std::endl; - } - if (y.size() > 0) { x.push_back(y.size()); - } - }, ChainableStack::instance_->nested_var_zeroing_stack_sizes_, ChainableStack::instance_->var_zeroing_stacks_); ChainableStack::instance_->nested_var_alloc_stack_starts_.push_back( From e742ec0e236a626ab1b98edf4c5532d63336f195 Mon Sep 17 00:00:00 2001 From: Steve Bronder Date: Wed, 17 Jun 2020 11:49:59 -0400 Subject: [PATCH 086/355] add size check on start_nested --- stan/math/rev/core/start_nested.hpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/stan/math/rev/core/start_nested.hpp b/stan/math/rev/core/start_nested.hpp index 697bb5405f0..3caf86313da 100644 --- a/stan/math/rev/core/start_nested.hpp +++ b/stan/math/rev/core/start_nested.hpp @@ -17,7 +17,9 @@ static inline void start_nested() { ChainableStack::instance_->nested_var_stack_sizes_.push_back( ChainableStack::instance_->var_stack_.size()); for_each_tuple([](auto& x, auto& y) { - x.push_back(y.size()); + if (y.size() > 0) { + x.push_back(y.size()); + } }, ChainableStack::instance_->nested_var_zeroing_stack_sizes_, ChainableStack::instance_->var_zeroing_stacks_); ChainableStack::instance_->nested_var_alloc_stack_starts_.push_back( From 5f4278fa4bccd78ff3ba3aeb7ef47342c7e006ec Mon Sep 17 00:00:00 2001 From: Stan Jenkins Date: Wed, 17 Jun 2020 11:51:19 -0400 Subject: [PATCH 087/355] [Jenkins] auto-formatting by clang-format version 6.0.0-1ubuntu2 (tags/RELEASE_600/final) --- stan/math/prim/functor/for_each_tuple.hpp | 31 ++++++++++--------- stan/math/rev/core/autodiffstackstorage.hpp | 18 ++++++----- stan/math/rev/core/chainablestack.hpp | 11 ++++--- stan/math/rev/core/recover_memory.hpp | 7 ++--- stan/math/rev/core/recover_memory_nested.hpp | 16 +++++----- stan/math/rev/core/set_zero_all_adjoints.hpp | 12 ++++--- .../rev/core/set_zero_all_adjoints_nested.hpp | 16 ++++++---- stan/math/rev/core/start_nested.hpp | 14 +++++---- stan/math/rev/core/vari.hpp | 21 +++++++++---- 9 files changed, 87 insertions(+), 59 deletions(-) diff --git a/stan/math/prim/functor/for_each_tuple.hpp b/stan/math/prim/functor/for_each_tuple.hpp index 8245d69a1b4..c520e02df91 100644 --- a/stan/math/prim/functor/for_each_tuple.hpp +++ b/stan/math/prim/functor/for_each_tuple.hpp @@ -9,26 +9,29 @@ namespace stan { namespace math { namespace internal { -template +template static inline auto for_each(F&& f, T&& t, std::index_sequence) { - auto l = { (std::forward(f)(std::get(t)), 0)...}; + auto l = {(std::forward(f)(std::get(t)), 0)...}; } -template -static inline auto for_each(F&& f, T1&& t1, T2&& t2, std::index_sequence) { - auto l = { (std::forward(f)(std::get(t1), std::get(t2)), 0)...}; +template +static inline auto for_each(F&& f, T1&& t1, T2&& t2, + std::index_sequence) { + auto l = {(std::forward(f)(std::get(t1), std::get(t2)), 0)...}; } -} -template +} // namespace internal +template static inline auto for_each_tuple(F&& f, T&& t) { - return internal::for_each(std::forward(f), std::forward(t), - std::make_index_sequence>::value>()); + return internal::for_each( + std::forward(f), std::forward(t), + std::make_index_sequence>::value>()); } -template +template static inline auto for_each_tuple(F&& f, T1&& t1, T2&& t2) { - return internal::for_each(std::forward(f), std::forward(t1), std::forward(t2), - std::make_index_sequence>::value>()); + return internal::for_each( + std::forward(f), std::forward(t1), std::forward(t2), + std::make_index_sequence>::value>()); } -} -} +} // namespace math +} // namespace stan #endif diff --git a/stan/math/rev/core/autodiffstackstorage.hpp b/stan/math/rev/core/autodiffstackstorage.hpp index 79dc4c52f57..e66ac4bf63b 100644 --- a/stan/math/rev/core/autodiffstackstorage.hpp +++ b/stan/math/rev/core/autodiffstackstorage.hpp @@ -88,10 +88,12 @@ class vari_value; * [3] * http://discourse.mc-stan.org/t/potentially-dropping-support-for-older-versions-of-apples-version-of-clang/3780/ */ -template +template struct AutodiffStackSingleton { using AutodiffStackSingleton_t - = AutodiffStackSingleton; + = AutodiffStackSingleton; AutodiffStackSingleton() : own_instance_(init()) {} ~AutodiffStackSingleton() { @@ -104,7 +106,7 @@ struct AutodiffStackSingleton { struct AutodiffStackStorage { AutodiffStackStorage &operator=(const AutodiffStackStorage &) = delete; - std::vector var_stack_; + std::vector var_stack_; ZeroingT var_zeroing_stacks_; std::vector var_alloc_stack_; stack_alloc memalloc_; @@ -139,11 +141,13 @@ struct AutodiffStackSingleton { bool own_instance_; }; -template +template STAN_THREADS_DEF - typename AutodiffStackSingleton::AutodiffStackStorage - *AutodiffStackSingleton::instance_; + typename AutodiffStackSingleton::AutodiffStackStorage + *AutodiffStackSingleton::instance_; } // namespace math } // namespace stan diff --git a/stan/math/rev/core/chainablestack.hpp b/stan/math/rev/core/chainablestack.hpp index eeaf0334d3f..35402d4ab68 100644 --- a/stan/math/rev/core/chainablestack.hpp +++ b/stan/math/rev/core/chainablestack.hpp @@ -11,10 +11,13 @@ class vari_value; class vari_base; class chainable_alloc; using zeroing_stacks = std::tuple*>, - std::vector*>, - std::vector*>>; -using zeroing_stacks_sizes = std::tuple, std::vector, std::vector>; -using ChainableStack = AutodiffStackSingleton; + std::vector*>, + std::vector*>>; +using zeroing_stacks_sizes + = std::tuple, std::vector, std::vector>; +using ChainableStack + = AutodiffStackSingleton; } // namespace math } // namespace stan diff --git a/stan/math/rev/core/recover_memory.hpp b/stan/math/rev/core/recover_memory.hpp index 0d5ef1c0eab..fe96f0133bb 100644 --- a/stan/math/rev/core/recover_memory.hpp +++ b/stan/math/rev/core/recover_memory.hpp @@ -23,10 +23,9 @@ static inline void recover_memory() { " before calling recover_memory()"); } ChainableStack::instance_->var_stack_.clear(); - for_each_tuple([](auto& x) { - x.clear(); - }, ChainableStack::instance_->var_zeroing_stacks_); - for (auto &x : ChainableStack::instance_->var_alloc_stack_) { + for_each_tuple([](auto& x) { x.clear(); }, + ChainableStack::instance_->var_zeroing_stacks_); + for (auto& x : ChainableStack::instance_->var_alloc_stack_) { delete x; } ChainableStack::instance_->var_alloc_stack_.clear(); diff --git a/stan/math/rev/core/recover_memory_nested.hpp b/stan/math/rev/core/recover_memory_nested.hpp index 9d7ff79125a..6bb26555729 100644 --- a/stan/math/rev/core/recover_memory_nested.hpp +++ b/stan/math/rev/core/recover_memory_nested.hpp @@ -31,13 +31,15 @@ static inline void recover_memory_nested() { ChainableStack::instance_->var_stack_.resize( ChainableStack::instance_->nested_var_stack_sizes_.back()); ChainableStack::instance_->nested_var_stack_sizes_.pop_back(); - for_each_tuple([](auto& x, auto& y) { - if (y.size() > 0) { - x.resize(y.back()); - y.pop_back(); - } - }, ChainableStack::instance_->var_zeroing_stacks_, - ChainableStack::instance_->nested_var_zeroing_stack_sizes_); + for_each_tuple( + [](auto& x, auto& y) { + if (y.size() > 0) { + x.resize(y.back()); + y.pop_back(); + } + }, + ChainableStack::instance_->var_zeroing_stacks_, + ChainableStack::instance_->nested_var_zeroing_stack_sizes_); for (size_t i = ChainableStack::instance_->nested_var_alloc_stack_starts_.back(); diff --git a/stan/math/rev/core/set_zero_all_adjoints.hpp b/stan/math/rev/core/set_zero_all_adjoints.hpp index 2049c95192a..8fd9863c6fc 100644 --- a/stan/math/rev/core/set_zero_all_adjoints.hpp +++ b/stan/math/rev/core/set_zero_all_adjoints.hpp @@ -13,11 +13,13 @@ namespace math { * Reset all adjoint values in the stack to zero. */ static EIGEN_STRONG_INLINE void set_zero_all_adjoints() { - for_each_tuple([](auto& x) { - for (auto& xx : x) { - xx->set_zero_adjoint(); - } - }, ChainableStack::instance_->var_zeroing_stacks_); + for_each_tuple( + [](auto& x) { + for (auto& xx : x) { + xx->set_zero_adjoint(); + } + }, + ChainableStack::instance_->var_zeroing_stacks_); } } // namespace math diff --git a/stan/math/rev/core/set_zero_all_adjoints_nested.hpp b/stan/math/rev/core/set_zero_all_adjoints_nested.hpp index 28e5f1200e1..f710119994e 100644 --- a/stan/math/rev/core/set_zero_all_adjoints_nested.hpp +++ b/stan/math/rev/core/set_zero_all_adjoints_nested.hpp @@ -25,12 +25,16 @@ static EIGEN_STRONG_INLINE void set_zero_all_adjoints_nested() { " set_zero_all_adjoints_nested()"); } size_t start1 = ChainableStack::instance_->nested_var_stack_sizes_.back(); - for_each_tuple([&start1](auto& x, auto& x_size) { - const auto stack_size = x.size(); - for (size_t i = (start1 == 0U) ? 0U : (start1 - 1); i < stack_size; ++i) { - x[i]->set_zero_adjoint(); - } - }, ChainableStack::instance_->var_zeroing_stacks_, ChainableStack::instance_->nested_var_zeroing_stack_sizes_); + for_each_tuple( + [&start1](auto& x, auto& x_size) { + const auto stack_size = x.size(); + for (size_t i = (start1 == 0U) ? 0U : (start1 - 1); i < stack_size; + ++i) { + x[i]->set_zero_adjoint(); + } + }, + ChainableStack::instance_->var_zeroing_stacks_, + ChainableStack::instance_->nested_var_zeroing_stack_sizes_); // avoid wrap with unsigned when start1 == 0 } diff --git a/stan/math/rev/core/start_nested.hpp b/stan/math/rev/core/start_nested.hpp index 3caf86313da..d9ac28787de 100644 --- a/stan/math/rev/core/start_nested.hpp +++ b/stan/math/rev/core/start_nested.hpp @@ -16,12 +16,14 @@ namespace math { static inline void start_nested() { ChainableStack::instance_->nested_var_stack_sizes_.push_back( ChainableStack::instance_->var_stack_.size()); - for_each_tuple([](auto& x, auto& y) { - if (y.size() > 0) { - x.push_back(y.size()); - } - }, ChainableStack::instance_->nested_var_zeroing_stack_sizes_, - ChainableStack::instance_->var_zeroing_stacks_); + for_each_tuple( + [](auto& x, auto& y) { + if (y.size() > 0) { + x.push_back(y.size()); + } + }, + ChainableStack::instance_->nested_var_zeroing_stack_sizes_, + ChainableStack::instance_->var_zeroing_stacks_); ChainableStack::instance_->nested_var_alloc_stack_starts_.push_back( ChainableStack::instance_->var_alloc_stack_.size()); ChainableStack::instance_->memalloc_.start_nested(); diff --git a/stan/math/rev/core/vari.hpp b/stan/math/rev/core/vari.hpp index d2b339e7fcf..8858a2527e8 100644 --- a/stan/math/rev/core/vari.hpp +++ b/stan/math/rev/core/vari.hpp @@ -15,7 +15,7 @@ template class var_value; class vari_base { -public: + public: virtual void chain() {} }; /** @@ -38,7 +38,8 @@ template class vari_value; template -class vari_value::value>> : public vari_base { +class vari_value::value>> + : public vari_base { private: template friend class var_value; @@ -72,7 +73,9 @@ class vari_value::value>> : public template ::value>* = nullptr> vari_value(S x) noexcept : val_(x), adj_(0.0) { // NOLINT - std::get*>>(ChainableStack::instance_->var_zeroing_stacks_).emplace_back(this); + std::get*>>( + ChainableStack::instance_->var_zeroing_stacks_) + .emplace_back(this); ChainableStack::instance_->var_stack_.emplace_back(this); } @@ -96,7 +99,9 @@ class vari_value::value>> : public template ::value>* = nullptr> vari_value(S x, bool stacked) noexcept : val_(x), adj_(0.0) { - std::get*>>(ChainableStack::instance_->var_zeroing_stacks_).emplace_back(this); + std::get*>>( + ChainableStack::instance_->var_zeroing_stacks_) + .emplace_back(this); if (stacked) { ChainableStack::instance_->var_stack_.emplace_back(this); } @@ -108,7 +113,9 @@ class vari_value::value>> : public * @param x A vari_value */ vari_value(const vari_value& x) noexcept : val_(x.val_), adj_(x.adj_) { - std::get*>>(ChainableStack::instance_->var_zeroing_stacks_).emplace_back(this); + std::get*>>( + ChainableStack::instance_->var_zeroing_stacks_) + .emplace_back(this); ChainableStack::instance_->var_stack_.emplace_back(this); } /** @@ -117,7 +124,9 @@ class vari_value::value>> : public * @param x A vari_value */ vari_value(vari_value&& x) noexcept : val_(x.val_), adj_(x.adj_) { - std::get*>>(ChainableStack::instance_->var_zeroing_stacks_).emplace_back(this); + std::get*>>( + ChainableStack::instance_->var_zeroing_stacks_) + .emplace_back(this); ChainableStack::instance_->var_stack_.emplace_back(this); } From 9a8ba4c5169276aadebd9fe170d3a4fcbc2147c5 Mon Sep 17 00:00:00 2001 From: Steve Bronder Date: Wed, 17 Jun 2020 13:31:15 -0400 Subject: [PATCH 088/355] add docs to for_each --- stan/math/prim/functor.hpp | 2 +- stan/math/prim/functor/for_each.hpp | 50 +++++++++++++++++++ stan/math/prim/functor/for_each_tuple.hpp | 34 ------------- stan/math/rev/core/autodiffstackstorage.hpp | 13 +++-- stan/math/rev/core/chainablestack.hpp | 3 +- stan/math/rev/core/recover_memory.hpp | 2 +- stan/math/rev/core/recover_memory_nested.hpp | 4 +- stan/math/rev/core/set_zero_all_adjoints.hpp | 2 +- .../rev/core/set_zero_all_adjoints_nested.hpp | 2 +- stan/math/rev/core/start_nested.hpp | 5 +- 10 files changed, 66 insertions(+), 51 deletions(-) create mode 100644 stan/math/prim/functor/for_each.hpp delete mode 100644 stan/math/prim/functor/for_each_tuple.hpp diff --git a/stan/math/prim/functor.hpp b/stan/math/prim/functor.hpp index a11d7dacbb4..03f49008c17 100644 --- a/stan/math/prim/functor.hpp +++ b/stan/math/prim/functor.hpp @@ -9,7 +9,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/stan/math/prim/functor/for_each.hpp b/stan/math/prim/functor/for_each.hpp new file mode 100644 index 00000000000..7e3c36ab315 --- /dev/null +++ b/stan/math/prim/functor/for_each.hpp @@ -0,0 +1,50 @@ +#ifndef STAN_MATH_PRIM_FUNCTOR_for_each_HPP +#define STAN_MATH_PRIM_FUNCTOR_for_each_HPP + +#include +#include +#include +#include + +namespace stan { +namespace math { +namespace internal { +template +constexpr inline auto for_each(F&& f, T&& t, std::index_sequence) { + std::initializer_list{( + static_cast(std::forward(f)(std::get(std::forward(t)))), 0)...}; +} +template +constexpr inline auto for_each(F&& f, T1&& t1, T2&& t2, std::index_sequence) { + std::initializer_list{(static_cast(std::forward(f)(std::get(std::forward(t1)), std::get(std::forward(t2)))), 0)...}; +} +} +/** + * Apply a function to each element of a tuple + * @tparam F type with a valid `operator()` + * @tparam T tuple + * @param f A functor to apply over each element of the tuple. + * @param t A tuple. + */ +template +constexpr inline auto for_each(F&& f, T&& t) { + return internal::for_each(std::forward(f), std::forward(t), + std::make_index_sequence>::value>()); +} +/** + * Apply a function to each element of a tuple and other container + * @tparam F type with a valid `operator()` + * @tparam T1 tuple + * @tparam Any container with an `operator[]` + * @param f A functor to apply over each element of the tuple. + * @param t A tuple. + */ +template +constexpr inline auto for_each(F&& f, T1&& t1, T2&& t2) { + return internal::for_each(std::forward(f), std::forward(t1), std::forward(t2), + std::make_index_sequence>::value>()); +} + +} +} +#endif diff --git a/stan/math/prim/functor/for_each_tuple.hpp b/stan/math/prim/functor/for_each_tuple.hpp deleted file mode 100644 index 8245d69a1b4..00000000000 --- a/stan/math/prim/functor/for_each_tuple.hpp +++ /dev/null @@ -1,34 +0,0 @@ -#ifndef STAN_MATH_PRIM_FUNCTOR_FOR_EACH_TUPLE_HPP -#define STAN_MATH_PRIM_FUNCTOR_FOR_EACH_TUPLE_HPP - -#include -#include -#include -#include - -namespace stan { -namespace math { -namespace internal { -template -static inline auto for_each(F&& f, T&& t, std::index_sequence) { - auto l = { (std::forward(f)(std::get(t)), 0)...}; -} -template -static inline auto for_each(F&& f, T1&& t1, T2&& t2, std::index_sequence) { - auto l = { (std::forward(f)(std::get(t1), std::get(t2)), 0)...}; -} -} -template -static inline auto for_each_tuple(F&& f, T&& t) { - return internal::for_each(std::forward(f), std::forward(t), - std::make_index_sequence>::value>()); -} -template -static inline auto for_each_tuple(F&& f, T1&& t1, T2&& t2) { - return internal::for_each(std::forward(f), std::forward(t1), std::forward(t2), - std::make_index_sequence>::value>()); -} - -} -} -#endif diff --git a/stan/math/rev/core/autodiffstackstorage.hpp b/stan/math/rev/core/autodiffstackstorage.hpp index 79dc4c52f57..0bdfccd4ba5 100644 --- a/stan/math/rev/core/autodiffstackstorage.hpp +++ b/stan/math/rev/core/autodiffstackstorage.hpp @@ -88,10 +88,10 @@ class vari_value; * [3] * http://discourse.mc-stan.org/t/potentially-dropping-support-for-older-versions-of-apples-version-of-clang/3780/ */ -template +template struct AutodiffStackSingleton { using AutodiffStackSingleton_t - = AutodiffStackSingleton; + = AutodiffStackSingleton; AutodiffStackSingleton() : own_instance_(init()) {} ~AutodiffStackSingleton() { @@ -111,7 +111,7 @@ struct AutodiffStackSingleton { // nested positions std::vector nested_var_stack_sizes_; - NumZeroingT nested_var_zeroing_stack_sizes_; + std::array, std::tuple_size::value> nested_var_zeroing_stack_sizes_; std::vector nested_var_alloc_stack_starts_; }; @@ -139,11 +139,10 @@ struct AutodiffStackSingleton { bool own_instance_; }; -template +template STAN_THREADS_DEF - typename AutodiffStackSingleton::AutodiffStackStorage - *AutodiffStackSingleton::instance_; + typename AutodiffStackSingleton::AutodiffStackStorage + *AutodiffStackSingleton::instance_; } // namespace math } // namespace stan diff --git a/stan/math/rev/core/chainablestack.hpp b/stan/math/rev/core/chainablestack.hpp index eeaf0334d3f..ac3d14246b5 100644 --- a/stan/math/rev/core/chainablestack.hpp +++ b/stan/math/rev/core/chainablestack.hpp @@ -13,8 +13,7 @@ class chainable_alloc; using zeroing_stacks = std::tuple*>, std::vector*>, std::vector*>>; -using zeroing_stacks_sizes = std::tuple, std::vector, std::vector>; -using ChainableStack = AutodiffStackSingleton; +using ChainableStack = AutodiffStackSingleton; } // namespace math } // namespace stan diff --git a/stan/math/rev/core/recover_memory.hpp b/stan/math/rev/core/recover_memory.hpp index 0d5ef1c0eab..b27206e6584 100644 --- a/stan/math/rev/core/recover_memory.hpp +++ b/stan/math/rev/core/recover_memory.hpp @@ -23,7 +23,7 @@ static inline void recover_memory() { " before calling recover_memory()"); } ChainableStack::instance_->var_stack_.clear(); - for_each_tuple([](auto& x) { + for_each([](auto& x) { x.clear(); }, ChainableStack::instance_->var_zeroing_stacks_); for (auto &x : ChainableStack::instance_->var_alloc_stack_) { diff --git a/stan/math/rev/core/recover_memory_nested.hpp b/stan/math/rev/core/recover_memory_nested.hpp index 9d7ff79125a..9d67972dc06 100644 --- a/stan/math/rev/core/recover_memory_nested.hpp +++ b/stan/math/rev/core/recover_memory_nested.hpp @@ -31,10 +31,10 @@ static inline void recover_memory_nested() { ChainableStack::instance_->var_stack_.resize( ChainableStack::instance_->nested_var_stack_sizes_.back()); ChainableStack::instance_->nested_var_stack_sizes_.pop_back(); - for_each_tuple([](auto& x, auto& y) { + for_each([](auto& x, auto& y) { if (y.size() > 0) { x.resize(y.back()); - y.pop_back(); + y.pop_back(); } }, ChainableStack::instance_->var_zeroing_stacks_, ChainableStack::instance_->nested_var_zeroing_stack_sizes_); diff --git a/stan/math/rev/core/set_zero_all_adjoints.hpp b/stan/math/rev/core/set_zero_all_adjoints.hpp index 2049c95192a..da4c4884418 100644 --- a/stan/math/rev/core/set_zero_all_adjoints.hpp +++ b/stan/math/rev/core/set_zero_all_adjoints.hpp @@ -13,7 +13,7 @@ namespace math { * Reset all adjoint values in the stack to zero. */ static EIGEN_STRONG_INLINE void set_zero_all_adjoints() { - for_each_tuple([](auto& x) { + for_each([](auto& x) { for (auto& xx : x) { xx->set_zero_adjoint(); } diff --git a/stan/math/rev/core/set_zero_all_adjoints_nested.hpp b/stan/math/rev/core/set_zero_all_adjoints_nested.hpp index 28e5f1200e1..7ced3afc76a 100644 --- a/stan/math/rev/core/set_zero_all_adjoints_nested.hpp +++ b/stan/math/rev/core/set_zero_all_adjoints_nested.hpp @@ -25,7 +25,7 @@ static EIGEN_STRONG_INLINE void set_zero_all_adjoints_nested() { " set_zero_all_adjoints_nested()"); } size_t start1 = ChainableStack::instance_->nested_var_stack_sizes_.back(); - for_each_tuple([&start1](auto& x, auto& x_size) { + for_each([&start1](auto& x, auto& x_size) { const auto stack_size = x.size(); for (size_t i = (start1 == 0U) ? 0U : (start1 - 1); i < stack_size; ++i) { x[i]->set_zero_adjoint(); diff --git a/stan/math/rev/core/start_nested.hpp b/stan/math/rev/core/start_nested.hpp index 3caf86313da..bae6387540e 100644 --- a/stan/math/rev/core/start_nested.hpp +++ b/stan/math/rev/core/start_nested.hpp @@ -1,6 +1,7 @@ #ifndef STAN_MATH_REV_CORE_START_NESTED_HPP #define STAN_MATH_REV_CORE_START_NESTED_HPP +#include #include namespace stan { @@ -16,9 +17,9 @@ namespace math { static inline void start_nested() { ChainableStack::instance_->nested_var_stack_sizes_.push_back( ChainableStack::instance_->var_stack_.size()); - for_each_tuple([](auto& x, auto& y) { + for_each([](auto& x, auto& y) { if (y.size() > 0) { - x.push_back(y.size()); + x.push_back(y.size()); } }, ChainableStack::instance_->nested_var_zeroing_stack_sizes_, ChainableStack::instance_->var_zeroing_stacks_); From 5c6faab9aedd5bfb5cff94dd4fbedb0033c5100b Mon Sep 17 00:00:00 2001 From: Stan Jenkins Date: Wed, 17 Jun 2020 13:45:54 -0400 Subject: [PATCH 089/355] [Jenkins] auto-formatting by clang-format version 6.0.0-1ubuntu2 (tags/RELEASE_600/final) --- stan/math/prim/functor/for_each.hpp | 37 +++++++++++-------- stan/math/rev/core/autodiffstackstorage.hpp | 9 +++-- stan/math/rev/core/chainablestack.hpp | 7 ++-- stan/math/rev/core/recover_memory.hpp | 7 ++-- stan/math/rev/core/recover_memory_nested.hpp | 16 ++++---- stan/math/rev/core/set_zero_all_adjoints.hpp | 13 ++++--- .../rev/core/set_zero_all_adjoints_nested.hpp | 16 +++++--- stan/math/rev/core/start_nested.hpp | 14 ++++--- 8 files changed, 69 insertions(+), 50 deletions(-) diff --git a/stan/math/prim/functor/for_each.hpp b/stan/math/prim/functor/for_each.hpp index 7e3c36ab315..216117828e5 100644 --- a/stan/math/prim/functor/for_each.hpp +++ b/stan/math/prim/functor/for_each.hpp @@ -9,16 +9,21 @@ namespace stan { namespace math { namespace internal { -template +template constexpr inline auto for_each(F&& f, T&& t, std::index_sequence) { - std::initializer_list{( - static_cast(std::forward(f)(std::get(std::forward(t)))), 0)...}; -} -template -constexpr inline auto for_each(F&& f, T1&& t1, T2&& t2, std::index_sequence) { - std::initializer_list{(static_cast(std::forward(f)(std::get(std::forward(t1)), std::get(std::forward(t2)))), 0)...}; + std::initializer_list{ + (static_cast(std::forward(f)(std::get(std::forward(t)))), + 0)...}; } +template +constexpr inline auto for_each(F&& f, T1&& t1, T2&& t2, + std::index_sequence) { + std::initializer_list{( + static_cast(std::forward(f)(std::get(std::forward(t1)), + std::get(std::forward(t2)))), + 0)...}; } +} // namespace internal /** * Apply a function to each element of a tuple * @tparam F type with a valid `operator()` @@ -26,10 +31,11 @@ constexpr inline auto for_each(F&& f, T1&& t1, T2&& t2, std::index_sequence +template constexpr inline auto for_each(F&& f, T&& t) { - return internal::for_each(std::forward(f), std::forward(t), - std::make_index_sequence>::value>()); + return internal::for_each( + std::forward(f), std::forward(t), + std::make_index_sequence>::value>()); } /** * Apply a function to each element of a tuple and other container @@ -39,12 +45,13 @@ constexpr inline auto for_each(F&& f, T&& t) { * @param f A functor to apply over each element of the tuple. * @param t A tuple. */ -template +template constexpr inline auto for_each(F&& f, T1&& t1, T2&& t2) { - return internal::for_each(std::forward(f), std::forward(t1), std::forward(t2), - std::make_index_sequence>::value>()); + return internal::for_each( + std::forward(f), std::forward(t1), std::forward(t2), + std::make_index_sequence>::value>()); } -} -} +} // namespace math +} // namespace stan #endif diff --git a/stan/math/rev/core/autodiffstackstorage.hpp b/stan/math/rev/core/autodiffstackstorage.hpp index 017ccfb4a45..42c74ea92dc 100644 --- a/stan/math/rev/core/autodiffstackstorage.hpp +++ b/stan/math/rev/core/autodiffstackstorage.hpp @@ -111,7 +111,8 @@ struct AutodiffStackSingleton { // nested positions std::vector nested_var_stack_sizes_; - std::array, std::tuple_size::value> nested_var_zeroing_stack_sizes_; + std::array, std::tuple_size::value> + nested_var_zeroing_stack_sizes_; std::vector nested_var_alloc_stack_starts_; }; @@ -140,9 +141,9 @@ struct AutodiffStackSingleton { }; template -STAN_THREADS_DEF - typename AutodiffStackSingleton::AutodiffStackStorage - *AutodiffStackSingleton::instance_; +STAN_THREADS_DEF typename AutodiffStackSingleton::AutodiffStackStorage + *AutodiffStackSingleton::instance_; } // namespace math } // namespace stan diff --git a/stan/math/rev/core/chainablestack.hpp b/stan/math/rev/core/chainablestack.hpp index ac3d14246b5..21f0101c23a 100644 --- a/stan/math/rev/core/chainablestack.hpp +++ b/stan/math/rev/core/chainablestack.hpp @@ -11,9 +11,10 @@ class vari_value; class vari_base; class chainable_alloc; using zeroing_stacks = std::tuple*>, - std::vector*>, - std::vector*>>; -using ChainableStack = AutodiffStackSingleton; + std::vector*>, + std::vector*>>; +using ChainableStack + = AutodiffStackSingleton; } // namespace math } // namespace stan diff --git a/stan/math/rev/core/recover_memory.hpp b/stan/math/rev/core/recover_memory.hpp index b27206e6584..0ceec6d5f35 100644 --- a/stan/math/rev/core/recover_memory.hpp +++ b/stan/math/rev/core/recover_memory.hpp @@ -23,10 +23,9 @@ static inline void recover_memory() { " before calling recover_memory()"); } ChainableStack::instance_->var_stack_.clear(); - for_each([](auto& x) { - x.clear(); - }, ChainableStack::instance_->var_zeroing_stacks_); - for (auto &x : ChainableStack::instance_->var_alloc_stack_) { + for_each([](auto& x) { x.clear(); }, + ChainableStack::instance_->var_zeroing_stacks_); + for (auto& x : ChainableStack::instance_->var_alloc_stack_) { delete x; } ChainableStack::instance_->var_alloc_stack_.clear(); diff --git a/stan/math/rev/core/recover_memory_nested.hpp b/stan/math/rev/core/recover_memory_nested.hpp index 9d67972dc06..ba3f33d5b0e 100644 --- a/stan/math/rev/core/recover_memory_nested.hpp +++ b/stan/math/rev/core/recover_memory_nested.hpp @@ -31,13 +31,15 @@ static inline void recover_memory_nested() { ChainableStack::instance_->var_stack_.resize( ChainableStack::instance_->nested_var_stack_sizes_.back()); ChainableStack::instance_->nested_var_stack_sizes_.pop_back(); - for_each([](auto& x, auto& y) { - if (y.size() > 0) { - x.resize(y.back()); - y.pop_back(); - } - }, ChainableStack::instance_->var_zeroing_stacks_, - ChainableStack::instance_->nested_var_zeroing_stack_sizes_); + for_each( + [](auto& x, auto& y) { + if (y.size() > 0) { + x.resize(y.back()); + y.pop_back(); + } + }, + ChainableStack::instance_->var_zeroing_stacks_, + ChainableStack::instance_->nested_var_zeroing_stack_sizes_); for (size_t i = ChainableStack::instance_->nested_var_alloc_stack_starts_.back(); diff --git a/stan/math/rev/core/set_zero_all_adjoints.hpp b/stan/math/rev/core/set_zero_all_adjoints.hpp index e5eb54c86b7..41e9f411947 100644 --- a/stan/math/rev/core/set_zero_all_adjoints.hpp +++ b/stan/math/rev/core/set_zero_all_adjoints.hpp @@ -13,11 +13,14 @@ namespace math { * Reset all adjoint values in the stack to zero. */ static EIGEN_STRONG_INLINE void set_zero_all_adjoints() { - for_each([](auto& x) { - for (auto& xx : x) { - xx->set_zero_adjoint(); - } - }, ChainableStack::instance_->var_zeroing_stacks_);} + for_each( + [](auto& x) { + for (auto& xx : x) { + xx->set_zero_adjoint(); + } + }, + ChainableStack::instance_->var_zeroing_stacks_); +} } // namespace math } // namespace stan diff --git a/stan/math/rev/core/set_zero_all_adjoints_nested.hpp b/stan/math/rev/core/set_zero_all_adjoints_nested.hpp index 7ced3afc76a..dbe1ce44b1f 100644 --- a/stan/math/rev/core/set_zero_all_adjoints_nested.hpp +++ b/stan/math/rev/core/set_zero_all_adjoints_nested.hpp @@ -25,12 +25,16 @@ static EIGEN_STRONG_INLINE void set_zero_all_adjoints_nested() { " set_zero_all_adjoints_nested()"); } size_t start1 = ChainableStack::instance_->nested_var_stack_sizes_.back(); - for_each([&start1](auto& x, auto& x_size) { - const auto stack_size = x.size(); - for (size_t i = (start1 == 0U) ? 0U : (start1 - 1); i < stack_size; ++i) { - x[i]->set_zero_adjoint(); - } - }, ChainableStack::instance_->var_zeroing_stacks_, ChainableStack::instance_->nested_var_zeroing_stack_sizes_); + for_each( + [&start1](auto& x, auto& x_size) { + const auto stack_size = x.size(); + for (size_t i = (start1 == 0U) ? 0U : (start1 - 1); i < stack_size; + ++i) { + x[i]->set_zero_adjoint(); + } + }, + ChainableStack::instance_->var_zeroing_stacks_, + ChainableStack::instance_->nested_var_zeroing_stack_sizes_); // avoid wrap with unsigned when start1 == 0 } diff --git a/stan/math/rev/core/start_nested.hpp b/stan/math/rev/core/start_nested.hpp index bae6387540e..a667f695136 100644 --- a/stan/math/rev/core/start_nested.hpp +++ b/stan/math/rev/core/start_nested.hpp @@ -17,12 +17,14 @@ namespace math { static inline void start_nested() { ChainableStack::instance_->nested_var_stack_sizes_.push_back( ChainableStack::instance_->var_stack_.size()); - for_each([](auto& x, auto& y) { - if (y.size() > 0) { - x.push_back(y.size()); - } - }, ChainableStack::instance_->nested_var_zeroing_stack_sizes_, - ChainableStack::instance_->var_zeroing_stacks_); + for_each( + [](auto& x, auto& y) { + if (y.size() > 0) { + x.push_back(y.size()); + } + }, + ChainableStack::instance_->nested_var_zeroing_stack_sizes_, + ChainableStack::instance_->var_zeroing_stacks_); ChainableStack::instance_->nested_var_alloc_stack_starts_.push_back( ChainableStack::instance_->var_alloc_stack_.size()); ChainableStack::instance_->memalloc_.start_nested(); From 388b075918991a26e97676b3efbf60ae10d09046 Mon Sep 17 00:00:00 2001 From: Steve Bronder Date: Wed, 17 Jun 2020 13:53:50 -0400 Subject: [PATCH 090/355] update docs --- stan/math/opencl/kernel_generator/type_str.hpp | 1 - stan/math/prim/functor/for_each.hpp | 3 ++- stan/math/rev/core/vari.hpp | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/stan/math/opencl/kernel_generator/type_str.hpp b/stan/math/opencl/kernel_generator/type_str.hpp index 465a5ba0258..43f4aba0333 100644 --- a/stan/math/opencl/kernel_generator/type_str.hpp +++ b/stan/math/opencl/kernel_generator/type_str.hpp @@ -26,7 +26,6 @@ ADD_TYPE_TO_TYPE_STR(int) ADD_TYPE_TO_TYPE_STR(char) ADD_TYPE_TO_TYPE_STR(bool) #undef ADD_TYPE_TO_TYPE_STR -/** @}*/ } // namespace math } // namespace stan #endif diff --git a/stan/math/prim/functor/for_each.hpp b/stan/math/prim/functor/for_each.hpp index 7e3c36ab315..230fce1df01 100644 --- a/stan/math/prim/functor/for_each.hpp +++ b/stan/math/prim/functor/for_each.hpp @@ -37,7 +37,8 @@ constexpr inline auto for_each(F&& f, T&& t) { * @tparam T1 tuple * @tparam Any container with an `operator[]` * @param f A functor to apply over each element of the tuple. - * @param t A tuple. + * @param t1 A tuple. + * @param t2 Any container with `operator[]`. */ template constexpr inline auto for_each(F&& f, T1&& t1, T2&& t2) { diff --git a/stan/math/rev/core/vari.hpp b/stan/math/rev/core/vari.hpp index 8858a2527e8..f33277780f0 100644 --- a/stan/math/rev/core/vari.hpp +++ b/stan/math/rev/core/vari.hpp @@ -16,7 +16,7 @@ class var_value; class vari_base { public: - virtual void chain() {} + virtual void chain() = 0 }; /** * The variable implementation base class. From caa55f489bc811b2d943b7e0edefdce936484763 Mon Sep 17 00:00:00 2001 From: Steve Bronder Date: Wed, 17 Jun 2020 15:05:47 -0400 Subject: [PATCH 091/355] Use trick from boost::hana on for_each to avoid unused-value warning --- stan/math/prim/functor/for_each.hpp | 21 +++++++++++++++++---- stan/math/rev/core/vari.hpp | 2 +- 2 files changed, 18 insertions(+), 5 deletions(-) diff --git a/stan/math/prim/functor/for_each.hpp b/stan/math/prim/functor/for_each.hpp index 3eda091ec87..7ee1d5e55a5 100644 --- a/stan/math/prim/functor/for_each.hpp +++ b/stan/math/prim/functor/for_each.hpp @@ -9,19 +9,32 @@ namespace stan { namespace math { namespace internal { +/** + * Implimentation of for_each. + * @note The static cast to void is used in boost::hana's for_each impl + * and is used to suppress unused value warnings from the compiler. + */ template constexpr inline auto for_each(F&& f, T&& t, std::index_sequence) { - std::initializer_list{ + using Swallow = int[]; + static_cast(Swallow{ (static_cast(std::forward(f)(std::get(std::forward(t)))), - 0)...}; + 0)...}); } + +/** + * Implimentation of Binary for_each. + * @note The static cast to void is used in boost::hana's for_each impl + * and is used to suppress unused value warnings from the compiler. + */ template constexpr inline auto for_each(F&& f, T1&& t1, T2&& t2, std::index_sequence) { - std::initializer_list{( + using Swallow = int[]; + static_cast(Swallow{( static_cast(std::forward(f)(std::get(std::forward(t1)), std::get(std::forward(t2)))), - 0)...}; + 0)...}); } } // namespace internal /** diff --git a/stan/math/rev/core/vari.hpp b/stan/math/rev/core/vari.hpp index f33277780f0..7cbca31440d 100644 --- a/stan/math/rev/core/vari.hpp +++ b/stan/math/rev/core/vari.hpp @@ -16,7 +16,7 @@ class var_value; class vari_base { public: - virtual void chain() = 0 + virtual void chain() {}; }; /** * The variable implementation base class. From 2d3648bd31fff2afaa59a73d5b4f74123f85ffb6 Mon Sep 17 00:00:00 2001 From: Stan Jenkins Date: Wed, 17 Jun 2020 15:06:38 -0400 Subject: [PATCH 092/355] [Jenkins] auto-formatting by clang-format version 6.0.0-1ubuntu2 (tags/RELEASE_600/final) --- stan/math/rev/core/vari.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stan/math/rev/core/vari.hpp b/stan/math/rev/core/vari.hpp index 7cbca31440d..b5928ec35e7 100644 --- a/stan/math/rev/core/vari.hpp +++ b/stan/math/rev/core/vari.hpp @@ -16,7 +16,7 @@ class var_value; class vari_base { public: - virtual void chain() {}; + virtual void chain(){}; }; /** * The variable implementation base class. From 52ddce42e87c8bdbdad6acd7f1360c30bb12b4d5 Mon Sep 17 00:00:00 2001 From: Steve Bronder Date: Wed, 17 Jun 2020 15:12:08 -0400 Subject: [PATCH 093/355] cpplint --- stan/math/rev/core/vari.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stan/math/rev/core/vari.hpp b/stan/math/rev/core/vari.hpp index 7cbca31440d..8858a2527e8 100644 --- a/stan/math/rev/core/vari.hpp +++ b/stan/math/rev/core/vari.hpp @@ -16,7 +16,7 @@ class var_value; class vari_base { public: - virtual void chain() {}; + virtual void chain() {} }; /** * The variable implementation base class. From b952d58c87d356a17ed154e48a58e9ff90861a53 Mon Sep 17 00:00:00 2001 From: Stan Jenkins Date: Wed, 17 Jun 2020 19:13:23 +0000 Subject: [PATCH 094/355] [Jenkins] auto-formatting by clang-format version 6.0.0-1ubuntu2~16.04.1 (tags/RELEASE_600/final) --- stan/math/rev/core/vari.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stan/math/rev/core/vari.hpp b/stan/math/rev/core/vari.hpp index 64d492e98d3..8858a2527e8 100644 --- a/stan/math/rev/core/vari.hpp +++ b/stan/math/rev/core/vari.hpp @@ -16,7 +16,7 @@ class var_value; class vari_base { public: - virtual void chain(){} + virtual void chain() {} }; /** * The variable implementation base class. From abf0a5eb80c9eac55130dae5d97315903449e242 Mon Sep 17 00:00:00 2001 From: Steve Bronder Date: Wed, 17 Jun 2020 15:59:23 -0400 Subject: [PATCH 095/355] update tests to use new zeroing vari stack instead of nochain --- stan/math/rev/core/var.hpp | 36 +++---------------- stan/math/rev/core/vari.hpp | 8 ++++- .../rev/core/thread_stack_instance_test.cpp | 4 +-- test/unit/math/rev/err/check_bounded_test.cpp | 8 ++--- .../rev/err/check_consistent_size_test.cpp | 4 +-- .../rev/err/check_consistent_sizes_test.cpp | 4 +-- test/unit/math/rev/err/check_finite_test.cpp | 12 +++---- .../rev/err/check_greater_or_equal_test.cpp | 12 +++---- test/unit/math/rev/err/check_greater_test.cpp | 12 +++---- .../math/rev/err/check_less_or_equal_test.cpp | 14 ++++---- test/unit/math/rev/err/check_less_test.cpp | 12 +++---- .../math/rev/err/check_nonnegative_test.cpp | 20 +++++------ test/unit/math/rev/err/check_not_nan_test.cpp | 16 ++++----- .../rev/err/check_pos_semidefinite_test.cpp | 4 +-- .../rev/err/check_positive_finite_test.cpp | 10 +++--- .../unit/math/rev/err/check_positive_test.cpp | 4 +-- 16 files changed, 80 insertions(+), 100 deletions(-) diff --git a/stan/math/rev/core/var.hpp b/stan/math/rev/core/var.hpp index c8001d28963..5688ef2833a 100644 --- a/stan/math/rev/core/var.hpp +++ b/stan/math/rev/core/var.hpp @@ -28,7 +28,7 @@ static void grad(Vari* vi); * and subtraction, as well as a range of mathematical functions * like exponentiation and powers are overridden to operate on * var values objects. - * @tparam T An Arithmetic type. + * @tparam T An Floating point type. */ template class var_value {}; @@ -36,16 +36,9 @@ class var_value {}; template class var_value> { public: - // The internal value_type is always a floating point type - using value_type = std::decay_t; - using vari_type = vari_value; + using value_type = std::decay_t; // Numeric type in vari_value + using vari_type = vari_value; // using vari_pointer = vari_type*; - template - using require_vari_convertible_t - = require_t*, vari_pointer>>; - template - using require_not_vari_convertible_t = require_t< - bool_constant*, vari_pointer>::value>>; /** * Pointer to the implementation of this variable. @@ -65,7 +58,7 @@ class var_value> { * @return true if this variable does not yet have * a defined variable. */ - bool is_uninitialized() { return (vi_ == static_cast(nullptr)); } + bool is_uninitialized() { return (vi_ == nullptr); } /** * Construct a variable for later assignment. @@ -74,7 +67,7 @@ class var_value> { * dangling. Before an assignment, the behavior is thus undefined just * as for a basic double. */ - var_value() : vi_(static_cast(nullptr)) {} + var_value() : vi_(nullptr) {} /** * Construct a variable from the specified arithmetic type argument @@ -89,22 +82,11 @@ class var_value> { /** * Construct a variable from a pointer to a variable implementation. - * @tparam S The type in the vari_value pointer that has the same `value_type` - * as this `var_value`. For integral types a `vari_value` is the - * same as `vari_value` so can be `reinterpret_cast` without a copy. * @param vi A vari_value pointer. */ var_value(vari_value* vi) // NOLINT : vi_(vi) {} - /** - * Constructor from `var_value` whose value_type is the same as this class's - * `value_type`. This is used in cases such as - * `var_value a(4.0); var_value b(a)` since the `value_type` for - * a `var_value` with an integral type is a double. - */ - var_value(const var_value& x) : vi_(x.vi_) {} // NOLINT - /** * Return a constant reference to the value of this variable. * @@ -197,7 +179,6 @@ class var_value> { * then (a += b) behaves exactly the same way as (a = a + b), * creating an intermediate variable representing (a + b). * - * @tparam S a type that is convertible to `value_type` * @param b The variable to add to this variable. * @return The result of adding the specified variable to this variable. */ @@ -210,7 +191,6 @@ class var_value> { * (a += b) behaves exactly the same way as (a = a + b). Note * that the result is an assignable lvalue. * - * @tparam Arith An arithmetic type * @param b The scalar to add to this variable. * @return The result of adding the specified variable to this variable. */ @@ -223,7 +203,6 @@ class var_value> { * then (a -= b) behaves exactly the same way as (a = a - b). * Note that the result is an assignable lvalue. * - * @tparam S a type that is convertible to `value_type` * @param b The variable to subtract from this variable. * @return The result of subtracting the specified variable from * this variable. @@ -237,7 +216,6 @@ class var_value> { * (a -= b) behaves exactly the same way as (a = a - b). Note * that the result is an assignable lvalue. * - * @tparam Arith An arithmetic type * @param b The scalar to subtract from this variable. * @return The result of subtracting the specified variable from this * variable. @@ -251,7 +229,6 @@ class var_value> { * then (a *= b) behaves exactly the same way as (a = a * b). * Note that the result is an assignable lvalue. * - * @tparam S a type that is convertible to `value_type` * @param b The variable to multiply this variable by. * @return The result of multiplying this variable by the * specified variable. @@ -265,7 +242,6 @@ class var_value> { * (a *= b) behaves exactly the same way as (a = a * b). Note * that the result is an assignable lvalue. * - * @tparam Arith An arithmetic type * @param b The scalar to multiply this variable by. * @return The result of multiplying this variable by the specified * variable. @@ -278,7 +254,6 @@ class var_value> { * behaves exactly the same way as (a = a / b). Note that the * result is an assignable lvalue. * - * @tparam S a type that is convertible to `value_type` * @param b The variable to divide this variable by. * @return The result of dividing this variable by the * specified variable. @@ -292,7 +267,6 @@ class var_value> { * (a /= b) behaves exactly the same way as (a = a / b). Note * that the result is an assignable lvalue. * - * @tparam Arith An arithmetic type * @param b The scalar to divide this variable by. * @return The result of dividing this variable by the specified * variable. diff --git a/stan/math/rev/core/vari.hpp b/stan/math/rev/core/vari.hpp index 64d492e98d3..4015a7fbfce 100644 --- a/stan/math/rev/core/vari.hpp +++ b/stan/math/rev/core/vari.hpp @@ -13,9 +13,15 @@ namespace math { // forward declaration of var template class var_value; - +/** + * Abstract base class that all `vari_value` and it's derived classes inherit. + */ class vari_base { public: + /** + * Apply the chain rule to this variable based on the variables + * on which it depends. + */ virtual void chain(){} }; /** diff --git a/test/unit/math/rev/core/thread_stack_instance_test.cpp b/test/unit/math/rev/core/thread_stack_instance_test.cpp index c47d4f0d2d6..17e20682246 100644 --- a/test/unit/math/rev/core/thread_stack_instance_test.cpp +++ b/test/unit/math/rev/core/thread_stack_instance_test.cpp @@ -93,14 +93,14 @@ TEST(thread_stack_instance, child_instances) { ChainableStack thread_instance; EXPECT_TRUE( main_ad_stack->var_stack_.size() - + stan::math::ChainableStack::instance_->var_nochain_stack_.size() + + std::get>(stan::math::ChainableStack::instance_->var_zeroing_stacks_).size() #ifdef STAN_THREADS > #else == #endif ChainableStack::instance_->var_stack_.size() - + stan::math::ChainableStack::instance_->var_nochain_stack_.size()); + + std::get>(stan::math::ChainableStack::instance_->var_zeroing_stacks_).size()); }; std::thread other_work(thread_tester); diff --git a/test/unit/math/rev/err/check_bounded_test.cpp b/test/unit/math/rev/err/check_bounded_test.cpp index 3f3e00455ce..d3fc2fb6bf6 100644 --- a/test/unit/math/rev/err/check_bounded_test.cpp +++ b/test/unit/math/rev/err/check_bounded_test.cpp @@ -17,14 +17,14 @@ TEST(AgradRevErrorHandlingScalar, CheckBoundedVarCheckVectorized) { size_t stack_size = stan::math::ChainableStack::instance_->var_stack_.size() - + stan::math::ChainableStack::instance_->var_nochain_stack_.size(); + + std::get>(stan::math::ChainableStack::instance_->var_zeroing_stacks_).size(); EXPECT_EQ(5U, stack_size); EXPECT_NO_THROW(check_bounded(function, "a", a, -1.0, 6.0)); size_t stack_size_after_call = stan::math::ChainableStack::instance_->var_stack_.size() - + stan::math::ChainableStack::instance_->var_nochain_stack_.size(); + + std::get>(stan::math::ChainableStack::instance_->var_zeroing_stacks_).size(); EXPECT_EQ(5U, stack_size_after_call); stan::math::recover_memory(); } @@ -150,14 +150,14 @@ TEST(AgradRevErrorHandlingScalar, CheckBoundedVarCheckUnivariate) { size_t stack_size = stan::math::ChainableStack::instance_->var_stack_.size() - + stan::math::ChainableStack::instance_->var_nochain_stack_.size(); + + std::get>(stan::math::ChainableStack::instance_->var_zeroing_stacks_).size(); EXPECT_EQ(1U, stack_size); EXPECT_NO_THROW(check_bounded(function, "a", a, 4.0, 6.0)); size_t stack_size_after_call = stan::math::ChainableStack::instance_->var_stack_.size() - + stan::math::ChainableStack::instance_->var_nochain_stack_.size(); + + std::get>(stan::math::ChainableStack::instance_->var_zeroing_stacks_).size(); EXPECT_EQ(1U, stack_size_after_call); stan::math::recover_memory(); diff --git a/test/unit/math/rev/err/check_consistent_size_test.cpp b/test/unit/math/rev/err/check_consistent_size_test.cpp index dabf63fdb3b..aaa6c70c74f 100644 --- a/test/unit/math/rev/err/check_consistent_size_test.cpp +++ b/test/unit/math/rev/err/check_consistent_size_test.cpp @@ -17,14 +17,14 @@ TEST(AgradRevErrorHandlingScalar, CheckConsistentSizeVarCheckVectorized) { size_t stack_size = stan::math::ChainableStack::instance_->var_stack_.size() - + stan::math::ChainableStack::instance_->var_nochain_stack_.size(); + + std::get>(stan::math::ChainableStack::instance_->var_zeroing_stacks_).size(); EXPECT_EQ(5U, stack_size); EXPECT_NO_THROW(check_consistent_size(function, "a", a, 5U)); size_t stack_size_after_call = stan::math::ChainableStack::instance_->var_stack_.size() - + stan::math::ChainableStack::instance_->var_nochain_stack_.size(); + + std::get>(stan::math::ChainableStack::instance_->var_zeroing_stacks_).size(); EXPECT_EQ(5U, stack_size_after_call); stan::math::recover_memory(); } diff --git a/test/unit/math/rev/err/check_consistent_sizes_test.cpp b/test/unit/math/rev/err/check_consistent_sizes_test.cpp index 26c87d413fa..fceb142762e 100644 --- a/test/unit/math/rev/err/check_consistent_sizes_test.cpp +++ b/test/unit/math/rev/err/check_consistent_sizes_test.cpp @@ -19,14 +19,14 @@ TEST(AgradRevErrorHandlingScalar, CheckConsistentSizesVarCheckVectorized) { size_t stack_size = stan::math::ChainableStack::instance_->var_stack_.size() - + stan::math::ChainableStack::instance_->var_nochain_stack_.size(); + + std::get>(stan::math::ChainableStack::instance_->var_zeroing_stacks_).size(); EXPECT_EQ(10U, stack_size); EXPECT_NO_THROW(check_consistent_sizes(function, "a", a, "b", b)); size_t stack_size_after_call = stan::math::ChainableStack::instance_->var_stack_.size() - + stan::math::ChainableStack::instance_->var_nochain_stack_.size(); + + std::get>(stan::math::ChainableStack::instance_->var_zeroing_stacks_).size(); EXPECT_EQ(10U, stack_size_after_call); stan::math::recover_memory(); } diff --git a/test/unit/math/rev/err/check_finite_test.cpp b/test/unit/math/rev/err/check_finite_test.cpp index 99a5ad41bd7..4d65b3f8132 100644 --- a/test/unit/math/rev/err/check_finite_test.cpp +++ b/test/unit/math/rev/err/check_finite_test.cpp @@ -17,21 +17,21 @@ TEST(AgradRevErrorHandlingScalar, CheckFiniteVarCheckVectorized) { size_t stack_size = stan::math::ChainableStack::instance_->var_stack_.size() - + stan::math::ChainableStack::instance_->var_nochain_stack_.size(); + + std::get>(stan::math::ChainableStack::instance_->var_zeroing_stacks_).size(); EXPECT_EQ(5U, stack_size); EXPECT_NO_THROW(check_finite(function, "a", a)); size_t stack_size_after_call = stan::math::ChainableStack::instance_->var_stack_.size() - + stan::math::ChainableStack::instance_->var_nochain_stack_.size(); + + std::get>(stan::math::ChainableStack::instance_->var_zeroing_stacks_).size(); EXPECT_EQ(5U, stack_size_after_call); a[1] = std::numeric_limits::infinity(); EXPECT_THROW(check_finite(function, "a", a), std::domain_error); stack_size_after_call = stan::math::ChainableStack::instance_->var_stack_.size() - + stan::math::ChainableStack::instance_->var_nochain_stack_.size(); + + std::get>(stan::math::ChainableStack::instance_->var_zeroing_stacks_).size(); EXPECT_EQ(6U, stack_size_after_call); stan::math::recover_memory(); @@ -71,21 +71,21 @@ TEST(AgradRevErrorHandlingScalar, CheckFiniteVarCheckUnivariate) { size_t stack_size = stan::math::ChainableStack::instance_->var_stack_.size() - + stan::math::ChainableStack::instance_->var_nochain_stack_.size(); + + std::get>(stan::math::ChainableStack::instance_->var_zeroing_stacks_).size(); EXPECT_EQ(1U, stack_size); EXPECT_NO_THROW(check_finite(function, "a", a)); size_t stack_size_after_call = stan::math::ChainableStack::instance_->var_stack_.size() - + stan::math::ChainableStack::instance_->var_nochain_stack_.size(); + + std::get>(stan::math::ChainableStack::instance_->var_zeroing_stacks_).size(); EXPECT_EQ(1U, stack_size_after_call); a = std::numeric_limits::infinity(); EXPECT_THROW(check_finite(function, "a", a), std::domain_error); stack_size_after_call = stan::math::ChainableStack::instance_->var_stack_.size() - + stan::math::ChainableStack::instance_->var_nochain_stack_.size(); + + std::get>(stan::math::ChainableStack::instance_->var_zeroing_stacks_).size(); EXPECT_EQ(2U, stack_size_after_call); stan::math::recover_memory(); diff --git a/test/unit/math/rev/err/check_greater_or_equal_test.cpp b/test/unit/math/rev/err/check_greater_or_equal_test.cpp index 24252646030..1f4f746b527 100644 --- a/test/unit/math/rev/err/check_greater_or_equal_test.cpp +++ b/test/unit/math/rev/err/check_greater_or_equal_test.cpp @@ -17,21 +17,21 @@ TEST(AgradRevErrorHandlingScalar, CheckGreateOrEqualVarCheckVectorized) { size_t stack_size = stan::math::ChainableStack::instance_->var_stack_.size() - + stan::math::ChainableStack::instance_->var_nochain_stack_.size(); + + std::get>(stan::math::ChainableStack::instance_->var_zeroing_stacks_).size(); EXPECT_EQ(5U, stack_size); EXPECT_NO_THROW(check_greater_or_equal(function, "a", a, -1.0)); size_t stack_size_after_call = stan::math::ChainableStack::instance_->var_stack_.size() - + stan::math::ChainableStack::instance_->var_nochain_stack_.size(); + + std::get>(stan::math::ChainableStack::instance_->var_zeroing_stacks_).size(); EXPECT_EQ(5U, stack_size_after_call); EXPECT_THROW(check_greater_or_equal(function, "a", a, 2.0), std::domain_error); stack_size_after_call = stan::math::ChainableStack::instance_->var_stack_.size() - + stan::math::ChainableStack::instance_->var_nochain_stack_.size(); + + std::get>(stan::math::ChainableStack::instance_->var_zeroing_stacks_).size(); EXPECT_EQ(5U, stack_size_after_call); stan::math::recover_memory(); @@ -198,21 +198,21 @@ TEST(AgradRevErrorHandlingScalar, CheckGreaterOrEqualVarCheckUnivariate) { size_t stack_size = stan::math::ChainableStack::instance_->var_stack_.size() - + stan::math::ChainableStack::instance_->var_nochain_stack_.size(); + + std::get>(stan::math::ChainableStack::instance_->var_zeroing_stacks_).size(); EXPECT_EQ(1U, stack_size); EXPECT_NO_THROW(check_greater_or_equal(function, "a", a, 2.0)); size_t stack_size_after_call = stan::math::ChainableStack::instance_->var_stack_.size() - + stan::math::ChainableStack::instance_->var_nochain_stack_.size(); + + std::get>(stan::math::ChainableStack::instance_->var_zeroing_stacks_).size(); EXPECT_EQ(1U, stack_size_after_call); EXPECT_THROW(check_greater_or_equal(function, "a", a, 10.0), std::domain_error); stack_size_after_call = stan::math::ChainableStack::instance_->var_stack_.size() - + stan::math::ChainableStack::instance_->var_nochain_stack_.size(); + + std::get>(stan::math::ChainableStack::instance_->var_zeroing_stacks_).size(); EXPECT_EQ(1U, stack_size_after_call); stan::math::recover_memory(); diff --git a/test/unit/math/rev/err/check_greater_test.cpp b/test/unit/math/rev/err/check_greater_test.cpp index 1da58eeb7ae..933cef600b4 100644 --- a/test/unit/math/rev/err/check_greater_test.cpp +++ b/test/unit/math/rev/err/check_greater_test.cpp @@ -16,20 +16,20 @@ TEST(AgradRevErrorHandlingScalar, CheckGreaterVarCheckVectorized) { size_t stack_size = stan::math::ChainableStack::instance_->var_stack_.size() - + stan::math::ChainableStack::instance_->var_nochain_stack_.size(); + + std::get>(stan::math::ChainableStack::instance_->var_zeroing_stacks_).size(); EXPECT_EQ(5U, stack_size); EXPECT_NO_THROW(check_greater(function, "a", a, -1.0)); size_t stack_size_after_call = stan::math::ChainableStack::instance_->var_stack_.size() - + stan::math::ChainableStack::instance_->var_nochain_stack_.size(); + + std::get>(stan::math::ChainableStack::instance_->var_zeroing_stacks_).size(); EXPECT_EQ(5U, stack_size_after_call); EXPECT_THROW(check_greater(function, "a", a, 2.0), std::domain_error); stack_size_after_call = stan::math::ChainableStack::instance_->var_stack_.size() - + stan::math::ChainableStack::instance_->var_nochain_stack_.size(); + + std::get>(stan::math::ChainableStack::instance_->var_zeroing_stacks_).size(); EXPECT_EQ(5U, stack_size_after_call); stan::math::recover_memory(); @@ -188,20 +188,20 @@ TEST(AgradRevErrorHandlingScalar, CheckGreaterVarCheckUnivariate) { size_t stack_size = stan::math::ChainableStack::instance_->var_stack_.size() - + stan::math::ChainableStack::instance_->var_nochain_stack_.size(); + + std::get>(stan::math::ChainableStack::instance_->var_zeroing_stacks_).size(); EXPECT_EQ(1U, stack_size); EXPECT_NO_THROW(check_greater(function, "a", a, 2.0)); size_t stack_size_after_call = stan::math::ChainableStack::instance_->var_stack_.size() - + stan::math::ChainableStack::instance_->var_nochain_stack_.size(); + + std::get>(stan::math::ChainableStack::instance_->var_zeroing_stacks_).size(); EXPECT_EQ(1U, stack_size_after_call); EXPECT_THROW(check_greater(function, "a", a, 10.0), std::domain_error); stack_size_after_call = stan::math::ChainableStack::instance_->var_stack_.size() - + stan::math::ChainableStack::instance_->var_nochain_stack_.size(); + + std::get>(stan::math::ChainableStack::instance_->var_zeroing_stacks_).size(); EXPECT_EQ(1U, stack_size_after_call); stan::math::recover_memory(); diff --git a/test/unit/math/rev/err/check_less_or_equal_test.cpp b/test/unit/math/rev/err/check_less_or_equal_test.cpp index bf63756ff02..fe96da18b5c 100644 --- a/test/unit/math/rev/err/check_less_or_equal_test.cpp +++ b/test/unit/math/rev/err/check_less_or_equal_test.cpp @@ -16,20 +16,20 @@ TEST(AgradRevErrorHandlingScalar, CheckLessOrEqualVarCheckVectorized) { size_t stack_size = stan::math::ChainableStack::instance_->var_stack_.size() - + stan::math::ChainableStack::instance_->var_nochain_stack_.size(); + + std::get>(stan::math::ChainableStack::instance_->var_zeroing_stacks_).size(); EXPECT_EQ(5U, stack_size); EXPECT_NO_THROW(check_less_or_equal(function, "a", a, 10.0)); size_t stack_size_after_call = stan::math::ChainableStack::instance_->var_stack_.size() - + stan::math::ChainableStack::instance_->var_nochain_stack_.size(); + + std::get>(stan::math::ChainableStack::instance_->var_zeroing_stacks_).size(); EXPECT_EQ(5U, stack_size_after_call); EXPECT_THROW(check_less_or_equal(function, "a", a, 2.0), std::domain_error); stack_size_after_call = stan::math::ChainableStack::instance_->var_stack_.size() - + stan::math::ChainableStack::instance_->var_nochain_stack_.size(); + + std::get>(stan::math::ChainableStack::instance_->var_zeroing_stacks_).size(); EXPECT_EQ(5U, stack_size_after_call); stan::math::recover_memory(); @@ -161,27 +161,27 @@ TEST(AgradRevErrorHandlingScalar, CheckLessOrEqualVarCheckUnivariate) { size_t stack_size = stan::math::ChainableStack::instance_->var_stack_.size() - + stan::math::ChainableStack::instance_->var_nochain_stack_.size(); + + std::get>(stan::math::ChainableStack::instance_->var_zeroing_stacks_).size(); EXPECT_EQ(1U, stack_size); EXPECT_THROW(check_less_or_equal(function, "a", a, 2.0), std::domain_error); size_t stack_size_after_call = stan::math::ChainableStack::instance_->var_stack_.size() - + stan::math::ChainableStack::instance_->var_nochain_stack_.size(); + + std::get>(stan::math::ChainableStack::instance_->var_zeroing_stacks_).size(); EXPECT_EQ(1U, stack_size_after_call); EXPECT_NO_THROW(check_less_or_equal(function, "a", a, 5.0)); stack_size_after_call = stan::math::ChainableStack::instance_->var_stack_.size() - + stan::math::ChainableStack::instance_->var_nochain_stack_.size(); + + std::get>(stan::math::ChainableStack::instance_->var_zeroing_stacks_).size(); EXPECT_EQ(1U, stack_size_after_call); EXPECT_NO_THROW(check_less_or_equal(function, "a", a, 10.0)); stack_size_after_call = stan::math::ChainableStack::instance_->var_stack_.size() - + stan::math::ChainableStack::instance_->var_nochain_stack_.size(); + + std::get>(stan::math::ChainableStack::instance_->var_zeroing_stacks_).size(); EXPECT_EQ(1U, stack_size_after_call); stan::math::recover_memory(); diff --git a/test/unit/math/rev/err/check_less_test.cpp b/test/unit/math/rev/err/check_less_test.cpp index 241d328b619..c30a694534c 100644 --- a/test/unit/math/rev/err/check_less_test.cpp +++ b/test/unit/math/rev/err/check_less_test.cpp @@ -16,20 +16,20 @@ TEST(AgradRevErrorHandlingScalar, CheckLessVarCheckVectorized) { size_t stack_size = stan::math::ChainableStack::instance_->var_stack_.size() - + stan::math::ChainableStack::instance_->var_nochain_stack_.size(); + + std::get>(stan::math::ChainableStack::instance_->var_zeroing_stacks_).size(); EXPECT_EQ(5U, stack_size); EXPECT_NO_THROW(check_less(function, "a", a, 10.0)); size_t stack_size_after_call = stan::math::ChainableStack::instance_->var_stack_.size() - + stan::math::ChainableStack::instance_->var_nochain_stack_.size(); + + std::get>(stan::math::ChainableStack::instance_->var_zeroing_stacks_).size(); EXPECT_EQ(5U, stack_size_after_call); EXPECT_THROW(check_less(function, "a", a, 2.0), std::domain_error); stack_size_after_call = stan::math::ChainableStack::instance_->var_stack_.size() - + stan::math::ChainableStack::instance_->var_nochain_stack_.size(); + + std::get>(stan::math::ChainableStack::instance_->var_zeroing_stacks_).size(); EXPECT_EQ(5U, stack_size_after_call); stan::math::recover_memory(); @@ -158,20 +158,20 @@ TEST(AgradRevErrorHandlingScalar, CheckLessVarCheckUnivariate) { size_t stack_size = stan::math::ChainableStack::instance_->var_stack_.size() - + stan::math::ChainableStack::instance_->var_nochain_stack_.size(); + + std::get>(stan::math::ChainableStack::instance_->var_zeroing_stacks_).size(); EXPECT_EQ(1U, stack_size); EXPECT_THROW(check_less(function, "a", a, 2.0), std::domain_error); size_t stack_size_after_call = stan::math::ChainableStack::instance_->var_stack_.size() - + stan::math::ChainableStack::instance_->var_nochain_stack_.size(); + + std::get>(stan::math::ChainableStack::instance_->var_zeroing_stacks_).size(); EXPECT_EQ(1U, stack_size_after_call); EXPECT_NO_THROW(check_less(function, "a", a, 10.0)); stack_size_after_call = stan::math::ChainableStack::instance_->var_stack_.size() - + stan::math::ChainableStack::instance_->var_nochain_stack_.size(); + + std::get>(stan::math::ChainableStack::instance_->var_zeroing_stacks_).size(); EXPECT_EQ(1U, stack_size_after_call); stan::math::recover_memory(); diff --git a/test/unit/math/rev/err/check_nonnegative_test.cpp b/test/unit/math/rev/err/check_nonnegative_test.cpp index 93113b8e186..6d2bafb4991 100644 --- a/test/unit/math/rev/err/check_nonnegative_test.cpp +++ b/test/unit/math/rev/err/check_nonnegative_test.cpp @@ -48,35 +48,35 @@ TEST(AgradRevErrorHandlingScalar, CheckNonnegativeVarCheckVectorized) { size_t stack_size = stan::math::ChainableStack::instance_->var_stack_.size() - + stan::math::ChainableStack::instance_->var_nochain_stack_.size(); + + std::get>(stan::math::ChainableStack::instance_->var_zeroing_stacks_).size(); EXPECT_EQ(5U, stack_size); EXPECT_NO_THROW(check_nonnegative(function, "a", a)); size_t stack_size_after_call = stan::math::ChainableStack::instance_->var_stack_.size() - + stan::math::ChainableStack::instance_->var_nochain_stack_.size(); + + std::get>(stan::math::ChainableStack::instance_->var_zeroing_stacks_).size(); EXPECT_EQ(5U, stack_size_after_call); a[1] = std::numeric_limits::infinity(); EXPECT_NO_THROW(check_nonnegative(function, "a", a)); stack_size_after_call = stan::math::ChainableStack::instance_->var_stack_.size() - + stan::math::ChainableStack::instance_->var_nochain_stack_.size(); + + std::get>(stan::math::ChainableStack::instance_->var_zeroing_stacks_).size(); EXPECT_EQ(6U, stack_size_after_call); a[1] = -1.0; EXPECT_THROW(check_nonnegative(function, "a", a), std::domain_error); stack_size_after_call = stan::math::ChainableStack::instance_->var_stack_.size() - + stan::math::ChainableStack::instance_->var_nochain_stack_.size(); + + std::get>(stan::math::ChainableStack::instance_->var_zeroing_stacks_).size(); EXPECT_EQ(7U, stack_size_after_call); a[1] = 0.0; EXPECT_NO_THROW(check_nonnegative(function, "a", a)); stack_size_after_call = stan::math::ChainableStack::instance_->var_stack_.size() - + stan::math::ChainableStack::instance_->var_nochain_stack_.size(); + + std::get>(stan::math::ChainableStack::instance_->var_zeroing_stacks_).size(); EXPECT_EQ(8U, stack_size_after_call); stan::math::recover_memory(); @@ -116,35 +116,35 @@ TEST(AgradRevErrorHandlingScalar, CheckNonnegativeVarCheckUnivariate) { size_t stack_size = stan::math::ChainableStack::instance_->var_stack_.size() - + stan::math::ChainableStack::instance_->var_nochain_stack_.size(); + + std::get>(stan::math::ChainableStack::instance_->var_zeroing_stacks_).size(); EXPECT_EQ(1U, stack_size); EXPECT_NO_THROW(check_nonnegative(function, "a", a)); size_t stack_size_after_call = stan::math::ChainableStack::instance_->var_stack_.size() - + stan::math::ChainableStack::instance_->var_nochain_stack_.size(); + + std::get>(stan::math::ChainableStack::instance_->var_zeroing_stacks_).size(); EXPECT_EQ(1U, stack_size_after_call); a = std::numeric_limits::infinity(); EXPECT_NO_THROW(check_nonnegative(function, "a", a)); stack_size_after_call = stan::math::ChainableStack::instance_->var_stack_.size() - + stan::math::ChainableStack::instance_->var_nochain_stack_.size(); + + std::get>(stan::math::ChainableStack::instance_->var_zeroing_stacks_).size(); EXPECT_EQ(2U, stack_size_after_call); a = 0.0; EXPECT_NO_THROW(check_nonnegative(function, "a", a)); stack_size_after_call = stan::math::ChainableStack::instance_->var_stack_.size() - + stan::math::ChainableStack::instance_->var_nochain_stack_.size(); + + std::get>(stan::math::ChainableStack::instance_->var_zeroing_stacks_).size(); EXPECT_EQ(3U, stack_size_after_call); a = -1.1; EXPECT_THROW(check_nonnegative(function, "a", a), std::domain_error); stack_size_after_call = stan::math::ChainableStack::instance_->var_stack_.size() - + stan::math::ChainableStack::instance_->var_nochain_stack_.size(); + + std::get>(stan::math::ChainableStack::instance_->var_zeroing_stacks_).size(); EXPECT_EQ(4U, stack_size_after_call); stan::math::recover_memory(); } diff --git a/test/unit/math/rev/err/check_not_nan_test.cpp b/test/unit/math/rev/err/check_not_nan_test.cpp index 820cf12b540..9d29b698126 100644 --- a/test/unit/math/rev/err/check_not_nan_test.cpp +++ b/test/unit/math/rev/err/check_not_nan_test.cpp @@ -16,14 +16,14 @@ TEST(AgradRevErrorHandlingScalar, CheckNotNanVarCheckVectorized) { size_t stack_size = stan::math::ChainableStack::instance_->var_stack_.size() - + stan::math::ChainableStack::instance_->var_nochain_stack_.size(); + + std::get>(stan::math::ChainableStack::instance_->var_zeroing_stacks_).size(); EXPECT_EQ(5U, stack_size); EXPECT_NO_THROW(check_not_nan(function, "a", a)); size_t stack_size_after_call = stan::math::ChainableStack::instance_->var_stack_.size() - + stan::math::ChainableStack::instance_->var_nochain_stack_.size(); + + std::get>(stan::math::ChainableStack::instance_->var_zeroing_stacks_).size(); EXPECT_EQ(5U, stack_size_after_call); stan::math::recover_memory(); } @@ -41,14 +41,14 @@ TEST(ErrorHandlingScalar, CheckNotNanVarCheckVectorized) { size_t stack_size = stan::math::ChainableStack::instance_->var_stack_.size() - + stan::math::ChainableStack::instance_->var_nochain_stack_.size(); + + std::get>(stan::math::ChainableStack::instance_->var_zeroing_stacks_).size(); EXPECT_EQ(5U, stack_size); EXPECT_NO_THROW(check_not_nan(function, "a", a)); size_t stack_size_after_call = stan::math::ChainableStack::instance_->var_stack_.size() - + stan::math::ChainableStack::instance_->var_nochain_stack_.size(); + + std::get>(stan::math::ChainableStack::instance_->var_zeroing_stacks_).size(); EXPECT_EQ(5U, stack_size_after_call); stan::math::recover_memory(); } @@ -98,14 +98,14 @@ TEST(AgradRevErrorHandlingScalar, CheckNotNanVarCheckUnivariate) { size_t stack_size = stan::math::ChainableStack::instance_->var_stack_.size() - + stan::math::ChainableStack::instance_->var_nochain_stack_.size(); + + std::get>(stan::math::ChainableStack::instance_->var_zeroing_stacks_).size(); EXPECT_EQ(1U, stack_size); EXPECT_NO_THROW(check_not_nan(function, "a", a)); size_t stack_size_after_call = stan::math::ChainableStack::instance_->var_stack_.size() - + stan::math::ChainableStack::instance_->var_nochain_stack_.size(); + + std::get>(stan::math::ChainableStack::instance_->var_zeroing_stacks_).size(); EXPECT_EQ(1U, stack_size_after_call); stan::math::recover_memory(); @@ -120,14 +120,14 @@ TEST(ErrorHandlingScalar, CheckNotNanVarCheckUnivariate) { size_t stack_size = stan::math::ChainableStack::instance_->var_stack_.size() - + stan::math::ChainableStack::instance_->var_nochain_stack_.size(); + + std::get>(stan::math::ChainableStack::instance_->var_zeroing_stacks_).size(); EXPECT_EQ(1U, stack_size); EXPECT_NO_THROW(check_not_nan(function, "a", a)); size_t stack_size_after_call = stan::math::ChainableStack::instance_->var_stack_.size() - + stan::math::ChainableStack::instance_->var_nochain_stack_.size(); + + std::get>(stan::math::ChainableStack::instance_->var_zeroing_stacks_).size(); EXPECT_EQ(1U, stack_size_after_call); stan::math::recover_memory(); diff --git a/test/unit/math/rev/err/check_pos_semidefinite_test.cpp b/test/unit/math/rev/err/check_pos_semidefinite_test.cpp index b384b023483..b4666582fcd 100644 --- a/test/unit/math/rev/err/check_pos_semidefinite_test.cpp +++ b/test/unit/math/rev/err/check_pos_semidefinite_test.cpp @@ -50,13 +50,13 @@ TEST(AgradRevErrorHandlingMatrix, checkPosSemiDefiniteMatrixVarCheck) { size_t stack_before_call = stan::math::ChainableStack::instance_->var_stack_.size() - + stan::math::ChainableStack::instance_->var_nochain_stack_.size(); + + std::get>(stan::math::ChainableStack::instance_->var_zeroing_stacks_).size(); EXPECT_EQ(9U, stack_before_call); EXPECT_NO_THROW(check_pos_semidefinite("checkPosDefiniteMatrix", "y", y)); size_t stack_after_call = stan::math::ChainableStack::instance_->var_stack_.size() - + stan::math::ChainableStack::instance_->var_nochain_stack_.size(); + + std::get>(stan::math::ChainableStack::instance_->var_zeroing_stacks_).size(); EXPECT_EQ(9U, stack_after_call); } diff --git a/test/unit/math/rev/err/check_positive_finite_test.cpp b/test/unit/math/rev/err/check_positive_finite_test.cpp index e8fb8af1a92..0e63eb4ca49 100644 --- a/test/unit/math/rev/err/check_positive_finite_test.cpp +++ b/test/unit/math/rev/err/check_positive_finite_test.cpp @@ -67,7 +67,7 @@ TEST(AgradRevErrorHandlingScalar, CheckPositiveFiniteVarCheckVectorized) { size_t stack_size = stan::math::ChainableStack::instance_->var_stack_.size() - + stan::math::ChainableStack::instance_->var_nochain_stack_.size(); + + std::get>(stan::math::ChainableStack::instance_->var_zeroing_stacks_).size(); EXPECT_EQ(5U, stack_size); EXPECT_THROW(check_positive_finite(function, "a", a), std::domain_error); @@ -75,14 +75,14 @@ TEST(AgradRevErrorHandlingScalar, CheckPositiveFiniteVarCheckVectorized) { size_t stack_size_after_call = stan::math::ChainableStack::instance_->var_stack_.size() - + stan::math::ChainableStack::instance_->var_nochain_stack_.size(); + + std::get>(stan::math::ChainableStack::instance_->var_zeroing_stacks_).size(); EXPECT_EQ(5U, stack_size_after_call); a[2] = std::numeric_limits::infinity(); EXPECT_THROW(check_positive_finite(function, "a", a), std::domain_error); stack_size_after_call = stan::math::ChainableStack::instance_->var_stack_.size() - + stan::math::ChainableStack::instance_->var_nochain_stack_.size(); + + std::get>(stan::math::ChainableStack::instance_->var_zeroing_stacks_).size(); EXPECT_EQ(6U, stack_size_after_call); stan::math::recover_memory(); } @@ -163,14 +163,14 @@ TEST(AgradRevErrorHandlingScalar, CheckPositiveFiniteVarCheckUnivariate) { size_t stack_size = stan::math::ChainableStack::instance_->var_stack_.size() - + stan::math::ChainableStack::instance_->var_nochain_stack_.size(); + + std::get>(stan::math::ChainableStack::instance_->var_zeroing_stacks_).size(); EXPECT_EQ(1U, stack_size); EXPECT_NO_THROW(check_positive_finite(function, "a", a)); size_t stack_size_after_call = stan::math::ChainableStack::instance_->var_stack_.size() - + stan::math::ChainableStack::instance_->var_nochain_stack_.size(); + + std::get>(stan::math::ChainableStack::instance_->var_zeroing_stacks_).size(); EXPECT_EQ(1U, stack_size_after_call); stan::math::recover_memory(); diff --git a/test/unit/math/rev/err/check_positive_test.cpp b/test/unit/math/rev/err/check_positive_test.cpp index dee6535363f..2b4ed43f15f 100644 --- a/test/unit/math/rev/err/check_positive_test.cpp +++ b/test/unit/math/rev/err/check_positive_test.cpp @@ -60,14 +60,14 @@ TEST(AgradRevErrorHandlingScalar, CheckPositiveVarCheckUnivariate) { size_t stack_size = stan::math::ChainableStack::instance_->var_stack_.size() - + stan::math::ChainableStack::instance_->var_nochain_stack_.size(); + + std::get>(stan::math::ChainableStack::instance_->var_zeroing_stacks_).size(); EXPECT_EQ(1U, stack_size); EXPECT_NO_THROW(check_positive(function, "a", a)); size_t stack_size_after_call = stan::math::ChainableStack::instance_->var_stack_.size() - + stan::math::ChainableStack::instance_->var_nochain_stack_.size(); + + std::get>(stan::math::ChainableStack::instance_->var_zeroing_stacks_).size(); EXPECT_EQ(1U, stack_size_after_call); stan::math::recover_memory(); From 4674b1de315adc68ce0ff4915e1da97845713c89 Mon Sep 17 00:00:00 2001 From: Steve Bronder Date: Wed, 17 Jun 2020 16:20:09 -0400 Subject: [PATCH 096/355] update docs for var and vari --- stan/math/rev/core/var.hpp | 8 ++++---- stan/math/rev/core/vari.hpp | 24 +++++++++++++----------- 2 files changed, 17 insertions(+), 15 deletions(-) diff --git a/stan/math/rev/core/var.hpp b/stan/math/rev/core/var.hpp index 5688ef2833a..629ca0ca7b7 100644 --- a/stan/math/rev/core/var.hpp +++ b/stan/math/rev/core/var.hpp @@ -24,7 +24,7 @@ static void grad(Vari* vi); * calculation. * * A var is constructed with a type `T` and used like any - * other scalar. Arithmetical functions like negation, addition, + * other scalar. Arithmetical functions like negation, addition, * and subtraction, as well as a range of mathematical functions * like exponentiation and powers are overridden to operate on * var values objects. @@ -36,9 +36,9 @@ class var_value {}; template class var_value> { public: - using value_type = std::decay_t; // Numeric type in vari_value - using vari_type = vari_value; // - using vari_pointer = vari_type*; + using value_type = std::decay_t; // Numeric type in vari_value. + using vari_type = vari_value; // Type of underlying vari impl. + using vari_pointer = vari_type*; // pointer type for underlying vari. /** * Pointer to the implementation of this variable. diff --git a/stan/math/rev/core/vari.hpp b/stan/math/rev/core/vari.hpp index 7f66cd39c99..f555175fa95 100644 --- a/stan/math/rev/core/vari.hpp +++ b/stan/math/rev/core/vari.hpp @@ -15,6 +15,12 @@ template class var_value; /** * Abstract base class that all `vari_value` and it's derived classes inherit. + * + * The chain() method applies the chain rule. Concrete extensions + * of this class will represent base variables or the result + * of operations such as addition or subtraction. These extended + * classes will store operand variables and propagate derivative + * information via an implementation of chain(). */ class vari_base { public: @@ -23,6 +29,7 @@ class vari_base { * on which it depends. */ virtual void chain(){} + virtual ~vari_base {} }; /** * The variable implementation base class. @@ -34,11 +41,6 @@ class vari_base { * value. It also stores the adjoint for storing the partial * derivative with respect to the root of the derivative tree. * - * The chain() method applies the chain rule. Concrete extensions - * of this class will represent base variables or the result - * of operations such as addition or subtraction. These extended - * classes will store operand variables and propagate derivative - * information via an implementation of chain(). */ template class vari_value; @@ -73,7 +75,7 @@ class vari_value::value>> * derivative propagation, the chain() method of each variable * will be called in the reverse order of construction. * - * @tparam S an Arithmetic type. + * @tparam S a floating point type. * @param x Value of the constructed variable. */ template ::value>> /** * Construct a variable implementation from a value. The * adjoint is initialized to zero and if `stacked` is `false` this vari - * will be moved to the nochain stack s.t. it's chain method will not be - * called when calling `grad()`. + * will be not be put on the var_stack. Instead it will only be put on + * a stack to keep track of whether the adjoint needs to be set to zero. * - * All constructed variables are added to the stack. Variables + * All constructed variables are added to a stack. Variables * should be constructed before variables on which they depend * to insure proper partial derivative propagation. During * derivative propagation, the chain() method of each variable * will be called in the reverse order of construction. * - * @tparam S an Arithmetic type. + * @tparam S n floating point type. * @param x Value of the constructed variable. * @param stacked If false will put this this vari on the nochain stack so * that its `chain()` method is not called. @@ -115,7 +117,7 @@ class vari_value::value>> /** * Constructor from vari_value - * @tparam S An arithmetic type + * @tparam S A floating point type * @param x A vari_value */ vari_value(const vari_value& x) noexcept : val_(x.val_), adj_(x.adj_) { From 64de92c694109d0d25566c9021d4cbea2186aac5 Mon Sep 17 00:00:00 2001 From: Stan Jenkins Date: Wed, 17 Jun 2020 20:26:00 +0000 Subject: [PATCH 097/355] [Jenkins] auto-formatting by clang-format version 6.0.0-1ubuntu2~16.04.1 (tags/RELEASE_600/final) --- stan/math/rev/core/var.hpp | 6 +-- stan/math/rev/core/vari.hpp | 11 +++-- .../rev/core/thread_stack_instance_test.cpp | 8 +++- test/unit/math/rev/err/check_bounded_test.cpp | 16 ++++++-- .../rev/err/check_consistent_size_test.cpp | 8 +++- .../rev/err/check_consistent_sizes_test.cpp | 8 +++- test/unit/math/rev/err/check_finite_test.cpp | 24 ++++++++--- .../rev/err/check_greater_or_equal_test.cpp | 24 ++++++++--- test/unit/math/rev/err/check_greater_test.cpp | 24 ++++++++--- .../math/rev/err/check_less_or_equal_test.cpp | 28 +++++++++---- test/unit/math/rev/err/check_less_test.cpp | 24 ++++++++--- .../math/rev/err/check_nonnegative_test.cpp | 40 ++++++++++++++----- test/unit/math/rev/err/check_not_nan_test.cpp | 32 +++++++++++---- .../rev/err/check_pos_semidefinite_test.cpp | 8 +++- .../rev/err/check_positive_finite_test.cpp | 20 +++++++--- .../unit/math/rev/err/check_positive_test.cpp | 8 +++- 16 files changed, 212 insertions(+), 77 deletions(-) diff --git a/stan/math/rev/core/var.hpp b/stan/math/rev/core/var.hpp index 629ca0ca7b7..f0a18a78fb3 100644 --- a/stan/math/rev/core/var.hpp +++ b/stan/math/rev/core/var.hpp @@ -36,9 +36,9 @@ class var_value {}; template class var_value> { public: - using value_type = std::decay_t; // Numeric type in vari_value. - using vari_type = vari_value; // Type of underlying vari impl. - using vari_pointer = vari_type*; // pointer type for underlying vari. + using value_type = std::decay_t; // Numeric type in vari_value. + using vari_type = vari_value; // Type of underlying vari impl. + using vari_pointer = vari_type*; // pointer type for underlying vari. /** * Pointer to the implementation of this variable. diff --git a/stan/math/rev/core/vari.hpp b/stan/math/rev/core/vari.hpp index f555175fa95..961d55f98b0 100644 --- a/stan/math/rev/core/vari.hpp +++ b/stan/math/rev/core/vari.hpp @@ -24,11 +24,11 @@ class var_value; */ class vari_base { public: - /** - * Apply the chain rule to this variable based on the variables - * on which it depends. - */ - virtual void chain(){} + /** + * Apply the chain rule to this variable based on the variables + * on which it depends. + */ + virtual void chain() {} virtual ~vari_base {} }; /** @@ -127,7 +127,6 @@ class vari_value::value>> ChainableStack::instance_->var_stack_.emplace_back(this); } - /** * Initialize the adjoint for this (dependent) variable to 1. * This operation is applied to the dependent variable before diff --git a/test/unit/math/rev/core/thread_stack_instance_test.cpp b/test/unit/math/rev/core/thread_stack_instance_test.cpp index 17e20682246..ce610781d15 100644 --- a/test/unit/math/rev/core/thread_stack_instance_test.cpp +++ b/test/unit/math/rev/core/thread_stack_instance_test.cpp @@ -93,14 +93,18 @@ TEST(thread_stack_instance, child_instances) { ChainableStack thread_instance; EXPECT_TRUE( main_ad_stack->var_stack_.size() - + std::get>(stan::math::ChainableStack::instance_->var_zeroing_stacks_).size() + + std::get>( + stan::math::ChainableStack::instance_->var_zeroing_stacks_) + .size() #ifdef STAN_THREADS > #else == #endif ChainableStack::instance_->var_stack_.size() - + std::get>(stan::math::ChainableStack::instance_->var_zeroing_stacks_).size()); + + std::get>( + stan::math::ChainableStack::instance_->var_zeroing_stacks_) + .size()); }; std::thread other_work(thread_tester); diff --git a/test/unit/math/rev/err/check_bounded_test.cpp b/test/unit/math/rev/err/check_bounded_test.cpp index d3fc2fb6bf6..c9fcb02b82a 100644 --- a/test/unit/math/rev/err/check_bounded_test.cpp +++ b/test/unit/math/rev/err/check_bounded_test.cpp @@ -17,14 +17,18 @@ TEST(AgradRevErrorHandlingScalar, CheckBoundedVarCheckVectorized) { size_t stack_size = stan::math::ChainableStack::instance_->var_stack_.size() - + std::get>(stan::math::ChainableStack::instance_->var_zeroing_stacks_).size(); + + std::get>( + stan::math::ChainableStack::instance_->var_zeroing_stacks_) + .size(); EXPECT_EQ(5U, stack_size); EXPECT_NO_THROW(check_bounded(function, "a", a, -1.0, 6.0)); size_t stack_size_after_call = stan::math::ChainableStack::instance_->var_stack_.size() - + std::get>(stan::math::ChainableStack::instance_->var_zeroing_stacks_).size(); + + std::get>( + stan::math::ChainableStack::instance_->var_zeroing_stacks_) + .size(); EXPECT_EQ(5U, stack_size_after_call); stan::math::recover_memory(); } @@ -150,14 +154,18 @@ TEST(AgradRevErrorHandlingScalar, CheckBoundedVarCheckUnivariate) { size_t stack_size = stan::math::ChainableStack::instance_->var_stack_.size() - + std::get>(stan::math::ChainableStack::instance_->var_zeroing_stacks_).size(); + + std::get>( + stan::math::ChainableStack::instance_->var_zeroing_stacks_) + .size(); EXPECT_EQ(1U, stack_size); EXPECT_NO_THROW(check_bounded(function, "a", a, 4.0, 6.0)); size_t stack_size_after_call = stan::math::ChainableStack::instance_->var_stack_.size() - + std::get>(stan::math::ChainableStack::instance_->var_zeroing_stacks_).size(); + + std::get>( + stan::math::ChainableStack::instance_->var_zeroing_stacks_) + .size(); EXPECT_EQ(1U, stack_size_after_call); stan::math::recover_memory(); diff --git a/test/unit/math/rev/err/check_consistent_size_test.cpp b/test/unit/math/rev/err/check_consistent_size_test.cpp index aaa6c70c74f..4f613901d48 100644 --- a/test/unit/math/rev/err/check_consistent_size_test.cpp +++ b/test/unit/math/rev/err/check_consistent_size_test.cpp @@ -17,14 +17,18 @@ TEST(AgradRevErrorHandlingScalar, CheckConsistentSizeVarCheckVectorized) { size_t stack_size = stan::math::ChainableStack::instance_->var_stack_.size() - + std::get>(stan::math::ChainableStack::instance_->var_zeroing_stacks_).size(); + + std::get>( + stan::math::ChainableStack::instance_->var_zeroing_stacks_) + .size(); EXPECT_EQ(5U, stack_size); EXPECT_NO_THROW(check_consistent_size(function, "a", a, 5U)); size_t stack_size_after_call = stan::math::ChainableStack::instance_->var_stack_.size() - + std::get>(stan::math::ChainableStack::instance_->var_zeroing_stacks_).size(); + + std::get>( + stan::math::ChainableStack::instance_->var_zeroing_stacks_) + .size(); EXPECT_EQ(5U, stack_size_after_call); stan::math::recover_memory(); } diff --git a/test/unit/math/rev/err/check_consistent_sizes_test.cpp b/test/unit/math/rev/err/check_consistent_sizes_test.cpp index fceb142762e..e2e6be8656a 100644 --- a/test/unit/math/rev/err/check_consistent_sizes_test.cpp +++ b/test/unit/math/rev/err/check_consistent_sizes_test.cpp @@ -19,14 +19,18 @@ TEST(AgradRevErrorHandlingScalar, CheckConsistentSizesVarCheckVectorized) { size_t stack_size = stan::math::ChainableStack::instance_->var_stack_.size() - + std::get>(stan::math::ChainableStack::instance_->var_zeroing_stacks_).size(); + + std::get>( + stan::math::ChainableStack::instance_->var_zeroing_stacks_) + .size(); EXPECT_EQ(10U, stack_size); EXPECT_NO_THROW(check_consistent_sizes(function, "a", a, "b", b)); size_t stack_size_after_call = stan::math::ChainableStack::instance_->var_stack_.size() - + std::get>(stan::math::ChainableStack::instance_->var_zeroing_stacks_).size(); + + std::get>( + stan::math::ChainableStack::instance_->var_zeroing_stacks_) + .size(); EXPECT_EQ(10U, stack_size_after_call); stan::math::recover_memory(); } diff --git a/test/unit/math/rev/err/check_finite_test.cpp b/test/unit/math/rev/err/check_finite_test.cpp index 4d65b3f8132..1e2acbca5b4 100644 --- a/test/unit/math/rev/err/check_finite_test.cpp +++ b/test/unit/math/rev/err/check_finite_test.cpp @@ -17,21 +17,27 @@ TEST(AgradRevErrorHandlingScalar, CheckFiniteVarCheckVectorized) { size_t stack_size = stan::math::ChainableStack::instance_->var_stack_.size() - + std::get>(stan::math::ChainableStack::instance_->var_zeroing_stacks_).size(); + + std::get>( + stan::math::ChainableStack::instance_->var_zeroing_stacks_) + .size(); EXPECT_EQ(5U, stack_size); EXPECT_NO_THROW(check_finite(function, "a", a)); size_t stack_size_after_call = stan::math::ChainableStack::instance_->var_stack_.size() - + std::get>(stan::math::ChainableStack::instance_->var_zeroing_stacks_).size(); + + std::get>( + stan::math::ChainableStack::instance_->var_zeroing_stacks_) + .size(); EXPECT_EQ(5U, stack_size_after_call); a[1] = std::numeric_limits::infinity(); EXPECT_THROW(check_finite(function, "a", a), std::domain_error); stack_size_after_call = stan::math::ChainableStack::instance_->var_stack_.size() - + std::get>(stan::math::ChainableStack::instance_->var_zeroing_stacks_).size(); + + std::get>( + stan::math::ChainableStack::instance_->var_zeroing_stacks_) + .size(); EXPECT_EQ(6U, stack_size_after_call); stan::math::recover_memory(); @@ -71,21 +77,27 @@ TEST(AgradRevErrorHandlingScalar, CheckFiniteVarCheckUnivariate) { size_t stack_size = stan::math::ChainableStack::instance_->var_stack_.size() - + std::get>(stan::math::ChainableStack::instance_->var_zeroing_stacks_).size(); + + std::get>( + stan::math::ChainableStack::instance_->var_zeroing_stacks_) + .size(); EXPECT_EQ(1U, stack_size); EXPECT_NO_THROW(check_finite(function, "a", a)); size_t stack_size_after_call = stan::math::ChainableStack::instance_->var_stack_.size() - + std::get>(stan::math::ChainableStack::instance_->var_zeroing_stacks_).size(); + + std::get>( + stan::math::ChainableStack::instance_->var_zeroing_stacks_) + .size(); EXPECT_EQ(1U, stack_size_after_call); a = std::numeric_limits::infinity(); EXPECT_THROW(check_finite(function, "a", a), std::domain_error); stack_size_after_call = stan::math::ChainableStack::instance_->var_stack_.size() - + std::get>(stan::math::ChainableStack::instance_->var_zeroing_stacks_).size(); + + std::get>( + stan::math::ChainableStack::instance_->var_zeroing_stacks_) + .size(); EXPECT_EQ(2U, stack_size_after_call); stan::math::recover_memory(); diff --git a/test/unit/math/rev/err/check_greater_or_equal_test.cpp b/test/unit/math/rev/err/check_greater_or_equal_test.cpp index 1f4f746b527..475901b8582 100644 --- a/test/unit/math/rev/err/check_greater_or_equal_test.cpp +++ b/test/unit/math/rev/err/check_greater_or_equal_test.cpp @@ -17,21 +17,27 @@ TEST(AgradRevErrorHandlingScalar, CheckGreateOrEqualVarCheckVectorized) { size_t stack_size = stan::math::ChainableStack::instance_->var_stack_.size() - + std::get>(stan::math::ChainableStack::instance_->var_zeroing_stacks_).size(); + + std::get>( + stan::math::ChainableStack::instance_->var_zeroing_stacks_) + .size(); EXPECT_EQ(5U, stack_size); EXPECT_NO_THROW(check_greater_or_equal(function, "a", a, -1.0)); size_t stack_size_after_call = stan::math::ChainableStack::instance_->var_stack_.size() - + std::get>(stan::math::ChainableStack::instance_->var_zeroing_stacks_).size(); + + std::get>( + stan::math::ChainableStack::instance_->var_zeroing_stacks_) + .size(); EXPECT_EQ(5U, stack_size_after_call); EXPECT_THROW(check_greater_or_equal(function, "a", a, 2.0), std::domain_error); stack_size_after_call = stan::math::ChainableStack::instance_->var_stack_.size() - + std::get>(stan::math::ChainableStack::instance_->var_zeroing_stacks_).size(); + + std::get>( + stan::math::ChainableStack::instance_->var_zeroing_stacks_) + .size(); EXPECT_EQ(5U, stack_size_after_call); stan::math::recover_memory(); @@ -198,21 +204,27 @@ TEST(AgradRevErrorHandlingScalar, CheckGreaterOrEqualVarCheckUnivariate) { size_t stack_size = stan::math::ChainableStack::instance_->var_stack_.size() - + std::get>(stan::math::ChainableStack::instance_->var_zeroing_stacks_).size(); + + std::get>( + stan::math::ChainableStack::instance_->var_zeroing_stacks_) + .size(); EXPECT_EQ(1U, stack_size); EXPECT_NO_THROW(check_greater_or_equal(function, "a", a, 2.0)); size_t stack_size_after_call = stan::math::ChainableStack::instance_->var_stack_.size() - + std::get>(stan::math::ChainableStack::instance_->var_zeroing_stacks_).size(); + + std::get>( + stan::math::ChainableStack::instance_->var_zeroing_stacks_) + .size(); EXPECT_EQ(1U, stack_size_after_call); EXPECT_THROW(check_greater_or_equal(function, "a", a, 10.0), std::domain_error); stack_size_after_call = stan::math::ChainableStack::instance_->var_stack_.size() - + std::get>(stan::math::ChainableStack::instance_->var_zeroing_stacks_).size(); + + std::get>( + stan::math::ChainableStack::instance_->var_zeroing_stacks_) + .size(); EXPECT_EQ(1U, stack_size_after_call); stan::math::recover_memory(); diff --git a/test/unit/math/rev/err/check_greater_test.cpp b/test/unit/math/rev/err/check_greater_test.cpp index 933cef600b4..cda6141c8bc 100644 --- a/test/unit/math/rev/err/check_greater_test.cpp +++ b/test/unit/math/rev/err/check_greater_test.cpp @@ -16,20 +16,26 @@ TEST(AgradRevErrorHandlingScalar, CheckGreaterVarCheckVectorized) { size_t stack_size = stan::math::ChainableStack::instance_->var_stack_.size() - + std::get>(stan::math::ChainableStack::instance_->var_zeroing_stacks_).size(); + + std::get>( + stan::math::ChainableStack::instance_->var_zeroing_stacks_) + .size(); EXPECT_EQ(5U, stack_size); EXPECT_NO_THROW(check_greater(function, "a", a, -1.0)); size_t stack_size_after_call = stan::math::ChainableStack::instance_->var_stack_.size() - + std::get>(stan::math::ChainableStack::instance_->var_zeroing_stacks_).size(); + + std::get>( + stan::math::ChainableStack::instance_->var_zeroing_stacks_) + .size(); EXPECT_EQ(5U, stack_size_after_call); EXPECT_THROW(check_greater(function, "a", a, 2.0), std::domain_error); stack_size_after_call = stan::math::ChainableStack::instance_->var_stack_.size() - + std::get>(stan::math::ChainableStack::instance_->var_zeroing_stacks_).size(); + + std::get>( + stan::math::ChainableStack::instance_->var_zeroing_stacks_) + .size(); EXPECT_EQ(5U, stack_size_after_call); stan::math::recover_memory(); @@ -188,20 +194,26 @@ TEST(AgradRevErrorHandlingScalar, CheckGreaterVarCheckUnivariate) { size_t stack_size = stan::math::ChainableStack::instance_->var_stack_.size() - + std::get>(stan::math::ChainableStack::instance_->var_zeroing_stacks_).size(); + + std::get>( + stan::math::ChainableStack::instance_->var_zeroing_stacks_) + .size(); EXPECT_EQ(1U, stack_size); EXPECT_NO_THROW(check_greater(function, "a", a, 2.0)); size_t stack_size_after_call = stan::math::ChainableStack::instance_->var_stack_.size() - + std::get>(stan::math::ChainableStack::instance_->var_zeroing_stacks_).size(); + + std::get>( + stan::math::ChainableStack::instance_->var_zeroing_stacks_) + .size(); EXPECT_EQ(1U, stack_size_after_call); EXPECT_THROW(check_greater(function, "a", a, 10.0), std::domain_error); stack_size_after_call = stan::math::ChainableStack::instance_->var_stack_.size() - + std::get>(stan::math::ChainableStack::instance_->var_zeroing_stacks_).size(); + + std::get>( + stan::math::ChainableStack::instance_->var_zeroing_stacks_) + .size(); EXPECT_EQ(1U, stack_size_after_call); stan::math::recover_memory(); diff --git a/test/unit/math/rev/err/check_less_or_equal_test.cpp b/test/unit/math/rev/err/check_less_or_equal_test.cpp index fe96da18b5c..1c0cd417aae 100644 --- a/test/unit/math/rev/err/check_less_or_equal_test.cpp +++ b/test/unit/math/rev/err/check_less_or_equal_test.cpp @@ -16,20 +16,26 @@ TEST(AgradRevErrorHandlingScalar, CheckLessOrEqualVarCheckVectorized) { size_t stack_size = stan::math::ChainableStack::instance_->var_stack_.size() - + std::get>(stan::math::ChainableStack::instance_->var_zeroing_stacks_).size(); + + std::get>( + stan::math::ChainableStack::instance_->var_zeroing_stacks_) + .size(); EXPECT_EQ(5U, stack_size); EXPECT_NO_THROW(check_less_or_equal(function, "a", a, 10.0)); size_t stack_size_after_call = stan::math::ChainableStack::instance_->var_stack_.size() - + std::get>(stan::math::ChainableStack::instance_->var_zeroing_stacks_).size(); + + std::get>( + stan::math::ChainableStack::instance_->var_zeroing_stacks_) + .size(); EXPECT_EQ(5U, stack_size_after_call); EXPECT_THROW(check_less_or_equal(function, "a", a, 2.0), std::domain_error); stack_size_after_call = stan::math::ChainableStack::instance_->var_stack_.size() - + std::get>(stan::math::ChainableStack::instance_->var_zeroing_stacks_).size(); + + std::get>( + stan::math::ChainableStack::instance_->var_zeroing_stacks_) + .size(); EXPECT_EQ(5U, stack_size_after_call); stan::math::recover_memory(); @@ -161,27 +167,35 @@ TEST(AgradRevErrorHandlingScalar, CheckLessOrEqualVarCheckUnivariate) { size_t stack_size = stan::math::ChainableStack::instance_->var_stack_.size() - + std::get>(stan::math::ChainableStack::instance_->var_zeroing_stacks_).size(); + + std::get>( + stan::math::ChainableStack::instance_->var_zeroing_stacks_) + .size(); EXPECT_EQ(1U, stack_size); EXPECT_THROW(check_less_or_equal(function, "a", a, 2.0), std::domain_error); size_t stack_size_after_call = stan::math::ChainableStack::instance_->var_stack_.size() - + std::get>(stan::math::ChainableStack::instance_->var_zeroing_stacks_).size(); + + std::get>( + stan::math::ChainableStack::instance_->var_zeroing_stacks_) + .size(); EXPECT_EQ(1U, stack_size_after_call); EXPECT_NO_THROW(check_less_or_equal(function, "a", a, 5.0)); stack_size_after_call = stan::math::ChainableStack::instance_->var_stack_.size() - + std::get>(stan::math::ChainableStack::instance_->var_zeroing_stacks_).size(); + + std::get>( + stan::math::ChainableStack::instance_->var_zeroing_stacks_) + .size(); EXPECT_EQ(1U, stack_size_after_call); EXPECT_NO_THROW(check_less_or_equal(function, "a", a, 10.0)); stack_size_after_call = stan::math::ChainableStack::instance_->var_stack_.size() - + std::get>(stan::math::ChainableStack::instance_->var_zeroing_stacks_).size(); + + std::get>( + stan::math::ChainableStack::instance_->var_zeroing_stacks_) + .size(); EXPECT_EQ(1U, stack_size_after_call); stan::math::recover_memory(); diff --git a/test/unit/math/rev/err/check_less_test.cpp b/test/unit/math/rev/err/check_less_test.cpp index c30a694534c..a671b4368b1 100644 --- a/test/unit/math/rev/err/check_less_test.cpp +++ b/test/unit/math/rev/err/check_less_test.cpp @@ -16,20 +16,26 @@ TEST(AgradRevErrorHandlingScalar, CheckLessVarCheckVectorized) { size_t stack_size = stan::math::ChainableStack::instance_->var_stack_.size() - + std::get>(stan::math::ChainableStack::instance_->var_zeroing_stacks_).size(); + + std::get>( + stan::math::ChainableStack::instance_->var_zeroing_stacks_) + .size(); EXPECT_EQ(5U, stack_size); EXPECT_NO_THROW(check_less(function, "a", a, 10.0)); size_t stack_size_after_call = stan::math::ChainableStack::instance_->var_stack_.size() - + std::get>(stan::math::ChainableStack::instance_->var_zeroing_stacks_).size(); + + std::get>( + stan::math::ChainableStack::instance_->var_zeroing_stacks_) + .size(); EXPECT_EQ(5U, stack_size_after_call); EXPECT_THROW(check_less(function, "a", a, 2.0), std::domain_error); stack_size_after_call = stan::math::ChainableStack::instance_->var_stack_.size() - + std::get>(stan::math::ChainableStack::instance_->var_zeroing_stacks_).size(); + + std::get>( + stan::math::ChainableStack::instance_->var_zeroing_stacks_) + .size(); EXPECT_EQ(5U, stack_size_after_call); stan::math::recover_memory(); @@ -158,20 +164,26 @@ TEST(AgradRevErrorHandlingScalar, CheckLessVarCheckUnivariate) { size_t stack_size = stan::math::ChainableStack::instance_->var_stack_.size() - + std::get>(stan::math::ChainableStack::instance_->var_zeroing_stacks_).size(); + + std::get>( + stan::math::ChainableStack::instance_->var_zeroing_stacks_) + .size(); EXPECT_EQ(1U, stack_size); EXPECT_THROW(check_less(function, "a", a, 2.0), std::domain_error); size_t stack_size_after_call = stan::math::ChainableStack::instance_->var_stack_.size() - + std::get>(stan::math::ChainableStack::instance_->var_zeroing_stacks_).size(); + + std::get>( + stan::math::ChainableStack::instance_->var_zeroing_stacks_) + .size(); EXPECT_EQ(1U, stack_size_after_call); EXPECT_NO_THROW(check_less(function, "a", a, 10.0)); stack_size_after_call = stan::math::ChainableStack::instance_->var_stack_.size() - + std::get>(stan::math::ChainableStack::instance_->var_zeroing_stacks_).size(); + + std::get>( + stan::math::ChainableStack::instance_->var_zeroing_stacks_) + .size(); EXPECT_EQ(1U, stack_size_after_call); stan::math::recover_memory(); diff --git a/test/unit/math/rev/err/check_nonnegative_test.cpp b/test/unit/math/rev/err/check_nonnegative_test.cpp index 6d2bafb4991..b7451c0c0aa 100644 --- a/test/unit/math/rev/err/check_nonnegative_test.cpp +++ b/test/unit/math/rev/err/check_nonnegative_test.cpp @@ -48,35 +48,45 @@ TEST(AgradRevErrorHandlingScalar, CheckNonnegativeVarCheckVectorized) { size_t stack_size = stan::math::ChainableStack::instance_->var_stack_.size() - + std::get>(stan::math::ChainableStack::instance_->var_zeroing_stacks_).size(); + + std::get>( + stan::math::ChainableStack::instance_->var_zeroing_stacks_) + .size(); EXPECT_EQ(5U, stack_size); EXPECT_NO_THROW(check_nonnegative(function, "a", a)); size_t stack_size_after_call = stan::math::ChainableStack::instance_->var_stack_.size() - + std::get>(stan::math::ChainableStack::instance_->var_zeroing_stacks_).size(); + + std::get>( + stan::math::ChainableStack::instance_->var_zeroing_stacks_) + .size(); EXPECT_EQ(5U, stack_size_after_call); a[1] = std::numeric_limits::infinity(); EXPECT_NO_THROW(check_nonnegative(function, "a", a)); stack_size_after_call = stan::math::ChainableStack::instance_->var_stack_.size() - + std::get>(stan::math::ChainableStack::instance_->var_zeroing_stacks_).size(); + + std::get>( + stan::math::ChainableStack::instance_->var_zeroing_stacks_) + .size(); EXPECT_EQ(6U, stack_size_after_call); a[1] = -1.0; EXPECT_THROW(check_nonnegative(function, "a", a), std::domain_error); stack_size_after_call = stan::math::ChainableStack::instance_->var_stack_.size() - + std::get>(stan::math::ChainableStack::instance_->var_zeroing_stacks_).size(); + + std::get>( + stan::math::ChainableStack::instance_->var_zeroing_stacks_) + .size(); EXPECT_EQ(7U, stack_size_after_call); a[1] = 0.0; EXPECT_NO_THROW(check_nonnegative(function, "a", a)); stack_size_after_call = stan::math::ChainableStack::instance_->var_stack_.size() - + std::get>(stan::math::ChainableStack::instance_->var_zeroing_stacks_).size(); + + std::get>( + stan::math::ChainableStack::instance_->var_zeroing_stacks_) + .size(); EXPECT_EQ(8U, stack_size_after_call); stan::math::recover_memory(); @@ -116,35 +126,45 @@ TEST(AgradRevErrorHandlingScalar, CheckNonnegativeVarCheckUnivariate) { size_t stack_size = stan::math::ChainableStack::instance_->var_stack_.size() - + std::get>(stan::math::ChainableStack::instance_->var_zeroing_stacks_).size(); + + std::get>( + stan::math::ChainableStack::instance_->var_zeroing_stacks_) + .size(); EXPECT_EQ(1U, stack_size); EXPECT_NO_THROW(check_nonnegative(function, "a", a)); size_t stack_size_after_call = stan::math::ChainableStack::instance_->var_stack_.size() - + std::get>(stan::math::ChainableStack::instance_->var_zeroing_stacks_).size(); + + std::get>( + stan::math::ChainableStack::instance_->var_zeroing_stacks_) + .size(); EXPECT_EQ(1U, stack_size_after_call); a = std::numeric_limits::infinity(); EXPECT_NO_THROW(check_nonnegative(function, "a", a)); stack_size_after_call = stan::math::ChainableStack::instance_->var_stack_.size() - + std::get>(stan::math::ChainableStack::instance_->var_zeroing_stacks_).size(); + + std::get>( + stan::math::ChainableStack::instance_->var_zeroing_stacks_) + .size(); EXPECT_EQ(2U, stack_size_after_call); a = 0.0; EXPECT_NO_THROW(check_nonnegative(function, "a", a)); stack_size_after_call = stan::math::ChainableStack::instance_->var_stack_.size() - + std::get>(stan::math::ChainableStack::instance_->var_zeroing_stacks_).size(); + + std::get>( + stan::math::ChainableStack::instance_->var_zeroing_stacks_) + .size(); EXPECT_EQ(3U, stack_size_after_call); a = -1.1; EXPECT_THROW(check_nonnegative(function, "a", a), std::domain_error); stack_size_after_call = stan::math::ChainableStack::instance_->var_stack_.size() - + std::get>(stan::math::ChainableStack::instance_->var_zeroing_stacks_).size(); + + std::get>( + stan::math::ChainableStack::instance_->var_zeroing_stacks_) + .size(); EXPECT_EQ(4U, stack_size_after_call); stan::math::recover_memory(); } diff --git a/test/unit/math/rev/err/check_not_nan_test.cpp b/test/unit/math/rev/err/check_not_nan_test.cpp index 9d29b698126..260e6908ba3 100644 --- a/test/unit/math/rev/err/check_not_nan_test.cpp +++ b/test/unit/math/rev/err/check_not_nan_test.cpp @@ -16,14 +16,18 @@ TEST(AgradRevErrorHandlingScalar, CheckNotNanVarCheckVectorized) { size_t stack_size = stan::math::ChainableStack::instance_->var_stack_.size() - + std::get>(stan::math::ChainableStack::instance_->var_zeroing_stacks_).size(); + + std::get>( + stan::math::ChainableStack::instance_->var_zeroing_stacks_) + .size(); EXPECT_EQ(5U, stack_size); EXPECT_NO_THROW(check_not_nan(function, "a", a)); size_t stack_size_after_call = stan::math::ChainableStack::instance_->var_stack_.size() - + std::get>(stan::math::ChainableStack::instance_->var_zeroing_stacks_).size(); + + std::get>( + stan::math::ChainableStack::instance_->var_zeroing_stacks_) + .size(); EXPECT_EQ(5U, stack_size_after_call); stan::math::recover_memory(); } @@ -41,14 +45,18 @@ TEST(ErrorHandlingScalar, CheckNotNanVarCheckVectorized) { size_t stack_size = stan::math::ChainableStack::instance_->var_stack_.size() - + std::get>(stan::math::ChainableStack::instance_->var_zeroing_stacks_).size(); + + std::get>( + stan::math::ChainableStack::instance_->var_zeroing_stacks_) + .size(); EXPECT_EQ(5U, stack_size); EXPECT_NO_THROW(check_not_nan(function, "a", a)); size_t stack_size_after_call = stan::math::ChainableStack::instance_->var_stack_.size() - + std::get>(stan::math::ChainableStack::instance_->var_zeroing_stacks_).size(); + + std::get>( + stan::math::ChainableStack::instance_->var_zeroing_stacks_) + .size(); EXPECT_EQ(5U, stack_size_after_call); stan::math::recover_memory(); } @@ -98,14 +106,18 @@ TEST(AgradRevErrorHandlingScalar, CheckNotNanVarCheckUnivariate) { size_t stack_size = stan::math::ChainableStack::instance_->var_stack_.size() - + std::get>(stan::math::ChainableStack::instance_->var_zeroing_stacks_).size(); + + std::get>( + stan::math::ChainableStack::instance_->var_zeroing_stacks_) + .size(); EXPECT_EQ(1U, stack_size); EXPECT_NO_THROW(check_not_nan(function, "a", a)); size_t stack_size_after_call = stan::math::ChainableStack::instance_->var_stack_.size() - + std::get>(stan::math::ChainableStack::instance_->var_zeroing_stacks_).size(); + + std::get>( + stan::math::ChainableStack::instance_->var_zeroing_stacks_) + .size(); EXPECT_EQ(1U, stack_size_after_call); stan::math::recover_memory(); @@ -120,14 +132,18 @@ TEST(ErrorHandlingScalar, CheckNotNanVarCheckUnivariate) { size_t stack_size = stan::math::ChainableStack::instance_->var_stack_.size() - + std::get>(stan::math::ChainableStack::instance_->var_zeroing_stacks_).size(); + + std::get>( + stan::math::ChainableStack::instance_->var_zeroing_stacks_) + .size(); EXPECT_EQ(1U, stack_size); EXPECT_NO_THROW(check_not_nan(function, "a", a)); size_t stack_size_after_call = stan::math::ChainableStack::instance_->var_stack_.size() - + std::get>(stan::math::ChainableStack::instance_->var_zeroing_stacks_).size(); + + std::get>( + stan::math::ChainableStack::instance_->var_zeroing_stacks_) + .size(); EXPECT_EQ(1U, stack_size_after_call); stan::math::recover_memory(); diff --git a/test/unit/math/rev/err/check_pos_semidefinite_test.cpp b/test/unit/math/rev/err/check_pos_semidefinite_test.cpp index b4666582fcd..f07cfc2311a 100644 --- a/test/unit/math/rev/err/check_pos_semidefinite_test.cpp +++ b/test/unit/math/rev/err/check_pos_semidefinite_test.cpp @@ -50,13 +50,17 @@ TEST(AgradRevErrorHandlingMatrix, checkPosSemiDefiniteMatrixVarCheck) { size_t stack_before_call = stan::math::ChainableStack::instance_->var_stack_.size() - + std::get>(stan::math::ChainableStack::instance_->var_zeroing_stacks_).size(); + + std::get>( + stan::math::ChainableStack::instance_->var_zeroing_stacks_) + .size(); EXPECT_EQ(9U, stack_before_call); EXPECT_NO_THROW(check_pos_semidefinite("checkPosDefiniteMatrix", "y", y)); size_t stack_after_call = stan::math::ChainableStack::instance_->var_stack_.size() - + std::get>(stan::math::ChainableStack::instance_->var_zeroing_stacks_).size(); + + std::get>( + stan::math::ChainableStack::instance_->var_zeroing_stacks_) + .size(); EXPECT_EQ(9U, stack_after_call); } diff --git a/test/unit/math/rev/err/check_positive_finite_test.cpp b/test/unit/math/rev/err/check_positive_finite_test.cpp index 0e63eb4ca49..0c359b38963 100644 --- a/test/unit/math/rev/err/check_positive_finite_test.cpp +++ b/test/unit/math/rev/err/check_positive_finite_test.cpp @@ -67,7 +67,9 @@ TEST(AgradRevErrorHandlingScalar, CheckPositiveFiniteVarCheckVectorized) { size_t stack_size = stan::math::ChainableStack::instance_->var_stack_.size() - + std::get>(stan::math::ChainableStack::instance_->var_zeroing_stacks_).size(); + + std::get>( + stan::math::ChainableStack::instance_->var_zeroing_stacks_) + .size(); EXPECT_EQ(5U, stack_size); EXPECT_THROW(check_positive_finite(function, "a", a), std::domain_error); @@ -75,14 +77,18 @@ TEST(AgradRevErrorHandlingScalar, CheckPositiveFiniteVarCheckVectorized) { size_t stack_size_after_call = stan::math::ChainableStack::instance_->var_stack_.size() - + std::get>(stan::math::ChainableStack::instance_->var_zeroing_stacks_).size(); + + std::get>( + stan::math::ChainableStack::instance_->var_zeroing_stacks_) + .size(); EXPECT_EQ(5U, stack_size_after_call); a[2] = std::numeric_limits::infinity(); EXPECT_THROW(check_positive_finite(function, "a", a), std::domain_error); stack_size_after_call = stan::math::ChainableStack::instance_->var_stack_.size() - + std::get>(stan::math::ChainableStack::instance_->var_zeroing_stacks_).size(); + + std::get>( + stan::math::ChainableStack::instance_->var_zeroing_stacks_) + .size(); EXPECT_EQ(6U, stack_size_after_call); stan::math::recover_memory(); } @@ -163,14 +169,18 @@ TEST(AgradRevErrorHandlingScalar, CheckPositiveFiniteVarCheckUnivariate) { size_t stack_size = stan::math::ChainableStack::instance_->var_stack_.size() - + std::get>(stan::math::ChainableStack::instance_->var_zeroing_stacks_).size(); + + std::get>( + stan::math::ChainableStack::instance_->var_zeroing_stacks_) + .size(); EXPECT_EQ(1U, stack_size); EXPECT_NO_THROW(check_positive_finite(function, "a", a)); size_t stack_size_after_call = stan::math::ChainableStack::instance_->var_stack_.size() - + std::get>(stan::math::ChainableStack::instance_->var_zeroing_stacks_).size(); + + std::get>( + stan::math::ChainableStack::instance_->var_zeroing_stacks_) + .size(); EXPECT_EQ(1U, stack_size_after_call); stan::math::recover_memory(); diff --git a/test/unit/math/rev/err/check_positive_test.cpp b/test/unit/math/rev/err/check_positive_test.cpp index 2b4ed43f15f..6a272d03e52 100644 --- a/test/unit/math/rev/err/check_positive_test.cpp +++ b/test/unit/math/rev/err/check_positive_test.cpp @@ -60,14 +60,18 @@ TEST(AgradRevErrorHandlingScalar, CheckPositiveVarCheckUnivariate) { size_t stack_size = stan::math::ChainableStack::instance_->var_stack_.size() - + std::get>(stan::math::ChainableStack::instance_->var_zeroing_stacks_).size(); + + std::get>( + stan::math::ChainableStack::instance_->var_zeroing_stacks_) + .size(); EXPECT_EQ(1U, stack_size); EXPECT_NO_THROW(check_positive(function, "a", a)); size_t stack_size_after_call = stan::math::ChainableStack::instance_->var_stack_.size() - + std::get>(stan::math::ChainableStack::instance_->var_zeroing_stacks_).size(); + + std::get>( + stan::math::ChainableStack::instance_->var_zeroing_stacks_) + .size(); EXPECT_EQ(1U, stack_size_after_call); stan::math::recover_memory(); From c8cd17a4711373a846bc9e65c351cb051b1fb6c9 Mon Sep 17 00:00:00 2001 From: Steve Bronder Date: Wed, 17 Jun 2020 16:37:59 -0400 Subject: [PATCH 098/355] forgot () in virtual vari_base destructor --- stan/math/rev/core/vari.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stan/math/rev/core/vari.hpp b/stan/math/rev/core/vari.hpp index f555175fa95..fd1854c0c10 100644 --- a/stan/math/rev/core/vari.hpp +++ b/stan/math/rev/core/vari.hpp @@ -29,7 +29,7 @@ class vari_base { * on which it depends. */ virtual void chain(){} - virtual ~vari_base {} + virtual ~vari_base() {}; }; /** * The variable implementation base class. From 9dd3eafe9f6dcdc39874e8779e3cbd8f2098fbf2 Mon Sep 17 00:00:00 2001 From: Stan Jenkins Date: Wed, 17 Jun 2020 16:41:39 -0400 Subject: [PATCH 099/355] [Jenkins] auto-formatting by clang-format version 6.0.0-1ubuntu2 (tags/RELEASE_600/final) --- stan/math/rev/core/var.hpp | 10 +++++----- stan/math/rev/core/vari.hpp | 12 ++++++------ 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/stan/math/rev/core/var.hpp b/stan/math/rev/core/var.hpp index 8071b2da784..66723a584df 100644 --- a/stan/math/rev/core/var.hpp +++ b/stan/math/rev/core/var.hpp @@ -36,9 +36,9 @@ class var_value {}; template class var_value> { public: - using value_type = std::decay_t; // Numeric type in vari_value. - using vari_type = vari_value; // Type of underlying vari impl. - using vari_pointer = vari_type*; // pointer type for underlying vari. + using value_type = std::decay_t; // Numeric type in vari_value. + using vari_type = vari_value; // Type of underlying vari impl. + using vari_pointer = vari_type*; // pointer type for underlying vari. /** * Pointer to the implementation of this variable. @@ -71,8 +71,8 @@ class var_value> { /** * Construct a variable from the specified floating point argument - * by constructing a new `vari_value`. This constructor is only valid - * when `S` is convertible to this `vari_value`'s `value_type`. + * by constructing a new `vari_value`. This constructor is only + * valid when `S` is convertible to this `vari_value`'s `value_type`. * @tparam S A type that is convertible to `value_type`. * @param x Value of the variable. */ diff --git a/stan/math/rev/core/vari.hpp b/stan/math/rev/core/vari.hpp index 21c914e6af5..65e29775a36 100644 --- a/stan/math/rev/core/vari.hpp +++ b/stan/math/rev/core/vari.hpp @@ -24,12 +24,12 @@ class var_value; */ class vari_base { public: - /** - * Apply the chain rule to this variable based on the variables - * on which it depends. - */ - virtual void chain(){} - virtual ~vari_base() {}; + /** + * Apply the chain rule to this variable based on the variables + * on which it depends. + */ + virtual void chain() {} + virtual ~vari_base(){}; }; /** * The variable implementation base class. From 1d187bcbaa728859424fcd6672a467b872a65c49 Mon Sep 17 00:00:00 2001 From: Steve Bronder Date: Wed, 17 Jun 2020 17:05:19 -0400 Subject: [PATCH 100/355] fix libstdc++ bug with array --- stan/math/rev/core/autodiffstackstorage.hpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/stan/math/rev/core/autodiffstackstorage.hpp b/stan/math/rev/core/autodiffstackstorage.hpp index 42c74ea92dc..a3e9e42a619 100644 --- a/stan/math/rev/core/autodiffstackstorage.hpp +++ b/stan/math/rev/core/autodiffstackstorage.hpp @@ -2,6 +2,7 @@ #define STAN_MATH_REV_CORE_AUTODIFFSTACKSTORAGE_HPP #include +#include #include namespace stan { @@ -112,7 +113,7 @@ struct AutodiffStackSingleton { // nested positions std::vector nested_var_stack_sizes_; std::array, std::tuple_size::value> - nested_var_zeroing_stack_sizes_; + nested_var_zeroing_stack_sizes_{}; std::vector nested_var_alloc_stack_starts_; }; From eccd3cb41850f23c1ce8c01a98e5b980e2707633 Mon Sep 17 00:00:00 2001 From: Steve Bronder Date: Wed, 17 Jun 2020 17:06:10 -0400 Subject: [PATCH 101/355] cpplint --- stan/math/rev/core/vari.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stan/math/rev/core/vari.hpp b/stan/math/rev/core/vari.hpp index 65e29775a36..8486051b0ee 100644 --- a/stan/math/rev/core/vari.hpp +++ b/stan/math/rev/core/vari.hpp @@ -29,7 +29,7 @@ class vari_base { * on which it depends. */ virtual void chain() {} - virtual ~vari_base(){}; + virtual ~vari_base(){} }; /** * The variable implementation base class. From 6ad67140b394dcbf866e5c9dcfcb9c9a771f4ad9 Mon Sep 17 00:00:00 2001 From: Stan Jenkins Date: Wed, 17 Jun 2020 17:06:58 -0400 Subject: [PATCH 102/355] [Jenkins] auto-formatting by clang-format version 6.0.0-1ubuntu2 (tags/RELEASE_600/final) --- stan/math/rev/core/vari.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stan/math/rev/core/vari.hpp b/stan/math/rev/core/vari.hpp index 8486051b0ee..37ec7ae49f9 100644 --- a/stan/math/rev/core/vari.hpp +++ b/stan/math/rev/core/vari.hpp @@ -29,7 +29,7 @@ class vari_base { * on which it depends. */ virtual void chain() {} - virtual ~vari_base(){} + virtual ~vari_base() {} }; /** * The variable implementation base class. From 165a88338cec8a71260972396b4d2ecbe5935e51 Mon Sep 17 00:00:00 2001 From: Steve Bronder Date: Wed, 17 Jun 2020 18:30:07 -0400 Subject: [PATCH 103/355] fix seg fault by not always giving var_zeroing stacks to nested_var_zero stack sizes --- stan/math/rev/core/start_nested.hpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/stan/math/rev/core/start_nested.hpp b/stan/math/rev/core/start_nested.hpp index a667f695136..fcd9b8170ea 100644 --- a/stan/math/rev/core/start_nested.hpp +++ b/stan/math/rev/core/start_nested.hpp @@ -19,9 +19,7 @@ static inline void start_nested() { ChainableStack::instance_->var_stack_.size()); for_each( [](auto& x, auto& y) { - if (y.size() > 0) { x.push_back(y.size()); - } }, ChainableStack::instance_->nested_var_zeroing_stack_sizes_, ChainableStack::instance_->var_zeroing_stacks_); From fa5de840dd16f7e1b566dd162e24eb42e16a8cf6 Mon Sep 17 00:00:00 2001 From: Stan Jenkins Date: Wed, 17 Jun 2020 18:30:56 -0400 Subject: [PATCH 104/355] [Jenkins] auto-formatting by clang-format version 6.0.0-1ubuntu2 (tags/RELEASE_600/final) --- stan/math/rev/core/start_nested.hpp | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/stan/math/rev/core/start_nested.hpp b/stan/math/rev/core/start_nested.hpp index fcd9b8170ea..241b0aa9a2e 100644 --- a/stan/math/rev/core/start_nested.hpp +++ b/stan/math/rev/core/start_nested.hpp @@ -17,12 +17,9 @@ namespace math { static inline void start_nested() { ChainableStack::instance_->nested_var_stack_sizes_.push_back( ChainableStack::instance_->var_stack_.size()); - for_each( - [](auto& x, auto& y) { - x.push_back(y.size()); - }, - ChainableStack::instance_->nested_var_zeroing_stack_sizes_, - ChainableStack::instance_->var_zeroing_stacks_); + for_each([](auto& x, auto& y) { x.push_back(y.size()); }, + ChainableStack::instance_->nested_var_zeroing_stack_sizes_, + ChainableStack::instance_->var_zeroing_stacks_); ChainableStack::instance_->nested_var_alloc_stack_starts_.push_back( ChainableStack::instance_->var_alloc_stack_.size()); ChainableStack::instance_->memalloc_.start_nested(); From efaa936d28906ea164a76587f7b73429b2d56a3d Mon Sep 17 00:00:00 2001 From: Steve Bronder Date: Thu, 18 Jun 2020 17:46:22 -0400 Subject: [PATCH 105/355] only push sizes if they are nonzero for the nested zeroing stack --- stan/math/rev/core/autodiffstackstorage.hpp | 2 +- stan/math/rev/core/start_nested.hpp | 6 +++++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/stan/math/rev/core/autodiffstackstorage.hpp b/stan/math/rev/core/autodiffstackstorage.hpp index a3e9e42a619..2a31d146eb0 100644 --- a/stan/math/rev/core/autodiffstackstorage.hpp +++ b/stan/math/rev/core/autodiffstackstorage.hpp @@ -113,7 +113,7 @@ struct AutodiffStackSingleton { // nested positions std::vector nested_var_stack_sizes_; std::array, std::tuple_size::value> - nested_var_zeroing_stack_sizes_{}; + nested_var_zeroing_stack_sizes_{std::vector{1, 0}}; std::vector nested_var_alloc_stack_starts_; }; diff --git a/stan/math/rev/core/start_nested.hpp b/stan/math/rev/core/start_nested.hpp index 241b0aa9a2e..125798a7907 100644 --- a/stan/math/rev/core/start_nested.hpp +++ b/stan/math/rev/core/start_nested.hpp @@ -17,7 +17,11 @@ namespace math { static inline void start_nested() { ChainableStack::instance_->nested_var_stack_sizes_.push_back( ChainableStack::instance_->var_stack_.size()); - for_each([](auto& x, auto& y) { x.push_back(y.size()); }, + for_each([](auto& x, auto& y) { + if (y.size() > 0) { + x.push_back(y.size()); + } + }, ChainableStack::instance_->nested_var_zeroing_stack_sizes_, ChainableStack::instance_->var_zeroing_stacks_); ChainableStack::instance_->nested_var_alloc_stack_starts_.push_back( From 908ff3c7c65bce0dadbbed912c82eba2b1e39692 Mon Sep 17 00:00:00 2001 From: Stan Jenkins Date: Thu, 18 Jun 2020 17:47:37 -0400 Subject: [PATCH 106/355] [Jenkins] auto-formatting by clang-format version 6.0.0-1ubuntu2 (tags/RELEASE_600/final) --- stan/math/rev/core/start_nested.hpp | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/stan/math/rev/core/start_nested.hpp b/stan/math/rev/core/start_nested.hpp index 125798a7907..a667f695136 100644 --- a/stan/math/rev/core/start_nested.hpp +++ b/stan/math/rev/core/start_nested.hpp @@ -17,13 +17,14 @@ namespace math { static inline void start_nested() { ChainableStack::instance_->nested_var_stack_sizes_.push_back( ChainableStack::instance_->var_stack_.size()); - for_each([](auto& x, auto& y) { - if (y.size() > 0) { - x.push_back(y.size()); - } - }, - ChainableStack::instance_->nested_var_zeroing_stack_sizes_, - ChainableStack::instance_->var_zeroing_stacks_); + for_each( + [](auto& x, auto& y) { + if (y.size() > 0) { + x.push_back(y.size()); + } + }, + ChainableStack::instance_->nested_var_zeroing_stack_sizes_, + ChainableStack::instance_->var_zeroing_stacks_); ChainableStack::instance_->nested_var_alloc_stack_starts_.push_back( ChainableStack::instance_->var_alloc_stack_.size()); ChainableStack::instance_->memalloc_.start_nested(); From 3b85b96eb40b2937f917ee502f0cff82a2d054fa Mon Sep 17 00:00:00 2001 From: Steve Bronder Date: Fri, 19 Jun 2020 14:40:49 -0400 Subject: [PATCH 107/355] move around the stacks to avoid double push_backs in vari --- stan/math/rev/core/set_zero_all_adjoints.hpp | 3 +++ .../rev/core/set_zero_all_adjoints_nested.hpp | 10 ++++++++-- stan/math/rev/core/start_nested.hpp | 2 -- stan/math/rev/core/vari.hpp | 16 ++++++---------- 4 files changed, 17 insertions(+), 14 deletions(-) diff --git a/stan/math/rev/core/set_zero_all_adjoints.hpp b/stan/math/rev/core/set_zero_all_adjoints.hpp index 41e9f411947..61b5f917247 100644 --- a/stan/math/rev/core/set_zero_all_adjoints.hpp +++ b/stan/math/rev/core/set_zero_all_adjoints.hpp @@ -13,6 +13,9 @@ namespace math { * Reset all adjoint values in the stack to zero. */ static EIGEN_STRONG_INLINE void set_zero_all_adjoints() { + for (auto& xx : ChainableStack::instance_->var_stack_) { + xx->set_zero_adjoint(); + } for_each( [](auto& x) { for (auto& xx : x) { diff --git a/stan/math/rev/core/set_zero_all_adjoints_nested.hpp b/stan/math/rev/core/set_zero_all_adjoints_nested.hpp index dbe1ce44b1f..3dd7577ae93 100644 --- a/stan/math/rev/core/set_zero_all_adjoints_nested.hpp +++ b/stan/math/rev/core/set_zero_all_adjoints_nested.hpp @@ -25,10 +25,16 @@ static EIGEN_STRONG_INLINE void set_zero_all_adjoints_nested() { " set_zero_all_adjoints_nested()"); } size_t start1 = ChainableStack::instance_->nested_var_stack_sizes_.back(); + // avoid wrap with unsigned when start1 == 0 + for (size_t i = (start1 == 0U) ? 0U : (start1 - 1); + i < ChainableStack::instance_->var_stack_.size(); ++i) { + ChainableStack::instance_->var_stack_[i]->set_zero_adjoint(); + } for_each( - [&start1](auto& x, auto& x_size) { + [](auto& x, auto& x_size) { + size_t start2 = x_size.size(); const auto stack_size = x.size(); - for (size_t i = (start1 == 0U) ? 0U : (start1 - 1); i < stack_size; + for (size_t i = (start2 == 0U) ? 0U : (start2 - 1); i < stack_size; ++i) { x[i]->set_zero_adjoint(); } diff --git a/stan/math/rev/core/start_nested.hpp b/stan/math/rev/core/start_nested.hpp index a667f695136..fcd9b8170ea 100644 --- a/stan/math/rev/core/start_nested.hpp +++ b/stan/math/rev/core/start_nested.hpp @@ -19,9 +19,7 @@ static inline void start_nested() { ChainableStack::instance_->var_stack_.size()); for_each( [](auto& x, auto& y) { - if (y.size() > 0) { x.push_back(y.size()); - } }, ChainableStack::instance_->nested_var_zeroing_stack_sizes_, ChainableStack::instance_->var_zeroing_stacks_); diff --git a/stan/math/rev/core/vari.hpp b/stan/math/rev/core/vari.hpp index 37ec7ae49f9..18572df3db5 100644 --- a/stan/math/rev/core/vari.hpp +++ b/stan/math/rev/core/vari.hpp @@ -29,6 +29,7 @@ class vari_base { * on which it depends. */ virtual void chain() {} + virtual void set_zero_adjoint() {} virtual ~vari_base() {} }; /** @@ -81,9 +82,6 @@ class vari_value::value>> template ::value>* = nullptr> vari_value(S x) noexcept : val_(x), adj_(0.0) { // NOLINT - std::get*>>( - ChainableStack::instance_->var_zeroing_stacks_) - .emplace_back(this); ChainableStack::instance_->var_stack_.emplace_back(this); } @@ -107,11 +105,12 @@ class vari_value::value>> template ::value>* = nullptr> vari_value(S x, bool stacked) noexcept : val_(x), adj_(0.0) { - std::get*>>( - ChainableStack::instance_->var_zeroing_stacks_) - .emplace_back(this); if (stacked) { ChainableStack::instance_->var_stack_.emplace_back(this); + } else { + std::get*>>( + ChainableStack::instance_->var_zeroing_stacks_) + .emplace_back(this); } } @@ -121,9 +120,6 @@ class vari_value::value>> * @param x A vari_value */ vari_value(const vari_value& x) noexcept : val_(x.val_), adj_(x.adj_) { - std::get*>>( - ChainableStack::instance_->var_zeroing_stacks_) - .emplace_back(this); ChainableStack::instance_->var_stack_.emplace_back(this); } @@ -140,7 +136,7 @@ class vari_value::value>> * reset adjoints before propagating derivatives again (for * example in a Jacobian calculation). */ - inline void set_zero_adjoint() noexcept { adj_ = 0.0; } + inline void set_zero_adjoint() noexcept final { adj_ = 0.0; } /** * Insertion operator for vari. Prints the current value and From 8b2a934aec3f739a3d26c3f73edca25eb71f2404 Mon Sep 17 00:00:00 2001 From: Stan Jenkins Date: Fri, 19 Jun 2020 15:42:24 -0400 Subject: [PATCH 108/355] [Jenkins] auto-formatting by clang-format version 6.0.0-1ubuntu2 (tags/RELEASE_600/final) --- stan/math/rev/core/start_nested.hpp | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/stan/math/rev/core/start_nested.hpp b/stan/math/rev/core/start_nested.hpp index fcd9b8170ea..241b0aa9a2e 100644 --- a/stan/math/rev/core/start_nested.hpp +++ b/stan/math/rev/core/start_nested.hpp @@ -17,12 +17,9 @@ namespace math { static inline void start_nested() { ChainableStack::instance_->nested_var_stack_sizes_.push_back( ChainableStack::instance_->var_stack_.size()); - for_each( - [](auto& x, auto& y) { - x.push_back(y.size()); - }, - ChainableStack::instance_->nested_var_zeroing_stack_sizes_, - ChainableStack::instance_->var_zeroing_stacks_); + for_each([](auto& x, auto& y) { x.push_back(y.size()); }, + ChainableStack::instance_->nested_var_zeroing_stack_sizes_, + ChainableStack::instance_->var_zeroing_stacks_); ChainableStack::instance_->nested_var_alloc_stack_starts_.push_back( ChainableStack::instance_->var_alloc_stack_.size()); ChainableStack::instance_->memalloc_.start_nested(); From 72fefc4df68265998654eabba5b2c972cf25238e Mon Sep 17 00:00:00 2001 From: Steve Bronder Date: Sat, 20 Jun 2020 00:21:31 -0400 Subject: [PATCH 109/355] Fix bad stack sizes --- stan/math/rev/core/autodiffstackstorage.hpp | 2 +- stan/math/rev/core/start_nested.hpp | 6 +++++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/stan/math/rev/core/autodiffstackstorage.hpp b/stan/math/rev/core/autodiffstackstorage.hpp index 2a31d146eb0..7a2ddde45ad 100644 --- a/stan/math/rev/core/autodiffstackstorage.hpp +++ b/stan/math/rev/core/autodiffstackstorage.hpp @@ -113,7 +113,7 @@ struct AutodiffStackSingleton { // nested positions std::vector nested_var_stack_sizes_; std::array, std::tuple_size::value> - nested_var_zeroing_stack_sizes_{std::vector{1, 0}}; + nested_var_zeroing_stack_sizes_; std::vector nested_var_alloc_stack_starts_; }; diff --git a/stan/math/rev/core/start_nested.hpp b/stan/math/rev/core/start_nested.hpp index 241b0aa9a2e..9c37d76195b 100644 --- a/stan/math/rev/core/start_nested.hpp +++ b/stan/math/rev/core/start_nested.hpp @@ -17,7 +17,11 @@ namespace math { static inline void start_nested() { ChainableStack::instance_->nested_var_stack_sizes_.push_back( ChainableStack::instance_->var_stack_.size()); - for_each([](auto& x, auto& y) { x.push_back(y.size()); }, + for_each([](auto& x, auto& y) { + if (y.size() > 0) { + x.push_back(y.size()); + } + }, ChainableStack::instance_->nested_var_zeroing_stack_sizes_, ChainableStack::instance_->var_zeroing_stacks_); ChainableStack::instance_->nested_var_alloc_stack_starts_.push_back( From 16919852efc0f2fdde16bb3bd30c13dc3bc22af4 Mon Sep 17 00:00:00 2001 From: Steve Bronder Date: Sat, 20 Jun 2020 00:32:31 -0400 Subject: [PATCH 110/355] use make_unique in ad_tape_observer --- stan/math/rev/core/init_chainablestack.hpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/stan/math/rev/core/init_chainablestack.hpp b/stan/math/rev/core/init_chainablestack.hpp index 4104e388081..5df2f797012 100644 --- a/stan/math/rev/core/init_chainablestack.hpp +++ b/stan/math/rev/core/init_chainablestack.hpp @@ -23,7 +23,7 @@ namespace math { * Refer to https://software.intel.com/en-us/node/506314 for details * on the observer concept. */ -class ad_tape_observer : public tbb::task_scheduler_observer { +class ad_tape_observer final : public tbb::task_scheduler_observer { using stack_ptr = std::unique_ptr; using ad_map = std::unordered_map; @@ -43,7 +43,7 @@ class ad_tape_observer : public tbb::task_scheduler_observer { bool status = false; std::tie(insert_elem, status) = thread_tape_map_.emplace(ad_map::value_type{thread_id, nullptr}); - insert_elem->second = stack_ptr(new ChainableStack()); + insert_elem->second = std::move(std::make_unique()); } } From c1e3d0e5f4fe703567e10ff1d6adbfd3bc203383 Mon Sep 17 00:00:00 2001 From: Stan Jenkins Date: Sat, 20 Jun 2020 01:18:10 -0400 Subject: [PATCH 111/355] [Jenkins] auto-formatting by clang-format version 6.0.0-1ubuntu2 (tags/RELEASE_600/final) --- stan/math/rev/core/start_nested.hpp | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/stan/math/rev/core/start_nested.hpp b/stan/math/rev/core/start_nested.hpp index 9c37d76195b..a667f695136 100644 --- a/stan/math/rev/core/start_nested.hpp +++ b/stan/math/rev/core/start_nested.hpp @@ -17,13 +17,14 @@ namespace math { static inline void start_nested() { ChainableStack::instance_->nested_var_stack_sizes_.push_back( ChainableStack::instance_->var_stack_.size()); - for_each([](auto& x, auto& y) { - if (y.size() > 0) { - x.push_back(y.size()); - } - }, - ChainableStack::instance_->nested_var_zeroing_stack_sizes_, - ChainableStack::instance_->var_zeroing_stacks_); + for_each( + [](auto& x, auto& y) { + if (y.size() > 0) { + x.push_back(y.size()); + } + }, + ChainableStack::instance_->nested_var_zeroing_stack_sizes_, + ChainableStack::instance_->var_zeroing_stacks_); ChainableStack::instance_->nested_var_alloc_stack_starts_.push_back( ChainableStack::instance_->var_alloc_stack_.size()); ChainableStack::instance_->memalloc_.start_nested(); From 4409bfd92a95003f7b192d0b338dbd659016b417 Mon Sep 17 00:00:00 2001 From: Steve Bronder Date: Tue, 23 Jun 2020 14:49:26 -0400 Subject: [PATCH 112/355] update to fix mem bug in mpi tests --- stan/math/rev/core/start_nested.hpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/stan/math/rev/core/start_nested.hpp b/stan/math/rev/core/start_nested.hpp index a667f695136..fcd9b8170ea 100644 --- a/stan/math/rev/core/start_nested.hpp +++ b/stan/math/rev/core/start_nested.hpp @@ -19,9 +19,7 @@ static inline void start_nested() { ChainableStack::instance_->var_stack_.size()); for_each( [](auto& x, auto& y) { - if (y.size() > 0) { x.push_back(y.size()); - } }, ChainableStack::instance_->nested_var_zeroing_stack_sizes_, ChainableStack::instance_->var_zeroing_stacks_); From 725555483cc4d90a27db0aa32832a2e1324466cf Mon Sep 17 00:00:00 2001 From: Stan Jenkins Date: Tue, 23 Jun 2020 18:50:03 +0000 Subject: [PATCH 113/355] [Jenkins] auto-formatting by clang-format version 6.0.0-1ubuntu2~16.04.1 (tags/RELEASE_600/final) --- stan/math/rev/core/start_nested.hpp | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/stan/math/rev/core/start_nested.hpp b/stan/math/rev/core/start_nested.hpp index fcd9b8170ea..241b0aa9a2e 100644 --- a/stan/math/rev/core/start_nested.hpp +++ b/stan/math/rev/core/start_nested.hpp @@ -17,12 +17,9 @@ namespace math { static inline void start_nested() { ChainableStack::instance_->nested_var_stack_sizes_.push_back( ChainableStack::instance_->var_stack_.size()); - for_each( - [](auto& x, auto& y) { - x.push_back(y.size()); - }, - ChainableStack::instance_->nested_var_zeroing_stack_sizes_, - ChainableStack::instance_->var_zeroing_stacks_); + for_each([](auto& x, auto& y) { x.push_back(y.size()); }, + ChainableStack::instance_->nested_var_zeroing_stack_sizes_, + ChainableStack::instance_->var_zeroing_stacks_); ChainableStack::instance_->nested_var_alloc_stack_starts_.push_back( ChainableStack::instance_->var_alloc_stack_.size()); ChainableStack::instance_->memalloc_.start_nested(); From 5e9f707f88975ef6704b3875fe839126df074a15 Mon Sep 17 00:00:00 2001 From: Steve Bronder Date: Wed, 24 Jun 2020 14:52:40 -0400 Subject: [PATCH 114/355] move back to virtual methods --- stan/math/rev/core/var.hpp | 14 -------------- stan/math/rev/core/vari.hpp | 20 ++------------------ 2 files changed, 2 insertions(+), 32 deletions(-) diff --git a/stan/math/rev/core/var.hpp b/stan/math/rev/core/var.hpp index c8001d28963..e3705fdbdd9 100644 --- a/stan/math/rev/core/var.hpp +++ b/stan/math/rev/core/var.hpp @@ -40,12 +40,6 @@ class var_value> { using value_type = std::decay_t; using vari_type = vari_value; using vari_pointer = vari_type*; - template - using require_vari_convertible_t - = require_t*, vari_pointer>>; - template - using require_not_vari_convertible_t = require_t< - bool_constant*, vari_pointer>::value>>; /** * Pointer to the implementation of this variable. @@ -97,14 +91,6 @@ class var_value> { var_value(vari_value* vi) // NOLINT : vi_(vi) {} - /** - * Constructor from `var_value` whose value_type is the same as this class's - * `value_type`. This is used in cases such as - * `var_value a(4.0); var_value b(a)` since the `value_type` for - * a `var_value` with an integral type is a double. - */ - var_value(const var_value& x) : vi_(x.vi_) {} // NOLINT - /** * Return a constant reference to the value of this variable. * diff --git a/stan/math/rev/core/vari.hpp b/stan/math/rev/core/vari.hpp index 81066ffbeaf..a5fd3df62ec 100644 --- a/stan/math/rev/core/vari.hpp +++ b/stan/math/rev/core/vari.hpp @@ -17,7 +17,7 @@ class var_value; class vari_base { public: virtual void chain() {} - virtual void set_zero_adjoint() noexcept {} + inline virtual void set_zero_adjoint() noexcept {} }; /** * The variable implementation base class. @@ -104,22 +104,6 @@ class vari_value::value>> : public } } - /** - * Constructor from vari_value - * @tparam S An arithmetic type - * @param x A vari_value - */ - vari_value(const vari_value& x) noexcept : val_(x.val_), adj_(x.adj_) { - ChainableStack::instance_->var_stack_.emplace_back(this); - } - /** - * Constructor from vari_value - * @tparam S An arithmetic type - * @param x A vari_value - */ - vari_value(vari_value&& x) noexcept : val_(x.val_), adj_(x.adj_) { - ChainableStack::instance_->var_stack_.emplace_back(this); - } /** * Initialize the adjoint for this (dependent) variable to 1. @@ -134,7 +118,7 @@ class vari_value::value>> : public * reset adjoints before propagating derivatives again (for * example in a Jacobian calculation). */ - void set_zero_adjoint() noexcept final { adj_ = 0.0; } + inline void set_zero_adjoint() noexcept final { adj_ = 0.0; } /** * Insertion operator for vari. Prints the current value and From 330af390fe62cad22930601d9e02f3f7f062e795 Mon Sep 17 00:00:00 2001 From: Stan Jenkins Date: Wed, 24 Jun 2020 15:39:27 -0400 Subject: [PATCH 115/355] [Jenkins] auto-formatting by clang-format version 6.0.0-1ubuntu2 (tags/RELEASE_600/final) --- stan/math/rev/core/autodiffstackstorage.hpp | 84 +++++++++---------- stan/math/rev/core/chainablestack.hpp | 3 +- stan/math/rev/core/recover_memory.hpp | 24 +++--- stan/math/rev/core/recover_memory_nested.hpp | 48 +++++------ stan/math/rev/core/set_zero_all_adjoints.hpp | 12 +-- .../rev/core/set_zero_all_adjoints_nested.hpp | 34 ++++---- stan/math/rev/core/start_nested.hpp | 14 ++-- stan/math/rev/core/vari.hpp | 4 +- 8 files changed, 111 insertions(+), 112 deletions(-) diff --git a/stan/math/rev/core/autodiffstackstorage.hpp b/stan/math/rev/core/autodiffstackstorage.hpp index a349d3968fd..93578cbbc63 100644 --- a/stan/math/rev/core/autodiffstackstorage.hpp +++ b/stan/math/rev/core/autodiffstackstorage.hpp @@ -91,60 +91,60 @@ class vari_value; */ template struct AutodiffStackSingleton { - using AutodiffStackSingleton_t - = AutodiffStackSingleton; + using AutodiffStackSingleton_t + = AutodiffStackSingleton; - AutodiffStackSingleton() : own_instance_(init()) {} - ~AutodiffStackSingleton() { - if (own_instance_) { - delete instance_; - instance_ = nullptr; - } - } + AutodiffStackSingleton() : own_instance_(init()) {} + ~AutodiffStackSingleton() { + if (own_instance_) { + delete instance_; + instance_ = nullptr; + } + } - struct AutodiffStackStorage { - AutodiffStackStorage &operator=(const AutodiffStackStorage &) = delete; + struct AutodiffStackStorage { + AutodiffStackStorage &operator=(const AutodiffStackStorage &) = delete; - std::vector var_stack_; - std::vector var_nochain_stack_; - std::vector var_alloc_stack_; - stack_alloc memalloc_; + std::vector var_stack_; + std::vector var_nochain_stack_; + std::vector var_alloc_stack_; + stack_alloc memalloc_; - // nested positions - std::vector nested_var_stack_sizes_; - std::vector nested_var_nochain_stack_sizes_; - std::vector nested_var_alloc_stack_starts_; - }; + // nested positions + std::vector nested_var_stack_sizes_; + std::vector nested_var_nochain_stack_sizes_; + std::vector nested_var_alloc_stack_starts_; + }; - explicit AutodiffStackSingleton(AutodiffStackSingleton_t const &) = delete; - AutodiffStackSingleton &operator=(const AutodiffStackSingleton_t &) = delete; + explicit AutodiffStackSingleton(AutodiffStackSingleton_t const &) = delete; + AutodiffStackSingleton &operator=(const AutodiffStackSingleton_t &) = delete; - static STAN_THREADS_DEF AutodiffStackStorage *instance_; + static STAN_THREADS_DEF AutodiffStackStorage *instance_; -private: - static bool init() { - static STAN_THREADS_DEF bool is_initialized = false; - if (!is_initialized) { - is_initialized = true; - instance_ = new AutodiffStackStorage(); - return true; - } - if (!instance_) { - is_initialized = true; - instance_ = new AutodiffStackStorage(); - return true; - } - return false; - } + private: + static bool init() { + static STAN_THREADS_DEF bool is_initialized = false; + if (!is_initialized) { + is_initialized = true; + instance_ = new AutodiffStackStorage(); + return true; + } + if (!instance_) { + is_initialized = true; + instance_ = new AutodiffStackStorage(); + return true; + } + return false; + } - bool own_instance_; + bool own_instance_; }; template STAN_THREADS_DEF - typename AutodiffStackSingleton::AutodiffStackStorage - *AutodiffStackSingleton::instance_; + typename AutodiffStackSingleton::AutodiffStackStorage + *AutodiffStackSingleton::instance_; } // namespace math } // namespace stan diff --git a/stan/math/rev/core/chainablestack.hpp b/stan/math/rev/core/chainablestack.hpp index bbf82f47a4d..d383fabdcf9 100644 --- a/stan/math/rev/core/chainablestack.hpp +++ b/stan/math/rev/core/chainablestack.hpp @@ -10,8 +10,7 @@ template class vari_value; class vari_base; class chainable_alloc; -using ChainableStack - = AutodiffStackSingleton; +using ChainableStack = AutodiffStackSingleton; } // namespace math } // namespace stan diff --git a/stan/math/rev/core/recover_memory.hpp b/stan/math/rev/core/recover_memory.hpp index 205d63946b1..c8ec7e92b66 100644 --- a/stan/math/rev/core/recover_memory.hpp +++ b/stan/math/rev/core/recover_memory.hpp @@ -16,18 +16,18 @@ namespace math { * false */ static inline void recover_memory() { - if (!empty_nested()) { - throw std::logic_error( - "empty_nested() must be true" - " before calling recover_memory()"); - } - ChainableStack::instance_->var_stack_.clear(); - ChainableStack::instance_->var_nochain_stack_.clear(); - for (auto &x : ChainableStack::instance_->var_alloc_stack_) { - delete x; - } - ChainableStack::instance_->var_alloc_stack_.clear(); - ChainableStack::instance_->memalloc_.recover_all(); + if (!empty_nested()) { + throw std::logic_error( + "empty_nested() must be true" + " before calling recover_memory()"); + } + ChainableStack::instance_->var_stack_.clear(); + ChainableStack::instance_->var_nochain_stack_.clear(); + for (auto &x : ChainableStack::instance_->var_alloc_stack_) { + delete x; + } + ChainableStack::instance_->var_alloc_stack_.clear(); + ChainableStack::instance_->memalloc_.recover_all(); } } // namespace math diff --git a/stan/math/rev/core/recover_memory_nested.hpp b/stan/math/rev/core/recover_memory_nested.hpp index d1654819953..1cd493a1a11 100644 --- a/stan/math/rev/core/recover_memory_nested.hpp +++ b/stan/math/rev/core/recover_memory_nested.hpp @@ -21,30 +21,30 @@ namespace math { * true */ static inline void recover_memory_nested() { - if (empty_nested()) { - throw std::logic_error( - "empty_nested() must be false" - " before calling recover_memory_nested()"); - } - - ChainableStack::instance_->var_stack_.resize( - ChainableStack::instance_->nested_var_stack_sizes_.back()); - ChainableStack::instance_->nested_var_stack_sizes_.pop_back(); - - ChainableStack::instance_->var_nochain_stack_.resize( - ChainableStack::instance_->nested_var_nochain_stack_sizes_.back()); - ChainableStack::instance_->nested_var_nochain_stack_sizes_.pop_back(); - - for (size_t i - = ChainableStack::instance_->nested_var_alloc_stack_starts_.back(); - i < ChainableStack::instance_->var_alloc_stack_.size(); ++i) { - delete ChainableStack::instance_->var_alloc_stack_[i]; - } - ChainableStack::instance_->var_alloc_stack_.resize( - ChainableStack::instance_->nested_var_alloc_stack_starts_.back()); - ChainableStack::instance_->nested_var_alloc_stack_starts_.pop_back(); - - ChainableStack::instance_->memalloc_.recover_nested(); + if (empty_nested()) { + throw std::logic_error( + "empty_nested() must be false" + " before calling recover_memory_nested()"); + } + + ChainableStack::instance_->var_stack_.resize( + ChainableStack::instance_->nested_var_stack_sizes_.back()); + ChainableStack::instance_->nested_var_stack_sizes_.pop_back(); + + ChainableStack::instance_->var_nochain_stack_.resize( + ChainableStack::instance_->nested_var_nochain_stack_sizes_.back()); + ChainableStack::instance_->nested_var_nochain_stack_sizes_.pop_back(); + + for (size_t i + = ChainableStack::instance_->nested_var_alloc_stack_starts_.back(); + i < ChainableStack::instance_->var_alloc_stack_.size(); ++i) { + delete ChainableStack::instance_->var_alloc_stack_[i]; + } + ChainableStack::instance_->var_alloc_stack_.resize( + ChainableStack::instance_->nested_var_alloc_stack_starts_.back()); + ChainableStack::instance_->nested_var_alloc_stack_starts_.pop_back(); + + ChainableStack::instance_->memalloc_.recover_nested(); } } // namespace math diff --git a/stan/math/rev/core/set_zero_all_adjoints.hpp b/stan/math/rev/core/set_zero_all_adjoints.hpp index f690ef96410..841ef6d5c60 100644 --- a/stan/math/rev/core/set_zero_all_adjoints.hpp +++ b/stan/math/rev/core/set_zero_all_adjoints.hpp @@ -12,12 +12,12 @@ namespace math { * Reset all adjoint values in the stack to zero. */ static void set_zero_all_adjoints() { - for (auto &x : ChainableStack::instance_->var_stack_) { - x->set_zero_adjoint(); - } - for (auto &x : ChainableStack::instance_->var_nochain_stack_) { - x->set_zero_adjoint(); - } + for (auto &x : ChainableStack::instance_->var_stack_) { + x->set_zero_adjoint(); + } + for (auto &x : ChainableStack::instance_->var_nochain_stack_) { + x->set_zero_adjoint(); + } } } // namespace math diff --git a/stan/math/rev/core/set_zero_all_adjoints_nested.hpp b/stan/math/rev/core/set_zero_all_adjoints_nested.hpp index 5e8df6404d8..34dc367556c 100644 --- a/stan/math/rev/core/set_zero_all_adjoints_nested.hpp +++ b/stan/math/rev/core/set_zero_all_adjoints_nested.hpp @@ -18,24 +18,24 @@ namespace math { * nested autodiff class as it handles recovery of memory automatically. */ static void set_zero_all_adjoints_nested() { - if (empty_nested()) { - throw std::logic_error( - "empty_nested() must be false before calling" - " set_zero_all_adjoints_nested()"); - } - size_t start1 = ChainableStack::instance_->nested_var_stack_sizes_.back(); - // avoid wrap with unsigned when start1 == 0 - for (size_t i = (start1 == 0U) ? 0U : (start1 - 1); - i < ChainableStack::instance_->var_stack_.size(); ++i) { - ChainableStack::instance_->var_stack_[i]->set_zero_adjoint(); - } + if (empty_nested()) { + throw std::logic_error( + "empty_nested() must be false before calling" + " set_zero_all_adjoints_nested()"); + } + size_t start1 = ChainableStack::instance_->nested_var_stack_sizes_.back(); + // avoid wrap with unsigned when start1 == 0 + for (size_t i = (start1 == 0U) ? 0U : (start1 - 1); + i < ChainableStack::instance_->var_stack_.size(); ++i) { + ChainableStack::instance_->var_stack_[i]->set_zero_adjoint(); + } - size_t start2 - = ChainableStack::instance_->nested_var_nochain_stack_sizes_.back(); - for (size_t i = (start2 == 0U) ? 0U : (start2 - 1); - i < ChainableStack::instance_->var_nochain_stack_.size(); ++i) { - ChainableStack::instance_->var_nochain_stack_[i]->set_zero_adjoint(); - } + size_t start2 + = ChainableStack::instance_->nested_var_nochain_stack_sizes_.back(); + for (size_t i = (start2 == 0U) ? 0U : (start2 - 1); + i < ChainableStack::instance_->var_nochain_stack_.size(); ++i) { + ChainableStack::instance_->var_nochain_stack_[i]->set_zero_adjoint(); + } } } // namespace math diff --git a/stan/math/rev/core/start_nested.hpp b/stan/math/rev/core/start_nested.hpp index 9b9ef395772..d17ff7e153b 100644 --- a/stan/math/rev/core/start_nested.hpp +++ b/stan/math/rev/core/start_nested.hpp @@ -14,13 +14,13 @@ namespace math { * nested autodiff as it handles recovery of memory automatically. */ static inline void start_nested() { - ChainableStack::instance_->nested_var_stack_sizes_.push_back( - ChainableStack::instance_->var_stack_.size()); - ChainableStack::instance_->nested_var_nochain_stack_sizes_.push_back( - ChainableStack::instance_->var_nochain_stack_.size()); - ChainableStack::instance_->nested_var_alloc_stack_starts_.push_back( - ChainableStack::instance_->var_alloc_stack_.size()); - ChainableStack::instance_->memalloc_.start_nested(); + ChainableStack::instance_->nested_var_stack_sizes_.push_back( + ChainableStack::instance_->var_stack_.size()); + ChainableStack::instance_->nested_var_nochain_stack_sizes_.push_back( + ChainableStack::instance_->var_nochain_stack_.size()); + ChainableStack::instance_->nested_var_alloc_stack_starts_.push_back( + ChainableStack::instance_->var_alloc_stack_.size()); + ChainableStack::instance_->memalloc_.start_nested(); } } // namespace math diff --git a/stan/math/rev/core/vari.hpp b/stan/math/rev/core/vari.hpp index 4b40fd2a261..294cece21bb 100644 --- a/stan/math/rev/core/vari.hpp +++ b/stan/math/rev/core/vari.hpp @@ -108,7 +108,7 @@ class vari_value::value>> if (stacked) { ChainableStack::instance_->var_stack_.emplace_back(this); } else { - ChainableStack::instance_->var_nochain_stack_.emplace_back(this); + ChainableStack::instance_->var_nochain_stack_.emplace_back(this); } } @@ -123,7 +123,7 @@ class vari_value::value>> ~vari_value() = default; - inline void chain() {} + inline void chain() {} /** * Initialize the adjoint for this (dependent) variable to 1. From 73e6599a1f47b456066e7f25e5c6faf5081f23b1 Mon Sep 17 00:00:00 2001 From: Steve Bronder Date: Wed, 24 Jun 2020 16:33:49 -0400 Subject: [PATCH 116/355] remove references to zero_stack from tests --- .../rev/core/thread_stack_instance_test.cpp | 8 ++-- test/unit/math/rev/err/check_bounded_test.cpp | 16 ++++---- .../rev/err/check_consistent_size_test.cpp | 8 ++-- .../rev/err/check_consistent_sizes_test.cpp | 8 ++-- test/unit/math/rev/err/check_finite_test.cpp | 24 +++++------ .../rev/err/check_greater_or_equal_test.cpp | 24 +++++------ test/unit/math/rev/err/check_greater_test.cpp | 24 +++++------ .../math/rev/err/check_less_or_equal_test.cpp | 28 ++++++------- test/unit/math/rev/err/check_less_test.cpp | 24 +++++------ .../math/rev/err/check_nonnegative_test.cpp | 40 +++++++++---------- test/unit/math/rev/err/check_not_nan_test.cpp | 32 +++++++-------- .../rev/err/check_pos_semidefinite_test.cpp | 8 ++-- .../rev/err/check_positive_finite_test.cpp | 20 +++++----- .../unit/math/rev/err/check_positive_test.cpp | 8 ++-- 14 files changed, 136 insertions(+), 136 deletions(-) diff --git a/test/unit/math/rev/core/thread_stack_instance_test.cpp b/test/unit/math/rev/core/thread_stack_instance_test.cpp index ce610781d15..9fba740b45e 100644 --- a/test/unit/math/rev/core/thread_stack_instance_test.cpp +++ b/test/unit/math/rev/core/thread_stack_instance_test.cpp @@ -93,8 +93,8 @@ TEST(thread_stack_instance, child_instances) { ChainableStack thread_instance; EXPECT_TRUE( main_ad_stack->var_stack_.size() - + std::get>( - stan::math::ChainableStack::instance_->var_zeroing_stacks_) + + + stan::math::ChainableStack::instance_->var_nochain_stack_ .size() #ifdef STAN_THREADS > @@ -102,8 +102,8 @@ TEST(thread_stack_instance, child_instances) { == #endif ChainableStack::instance_->var_stack_.size() - + std::get>( - stan::math::ChainableStack::instance_->var_zeroing_stacks_) + + + stan::math::ChainableStack::instance_->var_nochain_stack_ .size()); }; diff --git a/test/unit/math/rev/err/check_bounded_test.cpp b/test/unit/math/rev/err/check_bounded_test.cpp index c9fcb02b82a..59b593c5714 100644 --- a/test/unit/math/rev/err/check_bounded_test.cpp +++ b/test/unit/math/rev/err/check_bounded_test.cpp @@ -17,8 +17,8 @@ TEST(AgradRevErrorHandlingScalar, CheckBoundedVarCheckVectorized) { size_t stack_size = stan::math::ChainableStack::instance_->var_stack_.size() - + std::get>( - stan::math::ChainableStack::instance_->var_zeroing_stacks_) + + + stan::math::ChainableStack::instance_->var_nochain_stack_ .size(); EXPECT_EQ(5U, stack_size); @@ -26,8 +26,8 @@ TEST(AgradRevErrorHandlingScalar, CheckBoundedVarCheckVectorized) { size_t stack_size_after_call = stan::math::ChainableStack::instance_->var_stack_.size() - + std::get>( - stan::math::ChainableStack::instance_->var_zeroing_stacks_) + + + stan::math::ChainableStack::instance_->var_nochain_stack_ .size(); EXPECT_EQ(5U, stack_size_after_call); stan::math::recover_memory(); @@ -154,8 +154,8 @@ TEST(AgradRevErrorHandlingScalar, CheckBoundedVarCheckUnivariate) { size_t stack_size = stan::math::ChainableStack::instance_->var_stack_.size() - + std::get>( - stan::math::ChainableStack::instance_->var_zeroing_stacks_) + + + stan::math::ChainableStack::instance_->var_nochain_stack_ .size(); EXPECT_EQ(1U, stack_size); @@ -163,8 +163,8 @@ TEST(AgradRevErrorHandlingScalar, CheckBoundedVarCheckUnivariate) { size_t stack_size_after_call = stan::math::ChainableStack::instance_->var_stack_.size() - + std::get>( - stan::math::ChainableStack::instance_->var_zeroing_stacks_) + + + stan::math::ChainableStack::instance_->var_nochain_stack_ .size(); EXPECT_EQ(1U, stack_size_after_call); diff --git a/test/unit/math/rev/err/check_consistent_size_test.cpp b/test/unit/math/rev/err/check_consistent_size_test.cpp index 4f613901d48..12850980bb5 100644 --- a/test/unit/math/rev/err/check_consistent_size_test.cpp +++ b/test/unit/math/rev/err/check_consistent_size_test.cpp @@ -17,8 +17,8 @@ TEST(AgradRevErrorHandlingScalar, CheckConsistentSizeVarCheckVectorized) { size_t stack_size = stan::math::ChainableStack::instance_->var_stack_.size() - + std::get>( - stan::math::ChainableStack::instance_->var_zeroing_stacks_) + + + stan::math::ChainableStack::instance_->var_nochain_stack_ .size(); EXPECT_EQ(5U, stack_size); @@ -26,8 +26,8 @@ TEST(AgradRevErrorHandlingScalar, CheckConsistentSizeVarCheckVectorized) { size_t stack_size_after_call = stan::math::ChainableStack::instance_->var_stack_.size() - + std::get>( - stan::math::ChainableStack::instance_->var_zeroing_stacks_) + + + stan::math::ChainableStack::instance_->var_nochain_stack_ .size(); EXPECT_EQ(5U, stack_size_after_call); stan::math::recover_memory(); diff --git a/test/unit/math/rev/err/check_consistent_sizes_test.cpp b/test/unit/math/rev/err/check_consistent_sizes_test.cpp index e2e6be8656a..b9b1644efa8 100644 --- a/test/unit/math/rev/err/check_consistent_sizes_test.cpp +++ b/test/unit/math/rev/err/check_consistent_sizes_test.cpp @@ -19,8 +19,8 @@ TEST(AgradRevErrorHandlingScalar, CheckConsistentSizesVarCheckVectorized) { size_t stack_size = stan::math::ChainableStack::instance_->var_stack_.size() - + std::get>( - stan::math::ChainableStack::instance_->var_zeroing_stacks_) + + + stan::math::ChainableStack::instance_->var_nochain_stack_ .size(); EXPECT_EQ(10U, stack_size); @@ -28,8 +28,8 @@ TEST(AgradRevErrorHandlingScalar, CheckConsistentSizesVarCheckVectorized) { size_t stack_size_after_call = stan::math::ChainableStack::instance_->var_stack_.size() - + std::get>( - stan::math::ChainableStack::instance_->var_zeroing_stacks_) + + + stan::math::ChainableStack::instance_->var_nochain_stack_ .size(); EXPECT_EQ(10U, stack_size_after_call); stan::math::recover_memory(); diff --git a/test/unit/math/rev/err/check_finite_test.cpp b/test/unit/math/rev/err/check_finite_test.cpp index 1e2acbca5b4..db346a90537 100644 --- a/test/unit/math/rev/err/check_finite_test.cpp +++ b/test/unit/math/rev/err/check_finite_test.cpp @@ -17,8 +17,8 @@ TEST(AgradRevErrorHandlingScalar, CheckFiniteVarCheckVectorized) { size_t stack_size = stan::math::ChainableStack::instance_->var_stack_.size() - + std::get>( - stan::math::ChainableStack::instance_->var_zeroing_stacks_) + + + stan::math::ChainableStack::instance_->var_nochain_stack_ .size(); EXPECT_EQ(5U, stack_size); @@ -26,8 +26,8 @@ TEST(AgradRevErrorHandlingScalar, CheckFiniteVarCheckVectorized) { size_t stack_size_after_call = stan::math::ChainableStack::instance_->var_stack_.size() - + std::get>( - stan::math::ChainableStack::instance_->var_zeroing_stacks_) + + + stan::math::ChainableStack::instance_->var_nochain_stack_ .size(); EXPECT_EQ(5U, stack_size_after_call); @@ -35,8 +35,8 @@ TEST(AgradRevErrorHandlingScalar, CheckFiniteVarCheckVectorized) { EXPECT_THROW(check_finite(function, "a", a), std::domain_error); stack_size_after_call = stan::math::ChainableStack::instance_->var_stack_.size() - + std::get>( - stan::math::ChainableStack::instance_->var_zeroing_stacks_) + + + stan::math::ChainableStack::instance_->var_nochain_stack_ .size(); EXPECT_EQ(6U, stack_size_after_call); @@ -77,8 +77,8 @@ TEST(AgradRevErrorHandlingScalar, CheckFiniteVarCheckUnivariate) { size_t stack_size = stan::math::ChainableStack::instance_->var_stack_.size() - + std::get>( - stan::math::ChainableStack::instance_->var_zeroing_stacks_) + + + stan::math::ChainableStack::instance_->var_nochain_stack_ .size(); EXPECT_EQ(1U, stack_size); @@ -86,8 +86,8 @@ TEST(AgradRevErrorHandlingScalar, CheckFiniteVarCheckUnivariate) { size_t stack_size_after_call = stan::math::ChainableStack::instance_->var_stack_.size() - + std::get>( - stan::math::ChainableStack::instance_->var_zeroing_stacks_) + + + stan::math::ChainableStack::instance_->var_nochain_stack_ .size(); EXPECT_EQ(1U, stack_size_after_call); @@ -95,8 +95,8 @@ TEST(AgradRevErrorHandlingScalar, CheckFiniteVarCheckUnivariate) { EXPECT_THROW(check_finite(function, "a", a), std::domain_error); stack_size_after_call = stan::math::ChainableStack::instance_->var_stack_.size() - + std::get>( - stan::math::ChainableStack::instance_->var_zeroing_stacks_) + + + stan::math::ChainableStack::instance_->var_nochain_stack_ .size(); EXPECT_EQ(2U, stack_size_after_call); diff --git a/test/unit/math/rev/err/check_greater_or_equal_test.cpp b/test/unit/math/rev/err/check_greater_or_equal_test.cpp index 475901b8582..7fa273468d8 100644 --- a/test/unit/math/rev/err/check_greater_or_equal_test.cpp +++ b/test/unit/math/rev/err/check_greater_or_equal_test.cpp @@ -17,8 +17,8 @@ TEST(AgradRevErrorHandlingScalar, CheckGreateOrEqualVarCheckVectorized) { size_t stack_size = stan::math::ChainableStack::instance_->var_stack_.size() - + std::get>( - stan::math::ChainableStack::instance_->var_zeroing_stacks_) + + + stan::math::ChainableStack::instance_->var_nochain_stack_ .size(); EXPECT_EQ(5U, stack_size); @@ -26,8 +26,8 @@ TEST(AgradRevErrorHandlingScalar, CheckGreateOrEqualVarCheckVectorized) { size_t stack_size_after_call = stan::math::ChainableStack::instance_->var_stack_.size() - + std::get>( - stan::math::ChainableStack::instance_->var_zeroing_stacks_) + + + stan::math::ChainableStack::instance_->var_nochain_stack_ .size(); EXPECT_EQ(5U, stack_size_after_call); @@ -35,8 +35,8 @@ TEST(AgradRevErrorHandlingScalar, CheckGreateOrEqualVarCheckVectorized) { std::domain_error); stack_size_after_call = stan::math::ChainableStack::instance_->var_stack_.size() - + std::get>( - stan::math::ChainableStack::instance_->var_zeroing_stacks_) + + + stan::math::ChainableStack::instance_->var_nochain_stack_ .size(); EXPECT_EQ(5U, stack_size_after_call); @@ -204,8 +204,8 @@ TEST(AgradRevErrorHandlingScalar, CheckGreaterOrEqualVarCheckUnivariate) { size_t stack_size = stan::math::ChainableStack::instance_->var_stack_.size() - + std::get>( - stan::math::ChainableStack::instance_->var_zeroing_stacks_) + + + stan::math::ChainableStack::instance_->var_nochain_stack_ .size(); EXPECT_EQ(1U, stack_size); @@ -213,8 +213,8 @@ TEST(AgradRevErrorHandlingScalar, CheckGreaterOrEqualVarCheckUnivariate) { size_t stack_size_after_call = stan::math::ChainableStack::instance_->var_stack_.size() - + std::get>( - stan::math::ChainableStack::instance_->var_zeroing_stacks_) + + + stan::math::ChainableStack::instance_->var_nochain_stack_ .size(); EXPECT_EQ(1U, stack_size_after_call); @@ -222,8 +222,8 @@ TEST(AgradRevErrorHandlingScalar, CheckGreaterOrEqualVarCheckUnivariate) { std::domain_error); stack_size_after_call = stan::math::ChainableStack::instance_->var_stack_.size() - + std::get>( - stan::math::ChainableStack::instance_->var_zeroing_stacks_) + + + stan::math::ChainableStack::instance_->var_nochain_stack_ .size(); EXPECT_EQ(1U, stack_size_after_call); diff --git a/test/unit/math/rev/err/check_greater_test.cpp b/test/unit/math/rev/err/check_greater_test.cpp index cda6141c8bc..fa9051d1488 100644 --- a/test/unit/math/rev/err/check_greater_test.cpp +++ b/test/unit/math/rev/err/check_greater_test.cpp @@ -16,8 +16,8 @@ TEST(AgradRevErrorHandlingScalar, CheckGreaterVarCheckVectorized) { size_t stack_size = stan::math::ChainableStack::instance_->var_stack_.size() - + std::get>( - stan::math::ChainableStack::instance_->var_zeroing_stacks_) + + + stan::math::ChainableStack::instance_->var_nochain_stack_ .size(); EXPECT_EQ(5U, stack_size); @@ -25,16 +25,16 @@ TEST(AgradRevErrorHandlingScalar, CheckGreaterVarCheckVectorized) { size_t stack_size_after_call = stan::math::ChainableStack::instance_->var_stack_.size() - + std::get>( - stan::math::ChainableStack::instance_->var_zeroing_stacks_) + + + stan::math::ChainableStack::instance_->var_nochain_stack_ .size(); EXPECT_EQ(5U, stack_size_after_call); EXPECT_THROW(check_greater(function, "a", a, 2.0), std::domain_error); stack_size_after_call = stan::math::ChainableStack::instance_->var_stack_.size() - + std::get>( - stan::math::ChainableStack::instance_->var_zeroing_stacks_) + + + stan::math::ChainableStack::instance_->var_nochain_stack_ .size(); EXPECT_EQ(5U, stack_size_after_call); @@ -194,8 +194,8 @@ TEST(AgradRevErrorHandlingScalar, CheckGreaterVarCheckUnivariate) { size_t stack_size = stan::math::ChainableStack::instance_->var_stack_.size() - + std::get>( - stan::math::ChainableStack::instance_->var_zeroing_stacks_) + + + stan::math::ChainableStack::instance_->var_nochain_stack_ .size(); EXPECT_EQ(1U, stack_size); @@ -203,16 +203,16 @@ TEST(AgradRevErrorHandlingScalar, CheckGreaterVarCheckUnivariate) { size_t stack_size_after_call = stan::math::ChainableStack::instance_->var_stack_.size() - + std::get>( - stan::math::ChainableStack::instance_->var_zeroing_stacks_) + + + stan::math::ChainableStack::instance_->var_nochain_stack_ .size(); EXPECT_EQ(1U, stack_size_after_call); EXPECT_THROW(check_greater(function, "a", a, 10.0), std::domain_error); stack_size_after_call = stan::math::ChainableStack::instance_->var_stack_.size() - + std::get>( - stan::math::ChainableStack::instance_->var_zeroing_stacks_) + + + stan::math::ChainableStack::instance_->var_nochain_stack_ .size(); EXPECT_EQ(1U, stack_size_after_call); diff --git a/test/unit/math/rev/err/check_less_or_equal_test.cpp b/test/unit/math/rev/err/check_less_or_equal_test.cpp index 1c0cd417aae..9e96d55a855 100644 --- a/test/unit/math/rev/err/check_less_or_equal_test.cpp +++ b/test/unit/math/rev/err/check_less_or_equal_test.cpp @@ -16,8 +16,8 @@ TEST(AgradRevErrorHandlingScalar, CheckLessOrEqualVarCheckVectorized) { size_t stack_size = stan::math::ChainableStack::instance_->var_stack_.size() - + std::get>( - stan::math::ChainableStack::instance_->var_zeroing_stacks_) + + + stan::math::ChainableStack::instance_->var_nochain_stack_ .size(); EXPECT_EQ(5U, stack_size); @@ -25,16 +25,16 @@ TEST(AgradRevErrorHandlingScalar, CheckLessOrEqualVarCheckVectorized) { size_t stack_size_after_call = stan::math::ChainableStack::instance_->var_stack_.size() - + std::get>( - stan::math::ChainableStack::instance_->var_zeroing_stacks_) + + + stan::math::ChainableStack::instance_->var_nochain_stack_ .size(); EXPECT_EQ(5U, stack_size_after_call); EXPECT_THROW(check_less_or_equal(function, "a", a, 2.0), std::domain_error); stack_size_after_call = stan::math::ChainableStack::instance_->var_stack_.size() - + std::get>( - stan::math::ChainableStack::instance_->var_zeroing_stacks_) + + + stan::math::ChainableStack::instance_->var_nochain_stack_ .size(); EXPECT_EQ(5U, stack_size_after_call); @@ -167,8 +167,8 @@ TEST(AgradRevErrorHandlingScalar, CheckLessOrEqualVarCheckUnivariate) { size_t stack_size = stan::math::ChainableStack::instance_->var_stack_.size() - + std::get>( - stan::math::ChainableStack::instance_->var_zeroing_stacks_) + + + stan::math::ChainableStack::instance_->var_nochain_stack_ .size(); EXPECT_EQ(1U, stack_size); @@ -176,8 +176,8 @@ TEST(AgradRevErrorHandlingScalar, CheckLessOrEqualVarCheckUnivariate) { size_t stack_size_after_call = stan::math::ChainableStack::instance_->var_stack_.size() - + std::get>( - stan::math::ChainableStack::instance_->var_zeroing_stacks_) + + + stan::math::ChainableStack::instance_->var_nochain_stack_ .size(); EXPECT_EQ(1U, stack_size_after_call); @@ -185,16 +185,16 @@ TEST(AgradRevErrorHandlingScalar, CheckLessOrEqualVarCheckUnivariate) { stack_size_after_call = stan::math::ChainableStack::instance_->var_stack_.size() - + std::get>( - stan::math::ChainableStack::instance_->var_zeroing_stacks_) + + + stan::math::ChainableStack::instance_->var_nochain_stack_ .size(); EXPECT_EQ(1U, stack_size_after_call); EXPECT_NO_THROW(check_less_or_equal(function, "a", a, 10.0)); stack_size_after_call = stan::math::ChainableStack::instance_->var_stack_.size() - + std::get>( - stan::math::ChainableStack::instance_->var_zeroing_stacks_) + + + stan::math::ChainableStack::instance_->var_nochain_stack_ .size(); EXPECT_EQ(1U, stack_size_after_call); diff --git a/test/unit/math/rev/err/check_less_test.cpp b/test/unit/math/rev/err/check_less_test.cpp index a671b4368b1..3f501c41c33 100644 --- a/test/unit/math/rev/err/check_less_test.cpp +++ b/test/unit/math/rev/err/check_less_test.cpp @@ -16,8 +16,8 @@ TEST(AgradRevErrorHandlingScalar, CheckLessVarCheckVectorized) { size_t stack_size = stan::math::ChainableStack::instance_->var_stack_.size() - + std::get>( - stan::math::ChainableStack::instance_->var_zeroing_stacks_) + + + stan::math::ChainableStack::instance_->var_nochain_stack_ .size(); EXPECT_EQ(5U, stack_size); @@ -25,16 +25,16 @@ TEST(AgradRevErrorHandlingScalar, CheckLessVarCheckVectorized) { size_t stack_size_after_call = stan::math::ChainableStack::instance_->var_stack_.size() - + std::get>( - stan::math::ChainableStack::instance_->var_zeroing_stacks_) + + + stan::math::ChainableStack::instance_->var_nochain_stack_ .size(); EXPECT_EQ(5U, stack_size_after_call); EXPECT_THROW(check_less(function, "a", a, 2.0), std::domain_error); stack_size_after_call = stan::math::ChainableStack::instance_->var_stack_.size() - + std::get>( - stan::math::ChainableStack::instance_->var_zeroing_stacks_) + + + stan::math::ChainableStack::instance_->var_nochain_stack_ .size(); EXPECT_EQ(5U, stack_size_after_call); @@ -164,8 +164,8 @@ TEST(AgradRevErrorHandlingScalar, CheckLessVarCheckUnivariate) { size_t stack_size = stan::math::ChainableStack::instance_->var_stack_.size() - + std::get>( - stan::math::ChainableStack::instance_->var_zeroing_stacks_) + + + stan::math::ChainableStack::instance_->var_nochain_stack_ .size(); EXPECT_EQ(1U, stack_size); @@ -173,16 +173,16 @@ TEST(AgradRevErrorHandlingScalar, CheckLessVarCheckUnivariate) { size_t stack_size_after_call = stan::math::ChainableStack::instance_->var_stack_.size() - + std::get>( - stan::math::ChainableStack::instance_->var_zeroing_stacks_) + + + stan::math::ChainableStack::instance_->var_nochain_stack_ .size(); EXPECT_EQ(1U, stack_size_after_call); EXPECT_NO_THROW(check_less(function, "a", a, 10.0)); stack_size_after_call = stan::math::ChainableStack::instance_->var_stack_.size() - + std::get>( - stan::math::ChainableStack::instance_->var_zeroing_stacks_) + + + stan::math::ChainableStack::instance_->var_nochain_stack_ .size(); EXPECT_EQ(1U, stack_size_after_call); diff --git a/test/unit/math/rev/err/check_nonnegative_test.cpp b/test/unit/math/rev/err/check_nonnegative_test.cpp index b7451c0c0aa..2093535999c 100644 --- a/test/unit/math/rev/err/check_nonnegative_test.cpp +++ b/test/unit/math/rev/err/check_nonnegative_test.cpp @@ -48,8 +48,8 @@ TEST(AgradRevErrorHandlingScalar, CheckNonnegativeVarCheckVectorized) { size_t stack_size = stan::math::ChainableStack::instance_->var_stack_.size() - + std::get>( - stan::math::ChainableStack::instance_->var_zeroing_stacks_) + + + stan::math::ChainableStack::instance_->var_nochain_stack_ .size(); EXPECT_EQ(5U, stack_size); @@ -57,8 +57,8 @@ TEST(AgradRevErrorHandlingScalar, CheckNonnegativeVarCheckVectorized) { size_t stack_size_after_call = stan::math::ChainableStack::instance_->var_stack_.size() - + std::get>( - stan::math::ChainableStack::instance_->var_zeroing_stacks_) + + + stan::math::ChainableStack::instance_->var_nochain_stack_ .size(); EXPECT_EQ(5U, stack_size_after_call); @@ -66,8 +66,8 @@ TEST(AgradRevErrorHandlingScalar, CheckNonnegativeVarCheckVectorized) { EXPECT_NO_THROW(check_nonnegative(function, "a", a)); stack_size_after_call = stan::math::ChainableStack::instance_->var_stack_.size() - + std::get>( - stan::math::ChainableStack::instance_->var_zeroing_stacks_) + + + stan::math::ChainableStack::instance_->var_nochain_stack_ .size(); EXPECT_EQ(6U, stack_size_after_call); @@ -75,8 +75,8 @@ TEST(AgradRevErrorHandlingScalar, CheckNonnegativeVarCheckVectorized) { EXPECT_THROW(check_nonnegative(function, "a", a), std::domain_error); stack_size_after_call = stan::math::ChainableStack::instance_->var_stack_.size() - + std::get>( - stan::math::ChainableStack::instance_->var_zeroing_stacks_) + + + stan::math::ChainableStack::instance_->var_nochain_stack_ .size(); EXPECT_EQ(7U, stack_size_after_call); @@ -84,8 +84,8 @@ TEST(AgradRevErrorHandlingScalar, CheckNonnegativeVarCheckVectorized) { EXPECT_NO_THROW(check_nonnegative(function, "a", a)); stack_size_after_call = stan::math::ChainableStack::instance_->var_stack_.size() - + std::get>( - stan::math::ChainableStack::instance_->var_zeroing_stacks_) + + + stan::math::ChainableStack::instance_->var_nochain_stack_ .size(); EXPECT_EQ(8U, stack_size_after_call); @@ -126,8 +126,8 @@ TEST(AgradRevErrorHandlingScalar, CheckNonnegativeVarCheckUnivariate) { size_t stack_size = stan::math::ChainableStack::instance_->var_stack_.size() - + std::get>( - stan::math::ChainableStack::instance_->var_zeroing_stacks_) + + + stan::math::ChainableStack::instance_->var_nochain_stack_ .size(); EXPECT_EQ(1U, stack_size); @@ -135,8 +135,8 @@ TEST(AgradRevErrorHandlingScalar, CheckNonnegativeVarCheckUnivariate) { size_t stack_size_after_call = stan::math::ChainableStack::instance_->var_stack_.size() - + std::get>( - stan::math::ChainableStack::instance_->var_zeroing_stacks_) + + + stan::math::ChainableStack::instance_->var_nochain_stack_ .size(); EXPECT_EQ(1U, stack_size_after_call); @@ -144,8 +144,8 @@ TEST(AgradRevErrorHandlingScalar, CheckNonnegativeVarCheckUnivariate) { EXPECT_NO_THROW(check_nonnegative(function, "a", a)); stack_size_after_call = stan::math::ChainableStack::instance_->var_stack_.size() - + std::get>( - stan::math::ChainableStack::instance_->var_zeroing_stacks_) + + + stan::math::ChainableStack::instance_->var_nochain_stack_ .size(); EXPECT_EQ(2U, stack_size_after_call); @@ -153,8 +153,8 @@ TEST(AgradRevErrorHandlingScalar, CheckNonnegativeVarCheckUnivariate) { EXPECT_NO_THROW(check_nonnegative(function, "a", a)); stack_size_after_call = stan::math::ChainableStack::instance_->var_stack_.size() - + std::get>( - stan::math::ChainableStack::instance_->var_zeroing_stacks_) + + + stan::math::ChainableStack::instance_->var_nochain_stack_ .size(); EXPECT_EQ(3U, stack_size_after_call); @@ -162,8 +162,8 @@ TEST(AgradRevErrorHandlingScalar, CheckNonnegativeVarCheckUnivariate) { EXPECT_THROW(check_nonnegative(function, "a", a), std::domain_error); stack_size_after_call = stan::math::ChainableStack::instance_->var_stack_.size() - + std::get>( - stan::math::ChainableStack::instance_->var_zeroing_stacks_) + + + stan::math::ChainableStack::instance_->var_nochain_stack_ .size(); EXPECT_EQ(4U, stack_size_after_call); stan::math::recover_memory(); diff --git a/test/unit/math/rev/err/check_not_nan_test.cpp b/test/unit/math/rev/err/check_not_nan_test.cpp index 260e6908ba3..bc6b83bcbf4 100644 --- a/test/unit/math/rev/err/check_not_nan_test.cpp +++ b/test/unit/math/rev/err/check_not_nan_test.cpp @@ -16,8 +16,8 @@ TEST(AgradRevErrorHandlingScalar, CheckNotNanVarCheckVectorized) { size_t stack_size = stan::math::ChainableStack::instance_->var_stack_.size() - + std::get>( - stan::math::ChainableStack::instance_->var_zeroing_stacks_) + + + stan::math::ChainableStack::instance_->var_nochain_stack_ .size(); EXPECT_EQ(5U, stack_size); @@ -25,8 +25,8 @@ TEST(AgradRevErrorHandlingScalar, CheckNotNanVarCheckVectorized) { size_t stack_size_after_call = stan::math::ChainableStack::instance_->var_stack_.size() - + std::get>( - stan::math::ChainableStack::instance_->var_zeroing_stacks_) + + + stan::math::ChainableStack::instance_->var_nochain_stack_ .size(); EXPECT_EQ(5U, stack_size_after_call); stan::math::recover_memory(); @@ -45,8 +45,8 @@ TEST(ErrorHandlingScalar, CheckNotNanVarCheckVectorized) { size_t stack_size = stan::math::ChainableStack::instance_->var_stack_.size() - + std::get>( - stan::math::ChainableStack::instance_->var_zeroing_stacks_) + + + stan::math::ChainableStack::instance_->var_nochain_stack_ .size(); EXPECT_EQ(5U, stack_size); @@ -54,8 +54,8 @@ TEST(ErrorHandlingScalar, CheckNotNanVarCheckVectorized) { size_t stack_size_after_call = stan::math::ChainableStack::instance_->var_stack_.size() - + std::get>( - stan::math::ChainableStack::instance_->var_zeroing_stacks_) + + + stan::math::ChainableStack::instance_->var_nochain_stack_ .size(); EXPECT_EQ(5U, stack_size_after_call); stan::math::recover_memory(); @@ -106,8 +106,8 @@ TEST(AgradRevErrorHandlingScalar, CheckNotNanVarCheckUnivariate) { size_t stack_size = stan::math::ChainableStack::instance_->var_stack_.size() - + std::get>( - stan::math::ChainableStack::instance_->var_zeroing_stacks_) + + + stan::math::ChainableStack::instance_->var_nochain_stack_ .size(); EXPECT_EQ(1U, stack_size); @@ -115,8 +115,8 @@ TEST(AgradRevErrorHandlingScalar, CheckNotNanVarCheckUnivariate) { size_t stack_size_after_call = stan::math::ChainableStack::instance_->var_stack_.size() - + std::get>( - stan::math::ChainableStack::instance_->var_zeroing_stacks_) + + + stan::math::ChainableStack::instance_->var_nochain_stack_ .size(); EXPECT_EQ(1U, stack_size_after_call); @@ -132,8 +132,8 @@ TEST(ErrorHandlingScalar, CheckNotNanVarCheckUnivariate) { size_t stack_size = stan::math::ChainableStack::instance_->var_stack_.size() - + std::get>( - stan::math::ChainableStack::instance_->var_zeroing_stacks_) + + + stan::math::ChainableStack::instance_->var_nochain_stack_ .size(); EXPECT_EQ(1U, stack_size); @@ -141,8 +141,8 @@ TEST(ErrorHandlingScalar, CheckNotNanVarCheckUnivariate) { size_t stack_size_after_call = stan::math::ChainableStack::instance_->var_stack_.size() - + std::get>( - stan::math::ChainableStack::instance_->var_zeroing_stacks_) + + + stan::math::ChainableStack::instance_->var_nochain_stack_ .size(); EXPECT_EQ(1U, stack_size_after_call); diff --git a/test/unit/math/rev/err/check_pos_semidefinite_test.cpp b/test/unit/math/rev/err/check_pos_semidefinite_test.cpp index f07cfc2311a..f33712a0fe0 100644 --- a/test/unit/math/rev/err/check_pos_semidefinite_test.cpp +++ b/test/unit/math/rev/err/check_pos_semidefinite_test.cpp @@ -50,16 +50,16 @@ TEST(AgradRevErrorHandlingMatrix, checkPosSemiDefiniteMatrixVarCheck) { size_t stack_before_call = stan::math::ChainableStack::instance_->var_stack_.size() - + std::get>( - stan::math::ChainableStack::instance_->var_zeroing_stacks_) + + + stan::math::ChainableStack::instance_->var_nochain_stack_ .size(); EXPECT_EQ(9U, stack_before_call); EXPECT_NO_THROW(check_pos_semidefinite("checkPosDefiniteMatrix", "y", y)); size_t stack_after_call = stan::math::ChainableStack::instance_->var_stack_.size() - + std::get>( - stan::math::ChainableStack::instance_->var_zeroing_stacks_) + + + stan::math::ChainableStack::instance_->var_nochain_stack_ .size(); EXPECT_EQ(9U, stack_after_call); diff --git a/test/unit/math/rev/err/check_positive_finite_test.cpp b/test/unit/math/rev/err/check_positive_finite_test.cpp index 0c359b38963..662e7b63065 100644 --- a/test/unit/math/rev/err/check_positive_finite_test.cpp +++ b/test/unit/math/rev/err/check_positive_finite_test.cpp @@ -67,8 +67,8 @@ TEST(AgradRevErrorHandlingScalar, CheckPositiveFiniteVarCheckVectorized) { size_t stack_size = stan::math::ChainableStack::instance_->var_stack_.size() - + std::get>( - stan::math::ChainableStack::instance_->var_zeroing_stacks_) + + + stan::math::ChainableStack::instance_->var_nochain_stack_ .size(); EXPECT_EQ(5U, stack_size); @@ -77,8 +77,8 @@ TEST(AgradRevErrorHandlingScalar, CheckPositiveFiniteVarCheckVectorized) { size_t stack_size_after_call = stan::math::ChainableStack::instance_->var_stack_.size() - + std::get>( - stan::math::ChainableStack::instance_->var_zeroing_stacks_) + + + stan::math::ChainableStack::instance_->var_nochain_stack_ .size(); EXPECT_EQ(5U, stack_size_after_call); @@ -86,8 +86,8 @@ TEST(AgradRevErrorHandlingScalar, CheckPositiveFiniteVarCheckVectorized) { EXPECT_THROW(check_positive_finite(function, "a", a), std::domain_error); stack_size_after_call = stan::math::ChainableStack::instance_->var_stack_.size() - + std::get>( - stan::math::ChainableStack::instance_->var_zeroing_stacks_) + + + stan::math::ChainableStack::instance_->var_nochain_stack_ .size(); EXPECT_EQ(6U, stack_size_after_call); stan::math::recover_memory(); @@ -169,8 +169,8 @@ TEST(AgradRevErrorHandlingScalar, CheckPositiveFiniteVarCheckUnivariate) { size_t stack_size = stan::math::ChainableStack::instance_->var_stack_.size() - + std::get>( - stan::math::ChainableStack::instance_->var_zeroing_stacks_) + + + stan::math::ChainableStack::instance_->var_nochain_stack_ .size(); EXPECT_EQ(1U, stack_size); @@ -178,8 +178,8 @@ TEST(AgradRevErrorHandlingScalar, CheckPositiveFiniteVarCheckUnivariate) { size_t stack_size_after_call = stan::math::ChainableStack::instance_->var_stack_.size() - + std::get>( - stan::math::ChainableStack::instance_->var_zeroing_stacks_) + + + stan::math::ChainableStack::instance_->var_nochain_stack_ .size(); EXPECT_EQ(1U, stack_size_after_call); diff --git a/test/unit/math/rev/err/check_positive_test.cpp b/test/unit/math/rev/err/check_positive_test.cpp index 6a272d03e52..3ce7752cbc8 100644 --- a/test/unit/math/rev/err/check_positive_test.cpp +++ b/test/unit/math/rev/err/check_positive_test.cpp @@ -60,8 +60,8 @@ TEST(AgradRevErrorHandlingScalar, CheckPositiveVarCheckUnivariate) { size_t stack_size = stan::math::ChainableStack::instance_->var_stack_.size() - + std::get>( - stan::math::ChainableStack::instance_->var_zeroing_stacks_) + + + stan::math::ChainableStack::instance_->var_nochain_stack_ .size(); EXPECT_EQ(1U, stack_size); @@ -69,8 +69,8 @@ TEST(AgradRevErrorHandlingScalar, CheckPositiveVarCheckUnivariate) { size_t stack_size_after_call = stan::math::ChainableStack::instance_->var_stack_.size() - + std::get>( - stan::math::ChainableStack::instance_->var_zeroing_stacks_) + + + stan::math::ChainableStack::instance_->var_nochain_stack_ .size(); EXPECT_EQ(1U, stack_size_after_call); From 5d4deb57941303635f6419d0c564099cd17b8580 Mon Sep 17 00:00:00 2001 From: Stan Jenkins Date: Wed, 24 Jun 2020 21:10:12 +0000 Subject: [PATCH 117/355] [Jenkins] auto-formatting by clang-format version 6.0.0-1ubuntu2~16.04.1 (tags/RELEASE_600/final) --- .../rev/core/thread_stack_instance_test.cpp | 8 +--- test/unit/math/rev/err/check_bounded_test.cpp | 16 ++------ .../rev/err/check_consistent_size_test.cpp | 8 +--- .../rev/err/check_consistent_sizes_test.cpp | 8 +--- test/unit/math/rev/err/check_finite_test.cpp | 24 +++-------- .../rev/err/check_greater_or_equal_test.cpp | 24 +++-------- test/unit/math/rev/err/check_greater_test.cpp | 24 +++-------- .../math/rev/err/check_less_or_equal_test.cpp | 28 ++++--------- test/unit/math/rev/err/check_less_test.cpp | 24 +++-------- .../math/rev/err/check_nonnegative_test.cpp | 40 +++++-------------- test/unit/math/rev/err/check_not_nan_test.cpp | 32 ++++----------- .../rev/err/check_pos_semidefinite_test.cpp | 8 +--- .../rev/err/check_positive_finite_test.cpp | 20 +++------- .../unit/math/rev/err/check_positive_test.cpp | 8 +--- 14 files changed, 68 insertions(+), 204 deletions(-) diff --git a/test/unit/math/rev/core/thread_stack_instance_test.cpp b/test/unit/math/rev/core/thread_stack_instance_test.cpp index 9fba740b45e..c47d4f0d2d6 100644 --- a/test/unit/math/rev/core/thread_stack_instance_test.cpp +++ b/test/unit/math/rev/core/thread_stack_instance_test.cpp @@ -93,18 +93,14 @@ TEST(thread_stack_instance, child_instances) { ChainableStack thread_instance; EXPECT_TRUE( main_ad_stack->var_stack_.size() - + - stan::math::ChainableStack::instance_->var_nochain_stack_ - .size() + + stan::math::ChainableStack::instance_->var_nochain_stack_.size() #ifdef STAN_THREADS > #else == #endif ChainableStack::instance_->var_stack_.size() - + - stan::math::ChainableStack::instance_->var_nochain_stack_ - .size()); + + stan::math::ChainableStack::instance_->var_nochain_stack_.size()); }; std::thread other_work(thread_tester); diff --git a/test/unit/math/rev/err/check_bounded_test.cpp b/test/unit/math/rev/err/check_bounded_test.cpp index 59b593c5714..3f3e00455ce 100644 --- a/test/unit/math/rev/err/check_bounded_test.cpp +++ b/test/unit/math/rev/err/check_bounded_test.cpp @@ -17,18 +17,14 @@ TEST(AgradRevErrorHandlingScalar, CheckBoundedVarCheckVectorized) { size_t stack_size = stan::math::ChainableStack::instance_->var_stack_.size() - + - stan::math::ChainableStack::instance_->var_nochain_stack_ - .size(); + + stan::math::ChainableStack::instance_->var_nochain_stack_.size(); EXPECT_EQ(5U, stack_size); EXPECT_NO_THROW(check_bounded(function, "a", a, -1.0, 6.0)); size_t stack_size_after_call = stan::math::ChainableStack::instance_->var_stack_.size() - + - stan::math::ChainableStack::instance_->var_nochain_stack_ - .size(); + + stan::math::ChainableStack::instance_->var_nochain_stack_.size(); EXPECT_EQ(5U, stack_size_after_call); stan::math::recover_memory(); } @@ -154,18 +150,14 @@ TEST(AgradRevErrorHandlingScalar, CheckBoundedVarCheckUnivariate) { size_t stack_size = stan::math::ChainableStack::instance_->var_stack_.size() - + - stan::math::ChainableStack::instance_->var_nochain_stack_ - .size(); + + stan::math::ChainableStack::instance_->var_nochain_stack_.size(); EXPECT_EQ(1U, stack_size); EXPECT_NO_THROW(check_bounded(function, "a", a, 4.0, 6.0)); size_t stack_size_after_call = stan::math::ChainableStack::instance_->var_stack_.size() - + - stan::math::ChainableStack::instance_->var_nochain_stack_ - .size(); + + stan::math::ChainableStack::instance_->var_nochain_stack_.size(); EXPECT_EQ(1U, stack_size_after_call); stan::math::recover_memory(); diff --git a/test/unit/math/rev/err/check_consistent_size_test.cpp b/test/unit/math/rev/err/check_consistent_size_test.cpp index 12850980bb5..dabf63fdb3b 100644 --- a/test/unit/math/rev/err/check_consistent_size_test.cpp +++ b/test/unit/math/rev/err/check_consistent_size_test.cpp @@ -17,18 +17,14 @@ TEST(AgradRevErrorHandlingScalar, CheckConsistentSizeVarCheckVectorized) { size_t stack_size = stan::math::ChainableStack::instance_->var_stack_.size() - + - stan::math::ChainableStack::instance_->var_nochain_stack_ - .size(); + + stan::math::ChainableStack::instance_->var_nochain_stack_.size(); EXPECT_EQ(5U, stack_size); EXPECT_NO_THROW(check_consistent_size(function, "a", a, 5U)); size_t stack_size_after_call = stan::math::ChainableStack::instance_->var_stack_.size() - + - stan::math::ChainableStack::instance_->var_nochain_stack_ - .size(); + + stan::math::ChainableStack::instance_->var_nochain_stack_.size(); EXPECT_EQ(5U, stack_size_after_call); stan::math::recover_memory(); } diff --git a/test/unit/math/rev/err/check_consistent_sizes_test.cpp b/test/unit/math/rev/err/check_consistent_sizes_test.cpp index b9b1644efa8..26c87d413fa 100644 --- a/test/unit/math/rev/err/check_consistent_sizes_test.cpp +++ b/test/unit/math/rev/err/check_consistent_sizes_test.cpp @@ -19,18 +19,14 @@ TEST(AgradRevErrorHandlingScalar, CheckConsistentSizesVarCheckVectorized) { size_t stack_size = stan::math::ChainableStack::instance_->var_stack_.size() - + - stan::math::ChainableStack::instance_->var_nochain_stack_ - .size(); + + stan::math::ChainableStack::instance_->var_nochain_stack_.size(); EXPECT_EQ(10U, stack_size); EXPECT_NO_THROW(check_consistent_sizes(function, "a", a, "b", b)); size_t stack_size_after_call = stan::math::ChainableStack::instance_->var_stack_.size() - + - stan::math::ChainableStack::instance_->var_nochain_stack_ - .size(); + + stan::math::ChainableStack::instance_->var_nochain_stack_.size(); EXPECT_EQ(10U, stack_size_after_call); stan::math::recover_memory(); } diff --git a/test/unit/math/rev/err/check_finite_test.cpp b/test/unit/math/rev/err/check_finite_test.cpp index db346a90537..99a5ad41bd7 100644 --- a/test/unit/math/rev/err/check_finite_test.cpp +++ b/test/unit/math/rev/err/check_finite_test.cpp @@ -17,27 +17,21 @@ TEST(AgradRevErrorHandlingScalar, CheckFiniteVarCheckVectorized) { size_t stack_size = stan::math::ChainableStack::instance_->var_stack_.size() - + - stan::math::ChainableStack::instance_->var_nochain_stack_ - .size(); + + stan::math::ChainableStack::instance_->var_nochain_stack_.size(); EXPECT_EQ(5U, stack_size); EXPECT_NO_THROW(check_finite(function, "a", a)); size_t stack_size_after_call = stan::math::ChainableStack::instance_->var_stack_.size() - + - stan::math::ChainableStack::instance_->var_nochain_stack_ - .size(); + + stan::math::ChainableStack::instance_->var_nochain_stack_.size(); EXPECT_EQ(5U, stack_size_after_call); a[1] = std::numeric_limits::infinity(); EXPECT_THROW(check_finite(function, "a", a), std::domain_error); stack_size_after_call = stan::math::ChainableStack::instance_->var_stack_.size() - + - stan::math::ChainableStack::instance_->var_nochain_stack_ - .size(); + + stan::math::ChainableStack::instance_->var_nochain_stack_.size(); EXPECT_EQ(6U, stack_size_after_call); stan::math::recover_memory(); @@ -77,27 +71,21 @@ TEST(AgradRevErrorHandlingScalar, CheckFiniteVarCheckUnivariate) { size_t stack_size = stan::math::ChainableStack::instance_->var_stack_.size() - + - stan::math::ChainableStack::instance_->var_nochain_stack_ - .size(); + + stan::math::ChainableStack::instance_->var_nochain_stack_.size(); EXPECT_EQ(1U, stack_size); EXPECT_NO_THROW(check_finite(function, "a", a)); size_t stack_size_after_call = stan::math::ChainableStack::instance_->var_stack_.size() - + - stan::math::ChainableStack::instance_->var_nochain_stack_ - .size(); + + stan::math::ChainableStack::instance_->var_nochain_stack_.size(); EXPECT_EQ(1U, stack_size_after_call); a = std::numeric_limits::infinity(); EXPECT_THROW(check_finite(function, "a", a), std::domain_error); stack_size_after_call = stan::math::ChainableStack::instance_->var_stack_.size() - + - stan::math::ChainableStack::instance_->var_nochain_stack_ - .size(); + + stan::math::ChainableStack::instance_->var_nochain_stack_.size(); EXPECT_EQ(2U, stack_size_after_call); stan::math::recover_memory(); diff --git a/test/unit/math/rev/err/check_greater_or_equal_test.cpp b/test/unit/math/rev/err/check_greater_or_equal_test.cpp index 7fa273468d8..24252646030 100644 --- a/test/unit/math/rev/err/check_greater_or_equal_test.cpp +++ b/test/unit/math/rev/err/check_greater_or_equal_test.cpp @@ -17,27 +17,21 @@ TEST(AgradRevErrorHandlingScalar, CheckGreateOrEqualVarCheckVectorized) { size_t stack_size = stan::math::ChainableStack::instance_->var_stack_.size() - + - stan::math::ChainableStack::instance_->var_nochain_stack_ - .size(); + + stan::math::ChainableStack::instance_->var_nochain_stack_.size(); EXPECT_EQ(5U, stack_size); EXPECT_NO_THROW(check_greater_or_equal(function, "a", a, -1.0)); size_t stack_size_after_call = stan::math::ChainableStack::instance_->var_stack_.size() - + - stan::math::ChainableStack::instance_->var_nochain_stack_ - .size(); + + stan::math::ChainableStack::instance_->var_nochain_stack_.size(); EXPECT_EQ(5U, stack_size_after_call); EXPECT_THROW(check_greater_or_equal(function, "a", a, 2.0), std::domain_error); stack_size_after_call = stan::math::ChainableStack::instance_->var_stack_.size() - + - stan::math::ChainableStack::instance_->var_nochain_stack_ - .size(); + + stan::math::ChainableStack::instance_->var_nochain_stack_.size(); EXPECT_EQ(5U, stack_size_after_call); stan::math::recover_memory(); @@ -204,27 +198,21 @@ TEST(AgradRevErrorHandlingScalar, CheckGreaterOrEqualVarCheckUnivariate) { size_t stack_size = stan::math::ChainableStack::instance_->var_stack_.size() - + - stan::math::ChainableStack::instance_->var_nochain_stack_ - .size(); + + stan::math::ChainableStack::instance_->var_nochain_stack_.size(); EXPECT_EQ(1U, stack_size); EXPECT_NO_THROW(check_greater_or_equal(function, "a", a, 2.0)); size_t stack_size_after_call = stan::math::ChainableStack::instance_->var_stack_.size() - + - stan::math::ChainableStack::instance_->var_nochain_stack_ - .size(); + + stan::math::ChainableStack::instance_->var_nochain_stack_.size(); EXPECT_EQ(1U, stack_size_after_call); EXPECT_THROW(check_greater_or_equal(function, "a", a, 10.0), std::domain_error); stack_size_after_call = stan::math::ChainableStack::instance_->var_stack_.size() - + - stan::math::ChainableStack::instance_->var_nochain_stack_ - .size(); + + stan::math::ChainableStack::instance_->var_nochain_stack_.size(); EXPECT_EQ(1U, stack_size_after_call); stan::math::recover_memory(); diff --git a/test/unit/math/rev/err/check_greater_test.cpp b/test/unit/math/rev/err/check_greater_test.cpp index fa9051d1488..1da58eeb7ae 100644 --- a/test/unit/math/rev/err/check_greater_test.cpp +++ b/test/unit/math/rev/err/check_greater_test.cpp @@ -16,26 +16,20 @@ TEST(AgradRevErrorHandlingScalar, CheckGreaterVarCheckVectorized) { size_t stack_size = stan::math::ChainableStack::instance_->var_stack_.size() - + - stan::math::ChainableStack::instance_->var_nochain_stack_ - .size(); + + stan::math::ChainableStack::instance_->var_nochain_stack_.size(); EXPECT_EQ(5U, stack_size); EXPECT_NO_THROW(check_greater(function, "a", a, -1.0)); size_t stack_size_after_call = stan::math::ChainableStack::instance_->var_stack_.size() - + - stan::math::ChainableStack::instance_->var_nochain_stack_ - .size(); + + stan::math::ChainableStack::instance_->var_nochain_stack_.size(); EXPECT_EQ(5U, stack_size_after_call); EXPECT_THROW(check_greater(function, "a", a, 2.0), std::domain_error); stack_size_after_call = stan::math::ChainableStack::instance_->var_stack_.size() - + - stan::math::ChainableStack::instance_->var_nochain_stack_ - .size(); + + stan::math::ChainableStack::instance_->var_nochain_stack_.size(); EXPECT_EQ(5U, stack_size_after_call); stan::math::recover_memory(); @@ -194,26 +188,20 @@ TEST(AgradRevErrorHandlingScalar, CheckGreaterVarCheckUnivariate) { size_t stack_size = stan::math::ChainableStack::instance_->var_stack_.size() - + - stan::math::ChainableStack::instance_->var_nochain_stack_ - .size(); + + stan::math::ChainableStack::instance_->var_nochain_stack_.size(); EXPECT_EQ(1U, stack_size); EXPECT_NO_THROW(check_greater(function, "a", a, 2.0)); size_t stack_size_after_call = stan::math::ChainableStack::instance_->var_stack_.size() - + - stan::math::ChainableStack::instance_->var_nochain_stack_ - .size(); + + stan::math::ChainableStack::instance_->var_nochain_stack_.size(); EXPECT_EQ(1U, stack_size_after_call); EXPECT_THROW(check_greater(function, "a", a, 10.0), std::domain_error); stack_size_after_call = stan::math::ChainableStack::instance_->var_stack_.size() - + - stan::math::ChainableStack::instance_->var_nochain_stack_ - .size(); + + stan::math::ChainableStack::instance_->var_nochain_stack_.size(); EXPECT_EQ(1U, stack_size_after_call); stan::math::recover_memory(); diff --git a/test/unit/math/rev/err/check_less_or_equal_test.cpp b/test/unit/math/rev/err/check_less_or_equal_test.cpp index 9e96d55a855..bf63756ff02 100644 --- a/test/unit/math/rev/err/check_less_or_equal_test.cpp +++ b/test/unit/math/rev/err/check_less_or_equal_test.cpp @@ -16,26 +16,20 @@ TEST(AgradRevErrorHandlingScalar, CheckLessOrEqualVarCheckVectorized) { size_t stack_size = stan::math::ChainableStack::instance_->var_stack_.size() - + - stan::math::ChainableStack::instance_->var_nochain_stack_ - .size(); + + stan::math::ChainableStack::instance_->var_nochain_stack_.size(); EXPECT_EQ(5U, stack_size); EXPECT_NO_THROW(check_less_or_equal(function, "a", a, 10.0)); size_t stack_size_after_call = stan::math::ChainableStack::instance_->var_stack_.size() - + - stan::math::ChainableStack::instance_->var_nochain_stack_ - .size(); + + stan::math::ChainableStack::instance_->var_nochain_stack_.size(); EXPECT_EQ(5U, stack_size_after_call); EXPECT_THROW(check_less_or_equal(function, "a", a, 2.0), std::domain_error); stack_size_after_call = stan::math::ChainableStack::instance_->var_stack_.size() - + - stan::math::ChainableStack::instance_->var_nochain_stack_ - .size(); + + stan::math::ChainableStack::instance_->var_nochain_stack_.size(); EXPECT_EQ(5U, stack_size_after_call); stan::math::recover_memory(); @@ -167,35 +161,27 @@ TEST(AgradRevErrorHandlingScalar, CheckLessOrEqualVarCheckUnivariate) { size_t stack_size = stan::math::ChainableStack::instance_->var_stack_.size() - + - stan::math::ChainableStack::instance_->var_nochain_stack_ - .size(); + + stan::math::ChainableStack::instance_->var_nochain_stack_.size(); EXPECT_EQ(1U, stack_size); EXPECT_THROW(check_less_or_equal(function, "a", a, 2.0), std::domain_error); size_t stack_size_after_call = stan::math::ChainableStack::instance_->var_stack_.size() - + - stan::math::ChainableStack::instance_->var_nochain_stack_ - .size(); + + stan::math::ChainableStack::instance_->var_nochain_stack_.size(); EXPECT_EQ(1U, stack_size_after_call); EXPECT_NO_THROW(check_less_or_equal(function, "a", a, 5.0)); stack_size_after_call = stan::math::ChainableStack::instance_->var_stack_.size() - + - stan::math::ChainableStack::instance_->var_nochain_stack_ - .size(); + + stan::math::ChainableStack::instance_->var_nochain_stack_.size(); EXPECT_EQ(1U, stack_size_after_call); EXPECT_NO_THROW(check_less_or_equal(function, "a", a, 10.0)); stack_size_after_call = stan::math::ChainableStack::instance_->var_stack_.size() - + - stan::math::ChainableStack::instance_->var_nochain_stack_ - .size(); + + stan::math::ChainableStack::instance_->var_nochain_stack_.size(); EXPECT_EQ(1U, stack_size_after_call); stan::math::recover_memory(); diff --git a/test/unit/math/rev/err/check_less_test.cpp b/test/unit/math/rev/err/check_less_test.cpp index 3f501c41c33..241d328b619 100644 --- a/test/unit/math/rev/err/check_less_test.cpp +++ b/test/unit/math/rev/err/check_less_test.cpp @@ -16,26 +16,20 @@ TEST(AgradRevErrorHandlingScalar, CheckLessVarCheckVectorized) { size_t stack_size = stan::math::ChainableStack::instance_->var_stack_.size() - + - stan::math::ChainableStack::instance_->var_nochain_stack_ - .size(); + + stan::math::ChainableStack::instance_->var_nochain_stack_.size(); EXPECT_EQ(5U, stack_size); EXPECT_NO_THROW(check_less(function, "a", a, 10.0)); size_t stack_size_after_call = stan::math::ChainableStack::instance_->var_stack_.size() - + - stan::math::ChainableStack::instance_->var_nochain_stack_ - .size(); + + stan::math::ChainableStack::instance_->var_nochain_stack_.size(); EXPECT_EQ(5U, stack_size_after_call); EXPECT_THROW(check_less(function, "a", a, 2.0), std::domain_error); stack_size_after_call = stan::math::ChainableStack::instance_->var_stack_.size() - + - stan::math::ChainableStack::instance_->var_nochain_stack_ - .size(); + + stan::math::ChainableStack::instance_->var_nochain_stack_.size(); EXPECT_EQ(5U, stack_size_after_call); stan::math::recover_memory(); @@ -164,26 +158,20 @@ TEST(AgradRevErrorHandlingScalar, CheckLessVarCheckUnivariate) { size_t stack_size = stan::math::ChainableStack::instance_->var_stack_.size() - + - stan::math::ChainableStack::instance_->var_nochain_stack_ - .size(); + + stan::math::ChainableStack::instance_->var_nochain_stack_.size(); EXPECT_EQ(1U, stack_size); EXPECT_THROW(check_less(function, "a", a, 2.0), std::domain_error); size_t stack_size_after_call = stan::math::ChainableStack::instance_->var_stack_.size() - + - stan::math::ChainableStack::instance_->var_nochain_stack_ - .size(); + + stan::math::ChainableStack::instance_->var_nochain_stack_.size(); EXPECT_EQ(1U, stack_size_after_call); EXPECT_NO_THROW(check_less(function, "a", a, 10.0)); stack_size_after_call = stan::math::ChainableStack::instance_->var_stack_.size() - + - stan::math::ChainableStack::instance_->var_nochain_stack_ - .size(); + + stan::math::ChainableStack::instance_->var_nochain_stack_.size(); EXPECT_EQ(1U, stack_size_after_call); stan::math::recover_memory(); diff --git a/test/unit/math/rev/err/check_nonnegative_test.cpp b/test/unit/math/rev/err/check_nonnegative_test.cpp index 2093535999c..93113b8e186 100644 --- a/test/unit/math/rev/err/check_nonnegative_test.cpp +++ b/test/unit/math/rev/err/check_nonnegative_test.cpp @@ -48,45 +48,35 @@ TEST(AgradRevErrorHandlingScalar, CheckNonnegativeVarCheckVectorized) { size_t stack_size = stan::math::ChainableStack::instance_->var_stack_.size() - + - stan::math::ChainableStack::instance_->var_nochain_stack_ - .size(); + + stan::math::ChainableStack::instance_->var_nochain_stack_.size(); EXPECT_EQ(5U, stack_size); EXPECT_NO_THROW(check_nonnegative(function, "a", a)); size_t stack_size_after_call = stan::math::ChainableStack::instance_->var_stack_.size() - + - stan::math::ChainableStack::instance_->var_nochain_stack_ - .size(); + + stan::math::ChainableStack::instance_->var_nochain_stack_.size(); EXPECT_EQ(5U, stack_size_after_call); a[1] = std::numeric_limits::infinity(); EXPECT_NO_THROW(check_nonnegative(function, "a", a)); stack_size_after_call = stan::math::ChainableStack::instance_->var_stack_.size() - + - stan::math::ChainableStack::instance_->var_nochain_stack_ - .size(); + + stan::math::ChainableStack::instance_->var_nochain_stack_.size(); EXPECT_EQ(6U, stack_size_after_call); a[1] = -1.0; EXPECT_THROW(check_nonnegative(function, "a", a), std::domain_error); stack_size_after_call = stan::math::ChainableStack::instance_->var_stack_.size() - + - stan::math::ChainableStack::instance_->var_nochain_stack_ - .size(); + + stan::math::ChainableStack::instance_->var_nochain_stack_.size(); EXPECT_EQ(7U, stack_size_after_call); a[1] = 0.0; EXPECT_NO_THROW(check_nonnegative(function, "a", a)); stack_size_after_call = stan::math::ChainableStack::instance_->var_stack_.size() - + - stan::math::ChainableStack::instance_->var_nochain_stack_ - .size(); + + stan::math::ChainableStack::instance_->var_nochain_stack_.size(); EXPECT_EQ(8U, stack_size_after_call); stan::math::recover_memory(); @@ -126,45 +116,35 @@ TEST(AgradRevErrorHandlingScalar, CheckNonnegativeVarCheckUnivariate) { size_t stack_size = stan::math::ChainableStack::instance_->var_stack_.size() - + - stan::math::ChainableStack::instance_->var_nochain_stack_ - .size(); + + stan::math::ChainableStack::instance_->var_nochain_stack_.size(); EXPECT_EQ(1U, stack_size); EXPECT_NO_THROW(check_nonnegative(function, "a", a)); size_t stack_size_after_call = stan::math::ChainableStack::instance_->var_stack_.size() - + - stan::math::ChainableStack::instance_->var_nochain_stack_ - .size(); + + stan::math::ChainableStack::instance_->var_nochain_stack_.size(); EXPECT_EQ(1U, stack_size_after_call); a = std::numeric_limits::infinity(); EXPECT_NO_THROW(check_nonnegative(function, "a", a)); stack_size_after_call = stan::math::ChainableStack::instance_->var_stack_.size() - + - stan::math::ChainableStack::instance_->var_nochain_stack_ - .size(); + + stan::math::ChainableStack::instance_->var_nochain_stack_.size(); EXPECT_EQ(2U, stack_size_after_call); a = 0.0; EXPECT_NO_THROW(check_nonnegative(function, "a", a)); stack_size_after_call = stan::math::ChainableStack::instance_->var_stack_.size() - + - stan::math::ChainableStack::instance_->var_nochain_stack_ - .size(); + + stan::math::ChainableStack::instance_->var_nochain_stack_.size(); EXPECT_EQ(3U, stack_size_after_call); a = -1.1; EXPECT_THROW(check_nonnegative(function, "a", a), std::domain_error); stack_size_after_call = stan::math::ChainableStack::instance_->var_stack_.size() - + - stan::math::ChainableStack::instance_->var_nochain_stack_ - .size(); + + stan::math::ChainableStack::instance_->var_nochain_stack_.size(); EXPECT_EQ(4U, stack_size_after_call); stan::math::recover_memory(); } diff --git a/test/unit/math/rev/err/check_not_nan_test.cpp b/test/unit/math/rev/err/check_not_nan_test.cpp index bc6b83bcbf4..820cf12b540 100644 --- a/test/unit/math/rev/err/check_not_nan_test.cpp +++ b/test/unit/math/rev/err/check_not_nan_test.cpp @@ -16,18 +16,14 @@ TEST(AgradRevErrorHandlingScalar, CheckNotNanVarCheckVectorized) { size_t stack_size = stan::math::ChainableStack::instance_->var_stack_.size() - + - stan::math::ChainableStack::instance_->var_nochain_stack_ - .size(); + + stan::math::ChainableStack::instance_->var_nochain_stack_.size(); EXPECT_EQ(5U, stack_size); EXPECT_NO_THROW(check_not_nan(function, "a", a)); size_t stack_size_after_call = stan::math::ChainableStack::instance_->var_stack_.size() - + - stan::math::ChainableStack::instance_->var_nochain_stack_ - .size(); + + stan::math::ChainableStack::instance_->var_nochain_stack_.size(); EXPECT_EQ(5U, stack_size_after_call); stan::math::recover_memory(); } @@ -45,18 +41,14 @@ TEST(ErrorHandlingScalar, CheckNotNanVarCheckVectorized) { size_t stack_size = stan::math::ChainableStack::instance_->var_stack_.size() - + - stan::math::ChainableStack::instance_->var_nochain_stack_ - .size(); + + stan::math::ChainableStack::instance_->var_nochain_stack_.size(); EXPECT_EQ(5U, stack_size); EXPECT_NO_THROW(check_not_nan(function, "a", a)); size_t stack_size_after_call = stan::math::ChainableStack::instance_->var_stack_.size() - + - stan::math::ChainableStack::instance_->var_nochain_stack_ - .size(); + + stan::math::ChainableStack::instance_->var_nochain_stack_.size(); EXPECT_EQ(5U, stack_size_after_call); stan::math::recover_memory(); } @@ -106,18 +98,14 @@ TEST(AgradRevErrorHandlingScalar, CheckNotNanVarCheckUnivariate) { size_t stack_size = stan::math::ChainableStack::instance_->var_stack_.size() - + - stan::math::ChainableStack::instance_->var_nochain_stack_ - .size(); + + stan::math::ChainableStack::instance_->var_nochain_stack_.size(); EXPECT_EQ(1U, stack_size); EXPECT_NO_THROW(check_not_nan(function, "a", a)); size_t stack_size_after_call = stan::math::ChainableStack::instance_->var_stack_.size() - + - stan::math::ChainableStack::instance_->var_nochain_stack_ - .size(); + + stan::math::ChainableStack::instance_->var_nochain_stack_.size(); EXPECT_EQ(1U, stack_size_after_call); stan::math::recover_memory(); @@ -132,18 +120,14 @@ TEST(ErrorHandlingScalar, CheckNotNanVarCheckUnivariate) { size_t stack_size = stan::math::ChainableStack::instance_->var_stack_.size() - + - stan::math::ChainableStack::instance_->var_nochain_stack_ - .size(); + + stan::math::ChainableStack::instance_->var_nochain_stack_.size(); EXPECT_EQ(1U, stack_size); EXPECT_NO_THROW(check_not_nan(function, "a", a)); size_t stack_size_after_call = stan::math::ChainableStack::instance_->var_stack_.size() - + - stan::math::ChainableStack::instance_->var_nochain_stack_ - .size(); + + stan::math::ChainableStack::instance_->var_nochain_stack_.size(); EXPECT_EQ(1U, stack_size_after_call); stan::math::recover_memory(); diff --git a/test/unit/math/rev/err/check_pos_semidefinite_test.cpp b/test/unit/math/rev/err/check_pos_semidefinite_test.cpp index f33712a0fe0..b384b023483 100644 --- a/test/unit/math/rev/err/check_pos_semidefinite_test.cpp +++ b/test/unit/math/rev/err/check_pos_semidefinite_test.cpp @@ -50,17 +50,13 @@ TEST(AgradRevErrorHandlingMatrix, checkPosSemiDefiniteMatrixVarCheck) { size_t stack_before_call = stan::math::ChainableStack::instance_->var_stack_.size() - + - stan::math::ChainableStack::instance_->var_nochain_stack_ - .size(); + + stan::math::ChainableStack::instance_->var_nochain_stack_.size(); EXPECT_EQ(9U, stack_before_call); EXPECT_NO_THROW(check_pos_semidefinite("checkPosDefiniteMatrix", "y", y)); size_t stack_after_call = stan::math::ChainableStack::instance_->var_stack_.size() - + - stan::math::ChainableStack::instance_->var_nochain_stack_ - .size(); + + stan::math::ChainableStack::instance_->var_nochain_stack_.size(); EXPECT_EQ(9U, stack_after_call); } diff --git a/test/unit/math/rev/err/check_positive_finite_test.cpp b/test/unit/math/rev/err/check_positive_finite_test.cpp index 662e7b63065..e8fb8af1a92 100644 --- a/test/unit/math/rev/err/check_positive_finite_test.cpp +++ b/test/unit/math/rev/err/check_positive_finite_test.cpp @@ -67,9 +67,7 @@ TEST(AgradRevErrorHandlingScalar, CheckPositiveFiniteVarCheckVectorized) { size_t stack_size = stan::math::ChainableStack::instance_->var_stack_.size() - + - stan::math::ChainableStack::instance_->var_nochain_stack_ - .size(); + + stan::math::ChainableStack::instance_->var_nochain_stack_.size(); EXPECT_EQ(5U, stack_size); EXPECT_THROW(check_positive_finite(function, "a", a), std::domain_error); @@ -77,18 +75,14 @@ TEST(AgradRevErrorHandlingScalar, CheckPositiveFiniteVarCheckVectorized) { size_t stack_size_after_call = stan::math::ChainableStack::instance_->var_stack_.size() - + - stan::math::ChainableStack::instance_->var_nochain_stack_ - .size(); + + stan::math::ChainableStack::instance_->var_nochain_stack_.size(); EXPECT_EQ(5U, stack_size_after_call); a[2] = std::numeric_limits::infinity(); EXPECT_THROW(check_positive_finite(function, "a", a), std::domain_error); stack_size_after_call = stan::math::ChainableStack::instance_->var_stack_.size() - + - stan::math::ChainableStack::instance_->var_nochain_stack_ - .size(); + + stan::math::ChainableStack::instance_->var_nochain_stack_.size(); EXPECT_EQ(6U, stack_size_after_call); stan::math::recover_memory(); } @@ -169,18 +163,14 @@ TEST(AgradRevErrorHandlingScalar, CheckPositiveFiniteVarCheckUnivariate) { size_t stack_size = stan::math::ChainableStack::instance_->var_stack_.size() - + - stan::math::ChainableStack::instance_->var_nochain_stack_ - .size(); + + stan::math::ChainableStack::instance_->var_nochain_stack_.size(); EXPECT_EQ(1U, stack_size); EXPECT_NO_THROW(check_positive_finite(function, "a", a)); size_t stack_size_after_call = stan::math::ChainableStack::instance_->var_stack_.size() - + - stan::math::ChainableStack::instance_->var_nochain_stack_ - .size(); + + stan::math::ChainableStack::instance_->var_nochain_stack_.size(); EXPECT_EQ(1U, stack_size_after_call); stan::math::recover_memory(); diff --git a/test/unit/math/rev/err/check_positive_test.cpp b/test/unit/math/rev/err/check_positive_test.cpp index 3ce7752cbc8..dee6535363f 100644 --- a/test/unit/math/rev/err/check_positive_test.cpp +++ b/test/unit/math/rev/err/check_positive_test.cpp @@ -60,18 +60,14 @@ TEST(AgradRevErrorHandlingScalar, CheckPositiveVarCheckUnivariate) { size_t stack_size = stan::math::ChainableStack::instance_->var_stack_.size() - + - stan::math::ChainableStack::instance_->var_nochain_stack_ - .size(); + + stan::math::ChainableStack::instance_->var_nochain_stack_.size(); EXPECT_EQ(1U, stack_size); EXPECT_NO_THROW(check_positive(function, "a", a)); size_t stack_size_after_call = stan::math::ChainableStack::instance_->var_stack_.size() - + - stan::math::ChainableStack::instance_->var_nochain_stack_ - .size(); + + stan::math::ChainableStack::instance_->var_nochain_stack_.size(); EXPECT_EQ(1U, stack_size_after_call); stan::math::recover_memory(); From 05a31665f0a7a6c6c0d4c12fd590da58d52ebe0d Mon Sep 17 00:00:00 2001 From: Steve Bronder Date: Wed, 24 Jun 2020 19:55:38 -0400 Subject: [PATCH 118/355] small fixes --- stan/math/rev/core/autodiffstackstorage.hpp | 4 ---- stan/math/rev/core/chainable_alloc.hpp | 1 + stan/math/rev/core/chainablestack.hpp | 3 +-- stan/math/rev/core/vari.hpp | 4 +--- stan/math/rev/functor/coupled_ode_system.hpp | 3 ++- test/unit/math/rev/core/var_test.cpp | 1 - 6 files changed, 5 insertions(+), 11 deletions(-) diff --git a/stan/math/rev/core/autodiffstackstorage.hpp b/stan/math/rev/core/autodiffstackstorage.hpp index 93578cbbc63..fecdab186b5 100644 --- a/stan/math/rev/core/autodiffstackstorage.hpp +++ b/stan/math/rev/core/autodiffstackstorage.hpp @@ -2,7 +2,6 @@ #define STAN_MATH_REV_CORE_AUTODIFFSTACKSTORAGE_HPP #include -#include #include namespace stan { @@ -25,9 +24,6 @@ namespace math { #define STAN_THREADS_DEF #endif -template -class vari_value; - /** * This struct always provides access to the autodiff stack using * the singleton pattern. Read warnings below! diff --git a/stan/math/rev/core/chainable_alloc.hpp b/stan/math/rev/core/chainable_alloc.hpp index 6ff43fd0e43..a996173b1d7 100644 --- a/stan/math/rev/core/chainable_alloc.hpp +++ b/stan/math/rev/core/chainable_alloc.hpp @@ -18,6 +18,7 @@ class chainable_alloc { chainable_alloc() { ChainableStack::instance_->var_alloc_stack_.push_back(this); } + virtual ~chainable_alloc() {} }; } // namespace math diff --git a/stan/math/rev/core/chainablestack.hpp b/stan/math/rev/core/chainablestack.hpp index d383fabdcf9..4785afe1146 100644 --- a/stan/math/rev/core/chainablestack.hpp +++ b/stan/math/rev/core/chainablestack.hpp @@ -2,11 +2,10 @@ #define STAN_MATH_REV_CORE_CHAINABLESTACK_HPP #include -#include namespace stan { namespace math { -template +template class vari_value; class vari_base; class chainable_alloc; diff --git a/stan/math/rev/core/vari.hpp b/stan/math/rev/core/vari.hpp index 294cece21bb..6515174ae8b 100644 --- a/stan/math/rev/core/vari.hpp +++ b/stan/math/rev/core/vari.hpp @@ -32,6 +32,7 @@ class vari_base { virtual void set_zero_adjoint() = 0; virtual ~vari_base() noexcept {} }; + /** * The variable implementation base class. * @@ -43,9 +44,6 @@ class vari_base { * derivative with respect to the root of the derivative tree. * */ -template -class vari_value; - template class vari_value::value>> : public vari_base { diff --git a/stan/math/rev/functor/coupled_ode_system.hpp b/stan/math/rev/functor/coupled_ode_system.hpp index 773aebe625e..7ae5f4a1ab6 100644 --- a/stan/math/rev/functor/coupled_ode_system.hpp +++ b/stan/math/rev/functor/coupled_ode_system.hpp @@ -5,6 +5,7 @@ #include #include #include +#include #include #include #include @@ -484,7 +485,7 @@ struct coupled_ode_system { // See efficiency note above on template specialization for more details // on this. for (size_t j = 0; j < M_; ++j) { - theta_nochain_[j].vi_->adj_ = 0.0; + fill(theta_nochain_[j].vi_->adj_, 0.0); } } } diff --git a/test/unit/math/rev/core/var_test.cpp b/test/unit/math/rev/core/var_test.cpp index 303d00a3ec6..2b792ac41cd 100644 --- a/test/unit/math/rev/core/var_test.cpp +++ b/test/unit/math/rev/core/var_test.cpp @@ -1,6 +1,5 @@ #include #include -#include #include #include #include From b25944d54875bdc09a1a978ca86be81ed3cccefb Mon Sep 17 00:00:00 2001 From: Stan Jenkins Date: Wed, 24 Jun 2020 19:56:48 -0400 Subject: [PATCH 119/355] [Jenkins] auto-formatting by clang-format version 6.0.0-1ubuntu2 (tags/RELEASE_600/final) --- stan/math/rev/core/chainable_alloc.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stan/math/rev/core/chainable_alloc.hpp b/stan/math/rev/core/chainable_alloc.hpp index a996173b1d7..3541e88aee6 100644 --- a/stan/math/rev/core/chainable_alloc.hpp +++ b/stan/math/rev/core/chainable_alloc.hpp @@ -18,7 +18,7 @@ class chainable_alloc { chainable_alloc() { ChainableStack::instance_->var_alloc_stack_.push_back(this); } - virtual ~chainable_alloc() {} + virtual ~chainable_alloc() {} }; } // namespace math From ffd30da4949823167fd125db3385cb3b233b9ac0 Mon Sep 17 00:00:00 2001 From: Steve Bronder Date: Thu, 25 Jun 2020 13:38:08 -0400 Subject: [PATCH 120/355] use nested chainable stack class for set zero adjoint --- stan/math/prim/fun/cholesky_decompose.hpp | 8 +++----- stan/math/rev/core/init_chainablestack.hpp | 2 +- stan/math/rev/functor/coupled_ode_system.hpp | 6 +++--- stan/math/rev/functor/jacobian.hpp | 2 +- 4 files changed, 8 insertions(+), 10 deletions(-) diff --git a/stan/math/prim/fun/cholesky_decompose.hpp b/stan/math/prim/fun/cholesky_decompose.hpp index fe64e168b81..10254c001b6 100644 --- a/stan/math/prim/fun/cholesky_decompose.hpp +++ b/stan/math/prim/fun/cholesky_decompose.hpp @@ -59,8 +59,8 @@ cholesky_decompose(const EigMat& m) { * @throw std::domain_error if m is not a symmetric matrix or * if m is not positive definite (if m has more than 0 elements) */ -template * = nullptr> +template * = nullptr, + require_same_t>* = nullptr> inline Eigen::Matrix, EigMat::RowsAtCompileTime, EigMat::ColsAtCompileTime> cholesky_decompose(const EigMat& m) { @@ -68,9 +68,7 @@ cholesky_decompose(const EigMat& m) { eval_return_type_t& m_eval = m.eval(); check_not_nan("cholesky_decompose", "m", m_eval); #ifdef STAN_OPENCL - if (std::is_same::value - && m.rows() - >= opencl_context.tuning_opts().cholesky_size_worth_transfer) { + if (m.rows() >= opencl_context.tuning_opts().cholesky_size_worth_transfer) { matrix_cl m_cl(m_eval); return from_matrix_cl(cholesky_decompose(m_cl)); } else { diff --git a/stan/math/rev/core/init_chainablestack.hpp b/stan/math/rev/core/init_chainablestack.hpp index 5df2f797012..2f2de5a4086 100644 --- a/stan/math/rev/core/init_chainablestack.hpp +++ b/stan/math/rev/core/init_chainablestack.hpp @@ -43,7 +43,7 @@ class ad_tape_observer final : public tbb::task_scheduler_observer { bool status = false; std::tie(insert_elem, status) = thread_tape_map_.emplace(ad_map::value_type{thread_id, nullptr}); - insert_elem->second = std::move(std::make_unique()); + insert_elem->second = std::make_unique(); } } diff --git a/stan/math/rev/functor/coupled_ode_system.hpp b/stan/math/rev/functor/coupled_ode_system.hpp index 7ae5f4a1ab6..b6e0e4dbdd9 100644 --- a/stan/math/rev/functor/coupled_ode_system.hpp +++ b/stan/math/rev/functor/coupled_ode_system.hpp @@ -144,7 +144,7 @@ struct coupled_ode_system { dz_dt[offset + i] = temp_deriv; } - set_zero_all_adjoints_nested(); + nested.set_zero_all_adjoints(); // Parameters stored on the outer (non-nested) nochain stack are not // reset to zero by the last call. This is done as a separate step here. // See efficiency note above on template specialization for more details @@ -297,7 +297,7 @@ struct coupled_ode_system { dz_dt[offset + i] = temp_deriv; } - set_zero_all_adjoints_nested(); + nested.set_zero_all_adjoints(); } } @@ -479,7 +479,7 @@ struct coupled_ode_system { dz_dt[offset + i] = temp_deriv; } - set_zero_all_adjoints_nested(); + nested.set_zero_all_adjoints(); // Parameters stored on the outer (non-nested) nochain stack are not // reset to zero by the last call. This is done as a separate step here. // See efficiency note above on template specialization for more details diff --git a/stan/math/rev/functor/jacobian.hpp b/stan/math/rev/functor/jacobian.hpp index c388a8bcccb..75692b06911 100644 --- a/stan/math/rev/functor/jacobian.hpp +++ b/stan/math/rev/functor/jacobian.hpp @@ -27,7 +27,7 @@ void jacobian(const F& f, const Eigen::Matrix& x, grad(fx_var(0).vi_); J.col(0) = x_var.adj(); for (int i = 1; i < fx_var.size(); ++i) { - set_zero_all_adjoints_nested(); + nested.set_zero_all_adjoints(); grad(fx_var(i).vi_); J.col(i) = x_var.adj(); } From e5428e9d6c50154ed2552cba0809dd1ed93ebb29 Mon Sep 17 00:00:00 2001 From: Stan Jenkins Date: Thu, 25 Jun 2020 13:38:59 -0400 Subject: [PATCH 121/355] [Jenkins] auto-formatting by clang-format version 6.0.0-1ubuntu2 (tags/RELEASE_600/final) --- stan/math/prim/fun/cholesky_decompose.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stan/math/prim/fun/cholesky_decompose.hpp b/stan/math/prim/fun/cholesky_decompose.hpp index 10254c001b6..d3a6ca627a0 100644 --- a/stan/math/prim/fun/cholesky_decompose.hpp +++ b/stan/math/prim/fun/cholesky_decompose.hpp @@ -60,7 +60,7 @@ cholesky_decompose(const EigMat& m) { * if m is not positive definite (if m has more than 0 elements) */ template * = nullptr, - require_same_t>* = nullptr> + require_same_t>* = nullptr> inline Eigen::Matrix, EigMat::RowsAtCompileTime, EigMat::ColsAtCompileTime> cholesky_decompose(const EigMat& m) { From 356bb4ebdad0a4a0f012c90148b2c9a32ed32b61 Mon Sep 17 00:00:00 2001 From: Steve Bronder Date: Fri, 26 Jun 2020 19:56:45 -0400 Subject: [PATCH 122/355] merge to vari-base-templates and add sparse matrix var type --- stan/math/prim/meta/is_eigen_sparse_base.hpp | 2 +- stan/math/rev/core/var.hpp | 9 +- stan/math/rev/core/vari.hpp | 207 +++++++++++++++++-- test/unit/math/rev/core/var_test.cpp | 105 ++++++++-- 4 files changed, 279 insertions(+), 44 deletions(-) diff --git a/stan/math/prim/meta/is_eigen_sparse_base.hpp b/stan/math/prim/meta/is_eigen_sparse_base.hpp index 0628b3dce66..67d48396203 100644 --- a/stan/math/prim/meta/is_eigen_sparse_base.hpp +++ b/stan/math/prim/meta/is_eigen_sparse_base.hpp @@ -19,7 +19,7 @@ namespace stan { */ template struct is_eigen_sparse_base - : bool_constant::value> { + : bool_constant::value> { }; STAN_ADD_REQUIRE_UNARY(eigen_sparse_base, is_eigen_sparse_base, diff --git a/stan/math/rev/core/var.hpp b/stan/math/rev/core/var.hpp index da6cb4128ed..e704b796e4b 100644 --- a/stan/math/rev/core/var.hpp +++ b/stan/math/rev/core/var.hpp @@ -36,7 +36,7 @@ class var_value {}; template class var_value> { public: - using value_type = std::decay_t; // Numeric type in vari_value. + using value_type = std::decay_t>; // type in vari_value. using vari_type = vari_value; // Type of underlying vari impl. using vari_pointer = vari_type*; // pointer type for underlying vari. @@ -77,14 +77,15 @@ class var_value> { * @param x Value of the variable. */ template * = nullptr> - var_value(const S& x) : vi_(new vari_type(x, false)) {} // NOLINT + var_value(S&& x) : vi_(new vari_type(std::forward(x), false)) {} // NOLINT /** * Construct a variable from a pointer to a variable implementation. * @param vi A vari_value pointer. */ - var_value(vari_value* vi) // NOLINT - : vi_(vi) {} + template * = nullptr> + var_value(vari_value* vi) // NOLINT + : vi_(vi) {} /** * Return a constant reference to the value of this variable. diff --git a/stan/math/rev/core/vari.hpp b/stan/math/rev/core/vari.hpp index 7461682934c..6868ab941ab 100644 --- a/stan/math/rev/core/vari.hpp +++ b/stan/math/rev/core/vari.hpp @@ -189,24 +189,25 @@ using vari = vari_value; template -class vari_value::value>> { +class vari_value::value>> : public vari_base { private: template friend class var_value; - using eigen_scalar = value_type_t; - value_type_t* val_mem_; - value_type_t* adj_mem_; - + template + friend class vari_value; public: - using Scalar = T; - using value_type = T; - using PlainObject = typename T::PlainObject; + using PlainObject = typename std::decay_t::PlainObject; + using eigen_scalar = value_type_t; + value_type_t* val_mem_; + value_type_t* adj_mem_; + using Scalar = std::decay_t; + using value_type = Scalar; using eigen_map = Eigen::Map; const Eigen::Index rows_; const Eigen::Index cols_; const Eigen::Index size_; - const Eigen::Index RowsAtCompileTime = T::RowsAtCompileTime; - const Eigen::Index ColsAtCompileTime = T::ColsAtCompileTime; + const Eigen::Index RowsAtCompileTime = Scalar::RowsAtCompileTime; + const Eigen::Index ColsAtCompileTime = Scalar::ColsAtCompileTime; /** * The value of this variable. */ @@ -230,7 +231,8 @@ class vari_value::value>> { * * @param x Value of the constructed variable. */ - explicit vari_value(const T& x) + template * = nullptr> + explicit vari_value(S&& x) : val_mem_(ChainableStack::instance_->memalloc_.alloc_array( x.size())), adj_mem_(ChainableStack::instance_->memalloc_.alloc_array( @@ -244,8 +246,8 @@ class vari_value::value>> { adj_.setZero(); ChainableStack::instance_->var_stack_.push_back(this); } - - vari_value(const T& x, bool stacked) + template * = nullptr> + vari_value(S&& x, bool stacked) : val_mem_(ChainableStack::instance_->memalloc_.alloc_array( x.size())), adj_mem_(ChainableStack::instance_->memalloc_.alloc_array( @@ -325,15 +327,180 @@ class vari_value::value>> { } }; -struct vari_printer { - std::ostream& o_; - int i_{0}; - vari_printer(std::ostream& o, int i) : o_(o), i_(i) {} - template - inline void operator()(T*& x) const { - o_ << i_ << " " << x << " " << x->val_ << " : " << x->adj_ << std::endl; +template +class vari_value::value>> : public vari_base { + private: + template + friend class var_value; + public: + using PlainObject = std::decay_t::PlainObject>; + using eigen_scalar = value_type_t; + using eigen_index = typename std::decay_t::StorageIndex; + using Scalar = std::decay_t; + using value_type = Scalar; + using eigen_map = Eigen::Map; + eigen_scalar* val_mem_; + eigen_index* val_outer_index_; + eigen_index* val_inner_index_; + eigen_scalar* adj_mem_; + eigen_index* adj_outer_index_; + eigen_index* adj_inner_index_; + const Eigen::Index rows_; + const Eigen::Index cols_; + const Eigen::Index size_; + const Eigen::Index RowsAtCompileTime = T::RowsAtCompileTime; + const Eigen::Index ColsAtCompileTime = T::ColsAtCompileTime; + /** + * The value of this variable. + */ + eigen_map val_; + + /** + * The adjoint of this variable, which is the partial derivative + * of this variable with respect to the root variable. + */ + eigen_map adj_; + + /** + * Construct a variable implementation from a value. The + * adjoint is initialized to zero. + * + * All constructed variables are added to the stack. Variables + * should be constructed before variables on which they depend + * to insure proper partial derivative propagation. During + * derivative propagation, the chain() method of each variable + * will be called in the reverse order of construction. + * + * @param x Value of the constructed variable. + */ + template * = nullptr> + explicit vari_value(S&& x) + : val_mem_(ChainableStack::instance_->memalloc_.alloc_array( + x.nonZeros())), + val_outer_index_(ChainableStack::instance_->memalloc_.alloc_array( + x.outerSize())), + val_inner_index_(ChainableStack::instance_->memalloc_.alloc_array( + x.innerSize())), + adj_mem_(ChainableStack::instance_->memalloc_.alloc_array( + x.nonZeros())), + adj_outer_index_(ChainableStack::instance_->memalloc_.alloc_array( + x.outerSize())), + adj_inner_index_(ChainableStack::instance_->memalloc_.alloc_array( + x.innerSize())), + rows_(x.rows()), + cols_(x.cols()), + size_(x.size()), + val_(x.rows(), x.cols(), x.nonZeros(), val_outer_index_, val_inner_index_, val_mem_), + adj_(x.rows(), x.cols(), x.nonZeros(), adj_outer_index_, adj_inner_index_, adj_mem_) { + val_ = Eigen::Map(x.rows(), x.cols(), x.nonZeros(), x.outerIndexPtr(), x.innerIndexPtr(),x.valuePtr()); + adj_ = Eigen::Map(x.rows(), x.cols(), x.nonZeros(), x.outerIndexPtr(), x.innerIndexPtr(), adj_mem_); + for (int k = 0; k < adj_.outerSize(); ++k) { + for (typename eigen_map::InnerIterator it(adj_, k); it; ++it) { + it.valueRef() = 0.0; + } + } + ChainableStack::instance_->var_stack_.push_back(this); + } + template * = nullptr> + vari_value(S&& x, bool stacked) + : val_mem_(ChainableStack::instance_->memalloc_.alloc_array( + x.nonZeros())), + val_outer_index_(ChainableStack::instance_->memalloc_.alloc_array( + x.outerSize())), + val_inner_index_(ChainableStack::instance_->memalloc_.alloc_array( + x.innerSize())), + adj_mem_(ChainableStack::instance_->memalloc_.alloc_array( + x.nonZeros())), + adj_outer_index_(ChainableStack::instance_->memalloc_.alloc_array( + x.outerSize())), + adj_inner_index_(ChainableStack::instance_->memalloc_.alloc_array( + x.innerSize())), + rows_(x.rows()), + cols_(x.cols()), + size_(x.size()), + val_(x.rows(), x.cols(), x.nonZeros(), val_outer_index_, val_inner_index_, val_mem_), + adj_(x.rows(), x.cols(), x.nonZeros(), adj_outer_index_, adj_inner_index_, adj_mem_) { + val_ = Eigen::Map(x.rows(), x.cols(), x.nonZeros(), x.outerIndexPtr(), x.innerIndexPtr(), x.valuePtr()); + adj_ = Eigen::Map(x.rows(), x.cols(), x.nonZeros(), x.outerIndexPtr(), x.innerIndexPtr(), adj_mem_); + for (int k = 0; k < adj_.outerSize(); ++k) { + for (typename eigen_map::InnerIterator it(adj_, k); it; ++it) { + it.valueRef() = 0.0; + } + } + if (stacked) { + ChainableStack::instance_->var_stack_.push_back(this); + } else { + ChainableStack::instance_->var_nochain_stack_.push_back(this); + } + } + + const Eigen::Index rows() const { return rows_; } + const Eigen::Index cols() const { return cols_; } + const Eigen::Index size() const { return size_; } + void chain() {} + /** + * Initialize the adjoint for this (dependent) variable to 1. + * This operation is applied to the dependent variable before + * propagating derivatives, setting the derivative of the + * result with respect to itself to be 1. + */ + inline void init_dependent() { adj_.setOnes(); } + + /** + * Set the adjoint value of this variable to 0. This is used to + * reset adjoints before propagating derivatives again (for + * example in a Jacobian calculation). + */ + inline void set_zero_adjoint() noexcept final { + for (int k = 0; k < adj_.outerSize(); ++k) { + for (typename eigen_map::InnerIterator it(adj_, k); it; ++it) { + it.valueRef() = 0.0; + } + } + } + + /** + * Insertion operator for vari. Prints the current value and + * the adjoint value. + * + * @param os [in, out] ostream to modify + * @param v [in] vari object to print. + * + * @return The modified ostream. + */ + friend std::ostream& operator<<(std::ostream& os, const vari_value* v) { + return os << v->val_ << ":" << v->adj_; + } + + /** + * Allocate memory from the underlying memory pool. This memory is + * is managed as a whole externally. + * + * Warning: Classes should not be allocated with this operator + * if they have non-trivial destructors. + * + * @param nbytes Number of bytes to allocate. + * @return Pointer to allocated bytes. + */ + static inline void* operator new(size_t nbytes) { + return ChainableStack::instance_->memalloc_.alloc(nbytes); + } + + /** + * Delete a pointer from the underlying memory pool. + * + * This no-op implementation enables a subclass to throw + * exceptions in its constructor. An exception thrown in the + * constructor of a subclass will result in an error being + * raised, which is in turn caught and calls delete(). + * + * See the discussion of "plugging the memory leak" in: + * http://www.parashift.com/c++-faq/memory-pools.html + */ + static inline void operator delete(void* /* ignore arg */) { /* no op */ } }; + } // namespace math } // namespace stan #endif diff --git a/test/unit/math/rev/core/var_test.cpp b/test/unit/math/rev/core/var_test.cpp index 2b792ac41cd..14f22cd2773 100644 --- a/test/unit/math/rev/core/var_test.cpp +++ b/test/unit/math/rev/core/var_test.cpp @@ -1,5 +1,6 @@ #include #include +#include #include #include #include @@ -15,7 +16,7 @@ struct AgradRev : public testing::Test { }; template -void ctor_overloads_impl() { +void ctor_overloads_float_impl() { using stan::math::var_value; using stan::math::vari_value; using stan::math::test::type_name; @@ -39,28 +40,94 @@ void ctor_overloads_impl() { } template -void ctor_overloads() { - ctor_overloads_impl(); - ctor_overloads_impl(); - ctor_overloads_impl(); - ctor_overloads_impl(); - ctor_overloads_impl(); - ctor_overloads_impl(); - ctor_overloads_impl(); - ctor_overloads_impl(); - ctor_overloads_impl(); - ctor_overloads_impl(); - ctor_overloads_impl(); - ctor_overloads_impl(); - ctor_overloads_impl(); +void ctor_overloads_float() { + ctor_overloads_float_impl(); + ctor_overloads_float_impl(); + ctor_overloads_float_impl(); + ctor_overloads_float_impl(); + ctor_overloads_float_impl(); + ctor_overloads_float_impl(); + ctor_overloads_float_impl(); + ctor_overloads_float_impl(); + ctor_overloads_float_impl(); + ctor_overloads_float_impl(); + ctor_overloads_float_impl(); + ctor_overloads_float_impl(); + ctor_overloads_float_impl(); } -TEST_F(AgradRev, ctorOverloads) { - ctor_overloads(); - ctor_overloads(); - ctor_overloads(); +TEST_F(AgradRev, ctorfloatOverloads) { + ctor_overloads_float(); + ctor_overloads_float(); + ctor_overloads_float(); } +template +void ctor_overloads_matrix(EigenMat&& xx) { + using stan::math::var_value; + using stan::math::vari_value; + using stan::math::test::type_name; + using plain_type = std::decay_t>; + // standard constructor + plain_type x = xx; + EXPECT_MATRIX_FLOAT_EQ(x, var_value(x).val()); + // make sure copy ctor is used rather than casting vari* to unsigned int + EXPECT_MATRIX_FLOAT_EQ(x, var_value(new vari_value(x)).val()); + // make sure rvalue var_value can be accepted + EXPECT_MATRIX_FLOAT_EQ(x, var_value(var_value(x)).val()); +} + +template +void ctor_overloads_sparse_matrix(EigenMat&& x) { + using stan::math::var_value; + using stan::math::vari_value; + using stan::math::test::type_name; + // standard constructor + std::decay_t xx = var_value>(x).val(); + for (int k = 0; k < x.outerSize(); ++k) { + for (typename std::decay_t::InnerIterator it(x,k), iz(xx,k); + it; ++it, ++iz) { + EXPECT_FLOAT_EQ(iz.value(), it.value()); + } + } + std::decay_t xxx = var_value>(var_value>(x)).val(); + for (int k = 0; k < x.outerSize(); ++k) { + for (typename std::decay_t::InnerIterator it(x,k), iz(xxx,k); + it; ++it, ++iz) { + EXPECT_FLOAT_EQ(iz.value(), it.value()); + std::cout << "iz[" << iz.index() << "]: " << iz.value() << " it[" << it.index() << "]: " << it.value() << std::endl; + } + } + +} + +auto make_sparse_matrix_random(int rows, int cols) { +using eigen_triplet = Eigen::Triplet; +boost::mt19937 gen; +boost::random::uniform_real_distribution dist(0.0,1.0); +std::vector tripletList; + for(int i = 0; i < rows; ++i) { + for(int j = 0; j < cols; ++j) { + auto v_ij = dist(gen); //generate random number + if(v_ij < 0.1) { + tripletList.push_back(eigen_triplet(i,j,v_ij)); //if larger than treshold, insert it + } + } + } + Eigen::SparseMatrix mat(rows, cols); + mat.setFromTriplets(tripletList.begin(), tripletList.end()); + return mat; +} + +TEST_F(AgradRev, ctormatrixOverloads) { + using dense_mat = Eigen::Matrix; + using sparse_mat = Eigen::SparseMatrix; + ctor_overloads_matrix(dense_mat::Random(2, 2)); + sparse_mat sparse_x = make_sparse_matrix_random(2, 2); + ctor_overloads_sparse_matrix(sparse_x); +} + + TEST_F(AgradRev, a_eq_x) { AVAR a = 5.0; EXPECT_FLOAT_EQ(5.0, a.val()); From 2130cfed2b45ba4a2974402b369182b6d704e4f9 Mon Sep 17 00:00:00 2001 From: Steve Bronder Date: Sun, 28 Jun 2020 18:51:19 -0400 Subject: [PATCH 123/355] adds sparse and dense vari_value specializations --- stan/math/prim/fun/MatrixExponential.h | 2 +- stan/math/prim/meta/is_eigen_sparse_base.hpp | 4 +- .../rev/core/set_zero_all_adjoints_nested.hpp | 3 +- stan/math/rev/core/var.hpp | 23 +- stan/math/rev/core/vari.hpp | 376 ++++++++++++------ test/unit/math/rev/core/var_test.cpp | 96 +++-- 6 files changed, 344 insertions(+), 160 deletions(-) diff --git a/stan/math/prim/fun/MatrixExponential.h b/stan/math/prim/fun/MatrixExponential.h index 85e9f8274fa..74ae2a47ee2 100644 --- a/stan/math/prim/fun/MatrixExponential.h +++ b/stan/math/prim/fun/MatrixExponential.h @@ -185,7 +185,7 @@ namespace Eigen { { template static void run(const MatrixType& arg, MatrixType& U, MatrixType& V, int& squarings, - T scalar_type) + T scalar_type) { using std::frexp; using std::pow; diff --git a/stan/math/prim/meta/is_eigen_sparse_base.hpp b/stan/math/prim/meta/is_eigen_sparse_base.hpp index 67d48396203..b6eee02a4a7 100644 --- a/stan/math/prim/meta/is_eigen_sparse_base.hpp +++ b/stan/math/prim/meta/is_eigen_sparse_base.hpp @@ -19,8 +19,8 @@ namespace stan { */ template struct is_eigen_sparse_base - : bool_constant::value> { -}; + : bool_constant< + is_base_pointer_convertible::value> {}; STAN_ADD_REQUIRE_UNARY(eigen_sparse_base, is_eigen_sparse_base, require_eigens_types); diff --git a/stan/math/rev/core/set_zero_all_adjoints_nested.hpp b/stan/math/rev/core/set_zero_all_adjoints_nested.hpp index 070b718e82a..d81f5de557c 100644 --- a/stan/math/rev/core/set_zero_all_adjoints_nested.hpp +++ b/stan/math/rev/core/set_zero_all_adjoints_nested.hpp @@ -23,7 +23,8 @@ static void set_zero_all_adjoints_nested() { "empty_nested() must be false before calling" " set_zero_all_adjoints_nested()"); } - const size_t start1 = ChainableStack::instance_->nested_var_stack_sizes_.back(); + const size_t start1 = + ChainableStack::instance_->nested_var_stack_sizes_.back(); // avoid wrap with unsigned when start1 == 0 for (size_t i = (start1 == 0U) ? 0U : (start1 - 1); i < ChainableStack::instance_->var_stack_.size(); ++i) { diff --git a/stan/math/rev/core/var.hpp b/stan/math/rev/core/var.hpp index e704b796e4b..32d772293dc 100644 --- a/stan/math/rev/core/var.hpp +++ b/stan/math/rev/core/var.hpp @@ -36,7 +36,7 @@ class var_value {}; template class var_value> { public: - using value_type = std::decay_t>; // type in vari_value. + using value_type = std::decay_t>; // type in vari_value. using vari_type = vari_value; // Type of underlying vari impl. using vari_pointer = vari_type*; // pointer type for underlying vari. @@ -76,16 +76,33 @@ class var_value> { * @tparam S A type that is convertible to `value_type`. * @param x Value of the variable. */ - template * = nullptr> + template * = nullptr, + require_not_eigen_sparse_base_t* = nullptr> var_value(S&& x) : vi_(new vari_type(std::forward(x), false)) {} // NOLINT + /** + * Construct a variable from the specified floating point argument + * by constructing a new `vari_value`. This constructor is only + * valid when `S` is convertible to this `vari_value`'s `value_type` and is + * derived from Eigen's sparse matrix base class. This specialization exists + * because Eigen sparse matrix expressions do not have `innerSize()` and + * `outerSize()` members. While dense matrix expressions can be passed along + * to the constructor for `vari_value`, sparse matrix expressions need to + * be evaluated before they are passed to the `vari_value` constructor. + * @tparam S A type that is convertible to `value_type`. + * @param x Value of the variable. + */ + template * = nullptr, + require_eigen_sparse_base_t* = nullptr> + var_value(S&& x) : vi_(new vari_type(ref_type_t(x), false)) {} // NOLINT + /** * Construct a variable from a pointer to a variable implementation. * @param vi A vari_value pointer. */ template * = nullptr> var_value(vari_value* vi) // NOLINT - : vi_(vi) {} + : vi_(vi) {} /** * Return a constant reference to the value of this variable. diff --git a/stan/math/rev/core/vari.hpp b/stan/math/rev/core/vari.hpp index 6868ab941ab..c69ce0af278 100644 --- a/stan/math/rev/core/vari.hpp +++ b/stan/math/rev/core/vari.hpp @@ -36,7 +36,7 @@ class vari_base { template class vari_value; /** - * The variable implementation base class. + * The variable implementation for floating point types. * * This class is complete (not abstract) and may be used for * constants. @@ -186,32 +186,42 @@ class vari_value::value>> // For backwards compatability the default is double using vari = vari_value; - - +/** + * The variable implementation for Eigen dense matrix types. + * + * This class is complete (not abstract) and may be used for + * constants. + * + * A variable implementation is constructed with a constant + * value. It also stores the adjoint for storing the partial + * derivative with respect to the root of the derivative tree. + * + */ template -class vari_value::value>> : public vari_base { - private: - template - friend class var_value; - template - friend class vari_value; +class vari_value::value>> + : public vari_base { public: - using PlainObject = typename std::decay_t::PlainObject; - using eigen_scalar = value_type_t; - value_type_t* val_mem_; - value_type_t* adj_mem_; - using Scalar = std::decay_t; - using value_type = Scalar; - using eigen_map = Eigen::Map; - const Eigen::Index rows_; - const Eigen::Index cols_; - const Eigen::Index size_; - const Eigen::Index RowsAtCompileTime = Scalar::RowsAtCompileTime; - const Eigen::Index ColsAtCompileTime = Scalar::ColsAtCompileTime; /** - * The value of this variable. + * `PlainObject` represents a user constructible type such as Matrix or Array + */ + using PlainObject = std::decay_t>; + using eigen_scalar = value_type_t; // A floating point type + eigen_scalar* val_mem_; // Pointer to memory allocated on the stack for val_ + eigen_scalar* adj_mem_; // Pointer to memory allocated on the stack for adj_ + using Scalar = PlainObject; // The underlying type for this class + using value_type = Scalar; // The underlying type for this class + using eigen_map = Eigen::Map; // Maps for adj_ and val_ + const Eigen::Index rows_; // Number of rows + const Eigen::Index cols_; // Number of cols + const Eigen::Index size_; // Size of rows * cols + /** + * Number of rows known at compile time */ - eigen_map val_; + static constexpr Eigen::Index RowsAtCompileTime = Scalar::RowsAtCompileTime; + /** + * Number of columns known at compile time + */ + static constexpr Eigen::Index ColsAtCompileTime = Scalar::ColsAtCompileTime; /** * The adjoint of this variable, which is the partial derivative @@ -220,45 +230,65 @@ class vari_value::value>> : public va eigen_map adj_; /** - * Construct a variable implementation from a value. The + * The value of this variable. + */ + const eigen_map val_; + + /** + * Construct a dense Eigen variable implementation from a value. The * adjoint is initialized to zero. * - * All constructed variables are added to the stack. Variables + * All constructed variables are added to the stack. Variables * should be constructed before variables on which they depend * to insure proper partial derivative propagation. During * derivative propagation, the chain() method of each variable * will be called in the reverse order of construction. * + * @tparam S A dense Eigen type that is convertible to `value_type` * @param x Value of the constructed variable. */ - template * = nullptr> + template * = nullptr> explicit vari_value(S&& x) : val_mem_(ChainableStack::instance_->memalloc_.alloc_array( - x.size())), + x.size())), adj_mem_(ChainableStack::instance_->memalloc_.alloc_array( x.size())), rows_(x.rows()), cols_(x.cols()), size_(x.size()), - val_(val_mem_, x.rows(), x.cols()), - adj_(adj_mem_, x.rows(), x.cols()) { - val_ = x; - adj_.setZero(); + adj_(make_adj(adj_mem_, x)), + val_(make_val(val_mem_, std::forward(x))) { ChainableStack::instance_->var_stack_.push_back(this); } + + /** + * Construct an dense Eigen variable implementation from a value. The + * adjoint is initialized to zero and if `stacked` is `false` this vari + * will be not be put on the var_stack. Instead it will only be put on + * a stack to keep track of whether the adjoint needs to be set to zero. + * + * All constructed variables are added to a stack. Variables + * should be constructed before variables on which they depend + * to insure proper partial derivative propagation. During + * derivative propagation, the chain() method of each variable + * will be called in the reverse order of construction. + * + * @tparam S A dense Eigen type that is convertible to `value_type` + * @param x Value of the constructed variable. + * @param stacked If false will put this this vari on the nochain stack so + * that its `chain()` method is not called. + */ template * = nullptr> vari_value(S&& x, bool stacked) : val_mem_(ChainableStack::instance_->memalloc_.alloc_array( - x.size())), + x.size())), adj_mem_(ChainableStack::instance_->memalloc_.alloc_array( x.size())), rows_(x.rows()), cols_(x.cols()), size_(x.size()), - val_(val_mem_, x.rows(), x.cols()), - adj_(adj_mem_, x.rows(), x.cols()) { - val_ = x; - adj_.setZero(); + adj_(make_adj(adj_mem_, x)), + val_(make_val(val_mem_, x)) { if (stacked) { ChainableStack::instance_->var_stack_.push_back(this); } else { @@ -266,9 +296,19 @@ class vari_value::value>> : public va } } + /** + * Return the number of rows for this class's `val_` member + */ const Eigen::Index rows() const { return rows_; } + /** + * Return the number of columns for this class's `val_` member + */ const Eigen::Index cols() const { return cols_; } + /** + * Return the size of this class's `val_` member + */ const Eigen::Index size() const { return size_; } + virtual void chain() {} /** * Initialize the adjoint for this (dependent) variable to 1. @@ -283,7 +323,7 @@ class vari_value::value>> : public va * reset adjoints before propagating derivatives again (for * example in a Jacobian calculation). */ - void set_zero_adjoint() { adj_.setZero(); } + inline void set_zero_adjoint() final { adj_.setZero(); } /** * Insertion operator for vari. Prints the current value and @@ -325,35 +365,77 @@ class vari_value::value>> : public va */ static inline void operator delete(void* /* ignore arg */) { /* no op */ } -}; -template -class vari_value::value>> : public vari_base { private: template friend class var_value; + /** + * Create the map to the val_ stack allocated memory for an Eigen input. + * @tparam S an Eigen type. + * @param mem A pointer to stack allocated memory. + * @param x The Eigen type whose values will be assigned to `val_` + */ + template + inline eigen_map make_val(eigen_scalar*& mem, S&& x) { + eigen_map(mem, x.rows(), x.cols()) = std::forward(x); + return eigen_map(mem, x.rows(), x.cols()); + } + /** + * Create the map to the adj_ stack allocated memory for an Eigen input. + * @tparam S an Eigen type. + * @param mem A pointer to stack allocated memory. + * @param x The Eigen type whose dimensions are set the `adj_`s dimensions. + */ + template + inline eigen_map make_adj(eigen_scalar*& mem, S&& x) { + eigen_map(mem, x.rows(), x.cols()).setZero(); + return eigen_map(mem, x.rows(), x.cols()); + } +}; + +/** + * The variable implementation for Eigen sparse matrix types. + * + * This class is complete (not abstract) and may be used for + * constants. + * + * A variable implementation is constructed with a constant + * value. It also stores the adjoint for storing the partial + * derivative with respect to the root of the derivative tree. + * + */ +template +class vari_value::value>> + : public vari_base { public: - using PlainObject = std::decay_t::PlainObject>; - using eigen_scalar = value_type_t; - using eigen_index = typename std::decay_t::StorageIndex; - using Scalar = std::decay_t; - using value_type = Scalar; - using eigen_map = Eigen::Map; - eigen_scalar* val_mem_; - eigen_index* val_outer_index_; - eigen_index* val_inner_index_; - eigen_scalar* adj_mem_; - eigen_index* adj_outer_index_; - eigen_index* adj_inner_index_; - const Eigen::Index rows_; - const Eigen::Index cols_; - const Eigen::Index size_; - const Eigen::Index RowsAtCompileTime = T::RowsAtCompileTime; - const Eigen::Index ColsAtCompileTime = T::ColsAtCompileTime; + using PlainObject + = std::decay_t>; // Base type of Eigen class + using eigen_scalar = value_type_t; // Scalar type of Eigen class + using eigen_index = typename PlainObject::StorageIndex; // Index type + using Scalar = PlainObject; // vari's adj_ and val_ member type + using value_type = Scalar; // vari's adj_ and val_ member type + using eigen_map = Eigen::Map; // Map of stack alloc'd mem + eigen_scalar* val_mem_; // The value's nonzero values + eigen_index* val_outer_index_; // Value's Outer index of nonzero members + eigen_index* val_inner_index_; // Value's Inner index of nonzero members + eigen_scalar* adj_mem_; // Adjoint's nonzero values + eigen_index* adj_outer_index_; // Adjoint's outer index of nonzero members + eigen_index* adj_inner_index_; // Adjont's inner index of nonzero members + const Eigen::Index rows_; // Number of rows in val_ + const Eigen::Index cols_; // Number of cols in val_ + const Eigen::Index size_; // Size of val_ + /** + * Rows at compile time + */ + static constexpr Eigen::Index RowsAtCompileTime = T::RowsAtCompileTime; + /** + * Columns at compile time + */ + static constexpr Eigen::Index ColsAtCompileTime = T::ColsAtCompileTime; /** * The value of this variable. */ - eigen_map val_; + const eigen_map val_; /** * The adjoint of this variable, which is the partial derivative @@ -362,71 +444,84 @@ class vari_value::value>> : public v eigen_map adj_; /** - * Construct a variable implementation from a value. The + * Construct a variable implementation from a value. The * adjoint is initialized to zero. * - * All constructed variables are added to the stack. Variables - * should be constructed before variables on which they depend + * All constructed variables are added to the stack. For a sparse eigen matrix + * this includes the nozero values as well the inner and outer indices. + * Variables should be constructed before variables on which they depend * to insure proper partial derivative propagation. During * derivative propagation, the chain() method of each variable * will be called in the reverse order of construction. * + * @tparam S A sparse Eigen type that is convertible to `value_type` * @param x Value of the constructed variable. */ - template * = nullptr> + template * = nullptr> explicit vari_value(S&& x) : val_mem_(ChainableStack::instance_->memalloc_.alloc_array( - x.nonZeros())), - val_outer_index_(ChainableStack::instance_->memalloc_.alloc_array( - x.outerSize())), - val_inner_index_(ChainableStack::instance_->memalloc_.alloc_array( - x.innerSize())), - adj_mem_(ChainableStack::instance_->memalloc_.alloc_array( - x.nonZeros())), - adj_outer_index_(ChainableStack::instance_->memalloc_.alloc_array( - x.outerSize())), - adj_inner_index_(ChainableStack::instance_->memalloc_.alloc_array( - x.innerSize())), + x.nonZeros())), + val_outer_index_( + ChainableStack::instance_->memalloc_.alloc_array( + x.innerSize())), + val_inner_index_( + ChainableStack::instance_->memalloc_.alloc_array( + x.innerSize())), + adj_mem_(ChainableStack::instance_->memalloc_.alloc_array( + x.innerSize())), + adj_outer_index_( + ChainableStack::instance_->memalloc_.alloc_array( + x.outerSize())), + adj_inner_index_( + ChainableStack::instance_->memalloc_.alloc_array( + x.innerSize())), rows_(x.rows()), cols_(x.cols()), size_(x.size()), - val_(x.rows(), x.cols(), x.nonZeros(), val_outer_index_, val_inner_index_, val_mem_), - adj_(x.rows(), x.cols(), x.nonZeros(), adj_outer_index_, adj_inner_index_, adj_mem_) { - val_ = Eigen::Map(x.rows(), x.cols(), x.nonZeros(), x.outerIndexPtr(), x.innerIndexPtr(),x.valuePtr()); - adj_ = Eigen::Map(x.rows(), x.cols(), x.nonZeros(), x.outerIndexPtr(), x.innerIndexPtr(), adj_mem_); - for (int k = 0; k < adj_.outerSize(); ++k) { - for (typename eigen_map::InnerIterator it(adj_, k); it; ++it) { - it.valueRef() = 0.0; - } - } + val_(make_val(val_outer_index_, val_inner_index_, val_mem_, x)), + adj_(make_adj(adj_outer_index_, adj_inner_index_, adj_mem_, x)) { ChainableStack::instance_->var_stack_.push_back(this); } + /** + * Construct an sparse Eigen variable implementation from a value. The + * adjoint is initialized to zero and if `stacked` is `false` this vari + * will be not be put on the var_stack. Instead it will only be put on + * a stack to keep track of whether the adjoint needs to be set to zero. + * + * All constructed variables are added to a stack. Variables + * should be constructed before variables on which they depend + * to insure proper partial derivative propagation. During + * derivative propagation, the chain() method of each variable + * will be called in the reverse order of construction. + * + * @tparam S A sparse Eigen type that is convertible to `value_type` + * @param x Value of the constructed variable. + * @param stacked If false will put this this vari on the nochain stack so + * that its `chain()` method is not called. + */ template * = nullptr> vari_value(S&& x, bool stacked) - : val_mem_(ChainableStack::instance_->memalloc_.alloc_array( - x.nonZeros())), - val_outer_index_(ChainableStack::instance_->memalloc_.alloc_array( - x.outerSize())), - val_inner_index_(ChainableStack::instance_->memalloc_.alloc_array( - x.innerSize())), - adj_mem_(ChainableStack::instance_->memalloc_.alloc_array( - x.nonZeros())), - adj_outer_index_(ChainableStack::instance_->memalloc_.alloc_array( - x.outerSize())), - adj_inner_index_(ChainableStack::instance_->memalloc_.alloc_array( - x.innerSize())), - rows_(x.rows()), - cols_(x.cols()), - size_(x.size()), - val_(x.rows(), x.cols(), x.nonZeros(), val_outer_index_, val_inner_index_, val_mem_), - adj_(x.rows(), x.cols(), x.nonZeros(), adj_outer_index_, adj_inner_index_, adj_mem_) { - val_ = Eigen::Map(x.rows(), x.cols(), x.nonZeros(), x.outerIndexPtr(), x.innerIndexPtr(), x.valuePtr()); - adj_ = Eigen::Map(x.rows(), x.cols(), x.nonZeros(), x.outerIndexPtr(), x.innerIndexPtr(), adj_mem_); - for (int k = 0; k < adj_.outerSize(); ++k) { - for (typename eigen_map::InnerIterator it(adj_, k); it; ++it) { - it.valueRef() = 0.0; - } - } + : val_mem_(ChainableStack::instance_->memalloc_.alloc_array( + x.innerSize())), + val_outer_index_( + ChainableStack::instance_->memalloc_.alloc_array( + x.outerSize())), + val_inner_index_( + ChainableStack::instance_->memalloc_.alloc_array( + x.innerSize())), + adj_mem_(ChainableStack::instance_->memalloc_.alloc_array( + x.innerSize())), + adj_outer_index_( + ChainableStack::instance_->memalloc_.alloc_array( + x.outerSize())), + adj_inner_index_( + ChainableStack::instance_->memalloc_.alloc_array( + x.innerSize())), + rows_(x.rows()), + cols_(x.cols()), + size_(x.size()), + val_(make_val(val_outer_index_, val_inner_index_, val_mem_, x)), + adj_(make_adj(adj_outer_index_, adj_inner_index_, adj_mem_, x)) { if (stacked) { ChainableStack::instance_->var_stack_.push_back(this); } else { @@ -434,8 +529,17 @@ class vari_value::value>> : public v } } + /** + * Return the number of rows for this class's `val_` member + */ const Eigen::Index rows() const { return rows_; } + /** + * Return the number of columns for this class's `val_` member + */ const Eigen::Index cols() const { return cols_; } + /** + * Return the size of this class's `val_` member + */ const Eigen::Index size() const { return size_; } void chain() {} /** @@ -452,12 +556,12 @@ class vari_value::value>> : public v * example in a Jacobian calculation). */ inline void set_zero_adjoint() noexcept final { - for (int k = 0; k < adj_.outerSize(); ++k) { - for (typename eigen_map::InnerIterator it(adj_, k); it; ++it) { - it.valueRef() = 0.0; - } - } - } + for (int k = 0; k < adj_.outerSize(); ++k) { + for (typename eigen_map::InnerIterator it(adj_, k); it; ++it) { + it.valueRef() = 0.0; + } + } + } /** * Insertion operator for vari. Prints the current value and @@ -499,6 +603,54 @@ class vari_value::value>> : public v */ static inline void operator delete(void* /* ignore arg */) { /* no op */ } + + private: + template + friend class var_value; + /** + * Fill the val_ map and it's pointers. + * @tparam S An Eigen sparse matrix type. + * @param outer_mem Stack allocated memory for the outer index. + * @param inner_mem Stack allocated memory for the inner index. + * @param val_mem Stack allocated memory for the matrix values. + * @note This function exists because Eigen's `Map` class for sparse matrices + * has a lot of gotchas. + */ + template + inline eigen_map make_val(eigen_index*& outer_mem, eigen_index*& inner_mem, + eigen_scalar*& val_mem, S&& x) { + for (int k = 0; k < x.innerSize(); ++k) { + val_mem[k] = x.valuePtr()[k]; + inner_mem[k] = x.innerIndexPtr()[k]; + } + for (int k = 0; k < x.outerSize(); ++k) { + outer_mem[k] = x.outerIndexPtr()[k]; + } + return eigen_map(x.rows(), x.cols(), x.nonZeros(), outer_mem, inner_mem, + val_mem); + } + /** + * Fill the val_ map and it's pointers. + * @tparam S An Eigen sparse matrix type. + * @param outer_mem Stack allocated memory for the outer index. + * @param inner_mem Stack allocated memory for the inner index. + * @param val_mem Stack allocated memory for the matrix values. + * @note This function exists because Eigen's `Map` class for sparse matrices + * has a lot of gotchas. + */ + template + inline eigen_map make_adj(eigen_index*& outer_mem, eigen_index*& inner_mem, + eigen_scalar*& val_mem, S&& x) { + for (int k = 0; k < x.innerSize(); ++k) { + val_mem[k] = 0.0; + inner_mem[k] = x.innerIndexPtr()[k]; + } + for (int k = 0; k < x.outerSize(); ++k) { + outer_mem[k] = x.outerIndexPtr()[k]; + } + return eigen_map(x.rows(), x.cols(), x.nonZeros(), outer_mem, inner_mem, + val_mem); + } }; } // namespace math diff --git a/test/unit/math/rev/core/var_test.cpp b/test/unit/math/rev/core/var_test.cpp index 14f22cd2773..ee9064fea4a 100644 --- a/test/unit/math/rev/core/var_test.cpp +++ b/test/unit/math/rev/core/var_test.cpp @@ -67,14 +67,16 @@ void ctor_overloads_matrix(EigenMat&& xx) { using stan::math::var_value; using stan::math::vari_value; using stan::math::test::type_name; - using plain_type = std::decay_t>; + using eigen_plain = std::decay_t>; + eigen_plain x = xx; // standard constructor - plain_type x = xx; - EXPECT_MATRIX_FLOAT_EQ(x, var_value(x).val()); + EXPECT_MATRIX_FLOAT_EQ((x * x).eval(), var_value(x * x).val()); // make sure copy ctor is used rather than casting vari* to unsigned int - EXPECT_MATRIX_FLOAT_EQ(x, var_value(new vari_value(x)).val()); + EXPECT_MATRIX_FLOAT_EQ( + x, var_value(new vari_value(x)).val()); // make sure rvalue var_value can be accepted - EXPECT_MATRIX_FLOAT_EQ(x, var_value(var_value(x)).val()); + EXPECT_MATRIX_FLOAT_EQ( + x, var_value(var_value(x)).val()); } template @@ -82,52 +84,64 @@ void ctor_overloads_sparse_matrix(EigenMat&& x) { using stan::math::var_value; using stan::math::vari_value; using stan::math::test::type_name; - // standard constructor - std::decay_t xx = var_value>(x).val(); - for (int k = 0; k < x.outerSize(); ++k) { - for (typename std::decay_t::InnerIterator it(x,k), iz(xx,k); - it; ++it, ++iz) { - EXPECT_FLOAT_EQ(iz.value(), it.value()); - } - } - std::decay_t xxx = var_value>(var_value>(x)).val(); - for (int k = 0; k < x.outerSize(); ++k) { - for (typename std::decay_t::InnerIterator it(x,k), iz(xxx,k); - it; ++it, ++iz) { - EXPECT_FLOAT_EQ(iz.value(), it.value()); - std::cout << "iz[" << iz.index() << "]: " << iz.value() << " it[" << it.index() << "]: " << it.value() << std::endl; - } - } + using eigen_plain = std::decay_t>; + using inner_iterator = typename eigen_plain::InnerIterator; + // standard constructor with eigen expression + eigen_plain matmul_x = x * x; + eigen_plain matmul_xx = var_value(x * x).val(); + for (int k = 0; k < matmul_x.outerSize(); ++k) { + for (inner_iterator it(matmul_x, k), iz(matmul_xx, k); it; ++it, ++iz) { + EXPECT_FLOAT_EQ(iz.value(), it.value()); + } + } + // make sure rvalue var_value can be accepted + eigen_plain x_rv = var_value(var_value(x)).val(); + for (int k = 0; k < x.outerSize(); ++k) { + for (inner_iterator it(x, k), iz(x_rv, k); it; ++it, ++iz) { + EXPECT_FLOAT_EQ(iz.value(), it.value()); + } + } + /** from a vari_value with sparse + * NOTE: This will fail with an expression since allocating the mem + * for the vari requires knowing the sizes of the inner and outer indices + * which is not computed for expressions. + */ + eigen_plain x_from_vari + = var_value(new vari_value(x)).val(); + for (int k = 0; k < x.outerSize(); ++k) { + for (inner_iterator it(x, k), iz(x_from_vari, k); it; ++it, ++iz) { + EXPECT_FLOAT_EQ(iz.value(), it.value()); + } + } } auto make_sparse_matrix_random(int rows, int cols) { -using eigen_triplet = Eigen::Triplet; -boost::mt19937 gen; -boost::random::uniform_real_distribution dist(0.0,1.0); -std::vector tripletList; - for(int i = 0; i < rows; ++i) { - for(int j = 0; j < cols; ++j) { - auto v_ij = dist(gen); //generate random number - if(v_ij < 0.1) { - tripletList.push_back(eigen_triplet(i,j,v_ij)); //if larger than treshold, insert it - } + using eigen_triplet = Eigen::Triplet; + boost::mt19937 gen; + boost::random::uniform_real_distribution dist(0.0, 1.0); + std::vector tripletList; + for (int i = 0; i < rows; ++i) { + for (int j = 0; j < cols; ++j) { + auto v_ij = dist(gen); + if (v_ij < 0.1) { + tripletList.push_back(eigen_triplet(i, j, v_ij)); + } } - } - Eigen::SparseMatrix mat(rows, cols); - mat.setFromTriplets(tripletList.begin(), tripletList.end()); - return mat; + } + Eigen::SparseMatrix mat(rows, cols); + mat.setFromTriplets(tripletList.begin(), tripletList.end()); + return mat; } TEST_F(AgradRev, ctormatrixOverloads) { - using dense_mat = Eigen::Matrix; - using sparse_mat = Eigen::SparseMatrix; - ctor_overloads_matrix(dense_mat::Random(2, 2)); - sparse_mat sparse_x = make_sparse_matrix_random(2, 2); - ctor_overloads_sparse_matrix(sparse_x); + using dense_mat = Eigen::Matrix; + using sparse_mat = Eigen::SparseMatrix; + ctor_overloads_matrix(dense_mat::Random(10, 10)); + sparse_mat sparse_x = make_sparse_matrix_random(10, 10); + ctor_overloads_sparse_matrix(sparse_x); } - TEST_F(AgradRev, a_eq_x) { AVAR a = 5.0; EXPECT_FLOAT_EQ(5.0, a.val()); From 6f1ce8a5946905eae9b869878c66c246bfb031c0 Mon Sep 17 00:00:00 2001 From: Stan Jenkins Date: Sun, 28 Jun 2020 19:06:20 -0400 Subject: [PATCH 124/355] [Jenkins] auto-formatting by clang-format version 6.0.0-1ubuntu2 (tags/RELEASE_600/final) --- stan/math/prim/meta/is_eigen_dense_base.hpp | 3 +-- stan/math/rev/core/set_zero_all_adjoints_nested.hpp | 4 ++-- stan/math/rev/core/vari.hpp | 12 ++++++------ 3 files changed, 9 insertions(+), 10 deletions(-) diff --git a/stan/math/prim/meta/is_eigen_dense_base.hpp b/stan/math/prim/meta/is_eigen_dense_base.hpp index d838d83af90..225f833b45c 100644 --- a/stan/math/prim/meta/is_eigen_dense_base.hpp +++ b/stan/math/prim/meta/is_eigen_dense_base.hpp @@ -19,8 +19,7 @@ namespace stan { */ template struct is_eigen_dense_base - : bool_constant::value> { -}; + : bool_constant::value> {}; STAN_ADD_REQUIRE_UNARY(eigen_dense_base, is_eigen_dense_base, require_eigens_types); diff --git a/stan/math/rev/core/set_zero_all_adjoints_nested.hpp b/stan/math/rev/core/set_zero_all_adjoints_nested.hpp index d81f5de557c..22c74b5ccc8 100644 --- a/stan/math/rev/core/set_zero_all_adjoints_nested.hpp +++ b/stan/math/rev/core/set_zero_all_adjoints_nested.hpp @@ -23,8 +23,8 @@ static void set_zero_all_adjoints_nested() { "empty_nested() must be false before calling" " set_zero_all_adjoints_nested()"); } - const size_t start1 = - ChainableStack::instance_->nested_var_stack_sizes_.back(); + const size_t start1 + = ChainableStack::instance_->nested_var_stack_sizes_.back(); // avoid wrap with unsigned when start1 == 0 for (size_t i = (start1 == 0U) ? 0U : (start1 - 1); i < ChainableStack::instance_->var_stack_.size(); ++i) { diff --git a/stan/math/rev/core/vari.hpp b/stan/math/rev/core/vari.hpp index c69ce0af278..f886ee514a3 100644 --- a/stan/math/rev/core/vari.hpp +++ b/stan/math/rev/core/vari.hpp @@ -250,7 +250,7 @@ class vari_value::value>> template * = nullptr> explicit vari_value(S&& x) : val_mem_(ChainableStack::instance_->memalloc_.alloc_array( - x.size())), + x.size())), adj_mem_(ChainableStack::instance_->memalloc_.alloc_array( x.size())), rows_(x.rows()), @@ -281,7 +281,7 @@ class vari_value::value>> template * = nullptr> vari_value(S&& x, bool stacked) : val_mem_(ChainableStack::instance_->memalloc_.alloc_array( - x.size())), + x.size())), adj_mem_(ChainableStack::instance_->memalloc_.alloc_array( x.size())), rows_(x.rows()), @@ -460,7 +460,7 @@ class vari_value::value>> template * = nullptr> explicit vari_value(S&& x) : val_mem_(ChainableStack::instance_->memalloc_.alloc_array( - x.nonZeros())), + x.nonZeros())), val_outer_index_( ChainableStack::instance_->memalloc_.alloc_array( x.innerSize())), @@ -502,7 +502,7 @@ class vari_value::value>> template * = nullptr> vari_value(S&& x, bool stacked) : val_mem_(ChainableStack::instance_->memalloc_.alloc_array( - x.innerSize())), + x.innerSize())), val_outer_index_( ChainableStack::instance_->memalloc_.alloc_array( x.outerSize())), @@ -618,7 +618,7 @@ class vari_value::value>> */ template inline eigen_map make_val(eigen_index*& outer_mem, eigen_index*& inner_mem, - eigen_scalar*& val_mem, S&& x) { + eigen_scalar*& val_mem, S&& x) { for (int k = 0; k < x.innerSize(); ++k) { val_mem[k] = x.valuePtr()[k]; inner_mem[k] = x.innerIndexPtr()[k]; @@ -640,7 +640,7 @@ class vari_value::value>> */ template inline eigen_map make_adj(eigen_index*& outer_mem, eigen_index*& inner_mem, - eigen_scalar*& val_mem, S&& x) { + eigen_scalar*& val_mem, S&& x) { for (int k = 0; k < x.innerSize(); ++k) { val_mem[k] = 0.0; inner_mem[k] = x.innerIndexPtr()[k]; From dd900b2d250648863038ee5fb6b4ad3dfab8f9f0 Mon Sep 17 00:00:00 2001 From: Steve Bronder Date: Sun, 28 Jun 2020 21:46:51 -0400 Subject: [PATCH 125/355] add docs for x param for eigen_map vari_value constructors --- stan/math/rev/core/vari.hpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/stan/math/rev/core/vari.hpp b/stan/math/rev/core/vari.hpp index c69ce0af278..45116a988b4 100644 --- a/stan/math/rev/core/vari.hpp +++ b/stan/math/rev/core/vari.hpp @@ -613,6 +613,7 @@ class vari_value::value>> * @param outer_mem Stack allocated memory for the outer index. * @param inner_mem Stack allocated memory for the inner index. * @param val_mem Stack allocated memory for the matrix values. + * @param x The Eigen sparse type to fill in the stack memory. * @note This function exists because Eigen's `Map` class for sparse matrices * has a lot of gotchas. */ @@ -635,6 +636,7 @@ class vari_value::value>> * @param outer_mem Stack allocated memory for the outer index. * @param inner_mem Stack allocated memory for the inner index. * @param val_mem Stack allocated memory for the matrix values. + * @param x The Eigen sparse type to fill in the stack memory. * @note This function exists because Eigen's `Map` class for sparse matrices * has a lot of gotchas. */ From 5d8c384e42396d3ef0bc34a06014ef50bfaa4c40 Mon Sep 17 00:00:00 2001 From: Steve Bronder Date: Mon, 29 Jun 2020 17:16:25 -0400 Subject: [PATCH 126/355] use chainable_alloc for sparse matrix vari_value --- stan/math/rev/core/vari.hpp | 107 +++------------------------ test/unit/math/rev/core/var_test.cpp | 54 ++++++++++---- 2 files changed, 51 insertions(+), 110 deletions(-) diff --git a/stan/math/rev/core/vari.hpp b/stan/math/rev/core/vari.hpp index 282e33e3144..9aa1abea444 100644 --- a/stan/math/rev/core/vari.hpp +++ b/stan/math/rev/core/vari.hpp @@ -406,7 +406,7 @@ class vari_value::value>> */ template class vari_value::value>> - : public vari_base { + : public vari_base, chainable_alloc { public: using PlainObject = std::decay_t>; // Base type of Eigen class @@ -414,13 +414,6 @@ class vari_value::value>> using eigen_index = typename PlainObject::StorageIndex; // Index type using Scalar = PlainObject; // vari's adj_ and val_ member type using value_type = Scalar; // vari's adj_ and val_ member type - using eigen_map = Eigen::Map; // Map of stack alloc'd mem - eigen_scalar* val_mem_; // The value's nonzero values - eigen_index* val_outer_index_; // Value's Outer index of nonzero members - eigen_index* val_inner_index_; // Value's Inner index of nonzero members - eigen_scalar* adj_mem_; // Adjoint's nonzero values - eigen_index* adj_outer_index_; // Adjoint's outer index of nonzero members - eigen_index* adj_inner_index_; // Adjont's inner index of nonzero members const Eigen::Index rows_; // Number of rows in val_ const Eigen::Index cols_; // Number of cols in val_ const Eigen::Index size_; // Size of val_ @@ -435,13 +428,13 @@ class vari_value::value>> /** * The value of this variable. */ - const eigen_map val_; + const PlainObject val_; /** * The adjoint of this variable, which is the partial derivative * of this variable with respect to the root variable. */ - eigen_map adj_; + PlainObject adj_; /** * Construct a variable implementation from a value. The @@ -458,28 +451,13 @@ class vari_value::value>> * @param x Value of the constructed variable. */ template * = nullptr> - explicit vari_value(S&& x) - : val_mem_(ChainableStack::instance_->memalloc_.alloc_array( - x.nonZeros())), - val_outer_index_( - ChainableStack::instance_->memalloc_.alloc_array( - x.innerSize())), - val_inner_index_( - ChainableStack::instance_->memalloc_.alloc_array( - x.innerSize())), - adj_mem_(ChainableStack::instance_->memalloc_.alloc_array( - x.innerSize())), - adj_outer_index_( - ChainableStack::instance_->memalloc_.alloc_array( - x.outerSize())), - adj_inner_index_( - ChainableStack::instance_->memalloc_.alloc_array( - x.innerSize())), + explicit vari_value(S&& x) : rows_(x.rows()), cols_(x.cols()), size_(x.size()), - val_(make_val(val_outer_index_, val_inner_index_, val_mem_, x)), - adj_(make_adj(adj_outer_index_, adj_inner_index_, adj_mem_, x)) { + val_(x), + adj_(x) { + this->set_zero_adjoint(); ChainableStack::instance_->var_stack_.push_back(this); } /** @@ -500,28 +478,13 @@ class vari_value::value>> * that its `chain()` method is not called. */ template * = nullptr> - vari_value(S&& x, bool stacked) - : val_mem_(ChainableStack::instance_->memalloc_.alloc_array( - x.innerSize())), - val_outer_index_( - ChainableStack::instance_->memalloc_.alloc_array( - x.outerSize())), - val_inner_index_( - ChainableStack::instance_->memalloc_.alloc_array( - x.innerSize())), - adj_mem_(ChainableStack::instance_->memalloc_.alloc_array( - x.innerSize())), - adj_outer_index_( - ChainableStack::instance_->memalloc_.alloc_array( - x.outerSize())), - adj_inner_index_( - ChainableStack::instance_->memalloc_.alloc_array( - x.innerSize())), + vari_value(S&& x, bool stacked) : rows_(x.rows()), cols_(x.cols()), size_(x.size()), - val_(make_val(val_outer_index_, val_inner_index_, val_mem_, x)), - adj_(make_adj(adj_outer_index_, adj_inner_index_, adj_mem_, x)) { + val_(x), + adj_(x) { + this->set_zero_adjoint(); if (stacked) { ChainableStack::instance_->var_stack_.push_back(this); } else { @@ -557,7 +520,7 @@ class vari_value::value>> */ inline void set_zero_adjoint() noexcept final { for (int k = 0; k < adj_.outerSize(); ++k) { - for (typename eigen_map::InnerIterator it(adj_, k); it; ++it) { + for (typename PlainObject::InnerIterator it(adj_, k); it; ++it) { it.valueRef() = 0.0; } } @@ -607,52 +570,6 @@ class vari_value::value>> private: template friend class var_value; - /** - * Fill the val_ map and it's pointers. - * @tparam S An Eigen sparse matrix type. - * @param outer_mem Stack allocated memory for the outer index. - * @param inner_mem Stack allocated memory for the inner index. - * @param val_mem Stack allocated memory for the matrix values. - * @param x The Eigen sparse type to fill in the stack memory. - * @note This function exists because Eigen's `Map` class for sparse matrices - * has a lot of gotchas. - */ - template - inline eigen_map make_val(eigen_index*& outer_mem, eigen_index*& inner_mem, - eigen_scalar*& val_mem, S&& x) { - for (int k = 0; k < x.innerSize(); ++k) { - val_mem[k] = x.valuePtr()[k]; - inner_mem[k] = x.innerIndexPtr()[k]; - } - for (int k = 0; k < x.outerSize(); ++k) { - outer_mem[k] = x.outerIndexPtr()[k]; - } - return eigen_map(x.rows(), x.cols(), x.nonZeros(), outer_mem, inner_mem, - val_mem); - } - /** - * Fill the val_ map and it's pointers. - * @tparam S An Eigen sparse matrix type. - * @param outer_mem Stack allocated memory for the outer index. - * @param inner_mem Stack allocated memory for the inner index. - * @param val_mem Stack allocated memory for the matrix values. - * @param x The Eigen sparse type to fill in the stack memory. - * @note This function exists because Eigen's `Map` class for sparse matrices - * has a lot of gotchas. - */ - template - inline eigen_map make_adj(eigen_index*& outer_mem, eigen_index*& inner_mem, - eigen_scalar*& val_mem, S&& x) { - for (int k = 0; k < x.innerSize(); ++k) { - val_mem[k] = 0.0; - inner_mem[k] = x.innerIndexPtr()[k]; - } - for (int k = 0; k < x.outerSize(); ++k) { - outer_mem[k] = x.outerIndexPtr()[k]; - } - return eigen_map(x.rows(), x.cols(), x.nonZeros(), outer_mem, inner_mem, - val_mem); - } }; } // namespace math diff --git a/test/unit/math/rev/core/var_test.cpp b/test/unit/math/rev/core/var_test.cpp index ee9064fea4a..05e7802feb0 100644 --- a/test/unit/math/rev/core/var_test.cpp +++ b/test/unit/math/rev/core/var_test.cpp @@ -79,6 +79,24 @@ void ctor_overloads_matrix(EigenMat&& xx) { x, var_value(var_value(x)).val()); } +auto make_sparse_matrix_random(int rows, int cols) { + using eigen_triplet = Eigen::Triplet; + boost::mt19937 gen; + boost::random::uniform_real_distribution dist(0.0, 1.0); + std::vector tripletList; + for (int i = 0; i < rows; ++i) { + for (int j = 0; j < cols; ++j) { + auto v_ij = dist(gen); + if (v_ij < 0.1) { + tripletList.push_back(eigen_triplet(i, j, v_ij)); + } + } + } + Eigen::SparseMatrix mat(rows, cols); + mat.setFromTriplets(tripletList.begin(), tripletList.end()); + return mat; +} + template void ctor_overloads_sparse_matrix(EigenMat&& x) { using stan::math::var_value; @@ -94,6 +112,14 @@ void ctor_overloads_sparse_matrix(EigenMat&& x) { EXPECT_FLOAT_EQ(iz.value(), it.value()); } } + const eigen_plain const_matmul_x = x * x; + eigen_plain const_matmul_xx = var_value(const_matmul_x).val(); + for (int k = 0; k < matmul_x.outerSize(); ++k) { + for (inner_iterator it(const_matmul_x, k), iz(const_matmul_xx, k); it; ++it, ++iz) { + EXPECT_FLOAT_EQ(iz.value(), it.value()); + } + } + // make sure rvalue var_value can be accepted eigen_plain x_rv = var_value(var_value(x)).val(); for (int k = 0; k < x.outerSize(); ++k) { @@ -114,24 +140,22 @@ void ctor_overloads_sparse_matrix(EigenMat&& x) { EXPECT_FLOAT_EQ(iz.value(), it.value()); } } -} - -auto make_sparse_matrix_random(int rows, int cols) { - using eigen_triplet = Eigen::Triplet; - boost::mt19937 gen; - boost::random::uniform_real_distribution dist(0.0, 1.0); - std::vector tripletList; - for (int i = 0; i < rows; ++i) { - for (int j = 0; j < cols; ++j) { - auto v_ij = dist(gen); - if (v_ij < 0.1) { - tripletList.push_back(eigen_triplet(i, j, v_ij)); + // test inplace addition works + auto inplace_add_var = var_value(new vari_value(x)); + eigen_plain test_y = make_sparse_matrix_random(10, 10); + inplace_add_var.adj() += test_y; + // adjoints sparsity pattern will be pattern of x and test_y for addition + for (int k = 0; k < x.outerSize(); ++k) { + for (inner_iterator it(test_y, k), iz(inplace_add_var.adj(), k); iz; ++iz) { + if (iz.row() == it.row() && iz.col() == it.col()) { + EXPECT_FLOAT_EQ(iz.value(), it.value()); + ++it; + } else { + EXPECT_FLOAT_EQ(iz.value(), 0.0); } } } - Eigen::SparseMatrix mat(rows, cols); - mat.setFromTriplets(tripletList.begin(), tripletList.end()); - return mat; + } TEST_F(AgradRev, ctormatrixOverloads) { From 1cbd95bd54ce5f8cde52f389b4eb71d3eb991aee Mon Sep 17 00:00:00 2001 From: Stan Jenkins Date: Mon, 29 Jun 2020 17:17:14 -0400 Subject: [PATCH 127/355] [Jenkins] auto-formatting by clang-format version 6.0.0-1ubuntu2 (tags/RELEASE_600/final) --- stan/math/rev/core/vari.hpp | 22 +++++++--------------- test/unit/math/rev/core/var_test.cpp | 4 ++-- 2 files changed, 9 insertions(+), 17 deletions(-) diff --git a/stan/math/rev/core/vari.hpp b/stan/math/rev/core/vari.hpp index 9aa1abea444..a5a3954a7c7 100644 --- a/stan/math/rev/core/vari.hpp +++ b/stan/math/rev/core/vari.hpp @@ -414,9 +414,9 @@ class vari_value::value>> using eigen_index = typename PlainObject::StorageIndex; // Index type using Scalar = PlainObject; // vari's adj_ and val_ member type using value_type = Scalar; // vari's adj_ and val_ member type - const Eigen::Index rows_; // Number of rows in val_ - const Eigen::Index cols_; // Number of cols in val_ - const Eigen::Index size_; // Size of val_ + const Eigen::Index rows_; // Number of rows in val_ + const Eigen::Index cols_; // Number of cols in val_ + const Eigen::Index size_; // Size of val_ /** * Rows at compile time */ @@ -451,12 +451,8 @@ class vari_value::value>> * @param x Value of the constructed variable. */ template * = nullptr> - explicit vari_value(S&& x) : - rows_(x.rows()), - cols_(x.cols()), - size_(x.size()), - val_(x), - adj_(x) { + explicit vari_value(S&& x) + : rows_(x.rows()), cols_(x.cols()), size_(x.size()), val_(x), adj_(x) { this->set_zero_adjoint(); ChainableStack::instance_->var_stack_.push_back(this); } @@ -478,12 +474,8 @@ class vari_value::value>> * that its `chain()` method is not called. */ template * = nullptr> - vari_value(S&& x, bool stacked) : - rows_(x.rows()), - cols_(x.cols()), - size_(x.size()), - val_(x), - adj_(x) { + vari_value(S&& x, bool stacked) + : rows_(x.rows()), cols_(x.cols()), size_(x.size()), val_(x), adj_(x) { this->set_zero_adjoint(); if (stacked) { ChainableStack::instance_->var_stack_.push_back(this); diff --git a/test/unit/math/rev/core/var_test.cpp b/test/unit/math/rev/core/var_test.cpp index 05e7802feb0..4563b58ed2f 100644 --- a/test/unit/math/rev/core/var_test.cpp +++ b/test/unit/math/rev/core/var_test.cpp @@ -115,7 +115,8 @@ void ctor_overloads_sparse_matrix(EigenMat&& x) { const eigen_plain const_matmul_x = x * x; eigen_plain const_matmul_xx = var_value(const_matmul_x).val(); for (int k = 0; k < matmul_x.outerSize(); ++k) { - for (inner_iterator it(const_matmul_x, k), iz(const_matmul_xx, k); it; ++it, ++iz) { + for (inner_iterator it(const_matmul_x, k), iz(const_matmul_xx, k); it; + ++it, ++iz) { EXPECT_FLOAT_EQ(iz.value(), it.value()); } } @@ -155,7 +156,6 @@ void ctor_overloads_sparse_matrix(EigenMat&& x) { } } } - } TEST_F(AgradRev, ctormatrixOverloads) { From cea502a08cb9dc674b1b50cc647f552055ca6130 Mon Sep 17 00:00:00 2001 From: Steve Bronder Date: Mon, 29 Jun 2020 17:36:03 -0400 Subject: [PATCH 128/355] add chainable_alloc() constructor to sparse vari constructor --- stan/math/rev/core/vari.hpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/stan/math/rev/core/vari.hpp b/stan/math/rev/core/vari.hpp index 9aa1abea444..aade0dc72f5 100644 --- a/stan/math/rev/core/vari.hpp +++ b/stan/math/rev/core/vari.hpp @@ -456,7 +456,8 @@ class vari_value::value>> cols_(x.cols()), size_(x.size()), val_(x), - adj_(x) { + adj_(x), + chainable_alloc() { this->set_zero_adjoint(); ChainableStack::instance_->var_stack_.push_back(this); } @@ -483,7 +484,8 @@ class vari_value::value>> cols_(x.cols()), size_(x.size()), val_(x), - adj_(x) { + adj_(x), + chainable_alloc() { this->set_zero_adjoint(); if (stacked) { ChainableStack::instance_->var_stack_.push_back(this); From cc2a49d37a30533c59b0fda0e191546ec557b0e4 Mon Sep 17 00:00:00 2001 From: Stan Jenkins Date: Mon, 29 Jun 2020 17:37:25 -0400 Subject: [PATCH 129/355] [Jenkins] auto-formatting by clang-format version 6.0.0-1ubuntu2 (tags/RELEASE_600/final) --- stan/math/rev/core/vari.hpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/stan/math/rev/core/vari.hpp b/stan/math/rev/core/vari.hpp index 9df5e5fe74d..e52e8099910 100644 --- a/stan/math/rev/core/vari.hpp +++ b/stan/math/rev/core/vari.hpp @@ -451,8 +451,8 @@ class vari_value::value>> * @param x Value of the constructed variable. */ template * = nullptr> - explicit vari_value(S&& x) : - rows_(x.rows()), + explicit vari_value(S&& x) + : rows_(x.rows()), cols_(x.cols()), size_(x.size()), val_(x), @@ -479,8 +479,8 @@ class vari_value::value>> * that its `chain()` method is not called. */ template * = nullptr> - vari_value(S&& x, bool stacked) : - rows_(x.rows()), + vari_value(S&& x, bool stacked) + : rows_(x.rows()), cols_(x.cols()), size_(x.size()), val_(x), From 41d0e7474ddaef7745675733bceb3b8983d41b12 Mon Sep 17 00:00:00 2001 From: Steve Bronder Date: Tue, 30 Jun 2020 14:18:48 -0400 Subject: [PATCH 130/355] using chainable_alloc allows the sparse vari to accept eigen expressions --- stan/math/rev/core/vari.hpp | 8 +++++++- test/unit/math/rev/core/var_test.cpp | 17 +++++++---------- 2 files changed, 14 insertions(+), 11 deletions(-) diff --git a/stan/math/rev/core/vari.hpp b/stan/math/rev/core/vari.hpp index 9df5e5fe74d..fa34a32c197 100644 --- a/stan/math/rev/core/vari.hpp +++ b/stan/math/rev/core/vari.hpp @@ -513,7 +513,13 @@ class vari_value::value>> * propagating derivatives, setting the derivative of the * result with respect to itself to be 1. */ - inline void init_dependent() { adj_.setOnes(); } + inline void init_dependent() { + for (int k = 0; k < adj_.outerSize(); ++k) { + for (typename PlainObject::InnerIterator it(adj_, k); it; ++it) { + it.valueRef() = 1.0; + } + } + } /** * Set the adjoint value of this variable to 0. This is used to diff --git a/test/unit/math/rev/core/var_test.cpp b/test/unit/math/rev/core/var_test.cpp index 4563b58ed2f..b2e74001a5e 100644 --- a/test/unit/math/rev/core/var_test.cpp +++ b/test/unit/math/rev/core/var_test.cpp @@ -129,30 +129,27 @@ void ctor_overloads_sparse_matrix(EigenMat&& x) { } } - /** from a vari_value with sparse - * NOTE: This will fail with an expression since allocating the mem - * for the vari requires knowing the sizes of the inner and outer indices - * which is not computed for expressions. - */ + // from a vari_value with sparse eigen expression eigen_plain x_from_vari - = var_value(new vari_value(x)).val(); - for (int k = 0; k < x.outerSize(); ++k) { - for (inner_iterator it(x, k), iz(x_from_vari, k); it; ++it, ++iz) { + = var_value(new vari_value(x * x)).val(); + for (int k = 0; k < matmul_x.outerSize(); ++k) { + for (inner_iterator it(matmul_x, k), iz(x_from_vari, k); it; ++it, ++iz) { EXPECT_FLOAT_EQ(iz.value(), it.value()); } } // test inplace addition works auto inplace_add_var = var_value(new vari_value(x)); eigen_plain test_y = make_sparse_matrix_random(10, 10); + inplace_add_var.vi_->init_dependent(); inplace_add_var.adj() += test_y; // adjoints sparsity pattern will be pattern of x and test_y for addition for (int k = 0; k < x.outerSize(); ++k) { for (inner_iterator it(test_y, k), iz(inplace_add_var.adj(), k); iz; ++iz) { if (iz.row() == it.row() && iz.col() == it.col()) { - EXPECT_FLOAT_EQ(iz.value(), it.value()); + EXPECT_FLOAT_EQ(iz.value() - 1, it.value()); ++it; } else { - EXPECT_FLOAT_EQ(iz.value(), 0.0); + EXPECT_FLOAT_EQ(iz.value(), 1.0); } } } From cdaa2e61f93da11e95aa73ae820187e1da6238ea Mon Sep 17 00:00:00 2001 From: Stan Jenkins Date: Tue, 30 Jun 2020 14:19:43 -0400 Subject: [PATCH 131/355] [Jenkins] auto-formatting by clang-format version 6.0.0-1ubuntu2 (tags/RELEASE_600/final) --- stan/math/rev/core/vari.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stan/math/rev/core/vari.hpp b/stan/math/rev/core/vari.hpp index 1c5ae9a820d..60523e34c48 100644 --- a/stan/math/rev/core/vari.hpp +++ b/stan/math/rev/core/vari.hpp @@ -519,7 +519,7 @@ class vari_value::value>> it.valueRef() = 1.0; } } - } + } /** * Set the adjoint value of this variable to 0. This is used to From dc44dcc9200e914db1ee666c2e68a1ef65f53b04 Mon Sep 17 00:00:00 2001 From: Steve Bronder Date: Tue, 30 Jun 2020 16:49:50 -0400 Subject: [PATCH 132/355] add static_assert to make sure var inner type is assignable. Add tests for init_dependent --- stan/math/rev/core/var.hpp | 33 ++++++++++------------------ test/unit/math/rev/core/var_test.cpp | 4 ++++ 2 files changed, 15 insertions(+), 22 deletions(-) diff --git a/stan/math/rev/core/var.hpp b/stan/math/rev/core/var.hpp index 32d772293dc..2c6a682c831 100644 --- a/stan/math/rev/core/var.hpp +++ b/stan/math/rev/core/var.hpp @@ -35,10 +35,18 @@ class var_value {}; template class var_value> { + /** + * Checks whether the template type `T` is an assignable type. + */ + template + using check_plain_type = std::is_same, + std::decay_t>>; + static_assert(check_plain_type::value, "The template for this var is an" + " expression but a var_value's inner type must be assignable such as" + " a double, Eigen::Matrix, or Eigen::Array"); public: using value_type = std::decay_t>; // type in vari_value. using vari_type = vari_value; // Type of underlying vari impl. - using vari_pointer = vari_type*; // pointer type for underlying vari. /** * Pointer to the implementation of this variable. @@ -76,33 +84,14 @@ class var_value> { * @tparam S A type that is convertible to `value_type`. * @param x Value of the variable. */ - template * = nullptr, - require_not_eigen_sparse_base_t* = nullptr> + template * = nullptr> var_value(S&& x) : vi_(new vari_type(std::forward(x), false)) {} // NOLINT - /** - * Construct a variable from the specified floating point argument - * by constructing a new `vari_value`. This constructor is only - * valid when `S` is convertible to this `vari_value`'s `value_type` and is - * derived from Eigen's sparse matrix base class. This specialization exists - * because Eigen sparse matrix expressions do not have `innerSize()` and - * `outerSize()` members. While dense matrix expressions can be passed along - * to the constructor for `vari_value`, sparse matrix expressions need to - * be evaluated before they are passed to the `vari_value` constructor. - * @tparam S A type that is convertible to `value_type`. - * @param x Value of the variable. - */ - template * = nullptr, - require_eigen_sparse_base_t* = nullptr> - var_value(S&& x) : vi_(new vari_type(ref_type_t(x), false)) {} // NOLINT - /** * Construct a variable from a pointer to a variable implementation. * @param vi A vari_value pointer. */ - template * = nullptr> - var_value(vari_value* vi) // NOLINT - : vi_(vi) {} + var_value(vari_type* vi) : vi_(vi) {} // NOLINT /** * Return a constant reference to the value of this variable. diff --git a/test/unit/math/rev/core/var_test.cpp b/test/unit/math/rev/core/var_test.cpp index b2e74001a5e..9b2dfcde152 100644 --- a/test/unit/math/rev/core/var_test.cpp +++ b/test/unit/math/rev/core/var_test.cpp @@ -77,6 +77,10 @@ void ctor_overloads_matrix(EigenMat&& xx) { // make sure rvalue var_value can be accepted EXPECT_MATRIX_FLOAT_EQ( x, var_value(var_value(x)).val()); + // test init_dependent for adj + auto test_var_x = var_value(var_value(x)); + test_var_x.vi_->init_dependent(); + EXPECT_MATRIX_FLOAT_EQ(eigen_plain::Ones(x.rows(), x.cols()) , test_var_x.adj()); } auto make_sparse_matrix_random(int rows, int cols) { From fa3a6fc24a03ad2457a73372e633919f4b6d1b27 Mon Sep 17 00:00:00 2001 From: Stan Jenkins Date: Tue, 30 Jun 2020 20:50:50 +0000 Subject: [PATCH 133/355] [Jenkins] auto-formatting by clang-format version 6.0.0-1ubuntu2~16.04.1 (tags/RELEASE_600/final) --- stan/math/rev/core/var.hpp | 15 +++++++++------ test/unit/math/rev/core/var_test.cpp | 3 ++- 2 files changed, 11 insertions(+), 7 deletions(-) diff --git a/stan/math/rev/core/var.hpp b/stan/math/rev/core/var.hpp index 2c6a682c831..4c63d29e28d 100644 --- a/stan/math/rev/core/var.hpp +++ b/stan/math/rev/core/var.hpp @@ -39,11 +39,14 @@ class var_value> { * Checks whether the template type `T` is an assignable type. */ template - using check_plain_type = std::is_same, - std::decay_t>>; - static_assert(check_plain_type::value, "The template for this var is an" - " expression but a var_value's inner type must be assignable such as" - " a double, Eigen::Matrix, or Eigen::Array"); + using check_plain_type + = std::is_same, std::decay_t>>; + static_assert( + check_plain_type::value, + "The template for this var is an" + " expression but a var_value's inner type must be assignable such as" + " a double, Eigen::Matrix, or Eigen::Array"); + public: using value_type = std::decay_t>; // type in vari_value. using vari_type = vari_value; // Type of underlying vari impl. @@ -91,7 +94,7 @@ class var_value> { * Construct a variable from a pointer to a variable implementation. * @param vi A vari_value pointer. */ - var_value(vari_type* vi) : vi_(vi) {} // NOLINT + var_value(vari_type* vi) : vi_(vi) {} // NOLINT /** * Return a constant reference to the value of this variable. diff --git a/test/unit/math/rev/core/var_test.cpp b/test/unit/math/rev/core/var_test.cpp index 9b2dfcde152..35914078705 100644 --- a/test/unit/math/rev/core/var_test.cpp +++ b/test/unit/math/rev/core/var_test.cpp @@ -80,7 +80,8 @@ void ctor_overloads_matrix(EigenMat&& xx) { // test init_dependent for adj auto test_var_x = var_value(var_value(x)); test_var_x.vi_->init_dependent(); - EXPECT_MATRIX_FLOAT_EQ(eigen_plain::Ones(x.rows(), x.cols()) , test_var_x.adj()); + EXPECT_MATRIX_FLOAT_EQ(eigen_plain::Ones(x.rows(), x.cols()), + test_var_x.adj()); } auto make_sparse_matrix_random(int rows, int cols) { From 8d20a6727542b5c98b7a228af1ef9f88c567b996 Mon Sep 17 00:00:00 2001 From: Steve Bronder Date: Wed, 1 Jul 2020 17:34:34 -0400 Subject: [PATCH 134/355] Add tests for new meta functions, remove forwarding from vari --- stan/math/prim/meta.hpp | 1 + stan/math/prim/meta/is_eigen_dense_base.hpp | 4 +- stan/math/prim/meta/is_eigen_matrix_base.hpp | 2 +- stan/math/prim/meta/is_eigen_sparse_base.hpp | 4 +- stan/math/prim/meta/is_plain_type.hpp | 21 +++++ stan/math/rev/core/var.hpp | 12 +-- stan/math/rev/core/vari.hpp | 86 +++++++++---------- .../mix/meta/is_eigen_sparse_base_test.cpp | 58 +++++++++++++ .../math/prim/meta/is_plain_type_test.cpp | 28 ++++++ test/unit/math/rev/core/vari_test.cpp | 5 ++ 10 files changed, 160 insertions(+), 61 deletions(-) create mode 100644 stan/math/prim/meta/is_plain_type.hpp create mode 100644 test/unit/math/mix/meta/is_eigen_sparse_base_test.cpp create mode 100644 test/unit/math/prim/meta/is_plain_type_test.cpp diff --git a/stan/math/prim/meta.hpp b/stan/math/prim/meta.hpp index 94955d73d99..35945171495 100644 --- a/stan/math/prim/meta.hpp +++ b/stan/math/prim/meta.hpp @@ -192,6 +192,7 @@ #include #include #include +#include #include #include #include diff --git a/stan/math/prim/meta/is_eigen_dense_base.hpp b/stan/math/prim/meta/is_eigen_dense_base.hpp index 225f833b45c..3ce1dbe8ebc 100644 --- a/stan/math/prim/meta/is_eigen_dense_base.hpp +++ b/stan/math/prim/meta/is_eigen_dense_base.hpp @@ -10,10 +10,10 @@ namespace stan { /** - * Checks whether type T is derived from Eigen::MatrixBase. + * Checks whether type T is derived from Eigen::DenseBase. * If true this will have a static member function named value with a type * of true, else value is false. - * @tparam T Type to check if it is derived from `EigenBase` + * @tparam T Type to check if it is derived from `DenseBase` * @tparam Enable used for SFINAE deduction. * @ingroup type_trait */ diff --git a/stan/math/prim/meta/is_eigen_matrix_base.hpp b/stan/math/prim/meta/is_eigen_matrix_base.hpp index f6d47c0b2e1..9e4e6e9465e 100644 --- a/stan/math/prim/meta/is_eigen_matrix_base.hpp +++ b/stan/math/prim/meta/is_eigen_matrix_base.hpp @@ -13,7 +13,7 @@ namespace stan { * Checks whether type T is derived from Eigen::MatrixBase. * If true this will have a static member function named value with a type * of true, else value is false. - * @tparam T Type to check if it is derived from `EigenBase` + * @tparam T Type to check if it is derived from `MatrixBase` * @tparam Enable used for SFINAE deduction. * @ingroup type_trait */ diff --git a/stan/math/prim/meta/is_eigen_sparse_base.hpp b/stan/math/prim/meta/is_eigen_sparse_base.hpp index b6eee02a4a7..2c1028730bf 100644 --- a/stan/math/prim/meta/is_eigen_sparse_base.hpp +++ b/stan/math/prim/meta/is_eigen_sparse_base.hpp @@ -10,10 +10,10 @@ namespace stan { /** - * Checks whether type T is derived from Eigen::MatrixBase. + * Checks whether type T is derived from Eigen::SparseMatrixBase. * If true this will have a static member function named value with a type * of true, else value is false. - * @tparam T Type to check if it is derived from `EigenBase` + * @tparam T Type to check if it is derived from `SparseMatrixBase` * @tparam Enable used for SFINAE deduction. * @ingroup type_trait */ diff --git a/stan/math/prim/meta/is_plain_type.hpp b/stan/math/prim/meta/is_plain_type.hpp new file mode 100644 index 00000000000..bec202aef5f --- /dev/null +++ b/stan/math/prim/meta/is_plain_type.hpp @@ -0,0 +1,21 @@ +#ifndef STAN_MATH_PRIM_META_IS_PLAIN_TYPE_HPP +#define STAN_MATH_PRIM_META_IS_PLAIN_TYPE_HPP + +#include +#include +#include + +namespace stan { +/** \ingroup type_trait + * Checks whether the template type `T` is an assignable type. This is used + * to detect whether a type is an Eigen matrix expression. + */ + template + using is_plain_type + = std::is_same, std::decay_t>>; + +STAN_ADD_REQUIRE_UNARY(plain_type, is_plain_type, require_eigens_types); +STAN_ADD_REQUIRE_UNARY_INNER(plain_type, is_plain_type, require_eigens_types); + +} // namespace stan +#endif diff --git a/stan/math/rev/core/var.hpp b/stan/math/rev/core/var.hpp index 4c63d29e28d..af697d60a0e 100644 --- a/stan/math/rev/core/var.hpp +++ b/stan/math/rev/core/var.hpp @@ -35,20 +35,14 @@ class var_value {}; template class var_value> { - /** - * Checks whether the template type `T` is an assignable type. - */ - template - using check_plain_type - = std::is_same, std::decay_t>>; static_assert( - check_plain_type::value, + is_plain_type::value, "The template for this var is an" " expression but a var_value's inner type must be assignable such as" " a double, Eigen::Matrix, or Eigen::Array"); public: - using value_type = std::decay_t>; // type in vari_value. + using value_type = std::decay_t; // type in vari_value. using vari_type = vari_value; // Type of underlying vari impl. /** @@ -88,7 +82,7 @@ class var_value> { * @param x Value of the variable. */ template * = nullptr> - var_value(S&& x) : vi_(new vari_type(std::forward(x), false)) {} // NOLINT + var_value(S&& x) : vi_(new vari_type(x, false)) {} // NOLINT /** * Construct a variable from a pointer to a variable implementation. diff --git a/stan/math/rev/core/vari.hpp b/stan/math/rev/core/vari.hpp index 60523e34c48..5300bb8975e 100644 --- a/stan/math/rev/core/vari.hpp +++ b/stan/math/rev/core/vari.hpp @@ -49,10 +49,6 @@ class vari_value; template class vari_value::value>> : public vari_base { - private: - template - friend class var_value; - public: using Scalar = T; using value_type = Scalar; @@ -181,6 +177,11 @@ class vari_value::value>> static inline void operator delete( void* /* ignore arg */) noexcept { /* no op */ } + private: + template + friend class var_value; + template * = nullptr> + explicit vari_value(T1&& A, T2&& B) : val_(A), adj_(B) {} }; // For backwards compatability the default is double @@ -201,19 +202,23 @@ template class vari_value::value>> : public vari_base { public: + static_assert( + is_plain_type::value, + "The template for this var is an" + " expression but a var_value's inner type must be assignable such as" + " a double, Eigen::Matrix, or Eigen::Array"); + /** * `PlainObject` represents a user constructible type such as Matrix or Array */ using PlainObject = std::decay_t>; - using eigen_scalar = value_type_t; // A floating point type - eigen_scalar* val_mem_; // Pointer to memory allocated on the stack for val_ - eigen_scalar* adj_mem_; // Pointer to memory allocated on the stack for adj_ using Scalar = PlainObject; // The underlying type for this class using value_type = Scalar; // The underlying type for this class + using eigen_scalar = value_type_t; // A floating point type using eigen_map = Eigen::Map; // Maps for adj_ and val_ - const Eigen::Index rows_; // Number of rows - const Eigen::Index cols_; // Number of cols - const Eigen::Index size_; // Size of rows * cols + using vari_type = vari_value::value>>; + eigen_scalar* val_mem_; // Pointer to memory allocated on the stack for val_ + eigen_scalar* adj_mem_; // Pointer to memory allocated on the stack for adj_ /** * Number of rows known at compile time */ @@ -253,11 +258,8 @@ class vari_value::value>> x.size())), adj_mem_(ChainableStack::instance_->memalloc_.alloc_array( x.size())), - rows_(x.rows()), - cols_(x.cols()), - size_(x.size()), - adj_(make_adj(adj_mem_, x)), - val_(make_val(val_mem_, std::forward(x))) { + adj_(make_adj(x)), + val_(make_val(x)) { ChainableStack::instance_->var_stack_.push_back(this); } @@ -284,11 +286,8 @@ class vari_value::value>> x.size())), adj_mem_(ChainableStack::instance_->memalloc_.alloc_array( x.size())), - rows_(x.rows()), - cols_(x.cols()), - size_(x.size()), - adj_(make_adj(adj_mem_, x)), - val_(make_val(val_mem_, x)) { + adj_(make_adj(x)), + val_(make_val(x)) { if (stacked) { ChainableStack::instance_->var_stack_.push_back(this); } else { @@ -299,15 +298,15 @@ class vari_value::value>> /** * Return the number of rows for this class's `val_` member */ - const Eigen::Index rows() const { return rows_; } + const Eigen::Index rows() const { return val_.rows(); } /** * Return the number of columns for this class's `val_` member */ - const Eigen::Index cols() const { return cols_; } + const Eigen::Index cols() const { return val_.rows(); } /** * Return the size of this class's `val_` member */ - const Eigen::Index size() const { return size_; } + const Eigen::Index size() const { return val_.size(); } virtual void chain() {} /** @@ -334,9 +333,9 @@ class vari_value::value>> * * @return The modified ostream. */ - friend std::ostream& operator<<(std::ostream& os, const vari_value* v) { - return os << v->val_ << ":" << v->adj_; - } + friend std::ostream& operator<<(std::ostream& os, const vari_value* v) { + return os << "val: \n" << v->val_ << " \nadj: \n" << v->adj_; + } /** * Allocate memory from the underlying memory pool. This memory is @@ -369,6 +368,8 @@ class vari_value::value>> private: template friend class var_value; + template + friend class vari_value; /** * Create the map to the val_ stack allocated memory for an Eigen input. * @tparam S an Eigen type. @@ -376,9 +377,9 @@ class vari_value::value>> * @param x The Eigen type whose values will be assigned to `val_` */ template - inline eigen_map make_val(eigen_scalar*& mem, S&& x) { - eigen_map(mem, x.rows(), x.cols()) = std::forward(x); - return eigen_map(mem, x.rows(), x.cols()); + inline eigen_map make_val(S&& x) { + eigen_map(val_mem_, x.rows(), x.cols()) = x; + return eigen_map(val_mem_, x.rows(), x.cols()); } /** * Create the map to the adj_ stack allocated memory for an Eigen input. @@ -387,9 +388,9 @@ class vari_value::value>> * @param x The Eigen type whose dimensions are set the `adj_`s dimensions. */ template - inline eigen_map make_adj(eigen_scalar*& mem, S&& x) { - eigen_map(mem, x.rows(), x.cols()).setZero(); - return eigen_map(mem, x.rows(), x.cols()); + inline eigen_map make_adj(S&& x) { + eigen_map(adj_mem_, x.rows(), x.cols()).setZero(); + return eigen_map(adj_mem_, x.rows(), x.cols()); } }; @@ -414,9 +415,6 @@ class vari_value::value>> using eigen_index = typename PlainObject::StorageIndex; // Index type using Scalar = PlainObject; // vari's adj_ and val_ member type using value_type = Scalar; // vari's adj_ and val_ member type - const Eigen::Index rows_; // Number of rows in val_ - const Eigen::Index cols_; // Number of cols in val_ - const Eigen::Index size_; // Size of val_ /** * Rows at compile time */ @@ -452,10 +450,7 @@ class vari_value::value>> */ template * = nullptr> explicit vari_value(S&& x) - : rows_(x.rows()), - cols_(x.cols()), - size_(x.size()), - val_(x), + : val_(x), adj_(x), chainable_alloc() { this->set_zero_adjoint(); @@ -480,10 +475,7 @@ class vari_value::value>> */ template * = nullptr> vari_value(S&& x, bool stacked) - : rows_(x.rows()), - cols_(x.cols()), - size_(x.size()), - val_(x), + : val_(x), adj_(x), chainable_alloc() { this->set_zero_adjoint(); @@ -497,15 +489,15 @@ class vari_value::value>> /** * Return the number of rows for this class's `val_` member */ - const Eigen::Index rows() const { return rows_; } + const Eigen::Index rows() const { return val_.rows(); } /** * Return the number of columns for this class's `val_` member */ - const Eigen::Index cols() const { return cols_; } + const Eigen::Index cols() const { return val_.cols(); } /** * Return the size of this class's `val_` member */ - const Eigen::Index size() const { return size_; } + const Eigen::Index size() const { return val_.size(); } void chain() {} /** * Initialize the adjoint for this (dependent) variable to 1. @@ -544,7 +536,7 @@ class vari_value::value>> * @return The modified ostream. */ friend std::ostream& operator<<(std::ostream& os, const vari_value* v) { - return os << v->val_ << ":" << v->adj_; + return os << "val: \n" << v->val_ << " \nadj: \n" << v->adj_; } /** diff --git a/test/unit/math/mix/meta/is_eigen_sparse_base_test.cpp b/test/unit/math/mix/meta/is_eigen_sparse_base_test.cpp new file mode 100644 index 00000000000..c55adfc4364 --- /dev/null +++ b/test/unit/math/mix/meta/is_eigen_sparse_base_test.cpp @@ -0,0 +1,58 @@ +#include +#include +#include +#include + +TEST(MathMetaPrim, is_eigen_sparse_base_hierarchy_tests) { + using Eigen::Array; + using Eigen::Matrix; + using stan::is_eigen_sparse_base; + using stan::math::test::all_eigen_dense; + all_eigen_dense(); + all_eigen_dense(); + all_eigen_dense(); + all_eigen_dense(); + all_eigen_dense(); + all_eigen_dense(); +} + +TEST(MathMetaPrim, is_eigen_sparse_base_sparse_tests) { + using Eigen::Array; + using Eigen::Matrix; + using stan::is_eigen_sparse_base; + using stan::math::test::all_eigen_sparse; + all_eigen_sparse(); +} + +TEST(MathMetaPrim, is_eigen_sparse_base_decomp_tests) { + using Eigen::Array; + using Eigen::Matrix; + using stan::is_eigen_sparse_base; + using stan::math::test::all_eigen_dense_decomp; + all_eigen_dense_decomp(); +} + +TEST(MathMetaPrim, is_eigen_sparse_base_expr_tests) { + using Eigen::Array; + using Eigen::Matrix; + using stan::is_eigen_sparse_base; + using stan::math::test::all_eigen_dense_exprs; + all_eigen_dense_exprs(); + all_eigen_dense_exprs(); + all_eigen_dense_exprs(); + all_eigen_dense_exprs(); + all_eigen_dense_exprs(); + all_eigen_dense_exprs(); +} diff --git a/test/unit/math/prim/meta/is_plain_type_test.cpp b/test/unit/math/prim/meta/is_plain_type_test.cpp new file mode 100644 index 00000000000..a845657ede0 --- /dev/null +++ b/test/unit/math/prim/meta/is_plain_type_test.cpp @@ -0,0 +1,28 @@ +#include +#include +#include + +TEST(MathMetaPrim, is_plain_type) { + using stan::is_plain_type; + EXPECT_TRUE((is_plain_type::value)); + EXPECT_TRUE((is_plain_type::value)); + EXPECT_TRUE((is_plain_type::value)); + + EXPECT_TRUE((is_plain_type>::value)); + EXPECT_TRUE((is_plain_type>::value)); + EXPECT_TRUE((is_plain_type&>::value)); + + EXPECT_TRUE((is_plain_type>::value)); + EXPECT_TRUE((is_plain_type>::value)); + + EXPECT_TRUE((is_plain_type>::value)); + EXPECT_TRUE((is_plain_type&>::value)); + Eigen::Matrix a; + Eigen::Matrix b; + + EXPECT_FALSE((is_plain_type::value)); + EXPECT_FALSE((is_plain_type::value)); + EXPECT_FALSE((is_plain_type< + Eigen::MatrixBase>&&>::value)); + EXPECT_FALSE((is_plain_type>::value)); +} diff --git a/test/unit/math/rev/core/vari_test.cpp b/test/unit/math/rev/core/vari_test.cpp index fc5a6e34ab5..c8961eb62ae 100644 --- a/test/unit/math/rev/core/vari_test.cpp +++ b/test/unit/math/rev/core/vari_test.cpp @@ -15,3 +15,8 @@ TEST(AgradRev, long_double_test) { ss << &v; EXPECT_EQ("5:0", ss.str()); } + +TEST(AgradRev, dense_matrix_vari) { + using stan::math::vari_value; + stan::math::vari_value A(Eigen::MatrixXd::Random(3, 3)); +} From b83f5bf3234a77c360463af1a1f672f50a27d5e3 Mon Sep 17 00:00:00 2001 From: Stan Jenkins Date: Wed, 1 Jul 2020 17:45:09 -0400 Subject: [PATCH 135/355] [Jenkins] auto-formatting by clang-format version 6.0.0-1ubuntu2 (tags/RELEASE_600/final) --- stan/math/prim/meta/is_plain_type.hpp | 6 +-- stan/math/rev/core/var.hpp | 2 +- stan/math/rev/core/vari.hpp | 37 +++++++++---------- .../mix/meta/is_eigen_sparse_base_test.cpp | 36 +++++++++--------- 4 files changed, 39 insertions(+), 42 deletions(-) diff --git a/stan/math/prim/meta/is_plain_type.hpp b/stan/math/prim/meta/is_plain_type.hpp index bec202aef5f..9bb0cdc1a20 100644 --- a/stan/math/prim/meta/is_plain_type.hpp +++ b/stan/math/prim/meta/is_plain_type.hpp @@ -10,9 +10,9 @@ namespace stan { * Checks whether the template type `T` is an assignable type. This is used * to detect whether a type is an Eigen matrix expression. */ - template - using is_plain_type - = std::is_same, std::decay_t>>; +template +using is_plain_type + = std::is_same, std::decay_t>>; STAN_ADD_REQUIRE_UNARY(plain_type, is_plain_type, require_eigens_types); STAN_ADD_REQUIRE_UNARY_INNER(plain_type, is_plain_type, require_eigens_types); diff --git a/stan/math/rev/core/var.hpp b/stan/math/rev/core/var.hpp index af697d60a0e..8dbed9e7171 100644 --- a/stan/math/rev/core/var.hpp +++ b/stan/math/rev/core/var.hpp @@ -42,7 +42,7 @@ class var_value> { " a double, Eigen::Matrix, or Eigen::Array"); public: - using value_type = std::decay_t; // type in vari_value. + using value_type = std::decay_t; // type in vari_value. using vari_type = vari_value; // Type of underlying vari impl. /** diff --git a/stan/math/rev/core/vari.hpp b/stan/math/rev/core/vari.hpp index 5300bb8975e..81d2f4874d6 100644 --- a/stan/math/rev/core/vari.hpp +++ b/stan/math/rev/core/vari.hpp @@ -177,10 +177,12 @@ class vari_value::value>> static inline void operator delete( void* /* ignore arg */) noexcept { /* no op */ } - private: + + private: template friend class var_value; - template * = nullptr> + template * = nullptr> explicit vari_value(T1&& A, T2&& B) : val_(A), adj_(B) {} }; @@ -202,11 +204,11 @@ template class vari_value::value>> : public vari_base { public: - static_assert( - is_plain_type::value, - "The template for this var is an" - " expression but a var_value's inner type must be assignable such as" - " a double, Eigen::Matrix, or Eigen::Array"); + static_assert( + is_plain_type::value, + "The template for this var is an" + " expression but a var_value's inner type must be assignable such as" + " a double, Eigen::Matrix, or Eigen::Array"); /** * `PlainObject` represents a user constructible type such as Matrix or Array @@ -215,8 +217,9 @@ class vari_value::value>> using Scalar = PlainObject; // The underlying type for this class using value_type = Scalar; // The underlying type for this class using eigen_scalar = value_type_t; // A floating point type - using eigen_map = Eigen::Map; // Maps for adj_ and val_ - using vari_type = vari_value::value>>; + using eigen_map = Eigen::Map; // Maps for adj_ and val_ + using vari_type + = vari_value::value>>; eigen_scalar* val_mem_; // Pointer to memory allocated on the stack for val_ eigen_scalar* adj_mem_; // Pointer to memory allocated on the stack for adj_ /** @@ -333,9 +336,9 @@ class vari_value::value>> * * @return The modified ostream. */ - friend std::ostream& operator<<(std::ostream& os, const vari_value* v) { - return os << "val: \n" << v->val_ << " \nadj: \n" << v->adj_; - } + friend std::ostream& operator<<(std::ostream& os, const vari_value* v) { + return os << "val: \n" << v->val_ << " \nadj: \n" << v->adj_; + } /** * Allocate memory from the underlying memory pool. This memory is @@ -449,10 +452,7 @@ class vari_value::value>> * @param x Value of the constructed variable. */ template * = nullptr> - explicit vari_value(S&& x) - : val_(x), - adj_(x), - chainable_alloc() { + explicit vari_value(S&& x) : val_(x), adj_(x), chainable_alloc() { this->set_zero_adjoint(); ChainableStack::instance_->var_stack_.push_back(this); } @@ -474,10 +474,7 @@ class vari_value::value>> * that its `chain()` method is not called. */ template * = nullptr> - vari_value(S&& x, bool stacked) - : val_(x), - adj_(x), - chainable_alloc() { + vari_value(S&& x, bool stacked) : val_(x), adj_(x), chainable_alloc() { this->set_zero_adjoint(); if (stacked) { ChainableStack::instance_->var_stack_.push_back(this); diff --git a/test/unit/math/mix/meta/is_eigen_sparse_base_test.cpp b/test/unit/math/mix/meta/is_eigen_sparse_base_test.cpp index c55adfc4364..cc513e83160 100644 --- a/test/unit/math/mix/meta/is_eigen_sparse_base_test.cpp +++ b/test/unit/math/mix/meta/is_eigen_sparse_base_test.cpp @@ -8,18 +8,18 @@ TEST(MathMetaPrim, is_eigen_sparse_base_hierarchy_tests) { using Eigen::Matrix; using stan::is_eigen_sparse_base; using stan::math::test::all_eigen_dense; - all_eigen_dense(); - all_eigen_dense(); - all_eigen_dense(); - all_eigen_dense(); - all_eigen_dense(); - all_eigen_dense(); + all_eigen_dense(); + all_eigen_dense(); + all_eigen_dense(); + all_eigen_dense(); + all_eigen_dense(); + all_eigen_dense(); } TEST(MathMetaPrim, is_eigen_sparse_base_sparse_tests) { @@ -43,12 +43,12 @@ TEST(MathMetaPrim, is_eigen_sparse_base_expr_tests) { using Eigen::Matrix; using stan::is_eigen_sparse_base; using stan::math::test::all_eigen_dense_exprs; - all_eigen_dense_exprs(); - all_eigen_dense_exprs(); - all_eigen_dense_exprs(); + all_eigen_dense_exprs(); + all_eigen_dense_exprs(); + all_eigen_dense_exprs(); all_eigen_dense_exprs(); all_eigen_dense_exprs Date: Wed, 1 Jul 2020 20:02:28 -0400 Subject: [PATCH 136/355] remove docs for removed mem param in make_* functions in vari_value --- stan/math/rev/core/vari.hpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/stan/math/rev/core/vari.hpp b/stan/math/rev/core/vari.hpp index 81d2f4874d6..577ff3c419d 100644 --- a/stan/math/rev/core/vari.hpp +++ b/stan/math/rev/core/vari.hpp @@ -376,7 +376,6 @@ class vari_value::value>> /** * Create the map to the val_ stack allocated memory for an Eigen input. * @tparam S an Eigen type. - * @param mem A pointer to stack allocated memory. * @param x The Eigen type whose values will be assigned to `val_` */ template @@ -387,7 +386,6 @@ class vari_value::value>> /** * Create the map to the adj_ stack allocated memory for an Eigen input. * @tparam S an Eigen type. - * @param mem A pointer to stack allocated memory. * @param x The Eigen type whose dimensions are set the `adj_`s dimensions. */ template From fba6166e41e33eb6b1e4b19d47512d0d5d590aee Mon Sep 17 00:00:00 2001 From: Steve Bronder Date: Wed, 1 Jul 2020 23:04:07 -0400 Subject: [PATCH 137/355] remove private constructor for vari_value --- stan/math/rev/core/vari.hpp | 3 --- 1 file changed, 3 deletions(-) diff --git a/stan/math/rev/core/vari.hpp b/stan/math/rev/core/vari.hpp index 577ff3c419d..1570dd817fb 100644 --- a/stan/math/rev/core/vari.hpp +++ b/stan/math/rev/core/vari.hpp @@ -181,9 +181,6 @@ class vari_value::value>> private: template friend class var_value; - template * = nullptr> - explicit vari_value(T1&& A, T2&& B) : val_(A), adj_(B) {} }; // For backwards compatability the default is double From 48801a05d3a4a0ed18fe8d6bb2c8bd3db4dc43e4 Mon Sep 17 00:00:00 2001 From: Steve Bronder Date: Mon, 6 Jul 2020 15:42:47 -0400 Subject: [PATCH 138/355] remove make functions from vari_value matrix constructor. Add additional tests for matrix and sparse matrix vari_value construction --- stan/math/rev/core/var.hpp | 13 +++-- stan/math/rev/core/vari.hpp | 74 ++++++++------------------- test/unit/math/rev/core/var_test.cpp | 40 +++++---------- test/unit/math/rev/core/vari_test.cpp | 39 +++++++++++++- test/unit/util.hpp | 21 ++++++++ 5 files changed, 102 insertions(+), 85 deletions(-) diff --git a/stan/math/rev/core/var.hpp b/stan/math/rev/core/var.hpp index 8dbed9e7171..a356aa7100a 100644 --- a/stan/math/rev/core/var.hpp +++ b/stan/math/rev/core/var.hpp @@ -30,16 +30,19 @@ static void grad(Vari* vi); * var values objects. * @tparam T An Floating point type. */ -template -class var_value {}; - template -class var_value> { +class var_value { static_assert( is_plain_type::value, "The template for this var is an" " expression but a var_value's inner type must be assignable such as" " a double, Eigen::Matrix, or Eigen::Array"); + static_assert( + std::is_floating_point>::value, + "The template for must be a floating point or a container holding" + " floating point types"); + static_assert(std::is_reference::value, + "The template for a var_value must not be a reference!"); public: using value_type = std::decay_t; // type in vari_value. @@ -63,7 +66,7 @@ class var_value> { * @return true if this variable does not yet have * a defined variable. */ - bool is_uninitialized() { return (vi_ == nullptr); } + using bool is_uninitialized() { return (vi_ == nullptr); } /** * Construct a variable for later assignment. diff --git a/stan/math/rev/core/vari.hpp b/stan/math/rev/core/vari.hpp index 1570dd817fb..69e5ba2f802 100644 --- a/stan/math/rev/core/vari.hpp +++ b/stan/math/rev/core/vari.hpp @@ -47,8 +47,7 @@ class vari_value; * */ template -class vari_value::value>> - : public vari_base { +class vari_value> : public vari_base { public: using Scalar = T; using value_type = Scalar; @@ -75,8 +74,7 @@ class vari_value::value>> * @tparam S a floating point type. * @param x Value of the constructed variable. */ - template ::value>* = nullptr> + template * = nullptr> vari_value(S x) noexcept : val_(x), adj_(0.0) { // NOLINT ChainableStack::instance_->var_stack_.emplace_back(this); } @@ -98,8 +96,7 @@ class vari_value::value>> * @param stacked If false will put this this vari on the nochain stack so * that its `chain()` method is not called. */ - template ::value>* = nullptr> + template * = nullptr> vari_value(S x, bool stacked) noexcept : val_(x), adj_(0.0) { if (stacked) { ChainableStack::instance_->var_stack_.emplace_back(this); @@ -108,15 +105,6 @@ class vari_value::value>> } } - /** - * Constructor from vari_value - * @tparam S A floating point type - * @param x A vari_value - */ - vari_value(const vari_value& x) noexcept : val_(x.val_), adj_(x.adj_) { - ChainableStack::instance_->var_stack_.emplace_back(this); - } - ~vari_value() = default; inline void chain() {} @@ -198,8 +186,7 @@ using vari = vari_value; * */ template -class vari_value::value>> - : public vari_base { +class vari_value> : public vari_base { public: static_assert( is_plain_type::value, @@ -214,9 +201,11 @@ class vari_value::value>> using Scalar = PlainObject; // The underlying type for this class using value_type = Scalar; // The underlying type for this class using eigen_scalar = value_type_t; // A floating point type - using eigen_map = Eigen::Map; // Maps for adj_ and val_ - using vari_type - = vari_value::value>>; + /** + * Maps for adj_ and val_ + */ + using eigen_map = Eigen::Map; + using vari_type = vari_value>; eigen_scalar* val_mem_; // Pointer to memory allocated on the stack for val_ eigen_scalar* adj_mem_; // Pointer to memory allocated on the stack for adj_ /** @@ -229,15 +218,15 @@ class vari_value::value>> static constexpr Eigen::Index ColsAtCompileTime = Scalar::ColsAtCompileTime; /** - * The adjoint of this variable, which is the partial derivative - * of this variable with respect to the root variable. + * The value of this variable. */ - eigen_map adj_; + const eigen_map val_; /** - * The value of this variable. + * The adjoint of this variable, which is the partial derivative + * of this variable with respect to the root variable. */ - const eigen_map val_; + eigen_map adj_; /** * Construct a dense Eigen variable implementation from a value. The @@ -258,8 +247,8 @@ class vari_value::value>> x.size())), adj_mem_(ChainableStack::instance_->memalloc_.alloc_array( x.size())), - adj_(make_adj(x)), - val_(make_val(x)) { + val_(eigen_map(val_mem_, x.rows(), x.cols()) = x), + adj_(eigen_map(adj_mem_, x.rows(), x.cols()).setZero()) { ChainableStack::instance_->var_stack_.push_back(this); } @@ -286,8 +275,8 @@ class vari_value::value>> x.size())), adj_mem_(ChainableStack::instance_->memalloc_.alloc_array( x.size())), - adj_(make_adj(x)), - val_(make_val(x)) { + val_(eigen_map(val_mem_, x.rows(), x.cols()) = x), + adj_(eigen_map(adj_mem_, x.rows(), x.cols()).setZero()) { if (stacked) { ChainableStack::instance_->var_stack_.push_back(this); } else { @@ -315,7 +304,7 @@ class vari_value::value>> * propagating derivatives, setting the derivative of the * result with respect to itself to be 1. */ - void init_dependent() { adj_.setOnes(); } + inline void init_dependent() { adj_.setOnes(); } /** * Set the adjoint value of this variable to 0. This is used to @@ -370,26 +359,6 @@ class vari_value::value>> friend class var_value; template friend class vari_value; - /** - * Create the map to the val_ stack allocated memory for an Eigen input. - * @tparam S an Eigen type. - * @param x The Eigen type whose values will be assigned to `val_` - */ - template - inline eigen_map make_val(S&& x) { - eigen_map(val_mem_, x.rows(), x.cols()) = x; - return eigen_map(val_mem_, x.rows(), x.cols()); - } - /** - * Create the map to the adj_ stack allocated memory for an Eigen input. - * @tparam S an Eigen type. - * @param x The Eigen type whose dimensions are set the `adj_`s dimensions. - */ - template - inline eigen_map make_adj(S&& x) { - eigen_map(adj_mem_, x.rows(), x.cols()).setZero(); - return eigen_map(adj_mem_, x.rows(), x.cols()); - } }; /** @@ -409,8 +378,6 @@ class vari_value::value>> public: using PlainObject = std::decay_t>; // Base type of Eigen class - using eigen_scalar = value_type_t; // Scalar type of Eigen class - using eigen_index = typename PlainObject::StorageIndex; // Index type using Scalar = PlainObject; // vari's adj_ and val_ member type using value_type = Scalar; // vari's adj_ and val_ member type /** @@ -490,6 +457,7 @@ class vari_value::value>> * Return the size of this class's `val_` member */ const Eigen::Index size() const { return val_.size(); } + void chain() {} /** * Initialize the adjoint for this (dependent) variable to 1. @@ -562,6 +530,8 @@ class vari_value::value>> private: template friend class var_value; + template + friend class vari_value; }; } // namespace math diff --git a/test/unit/math/rev/core/var_test.cpp b/test/unit/math/rev/core/var_test.cpp index 35914078705..0c24ad72cb2 100644 --- a/test/unit/math/rev/core/var_test.cpp +++ b/test/unit/math/rev/core/var_test.cpp @@ -15,6 +15,8 @@ struct AgradRev : public testing::Test { } }; +namespace stan { + namespace test { template void ctor_overloads_float_impl() { using stan::math::var_value; @@ -56,12 +58,6 @@ void ctor_overloads_float() { ctor_overloads_float_impl(); } -TEST_F(AgradRev, ctorfloatOverloads) { - ctor_overloads_float(); - ctor_overloads_float(); - ctor_overloads_float(); -} - template void ctor_overloads_matrix(EigenMat&& xx) { using stan::math::var_value; @@ -84,24 +80,6 @@ void ctor_overloads_matrix(EigenMat&& xx) { test_var_x.adj()); } -auto make_sparse_matrix_random(int rows, int cols) { - using eigen_triplet = Eigen::Triplet; - boost::mt19937 gen; - boost::random::uniform_real_distribution dist(0.0, 1.0); - std::vector tripletList; - for (int i = 0; i < rows; ++i) { - for (int j = 0; j < cols; ++j) { - auto v_ij = dist(gen); - if (v_ij < 0.1) { - tripletList.push_back(eigen_triplet(i, j, v_ij)); - } - } - } - Eigen::SparseMatrix mat(rows, cols); - mat.setFromTriplets(tripletList.begin(), tripletList.end()); - return mat; -} - template void ctor_overloads_sparse_matrix(EigenMat&& x) { using stan::math::var_value; @@ -160,12 +138,20 @@ void ctor_overloads_sparse_matrix(EigenMat&& x) { } } +} +} +TEST_F(AgradRev, ctorfloatOverloads) { + stan::test::ctor_overloads_float(); + stan::test::ctor_overloads_float(); + stan::test::ctor_overloads_float(); +} + TEST_F(AgradRev, ctormatrixOverloads) { using dense_mat = Eigen::Matrix; using sparse_mat = Eigen::SparseMatrix; - ctor_overloads_matrix(dense_mat::Random(10, 10)); - sparse_mat sparse_x = make_sparse_matrix_random(10, 10); - ctor_overloads_sparse_matrix(sparse_x); + stan::test::ctor_overloads_matrix(dense_mat::Random(10, 10)); + sparse_mat sparse_x = stan::test::make_sparse_matrix_random(10, 10); + stan::test::ctor_overloads_sparse_matrix(sparse_x); } TEST_F(AgradRev, a_eq_x) { diff --git a/test/unit/math/rev/core/vari_test.cpp b/test/unit/math/rev/core/vari_test.cpp index c8961eb62ae..4ad4497c010 100644 --- a/test/unit/math/rev/core/vari_test.cpp +++ b/test/unit/math/rev/core/vari_test.cpp @@ -1,4 +1,5 @@ #include +#include #include #include @@ -18,5 +19,41 @@ TEST(AgradRev, long_double_test) { TEST(AgradRev, dense_matrix_vari) { using stan::math::vari_value; - stan::math::vari_value A(Eigen::MatrixXd::Random(3, 3)); + using eig_mat = Eigen::MatrixXd; + vari_value A_vari(eig_mat::Random(3, 3)); + eig_mat B(eig_mat::Random(3, 3)); + vari_value B_vari(B); + EXPECT_MATRIX_FLOAT_EQ(B, B_vari.val_); +} +TEST(AgradRev, dense_vector_vari) { + using stan::math::vari_value; + using eig_vec = Eigen::Matrix; + vari_value A_vari(eig_vec::Random(3)); + eig_vec B(eig_vec::Random(3)); + vari_value B_vari(B); + EXPECT_MATRIX_FLOAT_EQ(B, B_vari.val_); +} + +TEST(AgradRev, dense_row_vector_vari) { + using stan::math::vari_value; + using eig_row_vec = Eigen::Matrix; + vari_value A_vari(eig_row_vec::Random(3)); + eig_row_vec B(eig_row_vec::Random(3)); + vari_value B_vari(B); + EXPECT_MATRIX_FLOAT_EQ(B, B_vari.val_); +} + +TEST(AgradRev, sparse_matrix_vari) { + using stan::math::vari_value; + using eig_mat = Eigen::SparseMatrix; + using inner_iterator = typename eig_mat::InnerIterator; + using stan::test::make_sparse_matrix_random; + vari_value A_vari(make_sparse_matrix_random(10, 10)); + eig_mat B = make_sparse_matrix_random(10, 10); + vari_value B_vari(B); + for (int k = 0; k < B.outerSize(); ++k) { + for (inner_iterator it(B, k), iz(B_vari.val_, k); it; ++it, ++iz) { + EXPECT_FLOAT_EQ(iz.value(), it.value()); + } + } } diff --git a/test/unit/util.hpp b/test/unit/util.hpp index 4f0bf854254..b8746686e56 100644 --- a/test/unit/util.hpp +++ b/test/unit/util.hpp @@ -2,6 +2,8 @@ #define TEST_UNIT_UTIL_HPP #include +#include +#include #include #include #include @@ -195,6 +197,25 @@ void expect_type_matrix(const Eigen::Matrix& x) { EXPECT_EQ(Eigen::Dynamic, C); EXPECT_EQ(Eigen::Dynamic, R); } + +auto make_sparse_matrix_random(int rows, int cols) { + using eigen_triplet = Eigen::Triplet; + boost::mt19937 gen; + boost::random::uniform_real_distribution dist(0.0, 1.0); + std::vector tripletList; + for (int i = 0; i < rows; ++i) { + for (int j = 0; j < cols; ++j) { + auto v_ij = dist(gen); + if (v_ij < 0.1) { + tripletList.push_back(eigen_triplet(i, j, v_ij)); + } + } + } + Eigen::SparseMatrix mat(rows, cols); + mat.setFromTriplets(tripletList.begin(), tripletList.end()); + return mat; +} + } // namespace test } // namespace stan From 896b267b75d12100845ca5246cd893fc078c1f47 Mon Sep 17 00:00:00 2001 From: Stan Jenkins Date: Mon, 6 Jul 2020 15:43:37 -0400 Subject: [PATCH 139/355] [Jenkins] auto-formatting by clang-format version 6.0.0-1ubuntu2 (tags/RELEASE_600/final) --- stan/math/rev/core/var.hpp | 2 +- stan/math/rev/core/vari.hpp | 6 +++--- test/unit/math/rev/core/var_test.cpp | 6 +++--- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/stan/math/rev/core/var.hpp b/stan/math/rev/core/var.hpp index a356aa7100a..75535f0c899 100644 --- a/stan/math/rev/core/var.hpp +++ b/stan/math/rev/core/var.hpp @@ -42,7 +42,7 @@ class var_value { "The template for must be a floating point or a container holding" " floating point types"); static_assert(std::is_reference::value, - "The template for a var_value must not be a reference!"); + "The template for a var_value must not be a reference!"); public: using value_type = std::decay_t; // type in vari_value. diff --git a/stan/math/rev/core/vari.hpp b/stan/math/rev/core/vari.hpp index 69e5ba2f802..c0d1bc69dca 100644 --- a/stan/math/rev/core/vari.hpp +++ b/stan/math/rev/core/vari.hpp @@ -377,9 +377,9 @@ class vari_value::value>> : public vari_base, chainable_alloc { public: using PlainObject - = std::decay_t>; // Base type of Eigen class - using Scalar = PlainObject; // vari's adj_ and val_ member type - using value_type = Scalar; // vari's adj_ and val_ member type + = std::decay_t>; // Base type of Eigen class + using Scalar = PlainObject; // vari's adj_ and val_ member type + using value_type = Scalar; // vari's adj_ and val_ member type /** * Rows at compile time */ diff --git a/test/unit/math/rev/core/var_test.cpp b/test/unit/math/rev/core/var_test.cpp index 0c24ad72cb2..d6731d59ffd 100644 --- a/test/unit/math/rev/core/var_test.cpp +++ b/test/unit/math/rev/core/var_test.cpp @@ -16,7 +16,7 @@ struct AgradRev : public testing::Test { }; namespace stan { - namespace test { +namespace test { template void ctor_overloads_float_impl() { using stan::math::var_value; @@ -138,8 +138,8 @@ void ctor_overloads_sparse_matrix(EigenMat&& x) { } } -} -} +} // namespace test +} // namespace stan TEST_F(AgradRev, ctorfloatOverloads) { stan::test::ctor_overloads_float(); stan::test::ctor_overloads_float(); From 950498b5705481d7b6b3fe2a740a448c23779302 Mon Sep 17 00:00:00 2001 From: Steve Bronder Date: Mon, 6 Jul 2020 17:42:28 -0400 Subject: [PATCH 140/355] update var templates --- stan/math/rev/core/operator_divide_equal.hpp | 4 ++-- stan/math/rev/core/operator_minus_equal.hpp | 4 ++-- stan/math/rev/core/operator_multiply_equal.hpp | 4 ++-- stan/math/rev/core/operator_plus_equal.hpp | 4 ++-- stan/math/rev/core/var.hpp | 5 +---- stan/math/rev/core/vari.hpp | 8 ++++---- 6 files changed, 13 insertions(+), 16 deletions(-) diff --git a/stan/math/rev/core/operator_divide_equal.hpp b/stan/math/rev/core/operator_divide_equal.hpp index 306dbf4d2b0..71772987fcd 100644 --- a/stan/math/rev/core/operator_divide_equal.hpp +++ b/stan/math/rev/core/operator_divide_equal.hpp @@ -8,14 +8,14 @@ namespace stan { namespace math { template -inline var_value& var_value>::operator/=( +inline var_value& var_value::operator/=( const var_value& b) { vi_ = new internal::divide_vv_vari(vi_, b.vi_); return *this; } template -inline var_value& var_value>::operator/=( +inline var_value& var_value::operator/=( T b) { if (b == 1.0) { return *this; diff --git a/stan/math/rev/core/operator_minus_equal.hpp b/stan/math/rev/core/operator_minus_equal.hpp index 6be93a516e2..5ad0e377c9a 100644 --- a/stan/math/rev/core/operator_minus_equal.hpp +++ b/stan/math/rev/core/operator_minus_equal.hpp @@ -9,14 +9,14 @@ namespace stan { namespace math { template -inline var_value& var_value>::operator-=( +inline var_value& var_value::operator-=( const var_value& b) { vi_ = new internal::subtract_vv_vari(vi_, b.vi_); return *this; } template -inline var_value& var_value>::operator-=( +inline var_value& var_value::operator-=( T b) { if (b == 0.0) { return *this; diff --git a/stan/math/rev/core/operator_multiply_equal.hpp b/stan/math/rev/core/operator_multiply_equal.hpp index 91e2cc06e38..41c4dfde6f2 100644 --- a/stan/math/rev/core/operator_multiply_equal.hpp +++ b/stan/math/rev/core/operator_multiply_equal.hpp @@ -9,14 +9,14 @@ namespace stan { namespace math { template -inline var_value& var_value>::operator*=( +inline var_value& var_value::operator*=( const var_value& b) { vi_ = new internal::multiply_vv_vari(vi_, b.vi_); return *this; } template -inline var_value& var_value>::operator*=( +inline var_value& var_value::operator*=( T b) { if (b == 1.0) { return *this; diff --git a/stan/math/rev/core/operator_plus_equal.hpp b/stan/math/rev/core/operator_plus_equal.hpp index 2c58bf9fa2f..f50ac886045 100644 --- a/stan/math/rev/core/operator_plus_equal.hpp +++ b/stan/math/rev/core/operator_plus_equal.hpp @@ -9,14 +9,14 @@ namespace stan { namespace math { template -inline var_value& var_value>::operator+=( +inline var_value& var_value::operator+=( const var_value& b) { vi_ = new internal::add_vv_vari(vi_, b.vi_); return *this; } template -inline var_value& var_value>::operator+=( +inline var_value& var_value::operator+=( T b) { if (b == 0.0) { return *this; diff --git a/stan/math/rev/core/var.hpp b/stan/math/rev/core/var.hpp index 75535f0c899..4472b6df5ed 100644 --- a/stan/math/rev/core/var.hpp +++ b/stan/math/rev/core/var.hpp @@ -41,9 +41,6 @@ class var_value { std::is_floating_point>::value, "The template for must be a floating point or a container holding" " floating point types"); - static_assert(std::is_reference::value, - "The template for a var_value must not be a reference!"); - public: using value_type = std::decay_t; // type in vari_value. using vari_type = vari_value; // Type of underlying vari impl. @@ -66,7 +63,7 @@ class var_value { * @return true if this variable does not yet have * a defined variable. */ - using bool is_uninitialized() { return (vi_ == nullptr); } + inline bool is_uninitialized() { return (vi_ == nullptr); } /** * Construct a variable for later assignment. diff --git a/stan/math/rev/core/vari.hpp b/stan/math/rev/core/vari.hpp index c0d1bc69dca..fe253f8293a 100644 --- a/stan/math/rev/core/vari.hpp +++ b/stan/math/rev/core/vari.hpp @@ -11,7 +11,7 @@ namespace stan { namespace math { // forward declaration of var -template +template class var_value; /** * Abstract base class that all `vari_value` and it's derived classes inherit. @@ -167,7 +167,7 @@ class vari_value> : public vari_base { } private: - template + template friend class var_value; }; @@ -355,7 +355,7 @@ class vari_value> : public vari_base { } private: - template + template friend class var_value; template friend class vari_value; @@ -528,7 +528,7 @@ class vari_value::value>> } private: - template + template friend class var_value; template friend class vari_value; From 9cfb8a928519e8ccfa0c8478c9f2807f2fb9ee8e Mon Sep 17 00:00:00 2001 From: Stan Jenkins Date: Mon, 6 Jul 2020 17:58:39 -0400 Subject: [PATCH 141/355] [Jenkins] auto-formatting by clang-format version 6.0.0-1ubuntu2 (tags/RELEASE_600/final) --- stan/math/rev/core/operator_divide_equal.hpp | 6 ++---- stan/math/rev/core/operator_minus_equal.hpp | 6 ++---- stan/math/rev/core/operator_multiply_equal.hpp | 6 ++---- stan/math/rev/core/operator_plus_equal.hpp | 6 ++---- stan/math/rev/core/var.hpp | 1 + 5 files changed, 9 insertions(+), 16 deletions(-) diff --git a/stan/math/rev/core/operator_divide_equal.hpp b/stan/math/rev/core/operator_divide_equal.hpp index 71772987fcd..5374ad3467b 100644 --- a/stan/math/rev/core/operator_divide_equal.hpp +++ b/stan/math/rev/core/operator_divide_equal.hpp @@ -8,15 +8,13 @@ namespace stan { namespace math { template -inline var_value& var_value::operator/=( - const var_value& b) { +inline var_value& var_value::operator/=(const var_value& b) { vi_ = new internal::divide_vv_vari(vi_, b.vi_); return *this; } template -inline var_value& var_value::operator/=( - T b) { +inline var_value& var_value::operator/=(T b) { if (b == 1.0) { return *this; } diff --git a/stan/math/rev/core/operator_minus_equal.hpp b/stan/math/rev/core/operator_minus_equal.hpp index 5ad0e377c9a..2a9d33dea2b 100644 --- a/stan/math/rev/core/operator_minus_equal.hpp +++ b/stan/math/rev/core/operator_minus_equal.hpp @@ -9,15 +9,13 @@ namespace stan { namespace math { template -inline var_value& var_value::operator-=( - const var_value& b) { +inline var_value& var_value::operator-=(const var_value& b) { vi_ = new internal::subtract_vv_vari(vi_, b.vi_); return *this; } template -inline var_value& var_value::operator-=( - T b) { +inline var_value& var_value::operator-=(T b) { if (b == 0.0) { return *this; } diff --git a/stan/math/rev/core/operator_multiply_equal.hpp b/stan/math/rev/core/operator_multiply_equal.hpp index 41c4dfde6f2..45035a6acfe 100644 --- a/stan/math/rev/core/operator_multiply_equal.hpp +++ b/stan/math/rev/core/operator_multiply_equal.hpp @@ -9,15 +9,13 @@ namespace stan { namespace math { template -inline var_value& var_value::operator*=( - const var_value& b) { +inline var_value& var_value::operator*=(const var_value& b) { vi_ = new internal::multiply_vv_vari(vi_, b.vi_); return *this; } template -inline var_value& var_value::operator*=( - T b) { +inline var_value& var_value::operator*=(T b) { if (b == 1.0) { return *this; } diff --git a/stan/math/rev/core/operator_plus_equal.hpp b/stan/math/rev/core/operator_plus_equal.hpp index f50ac886045..769a96d0db1 100644 --- a/stan/math/rev/core/operator_plus_equal.hpp +++ b/stan/math/rev/core/operator_plus_equal.hpp @@ -9,15 +9,13 @@ namespace stan { namespace math { template -inline var_value& var_value::operator+=( - const var_value& b) { +inline var_value& var_value::operator+=(const var_value& b) { vi_ = new internal::add_vv_vari(vi_, b.vi_); return *this; } template -inline var_value& var_value::operator+=( - T b) { +inline var_value& var_value::operator+=(T b) { if (b == 0.0) { return *this; } diff --git a/stan/math/rev/core/var.hpp b/stan/math/rev/core/var.hpp index 4472b6df5ed..9fb4aeee2db 100644 --- a/stan/math/rev/core/var.hpp +++ b/stan/math/rev/core/var.hpp @@ -41,6 +41,7 @@ class var_value { std::is_floating_point>::value, "The template for must be a floating point or a container holding" " floating point types"); + public: using value_type = std::decay_t; // type in vari_value. using vari_type = vari_value; // Type of underlying vari impl. From f02d232a9064ec9e472f8a3d1d43f943ac4a7bb5 Mon Sep 17 00:00:00 2001 From: Steve Bronder Date: Tue, 7 Jul 2020 16:08:09 -0400 Subject: [PATCH 142/355] kickoff jenkins --- test/unit/math/rev/core/var_test.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/test/unit/math/rev/core/var_test.cpp b/test/unit/math/rev/core/var_test.cpp index d6731d59ffd..6ff5698a352 100644 --- a/test/unit/math/rev/core/var_test.cpp +++ b/test/unit/math/rev/core/var_test.cpp @@ -64,6 +64,7 @@ void ctor_overloads_matrix(EigenMat&& xx) { using stan::math::vari_value; using stan::math::test::type_name; using eigen_plain = std::decay_t>; + eigen_plain x = xx; // standard constructor EXPECT_MATRIX_FLOAT_EQ((x * x).eval(), var_value(x * x).val()); From 2d1928acfe13f1680a570077165085b8ee788f17 Mon Sep 17 00:00:00 2001 From: Stan Jenkins Date: Tue, 7 Jul 2020 16:28:41 -0400 Subject: [PATCH 143/355] [Jenkins] auto-formatting by clang-format version 6.0.0-1ubuntu2 (tags/RELEASE_600/final) --- test/unit/math/rev/core/var_test.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/unit/math/rev/core/var_test.cpp b/test/unit/math/rev/core/var_test.cpp index 6ff5698a352..2d83471b324 100644 --- a/test/unit/math/rev/core/var_test.cpp +++ b/test/unit/math/rev/core/var_test.cpp @@ -64,7 +64,7 @@ void ctor_overloads_matrix(EigenMat&& xx) { using stan::math::vari_value; using stan::math::test::type_name; using eigen_plain = std::decay_t>; - + eigen_plain x = xx; // standard constructor EXPECT_MATRIX_FLOAT_EQ((x * x).eval(), var_value(x * x).val()); From c8fd050d022743c54739f95dbad2a254991fac76 Mon Sep 17 00:00:00 2001 From: Steve Bronder Date: Wed, 8 Jul 2020 19:42:59 -0400 Subject: [PATCH 144/355] move Eigen numtraits and read_var to core to help with include order errors --- stan/math/rev/core.hpp | 3 +++ stan/math/rev/{fun => core}/Eigen_NumTraits.hpp | 6 +++--- stan/math/rev/core/gevv_vvv_vari.hpp | 4 ++-- stan/math/rev/core/matrix_vari.hpp | 2 +- stan/math/rev/{fun => core}/read_var.hpp | 0 stan/math/rev/core/var.hpp | 4 +--- stan/math/rev/core/vari.hpp | 4 +--- stan/math/rev/fun.hpp | 4 +--- stan/math/rev/fun/grad.hpp | 2 +- stan/math/rev/fun/tcrossprod.hpp | 2 +- stan/math/rev/meta/is_var.hpp | 5 ++++- stan/math/rev/meta/is_vari.hpp | 5 ++++- stan/math/rev/meta/partials_type.hpp | 2 +- 13 files changed, 23 insertions(+), 20 deletions(-) rename stan/math/rev/{fun => core}/Eigen_NumTraits.hpp (99%) rename stan/math/rev/{fun => core}/read_var.hpp (100%) diff --git a/stan/math/rev/core.hpp b/stan/math/rev/core.hpp index 33eb934c08e..88ca7b2f2c5 100644 --- a/stan/math/rev/core.hpp +++ b/stan/math/rev/core.hpp @@ -1,6 +1,8 @@ #ifndef STAN_MATH_REV_CORE_HPP #define STAN_MATH_REV_CORE_HPP +#include + #include #include #include @@ -48,6 +50,7 @@ #include #include #include +#include #include #include #include diff --git a/stan/math/rev/fun/Eigen_NumTraits.hpp b/stan/math/rev/core/Eigen_NumTraits.hpp similarity index 99% rename from stan/math/rev/fun/Eigen_NumTraits.hpp rename to stan/math/rev/core/Eigen_NumTraits.hpp index 1e6b3140427..68cd6ef1442 100644 --- a/stan/math/rev/fun/Eigen_NumTraits.hpp +++ b/stan/math/rev/core/Eigen_NumTraits.hpp @@ -2,10 +2,10 @@ #define STAN_MATH_REV_FUN_EIGEN_NUMTRAITS_HPP #include -#include -#include #include -#include +#include +#include +#include #include #include diff --git a/stan/math/rev/core/gevv_vvv_vari.hpp b/stan/math/rev/core/gevv_vvv_vari.hpp index 0505788ad3d..5fad3458a01 100644 --- a/stan/math/rev/core/gevv_vvv_vari.hpp +++ b/stan/math/rev/core/gevv_vvv_vari.hpp @@ -1,9 +1,9 @@ #ifndef STAN_MATH_REV_CORE_GEVV_VVV_VARI_HPP #define STAN_MATH_REV_CORE_GEVV_VVV_VARI_HPP -#include -#include #include +#include +#include namespace stan { namespace math { diff --git a/stan/math/rev/core/matrix_vari.hpp b/stan/math/rev/core/matrix_vari.hpp index 3aca20ff174..09c2cc93128 100644 --- a/stan/math/rev/core/matrix_vari.hpp +++ b/stan/math/rev/core/matrix_vari.hpp @@ -1,7 +1,7 @@ #ifndef STAN_MATH_REV_CORE_MATRIX_VARI_HPP #define STAN_MATH_REV_CORE_MATRIX_VARI_HPP -#include +#include #include #include #include diff --git a/stan/math/rev/fun/read_var.hpp b/stan/math/rev/core/read_var.hpp similarity index 100% rename from stan/math/rev/fun/read_var.hpp rename to stan/math/rev/core/read_var.hpp diff --git a/stan/math/rev/core/var.hpp b/stan/math/rev/core/var.hpp index 9fb4aeee2db..98660c12519 100644 --- a/stan/math/rev/core/var.hpp +++ b/stan/math/rev/core/var.hpp @@ -1,11 +1,9 @@ #ifndef STAN_MATH_REV_CORE_VAR_HPP #define STAN_MATH_REV_CORE_VAR_HPP +#include #include -#include #include -#include -#include #include #include diff --git a/stan/math/rev/core/vari.hpp b/stan/math/rev/core/vari.hpp index fe253f8293a..0af28d897e4 100644 --- a/stan/math/rev/core/vari.hpp +++ b/stan/math/rev/core/vari.hpp @@ -1,9 +1,9 @@ #ifndef STAN_MATH_REV_CORE_VARI_HPP #define STAN_MATH_REV_CORE_VARI_HPP +#include #include #include -#include #include #include @@ -33,8 +33,6 @@ class vari_base { virtual ~vari_base() noexcept {} }; -template -class vari_value; /** * The variable implementation for floating point types. * diff --git a/stan/math/rev/fun.hpp b/stan/math/rev/fun.hpp index 7aeaa486f67..8b5b8620b9f 100644 --- a/stan/math/rev/fun.hpp +++ b/stan/math/rev/fun.hpp @@ -2,8 +2,7 @@ #define STAN_MATH_REV_FUN_HPP #include -#include - +#include #include #include @@ -118,7 +117,6 @@ #include #include #include -#include #include #include #include diff --git a/stan/math/rev/fun/grad.hpp b/stan/math/rev/fun/grad.hpp index 099e641337a..31853a673f2 100644 --- a/stan/math/rev/fun/grad.hpp +++ b/stan/math/rev/fun/grad.hpp @@ -2,7 +2,7 @@ #define STAN_MATH_REV_FUN_GRAD_HPP #include -#include +#include #include #include diff --git a/stan/math/rev/fun/tcrossprod.hpp b/stan/math/rev/fun/tcrossprod.hpp index 02b57159a9f..08961cabe73 100644 --- a/stan/math/rev/fun/tcrossprod.hpp +++ b/stan/math/rev/fun/tcrossprod.hpp @@ -3,7 +3,7 @@ #include #include -#include +#include #include #include #include diff --git a/stan/math/rev/meta/is_var.hpp b/stan/math/rev/meta/is_var.hpp index e4d9fa54fed..5bb004524bb 100644 --- a/stan/math/rev/meta/is_var.hpp +++ b/stan/math/rev/meta/is_var.hpp @@ -1,12 +1,15 @@ #ifndef STAN_MATH_REV_META_IS_VAR_HPP #define STAN_MATH_REV_META_IS_VAR_HPP -#include #include #include namespace stan { +namespace math { + template + class var_value; +} namespace internal { template struct is_var_impl : std::false_type {}; diff --git a/stan/math/rev/meta/is_vari.hpp b/stan/math/rev/meta/is_vari.hpp index 39fb79cb767..4e7ddcc8315 100644 --- a/stan/math/rev/meta/is_vari.hpp +++ b/stan/math/rev/meta/is_vari.hpp @@ -1,12 +1,15 @@ #ifndef STAN_MATH_REV_META_IS_VARI_HPP #define STAN_MATH_REV_META_IS_VARI_HPP -#include #include #include namespace stan { +namespace math { + template + class vari_value; +} namespace internal { template struct is_vari_impl : std::false_type {}; diff --git a/stan/math/rev/meta/partials_type.hpp b/stan/math/rev/meta/partials_type.hpp index 823117fe062..1975c331ef1 100644 --- a/stan/math/rev/meta/partials_type.hpp +++ b/stan/math/rev/meta/partials_type.hpp @@ -1,9 +1,9 @@ #ifndef STAN_MATH_REV_META_PARTIALS_TYPE_HPP #define STAN_MATH_REV_META_PARTIALS_TYPE_HPP -#include #include #include +#include #include namespace stan { From 9660a5a18f620b1249f2478f4e8a4358011b8b83 Mon Sep 17 00:00:00 2001 From: Stan Jenkins Date: Wed, 8 Jul 2020 19:44:33 -0400 Subject: [PATCH 145/355] [Jenkins] auto-formatting by clang-format version 6.0.0-1ubuntu2 (tags/RELEASE_600/final) --- stan/math/rev/meta/is_var.hpp | 4 ++-- stan/math/rev/meta/is_vari.hpp | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/stan/math/rev/meta/is_var.hpp b/stan/math/rev/meta/is_var.hpp index 5bb004524bb..f0f3855bc7f 100644 --- a/stan/math/rev/meta/is_var.hpp +++ b/stan/math/rev/meta/is_var.hpp @@ -7,8 +7,8 @@ namespace stan { namespace math { - template - class var_value; +template +class var_value; } namespace internal { template diff --git a/stan/math/rev/meta/is_vari.hpp b/stan/math/rev/meta/is_vari.hpp index 4e7ddcc8315..db786456202 100644 --- a/stan/math/rev/meta/is_vari.hpp +++ b/stan/math/rev/meta/is_vari.hpp @@ -7,8 +7,8 @@ namespace stan { namespace math { - template - class vari_value; +template +class vari_value; } namespace internal { template From 826d1d545eae2ec53a456bb110f599a5119b18ab Mon Sep 17 00:00:00 2001 From: Steve Bronder Date: Thu, 9 Jul 2020 00:10:06 -0400 Subject: [PATCH 146/355] move Eigen Numtraits and typedefs to core for fwd and rev --- stan/math/fwd/core.hpp | 3 +++ stan/math/fwd/{fun => core}/Eigen_NumTraits.hpp | 4 ++-- stan/math/fwd/{fun => core}/read_fvar.hpp | 0 stan/math/fwd/core/std_iterator_traits.hpp | 2 +- stan/math/fwd/{fun => core}/typedefs.hpp | 8 ++++---- stan/math/fwd/fun.hpp | 4 +--- stan/math/fwd/fun/mdivide_left_tri_low.hpp | 3 +-- stan/math/fwd/fun/multiply.hpp | 3 +-- stan/math/mix/fun/typedefs.hpp | 6 +++--- stan/math/rev/core.hpp | 1 + test/unit/math/rev/{fun => core}/read_var_test.cpp | 0 test/unit/math/rev/meta/VectorBuilderHelper_test.cpp | 2 +- test/unit/math/rev/meta/VectorBuilder_test.cpp | 2 +- test/unit/math/rev/meta/ad_promotable_test.cpp | 2 +- test/unit/math/rev/meta/child_type_test.cpp | 2 +- test/unit/math/rev/meta/include_summand_test.cpp | 2 +- test/unit/math/rev/meta/is_constant_all_test.cpp | 3 ++- test/unit/math/rev/meta/partials_return_type_test.cpp | 2 +- test/unit/math/rev/meta/partials_type_test.cpp | 2 +- test/unit/math/rev/meta/require_generics_test.cpp | 3 +-- 20 files changed, 27 insertions(+), 27 deletions(-) rename stan/math/fwd/{fun => core}/Eigen_NumTraits.hpp (98%) rename stan/math/fwd/{fun => core}/read_fvar.hpp (100%) rename stan/math/fwd/{fun => core}/typedefs.hpp (79%) rename test/unit/math/rev/{fun => core}/read_var_test.cpp (100%) diff --git a/stan/math/fwd/core.hpp b/stan/math/fwd/core.hpp index 543a8206bf4..9ae0d7ac1fe 100644 --- a/stan/math/fwd/core.hpp +++ b/stan/math/fwd/core.hpp @@ -2,6 +2,7 @@ #define STAN_MATH_FWD_CORE_HPP #include +#include #include #include #include @@ -17,8 +18,10 @@ #include #include #include +#include #include #include #include +#include #endif diff --git a/stan/math/fwd/fun/Eigen_NumTraits.hpp b/stan/math/fwd/core/Eigen_NumTraits.hpp similarity index 98% rename from stan/math/fwd/fun/Eigen_NumTraits.hpp rename to stan/math/fwd/core/Eigen_NumTraits.hpp index 8612324d68a..9bc6f09275e 100644 --- a/stan/math/fwd/fun/Eigen_NumTraits.hpp +++ b/stan/math/fwd/core/Eigen_NumTraits.hpp @@ -3,8 +3,8 @@ #include #include -#include -#include +#include +#include #include #include diff --git a/stan/math/fwd/fun/read_fvar.hpp b/stan/math/fwd/core/read_fvar.hpp similarity index 100% rename from stan/math/fwd/fun/read_fvar.hpp rename to stan/math/fwd/core/read_fvar.hpp diff --git a/stan/math/fwd/core/std_iterator_traits.hpp b/stan/math/fwd/core/std_iterator_traits.hpp index 0caffd3e034..e3220e81108 100644 --- a/stan/math/fwd/core/std_iterator_traits.hpp +++ b/stan/math/fwd/core/std_iterator_traits.hpp @@ -1,8 +1,8 @@ #ifndef STAN_MATH_FWD_CORE_STD_ITERATOR_TRAITS_HPP #define STAN_MATH_FWD_CORE_STD_ITERATOR_TRAITS_HPP -#include #include +#include #include namespace std { diff --git a/stan/math/fwd/fun/typedefs.hpp b/stan/math/fwd/core/typedefs.hpp similarity index 79% rename from stan/math/fwd/fun/typedefs.hpp rename to stan/math/fwd/core/typedefs.hpp index bd8ab2d84e4..8e5ebd27320 100644 --- a/stan/math/fwd/fun/typedefs.hpp +++ b/stan/math/fwd/core/typedefs.hpp @@ -1,9 +1,9 @@ -#ifndef STAN_MATH_FWD_FUN_TYPEDEFS_HPP -#define STAN_MATH_FWD_FUN_TYPEDEFS_HPP +#ifndef STAN_MATH_FWD_CORE_TYPEDEFS_HPP +#define STAN_MATH_FWD_CORE_TYPEDEFS_HPP #include -#include -#include +#include +#include namespace stan { namespace math { diff --git a/stan/math/fwd/fun.hpp b/stan/math/fwd/fun.hpp index e10e9da72f1..91aafac3272 100644 --- a/stan/math/fwd/fun.hpp +++ b/stan/math/fwd/fun.hpp @@ -2,7 +2,7 @@ #define STAN_MATH_FWD_FUN_HPP #include -#include +#include #include #include @@ -94,7 +94,6 @@ #include #include #include -#include #include #include #include @@ -111,7 +110,6 @@ #include #include #include -#include #include #include #include diff --git a/stan/math/fwd/fun/mdivide_left_tri_low.hpp b/stan/math/fwd/fun/mdivide_left_tri_low.hpp index c2c19d8ee67..a172d19818c 100644 --- a/stan/math/fwd/fun/mdivide_left_tri_low.hpp +++ b/stan/math/fwd/fun/mdivide_left_tri_low.hpp @@ -4,10 +4,9 @@ #include #include #include -#include +#include #include #include -#include namespace stan { namespace math { diff --git a/stan/math/fwd/fun/multiply.hpp b/stan/math/fwd/fun/multiply.hpp index ebb03db7b07..71bda19187b 100644 --- a/stan/math/fwd/fun/multiply.hpp +++ b/stan/math/fwd/fun/multiply.hpp @@ -1,12 +1,11 @@ #ifndef STAN_MATH_FWD_FUN_MULTIPLY_HPP #define STAN_MATH_FWD_FUN_MULTIPLY_HPP +#include #include #include -#include #include #include -#include namespace stan { namespace math { diff --git a/stan/math/mix/fun/typedefs.hpp b/stan/math/mix/fun/typedefs.hpp index ddf7ea5d793..88370cfb82f 100644 --- a/stan/math/mix/fun/typedefs.hpp +++ b/stan/math/mix/fun/typedefs.hpp @@ -1,10 +1,10 @@ -#ifndef STAN_MATH_MIX_MAT_FUN_TYPEDEFS_HPP -#define STAN_MATH_MIX_MAT_FUN_TYPEDEFS_HPP +#ifndef STAN_MATH_MIX_MAT_CORE_TYPEDEFS_HPP +#define STAN_MATH_MIX_MAT_CORE_TYPEDEFS_HPP #include #include +#include #include -#include namespace stan { namespace math { diff --git a/stan/math/rev/core.hpp b/stan/math/rev/core.hpp index 88ca7b2f2c5..36f0b4f2349 100644 --- a/stan/math/rev/core.hpp +++ b/stan/math/rev/core.hpp @@ -2,6 +2,7 @@ #define STAN_MATH_REV_CORE_HPP #include +#include #include #include diff --git a/test/unit/math/rev/fun/read_var_test.cpp b/test/unit/math/rev/core/read_var_test.cpp similarity index 100% rename from test/unit/math/rev/fun/read_var_test.cpp rename to test/unit/math/rev/core/read_var_test.cpp diff --git a/test/unit/math/rev/meta/VectorBuilderHelper_test.cpp b/test/unit/math/rev/meta/VectorBuilderHelper_test.cpp index 70d8c464102..46fa4649963 100644 --- a/test/unit/math/rev/meta/VectorBuilderHelper_test.cpp +++ b/test/unit/math/rev/meta/VectorBuilderHelper_test.cpp @@ -1,4 +1,4 @@ -#include +#include #include #include diff --git a/test/unit/math/rev/meta/VectorBuilder_test.cpp b/test/unit/math/rev/meta/VectorBuilder_test.cpp index 557c21b1de6..c7c470d815c 100644 --- a/test/unit/math/rev/meta/VectorBuilder_test.cpp +++ b/test/unit/math/rev/meta/VectorBuilder_test.cpp @@ -1,4 +1,4 @@ -#include +#include #include #include diff --git a/test/unit/math/rev/meta/ad_promotable_test.cpp b/test/unit/math/rev/meta/ad_promotable_test.cpp index 3f21820fe1b..4ffcddb7222 100644 --- a/test/unit/math/rev/meta/ad_promotable_test.cpp +++ b/test/unit/math/rev/meta/ad_promotable_test.cpp @@ -1,4 +1,4 @@ -#include +#include #include #include diff --git a/test/unit/math/rev/meta/child_type_test.cpp b/test/unit/math/rev/meta/child_type_test.cpp index 8e6112fc0ba..afb585c4386 100644 --- a/test/unit/math/rev/meta/child_type_test.cpp +++ b/test/unit/math/rev/meta/child_type_test.cpp @@ -1,4 +1,4 @@ -#include +#include #include #include diff --git a/test/unit/math/rev/meta/include_summand_test.cpp b/test/unit/math/rev/meta/include_summand_test.cpp index 69ba28a7081..0d9dba66322 100644 --- a/test/unit/math/rev/meta/include_summand_test.cpp +++ b/test/unit/math/rev/meta/include_summand_test.cpp @@ -1,4 +1,4 @@ -#include +#include #include #include #include diff --git a/test/unit/math/rev/meta/is_constant_all_test.cpp b/test/unit/math/rev/meta/is_constant_all_test.cpp index 771eea6d8c9..ef703907916 100644 --- a/test/unit/math/rev/meta/is_constant_all_test.cpp +++ b/test/unit/math/rev/meta/is_constant_all_test.cpp @@ -1,4 +1,5 @@ -#include +#include +#include #include #include diff --git a/test/unit/math/rev/meta/partials_return_type_test.cpp b/test/unit/math/rev/meta/partials_return_type_test.cpp index 8eed06a2e8f..43e265137fb 100644 --- a/test/unit/math/rev/meta/partials_return_type_test.cpp +++ b/test/unit/math/rev/meta/partials_return_type_test.cpp @@ -1,4 +1,4 @@ -#include +#include #include #include #include diff --git a/test/unit/math/rev/meta/partials_type_test.cpp b/test/unit/math/rev/meta/partials_type_test.cpp index d3187a0ec47..aaeb2a7e81f 100644 --- a/test/unit/math/rev/meta/partials_type_test.cpp +++ b/test/unit/math/rev/meta/partials_type_test.cpp @@ -1,4 +1,4 @@ -#include +#include #include TEST(MetaTraitsRevScal, partials_type) { diff --git a/test/unit/math/rev/meta/require_generics_test.cpp b/test/unit/math/rev/meta/require_generics_test.cpp index ee93fe9b5a7..c4304af0abc 100644 --- a/test/unit/math/rev/meta/require_generics_test.cpp +++ b/test/unit/math/rev/meta/require_generics_test.cpp @@ -1,7 +1,6 @@ -#include // just this is bad #include -#include +#include #include #include #include From dcb763516ab0e0e9d32d66350f70445d83ed6db6 Mon Sep 17 00:00:00 2001 From: tadej Date: Wed, 8 Jul 2020 16:24:52 +0200 Subject: [PATCH 147/355] added support for var_value into operands_and_partials --- .../prim/functor/operands_and_partials.hpp | 9 ++ stan/math/rev/core/precomputed_gradients.hpp | 121 ++++++++++++++++-- stan/math/rev/core/var.hpp | 13 ++ stan/math/rev/core/vari.hpp | 13 ++ .../rev/functor/operands_and_partials.hpp | 50 +++++++- .../operands_and_partials_test.cpp | 0 .../operands_and_partials_test.cpp | 0 .../rev/core/precomputed_gradients_test.cpp | 33 +++++ .../operands_and_partials_test.cpp | 19 +++ 9 files changed, 243 insertions(+), 15 deletions(-) rename test/unit/math/fwd/{meta => functor}/operands_and_partials_test.cpp (100%) rename test/unit/math/prim/{meta => functor}/operands_and_partials_test.cpp (100%) rename test/unit/math/rev/{meta => functor}/operands_and_partials_test.cpp (93%) diff --git a/stan/math/prim/functor/operands_and_partials.hpp b/stan/math/prim/functor/operands_and_partials.hpp index fe355340097..7d41a79164e 100644 --- a/stan/math/prim/functor/operands_and_partials.hpp +++ b/stan/math/prim/functor/operands_and_partials.hpp @@ -7,6 +7,7 @@ #include #include #include +#include namespace stan { namespace math { @@ -52,6 +53,8 @@ class ops_partials_edge { void dump_operands(void* /* operands */) const {} // reverse mode ViewElt dx() const { return 0; } // used for fvars int size() const { return 0; } // reverse mode + std::tuple<> container_operands() {return std::tuple<>();} + std::tuple<> container_partials() {return std::tuple<>();} }; } // namespace internal @@ -151,6 +154,8 @@ class ops_partials_edge> { void dump_operands(void* /* operands */) const {} // reverse mode double dx() const { return 0; } // used for fvars int size() const { return 0; } + std::tuple<> container_operands() {return std::tuple<>();} + std::tuple<> container_partials() {return std::tuple<>();} }; /** \ingroup type_trait @@ -173,6 +178,8 @@ class ops_partials_edge>> { void dump_operands(void* /* operands */) const {} // reverse mode double dx() const { return 0; } // used for fvars int size() const { return 0; } + std::tuple<> container_operands() {return std::tuple<>();} + std::tuple<> container_partials() {return std::tuple<>();} }; /** \ingroup type_trait @@ -196,6 +203,8 @@ class ops_partials_edge>> { void dump_operands(void* /* operands */) const {} // reverse mode double dx() const { return 0; } // used for fvars int size() const { return 0; } + std::tuple<> container_operands() {return std::tuple<>();} + std::tuple<> container_partials() {return std::tuple<>();} }; } // namespace internal } // namespace math diff --git a/stan/math/rev/core/precomputed_gradients.hpp b/stan/math/rev/core/precomputed_gradients.hpp index d9b899cf60f..98d362d4c48 100644 --- a/stan/math/rev/core/precomputed_gradients.hpp +++ b/stan/math/rev/core/precomputed_gradients.hpp @@ -2,11 +2,13 @@ #define STAN_MATH_REV_CORE_PRECOMPUTED_GRADIENTS_HPP #include +#include // #include #include #include #include #include +#include namespace stan { namespace math { @@ -17,51 +19,118 @@ namespace math { * * Stan users should use function precomputed_gradients() * directly. + * + * @tparam ContainerOperands tuple of any container operands (var_value + * containing Eigen types) + * @tparam ContainerGradients tupleof any container gradients (Eigen types) */ -class precomputed_gradients_vari : public vari { +template , + typename ContainerGradients = std::tuple<>> +class precomputed_gradients_vari_template : public vari { protected: const size_t size_; vari** varis_; double* gradients_; + static_assert(std::tuple_size::value + == std::tuple_size::value, + "precomputed_gradients_vari: ContainerOperands and " + "ContainerGradients should have same size!"); + static constexpr size_t N_containers + = std::tuple_size::value; + ContainerOperands container_operands_; + ContainerGradients container_gradients_; + + /** + * Checks that sizes of containers in container operands and + * container_gradients match. + * + * @throws std::invalid_argument sizes do not match + */ + template + void check_sizes(std::index_sequence) { + static_cast(std::initializer_list{ + (check_size_match("precomputed_gradients_vari", "rows of operands", + std::get(container_operands_).vi_->rows(), + "rows of gradients", + std::get(container_gradients_).rows()), + check_size_match("precomputed_gradients_vari", "cols of operands", + std::get(container_operands_).vi_->cols(), + "cols of gradients", + std::get(container_gradients_).cols()), + 0)...}); + } public: /** * Construct a precomputed vari with the specified value, - * operands, and gradients. + * operands, gradients and optionally container operands and containers of + * gradients. * + * @tparam COps tuple of any container operands (var_value + * containing Eigen types) + * @tparam CGrads tupleof any container gradients (Eigen types) * @param[in] val The value of the variable. * @param[in] size Size of operands and gradients * @param[in] varis Operand implementations. * @param[in] gradients Gradients with respect to operands. + * @param container_operands any container operands + * @param container_gradients any container gradients */ - precomputed_gradients_vari(double val, size_t size, vari** varis, - double* gradients) - : vari(val), size_(size), varis_(varis), gradients_(gradients) {} + template , typename CGrads = std::tuple<>> + precomputed_gradients_vari_template(double val, size_t size, vari** varis, + double* gradients, + COps&& container_operands + = std::tuple<>(), + CGrads&& container_gradients + = std::tuple<>()) + : vari(val), + size_(size), + varis_(varis), + gradients_(gradients), + container_operands_(std::forward(container_operands)), + container_gradients_(std::forward(container_gradients)) { + check_sizes(std::make_index_sequence()); + } /** * Construct a precomputed vari with the specified value, - * operands, and gradients. + * operands, gradients and optionally container operands and containers of + * gradients. * * @tparam Arith An arithmetic type * @tparam VecVar A vector of vars * @tparam VecArith A vector of arithmetic types + * @tparam COps tuple of any container operands (var_value + * containing Eigen types) + * @tparam CGrads tupleof any container gradients (Eigen types) * @param[in] val The value of the variable. * @param[in] vars Vector of operands. * @param[in] gradients Vector of partial derivatives of value * with respect to operands. + * @param container_operands any container operands + * @param container_gradients any container gradients * @throws std::invalid_argument if the sizes of the vectors * don't match. */ - template - precomputed_gradients_vari(Arith val, VecVar&& vars, VecArith&& gradients) + template , typename CGrads = std::tuple<>> + precomputed_gradients_vari_template(Arith val, const VecVar& vars, + const VecArith& gradients, + COps&& container_operands + = std::tuple<>(), + CGrads&& container_gradients + = std::tuple<>()) : vari(val), size_(vars.size()), varis_(ChainableStack::instance_->memalloc_.alloc_array( vars.size())), gradients_(ChainableStack::instance_->memalloc_.alloc_array( - vars.size())) { + vars.size())), + container_operands_(std::forward(container_operands)), + container_gradients_(std::forward(container_gradients)) { check_consistent_sizes("precomputed_gradients_vari", "vars", vars, "gradients", gradients); + check_sizes(std::make_index_sequence()); for (size_t i = 0; i < vars.size(); ++i) { varis_[i] = vars[i].vi_; } @@ -76,9 +145,18 @@ class precomputed_gradients_vari : public vari { for (size_t i = 0; i < size_; ++i) { varis_[i]->adj_ += adj_ * gradients_[i]; } + index_apply([this](auto... Is) { + static_cast(std::initializer_list{ + (std::get(this->container_operands_).adj() + += this->adj_ * std::get(this->container_gradients_), + 0)...}); + }); } }; +using precomputed_gradients_vari + = precomputed_gradients_vari_template, std::tuple<>>; + /** * This function returns a var for an expression that has the * specified value, vector of operands, and vector of partial @@ -87,18 +165,33 @@ class precomputed_gradients_vari : public vari { * @tparam Arith An arithmetic type * @tparam VecVar A vector of vars * @tparam VecArith A vector of arithmetic types + * @tparam ContainerOperands tuple of any container operands (var_value + * containing Eigen types) + * @tparam ContainerGradients tupleof any container gradients (Eigen types) * @param[in] value The value of the resulting dependent variable. * @param[in] operands operands. * @param[in] gradients vector of partial derivatives of result with * respect to operands. + * @param container_operands any container operands + * @param container_gradients any container gradients * @return An autodiff variable that uses the precomputed * gradients provided. */ -template -inline var precomputed_gradients(Arith value, VecVar&& operands, - VecArith&& gradients) { - return {new precomputed_gradients_vari(value, std::forward(operands), - std::forward(gradients))}; +template , + typename ContainerGradinets = std::tuple<>> +inline var precomputed_gradients(Arith value, const VecVar& operands, + const VecArith& gradients, + ContainerOperands&& container_operands + = std::tuple<>(), + ContainerGradinets&& container_gradients + = std::tuple<>()) { + return { + new precomputed_gradients_vari_template, + std::decay_t>( + value, operands, gradients, + std::forward(container_operands), + std::forward(container_gradients))}; } } // namespace math diff --git a/stan/math/rev/core/var.hpp b/stan/math/rev/core/var.hpp index 9fb4aeee2db..e3bcb3c95ee 100644 --- a/stan/math/rev/core/var.hpp +++ b/stan/math/rev/core/var.hpp @@ -297,5 +297,18 @@ class var_value { using var = var_value; } // namespace math + +/** + * Template specialization defining the scalar type of + * values stored in var_value. + * + * @tparam T type to check. + * @ingroup type_trait + */ +template +struct scalar_type>{ + using type = math::var_value>; +}; + } // namespace stan #endif diff --git a/stan/math/rev/core/vari.hpp b/stan/math/rev/core/vari.hpp index fe253f8293a..31ba233afa1 100644 --- a/stan/math/rev/core/vari.hpp +++ b/stan/math/rev/core/vari.hpp @@ -535,5 +535,18 @@ class vari_value::value>> }; } // namespace math + +/** + * Template specialization defining the scalar type of + * values stored in vari_value. + * + * @tparam T type to check. + * @ingroup type_trait + */ +template +struct scalar_type>{ + using type = math::vari_value>; +}; + } // namespace stan #endif diff --git a/stan/math/rev/functor/operands_and_partials.hpp b/stan/math/rev/functor/operands_and_partials.hpp index 14c3513a1e1..1e6a75181ff 100644 --- a/stan/math/rev/functor/operands_and_partials.hpp +++ b/stan/math/rev/functor/operands_and_partials.hpp @@ -15,6 +15,7 @@ #include #include #include +#include namespace stan { namespace math { @@ -40,6 +41,8 @@ class ops_partials_edge { void dump_partials(double* partials) { *partials = this->partial_; } void dump_operands(vari** varis) { *varis = this->operand_.vi_; } int size() const { return 1; } + std::tuple<> container_operands() { return std::tuple<>(); } + std::tuple<> container_partials() { return std::tuple<>(); } }; } // namespace internal @@ -130,8 +133,18 @@ class operands_and_partials { edge5_.dump_operands(&varis[idx += edge4_.size()]); edge5_.dump_partials(&partials[idx]); + auto container_operands = std::tuple_cat( + edge1_.container_operands(), edge2_.container_operands(), + edge3_.container_operands(), edge4_.container_operands()); + auto container_partials = std::tuple_cat( + edge1_.container_partials(), edge2_.container_partials(), + edge3_.container_partials(), edge4_.container_partials()); + return var( - new precomputed_gradients_vari(value, edges_size, varis, partials)); + new precomputed_gradients_vari_template( + value, edges_size, varis, partials, std::move(container_operands), + std::move(container_partials))); } }; @@ -165,6 +178,8 @@ class ops_partials_edge> { } } int size() { return this->operands_.size(); } + std::tuple<> container_operands() { return std::tuple<>(); } + std::tuple<> container_partials() { return std::tuple<>(); } }; template @@ -194,6 +209,35 @@ class ops_partials_edge> { = this->partials_; } int size() { return this->operands_.size(); } + std::tuple<> container_operands() { return std::tuple<>(); } + std::tuple<> container_partials() { return std::tuple<>(); } +}; + +template +class ops_partials_edge, require_eigen_t> { + public: + using partials_t = plain_type_t; + partials_t partials_; // For univariate use-cases + broadcast_array partials_vec_; // For multivariate + explicit ops_partials_edge(const var_value& ops) + : partials_(partials_t::Zero(ops.vi_->rows(), ops.vi_->cols())), + partials_vec_(partials_), + operands_(ops) {} + + private: + template + friend class stan::math::operands_and_partials; + const var_value& operands_; + + void dump_operands(vari** varis) {} + void dump_partials(double* partials) {} + int size() { return 0; } + std::tuple> container_operands() { + return std::make_tuple(operands_); + } + std::tuple container_partials() { + return std::make_tuple(partials_); + } }; // SPECIALIZATIONS FOR MULTIVARIATE VECTORIZATIONS @@ -238,6 +282,8 @@ class ops_partials_edge>> { } return this->operands_.size() * this->operands_[0].size(); } + std::tuple<> container_operands() { return std::tuple<>(); } + std::tuple<> container_partials() { return std::tuple<>(); } }; template <> @@ -280,6 +326,8 @@ class ops_partials_edge>> { } return this->operands_.size() * this->operands_[0].size(); } + std::tuple<> container_operands() { return std::tuple<>(); } + std::tuple<> container_partials() { return std::tuple<>(); } }; } // namespace internal } // namespace math diff --git a/test/unit/math/fwd/meta/operands_and_partials_test.cpp b/test/unit/math/fwd/functor/operands_and_partials_test.cpp similarity index 100% rename from test/unit/math/fwd/meta/operands_and_partials_test.cpp rename to test/unit/math/fwd/functor/operands_and_partials_test.cpp diff --git a/test/unit/math/prim/meta/operands_and_partials_test.cpp b/test/unit/math/prim/functor/operands_and_partials_test.cpp similarity index 100% rename from test/unit/math/prim/meta/operands_and_partials_test.cpp rename to test/unit/math/prim/functor/operands_and_partials_test.cpp diff --git a/test/unit/math/rev/core/precomputed_gradients_test.cpp b/test/unit/math/rev/core/precomputed_gradients_test.cpp index 8757461a39b..3880d55f958 100644 --- a/test/unit/math/rev/core/precomputed_gradients_test.cpp +++ b/test/unit/math/rev/core/precomputed_gradients_test.cpp @@ -1,5 +1,6 @@ #include #include +#include #include TEST(StanAgradRevInternal, precomputed_gradients) { @@ -100,3 +101,35 @@ TEST(StanAgradRevInternal, precomputed_gradients_mismatched_sizes) { std::invalid_argument); stan::math::recover_memory(); } + +TEST(StanAgradRevInternal, precomputed_gradients_containers) { + double value = 1; + std::vector vars; + std::vector gradients; + stan::math::var_value a(Eigen::MatrixXd::Constant(3, 3, 2)); + std::tuple&> ops{a}; + Eigen::MatrixXd grad = Eigen::MatrixXd::Constant(3, 3, -1); + std::tuple grads(grad); + + stan::math::var lp + = stan::math::precomputed_gradients(value, vars, gradients, ops, grads); + (2 * lp).grad(); + EXPECT_MATRIX_EQ(a.adj(), Eigen::MatrixXd::Constant(3, 3, -2)); + + stan::math::recover_memory(); +} + +TEST(StanAgradRevInternal, precomputed_gradients_mismatched_containers) { + double value = 1; + std::vector vars; + std::vector gradients; + stan::math::var_value a(Eigen::MatrixXd::Constant(3, 3, 2)); + std::tuple&> ops(a); + Eigen::MatrixXd grad = Eigen::MatrixXd::Constant(3, 2, -1); + std::tuple grads(grad); + + EXPECT_THROW( + stan::math::precomputed_gradients(value, vars, gradients, ops, grads), + std::invalid_argument); + stan::math::recover_memory(); +} diff --git a/test/unit/math/rev/meta/operands_and_partials_test.cpp b/test/unit/math/rev/functor/operands_and_partials_test.cpp similarity index 93% rename from test/unit/math/rev/meta/operands_and_partials_test.cpp rename to test/unit/math/rev/functor/operands_and_partials_test.cpp index fd68b22fa2a..1a356ab35bd 100644 --- a/test/unit/math/rev/meta/operands_and_partials_test.cpp +++ b/test/unit/math/rev/functor/operands_and_partials_test.cpp @@ -1,5 +1,6 @@ #include #include +#include #include #include @@ -326,3 +327,21 @@ TEST(AgradPartialsVari, OperandsAndPartialsMultivarMixed) { } o6.edge3_.partials_vec_[0] += d_vec2; } + +TEST(AgradPartialsVari, OperandsAndPartialsVarValueMat) { + using stan::math::matrix_d; + using stan::math::matrix_v; + using stan::math::operands_and_partials; + using stan::math::var; + + Eigen::MatrixXd a(2, 2); + a << 10.0, 20.0, 30.0, 40.0; + stan::math::var_value av(a); + + operands_and_partials> ops(av); + + ops.edge1_.partials_ = Eigen::MatrixXd::Constant(2,2,-2); + var lp = ops.build(1); + (2*lp).grad(); + EXPECT_MATRIX_EQ(av.adj(), Eigen::MatrixXd::Constant(2,2,-4)) +} From d8c879e6f0f7c5d12fcc006e164dc72d6786b32f Mon Sep 17 00:00:00 2001 From: Stan Jenkins Date: Thu, 9 Jul 2020 09:01:22 +0000 Subject: [PATCH 148/355] [Jenkins] auto-formatting by clang-format version 6.0.0-1ubuntu2~16.04.1 (tags/RELEASE_600/final) --- .../prim/functor/operands_and_partials.hpp | 16 ++++++++-------- stan/math/rev/core/precomputed_gradients.hpp | 4 ++-- stan/math/rev/core/var.hpp | 4 ++-- stan/math/rev/core/vari.hpp | 4 ++-- .../rev/functor/operands_and_partials_test.cpp | 18 +++++++++--------- 5 files changed, 23 insertions(+), 23 deletions(-) diff --git a/stan/math/prim/functor/operands_and_partials.hpp b/stan/math/prim/functor/operands_and_partials.hpp index 7d41a79164e..6a755390a60 100644 --- a/stan/math/prim/functor/operands_and_partials.hpp +++ b/stan/math/prim/functor/operands_and_partials.hpp @@ -53,8 +53,8 @@ class ops_partials_edge { void dump_operands(void* /* operands */) const {} // reverse mode ViewElt dx() const { return 0; } // used for fvars int size() const { return 0; } // reverse mode - std::tuple<> container_operands() {return std::tuple<>();} - std::tuple<> container_partials() {return std::tuple<>();} + std::tuple<> container_operands() { return std::tuple<>(); } + std::tuple<> container_partials() { return std::tuple<>(); } }; } // namespace internal @@ -154,8 +154,8 @@ class ops_partials_edge> { void dump_operands(void* /* operands */) const {} // reverse mode double dx() const { return 0; } // used for fvars int size() const { return 0; } - std::tuple<> container_operands() {return std::tuple<>();} - std::tuple<> container_partials() {return std::tuple<>();} + std::tuple<> container_operands() { return std::tuple<>(); } + std::tuple<> container_partials() { return std::tuple<>(); } }; /** \ingroup type_trait @@ -178,8 +178,8 @@ class ops_partials_edge>> { void dump_operands(void* /* operands */) const {} // reverse mode double dx() const { return 0; } // used for fvars int size() const { return 0; } - std::tuple<> container_operands() {return std::tuple<>();} - std::tuple<> container_partials() {return std::tuple<>();} + std::tuple<> container_operands() { return std::tuple<>(); } + std::tuple<> container_partials() { return std::tuple<>(); } }; /** \ingroup type_trait @@ -203,8 +203,8 @@ class ops_partials_edge>> { void dump_operands(void* /* operands */) const {} // reverse mode double dx() const { return 0; } // used for fvars int size() const { return 0; } - std::tuple<> container_operands() {return std::tuple<>();} - std::tuple<> container_partials() {return std::tuple<>();} + std::tuple<> container_operands() { return std::tuple<>(); } + std::tuple<> container_partials() { return std::tuple<>(); } }; } // namespace internal } // namespace math diff --git a/stan/math/rev/core/precomputed_gradients.hpp b/stan/math/rev/core/precomputed_gradients.hpp index 98d362d4c48..fa58f964d04 100644 --- a/stan/math/rev/core/precomputed_gradients.hpp +++ b/stan/math/rev/core/precomputed_gradients.hpp @@ -172,8 +172,8 @@ using precomputed_gradients_vari * @param[in] operands operands. * @param[in] gradients vector of partial derivatives of result with * respect to operands. - * @param container_operands any container operands - * @param container_gradients any container gradients + * @param container_operands any container operands + * @param container_gradients any container gradients * @return An autodiff variable that uses the precomputed * gradients provided. */ diff --git a/stan/math/rev/core/var.hpp b/stan/math/rev/core/var.hpp index 5e57f8b9880..c971f863087 100644 --- a/stan/math/rev/core/var.hpp +++ b/stan/math/rev/core/var.hpp @@ -303,8 +303,8 @@ using var = var_value; * @tparam T type to check. * @ingroup type_trait */ -template -struct scalar_type>{ +template +struct scalar_type> { using type = math::var_value>; }; diff --git a/stan/math/rev/core/vari.hpp b/stan/math/rev/core/vari.hpp index 796888ef587..5fa9c777625 100644 --- a/stan/math/rev/core/vari.hpp +++ b/stan/math/rev/core/vari.hpp @@ -541,8 +541,8 @@ class vari_value::value>> * @tparam T type to check. * @ingroup type_trait */ -template -struct scalar_type>{ +template +struct scalar_type> { using type = math::vari_value>; }; diff --git a/test/unit/math/rev/functor/operands_and_partials_test.cpp b/test/unit/math/rev/functor/operands_and_partials_test.cpp index 1a356ab35bd..f5665b1325c 100644 --- a/test/unit/math/rev/functor/operands_and_partials_test.cpp +++ b/test/unit/math/rev/functor/operands_and_partials_test.cpp @@ -71,7 +71,7 @@ TEST(AgradPartialsVari, OperandsAndPartialsStdVec) { using stan::math::var; std::vector d_vec(4); - operands_and_partials > o3(d_vec); + operands_and_partials> o3(d_vec); EXPECT_EQ(5, sizeof(o3)); std::vector v_vec; @@ -84,7 +84,7 @@ TEST(AgradPartialsVari, OperandsAndPartialsStdVec) { v_vec.push_back(v3); v_vec.push_back(v4); - operands_and_partials > o4(v_vec); + operands_and_partials> o4(v_vec); o4.edge1_.partials_[0] += 10.0; o4.edge1_.partials_[1] += 20.0; o4.edge1_.partials_[2] += 30.0; @@ -151,7 +151,7 @@ TEST(AgradPartialsVari, OperandsAndPartialsMatMultivar) { d_mat << 10.0, 20.0, 30.0, 40.0; std::vector d_mat_vec; d_mat_vec.push_back(d_mat); - operands_and_partials > o3(d_mat_vec); + operands_and_partials> o3(d_mat_vec); EXPECT_EQ(5, sizeof(o3)); @@ -183,7 +183,7 @@ TEST(AgradPartialsVari, OperandsAndPartialsMatMultivar) { v_stdvec.push_back(v7); v_stdvec.push_back(v8); - operands_and_partials > o4(v_mat_vec); + operands_and_partials> o4(v_mat_vec); o4.edge1_.partials_vec_[0] += d_mat; // Should NOT affect the same vars as the call above o4.edge1_.partials_vec_[1] += d_mat; @@ -216,7 +216,7 @@ TEST(AgradPartialsVari, OperandsAndPartialsMultivar) { d_vec2 << 30.0, 40.0; d_vec_vec.push_back(d_vec1); d_vec_vec.push_back(d_vec2); - operands_and_partials > o3(d_vec_vec); + operands_and_partials> o3(d_vec_vec); EXPECT_EQ(5, sizeof(o3)); @@ -238,7 +238,7 @@ TEST(AgradPartialsVari, OperandsAndPartialsMultivar) { v_stdvec.push_back(v3); v_stdvec.push_back(v4); - operands_and_partials > o4(v_vec); + operands_and_partials> o4(v_vec); o4.edge1_.partials_vec_[0] += d_vec1; o4.edge1_.partials_vec_[1] += d_vec2; @@ -340,8 +340,8 @@ TEST(AgradPartialsVari, OperandsAndPartialsVarValueMat) { operands_and_partials> ops(av); - ops.edge1_.partials_ = Eigen::MatrixXd::Constant(2,2,-2); + ops.edge1_.partials_ = Eigen::MatrixXd::Constant(2, 2, -2); var lp = ops.build(1); - (2*lp).grad(); - EXPECT_MATRIX_EQ(av.adj(), Eigen::MatrixXd::Constant(2,2,-4)) + (2 * lp).grad(); + EXPECT_MATRIX_EQ(av.adj(), Eigen::MatrixXd::Constant(2, 2, -4)) } From 063b140411bac007d5ad1d4202ce3aa4cbf21167 Mon Sep 17 00:00:00 2001 From: tadej Date: Thu, 9 Jul 2020 11:18:01 +0200 Subject: [PATCH 149/355] fixed fvar circular include --- stan/math/fwd/meta/is_fvar.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stan/math/fwd/meta/is_fvar.hpp b/stan/math/fwd/meta/is_fvar.hpp index c767583db46..e208d08bc71 100644 --- a/stan/math/fwd/meta/is_fvar.hpp +++ b/stan/math/fwd/meta/is_fvar.hpp @@ -1,7 +1,7 @@ #ifndef STAN_MATH_FWD_META_IS_FVAR_HPP #define STAN_MATH_FWD_META_IS_FVAR_HPP -#include +#include #include #include From 2649505901f8861cb8a31aa2a66b445889d06749 Mon Sep 17 00:00:00 2001 From: tadej Date: Thu, 9 Jul 2020 11:32:55 +0200 Subject: [PATCH 150/355] another one --- stan/math/fwd/meta/partials_type.hpp | 1 - 1 file changed, 1 deletion(-) diff --git a/stan/math/fwd/meta/partials_type.hpp b/stan/math/fwd/meta/partials_type.hpp index 66ea6c5d32a..7d2a24cadd7 100644 --- a/stan/math/fwd/meta/partials_type.hpp +++ b/stan/math/fwd/meta/partials_type.hpp @@ -1,7 +1,6 @@ #ifndef STAN_MATH_FWD_META_PARTIALS_TYPE_HPP #define STAN_MATH_FWD_META_PARTIALS_TYPE_HPP -#include #include #include #include From fb317b7bf22dd348b6a4b824e7cdc8da7f5d24cb Mon Sep 17 00:00:00 2001 From: Steve Bronder Date: Thu, 9 Jul 2020 18:09:22 -0400 Subject: [PATCH 151/355] move around fvar Eigen_Numtraits --- stan/math/fwd/core/Eigen_NumTraits.hpp | 1 - stan/math/fwd/meta/is_fvar.hpp | 5 ++++- stan/math/fwd/meta/partials_type.hpp | 5 ++++- 3 files changed, 8 insertions(+), 3 deletions(-) diff --git a/stan/math/fwd/core/Eigen_NumTraits.hpp b/stan/math/fwd/core/Eigen_NumTraits.hpp index 9bc6f09275e..12d4d04b72e 100644 --- a/stan/math/fwd/core/Eigen_NumTraits.hpp +++ b/stan/math/fwd/core/Eigen_NumTraits.hpp @@ -2,7 +2,6 @@ #define STAN_MATH_FWD_FUN_EIGEN_NUMTRAITS_HPP #include -#include #include #include #include diff --git a/stan/math/fwd/meta/is_fvar.hpp b/stan/math/fwd/meta/is_fvar.hpp index c767583db46..6e62d94227e 100644 --- a/stan/math/fwd/meta/is_fvar.hpp +++ b/stan/math/fwd/meta/is_fvar.hpp @@ -1,12 +1,15 @@ #ifndef STAN_MATH_FWD_META_IS_FVAR_HPP #define STAN_MATH_FWD_META_IS_FVAR_HPP -#include #include #include namespace stan { +namespace math { + template + struct fvar; +} namespace internal { template struct is_fvar_impl : std::false_type {}; diff --git a/stan/math/fwd/meta/partials_type.hpp b/stan/math/fwd/meta/partials_type.hpp index 66ea6c5d32a..96fb08921e5 100644 --- a/stan/math/fwd/meta/partials_type.hpp +++ b/stan/math/fwd/meta/partials_type.hpp @@ -1,12 +1,15 @@ #ifndef STAN_MATH_FWD_META_PARTIALS_TYPE_HPP #define STAN_MATH_FWD_META_PARTIALS_TYPE_HPP -#include #include #include #include namespace stan { +namespace math { + template + struct fvar; +} template struct partials_type> { From eeeb4ee80603957e5c80f8a8e8b51aec97ed9f8c Mon Sep 17 00:00:00 2001 From: Stan Jenkins Date: Thu, 9 Jul 2020 18:10:11 -0400 Subject: [PATCH 152/355] [Jenkins] auto-formatting by clang-format version 6.0.0-1ubuntu2 (tags/RELEASE_600/final) --- stan/math/fwd/meta/is_fvar.hpp | 4 ++-- stan/math/fwd/meta/partials_type.hpp | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/stan/math/fwd/meta/is_fvar.hpp b/stan/math/fwd/meta/is_fvar.hpp index 6e62d94227e..e2f4e51e088 100644 --- a/stan/math/fwd/meta/is_fvar.hpp +++ b/stan/math/fwd/meta/is_fvar.hpp @@ -7,8 +7,8 @@ namespace stan { namespace math { - template - struct fvar; +template +struct fvar; } namespace internal { template diff --git a/stan/math/fwd/meta/partials_type.hpp b/stan/math/fwd/meta/partials_type.hpp index 96fb08921e5..4d80c547f57 100644 --- a/stan/math/fwd/meta/partials_type.hpp +++ b/stan/math/fwd/meta/partials_type.hpp @@ -7,8 +7,8 @@ namespace stan { namespace math { - template - struct fvar; +template +struct fvar; } template From 36fc9039505741a4b14696570440dcb25244ede9 Mon Sep 17 00:00:00 2001 From: tadej Date: Fri, 10 Jul 2020 09:05:37 +0200 Subject: [PATCH 153/355] added require to constructor --- stan/math/rev/core/precomputed_gradients.hpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/stan/math/rev/core/precomputed_gradients.hpp b/stan/math/rev/core/precomputed_gradients.hpp index fa58f964d04..7bd99156d05 100644 --- a/stan/math/rev/core/precomputed_gradients.hpp +++ b/stan/math/rev/core/precomputed_gradients.hpp @@ -113,7 +113,8 @@ class precomputed_gradients_vari_template : public vari { * don't match. */ template , typename CGrads = std::tuple<>> + typename COps = std::tuple<>, typename CGrads = std::tuple<>, + require_all_vector_t* = nullptr> precomputed_gradients_vari_template(Arith val, const VecVar& vars, const VecArith& gradients, COps&& container_operands From 58ca7e234373b0b0223f58001c2254e01d526790 Mon Sep 17 00:00:00 2001 From: Steve Bronder Date: Mon, 13 Jul 2020 10:58:47 -0400 Subject: [PATCH 154/355] Revert "[Jenkins] auto-formatting by clang-format version 6.0.0-1ubuntu2 (tags/RELEASE_600/final)" This reverts commit eeeb4ee80603957e5c80f8a8e8b51aec97ed9f8c. --- stan/math/fwd/meta/is_fvar.hpp | 4 ++-- stan/math/fwd/meta/partials_type.hpp | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/stan/math/fwd/meta/is_fvar.hpp b/stan/math/fwd/meta/is_fvar.hpp index e2f4e51e088..6e62d94227e 100644 --- a/stan/math/fwd/meta/is_fvar.hpp +++ b/stan/math/fwd/meta/is_fvar.hpp @@ -7,8 +7,8 @@ namespace stan { namespace math { -template -struct fvar; + template + struct fvar; } namespace internal { template diff --git a/stan/math/fwd/meta/partials_type.hpp b/stan/math/fwd/meta/partials_type.hpp index 4d80c547f57..96fb08921e5 100644 --- a/stan/math/fwd/meta/partials_type.hpp +++ b/stan/math/fwd/meta/partials_type.hpp @@ -7,8 +7,8 @@ namespace stan { namespace math { -template -struct fvar; + template + struct fvar; } template From 60f54abaf2cb8405a74f01ae12dabea47e0e54cc Mon Sep 17 00:00:00 2001 From: Steve Bronder Date: Mon, 13 Jul 2020 10:58:49 -0400 Subject: [PATCH 155/355] Revert "move around fvar Eigen_Numtraits" This reverts commit fb317b7bf22dd348b6a4b824e7cdc8da7f5d24cb. --- stan/math/fwd/core/Eigen_NumTraits.hpp | 1 + stan/math/fwd/meta/is_fvar.hpp | 5 +---- stan/math/fwd/meta/partials_type.hpp | 5 +---- 3 files changed, 3 insertions(+), 8 deletions(-) diff --git a/stan/math/fwd/core/Eigen_NumTraits.hpp b/stan/math/fwd/core/Eigen_NumTraits.hpp index 12d4d04b72e..9bc6f09275e 100644 --- a/stan/math/fwd/core/Eigen_NumTraits.hpp +++ b/stan/math/fwd/core/Eigen_NumTraits.hpp @@ -2,6 +2,7 @@ #define STAN_MATH_FWD_FUN_EIGEN_NUMTRAITS_HPP #include +#include #include #include #include diff --git a/stan/math/fwd/meta/is_fvar.hpp b/stan/math/fwd/meta/is_fvar.hpp index 6e62d94227e..c767583db46 100644 --- a/stan/math/fwd/meta/is_fvar.hpp +++ b/stan/math/fwd/meta/is_fvar.hpp @@ -1,15 +1,12 @@ #ifndef STAN_MATH_FWD_META_IS_FVAR_HPP #define STAN_MATH_FWD_META_IS_FVAR_HPP +#include #include #include namespace stan { -namespace math { - template - struct fvar; -} namespace internal { template struct is_fvar_impl : std::false_type {}; diff --git a/stan/math/fwd/meta/partials_type.hpp b/stan/math/fwd/meta/partials_type.hpp index 96fb08921e5..66ea6c5d32a 100644 --- a/stan/math/fwd/meta/partials_type.hpp +++ b/stan/math/fwd/meta/partials_type.hpp @@ -1,15 +1,12 @@ #ifndef STAN_MATH_FWD_META_PARTIALS_TYPE_HPP #define STAN_MATH_FWD_META_PARTIALS_TYPE_HPP +#include #include #include #include namespace stan { -namespace math { - template - struct fvar; -} template struct partials_type> { From d7bd3f582cd14bde58ebf658d66bb16191e54e4f Mon Sep 17 00:00:00 2001 From: Steve Bronder Date: Mon, 13 Jul 2020 10:58:50 -0400 Subject: [PATCH 156/355] Revert "move Eigen Numtraits and typedefs to core for fwd and rev" This reverts commit 826d1d545eae2ec53a456bb110f599a5119b18ab. --- stan/math/fwd/core.hpp | 3 --- stan/math/fwd/core/std_iterator_traits.hpp | 2 +- stan/math/fwd/fun.hpp | 4 +++- stan/math/fwd/{core => fun}/Eigen_NumTraits.hpp | 4 ++-- stan/math/fwd/fun/mdivide_left_tri_low.hpp | 3 ++- stan/math/fwd/fun/multiply.hpp | 3 ++- stan/math/fwd/{core => fun}/read_fvar.hpp | 0 stan/math/fwd/{core => fun}/typedefs.hpp | 8 ++++---- stan/math/mix/fun/typedefs.hpp | 6 +++--- stan/math/rev/core.hpp | 1 - test/unit/math/rev/{core => fun}/read_var_test.cpp | 0 test/unit/math/rev/meta/VectorBuilderHelper_test.cpp | 2 +- test/unit/math/rev/meta/VectorBuilder_test.cpp | 2 +- test/unit/math/rev/meta/ad_promotable_test.cpp | 2 +- test/unit/math/rev/meta/child_type_test.cpp | 2 +- test/unit/math/rev/meta/include_summand_test.cpp | 2 +- test/unit/math/rev/meta/is_constant_all_test.cpp | 3 +-- test/unit/math/rev/meta/partials_return_type_test.cpp | 2 +- test/unit/math/rev/meta/partials_type_test.cpp | 2 +- test/unit/math/rev/meta/require_generics_test.cpp | 3 ++- 20 files changed, 27 insertions(+), 27 deletions(-) rename stan/math/fwd/{core => fun}/Eigen_NumTraits.hpp (98%) rename stan/math/fwd/{core => fun}/read_fvar.hpp (100%) rename stan/math/fwd/{core => fun}/typedefs.hpp (79%) rename test/unit/math/rev/{core => fun}/read_var_test.cpp (100%) diff --git a/stan/math/fwd/core.hpp b/stan/math/fwd/core.hpp index 9ae0d7ac1fe..543a8206bf4 100644 --- a/stan/math/fwd/core.hpp +++ b/stan/math/fwd/core.hpp @@ -2,7 +2,6 @@ #define STAN_MATH_FWD_CORE_HPP #include -#include #include #include #include @@ -18,10 +17,8 @@ #include #include #include -#include #include #include #include -#include #endif diff --git a/stan/math/fwd/core/std_iterator_traits.hpp b/stan/math/fwd/core/std_iterator_traits.hpp index e3220e81108..0caffd3e034 100644 --- a/stan/math/fwd/core/std_iterator_traits.hpp +++ b/stan/math/fwd/core/std_iterator_traits.hpp @@ -1,8 +1,8 @@ #ifndef STAN_MATH_FWD_CORE_STD_ITERATOR_TRAITS_HPP #define STAN_MATH_FWD_CORE_STD_ITERATOR_TRAITS_HPP -#include #include +#include #include namespace std { diff --git a/stan/math/fwd/fun.hpp b/stan/math/fwd/fun.hpp index 91aafac3272..e10e9da72f1 100644 --- a/stan/math/fwd/fun.hpp +++ b/stan/math/fwd/fun.hpp @@ -2,7 +2,7 @@ #define STAN_MATH_FWD_FUN_HPP #include -#include +#include #include #include @@ -94,6 +94,7 @@ #include #include #include +#include #include #include #include @@ -110,6 +111,7 @@ #include #include #include +#include #include #include #include diff --git a/stan/math/fwd/core/Eigen_NumTraits.hpp b/stan/math/fwd/fun/Eigen_NumTraits.hpp similarity index 98% rename from stan/math/fwd/core/Eigen_NumTraits.hpp rename to stan/math/fwd/fun/Eigen_NumTraits.hpp index 9bc6f09275e..8612324d68a 100644 --- a/stan/math/fwd/core/Eigen_NumTraits.hpp +++ b/stan/math/fwd/fun/Eigen_NumTraits.hpp @@ -3,8 +3,8 @@ #include #include -#include -#include +#include +#include #include #include diff --git a/stan/math/fwd/fun/mdivide_left_tri_low.hpp b/stan/math/fwd/fun/mdivide_left_tri_low.hpp index a172d19818c..c2c19d8ee67 100644 --- a/stan/math/fwd/fun/mdivide_left_tri_low.hpp +++ b/stan/math/fwd/fun/mdivide_left_tri_low.hpp @@ -4,9 +4,10 @@ #include #include #include -#include +#include #include #include +#include namespace stan { namespace math { diff --git a/stan/math/fwd/fun/multiply.hpp b/stan/math/fwd/fun/multiply.hpp index 71bda19187b..ebb03db7b07 100644 --- a/stan/math/fwd/fun/multiply.hpp +++ b/stan/math/fwd/fun/multiply.hpp @@ -1,11 +1,12 @@ #ifndef STAN_MATH_FWD_FUN_MULTIPLY_HPP #define STAN_MATH_FWD_FUN_MULTIPLY_HPP -#include #include #include +#include #include #include +#include namespace stan { namespace math { diff --git a/stan/math/fwd/core/read_fvar.hpp b/stan/math/fwd/fun/read_fvar.hpp similarity index 100% rename from stan/math/fwd/core/read_fvar.hpp rename to stan/math/fwd/fun/read_fvar.hpp diff --git a/stan/math/fwd/core/typedefs.hpp b/stan/math/fwd/fun/typedefs.hpp similarity index 79% rename from stan/math/fwd/core/typedefs.hpp rename to stan/math/fwd/fun/typedefs.hpp index 8e5ebd27320..bd8ab2d84e4 100644 --- a/stan/math/fwd/core/typedefs.hpp +++ b/stan/math/fwd/fun/typedefs.hpp @@ -1,9 +1,9 @@ -#ifndef STAN_MATH_FWD_CORE_TYPEDEFS_HPP -#define STAN_MATH_FWD_CORE_TYPEDEFS_HPP +#ifndef STAN_MATH_FWD_FUN_TYPEDEFS_HPP +#define STAN_MATH_FWD_FUN_TYPEDEFS_HPP #include -#include -#include +#include +#include namespace stan { namespace math { diff --git a/stan/math/mix/fun/typedefs.hpp b/stan/math/mix/fun/typedefs.hpp index 88370cfb82f..ddf7ea5d793 100644 --- a/stan/math/mix/fun/typedefs.hpp +++ b/stan/math/mix/fun/typedefs.hpp @@ -1,10 +1,10 @@ -#ifndef STAN_MATH_MIX_MAT_CORE_TYPEDEFS_HPP -#define STAN_MATH_MIX_MAT_CORE_TYPEDEFS_HPP +#ifndef STAN_MATH_MIX_MAT_FUN_TYPEDEFS_HPP +#define STAN_MATH_MIX_MAT_FUN_TYPEDEFS_HPP #include #include -#include #include +#include namespace stan { namespace math { diff --git a/stan/math/rev/core.hpp b/stan/math/rev/core.hpp index 36f0b4f2349..88ca7b2f2c5 100644 --- a/stan/math/rev/core.hpp +++ b/stan/math/rev/core.hpp @@ -2,7 +2,6 @@ #define STAN_MATH_REV_CORE_HPP #include -#include #include #include diff --git a/test/unit/math/rev/core/read_var_test.cpp b/test/unit/math/rev/fun/read_var_test.cpp similarity index 100% rename from test/unit/math/rev/core/read_var_test.cpp rename to test/unit/math/rev/fun/read_var_test.cpp diff --git a/test/unit/math/rev/meta/VectorBuilderHelper_test.cpp b/test/unit/math/rev/meta/VectorBuilderHelper_test.cpp index 46fa4649963..70d8c464102 100644 --- a/test/unit/math/rev/meta/VectorBuilderHelper_test.cpp +++ b/test/unit/math/rev/meta/VectorBuilderHelper_test.cpp @@ -1,4 +1,4 @@ -#include +#include #include #include diff --git a/test/unit/math/rev/meta/VectorBuilder_test.cpp b/test/unit/math/rev/meta/VectorBuilder_test.cpp index c7c470d815c..557c21b1de6 100644 --- a/test/unit/math/rev/meta/VectorBuilder_test.cpp +++ b/test/unit/math/rev/meta/VectorBuilder_test.cpp @@ -1,4 +1,4 @@ -#include +#include #include #include diff --git a/test/unit/math/rev/meta/ad_promotable_test.cpp b/test/unit/math/rev/meta/ad_promotable_test.cpp index 4ffcddb7222..3f21820fe1b 100644 --- a/test/unit/math/rev/meta/ad_promotable_test.cpp +++ b/test/unit/math/rev/meta/ad_promotable_test.cpp @@ -1,4 +1,4 @@ -#include +#include #include #include diff --git a/test/unit/math/rev/meta/child_type_test.cpp b/test/unit/math/rev/meta/child_type_test.cpp index afb585c4386..8e6112fc0ba 100644 --- a/test/unit/math/rev/meta/child_type_test.cpp +++ b/test/unit/math/rev/meta/child_type_test.cpp @@ -1,4 +1,4 @@ -#include +#include #include #include diff --git a/test/unit/math/rev/meta/include_summand_test.cpp b/test/unit/math/rev/meta/include_summand_test.cpp index 0d9dba66322..69ba28a7081 100644 --- a/test/unit/math/rev/meta/include_summand_test.cpp +++ b/test/unit/math/rev/meta/include_summand_test.cpp @@ -1,4 +1,4 @@ -#include +#include #include #include #include diff --git a/test/unit/math/rev/meta/is_constant_all_test.cpp b/test/unit/math/rev/meta/is_constant_all_test.cpp index ef703907916..771eea6d8c9 100644 --- a/test/unit/math/rev/meta/is_constant_all_test.cpp +++ b/test/unit/math/rev/meta/is_constant_all_test.cpp @@ -1,5 +1,4 @@ -#include -#include +#include #include #include diff --git a/test/unit/math/rev/meta/partials_return_type_test.cpp b/test/unit/math/rev/meta/partials_return_type_test.cpp index 43e265137fb..8eed06a2e8f 100644 --- a/test/unit/math/rev/meta/partials_return_type_test.cpp +++ b/test/unit/math/rev/meta/partials_return_type_test.cpp @@ -1,4 +1,4 @@ -#include +#include #include #include #include diff --git a/test/unit/math/rev/meta/partials_type_test.cpp b/test/unit/math/rev/meta/partials_type_test.cpp index aaeb2a7e81f..d3187a0ec47 100644 --- a/test/unit/math/rev/meta/partials_type_test.cpp +++ b/test/unit/math/rev/meta/partials_type_test.cpp @@ -1,4 +1,4 @@ -#include +#include #include TEST(MetaTraitsRevScal, partials_type) { diff --git a/test/unit/math/rev/meta/require_generics_test.cpp b/test/unit/math/rev/meta/require_generics_test.cpp index c4304af0abc..ee93fe9b5a7 100644 --- a/test/unit/math/rev/meta/require_generics_test.cpp +++ b/test/unit/math/rev/meta/require_generics_test.cpp @@ -1,6 +1,7 @@ +#include // just this is bad #include -#include +#include #include #include #include From 370c55ba179dce87a3508fe227e159e90c921ac1 Mon Sep 17 00:00:00 2001 From: Steve Bronder Date: Mon, 13 Jul 2020 10:58:51 -0400 Subject: [PATCH 157/355] Revert "[Jenkins] auto-formatting by clang-format version 6.0.0-1ubuntu2 (tags/RELEASE_600/final)" This reverts commit 9660a5a18f620b1249f2478f4e8a4358011b8b83. --- stan/math/rev/meta/is_var.hpp | 4 ++-- stan/math/rev/meta/is_vari.hpp | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/stan/math/rev/meta/is_var.hpp b/stan/math/rev/meta/is_var.hpp index f0f3855bc7f..5bb004524bb 100644 --- a/stan/math/rev/meta/is_var.hpp +++ b/stan/math/rev/meta/is_var.hpp @@ -7,8 +7,8 @@ namespace stan { namespace math { -template -class var_value; + template + class var_value; } namespace internal { template diff --git a/stan/math/rev/meta/is_vari.hpp b/stan/math/rev/meta/is_vari.hpp index db786456202..4e7ddcc8315 100644 --- a/stan/math/rev/meta/is_vari.hpp +++ b/stan/math/rev/meta/is_vari.hpp @@ -7,8 +7,8 @@ namespace stan { namespace math { -template -class vari_value; + template + class vari_value; } namespace internal { template From 0f12bbf67d02c873932e2861b2fd9e8faac0ff61 Mon Sep 17 00:00:00 2001 From: Steve Bronder Date: Mon, 13 Jul 2020 10:58:51 -0400 Subject: [PATCH 158/355] Revert "move Eigen numtraits and read_var to core to help with include order errors" This reverts commit c8fd050d022743c54739f95dbad2a254991fac76. --- stan/math/rev/core.hpp | 3 --- stan/math/rev/core/gevv_vvv_vari.hpp | 4 ++-- stan/math/rev/core/matrix_vari.hpp | 2 +- stan/math/rev/core/var.hpp | 4 +++- stan/math/rev/core/vari.hpp | 4 +++- stan/math/rev/fun.hpp | 4 +++- stan/math/rev/{core => fun}/Eigen_NumTraits.hpp | 6 +++--- stan/math/rev/fun/grad.hpp | 2 +- stan/math/rev/{core => fun}/read_var.hpp | 0 stan/math/rev/fun/tcrossprod.hpp | 2 +- stan/math/rev/meta/is_var.hpp | 5 +---- stan/math/rev/meta/is_vari.hpp | 5 +---- stan/math/rev/meta/partials_type.hpp | 2 +- 13 files changed, 20 insertions(+), 23 deletions(-) rename stan/math/rev/{core => fun}/Eigen_NumTraits.hpp (99%) rename stan/math/rev/{core => fun}/read_var.hpp (100%) diff --git a/stan/math/rev/core.hpp b/stan/math/rev/core.hpp index 88ca7b2f2c5..33eb934c08e 100644 --- a/stan/math/rev/core.hpp +++ b/stan/math/rev/core.hpp @@ -1,8 +1,6 @@ #ifndef STAN_MATH_REV_CORE_HPP #define STAN_MATH_REV_CORE_HPP -#include - #include #include #include @@ -50,7 +48,6 @@ #include #include #include -#include #include #include #include diff --git a/stan/math/rev/core/gevv_vvv_vari.hpp b/stan/math/rev/core/gevv_vvv_vari.hpp index 5fad3458a01..0505788ad3d 100644 --- a/stan/math/rev/core/gevv_vvv_vari.hpp +++ b/stan/math/rev/core/gevv_vvv_vari.hpp @@ -1,9 +1,9 @@ #ifndef STAN_MATH_REV_CORE_GEVV_VVV_VARI_HPP #define STAN_MATH_REV_CORE_GEVV_VVV_VARI_HPP -#include -#include #include +#include +#include namespace stan { namespace math { diff --git a/stan/math/rev/core/matrix_vari.hpp b/stan/math/rev/core/matrix_vari.hpp index 09c2cc93128..3aca20ff174 100644 --- a/stan/math/rev/core/matrix_vari.hpp +++ b/stan/math/rev/core/matrix_vari.hpp @@ -1,7 +1,7 @@ #ifndef STAN_MATH_REV_CORE_MATRIX_VARI_HPP #define STAN_MATH_REV_CORE_MATRIX_VARI_HPP -#include +#include #include #include #include diff --git a/stan/math/rev/core/var.hpp b/stan/math/rev/core/var.hpp index 98660c12519..9fb4aeee2db 100644 --- a/stan/math/rev/core/var.hpp +++ b/stan/math/rev/core/var.hpp @@ -1,9 +1,11 @@ #ifndef STAN_MATH_REV_CORE_VAR_HPP #define STAN_MATH_REV_CORE_VAR_HPP -#include #include +#include #include +#include +#include #include #include diff --git a/stan/math/rev/core/vari.hpp b/stan/math/rev/core/vari.hpp index 0af28d897e4..fe253f8293a 100644 --- a/stan/math/rev/core/vari.hpp +++ b/stan/math/rev/core/vari.hpp @@ -1,9 +1,9 @@ #ifndef STAN_MATH_REV_CORE_VARI_HPP #define STAN_MATH_REV_CORE_VARI_HPP -#include #include #include +#include #include #include @@ -33,6 +33,8 @@ class vari_base { virtual ~vari_base() noexcept {} }; +template +class vari_value; /** * The variable implementation for floating point types. * diff --git a/stan/math/rev/fun.hpp b/stan/math/rev/fun.hpp index 8b5b8620b9f..7aeaa486f67 100644 --- a/stan/math/rev/fun.hpp +++ b/stan/math/rev/fun.hpp @@ -2,7 +2,8 @@ #define STAN_MATH_REV_FUN_HPP #include -#include +#include + #include #include @@ -117,6 +118,7 @@ #include #include #include +#include #include #include #include diff --git a/stan/math/rev/core/Eigen_NumTraits.hpp b/stan/math/rev/fun/Eigen_NumTraits.hpp similarity index 99% rename from stan/math/rev/core/Eigen_NumTraits.hpp rename to stan/math/rev/fun/Eigen_NumTraits.hpp index 68cd6ef1442..1e6b3140427 100644 --- a/stan/math/rev/core/Eigen_NumTraits.hpp +++ b/stan/math/rev/fun/Eigen_NumTraits.hpp @@ -2,10 +2,10 @@ #define STAN_MATH_REV_FUN_EIGEN_NUMTRAITS_HPP #include +#include +#include #include -#include -#include -#include +#include #include #include diff --git a/stan/math/rev/fun/grad.hpp b/stan/math/rev/fun/grad.hpp index 31853a673f2..099e641337a 100644 --- a/stan/math/rev/fun/grad.hpp +++ b/stan/math/rev/fun/grad.hpp @@ -2,7 +2,7 @@ #define STAN_MATH_REV_FUN_GRAD_HPP #include -#include +#include #include #include diff --git a/stan/math/rev/core/read_var.hpp b/stan/math/rev/fun/read_var.hpp similarity index 100% rename from stan/math/rev/core/read_var.hpp rename to stan/math/rev/fun/read_var.hpp diff --git a/stan/math/rev/fun/tcrossprod.hpp b/stan/math/rev/fun/tcrossprod.hpp index 08961cabe73..02b57159a9f 100644 --- a/stan/math/rev/fun/tcrossprod.hpp +++ b/stan/math/rev/fun/tcrossprod.hpp @@ -3,7 +3,7 @@ #include #include -#include +#include #include #include #include diff --git a/stan/math/rev/meta/is_var.hpp b/stan/math/rev/meta/is_var.hpp index 5bb004524bb..e4d9fa54fed 100644 --- a/stan/math/rev/meta/is_var.hpp +++ b/stan/math/rev/meta/is_var.hpp @@ -1,15 +1,12 @@ #ifndef STAN_MATH_REV_META_IS_VAR_HPP #define STAN_MATH_REV_META_IS_VAR_HPP +#include #include #include namespace stan { -namespace math { - template - class var_value; -} namespace internal { template struct is_var_impl : std::false_type {}; diff --git a/stan/math/rev/meta/is_vari.hpp b/stan/math/rev/meta/is_vari.hpp index 4e7ddcc8315..39fb79cb767 100644 --- a/stan/math/rev/meta/is_vari.hpp +++ b/stan/math/rev/meta/is_vari.hpp @@ -1,15 +1,12 @@ #ifndef STAN_MATH_REV_META_IS_VARI_HPP #define STAN_MATH_REV_META_IS_VARI_HPP +#include #include #include namespace stan { -namespace math { - template - class vari_value; -} namespace internal { template struct is_vari_impl : std::false_type {}; diff --git a/stan/math/rev/meta/partials_type.hpp b/stan/math/rev/meta/partials_type.hpp index 1975c331ef1..823117fe062 100644 --- a/stan/math/rev/meta/partials_type.hpp +++ b/stan/math/rev/meta/partials_type.hpp @@ -1,9 +1,9 @@ #ifndef STAN_MATH_REV_META_PARTIALS_TYPE_HPP #define STAN_MATH_REV_META_PARTIALS_TYPE_HPP +#include #include #include -#include #include namespace stan { From b252e964584e179044e0761e477cdf47af4a508e Mon Sep 17 00:00:00 2001 From: tadej Date: Tue, 14 Jul 2020 07:48:46 +0200 Subject: [PATCH 159/355] addressed review comments --- stan/math/rev/core/precomputed_gradients.hpp | 37 ++++++++++---------- 1 file changed, 18 insertions(+), 19 deletions(-) diff --git a/stan/math/rev/core/precomputed_gradients.hpp b/stan/math/rev/core/precomputed_gradients.hpp index 7bd99156d05..6f76cfbb989 100644 --- a/stan/math/rev/core/precomputed_gradients.hpp +++ b/stan/math/rev/core/precomputed_gradients.hpp @@ -3,7 +3,6 @@ #include #include -// #include #include #include #include @@ -66,9 +65,9 @@ class precomputed_gradients_vari_template : public vari { * operands, gradients and optionally container operands and containers of * gradients. * - * @tparam COps tuple of any container operands (var_value + * @tparam ContainerOps tuple of any container operands (var_value * containing Eigen types) - * @tparam CGrads tupleof any container gradients (Eigen types) + * @tparam ContainerGrads tupleof any container gradients (Eigen types) * @param[in] val The value of the variable. * @param[in] size Size of operands and gradients * @param[in] varis Operand implementations. @@ -76,19 +75,19 @@ class precomputed_gradients_vari_template : public vari { * @param container_operands any container operands * @param container_gradients any container gradients */ - template , typename CGrads = std::tuple<>> + template , typename ContainerGrads = std::tuple<>> precomputed_gradients_vari_template(double val, size_t size, vari** varis, double* gradients, - COps&& container_operands + ContainerOps&& container_operands = std::tuple<>(), - CGrads&& container_gradients + ContainerGrads&& container_gradients = std::tuple<>()) : vari(val), size_(size), varis_(varis), gradients_(gradients), - container_operands_(std::forward(container_operands)), - container_gradients_(std::forward(container_gradients)) { + container_operands_(std::forward(container_operands)), + container_gradients_(std::forward(container_gradients)) { check_sizes(std::make_index_sequence()); } @@ -100,9 +99,9 @@ class precomputed_gradients_vari_template : public vari { * @tparam Arith An arithmetic type * @tparam VecVar A vector of vars * @tparam VecArith A vector of arithmetic types - * @tparam COps tuple of any container operands (var_value + * @tparam ContainerOps tuple of any container operands (var_value * containing Eigen types) - * @tparam CGrads tupleof any container gradients (Eigen types) + * @tparam ContainerGrads tupleof any container gradients (Eigen types) * @param[in] val The value of the variable. * @param[in] vars Vector of operands. * @param[in] gradients Vector of partial derivatives of value @@ -113,13 +112,13 @@ class precomputed_gradients_vari_template : public vari { * don't match. */ template , typename CGrads = std::tuple<>, + typename ContainerOps = std::tuple<>, typename ContainerGrads = std::tuple<>, require_all_vector_t* = nullptr> precomputed_gradients_vari_template(Arith val, const VecVar& vars, const VecArith& gradients, - COps&& container_operands + ContainerOps&& container_operands = std::tuple<>(), - CGrads&& container_gradients + ContainerGrads&& container_gradients = std::tuple<>()) : vari(val), size_(vars.size()), @@ -127,8 +126,8 @@ class precomputed_gradients_vari_template : public vari { vars.size())), gradients_(ChainableStack::instance_->memalloc_.alloc_array( vars.size())), - container_operands_(std::forward(container_operands)), - container_gradients_(std::forward(container_gradients)) { + container_operands_(std::forward(container_operands)), + container_gradients_(std::forward(container_gradients)) { check_consistent_sizes("precomputed_gradients_vari", "vars", vars, "gradients", gradients); check_sizes(std::make_index_sequence()); @@ -180,19 +179,19 @@ using precomputed_gradients_vari */ template , - typename ContainerGradinets = std::tuple<>> + typename ContainerGradients = std::tuple<>> inline var precomputed_gradients(Arith value, const VecVar& operands, const VecArith& gradients, ContainerOperands&& container_operands = std::tuple<>(), - ContainerGradinets&& container_gradients + ContainerGradients&& container_gradients = std::tuple<>()) { return { new precomputed_gradients_vari_template, - std::decay_t>( + std::decay_t>( value, operands, gradients, std::forward(container_operands), - std::forward(container_gradients))}; + std::forward(container_gradients))}; } } // namespace math From 7b7cc3b42c4bb691868fd8712f51808181b1773d Mon Sep 17 00:00:00 2001 From: tadej Date: Tue, 14 Jul 2020 09:09:27 +0200 Subject: [PATCH 160/355] added edge for std::vector of var_values --- stan/math/prim/err/check_matching_dims.hpp | 26 +-------- stan/math/rev/core/precomputed_gradients.hpp | 58 ++++++++++++++----- stan/math/rev/fun.hpp | 1 + stan/math/rev/fun/dims.hpp | 24 ++++++++ .../rev/functor/operands_and_partials.hpp | 29 ++++++++++ .../rev/core/precomputed_gradients_test.cpp | 36 ++++++++---- .../functor/operands_and_partials_test.cpp | 20 +++++++ 7 files changed, 143 insertions(+), 51 deletions(-) create mode 100644 stan/math/rev/fun/dims.hpp diff --git a/stan/math/prim/err/check_matching_dims.hpp b/stan/math/prim/err/check_matching_dims.hpp index cebf42fac60..d4c64f4e49b 100644 --- a/stan/math/prim/err/check_matching_dims.hpp +++ b/stan/math/prim/err/check_matching_dims.hpp @@ -11,30 +11,6 @@ namespace stan { namespace math { -/** - * Check if the two matrices are of the same size. - * This function checks the runtime sizes only. - * @tparam Mat1 type of the first matrix - * @tparam Mat2 type of the second matrix - * @param function name of function (for error messages) - * @param name1 variable name for the first matrix (for error messages) - * @param y1 first matrix to test - * @param name2 variable name for the second matrix (for error messages) - * @param y2 second matrix to test - * @throw std::invalid_argument if the dimensions of the - * matrices do not match - */ -template > -inline void check_matching_dims(const char* function, const char* name1, - const Mat1& y1, const char* name2, - const Mat2& y2) { - check_size_match(function, "Rows of ", name1, y1.rows(), "rows of ", name2, - y2.rows()); - check_size_match(function, "Columns of ", name1, y1.cols(), "columns of ", - name2, y2.cols()); -} - /** * Check if the two matrices are of the same size. * This function checks the runtime sizes and can also check the static @@ -82,7 +58,7 @@ inline void check_matching_dims(const char* function, const char* name1, * @throw std::invalid_argument if the dimensions of the * containers do not match */ -template * = nullptr> +template inline void check_matching_dims(const char* function, const char* name1, const T1& y1, const char* name2, const T2& y2) { std::vector y1_d = dims(y1); diff --git a/stan/math/rev/core/precomputed_gradients.hpp b/stan/math/rev/core/precomputed_gradients.hpp index 6f76cfbb989..238939b184f 100644 --- a/stan/math/rev/core/precomputed_gradients.hpp +++ b/stan/math/rev/core/precomputed_gradients.hpp @@ -1,8 +1,7 @@ #ifndef STAN_MATH_REV_CORE_PRECOMPUTED_GRADIENTS_HPP #define STAN_MATH_REV_CORE_PRECOMPUTED_GRADIENTS_HPP -#include -#include +#include #include #include #include @@ -48,14 +47,9 @@ class precomputed_gradients_vari_template : public vari { template void check_sizes(std::index_sequence) { static_cast(std::initializer_list{ - (check_size_match("precomputed_gradients_vari", "rows of operands", - std::get(container_operands_).vi_->rows(), - "rows of gradients", - std::get(container_gradients_).rows()), - check_size_match("precomputed_gradients_vari", "cols of operands", - std::get(container_operands_).vi_->cols(), - "cols of gradients", - std::get(container_gradients_).cols()), + (check_matching_dims("precomputed_gradients_vari", "operands", + std::get(container_operands_), "gradients", + std::get(container_gradients_)), 0)...}); } @@ -75,7 +69,8 @@ class precomputed_gradients_vari_template : public vari { * @param container_operands any container operands * @param container_gradients any container gradients */ - template , typename ContainerGrads = std::tuple<>> + template , + typename ContainerGrads = std::tuple<>> precomputed_gradients_vari_template(double val, size_t size, vari** varis, double* gradients, ContainerOps&& container_operands @@ -87,7 +82,8 @@ class precomputed_gradients_vari_template : public vari { varis_(varis), gradients_(gradients), container_operands_(std::forward(container_operands)), - container_gradients_(std::forward(container_gradients)) { + container_gradients_( + std::forward(container_gradients)) { check_sizes(std::make_index_sequence()); } @@ -112,7 +108,8 @@ class precomputed_gradients_vari_template : public vari { * don't match. */ template , typename ContainerGrads = std::tuple<>, + typename ContainerOps = std::tuple<>, + typename ContainerGrads = std::tuple<>, require_all_vector_t* = nullptr> precomputed_gradients_vari_template(Arith val, const VecVar& vars, const VecArith& gradients, @@ -127,7 +124,8 @@ class precomputed_gradients_vari_template : public vari { gradients_(ChainableStack::instance_->memalloc_.alloc_array( vars.size())), container_operands_(std::forward(container_operands)), - container_gradients_(std::forward(container_gradients)) { + container_gradients_( + std::forward(container_gradients)) { check_consistent_sizes("precomputed_gradients_vari", "vars", vars, "gradients", gradients); check_sizes(std::make_index_sequence()); @@ -147,11 +145,39 @@ class precomputed_gradients_vari_template : public vari { } index_apply([this](auto... Is) { static_cast(std::initializer_list{ - (std::get(this->container_operands_).adj() - += this->adj_ * std::get(this->container_gradients_), + (chain_one(std::get(this->container_operands_), + std::get(this->container_gradients_)), 0)...}); }); } + + private: + /** + * Implements the chain rule for one non-`std::vector` operand. + * @tparam Op type of the operand + * @tparam Grad type of the gradient + * @param op operand + * @param grad gradient + */ + template * = nullptr> + void chain_one(Op& op, const Grad& grad) { + op.adj() += this->adj_ * grad; + } + + /** + * Implements the chain rule for one `std::vector` operand. + * @tparam Op type of the operand element + * @tparam Grad type of the gradient element + * @param op operand + * @param grad gradient + */ + template + void chain_one(std::vector& op, const std::vector& grad) { + for (int i = 0; i < op.size(); i++) { + chain_one(op[i], grad[i]); + } + } }; using precomputed_gradients_vari diff --git a/stan/math/rev/fun.hpp b/stan/math/rev/fun.hpp index 7aeaa486f67..a4c85598cf3 100644 --- a/stan/math/rev/fun.hpp +++ b/stan/math/rev/fun.hpp @@ -35,6 +35,7 @@ #include #include #include +#include #include #include #include diff --git a/stan/math/rev/fun/dims.hpp b/stan/math/rev/fun/dims.hpp new file mode 100644 index 00000000000..7bb61e63e12 --- /dev/null +++ b/stan/math/rev/fun/dims.hpp @@ -0,0 +1,24 @@ +#ifndef STAN_MATH_REV_FUN_DIMS_HPP +#define STAN_MATH_REV_FUN_DIMS_HPP + +#include +#include +#include + +namespace stan { +namespace math { + +template , typename = void> +inline void dims(const var_value& x, std::vector& result) { + dims(*x.vi_, result); +} +template , typename = void> +inline void dims(const vari_value& x, std::vector& result) { + result.push_back(x.rows()); + result.push_back(x.cols()); +} + +} // namespace math +} // namespace stan + +#endif // DIMS_HPP diff --git a/stan/math/rev/functor/operands_and_partials.hpp b/stan/math/rev/functor/operands_and_partials.hpp index 1e6a75181ff..2988470c7ea 100644 --- a/stan/math/rev/functor/operands_and_partials.hpp +++ b/stan/math/rev/functor/operands_and_partials.hpp @@ -329,6 +329,35 @@ class ops_partials_edge>> { std::tuple<> container_operands() { return std::tuple<>(); } std::tuple<> container_partials() { return std::tuple<>(); } }; + +template +class ops_partials_edge>, + require_eigen_t> { + public: + using partials_t = std::vector>; + partials_t partials_vec_; + explicit ops_partials_edge(const std::vector>& ops) + : partials_vec_(ops.size()), operands_(ops) { + for (size_t i = 0; i < ops.size(); ++i) { + partials_vec_[i] = plain_type_t::Zero(ops[i].vi_->rows(), ops[i].vi_->cols()); + } + } + + private: + template + friend class stan::math::operands_and_partials; + const std::vector>& operands_; + + void dump_operands(vari** varis) {} + void dump_partials(double* partials) {} + int size() { return 0; } + std::tuple>> container_operands() { + return std::make_tuple(operands_); + } + std::tuple container_partials() { + return std::make_tuple(partials_vec_); + } +}; } // namespace internal } // namespace math } // namespace stan diff --git a/test/unit/math/rev/core/precomputed_gradients_test.cpp b/test/unit/math/rev/core/precomputed_gradients_test.cpp index 3880d55f958..b59abee62cd 100644 --- a/test/unit/math/rev/core/precomputed_gradients_test.cpp +++ b/test/unit/math/rev/core/precomputed_gradients_test.cpp @@ -107,14 +107,23 @@ TEST(StanAgradRevInternal, precomputed_gradients_containers) { std::vector vars; std::vector gradients; stan::math::var_value a(Eigen::MatrixXd::Constant(3, 3, 2)); - std::tuple&> ops{a}; - Eigen::MatrixXd grad = Eigen::MatrixXd::Constant(3, 3, -1); - std::tuple grads(grad); + std::vector> b{ + Eigen::MatrixXd::Constant(3, 3, 4), Eigen::MatrixXd::Constant(3, 3, 5)}; + std::tuple&, + std::vector>&> + ops{a, b}; + Eigen::MatrixXd grad_a = Eigen::MatrixXd::Constant(3, 3, -1); + std::vector grad_b{Eigen::MatrixXd::Constant(3, 3, -2), + Eigen::MatrixXd::Constant(3, 3, -3)}; + std::tuple&> grads(grad_a, + grad_b); stan::math::var lp = stan::math::precomputed_gradients(value, vars, gradients, ops, grads); (2 * lp).grad(); EXPECT_MATRIX_EQ(a.adj(), Eigen::MatrixXd::Constant(3, 3, -2)); + EXPECT_MATRIX_EQ(b[0].adj(), Eigen::MatrixXd::Constant(3, 3, -4)); + EXPECT_MATRIX_EQ(b[1].adj(), Eigen::MatrixXd::Constant(3, 3, -6)); stan::math::recover_memory(); } @@ -124,12 +133,19 @@ TEST(StanAgradRevInternal, precomputed_gradients_mismatched_containers) { std::vector vars; std::vector gradients; stan::math::var_value a(Eigen::MatrixXd::Constant(3, 3, 2)); - std::tuple&> ops(a); - Eigen::MatrixXd grad = Eigen::MatrixXd::Constant(3, 2, -1); - std::tuple grads(grad); - - EXPECT_THROW( - stan::math::precomputed_gradients(value, vars, gradients, ops, grads), - std::invalid_argument); + std::vector> b{ + Eigen::MatrixXd::Constant(3, 3, 4), Eigen::MatrixXd::Constant(3, 3, 5)}; + Eigen::MatrixXd grad_a = Eigen::MatrixXd::Constant(3, 2, -1); + std::vector grad_b{Eigen::MatrixXd::Constant(3, 2, -2), + Eigen::MatrixXd::Constant(3, 2, -3)}; + + EXPECT_THROW(stan::math::precomputed_gradients(value, vars, gradients, + std::forward_as_tuple(a), + std::forward_as_tuple(grad_a)), + std::invalid_argument); + EXPECT_THROW(stan::math::precomputed_gradients(value, vars, gradients, + std::forward_as_tuple(b), + std::forward_as_tuple(grad_b)), + std::invalid_argument); stan::math::recover_memory(); } diff --git a/test/unit/math/rev/functor/operands_and_partials_test.cpp b/test/unit/math/rev/functor/operands_and_partials_test.cpp index f5665b1325c..a63fb7473c2 100644 --- a/test/unit/math/rev/functor/operands_and_partials_test.cpp +++ b/test/unit/math/rev/functor/operands_and_partials_test.cpp @@ -345,3 +345,23 @@ TEST(AgradPartialsVari, OperandsAndPartialsVarValueMat) { (2 * lp).grad(); EXPECT_MATRIX_EQ(av.adj(), Eigen::MatrixXd::Constant(2, 2, -4)) } + +TEST(AgradPartialsVari, OperandsAndPartialsStdVectorVarValueMat) { + using stan::math::matrix_d; + using stan::math::matrix_v; + using stan::math::operands_and_partials; + using stan::math::var; + + Eigen::MatrixXd a(2, 2); + a << 10.0, 20.0, 30.0, 40.0; + std::vector> av{a,a}; + + operands_and_partials>> ops(av); + + ops.edge1_.partials_vec_[0] = Eigen::MatrixXd::Constant(2, 2, -2); + ops.edge1_.partials_vec_[1] = Eigen::MatrixXd::Constant(2, 2, -3); + var lp = ops.build(1); + (2 * lp).grad(); + EXPECT_MATRIX_EQ(av[0].adj(), Eigen::MatrixXd::Constant(2, 2, -4)); + EXPECT_MATRIX_EQ(av[1].adj(), Eigen::MatrixXd::Constant(2, 2, -6)); +} From 04b188cf8f0890008ef0f8788518d83b44e642f2 Mon Sep 17 00:00:00 2001 From: Stan Jenkins Date: Tue, 14 Jul 2020 03:07:59 -0400 Subject: [PATCH 161/355] [Jenkins] auto-formatting by clang-format version 6.0.0-1ubuntu2 (tags/RELEASE_600/final) --- stan/math/rev/functor/operands_and_partials.hpp | 3 ++- test/unit/math/rev/functor/operands_and_partials_test.cpp | 5 +++-- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/stan/math/rev/functor/operands_and_partials.hpp b/stan/math/rev/functor/operands_and_partials.hpp index 2988470c7ea..c65f759eae9 100644 --- a/stan/math/rev/functor/operands_and_partials.hpp +++ b/stan/math/rev/functor/operands_and_partials.hpp @@ -339,7 +339,8 @@ class ops_partials_edge>, explicit ops_partials_edge(const std::vector>& ops) : partials_vec_(ops.size()), operands_(ops) { for (size_t i = 0; i < ops.size(); ++i) { - partials_vec_[i] = plain_type_t::Zero(ops[i].vi_->rows(), ops[i].vi_->cols()); + partials_vec_[i] + = plain_type_t::Zero(ops[i].vi_->rows(), ops[i].vi_->cols()); } } diff --git a/test/unit/math/rev/functor/operands_and_partials_test.cpp b/test/unit/math/rev/functor/operands_and_partials_test.cpp index a63fb7473c2..62b35aca304 100644 --- a/test/unit/math/rev/functor/operands_and_partials_test.cpp +++ b/test/unit/math/rev/functor/operands_and_partials_test.cpp @@ -354,9 +354,10 @@ TEST(AgradPartialsVari, OperandsAndPartialsStdVectorVarValueMat) { Eigen::MatrixXd a(2, 2); a << 10.0, 20.0, 30.0, 40.0; - std::vector> av{a,a}; + std::vector> av{a, a}; - operands_and_partials>> ops(av); + operands_and_partials>> + ops(av); ops.edge1_.partials_vec_[0] = Eigen::MatrixXd::Constant(2, 2, -2); ops.edge1_.partials_vec_[1] = Eigen::MatrixXd::Constant(2, 2, -3); From e023ae007268070d8516d04b54310959d97a1966 Mon Sep 17 00:00:00 2001 From: tadej Date: Tue, 14 Jul 2020 14:33:20 +0200 Subject: [PATCH 162/355] added missing include --- stan/math/rev/fun/dims.hpp | 1 + 1 file changed, 1 insertion(+) diff --git a/stan/math/rev/fun/dims.hpp b/stan/math/rev/fun/dims.hpp index 7bb61e63e12..a42518104e1 100644 --- a/stan/math/rev/fun/dims.hpp +++ b/stan/math/rev/fun/dims.hpp @@ -3,6 +3,7 @@ #include #include +#include #include namespace stan { From 9e0eeeff840eced4af66aed5e9cf770a88a16217 Mon Sep 17 00:00:00 2001 From: tadej Date: Tue, 14 Jul 2020 15:08:55 +0200 Subject: [PATCH 163/355] reorded check_matching_dims overloads --- stan/math/prim/err/check_matching_dims.hpp | 70 +++++++++++----------- 1 file changed, 35 insertions(+), 35 deletions(-) diff --git a/stan/math/prim/err/check_matching_dims.hpp b/stan/math/prim/err/check_matching_dims.hpp index d4c64f4e49b..d2bff42c10b 100644 --- a/stan/math/prim/err/check_matching_dims.hpp +++ b/stan/math/prim/err/check_matching_dims.hpp @@ -11,41 +11,6 @@ namespace stan { namespace math { -/** - * Check if the two matrices are of the same size. - * This function checks the runtime sizes and can also check the static - * sizes as well. For example, a 4x1 matrix is not the same as a vector - * with 4 elements. - * @tparam check_compile Whether to check the static sizes - * @tparam Mat1 type of the first matrix - * @tparam Mat2 type of the second matrix - * @param function name of function (for error messages) - * @param name1 variable name for the first matrix (for error messages) - * @param y1 first matrix to test - * @param name2 variable name for the second matrix (for error messages) - * @param y2 second matrix to test - * @throw std::invalid_argument if the dimensions of the matrices - * do not match - */ -template > -inline void check_matching_dims(const char* function, const char* name1, - const Mat1& y1, const char* name2, - const Mat2& y2) { - if (check_compile - && (static_cast(Mat1::RowsAtCompileTime) - != static_cast(Mat2::RowsAtCompileTime) - || static_cast(Mat1::ColsAtCompileTime) - != static_cast(Mat2::ColsAtCompileTime))) { - std::ostringstream msg; - msg << "Static rows and cols of " << name1 << " and " << name2 - << " must match in size."; - std::string msg_str(msg.str()); - invalid_argument(function, msg_str.c_str(), "", ""); - } - check_matching_dims(function, name1, y1, name2, y2); -} - /** * Check if the two containers have the same dimensions. * @tparam T1 type of the first container @@ -96,6 +61,41 @@ inline void check_matching_dims(const char* function, const char* name1, } } +/** + * Check if the two matrices are of the same size. + * This function checks the runtime sizes and can also check the static + * sizes as well. For example, a 4x1 matrix is not the same as a vector + * with 4 elements. + * @tparam check_compile Whether to check the static sizes + * @tparam Mat1 type of the first matrix + * @tparam Mat2 type of the second matrix + * @param function name of function (for error messages) + * @param name1 variable name for the first matrix (for error messages) + * @param y1 first matrix to test + * @param name2 variable name for the second matrix (for error messages) + * @param y2 second matrix to test + * @throw std::invalid_argument if the dimensions of the matrices + * do not match + */ +template > +inline void check_matching_dims(const char* function, const char* name1, + const Mat1& y1, const char* name2, + const Mat2& y2) { + if (check_compile + && (static_cast(Mat1::RowsAtCompileTime) + != static_cast(Mat2::RowsAtCompileTime) + || static_cast(Mat1::ColsAtCompileTime) + != static_cast(Mat2::ColsAtCompileTime))) { + std::ostringstream msg; + msg << "Static rows and cols of " << name1 << " and " << name2 + << " must match in size."; + std::string msg_str(msg.str()); + invalid_argument(function, msg_str.c_str(), "", ""); + } + check_matching_dims(function, name1, y1, name2, y2); +} + } // namespace math } // namespace stan #endif From 61ea2cb612464933066bc8972a601bedee7c251f Mon Sep 17 00:00:00 2001 From: tadej Date: Wed, 15 Jul 2020 07:35:21 +0200 Subject: [PATCH 164/355] fixed brittle tests --- .../prim/err/check_matching_dims_test.cpp | 18 +++++--------- test/unit/math/prim/fun/assign_test.cpp | 24 +++++-------------- 2 files changed, 12 insertions(+), 30 deletions(-) diff --git a/test/unit/math/prim/err/check_matching_dims_test.cpp b/test/unit/math/prim/err/check_matching_dims_test.cpp index 3d50c5f0b71..73f0c0f8517 100644 --- a/test/unit/math/prim/err/check_matching_dims_test.cpp +++ b/test/unit/math/prim/err/check_matching_dims_test.cpp @@ -118,11 +118,9 @@ TEST(ErrorHandlingMatrix, checkMatchingDims_compile_time_sizes) { "check_matching_dims: Static rows and cols of dynamic and " "2x2 must match in size"); m_dynamic.resize(3, 3); - EXPECT_THROW_MSG(check_matching_dims("check_matching_dims", "dynamic", + EXPECT_THROW(check_matching_dims("check_matching_dims", "dynamic", m_dynamic, "2x2", m_2x2), - std::invalid_argument, - "check_matching_dims: Rows of dynamic (3) and rows of 2x2 " - "(2) must match in size"); + std::invalid_argument); m_dynamic.resize(4, 1); EXPECT_NO_THROW(check_matching_dims("check_matching_dims", "dynamic", @@ -134,11 +132,9 @@ TEST(ErrorHandlingMatrix, checkMatchingDims_compile_time_sizes) { "check_matching_dims: Static rows and cols of dynamic and " "vector must match in size"); m_dynamic.resize(3, 1); - EXPECT_THROW_MSG(check_matching_dims("check_matching_dims", "dynamic", + EXPECT_THROW(check_matching_dims("check_matching_dims", "dynamic", m_dynamic, "vector", vector), - std::invalid_argument, - "check_matching_dims: Rows of dynamic (3) and rows of " - "vector (4) must match in size"); + std::invalid_argument); m_dynamic.resize(1, 4); EXPECT_NO_THROW(check_matching_dims("check_matching_dims", "dynamic", @@ -150,9 +146,7 @@ TEST(ErrorHandlingMatrix, checkMatchingDims_compile_time_sizes) { "rowvector must match in size"); m_dynamic.resize(1, 3); - EXPECT_THROW_MSG(check_matching_dims("check_matching_dims", "dynamic", + EXPECT_THROW(check_matching_dims("check_matching_dims", "dynamic", m_dynamic, "rowvector", rowvector), - std::invalid_argument, - "check_matching_dims: Columns of dynamic (3) and columns of " - "rowvector (4) must match in size"); + std::invalid_argument); } diff --git a/test/unit/math/prim/fun/assign_test.cpp b/test/unit/math/prim/fun/assign_test.cpp index b27dbc95d38..89c5422f7e8 100644 --- a/test/unit/math/prim/fun/assign_test.cpp +++ b/test/unit/math/prim/fun/assign_test.cpp @@ -35,37 +35,25 @@ TEST(MathMatrixAssign, matSizeMismatch) { Matrix y(3); EXPECT_NO_THROW(assign(x, y)); Matrix z(10); - EXPECT_THROW_MSG(assign(x, z), std::exception, - "Columns of left-hand-side (3) and columns" - " of right-hand-side (10) must match in size"); + EXPECT_THROW(assign(x, z), std::invalid_argument); Matrix a(5); Matrix b(6); - EXPECT_THROW_MSG(assign(a, b), std::exception, - "Rows of left-hand-side (5) and rows" - " of right-hand-side (6) must match in size"); + EXPECT_THROW(assign(a, b), std::invalid_argument); std::vector u(5); std::vector v(7); - EXPECT_THROW_MSG(assign(u, v), std::exception, - "size of left-hand side (5) and size of" - " right-hand side (7) must match in size"); + EXPECT_THROW(assign(u, v), std::invalid_argument); Matrix m1(4, 5); Matrix m2(5, 4); - EXPECT_THROW_MSG(assign(m1, m2), std::exception, - "Rows of left-hand-side (4) and rows of" - " right-hand-side (5) must match in size"); + EXPECT_THROW(assign(m1, m2), std::invalid_argument); Matrix m3(10, 10); Matrix m4(2, 3); - EXPECT_THROW_MSG(assign(m3.block(1, 1, 7, 3), m4), std::exception, - "Rows of left-hand-side (7) and rows of" - " right-hand-side (2) must match in size"); + EXPECT_THROW(assign(m3.block(1, 1, 7, 3), m4), std::invalid_argument); - EXPECT_THROW_MSG(assign(m3.block(1, 1, 2, 5), m4), std::exception, - "Columns of left-hand-side (5) and columns" - " of right-hand-side (3) must match in size"); + EXPECT_THROW(assign(m3.block(1, 1, 2, 5), m4), std::invalid_argument); } TEST(MathMatrixAssign, test_int) { From 0090f0498d2460c05ead8f1b135ee27730658070 Mon Sep 17 00:00:00 2001 From: Stan Jenkins Date: Wed, 15 Jul 2020 02:38:48 -0400 Subject: [PATCH 165/355] [Jenkins] auto-formatting by clang-format version 6.0.0-1ubuntu2 (tags/RELEASE_600/final) --- .../math/prim/err/check_matching_dims_test.cpp | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/test/unit/math/prim/err/check_matching_dims_test.cpp b/test/unit/math/prim/err/check_matching_dims_test.cpp index 73f0c0f8517..1fad4572dba 100644 --- a/test/unit/math/prim/err/check_matching_dims_test.cpp +++ b/test/unit/math/prim/err/check_matching_dims_test.cpp @@ -118,9 +118,9 @@ TEST(ErrorHandlingMatrix, checkMatchingDims_compile_time_sizes) { "check_matching_dims: Static rows and cols of dynamic and " "2x2 must match in size"); m_dynamic.resize(3, 3); - EXPECT_THROW(check_matching_dims("check_matching_dims", "dynamic", - m_dynamic, "2x2", m_2x2), - std::invalid_argument); + EXPECT_THROW(check_matching_dims("check_matching_dims", "dynamic", m_dynamic, + "2x2", m_2x2), + std::invalid_argument); m_dynamic.resize(4, 1); EXPECT_NO_THROW(check_matching_dims("check_matching_dims", "dynamic", @@ -132,9 +132,9 @@ TEST(ErrorHandlingMatrix, checkMatchingDims_compile_time_sizes) { "check_matching_dims: Static rows and cols of dynamic and " "vector must match in size"); m_dynamic.resize(3, 1); - EXPECT_THROW(check_matching_dims("check_matching_dims", "dynamic", - m_dynamic, "vector", vector), - std::invalid_argument); + EXPECT_THROW(check_matching_dims("check_matching_dims", "dynamic", m_dynamic, + "vector", vector), + std::invalid_argument); m_dynamic.resize(1, 4); EXPECT_NO_THROW(check_matching_dims("check_matching_dims", "dynamic", @@ -146,7 +146,7 @@ TEST(ErrorHandlingMatrix, checkMatchingDims_compile_time_sizes) { "rowvector must match in size"); m_dynamic.resize(1, 3); - EXPECT_THROW(check_matching_dims("check_matching_dims", "dynamic", - m_dynamic, "rowvector", rowvector), - std::invalid_argument); + EXPECT_THROW(check_matching_dims("check_matching_dims", "dynamic", m_dynamic, + "rowvector", rowvector), + std::invalid_argument); } From fb75fc0224fa28ea83faa2c8b7a7580b76aa7f42 Mon Sep 17 00:00:00 2001 From: tadej Date: Fri, 17 Jul 2020 14:03:26 +0200 Subject: [PATCH 166/355] added missing size includes in tests --- test/unit/math/rev/meta/VectorBuilderHelper_test.cpp | 1 + test/unit/math/rev/meta/VectorBuilder_test.cpp | 1 + test/unit/math/rev/meta/is_constant_all_test.cpp | 2 -- 3 files changed, 2 insertions(+), 2 deletions(-) diff --git a/test/unit/math/rev/meta/VectorBuilderHelper_test.cpp b/test/unit/math/rev/meta/VectorBuilderHelper_test.cpp index 70d8c464102..f8f86e7b13f 100644 --- a/test/unit/math/rev/meta/VectorBuilderHelper_test.cpp +++ b/test/unit/math/rev/meta/VectorBuilderHelper_test.cpp @@ -1,4 +1,5 @@ #include +#include #include #include diff --git a/test/unit/math/rev/meta/VectorBuilder_test.cpp b/test/unit/math/rev/meta/VectorBuilder_test.cpp index 557c21b1de6..1ccc86750c9 100644 --- a/test/unit/math/rev/meta/VectorBuilder_test.cpp +++ b/test/unit/math/rev/meta/VectorBuilder_test.cpp @@ -1,4 +1,5 @@ #include +#include #include #include diff --git a/test/unit/math/rev/meta/is_constant_all_test.cpp b/test/unit/math/rev/meta/is_constant_all_test.cpp index 771eea6d8c9..8c523c1bde5 100644 --- a/test/unit/math/rev/meta/is_constant_all_test.cpp +++ b/test/unit/math/rev/meta/is_constant_all_test.cpp @@ -34,8 +34,6 @@ TEST(MetaTraitsRevArr, isConstantStruct) { vector >(); } -using stan::math::size; - using var_t1 = Eigen::Matrix; using var_t2 = std::vector; using var_t3 = std::vector; From c3b0c3c368e3be59fad646d7c69d3f99ec5b27a5 Mon Sep 17 00:00:00 2001 From: tadej Date: Mon, 20 Jul 2020 16:45:35 +0200 Subject: [PATCH 167/355] Added doxygen to dims --- stan/math/prim/fun/dims.hpp | 34 +++++++++++++++++++++++++++++++--- stan/math/rev/fun/dims.hpp | 21 +++++++++++++++++++-- 2 files changed, 50 insertions(+), 5 deletions(-) diff --git a/stan/math/prim/fun/dims.hpp b/stan/math/prim/fun/dims.hpp index 1c6e9510b5b..cdcc02db93e 100644 --- a/stan/math/prim/fun/dims.hpp +++ b/stan/math/prim/fun/dims.hpp @@ -8,15 +8,38 @@ namespace stan { namespace math { +/** + * Pushes dimensions of given argument into given result vector. + * + * For a scalar that is a no-op. + * @tparam type of scalar + * @param x argument + * @param result result + */ template > -inline void dims(const T& x, std::vector& result) { - /* no op */ -} +inline void dims(const T& x, std::vector& result) {} + +/** + * Pushes dimensions of given argument into given result vector. + * + * For an Eigen type those are the numbers of rows and columns. + * @param x argument + * @param result result + */ template , typename = void> inline void dims(const T& x, std::vector& result) { result.push_back(x.rows()); result.push_back(x.cols()); } + +/** + * Pushes dimensions of given argument into given result vector. + * + * For a `std::vector` that is its size and dimensions of its elements. + * @tparam type of scalar + * @param x argument + * @param result result + */ template inline void dims(const std::vector& x, std::vector& result) { result.push_back(x.size()); @@ -25,6 +48,11 @@ inline void dims(const std::vector& x, std::vector& result) { } } +/** + * Determines dimensions of an argument. + * @param x argument + * @return vector of sizes in each of arguemnt's dimensions + */ template inline std::vector dims(const T& x) { std::vector result; diff --git a/stan/math/rev/fun/dims.hpp b/stan/math/rev/fun/dims.hpp index a42518104e1..33ab63d49d5 100644 --- a/stan/math/rev/fun/dims.hpp +++ b/stan/math/rev/fun/dims.hpp @@ -9,11 +9,28 @@ namespace stan { namespace math { -template , typename = void> +/** + * Pushes dimensions of given argument into given result vector. + * + * For `var_value` that is the dimensions of inner `vari_value`. + * @tparam type in `var_value` + * @param x argument + * @param result result + */ +template * = nullptr> inline void dims(const var_value& x, std::vector& result) { dims(*x.vi_, result); } -template , typename = void> + +/** + * Pushes dimensions of given argument into given result vector. + * + * For `vari_value` containing Eigen type those are the numbers of rows and + * columns. + * @param x argument + * @param result result + */ +template * = nullptr> inline void dims(const vari_value& x, std::vector& result) { result.push_back(x.rows()); result.push_back(x.cols()); From 2a14395174551f4e8f65ad401946d71dbeb6006a Mon Sep 17 00:00:00 2001 From: Steve Bronder Date: Wed, 22 Jul 2020 13:41:29 -0400 Subject: [PATCH 168/355] adds uint16_t to var test --- test/unit/math/rev/core/var_test.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/test/unit/math/rev/core/var_test.cpp b/test/unit/math/rev/core/var_test.cpp index 2b792ac41cd..c9bb2dfb48b 100644 --- a/test/unit/math/rev/core/var_test.cpp +++ b/test/unit/math/rev/core/var_test.cpp @@ -51,6 +51,7 @@ void ctor_overloads() { ctor_overloads_impl(); ctor_overloads_impl(); ctor_overloads_impl(); + ctor_overloads_impl(); ctor_overloads_impl(); ctor_overloads_impl(); } From 9df61cad06820380333375a05d4fdbf231d0011b Mon Sep 17 00:00:00 2001 From: Stan Jenkins Date: Wed, 22 Jul 2020 18:34:36 +0000 Subject: [PATCH 169/355] [Jenkins] auto-formatting by clang-format version 6.0.0-1ubuntu2~16.04.1 (tags/RELEASE_600/final) --- stan/math/rev/core/vari.hpp | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/stan/math/rev/core/vari.hpp b/stan/math/rev/core/vari.hpp index 3384575923f..089edc383eb 100644 --- a/stan/math/rev/core/vari.hpp +++ b/stan/math/rev/core/vari.hpp @@ -196,8 +196,9 @@ class vari_value> : public vari_base { * `PlainObject` represents a user constructible type such as Matrix or Array */ using PlainObject = plain_type_t; - using Scalar = typename PlainObject::Scalar; // The underlying type for this class - using value_type = PlainObject; // The underlying type for this class + using Scalar = + typename PlainObject::Scalar; // The underlying type for this class + using value_type = PlainObject; // The underlying type for this class using eigen_scalar = value_type_t; // A floating point type /** * Maps for adj_ and val_ @@ -209,11 +210,13 @@ class vari_value> : public vari_base { /** * Number of rows known at compile time */ - static constexpr Eigen::Index RowsAtCompileTime = PlainObject::RowsAtCompileTime; + static constexpr Eigen::Index RowsAtCompileTime + = PlainObject::RowsAtCompileTime; /** * Number of columns known at compile time */ - static constexpr Eigen::Index ColsAtCompileTime = PlainObject::ColsAtCompileTime; + static constexpr Eigen::Index ColsAtCompileTime + = PlainObject::ColsAtCompileTime; /** * The value of this variable. @@ -369,12 +372,13 @@ class vari_value> : public vari_base { * */ template -class vari_value> - : public vari_base, chainable_alloc { +class vari_value> : public vari_base, + chainable_alloc { public: using PlainObject = plain_type_t; // Base type of Eigen class - using Scalar = typename PlainObject::Scalar; // vari's adj_ and val_ member type - using value_type = PlainObject; // vari's adj_ and val_ member type + using Scalar = + typename PlainObject::Scalar; // vari's adj_ and val_ member type + using value_type = PlainObject; // vari's adj_ and val_ member type /** * Rows at compile time */ From 1030c5cf95ef9f2ea3adbe84157891d133ce5df8 Mon Sep 17 00:00:00 2001 From: tadej Date: Thu, 23 Jul 2020 09:16:19 +0200 Subject: [PATCH 170/355] fixed compiler not seeing chain_one --- stan/math/rev/core/precomputed_gradients.hpp | 33 ++++++++++---------- 1 file changed, 17 insertions(+), 16 deletions(-) diff --git a/stan/math/rev/core/precomputed_gradients.hpp b/stan/math/rev/core/precomputed_gradients.hpp index 238939b184f..cafb1c8f673 100644 --- a/stan/math/rev/core/precomputed_gradients.hpp +++ b/stan/math/rev/core/precomputed_gradients.hpp @@ -135,22 +135,6 @@ class precomputed_gradients_vari_template : public vari { std::copy(gradients.begin(), gradients.end(), gradients_); } - /** - * Implements the chain rule for this variable, using the - * prestored operands and gradient. - */ - void chain() { - for (size_t i = 0; i < size_; ++i) { - varis_[i]->adj_ += adj_ * gradients_[i]; - } - index_apply([this](auto... Is) { - static_cast(std::initializer_list{ - (chain_one(std::get(this->container_operands_), - std::get(this->container_gradients_)), - 0)...}); - }); - } - private: /** * Implements the chain rule for one non-`std::vector` operand. @@ -178,6 +162,23 @@ class precomputed_gradients_vari_template : public vari { chain_one(op[i], grad[i]); } } + + public: + /** + * Implements the chain rule for this variable, using the + * prestored operands and gradient. + */ + void chain() { + for (size_t i = 0; i < size_; ++i) { + varis_[i]->adj_ += adj_ * gradients_[i]; + } + index_apply([this](auto... Is) { + static_cast(std::initializer_list{ + (chain_one(std::get(this->container_operands_), + std::get(this->container_gradients_)), + 0)...}); + }); + } }; using precomputed_gradients_vari From 270d352512361408a1cbb8e12afc9ad4ca4f2747 Mon Sep 17 00:00:00 2001 From: tadej Date: Thu, 23 Jul 2020 14:44:54 +0200 Subject: [PATCH 171/355] trying to fix it another way --- stan/math/rev/core/precomputed_gradients.hpp | 33 ++++++++++---------- 1 file changed, 16 insertions(+), 17 deletions(-) diff --git a/stan/math/rev/core/precomputed_gradients.hpp b/stan/math/rev/core/precomputed_gradients.hpp index cafb1c8f673..c164345a47e 100644 --- a/stan/math/rev/core/precomputed_gradients.hpp +++ b/stan/math/rev/core/precomputed_gradients.hpp @@ -135,6 +135,22 @@ class precomputed_gradients_vari_template : public vari { std::copy(gradients.begin(), gradients.end(), gradients_); } + /** + * Implements the chain rule for this variable, using the + * prestored operands and gradient. + */ + void chain() { + for (size_t i = 0; i < size_; ++i) { + varis_[i]->adj_ += adj_ * gradients_[i]; + } + index_apply([this](auto... Is) { + static_cast(std::initializer_list{ + (this->chain_one(std::get(this->container_operands_), + std::get(this->container_gradients_)), + 0)...}); + }); + } + private: /** * Implements the chain rule for one non-`std::vector` operand. @@ -162,23 +178,6 @@ class precomputed_gradients_vari_template : public vari { chain_one(op[i], grad[i]); } } - - public: - /** - * Implements the chain rule for this variable, using the - * prestored operands and gradient. - */ - void chain() { - for (size_t i = 0; i < size_; ++i) { - varis_[i]->adj_ += adj_ * gradients_[i]; - } - index_apply([this](auto... Is) { - static_cast(std::initializer_list{ - (chain_one(std::get(this->container_operands_), - std::get(this->container_gradients_)), - 0)...}); - }); - } }; using precomputed_gradients_vari From 5060b683bc031f102ae8ade4a451013a5e567f59 Mon Sep 17 00:00:00 2001 From: tadej Date: Sat, 25 Jul 2020 09:59:56 +0200 Subject: [PATCH 172/355] fixed 5 edges --- stan/math/rev/functor/operands_and_partials.hpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/stan/math/rev/functor/operands_and_partials.hpp b/stan/math/rev/functor/operands_and_partials.hpp index c65f759eae9..e9e00e1f58a 100644 --- a/stan/math/rev/functor/operands_and_partials.hpp +++ b/stan/math/rev/functor/operands_and_partials.hpp @@ -135,10 +135,12 @@ class operands_and_partials { auto container_operands = std::tuple_cat( edge1_.container_operands(), edge2_.container_operands(), - edge3_.container_operands(), edge4_.container_operands()); + edge3_.container_operands(), edge4_.container_operands(), + edge5_.container_operands()); auto container_partials = std::tuple_cat( edge1_.container_partials(), edge2_.container_partials(), - edge3_.container_partials(), edge4_.container_partials()); + edge3_.container_partials(), edge4_.container_partials(), + edge5_.container_partials()); return var( new precomputed_gradients_vari_template Date: Mon, 3 Aug 2020 13:04:37 -0400 Subject: [PATCH 173/355] remove Scalar type trait from vari_value --- stan/math/rev/core/vari.hpp | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/stan/math/rev/core/vari.hpp b/stan/math/rev/core/vari.hpp index 089edc383eb..032fca6d776 100644 --- a/stan/math/rev/core/vari.hpp +++ b/stan/math/rev/core/vari.hpp @@ -49,17 +49,16 @@ class vari_value; template class vari_value> : public vari_base { public: - using Scalar = T; - using value_type = Scalar; + using value_type = std::decay_t; /** * The value of this variable. */ - const Scalar val_; + const value_type val_; /** * The adjoint of this variable, which is the partial derivative * of this variable with respect to the root variable. */ - Scalar adj_; + value_type adj_; /** * Construct a variable implementation from a value. The @@ -196,8 +195,6 @@ class vari_value> : public vari_base { * `PlainObject` represents a user constructible type such as Matrix or Array */ using PlainObject = plain_type_t; - using Scalar = - typename PlainObject::Scalar; // The underlying type for this class using value_type = PlainObject; // The underlying type for this class using eigen_scalar = value_type_t; // A floating point type /** @@ -376,8 +373,6 @@ class vari_value> : public vari_base, chainable_alloc { public: using PlainObject = plain_type_t; // Base type of Eigen class - using Scalar = - typename PlainObject::Scalar; // vari's adj_ and val_ member type using value_type = PlainObject; // vari's adj_ and val_ member type /** * Rows at compile time From 547909347f79b30758f1d9cbe461b1f135f11cbd Mon Sep 17 00:00:00 2001 From: Stan Jenkins Date: Mon, 3 Aug 2020 17:25:46 +0000 Subject: [PATCH 174/355] [Jenkins] auto-formatting by clang-format version 6.0.0-1ubuntu2~16.04.1 (tags/RELEASE_600/final) --- stan/math/rev/core/vari.hpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/stan/math/rev/core/vari.hpp b/stan/math/rev/core/vari.hpp index 032fca6d776..b52b5b375e8 100644 --- a/stan/math/rev/core/vari.hpp +++ b/stan/math/rev/core/vari.hpp @@ -195,7 +195,7 @@ class vari_value> : public vari_base { * `PlainObject` represents a user constructible type such as Matrix or Array */ using PlainObject = plain_type_t; - using value_type = PlainObject; // The underlying type for this class + using value_type = PlainObject; // The underlying type for this class using eigen_scalar = value_type_t; // A floating point type /** * Maps for adj_ and val_ @@ -373,7 +373,7 @@ class vari_value> : public vari_base, chainable_alloc { public: using PlainObject = plain_type_t; // Base type of Eigen class - using value_type = PlainObject; // vari's adj_ and val_ member type + using value_type = PlainObject; // vari's adj_ and val_ member type /** * Rows at compile time */ From ec592d593143e5a4492ea098dfc599fb1dfec04d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tadej=20Ciglari=C4=8D?= Date: Tue, 4 Aug 2020 00:50:06 +0200 Subject: [PATCH 175/355] Add vari_base (#1967) Adds matrix_cl template specializations for vari_value * tmp * added vari * [Jenkins] auto-formatting by clang-format version 6.0.0-1ubuntu2 (tags/RELEASE_600/final) * fix doxygen * [Jenkins] auto-formatting by clang-format version 6.0.0-1ubuntu2~16.04.1 (tags/RELEASE_600/final) * fixed copying * fixed doxygen * [Jenkins] auto-formatting by clang-format version 6.0.0-1ubuntu2~16.04.1 (tags/RELEASE_600/final) * fixed cpplint * adds support for copying matrix to device * [Jenkins] auto-formatting by clang-format version 6.0.0-1ubuntu2~16.04.1 (tags/RELEASE_600/final) * bugfixes * fixed a test * bugfixed segfault in constant * [Jenkins] auto-formatting by clang-format version 6.0.0-1ubuntu2 (tags/RELEASE_600/final) * fixed circular include * wake up github * [Jenkins] auto-formatting by clang-format version 6.0.0-1ubuntu2 (tags/RELEASE_600/final) * added include * more includes * [Jenkins] auto-formatting by clang-format version 6.0.0-1ubuntu2~16.04.1 (tags/RELEASE_600/final) * added Eigen constructor and fixed docs * views are not put on stack anymore * [Jenkins] auto-formatting by clang-format version 6.0.0-1ubuntu2~16.04.1 (tags/RELEASE_600/final) * bugfix * added const * [Jenkins] auto-formatting by clang-format version 6.0.0-1ubuntu2~16.04.1 (tags/RELEASE_600/final) Co-authored-by: Stan Jenkins Co-authored-by: Jenkins --- stan/math/opencl/copy.hpp | 18 ++ stan/math/opencl/kernel_generator.hpp | 1 + .../math/opencl/kernel_generator/constant.hpp | 132 ++++++++++++ .../kernel_generator/is_kernel_expression.hpp | 27 ++- .../opencl/kernel_generator/operation_cl.hpp | 7 + .../kernel_generator/operation_cl_lhs.hpp | 3 +- stan/math/opencl/kernel_generator/scalar.hpp | 2 +- stan/math/opencl/rev/copy.hpp | 94 ++++++-- stan/math/opencl/rev/vari.hpp | 204 ++++++++++++++++++ stan/math/opencl/value_type.hpp | 4 +- stan/math/prim/meta/ref_type.hpp | 5 +- stan/math/rev/core/var.hpp | 3 + stan/math/rev/fun/lambert_w.hpp | 1 + .../opencl/kernel_generator/constant_test.cpp | 17 ++ test/unit/math/opencl/rev/copy_test.cpp | 51 ++++- test/unit/math/opencl/rev/sub_block_test.cpp | 39 ++-- test/unit/math/opencl/rev/vari_test.cpp | 25 +++ test/unit/math/rev/meta/is_fvar_test.cpp | 1 + .../rev/meta/is_var_or_arithmetic_test.cpp | 1 + test/unit/math/rev/meta/is_var_test.cpp | 1 + test/unit/math/rev/meta/is_vari_test.cpp | 1 + 21 files changed, 596 insertions(+), 41 deletions(-) create mode 100644 stan/math/opencl/kernel_generator/constant.hpp create mode 100644 stan/math/opencl/rev/vari.hpp create mode 100644 test/unit/math/opencl/kernel_generator/constant_test.cpp create mode 100644 test/unit/math/opencl/rev/vari_test.cpp diff --git a/stan/math/opencl/copy.hpp b/stan/math/opencl/copy.hpp index 6a4b8657c77..e795f7c1b04 100644 --- a/stan/math/opencl/copy.hpp +++ b/stan/math/opencl/copy.hpp @@ -11,6 +11,7 @@ #include #include #include +#include #include #include #include @@ -101,6 +102,23 @@ inline Eigen::Matrix from_matrix_cl(const matrix_cl& src) { return dst; } +/** \ingroup opencl + * Copies result of a kernel generator expression to the + * destination Eigen matrix. + * + * @tparam R rows type of the destination + * @tparam C cols type of the destination + * @tparam T type of expression + * @param src source expression + * @return Eigen matrix with a copy of the data in the source matrix + */ +template * = nullptr, + require_not_matrix_cl_t* = nullptr> +inline Eigen::Matrix, R, C> from_matrix_cl(const T& src) { + return from_matrix_cl(src.eval()); +} + /** \ingroup opencl * Packs the flat triangular matrix on the OpenCL device and * copies it to the std::vector. diff --git a/stan/math/opencl/kernel_generator.hpp b/stan/math/opencl/kernel_generator.hpp index 2d66030ff3a..aba3e0abe43 100644 --- a/stan/math/opencl/kernel_generator.hpp +++ b/stan/math/opencl/kernel_generator.hpp @@ -114,6 +114,7 @@ #include #include +#include #include #include #include diff --git a/stan/math/opencl/kernel_generator/constant.hpp b/stan/math/opencl/kernel_generator/constant.hpp new file mode 100644 index 00000000000..ff9e48f07e7 --- /dev/null +++ b/stan/math/opencl/kernel_generator/constant.hpp @@ -0,0 +1,132 @@ +#ifndef STAN_MATH_OPENCL_KERNEL_GENERATOR_CONSTANT_HPP +#define STAN_MATH_OPENCL_KERNEL_GENERATOR_CONSTANT_HPP +#ifdef STAN_OPENCL + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace stan { +namespace math { + +/** \addtogroup opencl_kernel_generator + * @{ + */ + +/** + * Represents a matrix of single repeated value in kernel generator expressions. + * @tparam T type of the scalar + */ +template +class constant_ : public operation_cl, T> { + T a_; + int rows_; + int cols_; + + public: + static_assert(std::is_arithmetic::value, + "class scalar_: std::is_arithmetic must be true!"); + using Scalar = T; + using base = operation_cl, T>; + using base::var_name_; + + /** + * Constructor + * @param a scalar value + * @param rows number of rows of the matrix + * @param cols number of columns of the matrix + */ + explicit constant_(const T a, int rows, int cols) + : a_(a), rows_(rows), cols_(cols) {} + + /** + * Creates a deep copy of this expression. + * @return copy of \c *this + */ + inline constant_ deep_copy() const { + return constant_(a_, rows_, cols_); + } + + /** + * Generates kernel code for this expression. + * @param row_index_name row index variable name + * @param col_index_name column index variable name + * @param view_handled whether whether caller already handled matrix view + * @return part of kernel with code for this expression + */ + inline kernel_parts generate(const std::string& row_index_name, + const std::string& col_index_name, + const bool view_handled) const { + kernel_parts res{}; + res.args = type_str() + " " + var_name_ + ", "; + return res; + } + + /** + * Sets kernel arguments for this and nested expressions. + * @param[in,out] generated set of expressions that already set their kernel + * arguments + * @param kernel kernel to set arguments on + * @param[in,out] arg_num consecutive number of the first argument to set. + * This is incremented for each argument set by this function. + */ + inline void set_args(std::set& generated, + cl::Kernel& kernel, int& arg_num) const { + kernel.setArg(arg_num++, a_); + } + + /** + * Number of rows of a matrix that would be the result of evaluating this + * expression. + * @return number of rows + */ + inline int rows() const { return rows_; } + + /** + * Number of columns of a matrix that would be the result of evaluating this + * expression. + * @return number of columns + */ + inline int cols() const { return cols_; } + + /** + * Determine indices of extreme sub- and superdiagonals written. + * @return pair of indices - bottom and top diagonal + */ + inline std::pair extreme_diagonals() const { + return {std::numeric_limits::min(), std::numeric_limits::max()}; + } +}; + +/** + * Matrix of repeated values in kernel generator expressions. + * + * In most cases scalars should be directly used instead of this. This is, + * however, useful for initializing some expression to specific value if that + * expresssion could also be plain `matrix_cl`. + * + * @tparam T type of argument + * @param a input argument + * @param rows number of rows + * @param cols number of columns + * @return Block of given expression + */ +template > +inline auto constant(const T a, int rows, int cols) { + return constant_(a, rows, cols); +} + +/** @}*/ +} // namespace math +} // namespace stan + +#endif +#endif diff --git a/stan/math/opencl/kernel_generator/is_kernel_expression.hpp b/stan/math/opencl/kernel_generator/is_kernel_expression.hpp index 5bb54c818d2..186f3f84ba1 100644 --- a/stan/math/opencl/kernel_generator/is_kernel_expression.hpp +++ b/stan/math/opencl/kernel_generator/is_kernel_expression.hpp @@ -7,16 +7,21 @@ #include namespace stan { -namespace math { /** \addtogroup opencl_kernel_generator * @{ */ + /** - * Non-templated base of \c operation is needed for easy checking if something - * is a subclass of \c operation. + * Non-templated base of `operation_cl` is needed for easy checking if something + * is a subclass of `operation_cl`. */ class operation_cl_base {}; +/** + * Non-templated base of `operation_cl_lhs` is needed for easy checking if + * something is a subclass of `operation_cl_lhs`. + */ +class operation_cl_lhs_base {}; /** * Determines whether a type is non-scalar type that is a valid kernel generator @@ -26,7 +31,6 @@ template struct is_kernel_expression_and_not_scalar : bool_constant>::value> {}; - template struct is_kernel_expression_and_not_scalar> : std::true_type {}; @@ -57,8 +61,21 @@ using require_all_kernel_expressions_and_none_scalar_t template using require_all_kernel_expressions_t = require_all_t...>; + +/** + * Determines whether a type is an assignable kernel generator + * expression. + */ +template +struct is_kernel_expression_lhs + : bool_constant>::value> {}; +template +struct is_kernel_expression_lhs> : std::true_type {}; + /** @}*/ -} // namespace math +STAN_ADD_REQUIRE_UNARY(kernel_expression_lhs, is_kernel_expression_lhs, + opencl_kernel_generator); } // namespace stan #endif diff --git a/stan/math/opencl/kernel_generator/operation_cl.hpp b/stan/math/opencl/kernel_generator/operation_cl.hpp index 846e4403606..a20478a793b 100644 --- a/stan/math/opencl/kernel_generator/operation_cl.hpp +++ b/stan/math/opencl/kernel_generator/operation_cl.hpp @@ -314,6 +314,8 @@ class operation_cl : public operation_cl_base { * @return number of rows */ inline int rows() const { + static_assert( + N > 0, "default rows does not work on expressions with no arguments!"); return index_apply([&](auto... Is) { // assuming all non-dynamic sizes match return std::max({this->get_arg().rows()...}); @@ -326,6 +328,8 @@ class operation_cl : public operation_cl_base { * @return number of columns */ inline int cols() const { + static_assert( + N > 0, "default cols does not work on expressions with no arguments!"); return index_apply([&](auto... Is) { // assuming all non-dynamic sizes match return std::max({this->get_arg().cols()...}); @@ -352,6 +356,9 @@ class operation_cl : public operation_cl_base { * @return pair of indices - bottom and top diagonal */ inline std::pair extreme_diagonals() const { + static_assert(N > 0, + "default extreme_diagonals does not work on expressions with " + "no arguments!"); return index_apply([&](auto... Is) { auto arg_diags = std::make_tuple(this->get_arg().extreme_diagonals()...); diff --git a/stan/math/opencl/kernel_generator/operation_cl_lhs.hpp b/stan/math/opencl/kernel_generator/operation_cl_lhs.hpp index ef2c73b812d..c7b47d8bb98 100644 --- a/stan/math/opencl/kernel_generator/operation_cl_lhs.hpp +++ b/stan/math/opencl/kernel_generator/operation_cl_lhs.hpp @@ -24,7 +24,8 @@ namespace math { * @tparam Args types of arguments to this operation */ template -class operation_cl_lhs : public operation_cl { +class operation_cl_lhs : public operation_cl, + public operation_cl_lhs_base { protected: using base = operation_cl; static constexpr int N = sizeof...(Args); diff --git a/stan/math/opencl/kernel_generator/scalar.hpp b/stan/math/opencl/kernel_generator/scalar.hpp index 2ddd13b5d01..5282b1f3c4f 100644 --- a/stan/math/opencl/kernel_generator/scalar.hpp +++ b/stan/math/opencl/kernel_generator/scalar.hpp @@ -27,7 +27,7 @@ namespace math { */ template class scalar_ : public operation_cl, T> { - private: + protected: T a_; public: diff --git a/stan/math/opencl/rev/copy.hpp b/stan/math/opencl/rev/copy.hpp index 2dda8fe80d5..b343a4a06f9 100644 --- a/stan/math/opencl/rev/copy.hpp +++ b/stan/math/opencl/rev/copy.hpp @@ -16,6 +16,76 @@ namespace stan { namespace math { +namespace internal { +template * = nullptr> +class op_copy_to_cl_vari final + : public vari_value>> { + T_arg_adj arg_adj_; + + public: + template * = nullptr, + require_vt_same* = nullptr> + explicit op_copy_to_cl_vari(const T_arg_val& val, T_arg_adj adj) + : vari_value>>(to_matrix_cl(val)), + arg_adj_(adj) {} + + virtual void chain() { + arg_adj_ += from_matrix_cl::RowsAtCompileTime, + std::decay_t::ColsAtCompileTime>( + this->adj_); + } +}; +} // namespace internal + +/** \ingroup opencl + * Copies the source var containing Eigen matrices to destination var that has + * data stored on the OpenCL device. + * + * @tparam T type of the Eigen matrix + * @param a source Eigen matrix + * @return var with a copy of the data on the OpenCL device + */ +template +inline var_value>> to_matrix_cl( + const var_value& a) { + return new internal::op_copy_to_cl_variadj_)>(a.val(), + a.vi_->adj_); +} + +namespace internal { +template * = nullptr> +class op_copy_from_cl_vari final + : public vari_value, Rows, Cols>> { + vari_value& a_; + + public: + explicit op_copy_from_cl_vari(vari_value& a) + : vari_value, Rows, Cols>>( + from_matrix_cl(a.val_)), + a_(a) {} + + virtual void chain() { a_.adj_ = a_.adj_ + to_matrix_cl(this->adj_); } +}; +} // namespace internal + +/** \ingroup opencl + * Copies the source var that has data stored on the OpenCL device to + * destination var containing Eigen matrices. + * + * @tparam Rows number of compile time rows of the destination matrix + * @tparam Rows number of compile time columns of the destination matrix + * @tparam T type of the matrix or expression on the OpenCL device + * @param a source matrix_cl or expression + * @return var with a copy of the data on the host + */ +template * = nullptr> +inline var_value, Rows, Cols>> from_matrix_cl( + const var_value& a) { + return new internal::op_copy_from_cl_vari(*a.vi_); +} + /** \ingroup opencl * Copies the source Eigen matrix of vars to * the destination matrix that is stored @@ -26,19 +96,17 @@ namespace math { * @param src source Eigen matrix * @return matrix_cl with a copy of the data in the source matrix */ -template * = nullptr> -inline matrix_cl to_matrix_cl(const Eigen::Matrix& src) try { - matrix_cl dst(src.rows(), src.cols()); - if (src.size() == 0) { - return dst; - } - dst.val() = to_matrix_cl(src.val().eval()); - dst.adj() = to_matrix_cl(src.adj().eval()); - return dst; -} catch (const cl::Error& e) { - check_opencl_error("copy var Eigen->(OpenCL)", e); - matrix_cl dst(src.rows(), src.cols()); - return dst; +template * = nullptr> +inline var_value>>> to_matrix_cl( + const T& src) { + // the matrix can go out of scope before chain() is called. So we store a map + // to the data + var* src_array + = ChainableStack::instance_->memalloc_.alloc_array(src.size()); + Eigen::Map> src_stacked(src_array, src.rows(), src.cols()); + src_stacked = src; + return new internal::op_copy_to_cl_vari( + src_stacked.val(), src_stacked.adj()); } /** \ingroup opencl diff --git a/stan/math/opencl/rev/vari.hpp b/stan/math/opencl/rev/vari.hpp new file mode 100644 index 00000000000..0d63bbe9ac0 --- /dev/null +++ b/stan/math/opencl/rev/vari.hpp @@ -0,0 +1,204 @@ +#ifndef STAN_MATH_OPENCL_REV_VARI_HPP +#define STAN_MATH_OPENCL_REV_VARI_HPP +#ifdef STAN_OPENCL + +#include +#include +#include + +namespace stan { +namespace math { +/** + * The variable implementation for `matrix_cl`. + * + * This class is complete (not abstract) and may be used for + * constants. + * + * A variable implementation is constructed with a constant + * value. It also stores the adjoint for storing the partial + * derivative with respect to the root of the derivative tree. + * + */ +template +class vari_value> + : public vari_base, public chainable_alloc { + public: + /** + * The adjoint of this variable, which is the partial derivative + * of this variable with respect to the root variable. + */ + T adj_; + + /** + * The value of this variable. + */ + T val_; + + /** + * Construct a matrix_cl variable implementation from a value. The + * adjoint is initialized to zero. + * + * All constructed variables are added to the stack. Variables + * should be constructed before variables on which they depend + * to insure proper partial derivative propagation. During + * derivative propagation, the chain() method of each variable + * will be called in the reverse order of construction. + * + * @tparam S A `matrix_cl` or kernel generator expression type that is + * convertible to `value_type` + * @param x Value of the constructed variable. + */ + template * = nullptr> + explicit vari_value(S&& x) + : chainable_alloc(), + adj_(constant(0, x.rows(), x.cols())), + val_(std::forward(x)) { + ChainableStack::instance_->var_stack_.push_back(this); + } + + /** + * Construct a matrix_cl variable implementation from an Eigen value. The + * adjoint is initialized to zero. + * + * All constructed variables are added to the stack. Variables + * should be constructed before variables on which they depend + * to insure proper partial derivative propagation. During + * derivative propagation, the chain() method of each variable + * will be called in the reverse order of construction. + * + * @tparam S A dense Eigen value or expression that has same scalar type as T + * @param x Value of the constructed variable. + */ + template * = nullptr, + require_vt_same* = nullptr> + explicit vari_value(const S& x) + : chainable_alloc(), adj_(constant(0, x.rows(), x.cols())), val_(x) { + ChainableStack::instance_->var_stack_.push_back(this); + } + + /** + * Construct an matrix_cl variable implementation from a value. The + * adjoint is initialized to zero and if `stacked` is `false` this vari + * will be not be put on the var_stack. Instead it will only be put on + * a stack to keep track of whether the adjoint needs to be set to zero. + * + * All constructed variables are added to a stack. Variables + * should be constructed before variables on which they depend + * to insure proper partial derivative propagation. During + * derivative propagation, the chain() method of each variable + * will be called in the reverse order of construction. + * + * @tparam S A `matrix_cl` or kernel generator expression type that is + * convertible to `value_type` + * @param x Value of the constructed variable. + * @param stacked If false will put this this vari on the nochain stack so + * that its `chain()` method is not called. + */ + template * = nullptr> + vari_value(S&& x, bool stacked) + : chainable_alloc(), + adj_(constant(0, x.rows(), x.cols())), + val_(std::forward(x)) { + if (stacked) { + ChainableStack::instance_->var_stack_.push_back(this); + } else { + ChainableStack::instance_->var_nochain_stack_.push_back(this); + } + } + + /** + * Returns a view into a block of matrix. + * @param row starting row of the block + * @param col starting column of the block + * @param rows number of rows in the block + * @param cols number of columns in the block + * @return block + */ + auto block(int row, int col, int rows, int cols) { + auto&& val_block = stan::math::block(val_, row, col, rows, cols); + auto&& adj_block = stan::math::block(adj_, row, col, rows, cols); + return vari_value>(std::move(val_block), + std::move(adj_block)); + } + + /** + * Return the number of rows for this class's `val_` member + */ + const Eigen::Index rows() const { return val_.rows(); } + /** + * Return the number of columns for this class's `val_` member + */ + const Eigen::Index cols() const { return val_.cols(); } + /** + * Return the size of this class's `val_` member + */ + const Eigen::Index size() const { return val_.size(); } + + virtual void chain() {} + + /** + * Set the adjoint value of this variable to 0. This is used to + * reset adjoints before propagating derivatives again (for + * example in a Jacobian calculation). + */ + inline void set_zero_adjoint() final { adj_ = constant(0, rows(), cols()); } + + /** + * Allocate memory from the underlying memory pool. This memory is + * is managed as a whole externally. + * + * Warning: Classes should not be allocated with this operator + * if they have non-trivial destructors. + * + * @param nbytes Number of bytes to allocate. + * @return Pointer to allocated bytes. + */ + static inline void* operator new(size_t nbytes) { + return ChainableStack::instance_->memalloc_.alloc(nbytes); + } + + /** + * Delete a pointer from the underlying memory pool. + * + * This no-op implementation enables a subclass to throw + * exceptions in its constructor. An exception thrown in the + * constructor of a subclass will result in an error being + * raised, which is in turn caught and calls delete(). + * + * See the discussion of "plugging the memory leak" in: + * http://www.parashift.com/c++-faq/memory-pools.html + */ + static inline void operator delete(void* /* ignore arg */) { /* no op */ + } + + protected: + // to allow access to this constructor from instantinations with different + // template parameters + template + friend class vari_value; + + /** + * Construct a matrix_cl variable implementation from a value and + * adjoint. + * + * This constructor does not add the matrix to any stack! It is intended only + * for views into matrices already on stack. + * + * @param val Value of the constructed variable. + * @param adj Adjoint of the constructed variable. + */ + vari_value(T&& val, T&& adj) + : chainable_alloc(), + adj_(std::forward(adj)), + val_(std::forward(val)) {} + + private: + template + friend class var_value; +}; + +} // namespace math +} // namespace stan + +#endif +#endif diff --git a/stan/math/opencl/value_type.hpp b/stan/math/opencl/value_type.hpp index 0392008483e..2effcf27184 100644 --- a/stan/math/opencl/value_type.hpp +++ b/stan/math/opencl/value_type.hpp @@ -3,7 +3,7 @@ #ifdef STAN_OPENCL #include -#include +#include #include namespace stan { @@ -12,7 +12,7 @@ namespace stan { * Return the value type of an OpenCL matrix. */ template -struct value_type> { +struct value_type> { using type = typename std::decay_t::Scalar; }; } // namespace stan diff --git a/stan/math/prim/meta/ref_type.hpp b/stan/math/prim/meta/ref_type.hpp index 1660f9eb183..03a83a76607 100644 --- a/stan/math/prim/meta/ref_type.hpp +++ b/stan/math/prim/meta/ref_type.hpp @@ -73,12 +73,13 @@ struct ref_type_for_opencl { = std::conditional_t::value, T_val, const T&>; // Setting Outer stride of Ref to 0 (default) won't actually check that // expression has contiguous outer stride. Instead we need to check that - // evaluator flags contain LinearAccessBit. + // evaluator flags contain LinearAccessBit and PacketAccessBit. using type = std::conditional_t< Eigen::internal::traits>>:: template match::MatchAtCompileTime + && (Eigen::internal::evaluator::Flags & Eigen::LinearAccessBit) && (Eigen::internal::evaluator::Flags - & Eigen::LinearAccessBit), + & Eigen::PacketAccessBit), T_optionally_ref, T_plain_col_major>; }; diff --git a/stan/math/rev/core/var.hpp b/stan/math/rev/core/var.hpp index 9fb4aeee2db..da5af408c83 100644 --- a/stan/math/rev/core/var.hpp +++ b/stan/math/rev/core/var.hpp @@ -8,6 +8,9 @@ #include #include #include +#ifdef STAN_OPENCL +#include +#endif namespace stan { namespace math { diff --git a/stan/math/rev/fun/lambert_w.hpp b/stan/math/rev/fun/lambert_w.hpp index 0f2455f3cc6..b1c845585cf 100644 --- a/stan/math/rev/fun/lambert_w.hpp +++ b/stan/math/rev/fun/lambert_w.hpp @@ -5,6 +5,7 @@ #include #include #include +#include #include namespace stan { diff --git a/test/unit/math/opencl/kernel_generator/constant_test.cpp b/test/unit/math/opencl/kernel_generator/constant_test.cpp new file mode 100644 index 00000000000..a14dbabff5b --- /dev/null +++ b/test/unit/math/opencl/kernel_generator/constant_test.cpp @@ -0,0 +1,17 @@ +#ifdef STAN_OPENCL + +#include +#include +#include +#include +#include +#include + +TEST(KernelGenerator, constant_test) { + stan::math::matrix_cl m1_cl(stan::math::constant(1.2, 3, 4)); + + Eigen::MatrixXd res = stan::math::from_matrix_cl(m1_cl); + EXPECT_MATRIX_EQ(res, Eigen::MatrixXd::Constant(3, 4, 1.2)); +} + +#endif diff --git a/test/unit/math/opencl/rev/copy_test.cpp b/test/unit/math/opencl/rev/copy_test.cpp index c5e43d49db3..b55432ad6bc 100644 --- a/test/unit/math/opencl/rev/copy_test.cpp +++ b/test/unit/math/opencl/rev/copy_test.cpp @@ -1,5 +1,6 @@ #ifdef STAN_OPENCL #include +#include #include #include #include @@ -14,7 +15,8 @@ TEST(MathMatrixRevCL, matrix_cl_vector_copy) { // vector stan::math::matrix_cl d11_cl(3, 1); stan::math::matrix_cl d111_cl(3, 1); - EXPECT_NO_THROW(d11_cl = stan::math::to_matrix_cl(d1_cpu)); + d11_cl.val() = stan::math::to_matrix_cl(d1_cpu.val()); + d11_cl.adj() = stan::math::to_matrix_cl(d1_cpu.adj()); EXPECT_NO_THROW(d11_cl.adj() = stan::math::copy_cl(d11_cl.val())); EXPECT_NO_THROW(d111_cl = stan::math::copy_cl(d11_cl)); EXPECT_NO_THROW(d1_a_cpu = stan::math::from_matrix_cl(d11_cl)); @@ -39,7 +41,8 @@ TEST(MathMatrixRevCL, matrix_cl_matrix_copy) { stan::math::matrix_cl d000_cl; stan::math::matrix_cl d22_cl(2, 3); stan::math::matrix_cl d222_cl(2, 3); - EXPECT_NO_THROW(d22_cl = stan::math::to_matrix_cl(d2_cpu)); + d22_cl.val() = stan::math::to_matrix_cl(d2_cpu.val()); + d22_cl.adj() = stan::math::to_matrix_cl(d2_cpu.adj()); EXPECT_NO_THROW(d222_cl = stan::math::copy_cl(d22_cl)); EXPECT_NO_THROW(d2_a_cpu = stan::math::from_matrix_cl(d22_cl.val())); EXPECT_NO_THROW(d2_b_cpu = stan::math::from_matrix_cl(d222_cl.val())); @@ -55,8 +58,8 @@ TEST(MathMatrixRevCL, matrix_cl_matrix_copy) { EXPECT_EQ(4, d2_b_cpu(1, 0)); EXPECT_EQ(5, d2_b_cpu(1, 1)); EXPECT_EQ(6, d2_b_cpu(1, 2)); - d00_cl = stan::math::to_matrix_cl(d0_cpu); - EXPECT_NO_THROW(d00_cl = stan::math::to_matrix_cl(d0_cpu)); + d00_cl.val() = stan::math::to_matrix_cl(d0_cpu.val()); + d00_cl.adj() = stan::math::to_matrix_cl(d0_cpu.adj()); EXPECT_NO_THROW(d0_cpu = stan::math::from_matrix_cl(d00_cl.val())); EXPECT_NO_THROW(d000_cl = stan::math::copy_cl(d00_cl)); } @@ -150,4 +153,44 @@ TEST(MathMatrixRevCL, matrix_cl_pack_unpack_copy_exception) { std::invalid_argument); */ } + +TEST(VariCL, var_matrix_to_matrix_cl) { + using stan::math::var_value; + Eigen::MatrixXd vals(2, 3); + vals << 1, 2, 3, 4, 5, 6; + var_value a(vals); + var_value> a_cl = stan::math::to_matrix_cl(a); + EXPECT_MATRIX_EQ(from_matrix_cl(a_cl.val()), vals); + a_cl.adj() = stan::math::constant(1, 2, 3); + a_cl.vi_->chain(); + EXPECT_MATRIX_EQ(a.adj(), Eigen::MatrixXd::Constant(2, 3, 1)); +} + +TEST(VariCL, matrix_var_to_matrix_cl) { + using stan::math::var_value; + Eigen::MatrixXd vals(2, 3); + vals << 1, 2, 3, 4, 5, 6; + stan::math::matrix_v vars = vals; + var_value> a_cl + = stan::math::to_matrix_cl(vars); + EXPECT_MATRIX_EQ(from_matrix_cl(a_cl.val()), vals); + a_cl.adj() = stan::math::constant(1, 2, 3); + a_cl.vi_->chain(); + EXPECT_MATRIX_EQ(vars.adj(), Eigen::MatrixXd::Constant(2, 3, 1)); +} + +TEST(VariCL, from_matrix_cl) { + using stan::math::var_value; + Eigen::MatrixXd vals(2, 3); + vals << 1, 2, 3, 4, 5, 6; + stan::math::matrix_cl vals_cl(vals); + var_value> a_cl(vals_cl); + var_value a = stan::math::from_matrix_cl(a_cl); + EXPECT_MATRIX_EQ(a.val(), vals); + a.adj() = Eigen::MatrixXd::Constant(2, 3, 1); + a.vi_->chain(); + EXPECT_MATRIX_EQ(from_matrix_cl(a_cl.adj()), + Eigen::MatrixXd::Constant(2, 3, 1)); +} + #endif diff --git a/test/unit/math/opencl/rev/sub_block_test.cpp b/test/unit/math/opencl/rev/sub_block_test.cpp index f492b26de63..32ccc28cded 100644 --- a/test/unit/math/opencl/rev/sub_block_test.cpp +++ b/test/unit/math/opencl/rev/sub_block_test.cpp @@ -64,7 +64,8 @@ TEST(MathMatrixRevCL, sub_block_triangular) { stan::math::matrix_cl b_cl(b); Eigen::Matrix c; - a_cl = stan::math::to_matrix_cl(a); + a_cl.val() = stan::math::to_matrix_cl(a.val()); + a_cl.adj() = stan::math::to_matrix_cl(a.adj()); a_cl.view(stan::math::matrix_cl_view::Lower); b_cl.view(stan::math::matrix_cl_view::Lower); a_cl.sub_block(b_cl, 0, 1, 0, 1, 2, 2); @@ -80,7 +81,8 @@ TEST(MathMatrixRevCL, sub_block_triangular) { EXPECT_EQ(c(2, 1), 0); EXPECT_EQ(c(2, 2), 0); - a_cl = stan::math::to_matrix_cl(a); + a_cl.val() = stan::math::to_matrix_cl(a.val()); + a_cl.adj() = stan::math::to_matrix_cl(a.adj()); a_cl.view(stan::math::matrix_cl_view::Lower); b_cl.view(stan::math::matrix_cl_view::Lower); a_cl.sub_block(b_cl, 1, 0, 1, 1, 2, 2); @@ -96,7 +98,8 @@ TEST(MathMatrixRevCL, sub_block_triangular) { EXPECT_EQ(c(2, 1), 1); EXPECT_EQ(c(2, 2), 1); - a_cl = stan::math::to_matrix_cl(a); + a_cl.val() = stan::math::to_matrix_cl(a.val()); + a_cl.adj() = stan::math::to_matrix_cl(a.adj()); a_cl.view(stan::math::matrix_cl_view::Lower); b_cl.view(stan::math::matrix_cl_view::Upper); a_cl.sub_block(b_cl, 0, 0, 1, 0, 2, 2); @@ -112,7 +115,8 @@ TEST(MathMatrixRevCL, sub_block_triangular) { EXPECT_EQ(c(2, 1), 1); EXPECT_EQ(c(2, 2), 0); - a_cl = stan::math::to_matrix_cl(a); + a_cl.val() = stan::math::to_matrix_cl(a.val()); + a_cl.adj() = stan::math::to_matrix_cl(a.adj()); a_cl.view(stan::math::matrix_cl_view::Lower); b_cl.view(stan::math::matrix_cl_view::Upper); a_cl.sub_block(b_cl, 0, 0, 0, 0, 2, 2); @@ -128,7 +132,8 @@ TEST(MathMatrixRevCL, sub_block_triangular) { EXPECT_EQ(c(2, 1), 0); EXPECT_EQ(c(2, 2), 0); - a_cl = stan::math::to_matrix_cl(a); + a_cl.val() = stan::math::to_matrix_cl(a.val()); + a_cl.adj() = stan::math::to_matrix_cl(a.adj()); a_cl.view(stan::math::matrix_cl_view::Lower); b_cl.view(stan::math::matrix_cl_view::Upper); a_cl.sub_block(b_cl, 1, 0, 1, 0, 2, 2); @@ -144,7 +149,8 @@ TEST(MathMatrixRevCL, sub_block_triangular) { EXPECT_EQ(c(2, 1), 0); EXPECT_EQ(c(2, 2), 0); - a_cl = stan::math::to_matrix_cl(a); + a_cl.val() = stan::math::to_matrix_cl(a.val()); + a_cl.adj() = stan::math::to_matrix_cl(a.adj()); a_cl.view(stan::math::matrix_cl_view::Lower); b_cl.view(stan::math::matrix_cl_view::Upper); a_cl.sub_block(b_cl, 1, 0, 1, 0, 2, 3); @@ -160,7 +166,8 @@ TEST(MathMatrixRevCL, sub_block_triangular) { EXPECT_EQ(c(2, 1), 0); EXPECT_EQ(c(2, 2), 1); - a_cl = stan::math::to_matrix_cl(a); + a_cl.val() = stan::math::to_matrix_cl(a.val()); + a_cl.adj() = stan::math::to_matrix_cl(a.adj()); a_cl.view(stan::math::matrix_cl_view::Upper); b_cl.view(stan::math::matrix_cl_view::Upper); a_cl.sub_block(b_cl, 1, 0, 1, 0, 2, 2); @@ -176,7 +183,8 @@ TEST(MathMatrixRevCL, sub_block_triangular) { EXPECT_EQ(c(2, 1), 0); EXPECT_EQ(c(2, 2), 0); - a_cl = stan::math::to_matrix_cl(a); + a_cl.val() = stan::math::to_matrix_cl(a.val()); + a_cl.adj() = stan::math::to_matrix_cl(a.adj()); a_cl.view(stan::math::matrix_cl_view::Upper); b_cl.view(stan::math::matrix_cl_view::Upper); a_cl.sub_block(b_cl, 0, 1, 1, 1, 2, 2); @@ -192,7 +200,8 @@ TEST(MathMatrixRevCL, sub_block_triangular) { EXPECT_EQ(c(2, 1), 1); EXPECT_EQ(c(2, 2), 1); - a_cl = stan::math::to_matrix_cl(a); + a_cl.val() = stan::math::to_matrix_cl(a.val()); + a_cl.adj() = stan::math::to_matrix_cl(a.adj()); a_cl.view(stan::math::matrix_cl_view::Upper); b_cl.view(stan::math::matrix_cl_view::Lower); a_cl.sub_block(b_cl, 0, 0, 0, 1, 2, 2); @@ -208,7 +217,8 @@ TEST(MathMatrixRevCL, sub_block_triangular) { EXPECT_EQ(c(2, 1), 0); EXPECT_EQ(c(2, 2), 0); - a_cl = stan::math::to_matrix_cl(a); + a_cl.val() = stan::math::to_matrix_cl(a.val()); + a_cl.adj() = stan::math::to_matrix_cl(a.adj()); a_cl.view(stan::math::matrix_cl_view::Upper); b_cl.view(stan::math::matrix_cl_view::Lower); a_cl.sub_block(b_cl, 0, 0, 0, 0, 2, 2); @@ -224,7 +234,8 @@ TEST(MathMatrixRevCL, sub_block_triangular) { EXPECT_EQ(c(2, 1), 0); EXPECT_EQ(c(2, 2), 0); - a_cl = stan::math::to_matrix_cl(a); + a_cl.val() = stan::math::to_matrix_cl(a.val()); + a_cl.adj() = stan::math::to_matrix_cl(a.adj()); a_cl.view(stan::math::matrix_cl_view::Upper); b_cl.view(stan::math::matrix_cl_view::Lower); a_cl.sub_block(b_cl, 0, 1, 0, 1, 2, 2); @@ -240,7 +251,8 @@ TEST(MathMatrixRevCL, sub_block_triangular) { EXPECT_EQ(c(2, 1), 0); EXPECT_EQ(c(2, 2), 0); - a_cl = stan::math::to_matrix_cl(a); + a_cl.val() = stan::math::to_matrix_cl(a.val()); + a_cl.adj() = stan::math::to_matrix_cl(a.adj()); a_cl.view(stan::math::matrix_cl_view::Upper); b_cl.view(stan::math::matrix_cl_view::Lower); a_cl.sub_block(b_cl, 0, 1, 0, 1, 3, 2); @@ -256,7 +268,8 @@ TEST(MathMatrixRevCL, sub_block_triangular) { EXPECT_EQ(c(2, 1), 1); EXPECT_EQ(c(2, 2), 1); - a_cl = stan::math::to_matrix_cl(a); + a_cl.val() = stan::math::to_matrix_cl(a.val()); + a_cl.adj() = stan::math::to_matrix_cl(a.adj()); a_cl.view(stan::math::matrix_cl_view::Upper); b_cl.view(stan::math::matrix_cl_view::Lower); a_cl.sub_block(b_cl, 0, 0, 0, 0, 3, 3); diff --git a/test/unit/math/opencl/rev/vari_test.cpp b/test/unit/math/opencl/rev/vari_test.cpp new file mode 100644 index 00000000000..4960f887324 --- /dev/null +++ b/test/unit/math/opencl/rev/vari_test.cpp @@ -0,0 +1,25 @@ +#ifdef STAN_OPENCL +#include +#include +#include +#include + +TEST(AgradRev, matrix_cl_vari_block) { + using stan::math::vari_value; + Eigen::MatrixXd a = Eigen::MatrixXd::Random(3, 3); + Eigen::MatrixXd b = Eigen::MatrixXd::Random(3, 3); + stan::math::matrix_cl a_cl(a); + stan::math::matrix_cl b_cl(b); + + vari_value> A(a); + EXPECT_MATRIX_EQ(a.block(0, 1, 2, 2), + stan::math::from_matrix_cl(A.block(0, 1, 2, 2).val_)); + vari_value> B(a_cl); + B.adj_ = b_cl; + EXPECT_MATRIX_EQ(a.block(0, 1, 2, 2), + stan::math::from_matrix_cl(B.block(0, 1, 2, 2).val_)); + EXPECT_MATRIX_EQ(b.block(0, 1, 2, 2), + stan::math::from_matrix_cl(B.block(0, 1, 2, 2).adj_)); +} + +#endif diff --git a/test/unit/math/rev/meta/is_fvar_test.cpp b/test/unit/math/rev/meta/is_fvar_test.cpp index 4a159531f99..46e38837ca7 100644 --- a/test/unit/math/rev/meta/is_fvar_test.cpp +++ b/test/unit/math/rev/meta/is_fvar_test.cpp @@ -1,4 +1,5 @@ #include +#include #include TEST(MetaTraitsRevScal, is_fvar) { diff --git a/test/unit/math/rev/meta/is_var_or_arithmetic_test.cpp b/test/unit/math/rev/meta/is_var_or_arithmetic_test.cpp index ff1188df1bc..4778049da7a 100644 --- a/test/unit/math/rev/meta/is_var_or_arithmetic_test.cpp +++ b/test/unit/math/rev/meta/is_var_or_arithmetic_test.cpp @@ -1,4 +1,5 @@ #include +#include #include #include #include diff --git a/test/unit/math/rev/meta/is_var_test.cpp b/test/unit/math/rev/meta/is_var_test.cpp index cb225ff7d1c..ec276e7ab7a 100644 --- a/test/unit/math/rev/meta/is_var_test.cpp +++ b/test/unit/math/rev/meta/is_var_test.cpp @@ -1,4 +1,5 @@ #include +#include #include TEST(MetaTraitsRevScal, is_var) { diff --git a/test/unit/math/rev/meta/is_vari_test.cpp b/test/unit/math/rev/meta/is_vari_test.cpp index 818d6c3b4d7..cf132d8eb15 100644 --- a/test/unit/math/rev/meta/is_vari_test.cpp +++ b/test/unit/math/rev/meta/is_vari_test.cpp @@ -1,4 +1,5 @@ #include +#include #include TEST(MetaTraitsRevScal, is_vari) { From 0172384f780c87fd3289bfdf62a26c40b5642220 Mon Sep 17 00:00:00 2001 From: tadej Date: Tue, 4 Aug 2020 10:15:15 +0200 Subject: [PATCH 176/355] improved argument passing --- stan/math/rev/core/precomputed_gradients.hpp | 54 ++++++++++--------- .../rev/functor/operands_and_partials.hpp | 42 ++++++++++----- .../rev/core/precomputed_gradients_test.cpp | 36 ++++++++++++- 3 files changed, 92 insertions(+), 40 deletions(-) diff --git a/stan/math/rev/core/precomputed_gradients.hpp b/stan/math/rev/core/precomputed_gradients.hpp index c164345a47e..dce22aec4b6 100644 --- a/stan/math/rev/core/precomputed_gradients.hpp +++ b/stan/math/rev/core/precomputed_gradients.hpp @@ -18,9 +18,9 @@ namespace math { * Stan users should use function precomputed_gradients() * directly. * - * @tparam ContainerOperands tuple of any container operands (var_value + * @tparam ContainerOperands tuple of any container operands (lvalue references to var_value * containing Eigen types) - * @tparam ContainerGradients tupleof any container gradients (Eigen types) + * @tparam ContainerGradients tuple of any container gradients (Eigen types) */ template , typename ContainerGradients = std::tuple<>> @@ -69,21 +69,22 @@ class precomputed_gradients_vari_template : public vari { * @param container_operands any container operands * @param container_gradients any container gradients */ - template , - typename ContainerGrads = std::tuple<>> + template precomputed_gradients_vari_template(double val, size_t size, vari** varis, double* gradients, - ContainerOps&& container_operands + const std::tuple& container_operands = std::tuple<>(), - ContainerGrads&& container_gradients + const std::tuple& container_gradients = std::tuple<>()) : vari(val), size_(size), varis_(varis), gradients_(gradients), - container_operands_(std::forward(container_operands)), - container_gradients_( - std::forward(container_gradients)) { + container_operands_(container_operands){ + index_apply([&, this](auto... Is){ + this->container_gradients_ = {std::forward(std::get(container_gradients))...}; + }); check_sizes(std::make_index_sequence()); } @@ -108,14 +109,14 @@ class precomputed_gradients_vari_template : public vari { * don't match. */ template , - typename ContainerGrads = std::tuple<>, + typename... ContainerOps, + typename... ContainerGrads, require_all_vector_t* = nullptr> precomputed_gradients_vari_template(Arith val, const VecVar& vars, const VecArith& gradients, - ContainerOps&& container_operands + const std::tuple& container_operands = std::tuple<>(), - ContainerGrads&& container_gradients + const std::tuple& container_gradients = std::tuple<>()) : vari(val), size_(vars.size()), @@ -123,9 +124,10 @@ class precomputed_gradients_vari_template : public vari { vars.size())), gradients_(ChainableStack::instance_->memalloc_.alloc_array( vars.size())), - container_operands_(std::forward(container_operands)), - container_gradients_( - std::forward(container_gradients)) { + container_operands_(container_operands){ + index_apply([&, this](auto... Is){ + this->container_gradients_ = {std::forward(std::get(container_gradients))...}; + }); check_consistent_sizes("precomputed_gradients_vari", "vars", vars, "gradients", gradients); check_sizes(std::make_index_sequence()); @@ -162,7 +164,7 @@ class precomputed_gradients_vari_template : public vari { template * = nullptr> void chain_one(Op& op, const Grad& grad) { - op.adj() += this->adj_ * grad; + op.vi_->adj_ += this->adj_ * grad; } /** @@ -173,7 +175,7 @@ class precomputed_gradients_vari_template : public vari { * @param grad gradient */ template - void chain_one(std::vector& op, const std::vector& grad) { + void chain_one(const std::vector& op, const std::vector& grad) { for (int i = 0; i < op.size(); i++) { chain_one(op[i], grad[i]); } @@ -204,20 +206,20 @@ using precomputed_gradients_vari * gradients provided. */ template , - typename ContainerGradients = std::tuple<>> + typename... ContainerOperands, + typename... ContainerGradients> inline var precomputed_gradients(Arith value, const VecVar& operands, const VecArith& gradients, - ContainerOperands&& container_operands + const std::tuple& container_operands = std::tuple<>(), - ContainerGradients&& container_gradients + const std::tuple& container_gradients = std::tuple<>()) { return { - new precomputed_gradients_vari_template, - std::decay_t>( + new precomputed_gradients_vari_template, + std::tuple...>>( value, operands, gradients, - std::forward(container_operands), - std::forward(container_gradients))}; + container_operands, + container_gradients)}; } } // namespace math diff --git a/stan/math/rev/functor/operands_and_partials.hpp b/stan/math/rev/functor/operands_and_partials.hpp index e9e00e1f58a..f7e03485e80 100644 --- a/stan/math/rev/functor/operands_and_partials.hpp +++ b/stan/math/rev/functor/operands_and_partials.hpp @@ -142,11 +142,27 @@ class operands_and_partials { edge3_.container_partials(), edge4_.container_partials(), edge5_.container_partials()); - return var( - new precomputed_gradients_vari_template( - value, edges_size, varis, partials, std::move(container_operands), - std::move(container_partials))); + return var(return_vari(value, edges_size, varis, partials, container_operands, container_partials)); + } + +private: + /** + * Deduces types and constructs the vari to return from `build()`. + * @param value the value + * @param edges_size number of elements in all non-var_value of container edges + * @param varis pointer to varis from non-var_value of container edges + * @param partials pointer to values for partials from non-var_value of container edges + * @param container_operands operands from var_value of container edges + * @param container_partials partial derivatives from var_value of container edges + */ + template + auto* return_vari(double value, size_t edges_size, vari** varis, double* partials, + const std::tuple& container_operands, + const std::tuple& container_partials){ + //Partials are decayed, so precomputed_gradients_vari_template always stores values, not references + return new precomputed_gradients_vari_template, + std::tuple...>>( + value, edges_size, varis, partials, container_operands, container_partials); } }; @@ -234,11 +250,11 @@ class ops_partials_edge, require_eigen_t> { void dump_operands(vari** varis) {} void dump_partials(double* partials) {} int size() { return 0; } - std::tuple> container_operands() { - return std::make_tuple(operands_); + std::tuple&> container_operands() { + return std::forward_as_tuple(operands_); } - std::tuple container_partials() { - return std::make_tuple(partials_); + std::tuple container_partials() { + return std::forward_as_tuple(std::move(partials_)); } }; @@ -354,11 +370,11 @@ class ops_partials_edge>, void dump_operands(vari** varis) {} void dump_partials(double* partials) {} int size() { return 0; } - std::tuple>> container_operands() { - return std::make_tuple(operands_); + std::tuple>&> container_operands() { + return std::forward_as_tuple(operands_); } - std::tuple container_partials() { - return std::make_tuple(partials_vec_); + std::tuple container_partials() { + return std::forward_as_tuple(std::move(partials_vec_)); } }; } // namespace internal diff --git a/test/unit/math/rev/core/precomputed_gradients_test.cpp b/test/unit/math/rev/core/precomputed_gradients_test.cpp index b59abee62cd..a530ce16bf7 100644 --- a/test/unit/math/rev/core/precomputed_gradients_test.cpp +++ b/test/unit/math/rev/core/precomputed_gradients_test.cpp @@ -115,7 +115,7 @@ TEST(StanAgradRevInternal, precomputed_gradients_containers) { Eigen::MatrixXd grad_a = Eigen::MatrixXd::Constant(3, 3, -1); std::vector grad_b{Eigen::MatrixXd::Constant(3, 3, -2), Eigen::MatrixXd::Constant(3, 3, -3)}; - std::tuple&> grads(grad_a, + std::tuple&> grads(std::move(grad_a), grad_b); stan::math::var lp @@ -128,6 +128,40 @@ TEST(StanAgradRevInternal, precomputed_gradients_containers) { stan::math::recover_memory(); } +TEST(StanAgradRevInternal, precomputed_gradients_containers_direct_construction) { + double value = 1; + std::vector vars; + std::vector gradients; + stan::math::var_value a(Eigen::MatrixXd::Constant(3, 3, 2)); + std::vector> b{ + Eigen::MatrixXd::Constant(3, 3, 4), Eigen::MatrixXd::Constant(3, 3, 5)}; + std::tuple&, + std::vector>&> + ops{a, b}; + Eigen::MatrixXd grad_a = Eigen::MatrixXd::Constant(3, 3, -1); + std::vector grad_b{Eigen::MatrixXd::Constant(3, 3, -2), + Eigen::MatrixXd::Constant(3, 3, -3)}; + std::tuple&> grads(std::move(grad_a), + grad_b); + + stan::math::var lp + = new stan::math::precomputed_gradients_vari_template< + std::tuple< + stan::math::var_value&, + std::vector>& + >, + std::tuple< + Eigen::MatrixXd, + std::vector + >>(value, 0, nullptr, nullptr, ops, grads); + (2 * lp).grad(); + EXPECT_MATRIX_EQ(a.adj(), Eigen::MatrixXd::Constant(3, 3, -2)); + EXPECT_MATRIX_EQ(b[0].adj(), Eigen::MatrixXd::Constant(3, 3, -4)); + EXPECT_MATRIX_EQ(b[1].adj(), Eigen::MatrixXd::Constant(3, 3, -6)); + + stan::math::recover_memory(); +} + TEST(StanAgradRevInternal, precomputed_gradients_mismatched_containers) { double value = 1; std::vector vars; From 33e266d9d2933aab6b7c67266e9067ece651fd47 Mon Sep 17 00:00:00 2001 From: Steve Bronder Date: Tue, 4 Aug 2020 12:34:17 -0400 Subject: [PATCH 177/355] remove changes to cholesky and vari_pointer type trait in var --- stan/math/prim/fun/cholesky_decompose.hpp | 8 +++++--- stan/math/rev/core/var.hpp | 1 - 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/stan/math/prim/fun/cholesky_decompose.hpp b/stan/math/prim/fun/cholesky_decompose.hpp index 5b15002b77d..c382bd84d09 100644 --- a/stan/math/prim/fun/cholesky_decompose.hpp +++ b/stan/math/prim/fun/cholesky_decompose.hpp @@ -29,7 +29,9 @@ namespace math { * @throw std::domain_error if m is not a symmetric matrix or * if m is not positive definite (if m has more than 0 elements) */ -template * = nullptr> +template * = nullptr, + require_not_vt_same* = nullptr, + require_not_eigen_vt* = nullptr> inline Eigen::Matrix, EigMat::RowsAtCompileTime, EigMat::ColsAtCompileTime> cholesky_decompose(const EigMat& m) { @@ -60,8 +62,8 @@ cholesky_decompose(const EigMat& m) { * if m is not positive definite (if m has more than 0 elements) */ template * = nullptr, - require_same_t>* = nullptr> -inline Eigen::Matrix, EigMat::RowsAtCompileTime, + require_vt_same* = nullptr> +inline Eigen::Matrix cholesky_decompose(const EigMat& m) { const eval_return_type_t& m_eval = m.eval(); diff --git a/stan/math/rev/core/var.hpp b/stan/math/rev/core/var.hpp index 66723a584df..a7dbaf7b149 100644 --- a/stan/math/rev/core/var.hpp +++ b/stan/math/rev/core/var.hpp @@ -38,7 +38,6 @@ class var_value> { public: using value_type = std::decay_t; // Numeric type in vari_value. using vari_type = vari_value; // Type of underlying vari impl. - using vari_pointer = vari_type*; // pointer type for underlying vari. /** * Pointer to the implementation of this variable. From 6a71d765c216efcfdfedb57817d77d8bca4de1b8 Mon Sep 17 00:00:00 2001 From: tadej Date: Wed, 5 Aug 2020 12:43:54 +0200 Subject: [PATCH 178/355] fixed memory leak (added AD stack types) --- stan/math/prim/fun/dims.hpp | 5 +- stan/math/rev/core/ad_allocator.hpp | 37 +++++++++ stan/math/rev/core/precomputed_gradients.hpp | 27 +++---- stan/math/rev/fun.hpp | 1 + stan/math/rev/fun/to_ad_stack.hpp | 77 +++++++++++++++++++ stan/math/rev/functor.hpp | 1 + stan/math/rev/functor/ad_stack_matrix.hpp | 67 ++++++++++++++++ .../rev/functor/operands_and_partials.hpp | 4 +- stan/math/rev/meta.hpp | 1 + stan/math/rev/meta/ad_stack_type.hpp | 42 ++++++++++ test/expressions/tests0_test.cpp | 55 +++++++++++++ .../rev/core/precomputed_gradients_test.cpp | 8 +- .../math/rev/functor/ad_stack_matrix_test.cpp | 75 ++++++++++++++++++ 13 files changed, 379 insertions(+), 21 deletions(-) create mode 100644 stan/math/rev/core/ad_allocator.hpp create mode 100644 stan/math/rev/fun/to_ad_stack.hpp create mode 100644 stan/math/rev/functor/ad_stack_matrix.hpp create mode 100644 stan/math/rev/meta/ad_stack_type.hpp create mode 100644 test/expressions/tests0_test.cpp create mode 100644 test/unit/math/rev/functor/ad_stack_matrix_test.cpp diff --git a/stan/math/prim/fun/dims.hpp b/stan/math/prim/fun/dims.hpp index cdcc02db93e..1aba09a8413 100644 --- a/stan/math/prim/fun/dims.hpp +++ b/stan/math/prim/fun/dims.hpp @@ -37,11 +37,12 @@ inline void dims(const T& x, std::vector& result) { * * For a `std::vector` that is its size and dimensions of its elements. * @tparam type of scalar + * @tparam Alloc type of allocator * @param x argument * @param result result */ -template -inline void dims(const std::vector& x, std::vector& result) { +template +inline void dims(const std::vector& x, std::vector& result) { result.push_back(x.size()); if (x.size() > 0) { dims(x[0], result); diff --git a/stan/math/rev/core/ad_allocator.hpp b/stan/math/rev/core/ad_allocator.hpp new file mode 100644 index 00000000000..115a92e6249 --- /dev/null +++ b/stan/math/rev/core/ad_allocator.hpp @@ -0,0 +1,37 @@ +#ifndef STAN_MATH_REV_CORE_AD_ALLOCATOR_HPP +#define STAN_MATH_REV_CORE_AD_ALLOCATOR_HPP + +#include + +namespace stan { +namespace math { + +/** + * std library compatible allocator that uses AD stack. + * @tparam T type of scalar + */ +template +struct AD_allocator{ + using value_type = T; + + /** + * Allocates space for `n` items of type `T`. + * + * @param n number of items to allocate space for + * @return pointer to allocated space + */ + T* allocate(std::size_t n) { + return ChainableStack::instance_->memalloc_.alloc_array(n); + } + + /** + * No-op. Memory is dealocated by caling `recover_memory()`. + */ + void deallocate(T* /*p*/, std::size_t /*n*/) noexcept {} +}; + +} +} + + +#endif diff --git a/stan/math/rev/core/precomputed_gradients.hpp b/stan/math/rev/core/precomputed_gradients.hpp index dce22aec4b6..74300608f95 100644 --- a/stan/math/rev/core/precomputed_gradients.hpp +++ b/stan/math/rev/core/precomputed_gradients.hpp @@ -4,6 +4,7 @@ #include #include #include +#include #include #include #include @@ -18,7 +19,7 @@ namespace math { * Stan users should use function precomputed_gradients() * directly. * - * @tparam ContainerOperands tuple of any container operands (lvalue references to var_value + * @tparam ContainerOperands tuple of any container operands ((optionally std vector of) var_value * containing Eigen types) * @tparam ContainerGradients tuple of any container gradients (Eigen types) */ @@ -73,17 +74,17 @@ class precomputed_gradients_vari_template : public vari { typename... ContainerGrads> precomputed_gradients_vari_template(double val, size_t size, vari** varis, double* gradients, - const std::tuple& container_operands + const std::tuple& container_operands = std::tuple<>(), const std::tuple& container_gradients = std::tuple<>()) : vari(val), size_(size), varis_(varis), - gradients_(gradients), - container_operands_(container_operands){ + gradients_(gradients){ index_apply([&, this](auto... Is){ - this->container_gradients_ = {std::forward(std::get(container_gradients))...}; + this->container_operands_ = std::make_tuple(to_AD_stack(std::get(container_operands))...); + this->container_gradients_ = std::make_tuple(to_AD_stack(std::get(container_gradients))...); }); check_sizes(std::make_index_sequence()); } @@ -114,7 +115,7 @@ class precomputed_gradients_vari_template : public vari { require_all_vector_t* = nullptr> precomputed_gradients_vari_template(Arith val, const VecVar& vars, const VecArith& gradients, - const std::tuple& container_operands + const std::tuple& container_operands = std::tuple<>(), const std::tuple& container_gradients = std::tuple<>()) @@ -123,10 +124,10 @@ class precomputed_gradients_vari_template : public vari { varis_(ChainableStack::instance_->memalloc_.alloc_array( vars.size())), gradients_(ChainableStack::instance_->memalloc_.alloc_array( - vars.size())), - container_operands_(container_operands){ + vars.size())){ index_apply([&, this](auto... Is){ - this->container_gradients_ = {std::forward(std::get(container_gradients))...}; + this->container_operands_ = std::make_tuple(to_AD_stack(std::get(container_operands))...); + this->container_gradients_ = std::make_tuple(to_AD_stack(std::get(container_gradients))...); }); check_consistent_sizes("precomputed_gradients_vari", "vars", vars, "gradients", gradients); @@ -174,8 +175,8 @@ class precomputed_gradients_vari_template : public vari { * @param op operand * @param grad gradient */ - template - void chain_one(const std::vector& op, const std::vector& grad) { + template + void chain_one(const std::vector& op, const std::vector& grad) { for (int i = 0; i < op.size(); i++) { chain_one(op[i], grad[i]); } @@ -215,8 +216,8 @@ inline var precomputed_gradients(Arith value, const VecVar& operands, const std::tuple& container_gradients = std::tuple<>()) { return { - new precomputed_gradients_vari_template, - std::tuple...>>( + new precomputed_gradients_vari_template...>, + std::tuple...>>( value, operands, gradients, container_operands, container_gradients)}; diff --git a/stan/math/rev/fun.hpp b/stan/math/rev/fun.hpp index a4c85598cf3..d1c83df0079 100644 --- a/stan/math/rev/fun.hpp +++ b/stan/math/rev/fun.hpp @@ -139,6 +139,7 @@ #include #include #include +#include #include #include #include diff --git a/stan/math/rev/fun/to_ad_stack.hpp b/stan/math/rev/fun/to_ad_stack.hpp new file mode 100644 index 00000000000..555e98a59b7 --- /dev/null +++ b/stan/math/rev/fun/to_ad_stack.hpp @@ -0,0 +1,77 @@ +#ifndef STAN_MATH_REF_FUN_TO_AD_STACK_HPP +#define STAN_MATH_REF_FUN_TO_AD_STACK_HPP + +#include +#include +#include + +namespace stan { +namespace math { + +/** + * Converts given argument into a type that has any dynamic allocation on AD stack. + * + * For scalars this is a no-op. + * @tparam type of scalar + * @param a argument + * @return argument + */ +template* = nullptr> +T to_AD_stack(T&& a){ + return std::forward(a); +} + +/** + * Converts given argument into a type that has any dynamic allocation on AD stack. + * + * Converts eigen types to `AD_stack_matrix`. + * @tparam type of argument + * @param a argument + * @return argument copied/evaluated on AD stack + */ +template* = nullptr> +AD_stack_t to_AD_stack(const T& a){ + return AD_stack_t(a); +} + +/** + * Converts given argument into a type that has any dynamic allocation on AD stack. + * + * Std vectors are copied into another std vector with custom allocator that uses AD stack. + * + * This overload works on vectors with simple scalars that don't need to be converthed themselves. + * + * @tparam type of argument + * @param a argument + * @return argument copied on AD stack + */ +template>* = nullptr> +AD_stack_t> to_AD_stack(const std::vector& a){ + return {a.begin(), a.end()}; +} + +/** + * Converts given argument into a type that has any dynamic allocation on AD stack. + * + * Std vectors are copied into another std vector with custom allocator that uses AD stack. + * + * This overload works on vectors with scalars that also need conversion. + * + * @tparam type of argument + * @param a argument + * @return argument copied on AD stack + */ +template>* = nullptr> +AD_stack_t> to_AD_stack(const std::vector& a){ + AD_stack_t> res; + res.reserve(a.size()); + for(const T& i : a){ + res.push_back(to_AD_stack(i)); + } + return res; +} + +} +} + +#endif diff --git a/stan/math/rev/functor.hpp b/stan/math/rev/functor.hpp index 0892095ab47..2331b8d8774 100644 --- a/stan/math/rev/functor.hpp +++ b/stan/math/rev/functor.hpp @@ -1,6 +1,7 @@ #ifndef STAN_MATH_REV_FUNCTOR_HPP #define STAN_MATH_REV_FUNCTOR_HPP +#include #include #include #include diff --git a/stan/math/rev/functor/ad_stack_matrix.hpp b/stan/math/rev/functor/ad_stack_matrix.hpp new file mode 100644 index 00000000000..f1e2009cf42 --- /dev/null +++ b/stan/math/rev/functor/ad_stack_matrix.hpp @@ -0,0 +1,67 @@ +#ifndef STAN_MATH_REV_FUNCTOR_AD_STACK_MATRIX_HPP +#define STAN_MATH_REV_FUNCTOR_AD_STACK_MATRIX_HPP + +#include +#include + +namespace stan { +namespace math { + +template +class AD_stack_matrix : public Eigen::Map{ +public: + using Scalar = value_type_t; + static constexpr int RowsAtCompileTime = MatrixType::RowsAtCompileTime; + static constexpr int ColsAtCompileTime = MatrixType::ColsAtCompileTime; + + AD_stack_matrix() : + Eigen::Map::Map(nullptr, RowsAtCompileTime==Eigen::Dynamic ? 0 : RowsAtCompileTime, ColsAtCompileTime==Eigen::Dynamic ? 0 : ColsAtCompileTime ) {} + + AD_stack_matrix(Eigen::Index rows, Eigen::Index cols) : + Eigen::Map::Map(ChainableStack::instance_->memalloc_.alloc_array(rows*cols), rows, cols){} + + AD_stack_matrix(Eigen::Index size) : + Eigen::Map::Map(ChainableStack::instance_->memalloc_.alloc_array(size), size){} + + template* = nullptr> + explicit AD_stack_matrix(const T& other) : Eigen::Map::Map(ChainableStack::instance_->memalloc_.alloc_array(other.size()), other.rows(), other.cols() ){ + *this = other; + } + + AD_stack_matrix(const AD_stack_matrix& other) : + Eigen::Map::Map(ChainableStack::instance_->memalloc_.alloc_array(other.size()), other.rows(), other.cols()){ + *this = other; + } + + AD_stack_matrix(AD_stack_matrix&& other) : + Eigen::Map::Map(other.data(), other.rows(), other.cols()){} + + using Eigen::Map::operator=; + + AD_stack_matrix& operator=(const AD_stack_matrix& other){ + resize(other.rows(), other.cols()); + Eigen::Map::operator=(other); + return *this; + } + + AD_stack_matrix& operator=(AD_stack_matrix&& other){ + //placement new changes what data map points to - there is no allocation + new (this) Eigen::Map(other.data(), other.rows(), other.cols()); + return *this; + } + + void resize(Eigen::Index rows, Eigen::Index cols){ + //placement new changes what data map points to - there is no allocation + new (this) Eigen::Map(ChainableStack::instance_->memalloc_.alloc_array(rows*cols), rows, cols); + } + + void resize(Eigen::Index size){ + //placement new changes what data map points to - there is no allocation + new (this) Eigen::Map(ChainableStack::instance_->memalloc_.alloc_array(size), size); + } +}; + +} +} + +#endif diff --git a/stan/math/rev/functor/operands_and_partials.hpp b/stan/math/rev/functor/operands_and_partials.hpp index f7e03485e80..bacaeff8c84 100644 --- a/stan/math/rev/functor/operands_and_partials.hpp +++ b/stan/math/rev/functor/operands_and_partials.hpp @@ -160,8 +160,8 @@ class operands_and_partials { const std::tuple& container_operands, const std::tuple& container_partials){ //Partials are decayed, so precomputed_gradients_vari_template always stores values, not references - return new precomputed_gradients_vari_template, - std::tuple...>>( + return new precomputed_gradients_vari_template...>, + std::tuple...>>( value, edges_size, varis, partials, container_operands, container_partials); } }; diff --git a/stan/math/rev/meta.hpp b/stan/math/rev/meta.hpp index 7b3dcfabe68..c4197a50d60 100644 --- a/stan/math/rev/meta.hpp +++ b/stan/math/rev/meta.hpp @@ -2,6 +2,7 @@ #define STAN_MATH_REV_META_HPP #include +#include #include #include #include diff --git a/stan/math/rev/meta/ad_stack_type.hpp b/stan/math/rev/meta/ad_stack_type.hpp new file mode 100644 index 00000000000..43dbcb94775 --- /dev/null +++ b/stan/math/rev/meta/ad_stack_type.hpp @@ -0,0 +1,42 @@ +#ifndef AD_STACK_TYPE_HPP +#define AD_STACK_TYPE_HPP + +#include +#include +#include + +namespace stan { +namespace math { +//forward declaration +template +class AD_stack_matrix; +} + +namespace internal{ +template +struct AD_stack_type_impl{ + using type = T; +}; + +template +struct AD_stack_type_impl>{ + using T_ad = typename AD_stack_type_impl>::type; + using type = std::vector>; +}; + +template +struct AD_stack_type_impl>{ + using type = math::AD_stack_matrix>; +}; +} + +/** + * Determines a type that can be used in place of `T` that does any dynamic allocations on the AD stack. This way resulting types are trivially destructible and can be used in vari classes. + * (only works for POD types, `std::vector`s and Eigen types) + */ +template +using AD_stack_t = typename internal::AD_stack_type_impl>::type; + +} + +#endif // AD_STACK_TYPE_HPP diff --git a/test/expressions/tests0_test.cpp b/test/expressions/tests0_test.cpp new file mode 100644 index 00000000000..92fb0276ee8 --- /dev/null +++ b/test/expressions/tests0_test.cpp @@ -0,0 +1,55 @@ +#include + + +TEST(ExpressionTestPrim, bad_wrong_value0) { + Eigen::Matrix arg_mat0 = stan::test::make_arg>(); + + auto res_mat = stan::math::bad_wrong_value(arg_mat0); + + Eigen::Matrix arg_expr0 = stan::test::make_arg>(); + int counter0 = 0; + stan::test::counterOp counter_op0(&counter0); + + auto res_expr = stan::math::bad_wrong_value(arg_expr0.unaryExpr(counter_op0)); + + EXPECT_STAN_EQ(res_expr, res_mat); + + EXPECT_LE(counter0, 1); + +} + +TEST(ExpressionTestRev, bad_wrong_value0) { + Eigen::Matrix arg_mat0 = stan::test::make_arg>(); + + auto res_mat = stan::math::bad_wrong_value(arg_mat0); + + Eigen::Matrix arg_expr0 = stan::test::make_arg>(); + int counter0 = 0; + stan::test::counterOp counter_op0(&counter0); + + auto res_expr = stan::math::bad_wrong_value(arg_expr0.unaryExpr(counter_op0)); + + EXPECT_STAN_EQ(res_expr, res_mat); + + EXPECT_LE(counter0, 1); + (stan::test::recursive_sum(res_mat) + stan::test::recursive_sum(res_expr)).grad(); + EXPECT_STAN_ADJ_EQ(arg_expr0,arg_mat0); + +} + +TEST(ExpressionTestFwd, bad_wrong_value0) { + Eigen::Matrix, Eigen::Dynamic, Eigen::Dynamic> arg_mat0 = stan::test::make_arg, Eigen::Dynamic, Eigen::Dynamic>>(); + + auto res_mat = stan::math::bad_wrong_value(arg_mat0); + + Eigen::Matrix, Eigen::Dynamic, Eigen::Dynamic> arg_expr0 = stan::test::make_arg, Eigen::Dynamic, Eigen::Dynamic>>(); + int counter0 = 0; + stan::test::counterOp> counter_op0(&counter0); + + auto res_expr = stan::math::bad_wrong_value(arg_expr0.unaryExpr(counter_op0)); + + EXPECT_STAN_EQ(res_expr, res_mat); + + EXPECT_LE(counter0, 1); + +} diff --git a/test/unit/math/rev/core/precomputed_gradients_test.cpp b/test/unit/math/rev/core/precomputed_gradients_test.cpp index a530ce16bf7..da7c5c903bb 100644 --- a/test/unit/math/rev/core/precomputed_gradients_test.cpp +++ b/test/unit/math/rev/core/precomputed_gradients_test.cpp @@ -147,12 +147,12 @@ TEST(StanAgradRevInternal, precomputed_gradients_containers_direct_construction) stan::math::var lp = new stan::math::precomputed_gradients_vari_template< std::tuple< - stan::math::var_value&, - std::vector>& + stan::AD_stack_t>, + stan::AD_stack_t>> >, std::tuple< - Eigen::MatrixXd, - std::vector + stan::AD_stack_t, + stan::AD_stack_t> >>(value, 0, nullptr, nullptr, ops, grads); (2 * lp).grad(); EXPECT_MATRIX_EQ(a.adj(), Eigen::MatrixXd::Constant(3, 3, -2)); diff --git a/test/unit/math/rev/functor/ad_stack_matrix_test.cpp b/test/unit/math/rev/functor/ad_stack_matrix_test.cpp new file mode 100644 index 00000000000..ab22e86bc51 --- /dev/null +++ b/test/unit/math/rev/functor/ad_stack_matrix_test.cpp @@ -0,0 +1,75 @@ +#include +#include +#include + +TEST(AgradRev, AD_stack_matrix_matrix_test) { + using stan::math::AD_stack_matrix; + using Eigen::MatrixXd; + + //construction + AD_stack_matrix a; + AD_stack_matrix a2; + AD_stack_matrix b(3,2); + AD_stack_matrix b2(3,2); + AD_stack_matrix c(MatrixXd::Ones(3,2)); + AD_stack_matrix d(c); + AD_stack_matrix e(2*d); + + //assignment + a = c; + a2 = std::move(d); + b = d; + b2 = std::move(c); + e = e + a; + a = MatrixXd::Ones(3,2); + + EXPECT_MATRIX_EQ(a + a2 + b + b2 + e, MatrixXd::Ones(3,2) * 7); +} + +TEST(AgradRev, AD_stack_matrix_vector_test) { + using stan::math::AD_stack_matrix; + using Eigen::VectorXd; + + //construction + AD_stack_matrix a; + AD_stack_matrix a2; + AD_stack_matrix b(3); + AD_stack_matrix b2(3); + AD_stack_matrix c(VectorXd::Ones(3)); + AD_stack_matrix d(c); + AD_stack_matrix e(2*d); + + //assignment + a = c; + a2 = std::move(d); + b = d; + b2 = std::move(c); + e = e + a; + a = VectorXd::Ones(3); + + EXPECT_MATRIX_EQ(a + a2 + b + b2 + e, VectorXd::Ones(3) * 7); +} + +TEST(AgradRev, AD_stack_matrix_row_vector_test) { + using stan::math::AD_stack_matrix; + using Eigen::RowVectorXd; + + //construction + AD_stack_matrix a; + AD_stack_matrix a2; + AD_stack_matrix b(3); + AD_stack_matrix b2(3); + AD_stack_matrix c(RowVectorXd::Ones(3)); + AD_stack_matrix d(c); + AD_stack_matrix e(2*d); + + //assignment + a = c; + a2 = std::move(d); + b = d; + b2 = std::move(c); + e = e + a; + a = RowVectorXd::Ones(3); + + EXPECT_MATRIX_EQ(a + a2 + b + b2 + e, RowVectorXd::Ones(3) * 7); +} From 6eb8f5c8d5cf562f1a7844b60ad663231d57f22d Mon Sep 17 00:00:00 2001 From: tadej Date: Wed, 5 Aug 2020 13:02:03 +0200 Subject: [PATCH 179/355] added docs to AD_stack_matrix and removed a file added by mistake. --- stan/math/rev/functor/ad_stack_matrix.hpp | 47 ++++++++++++++++++- test/expressions/tests0_test.cpp | 55 ----------------------- 2 files changed, 45 insertions(+), 57 deletions(-) delete mode 100644 test/expressions/tests0_test.cpp diff --git a/stan/math/rev/functor/ad_stack_matrix.hpp b/stan/math/rev/functor/ad_stack_matrix.hpp index f1e2009cf42..6baf3830c20 100644 --- a/stan/math/rev/functor/ad_stack_matrix.hpp +++ b/stan/math/rev/functor/ad_stack_matrix.hpp @@ -14,49 +14,92 @@ class AD_stack_matrix : public Eigen::Map{ static constexpr int RowsAtCompileTime = MatrixType::RowsAtCompileTime; static constexpr int ColsAtCompileTime = MatrixType::ColsAtCompileTime; + /** + * Default constructor. + */ AD_stack_matrix() : Eigen::Map::Map(nullptr, RowsAtCompileTime==Eigen::Dynamic ? 0 : RowsAtCompileTime, ColsAtCompileTime==Eigen::Dynamic ? 0 : ColsAtCompileTime ) {} + /** + * Constructs `AD_stack_matrix` with given number of rows and columns. + * @param rows number of rows + * @param cols number of columns + */ AD_stack_matrix(Eigen::Index rows, Eigen::Index cols) : Eigen::Map::Map(ChainableStack::instance_->memalloc_.alloc_array(rows*cols), rows, cols){} + /** + * Constructs `AD_stack_matrix` with given size. This only works if `MatrixType` is row or col vector. + * @param size number of elements + */ AD_stack_matrix(Eigen::Index size) : Eigen::Map::Map(ChainableStack::instance_->memalloc_.alloc_array(size), size){} + /** + * Constructs `AD_stack_matrix` form an expression. + * @param other expression + */ template* = nullptr> explicit AD_stack_matrix(const T& other) : Eigen::Map::Map(ChainableStack::instance_->memalloc_.alloc_array(other.size()), other.rows(), other.cols() ){ *this = other; } + /** + * Copy constructor. Copies values, not the whole object (same as Eigen types). + * @param other matrix to copy from + */ AD_stack_matrix(const AD_stack_matrix& other) : Eigen::Map::Map(ChainableStack::instance_->memalloc_.alloc_array(other.size()), other.rows(), other.cols()){ *this = other; } + /** + * Move constructor. + * @param other matrix to move from + */ AD_stack_matrix(AD_stack_matrix&& other) : Eigen::Map::Map(other.data(), other.rows(), other.cols()){} using Eigen::Map::operator=; + /** + * Copy assignment operator. Copies values, not the whole object (same as Eigen types). + * @param other matrix to copy from + * @return `*this` + */ AD_stack_matrix& operator=(const AD_stack_matrix& other){ resize(other.rows(), other.cols()); Eigen::Map::operator=(other); return *this; } + /** + * Move assignment operator. + * @param other matrix to move from + * @return `*this` + */ AD_stack_matrix& operator=(AD_stack_matrix&& other){ //placement new changes what data map points to - there is no allocation new (this) Eigen::Map(other.data(), other.rows(), other.cols()); return *this; } + /** + * Resizes this object to given number of rows and columns. + * @param rows number of rows + * @param cols number of columns + */ void resize(Eigen::Index rows, Eigen::Index cols){ - //placement new changes what data map points to - there is no allocation + //placement new changes what data map points to - this new is not an allocation new (this) Eigen::Map(ChainableStack::instance_->memalloc_.alloc_array(rows*cols), rows, cols); } + /** + * Resizes this object to given size. This only works if `MatrixType` is row or col vector. + * @param size number of elements + */ void resize(Eigen::Index size){ - //placement new changes what data map points to - there is no allocation + //placement new changes what data map points to - this new is not an allocation new (this) Eigen::Map(ChainableStack::instance_->memalloc_.alloc_array(size), size); } }; diff --git a/test/expressions/tests0_test.cpp b/test/expressions/tests0_test.cpp deleted file mode 100644 index 92fb0276ee8..00000000000 --- a/test/expressions/tests0_test.cpp +++ /dev/null @@ -1,55 +0,0 @@ -#include - - -TEST(ExpressionTestPrim, bad_wrong_value0) { - Eigen::Matrix arg_mat0 = stan::test::make_arg>(); - - auto res_mat = stan::math::bad_wrong_value(arg_mat0); - - Eigen::Matrix arg_expr0 = stan::test::make_arg>(); - int counter0 = 0; - stan::test::counterOp counter_op0(&counter0); - - auto res_expr = stan::math::bad_wrong_value(arg_expr0.unaryExpr(counter_op0)); - - EXPECT_STAN_EQ(res_expr, res_mat); - - EXPECT_LE(counter0, 1); - -} - -TEST(ExpressionTestRev, bad_wrong_value0) { - Eigen::Matrix arg_mat0 = stan::test::make_arg>(); - - auto res_mat = stan::math::bad_wrong_value(arg_mat0); - - Eigen::Matrix arg_expr0 = stan::test::make_arg>(); - int counter0 = 0; - stan::test::counterOp counter_op0(&counter0); - - auto res_expr = stan::math::bad_wrong_value(arg_expr0.unaryExpr(counter_op0)); - - EXPECT_STAN_EQ(res_expr, res_mat); - - EXPECT_LE(counter0, 1); - (stan::test::recursive_sum(res_mat) + stan::test::recursive_sum(res_expr)).grad(); - EXPECT_STAN_ADJ_EQ(arg_expr0,arg_mat0); - -} - -TEST(ExpressionTestFwd, bad_wrong_value0) { - Eigen::Matrix, Eigen::Dynamic, Eigen::Dynamic> arg_mat0 = stan::test::make_arg, Eigen::Dynamic, Eigen::Dynamic>>(); - - auto res_mat = stan::math::bad_wrong_value(arg_mat0); - - Eigen::Matrix, Eigen::Dynamic, Eigen::Dynamic> arg_expr0 = stan::test::make_arg, Eigen::Dynamic, Eigen::Dynamic>>(); - int counter0 = 0; - stan::test::counterOp> counter_op0(&counter0); - - auto res_expr = stan::math::bad_wrong_value(arg_expr0.unaryExpr(counter_op0)); - - EXPECT_STAN_EQ(res_expr, res_mat); - - EXPECT_LE(counter0, 1); - -} From 996972b957c161a49695aefc719d40295b74a51b Mon Sep 17 00:00:00 2001 From: Stan Jenkins Date: Wed, 5 Aug 2020 11:37:27 +0000 Subject: [PATCH 180/355] [Jenkins] auto-formatting by clang-format version 6.0.0-1ubuntu2~16.04.1 (tags/RELEASE_600/final) --- stan/math/rev/core/ad_allocator.hpp | 41 ++-- stan/math/rev/core/precomputed_gradients.hpp | 84 +++---- stan/math/rev/fun/to_ad_stack.hpp | 59 ++--- stan/math/rev/functor/ad_stack_matrix.hpp | 218 ++++++++++-------- .../rev/functor/operands_and_partials.hpp | 31 ++- stan/math/rev/meta/ad_stack_type.hpp | 40 ++-- .../rev/core/precomputed_gradients_test.cpp | 30 ++- .../math/rev/functor/ad_stack_matrix_test.cpp | 108 ++++----- 8 files changed, 320 insertions(+), 291 deletions(-) diff --git a/stan/math/rev/core/ad_allocator.hpp b/stan/math/rev/core/ad_allocator.hpp index 115a92e6249..74503068e53 100644 --- a/stan/math/rev/core/ad_allocator.hpp +++ b/stan/math/rev/core/ad_allocator.hpp @@ -10,28 +10,27 @@ namespace math { * std library compatible allocator that uses AD stack. * @tparam T type of scalar */ -template -struct AD_allocator{ - using value_type = T; - - /** - * Allocates space for `n` items of type `T`. - * - * @param n number of items to allocate space for - * @return pointer to allocated space - */ - T* allocate(std::size_t n) { - return ChainableStack::instance_->memalloc_.alloc_array(n); - } - - /** - * No-op. Memory is dealocated by caling `recover_memory()`. - */ - void deallocate(T* /*p*/, std::size_t /*n*/) noexcept {} +template +struct AD_allocator { + using value_type = T; + + /** + * Allocates space for `n` items of type `T`. + * + * @param n number of items to allocate space for + * @return pointer to allocated space + */ + T* allocate(std::size_t n) { + return ChainableStack::instance_->memalloc_.alloc_array(n); + } + + /** + * No-op. Memory is dealocated by caling `recover_memory()`. + */ + void deallocate(T* /*p*/, std::size_t /*n*/) noexcept {} }; -} -} - +} // namespace math +} // namespace stan #endif diff --git a/stan/math/rev/core/precomputed_gradients.hpp b/stan/math/rev/core/precomputed_gradients.hpp index 74300608f95..95f70563a0d 100644 --- a/stan/math/rev/core/precomputed_gradients.hpp +++ b/stan/math/rev/core/precomputed_gradients.hpp @@ -19,8 +19,8 @@ namespace math { * Stan users should use function precomputed_gradients() * directly. * - * @tparam ContainerOperands tuple of any container operands ((optionally std vector of) var_value - * containing Eigen types) + * @tparam ContainerOperands tuple of any container operands ((optionally std + * vector of) var_value containing Eigen types) * @tparam ContainerGradients tuple of any container gradients (Eigen types) */ template , @@ -70,22 +70,18 @@ class precomputed_gradients_vari_template : public vari { * @param container_operands any container operands * @param container_gradients any container gradients */ - template - precomputed_gradients_vari_template(double val, size_t size, vari** varis, - double* gradients, - const std::tuple& container_operands - = std::tuple<>(), - const std::tuple& container_gradients - = std::tuple<>()) - : vari(val), - size_(size), - varis_(varis), - gradients_(gradients){ - index_apply([&, this](auto... Is){ - this->container_operands_ = std::make_tuple(to_AD_stack(std::get(container_operands))...); - this->container_gradients_ = std::make_tuple(to_AD_stack(std::get(container_gradients))...); - }); + template + precomputed_gradients_vari_template( + double val, size_t size, vari** varis, double* gradients, + const std::tuple& container_operands = std::tuple<>(), + const std::tuple& container_gradients = std::tuple<>()) + : vari(val), size_(size), varis_(varis), gradients_(gradients) { + index_apply([&, this](auto... Is) { + this->container_operands_ + = std::make_tuple(to_AD_stack(std::get(container_operands))...); + this->container_gradients_ + = std::make_tuple(to_AD_stack(std::get(container_gradients))...); + }); check_sizes(std::make_index_sequence()); } @@ -110,25 +106,24 @@ class precomputed_gradients_vari_template : public vari { * don't match. */ template * = nullptr> - precomputed_gradients_vari_template(Arith val, const VecVar& vars, - const VecArith& gradients, - const std::tuple& container_operands - = std::tuple<>(), - const std::tuple& container_gradients - = std::tuple<>()) + precomputed_gradients_vari_template( + Arith val, const VecVar& vars, const VecArith& gradients, + const std::tuple& container_operands = std::tuple<>(), + const std::tuple& container_gradients = std::tuple<>()) : vari(val), size_(vars.size()), varis_(ChainableStack::instance_->memalloc_.alloc_array( vars.size())), gradients_(ChainableStack::instance_->memalloc_.alloc_array( - vars.size())){ - index_apply([&, this](auto... Is){ - this->container_operands_ = std::make_tuple(to_AD_stack(std::get(container_operands))...); - this->container_gradients_ = std::make_tuple(to_AD_stack(std::get(container_gradients))...); - }); + vars.size())) { + index_apply([&, this](auto... Is) { + this->container_operands_ + = std::make_tuple(to_AD_stack(std::get(container_operands))...); + this->container_gradients_ + = std::make_tuple(to_AD_stack(std::get(container_gradients))...); + }); check_consistent_sizes("precomputed_gradients_vari", "vars", vars, "gradients", gradients); check_sizes(std::make_index_sequence()); @@ -176,7 +171,8 @@ class precomputed_gradients_vari_template : public vari { * @param grad gradient */ template - void chain_one(const std::vector& op, const std::vector& grad) { + void chain_one(const std::vector& op, + const std::vector& grad) { for (int i = 0; i < op.size(); i++) { chain_one(op[i], grad[i]); } @@ -207,20 +203,16 @@ using precomputed_gradients_vari * gradients provided. */ template -inline var precomputed_gradients(Arith value, const VecVar& operands, - const VecArith& gradients, - const std::tuple& container_operands - = std::tuple<>(), - const std::tuple& container_gradients - = std::tuple<>()) { - return { - new precomputed_gradients_vari_template...>, - std::tuple...>>( - value, operands, gradients, - container_operands, - container_gradients)}; + typename... ContainerOperands, typename... ContainerGradients> +inline var precomputed_gradients( + Arith value, const VecVar& operands, const VecArith& gradients, + const std::tuple& container_operands = std::tuple<>(), + const std::tuple& container_gradients + = std::tuple<>()) { + return {new precomputed_gradients_vari_template< + std::tuple...>, + std::tuple...>>( + value, operands, gradients, container_operands, container_gradients)}; } } // namespace math diff --git a/stan/math/rev/fun/to_ad_stack.hpp b/stan/math/rev/fun/to_ad_stack.hpp index 555e98a59b7..eaa93d3dba2 100644 --- a/stan/math/rev/fun/to_ad_stack.hpp +++ b/stan/math/rev/fun/to_ad_stack.hpp @@ -9,51 +9,58 @@ namespace stan { namespace math { /** - * Converts given argument into a type that has any dynamic allocation on AD stack. + * Converts given argument into a type that has any dynamic allocation on AD + * stack. * * For scalars this is a no-op. * @tparam type of scalar * @param a argument * @return argument */ -template* = nullptr> -T to_AD_stack(T&& a){ - return std::forward(a); +template * = nullptr> +T to_AD_stack(T&& a) { + return std::forward(a); } /** - * Converts given argument into a type that has any dynamic allocation on AD stack. + * Converts given argument into a type that has any dynamic allocation on AD + * stack. * * Converts eigen types to `AD_stack_matrix`. * @tparam type of argument * @param a argument * @return argument copied/evaluated on AD stack */ -template* = nullptr> -AD_stack_t to_AD_stack(const T& a){ - return AD_stack_t(a); +template * = nullptr> +AD_stack_t to_AD_stack(const T& a) { + return AD_stack_t(a); } /** - * Converts given argument into a type that has any dynamic allocation on AD stack. + * Converts given argument into a type that has any dynamic allocation on AD + * stack. * - * Std vectors are copied into another std vector with custom allocator that uses AD stack. + * Std vectors are copied into another std vector with custom allocator that + * uses AD stack. * - * This overload works on vectors with simple scalars that don't need to be converthed themselves. + * This overload works on vectors with simple scalars that don't need to be + * converthed themselves. * * @tparam type of argument * @param a argument * @return argument copied on AD stack */ -template>* = nullptr> -AD_stack_t> to_AD_stack(const std::vector& a){ - return {a.begin(), a.end()}; +template >* = nullptr> +AD_stack_t> to_AD_stack(const std::vector& a) { + return {a.begin(), a.end()}; } /** - * Converts given argument into a type that has any dynamic allocation on AD stack. + * Converts given argument into a type that has any dynamic allocation on AD + * stack. * - * Std vectors are copied into another std vector with custom allocator that uses AD stack. + * Std vectors are copied into another std vector with custom allocator that + * uses AD stack. * * This overload works on vectors with scalars that also need conversion. * @@ -61,17 +68,17 @@ AD_stack_t> to_AD_stack(const std::vector& a){ * @param a argument * @return argument copied on AD stack */ -template>* = nullptr> -AD_stack_t> to_AD_stack(const std::vector& a){ - AD_stack_t> res; - res.reserve(a.size()); - for(const T& i : a){ - res.push_back(to_AD_stack(i)); - } - return res; +template >* = nullptr> +AD_stack_t> to_AD_stack(const std::vector& a) { + AD_stack_t> res; + res.reserve(a.size()); + for (const T& i : a) { + res.push_back(to_AD_stack(i)); + } + return res; } -} -} +} // namespace math +} // namespace stan #endif diff --git a/stan/math/rev/functor/ad_stack_matrix.hpp b/stan/math/rev/functor/ad_stack_matrix.hpp index 6baf3830c20..f2780d5ffef 100644 --- a/stan/math/rev/functor/ad_stack_matrix.hpp +++ b/stan/math/rev/functor/ad_stack_matrix.hpp @@ -7,104 +7,128 @@ namespace stan { namespace math { -template -class AD_stack_matrix : public Eigen::Map{ -public: - using Scalar = value_type_t; - static constexpr int RowsAtCompileTime = MatrixType::RowsAtCompileTime; - static constexpr int ColsAtCompileTime = MatrixType::ColsAtCompileTime; - - /** - * Default constructor. - */ - AD_stack_matrix() : - Eigen::Map::Map(nullptr, RowsAtCompileTime==Eigen::Dynamic ? 0 : RowsAtCompileTime, ColsAtCompileTime==Eigen::Dynamic ? 0 : ColsAtCompileTime ) {} - - /** - * Constructs `AD_stack_matrix` with given number of rows and columns. - * @param rows number of rows - * @param cols number of columns - */ - AD_stack_matrix(Eigen::Index rows, Eigen::Index cols) : - Eigen::Map::Map(ChainableStack::instance_->memalloc_.alloc_array(rows*cols), rows, cols){} - - /** - * Constructs `AD_stack_matrix` with given size. This only works if `MatrixType` is row or col vector. - * @param size number of elements - */ - AD_stack_matrix(Eigen::Index size) : - Eigen::Map::Map(ChainableStack::instance_->memalloc_.alloc_array(size), size){} - - /** - * Constructs `AD_stack_matrix` form an expression. - * @param other expression - */ - template* = nullptr> - explicit AD_stack_matrix(const T& other) : Eigen::Map::Map(ChainableStack::instance_->memalloc_.alloc_array(other.size()), other.rows(), other.cols() ){ - *this = other; - } - - /** - * Copy constructor. Copies values, not the whole object (same as Eigen types). - * @param other matrix to copy from - */ - AD_stack_matrix(const AD_stack_matrix& other) : - Eigen::Map::Map(ChainableStack::instance_->memalloc_.alloc_array(other.size()), other.rows(), other.cols()){ - *this = other; - } - - /** - * Move constructor. - * @param other matrix to move from - */ - AD_stack_matrix(AD_stack_matrix&& other) : - Eigen::Map::Map(other.data(), other.rows(), other.cols()){} - - using Eigen::Map::operator=; - - /** - * Copy assignment operator. Copies values, not the whole object (same as Eigen types). - * @param other matrix to copy from - * @return `*this` - */ - AD_stack_matrix& operator=(const AD_stack_matrix& other){ - resize(other.rows(), other.cols()); - Eigen::Map::operator=(other); - return *this; - } - - /** - * Move assignment operator. - * @param other matrix to move from - * @return `*this` - */ - AD_stack_matrix& operator=(AD_stack_matrix&& other){ - //placement new changes what data map points to - there is no allocation - new (this) Eigen::Map(other.data(), other.rows(), other.cols()); - return *this; - } - - /** - * Resizes this object to given number of rows and columns. - * @param rows number of rows - * @param cols number of columns - */ - void resize(Eigen::Index rows, Eigen::Index cols){ - //placement new changes what data map points to - this new is not an allocation - new (this) Eigen::Map(ChainableStack::instance_->memalloc_.alloc_array(rows*cols), rows, cols); - } - - /** - * Resizes this object to given size. This only works if `MatrixType` is row or col vector. - * @param size number of elements - */ - void resize(Eigen::Index size){ - //placement new changes what data map points to - this new is not an allocation - new (this) Eigen::Map(ChainableStack::instance_->memalloc_.alloc_array(size), size); - } +template +class AD_stack_matrix : public Eigen::Map { + public: + using Scalar = value_type_t; + static constexpr int RowsAtCompileTime = MatrixType::RowsAtCompileTime; + static constexpr int ColsAtCompileTime = MatrixType::ColsAtCompileTime; + + /** + * Default constructor. + */ + AD_stack_matrix() + : Eigen::Map::Map( + nullptr, + RowsAtCompileTime == Eigen::Dynamic ? 0 : RowsAtCompileTime, + ColsAtCompileTime == Eigen::Dynamic ? 0 : ColsAtCompileTime) {} + + /** + * Constructs `AD_stack_matrix` with given number of rows and columns. + * @param rows number of rows + * @param cols number of columns + */ + AD_stack_matrix(Eigen::Index rows, Eigen::Index cols) + : Eigen::Map::Map( + ChainableStack::instance_->memalloc_.alloc_array(rows + * cols), + rows, cols) {} + + /** + * Constructs `AD_stack_matrix` with given size. This only works if + * `MatrixType` is row or col vector. + * @param size number of elements + */ + AD_stack_matrix(Eigen::Index size) + : Eigen::Map::Map( + ChainableStack::instance_->memalloc_.alloc_array(size), + size) {} + + /** + * Constructs `AD_stack_matrix` form an expression. + * @param other expression + */ + template * = nullptr> + explicit AD_stack_matrix(const T& other) + : Eigen::Map::Map( + ChainableStack::instance_->memalloc_.alloc_array( + other.size()), + other.rows(), other.cols()) { + *this = other; + } + + /** + * Copy constructor. Copies values, not the whole object (same as Eigen + * types). + * @param other matrix to copy from + */ + AD_stack_matrix(const AD_stack_matrix& other) + : Eigen::Map::Map( + ChainableStack::instance_->memalloc_.alloc_array( + other.size()), + other.rows(), other.cols()) { + *this = other; + } + + /** + * Move constructor. + * @param other matrix to move from + */ + AD_stack_matrix(AD_stack_matrix&& other) + : Eigen::Map::Map(other.data(), other.rows(), other.cols()) {} + + using Eigen::Map::operator=; + + /** + * Copy assignment operator. Copies values, not the whole object (same as + * Eigen types). + * @param other matrix to copy from + * @return `*this` + */ + AD_stack_matrix& operator=(const AD_stack_matrix& other) { + resize(other.rows(), other.cols()); + Eigen::Map::operator=(other); + return *this; + } + + /** + * Move assignment operator. + * @param other matrix to move from + * @return `*this` + */ + AD_stack_matrix& operator=(AD_stack_matrix&& other) { + // placement new changes what data map points to - there is no allocation + new (this) Eigen::Map(other.data(), other.rows(), other.cols()); + return *this; + } + + /** + * Resizes this object to given number of rows and columns. + * @param rows number of rows + * @param cols number of columns + */ + void resize(Eigen::Index rows, Eigen::Index cols) { + // placement new changes what data map points to - this new is not an + // allocation + new (this) Eigen::Map( + ChainableStack::instance_->memalloc_.alloc_array(rows * cols), + rows, cols); + } + + /** + * Resizes this object to given size. This only works if `MatrixType` is row + * or col vector. + * @param size number of elements + */ + void resize(Eigen::Index size) { + // placement new changes what data map points to - this new is not an + // allocation + new (this) Eigen::Map( + ChainableStack::instance_->memalloc_.alloc_array(size), size); + } }; -} -} +} // namespace math +} // namespace stan #endif diff --git a/stan/math/rev/functor/operands_and_partials.hpp b/stan/math/rev/functor/operands_and_partials.hpp index bacaeff8c84..1f7ebce0725 100644 --- a/stan/math/rev/functor/operands_and_partials.hpp +++ b/stan/math/rev/functor/operands_and_partials.hpp @@ -142,27 +142,34 @@ class operands_and_partials { edge3_.container_partials(), edge4_.container_partials(), edge5_.container_partials()); - return var(return_vari(value, edges_size, varis, partials, container_operands, container_partials)); + return var(return_vari(value, edges_size, varis, partials, + container_operands, container_partials)); } -private: + private: /** * Deduces types and constructs the vari to return from `build()`. * @param value the value - * @param edges_size number of elements in all non-var_value of container edges + * @param edges_size number of elements in all non-var_value of container + * edges * @param varis pointer to varis from non-var_value of container edges - * @param partials pointer to values for partials from non-var_value of container edges + * @param partials pointer to values for partials from non-var_value of + * container edges * @param container_operands operands from var_value of container edges - * @param container_partials partial derivatives from var_value of container edges + * @param container_partials partial derivatives from var_value of container + * edges */ - template - auto* return_vari(double value, size_t edges_size, vari** varis, double* partials, + template + auto* return_vari(double value, size_t edges_size, vari** varis, + double* partials, const std::tuple& container_operands, - const std::tuple& container_partials){ - //Partials are decayed, so precomputed_gradients_vari_template always stores values, not references - return new precomputed_gradients_vari_template...>, - std::tuple...>>( - value, edges_size, varis, partials, container_operands, container_partials); + const std::tuple& container_partials) { + // Partials are decayed, so precomputed_gradients_vari_template always + // stores values, not references + return new precomputed_gradients_vari_template< + std::tuple...>, std::tuple...>>( + value, edges_size, varis, partials, container_operands, + container_partials); } }; diff --git a/stan/math/rev/meta/ad_stack_type.hpp b/stan/math/rev/meta/ad_stack_type.hpp index 43dbcb94775..045f5486678 100644 --- a/stan/math/rev/meta/ad_stack_type.hpp +++ b/stan/math/rev/meta/ad_stack_type.hpp @@ -7,36 +7,38 @@ namespace stan { namespace math { -//forward declaration -template +// forward declaration +template class AD_stack_matrix; -} +} // namespace math -namespace internal{ -template -struct AD_stack_type_impl{ - using type = T; +namespace internal { +template +struct AD_stack_type_impl { + using type = T; }; -template -struct AD_stack_type_impl>{ - using T_ad = typename AD_stack_type_impl>::type; - using type = std::vector>; +template +struct AD_stack_type_impl> { + using T_ad = typename AD_stack_type_impl>::type; + using type = std::vector>; }; -template -struct AD_stack_type_impl>{ - using type = math::AD_stack_matrix>; +template +struct AD_stack_type_impl> { + using type = math::AD_stack_matrix>; }; -} +} // namespace internal /** - * Determines a type that can be used in place of `T` that does any dynamic allocations on the AD stack. This way resulting types are trivially destructible and can be used in vari classes. - * (only works for POD types, `std::vector`s and Eigen types) + * Determines a type that can be used in place of `T` that does any dynamic + * allocations on the AD stack. This way resulting types are trivially + * destructible and can be used in vari classes. (only works for POD types, + * `std::vector`s and Eigen types) */ template using AD_stack_t = typename internal::AD_stack_type_impl>::type; -} +} // namespace stan -#endif // AD_STACK_TYPE_HPP +#endif // AD_STACK_TYPE_HPP diff --git a/test/unit/math/rev/core/precomputed_gradients_test.cpp b/test/unit/math/rev/core/precomputed_gradients_test.cpp index da7c5c903bb..894700e5f82 100644 --- a/test/unit/math/rev/core/precomputed_gradients_test.cpp +++ b/test/unit/math/rev/core/precomputed_gradients_test.cpp @@ -115,8 +115,8 @@ TEST(StanAgradRevInternal, precomputed_gradients_containers) { Eigen::MatrixXd grad_a = Eigen::MatrixXd::Constant(3, 3, -1); std::vector grad_b{Eigen::MatrixXd::Constant(3, 3, -2), Eigen::MatrixXd::Constant(3, 3, -3)}; - std::tuple&> grads(std::move(grad_a), - grad_b); + std::tuple&> grads( + std::move(grad_a), grad_b); stan::math::var lp = stan::math::precomputed_gradients(value, vars, gradients, ops, grads); @@ -128,7 +128,8 @@ TEST(StanAgradRevInternal, precomputed_gradients_containers) { stan::math::recover_memory(); } -TEST(StanAgradRevInternal, precomputed_gradients_containers_direct_construction) { +TEST(StanAgradRevInternal, + precomputed_gradients_containers_direct_construction) { double value = 1; std::vector vars; std::vector gradients; @@ -141,19 +142,16 @@ TEST(StanAgradRevInternal, precomputed_gradients_containers_direct_construction) Eigen::MatrixXd grad_a = Eigen::MatrixXd::Constant(3, 3, -1); std::vector grad_b{Eigen::MatrixXd::Constant(3, 3, -2), Eigen::MatrixXd::Constant(3, 3, -3)}; - std::tuple&> grads(std::move(grad_a), - grad_b); - - stan::math::var lp - = new stan::math::precomputed_gradients_vari_template< - std::tuple< - stan::AD_stack_t>, - stan::AD_stack_t>> - >, - std::tuple< - stan::AD_stack_t, - stan::AD_stack_t> - >>(value, 0, nullptr, nullptr, ops, grads); + std::tuple&> grads( + std::move(grad_a), grad_b); + + stan::math::var lp = new stan::math::precomputed_gradients_vari_template< + std::tuple>, + stan::AD_stack_t< + std::vector>>>, + std::tuple, + stan::AD_stack_t>>>( + value, 0, nullptr, nullptr, ops, grads); (2 * lp).grad(); EXPECT_MATRIX_EQ(a.adj(), Eigen::MatrixXd::Constant(3, 3, -2)); EXPECT_MATRIX_EQ(b[0].adj(), Eigen::MatrixXd::Constant(3, 3, -4)); diff --git a/test/unit/math/rev/functor/ad_stack_matrix_test.cpp b/test/unit/math/rev/functor/ad_stack_matrix_test.cpp index ab22e86bc51..1a8c36cef9c 100644 --- a/test/unit/math/rev/functor/ad_stack_matrix_test.cpp +++ b/test/unit/math/rev/functor/ad_stack_matrix_test.cpp @@ -3,73 +3,73 @@ #include TEST(AgradRev, AD_stack_matrix_matrix_test) { - using stan::math::AD_stack_matrix; - using Eigen::MatrixXd; + using Eigen::MatrixXd; + using stan::math::AD_stack_matrix; - //construction - AD_stack_matrix a; - AD_stack_matrix a2; - AD_stack_matrix b(3,2); - AD_stack_matrix b2(3,2); - AD_stack_matrix c(MatrixXd::Ones(3,2)); - AD_stack_matrix d(c); - AD_stack_matrix e(2*d); + // construction + AD_stack_matrix a; + AD_stack_matrix a2; + AD_stack_matrix b(3, 2); + AD_stack_matrix b2(3, 2); + AD_stack_matrix c(MatrixXd::Ones(3, 2)); + AD_stack_matrix d(c); + AD_stack_matrix e(2 * d); - //assignment - a = c; - a2 = std::move(d); - b = d; - b2 = std::move(c); - e = e + a; - a = MatrixXd::Ones(3,2); + // assignment + a = c; + a2 = std::move(d); + b = d; + b2 = std::move(c); + e = e + a; + a = MatrixXd::Ones(3, 2); - EXPECT_MATRIX_EQ(a + a2 + b + b2 + e, MatrixXd::Ones(3,2) * 7); + EXPECT_MATRIX_EQ(a + a2 + b + b2 + e, MatrixXd::Ones(3, 2) * 7); } TEST(AgradRev, AD_stack_matrix_vector_test) { - using stan::math::AD_stack_matrix; - using Eigen::VectorXd; + using Eigen::VectorXd; + using stan::math::AD_stack_matrix; - //construction - AD_stack_matrix a; - AD_stack_matrix a2; - AD_stack_matrix b(3); - AD_stack_matrix b2(3); - AD_stack_matrix c(VectorXd::Ones(3)); - AD_stack_matrix d(c); - AD_stack_matrix e(2*d); + // construction + AD_stack_matrix a; + AD_stack_matrix a2; + AD_stack_matrix b(3); + AD_stack_matrix b2(3); + AD_stack_matrix c(VectorXd::Ones(3)); + AD_stack_matrix d(c); + AD_stack_matrix e(2 * d); - //assignment - a = c; - a2 = std::move(d); - b = d; - b2 = std::move(c); - e = e + a; - a = VectorXd::Ones(3); + // assignment + a = c; + a2 = std::move(d); + b = d; + b2 = std::move(c); + e = e + a; + a = VectorXd::Ones(3); - EXPECT_MATRIX_EQ(a + a2 + b + b2 + e, VectorXd::Ones(3) * 7); + EXPECT_MATRIX_EQ(a + a2 + b + b2 + e, VectorXd::Ones(3) * 7); } TEST(AgradRev, AD_stack_matrix_row_vector_test) { - using stan::math::AD_stack_matrix; - using Eigen::RowVectorXd; + using Eigen::RowVectorXd; + using stan::math::AD_stack_matrix; - //construction - AD_stack_matrix a; - AD_stack_matrix a2; - AD_stack_matrix b(3); - AD_stack_matrix b2(3); - AD_stack_matrix c(RowVectorXd::Ones(3)); - AD_stack_matrix d(c); - AD_stack_matrix e(2*d); + // construction + AD_stack_matrix a; + AD_stack_matrix a2; + AD_stack_matrix b(3); + AD_stack_matrix b2(3); + AD_stack_matrix c(RowVectorXd::Ones(3)); + AD_stack_matrix d(c); + AD_stack_matrix e(2 * d); - //assignment - a = c; - a2 = std::move(d); - b = d; - b2 = std::move(c); - e = e + a; - a = RowVectorXd::Ones(3); + // assignment + a = c; + a2 = std::move(d); + b = d; + b2 = std::move(c); + e = e + a; + a = RowVectorXd::Ones(3); - EXPECT_MATRIX_EQ(a + a2 + b + b2 + e, RowVectorXd::Ones(3) * 7); + EXPECT_MATRIX_EQ(a + a2 + b + b2 + e, RowVectorXd::Ones(3) * 7); } From 8ccc28b354f8f812c849b0f71321ba2cca588e75 Mon Sep 17 00:00:00 2001 From: tadej Date: Wed, 5 Aug 2020 14:55:58 +0200 Subject: [PATCH 181/355] fixed explicit constructors --- stan/math/rev/functor/ad_stack_matrix.hpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/stan/math/rev/functor/ad_stack_matrix.hpp b/stan/math/rev/functor/ad_stack_matrix.hpp index f2780d5ffef..c945e1c31ca 100644 --- a/stan/math/rev/functor/ad_stack_matrix.hpp +++ b/stan/math/rev/functor/ad_stack_matrix.hpp @@ -39,7 +39,7 @@ class AD_stack_matrix : public Eigen::Map { * `MatrixType` is row or col vector. * @param size number of elements */ - AD_stack_matrix(Eigen::Index size) + explicit AD_stack_matrix(Eigen::Index size) : Eigen::Map::Map( ChainableStack::instance_->memalloc_.alloc_array(size), size) {} @@ -49,7 +49,7 @@ class AD_stack_matrix : public Eigen::Map { * @param other expression */ template * = nullptr> - explicit AD_stack_matrix(const T& other) + AD_stack_matrix(const T& other) // NOLINT : Eigen::Map::Map( ChainableStack::instance_->memalloc_.alloc_array( other.size()), From 985c2b70c5f67aad5d74f07b6f342cc07a67aefe Mon Sep 17 00:00:00 2001 From: Stan Jenkins Date: Wed, 5 Aug 2020 13:03:06 +0000 Subject: [PATCH 182/355] [Jenkins] auto-formatting by clang-format version 6.0.0-1ubuntu2~16.04.1 (tags/RELEASE_600/final) --- stan/math/rev/functor/ad_stack_matrix.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stan/math/rev/functor/ad_stack_matrix.hpp b/stan/math/rev/functor/ad_stack_matrix.hpp index c945e1c31ca..17916ff2ffc 100644 --- a/stan/math/rev/functor/ad_stack_matrix.hpp +++ b/stan/math/rev/functor/ad_stack_matrix.hpp @@ -49,7 +49,7 @@ class AD_stack_matrix : public Eigen::Map { * @param other expression */ template * = nullptr> - AD_stack_matrix(const T& other) // NOLINT + AD_stack_matrix(const T& other) // NOLINT : Eigen::Map::Map( ChainableStack::instance_->memalloc_.alloc_array( other.size()), From aa8a1e1f82782ca439ba0ee59cbfdca75dbcff9d Mon Sep 17 00:00:00 2001 From: tadej Date: Wed, 5 Aug 2020 16:11:16 +0200 Subject: [PATCH 183/355] tmp --- stan/math/rev/fun/softmax.hpp | 117 +++++++++++++--------- stan/math/rev/functor/ad_stack_matrix.hpp | 33 +----- stan/math/rev/functor/adj_jac_apply.hpp | 20 ++++ 3 files changed, 91 insertions(+), 79 deletions(-) diff --git a/stan/math/rev/fun/softmax.hpp b/stan/math/rev/fun/softmax.hpp index 77e66019acb..e5201be1078 100644 --- a/stan/math/rev/fun/softmax.hpp +++ b/stan/math/rev/fun/softmax.hpp @@ -3,6 +3,7 @@ #include #include +#include #include #include #include @@ -12,55 +13,55 @@ namespace stan { namespace math { -namespace internal { -class softmax_op { - int N_; - double* y_; // Holds the results of the softmax - - public: - softmax_op() : N_(0), y_(nullptr) {} - - /** - * Compute the softmax of the unconstrained input vector - * - * @param alpha Unconstrained input vector. - * @return Softmax of the input. - */ - template - Eigen::VectorXd operator()(const std::array& /* needs_adj */, - const Eigen::VectorXd& alpha) { - N_ = alpha.size(); - y_ = ChainableStack::instance_->memalloc_.alloc_array(N_); - - auto y = softmax(alpha); - for (int n = 0; n < N_; ++n) { - y_[n] = y(n); - } - return y; - } - - /** - * Compute the result of multiply the transpose of the adjoint vector times - * the Jacobian of the softmax operator. It is more efficient to do this - * without actually computing the Jacobian and doing the vector-matrix - * product. - * - * @param adj Eigen::VectorXd of adjoints at the output of the softmax - * @return Eigen::VectorXd of adjoints propagated through softmax operation - */ - template - std::tuple multiply_adjoint_jacobian( - const std::array& /* needs_adj */, - const Eigen::VectorXd& adj) const { - vector_d adj_times_jac(N_); - Eigen::Map y(y_, N_); - - adj_times_jac = -y * adj.dot(y) + y.cwiseProduct(adj); - - return std::make_tuple(adj_times_jac); - } -}; -} // namespace internal +//namespace internal { +//class softmax_op { +// int N_; +// double* y_; // Holds the results of the softmax + +// public: +// softmax_op() : N_(0), y_(nullptr) {} + +// /** +// * Compute the softmax of the unconstrained input vector +// * +// * @param alpha Unconstrained input vector. +// * @return Softmax of the input. +// */ +// template +// Eigen::VectorXd operator()(const std::array& /* needs_adj */, +// const Eigen::VectorXd& alpha) { +// N_ = alpha.size(); +// y_ = ChainableStack::instance_->memalloc_.alloc_array(N_); + +// auto y = softmax(alpha); +// for (int n = 0; n < N_; ++n) { +// y_[n] = y(n); +// } +// return y; +// } + +// /** +// * Compute the result of multiply the transpose of the adjoint vector times +// * the Jacobian of the softmax operator. It is more efficient to do this +// * without actually computing the Jacobian and doing the vector-matrix +// * product. +// * +// * @param adj Eigen::VectorXd of adjoints at the output of the softmax +// * @return Eigen::VectorXd of adjoints propagated through softmax operation +// */ +// template +// std::tuple multiply_adjoint_jacobian( +// const std::array& /* needs_adj */, +// const Eigen::VectorXd& adj) const { +// vector_d adj_times_jac(N_); +// Eigen::Map y(y_, N_); + +// adj_times_jac = -y * adj.dot(y) + y.cwiseProduct(adj); + +// return std::make_tuple(adj_times_jac); +// } +//}; +//} // namespace internal /** * Return the softmax of the specified Eigen vector. Softmax is @@ -70,11 +71,27 @@ class softmax_op { * @return Softmax of the input. * @throw std::domain_error If the input vector is size 0. */ +//inline Eigen::Matrix softmax( +// const Eigen::Matrix& alpha) { +// check_nonzero_size("softmax", "alpha", alpha); + +// return adj_jac_apply(alpha); +//} + inline Eigen::Matrix softmax( const Eigen::Matrix& alpha) { check_nonzero_size("softmax", "alpha", alpha); - return adj_jac_apply(alpha); + AD_stack_matrix res_val = softmax(value_of(alpha)); + AD_stack_matrix> res = res_val; + AD_stack_matrix> alpha_ad_stack = alpha; + + adjac_apply([=]() mutable { + Eigen::VectorXd res_adj = res.adj(); + alpha_ad_stack.adj() = -res_val * res_adj.dot(res_val) + res_val.cwiseProduct(res_adj); + }); + + return res; } } // namespace math diff --git a/stan/math/rev/functor/ad_stack_matrix.hpp b/stan/math/rev/functor/ad_stack_matrix.hpp index c945e1c31ca..bceea53b468 100644 --- a/stan/math/rev/functor/ad_stack_matrix.hpp +++ b/stan/math/rev/functor/ad_stack_matrix.hpp @@ -58,47 +58,22 @@ class AD_stack_matrix : public Eigen::Map { } /** - * Copy constructor. Copies values, not the whole object (same as Eigen - * types). + * Copy constructor. * @param other matrix to copy from */ AD_stack_matrix(const AD_stack_matrix& other) - : Eigen::Map::Map( - ChainableStack::instance_->memalloc_.alloc_array( - other.size()), - other.rows(), other.cols()) { - *this = other; - } - - /** - * Move constructor. - * @param other matrix to move from - */ - AD_stack_matrix(AD_stack_matrix&& other) - : Eigen::Map::Map(other.data(), other.rows(), other.cols()) {} + : Eigen::Map::Map(const_cast(other.data()), other.rows(), other.cols()) {} using Eigen::Map::operator=; /** - * Copy assignment operator. Copies values, not the whole object (same as - * Eigen types). + * Copy assignment operator. * @param other matrix to copy from * @return `*this` */ AD_stack_matrix& operator=(const AD_stack_matrix& other) { - resize(other.rows(), other.cols()); - Eigen::Map::operator=(other); - return *this; - } - - /** - * Move assignment operator. - * @param other matrix to move from - * @return `*this` - */ - AD_stack_matrix& operator=(AD_stack_matrix&& other) { // placement new changes what data map points to - there is no allocation - new (this) Eigen::Map(other.data(), other.rows(), other.cols()); + new (this) Eigen::Map(const_cast(other.data()), other.rows(), other.cols()); return *this; } diff --git a/stan/math/rev/functor/adj_jac_apply.hpp b/stan/math/rev/functor/adj_jac_apply.hpp index 26409600952..b30c660fb01 100644 --- a/stan/math/rev/functor/adj_jac_apply.hpp +++ b/stan/math/rev/functor/adj_jac_apply.hpp @@ -105,6 +105,26 @@ struct compute_dims> { }; } // namespace internal + + +template +struct adjac_vari : public vari { + F rev_functor_; + + adjac_vari(F&& rev_functor) : vari(NOT_A_NUMBER), rev_functor_(rev_functor){} + + inline void chain() { + rev_functor_(); + } +}; + +template +inline void adjac_apply(F&& rev_functor){ + new adjac_vari(std::forward(rev_functor)); +} + + + /** * adj_jac_vari interfaces a user supplied functor with the reverse mode * autodiff. It allows someone to implement functions with custom reverse mode From 39fc7e67af3241b426535af3913b71310f7362ac Mon Sep 17 00:00:00 2001 From: tadej Date: Wed, 5 Aug 2020 16:23:33 +0200 Subject: [PATCH 184/355] bugfix missing allocator operators --- stan/math/rev/core/ad_allocator.hpp | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/stan/math/rev/core/ad_allocator.hpp b/stan/math/rev/core/ad_allocator.hpp index 74503068e53..313ee49f21b 100644 --- a/stan/math/rev/core/ad_allocator.hpp +++ b/stan/math/rev/core/ad_allocator.hpp @@ -28,6 +28,18 @@ struct AD_allocator { * No-op. Memory is dealocated by caling `recover_memory()`. */ void deallocate(T* /*p*/, std::size_t /*n*/) noexcept {} + + /** + * Equality comparison operator. + * @return true + */ + bool operator==(const AD_allocator&){ return true; } + + /** + * Inequality comparison operator. + * @return false + */ + bool operator!=(const AD_allocator&){ return false; } }; } // namespace math From b84b410731c82d570f14484709bf3b28d14b58d2 Mon Sep 17 00:00:00 2001 From: tadej Date: Wed, 5 Aug 2020 16:25:44 +0200 Subject: [PATCH 185/355] modified how copying of AD_stack_matrix works. --- stan/math/rev/functor/ad_stack_matrix.hpp | 35 ++++------------------- 1 file changed, 5 insertions(+), 30 deletions(-) diff --git a/stan/math/rev/functor/ad_stack_matrix.hpp b/stan/math/rev/functor/ad_stack_matrix.hpp index 17916ff2ffc..bceea53b468 100644 --- a/stan/math/rev/functor/ad_stack_matrix.hpp +++ b/stan/math/rev/functor/ad_stack_matrix.hpp @@ -49,7 +49,7 @@ class AD_stack_matrix : public Eigen::Map { * @param other expression */ template * = nullptr> - AD_stack_matrix(const T& other) // NOLINT + AD_stack_matrix(const T& other) // NOLINT : Eigen::Map::Map( ChainableStack::instance_->memalloc_.alloc_array( other.size()), @@ -58,47 +58,22 @@ class AD_stack_matrix : public Eigen::Map { } /** - * Copy constructor. Copies values, not the whole object (same as Eigen - * types). + * Copy constructor. * @param other matrix to copy from */ AD_stack_matrix(const AD_stack_matrix& other) - : Eigen::Map::Map( - ChainableStack::instance_->memalloc_.alloc_array( - other.size()), - other.rows(), other.cols()) { - *this = other; - } - - /** - * Move constructor. - * @param other matrix to move from - */ - AD_stack_matrix(AD_stack_matrix&& other) - : Eigen::Map::Map(other.data(), other.rows(), other.cols()) {} + : Eigen::Map::Map(const_cast(other.data()), other.rows(), other.cols()) {} using Eigen::Map::operator=; /** - * Copy assignment operator. Copies values, not the whole object (same as - * Eigen types). + * Copy assignment operator. * @param other matrix to copy from * @return `*this` */ AD_stack_matrix& operator=(const AD_stack_matrix& other) { - resize(other.rows(), other.cols()); - Eigen::Map::operator=(other); - return *this; - } - - /** - * Move assignment operator. - * @param other matrix to move from - * @return `*this` - */ - AD_stack_matrix& operator=(AD_stack_matrix&& other) { // placement new changes what data map points to - there is no allocation - new (this) Eigen::Map(other.data(), other.rows(), other.cols()); + new (this) Eigen::Map(const_cast(other.data()), other.rows(), other.cols()); return *this; } From 79d231100bf3d364abdd4126747ce95123f900de Mon Sep 17 00:00:00 2001 From: Stan Jenkins Date: Wed, 5 Aug 2020 14:26:26 +0000 Subject: [PATCH 186/355] [Jenkins] auto-formatting by clang-format version 6.0.0-1ubuntu2~16.04.1 (tags/RELEASE_600/final) --- stan/math/rev/core/ad_allocator.hpp | 4 ++-- stan/math/rev/functor/ad_stack_matrix.hpp | 8 +++++--- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/stan/math/rev/core/ad_allocator.hpp b/stan/math/rev/core/ad_allocator.hpp index 313ee49f21b..183e2592c82 100644 --- a/stan/math/rev/core/ad_allocator.hpp +++ b/stan/math/rev/core/ad_allocator.hpp @@ -33,13 +33,13 @@ struct AD_allocator { * Equality comparison operator. * @return true */ - bool operator==(const AD_allocator&){ return true; } + bool operator==(const AD_allocator&) { return true; } /** * Inequality comparison operator. * @return false */ - bool operator!=(const AD_allocator&){ return false; } + bool operator!=(const AD_allocator&) { return false; } }; } // namespace math diff --git a/stan/math/rev/functor/ad_stack_matrix.hpp b/stan/math/rev/functor/ad_stack_matrix.hpp index bceea53b468..3a60f04a15b 100644 --- a/stan/math/rev/functor/ad_stack_matrix.hpp +++ b/stan/math/rev/functor/ad_stack_matrix.hpp @@ -49,7 +49,7 @@ class AD_stack_matrix : public Eigen::Map { * @param other expression */ template * = nullptr> - AD_stack_matrix(const T& other) // NOLINT + AD_stack_matrix(const T& other) // NOLINT : Eigen::Map::Map( ChainableStack::instance_->memalloc_.alloc_array( other.size()), @@ -62,7 +62,8 @@ class AD_stack_matrix : public Eigen::Map { * @param other matrix to copy from */ AD_stack_matrix(const AD_stack_matrix& other) - : Eigen::Map::Map(const_cast(other.data()), other.rows(), other.cols()) {} + : Eigen::Map::Map(const_cast(other.data()), + other.rows(), other.cols()) {} using Eigen::Map::operator=; @@ -73,7 +74,8 @@ class AD_stack_matrix : public Eigen::Map { */ AD_stack_matrix& operator=(const AD_stack_matrix& other) { // placement new changes what data map points to - there is no allocation - new (this) Eigen::Map(const_cast(other.data()), other.rows(), other.cols()); + new (this) Eigen::Map(const_cast(other.data()), + other.rows(), other.cols()); return *this; } From e2b93c23dede32ae3e51b18570d612bde854e89c Mon Sep 17 00:00:00 2001 From: tadej Date: Wed, 5 Aug 2020 16:31:17 +0200 Subject: [PATCH 187/355] cleanup --- stan/math/rev/fun/softmax.hpp | 56 ----------------------------------- 1 file changed, 56 deletions(-) diff --git a/stan/math/rev/fun/softmax.hpp b/stan/math/rev/fun/softmax.hpp index e5201be1078..e4d472df3f9 100644 --- a/stan/math/rev/fun/softmax.hpp +++ b/stan/math/rev/fun/softmax.hpp @@ -13,56 +13,6 @@ namespace stan { namespace math { -//namespace internal { -//class softmax_op { -// int N_; -// double* y_; // Holds the results of the softmax - -// public: -// softmax_op() : N_(0), y_(nullptr) {} - -// /** -// * Compute the softmax of the unconstrained input vector -// * -// * @param alpha Unconstrained input vector. -// * @return Softmax of the input. -// */ -// template -// Eigen::VectorXd operator()(const std::array& /* needs_adj */, -// const Eigen::VectorXd& alpha) { -// N_ = alpha.size(); -// y_ = ChainableStack::instance_->memalloc_.alloc_array(N_); - -// auto y = softmax(alpha); -// for (int n = 0; n < N_; ++n) { -// y_[n] = y(n); -// } -// return y; -// } - -// /** -// * Compute the result of multiply the transpose of the adjoint vector times -// * the Jacobian of the softmax operator. It is more efficient to do this -// * without actually computing the Jacobian and doing the vector-matrix -// * product. -// * -// * @param adj Eigen::VectorXd of adjoints at the output of the softmax -// * @return Eigen::VectorXd of adjoints propagated through softmax operation -// */ -// template -// std::tuple multiply_adjoint_jacobian( -// const std::array& /* needs_adj */, -// const Eigen::VectorXd& adj) const { -// vector_d adj_times_jac(N_); -// Eigen::Map y(y_, N_); - -// adj_times_jac = -y * adj.dot(y) + y.cwiseProduct(adj); - -// return std::make_tuple(adj_times_jac); -// } -//}; -//} // namespace internal - /** * Return the softmax of the specified Eigen vector. Softmax is * guaranteed to return a simplex. @@ -71,12 +21,6 @@ namespace math { * @return Softmax of the input. * @throw std::domain_error If the input vector is size 0. */ -//inline Eigen::Matrix softmax( -// const Eigen::Matrix& alpha) { -// check_nonzero_size("softmax", "alpha", alpha); - -// return adj_jac_apply(alpha); -//} inline Eigen::Matrix softmax( const Eigen::Matrix& alpha) { From bf096b92d1d986265d41f3b0a78c9cc4d4559246 Mon Sep 17 00:00:00 2001 From: Steve Bronder Date: Wed, 5 Aug 2020 18:34:35 -0400 Subject: [PATCH 188/355] Add grad() method without an input vari and add template paramter to var_value's grad so that it is only available when the value_type of the var_value is not a container --- stan/math/rev/core/grad.hpp | 20 ++++++++++++++++++++ stan/math/rev/core/var.hpp | 8 ++++++++ 2 files changed, 28 insertions(+) diff --git a/stan/math/rev/core/grad.hpp b/stan/math/rev/core/grad.hpp index efe8fee1e87..02b1ae824de 100644 --- a/stan/math/rev/core/grad.hpp +++ b/stan/math/rev/core/grad.hpp @@ -37,6 +37,26 @@ static void grad(Vari* vi) { } } +/** + * Compute the gradient for all variables starting from the end of the AD tape. + * This function does not recover memory. The chain + * rule is applied working down the stack from the last vari created on the + * AD tape and then calling each vari's `chain()` method in turn. + * + *

This function computes a nested gradient only going back as far + * as the last nesting. + * + *

This function does not recover any memory from the computation. + * + */ +static void grad() { + size_t end = ChainableStack::instance_->var_stack_.size(); + size_t beginning = empty_nested() ? 0 : end - nested_size(); + for (size_t i = end; i-- > beginning;) { + ChainableStack::instance_->var_stack_[i]->chain(); + } +} + } // namespace math } // namespace stan diff --git a/stan/math/rev/core/var.hpp b/stan/math/rev/core/var.hpp index da5af408c83..c6e77960123 100644 --- a/stan/math/rev/core/var.hpp +++ b/stan/math/rev/core/var.hpp @@ -129,10 +129,14 @@ class var_value { * The grad() function does not recover memory. In Stan * 2.4 and earlier, this function did recover memory. * + * @tparam CheckContainer Not set by user. The default value of value_type + * is used to require that grad is only available for scalar `var_value` + * types. * @param x Vector of independent variables. * @param g Gradient vector of partial derivatives of this * variable with respect to x. */ + template * = nullptr> inline void grad(std::vector>& x, std::vector& g) { stan::math::grad(vi_); g.resize(x.size()); @@ -145,8 +149,12 @@ class var_value { * Compute the gradient of this (dependent) variable with respect * to all (independent) variables. * + * @tparam CheckContainer Not set by user. The default value of value_type + * is used to require that grad is only available for scalar `var_value` + * types. * The grad() function does not recover memory. */ + template * = nullptr> void grad() { stan::math::grad(vi_); } // POINTER OVERRIDES From d2edb26b74e7c6335bf1c01178e7f07c656019f3 Mon Sep 17 00:00:00 2001 From: Stan Jenkins Date: Wed, 5 Aug 2020 22:35:14 +0000 Subject: [PATCH 189/355] [Jenkins] auto-formatting by clang-format version 6.0.0-1ubuntu2~16.04.1 (tags/RELEASE_600/final) --- stan/math/rev/core/var.hpp | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/stan/math/rev/core/var.hpp b/stan/math/rev/core/var.hpp index c6e77960123..fef1d79588f 100644 --- a/stan/math/rev/core/var.hpp +++ b/stan/math/rev/core/var.hpp @@ -136,7 +136,8 @@ class var_value { * @param g Gradient vector of partial derivatives of this * variable with respect to x. */ - template * = nullptr> + template * = nullptr> inline void grad(std::vector>& x, std::vector& g) { stan::math::grad(vi_); g.resize(x.size()); @@ -154,8 +155,11 @@ class var_value { * types. * The grad() function does not recover memory. */ - template * = nullptr> - void grad() { stan::math::grad(vi_); } + template * = nullptr> + void grad() { + stan::math::grad(vi_); + } // POINTER OVERRIDES From 614ae976fb56adbb68c05bfc687b667c11cf2f1f Mon Sep 17 00:00:00 2001 From: Steve Bronder Date: Wed, 5 Aug 2020 18:37:40 -0400 Subject: [PATCH 190/355] fix docs in vari for matrix_cl --- stan/math/opencl/rev/vari.hpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/stan/math/opencl/rev/vari.hpp b/stan/math/opencl/rev/vari.hpp index 0d63bbe9ac0..b02edc27d19 100644 --- a/stan/math/opencl/rev/vari.hpp +++ b/stan/math/opencl/rev/vari.hpp @@ -45,7 +45,7 @@ class vari_value> * will be called in the reverse order of construction. * * @tparam S A `matrix_cl` or kernel generator expression type that is - * convertible to `value_type` + * convertible to `T` * @param x Value of the constructed variable. */ template * = nullptr> @@ -89,7 +89,7 @@ class vari_value> * will be called in the reverse order of construction. * * @tparam S A `matrix_cl` or kernel generator expression type that is - * convertible to `value_type` + * convertible to `T` * @param x Value of the constructed variable. * @param stacked If false will put this this vari on the nochain stack so * that its `chain()` method is not called. From bf38a76f9b37969978ff78a4adeed35b4e053bae Mon Sep 17 00:00:00 2001 From: Steve Bronder Date: Wed, 5 Aug 2020 22:00:15 -0400 Subject: [PATCH 191/355] use grad() in grad(Vari*) --- stan/math/rev/core/grad.hpp | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/stan/math/rev/core/grad.hpp b/stan/math/rev/core/grad.hpp index 02b1ae824de..d6d43a18f0d 100644 --- a/stan/math/rev/core/grad.hpp +++ b/stan/math/rev/core/grad.hpp @@ -30,11 +30,7 @@ namespace math { template static void grad(Vari* vi) { vi->init_dependent(); - size_t end = ChainableStack::instance_->var_stack_.size(); - size_t beginning = empty_nested() ? 0 : end - nested_size(); - for (size_t i = end; i-- > beginning;) { - ChainableStack::instance_->var_stack_[i]->chain(); - } + grad(); } /** From c6af0b07130712d0b5f91dd27c4c7619a43f13be Mon Sep 17 00:00:00 2001 From: Steve Bronder Date: Wed, 5 Aug 2020 22:09:39 -0400 Subject: [PATCH 192/355] Move grad() in front of grad(Vari*) --- stan/math/rev/core/grad.hpp | 40 ++++++++++++++++++------------------- 1 file changed, 20 insertions(+), 20 deletions(-) diff --git a/stan/math/rev/core/grad.hpp b/stan/math/rev/core/grad.hpp index d6d43a18f0d..570b86d18d6 100644 --- a/stan/math/rev/core/grad.hpp +++ b/stan/math/rev/core/grad.hpp @@ -11,6 +11,26 @@ namespace stan { namespace math { +/** + * Compute the gradient for all variables starting from the end of the AD tape. + * This function does not recover memory. The chain + * rule is applied working down the stack from the last vari created on the + * AD tape and then calling each vari's `chain()` method in turn. + * + *

This function computes a nested gradient only going back as far + * as the last nesting. + * + *

This function does not recover any memory from the computation. + * + */ +static void grad() { + size_t end = ChainableStack::instance_->var_stack_.size(); + size_t beginning = empty_nested() ? 0 : end - nested_size(); + for (size_t i = end; i-- > beginning;) { + ChainableStack::instance_->var_stack_[i]->chain(); + } +} + /** * Compute the gradient for all variables starting from the * specified root variable implementation. Does not recover @@ -33,26 +53,6 @@ static void grad(Vari* vi) { grad(); } -/** - * Compute the gradient for all variables starting from the end of the AD tape. - * This function does not recover memory. The chain - * rule is applied working down the stack from the last vari created on the - * AD tape and then calling each vari's `chain()` method in turn. - * - *

This function computes a nested gradient only going back as far - * as the last nesting. - * - *

This function does not recover any memory from the computation. - * - */ -static void grad() { - size_t end = ChainableStack::instance_->var_stack_.size(); - size_t beginning = empty_nested() ? 0 : end - nested_size(); - for (size_t i = end; i-- > beginning;) { - ChainableStack::instance_->var_stack_[i]->chain(); - } -} - } // namespace math } // namespace stan From 72d85a6ec4f5ba6df17ad5a85f927e1e6357ef8b Mon Sep 17 00:00:00 2001 From: tadej Date: Thu, 6 Aug 2020 13:42:46 +0200 Subject: [PATCH 193/355] addressed review comments --- stan/math/rev/core.hpp | 1 + stan/math/rev/core/precomputed_gradients.hpp | 31 ++++++----- stan/math/rev/core/vari.hpp | 2 +- stan/math/rev/fun/to_ad_stack.hpp | 40 +++++++++++--- stan/math/rev/functor/ad_stack_matrix.hpp | 52 +++++++++++++------ .../rev/functor/operands_and_partials.hpp | 16 +++--- stan/math/rev/meta/ad_stack_type.hpp | 6 +-- test/unit/math/rev/core/ad_allocator_test.cpp | 23 ++++++++ .../math/rev/functor/ad_stack_matrix_test.cpp | 30 ++++++++--- 9 files changed, 147 insertions(+), 54 deletions(-) create mode 100644 test/unit/math/rev/core/ad_allocator_test.cpp diff --git a/stan/math/rev/core.hpp b/stan/math/rev/core.hpp index 7ff988c98f0..449a0bcb740 100644 --- a/stan/math/rev/core.hpp +++ b/stan/math/rev/core.hpp @@ -2,6 +2,7 @@ #define STAN_MATH_REV_CORE_HPP #include +#include #include #include #include diff --git a/stan/math/rev/core/precomputed_gradients.hpp b/stan/math/rev/core/precomputed_gradients.hpp index 95f70563a0d..acd4e70d518 100644 --- a/stan/math/rev/core/precomputed_gradients.hpp +++ b/stan/math/rev/core/precomputed_gradients.hpp @@ -75,13 +75,16 @@ class precomputed_gradients_vari_template : public vari { double val, size_t size, vari** varis, double* gradients, const std::tuple& container_operands = std::tuple<>(), const std::tuple& container_gradients = std::tuple<>()) - : vari(val), size_(size), varis_(varis), gradients_(gradients) { - index_apply([&, this](auto... Is) { - this->container_operands_ - = std::make_tuple(to_AD_stack(std::get(container_operands))...); - this->container_gradients_ - = std::make_tuple(to_AD_stack(std::get(container_gradients))...); - }); + : vari(val), + size_(size), + varis_(varis), + gradients_(gradients), + container_operands_(index_apply([&, this](auto... Is) { + return std::make_tuple(to_AD_stack(std::get(container_operands))...); + })), + container_gradients_(index_apply([&, this](auto... Is) { + return std::make_tuple(to_AD_stack(std::get(container_gradients))...); + })) { check_sizes(std::make_index_sequence()); } @@ -117,13 +120,13 @@ class precomputed_gradients_vari_template : public vari { varis_(ChainableStack::instance_->memalloc_.alloc_array( vars.size())), gradients_(ChainableStack::instance_->memalloc_.alloc_array( - vars.size())) { - index_apply([&, this](auto... Is) { - this->container_operands_ - = std::make_tuple(to_AD_stack(std::get(container_operands))...); - this->container_gradients_ - = std::make_tuple(to_AD_stack(std::get(container_gradients))...); - }); + vars.size())), + container_operands_(index_apply([&, this](auto... Is) { + return std::make_tuple(to_AD_stack(std::get(container_operands))...); + })), + container_gradients_(index_apply([&, this](auto... Is) { + return std::make_tuple(to_AD_stack(std::get(container_gradients))...); + })) { check_consistent_sizes("precomputed_gradients_vari", "vars", vars, "gradients", gradients); check_sizes(std::make_index_sequence()); diff --git a/stan/math/rev/core/vari.hpp b/stan/math/rev/core/vari.hpp index 7a31e045fd6..e6d302ad0c1 100644 --- a/stan/math/rev/core/vari.hpp +++ b/stan/math/rev/core/vari.hpp @@ -287,7 +287,7 @@ class vari_value> : public vari_base { /** * Return the number of columns for this class's `val_` member */ - const Eigen::Index cols() const { return val_.rows(); } + const Eigen::Index cols() const { return val_.cols(); } /** * Return the size of this class's `val_` member */ diff --git a/stan/math/rev/fun/to_ad_stack.hpp b/stan/math/rev/fun/to_ad_stack.hpp index eaa93d3dba2..8d7d2f18af4 100644 --- a/stan/math/rev/fun/to_ad_stack.hpp +++ b/stan/math/rev/fun/to_ad_stack.hpp @@ -4,6 +4,7 @@ #include #include #include +#include namespace stan { namespace math { @@ -12,14 +13,40 @@ namespace math { * Converts given argument into a type that has any dynamic allocation on AD * stack. * - * For scalars this is a no-op. + * For types that already have this property (including scalars and + * `var_value`s) this is a no-op. * @tparam type of scalar * @param a argument * @return argument */ -template * = nullptr> -T to_AD_stack(T&& a) { - return std::forward(a); +template >* = nullptr> +T to_AD_stack(const T& a) { + // intentionally making a copy (not using forwarding or returning references) + // as these types are cheap to copy and any object referenced by an input + // reference might go out of scope before the returned value is used + return a; +} + +/** + * Converts given argument into a type that has any dynamic allocation on AD + * stack. + * + * For std vectors that have data already on AD stack this is a shallow copy. + * @tparam type of scalar + * @param a argument + * @return argument + */ +template +std::vector> to_AD_stack( + const std::vector>& a) { + // What we want to do here is the same as moving input into output, except + // that we want input to be left unchanged. With any normal allocator that + // lead to deallocating memory twice (probably segfaulting). However, + // dealocation with `AD_allocator` is a no-op, so we can do that. + std::vector> res; + std::memcpy(static_cast(&res), static_cast(&a), + sizeof(std::vector>)); + return res; } /** @@ -31,9 +58,10 @@ T to_AD_stack(T&& a) { * @param a argument * @return argument copied/evaluated on AD stack */ -template * = nullptr> +template * = nullptr, + require_not_same_t>* = nullptr> AD_stack_t to_AD_stack(const T& a) { - return AD_stack_t(a); + return {a}; } /** diff --git a/stan/math/rev/functor/ad_stack_matrix.hpp b/stan/math/rev/functor/ad_stack_matrix.hpp index bceea53b468..3dd3dac3748 100644 --- a/stan/math/rev/functor/ad_stack_matrix.hpp +++ b/stan/math/rev/functor/ad_stack_matrix.hpp @@ -7,6 +7,13 @@ namespace stan { namespace math { +/** + * Equivalent to `Eigen::Matrix`, except that the data is stored on AD stack. + * That makes these objects triviali destructible and usable in `vari`s. + * + * @tparam MatrixType Eigen matrix type this works as (`MatrixXd`, `VectorXd` + * ...) + */ template class AD_stack_matrix : public Eigen::Map { public: @@ -19,9 +26,8 @@ class AD_stack_matrix : public Eigen::Map { */ AD_stack_matrix() : Eigen::Map::Map( - nullptr, - RowsAtCompileTime == Eigen::Dynamic ? 0 : RowsAtCompileTime, - ColsAtCompileTime == Eigen::Dynamic ? 0 : ColsAtCompileTime) {} + nullptr, RowsAtCompileTime == Eigen::Dynamic ? 0 : RowsAtCompileTime, + ColsAtCompileTime == Eigen::Dynamic ? 0 : ColsAtCompileTime) {} /** * Constructs `AD_stack_matrix` with given number of rows and columns. @@ -30,9 +36,8 @@ class AD_stack_matrix : public Eigen::Map { */ AD_stack_matrix(Eigen::Index rows, Eigen::Index cols) : Eigen::Map::Map( - ChainableStack::instance_->memalloc_.alloc_array(rows - * cols), - rows, cols) {} + ChainableStack::instance_->memalloc_.alloc_array(rows * cols), + rows, cols) {} /** * Constructs `AD_stack_matrix` with given size. This only works if @@ -41,19 +46,19 @@ class AD_stack_matrix : public Eigen::Map { */ explicit AD_stack_matrix(Eigen::Index size) : Eigen::Map::Map( - ChainableStack::instance_->memalloc_.alloc_array(size), - size) {} + ChainableStack::instance_->memalloc_.alloc_array(size), + size) {} /** - * Constructs `AD_stack_matrix` form an expression. + * Constructs `AD_stack_matrix` from an expression. * @param other expression */ template * = nullptr> - AD_stack_matrix(const T& other) // NOLINT + AD_stack_matrix(const T& other) // NOLINT : Eigen::Map::Map( - ChainableStack::instance_->memalloc_.alloc_array( - other.size()), - other.rows(), other.cols()) { + ChainableStack::instance_->memalloc_.alloc_array( + other.size()), + other.rows(), other.cols()) { *this = other; } @@ -62,7 +67,8 @@ class AD_stack_matrix : public Eigen::Map { * @param other matrix to copy from */ AD_stack_matrix(const AD_stack_matrix& other) - : Eigen::Map::Map(const_cast(other.data()), other.rows(), other.cols()) {} + : Eigen::Map::Map(const_cast(other.data()), + other.rows(), other.cols()) {} using Eigen::Map::operator=; @@ -73,7 +79,23 @@ class AD_stack_matrix : public Eigen::Map { */ AD_stack_matrix& operator=(const AD_stack_matrix& other) { // placement new changes what data map points to - there is no allocation - new (this) Eigen::Map(const_cast(other.data()), other.rows(), other.cols()); + new (this) Eigen::Map(const_cast(other.data()), + other.rows(), other.cols()); + return *this; + } + + /** + * Assignment operator for assigning an expression. + * @param other expression to evaluate into this + * @return `*this` + */ + template + AD_stack_matrix& operator=(const T& a) { + // placement new changes what data map points to - there is no allocation + new (this) Eigen::Map( + ChainableStack::instance_->memalloc_.alloc_array(a.size()), + a.rows(), a.cols()); + Eigen::Map::operator=(a); return *this; } diff --git a/stan/math/rev/functor/operands_and_partials.hpp b/stan/math/rev/functor/operands_and_partials.hpp index 1f7ebce0725..3279f2316bf 100644 --- a/stan/math/rev/functor/operands_and_partials.hpp +++ b/stan/math/rev/functor/operands_and_partials.hpp @@ -164,8 +164,6 @@ class operands_and_partials { double* partials, const std::tuple& container_operands, const std::tuple& container_partials) { - // Partials are decayed, so precomputed_gradients_vari_template always - // stores values, not references return new precomputed_gradients_vari_template< std::tuple...>, std::tuple...>>( value, edges_size, varis, partials, container_operands, @@ -241,11 +239,11 @@ class ops_partials_edge> { template class ops_partials_edge, require_eigen_t> { public: - using partials_t = plain_type_t; + using partials_t = AD_stack_t; partials_t partials_; // For univariate use-cases broadcast_array partials_vec_; // For multivariate explicit ops_partials_edge(const var_value& ops) - : partials_(partials_t::Zero(ops.vi_->rows(), ops.vi_->cols())), + : partials_(plain_type_t::Zero(ops.vi_->rows(), ops.vi_->cols())), partials_vec_(partials_), operands_(ops) {} @@ -260,8 +258,8 @@ class ops_partials_edge, require_eigen_t> { std::tuple&> container_operands() { return std::forward_as_tuple(operands_); } - std::tuple container_partials() { - return std::forward_as_tuple(std::move(partials_)); + std::tuple container_partials() { + return std::forward_as_tuple(partials_); } }; @@ -359,7 +357,7 @@ template class ops_partials_edge>, require_eigen_t> { public: - using partials_t = std::vector>; + using partials_t = AD_stack_t>; partials_t partials_vec_; explicit ops_partials_edge(const std::vector>& ops) : partials_vec_(ops.size()), operands_(ops) { @@ -380,8 +378,8 @@ class ops_partials_edge>, std::tuple>&> container_operands() { return std::forward_as_tuple(operands_); } - std::tuple container_partials() { - return std::forward_as_tuple(std::move(partials_vec_)); + std::tuple container_partials() { + return std::forward_as_tuple(partials_vec_); } }; } // namespace internal diff --git a/stan/math/rev/meta/ad_stack_type.hpp b/stan/math/rev/meta/ad_stack_type.hpp index 045f5486678..071cf2b6813 100644 --- a/stan/math/rev/meta/ad_stack_type.hpp +++ b/stan/math/rev/meta/ad_stack_type.hpp @@ -1,5 +1,5 @@ -#ifndef AD_STACK_TYPE_HPP -#define AD_STACK_TYPE_HPP +#ifndef STAN_MATH_REV_META_AD_STACK_TYPE_HPP +#define STAN_MATH_REV_META_AD_STACK_TYPE_HPP #include #include @@ -41,4 +41,4 @@ using AD_stack_t = typename internal::AD_stack_type_impl>::type; } // namespace stan -#endif // AD_STACK_TYPE_HPP +#endif diff --git a/test/unit/math/rev/core/ad_allocator_test.cpp b/test/unit/math/rev/core/ad_allocator_test.cpp new file mode 100644 index 00000000000..3ffd1e7f61b --- /dev/null +++ b/test/unit/math/rev/core/ad_allocator_test.cpp @@ -0,0 +1,23 @@ +#include +#include +#include + +void ad_allocator_test() { + std::vector> v; + v.reserve(3); + for (int i = 0; i < 5; i++) { + v.push_back(1); + } + + std::vector> v2(2, 3); + for (int i = 0; i < 5; i++) { + v2.push_back(2); + } + + std::vector> v3(v2); + for (int i = 0; i < 15; i++) { + v3.push_back(3); + } +} + +TEST(AgradRev, AD_allocator_test) { EXPECT_NO_THROW(ad_allocator_test()); } diff --git a/test/unit/math/rev/functor/ad_stack_matrix_test.cpp b/test/unit/math/rev/functor/ad_stack_matrix_test.cpp index 1a8c36cef9c..9e9953073fe 100644 --- a/test/unit/math/rev/functor/ad_stack_matrix_test.cpp +++ b/test/unit/math/rev/functor/ad_stack_matrix_test.cpp @@ -9,21 +9,27 @@ TEST(AgradRev, AD_stack_matrix_matrix_test) { // construction AD_stack_matrix a; AD_stack_matrix a2; + AD_stack_matrix a3; AD_stack_matrix b(3, 2); - AD_stack_matrix b2(3, 2); + AD_stack_matrix b2(4, 5); AD_stack_matrix c(MatrixXd::Ones(3, 2)); AD_stack_matrix d(c); AD_stack_matrix e(2 * d); + // resize + a2.resize(4, 5); + b2.resize(3, 2); + // assignment a = c; a2 = std::move(d); + a3 = 2 * a; b = d; b2 = std::move(c); e = e + a; a = MatrixXd::Ones(3, 2); - EXPECT_MATRIX_EQ(a + a2 + b + b2 + e, MatrixXd::Ones(3, 2) * 7); + EXPECT_MATRIX_EQ(a + a2 + a3 + b + b2 + e, MatrixXd::Ones(3, 2) * 9); } TEST(AgradRev, AD_stack_matrix_vector_test) { @@ -33,21 +39,27 @@ TEST(AgradRev, AD_stack_matrix_vector_test) { // construction AD_stack_matrix a; AD_stack_matrix a2; + AD_stack_matrix a3; AD_stack_matrix b(3); - AD_stack_matrix b2(3); + AD_stack_matrix b2(4); AD_stack_matrix c(VectorXd::Ones(3)); AD_stack_matrix d(c); AD_stack_matrix e(2 * d); + // resize + a2.resize(4); + b2.resize(3); + // assignment a = c; a2 = std::move(d); + a3 = 2 * a; b = d; b2 = std::move(c); e = e + a; a = VectorXd::Ones(3); - EXPECT_MATRIX_EQ(a + a2 + b + b2 + e, VectorXd::Ones(3) * 7); + EXPECT_MATRIX_EQ(a + a2 + a3 + b + b2 + e, VectorXd::Ones(3) * 9); } TEST(AgradRev, AD_stack_matrix_row_vector_test) { @@ -57,19 +69,25 @@ TEST(AgradRev, AD_stack_matrix_row_vector_test) { // construction AD_stack_matrix a; AD_stack_matrix a2; + AD_stack_matrix a3; AD_stack_matrix b(3); - AD_stack_matrix b2(3); + AD_stack_matrix b2(4); AD_stack_matrix c(RowVectorXd::Ones(3)); AD_stack_matrix d(c); AD_stack_matrix e(2 * d); + // resize + a2.resize(4); + b2.resize(3); + // assignment a = c; a2 = std::move(d); + a3 = 2 * a; b = d; b2 = std::move(c); e = e + a; a = RowVectorXd::Ones(3); - EXPECT_MATRIX_EQ(a + a2 + b + b2 + e, RowVectorXd::Ones(3) * 7); + EXPECT_MATRIX_EQ(a + a2 + a3 + b + b2 + e, RowVectorXd::Ones(3) * 9); } From cb04a08fd22ca0cb98537357f31eb64cb80448f4 Mon Sep 17 00:00:00 2001 From: Stan Jenkins Date: Thu, 6 Aug 2020 13:28:56 +0000 Subject: [PATCH 194/355] [Jenkins] auto-formatting by clang-format version 6.0.0-1ubuntu2~16.04.1 (tags/RELEASE_600/final) --- stan/math/rev/core/precomputed_gradients.hpp | 12 +++++++---- stan/math/rev/functor/ad_stack_matrix.hpp | 20 ++++++++++--------- .../rev/functor/operands_and_partials.hpp | 3 ++- 3 files changed, 21 insertions(+), 14 deletions(-) diff --git a/stan/math/rev/core/precomputed_gradients.hpp b/stan/math/rev/core/precomputed_gradients.hpp index acd4e70d518..2be9ca5740a 100644 --- a/stan/math/rev/core/precomputed_gradients.hpp +++ b/stan/math/rev/core/precomputed_gradients.hpp @@ -80,10 +80,12 @@ class precomputed_gradients_vari_template : public vari { varis_(varis), gradients_(gradients), container_operands_(index_apply([&, this](auto... Is) { - return std::make_tuple(to_AD_stack(std::get(container_operands))...); + return std::make_tuple( + to_AD_stack(std::get(container_operands))...); })), container_gradients_(index_apply([&, this](auto... Is) { - return std::make_tuple(to_AD_stack(std::get(container_gradients))...); + return std::make_tuple( + to_AD_stack(std::get(container_gradients))...); })) { check_sizes(std::make_index_sequence()); } @@ -122,10 +124,12 @@ class precomputed_gradients_vari_template : public vari { gradients_(ChainableStack::instance_->memalloc_.alloc_array( vars.size())), container_operands_(index_apply([&, this](auto... Is) { - return std::make_tuple(to_AD_stack(std::get(container_operands))...); + return std::make_tuple( + to_AD_stack(std::get(container_operands))...); })), container_gradients_(index_apply([&, this](auto... Is) { - return std::make_tuple(to_AD_stack(std::get(container_gradients))...); + return std::make_tuple( + to_AD_stack(std::get(container_gradients))...); })) { check_consistent_sizes("precomputed_gradients_vari", "vars", vars, "gradients", gradients); diff --git a/stan/math/rev/functor/ad_stack_matrix.hpp b/stan/math/rev/functor/ad_stack_matrix.hpp index 3dd3dac3748..b22df5dbe4d 100644 --- a/stan/math/rev/functor/ad_stack_matrix.hpp +++ b/stan/math/rev/functor/ad_stack_matrix.hpp @@ -26,8 +26,9 @@ class AD_stack_matrix : public Eigen::Map { */ AD_stack_matrix() : Eigen::Map::Map( - nullptr, RowsAtCompileTime == Eigen::Dynamic ? 0 : RowsAtCompileTime, - ColsAtCompileTime == Eigen::Dynamic ? 0 : ColsAtCompileTime) {} + nullptr, + RowsAtCompileTime == Eigen::Dynamic ? 0 : RowsAtCompileTime, + ColsAtCompileTime == Eigen::Dynamic ? 0 : ColsAtCompileTime) {} /** * Constructs `AD_stack_matrix` with given number of rows and columns. @@ -36,8 +37,9 @@ class AD_stack_matrix : public Eigen::Map { */ AD_stack_matrix(Eigen::Index rows, Eigen::Index cols) : Eigen::Map::Map( - ChainableStack::instance_->memalloc_.alloc_array(rows * cols), - rows, cols) {} + ChainableStack::instance_->memalloc_.alloc_array(rows + * cols), + rows, cols) {} /** * Constructs `AD_stack_matrix` with given size. This only works if @@ -46,8 +48,8 @@ class AD_stack_matrix : public Eigen::Map { */ explicit AD_stack_matrix(Eigen::Index size) : Eigen::Map::Map( - ChainableStack::instance_->memalloc_.alloc_array(size), - size) {} + ChainableStack::instance_->memalloc_.alloc_array(size), + size) {} /** * Constructs `AD_stack_matrix` from an expression. @@ -56,9 +58,9 @@ class AD_stack_matrix : public Eigen::Map { template * = nullptr> AD_stack_matrix(const T& other) // NOLINT : Eigen::Map::Map( - ChainableStack::instance_->memalloc_.alloc_array( - other.size()), - other.rows(), other.cols()) { + ChainableStack::instance_->memalloc_.alloc_array( + other.size()), + other.rows(), other.cols()) { *this = other; } diff --git a/stan/math/rev/functor/operands_and_partials.hpp b/stan/math/rev/functor/operands_and_partials.hpp index 3279f2316bf..fcc1fef9c76 100644 --- a/stan/math/rev/functor/operands_and_partials.hpp +++ b/stan/math/rev/functor/operands_and_partials.hpp @@ -243,7 +243,8 @@ class ops_partials_edge, require_eigen_t> { partials_t partials_; // For univariate use-cases broadcast_array partials_vec_; // For multivariate explicit ops_partials_edge(const var_value& ops) - : partials_(plain_type_t::Zero(ops.vi_->rows(), ops.vi_->cols())), + : partials_( + plain_type_t::Zero(ops.vi_->rows(), ops.vi_->cols())), partials_vec_(partials_), operands_(ops) {} From 84b65857ebfe58b07ae62c3c04c4aa61b06186bc Mon Sep 17 00:00:00 2001 From: tadej Date: Thu, 6 Aug 2020 17:09:02 +0200 Subject: [PATCH 195/355] fixed doxygen --- stan/math/rev/functor/ad_stack_matrix.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stan/math/rev/functor/ad_stack_matrix.hpp b/stan/math/rev/functor/ad_stack_matrix.hpp index 3dd3dac3748..7c1d57996db 100644 --- a/stan/math/rev/functor/ad_stack_matrix.hpp +++ b/stan/math/rev/functor/ad_stack_matrix.hpp @@ -86,7 +86,7 @@ class AD_stack_matrix : public Eigen::Map { /** * Assignment operator for assigning an expression. - * @param other expression to evaluate into this + * @param a expression to evaluate into this * @return `*this` */ template From 4e70ba6b3165a0b68885861eab8d705a939929e9 Mon Sep 17 00:00:00 2001 From: Stan Jenkins Date: Thu, 6 Aug 2020 17:55:21 +0000 Subject: [PATCH 196/355] [Jenkins] auto-formatting by clang-format version 6.0.0-1ubuntu2~16.04.1 (tags/RELEASE_600/final) --- stan/math/rev/core/vari.hpp | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/stan/math/rev/core/vari.hpp b/stan/math/rev/core/vari.hpp index b0ae98487c3..51925ac349d 100644 --- a/stan/math/rev/core/vari.hpp +++ b/stan/math/rev/core/vari.hpp @@ -207,13 +207,11 @@ class vari_value> : public vari_base { /** * Number of rows known at compile time */ - static constexpr int RowsAtCompileTime - = PlainObject::RowsAtCompileTime; + static constexpr int RowsAtCompileTime = PlainObject::RowsAtCompileTime; /** * Number of columns known at compile time */ - static constexpr int ColsAtCompileTime - = PlainObject::ColsAtCompileTime; + static constexpr int ColsAtCompileTime = PlainObject::ColsAtCompileTime; /** * The value of this variable. From 8cec8bb9b99614237f7fc7acfbda91083b6610cd Mon Sep 17 00:00:00 2001 From: Steve Bronder Date: Thu, 6 Aug 2020 16:38:17 -0400 Subject: [PATCH 197/355] Use pf in var_value for the sparse matrix constructor --- stan/math/rev/core/var.hpp | 2 +- stan/math/rev/core/vari.hpp | 13 +++++++------ 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/stan/math/rev/core/var.hpp b/stan/math/rev/core/var.hpp index be9c43cda5e..b7b453d7a28 100644 --- a/stan/math/rev/core/var.hpp +++ b/stan/math/rev/core/var.hpp @@ -86,7 +86,7 @@ class var_value { * @param x Value of the variable. */ template * = nullptr> - var_value(const S& x) : vi_(new vari_type(x, false)) {} // NOLINT + var_value(S&& x) : vi_(new vari_type(std::forward(x), false)) {} // NOLINT /** * Construct a variable from a pointer to a variable implementation. diff --git a/stan/math/rev/core/vari.hpp b/stan/math/rev/core/vari.hpp index 51925ac349d..4aec90125b5 100644 --- a/stan/math/rev/core/vari.hpp +++ b/stan/math/rev/core/vari.hpp @@ -380,10 +380,6 @@ class vari_value> : public vari_base, * Columns at compile time */ static constexpr int ColsAtCompileTime = T::ColsAtCompileTime; - /** - * The value of this variable. - */ - const PlainObject val_; /** * The adjoint of this variable, which is the partial derivative @@ -391,6 +387,11 @@ class vari_value> : public vari_base, */ PlainObject adj_; + /** + * The value of this variable. + */ + const PlainObject val_; + /** * Construct a variable implementation from a value. The * adjoint is initialized to zero. @@ -406,7 +407,7 @@ class vari_value> : public vari_base, * @param x Value of the constructed variable. */ template * = nullptr> - explicit vari_value(const S& x) : val_(x), adj_(x), chainable_alloc() { + explicit vari_value(S&& x) : adj_(x), val_(std::forward(x)), chainable_alloc() { this->set_zero_adjoint(); ChainableStack::instance_->var_stack_.push_back(this); } @@ -428,7 +429,7 @@ class vari_value> : public vari_base, * that its `chain()` method is not called. */ template * = nullptr> - vari_value(const S& x, bool stacked) : val_(x), adj_(x), chainable_alloc() { + vari_value(S&& x, bool stacked) : adj_(x), val_(std::forward(x)), chainable_alloc() { this->set_zero_adjoint(); if (stacked) { ChainableStack::instance_->var_stack_.push_back(this); From 32045cca0cd25023b9606c66a8f5f0a7976281f0 Mon Sep 17 00:00:00 2001 From: Stan Jenkins Date: Thu, 6 Aug 2020 20:38:56 +0000 Subject: [PATCH 198/355] [Jenkins] auto-formatting by clang-format version 6.0.0-1ubuntu2~16.04.1 (tags/RELEASE_600/final) --- stan/math/rev/core/vari.hpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/stan/math/rev/core/vari.hpp b/stan/math/rev/core/vari.hpp index 4aec90125b5..b17e532870c 100644 --- a/stan/math/rev/core/vari.hpp +++ b/stan/math/rev/core/vari.hpp @@ -407,7 +407,8 @@ class vari_value> : public vari_base, * @param x Value of the constructed variable. */ template * = nullptr> - explicit vari_value(S&& x) : adj_(x), val_(std::forward(x)), chainable_alloc() { + explicit vari_value(S&& x) + : adj_(x), val_(std::forward(x)), chainable_alloc() { this->set_zero_adjoint(); ChainableStack::instance_->var_stack_.push_back(this); } @@ -429,7 +430,8 @@ class vari_value> : public vari_base, * that its `chain()` method is not called. */ template * = nullptr> - vari_value(S&& x, bool stacked) : adj_(x), val_(std::forward(x)), chainable_alloc() { + vari_value(S&& x, bool stacked) + : adj_(x), val_(std::forward(x)), chainable_alloc() { this->set_zero_adjoint(); if (stacked) { ChainableStack::instance_->var_stack_.push_back(this); From 07b96b8f52a6f96120c7f5a678fdd2b29ee8f4c2 Mon Sep 17 00:00:00 2001 From: tadej Date: Fri, 7 Aug 2020 10:06:56 +0200 Subject: [PATCH 199/355] addressed second batch of review comments --- stan/math/rev/core.hpp | 2 +- stan/math/rev/core/ad_allocator.hpp | 48 -------------- stan/math/rev/fun/to_ad_stack.hpp | 10 +-- stan/math/rev/functor/ad_stack_matrix.hpp | 27 +------- stan/math/rev/meta/ad_stack_type.hpp | 4 +- test/unit/math/rev/core/ad_allocator_test.cpp | 23 ------- .../math/rev/core/ad_stack_allocator_test.cpp | 23 +++++++ test/unit/math/rev/fun/to_ad_stack_test.cpp | 62 +++++++++++++++++++ .../math/rev/functor/ad_stack_matrix_test.cpp | 12 ---- 9 files changed, 95 insertions(+), 116 deletions(-) delete mode 100644 stan/math/rev/core/ad_allocator.hpp delete mode 100644 test/unit/math/rev/core/ad_allocator_test.cpp create mode 100644 test/unit/math/rev/core/ad_stack_allocator_test.cpp create mode 100644 test/unit/math/rev/fun/to_ad_stack_test.cpp diff --git a/stan/math/rev/core.hpp b/stan/math/rev/core.hpp index 449a0bcb740..a93d2639eac 100644 --- a/stan/math/rev/core.hpp +++ b/stan/math/rev/core.hpp @@ -2,7 +2,7 @@ #define STAN_MATH_REV_CORE_HPP #include -#include +#include #include #include #include diff --git a/stan/math/rev/core/ad_allocator.hpp b/stan/math/rev/core/ad_allocator.hpp deleted file mode 100644 index 183e2592c82..00000000000 --- a/stan/math/rev/core/ad_allocator.hpp +++ /dev/null @@ -1,48 +0,0 @@ -#ifndef STAN_MATH_REV_CORE_AD_ALLOCATOR_HPP -#define STAN_MATH_REV_CORE_AD_ALLOCATOR_HPP - -#include - -namespace stan { -namespace math { - -/** - * std library compatible allocator that uses AD stack. - * @tparam T type of scalar - */ -template -struct AD_allocator { - using value_type = T; - - /** - * Allocates space for `n` items of type `T`. - * - * @param n number of items to allocate space for - * @return pointer to allocated space - */ - T* allocate(std::size_t n) { - return ChainableStack::instance_->memalloc_.alloc_array(n); - } - - /** - * No-op. Memory is dealocated by caling `recover_memory()`. - */ - void deallocate(T* /*p*/, std::size_t /*n*/) noexcept {} - - /** - * Equality comparison operator. - * @return true - */ - bool operator==(const AD_allocator&) { return true; } - - /** - * Inequality comparison operator. - * @return false - */ - bool operator!=(const AD_allocator&) { return false; } -}; - -} // namespace math -} // namespace stan - -#endif diff --git a/stan/math/rev/fun/to_ad_stack.hpp b/stan/math/rev/fun/to_ad_stack.hpp index 8d7d2f18af4..938c6394df7 100644 --- a/stan/math/rev/fun/to_ad_stack.hpp +++ b/stan/math/rev/fun/to_ad_stack.hpp @@ -37,15 +37,15 @@ T to_AD_stack(const T& a) { * @return argument */ template -std::vector> to_AD_stack( - const std::vector>& a) { +std::vector> to_AD_stack( + const std::vector>& a) { // What we want to do here is the same as moving input into output, except // that we want input to be left unchanged. With any normal allocator that // lead to deallocating memory twice (probably segfaulting). However, - // dealocation with `AD_allocator` is a no-op, so we can do that. - std::vector> res; + // dealocation with `AD_stack_allocator` is a no-op, so we can do that. + std::vector> res; std::memcpy(static_cast(&res), static_cast(&a), - sizeof(std::vector>)); + sizeof(std::vector>)); return res; } diff --git a/stan/math/rev/functor/ad_stack_matrix.hpp b/stan/math/rev/functor/ad_stack_matrix.hpp index ac4653cfb8c..114108a4259 100644 --- a/stan/math/rev/functor/ad_stack_matrix.hpp +++ b/stan/math/rev/functor/ad_stack_matrix.hpp @@ -72,6 +72,8 @@ class AD_stack_matrix : public Eigen::Map { : Eigen::Map::Map(const_cast(other.data()), other.rows(), other.cols()) {} + // without this using, compiler prefers combination of implicit construction + // and copy assignment to the inherited operator when assigned an expression using Eigen::Map::operator=; /** @@ -100,31 +102,6 @@ class AD_stack_matrix : public Eigen::Map { Eigen::Map::operator=(a); return *this; } - - /** - * Resizes this object to given number of rows and columns. - * @param rows number of rows - * @param cols number of columns - */ - void resize(Eigen::Index rows, Eigen::Index cols) { - // placement new changes what data map points to - this new is not an - // allocation - new (this) Eigen::Map( - ChainableStack::instance_->memalloc_.alloc_array(rows * cols), - rows, cols); - } - - /** - * Resizes this object to given size. This only works if `MatrixType` is row - * or col vector. - * @param size number of elements - */ - void resize(Eigen::Index size) { - // placement new changes what data map points to - this new is not an - // allocation - new (this) Eigen::Map( - ChainableStack::instance_->memalloc_.alloc_array(size), size); - } }; } // namespace math diff --git a/stan/math/rev/meta/ad_stack_type.hpp b/stan/math/rev/meta/ad_stack_type.hpp index 071cf2b6813..bb83ad35041 100644 --- a/stan/math/rev/meta/ad_stack_type.hpp +++ b/stan/math/rev/meta/ad_stack_type.hpp @@ -3,7 +3,7 @@ #include #include -#include +#include namespace stan { namespace math { @@ -21,7 +21,7 @@ struct AD_stack_type_impl { template struct AD_stack_type_impl> { using T_ad = typename AD_stack_type_impl>::type; - using type = std::vector>; + using type = std::vector>; }; template diff --git a/test/unit/math/rev/core/ad_allocator_test.cpp b/test/unit/math/rev/core/ad_allocator_test.cpp deleted file mode 100644 index 3ffd1e7f61b..00000000000 --- a/test/unit/math/rev/core/ad_allocator_test.cpp +++ /dev/null @@ -1,23 +0,0 @@ -#include -#include -#include - -void ad_allocator_test() { - std::vector> v; - v.reserve(3); - for (int i = 0; i < 5; i++) { - v.push_back(1); - } - - std::vector> v2(2, 3); - for (int i = 0; i < 5; i++) { - v2.push_back(2); - } - - std::vector> v3(v2); - for (int i = 0; i < 15; i++) { - v3.push_back(3); - } -} - -TEST(AgradRev, AD_allocator_test) { EXPECT_NO_THROW(ad_allocator_test()); } diff --git a/test/unit/math/rev/core/ad_stack_allocator_test.cpp b/test/unit/math/rev/core/ad_stack_allocator_test.cpp new file mode 100644 index 00000000000..d8f7debcecc --- /dev/null +++ b/test/unit/math/rev/core/ad_stack_allocator_test.cpp @@ -0,0 +1,23 @@ +#include +#include +#include + +void ad_stack_allocator_test() { + std::vector> v; + v.reserve(3); + for (int i = 0; i < 5; i++) { + v.push_back(1); + } + + std::vector> v2(2, 3); + for (int i = 0; i < 5; i++) { + v2.push_back(2); + } + + std::vector> v3(v2); + for (int i = 0; i < 15; i++) { + v3.push_back(3); + } +} + +TEST(AgradRev, AD_stack_allocator_test) { EXPECT_NO_THROW(ad_stack_allocator_test()); } diff --git a/test/unit/math/rev/fun/to_ad_stack_test.cpp b/test/unit/math/rev/fun/to_ad_stack_test.cpp new file mode 100644 index 00000000000..c649d7d1568 --- /dev/null +++ b/test/unit/math/rev/fun/to_ad_stack_test.cpp @@ -0,0 +1,62 @@ +#include +#include +#include +#include + +TEST(AgradRev, to_AD_stack_scalar_test) { + int a = 2; + auto b = stan::math::to_AD_stack(a); + EXPECT_EQ(b, a); + EXPECT_TRUE((std::is_same::value)); + double a2 = 2; + auto b2 = stan::math::to_AD_stack(a2); + EXPECT_EQ(b2, a2); + EXPECT_TRUE((std::is_same::value)); +} + +TEST(AgradRev, to_AD_stack_std_vector_test) { + std::vector a{1, 2}; + auto b = stan::math::to_AD_stack(a); + ASSERT_EQ(a.size(), b.size()); + for (int i = 0; i < a.size(); i++) { + EXPECT_EQ(a[i], b[i]); + } + EXPECT_FALSE((std::is_same::value)); + + auto c = stan::math::to_AD_stack(b); + EXPECT_EQ(b.size(), c.size()); + EXPECT_EQ(b.data(), c.data()); +} + +TEST(AgradRev, to_AD_stack_col_vector_test) { + Eigen::VectorXd a(2); + a << 1, 2; + auto b = stan::math::to_AD_stack(a); + EXPECT_MATRIX_EQ(a, b); + EXPECT_FALSE((std::is_same::value)); + auto c = stan::math::to_AD_stack(b); + EXPECT_EQ(b.size(), c.size()); + EXPECT_EQ(b.data(), c.data()); +} + +TEST(AgradRev, to_AD_stack_row_vector_test) { + Eigen::RowVectorXd a(2); + a << 1, 2; + auto b = stan::math::to_AD_stack(a); + EXPECT_MATRIX_EQ(a, b); + EXPECT_FALSE((std::is_same::value)); + auto c = stan::math::to_AD_stack(b); + EXPECT_EQ(b.size(), c.size()); + EXPECT_EQ(b.data(), c.data()); +} + +TEST(AgradRev, to_AD_stack_matrix_test) { + Eigen::MatrixXd a(2, 2); + a << 1, 2, 3, 4; + auto b = stan::math::to_AD_stack(a); + EXPECT_MATRIX_EQ(a, b); + EXPECT_FALSE((std::is_same::value)); + auto c = stan::math::to_AD_stack(b); + EXPECT_EQ(b.size(), c.size()); + EXPECT_EQ(b.data(), c.data()); +} diff --git a/test/unit/math/rev/functor/ad_stack_matrix_test.cpp b/test/unit/math/rev/functor/ad_stack_matrix_test.cpp index 9e9953073fe..6c646657bc4 100644 --- a/test/unit/math/rev/functor/ad_stack_matrix_test.cpp +++ b/test/unit/math/rev/functor/ad_stack_matrix_test.cpp @@ -16,10 +16,6 @@ TEST(AgradRev, AD_stack_matrix_matrix_test) { AD_stack_matrix d(c); AD_stack_matrix e(2 * d); - // resize - a2.resize(4, 5); - b2.resize(3, 2); - // assignment a = c; a2 = std::move(d); @@ -46,10 +42,6 @@ TEST(AgradRev, AD_stack_matrix_vector_test) { AD_stack_matrix d(c); AD_stack_matrix e(2 * d); - // resize - a2.resize(4); - b2.resize(3); - // assignment a = c; a2 = std::move(d); @@ -76,10 +68,6 @@ TEST(AgradRev, AD_stack_matrix_row_vector_test) { AD_stack_matrix d(c); AD_stack_matrix e(2 * d); - // resize - a2.resize(4); - b2.resize(3); - // assignment a = c; a2 = std::move(d); From 8b13df9486542ae13cd0350b8e94f80151d0acb4 Mon Sep 17 00:00:00 2001 From: tadej Date: Fri, 7 Aug 2020 10:51:27 +0200 Subject: [PATCH 200/355] remove dot_product vari* calls --- stan/math/rev/fun/columns_dot_product.hpp | 4 +--- stan/math/rev/fun/multiply_lower_tri_self_transpose.hpp | 5 +++-- stan/math/rev/fun/rows_dot_product.hpp | 4 +--- stan/math/rev/fun/tcrossprod.hpp | 4 +--- test/unit/math/mix/fun/dot_product_test.cpp | 5 ----- 5 files changed, 6 insertions(+), 16 deletions(-) diff --git a/stan/math/rev/fun/columns_dot_product.hpp b/stan/math/rev/fun/columns_dot_product.hpp index 19cde25dad7..eeba5abc810 100644 --- a/stan/math/rev/fun/columns_dot_product.hpp +++ b/stan/math/rev/fun/columns_dot_product.hpp @@ -22,9 +22,7 @@ columns_dot_product(const Mat1& v1, const Mat2& v2) { check_matching_sizes("dot_product", "v1", v1, "v2", v2); Eigen::Matrix ret(1, v1.cols()); for (size_type j = 0; j < v1.cols(); ++j) { - ret(j) = var( - new internal::dot_product_vari, value_type_t>( - v1.col(j), v2.col(j))); + ret(j) = dot_product(v1.col(j), v2.col(j)); } return ret; } diff --git a/stan/math/rev/fun/multiply_lower_tri_self_transpose.hpp b/stan/math/rev/fun/multiply_lower_tri_self_transpose.hpp index 8061ecedd3c..ea9db888dca 100644 --- a/stan/math/rev/fun/multiply_lower_tri_self_transpose.hpp +++ b/stan/math/rev/fun/multiply_lower_tri_self_transpose.hpp @@ -42,8 +42,9 @@ inline matrix_v multiply_lower_tri_self_transpose(const matrix_v& L) { LLt(m, m) = var( new internal::dot_self_vari(vs + mpos, (J < (m + 1)) ? J : (m + 1))); for (int n = 0, npos = 0; n < m; ++n, npos += (J < n) ? J : n) { - LLt(m, n) = LLt(n, m) = var(new internal::dot_product_vari( - vs + mpos, vs + npos, (J < (n + 1)) ? J : (n + 1))); + LLt(m, n) = LLt(n, m) + = dot_product(L.row(m).head((J < (n + 1)) ? J : (n + 1)), + L.row(n).head((J < (n + 1)) ? J : (n + 1))); } } return LLt; diff --git a/stan/math/rev/fun/rows_dot_product.hpp b/stan/math/rev/fun/rows_dot_product.hpp index 7cc73f9396f..e3d643941ad 100644 --- a/stan/math/rev/fun/rows_dot_product.hpp +++ b/stan/math/rev/fun/rows_dot_product.hpp @@ -20,9 +20,7 @@ inline Eigen::Matrix rows_dot_product( check_matching_sizes("dot_product", "v1", v1, "v2", v2); Eigen::Matrix ret(v1.rows(), 1); for (size_type j = 0; j < v1.rows(); ++j) { - ret(j) = var( - new internal::dot_product_vari, value_type_t>( - v1.row(j), v2.row(j))); + ret(j) = dot_product(v1.row(j), v2.row(j)); } return ret; } diff --git a/stan/math/rev/fun/tcrossprod.hpp b/stan/math/rev/fun/tcrossprod.hpp index 02b57159a9f..cbcefa4cfd2 100644 --- a/stan/math/rev/fun/tcrossprod.hpp +++ b/stan/math/rev/fun/tcrossprod.hpp @@ -51,9 +51,7 @@ tcrossprod(const T& M) { } for (int m = 0; m < M.rows(); ++m) { for (int n = 0; n < m; ++n) { - MMt(m, n) = var(new internal::dot_product_vari( - vs + m * M.cols(), vs + n * M.cols(), M.cols())); - MMt(n, m) = MMt(m, n); + MMt(n, m) = MMt(m, n) = dot_product(M.row(m), M.row(n)); } } return MMt; diff --git a/test/unit/math/mix/fun/dot_product_test.cpp b/test/unit/math/mix/fun/dot_product_test.cpp index 301a691a6e1..876b47249bf 100644 --- a/test/unit/math/mix/fun/dot_product_test.cpp +++ b/test/unit/math/mix/fun/dot_product_test.cpp @@ -98,10 +98,5 @@ TEST(mathMixMatFun, dotProduct) { auto g = [](const auto& x, const auto& y) { return stan::math::dot_product(x, y); }; - auto h = [](const auto& x, const auto& y) { - return stan::math::dot_product(x.size() > 0 ? &x[0] : nullptr, - y.size() > 0 ? &y[0] : nullptr, x.size()); - }; test_dot_product(g); // standard data type args - test_dot_product(h); // pointer args with size } From 77aaab961a87d8b6f4d395b6eca9c259227814dd Mon Sep 17 00:00:00 2001 From: Stan Jenkins Date: Fri, 7 Aug 2020 10:29:23 +0000 Subject: [PATCH 201/355] [Jenkins] auto-formatting by clang-format version 6.0.0-1ubuntu2~16.04.1 (tags/RELEASE_600/final) --- test/unit/math/rev/core/ad_stack_allocator_test.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/test/unit/math/rev/core/ad_stack_allocator_test.cpp b/test/unit/math/rev/core/ad_stack_allocator_test.cpp index d8f7debcecc..7edd0fd21d2 100644 --- a/test/unit/math/rev/core/ad_stack_allocator_test.cpp +++ b/test/unit/math/rev/core/ad_stack_allocator_test.cpp @@ -20,4 +20,6 @@ void ad_stack_allocator_test() { } } -TEST(AgradRev, AD_stack_allocator_test) { EXPECT_NO_THROW(ad_stack_allocator_test()); } +TEST(AgradRev, AD_stack_allocator_test) { + EXPECT_NO_THROW(ad_stack_allocator_test()); +} From b8674dc1aefd6c55e5951160d57c468831bbe754 Mon Sep 17 00:00:00 2001 From: tadej Date: Fri, 7 Aug 2020 13:46:36 +0200 Subject: [PATCH 202/355] dot_product now uses adjac_apply --- stan/math/prim/fun/dot_product.hpp | 6 +- stan/math/rev/fun/dot_product.hpp | 243 +++++------------------------ stan/math/rev/fun/to_ad_stack.hpp | 38 +++-- 3 files changed, 67 insertions(+), 220 deletions(-) diff --git a/stan/math/prim/fun/dot_product.hpp b/stan/math/prim/fun/dot_product.hpp index 3caefb68e31..3671cf094aa 100644 --- a/stan/math/prim/fun/dot_product.hpp +++ b/stan/math/prim/fun/dot_product.hpp @@ -56,11 +56,11 @@ inline auto dot_product(const Scalar1 *v1, const Scalar2 *v2, size_t length) { * @param v2 Second array. * @throw std::domain_error if the vectors are not the same size. */ -template , typename = require_all_not_var_t> -inline auto dot_product(const std::vector &v1, - const std::vector &v2) { +inline auto dot_product(const std::vector &v1, + const std::vector &v2) { check_matching_sizes("dot_product", "v1", v1, "v2", v2); return dot_product(&v1[0], &v2[0], v1.size()); } diff --git a/stan/math/rev/fun/dot_product.hpp b/stan/math/rev/fun/dot_product.hpp index e86755ad409..a891a9780d5 100644 --- a/stan/math/rev/fun/dot_product.hpp +++ b/stan/math/rev/fun/dot_product.hpp @@ -4,6 +4,9 @@ #include #include #include +#include +#include +#include #include #include #include @@ -14,209 +17,6 @@ namespace stan { namespace math { -namespace internal { - -template -struct dot_product_store_type; - -template <> -struct dot_product_store_type { - using type = vari**; -}; - -template <> -struct dot_product_store_type { - using type = double*; -}; - -template -class dot_product_vari : public vari { - protected: - typename dot_product_store_type::type v1_; - typename dot_product_store_type::type v2_; - size_t length_; - - inline static double var_dot(vari** v1, vari** v2, size_t length) { - Eigen::Map vd1(v1, length); - Eigen::Map vd2(v2, length); - - return vd1.val().dot(vd2.val()); - } - - inline static double var_dot(const T1* v1, const T2* v2, size_t length) { - Eigen::Map> vd1(v1, length); - Eigen::Map> vd2(v2, length); - return vd1.val().dot(vd2.val()); - } - - template - inline static double var_dot(const Eigen::DenseBase& v1, - const Eigen::DenseBase& v2) { - vector_d vd1 - = Eigen::Ref>(v1) - .val(); - vector_d vd2 - = Eigen::Ref>(v2) - .val(); - return vd1.dot(vd2); - } - inline void chain(vari** v1, vari** v2) { - Eigen::Map vd1(v1, length_); - Eigen::Map vd2(v2, length_); - vd1.adj() += adj_ * vd2.val(); - vd2.adj() += adj_ * vd1.val(); - } - inline void chain(double* v1, vari** v2) { - Eigen::Map(v2, length_).adj() - += adj_ * Eigen::Map(v1, length_); - } - inline void chain(vari** v1, double* v2) { - Eigen::Map(v1, length_).adj() - += adj_ * Eigen::Map(v2, length_); - } - inline void initialize(vari**& mem_v, const var* inv, - vari** shared = nullptr) { - if (shared == nullptr) { - mem_v = reinterpret_cast( - ChainableStack::instance_->memalloc_.alloc(length_ * sizeof(vari*))); - Eigen::Map(mem_v, length_) - = Eigen::Map(inv, length_).vi(); - } else { - mem_v = shared; - } - } - template - inline void initialize(vari**& mem_v, const Eigen::DenseBase& inv, - vari** shared = nullptr) { - if (shared == nullptr) { - mem_v = reinterpret_cast( - ChainableStack::instance_->memalloc_.alloc(length_ * sizeof(vari*))); - Eigen::Map(mem_v, length_) - = Eigen::Ref(inv).vi(); - } else { - mem_v = shared; - } - } - - inline void initialize(double*& mem_d, const double* ind, - double* shared = nullptr) { - if (shared == nullptr) { - mem_d = reinterpret_cast( - ChainableStack::instance_->memalloc_.alloc(length_ * sizeof(double))); - for (size_t i = 0; i < length_; i++) { - mem_d[i] = ind[i]; - } - } else { - mem_d = shared; - } - } - template - inline void initialize(double*& mem_d, const Eigen::DenseBase& ind, - double* shared = nullptr) { - if (shared == nullptr) { - mem_d = reinterpret_cast( - ChainableStack::instance_->memalloc_.alloc(length_ * sizeof(double))); - Eigen::Map(mem_d, length_) = Eigen::Ref(ind); - } else { - mem_d = shared; - } - } - - public: - dot_product_vari(typename dot_product_store_type::type v1, - typename dot_product_store_type::type v2, size_t length) - : vari(var_dot(v1, v2, length)), v1_(v1), v2_(v2), length_(length) {} - - dot_product_vari(const T1* v1, const T2* v2, size_t length, - dot_product_vari* shared_v1 = NULL, - dot_product_vari* shared_v2 = NULL) - : vari(var_dot(v1, v2, length)), length_(length) { - if (shared_v1 == NULL) { - initialize(v1_, v1); - } else { - initialize(v1_, v1, shared_v1->v1_); - } - if (shared_v2 == NULL) { - initialize(v2_, v2); - } else { - initialize(v2_, v2, shared_v2->v2_); - } - } - template - dot_product_vari(const Eigen::DenseBase& v1, - const Eigen::DenseBase& v2, - dot_product_vari* shared_v1 = NULL, - dot_product_vari* shared_v2 = NULL) - : vari(var_dot(v1, v2)), length_(v1.size()) { - if (shared_v1 == NULL) { - initialize(v1_, v1); - } else { - initialize(v1_, v1, shared_v1->v1_); - } - if (shared_v2 == NULL) { - initialize(v2_, v2); - } else { - initialize(v2_, v2, shared_v2->v2_); - } - } - template - dot_product_vari(const Eigen::Matrix& v1, - const Eigen::Matrix& v2, - dot_product_vari* shared_v1 = NULL, - dot_product_vari* shared_v2 = NULL) - : vari(var_dot(v1, v2)), length_(v1.size()) { - if (shared_v1 == NULL) { - initialize(v1_, v1); - } else { - initialize(v1_, v1, shared_v1->v1_); - } - if (shared_v2 == NULL) { - initialize(v2_, v2); - } else { - initialize(v2_, v2, shared_v2->v2_); - } - } - virtual void chain() { chain(v1_, v2_); } -}; -} // namespace internal - -/** - * Returns the dot product. - * - * @tparam T1 type of the first vector - * @tparam T2 type of the second vector - * - * @param[in] v1 First row or column vector. - * @param[in] v2 Second row or column vector. - * @return Dot product of the vectors. - * @throw std::domain_error if length of v1 is not equal to length of v2. - */ -template , - typename = require_any_eigen_vt, typename = void> -inline auto dot_product(const Vec1& v1, const Vec2& v2) { - check_matching_sizes("dot_product", "v1", v1, "v2", v2); - return var( - new internal::dot_product_vari, value_type_t>( - v1, v2)); -} - -/** - * Returns the dot product. - * - * @tparam T1 type of elements in the first vector - * @tparam T2 type of elements in the second vector - * - * @param[in] v1 First array. - * @param[in] v2 Second array. - * @param[in] length Length of both arrays. - * @return Dot product of the arrays. - */ -template > -inline return_type_t dot_product(const T1* v1, const T2* v2, - size_t length) { - return var(new internal::dot_product_vari(v1, v2, length)); -} /** * Returns the dot product. @@ -229,11 +29,40 @@ inline return_type_t dot_product(const T1* v1, const T2* v2, * @return Dot product of the vectors. * @throw std::domain_error if sizes of v1 and v2 do not match. */ -template > -inline return_type_t dot_product(const std::vector& v1, - const std::vector& v2) { +template * = nullptr, + require_any_vt_var* = nullptr> +inline return_type_t dot_product(const T1& v1, const T2& v2) { check_matching_sizes("dot_product", "v1", v1, "v2", v2); - return var(new internal::dot_product_vari(&v1[0], &v2[0], v1.size())); + + const auto& v1_col = as_column_vector_or_scalar(v1); + const auto& v2_col = as_column_vector_or_scalar(v2); + + const auto& v1_val + = to_AD_stack_if::value>(value_of(v1_col)); + const auto& v2_val + = to_AD_stack_if::value>(value_of(v2_col)); + + var res(new vari(dot_product(v1_val, v2_val))); + + AD_stack_matrix> v1_ad_stack; + if (!is_constant::value) { + v1_ad_stack = v1_col; + } + AD_stack_matrix> v2_ad_stack; + if (!is_constant::value) { + v2_ad_stack = v2_col; + } + + adjac_apply([=]() mutable { + if (!is_constant::value) { + v1_ad_stack.adj() += res.adj() * v2_val; + } + if (!is_constant::value) { + v2_ad_stack.adj() += res.adj() * v1_val; + } + }); + + return res; } } // namespace math diff --git a/stan/math/rev/fun/to_ad_stack.hpp b/stan/math/rev/fun/to_ad_stack.hpp index 938c6394df7..68257abca5e 100644 --- a/stan/math/rev/fun/to_ad_stack.hpp +++ b/stan/math/rev/fun/to_ad_stack.hpp @@ -15,12 +15,12 @@ namespace math { * * For types that already have this property (including scalars and * `var_value`s) this is a no-op. - * @tparam type of scalar + * @tparam T type of scalar * @param a argument * @return argument */ template >* = nullptr> -T to_AD_stack(const T& a) { +inline T to_AD_stack(const T& a) { // intentionally making a copy (not using forwarding or returning references) // as these types are cheap to copy and any object referenced by an input // reference might go out of scope before the returned value is used @@ -32,12 +32,12 @@ T to_AD_stack(const T& a) { * stack. * * For std vectors that have data already on AD stack this is a shallow copy. - * @tparam type of scalar + * @tparam T type of scalar * @param a argument * @return argument */ template -std::vector> to_AD_stack( +inline std::vector> to_AD_stack( const std::vector>& a) { // What we want to do here is the same as moving input into output, except // that we want input to be left unchanged. With any normal allocator that @@ -54,13 +54,13 @@ std::vector> to_AD_stack( * stack. * * Converts eigen types to `AD_stack_matrix`. - * @tparam type of argument + * @tparam T type of argument * @param a argument * @return argument copied/evaluated on AD stack */ template * = nullptr, require_not_same_t>* = nullptr> -AD_stack_t to_AD_stack(const T& a) { +inline AD_stack_t to_AD_stack(const T& a) { return {a}; } @@ -74,12 +74,12 @@ AD_stack_t to_AD_stack(const T& a) { * This overload works on vectors with simple scalars that don't need to be * converthed themselves. * - * @tparam type of argument + * @tparam T type of argument * @param a argument * @return argument copied on AD stack */ template >* = nullptr> -AD_stack_t> to_AD_stack(const std::vector& a) { +inline AD_stack_t> to_AD_stack(const std::vector& a) { return {a.begin(), a.end()}; } @@ -92,12 +92,12 @@ AD_stack_t> to_AD_stack(const std::vector& a) { * * This overload works on vectors with scalars that also need conversion. * - * @tparam type of argument + * @tparam T type of argument * @param a argument * @return argument copied on AD stack */ template >* = nullptr> -AD_stack_t> to_AD_stack(const std::vector& a) { +inline AD_stack_t> to_AD_stack(const std::vector& a) { AD_stack_t> res; res.reserve(a.size()); for (const T& i : a) { @@ -106,6 +106,24 @@ AD_stack_t> to_AD_stack(const std::vector& a) { return res; } +/** + * If the condition is true, converts given argument into a type that has any + * dynamic allocation on AD stack. Otherwise this is a no-op. + * + * @tparam T type of argument + * @param a argument + * @return argument copied/evaluated on AD stack + */ +template * = nullptr> +inline T to_AD_stack_if(T&& a) { + return std::forward(a); +} + +template * = nullptr> +inline AD_stack_t to_AD_stack_if(const T& a) { + return to_AD_stack(a); +} + } // namespace math } // namespace stan From c42690e67e55f400a5e57a92a4ed91d1843975f9 Mon Sep 17 00:00:00 2001 From: tadej Date: Fri, 7 Aug 2020 13:51:28 +0200 Subject: [PATCH 203/355] added missing file --- stan/math/rev/core/ad_stack_allocator.hpp | 48 +++++++++++++++++++++++ 1 file changed, 48 insertions(+) create mode 100644 stan/math/rev/core/ad_stack_allocator.hpp diff --git a/stan/math/rev/core/ad_stack_allocator.hpp b/stan/math/rev/core/ad_stack_allocator.hpp new file mode 100644 index 00000000000..4299d249751 --- /dev/null +++ b/stan/math/rev/core/ad_stack_allocator.hpp @@ -0,0 +1,48 @@ +#ifndef STAN_MATH_REV_CORE_AD_STACK_ALLOCATOR_HPP +#define STAN_MATH_REV_CORE_AD_STACK_ALLOCATOR_HPP + +#include + +namespace stan { +namespace math { + +/** + * std library compatible allocator that uses AD stack. + * @tparam T type of scalar + */ +template +struct AD_stack_allocator { + using value_type = T; + + /** + * Allocates space for `n` items of type `T`. + * + * @param n number of items to allocate space for + * @return pointer to allocated space + */ + T* allocate(std::size_t n) { + return ChainableStack::instance_->memalloc_.alloc_array(n); + } + + /** + * No-op. Memory is dealocated by caling `recover_memory()`. + */ + void deallocate(T* /*p*/, std::size_t /*n*/) noexcept {} + + /** + * Equality comparison operator. + * @return true + */ + bool operator==(const AD_stack_allocator&) { return true; } + + /** + * Inequality comparison operator. + * @return false + */ + bool operator!=(const AD_stack_allocator&) { return false; } +}; + +} // namespace math +} // namespace stan + +#endif From 281c52e7a60afef9f604d4d2e4cde971fc9015d4 Mon Sep 17 00:00:00 2001 From: tadej Date: Fri, 7 Aug 2020 14:35:41 +0200 Subject: [PATCH 204/355] moved new and delete into vari_base --- stan/math/opencl/rev/vari.hpp | 28 --------- stan/math/rev/core/vari.hpp | 115 +++++++++------------------------- 2 files changed, 29 insertions(+), 114 deletions(-) diff --git a/stan/math/opencl/rev/vari.hpp b/stan/math/opencl/rev/vari.hpp index b02edc27d19..091a29be231 100644 --- a/stan/math/opencl/rev/vari.hpp +++ b/stan/math/opencl/rev/vari.hpp @@ -143,34 +143,6 @@ class vari_value> */ inline void set_zero_adjoint() final { adj_ = constant(0, rows(), cols()); } - /** - * Allocate memory from the underlying memory pool. This memory is - * is managed as a whole externally. - * - * Warning: Classes should not be allocated with this operator - * if they have non-trivial destructors. - * - * @param nbytes Number of bytes to allocate. - * @return Pointer to allocated bytes. - */ - static inline void* operator new(size_t nbytes) { - return ChainableStack::instance_->memalloc_.alloc(nbytes); - } - - /** - * Delete a pointer from the underlying memory pool. - * - * This no-op implementation enables a subclass to throw - * exceptions in its constructor. An exception thrown in the - * constructor of a subclass will result in an error being - * raised, which is in turn caught and calls delete(). - * - * See the discussion of "plugging the memory leak" in: - * http://www.parashift.com/c++-faq/memory-pools.html - */ - static inline void operator delete(void* /* ignore arg */) { /* no op */ - } - protected: // to allow access to this constructor from instantinations with different // template parameters diff --git a/stan/math/rev/core/vari.hpp b/stan/math/rev/core/vari.hpp index aff64251a69..114afbf83ed 100644 --- a/stan/math/rev/core/vari.hpp +++ b/stan/math/rev/core/vari.hpp @@ -31,6 +31,35 @@ class vari_base { virtual void chain() = 0; virtual void set_zero_adjoint() = 0; virtual ~vari_base() noexcept {} + + /** + * Allocate memory from the underlying memory pool. This memory is + * is managed as a whole externally. + * + * Warning: Classes should not be allocated with this operator + * if they have non-trivial destructors. + * + * @param nbytes Number of bytes to allocate. + * @return Pointer to allocated bytes. + */ + static inline void* operator new(size_t nbytes) noexcept { + return ChainableStack::instance_->memalloc_.alloc(nbytes); + } + + /** + * Delete a pointer from the underlying memory pool. + * + * This no-op implementation enables a subclass to throw + * exceptions in its constructor. An exception thrown in the + * constructor of a subclass will result in an error being + * raised, which is in turn caught and calls delete(). + * + * See the discussion of "plugging the memory leak" in: + * http://www.parashift.com/c++-faq/memory-pools.html + */ + static inline void operator delete( + void* /* ignore arg */) noexcept { /* no op */ + } }; template @@ -134,35 +163,6 @@ class vari_value> : public vari_base { return os << v->val_ << ":" << v->adj_; } - /** - * Allocate memory from the underlying memory pool. This memory is - * is managed as a whole externally. - * - * Warning: Classes should not be allocated with this operator - * if they have non-trivial destructors. - * - * @param nbytes Number of bytes to allocate. - * @return Pointer to allocated bytes. - */ - static inline void* operator new(size_t nbytes) noexcept { - return ChainableStack::instance_->memalloc_.alloc(nbytes); - } - - /** - * Delete a pointer from the underlying memory pool. - * - * This no-op implementation enables a subclass to throw - * exceptions in its constructor. An exception thrown in the - * constructor of a subclass will result in an error being - * raised, which is in turn caught and calls delete(). - * - * See the discussion of "plugging the memory leak" in: - * http://www.parashift.com/c++-faq/memory-pools.html - */ - static inline void operator delete( - void* /* ignore arg */) noexcept { /* no op */ - } - private: template friend class var_value; @@ -320,34 +320,6 @@ class vari_value> : public vari_base { return os << "val: \n" << v->val_ << " \nadj: \n" << v->adj_; } - /** - * Allocate memory from the underlying memory pool. This memory is - * is managed as a whole externally. - * - * Warning: Classes should not be allocated with this operator - * if they have non-trivial destructors. - * - * @param nbytes Number of bytes to allocate. - * @return Pointer to allocated bytes. - */ - static inline void* operator new(size_t nbytes) { - return ChainableStack::instance_->memalloc_.alloc(nbytes); - } - - /** - * Delete a pointer from the underlying memory pool. - * - * This no-op implementation enables a subclass to throw - * exceptions in its constructor. An exception thrown in the - * constructor of a subclass will result in an error being - * raised, which is in turn caught and calls delete(). - * - * See the discussion of "plugging the memory leak" in: - * http://www.parashift.com/c++-faq/memory-pools.html - */ - static inline void operator delete(void* /* ignore arg */) { /* no op */ - } - private: template friend class var_value; @@ -494,35 +466,6 @@ class vari_value> : public vari_base, return os << "val: \n" << v->val_ << " \nadj: \n" << v->adj_; } - /** - * Allocate memory from the underlying memory pool. This memory is - * is managed as a whole externally. - * - * Warning: Classes should not be allocated with this operator - * if they have non-trivial destructors. - * - * @param nbytes Number of bytes to allocate. - * @return Pointer to allocated bytes. - */ - static inline void* operator new(size_t nbytes) noexcept { - return ChainableStack::instance_->memalloc_.alloc(nbytes); - } - - /** - * Delete a pointer from the underlying memory pool. - * - * This no-op implementation enables a subclass to throw - * exceptions in its constructor. An exception thrown in the - * constructor of a subclass will result in an error being - * raised, which is in turn caught and calls delete(). - * - * See the discussion of "plugging the memory leak" in: - * http://www.parashift.com/c++-faq/memory-pools.html - */ - static inline void operator delete( - void* /* ignore arg */) noexcept { /* no op */ - } - private: template friend class var_value; From 239df357e5fdcf205d4c6e8e94544a70ec3219b5 Mon Sep 17 00:00:00 2001 From: tadej Date: Fri, 7 Aug 2020 14:45:47 +0200 Subject: [PATCH 205/355] renamed, doced and added a test --- stan/math/rev/fun/dot_product.hpp | 4 +- stan/math/rev/fun/softmax.hpp | 4 +- stan/math/rev/functor.hpp | 1 + stan/math/rev/functor/adj_jac_apply.hpp | 20 --------- .../rev/functor/reverse_pass_callback.hpp | 43 +++++++++++++++++++ .../functor/reverse_pass_callback_test.cpp | 13 ++++++ 6 files changed, 61 insertions(+), 24 deletions(-) create mode 100644 stan/math/rev/functor/reverse_pass_callback.hpp create mode 100644 test/unit/math/rev/functor/reverse_pass_callback_test.cpp diff --git a/stan/math/rev/fun/dot_product.hpp b/stan/math/rev/fun/dot_product.hpp index a891a9780d5..63578e4cc24 100644 --- a/stan/math/rev/fun/dot_product.hpp +++ b/stan/math/rev/fun/dot_product.hpp @@ -6,7 +6,7 @@ #include #include #include -#include +#include #include #include #include @@ -53,7 +53,7 @@ inline return_type_t dot_product(const T1& v1, const T2& v2) { v2_ad_stack = v2_col; } - adjac_apply([=]() mutable { + reverse_pass_callback([=]() mutable { if (!is_constant::value) { v1_ad_stack.adj() += res.adj() * v2_val; } diff --git a/stan/math/rev/fun/softmax.hpp b/stan/math/rev/fun/softmax.hpp index e4d472df3f9..22bd3a198da 100644 --- a/stan/math/rev/fun/softmax.hpp +++ b/stan/math/rev/fun/softmax.hpp @@ -2,7 +2,7 @@ #define STAN_MATH_REV_FUN_SOFTMAX_HPP #include -#include +#include #include #include #include @@ -30,7 +30,7 @@ inline Eigen::Matrix softmax( AD_stack_matrix> res = res_val; AD_stack_matrix> alpha_ad_stack = alpha; - adjac_apply([=]() mutable { + reverse_pass_callback([=]() mutable { Eigen::VectorXd res_adj = res.adj(); alpha_ad_stack.adj() = -res_val * res_adj.dot(res_val) + res_val.cwiseProduct(res_adj); }); diff --git a/stan/math/rev/functor.hpp b/stan/math/rev/functor.hpp index 72347bd2c06..cb9c17b6ce5 100644 --- a/stan/math/rev/functor.hpp +++ b/stan/math/rev/functor.hpp @@ -26,5 +26,6 @@ #include #include #include +#include #endif diff --git a/stan/math/rev/functor/adj_jac_apply.hpp b/stan/math/rev/functor/adj_jac_apply.hpp index b30c660fb01..26409600952 100644 --- a/stan/math/rev/functor/adj_jac_apply.hpp +++ b/stan/math/rev/functor/adj_jac_apply.hpp @@ -105,26 +105,6 @@ struct compute_dims> { }; } // namespace internal - - -template -struct adjac_vari : public vari { - F rev_functor_; - - adjac_vari(F&& rev_functor) : vari(NOT_A_NUMBER), rev_functor_(rev_functor){} - - inline void chain() { - rev_functor_(); - } -}; - -template -inline void adjac_apply(F&& rev_functor){ - new adjac_vari(std::forward(rev_functor)); -} - - - /** * adj_jac_vari interfaces a user supplied functor with the reverse mode * autodiff. It allows someone to implement functions with custom reverse mode diff --git a/stan/math/rev/functor/reverse_pass_callback.hpp b/stan/math/rev/functor/reverse_pass_callback.hpp new file mode 100644 index 00000000000..b1c2e405233 --- /dev/null +++ b/stan/math/rev/functor/reverse_pass_callback.hpp @@ -0,0 +1,43 @@ +#ifndef STAN_MATH_REV_FUNCTOR_REVERSE_PASS_CALLBACK_HPP +#define STAN_MATH_REV_FUNCTOR_REVERSE_PASS_CALLBACK_HPP + +#include + +namespace stan { +namespace math { +namespace internal { + +template +struct callback_vari : public vari_base { + F rev_functor_; + + callback_vari(F&& rev_functor) : rev_functor_(rev_functor) { + ChainableStack::instance_->var_stack_.push_back(this); + } + + inline void chain() final { rev_functor_(); } + inline void set_zero_adjoint() final {} +}; + +} // namespace internal + +/** + * Puts a callback on the autodiff stack to be called in reverse pass. + * + * The intended use case is for the callable to ba a lambda function that + * captures any arguments it needs to work with. All captured values must be + * trivially destructible or they will leak memory! `to_AD_stack()` function can + * be used to ensure that. + * + * @tparam F type of callable + * @param functor funtor or other callable to call in the reverse pass + */ +template +inline void reverse_pass_callback(F&& functor) { + new internal::callback_vari(std::forward(functor)); +} + +} // namespace math +} // namespace stan + +#endif diff --git a/test/unit/math/rev/functor/reverse_pass_callback_test.cpp b/test/unit/math/rev/functor/reverse_pass_callback_test.cpp new file mode 100644 index 00000000000..cdb7f200fe1 --- /dev/null +++ b/test/unit/math/rev/functor/reverse_pass_callback_test.cpp @@ -0,0 +1,13 @@ +#include +#include + +TEST(AgradRev, reverse_pass_callback_test) { + stan::math::var a = 1; + stan::math::var b = 1; + + stan::math::reverse_pass_callback( + [=]() mutable { a.vi_->adj_ = b.adj() * 3; }); + EXPECT_EQ(a.adj(), 0); + b.grad(); + EXPECT_EQ(a.adj(), 3); +} From b3def37de8342804bdcb16cc0c67eab59c8c7901 Mon Sep 17 00:00:00 2001 From: tadej Date: Mon, 10 Aug 2020 09:31:37 +0200 Subject: [PATCH 206/355] rename to arena_* --- stan/math/rev/core.hpp | 2 +- ...tack_allocator.hpp => arena_allocator.hpp} | 10 +-- stan/math/rev/core/precomputed_gradients.hpp | 6 +- stan/math/rev/fun.hpp | 2 +- .../rev/fun/{to_ad_stack.hpp => to_arena.hpp} | 63 ++++++++++----- stan/math/rev/functor.hpp | 2 +- .../{ad_stack_matrix.hpp => arena_matrix.hpp} | 26 +++--- .../rev/functor/operands_and_partials.hpp | 6 +- stan/math/rev/meta.hpp | 2 +- .../{ad_stack_type.hpp => arena_type.hpp} | 18 ++--- .../math/rev/core/ad_stack_allocator_test.cpp | 25 ------ .../math/rev/core/arena_allocator_test.cpp | 25 ++++++ ...to_ad_stack_test.cpp => to_arena_test.cpp} | 30 +++---- .../math/rev/functor/ad_stack_matrix_test.cpp | 81 ------------------- .../math/rev/functor/arena_matrix_test.cpp | 81 +++++++++++++++++++ 15 files changed, 199 insertions(+), 180 deletions(-) rename stan/math/rev/core/{ad_stack_allocator.hpp => arena_allocator.hpp} (76%) rename stan/math/rev/fun/{to_ad_stack.hpp => to_arena.hpp} (59%) rename stan/math/rev/functor/{ad_stack_matrix.hpp => arena_matrix.hpp} (80%) rename stan/math/rev/meta/{ad_stack_type.hpp => arena_type.hpp} (62%) delete mode 100644 test/unit/math/rev/core/ad_stack_allocator_test.cpp create mode 100644 test/unit/math/rev/core/arena_allocator_test.cpp rename test/unit/math/rev/fun/{to_ad_stack_test.cpp => to_arena_test.cpp} (65%) delete mode 100644 test/unit/math/rev/functor/ad_stack_matrix_test.cpp create mode 100644 test/unit/math/rev/functor/arena_matrix_test.cpp diff --git a/stan/math/rev/core.hpp b/stan/math/rev/core.hpp index a93d2639eac..212c1e7df71 100644 --- a/stan/math/rev/core.hpp +++ b/stan/math/rev/core.hpp @@ -2,7 +2,7 @@ #define STAN_MATH_REV_CORE_HPP #include -#include +#include #include #include #include diff --git a/stan/math/rev/core/ad_stack_allocator.hpp b/stan/math/rev/core/arena_allocator.hpp similarity index 76% rename from stan/math/rev/core/ad_stack_allocator.hpp rename to stan/math/rev/core/arena_allocator.hpp index 4299d249751..7658fe7189e 100644 --- a/stan/math/rev/core/ad_stack_allocator.hpp +++ b/stan/math/rev/core/arena_allocator.hpp @@ -1,5 +1,5 @@ -#ifndef STAN_MATH_REV_CORE_AD_STACK_ALLOCATOR_HPP -#define STAN_MATH_REV_CORE_AD_STACK_ALLOCATOR_HPP +#ifndef STAN_MATH_REV_CORE_ARENA_ALLOCATOR_HPP +#define STAN_MATH_REV_CORE_ARENA_ALLOCATOR_HPP #include @@ -11,7 +11,7 @@ namespace math { * @tparam T type of scalar */ template -struct AD_stack_allocator { +struct arena_allocator { using value_type = T; /** @@ -33,13 +33,13 @@ struct AD_stack_allocator { * Equality comparison operator. * @return true */ - bool operator==(const AD_stack_allocator&) { return true; } + bool operator==(const arena_allocator&) { return true; } /** * Inequality comparison operator. * @return false */ - bool operator!=(const AD_stack_allocator&) { return false; } + bool operator!=(const arena_allocator&) { return false; } }; } // namespace math diff --git a/stan/math/rev/core/precomputed_gradients.hpp b/stan/math/rev/core/precomputed_gradients.hpp index 2be9ca5740a..b10b98de72e 100644 --- a/stan/math/rev/core/precomputed_gradients.hpp +++ b/stan/math/rev/core/precomputed_gradients.hpp @@ -4,7 +4,7 @@ #include #include #include -#include +#include #include #include #include @@ -217,8 +217,8 @@ inline var precomputed_gradients( const std::tuple& container_gradients = std::tuple<>()) { return {new precomputed_gradients_vari_template< - std::tuple...>, - std::tuple...>>( + std::tuple...>, + std::tuple...>>( value, operands, gradients, container_operands, container_gradients)}; } diff --git a/stan/math/rev/fun.hpp b/stan/math/rev/fun.hpp index d1c83df0079..671ab4a46a4 100644 --- a/stan/math/rev/fun.hpp +++ b/stan/math/rev/fun.hpp @@ -139,7 +139,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/stan/math/rev/fun/to_ad_stack.hpp b/stan/math/rev/fun/to_arena.hpp similarity index 59% rename from stan/math/rev/fun/to_ad_stack.hpp rename to stan/math/rev/fun/to_arena.hpp index 938c6394df7..0b010840752 100644 --- a/stan/math/rev/fun/to_ad_stack.hpp +++ b/stan/math/rev/fun/to_arena.hpp @@ -1,7 +1,8 @@ -#ifndef STAN_MATH_REF_FUN_TO_AD_STACK_HPP -#define STAN_MATH_REF_FUN_TO_AD_STACK_HPP +#ifndef STAN_MATH_REF_FUN_TO_ARENA_HPP +#define STAN_MATH_REF_FUN_TO_ARENA_HPP #include +#include #include #include #include @@ -15,12 +16,12 @@ namespace math { * * For types that already have this property (including scalars and * `var_value`s) this is a no-op. - * @tparam type of scalar + * @tparam T type of scalar * @param a argument * @return argument */ -template >* = nullptr> -T to_AD_stack(const T& a) { +template >* = nullptr> +inline T to_arena(const T& a) { // intentionally making a copy (not using forwarding or returning references) // as these types are cheap to copy and any object referenced by an input // reference might go out of scope before the returned value is used @@ -32,20 +33,20 @@ T to_AD_stack(const T& a) { * stack. * * For std vectors that have data already on AD stack this is a shallow copy. - * @tparam type of scalar + * @tparam T type of scalar * @param a argument * @return argument */ template -std::vector> to_AD_stack( - const std::vector>& a) { +inline std::vector> to_arena( + const std::vector>& a) { // What we want to do here is the same as moving input into output, except // that we want input to be left unchanged. With any normal allocator that // lead to deallocating memory twice (probably segfaulting). However, // dealocation with `AD_stack_allocator` is a no-op, so we can do that. - std::vector> res; + std::vector> res; std::memcpy(static_cast(&res), static_cast(&a), - sizeof(std::vector>)); + sizeof(std::vector>)); return res; } @@ -53,14 +54,14 @@ std::vector> to_AD_stack( * Converts given argument into a type that has any dynamic allocation on AD * stack. * - * Converts eigen types to `AD_stack_matrix`. - * @tparam type of argument + * Converts eigen types to `arena_matrix`. + * @tparam T type of argument * @param a argument * @return argument copied/evaluated on AD stack */ template * = nullptr, - require_not_same_t>* = nullptr> -AD_stack_t to_AD_stack(const T& a) { + require_not_same_t>* = nullptr> +inline arena_t to_arena(const T& a) { return {a}; } @@ -74,12 +75,12 @@ AD_stack_t to_AD_stack(const T& a) { * This overload works on vectors with simple scalars that don't need to be * converthed themselves. * - * @tparam type of argument + * @tparam T type of argument * @param a argument * @return argument copied on AD stack */ -template >* = nullptr> -AD_stack_t> to_AD_stack(const std::vector& a) { +template >* = nullptr> +inline arena_t> to_arena(const std::vector& a) { return {a.begin(), a.end()}; } @@ -92,20 +93,38 @@ AD_stack_t> to_AD_stack(const std::vector& a) { * * This overload works on vectors with scalars that also need conversion. * - * @tparam type of argument + * @tparam T type of argument * @param a argument * @return argument copied on AD stack */ -template >* = nullptr> -AD_stack_t> to_AD_stack(const std::vector& a) { - AD_stack_t> res; +template >* = nullptr> +inline arena_t> to_arena(const std::vector& a) { + arena_t> res; res.reserve(a.size()); for (const T& i : a) { - res.push_back(to_AD_stack(i)); + res.push_back(to_arena(i)); } return res; } +/** + * If the condition is true, converts given argument into a type that has any + * dynamic allocation on AD stack. Otherwise this is a no-op. + * + * @tparam T type of argument + * @param a argument + * @return argument copied/evaluated on AD stack + */ +template * = nullptr> +inline T to_arena_if(T&& a) { + return std::forward(a); +} + +template * = nullptr> +inline arena_t to_arena_if(const T& a) { + return to_arena(a); +} + } // namespace math } // namespace stan diff --git a/stan/math/rev/functor.hpp b/stan/math/rev/functor.hpp index 72347bd2c06..a0b5c156e0e 100644 --- a/stan/math/rev/functor.hpp +++ b/stan/math/rev/functor.hpp @@ -1,7 +1,7 @@ #ifndef STAN_MATH_REV_FUNCTOR_HPP #define STAN_MATH_REV_FUNCTOR_HPP -#include +#include #include #include #include diff --git a/stan/math/rev/functor/ad_stack_matrix.hpp b/stan/math/rev/functor/arena_matrix.hpp similarity index 80% rename from stan/math/rev/functor/ad_stack_matrix.hpp rename to stan/math/rev/functor/arena_matrix.hpp index 114108a4259..a09462c44ee 100644 --- a/stan/math/rev/functor/ad_stack_matrix.hpp +++ b/stan/math/rev/functor/arena_matrix.hpp @@ -1,5 +1,5 @@ -#ifndef STAN_MATH_REV_FUNCTOR_AD_STACK_MATRIX_HPP -#define STAN_MATH_REV_FUNCTOR_AD_STACK_MATRIX_HPP +#ifndef STAN_MATH_REV_FUNCTOR_ARENA_MATRIX_HPP +#define STAN_MATH_REV_FUNCTOR_ARENA_MATRIX_HPP #include #include @@ -15,7 +15,7 @@ namespace math { * ...) */ template -class AD_stack_matrix : public Eigen::Map { +class arena_matrix : public Eigen::Map { public: using Scalar = value_type_t; static constexpr int RowsAtCompileTime = MatrixType::RowsAtCompileTime; @@ -24,39 +24,39 @@ class AD_stack_matrix : public Eigen::Map { /** * Default constructor. */ - AD_stack_matrix() + arena_matrix() : Eigen::Map::Map( nullptr, RowsAtCompileTime == Eigen::Dynamic ? 0 : RowsAtCompileTime, ColsAtCompileTime == Eigen::Dynamic ? 0 : ColsAtCompileTime) {} /** - * Constructs `AD_stack_matrix` with given number of rows and columns. + * Constructs `arena_matrix` with given number of rows and columns. * @param rows number of rows * @param cols number of columns */ - AD_stack_matrix(Eigen::Index rows, Eigen::Index cols) + arena_matrix(Eigen::Index rows, Eigen::Index cols) : Eigen::Map::Map( ChainableStack::instance_->memalloc_.alloc_array(rows * cols), rows, cols) {} /** - * Constructs `AD_stack_matrix` with given size. This only works if + * Constructs `arena_matrix` with given size. This only works if * `MatrixType` is row or col vector. * @param size number of elements */ - explicit AD_stack_matrix(Eigen::Index size) + explicit arena_matrix(Eigen::Index size) : Eigen::Map::Map( ChainableStack::instance_->memalloc_.alloc_array(size), size) {} /** - * Constructs `AD_stack_matrix` from an expression. + * Constructs `arena_matrix` from an expression. * @param other expression */ template * = nullptr> - AD_stack_matrix(const T& other) // NOLINT + arena_matrix(const T& other) // NOLINT : Eigen::Map::Map( ChainableStack::instance_->memalloc_.alloc_array( other.size()), @@ -68,7 +68,7 @@ class AD_stack_matrix : public Eigen::Map { * Copy constructor. * @param other matrix to copy from */ - AD_stack_matrix(const AD_stack_matrix& other) + arena_matrix(const arena_matrix& other) : Eigen::Map::Map(const_cast(other.data()), other.rows(), other.cols()) {} @@ -81,7 +81,7 @@ class AD_stack_matrix : public Eigen::Map { * @param other matrix to copy from * @return `*this` */ - AD_stack_matrix& operator=(const AD_stack_matrix& other) { + arena_matrix& operator=(const arena_matrix& other) { // placement new changes what data map points to - there is no allocation new (this) Eigen::Map(const_cast(other.data()), other.rows(), other.cols()); @@ -94,7 +94,7 @@ class AD_stack_matrix : public Eigen::Map { * @return `*this` */ template - AD_stack_matrix& operator=(const T& a) { + arena_matrix& operator=(const T& a) { // placement new changes what data map points to - there is no allocation new (this) Eigen::Map( ChainableStack::instance_->memalloc_.alloc_array(a.size()), diff --git a/stan/math/rev/functor/operands_and_partials.hpp b/stan/math/rev/functor/operands_and_partials.hpp index fcc1fef9c76..58bc4a51c0e 100644 --- a/stan/math/rev/functor/operands_and_partials.hpp +++ b/stan/math/rev/functor/operands_and_partials.hpp @@ -165,7 +165,7 @@ class operands_and_partials { const std::tuple& container_operands, const std::tuple& container_partials) { return new precomputed_gradients_vari_template< - std::tuple...>, std::tuple...>>( + std::tuple...>, std::tuple...>>( value, edges_size, varis, partials, container_operands, container_partials); } @@ -239,7 +239,7 @@ class ops_partials_edge> { template class ops_partials_edge, require_eigen_t> { public: - using partials_t = AD_stack_t; + using partials_t = arena_t; partials_t partials_; // For univariate use-cases broadcast_array partials_vec_; // For multivariate explicit ops_partials_edge(const var_value& ops) @@ -358,7 +358,7 @@ template class ops_partials_edge>, require_eigen_t> { public: - using partials_t = AD_stack_t>; + using partials_t = arena_t>; partials_t partials_vec_; explicit ops_partials_edge(const std::vector>& ops) : partials_vec_(ops.size()), operands_(ops) { diff --git a/stan/math/rev/meta.hpp b/stan/math/rev/meta.hpp index c4197a50d60..4693f0e1905 100644 --- a/stan/math/rev/meta.hpp +++ b/stan/math/rev/meta.hpp @@ -2,7 +2,7 @@ #define STAN_MATH_REV_META_HPP #include -#include +#include #include #include #include diff --git a/stan/math/rev/meta/ad_stack_type.hpp b/stan/math/rev/meta/arena_type.hpp similarity index 62% rename from stan/math/rev/meta/ad_stack_type.hpp rename to stan/math/rev/meta/arena_type.hpp index bb83ad35041..3245ef06ae3 100644 --- a/stan/math/rev/meta/ad_stack_type.hpp +++ b/stan/math/rev/meta/arena_type.hpp @@ -3,30 +3,30 @@ #include #include -#include +#include namespace stan { namespace math { // forward declaration template -class AD_stack_matrix; +class arena_matrix; } // namespace math namespace internal { template -struct AD_stack_type_impl { +struct arena_type_impl { using type = T; }; template -struct AD_stack_type_impl> { - using T_ad = typename AD_stack_type_impl>::type; - using type = std::vector>; +struct arena_type_impl> { + using T_ad = typename arena_type_impl>::type; + using type = std::vector>; }; template -struct AD_stack_type_impl> { - using type = math::AD_stack_matrix>; +struct arena_type_impl> { + using type = math::arena_matrix>; }; } // namespace internal @@ -37,7 +37,7 @@ struct AD_stack_type_impl> { * `std::vector`s and Eigen types) */ template -using AD_stack_t = typename internal::AD_stack_type_impl>::type; +using arena_t = typename internal::arena_type_impl>::type; } // namespace stan diff --git a/test/unit/math/rev/core/ad_stack_allocator_test.cpp b/test/unit/math/rev/core/ad_stack_allocator_test.cpp deleted file mode 100644 index 7edd0fd21d2..00000000000 --- a/test/unit/math/rev/core/ad_stack_allocator_test.cpp +++ /dev/null @@ -1,25 +0,0 @@ -#include -#include -#include - -void ad_stack_allocator_test() { - std::vector> v; - v.reserve(3); - for (int i = 0; i < 5; i++) { - v.push_back(1); - } - - std::vector> v2(2, 3); - for (int i = 0; i < 5; i++) { - v2.push_back(2); - } - - std::vector> v3(v2); - for (int i = 0; i < 15; i++) { - v3.push_back(3); - } -} - -TEST(AgradRev, AD_stack_allocator_test) { - EXPECT_NO_THROW(ad_stack_allocator_test()); -} diff --git a/test/unit/math/rev/core/arena_allocator_test.cpp b/test/unit/math/rev/core/arena_allocator_test.cpp new file mode 100644 index 00000000000..4eb63dd4c37 --- /dev/null +++ b/test/unit/math/rev/core/arena_allocator_test.cpp @@ -0,0 +1,25 @@ +#include +#include +#include + +void arena_allocator_test() { + std::vector> v; + v.reserve(3); + for (int i = 0; i < 5; i++) { + v.push_back(1); + } + + std::vector> v2(2, 3); + for (int i = 0; i < 5; i++) { + v2.push_back(2); + } + + std::vector> v3(v2); + for (int i = 0; i < 15; i++) { + v3.push_back(3); + } +} + +TEST(AgradRev, arena_allocator_test) { + EXPECT_NO_THROW(arena_allocator_test()); +} diff --git a/test/unit/math/rev/fun/to_ad_stack_test.cpp b/test/unit/math/rev/fun/to_arena_test.cpp similarity index 65% rename from test/unit/math/rev/fun/to_ad_stack_test.cpp rename to test/unit/math/rev/fun/to_arena_test.cpp index c649d7d1568..b36b00fa3bb 100644 --- a/test/unit/math/rev/fun/to_ad_stack_test.cpp +++ b/test/unit/math/rev/fun/to_arena_test.cpp @@ -3,60 +3,60 @@ #include #include -TEST(AgradRev, to_AD_stack_scalar_test) { +TEST(AgradRev, to_arena_scalar_test) { int a = 2; - auto b = stan::math::to_AD_stack(a); + auto b = stan::math::to_arena(a); EXPECT_EQ(b, a); EXPECT_TRUE((std::is_same::value)); double a2 = 2; - auto b2 = stan::math::to_AD_stack(a2); + auto b2 = stan::math::to_arena(a2); EXPECT_EQ(b2, a2); EXPECT_TRUE((std::is_same::value)); } -TEST(AgradRev, to_AD_stack_std_vector_test) { +TEST(AgradRev, to_arena_std_vector_test) { std::vector a{1, 2}; - auto b = stan::math::to_AD_stack(a); + auto b = stan::math::to_arena(a); ASSERT_EQ(a.size(), b.size()); for (int i = 0; i < a.size(); i++) { EXPECT_EQ(a[i], b[i]); } EXPECT_FALSE((std::is_same::value)); - auto c = stan::math::to_AD_stack(b); + auto c = stan::math::to_arena(b); EXPECT_EQ(b.size(), c.size()); EXPECT_EQ(b.data(), c.data()); } -TEST(AgradRev, to_AD_stack_col_vector_test) { +TEST(AgradRev, to_arena_col_vector_test) { Eigen::VectorXd a(2); a << 1, 2; - auto b = stan::math::to_AD_stack(a); + auto b = stan::math::to_arena(a); EXPECT_MATRIX_EQ(a, b); EXPECT_FALSE((std::is_same::value)); - auto c = stan::math::to_AD_stack(b); + auto c = stan::math::to_arena(b); EXPECT_EQ(b.size(), c.size()); EXPECT_EQ(b.data(), c.data()); } -TEST(AgradRev, to_AD_stack_row_vector_test) { +TEST(AgradRev, to_arena_row_vector_test) { Eigen::RowVectorXd a(2); a << 1, 2; - auto b = stan::math::to_AD_stack(a); + auto b = stan::math::to_arena(a); EXPECT_MATRIX_EQ(a, b); EXPECT_FALSE((std::is_same::value)); - auto c = stan::math::to_AD_stack(b); + auto c = stan::math::to_arena(b); EXPECT_EQ(b.size(), c.size()); EXPECT_EQ(b.data(), c.data()); } -TEST(AgradRev, to_AD_stack_matrix_test) { +TEST(AgradRev, to_arena_matrix_test) { Eigen::MatrixXd a(2, 2); a << 1, 2, 3, 4; - auto b = stan::math::to_AD_stack(a); + auto b = stan::math::to_arena(a); EXPECT_MATRIX_EQ(a, b); EXPECT_FALSE((std::is_same::value)); - auto c = stan::math::to_AD_stack(b); + auto c = stan::math::to_arena(b); EXPECT_EQ(b.size(), c.size()); EXPECT_EQ(b.data(), c.data()); } diff --git a/test/unit/math/rev/functor/ad_stack_matrix_test.cpp b/test/unit/math/rev/functor/ad_stack_matrix_test.cpp deleted file mode 100644 index 6c646657bc4..00000000000 --- a/test/unit/math/rev/functor/ad_stack_matrix_test.cpp +++ /dev/null @@ -1,81 +0,0 @@ -#include -#include -#include - -TEST(AgradRev, AD_stack_matrix_matrix_test) { - using Eigen::MatrixXd; - using stan::math::AD_stack_matrix; - - // construction - AD_stack_matrix a; - AD_stack_matrix a2; - AD_stack_matrix a3; - AD_stack_matrix b(3, 2); - AD_stack_matrix b2(4, 5); - AD_stack_matrix c(MatrixXd::Ones(3, 2)); - AD_stack_matrix d(c); - AD_stack_matrix e(2 * d); - - // assignment - a = c; - a2 = std::move(d); - a3 = 2 * a; - b = d; - b2 = std::move(c); - e = e + a; - a = MatrixXd::Ones(3, 2); - - EXPECT_MATRIX_EQ(a + a2 + a3 + b + b2 + e, MatrixXd::Ones(3, 2) * 9); -} - -TEST(AgradRev, AD_stack_matrix_vector_test) { - using Eigen::VectorXd; - using stan::math::AD_stack_matrix; - - // construction - AD_stack_matrix a; - AD_stack_matrix a2; - AD_stack_matrix a3; - AD_stack_matrix b(3); - AD_stack_matrix b2(4); - AD_stack_matrix c(VectorXd::Ones(3)); - AD_stack_matrix d(c); - AD_stack_matrix e(2 * d); - - // assignment - a = c; - a2 = std::move(d); - a3 = 2 * a; - b = d; - b2 = std::move(c); - e = e + a; - a = VectorXd::Ones(3); - - EXPECT_MATRIX_EQ(a + a2 + a3 + b + b2 + e, VectorXd::Ones(3) * 9); -} - -TEST(AgradRev, AD_stack_matrix_row_vector_test) { - using Eigen::RowVectorXd; - using stan::math::AD_stack_matrix; - - // construction - AD_stack_matrix a; - AD_stack_matrix a2; - AD_stack_matrix a3; - AD_stack_matrix b(3); - AD_stack_matrix b2(4); - AD_stack_matrix c(RowVectorXd::Ones(3)); - AD_stack_matrix d(c); - AD_stack_matrix e(2 * d); - - // assignment - a = c; - a2 = std::move(d); - a3 = 2 * a; - b = d; - b2 = std::move(c); - e = e + a; - a = RowVectorXd::Ones(3); - - EXPECT_MATRIX_EQ(a + a2 + a3 + b + b2 + e, RowVectorXd::Ones(3) * 9); -} diff --git a/test/unit/math/rev/functor/arena_matrix_test.cpp b/test/unit/math/rev/functor/arena_matrix_test.cpp new file mode 100644 index 00000000000..ddea6ed53ed --- /dev/null +++ b/test/unit/math/rev/functor/arena_matrix_test.cpp @@ -0,0 +1,81 @@ +#include +#include +#include + +TEST(AgradRev, arena_matrix_matrix_test) { + using Eigen::MatrixXd; + using stan::math::arena_matrix; + + // construction + arena_matrix a; + arena_matrix a2; + arena_matrix a3; + arena_matrix b(3, 2); + arena_matrix b2(4, 5); + arena_matrix c(MatrixXd::Ones(3, 2)); + arena_matrix d(c); + arena_matrix e(2 * d); + + // assignment + a = c; + a2 = std::move(d); + a3 = 2 * a; + b = d; + b2 = std::move(c); + e = e + a; + a = MatrixXd::Ones(3, 2); + + EXPECT_MATRIX_EQ(a + a2 + a3 + b + b2 + e, MatrixXd::Ones(3, 2) * 9); +} + +TEST(AgradRev, arena_matrix_vector_test) { + using Eigen::VectorXd; + using stan::math::arena_matrix; + + // construction + arena_matrix a; + arena_matrix a2; + arena_matrix a3; + arena_matrix b(3); + arena_matrix b2(4); + arena_matrix c(VectorXd::Ones(3)); + arena_matrix d(c); + arena_matrix e(2 * d); + + // assignment + a = c; + a2 = std::move(d); + a3 = 2 * a; + b = d; + b2 = std::move(c); + e = e + a; + a = VectorXd::Ones(3); + + EXPECT_MATRIX_EQ(a + a2 + a3 + b + b2 + e, VectorXd::Ones(3) * 9); +} + +TEST(AgradRev, arena_matrix_row_vector_test) { + using Eigen::RowVectorXd; + using stan::math::arena_matrix; + + // construction + arena_matrix a; + arena_matrix a2; + arena_matrix a3; + arena_matrix b(3); + arena_matrix b2(4); + arena_matrix c(RowVectorXd::Ones(3)); + arena_matrix d(c); + arena_matrix e(2 * d); + + // assignment + a = c; + a2 = std::move(d); + a3 = 2 * a; + b = d; + b2 = std::move(c); + e = e + a; + a = RowVectorXd::Ones(3); + + EXPECT_MATRIX_EQ(a + a2 + a3 + b + b2 + e, RowVectorXd::Ones(3) * 9); +} From b14a477a87c1f09c64cd9c39e38c7895f9675143 Mon Sep 17 00:00:00 2001 From: tadej Date: Mon, 10 Aug 2020 09:57:56 +0200 Subject: [PATCH 207/355] third batch of comments --- stan/math/rev/core/precomputed_gradients.hpp | 8 ++++---- stan/math/rev/meta/arena_type.hpp | 8 ++++++-- test/unit/math/rev/core/arena_allocator_test.cpp | 6 ++++++ test/unit/math/rev/core/precomputed_gradients_test.cpp | 8 ++++---- 4 files changed, 20 insertions(+), 10 deletions(-) diff --git a/stan/math/rev/core/precomputed_gradients.hpp b/stan/math/rev/core/precomputed_gradients.hpp index b10b98de72e..0b2b7a3cbe1 100644 --- a/stan/math/rev/core/precomputed_gradients.hpp +++ b/stan/math/rev/core/precomputed_gradients.hpp @@ -81,11 +81,11 @@ class precomputed_gradients_vari_template : public vari { gradients_(gradients), container_operands_(index_apply([&, this](auto... Is) { return std::make_tuple( - to_AD_stack(std::get(container_operands))...); + to_arena(std::get(container_operands))...); })), container_gradients_(index_apply([&, this](auto... Is) { return std::make_tuple( - to_AD_stack(std::get(container_gradients))...); + to_arena(std::get(container_gradients))...); })) { check_sizes(std::make_index_sequence()); } @@ -125,11 +125,11 @@ class precomputed_gradients_vari_template : public vari { vars.size())), container_operands_(index_apply([&, this](auto... Is) { return std::make_tuple( - to_AD_stack(std::get(container_operands))...); + to_arena(std::get(container_operands))...); })), container_gradients_(index_apply([&, this](auto... Is) { return std::make_tuple( - to_AD_stack(std::get(container_gradients))...); + to_arena(std::get(container_gradients))...); })) { check_consistent_sizes("precomputed_gradients_vari", "vars", vars, "gradients", gradients); diff --git a/stan/math/rev/meta/arena_type.hpp b/stan/math/rev/meta/arena_type.hpp index 3245ef06ae3..10cd31e6eaa 100644 --- a/stan/math/rev/meta/arena_type.hpp +++ b/stan/math/rev/meta/arena_type.hpp @@ -15,11 +15,15 @@ class arena_matrix; namespace internal { template struct arena_type_impl { - using type = T; }; template -struct arena_type_impl> { +struct arena_type_impl, bool_constant::value>>> { + using type = T; +}; + +template +struct arena_type_impl> { using T_ad = typename arena_type_impl>::type; using type = std::vector>; }; diff --git a/test/unit/math/rev/core/arena_allocator_test.cpp b/test/unit/math/rev/core/arena_allocator_test.cpp index 4eb63dd4c37..bd9922900d6 100644 --- a/test/unit/math/rev/core/arena_allocator_test.cpp +++ b/test/unit/math/rev/core/arena_allocator_test.cpp @@ -8,16 +8,22 @@ void arena_allocator_test() { for (int i = 0; i < 5; i++) { v.push_back(1); } + EXPECT_TRUE(stan::math::ChainableStack::instance_->memalloc_.in_stack(v.data())); + EXPECT_TRUE(stan::math::ChainableStack::instance_->memalloc_.in_stack(v.data() + v.size())); std::vector> v2(2, 3); for (int i = 0; i < 5; i++) { v2.push_back(2); } + EXPECT_TRUE(stan::math::ChainableStack::instance_->memalloc_.in_stack(v2.data())); + EXPECT_TRUE(stan::math::ChainableStack::instance_->memalloc_.in_stack(v2.data() + v2.size())); std::vector> v3(v2); for (int i = 0; i < 15; i++) { v3.push_back(3); } + EXPECT_TRUE(stan::math::ChainableStack::instance_->memalloc_.in_stack(v3.data())); + EXPECT_TRUE(stan::math::ChainableStack::instance_->memalloc_.in_stack(v3.data() + v3.size())); } TEST(AgradRev, arena_allocator_test) { diff --git a/test/unit/math/rev/core/precomputed_gradients_test.cpp b/test/unit/math/rev/core/precomputed_gradients_test.cpp index 894700e5f82..87a6f8516ec 100644 --- a/test/unit/math/rev/core/precomputed_gradients_test.cpp +++ b/test/unit/math/rev/core/precomputed_gradients_test.cpp @@ -146,11 +146,11 @@ TEST(StanAgradRevInternal, std::move(grad_a), grad_b); stan::math::var lp = new stan::math::precomputed_gradients_vari_template< - std::tuple>, - stan::AD_stack_t< + std::tuple>, + stan::arena_t< std::vector>>>, - std::tuple, - stan::AD_stack_t>>>( + std::tuple, + stan::arena_t>>>( value, 0, nullptr, nullptr, ops, grads); (2 * lp).grad(); EXPECT_MATRIX_EQ(a.adj(), Eigen::MatrixXd::Constant(3, 3, -2)); From cf2c2ca89cd894e7585493d910a4655b228dd91d Mon Sep 17 00:00:00 2001 From: Stan Jenkins Date: Mon, 10 Aug 2020 07:58:41 +0000 Subject: [PATCH 208/355] [Jenkins] auto-formatting by clang-format version 6.0.0-1ubuntu2~16.04.1 (tags/RELEASE_600/final) --- stan/math/rev/core/precomputed_gradients.hpp | 6 ++---- stan/math/rev/meta/arena_type.hpp | 6 +++--- .../math/rev/core/arena_allocator_test.cpp | 18 ++++++++++++------ .../rev/core/precomputed_gradients_test.cpp | 6 +++--- 4 files changed, 20 insertions(+), 16 deletions(-) diff --git a/stan/math/rev/core/precomputed_gradients.hpp b/stan/math/rev/core/precomputed_gradients.hpp index 0b2b7a3cbe1..0e7178021d3 100644 --- a/stan/math/rev/core/precomputed_gradients.hpp +++ b/stan/math/rev/core/precomputed_gradients.hpp @@ -80,8 +80,7 @@ class precomputed_gradients_vari_template : public vari { varis_(varis), gradients_(gradients), container_operands_(index_apply([&, this](auto... Is) { - return std::make_tuple( - to_arena(std::get(container_operands))...); + return std::make_tuple(to_arena(std::get(container_operands))...); })), container_gradients_(index_apply([&, this](auto... Is) { return std::make_tuple( @@ -124,8 +123,7 @@ class precomputed_gradients_vari_template : public vari { gradients_(ChainableStack::instance_->memalloc_.alloc_array( vars.size())), container_operands_(index_apply([&, this](auto... Is) { - return std::make_tuple( - to_arena(std::get(container_operands))...); + return std::make_tuple(to_arena(std::get(container_operands))...); })), container_gradients_(index_apply([&, this](auto... Is) { return std::make_tuple( diff --git a/stan/math/rev/meta/arena_type.hpp b/stan/math/rev/meta/arena_type.hpp index 10cd31e6eaa..73eeb69b7a4 100644 --- a/stan/math/rev/meta/arena_type.hpp +++ b/stan/math/rev/meta/arena_type.hpp @@ -14,11 +14,11 @@ class arena_matrix; namespace internal { template -struct arena_type_impl { -}; +struct arena_type_impl {}; template -struct arena_type_impl, bool_constant::value>>> { +struct arena_type_impl, + bool_constant::value>>> { using type = T; }; diff --git a/test/unit/math/rev/core/arena_allocator_test.cpp b/test/unit/math/rev/core/arena_allocator_test.cpp index bd9922900d6..66c6ece938a 100644 --- a/test/unit/math/rev/core/arena_allocator_test.cpp +++ b/test/unit/math/rev/core/arena_allocator_test.cpp @@ -8,22 +8,28 @@ void arena_allocator_test() { for (int i = 0; i < 5; i++) { v.push_back(1); } - EXPECT_TRUE(stan::math::ChainableStack::instance_->memalloc_.in_stack(v.data())); - EXPECT_TRUE(stan::math::ChainableStack::instance_->memalloc_.in_stack(v.data() + v.size())); + EXPECT_TRUE( + stan::math::ChainableStack::instance_->memalloc_.in_stack(v.data())); + EXPECT_TRUE(stan::math::ChainableStack::instance_->memalloc_.in_stack( + v.data() + v.size())); std::vector> v2(2, 3); for (int i = 0; i < 5; i++) { v2.push_back(2); } - EXPECT_TRUE(stan::math::ChainableStack::instance_->memalloc_.in_stack(v2.data())); - EXPECT_TRUE(stan::math::ChainableStack::instance_->memalloc_.in_stack(v2.data() + v2.size())); + EXPECT_TRUE( + stan::math::ChainableStack::instance_->memalloc_.in_stack(v2.data())); + EXPECT_TRUE(stan::math::ChainableStack::instance_->memalloc_.in_stack( + v2.data() + v2.size())); std::vector> v3(v2); for (int i = 0; i < 15; i++) { v3.push_back(3); } - EXPECT_TRUE(stan::math::ChainableStack::instance_->memalloc_.in_stack(v3.data())); - EXPECT_TRUE(stan::math::ChainableStack::instance_->memalloc_.in_stack(v3.data() + v3.size())); + EXPECT_TRUE( + stan::math::ChainableStack::instance_->memalloc_.in_stack(v3.data())); + EXPECT_TRUE(stan::math::ChainableStack::instance_->memalloc_.in_stack( + v3.data() + v3.size())); } TEST(AgradRev, arena_allocator_test) { diff --git a/test/unit/math/rev/core/precomputed_gradients_test.cpp b/test/unit/math/rev/core/precomputed_gradients_test.cpp index 87a6f8516ec..4bc34d853d1 100644 --- a/test/unit/math/rev/core/precomputed_gradients_test.cpp +++ b/test/unit/math/rev/core/precomputed_gradients_test.cpp @@ -146,9 +146,9 @@ TEST(StanAgradRevInternal, std::move(grad_a), grad_b); stan::math::var lp = new stan::math::precomputed_gradients_vari_template< - std::tuple>, - stan::arena_t< - std::vector>>>, + std::tuple< + stan::arena_t>, + stan::arena_t>>>, std::tuple, stan::arena_t>>>( value, 0, nullptr, nullptr, ops, grads); From 2545756ddd685c00c9b3cc2c8216a1aee9cc0dc9 Mon Sep 17 00:00:00 2001 From: tadej Date: Mon, 10 Aug 2020 11:13:54 +0200 Subject: [PATCH 209/355] small fixes --- stan/math/rev/functor/reverse_pass_callback.hpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/stan/math/rev/functor/reverse_pass_callback.hpp b/stan/math/rev/functor/reverse_pass_callback.hpp index b1c2e405233..24b3aa827a2 100644 --- a/stan/math/rev/functor/reverse_pass_callback.hpp +++ b/stan/math/rev/functor/reverse_pass_callback.hpp @@ -11,12 +11,13 @@ template struct callback_vari : public vari_base { F rev_functor_; - callback_vari(F&& rev_functor) : rev_functor_(rev_functor) { + callback_vari(F&& rev_functor) : rev_functor_(std::forward(rev_functor)) { ChainableStack::instance_->var_stack_.push_back(this); } inline void chain() final { rev_functor_(); } inline void set_zero_adjoint() final {} + inline void init_dependent() final {} }; } // namespace internal From 0f3517cc4b755012bf808215812849716c307021 Mon Sep 17 00:00:00 2001 From: Ben Date: Tue, 11 Aug 2020 16:16:33 -0700 Subject: [PATCH 210/355] Converted remaining functions using adj_jac_apply to reverse_pass_callback --- stan/math/rev/fun/ordered_constrain.hpp | 37 +++++- .../rev/fun/positive_ordered_constrain.hpp | 99 ++++++---------- stan/math/rev/fun/simplex_constrain.hpp | 108 ++++++------------ .../rev/functor/reverse_pass_callback.hpp | 2 +- 4 files changed, 105 insertions(+), 141 deletions(-) diff --git a/stan/math/rev/fun/ordered_constrain.hpp b/stan/math/rev/fun/ordered_constrain.hpp index e93df166d7c..818db3273ca 100644 --- a/stan/math/rev/fun/ordered_constrain.hpp +++ b/stan/math/rev/fun/ordered_constrain.hpp @@ -2,7 +2,8 @@ #define STAN_MATH_REV_FUN_ORDERED_CONSTRAIN_HPP #include -#include +#include +#include #include #include #include @@ -88,7 +89,39 @@ class ordered_constrain_op { */ inline Eigen::Matrix ordered_constrain( const Eigen::Matrix& x) { - return adj_jac_apply(x); + using std::exp; + + size_t N = x.size(); + if (N == 0) { + return x; + } + + Eigen::VectorXd y_val(N); + arena_matrix exp_x(N - 1); + + y_val.coeffRef(0) = value_of(x.coeffRef(0)); + for (int n = 1; n < N; ++n) { + exp_x.coeffRef(n - 1) = exp(value_of(x.coeffRef(n))); + y_val.coeffRef(n) = y_val.coeffRef(n - 1) + exp_x.coeffRef(n - 1); + } + + arena_matrix> y = y_val; + arena_matrix> arena_x = x; + + reverse_pass_callback([=]() mutable { + const auto& adj = y.adj(); + double rolling_adjoint_sum = 0.0; + + if (N > 0) { + for (int n = N - 1; n > 0; --n) { + rolling_adjoint_sum += adj(n); + arena_x.adj().coeffRef(n) += exp_x.coeffRef(n - 1) * rolling_adjoint_sum; + } + arena_x.adj().coeffRef(0) += rolling_adjoint_sum + adj(0); + } + }); + + return y; } } // namespace math diff --git a/stan/math/rev/fun/positive_ordered_constrain.hpp b/stan/math/rev/fun/positive_ordered_constrain.hpp index 64ce12d64d5..938e7decebc 100644 --- a/stan/math/rev/fun/positive_ordered_constrain.hpp +++ b/stan/math/rev/fun/positive_ordered_constrain.hpp @@ -2,7 +2,8 @@ #define STAN_MATH_REV_FUN_POSITIVE_ORDERED_CONSTRAIN_HPP #include -#include +#include +#include #include #include #include @@ -11,70 +12,6 @@ namespace stan { namespace math { -namespace internal { -class positive_ordered_constrain_op { - int N_; - double* exp_x_; - - public: - /** - * Return an increasing positive ordered vector derived from the specified - * free vector. The returned constrained vector will have the - * same dimensionality as the specified free vector. - * - * @tparam size Number of arguments - * @param needs_adj Boolean indicators of if adjoints of arguments will be - * needed - * @param x Free vector of scalars - * @return Positive, increasing ordered vector - */ - template - Eigen::VectorXd operator()(const std::array& needs_adj, - const Eigen::VectorXd& x) { - N_ = x.size(); - using std::exp; - Eigen::Matrix y(N_); - if (N_ == 0) { - return y; - } - - exp_x_ = ChainableStack::instance_->memalloc_.alloc_array(N_); - - exp_x_[0] = exp(x[0]); - y[0] = exp_x_[0]; - for (int n = 1; n < N_; ++n) { - exp_x_[n] = exp(x[n]); - y[n] = y[n - 1] + exp_x_[n]; - } - return y; - } - - /** - * Compute the result of multiply the transpose of the adjoint vector times - * the Jacobian of the positive_ordered_constrain operator. - * - * @tparam size Number of adjoints to return - * @param needs_adj Boolean indicators of if adjoints of arguments will be - * needed - * @param adj Eigen::VectorXd of adjoints at the output of the softmax - * @return Eigen::VectorXd of adjoints propagated through softmax operation - */ - template - auto multiply_adjoint_jacobian(const std::array& needs_adj, - const Eigen::VectorXd& adj) const { - Eigen::VectorXd adj_times_jac(N_); - double rolling_adjoint_sum = 0.0; - - for (int n = N_; --n >= 0;) { - rolling_adjoint_sum += adj(n); - adj_times_jac(n) = exp_x_[n] * rolling_adjoint_sum; - } - - return std::make_tuple(adj_times_jac); - } -}; -} // namespace internal - /** * Return an increasing positive ordered vector derived from the specified * free vector. The returned constrained vector will have the @@ -85,7 +22,37 @@ class positive_ordered_constrain_op { */ inline Eigen::Matrix positive_ordered_constrain( const Eigen::Matrix& x) { - return adj_jac_apply(x); + using std::exp; + + size_t N = x.size(); + if (N == 0) { + return x; + } + + Eigen::VectorXd y_val(N); + arena_matrix exp_x(N); + + exp_x(0) = exp(value_of(x.coeffRef(0))); + y_val(0) = exp_x.coeffRef(0); + for (int n = 1; n < N; ++n) { + exp_x(n) = exp(value_of(x.coeffRef(n))); + y_val(n) = y_val.coeffRef(n - 1) + exp_x.coeffRef(n); + } + + arena_matrix> y = y_val; + arena_matrix> arena_x = x; + + reverse_pass_callback([=]() mutable { + const auto& adj = y.adj(); + double rolling_adjoint_sum = 0.0; + + for (int n = N; --n >= 0;) { + rolling_adjoint_sum += adj(n); + arena_x.adj().coeffRef(n) += exp_x.coeffRef(n) * rolling_adjoint_sum; + } + }); + + return y; } } // namespace math diff --git a/stan/math/rev/fun/simplex_constrain.hpp b/stan/math/rev/fun/simplex_constrain.hpp index 682a66293f0..4b3c3562985 100644 --- a/stan/math/rev/fun/simplex_constrain.hpp +++ b/stan/math/rev/fun/simplex_constrain.hpp @@ -2,7 +2,8 @@ #define STAN_MATH_REV_FUN_SIMPLEX_CONSTRAIN_HPP #include -#include +#include +#include #include #include #include @@ -12,76 +13,6 @@ namespace stan { namespace math { -namespace internal { -class simplex_constrain_op { - int N_; - double* diag_; // diagonal of the Jacobian of the operator - double* z_; - - public: - /** - * Return the simplex corresponding to the specified free vector. - * A simplex is a vector containing values greater than or equal - * to 0 that sum to 1. A vector with (K-1) unconstrained values - * will produce a simplex of size K. - * - * The transform is based on a centered stick-breaking process. - * - * @tparam size Number of adjoints to return - * @param needs_adj Boolean indicators of if adjoints of arguments will be - * needed - * @param y Free vector input of dimensionality K - 1 - * @return Simplex of dimensionality K - */ - template - Eigen::VectorXd operator()(const std::array& needs_adj, - const Eigen::VectorXd& y) { - N_ = y.size(); - diag_ = ChainableStack::instance_->memalloc_.alloc_array(N_); - z_ = ChainableStack::instance_->memalloc_.alloc_array(N_); - - Eigen::Matrix x(N_ + 1); - double stick_len(1.0); - for (int k = 0; k < N_; ++k) { - double log_N_minus_k = std::log(N_ - k); - z_[k] = inv_logit(y(k) - log_N_minus_k); - diag_[k] = stick_len * z_[k] * inv_logit(log_N_minus_k - y(k)); - x(k) = stick_len * z_[k]; - stick_len -= x(k); - } - x(N_) = stick_len; - return x; - } - - /** - * Compute the result of multiply the transpose of the adjoint vector times - * the Jacobian of the simplex_constrain operator. - * - * @tparam size Number of adjoints to return - * @param needs_adj Boolean indicators of if adjoints of arguments will be - * needed - * @param adj Eigen::VectorXd of adjoints at the output of the softmax - * @return Eigen::VectorXd of adjoints propagated through softmax operation - */ - template - auto multiply_adjoint_jacobian(const std::array& needs_adj, - const Eigen::VectorXd& adj) const { - Eigen::VectorXd adj_times_jac(N_); - double acc = adj(N_); - - if (N_ > 0) { - adj_times_jac(N_ - 1) = diag_[N_ - 1] * (adj(N_ - 1) - acc); - for (int n = N_ - 1; --n >= 0;) { - acc = adj(n + 1) * z_[n + 1] + (1 - z_[n + 1]) * acc; - adj_times_jac(n) = diag_[n] * (adj(n) - acc); - } - } - - return std::make_tuple(adj_times_jac); - } -}; -} // namespace internal - /** * Return the simplex corresponding to the specified free vector. * A simplex is a vector containing values greater than or equal @@ -95,7 +26,40 @@ class simplex_constrain_op { */ inline Eigen::Matrix simplex_constrain( const Eigen::Matrix& y) { - return adj_jac_apply(y); + size_t N = y.size(); + + arena_matrix diag(N); + arena_matrix z(N); + + Eigen::VectorXd x_val(N + 1); + + double stick_len(1.0); + for (int k = 0; k < N; ++k) { + double log_N_minus_k = std::log(N - k); + z.coeffRef(k) = inv_logit(value_of(y.coeffRef(k)) - log_N_minus_k); + diag.coeffRef(k) = stick_len * z.coeffRef(k) * inv_logit(log_N_minus_k - value_of(y.coeffRef(k))); + x_val.coeffRef(k) = stick_len * z.coeffRef(k); + stick_len -= x_val(k); + } + x_val.coeffRef(N) = stick_len; + + arena_matrix> x = x_val; + arena_matrix> arena_y = y; + + reverse_pass_callback([=]() mutable { + const auto& adj = x.adj(); + double acc = adj(N); + + if (N > 0) { + arena_y.adj().coeffRef(N - 1) += diag.coeffRef(N - 1) * (adj(N - 1) - acc); + for (int n = N - 1; --n >= 0;) { + acc = adj(n + 1) * z.coeffRef(n + 1) + (1 - z.coeffRef(n + 1)) * acc; + arena_y.adj().coeffRef(n) += diag.coeffRef(n) * (adj(n) - acc); + } + } + }); + + return x; } } // namespace math diff --git a/stan/math/rev/functor/reverse_pass_callback.hpp b/stan/math/rev/functor/reverse_pass_callback.hpp index 24b3aa827a2..12c76ef4c96 100644 --- a/stan/math/rev/functor/reverse_pass_callback.hpp +++ b/stan/math/rev/functor/reverse_pass_callback.hpp @@ -17,7 +17,7 @@ struct callback_vari : public vari_base { inline void chain() final { rev_functor_(); } inline void set_zero_adjoint() final {} - inline void init_dependent() final {} + inline void init_dependent() {} }; } // namespace internal From b36cf6b0e8413d17bb47aee598822674a440834c Mon Sep 17 00:00:00 2001 From: Ben Date: Tue, 11 Aug 2020 16:20:12 -0700 Subject: [PATCH 211/355] Removed some code --- stan/math/rev/fun/ordered_constrain.hpp | 67 ------------------------- 1 file changed, 67 deletions(-) diff --git a/stan/math/rev/fun/ordered_constrain.hpp b/stan/math/rev/fun/ordered_constrain.hpp index 818db3273ca..239772a44ac 100644 --- a/stan/math/rev/fun/ordered_constrain.hpp +++ b/stan/math/rev/fun/ordered_constrain.hpp @@ -12,73 +12,6 @@ namespace stan { namespace math { -namespace internal { -class ordered_constrain_op { - int N_; - double* exp_x_; - - public: - /** - * Return an increasing ordered vector derived from the specified - * free vector. The returned constrained vector will have the - * same dimensionality as the specified free vector. - * - * @tparam size Number of arguments - * @param needs_adj Boolean indicators of if adjoints of arguments will be - * needed - * @param x Free vector of scalars - * @return Increasing ordered vector - */ - template - Eigen::VectorXd operator()(const std::array& needs_adj, - const Eigen::VectorXd& x) { - N_ = x.size(); - using std::exp; - - Eigen::Matrix y(N_); - if (N_ == 0) { - return y; - } - - exp_x_ = ChainableStack::instance_->memalloc_.alloc_array(N_ - 1); - - y[0] = x[0]; - for (int n = 1; n < N_; ++n) { - exp_x_[n - 1] = exp(x[n]); - y[n] = y[n - 1] + exp_x_[n - 1]; - } - return y; - } - - /** - * Compute the result of multiply the transpose of the adjoint vector times - * the Jacobian of the ordered_constrain operator. - * - * @tparam size Number of adjoints to return - * @param needs_adj Boolean indicators of if adjoints of arguments will be - * needed - * @param adj Eigen::VectorXd of adjoints at the output of the softmax - * @return Eigen::VectorXd of adjoints propagated through softmax operation - */ - template - auto multiply_adjoint_jacobian(const std::array& needs_adj, - const Eigen::VectorXd& adj) const { - Eigen::VectorXd adj_times_jac(N_); - double rolling_adjoint_sum = 0.0; - - if (N_ > 0) { - for (int n = N_ - 1; n > 0; --n) { - rolling_adjoint_sum += adj(n); - adj_times_jac(n) = exp_x_[n - 1] * rolling_adjoint_sum; - } - adj_times_jac(0) = rolling_adjoint_sum + adj(0); - } - - return std::make_tuple(adj_times_jac); - } -}; -} // namespace internal - /** * Return an increasing ordered vector derived from the specified * free vector. The returned constrained vector will have the From 32b7c22f037d67ad9bf647f2b858d632a437fed1 Mon Sep 17 00:00:00 2001 From: Ben Date: Wed, 12 Aug 2020 13:12:11 -0700 Subject: [PATCH 212/355] Replaced some coeffRef's wit coeffs --- stan/math/rev/fun/ordered_constrain.hpp | 13 ++++++------- stan/math/rev/fun/positive_ordered_constrain.hpp | 13 ++++++------- stan/math/rev/fun/simplex_constrain.hpp | 15 +++++++-------- 3 files changed, 19 insertions(+), 22 deletions(-) diff --git a/stan/math/rev/fun/ordered_constrain.hpp b/stan/math/rev/fun/ordered_constrain.hpp index 239772a44ac..e875ddf908c 100644 --- a/stan/math/rev/fun/ordered_constrain.hpp +++ b/stan/math/rev/fun/ordered_constrain.hpp @@ -32,25 +32,24 @@ inline Eigen::Matrix ordered_constrain( Eigen::VectorXd y_val(N); arena_matrix exp_x(N - 1); - y_val.coeffRef(0) = value_of(x.coeffRef(0)); + y_val.coeffRef(0) = value_of(x.coeff(0)); for (int n = 1; n < N; ++n) { - exp_x.coeffRef(n - 1) = exp(value_of(x.coeffRef(n))); - y_val.coeffRef(n) = y_val.coeffRef(n - 1) + exp_x.coeffRef(n - 1); + exp_x.coeffRef(n - 1) = exp(value_of(x.coeff(n))); + y_val.coeffRef(n) = y_val.coeff(n - 1) + exp_x.coeff(n - 1); } arena_matrix> y = y_val; arena_matrix> arena_x = x; reverse_pass_callback([=]() mutable { - const auto& adj = y.adj(); double rolling_adjoint_sum = 0.0; if (N > 0) { for (int n = N - 1; n > 0; --n) { - rolling_adjoint_sum += adj(n); - arena_x.adj().coeffRef(n) += exp_x.coeffRef(n - 1) * rolling_adjoint_sum; + rolling_adjoint_sum += y.adj().coeff(n); + arena_x.adj().coeffRef(n) += exp_x.coeff(n - 1) * rolling_adjoint_sum; } - arena_x.adj().coeffRef(0) += rolling_adjoint_sum + adj(0); + arena_x.adj().coeffRef(0) += rolling_adjoint_sum + y.adj().coeff(0); } }); diff --git a/stan/math/rev/fun/positive_ordered_constrain.hpp b/stan/math/rev/fun/positive_ordered_constrain.hpp index 938e7decebc..1dc0635b935 100644 --- a/stan/math/rev/fun/positive_ordered_constrain.hpp +++ b/stan/math/rev/fun/positive_ordered_constrain.hpp @@ -32,23 +32,22 @@ inline Eigen::Matrix positive_ordered_constrain( Eigen::VectorXd y_val(N); arena_matrix exp_x(N); - exp_x(0) = exp(value_of(x.coeffRef(0))); - y_val(0) = exp_x.coeffRef(0); + exp_x(0) = exp(value_of(x.coeff(0))); + y_val(0) = exp_x.coeff(0); for (int n = 1; n < N; ++n) { - exp_x(n) = exp(value_of(x.coeffRef(n))); - y_val(n) = y_val.coeffRef(n - 1) + exp_x.coeffRef(n); + exp_x(n) = exp(value_of(x.coeff(n))); + y_val(n) = y_val.coeff(n - 1) + exp_x.coeff(n); } arena_matrix> y = y_val; arena_matrix> arena_x = x; reverse_pass_callback([=]() mutable { - const auto& adj = y.adj(); double rolling_adjoint_sum = 0.0; for (int n = N; --n >= 0;) { - rolling_adjoint_sum += adj(n); - arena_x.adj().coeffRef(n) += exp_x.coeffRef(n) * rolling_adjoint_sum; + rolling_adjoint_sum += y.adj().coeff(n); + arena_x.adj().coeffRef(n) += exp_x.coeff(n) * rolling_adjoint_sum; } }); diff --git a/stan/math/rev/fun/simplex_constrain.hpp b/stan/math/rev/fun/simplex_constrain.hpp index 4b3c3562985..fe81e331313 100644 --- a/stan/math/rev/fun/simplex_constrain.hpp +++ b/stan/math/rev/fun/simplex_constrain.hpp @@ -36,9 +36,9 @@ inline Eigen::Matrix simplex_constrain( double stick_len(1.0); for (int k = 0; k < N; ++k) { double log_N_minus_k = std::log(N - k); - z.coeffRef(k) = inv_logit(value_of(y.coeffRef(k)) - log_N_minus_k); - diag.coeffRef(k) = stick_len * z.coeffRef(k) * inv_logit(log_N_minus_k - value_of(y.coeffRef(k))); - x_val.coeffRef(k) = stick_len * z.coeffRef(k); + z.coeffRef(k) = inv_logit(value_of(y.coeff(k)) - log_N_minus_k); + diag.coeffRef(k) = stick_len * z.coeff(k) * inv_logit(log_N_minus_k - value_of(y.coeff(k))); + x_val.coeffRef(k) = stick_len * z.coeff(k); stick_len -= x_val(k); } x_val.coeffRef(N) = stick_len; @@ -47,14 +47,13 @@ inline Eigen::Matrix simplex_constrain( arena_matrix> arena_y = y; reverse_pass_callback([=]() mutable { - const auto& adj = x.adj(); - double acc = adj(N); + double acc = x.adj().coeff(N); if (N > 0) { - arena_y.adj().coeffRef(N - 1) += diag.coeffRef(N - 1) * (adj(N - 1) - acc); + arena_y.adj().coeffRef(N - 1) += diag.coeff(N - 1) * (x.adj().coeff(N - 1) - acc); for (int n = N - 1; --n >= 0;) { - acc = adj(n + 1) * z.coeffRef(n + 1) + (1 - z.coeffRef(n + 1)) * acc; - arena_y.adj().coeffRef(n) += diag.coeffRef(n) * (adj(n) - acc); + acc = x.adj().coeff(n + 1) * z.coeff(n + 1) + (1 - z.coeff(n + 1)) * acc; + arena_y.adj().coeffRef(n) += diag.coeff(n) * (x.adj().coeff(n) - acc); } } }); From 395858f93ed9d584f69740a92bf039f049fa3ccb Mon Sep 17 00:00:00 2001 From: Ben Date: Mon, 17 Aug 2020 20:14:21 -0400 Subject: [PATCH 213/355] Converted divide, dot_self, determinant, and gp_exp_quad_cov to use new autodiff structure (Issue #2018) --- stan/math/prim/fun/divide.hpp | 7 +- stan/math/prim/fun/gp_exp_quad_cov.hpp | 23 +- stan/math/rev/core/accumulate_adjoints.hpp | 16 + stan/math/rev/fun/columns_dot_self.hpp | 2 +- stan/math/rev/fun/determinant.hpp | 48 +-- stan/math/rev/fun/divide.hpp | 184 ++--------- stan/math/rev/fun/dot_self.hpp | 37 +-- stan/math/rev/fun/gp_exp_quad_cov.hpp | 310 ++++-------------- .../fun/multiply_lower_tri_self_transpose.hpp | 11 +- stan/math/rev/fun/tcrossprod.hpp | 11 +- .../math/prim/fun/gp_exp_quad_cov_test.cpp | 12 +- .../math/rev/fun/gp_exp_quad_cov_test.cpp | 13 +- 12 files changed, 163 insertions(+), 511 deletions(-) diff --git a/stan/math/prim/fun/divide.hpp b/stan/math/prim/fun/divide.hpp index fd7e48de087..a165f0e3428 100644 --- a/stan/math/prim/fun/divide.hpp +++ b/stan/math/prim/fun/divide.hpp @@ -40,9 +40,10 @@ inline int divide(int x, int y) { * @param[in] c specified scalar * @return matrix divided by the scalar */ -template , - typename = require_stan_scalar_t, - typename = require_all_not_var_t, Scal>> +template * = nullptr, + require_stan_scalar_t* = nullptr, + require_all_not_st_var* = nullptr> inline auto divide(const Mat& m, Scal c) { return (m / c).eval(); } diff --git a/stan/math/prim/fun/gp_exp_quad_cov.hpp b/stan/math/prim/fun/gp_exp_quad_cov.hpp index 827e5cbf4f3..bb3aa60e47f 100644 --- a/stan/math/prim/fun/gp_exp_quad_cov.hpp +++ b/stan/math/prim/fun/gp_exp_quad_cov.hpp @@ -169,12 +169,13 @@ gp_exp_quad_cov(const std::vector> &x1, * @throw std::domain_error if sigma <= 0, l <= 0, or * x is nan or infinite */ -template +template * = nullptr> inline typename Eigen::Matrix, Eigen::Dynamic, Eigen::Dynamic> gp_exp_quad_cov(const std::vector &x, const T_sigma &sigma, const T_l &length_scale) { - check_positive("gp_exp_quad_cov", "magnitude", sigma); + check_positive("gp_exp_quad_cov", "marginal standard deviation", sigma); check_positive("gp_exp_quad_cov", "length scale", length_scale); const size_t x_size = x.size(); @@ -214,7 +215,7 @@ inline typename Eigen::Matrix, Eigen::Dynamic, Eigen::Dynamic> gp_exp_quad_cov(const std::vector> &x, const T_sigma &sigma, const std::vector &length_scale) { - check_positive_finite("gp_exp_quad_cov", "magnitude", sigma); + check_positive_finite("gp_exp_quad_cov", "marginal standard deviation", sigma); check_positive_finite("gp_exp_quad_cov", "length scale", length_scale); size_t x_size = x.size(); @@ -258,7 +259,7 @@ inline typename Eigen::Matrix, gp_exp_quad_cov(const std::vector &x1, const std::vector &x2, const T_sigma &sigma, const T_l &length_scale) { const char *function_name = "gp_exp_quad_cov"; - check_positive(function_name, "magnitude", sigma); + check_positive(function_name, "marginal standard deviation", sigma); check_positive(function_name, "length scale", length_scale); const size_t x1_size = x1.size(); @@ -326,7 +327,7 @@ gp_exp_quad_cov(const std::vector> &x1, for (size_t i = 0; i < x2_size; ++i) { check_not_nan(function_name, "x2", x2[i]); } - check_positive_finite(function_name, "magnitude", sigma); + check_positive_finite(function_name, "marginal standard deviation", sigma); check_positive_finite(function_name, "length scale", length_scale); check_size_match(function_name, "x dimension", x1[0].size(), "number of length scales", l_size); @@ -354,7 +355,7 @@ inline Eigen::MatrixXd gp_exp_quad_cov(const std::vector &x, const double &sigma, const double &length_scale) { const char *function_name = "gp_exp_quad_cov"; - check_positive(function_name, "magnitude", sigma); + check_positive(function_name, "marginal standard deviation", sigma); check_positive(function_name, "length scale", length_scale); const auto x_size = x.size(); @@ -397,7 +398,7 @@ inline Eigen::MatrixXd gp_exp_quad_cov(const std::vector &x, const double &sigma, const double &length_scale) { const char *function_name = "gp_exp_quad_cov"; - check_positive(function_name, "magnitude", sigma); + check_positive(function_name, "marginal standard deviation", sigma); check_positive(function_name, "length scale", length_scale); const size_t x_size = x.size(); @@ -441,7 +442,7 @@ inline Eigen::MatrixXd gp_exp_quad_cov( const std::vector &x, const double &sigma, const std::vector &length_scale) { const char *function_name = "gp_exp_quad_cov"; - check_positive_finite(function_name, "magnitude", sigma); + check_positive_finite(function_name, "marginal standard deviation", sigma); check_positive_finite(function_name, "length scale", length_scale); const size_t x_size = x.size(); @@ -489,7 +490,7 @@ inline typename Eigen::MatrixXd gp_exp_quad_cov(const std::vector &x1, const double &sigma, const double &length_scale) { const char *function_name = "gp_exp_quad_cov"; - check_positive_finite(function_name, "magnitude", sigma); + check_positive_finite(function_name, "marginal standard deviation", sigma); check_positive_finite(function_name, "length scale", length_scale); Eigen::MatrixXd cov(x1.size(), x2.size()); @@ -542,7 +543,7 @@ inline typename Eigen::MatrixXd gp_exp_quad_cov( const char *function_name = "gp_exp_quad_cov"; const int x1_size = x1.size(); const int x2_size = x2.size(); - check_positive_finite(function_name, "magnitude", sigma); + check_positive_finite(function_name, "marginal standard deviation", sigma); check_positive_finite(function_name, "length scale", length_scale); Eigen::MatrixXd cov(x1.size(), x2.size()); @@ -607,7 +608,7 @@ inline typename Eigen::MatrixXd gp_exp_quad_cov( const int x1_inner_size = x1[0].size(); const int x2_inner_size = x1[0].size(); const char *function_name = "gp_exp_quad_cov"; - check_positive_finite(function_name, "magnitude", sigma); + check_positive_finite(function_name, "marginal standard deviation", sigma); check_positive_finite(function_name, "length scale", length_scale); check_size_match(function_name, "x dimension", x1[0].size(), "number of length scales", l_size); diff --git a/stan/math/rev/core/accumulate_adjoints.hpp b/stan/math/rev/core/accumulate_adjoints.hpp index e5b27354ebd..a78357a19d0 100644 --- a/stan/math/rev/core/accumulate_adjoints.hpp +++ b/stan/math/rev/core/accumulate_adjoints.hpp @@ -147,6 +147,22 @@ inline double* accumulate_adjoints(double* dest, Arith&& x, Pargs&&... args) { */ inline double* accumulate_adjoints(double* dest) { return dest; } +template * = nullptr> +inline void accumulate_adjoints(const arena_matrix& sum, const T2& summand) { + sum.adj() += summand; +} + +template * = nullptr> +inline void accumulate_adjoints(T1& sum, const T2& summand) { + sum.adj() += summand; +} + +template * = nullptr> +inline void accumulate_adjoints(T1& sum, const T2& summand) {} + } // namespace math } // namespace stan diff --git a/stan/math/rev/fun/columns_dot_self.hpp b/stan/math/rev/fun/columns_dot_self.hpp index 7db4a3654f6..f1ac7f46abc 100644 --- a/stan/math/rev/fun/columns_dot_self.hpp +++ b/stan/math/rev/fun/columns_dot_self.hpp @@ -21,7 +21,7 @@ inline Eigen::Matrix columns_dot_self( const Mat& x) { Eigen::Matrix ret(1, x.cols()); for (size_type i = 0; i < x.cols(); i++) { - ret(i) = var(new internal::dot_self_vari(x.col(i))); + ret(i) = dot_self(x.col(i)); } return ret; } diff --git a/stan/math/rev/fun/determinant.hpp b/stan/math/rev/fun/determinant.hpp index 74302537c8b..086ada0daa2 100644 --- a/stan/math/rev/fun/determinant.hpp +++ b/stan/math/rev/fun/determinant.hpp @@ -10,40 +10,6 @@ namespace stan { namespace math { -namespace internal { -template -class determinant_vari : public vari { - int rows_; - int cols_; - double* A_; - vari** adjARef_; - - public: - explicit determinant_vari(const Eigen::Matrix& A) - : vari(determinant_vari_calc(A)), - rows_(A.rows()), - cols_(A.cols()), - A_(reinterpret_cast(ChainableStack::instance_->memalloc_.alloc( - sizeof(double) * A.rows() * A.cols()))), - adjARef_( - reinterpret_cast(ChainableStack::instance_->memalloc_.alloc( - sizeof(vari*) * A.rows() * A.cols()))) { - Eigen::Map(A_, rows_, cols_) = A.val(); - Eigen::Map(adjARef_, rows_, cols_) = A.vi(); - } - static double determinant_vari_calc(const Eigen::Matrix& A) { - return A.val().determinant(); - } - virtual void chain() { - Eigen::Map(adjARef_, rows_, cols_).adj() - += (adj_ * val_) - * Eigen::Map(A_, rows_, cols_) - .inverse() - .transpose(); - } -}; -} // namespace internal - template * = nullptr> inline var determinant(const T& m) { check_square("determinant", "m", m); @@ -51,8 +17,18 @@ inline var determinant(const T& m) { return 1; } - return {new internal::determinant_vari(m)}; + double det_val = m.val().determinant(); + arena_matrix> arena_m = m; + arena_matrix arena_m_inv_t = m.val().inverse().transpose(); + + var det = det_val; + + reverse_pass_callback([=]() mutable { + arena_m.adj() + += (det.adj() * det_val) * arena_m_inv_t; + }); + + return det; } } // namespace math diff --git a/stan/math/rev/fun/divide.hpp b/stan/math/rev/fun/divide.hpp index 17a32e1dafc..07edcee933f 100644 --- a/stan/math/rev/fun/divide.hpp +++ b/stan/math/rev/fun/divide.hpp @@ -10,171 +10,43 @@ namespace stan { namespace math { -namespace internal { - -template -class matrix_scalar_divide_dv_vari : public vari { - public: - int rows_; - int cols_; - vari* adjCRef_; - vari** adjResultRef_; - double invc_; - - explicit matrix_scalar_divide_dv_vari(const Eigen::Matrix& m, - const var& c) - : vari(0), - rows_(m.rows()), - cols_(m.cols()), - adjCRef_(c.vi_), - adjResultRef_(ChainableStack::instance_->memalloc_.alloc_array( - m.rows() * m.cols())), - invc_(1.0 / c.val()) { - Eigen::Map(adjResultRef_, rows_, cols_) - = (invc_ * m).unaryExpr([](double x) { return new vari(x, false); }); - } - - virtual void chain() { - Eigen::Map adjResult(adjResultRef_, rows_, cols_); - adjCRef_->adj_ - -= invc_ * (adjResult.adj().array() * adjResult.val().array()).sum(); - } -}; - -template -class matrix_scalar_divide_vd_vari : public vari { - public: - int rows_; - int cols_; - vari** adjMRef_; - vari** adjResultRef_; - double invc_; - - explicit matrix_scalar_divide_vd_vari(const Eigen::Matrix& m, - const double& c) - : vari(0), - rows_(m.rows()), - cols_(m.cols()), - adjMRef_(ChainableStack::instance_->memalloc_.alloc_array( - m.rows() * m.cols())), - adjResultRef_(ChainableStack::instance_->memalloc_.alloc_array( - m.rows() * m.cols())), - invc_(1.0 / c) { - Eigen::Map(adjMRef_, rows_, cols_) = m.vi(); - Eigen::Map(adjResultRef_, rows_, cols_) - = (invc_ * m.val()).unaryExpr([](double x) { - return new vari(x, false); - }); - } - - virtual void chain() { - Eigen::Map adjM(adjMRef_, rows_, cols_); - Eigen::Map adjResult(adjResultRef_, rows_, cols_); - adjM.adj() += invc_ * adjResult.adj(); - } -}; - -template -class matrix_scalar_divide_vv_vari : public vari { - public: - int rows_; - int cols_; - vari** adjMRef_; - vari* adjC_; - vari** adjResultRef_; - double invc_; - - explicit matrix_scalar_divide_vv_vari(const Eigen::Matrix& m, - const var& c) - : vari(0), - rows_(m.rows()), - cols_(m.cols()), - adjMRef_(ChainableStack::instance_->memalloc_.alloc_array( - m.rows() * m.cols())), - adjC_(c.vi_), - adjResultRef_(ChainableStack::instance_->memalloc_.alloc_array( - m.rows() * m.cols())), - invc_(1.0 / c.val()) { - Eigen::Map(adjMRef_, rows_, cols_) = m.vi(); - Eigen::Map(adjResultRef_, rows_, cols_) - = (invc_ * m.val()).unaryExpr([](double x) { - return new vari(x, false); - }); - } - - virtual void chain() { - Eigen::Map adjM(adjMRef_, rows_, cols_); - Eigen::Map adjResult(adjResultRef_, rows_, cols_); - adjC_->adj_ - -= invc_ * (adjResult.adj().array() * adjResult.val().array()).sum(); - adjM.adj() += invc_ * adjResult.adj(); - } -}; - -} // namespace internal - -/** - * Return matrix divided by scalar. - * - * @tparam Mat type of the matrix or expression - * @param[in] m specified matrix or expression - * @param[in] c specified scalar - * @return matrix divided by the scalar - */ -template > -inline auto divide(const Mat& m, const var& c) { - auto* baseVari - = new internal::matrix_scalar_divide_dv_vari(m, - c); - Eigen::Matrix result( - m.rows(), m.cols()); - result.vi() - = Eigen::Map(baseVari->adjResultRef_, m.rows(), m.cols()); - return result; -} - -/** - * Return matrix divided by scalar. - * - * @tparam Mat type of the matrix or expression - * @param[in] m specified matrix or expression - * @param[in] c specified scalar - * @return matrix divided by the scalar - */ -template > -inline auto divide(const Mat& m, const double& c) { - auto* baseVari - = new internal::matrix_scalar_divide_vd_vari(m, - c); - Eigen::Matrix result( - m.rows(), m.cols()); - result.vi() - = Eigen::Map(baseVari->adjResultRef_, m.rows(), m.cols()); - return result; -} /** * Return matrix divided by scalar. * * @tparam Mat type of the matrix or expression + * @tparam Scal type of the scalar * @param[in] m specified matrix or expression * @param[in] c specified scalar * @return matrix divided by the scalar */ -template , - typename = void> -inline auto divide(const Mat& m, const var& c) { - auto* baseVari - = new internal::matrix_scalar_divide_vv_vari(m, - c); - Eigen::Matrix result( - m.rows(), m.cols()); - result.vi() - = Eigen::Map(baseVari->adjResultRef_, m.rows(), m.cols()); - return result; +template * = nullptr, + require_stan_scalar_t* = nullptr, + require_any_st_var* = nullptr> +inline Eigen::Matrix +divide(const Mat& m, Scal c) { + auto arena_m = to_arena_if::value>(m); + + double invc = 1.0 / value_of(c); + + using Mat_v = Eigen::Matrix; + + arena_matrix res = invc * value_of(m); + + reverse_pass_callback([=]() mutable { + if (!is_constant::value) { + accumulate_adjoints(arena_m, invc * res.adj()); + } + if (!is_constant::value) { + accumulate_adjoints(c, -invc * + (res.adj().array() * res.val().array()).sum()); + } + }); + + return res; } } // namespace math diff --git a/stan/math/rev/fun/dot_self.hpp b/stan/math/rev/fun/dot_self.hpp index e5036538d5a..21ae3577f50 100644 --- a/stan/math/rev/fun/dot_self.hpp +++ b/stan/math/rev/fun/dot_self.hpp @@ -12,31 +12,6 @@ namespace stan { namespace math { -namespace internal { -class dot_self_vari : public vari { - protected: - vari** v_; - size_t size_; - - public: - dot_self_vari(vari** v, size_t size) - : vari(Eigen::Map(v, size).val().squaredNorm()), - v_(v), - size_(size) {} - template * = nullptr> - explicit dot_self_vari(const T& v) - : vari(v.val().squaredNorm()), size_(v.size()) { - v_ = reinterpret_cast( - ChainableStack::instance_->memalloc_.alloc(size_ * sizeof(vari*))); - Eigen::Map(v_, v.rows(), v.cols()) = v.vi(); - } - virtual void chain() { - Eigen::Map v_map(v_, size_); - v_map.adj() += adj_ * 2.0 * v_map.val(); - } -}; -} // namespace internal - /** * Returns the dot product of a vector of var with itself. * @@ -47,8 +22,16 @@ class dot_self_vari : public vari { */ template * = nullptr> inline var dot_self(const T& v) { - const Eigen::Ref>& v_ref = v; - return {new internal::dot_self_vari(v_ref)}; + arena_matrix> v_val = value_of(v); + arena_matrix> arena_v = v; + + var res = v_val.dot(v_val); + + reverse_pass_callback([=]() mutable { + arena_v.adj() += 2.0 * res.adj() * v_val; + }); + + return res; } } // namespace math diff --git a/stan/math/rev/fun/gp_exp_quad_cov.hpp b/stan/math/rev/fun/gp_exp_quad_cov.hpp index d3fcb2a8b6a..f5b213ec81f 100644 --- a/stan/math/rev/fun/gp_exp_quad_cov.hpp +++ b/stan/math/rev/fun/gp_exp_quad_cov.hpp @@ -15,187 +15,6 @@ namespace stan { namespace math { -/** - * This is a subclass of the vari class for precomputed - * gradients of gp_exp_quad_cov. - * - * The class stores the double values for the distance - * matrix, pointers to the varis for the covariance - * matrix, along with a pointer to the vari for sigma, - * and the vari for length_scale. - * - * @tparam T_x type of std::vector of elements - * @tparam T_sigma type of sigma - * @tparam T_l type of length scale - */ -template -class gp_exp_quad_cov_vari : public vari { - public: - const size_t size_; - const size_t size_ltri_; - const double l_d_; - const double sigma_d_; - const double sigma_sq_d_; - double *dist_; - vari *l_vari_; - vari *sigma_vari_; - vari **cov_lower_; - vari **cov_diag_; - - /** - * Constructor for gp_exp_quad_cov. - * - * All memory allocated in - * ChainableStack's stack_alloc arena. - * - * It is critical for the efficiency of this object - * that the constructor create new varis that aren't - * popped onto the var_stack_, but rather are - * popped onto the var_nochain_stack_. This is - * controlled to the second argument to - * vari's constructor. - * - * @param x std::vector input that can be used in square distance - * Assumes each element of x is the same size - * @param sigma standard deviation - * @param length_scale length scale - */ - gp_exp_quad_cov_vari(const std::vector &x, const T_sigma &sigma, - const T_l &length_scale) - : vari(0.0), - size_(x.size()), - size_ltri_(size_ * (size_ - 1) / 2), - l_d_(value_of(length_scale)), - sigma_d_(value_of(sigma)), - sigma_sq_d_(sigma_d_ * sigma_d_), - dist_(ChainableStack::instance_->memalloc_.alloc_array( - size_ltri_)), - l_vari_(length_scale.vi_), - sigma_vari_(sigma.vi_), - cov_lower_(ChainableStack::instance_->memalloc_.alloc_array( - size_ltri_)), - cov_diag_( - ChainableStack::instance_->memalloc_.alloc_array(size_)) { - double inv_half_sq_l_d = 0.5 / (l_d_ * l_d_); - size_t pos = 0; - for (size_t j = 0; j < size_ - 1; ++j) { - for (size_t i = j + 1; i < size_; ++i) { - double dist_sq = squared_distance(x[i], x[j]); - dist_[pos] = dist_sq; - cov_lower_[pos] = new vari( - sigma_sq_d_ * std::exp(-dist_sq * inv_half_sq_l_d), false); - ++pos; - } - } - for (size_t i = 0; i < size_; ++i) { - cov_diag_[i] = new vari(sigma_sq_d_, false); - } - } - - virtual void chain() { - double adjl = 0; - double adjsigma = 0; - - for (size_t i = 0; i < size_ltri_; ++i) { - vari *el_low = cov_lower_[i]; - double prod_add = el_low->adj_ * el_low->val_; - adjl += prod_add * dist_[i]; - adjsigma += prod_add; - } - for (size_t i = 0; i < size_; ++i) { - vari *el = cov_diag_[i]; - adjsigma += el->adj_ * el->val_; - } - l_vari_->adj_ += adjl / (l_d_ * l_d_ * l_d_); - sigma_vari_->adj_ += adjsigma * 2 / sigma_d_; - } -}; - -/** - * This is a subclass of the vari class for precomputed - * gradients of gp_exp_quad_cov. - * - * The class stores the double values for the distance - * matrix, pointers to the varis for the covariance - * matrix, along with a pointer to the vari for sigma, - * and the vari for length_scale. - * - * @tparam T_x type of std::vector of elements - * @tparam T_l type of length scale - */ -template -class gp_exp_quad_cov_vari : public vari { - public: - const size_t size_; - const size_t size_ltri_; - const double l_d_; - const double sigma_d_; - const double sigma_sq_d_; - double *dist_; - vari *l_vari_; - vari **cov_lower_; - vari **cov_diag_; - - /** - * Constructor for gp_exp_quad_cov. - * - * All memory allocated in - * ChainableStack's stack_alloc arena. - * - * It is critical for the efficiency of this object - * that the constructor create new varis that aren't - * popped onto the var_stack_, but rather are - * popped onto the var_nochain_stack_. This is - * controlled to the second argument to - * vari's constructor. - * - * @param x std::vector input that can be used in square distance - * Assumes each element of x is the same size - * @param sigma standard deviation - * @param length_scale length scale - */ - gp_exp_quad_cov_vari(const std::vector &x, double sigma, - const T_l &length_scale) - : vari(0.0), - size_(x.size()), - size_ltri_(size_ * (size_ - 1) / 2), - l_d_(value_of(length_scale)), - sigma_d_(value_of(sigma)), - sigma_sq_d_(sigma_d_ * sigma_d_), - dist_(ChainableStack::instance_->memalloc_.alloc_array( - size_ltri_)), - l_vari_(length_scale.vi_), - cov_lower_(ChainableStack::instance_->memalloc_.alloc_array( - size_ltri_)), - cov_diag_( - ChainableStack::instance_->memalloc_.alloc_array(size_)) { - double inv_half_sq_l_d = 0.5 / (l_d_ * l_d_); - size_t pos = 0; - for (size_t j = 0; j < size_ - 1; ++j) { - for (size_t i = j + 1; i < size_; ++i) { - double dist_sq = squared_distance(x[i], x[j]); - dist_[pos] = dist_sq; - cov_lower_[pos] = new vari( - sigma_sq_d_ * std::exp(-dist_sq * inv_half_sq_l_d), false); - ++pos; - } - } - for (size_t i = 0; i < size_; ++i) { - cov_diag_[i] = new vari(sigma_sq_d_, false); - } - } - - virtual void chain() { - double adjl = 0; - - for (size_t i = 0; i < size_ltri_; ++i) { - vari *el_low = cov_lower_[i]; - adjl += el_low->adj_ * el_low->val_ * dist_[i]; - } - l_vari_->adj_ += adjl / (l_d_ * l_d_ * l_d_); - } -}; - /** * Returns a squared exponential kernel. * @@ -208,82 +27,83 @@ class gp_exp_quad_cov_vari : public vari { * @throw std::domain_error if sigma <= 0, l <= 0, or * x is nan or infinite */ -template ::type>> -inline Eigen::Matrix gp_exp_quad_cov(const std::vector &x, - const var &sigma, - const var &length_scale) { - check_positive("gp_exp_quad_cov", "sigma", sigma); - check_positive("gp_exp_quad_cov", "length_scale", length_scale); - size_t x_size = x.size(); - for (size_t i = 0; i < x_size; ++i) { +template * = nullptr, + require_stan_scalar_t* = nullptr, + require_any_st_var* = nullptr> +inline Eigen::Matrix +gp_exp_quad_cov(const std::vector& x, + T_sigma sigma, + T_l length_scale) { + check_positive("gp_exp_quad_cov", "marginal standard deviation", sigma); + check_positive("gp_exp_quad_cov", "length scale", length_scale); + for (size_t i = 0; i < x.size(); ++i) { check_not_nan("gp_exp_quad_cov", "x", x[i]); } - Eigen::Matrix cov(x_size, x_size); - if (x_size == 0) { - return cov; + if (x.size() == 0) { + return Eigen::Matrix(); } - gp_exp_quad_cov_vari *baseVari - = new gp_exp_quad_cov_vari(x, sigma, length_scale); + double l_d = value_of(length_scale); + double sigma_d = value_of(sigma); + double sigma_sq_d = sigma_d * sigma_d; + + arena_matrix dist(x.size(), x.size()); + arena_matrix res_val(x.size(), x.size()); - size_t pos = 0; - for (size_t j = 0; j < x_size - 1; ++j) { - for (size_t i = (j + 1); i < x_size; ++i) { - cov.coeffRef(i, j).vi_ = baseVari->cov_lower_[pos]; - cov.coeffRef(j, i).vi_ = cov.coeffRef(i, j).vi_; - ++pos; + auto arena_x = to_arena_if::value>(x); + + double inv_half_sq_l_d = 0.5 / (value_of(length_scale) * value_of(length_scale)); + for (size_t j = 0; j < x.size(); ++j) { + for (size_t i = 0; i < j; ++i) { + double dist_sq = squared_distance(value_of(x[i]), value_of(x[j])); + dist(i, j) = dist_sq; + res_val(i, j) = sigma_sq_d * std::exp(-dist_sq * inv_half_sq_l_d); + res_val(j, i) = res_val(i, j); + dist(j, i) = dist(i, j); } - cov.coeffRef(j, j).vi_ = baseVari->cov_diag_[j]; } - cov.coeffRef(x_size - 1, x_size - 1).vi_ = baseVari->cov_diag_[x_size - 1]; - return cov; -} - -/** - * Returns a squared exponential kernel. - * - * @tparam T_x type of elements in the vector - * @param x std::vector input that can be used in square distance - * Assumes each element of x is the same size - * @param sigma standard deviation - * @param length_scale length scale - * @return squared distance - * @throw std::domain_error if sigma <= 0, l <= 0, or - * x is nan or infinite - */ -template ::type>> -inline Eigen::Matrix gp_exp_quad_cov(const std::vector &x, - double sigma, - const var &length_scale) { - check_positive("gp_exp_quad_cov", "marginal variance", sigma); - check_positive("gp_exp_quad_cov", "length-scale", length_scale); - size_t x_size = x.size(); - for (size_t i = 0; i < x_size; ++i) { - check_not_nan("gp_exp_quad_cov", "x", x[i]); + for (size_t i = 0; i < x.size(); ++i) { + dist(i, i) = 0.0; + res_val(i, i) = sigma_sq_d; } - Eigen::Matrix cov(x_size, x_size); - if (x_size == 0) { - return cov; - } + arena_matrix> res = res_val; + + reverse_pass_callback([=]() mutable { + Eigen::ArrayXXd adj_times_val = res.adj().array() * res.val().array(); + + /*std::cout << res.adj() << std::endl << "----" << std::endl; + std::cout << res.val() << std::endl << "----" << std::endl; + std::cout << adj_times_val << std::endl << "----" << std::endl; + std::cout << dist.array() << std::endl << "----" << std::endl;*/ + + if(!is_constant::value) + for(size_t i = 0; i < arena_x.size(); ++i) { + for(size_t j = 0; j < arena_x.size(); ++j) { + auto adj = eval(-(value_of(arena_x[i]) - value_of(arena_x[j])) * + adj_times_val(i, j) / (l_d * l_d)); + //std::cout << "(" << i << ", " << j << ") : " << adj << std::endl; + accumulate_adjoints(arena_x[i], adj); + accumulate_adjoints(arena_x[j], -adj); + } + } + + if(!is_constant::value) { + accumulate_adjoints(sigma, 2.0 * adj_times_val.sum() / sigma_d); + /*for(size_t i = 0; i < arena_x.size(); ++i) { + sigma + }*/ + } - gp_exp_quad_cov_vari *baseVari - = new gp_exp_quad_cov_vari(x, sigma, length_scale); + if(!is_constant::value) + accumulate_adjoints(length_scale, (dist.array() * adj_times_val).sum() / (l_d * l_d * l_d)); + }); - size_t pos = 0; - for (size_t j = 0; j < x_size - 1; ++j) { - for (size_t i = (j + 1); i < x_size; ++i) { - cov.coeffRef(i, j).vi_ = baseVari->cov_lower_[pos]; - cov.coeffRef(j, i).vi_ = cov.coeffRef(i, j).vi_; - ++pos; - } - cov.coeffRef(j, j).vi_ = baseVari->cov_diag_[j]; - } - cov.coeffRef(x_size - 1, x_size - 1).vi_ = baseVari->cov_diag_[x_size - 1]; - return cov; + return res; } } // namespace math diff --git a/stan/math/rev/fun/multiply_lower_tri_self_transpose.hpp b/stan/math/rev/fun/multiply_lower_tri_self_transpose.hpp index ba880c007e7..df269fb8d30 100644 --- a/stan/math/rev/fun/multiply_lower_tri_self_transpose.hpp +++ b/stan/math/rev/fun/multiply_lower_tri_self_transpose.hpp @@ -30,17 +30,8 @@ inline matrix_v multiply_lower_tri_self_transpose(const matrix_v& L) { } else { // if (K < J) Knz = (K * (K + 1)) / 2; } - vari** vs = reinterpret_cast( - ChainableStack::instance_->memalloc_.alloc(Knz * sizeof(vari*))); - int pos = 0; - for (int m = 0; m < K; ++m) { - for (int n = 0; n < ((J < (m + 1)) ? J : (m + 1)); ++n) { - vs[pos++] = L(m, n).vi_; - } - } for (int m = 0, mpos = 0; m < K; ++m, mpos += (J < m) ? J : m) { - LLt.coeffRef(m, m) = var( - new internal::dot_self_vari(vs + mpos, (J < (m + 1)) ? J : (m + 1))); + LLt.coeffRef(m, m) = dot_self(L.row(m).head((J < (m + 1)) ? J : (m + 1))); for (int n = 0, npos = 0; n < m; ++n, npos += (J < n) ? J : n) { LLt.coeffRef(m, n) = LLt.coeffRef(n, m) = dot_product(L.row(m).head((J < (n + 1)) ? J : (n + 1)), diff --git a/stan/math/rev/fun/tcrossprod.hpp b/stan/math/rev/fun/tcrossprod.hpp index f1196c836d3..c2016d289dc 100644 --- a/stan/math/rev/fun/tcrossprod.hpp +++ b/stan/math/rev/fun/tcrossprod.hpp @@ -37,18 +37,9 @@ tcrossprod(const T& M) { Eigen::Matrix MMt(M.rows(), M.rows()); - vari** vs - = reinterpret_cast(ChainableStack::instance_->memalloc_.alloc( - (M.rows() * M.cols()) * sizeof(vari*))); - int pos = 0; - for (int m = 0; m < M.rows(); ++m) { - for (int n = 0; n < M.cols(); ++n) { - vs[pos++] = M(m, n).vi_; - } - } for (int m = 0; m < M.rows(); ++m) { MMt.coeffRef(m, m) - = var(new internal::dot_self_vari(vs + m * M.cols(), M.cols())); + = dot_self(M.row(m)); } for (int m = 0; m < M.rows(); ++m) { for (int n = 0; n < m; ++n) { diff --git a/test/unit/math/prim/fun/gp_exp_quad_cov_test.cpp b/test/unit/math/prim/fun/gp_exp_quad_cov_test.cpp index ba7a3c87fab..0171854558e 100644 --- a/test/unit/math/prim/fun/gp_exp_quad_cov_test.cpp +++ b/test/unit/math/prim/fun/gp_exp_quad_cov_test.cpp @@ -215,7 +215,7 @@ TEST(MathPrimMat, domain_error_training_sig_l_gp_cov_exp) { EXPECT_THROW_MSG(stan::math::gp_exp_quad_cov(x, sigma, l_bad), std::domain_error, " length scale"); EXPECT_THROW_MSG(stan::math::gp_exp_quad_cov(x, sigma_bad, l), - std::domain_error, " magnitude"); + std::domain_error, " marginal standard deviation"); EXPECT_THROW(stan::math::gp_exp_quad_cov(x_2, sigma, l_bad), std::domain_error); @@ -269,7 +269,7 @@ TEST(MathPrimMat, nan_error_training_sig_l_gp_cov_exp) { EXPECT_THROW_MSG(stan::math::gp_exp_quad_cov(x, sigma, l_bad), std::domain_error, " length scale"); EXPECT_THROW_MSG(stan::math::gp_exp_quad_cov(x, sigma_bad, l), - std::domain_error, " magnitude"); + std::domain_error, " marginal standard deviation"); EXPECT_THROW(stan::math::gp_exp_quad_cov(x, sigma, l_bad), std::domain_error); EXPECT_THROW(stan::math::gp_exp_quad_cov(x, sigma_bad, l), std::domain_error); @@ -336,7 +336,7 @@ TEST(MathPrimMat, domain_error_gp_exp_quad_cov2) { EXPECT_THROW_MSG(stan::math::gp_exp_quad_cov(x1, x2, sigma, l_bad), std::domain_error, " length scale"); EXPECT_THROW_MSG(stan::math::gp_exp_quad_cov(x1, x2, sigma_bad, l), - std::domain_error, " magnitude"); + std::domain_error, " marginal standard deviation"); EXPECT_THROW(stan::math::gp_exp_quad_cov(x1, x2, sigma_bad, l_bad), std::domain_error); @@ -416,7 +416,7 @@ TEST(MathPrimMat, nan_domain_error_gp_exp_quad_cov2) { EXPECT_THROW_MSG(stan::math::gp_exp_quad_cov(x1, x2, sigma, l_bad), std::domain_error, " length scale"); EXPECT_THROW_MSG(stan::math::gp_exp_quad_cov(x1, x2, sigma_bad, l), - std::domain_error, " magnitude"); + std::domain_error, " marginal standard deviation"); EXPECT_THROW(stan::math::gp_exp_quad_cov(x1, x2, sigma_bad, l_bad), std::domain_error); @@ -667,7 +667,7 @@ TEST(MathPrimMat, domain_error_training_sig_vec_length_scale_gp_exp_quad_cov) { EXPECT_THROW_MSG(stan::math::gp_exp_quad_cov(x_2, sigma, l_bad), std::domain_error, " length scale"); EXPECT_THROW_MSG(stan::math::gp_exp_quad_cov(x_2, sigma_bad, l), - std::domain_error, " magnitude"); + std::domain_error, " marginal standard deviation"); EXPECT_THROW(stan::math::gp_exp_quad_cov(x_2, sigma_bad, l_bad), std::domain_error); } @@ -751,7 +751,7 @@ TEST(MathPrimMat, nan_domain_error_gp_exp_quad_cov2_vec_length_scale) { EXPECT_THROW(stan::math::gp_exp_quad_cov(x_vec_1, x_vec_2, sigma_bad, l_bad1), std::domain_error); EXPECT_THROW_MSG(stan::math::gp_exp_quad_cov(x_vec_1, x_vec_2, sigma_bad, l), - std::domain_error, " magnitude"); + std::domain_error, " marginal standard deviation"); EXPECT_THROW_MSG(stan::math::gp_exp_quad_cov(x_vec_1, x_vec_2, sigma, l_bad1), std::domain_error, " length scale"); EXPECT_THROW_MSG(stan::math::gp_exp_quad_cov(x_vec_1, x_vec_2, sigma, l_bad2), diff --git a/test/unit/math/rev/fun/gp_exp_quad_cov_test.cpp b/test/unit/math/rev/fun/gp_exp_quad_cov_test.cpp index 7d577592d2b..1ac74330ce4 100644 --- a/test/unit/math/rev/fun/gp_exp_quad_cov_test.cpp +++ b/test/unit/math/rev/fun/gp_exp_quad_cov_test.cpp @@ -938,9 +938,9 @@ TEST(RevMath, gp_exp_quad_cov_domain_error_training) { EXPECT_THROW_MSG(stan::math::gp_exp_quad_cov(x, sigma, l_bad), std::domain_error, " length scale"); EXPECT_THROW_MSG(stan::math::gp_exp_quad_cov(x, sigma_bad, l), - std::domain_error, " magnitude"); + std::domain_error, " marginal standard deviation"); EXPECT_THROW_MSG(stan::math::gp_exp_quad_cov(x, sigma_bad, l_bad), - std::domain_error, " magnitude"); + std::domain_error, " marginal standard deviation"); EXPECT_THROW(stan::math::gp_exp_quad_cov(x_2, sigma, l_bad), std::domain_error); @@ -995,9 +995,9 @@ TEST(RevMath, gp_exp_quad_cov_nan_error_training) { EXPECT_THROW_MSG(stan::math::gp_exp_quad_cov(x, sigma, l_bad), std::domain_error, " length scale"); EXPECT_THROW_MSG(stan::math::gp_exp_quad_cov(x, sigma_bad, l), - std::domain_error, " magnitude"); + std::domain_error, " marginal standard deviation"); EXPECT_THROW_MSG(stan::math::gp_exp_quad_cov(x, sigma_bad, l_bad), - std::domain_error, " magnitude"); + std::domain_error, " marginal standard deviation"); EXPECT_THROW(stan::math::gp_exp_quad_cov(x_bad, sigma, l), std::domain_error); EXPECT_THROW(stan::math::gp_exp_quad_cov(x_bad, sigma_bad, l), @@ -1060,9 +1060,9 @@ TEST(RevMath, gp_exp_quad_cov_domain_error) { EXPECT_THROW_MSG(stan::math::gp_exp_quad_cov(x1, x2, sigma, l_bad), std::domain_error, "length scale"); EXPECT_THROW_MSG(stan::math::gp_exp_quad_cov(x1, x2, sigma_bad, l), - std::domain_error, "magnitude"); + std::domain_error, "marginal standard deviation"); EXPECT_THROW_MSG(stan::math::gp_exp_quad_cov(x1, x2, sigma_bad, l_bad), - std::domain_error, "magnitude"); + std::domain_error, "marginal standard deviation"); std::vector > x_vec_1(3); for (size_t i = 0; i < x_vec_1.size(); ++i) { @@ -1350,3 +1350,4 @@ TEST(AgradRevMatrix, gp_exp_quad_cov_check_varis_on_stack) { test::check_varis_on_stack(stan::math::gp_exp_quad_cov(x, to_var(sigma), l)); test::check_varis_on_stack(stan::math::gp_exp_quad_cov(x, sigma, to_var(l))); } + From a1a73e7a34d638c2473a713fd0c33f692efd5c18 Mon Sep 17 00:00:00 2001 From: Stan Jenkins Date: Tue, 18 Aug 2020 00:35:35 +0000 Subject: [PATCH 214/355] [Jenkins] auto-formatting by clang-format version 6.0.0-1ubuntu2~16.04.1 (tags/RELEASE_600/final) --- stan/math/prim/fun/divide.hpp | 3 +- stan/math/prim/fun/gp_exp_quad_cov.hpp | 5 +- stan/math/rev/core/accumulate_adjoints.hpp | 14 +++-- stan/math/rev/fun/determinant.hpp | 7 ++- stan/math/rev/fun/divide.hpp | 18 +++---- stan/math/rev/fun/dot_self.hpp | 5 +- stan/math/rev/fun/gp_exp_quad_cov.hpp | 54 +++++++++---------- stan/math/rev/fun/tcrossprod.hpp | 3 +- .../math/rev/fun/gp_exp_quad_cov_test.cpp | 1 - 9 files changed, 51 insertions(+), 59 deletions(-) diff --git a/stan/math/prim/fun/divide.hpp b/stan/math/prim/fun/divide.hpp index a165f0e3428..642f5c89200 100644 --- a/stan/math/prim/fun/divide.hpp +++ b/stan/math/prim/fun/divide.hpp @@ -40,8 +40,7 @@ inline int divide(int x, int y) { * @param[in] c specified scalar * @return matrix divided by the scalar */ -template * = nullptr, +template * = nullptr, require_stan_scalar_t* = nullptr, require_all_not_st_var* = nullptr> inline auto divide(const Mat& m, Scal c) { diff --git a/stan/math/prim/fun/gp_exp_quad_cov.hpp b/stan/math/prim/fun/gp_exp_quad_cov.hpp index bb3aa60e47f..72a7b655ad4 100644 --- a/stan/math/prim/fun/gp_exp_quad_cov.hpp +++ b/stan/math/prim/fun/gp_exp_quad_cov.hpp @@ -170,7 +170,7 @@ gp_exp_quad_cov(const std::vector> &x1, * x is nan or infinite */ template * = nullptr> + require_all_not_st_var * = nullptr> inline typename Eigen::Matrix, Eigen::Dynamic, Eigen::Dynamic> gp_exp_quad_cov(const std::vector &x, const T_sigma &sigma, @@ -215,7 +215,8 @@ inline typename Eigen::Matrix, Eigen::Dynamic, Eigen::Dynamic> gp_exp_quad_cov(const std::vector> &x, const T_sigma &sigma, const std::vector &length_scale) { - check_positive_finite("gp_exp_quad_cov", "marginal standard deviation", sigma); + check_positive_finite("gp_exp_quad_cov", "marginal standard deviation", + sigma); check_positive_finite("gp_exp_quad_cov", "length scale", length_scale); size_t x_size = x.size(); diff --git a/stan/math/rev/core/accumulate_adjoints.hpp b/stan/math/rev/core/accumulate_adjoints.hpp index a78357a19d0..b86abe6d14c 100644 --- a/stan/math/rev/core/accumulate_adjoints.hpp +++ b/stan/math/rev/core/accumulate_adjoints.hpp @@ -147,22 +147,20 @@ inline double* accumulate_adjoints(double* dest, Arith&& x, Pargs&&... args) { */ inline double* accumulate_adjoints(double* dest) { return dest; } -template * = nullptr> -inline void accumulate_adjoints(const arena_matrix& sum, const T2& summand) { +template * = nullptr> +inline void accumulate_adjoints(const arena_matrix& sum, + const T2& summand) { sum.adj() += summand; } -template * = nullptr> +template * = nullptr> inline void accumulate_adjoints(T1& sum, const T2& summand) { sum.adj() += summand; } -template * = nullptr> +template * = nullptr> inline void accumulate_adjoints(T1& sum, const T2& summand) {} - + } // namespace math } // namespace stan diff --git a/stan/math/rev/fun/determinant.hpp b/stan/math/rev/fun/determinant.hpp index 086ada0daa2..e87b48a0acb 100644 --- a/stan/math/rev/fun/determinant.hpp +++ b/stan/math/rev/fun/determinant.hpp @@ -20,14 +20,13 @@ inline var determinant(const T& m) { double det_val = m.val().determinant(); arena_matrix> arena_m = m; arena_matrix arena_m_inv_t = m.val().inverse().transpose(); - + var det = det_val; reverse_pass_callback([=]() mutable { - arena_m.adj() - += (det.adj() * det_val) * arena_m_inv_t; + arena_m.adj() += (det.adj() * det_val) * arena_m_inv_t; }); - + return det; } diff --git a/stan/math/rev/fun/divide.hpp b/stan/math/rev/fun/divide.hpp index 07edcee933f..244b34ff2c0 100644 --- a/stan/math/rev/fun/divide.hpp +++ b/stan/math/rev/fun/divide.hpp @@ -20,20 +20,18 @@ namespace math { * @param[in] c specified scalar * @return matrix divided by the scalar */ -template * = nullptr, - require_stan_scalar_t* = nullptr, - require_any_st_var* = nullptr> +template * = nullptr, + require_stan_scalar_t* = nullptr, + require_any_st_var* = nullptr> inline Eigen::Matrix divide(const Mat& m, Scal c) { auto arena_m = to_arena_if::value>(m); double invc = 1.0 / value_of(c); - using Mat_v = Eigen::Matrix; - + using Mat_v + = Eigen::Matrix; + arena_matrix res = invc * value_of(m); reverse_pass_callback([=]() mutable { @@ -41,8 +39,8 @@ divide(const Mat& m, Scal c) { accumulate_adjoints(arena_m, invc * res.adj()); } if (!is_constant::value) { - accumulate_adjoints(c, -invc * - (res.adj().array() * res.val().array()).sum()); + accumulate_adjoints( + c, -invc * (res.adj().array() * res.val().array()).sum()); } }); diff --git a/stan/math/rev/fun/dot_self.hpp b/stan/math/rev/fun/dot_self.hpp index 21ae3577f50..23246397913 100644 --- a/stan/math/rev/fun/dot_self.hpp +++ b/stan/math/rev/fun/dot_self.hpp @@ -27,9 +27,8 @@ inline var dot_self(const T& v) { var res = v_val.dot(v_val); - reverse_pass_callback([=]() mutable { - arena_v.adj() += 2.0 * res.adj() * v_val; - }); + reverse_pass_callback( + [=]() mutable { arena_v.adj() += 2.0 * res.adj() * v_val; }); return res; } diff --git a/stan/math/rev/fun/gp_exp_quad_cov.hpp b/stan/math/rev/fun/gp_exp_quad_cov.hpp index f5b213ec81f..e54eeda2b12 100644 --- a/stan/math/rev/fun/gp_exp_quad_cov.hpp +++ b/stan/math/rev/fun/gp_exp_quad_cov.hpp @@ -28,13 +28,12 @@ namespace math { * x is nan or infinite */ template * = nullptr, - require_stan_scalar_t* = nullptr, - require_any_st_var* = nullptr> -inline Eigen::Matrix -gp_exp_quad_cov(const std::vector& x, - T_sigma sigma, - T_l length_scale) { + require_stan_scalar_t* = nullptr, + require_stan_scalar_t* = nullptr, + require_any_st_var* = nullptr> +inline Eigen::Matrix gp_exp_quad_cov(const std::vector& x, + T_sigma sigma, + T_l length_scale) { check_positive("gp_exp_quad_cov", "marginal standard deviation", sigma); check_positive("gp_exp_quad_cov", "length scale", length_scale); for (size_t i = 0; i < x.size(); ++i) { @@ -54,7 +53,8 @@ gp_exp_quad_cov(const std::vector& x, auto arena_x = to_arena_if::value>(x); - double inv_half_sq_l_d = 0.5 / (value_of(length_scale) * value_of(length_scale)); + double inv_half_sq_l_d + = 0.5 / (value_of(length_scale) * value_of(length_scale)); for (size_t j = 0; j < x.size(); ++j) { for (size_t i = 0; i < j; ++i) { double dist_sq = squared_distance(value_of(x[i]), value_of(x[j])); @@ -69,9 +69,8 @@ gp_exp_quad_cov(const std::vector& x, res_val(i, i) = sigma_sq_d; } - arena_matrix> res = res_val; + arena_matrix> res + = res_val; reverse_pass_callback([=]() mutable { Eigen::ArrayXXd adj_times_val = res.adj().array() * res.val().array(); @@ -80,27 +79,28 @@ gp_exp_quad_cov(const std::vector& x, std::cout << res.val() << std::endl << "----" << std::endl; std::cout << adj_times_val << std::endl << "----" << std::endl; std::cout << dist.array() << std::endl << "----" << std::endl;*/ - - if(!is_constant::value) - for(size_t i = 0; i < arena_x.size(); ++i) { - for(size_t j = 0; j < arena_x.size(); ++j) { - auto adj = eval(-(value_of(arena_x[i]) - value_of(arena_x[j])) * - adj_times_val(i, j) / (l_d * l_d)); - //std::cout << "(" << i << ", " << j << ") : " << adj << std::endl; - accumulate_adjoints(arena_x[i], adj); - accumulate_adjoints(arena_x[j], -adj); - } + + if (!is_constant::value) + for (size_t i = 0; i < arena_x.size(); ++i) { + for (size_t j = 0; j < arena_x.size(); ++j) { + auto adj = eval(-(value_of(arena_x[i]) - value_of(arena_x[j])) + * adj_times_val(i, j) / (l_d * l_d)); + // std::cout << "(" << i << ", " << j << ") : " << adj << std::endl; + accumulate_adjoints(arena_x[i], adj); + accumulate_adjoints(arena_x[j], -adj); + } } - - if(!is_constant::value) { + + if (!is_constant::value) { accumulate_adjoints(sigma, 2.0 * adj_times_val.sum() / sigma_d); /*for(size_t i = 0; i < arena_x.size(); ++i) { - sigma - }*/ + sigma + }*/ } - if(!is_constant::value) - accumulate_adjoints(length_scale, (dist.array() * adj_times_val).sum() / (l_d * l_d * l_d)); + if (!is_constant::value) + accumulate_adjoints(length_scale, (dist.array() * adj_times_val).sum() + / (l_d * l_d * l_d)); }); return res; diff --git a/stan/math/rev/fun/tcrossprod.hpp b/stan/math/rev/fun/tcrossprod.hpp index c2016d289dc..c8a10289426 100644 --- a/stan/math/rev/fun/tcrossprod.hpp +++ b/stan/math/rev/fun/tcrossprod.hpp @@ -38,8 +38,7 @@ tcrossprod(const T& M) { M.rows()); for (int m = 0; m < M.rows(); ++m) { - MMt.coeffRef(m, m) - = dot_self(M.row(m)); + MMt.coeffRef(m, m) = dot_self(M.row(m)); } for (int m = 0; m < M.rows(); ++m) { for (int n = 0; n < m; ++n) { diff --git a/test/unit/math/rev/fun/gp_exp_quad_cov_test.cpp b/test/unit/math/rev/fun/gp_exp_quad_cov_test.cpp index 1ac74330ce4..6b13c277cb3 100644 --- a/test/unit/math/rev/fun/gp_exp_quad_cov_test.cpp +++ b/test/unit/math/rev/fun/gp_exp_quad_cov_test.cpp @@ -1350,4 +1350,3 @@ TEST(AgradRevMatrix, gp_exp_quad_cov_check_varis_on_stack) { test::check_varis_on_stack(stan::math::gp_exp_quad_cov(x, to_var(sigma), l)); test::check_varis_on_stack(stan::math::gp_exp_quad_cov(x, sigma, to_var(l))); } - From eeac6c6d274ef1c2d59eef9fe2b1493fd9e84e5b Mon Sep 17 00:00:00 2001 From: Ben Date: Tue, 18 Aug 2020 18:32:39 -0400 Subject: [PATCH 215/355] Changed forward_as to avoid needing new accumulate adjoints function. Made adj() accessor in var not respect const (Issue #2018) --- stan/math/prim/meta/forward_as.hpp | 15 +++++++--- stan/math/rev/core/accumulate_adjoints.hpp | 16 ----------- stan/math/rev/core/var.hpp | 14 ++------- stan/math/rev/fun/determinant.hpp | 5 ++-- stan/math/rev/fun/divide.hpp | 8 +++--- stan/math/rev/fun/gp_exp_quad_cov.hpp | 33 ++++++++-------------- 6 files changed, 31 insertions(+), 60 deletions(-) diff --git a/stan/math/prim/meta/forward_as.hpp b/stan/math/prim/meta/forward_as.hpp index 3cdab43fb4d..66a90b439b1 100644 --- a/stan/math/prim/meta/forward_as.hpp +++ b/stan/math/prim/meta/forward_as.hpp @@ -32,7 +32,8 @@ constexpr bool eigen_static_size_match(T1 desired, T2 actual) { */ template ::value + = std::enable_if_t, + std::decay_t>::value && !is_eigen::value>> inline T_actual&& forward_as(T_actual&& a) { // NOLINT return std::forward(a); @@ -56,7 +57,9 @@ inline T_actual&& forward_as(T_actual&& a) { // NOLINT */ template ::value>> + = std::enable_if_t, + std::decay>::value + && !is_eigen::value>> inline T_desired forward_as(const T_actual& a) { throw std::runtime_error("Wrong type assumed! Please file a bug report."); } @@ -79,6 +82,8 @@ template < typename T_desired, typename T_actual, typename = std::enable_if_t< std::is_same, value_type_t>::value + && is_eigen::value + && is_eigen::value && internal::eigen_static_size_match( T_desired::RowsAtCompileTime, std::decay_t::RowsAtCompileTime) @@ -109,13 +114,15 @@ inline T_actual&& forward_as(T_actual&& a) { // NOLINT template < typename T_desired, typename T_actual, typename = std::enable_if_t< - !std::is_same, value_type_t>::value + is_eigen::value + && is_eigen::value + && (!std::is_same, value_type_t>::value || !internal::eigen_static_size_match( T_desired::RowsAtCompileTime, std::decay_t::RowsAtCompileTime) || !internal::eigen_static_size_match( T_desired::ColsAtCompileTime, - std::decay_t::ColsAtCompileTime)>, + std::decay_t::ColsAtCompileTime))>, typename = void> inline T_desired forward_as(const T_actual& a) { throw std::runtime_error("Wrong type assumed! Please file a bug report."); diff --git a/stan/math/rev/core/accumulate_adjoints.hpp b/stan/math/rev/core/accumulate_adjoints.hpp index a78357a19d0..19500ff65ec 100644 --- a/stan/math/rev/core/accumulate_adjoints.hpp +++ b/stan/math/rev/core/accumulate_adjoints.hpp @@ -146,22 +146,6 @@ inline double* accumulate_adjoints(double* dest, Arith&& x, Pargs&&... args) { * @param dest Pointer */ inline double* accumulate_adjoints(double* dest) { return dest; } - -template * = nullptr> -inline void accumulate_adjoints(const arena_matrix& sum, const T2& summand) { - sum.adj() += summand; -} - -template * = nullptr> -inline void accumulate_adjoints(T1& sum, const T2& summand) { - sum.adj() += summand; -} - -template * = nullptr> -inline void accumulate_adjoints(T1& sum, const T2& summand) {} } // namespace math } // namespace stan diff --git a/stan/math/rev/core/var.hpp b/stan/math/rev/core/var.hpp index 482d6652b92..2e3330f36a5 100644 --- a/stan/math/rev/core/var.hpp +++ b/stan/math/rev/core/var.hpp @@ -102,24 +102,14 @@ class var_value { inline const auto& val() const { return vi_->val_; } /** - * Return a const reference of the derivative of the root expression with + * Return a reference of the derivative of the root expression with * respect to this expression. This method only works * after one of the `grad()` methods has been * called. * * @return Adjoint for this variable. */ - inline const auto& adj() const { return vi_->adj_; } - - /** - * Return a reference to the derivative of the root expression with - * respect to this expression. This method only works - * after one of the `grad()` methods has been - * called. - * - * @return Adjoint for this variable. - */ - inline auto& adj() { return vi_->adj_; } + inline auto& adj() const { return vi_->adj_; } /** * Compute the gradient of this (dependent) variable with respect to diff --git a/stan/math/rev/fun/determinant.hpp b/stan/math/rev/fun/determinant.hpp index 086ada0daa2..cc398662ecc 100644 --- a/stan/math/rev/fun/determinant.hpp +++ b/stan/math/rev/fun/determinant.hpp @@ -17,9 +17,10 @@ inline var determinant(const T& m) { return 1; } - double det_val = m.val().determinant(); + arena_matrix m_val = m.val(); + double det_val = m_val.determinant(); arena_matrix> arena_m = m; - arena_matrix arena_m_inv_t = m.val().inverse().transpose(); + arena_matrix arena_m_inv_t = m_val.inverse().transpose(); var det = det_val; diff --git a/stan/math/rev/fun/divide.hpp b/stan/math/rev/fun/divide.hpp index 07edcee933f..38cc9166710 100644 --- a/stan/math/rev/fun/divide.hpp +++ b/stan/math/rev/fun/divide.hpp @@ -25,7 +25,7 @@ template * = nullptr, require_any_st_var* = nullptr> inline Eigen::Matrix -divide(const Mat& m, Scal c) { +divide(const Mat& m, const Scal& c) { auto arena_m = to_arena_if::value>(m); double invc = 1.0 / value_of(c); @@ -38,11 +38,11 @@ divide(const Mat& m, Scal c) { reverse_pass_callback([=]() mutable { if (!is_constant::value) { - accumulate_adjoints(arena_m, invc * res.adj()); + forward_as(arena_m).adj() += invc * res.adj(); } if (!is_constant::value) { - accumulate_adjoints(c, -invc * - (res.adj().array() * res.val().array()).sum()); + forward_as(c).adj() += -invc * + (res.adj().array() * res.val().array()).sum(); } }); diff --git a/stan/math/rev/fun/gp_exp_quad_cov.hpp b/stan/math/rev/fun/gp_exp_quad_cov.hpp index f5b213ec81f..3f1c96cad50 100644 --- a/stan/math/rev/fun/gp_exp_quad_cov.hpp +++ b/stan/math/rev/fun/gp_exp_quad_cov.hpp @@ -28,8 +28,7 @@ namespace math { * x is nan or infinite */ template * = nullptr, - require_stan_scalar_t* = nullptr, + require_all_stan_scalar_t* = nullptr, require_any_st_var* = nullptr> inline Eigen::Matrix gp_exp_quad_cov(const std::vector& x, @@ -58,10 +57,8 @@ gp_exp_quad_cov(const std::vector& x, for (size_t j = 0; j < x.size(); ++j) { for (size_t i = 0; i < j; ++i) { double dist_sq = squared_distance(value_of(x[i]), value_of(x[j])); - dist(i, j) = dist_sq; - res_val(i, j) = sigma_sq_d * std::exp(-dist_sq * inv_half_sq_l_d); - res_val(j, i) = res_val(i, j); - dist(j, i) = dist(i, j); + dist.coeffRef(i, j) = dist.coeffRef(j, i) = dist_sq; + res_val.coeffRef(i, j) = res_val.coeffRef(j, i) = sigma_sq_d * std::exp(-dist_sq * inv_half_sq_l_d); } } for (size_t i = 0; i < x.size(); ++i) { @@ -76,31 +73,23 @@ gp_exp_quad_cov(const std::vector& x, reverse_pass_callback([=]() mutable { Eigen::ArrayXXd adj_times_val = res.adj().array() * res.val().array(); - /*std::cout << res.adj() << std::endl << "----" << std::endl; - std::cout << res.val() << std::endl << "----" << std::endl; - std::cout << adj_times_val << std::endl << "----" << std::endl; - std::cout << dist.array() << std::endl << "----" << std::endl;*/ - if(!is_constant::value) for(size_t i = 0; i < arena_x.size(); ++i) { for(size_t j = 0; j < arena_x.size(); ++j) { auto adj = eval(-(value_of(arena_x[i]) - value_of(arena_x[j])) * adj_times_val(i, j) / (l_d * l_d)); - //std::cout << "(" << i << ", " << j << ") : " << adj << std::endl; - accumulate_adjoints(arena_x[i], adj); - accumulate_adjoints(arena_x[j], -adj); + using T_x_var = promote_scalar_t; + forward_as(arena_x[i]).adj() += adj; + forward_as(arena_x[j]).adj() -= adj; } } - - if(!is_constant::value) { - accumulate_adjoints(sigma, 2.0 * adj_times_val.sum() / sigma_d); - /*for(size_t i = 0; i < arena_x.size(); ++i) { - sigma - }*/ - } + + if(!is_constant::value) + forward_as(sigma).adj() += 2.0 * adj_times_val.sum() / sigma_d; if(!is_constant::value) - accumulate_adjoints(length_scale, (dist.array() * adj_times_val).sum() / (l_d * l_d * l_d)); + forward_as(length_scale).adj() += + (dist.array() * adj_times_val).sum() / (l_d * l_d * l_d); }); return res; From 094ba39575ffc405ad0c02c45d8c8c0aefab0c6b Mon Sep 17 00:00:00 2001 From: Stan Jenkins Date: Tue, 18 Aug 2020 22:53:23 +0000 Subject: [PATCH 216/355] [Jenkins] auto-formatting by clang-format version 6.0.0-1ubuntu2~16.04.1 (tags/RELEASE_600/final) --- stan/math/prim/meta/forward_as.hpp | 37 +++++++++----------- stan/math/rev/core/accumulate_adjoints.hpp | 2 +- stan/math/rev/fun/divide.hpp | 4 +-- stan/math/rev/fun/gp_exp_quad_cov.hpp | 40 +++++++++++----------- 4 files changed, 40 insertions(+), 43 deletions(-) diff --git a/stan/math/prim/meta/forward_as.hpp b/stan/math/prim/meta/forward_as.hpp index 756ebc705fe..032047bb5d1 100644 --- a/stan/math/prim/meta/forward_as.hpp +++ b/stan/math/prim/meta/forward_as.hpp @@ -32,7 +32,7 @@ constexpr bool eigen_static_size_match(T1 desired, T2 actual) { template , - std::decay_t>::value + std::decay_t>::value && !is_eigen::value>> inline T_actual&& forward_as(T_actual&& a) { // NOLINT return std::forward(a); @@ -55,10 +55,9 @@ inline T_actual&& forward_as(T_actual&& a) { // NOLINT * @throw always throws std::runtime_error */ template , - std::decay>::value - && !is_eigen::value>> + typename = std::enable_if_t< + !std::is_same, std::decay>::value + && !is_eigen::value>> inline T_desired forward_as(const T_actual& a) { throw std::runtime_error("Wrong type assumed! Please file a bug report."); } @@ -81,8 +80,7 @@ template < typename T_desired, typename T_actual, typename = std::enable_if_t< std::is_same, value_type_t>::value - && is_eigen::value - && is_eigen::value + && is_eigen::value && is_eigen::value && internal::eigen_static_size_match( T_desired::RowsAtCompileTime, std::decay_t::RowsAtCompileTime) @@ -110,19 +108,18 @@ inline T_actual&& forward_as(T_actual&& a) { // NOLINT * @return nothing, this always throws * @throw always throws std::runtime_error */ -template < - typename T_desired, typename T_actual, - typename = std::enable_if_t< - is_eigen::value - && is_eigen::value - && (!std::is_same, value_type_t>::value - || !internal::eigen_static_size_match( - T_desired::RowsAtCompileTime, - std::decay_t::RowsAtCompileTime) - || !internal::eigen_static_size_match( - T_desired::ColsAtCompileTime, - std::decay_t::ColsAtCompileTime))>, - typename = void> +template ::value && is_eigen::value + && (!std::is_same, + value_type_t>::value + || !internal::eigen_static_size_match( + T_desired::RowsAtCompileTime, + std::decay_t::RowsAtCompileTime) + || !internal::eigen_static_size_match( + T_desired::ColsAtCompileTime, + std::decay_t::ColsAtCompileTime))>, + typename = void> inline T_desired forward_as(const T_actual& a) { throw std::runtime_error("Wrong type assumed! Please file a bug report."); } diff --git a/stan/math/rev/core/accumulate_adjoints.hpp b/stan/math/rev/core/accumulate_adjoints.hpp index 19500ff65ec..e5b27354ebd 100644 --- a/stan/math/rev/core/accumulate_adjoints.hpp +++ b/stan/math/rev/core/accumulate_adjoints.hpp @@ -146,7 +146,7 @@ inline double* accumulate_adjoints(double* dest, Arith&& x, Pargs&&... args) { * @param dest Pointer */ inline double* accumulate_adjoints(double* dest) { return dest; } - + } // namespace math } // namespace stan diff --git a/stan/math/rev/fun/divide.hpp b/stan/math/rev/fun/divide.hpp index 9fb9054a6d6..30e130ddcd7 100644 --- a/stan/math/rev/fun/divide.hpp +++ b/stan/math/rev/fun/divide.hpp @@ -39,8 +39,8 @@ divide(const Mat& m, const Scal& c) { forward_as(arena_m).adj() += invc * res.adj(); } if (!is_constant::value) { - forward_as(c).adj() += -invc * - (res.adj().array() * res.val().array()).sum(); + forward_as(c).adj() + += -invc * (res.adj().array() * res.val().array()).sum(); } }); diff --git a/stan/math/rev/fun/gp_exp_quad_cov.hpp b/stan/math/rev/fun/gp_exp_quad_cov.hpp index 6c257eb2c37..a1931a0f4fa 100644 --- a/stan/math/rev/fun/gp_exp_quad_cov.hpp +++ b/stan/math/rev/fun/gp_exp_quad_cov.hpp @@ -28,12 +28,11 @@ namespace math { * x is nan or infinite */ template * = nullptr, - require_any_st_var* = nullptr> -inline Eigen::Matrix -gp_exp_quad_cov(const std::vector& x, - T_sigma sigma, - T_l length_scale) { + require_all_stan_scalar_t* = nullptr, + require_any_st_var* = nullptr> +inline Eigen::Matrix gp_exp_quad_cov(const std::vector& x, + T_sigma sigma, + T_l length_scale) { check_positive("gp_exp_quad_cov", "marginal standard deviation", sigma); check_positive("gp_exp_quad_cov", "length scale", length_scale); for (size_t i = 0; i < x.size(); ++i) { @@ -59,7 +58,8 @@ gp_exp_quad_cov(const std::vector& x, for (size_t i = 0; i < j; ++i) { double dist_sq = squared_distance(value_of(x[i]), value_of(x[j])); dist.coeffRef(i, j) = dist.coeffRef(j, i) = dist_sq; - res_val.coeffRef(i, j) = res_val.coeffRef(j, i) = sigma_sq_d * std::exp(-dist_sq * inv_half_sq_l_d); + res_val.coeffRef(i, j) = res_val.coeffRef(j, i) + = sigma_sq_d * std::exp(-dist_sq * inv_half_sq_l_d); } } for (size_t i = 0; i < x.size(); ++i) { @@ -73,23 +73,23 @@ gp_exp_quad_cov(const std::vector& x, reverse_pass_callback([=]() mutable { Eigen::ArrayXXd adj_times_val = res.adj().array() * res.val().array(); - if(!is_constant::value) - for(size_t i = 0; i < arena_x.size(); ++i) { - for(size_t j = 0; j < arena_x.size(); ++j) { - auto adj = eval(-(value_of(arena_x[i]) - value_of(arena_x[j])) * - adj_times_val(i, j) / (l_d * l_d)); - using T_x_var = promote_scalar_t; - forward_as(arena_x[i]).adj() += adj; - forward_as(arena_x[j]).adj() -= adj; - } + if (!is_constant::value) + for (size_t i = 0; i < arena_x.size(); ++i) { + for (size_t j = 0; j < arena_x.size(); ++j) { + auto adj = eval(-(value_of(arena_x[i]) - value_of(arena_x[j])) + * adj_times_val(i, j) / (l_d * l_d)); + using T_x_var = promote_scalar_t; + forward_as(arena_x[i]).adj() += adj; + forward_as(arena_x[j]).adj() -= adj; + } } - if(!is_constant::value) + if (!is_constant::value) forward_as(sigma).adj() += 2.0 * adj_times_val.sum() / sigma_d; - if(!is_constant::value) - forward_as(length_scale).adj() += - (dist.array() * adj_times_val).sum() / (l_d * l_d * l_d); + if (!is_constant::value) + forward_as(length_scale).adj() + += (dist.array() * adj_times_val).sum() / (l_d * l_d * l_d); }); return res; From 66525b92cd8d03e5c45f3716cf168f5183575bc7 Mon Sep 17 00:00:00 2001 From: Ben Date: Wed, 19 Aug 2020 00:13:10 -0400 Subject: [PATCH 217/355] Added autodiff for cols_dot_product and rows_dot_product (Issue #2018) --- stan/math/rev/fun/columns_dot_product.hpp | 50 ++++++++++++++++++++--- stan/math/rev/fun/determinant.hpp | 2 + stan/math/rev/fun/gp_exp_quad_cov.hpp | 2 + stan/math/rev/fun/rows_dot_product.hpp | 48 +++++++++++++++++++--- 4 files changed, 90 insertions(+), 12 deletions(-) diff --git a/stan/math/rev/fun/columns_dot_product.hpp b/stan/math/rev/fun/columns_dot_product.hpp index 79704e4363d..2329e9c7fe2 100644 --- a/stan/math/rev/fun/columns_dot_product.hpp +++ b/stan/math/rev/fun/columns_dot_product.hpp @@ -6,7 +6,8 @@ #include #include #include -#include +#include +#include #include #include @@ -19,12 +20,49 @@ template * = nullptr> inline Eigen::Matrix, 1, Mat1::ColsAtCompileTime> columns_dot_product(const Mat1& v1, const Mat2& v2) { - check_matching_sizes("dot_product", "v1", v1, "v2", v2); - Eigen::Matrix ret(1, v1.cols()); - for (size_type j = 0; j < v1.cols(); ++j) { - ret.coeffRef(j) = dot_product(v1.col(j), v2.col(j)); + check_matching_sizes("columns_dot_product", "v1", v1, "v2", v2); + + ref_type_t v1_ref = v1; + ref_type_t v2_ref = v2; + + using Mat1_double = plain_type_t; + using Mat1_var = promote_scalar_t; + + using Mat2_double = plain_type_t; + using Mat2_var = promote_scalar_t; + + arena_matrix arena_v1_val = value_of(v1_ref); + arena_matrix arena_v2_val = value_of(v2_ref); + + arena_matrix arena_v1; + arena_matrix arena_v2; + + if(!is_constant::value) { + arena_v1 = v1_ref; + } + + if(!is_constant::value) { + arena_v2 = v2_ref; } - return ret; + + Eigen::RowVectorXd out_val(arena_v1_val.cols()); + for(size_t m = 0; m < arena_v1_val.cols(); ++m) + out_val.coeffRef(m) = arena_v1_val.col(m).dot(arena_v2_val.col(m)); + + arena_matrix> out = out_val; + + reverse_pass_callback([out, arena_v1, arena_v2, + arena_v1_val, arena_v2_val]() mutable { + Eigen::RowVectorXd adj = out.adj(); + + if(!is_constant::value) + arena_v1.adj() += arena_v2_val * adj.asDiagonal(); + + if(!is_constant::value) + arena_v2.adj() += arena_v1_val * adj.asDiagonal(); + }); + + return out; } } // namespace math diff --git a/stan/math/rev/fun/determinant.hpp b/stan/math/rev/fun/determinant.hpp index 4e11180723e..385195600b7 100644 --- a/stan/math/rev/fun/determinant.hpp +++ b/stan/math/rev/fun/determinant.hpp @@ -3,6 +3,8 @@ #include #include +#include +#include #include #include #include diff --git a/stan/math/rev/fun/gp_exp_quad_cov.hpp b/stan/math/rev/fun/gp_exp_quad_cov.hpp index 6c257eb2c37..a22327852a5 100644 --- a/stan/math/rev/fun/gp_exp_quad_cov.hpp +++ b/stan/math/rev/fun/gp_exp_quad_cov.hpp @@ -4,6 +4,8 @@ #include #include #include +#include +#include #include #include #include diff --git a/stan/math/rev/fun/rows_dot_product.hpp b/stan/math/rev/fun/rows_dot_product.hpp index 7ea19034adf..65191b82a46 100644 --- a/stan/math/rev/fun/rows_dot_product.hpp +++ b/stan/math/rev/fun/rows_dot_product.hpp @@ -4,7 +4,6 @@ #include #include #include -#include #include #include #include @@ -17,12 +16,49 @@ template * = nullptr> inline Eigen::Matrix rows_dot_product( const Mat1& v1, const Mat2& v2) { - check_matching_sizes("dot_product", "v1", v1, "v2", v2); - Eigen::Matrix ret(v1.rows(), 1); - for (size_type j = 0; j < v1.rows(); ++j) { - ret.coeffRef(j) = dot_product(v1.row(j), v2.row(j)); + check_matching_sizes("rows_dot_product", "v1", v1, "v2", v2); + + ref_type_t v1_ref = v1; + ref_type_t v2_ref = v2; + + using Mat1_double = plain_type_t; + using Mat1_var = promote_scalar_t; + + using Mat2_double = plain_type_t; + using Mat2_var = promote_scalar_t; + + arena_matrix arena_v1_val = value_of(v1_ref); + arena_matrix arena_v2_val = value_of(v2_ref); + + arena_matrix arena_v1; + arena_matrix arena_v2; + + if(!is_constant::value) { + arena_v1 = v1_ref; + } + + if(!is_constant::value) { + arena_v2 = v2_ref; } - return ret; + + Eigen::VectorXd out_val(arena_v1_val.rows()); + for(size_t m = 0; m < arena_v1_val.rows(); ++m) + out_val.coeffRef(m) = arena_v1_val.row(m).dot(arena_v2_val.row(m)); + + arena_matrix> out = out_val; + + reverse_pass_callback([out, arena_v1, arena_v2, + arena_v1_val, arena_v2_val]() mutable { + Eigen::VectorXd adj = out.adj(); + + if(!is_constant::value) + arena_v1.adj() += adj.asDiagonal() * arena_v2_val; + + if(!is_constant::value) + arena_v2.adj() += adj.asDiagonal() * arena_v1_val; + }); + + return out; } } // namespace math From afd36c458ba624d605e09c4a1cc128b9b1968f1d Mon Sep 17 00:00:00 2001 From: Stan Jenkins Date: Wed, 19 Aug 2020 04:14:29 +0000 Subject: [PATCH 218/355] [Jenkins] auto-formatting by clang-format version 6.0.0-1ubuntu2~16.04.1 (tags/RELEASE_600/final) --- stan/math/rev/fun/columns_dot_product.hpp | 24 +++++++++++------------ stan/math/rev/fun/rows_dot_product.hpp | 24 +++++++++++------------ 2 files changed, 24 insertions(+), 24 deletions(-) diff --git a/stan/math/rev/fun/columns_dot_product.hpp b/stan/math/rev/fun/columns_dot_product.hpp index 2329e9c7fe2..72f98105653 100644 --- a/stan/math/rev/fun/columns_dot_product.hpp +++ b/stan/math/rev/fun/columns_dot_product.hpp @@ -24,7 +24,7 @@ columns_dot_product(const Mat1& v1, const Mat2& v2) { ref_type_t v1_ref = v1; ref_type_t v2_ref = v2; - + using Mat1_double = plain_type_t; using Mat1_var = promote_scalar_t; @@ -37,30 +37,30 @@ columns_dot_product(const Mat1& v1, const Mat2& v2) { arena_matrix arena_v1; arena_matrix arena_v2; - if(!is_constant::value) { + if (!is_constant::value) { arena_v1 = v1_ref; } - if(!is_constant::value) { + if (!is_constant::value) { arena_v2 = v2_ref; } Eigen::RowVectorXd out_val(arena_v1_val.cols()); - for(size_t m = 0; m < arena_v1_val.cols(); ++m) + for (size_t m = 0; m < arena_v1_val.cols(); ++m) out_val.coeffRef(m) = arena_v1_val.col(m).dot(arena_v2_val.col(m)); arena_matrix> out = out_val; - reverse_pass_callback([out, arena_v1, arena_v2, - arena_v1_val, arena_v2_val]() mutable { - Eigen::RowVectorXd adj = out.adj(); + reverse_pass_callback( + [out, arena_v1, arena_v2, arena_v1_val, arena_v2_val]() mutable { + Eigen::RowVectorXd adj = out.adj(); - if(!is_constant::value) - arena_v1.adj() += arena_v2_val * adj.asDiagonal(); + if (!is_constant::value) + arena_v1.adj() += arena_v2_val * adj.asDiagonal(); - if(!is_constant::value) - arena_v2.adj() += arena_v1_val * adj.asDiagonal(); - }); + if (!is_constant::value) + arena_v2.adj() += arena_v1_val * adj.asDiagonal(); + }); return out; } diff --git a/stan/math/rev/fun/rows_dot_product.hpp b/stan/math/rev/fun/rows_dot_product.hpp index 65191b82a46..5f010b21650 100644 --- a/stan/math/rev/fun/rows_dot_product.hpp +++ b/stan/math/rev/fun/rows_dot_product.hpp @@ -20,7 +20,7 @@ inline Eigen::Matrix rows_dot_product( ref_type_t v1_ref = v1; ref_type_t v2_ref = v2; - + using Mat1_double = plain_type_t; using Mat1_var = promote_scalar_t; @@ -33,30 +33,30 @@ inline Eigen::Matrix rows_dot_product( arena_matrix arena_v1; arena_matrix arena_v2; - if(!is_constant::value) { + if (!is_constant::value) { arena_v1 = v1_ref; } - if(!is_constant::value) { + if (!is_constant::value) { arena_v2 = v2_ref; } Eigen::VectorXd out_val(arena_v1_val.rows()); - for(size_t m = 0; m < arena_v1_val.rows(); ++m) + for (size_t m = 0; m < arena_v1_val.rows(); ++m) out_val.coeffRef(m) = arena_v1_val.row(m).dot(arena_v2_val.row(m)); arena_matrix> out = out_val; - reverse_pass_callback([out, arena_v1, arena_v2, - arena_v1_val, arena_v2_val]() mutable { - Eigen::VectorXd adj = out.adj(); + reverse_pass_callback( + [out, arena_v1, arena_v2, arena_v1_val, arena_v2_val]() mutable { + Eigen::VectorXd adj = out.adj(); - if(!is_constant::value) - arena_v1.adj() += adj.asDiagonal() * arena_v2_val; + if (!is_constant::value) + arena_v1.adj() += adj.asDiagonal() * arena_v2_val; - if(!is_constant::value) - arena_v2.adj() += adj.asDiagonal() * arena_v1_val; - }); + if (!is_constant::value) + arena_v2.adj() += adj.asDiagonal() * arena_v1_val; + }); return out; } From 91a6bb9b7e1f95e5a7cb35f09fcc90f5e389f8ed Mon Sep 17 00:00:00 2001 From: Ben Date: Wed, 19 Aug 2020 19:11:29 -0400 Subject: [PATCH 219/355] More functions converted to reverse_pass_callback (Issue #2018) --- stan/math/prim/fun/gp_periodic_cov.hpp | 3 +- stan/math/rev/fun/columns_dot_product.hpp | 14 +- stan/math/rev/fun/gp_exp_quad_cov.hpp | 6 +- stan/math/rev/fun/gp_periodic_cov.hpp | 416 ++++-------------- .../fun/multiply_lower_tri_self_transpose.hpp | 57 +-- stan/math/rev/fun/rows_dot_product.hpp | 14 +- stan/math/rev/fun/tcrossprod.hpp | 26 +- 7 files changed, 134 insertions(+), 402 deletions(-) diff --git a/stan/math/prim/fun/gp_periodic_cov.hpp b/stan/math/prim/fun/gp_periodic_cov.hpp index ae63bbbb176..e16c1a20c0f 100644 --- a/stan/math/prim/fun/gp_periodic_cov.hpp +++ b/stan/math/prim/fun/gp_periodic_cov.hpp @@ -41,7 +41,8 @@ namespace math { * @throw std::domain_error if sigma <= 0, l <= 0, p <= 0 or * x is nan or infinite */ -template +template > inline typename Eigen::Matrix, Eigen::Dynamic, Eigen::Dynamic> gp_periodic_cov(const std::vector &x, const T_sigma &sigma, const T_l &l, diff --git a/stan/math/rev/fun/columns_dot_product.hpp b/stan/math/rev/fun/columns_dot_product.hpp index 72f98105653..f93365615bc 100644 --- a/stan/math/rev/fun/columns_dot_product.hpp +++ b/stan/math/rev/fun/columns_dot_product.hpp @@ -25,17 +25,11 @@ columns_dot_product(const Mat1& v1, const Mat2& v2) { ref_type_t v1_ref = v1; ref_type_t v2_ref = v2; - using Mat1_double = plain_type_t; - using Mat1_var = promote_scalar_t; + arena_matrix> arena_v1_val = value_of(v1_ref); + arena_matrix> arena_v2_val = value_of(v2_ref); - using Mat2_double = plain_type_t; - using Mat2_var = promote_scalar_t; - - arena_matrix arena_v1_val = value_of(v1_ref); - arena_matrix arena_v2_val = value_of(v2_ref); - - arena_matrix arena_v1; - arena_matrix arena_v2; + arena_matrix> arena_v1; + arena_matrix> arena_v2; if (!is_constant::value) { arena_v1 = v1_ref; diff --git a/stan/math/rev/fun/gp_exp_quad_cov.hpp b/stan/math/rev/fun/gp_exp_quad_cov.hpp index 46dd6ad1e5f..968a8d3b806 100644 --- a/stan/math/rev/fun/gp_exp_quad_cov.hpp +++ b/stan/math/rev/fun/gp_exp_quad_cov.hpp @@ -42,7 +42,7 @@ inline Eigen::Matrix gp_exp_quad_cov(const std::vector& x, } if (x.size() == 0) { - return Eigen::Matrix(); + return Eigen::Matrix(); } double l_d = value_of(length_scale); @@ -78,8 +78,8 @@ inline Eigen::Matrix gp_exp_quad_cov(const std::vector& x, if (!is_constant::value) for (size_t i = 0; i < arena_x.size(); ++i) { for (size_t j = 0; j < arena_x.size(); ++j) { - auto adj = eval(-(value_of(arena_x[i]) - value_of(arena_x[j])) - * adj_times_val(i, j) / (l_d * l_d)); + auto adj = eval(-(value_of(arena_x[i]) - value_of(arena_x[j])) * + adj_times_val(i, j) / (l_d * l_d)); using T_x_var = promote_scalar_t; forward_as(arena_x[i]).adj() += adj; forward_as(arena_x[j]).adj() -= adj; diff --git a/stan/math/rev/fun/gp_periodic_cov.hpp b/stan/math/rev/fun/gp_periodic_cov.hpp index a592e316cb6..90f7cd9c94b 100644 --- a/stan/math/rev/fun/gp_periodic_cov.hpp +++ b/stan/math/rev/fun/gp_periodic_cov.hpp @@ -4,6 +4,8 @@ #include #include #include +#include +#include #include #include #include @@ -16,270 +18,6 @@ namespace stan { namespace math { -/** - * This is a subclass of the vari class for precomputed - * gradients of gp_periodic_cov. - * - * The class stores the double values for the distance - * matrix, sine, cosine and sine squared of the latter, - * pointers to the varis for the covariance - * matrix, along with a pointer to the vari for sigma, - * the vari for l and the vari for p. - * - * The elements of periodic covariance matrix \f$ \mathbf{K} \f$ using the - * input \f$ \mathbf{X} \f$ are defined as - * \f$ \mathbf{K}_{ij} = k(\mathbf{X}_i,\mathbf{X}_j), \f$ where - * \f$ \mathbf{X}_i \f$ is the \f$i\f$-th row of \f$ \mathbf{X} \f$ and \n - * \f$ k(\mathbf{x},\mathbf{x}^\prime) = - * \sigma^2 \exp\left(-\frac{2\sin^2(\pi - * |\mathbf{x}-\mathbf{x}^\prime|/p)}{\ell^2}\right), \f$ \n where \f$ \sigma^2 - * \f$, \f$ \ell \f$ and \f$ p \f$ are the signal variance, length-scale and - * period. - * - * The partial derivatives w.r.t. the parameters are the following:\n - * - * \f$ \frac{\partial k}{\partial \sigma} = \frac{2k}{\sigma} \f$\n - * \f$ \frac{\partial k}{\partial \ell} = \frac{4k}{\ell^3} - * \sin^2(\pi|\mathbf{x}-\mathbf{x}^\prime|/p) \f$\n \f$ \frac{\partial - * k}{\partial p} = \frac{2k\pi|\mathbf{x}-\mathbf{x}^\prime|}{\ell^2p^2} - * \sin(2\pi|\mathbf{x}-\mathbf{x}^\prime|/p) \f$\n - * - * @tparam T_x type of std::vector elements of x. - * T_x can be a scalar, an Eigen::Vector, or an Eigen::RowVector. - * @tparam T_sigma type of sigma - * @tparam T_l type of length-scale - * @tparam T_p type of period - */ -template -class gp_periodic_cov_vari : public vari { - public: - const size_t size_; - const size_t size_ltri_; - const double l_d_; - const double sigma_d_; - const double p_d_; - const double sigma_sq_d_; - double *dist_; - double *sin_2_dist_; - double *sin_dist_sq_; - vari *l_vari_; - vari *sigma_vari_; - vari *p_vari_; - vari **cov_lower_; - vari **cov_diag_; - - /** - * Constructor for gp_periodic_cov. - * - * All memory allocated in - * ChainableStack's stack_alloc arena. - * - * It is critical for the efficiency of this object - * that the constructor create new varis that aren't - * popped onto the var_stack_, but rather are - * popped onto the var_nochain_stack_. This is - * controlled by the second argument to - * vari's constructor. - * - * @param x std::vector of input elements. - * Assumes that all elements of x have the same size. - * @param sigma standard deviation of the signal - * @param l length-scale - * @param p period - */ - gp_periodic_cov_vari(const std::vector &x, const T_sigma &sigma, - const T_l &l, const T_p &p) - : vari(0.0), - size_(x.size()), - size_ltri_(size_ * (size_ - 1) / 2), - l_d_(value_of(l)), - sigma_d_(value_of(sigma)), - p_d_(value_of(p)), - sigma_sq_d_(sigma_d_ * sigma_d_), - dist_(ChainableStack::instance_->memalloc_.alloc_array( - size_ltri_)), - sin_2_dist_(ChainableStack::instance_->memalloc_.alloc_array( - size_ltri_)), - sin_dist_sq_(ChainableStack::instance_->memalloc_.alloc_array( - size_ltri_)), - l_vari_(l.vi_), - sigma_vari_(sigma.vi_), - p_vari_(p.vi_), - cov_lower_(ChainableStack::instance_->memalloc_.alloc_array( - size_ltri_)), - cov_diag_( - ChainableStack::instance_->memalloc_.alloc_array(size_)) { - using std::sin; - double neg_two_inv_l_sq = -2.0 / (l_d_ * l_d_); - double pi_div_p = pi() / p_d_; - - size_t pos = 0; - for (size_t j = 0; j < size_; ++j) { - for (size_t i = j + 1; i < size_; ++i) { - double dist = distance(x[i], x[j]); - double sin_dist = sin(pi_div_p * dist); - double sin_dist_sq = square(sin_dist); - dist_[pos] = dist; - sin_2_dist_[pos] = sin(2.0 * pi_div_p * dist); - sin_dist_sq_[pos] = sin_dist_sq; - cov_lower_[pos] = new vari( - sigma_sq_d_ * std::exp(sin_dist_sq * neg_two_inv_l_sq), false); - ++pos; - } - cov_diag_[j] = new vari(sigma_sq_d_, false); - } - } - - virtual void chain() { - double adjl = 0; - double adjsigma = 0; - double adjp = 0; - - for (size_t i = 0; i < size_ltri_; ++i) { - vari *el_low = cov_lower_[i]; - double prod_add = el_low->adj_ * el_low->val_; - adjl += prod_add * sin_dist_sq_[i]; - adjsigma += prod_add; - adjp += prod_add * sin_2_dist_[i] * dist_[i]; - } - for (size_t i = 0; i < size_; ++i) { - vari *el = cov_diag_[i]; - adjsigma += el->adj_ * el->val_; - } - double l_d_sq = l_d_ * l_d_; - l_vari_->adj_ += adjl * 4 / (l_d_sq * l_d_); - sigma_vari_->adj_ += adjsigma * 2 / sigma_d_; - p_vari_->adj_ += adjp * TWO_PI / l_d_sq / (p_d_ * p_d_); - } -}; - -/** - * This is a subclass of the vari class for precomputed - * gradients of gp_periodic_cov. - * - * The class stores the double values for the distance - * matrix, sine, cosine and sine squared of the latter, - * pointers to the varis for the covariance - * matrix, along with a pointer to the vari for sigma, - * the vari for l and the vari for p. - * - * The elements of periodic covariance matrix \f$ \mathbf{K} \f$ using the - * input \f$ \mathbf{X} \f$ are defined as - * \f$ \mathbf{K}_{ij} = k(\mathbf{X}_i,\mathbf{X}_j), \f$ where - * \f$ \mathbf{X}_i \f$ is the \f$i\f$-th row of \f$ \mathbf{X} \f$ and \n - * \f$ k(\mathbf{x},\mathbf{x}^\prime) = - * \sigma^2 \exp\left(-\frac{2\sin^2(\pi - * |\mathbf{x}-\mathbf{x}^\prime|/p)}{\ell^2}\right), \f$ \n where \f$ \sigma^2 - * \f$, \f$ \ell \f$ and \f$ p \f$ are the signal variance, length-scale and - * period. - * - * The partial derivatives w.r.t. the parameters are the following:\n - * - * \f$ \frac{\partial k}{\partial \sigma} = \frac{2k}{\sigma} \f$\n - * \f$ \frac{\partial k}{\partial \ell} = \frac{4k}{\ell^3} - * \sin^2(\pi|\mathbf{x}-\mathbf{x}^\prime|/p) \f$\n \f$ \frac{\partial - * k}{\partial p} = \frac{2k\pi|\mathbf{x}-\mathbf{x}^\prime|}{\ell^2p^2} - * \sin(2\pi|\mathbf{x}-\mathbf{x}^\prime|/p) \f$\n - * - * @tparam T_x type of std::vector elements of x - * T_x can be a scalar, an Eigen::Vector, or an Eigen::RowVector. - * @tparam T_l type of length-scale - * @tparam T_p type of period - */ -template -class gp_periodic_cov_vari : public vari { - public: - const size_t size_; - const size_t size_ltri_; - const double l_d_; - const double sigma_d_; - const double p_d_; - const double sigma_sq_d_; - double *dist_; - double *sin_2_dist_; - double *sin_dist_sq_; - vari *l_vari_; - vari *p_vari_; - vari **cov_lower_; - vari **cov_diag_; - - /** - * Constructor for gp_periodic_cov. - * - * All memory allocated in - * ChainableStack's stack_alloc arena. - * - * It is critical for the efficiency of this object - * that the constructor create new varis that aren't - * popped onto the var_stack_, but rather are - * popped onto the var_nochain_stack_. This is - * controlled by the second argument to - * vari's constructor. - * - * @param x std::vector of input elements. - * Assumes that all elements of x have the same size. - * @param sigma standard deviation of the signal - * @param l length-scale - * @param p period - */ - gp_periodic_cov_vari(const std::vector &x, double sigma, const T_l &l, - const T_p &p) - : vari(0.0), - size_(x.size()), - size_ltri_(size_ * (size_ - 1) / 2), - l_d_(value_of(l)), - sigma_d_(sigma), - p_d_(value_of(p)), - sigma_sq_d_(sigma_d_ * sigma_d_), - dist_(ChainableStack::instance_->memalloc_.alloc_array( - size_ltri_)), - sin_2_dist_(ChainableStack::instance_->memalloc_.alloc_array( - size_ltri_)), - sin_dist_sq_(ChainableStack::instance_->memalloc_.alloc_array( - size_ltri_)), - l_vari_(l.vi_), - p_vari_(p.vi_), - cov_lower_(ChainableStack::instance_->memalloc_.alloc_array( - size_ltri_)), - cov_diag_( - ChainableStack::instance_->memalloc_.alloc_array(size_)) { - using std::sin; - double neg_two_inv_l_sq = -2.0 / (l_d_ * l_d_); - double pi_div_p = pi() / p_d_; - - size_t pos = 0; - for (size_t j = 0; j < size_; ++j) { - for (size_t i = j + 1; i < size_; ++i) { - double dist = distance(x[i], x[j]); - double sin_dist = sin(pi_div_p * dist); - double sin_dist_sq = square(sin_dist); - dist_[pos] = dist; - sin_2_dist_[pos] = sin(2.0 * pi_div_p * dist); - sin_dist_sq_[pos] = sin_dist_sq; - cov_lower_[pos] = new vari( - sigma_sq_d_ * std::exp(sin_dist_sq * neg_two_inv_l_sq), false); - ++pos; - } - cov_diag_[j] = new vari(sigma_sq_d_, false); - } - } - - virtual void chain() { - double adjl = 0; - double adjp = 0; - - for (size_t i = 0; i < size_ltri_; ++i) { - vari *el_low = cov_lower_[i]; - double prod_add = el_low->adj_ * el_low->val_; - adjl += prod_add * sin_dist_sq_[i]; - adjp += prod_add * sin_2_dist_[i] * dist_[i]; - } - double l_d_sq = l_d_ * l_d_; - l_vari_->adj_ += adjl * 4 / (l_d_sq * l_d_); - p_vari_->adj_ += adjp * TWO_PI / l_d_sq / (p_d_ * p_d_); - } -}; - /** * Returns a periodic covariance matrix \f$ \mathbf{K} \f$ using the input \f$ * \mathbf{X} \f$. The elements of \f$ \mathbf{K} \f$ are defined as \f$ @@ -300,95 +38,105 @@ class gp_periodic_cov_vari : public vari { * @throw std::domain_error if sigma <= 0, l <= 0, p <= 0, or * x is nan or infinite */ -template -inline typename std::enable_if< - std::is_same::type, double>::value, - Eigen::Matrix>::type -gp_periodic_cov(const std::vector &x, const var &sigma, const var &l, - const var &p) { +template * = nullptr, + require_any_st_var* = nullptr> +Eigen::Matrix +gp_periodic_cov(const std::vector &x, + T_sigma sigma, T_l l, T_p p) { const char *fun = "gp_periodic_cov"; + check_positive(fun, "signal standard deviation", sigma); check_positive(fun, "length-scale", l); check_positive(fun, "period", p); + size_t x_size = x.size(); for (size_t i = 0; i < x_size; ++i) { check_not_nan(fun, "element of x", x[i]); } - Eigen::Matrix cov(x_size, x_size); if (x_size == 0) { - return cov; + return Eigen::Matrix(); } - gp_periodic_cov_vari *baseVari - = new gp_periodic_cov_vari(x, sigma, l, p); - - size_t pos = 0; - for (size_t j = 0; j < x_size; ++j) { - for (size_t i = (j + 1); i < x_size; ++i) { - cov.coeffRef(i, j).vi_ = baseVari->cov_lower_[pos]; - cov.coeffRef(j, i).vi_ = cov.coeffRef(i, j).vi_; - ++pos; + double l_d = value_of(l); + double p_d = value_of(p); + double sigma_d = value_of(sigma); + double sigma_squared = sigma_d * sigma_d; + double pi_over_p = pi() / p_d; + double negative_two_over_l_squared = -2.0 / (l_d * l_d); + + arena_matrix arena_dist(x.size(), x.size()); + arena_matrix arena_sin_squared(x.size(), x.size()); + arena_matrix arena_sin_squared_derivative(x.size(), x.size()); + arena_matrix res_val(x.size(), x.size()); + + auto arena_x = to_arena_if::value>(x); + + double inv_half_sq_l_d + = 0.5 / (value_of(l) * value_of(l)); + for (size_t j = 0; j < x.size(); ++j) { + for (size_t i = 0; i < j; ++i) { + arena_dist.coeffRef(i, j) = arena_dist.coeffRef(j, i) = + distance(value_of(x[i]), value_of(x[j])); + arena_sin_squared.coeffRef(i, j) = arena_sin_squared.coeffRef(j, i) = + square(sin(pi_over_p * arena_dist.coeff(i, j))); + arena_sin_squared_derivative.coeffRef(i, j) = + arena_sin_squared_derivative.coeffRef(j, i) = sin(2 * pi_over_p * arena_dist(i, j)); + + res_val.coeffRef(i, j) = res_val.coeffRef(j, i) = + sigma_squared * std::exp(arena_sin_squared.coeff(i, j) * + negative_two_over_l_squared); } - cov.coeffRef(j, j).vi_ = baseVari->cov_diag_[j]; } - return cov; -} -/** - * Returns a periodic covariance matrix \f$ \mathbf{K} \f$ using the input \f$ - * \mathbf{X} \f$. The elements of \f$ \mathbf{K} \f$ are defined as \f$ - * \mathbf{K}_{ij} = k(\mathbf{X}_i,\mathbf{X}_j), \f$ where \f$ \mathbf{X}_i - * \f$ is the \f$i\f$-th row of \f$ \mathbf{X} \f$ and \n \f$ - * k(\mathbf{x},\mathbf{x}^\prime) = \sigma^2 \exp\left(-\frac{2\sin^2(\pi - * |\mathbf{x}-\mathbf{x}^\prime|/p)}{\ell^2}\right), \f$ \n where \f$ \sigma^2 - * \f$, \f$ \ell \f$ and \f$ p \f$ are the signal variance, length-scale and - * period. - * - * @tparam T_x type of elements in the std::vector - * @param x std::vector of input elements. - * Assumes that all elements of x have the same size. - * @param sigma standard deviation of the signal - * @param l length-scale - * @param p period - * @return periodic covariance matrix - * @throw std::domain_error if sigma <= 0, l <= 0, p <= 0, or - * x is nan or infinite - */ -template -inline typename std::enable_if< - std::is_same::type, double>::value, - Eigen::Matrix>::type -gp_periodic_cov(const std::vector &x, double sigma, const var &l, - const var &p) { - const char *fun = "gp_periodic_cov"; - check_positive(fun, "signal standard deviation", sigma); - check_positive(fun, "length-scale", l); - check_positive(fun, "period", p); - size_t x_size = x.size(); - for (size_t i = 0; i < x_size; ++i) { - check_not_nan(fun, "element of x", x[i]); + for (size_t i = 0; i < x.size(); ++i) { + arena_sin_squared(i, i) = 0.0; + arena_sin_squared_derivative(i, i) = 0.0; + res_val(i, i) = sigma_squared; } - Eigen::Matrix cov(x_size, x_size); - if (x_size == 0) { - return cov; - } + arena_matrix> res + = res_val; + + reverse_pass_callback([res, res_val, arena_x, + sigma, l, p, + sigma_d, l_d, p_d, + pi_over_p, + arena_dist, + arena_sin_squared, + arena_sin_squared_derivative]() mutable { + Eigen::ArrayXXd adj_times_val = res.adj().array() * res_val.array(); + + if (!is_constant::value) + for (size_t i = 0; i < arena_x.size(); ++i) { + for (size_t j = 0; j < arena_x.size(); ++j) { + if(arena_dist.coeff(i, j) != 0.0) { + auto adj = eval(-2 * pi_over_p * + (value_of(arena_x[i]) - value_of(arena_x[j])) * + arena_sin_squared_derivative(i, j) * + adj_times_val(i, j) / + (arena_dist.coeff(i, j) * l_d * l_d)); + using T_x_var = promote_scalar_t; + forward_as(arena_x[i]).adj() += adj; + forward_as(arena_x[j]).adj() -= adj; + } + } + } - gp_periodic_cov_vari *baseVari - = new gp_periodic_cov_vari(x, sigma, l, p); + if (!is_constant::value) + forward_as(sigma).adj() += 2.0 * adj_times_val.sum() / sigma_d; - size_t pos = 0; - for (size_t j = 0; j < x_size - 1; ++j) { - for (size_t i = (j + 1); i < x_size; ++i) { - cov.coeffRef(i, j).vi_ = baseVari->cov_lower_[pos]; - cov.coeffRef(j, i).vi_ = cov.coeffRef(i, j).vi_; - ++pos; - } - cov.coeffRef(j, j).vi_ = baseVari->cov_diag_[j]; - } - cov.coeffRef(x_size - 1, x_size - 1).vi_ = baseVari->cov_diag_[x_size - 1]; - return cov; + if (!is_constant::value) + forward_as(l).adj() + += 4 * (arena_sin_squared.array() * adj_times_val).sum() / (l_d * l_d * l_d); + + if (!is_constant::value) + forward_as(p).adj() + += 2 * pi() * (arena_dist.array() * arena_sin_squared_derivative.array() * adj_times_val).sum() / (p_d * p_d * l_d * l_d); + }); + + return res; } } // namespace math diff --git a/stan/math/rev/fun/multiply_lower_tri_self_transpose.hpp b/stan/math/rev/fun/multiply_lower_tri_self_transpose.hpp index df269fb8d30..5f22ee77265 100644 --- a/stan/math/rev/fun/multiply_lower_tri_self_transpose.hpp +++ b/stan/math/rev/fun/multiply_lower_tri_self_transpose.hpp @@ -11,34 +11,35 @@ namespace stan { namespace math { -inline matrix_v multiply_lower_tri_self_transpose(const matrix_v& L) { - // check_square("multiply_lower_tri_self_transpose", - // L, "L", (double*)0); - int K = L.rows(); - int J = L.cols(); - matrix_v LLt(K, K); - if (K == 0) { - return LLt; - } - // if (K == 1) { - // LLt(0, 0) = L(0, 0) * L(0, 0); - // return LLt; - // } - int Knz; - if (K >= J) { - Knz = (K - J) * J + (J * (J + 1)) / 2; - } else { // if (K < J) - Knz = (K * (K + 1)) / 2; - } - for (int m = 0, mpos = 0; m < K; ++m, mpos += (J < m) ? J : m) { - LLt.coeffRef(m, m) = dot_self(L.row(m).head((J < (m + 1)) ? J : (m + 1))); - for (int n = 0, npos = 0; n < m; ++n, npos += (J < n) ? J : n) { - LLt.coeffRef(m, n) = LLt.coeffRef(n, m) - = dot_product(L.row(m).head((J < (n + 1)) ? J : (n + 1)), - L.row(n).head((J < (n + 1)) ? J : (n + 1))); - } - } - return LLt; +template * = nullptr> +inline Eigen::Matrix +multiply_lower_tri_self_transpose(const T& L) { + using T_double = promote_scalar_t; + using T_var = promote_scalar_t; + + if(L.rows() == 0) + return T_var(); + + arena_matrix arena_L = L; + arena_matrix arena_L_val = + value_of(arena_L).template triangularView(); + + arena_matrix res = + arena_L_val.template triangularView() * arena_L_val.transpose(); + + reverse_pass_callback([res, arena_L, arena_L_val]() mutable { + ref_type_t adj = res.adj(); + Eigen::MatrixXd adjL = (adj.transpose() + adj) * arena_L_val; + + for(size_t j = 1; j < adjL.cols(); ++j) + for(size_t i = 0; i < std::min(static_cast(adjL.rows()), j); ++i) + adjL(i, j) = 0.0; + + arena_L.adj() += adjL; + }); + + return res; } } // namespace math diff --git a/stan/math/rev/fun/rows_dot_product.hpp b/stan/math/rev/fun/rows_dot_product.hpp index 5f010b21650..a024992bb6a 100644 --- a/stan/math/rev/fun/rows_dot_product.hpp +++ b/stan/math/rev/fun/rows_dot_product.hpp @@ -21,17 +21,11 @@ inline Eigen::Matrix rows_dot_product( ref_type_t v1_ref = v1; ref_type_t v2_ref = v2; - using Mat1_double = plain_type_t; - using Mat1_var = promote_scalar_t; + arena_matrix> arena_v1_val = value_of(v1_ref); + arena_matrix> arena_v2_val = value_of(v2_ref); - using Mat2_double = plain_type_t; - using Mat2_var = promote_scalar_t; - - arena_matrix arena_v1_val = value_of(v1_ref); - arena_matrix arena_v2_val = value_of(v2_ref); - - arena_matrix arena_v1; - arena_matrix arena_v2; + arena_matrix> arena_v1; + arena_matrix> arena_v2; if (!is_constant::value) { arena_v1 = v1_ref; diff --git a/stan/math/rev/fun/tcrossprod.hpp b/stan/math/rev/fun/tcrossprod.hpp index c8a10289426..7f971a4bc9b 100644 --- a/stan/math/rev/fun/tcrossprod.hpp +++ b/stan/math/rev/fun/tcrossprod.hpp @@ -27,25 +27,19 @@ tcrossprod(const T& M) { if (M.rows() == 0) { return {}; } - // if (M.rows() == 1) - // return M * M.transpose(); - // WAS JUST THIS - // matrix_v result(M.rows(), M.rows()); - // return result.setZero().selfadjointView().rankUpdate(M); + arena_matrix> arena_M = M; + arena_matrix> arena_M_val = value_of(arena_M); - Eigen::Matrix MMt(M.rows(), - M.rows()); + Eigen::MatrixXd res_val(M.rows(), M.rows()); + arena_matrix> res = arena_M_val * arena_M_val.transpose(); - for (int m = 0; m < M.rows(); ++m) { - MMt.coeffRef(m, m) = dot_self(M.row(m)); - } - for (int m = 0; m < M.rows(); ++m) { - for (int n = 0; n < m; ++n) { - MMt.coeffRef(n, m) = MMt.coeffRef(m, n) = dot_product(M.row(m), M.row(n)); - } - } - return MMt; + reverse_pass_callback([res, arena_M, arena_M_val]() mutable { + ref_type_t adj = res.adj(); + arena_M.adj() += (adj.transpose() + adj) * arena_M_val; + }); + + return res; } } // namespace math From de71a10f2dd648fb7816d86afae7092dbfc8b579 Mon Sep 17 00:00:00 2001 From: Stan Jenkins Date: Wed, 19 Aug 2020 23:13:35 +0000 Subject: [PATCH 220/355] [Jenkins] auto-formatting by clang-format version 6.0.0-1ubuntu2~16.04.1 (tags/RELEASE_600/final) --- stan/math/prim/fun/gp_periodic_cov.hpp | 2 +- stan/math/rev/fun/gp_exp_quad_cov.hpp | 4 +- stan/math/rev/fun/gp_periodic_cov.hpp | 75 ++++++++++--------- .../fun/multiply_lower_tri_self_transpose.hpp | 19 +++-- stan/math/rev/fun/tcrossprod.hpp | 5 +- 5 files changed, 53 insertions(+), 52 deletions(-) diff --git a/stan/math/prim/fun/gp_periodic_cov.hpp b/stan/math/prim/fun/gp_periodic_cov.hpp index e16c1a20c0f..0815d584b20 100644 --- a/stan/math/prim/fun/gp_periodic_cov.hpp +++ b/stan/math/prim/fun/gp_periodic_cov.hpp @@ -42,7 +42,7 @@ namespace math { * x is nan or infinite */ template > + require_all_not_st_var> inline typename Eigen::Matrix, Eigen::Dynamic, Eigen::Dynamic> gp_periodic_cov(const std::vector &x, const T_sigma &sigma, const T_l &l, diff --git a/stan/math/rev/fun/gp_exp_quad_cov.hpp b/stan/math/rev/fun/gp_exp_quad_cov.hpp index 968a8d3b806..f24c5286977 100644 --- a/stan/math/rev/fun/gp_exp_quad_cov.hpp +++ b/stan/math/rev/fun/gp_exp_quad_cov.hpp @@ -78,8 +78,8 @@ inline Eigen::Matrix gp_exp_quad_cov(const std::vector& x, if (!is_constant::value) for (size_t i = 0; i < arena_x.size(); ++i) { for (size_t j = 0; j < arena_x.size(); ++j) { - auto adj = eval(-(value_of(arena_x[i]) - value_of(arena_x[j])) * - adj_times_val(i, j) / (l_d * l_d)); + auto adj = eval(-(value_of(arena_x[i]) - value_of(arena_x[j])) + * adj_times_val(i, j) / (l_d * l_d)); using T_x_var = promote_scalar_t; forward_as(arena_x[i]).adj() += adj; forward_as(arena_x[j]).adj() -= adj; diff --git a/stan/math/rev/fun/gp_periodic_cov.hpp b/stan/math/rev/fun/gp_periodic_cov.hpp index 90f7cd9c94b..e7682789c3c 100644 --- a/stan/math/rev/fun/gp_periodic_cov.hpp +++ b/stan/math/rev/fun/gp_periodic_cov.hpp @@ -41,10 +41,9 @@ namespace math { template * = nullptr, require_any_st_var* = nullptr> -Eigen::Matrix -gp_periodic_cov(const std::vector &x, - T_sigma sigma, T_l l, T_p p) { - const char *fun = "gp_periodic_cov"; +Eigen::Matrix gp_periodic_cov( + const std::vector& x, T_sigma sigma, T_l l, T_p p) { + const char* fun = "gp_periodic_cov"; check_positive(fun, "signal standard deviation", sigma); check_positive(fun, "length-scale", l); @@ -65,28 +64,30 @@ gp_periodic_cov(const std::vector &x, double sigma_squared = sigma_d * sigma_d; double pi_over_p = pi() / p_d; double negative_two_over_l_squared = -2.0 / (l_d * l_d); - + arena_matrix arena_dist(x.size(), x.size()); arena_matrix arena_sin_squared(x.size(), x.size()); - arena_matrix arena_sin_squared_derivative(x.size(), x.size()); + arena_matrix arena_sin_squared_derivative(x.size(), + x.size()); arena_matrix res_val(x.size(), x.size()); auto arena_x = to_arena_if::value>(x); - double inv_half_sq_l_d - = 0.5 / (value_of(l) * value_of(l)); + double inv_half_sq_l_d = 0.5 / (value_of(l) * value_of(l)); for (size_t j = 0; j < x.size(); ++j) { for (size_t i = 0; i < j; ++i) { - arena_dist.coeffRef(i, j) = arena_dist.coeffRef(j, i) = - distance(value_of(x[i]), value_of(x[j])); - arena_sin_squared.coeffRef(i, j) = arena_sin_squared.coeffRef(j, i) = - square(sin(pi_over_p * arena_dist.coeff(i, j))); - arena_sin_squared_derivative.coeffRef(i, j) = - arena_sin_squared_derivative.coeffRef(j, i) = sin(2 * pi_over_p * arena_dist(i, j)); - - res_val.coeffRef(i, j) = res_val.coeffRef(j, i) = - sigma_squared * std::exp(arena_sin_squared.coeff(i, j) * - negative_two_over_l_squared); + arena_dist.coeffRef(i, j) = arena_dist.coeffRef(j, i) + = distance(value_of(x[i]), value_of(x[j])); + arena_sin_squared.coeffRef(i, j) = arena_sin_squared.coeffRef(j, i) + = square(sin(pi_over_p * arena_dist.coeff(i, j))); + arena_sin_squared_derivative.coeffRef(i, j) + = arena_sin_squared_derivative.coeffRef(j, i) + = sin(2 * pi_over_p * arena_dist(i, j)); + + res_val.coeffRef(i, j) = res_val.coeffRef(j, i) + = sigma_squared + * std::exp(arena_sin_squared.coeff(i, j) + * negative_two_over_l_squared); } } @@ -99,28 +100,23 @@ gp_periodic_cov(const std::vector &x, arena_matrix> res = res_val; - reverse_pass_callback([res, res_val, arena_x, - sigma, l, p, - sigma_d, l_d, p_d, - pi_over_p, - arena_dist, - arena_sin_squared, - arena_sin_squared_derivative]() mutable { + reverse_pass_callback([res, res_val, arena_x, sigma, l, p, sigma_d, l_d, p_d, + pi_over_p, arena_dist, arena_sin_squared, + arena_sin_squared_derivative]() mutable { Eigen::ArrayXXd adj_times_val = res.adj().array() * res_val.array(); if (!is_constant::value) for (size_t i = 0; i < arena_x.size(); ++i) { for (size_t j = 0; j < arena_x.size(); ++j) { - if(arena_dist.coeff(i, j) != 0.0) { - auto adj = eval(-2 * pi_over_p * - (value_of(arena_x[i]) - value_of(arena_x[j])) * - arena_sin_squared_derivative(i, j) * - adj_times_val(i, j) / - (arena_dist.coeff(i, j) * l_d * l_d)); - using T_x_var = promote_scalar_t; - forward_as(arena_x[i]).adj() += adj; - forward_as(arena_x[j]).adj() -= adj; - } + if (arena_dist.coeff(i, j) != 0.0) { + auto adj = eval( + -2 * pi_over_p * (value_of(arena_x[i]) - value_of(arena_x[j])) + * arena_sin_squared_derivative(i, j) * adj_times_val(i, j) + / (arena_dist.coeff(i, j) * l_d * l_d)); + using T_x_var = promote_scalar_t; + forward_as(arena_x[i]).adj() += adj; + forward_as(arena_x[j]).adj() -= adj; + } } } @@ -129,11 +125,16 @@ gp_periodic_cov(const std::vector &x, if (!is_constant::value) forward_as(l).adj() - += 4 * (arena_sin_squared.array() * adj_times_val).sum() / (l_d * l_d * l_d); + += 4 * (arena_sin_squared.array() * adj_times_val).sum() + / (l_d * l_d * l_d); if (!is_constant::value) forward_as(p).adj() - += 2 * pi() * (arena_dist.array() * arena_sin_squared_derivative.array() * adj_times_val).sum() / (p_d * p_d * l_d * l_d); + += 2 * pi() + * (arena_dist.array() * arena_sin_squared_derivative.array() + * adj_times_val) + .sum() + / (p_d * p_d * l_d * l_d); }); return res; diff --git a/stan/math/rev/fun/multiply_lower_tri_self_transpose.hpp b/stan/math/rev/fun/multiply_lower_tri_self_transpose.hpp index 5f22ee77265..a636e70fadb 100644 --- a/stan/math/rev/fun/multiply_lower_tri_self_transpose.hpp +++ b/stan/math/rev/fun/multiply_lower_tri_self_transpose.hpp @@ -11,30 +11,29 @@ namespace stan { namespace math { -template * = nullptr> +template * = nullptr> inline Eigen::Matrix multiply_lower_tri_self_transpose(const T& L) { using T_double = promote_scalar_t; using T_var = promote_scalar_t; - if(L.rows() == 0) + if (L.rows() == 0) return T_var(); arena_matrix arena_L = L; - arena_matrix arena_L_val = - value_of(arena_L).template triangularView(); + arena_matrix arena_L_val + = value_of(arena_L).template triangularView(); - arena_matrix res = - arena_L_val.template triangularView() * arena_L_val.transpose(); + arena_matrix res = arena_L_val.template triangularView() + * arena_L_val.transpose(); reverse_pass_callback([res, arena_L, arena_L_val]() mutable { ref_type_t adj = res.adj(); Eigen::MatrixXd adjL = (adj.transpose() + adj) * arena_L_val; - for(size_t j = 1; j < adjL.cols(); ++j) - for(size_t i = 0; i < std::min(static_cast(adjL.rows()), j); ++i) - adjL(i, j) = 0.0; + for (size_t j = 1; j < adjL.cols(); ++j) + for (size_t i = 0; i < std::min(static_cast(adjL.rows()), j); ++i) + adjL(i, j) = 0.0; arena_L.adj() += adjL; }); diff --git a/stan/math/rev/fun/tcrossprod.hpp b/stan/math/rev/fun/tcrossprod.hpp index 7f971a4bc9b..228e96be0c8 100644 --- a/stan/math/rev/fun/tcrossprod.hpp +++ b/stan/math/rev/fun/tcrossprod.hpp @@ -32,13 +32,14 @@ tcrossprod(const T& M) { arena_matrix> arena_M_val = value_of(arena_M); Eigen::MatrixXd res_val(M.rows(), M.rows()); - arena_matrix> res = arena_M_val * arena_M_val.transpose(); + arena_matrix> res + = arena_M_val * arena_M_val.transpose(); reverse_pass_callback([res, arena_M, arena_M_val]() mutable { ref_type_t adj = res.adj(); arena_M.adj() += (adj.transpose() + adj) * arena_M_val; }); - + return res; } From 4ab3e0e2ec553a8f8ce945b0063a5642424373c5 Mon Sep 17 00:00:00 2001 From: Ben Date: Wed, 19 Aug 2020 20:07:58 -0400 Subject: [PATCH 221/355] Added inverse specialization (Issue #1635) --- stan/math/rev/fun/inverse.hpp | 75 +++++++---------------------------- 1 file changed, 14 insertions(+), 61 deletions(-) diff --git a/stan/math/rev/fun/inverse.hpp b/stan/math/rev/fun/inverse.hpp index 79887d259b7..9261e2c4185 100644 --- a/stan/math/rev/fun/inverse.hpp +++ b/stan/math/rev/fun/inverse.hpp @@ -3,6 +3,8 @@ #include #include +#include +#include #include #include #include @@ -11,62 +13,6 @@ namespace stan { namespace math { -namespace internal { -class inverse_vari : public vari { - public: - int M_; // A.rows() = A.cols() - double *A_; - double *A_inv_; - vari **vari_ref_A_; - vari **vari_ref_A_inv_; - - explicit inverse_vari(const Eigen::Matrix &A) - : vari(0.0), - M_(A.rows()), - A_(reinterpret_cast( - ChainableStack::instance_->memalloc_.alloc(sizeof(double) * A.rows() - * A.cols()))), - A_inv_(reinterpret_cast( - ChainableStack::instance_->memalloc_.alloc(sizeof(double) * A.rows() - * A.cols()))), - vari_ref_A_(reinterpret_cast( - ChainableStack::instance_->memalloc_.alloc(sizeof(vari *) * A.rows() - * A.cols()))), - vari_ref_A_inv_(reinterpret_cast( - ChainableStack::instance_->memalloc_.alloc(sizeof(vari *) * A.rows() - * A.cols()))) { - using Eigen::Map; - - Map Ad(A_, M_, M_); - Map A_inv_d(A_inv_, M_, M_); - Ad = A.val(); - A_inv_d = Ad.inverse(); - - Map(vari_ref_A_, M_, M_) = A.vi(); - Map(vari_ref_A_inv_, M_, M_) - = A_inv_d.unaryExpr([](double x) { return new vari(x, false); }); - } - - /** - * Reverse mode differentiation algorithm reference: - * - * Mike Giles. An extended collection of matrix derivative results for - * forward and reverse mode AD. Jan. 2008. - * - * Section 2.2.3 Inverse. - */ - virtual void chain() { - using Eigen::Map; - - matrix_d adj_A_inv = Map(vari_ref_A_inv_, M_, M_).adj(); - Map A_inv_d(A_inv_, M_, M_); - - matrix_d adjA = A_inv_d.transpose() * adj_A_inv * A_inv_d.transpose(); - Map(vari_ref_A_, M_, M_).adj() -= adjA; - } -}; -} // namespace internal - /** * Reverse mode specialization of calculating the inverse of the matrix. * @@ -75,16 +21,23 @@ class inverse_vari : public vari { * size zero). * @throw std::invalid_argument if the matrix is not square. */ -inline matrix_v inverse(const matrix_v &m) { +template * = nullptr> +inline Eigen::Matrix +inverse(const T& m) { check_square("inverse", "m", m); if (m.size() == 0) { return {}; } - matrix_v res(m.rows(), m.cols()); - internal::inverse_vari *baseVari = new internal::inverse_vari(m); - res.vi() = Eigen::Map(baseVari->vari_ref_A_inv_, res.rows(), - res.cols()); + arena_matrix> arena_m = m; + arena_matrix res_val = value_of(arena_m).inverse(); + arena_matrix> res = res_val; + + reverse_pass_callback([res, res_val, arena_m]() mutable { + Eigen::MatrixXd res_adj = res.adj(); + arena_m.adj() -= res_val.transpose() * res_adj * res_val.transpose(); + }); + return res; } From 45f468dcd26173c88a72b13914f9576bb8de3010 Mon Sep 17 00:00:00 2001 From: Stan Jenkins Date: Thu, 20 Aug 2020 00:08:49 +0000 Subject: [PATCH 222/355] [Jenkins] auto-formatting by clang-format version 6.0.0-1ubuntu2~16.04.1 (tags/RELEASE_600/final) --- stan/math/rev/fun/inverse.hpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/stan/math/rev/fun/inverse.hpp b/stan/math/rev/fun/inverse.hpp index 9261e2c4185..a1afcce27e8 100644 --- a/stan/math/rev/fun/inverse.hpp +++ b/stan/math/rev/fun/inverse.hpp @@ -22,8 +22,7 @@ namespace math { * @throw std::invalid_argument if the matrix is not square. */ template * = nullptr> -inline Eigen::Matrix -inverse(const T& m) { +inline Eigen::Matrix inverse(const T& m) { check_square("inverse", "m", m); if (m.size() == 0) { return {}; @@ -31,7 +30,8 @@ inverse(const T& m) { arena_matrix> arena_m = m; arena_matrix res_val = value_of(arena_m).inverse(); - arena_matrix> res = res_val; + arena_matrix> res + = res_val; reverse_pass_callback([res, res_val, arena_m]() mutable { Eigen::MatrixXd res_adj = res.adj(); From 183760531fb591cd63b6484730fdd4535b17dec3 Mon Sep 17 00:00:00 2001 From: Ben Date: Fri, 21 Aug 2020 16:33:53 -0400 Subject: [PATCH 223/355] Couple updates to the gps (Issue stan-dev/math 2018) --- stan/math/rev/fun/gp_exp_quad_cov.hpp | 2 +- stan/math/rev/fun/gp_periodic_cov.hpp | 26 ++++++++++++++++---------- 2 files changed, 17 insertions(+), 11 deletions(-) diff --git a/stan/math/rev/fun/gp_exp_quad_cov.hpp b/stan/math/rev/fun/gp_exp_quad_cov.hpp index f24c5286977..d4c4c1c786b 100644 --- a/stan/math/rev/fun/gp_exp_quad_cov.hpp +++ b/stan/math/rev/fun/gp_exp_quad_cov.hpp @@ -80,7 +80,7 @@ inline Eigen::Matrix gp_exp_quad_cov(const std::vector& x, for (size_t j = 0; j < arena_x.size(); ++j) { auto adj = eval(-(value_of(arena_x[i]) - value_of(arena_x[j])) * adj_times_val(i, j) / (l_d * l_d)); - using T_x_var = promote_scalar_t; + using T_x_var = promote_scalar_t; forward_as(arena_x[i]).adj() += adj; forward_as(arena_x[j]).adj() -= adj; } diff --git a/stan/math/rev/fun/gp_periodic_cov.hpp b/stan/math/rev/fun/gp_periodic_cov.hpp index e7682789c3c..d3589337557 100644 --- a/stan/math/rev/fun/gp_periodic_cov.hpp +++ b/stan/math/rev/fun/gp_periodic_cov.hpp @@ -78,20 +78,27 @@ Eigen::Matrix gp_periodic_cov( for (size_t i = 0; i < j; ++i) { arena_dist.coeffRef(i, j) = arena_dist.coeffRef(j, i) = distance(value_of(x[i]), value_of(x[j])); + + double sine = sin(pi_over_p * arena_dist.coeff(i, j)); + double cosine = cos(pi_over_p * arena_dist.coeff(i, j)); + double sine_squared = sine * sine; + arena_sin_squared.coeffRef(i, j) = arena_sin_squared.coeffRef(j, i) - = square(sin(pi_over_p * arena_dist.coeff(i, j))); + = sine_squared; + arena_sin_squared_derivative.coeffRef(i, j) - = arena_sin_squared_derivative.coeffRef(j, i) - = sin(2 * pi_over_p * arena_dist(i, j)); + = arena_sin_squared_derivative.coeffRef(j, i) + = 2.0 * sine * cosine; res_val.coeffRef(i, j) = res_val.coeffRef(j, i) = sigma_squared - * std::exp(arena_sin_squared.coeff(i, j) - * negative_two_over_l_squared); + * std::exp(sine_squared + * negative_two_over_l_squared); } } for (size_t i = 0; i < x.size(); ++i) { + arena_dist(i, i) = 0.0; arena_sin_squared(i, i) = 0.0; arena_sin_squared_derivative(i, i) = 0.0; res_val(i, i) = sigma_squared; @@ -111,11 +118,10 @@ Eigen::Matrix gp_periodic_cov( if (arena_dist.coeff(i, j) != 0.0) { auto adj = eval( -2 * pi_over_p * (value_of(arena_x[i]) - value_of(arena_x[j])) - * arena_sin_squared_derivative(i, j) * adj_times_val(i, j) - / (arena_dist.coeff(i, j) * l_d * l_d)); - using T_x_var = promote_scalar_t; - forward_as(arena_x[i]).adj() += adj; - forward_as(arena_x[j]).adj() -= adj; + * arena_sin_squared_derivative(i, j) * adj_times_val(i, j) / + (arena_dist.coeff(i, j) * l_d * l_d)); + forward_as>(arena_x[i]).adj() += adj; + forward_as>(arena_x[j]).adj() -= adj; } } } From 9704fa7007e31f2faf2bcedc21e44570b29cd8b0 Mon Sep 17 00:00:00 2001 From: Stan Jenkins Date: Fri, 21 Aug 2020 20:47:51 +0000 Subject: [PATCH 224/355] [Jenkins] auto-formatting by clang-format version 6.0.0-1ubuntu2~16.04.1 (tags/RELEASE_600/final) --- stan/math/rev/fun/gp_exp_quad_cov.hpp | 2 +- stan/math/rev/fun/gp_periodic_cov.hpp | 16 +++++++--------- 2 files changed, 8 insertions(+), 10 deletions(-) diff --git a/stan/math/rev/fun/gp_exp_quad_cov.hpp b/stan/math/rev/fun/gp_exp_quad_cov.hpp index d4c4c1c786b..f24c5286977 100644 --- a/stan/math/rev/fun/gp_exp_quad_cov.hpp +++ b/stan/math/rev/fun/gp_exp_quad_cov.hpp @@ -80,7 +80,7 @@ inline Eigen::Matrix gp_exp_quad_cov(const std::vector& x, for (size_t j = 0; j < arena_x.size(); ++j) { auto adj = eval(-(value_of(arena_x[i]) - value_of(arena_x[j])) * adj_times_val(i, j) / (l_d * l_d)); - using T_x_var = promote_scalar_t; + using T_x_var = promote_scalar_t; forward_as(arena_x[i]).adj() += adj; forward_as(arena_x[j]).adj() -= adj; } diff --git a/stan/math/rev/fun/gp_periodic_cov.hpp b/stan/math/rev/fun/gp_periodic_cov.hpp index d3589337557..c1f87729581 100644 --- a/stan/math/rev/fun/gp_periodic_cov.hpp +++ b/stan/math/rev/fun/gp_periodic_cov.hpp @@ -82,18 +82,16 @@ Eigen::Matrix gp_periodic_cov( double sine = sin(pi_over_p * arena_dist.coeff(i, j)); double cosine = cos(pi_over_p * arena_dist.coeff(i, j)); double sine_squared = sine * sine; - + arena_sin_squared.coeffRef(i, j) = arena_sin_squared.coeffRef(j, i) = sine_squared; arena_sin_squared_derivative.coeffRef(i, j) - = arena_sin_squared_derivative.coeffRef(j, i) - = 2.0 * sine * cosine; + = arena_sin_squared_derivative.coeffRef(j, i) = 2.0 * sine * cosine; res_val.coeffRef(i, j) = res_val.coeffRef(j, i) = sigma_squared - * std::exp(sine_squared - * negative_two_over_l_squared); + * std::exp(sine_squared * negative_two_over_l_squared); } } @@ -118,10 +116,10 @@ Eigen::Matrix gp_periodic_cov( if (arena_dist.coeff(i, j) != 0.0) { auto adj = eval( -2 * pi_over_p * (value_of(arena_x[i]) - value_of(arena_x[j])) - * arena_sin_squared_derivative(i, j) * adj_times_val(i, j) / - (arena_dist.coeff(i, j) * l_d * l_d)); - forward_as>(arena_x[i]).adj() += adj; - forward_as>(arena_x[j]).adj() -= adj; + * arena_sin_squared_derivative(i, j) * adj_times_val(i, j) + / (arena_dist.coeff(i, j) * l_d * l_d)); + forward_as>(arena_x[i]).adj() += adj; + forward_as>(arena_x[j]).adj() -= adj; } } } From 1bfd17305e11123dab4019f800379c142d386bc1 Mon Sep 17 00:00:00 2001 From: Ben Date: Fri, 21 Aug 2020 18:00:22 -0400 Subject: [PATCH 225/355] Made new gp autodiff more like it was previously (Issue #2018) --- stan/math/rev/fun/gp_exp_quad_cov.hpp | 78 ++++++++++++++++--------- stan/math/rev/fun/gp_periodic_cov.hpp | 84 ++++++++++++++++----------- 2 files changed, 101 insertions(+), 61 deletions(-) diff --git a/stan/math/rev/fun/gp_exp_quad_cov.hpp b/stan/math/rev/fun/gp_exp_quad_cov.hpp index d4c4c1c786b..9f20cf70e1f 100644 --- a/stan/math/rev/fun/gp_exp_quad_cov.hpp +++ b/stan/math/rev/fun/gp_exp_quad_cov.hpp @@ -49,49 +49,75 @@ inline Eigen::Matrix gp_exp_quad_cov(const std::vector& x, double sigma_d = value_of(sigma); double sigma_sq_d = sigma_d * sigma_d; - arena_matrix dist(x.size(), x.size()); - arena_matrix res_val(x.size(), x.size()); + size_t P = (x.size() * x.size() - x.size()) / 2 + x.size(); + arena_matrix dist(P); + arena_matrix res_val(P); auto arena_x = to_arena_if::value>(x); - + double inv_half_sq_l_d = 0.5 / (value_of(length_scale) * value_of(length_scale)); + + size_t pos = 0; for (size_t j = 0; j < x.size(); ++j) { - for (size_t i = 0; i < j; ++i) { - double dist_sq = squared_distance(value_of(x[i]), value_of(x[j])); - dist.coeffRef(i, j) = dist.coeffRef(j, i) = dist_sq; - res_val.coeffRef(i, j) = res_val.coeffRef(j, i) - = sigma_sq_d * std::exp(-dist_sq * inv_half_sq_l_d); + for (size_t i = 0; i <= j; ++i) { + if(i != j) { + double dist_sq = squared_distance(value_of(x[i]), value_of(x[j])); + dist.coeffRef(pos) = dist_sq; + res_val.coeffRef(pos) = sigma_sq_d * std::exp(-dist_sq * inv_half_sq_l_d); + } else { + dist.coeffRef(pos) = 0.0; + res_val.coeffRef(pos) = sigma_sq_d; + } + pos++; } } - for (size_t i = 0; i < x.size(); ++i) { - dist(i, i) = 0.0; - res_val(i, i) = sigma_sq_d; - } - arena_matrix> res - = res_val; + arena_matrix> res(x.size(), x.size()); + + pos = 0; + for(size_t j = 0; j < res.cols(); ++j) + for(size_t i = 0; i <= j; ++i) { + res.coeffRef(j, i) = res.coeffRef(i, j) = res_val.coeff(pos); + pos++; + } - reverse_pass_callback([=]() mutable { - Eigen::ArrayXXd adj_times_val = res.adj().array() * res.val().array(); + reverse_pass_callback([res, res_val, + arena_x, dist, + sigma, length_scale, + sigma_d, l_d]() mutable { + double sigma_adj = 0.0; + double l_adj = 0.0; + double inv_l_d_squared = 1.0 / (l_d * l_d); - if (!is_constant::value) - for (size_t i = 0; i < arena_x.size(); ++i) { - for (size_t j = 0; j < arena_x.size(); ++j) { - auto adj = eval(-(value_of(arena_x[i]) - value_of(arena_x[j])) - * adj_times_val(i, j) / (l_d * l_d)); + size_t pos = 0; + for (size_t j = 0; j < arena_x.size(); ++j) { + for (size_t i = 0; i <= j; ++i) { + double adj_times_val = res_val.coeffRef(pos) * res.adj().coeff(i, j); + + if (!is_constant::value) + sigma_adj += adj_times_val; + + if (!is_constant::value) + l_adj += dist.coeff(pos) * adj_times_val; + + if(!is_constant::value && i != j) { + auto adj = eval(-(value_of(arena_x[i]) - value_of(arena_x[j])) + * adj_times_val * inv_l_d_squared); using T_x_var = promote_scalar_t; - forward_as(arena_x[i]).adj() += adj; - forward_as(arena_x[j]).adj() -= adj; - } + forward_as(arena_x[i]).adj() += adj; + forward_as(arena_x[j]).adj() -= adj; + } + pos++; } + } if (!is_constant::value) - forward_as(sigma).adj() += 2.0 * adj_times_val.sum() / sigma_d; + forward_as(sigma).adj() += 2.0 * sigma_adj / sigma_d; if (!is_constant::value) forward_as(length_scale).adj() - += (dist.array() * adj_times_val).sum() / (l_d * l_d * l_d); + += l_adj / (l_d * l_d * l_d); }); return res; diff --git a/stan/math/rev/fun/gp_periodic_cov.hpp b/stan/math/rev/fun/gp_periodic_cov.hpp index d3589337557..189511ffaf0 100644 --- a/stan/math/rev/fun/gp_periodic_cov.hpp +++ b/stan/math/rev/fun/gp_periodic_cov.hpp @@ -65,64 +65,78 @@ Eigen::Matrix gp_periodic_cov( double pi_over_p = pi() / p_d; double negative_two_over_l_squared = -2.0 / (l_d * l_d); - arena_matrix arena_dist(x.size(), x.size()); - arena_matrix arena_sin_squared(x.size(), x.size()); - arena_matrix arena_sin_squared_derivative(x.size(), - x.size()); - arena_matrix res_val(x.size(), x.size()); + size_t P = (x.size() * x.size() - x.size()) / 2 + x.size(); + arena_matrix arena_dist(P); + arena_matrix arena_sin_squared(P); + arena_matrix arena_sin_squared_derivative(P); + arena_matrix res_val(P); auto arena_x = to_arena_if::value>(x); + size_t pos = 0; double inv_half_sq_l_d = 0.5 / (value_of(l) * value_of(l)); for (size_t j = 0; j < x.size(); ++j) { - for (size_t i = 0; i < j; ++i) { - arena_dist.coeffRef(i, j) = arena_dist.coeffRef(j, i) + for (size_t i = 0; i <= j; ++i) { + if(i != j) { + arena_dist.coeffRef(pos) = distance(value_of(x[i]), value_of(x[j])); + + double sine = sin(pi_over_p * arena_dist.coeff(pos)); + double cosine = cos(pi_over_p * arena_dist.coeff(pos)); + double sine_squared = sine * sine; + + arena_sin_squared.coeffRef(pos) = sine_squared; + + arena_sin_squared_derivative.coeffRef(pos) + = 2.0 * sine * cosine; + + res_val.coeffRef(pos) = sigma_squared * + std::exp(sine_squared * negative_two_over_l_squared); + } else { + arena_dist(pos) = 0.0; + arena_sin_squared(pos) = 0.0; + arena_sin_squared_derivative(pos) = 0.0; + res_val(pos) = sigma_squared; + } - double sine = sin(pi_over_p * arena_dist.coeff(i, j)); - double cosine = cos(pi_over_p * arena_dist.coeff(i, j)); - double sine_squared = sine * sine; - - arena_sin_squared.coeffRef(i, j) = arena_sin_squared.coeffRef(j, i) - = sine_squared; - - arena_sin_squared_derivative.coeffRef(i, j) - = arena_sin_squared_derivative.coeffRef(j, i) - = 2.0 * sine * cosine; - - res_val.coeffRef(i, j) = res_val.coeffRef(j, i) - = sigma_squared - * std::exp(sine_squared - * negative_two_over_l_squared); + pos++; } } - for (size_t i = 0; i < x.size(); ++i) { - arena_dist(i, i) = 0.0; - arena_sin_squared(i, i) = 0.0; - arena_sin_squared_derivative(i, i) = 0.0; - res_val(i, i) = sigma_squared; - } + arena_matrix> res(x.size(), x.size()); - arena_matrix> res - = res_val; + pos = 0; + for(size_t j = 0; j < res.cols(); ++j) + for(size_t i = 0; i <= j; ++i) { + res.coeffRef(j, i) = res.coeffRef(i, j) = res_val.coeff(pos); + pos++; + } reverse_pass_callback([res, res_val, arena_x, sigma, l, p, sigma_d, l_d, p_d, pi_over_p, arena_dist, arena_sin_squared, arena_sin_squared_derivative]() mutable { - Eigen::ArrayXXd adj_times_val = res.adj().array() * res_val.array(); + Eigen::ArrayXd adj_times_val = res_val; + + size_t pos = 0; + for(size_t j = 0; j < res.cols(); ++j) + for(size_t i = 0; i <= j; ++i) { + adj_times_val.coeffRef(pos) *= res.adj().coeff(i, j); + pos++; + } + pos = 0; if (!is_constant::value) for (size_t i = 0; i < arena_x.size(); ++i) { - for (size_t j = 0; j < arena_x.size(); ++j) { - if (arena_dist.coeff(i, j) != 0.0) { + for (size_t j = 0; j <= i; ++j) { + if (i != j && arena_dist.coeff(pos) != 0.0) { auto adj = eval( -2 * pi_over_p * (value_of(arena_x[i]) - value_of(arena_x[j])) - * arena_sin_squared_derivative(i, j) * adj_times_val(i, j) / - (arena_dist.coeff(i, j) * l_d * l_d)); + * arena_sin_squared_derivative(pos) * adj_times_val(pos) / + (arena_dist.coeff(pos) * l_d * l_d)); forward_as>(arena_x[i]).adj() += adj; forward_as>(arena_x[j]).adj() -= adj; } + pos++; } } From 912d437ea158ec731400671aaa604f0af93847d2 Mon Sep 17 00:00:00 2001 From: Stan Jenkins Date: Fri, 21 Aug 2020 22:45:29 +0000 Subject: [PATCH 226/355] [Jenkins] auto-formatting by clang-format version 6.0.0-1ubuntu2~16.04.1 (tags/RELEASE_600/final) --- stan/math/rev/fun/gp_exp_quad_cov.hpp | 63 +++++++++---------- stan/math/rev/fun/gp_periodic_cov.hpp | 91 ++++++++++++++------------- 2 files changed, 77 insertions(+), 77 deletions(-) diff --git a/stan/math/rev/fun/gp_exp_quad_cov.hpp b/stan/math/rev/fun/gp_exp_quad_cov.hpp index 9f20cf70e1f..8495f17503e 100644 --- a/stan/math/rev/fun/gp_exp_quad_cov.hpp +++ b/stan/math/rev/fun/gp_exp_quad_cov.hpp @@ -54,38 +54,38 @@ inline Eigen::Matrix gp_exp_quad_cov(const std::vector& x, arena_matrix res_val(P); auto arena_x = to_arena_if::value>(x); - + double inv_half_sq_l_d = 0.5 / (value_of(length_scale) * value_of(length_scale)); size_t pos = 0; for (size_t j = 0; j < x.size(); ++j) { for (size_t i = 0; i <= j; ++i) { - if(i != j) { - double dist_sq = squared_distance(value_of(x[i]), value_of(x[j])); - dist.coeffRef(pos) = dist_sq; - res_val.coeffRef(pos) = sigma_sq_d * std::exp(-dist_sq * inv_half_sq_l_d); + if (i != j) { + double dist_sq = squared_distance(value_of(x[i]), value_of(x[j])); + dist.coeffRef(pos) = dist_sq; + res_val.coeffRef(pos) + = sigma_sq_d * std::exp(-dist_sq * inv_half_sq_l_d); } else { - dist.coeffRef(pos) = 0.0; - res_val.coeffRef(pos) = sigma_sq_d; + dist.coeffRef(pos) = 0.0; + res_val.coeffRef(pos) = sigma_sq_d; } pos++; } } - arena_matrix> res(x.size(), x.size()); + arena_matrix> res( + x.size(), x.size()); pos = 0; - for(size_t j = 0; j < res.cols(); ++j) - for(size_t i = 0; i <= j; ++i) { + for (size_t j = 0; j < res.cols(); ++j) + for (size_t i = 0; i <= j; ++i) { res.coeffRef(j, i) = res.coeffRef(i, j) = res_val.coeff(pos); pos++; } - reverse_pass_callback([res, res_val, - arena_x, dist, - sigma, length_scale, - sigma_d, l_d]() mutable { + reverse_pass_callback([res, res_val, arena_x, dist, sigma, length_scale, + sigma_d, l_d]() mutable { double sigma_adj = 0.0; double l_adj = 0.0; double inv_l_d_squared = 1.0 / (l_d * l_d); @@ -93,22 +93,22 @@ inline Eigen::Matrix gp_exp_quad_cov(const std::vector& x, size_t pos = 0; for (size_t j = 0; j < arena_x.size(); ++j) { for (size_t i = 0; i <= j; ++i) { - double adj_times_val = res_val.coeffRef(pos) * res.adj().coeff(i, j); - - if (!is_constant::value) - sigma_adj += adj_times_val; - - if (!is_constant::value) - l_adj += dist.coeff(pos) * adj_times_val; - - if(!is_constant::value && i != j) { - auto adj = eval(-(value_of(arena_x[i]) - value_of(arena_x[j])) - * adj_times_val * inv_l_d_squared); - using T_x_var = promote_scalar_t; - forward_as(arena_x[i]).adj() += adj; - forward_as(arena_x[j]).adj() -= adj; - } - pos++; + double adj_times_val = res_val.coeffRef(pos) * res.adj().coeff(i, j); + + if (!is_constant::value) + sigma_adj += adj_times_val; + + if (!is_constant::value) + l_adj += dist.coeff(pos) * adj_times_val; + + if (!is_constant::value && i != j) { + auto adj = eval(-(value_of(arena_x[i]) - value_of(arena_x[j])) + * adj_times_val * inv_l_d_squared); + using T_x_var = promote_scalar_t; + forward_as(arena_x[i]).adj() += adj; + forward_as(arena_x[j]).adj() -= adj; + } + pos++; } } @@ -116,8 +116,7 @@ inline Eigen::Matrix gp_exp_quad_cov(const std::vector& x, forward_as(sigma).adj() += 2.0 * sigma_adj / sigma_d; if (!is_constant::value) - forward_as(length_scale).adj() - += l_adj / (l_d * l_d * l_d); + forward_as(length_scale).adj() += l_adj / (l_d * l_d * l_d); }); return res; diff --git a/stan/math/rev/fun/gp_periodic_cov.hpp b/stan/math/rev/fun/gp_periodic_cov.hpp index f7b2c4c8821..4224a83c96d 100644 --- a/stan/math/rev/fun/gp_periodic_cov.hpp +++ b/stan/math/rev/fun/gp_periodic_cov.hpp @@ -77,37 +77,37 @@ Eigen::Matrix gp_periodic_cov( double inv_half_sq_l_d = 0.5 / (value_of(l) * value_of(l)); for (size_t j = 0; j < x.size(); ++j) { for (size_t i = 0; i <= j; ++i) { - if(i != j) { - arena_dist.coeffRef(pos) - = distance(value_of(x[i]), value_of(x[j])); - - double sine = sin(pi_over_p * arena_dist.coeff(pos)); - double cosine = cos(pi_over_p * arena_dist.coeff(pos)); - double sine_squared = sine * sine; - - arena_sin_squared.coeffRef(pos) = sine_squared; - - arena_sin_squared_derivative.coeffRef(pos) - = 2.0 * sine * cosine; - - res_val.coeffRef(pos) = sigma_squared * - std::exp(sine_squared * negative_two_over_l_squared); + if (i != j) { + arena_dist.coeffRef(pos) = distance(value_of(x[i]), value_of(x[j])); + + double sine = sin(pi_over_p * arena_dist.coeff(pos)); + double cosine = cos(pi_over_p * arena_dist.coeff(pos)); + double sine_squared = sine * sine; + + arena_sin_squared.coeffRef(pos) = sine_squared; + + arena_sin_squared_derivative.coeffRef(pos) = 2.0 * sine * cosine; + + res_val.coeffRef(pos) + = sigma_squared + * std::exp(sine_squared * negative_two_over_l_squared); } else { - arena_dist(pos) = 0.0; - arena_sin_squared(pos) = 0.0; - arena_sin_squared_derivative(pos) = 0.0; - res_val(pos) = sigma_squared; + arena_dist(pos) = 0.0; + arena_sin_squared(pos) = 0.0; + arena_sin_squared_derivative(pos) = 0.0; + res_val(pos) = sigma_squared; } pos++; } } - arena_matrix> res(x.size(), x.size()); + arena_matrix> res( + x.size(), x.size()); pos = 0; - for(size_t j = 0; j < res.cols(); ++j) - for(size_t i = 0; i <= j; ++i) { + for (size_t j = 0; j < res.cols(); ++j) + for (size_t i = 0; i <= j; ++i) { res.coeffRef(j, i) = res.coeffRef(i, j) = res_val.coeff(pos); pos++; } @@ -122,25 +122,28 @@ Eigen::Matrix gp_periodic_cov( size_t pos = 0; for (size_t i = 0; i < arena_x.size(); ++i) { for (size_t j = 0; j <= i; ++j) { - double adj_times_val = res_val.coeffRef(pos) * res.adj().coeff(i, j); - - if (!is_constant::value) - sigma_adj += adj_times_val; - - if (!is_constant::value) - l_adj += arena_sin_squared.coeff(pos) * adj_times_val; - - if (!is_constant::value) - p_adj += arena_dist.coeff(pos) * arena_sin_squared_derivative.coeff(pos) * adj_times_val; - - if (!is_constant::value && i != j && arena_dist.coeff(pos) != 0.0) { - auto adj = eval(-2 * pi_over_p * (value_of(arena_x[i]) - value_of(arena_x[j])) - * arena_sin_squared_derivative(pos) * adj_times_val / - (arena_dist.coeff(pos) * l_d * l_d)); - forward_as>(arena_x[i]).adj() += adj; - forward_as>(arena_x[j]).adj() -= adj; - } - pos++; + double adj_times_val = res_val.coeffRef(pos) * res.adj().coeff(i, j); + + if (!is_constant::value) + sigma_adj += adj_times_val; + + if (!is_constant::value) + l_adj += arena_sin_squared.coeff(pos) * adj_times_val; + + if (!is_constant::value) + p_adj += arena_dist.coeff(pos) + * arena_sin_squared_derivative.coeff(pos) * adj_times_val; + + if (!is_constant::value && i != j + && arena_dist.coeff(pos) != 0.0) { + auto adj = eval(-2 * pi_over_p + * (value_of(arena_x[i]) - value_of(arena_x[j])) + * arena_sin_squared_derivative(pos) * adj_times_val + / (arena_dist.coeff(pos) * l_d * l_d)); + forward_as>(arena_x[i]).adj() += adj; + forward_as>(arena_x[j]).adj() -= adj; + } + pos++; } } @@ -148,12 +151,10 @@ Eigen::Matrix gp_periodic_cov( forward_as(sigma).adj() += 2.0 * sigma_adj / sigma_d; if (!is_constant::value) - forward_as(l).adj() - += 4 * l_adj / (l_d * l_d * l_d); + forward_as(l).adj() += 4 * l_adj / (l_d * l_d * l_d); if (!is_constant::value) - forward_as(p).adj() - += 2 * pi() * p_adj / (p_d * p_d * l_d * l_d); + forward_as(p).adj() += 2 * pi() * p_adj / (p_d * p_d * l_d * l_d); }); return res; From 1e09d8b30a52d2e6d5c7e0e8bfe6a5d2ea59f1cc Mon Sep 17 00:00:00 2001 From: Ben Date: Sun, 23 Aug 2020 14:33:30 -0400 Subject: [PATCH 227/355] More work on gp_exp_quad_cov (Issue #2018) --- stan/math/rev/fun/gp_exp_quad_cov.hpp | 51 ++++++++++++++------------- 1 file changed, 26 insertions(+), 25 deletions(-) diff --git a/stan/math/rev/fun/gp_exp_quad_cov.hpp b/stan/math/rev/fun/gp_exp_quad_cov.hpp index 8495f17503e..5900546c7a0 100644 --- a/stan/math/rev/fun/gp_exp_quad_cov.hpp +++ b/stan/math/rev/fun/gp_exp_quad_cov.hpp @@ -51,12 +51,12 @@ inline Eigen::Matrix gp_exp_quad_cov(const std::vector& x, size_t P = (x.size() * x.size() - x.size()) / 2 + x.size(); arena_matrix dist(P); - arena_matrix res_val(P); + arena_matrix> arena_res(P); auto arena_x = to_arena_if::value>(x); double inv_half_sq_l_d - = 0.5 / (value_of(length_scale) * value_of(length_scale)); + = 0.5 / (l_d * l_d); size_t pos = 0; for (size_t j = 0; j < x.size(); ++j) { @@ -64,51 +64,52 @@ inline Eigen::Matrix gp_exp_quad_cov(const std::vector& x, if (i != j) { double dist_sq = squared_distance(value_of(x[i]), value_of(x[j])); dist.coeffRef(pos) = dist_sq; - res_val.coeffRef(pos) + arena_res.coeffRef(pos) = sigma_sq_d * std::exp(-dist_sq * inv_half_sq_l_d); } else { dist.coeffRef(pos) = 0.0; - res_val.coeffRef(pos) = sigma_sq_d; + arena_res.coeffRef(pos) = sigma_sq_d; } pos++; } } - arena_matrix> res( - x.size(), x.size()); + Eigen::Matrix res(x.size(), x.size()); pos = 0; for (size_t j = 0; j < res.cols(); ++j) for (size_t i = 0; i <= j; ++i) { - res.coeffRef(j, i) = res.coeffRef(i, j) = res_val.coeff(pos); + res.coeffRef(j, i) = res.coeffRef(i, j) = arena_res.coeff(pos); pos++; } - reverse_pass_callback([res, res_val, arena_x, dist, sigma, length_scale, + reverse_pass_callback([arena_res, arena_x, dist, sigma, length_scale, sigma_d, l_d]() mutable { + size_t pos = 0; + double sigma_adj = 0.0; double l_adj = 0.0; double inv_l_d_squared = 1.0 / (l_d * l_d); - size_t pos = 0; + pos = 0; for (size_t j = 0; j < arena_x.size(); ++j) { for (size_t i = 0; i <= j; ++i) { - double adj_times_val = res_val.coeffRef(pos) * res.adj().coeff(i, j); - - if (!is_constant::value) - sigma_adj += adj_times_val; - - if (!is_constant::value) - l_adj += dist.coeff(pos) * adj_times_val; - - if (!is_constant::value && i != j) { - auto adj = eval(-(value_of(arena_x[i]) - value_of(arena_x[j])) - * adj_times_val * inv_l_d_squared); - using T_x_var = promote_scalar_t; - forward_as(arena_x[i]).adj() += adj; - forward_as(arena_x[j]).adj() -= adj; - } - pos++; + double adj_times_val = arena_res.coeff(pos).val() * arena_res.coeff(pos).adj(); + + if (!is_constant::value) + sigma_adj += adj_times_val; + + if (!is_constant::value) + l_adj += dist.coeff(pos) * adj_times_val; + + if (!is_constant::value && i != j) { + auto adj = eval(-(value_of(arena_x[i]) - value_of(arena_x[j])) + * adj_times_val * inv_l_d_squared); + using T_x_var = promote_scalar_t; + forward_as(arena_x[i]).adj() += adj; + forward_as(arena_x[j]).adj() -= adj; + } + pos++; } } From 8d551b2cfc503fe3a96b7b4f72c22a5b52facb7c Mon Sep 17 00:00:00 2001 From: Stan Jenkins Date: Sun, 23 Aug 2020 18:41:35 +0000 Subject: [PATCH 228/355] [Jenkins] auto-formatting by clang-format version 6.0.0-1ubuntu2~16.04.1 (tags/RELEASE_600/final) --- stan/math/rev/fun/gp_exp_quad_cov.hpp | 76 +++++++++++++-------------- 1 file changed, 38 insertions(+), 38 deletions(-) diff --git a/stan/math/rev/fun/gp_exp_quad_cov.hpp b/stan/math/rev/fun/gp_exp_quad_cov.hpp index 5900546c7a0..e907236c853 100644 --- a/stan/math/rev/fun/gp_exp_quad_cov.hpp +++ b/stan/math/rev/fun/gp_exp_quad_cov.hpp @@ -55,8 +55,7 @@ inline Eigen::Matrix gp_exp_quad_cov(const std::vector& x, auto arena_x = to_arena_if::value>(x); - double inv_half_sq_l_d - = 0.5 / (l_d * l_d); + double inv_half_sq_l_d = 0.5 / (l_d * l_d); size_t pos = 0; for (size_t j = 0; j < x.size(); ++j) { @@ -83,42 +82,43 @@ inline Eigen::Matrix gp_exp_quad_cov(const std::vector& x, pos++; } - reverse_pass_callback([arena_res, arena_x, dist, sigma, length_scale, - sigma_d, l_d]() mutable { - size_t pos = 0; - - double sigma_adj = 0.0; - double l_adj = 0.0; - double inv_l_d_squared = 1.0 / (l_d * l_d); - - pos = 0; - for (size_t j = 0; j < arena_x.size(); ++j) { - for (size_t i = 0; i <= j; ++i) { - double adj_times_val = arena_res.coeff(pos).val() * arena_res.coeff(pos).adj(); - - if (!is_constant::value) - sigma_adj += adj_times_val; - - if (!is_constant::value) - l_adj += dist.coeff(pos) * adj_times_val; - - if (!is_constant::value && i != j) { - auto adj = eval(-(value_of(arena_x[i]) - value_of(arena_x[j])) - * adj_times_val * inv_l_d_squared); - using T_x_var = promote_scalar_t; - forward_as(arena_x[i]).adj() += adj; - forward_as(arena_x[j]).adj() -= adj; - } - pos++; - } - } - - if (!is_constant::value) - forward_as(sigma).adj() += 2.0 * sigma_adj / sigma_d; - - if (!is_constant::value) - forward_as(length_scale).adj() += l_adj / (l_d * l_d * l_d); - }); + reverse_pass_callback( + [arena_res, arena_x, dist, sigma, length_scale, sigma_d, l_d]() mutable { + size_t pos = 0; + + double sigma_adj = 0.0; + double l_adj = 0.0; + double inv_l_d_squared = 1.0 / (l_d * l_d); + + pos = 0; + for (size_t j = 0; j < arena_x.size(); ++j) { + for (size_t i = 0; i <= j; ++i) { + double adj_times_val + = arena_res.coeff(pos).val() * arena_res.coeff(pos).adj(); + + if (!is_constant::value) + sigma_adj += adj_times_val; + + if (!is_constant::value) + l_adj += dist.coeff(pos) * adj_times_val; + + if (!is_constant::value && i != j) { + auto adj = eval(-(value_of(arena_x[i]) - value_of(arena_x[j])) + * adj_times_val * inv_l_d_squared); + using T_x_var = promote_scalar_t; + forward_as(arena_x[i]).adj() += adj; + forward_as(arena_x[j]).adj() -= adj; + } + pos++; + } + } + + if (!is_constant::value) + forward_as(sigma).adj() += 2.0 * sigma_adj / sigma_d; + + if (!is_constant::value) + forward_as(length_scale).adj() += l_adj / (l_d * l_d * l_d); + }); return res; } From 74b6abc88f42296c20313ae3b44342f05d8bf4e0 Mon Sep 17 00:00:00 2001 From: Ben Date: Sun, 23 Aug 2020 19:46:15 -0400 Subject: [PATCH 229/355] Update gp_periodic to match gp_exp_quad (Issue #2018) --- stan/math/rev/fun/gp_periodic_cov.hpp | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/stan/math/rev/fun/gp_periodic_cov.hpp b/stan/math/rev/fun/gp_periodic_cov.hpp index 4224a83c96d..6383d1c206a 100644 --- a/stan/math/rev/fun/gp_periodic_cov.hpp +++ b/stan/math/rev/fun/gp_periodic_cov.hpp @@ -69,7 +69,7 @@ Eigen::Matrix gp_periodic_cov( arena_matrix arena_dist(P); arena_matrix arena_sin_squared(P); arena_matrix arena_sin_squared_derivative(P); - arena_matrix res_val(P); + arena_matrix> arena_res(P); auto arena_x = to_arena_if::value>(x); @@ -88,31 +88,30 @@ Eigen::Matrix gp_periodic_cov( arena_sin_squared_derivative.coeffRef(pos) = 2.0 * sine * cosine; - res_val.coeffRef(pos) + arena_res.coeffRef(pos) = sigma_squared * std::exp(sine_squared * negative_two_over_l_squared); } else { - arena_dist(pos) = 0.0; - arena_sin_squared(pos) = 0.0; - arena_sin_squared_derivative(pos) = 0.0; - res_val(pos) = sigma_squared; + arena_dist.coeffRef(pos) = 0.0; + arena_sin_squared.coeffRef(pos) = 0.0; + arena_sin_squared_derivative.coeffRef(pos) = 0.0; + arena_res.coeffRef(pos) = sigma_squared; } pos++; } } - arena_matrix> res( - x.size(), x.size()); + Eigen::Matrix res(x.size(), x.size()); pos = 0; for (size_t j = 0; j < res.cols(); ++j) for (size_t i = 0; i <= j; ++i) { - res.coeffRef(j, i) = res.coeffRef(i, j) = res_val.coeff(pos); + res.coeffRef(j, i) = res.coeffRef(i, j) = arena_res.coeff(pos); pos++; } - reverse_pass_callback([res, res_val, arena_x, sigma, l, p, sigma_d, l_d, p_d, + reverse_pass_callback([arena_res, arena_x, sigma, l, p, sigma_d, l_d, p_d, pi_over_p, arena_dist, arena_sin_squared, arena_sin_squared_derivative]() mutable { double sigma_adj = 0.0; @@ -122,7 +121,8 @@ Eigen::Matrix gp_periodic_cov( size_t pos = 0; for (size_t i = 0; i < arena_x.size(); ++i) { for (size_t j = 0; j <= i; ++j) { - double adj_times_val = res_val.coeffRef(pos) * res.adj().coeff(i, j); + double adj_times_val = arena_res.coeff(pos).val() * + arena_res.coeff(pos).adj(); if (!is_constant::value) sigma_adj += adj_times_val; From 97fedc314c026653a84705996f5ce2a7195ba2af Mon Sep 17 00:00:00 2001 From: Stan Jenkins Date: Sun, 23 Aug 2020 23:48:11 +0000 Subject: [PATCH 230/355] [Jenkins] auto-formatting by clang-format version 6.0.0-1ubuntu2~16.04.1 (tags/RELEASE_600/final) --- stan/math/rev/fun/gp_periodic_cov.hpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/stan/math/rev/fun/gp_periodic_cov.hpp b/stan/math/rev/fun/gp_periodic_cov.hpp index 6383d1c206a..ad611565983 100644 --- a/stan/math/rev/fun/gp_periodic_cov.hpp +++ b/stan/math/rev/fun/gp_periodic_cov.hpp @@ -121,8 +121,8 @@ Eigen::Matrix gp_periodic_cov( size_t pos = 0; for (size_t i = 0; i < arena_x.size(); ++i) { for (size_t j = 0; j <= i; ++j) { - double adj_times_val = arena_res.coeff(pos).val() * - arena_res.coeff(pos).adj(); + double adj_times_val + = arena_res.coeff(pos).val() * arena_res.coeff(pos).adj(); if (!is_constant::value) sigma_adj += adj_times_val; From fc4fc0302ac60a13209afed4e1d85858657eb72e Mon Sep 17 00:00:00 2001 From: steve Date: Wed, 26 Aug 2020 15:07:27 -0400 Subject: [PATCH 231/355] update headers for inverse so test-headers passes --- stan/math/rev/fun/inverse.hpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/stan/math/rev/fun/inverse.hpp b/stan/math/rev/fun/inverse.hpp index a1afcce27e8..e59d0cd3e6e 100644 --- a/stan/math/rev/fun/inverse.hpp +++ b/stan/math/rev/fun/inverse.hpp @@ -1,14 +1,15 @@ #ifndef STAN_MATH_REV_FUN_INVERSE_HPP #define STAN_MATH_REV_FUN_INVERSE_HPP +#include +#include #include #include #include #include #include +#include #include -#include -#include namespace stan { namespace math { From 2f204fb299c317b5f3017abca7b8062478702b38 Mon Sep 17 00:00:00 2001 From: steve Date: Wed, 26 Aug 2020 19:12:58 -0400 Subject: [PATCH 232/355] forgot * = nullptr for gp_periodic_cov --- stan/math/prim/fun/gp_periodic_cov.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stan/math/prim/fun/gp_periodic_cov.hpp b/stan/math/prim/fun/gp_periodic_cov.hpp index 0815d584b20..1f007e22185 100644 --- a/stan/math/prim/fun/gp_periodic_cov.hpp +++ b/stan/math/prim/fun/gp_periodic_cov.hpp @@ -42,7 +42,7 @@ namespace math { * x is nan or infinite */ template > + require_all_not_st_var* = nullptr> inline typename Eigen::Matrix, Eigen::Dynamic, Eigen::Dynamic> gp_periodic_cov(const std::vector &x, const T_sigma &sigma, const T_l &l, From b5bd3cfca40dbceb1a0504564d512ed98197d994 Mon Sep 17 00:00:00 2001 From: Stan Jenkins Date: Wed, 26 Aug 2020 23:13:38 +0000 Subject: [PATCH 233/355] [Jenkins] auto-formatting by clang-format version 6.0.0-1ubuntu2~16.04.1 (tags/RELEASE_600/final) --- stan/math/prim/fun/gp_periodic_cov.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stan/math/prim/fun/gp_periodic_cov.hpp b/stan/math/prim/fun/gp_periodic_cov.hpp index 1f007e22185..47d80ab5772 100644 --- a/stan/math/prim/fun/gp_periodic_cov.hpp +++ b/stan/math/prim/fun/gp_periodic_cov.hpp @@ -42,7 +42,7 @@ namespace math { * x is nan or infinite */ template * = nullptr> + require_all_not_st_var * = nullptr> inline typename Eigen::Matrix, Eigen::Dynamic, Eigen::Dynamic> gp_periodic_cov(const std::vector &x, const T_sigma &sigma, const T_l &l, From 61aa116b284f1eb472e52f82a4ab1f22c9dc02ad Mon Sep 17 00:00:00 2001 From: Stan Jenkins Date: Thu, 27 Aug 2020 17:29:33 -0400 Subject: [PATCH 234/355] [Jenkins] auto-formatting by clang-format version 6.0.1-14 (tags/RELEASE_601/final) --- stan/math/rev/fun/simplex_constrain.hpp | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/stan/math/rev/fun/simplex_constrain.hpp b/stan/math/rev/fun/simplex_constrain.hpp index fe81e331313..14f7d206ddc 100644 --- a/stan/math/rev/fun/simplex_constrain.hpp +++ b/stan/math/rev/fun/simplex_constrain.hpp @@ -37,7 +37,8 @@ inline Eigen::Matrix simplex_constrain( for (int k = 0; k < N; ++k) { double log_N_minus_k = std::log(N - k); z.coeffRef(k) = inv_logit(value_of(y.coeff(k)) - log_N_minus_k); - diag.coeffRef(k) = stick_len * z.coeff(k) * inv_logit(log_N_minus_k - value_of(y.coeff(k))); + diag.coeffRef(k) = stick_len * z.coeff(k) + * inv_logit(log_N_minus_k - value_of(y.coeff(k))); x_val.coeffRef(k) = stick_len * z.coeff(k); stick_len -= x_val(k); } @@ -50,10 +51,12 @@ inline Eigen::Matrix simplex_constrain( double acc = x.adj().coeff(N); if (N > 0) { - arena_y.adj().coeffRef(N - 1) += diag.coeff(N - 1) * (x.adj().coeff(N - 1) - acc); + arena_y.adj().coeffRef(N - 1) + += diag.coeff(N - 1) * (x.adj().coeff(N - 1) - acc); for (int n = N - 1; --n >= 0;) { - acc = x.adj().coeff(n + 1) * z.coeff(n + 1) + (1 - z.coeff(n + 1)) * acc; - arena_y.adj().coeffRef(n) += diag.coeff(n) * (x.adj().coeff(n) - acc); + acc = x.adj().coeff(n + 1) * z.coeff(n + 1) + + (1 - z.coeff(n + 1)) * acc; + arena_y.adj().coeffRef(n) += diag.coeff(n) * (x.adj().coeff(n) - acc); } } }); From cec22ec159e159d1f4642a79caa2d40241faa3dc Mon Sep 17 00:00:00 2001 From: Ben Date: Sun, 30 Aug 2020 17:48:15 -0400 Subject: [PATCH 235/355] Updated more functions (Issue #2018) --- stan/math/prim/fun/log_sum_exp.hpp | 6 +- stan/math/rev/fun.hpp | 1 - stan/math/rev/fun/cov_exp_quad.hpp | 171 ------ stan/math/rev/fun/determinant.hpp | 6 +- stan/math/rev/fun/log_determinant.hpp | 32 +- stan/math/rev/fun/log_determinant_spd.hpp | 33 +- stan/math/rev/fun/log_softmax.hpp | 77 +-- stan/math/rev/fun/log_sum_exp.hpp | 86 +-- stan/math/rev/fun/multiply.hpp | 658 +++------------------- 9 files changed, 175 insertions(+), 895 deletions(-) delete mode 100644 stan/math/rev/fun/cov_exp_quad.hpp diff --git a/stan/math/prim/fun/log_sum_exp.hpp b/stan/math/prim/fun/log_sum_exp.hpp index 7e003b2855b..2482c27a4b2 100644 --- a/stan/math/prim/fun/log_sum_exp.hpp +++ b/stan/math/prim/fun/log_sum_exp.hpp @@ -47,8 +47,10 @@ namespace math { * @param a the first variable * @param b the second variable */ -template -inline return_type_t log_sum_exp(const T2& a, const T1& b) { +template * = nullptr, + require_all_not_var_t* = nullptr> +inline return_type_t log_sum_exp(const T1& a, const T2& b) { if (a == NEGATIVE_INFTY) { return b; } diff --git a/stan/math/rev/fun.hpp b/stan/math/rev/fun.hpp index 671ab4a46a4..ca0c09695f7 100644 --- a/stan/math/rev/fun.hpp +++ b/stan/math/rev/fun.hpp @@ -32,7 +32,6 @@ #include #include #include -#include #include #include #include diff --git a/stan/math/rev/fun/cov_exp_quad.hpp b/stan/math/rev/fun/cov_exp_quad.hpp deleted file mode 100644 index 2fb9cf9db81..00000000000 --- a/stan/math/rev/fun/cov_exp_quad.hpp +++ /dev/null @@ -1,171 +0,0 @@ -#ifndef STAN_MATH_REV_FUN_COV_EXP_QUAD_HPP -#define STAN_MATH_REV_FUN_COV_EXP_QUAD_HPP - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -namespace stan { -namespace math { - -/** - * @deprecated use gp_exp_quad_cov_vari - */ -template -class cov_exp_quad_vari : public vari { - public: - const size_t size_; - const size_t size_ltri_; - const double l_d_; - const double sigma_d_; - const double sigma_sq_d_; - double* dist_; - vari* l_vari_; - vari* sigma_vari_; - vari** cov_lower_; - vari** cov_diag_; - - /** - * @deprecated use gp_exp_quad_cov_vari - */ - cov_exp_quad_vari(const std::vector& x, const T_sigma& sigma, - const T_l& l) - : vari(0.0), - size_(x.size()), - size_ltri_(size_ * (size_ - 1) / 2), - l_d_(value_of(l)), - sigma_d_(value_of(sigma)), - sigma_sq_d_(sigma_d_ * sigma_d_), - dist_(ChainableStack::instance_->memalloc_.alloc_array( - size_ltri_)), - l_vari_(l.vi_), - sigma_vari_(sigma.vi_), - cov_lower_(ChainableStack::instance_->memalloc_.alloc_array( - size_ltri_)), - cov_diag_( - ChainableStack::instance_->memalloc_.alloc_array(size_)) { - double inv_half_sq_l_d = 0.5 / (l_d_ * l_d_); - size_t pos = 0; - for (size_t j = 0; j < size_ - 1; ++j) { - for (size_t i = j + 1; i < size_; ++i) { - double dist_sq = squared_distance(x[i], x[j]); - dist_[pos] = dist_sq; - cov_lower_[pos] = new vari( - sigma_sq_d_ * std::exp(-dist_sq * inv_half_sq_l_d), false); - ++pos; - } - } - for (size_t i = 0; i < size_; ++i) { - cov_diag_[i] = new vari(sigma_sq_d_, false); - } - } - - virtual void chain() { - double adjl = 0; - double adjsigma = 0; - - for (size_t i = 0; i < size_ltri_; ++i) { - vari* el_low = cov_lower_[i]; - double prod_add = el_low->adj_ * el_low->val_; - adjl += prod_add * dist_[i]; - adjsigma += prod_add; - } - for (size_t i = 0; i < size_; ++i) { - vari* el = cov_diag_[i]; - adjsigma += el->adj_ * el->val_; - } - l_vari_->adj_ += adjl / (l_d_ * l_d_ * l_d_); - sigma_vari_->adj_ += adjsigma * 2 / sigma_d_; - } -}; - -/** - * @deprecated use gp_exp_quad_cov_vari - */ -template -class cov_exp_quad_vari : public vari { - public: - const size_t size_; - const size_t size_ltri_; - const double l_d_; - const double sigma_d_; - const double sigma_sq_d_; - double* dist_; - vari* l_vari_; - vari** cov_lower_; - vari** cov_diag_; - - /** - * @deprecated use gp_exp_quad_cov_vari - */ - cov_exp_quad_vari(const std::vector& x, double sigma, const T_l& l) - : vari(0.0), - size_(x.size()), - size_ltri_(size_ * (size_ - 1) / 2), - l_d_(value_of(l)), - sigma_d_(value_of(sigma)), - sigma_sq_d_(sigma_d_ * sigma_d_), - dist_(ChainableStack::instance_->memalloc_.alloc_array( - size_ltri_)), - l_vari_(l.vi_), - cov_lower_(ChainableStack::instance_->memalloc_.alloc_array( - size_ltri_)), - cov_diag_( - ChainableStack::instance_->memalloc_.alloc_array(size_)) { - double inv_half_sq_l_d = 0.5 / (l_d_ * l_d_); - size_t pos = 0; - for (size_t j = 0; j < size_ - 1; ++j) { - for (size_t i = j + 1; i < size_; ++i) { - double dist_sq = squared_distance(x[i], x[j]); - dist_[pos] = dist_sq; - cov_lower_[pos] = new vari( - sigma_sq_d_ * std::exp(-dist_sq * inv_half_sq_l_d), false); - ++pos; - } - } - for (size_t i = 0; i < size_; ++i) { - cov_diag_[i] = new vari(sigma_sq_d_, false); - } - } - - virtual void chain() { - double adjl = 0; - - for (size_t i = 0; i < size_ltri_; ++i) { - vari* el_low = cov_lower_[i]; - adjl += el_low->adj_ * el_low->val_ * dist_[i]; - } - l_vari_->adj_ += adjl / (l_d_ * l_d_ * l_d_); - } -}; - -/** - * @deprecated use gp_exp_quad_cov_vari - */ -template ::type>> -inline Eigen::Matrix cov_exp_quad(const std::vector& x, - const var& sigma, const var& l) { - return gp_exp_quad_cov(x, sigma, l); -} - -/** - * @deprecated use gp_exp_quad_cov_vari - */ -template ::type>> -inline Eigen::Matrix cov_exp_quad(const std::vector& x, - double sigma, const var& l) { - return gp_exp_quad_cov(x, sigma, l); -} - -} // namespace math -} // namespace stan -#endif diff --git a/stan/math/rev/fun/determinant.hpp b/stan/math/rev/fun/determinant.hpp index 385195600b7..844bfd2aa10 100644 --- a/stan/math/rev/fun/determinant.hpp +++ b/stan/math/rev/fun/determinant.hpp @@ -19,15 +19,15 @@ inline var determinant(const T& m) { return 1; } - arena_matrix m_val = m.val(); + const auto& m_val = to_ref(m.val()); double det_val = m_val.determinant(); arena_matrix> arena_m = m; arena_matrix arena_m_inv_t = m_val.inverse().transpose(); var det = det_val; - reverse_pass_callback([=]() mutable { - arena_m.adj() += (det.adj() * det_val) * arena_m_inv_t; + reverse_pass_callback([arena_m, det, arena_m_inv_t]() mutable { + arena_m.adj() += (det.adj() * det.val()) * arena_m_inv_t; }); return det; diff --git a/stan/math/rev/fun/log_determinant.hpp b/stan/math/rev/fun/log_determinant.hpp index 7cfe2c38ff8..48ee0ba1831 100644 --- a/stan/math/rev/fun/log_determinant.hpp +++ b/stan/math/rev/fun/log_determinant.hpp @@ -4,6 +4,8 @@ #include #include #include +#include +#include #include #include #include @@ -11,26 +13,26 @@ namespace stan { namespace math { -template * = nullptr> -inline var log_determinant(const EigMat& m) { - using Eigen::Matrix; +template * = nullptr> +inline var log_determinant(const T& m) { + check_square("determinant", "m", m); + if (m.size() == 0) { + return 0.0; + } - math::check_square("log_determinant", "m", m); - - Eigen::FullPivHouseholderQR> hh + Eigen::FullPivHouseholderQR>> hh = m.val().fullPivHouseholderQr(); - vari** varis - = ChainableStack::instance_->memalloc_.alloc_array(m.size()); - Eigen::Map(varis, m.rows(), m.cols()) = m.vi(); + arena_matrix> arena_m = m; + arena_matrix arena_hh_inv_t = hh.inverse().transpose(); + + var log_det = hh.logAbsDeterminant(); - double* gradients - = ChainableStack::instance_->memalloc_.alloc_array(m.size()); - Eigen::Map(gradients, m.rows(), m.cols()) - = hh.inverse().transpose(); + reverse_pass_callback([arena_m, log_det, arena_hh_inv_t]() mutable { + arena_m.adj() += log_det.adj() * arena_hh_inv_t; + }); - return var(new precomputed_gradients_vari(hh.logAbsDeterminant(), m.size(), - varis, gradients)); + return log_det; } } // namespace math diff --git a/stan/math/rev/fun/log_determinant_spd.hpp b/stan/math/rev/fun/log_determinant_spd.hpp index 276f3203b87..a15e74029ae 100644 --- a/stan/math/rev/fun/log_determinant_spd.hpp +++ b/stan/math/rev/fun/log_determinant_spd.hpp @@ -4,6 +4,8 @@ #include #include #include +#include +#include #include #include #include @@ -20,16 +22,16 @@ namespace math { * @param m a symmetric, positive-definite matrix * @return The log determinant of the specified matrix */ -template * = nullptr> -inline var log_determinant_spd(const EigMat& m) { +template * = nullptr> +inline var log_determinant_spd(const T& m) { if (m.size() == 0) { return 0; } - matrix_d m_d = m.val(); - check_symmetric("log_determinant_spd", "m", m_d); + arena_matrix arena_m_d = m.val(); + check_symmetric("log_determinant_spd", "m", arena_m_d); - Eigen::LDLT ldlt(m_d); + Eigen::LDLT ldlt(arena_m_d); if (ldlt.info() != Eigen::Success) { double y = 0; throw_domain_error("log_determinant_spd", "matrix argument", y, @@ -37,8 +39,8 @@ inline var log_determinant_spd(const EigMat& m) { } // compute the inverse of A (needed for the derivative) - m_d.setIdentity(m.rows(), m.cols()); - ldlt.solveInPlace(m_d); + arena_m_d.setIdentity(m.rows(), m.cols()); + ldlt.solveInPlace(arena_m_d); if (ldlt.isNegative() || (ldlt.vectorD().array() <= 1e-16).any()) { double y = 0; @@ -46,21 +48,18 @@ inline var log_determinant_spd(const EigMat& m) { "matrix is negative definite"); } - double val = sum(log(ldlt.vectorD())); + var log_det = sum(log(ldlt.vectorD())); check_finite("log_determinant_spd", - "log determininant of the matrix argument", val); + "log determininant of the matrix argument", log_det); - vari** operands - = ChainableStack::instance_->memalloc_.alloc_array(m.size()); - Eigen::Map(operands, m.rows(), m.cols()) = m.vi(); + arena_matrix> arena_m = m; - double* gradients - = ChainableStack::instance_->memalloc_.alloc_array(m.size()); - Eigen::Map(gradients, m.rows(), m.cols()) = m_d; + reverse_pass_callback([arena_m, log_det, arena_m_d]() mutable { + arena_m.adj() += log_det.adj() * arena_m_d; + }); - return var( - new precomputed_gradients_vari(val, m.size(), operands, gradients)); + return log_det; } } // namespace math diff --git a/stan/math/rev/fun/log_softmax.hpp b/stan/math/rev/fun/log_softmax.hpp index bad74768d9f..185cf13137b 100644 --- a/stan/math/rev/fun/log_softmax.hpp +++ b/stan/math/rev/fun/log_softmax.hpp @@ -3,6 +3,8 @@ #include #include +#include +#include #include #include #include @@ -10,42 +12,13 @@ #include #include #include +#include #include #include namespace stan { namespace math { -namespace internal { - -class log_softmax_elt_vari : public vari { - private: - vari** alpha_; - const double* softmax_alpha_; - const int size_; // array sizes - const int idx_; // in in softmax output - - public: - log_softmax_elt_vari(double val, vari** alpha, const double* softmax_alpha, - int size, int idx) - : vari(val), - alpha_(alpha), - softmax_alpha_(softmax_alpha), - size_(size), - idx_(idx) {} - void chain() { - for (int m = 0; m < size_; ++m) { - if (m == idx_) { - alpha_[m]->adj_ += adj_ * (1 - softmax_alpha_[m]); - } else { - alpha_[m]->adj_ -= adj_ * softmax_alpha_[m]; - } - } - } -}; - -} // namespace internal - /** * Return the log softmax of the specified vector or container of vectors. * @@ -59,39 +32,25 @@ class log_softmax_elt_vari : public vari { template * = nullptr> inline auto log_softmax(const T& x) { return apply_vector_unary>::apply( - to_ref(x), [&](const auto& alpha) { - const int a_size = alpha.size(); - - check_nonzero_size("log_softmax", "alpha", alpha); + to_ref(x), [](const auto& alpha) { + check_nonzero_size("log_softmax", "alpha", alpha); - vari** alpha_vi_array - = ChainableStack::instance_->memalloc_.alloc_array(a_size); - Eigen::Map(alpha_vi_array, a_size) = alpha.vi(); + const auto& alpha_col = as_column_vector_or_scalar(alpha); + const auto& alpha_val = to_ref(value_of(alpha_col)); + const auto& theta = to_ref(alpha_val.array() - alpha_val.maxCoeff()); + arena_matrix res_val = theta.array() - log(theta.exp().sum()); - vector_d alpha_d = alpha.val(); + arena_matrix> res = res_val; + auto alpha_arena = to_arena(alpha_col); - // fold logic of math::softmax() and math::log_softmax() - // to save computations - - vector_d diff = (alpha_d.array() - alpha_d.maxCoeff()); - vector_d softmax_alpha_d = diff.array().exp(); - double sum = softmax_alpha_d.sum(); - vector_d log_softmax_alpha_d = diff.array() - std::log(sum); - - // end fold - double* softmax_alpha_d_array - = ChainableStack::instance_->memalloc_.alloc_array(a_size); - Eigen::Map(softmax_alpha_d_array, a_size) - = softmax_alpha_d.array() / sum; - - vector_v log_softmax_alpha(a_size); - for (int k = 0; k < a_size; ++k) { - log_softmax_alpha(k) = var(new internal::log_softmax_elt_vari( - log_softmax_alpha_d[k], alpha_vi_array, softmax_alpha_d_array, - a_size, k)); - } - return log_softmax_alpha; + reverse_pass_callback([alpha_arena, res, res_val]() mutable { + const auto& res_adj = to_ref(res.adj()); + alpha_arena.adj() + += res_adj - (res_adj.sum() * res_val.array().exp()).matrix(); }); + + return plain_type_t(res); + }); } } // namespace math diff --git a/stan/math/rev/fun/log_sum_exp.hpp b/stan/math/rev/fun/log_sum_exp.hpp index bc56361d96d..85cedf1f128 100644 --- a/stan/math/rev/fun/log_sum_exp.hpp +++ b/stan/math/rev/fun/log_sum_exp.hpp @@ -15,64 +15,31 @@ namespace stan { namespace math { -namespace internal { - -class log_sum_exp_vv_vari : public op_vv_vari { - public: - log_sum_exp_vv_vari(vari* avi, vari* bvi) - : op_vv_vari(log_sum_exp(avi->val_, bvi->val_), avi, bvi) {} - void chain() { - avi_->adj_ += adj_ * inv_logit(avi_->val_ - bvi_->val_); - bvi_->adj_ += adj_ * inv_logit(bvi_->val_ - avi_->val_); - } -}; -class log_sum_exp_vd_vari : public op_vd_vari { - public: - log_sum_exp_vd_vari(vari* avi, double b) - : op_vd_vari(log_sum_exp(avi->val_, b), avi, b) {} - void chain() { - if (val_ == NEGATIVE_INFTY) { - avi_->adj_ += adj_; - } else { - avi_->adj_ += adj_ * inv_logit(avi_->val_ - bd_); - } - } -}; - -} // namespace internal - -/** - * Returns the log sum of exponentials. - */ -inline var log_sum_exp(const var& a, const var& b) { - return var(new internal::log_sum_exp_vv_vari(a.vi_, b.vi_)); -} -/** - * Returns the log sum of exponentials. - */ -inline var log_sum_exp(const var& a, double b) { - return var(new internal::log_sum_exp_vd_vari(a.vi_, b)); -} /** * Returns the log sum of exponentials. + * + * @tparam T_a type of a + * @tparam T_b type of b + * @param a first argument + * @param b first argument + * @return log of e^a + e^b */ -inline var log_sum_exp(double a, const var& b) { - return var(new internal::log_sum_exp_vd_vari(b.vi_, a)); -} +template * = nullptr, + require_any_var_t* = nullptr> +inline var log_sum_exp(const T1& a, const T2& b) { + var res = log_sum_exp(value_of(a), value_of(b)); -namespace internal { + reverse_pass_callback([a, b, res]() mutable { + if(!is_constant::value) + forward_as(a).adj() += res.adj() * inv_logit(value_of(a) - value_of(b)); -class log_sum_exp_matrix_vari : public op_matrix_vari { - public: - template - explicit log_sum_exp_matrix_vari(const T& x) - : op_matrix_vari(log_sum_exp(x.val()), x) {} - void chain() { - Eigen::Map vis_map(vis_, size_); - vis_map.adj().array() += adj_ * (vis_map.val().array() - val_).exp(); - } -}; -} // namespace internal + if(!is_constant::value) + forward_as(b).adj() += res.adj() * inv_logit(value_of(b) - value_of(a)); + }); + + return res; +} /** * Returns the log sum of exponentials. @@ -82,8 +49,17 @@ class log_sum_exp_matrix_vari : public op_matrix_vari { */ template * = nullptr> inline auto log_sum_exp(const T& x) { - return apply_vector_unary::reduce(x, [&](const auto& v) { - return var(new internal::log_sum_exp_matrix_vari(v.eval())); + return apply_vector_unary::reduce(x, [](const auto& v) { + const auto& v_val = to_ref(value_of(v)); + + var res = log_sum_exp(v_val); + auto arena_v = to_arena(v); + + reverse_pass_callback([arena_v, res]() mutable { + arena_v.adj() += res.adj() * (arena_v.array().val() - res.val()).exp().matrix(); + }); + + return res; }); } diff --git a/stan/math/rev/fun/multiply.hpp b/stan/math/rev/fun/multiply.hpp index ad428c7e26c..3732cc32a88 100644 --- a/stan/math/rev/fun/multiply.hpp +++ b/stan/math/rev/fun/multiply.hpp @@ -10,606 +10,120 @@ namespace stan { namespace math { -/** - * This is a subclass of the vari class for matrix - * multiplication A * B where A is N by M and B - * is M by K. - * - * The class stores the structure of each matrix, - * the double values of A and B, and pointers to - * the varis for A and B if A or B is a var. It - * also instantiates and stores pointers to - * varis for all elements of A * B. - * - * @tparam Ta type of elements in matrix A - * @tparam Ra number of rows in matrix A, can be Eigen::Dynamic - * @tparam Ca number of columns in matrix A and rows in matrix B - * @tparam Tb type of elements in matrix B - * @tparam Cb number of columns in matrix B, can be Eigen::Dynamic - */ -template -class multiply_mat_vari : public vari { - public: - int A_rows_; - int A_cols_; - int B_cols_; - int A_size_; - int B_size_; - double* Ad_; - double* Bd_; - vari** variRefA_; - vari** variRefB_; - vari** variRefAB_; - - /** - * Constructor for multiply_mat_vari. - * - * All memory allocated in - * ChainableStack's stack_alloc arena. - * - * It is critical for the efficiency of this object - * that the constructor create new varis that aren't - * popped onto the var_stack_, but rather are - * popped onto the var_nochain_stack_. This is - * controlled by the second argument to - * vari's constructor. - * - * @param A matrix - * @param B matrix - */ - multiply_mat_vari(const Eigen::Matrix& A, - const Eigen::Matrix& B) - : vari(0.0), - A_rows_(A.rows()), - A_cols_(A.cols()), - B_cols_(B.cols()), - A_size_(A.size()), - B_size_(B.size()), - Ad_(ChainableStack::instance_->memalloc_.alloc_array(A_size_)), - Bd_(ChainableStack::instance_->memalloc_.alloc_array(B_size_)), - variRefA_( - ChainableStack::instance_->memalloc_.alloc_array(A_size_)), - variRefB_( - ChainableStack::instance_->memalloc_.alloc_array(B_size_)), - variRefAB_(ChainableStack::instance_->memalloc_.alloc_array( - A_rows_ * B_cols_)) { - using Eigen::Map; - Map(variRefA_, A_rows_, A_cols_) = A.vi(); - Map(variRefB_, A_cols_, B_cols_) = B.vi(); - Map Ad(Ad_, A_rows_, A_cols_); - Map Bd(Bd_, A_cols_, B_cols_); - Ad = A.val(); - Bd = B.val(); -#ifdef STAN_OPENCL - if (Ad.rows() * Ad.cols() * Bd.cols() - > opencl_context.tuning_opts().multiply_dim_prod_worth_transfer) { - matrix_cl Ad_cl(Ad); - matrix_cl Bd_cl(Bd); - matrix_cl variRefAB_cl = Ad_cl * Bd_cl; - matrix_d temp = from_matrix_cl(variRefAB_cl); - Map(variRefAB_, A_rows_, B_cols_) - = temp.unaryExpr([](double x) { return new vari(x, false); }); - } else { - Map(variRefAB_, A_rows_, B_cols_) - = (Ad * Bd).unaryExpr([](double x) { return new vari(x, false); }); - } -#else - Map(variRefAB_, A_rows_, B_cols_) - = (Ad * Bd).unaryExpr([](double x) { return new vari(x, false); }); -#endif - } - - virtual void chain() { - using Eigen::Map; - matrix_d adjAB(A_rows_, B_cols_); - adjAB = Map(variRefAB_, A_rows_, B_cols_).adj(); -#ifdef STAN_OPENCL - if (A_rows_ * A_cols_ * B_cols_ - > opencl_context.tuning_opts().multiply_dim_prod_worth_transfer) { - matrix_cl adjAB_cl(adjAB); - matrix_cl Ad_cl(Ad_, A_rows_, A_cols_); - matrix_cl Bd_cl(Bd_, A_cols_, B_cols_); - matrix_cl variRefA_cl = adjAB_cl * transpose(Bd_cl); - matrix_cl variRefB_cl = transpose(Ad_cl) * adjAB_cl; - matrix_d temp_variRefA = from_matrix_cl(variRefA_cl); - matrix_d temp_variRefB = from_matrix_cl(variRefB_cl); - Map(variRefA_, A_rows_, A_cols_).adj() += temp_variRefA; - Map(variRefB_, A_cols_, B_cols_).adj() += temp_variRefB; - } else { - Map(variRefA_, A_rows_, A_cols_).adj() - += adjAB * Map(Bd_, A_cols_, B_cols_).transpose(); - Map(variRefB_, A_cols_, B_cols_).adj() - += Map(Ad_, A_rows_, A_cols_).transpose() * adjAB; - } -#else - Map(variRefA_, A_rows_, A_cols_).adj() - += adjAB * Map(Bd_, A_cols_, B_cols_).transpose(); - Map(variRefB_, A_cols_, B_cols_).adj() - += Map(Ad_, A_rows_, A_cols_).transpose() * adjAB; -#endif - } -}; +namespace internal { /** - * This is a subclass of the vari class for matrix - * multiplication A * B where A is 1 by M and B - * is M by 1. - * - * The class stores the structure of each matrix, - * the double values of A and B, and pointers to - * the varis for A and B if A or B is a var. It - * also instantiates and stores pointers to - * varis for all elements of A * B. - * - * @tparam Ta type of elements in matrix A - * @tparam Ca number of columns in matrix A and rows in matrix B - * @tparam Tb type of elements in matrix B - */ -template -class multiply_mat_vari : public vari { - public: - int size_; - double* Ad_; - double* Bd_; - vari** variRefA_; - vari** variRefB_; - vari* variRefAB_; - - /** - * Constructor for multiply_mat_vari. - * - * All memory allocated in - * ChainableStack's stack_alloc arena. - * - * It is critical for the efficiency of this object - * that the constructor create new varis that aren't - * popped onto the var_stack_, but rather are - * popped onto the var_nochain_stack_. This is - * controlled by the second argument to - * vari's constructor. - * - * @param A row vector - * @param B vector - */ - multiply_mat_vari(const Eigen::Matrix& A, - const Eigen::Matrix& B) - : vari(0.0), - size_(A.cols()), - Ad_(ChainableStack::instance_->memalloc_.alloc_array(size_)), - Bd_(ChainableStack::instance_->memalloc_.alloc_array(size_)), - variRefA_( - ChainableStack::instance_->memalloc_.alloc_array(size_)), - variRefB_( - ChainableStack::instance_->memalloc_.alloc_array(size_)) { - using Eigen::Map; - Map(variRefA_, size_) = A.vi(); - Map(variRefB_, size_) = B.vi(); - Map Ad(Ad_, size_); - Map Bd(Bd_, size_); - Ad = A.val(); - Bd = B.val(); - - variRefAB_ = new vari(Ad * Bd, false); - } - - virtual void chain() { - using Eigen::Map; - - double adjAB = variRefAB_->adj_; - Map(variRefA_, size_).adj() += adjAB * Map(Bd_, size_); - Map(variRefB_, size_).adj() += Map(Ad_, size_) * adjAB; - } -}; - -/** - * This is a subclass of the vari class for matrix - * multiplication A * B where A is an N by M - * matrix of double and B is M by K. - * - * The class stores the structure of each matrix, - * the double values of A and B, and pointers to - * the varis for A and B if A or B is a var. It - * also instantiates and stores pointers to - * varis for all elements of A * B. - * - * @tparam Ra number of rows in matrix A, can be Eigen::Dynamic - * @tparam Ca number of columns in matrix A and rows in matrix B - * @tparam Tb type of elements in matrix B - * @tparam Cb number of columns in matrix B, can be Eigen::Dynamic - */ -template -class multiply_mat_vari : public vari { - public: - int A_rows_; - int A_cols_; - int B_cols_; - int A_size_; - int B_size_; - double* Ad_; - double* Bd_; - vari** variRefB_; - vari** variRefAB_; - - /** - * Constructor for multiply_mat_vari. - * - * All memory allocated in - * ChainableStack's stack_alloc arena. - * - * It is critical for the efficiency of this object - * that the constructor create new varis that aren't - * popped onto the var_stack_, but rather are - * popped onto the var_nochain_stack_. This is - * controlled by the second argument to - * vari's constructor. - * - * @param A row vector - * @param B vector - */ - multiply_mat_vari(const Eigen::Matrix& A, - const Eigen::Matrix& B) - : vari(0.0), - A_rows_(A.rows()), - A_cols_(A.cols()), - B_cols_(B.cols()), - A_size_(A.size()), - B_size_(B.size()), - Ad_(ChainableStack::instance_->memalloc_.alloc_array(A_size_)), - Bd_(ChainableStack::instance_->memalloc_.alloc_array(B_size_)), - variRefB_( - ChainableStack::instance_->memalloc_.alloc_array(B_size_)), - variRefAB_(ChainableStack::instance_->memalloc_.alloc_array( - A_rows_ * B_cols_)) { - using Eigen::Map; - Map(variRefB_, A_cols_, B_cols_) = B.vi(); - Map Ad(Ad_, A_rows_, A_cols_); - Map Bd(Bd_, A_cols_, B_cols_); - Ad = A; - Bd = B.val(); -#ifdef STAN_OPENCL - if (Ad.rows() * Ad.cols() * Bd.cols() - > opencl_context.tuning_opts().multiply_dim_prod_worth_transfer) { - matrix_cl Ad_cl(Ad); - matrix_cl Bd_cl(Bd); - matrix_cl variRefAB_cl = Ad_cl * Bd_cl; - matrix_d temp = from_matrix_cl(variRefAB_cl); - Map(variRefAB_, A_rows_, B_cols_) - = temp.unaryExpr([](double x) { return new vari(x, false); }); - } else { - Map(variRefAB_, A_rows_, B_cols_) - = (Ad * Bd).unaryExpr([](double x) { return new vari(x, false); }); - } -#else - Map(variRefAB_, A_rows_, B_cols_) - = (Ad * Bd).unaryExpr([](double x) { return new vari(x, false); }); -#endif - } - - virtual void chain() { - using Eigen::Map; - matrix_d adjAB = Map(variRefAB_, A_rows_, B_cols_).adj(); -#ifdef STAN_OPENCL - if (A_rows_ * A_cols_ * B_cols_ - > opencl_context.tuning_opts().multiply_dim_prod_worth_transfer) { - matrix_cl adjAB_cl(adjAB); - matrix_cl Ad_cl(Ad_, A_rows_, A_cols_); - matrix_cl variRefB_cl = transpose(Ad_cl) * adjAB_cl; - matrix_d temp_variRefB = from_matrix_cl(variRefB_cl); - Map(variRefB_, A_cols_, B_cols_).adj() += temp_variRefB; - } else { - Map(variRefB_, A_cols_, B_cols_).adj() - += Map(Ad_, A_rows_, A_cols_).transpose() * adjAB; - } -#else - Map(variRefB_, A_cols_, B_cols_).adj() - += Map(Ad_, A_rows_, A_cols_).transpose() * adjAB; -#endif - } -}; - -/** - * This is a subclass of the vari class for matrix - * multiplication A * B where A is a double - * row vector of length M and B is a vector of - * length M. + * Return the product of two matrices. * - * The class stores the structure of each matrix, - * the double values of A and B, and pointers to - * the varis for A and B if A or B is a var. It - * also instantiates and stores pointers to - * varis for all elements of A * B. + * @tparam T1 type of first matrix + * @tparam T2 type of second matrix * - * @tparam Ca number of columns in matrix A and rows in matrix B - * @tparam Tb type of elements in matrix B + * @param[in] A first matrix + * @param[in] B second matrix + * @return A * B */ -template -class multiply_mat_vari : public vari { - public: - int size_; - double* Ad_; - double* Bd_; - vari** variRefB_; - vari* variRefAB_; - - /** - * Constructor for multiply_mat_vari. - * - * All memory allocated in - * ChainableStack's stack_alloc arena. - * - * It is critical for the efficiency of this object - * that the constructor create new varis that aren't - * popped onto the var_stack_, but rather are - * popped onto the var_nochain_stack_. This is - * controlled by the second argument to - * vari's constructor. - * - * @param A row vector - * @param B vector - */ - multiply_mat_vari(const Eigen::Matrix& A, - const Eigen::Matrix& B) - : vari(0.0), - size_(A.cols()), - Ad_(ChainableStack::instance_->memalloc_.alloc_array(size_)), - Bd_(ChainableStack::instance_->memalloc_.alloc_array(size_)), - variRefB_( - ChainableStack::instance_->memalloc_.alloc_array(size_)) { - using Eigen::Map; - Map Ad(Ad_, size_); - Map Bd(Bd_, size_); - Map(variRefB_, size_) = B.vi(); - Ad = A; - Bd = B.val(); - variRefAB_ = new vari(Ad * Bd, false); +template * = nullptr, + require_any_vt_var* = nullptr> +inline Eigen::Matrix +multiply_impl(const T1& A, const T2& B) { + check_multiplicable("multiply", "A", A, "B", B); + + using A_ref_t = ref_type_t; + using B_ref_t = ref_type_t; + + A_ref_t A_ref = A; + B_ref_t B_ref = B; + + check_not_nan("multiply", "A", A_ref); + check_not_nan("multiply", "B", B_ref); + + arena_matrix> arena_A_val = value_of(A_ref); + arena_matrix> arena_B_val = value_of(B_ref); + + arena_matrix> arena_A; + arena_matrix> arena_B; + + if (!is_constant::value) { + arena_A = A_ref; + arena_B_val = value_of(B_ref); } - virtual void chain() { - using Eigen::Map; - Map(variRefB_, size_).adj() - += Map(Ad_, size_) * variRefAB_->adj_; + if (!is_constant::value) { + arena_B = B_ref; + arena_A_val = value_of(A_ref); } -}; -/** - * This is a subclass of the vari class for matrix - * multiplication A * B where A is N by M and B - * is an M by K matrix of doubles. - * - * The class stores the structure of each matrix, - * the double values of A and B, and pointers to - * the varis for A and B if A or B is a var. It - * also instantiates and stores pointers to - * varis for all elements of A * B. - * - * @tparam Ta type of elements in matrix A - * @tparam Ra number of rows in matrix A, can be Eigen::Dynamic - * @tparam Ca number of columns in matrix A and rows in matrix B - * @tparam Cb number of columns in matrix B, can be Eigen::Dynamic - */ -template -class multiply_mat_vari : public vari { - public: - int A_rows_; - int A_cols_; - int B_cols_; - int A_size_; - int B_size_; - double* Ad_; - double* Bd_; - vari** variRefA_; - vari** variRefAB_; - - /** - * Constructor for multiply_mat_vari. - * - * All memory allocated in - * ChainableStack's stack_alloc arena. - * - * It is critical for the efficiency of this object - * that the constructor create new varis that aren't - * popped onto the var_stack_, but rather are - * popped onto the var_nochain_stack_. This is - * controlled by the second argument to - * vari's constructor. - * - * @param A row vector - * @param B vector - */ - multiply_mat_vari(const Eigen::Matrix& A, - const Eigen::Matrix& B) - : vari(0.0), - A_rows_(A.rows()), - A_cols_(A.cols()), - B_cols_(B.cols()), - A_size_(A.size()), - B_size_(B.size()), - Ad_(ChainableStack::instance_->memalloc_.alloc_array(A_size_)), - Bd_(ChainableStack::instance_->memalloc_.alloc_array(B_size_)), - variRefA_( - ChainableStack::instance_->memalloc_.alloc_array(A_size_)), - variRefAB_(ChainableStack::instance_->memalloc_.alloc_array( - A_rows_ * B_cols_)) { - using Eigen::Map; - Map(variRefA_, A_rows_, A_cols_) = A.vi(); - Map Ad(Ad_, A_rows_, A_cols_); - Map Bd(Bd_, A_cols_, B_cols_); - Ad = A.val(); - Bd = B.val(); -#ifdef STAN_OPENCL - if (Ad.rows() * Ad.cols() * Bd.cols() - > opencl_context.tuning_opts().multiply_dim_prod_worth_transfer) { - matrix_cl Ad_cl(Ad); - matrix_cl Bd_cl(Bd); - matrix_cl variRefAB_cl = Ad_cl * Bd_cl; - matrix_d temp = from_matrix_cl(variRefAB_cl); - Map(variRefAB_, A_rows_, B_cols_) - = temp.unaryExpr([](double x) { return new vari(x, false); }); - } else { - Map(variRefAB_, A_rows_, B_cols_) - = (Ad * Bd).unaryExpr([](double x) { return new vari(x, false); }); - } -#else - Map(variRefAB_, A_rows_, B_cols_) - = (Ad * Bd).unaryExpr([](double x) { return new vari(x, false); }); -#endif - } + arena_matrix> res; - virtual void chain() { - using Eigen::Map; - matrix_d adjAB = Map(variRefAB_, A_rows_, B_cols_).adj(); -#ifdef STAN_OPENCL - if (A_rows_ * A_cols_ * B_cols_ - > opencl_context.tuning_opts().multiply_dim_prod_worth_transfer) { - matrix_cl adjAB_cl(adjAB); - matrix_cl Bd_cl(Bd_, A_cols_, B_cols_); - matrix_cl variRefA_cl = adjAB_cl * transpose(Bd_cl); - matrix_d temp_variRefA = from_matrix_cl(variRefA_cl); - Map(variRefA_, A_rows_, A_cols_).adj() += temp_variRefA; - } else { - Map(variRefA_, A_rows_, A_cols_).adj() - += adjAB * Map(Bd_, A_cols_, B_cols_).transpose(); - } -#else - Map(variRefA_, A_rows_, A_cols_).adj() - += adjAB * Map(Bd_, A_cols_, B_cols_).transpose(); -#endif + if(!is_constant::value) { + res = arena_A_val * arena_B_val; + } else if(!is_constant::value) { + res = value_of(A_ref) * arena_B_val; + } else if(!is_constant::value) { + res = arena_A_val * value_of(B_ref); } -}; -/** - * This is a subclass of the vari class for matrix - * multiplication A * B where A is a row - * vector of length M and B is a vector of length M - * of doubles. - * - * The class stores the structure of each matrix, - * the double values of A and B, and pointers to - * the varis for A and B if A or B is a var. It - * also instantiates and stores pointers to - * varis for all elements of A * B. - * - * @tparam Ta type of elements in matrix A - * @tparam Ca number of columns in matrix A and rows in matrix B - */ -template -class multiply_mat_vari : public vari { - public: - int size_; - double* Ad_; - double* Bd_; - vari** variRefA_; - vari* variRefAB_; + reverse_pass_callback([arena_A, arena_B, + arena_A_val, arena_B_val, + res]() mutable { + auto res_adj = res.adj().eval(); - /** - * Constructor for multiply_mat_vari. - * - * All memory allocated in - * ChainableStack's stack_alloc arena. - * - * It is critical for the efficiency of this object - * that the constructor create new varis that aren't - * popped onto the var_stack_, but rather are - * popped onto the var_nochain_stack_. This is - * controlled by the second argument to - * vari's constructor. - * - * @param A row vector - * @param B vector - */ - multiply_mat_vari(const Eigen::Matrix& A, - const Eigen::Matrix& B) - : vari(0.0), - size_(A.cols()), - Ad_(ChainableStack::instance_->memalloc_.alloc_array(size_)), - Bd_(ChainableStack::instance_->memalloc_.alloc_array(size_)), - variRefA_( - ChainableStack::instance_->memalloc_.alloc_array(size_)) { - using Eigen::Map; - Map(variRefA_, size_) = A.vi(); - Map Ad(Ad_, size_); - Map Bd(Bd_, size_); - Ad = A.val(); - Bd = B; + if (!is_constant::value) + arena_A.adj() += res_adj * arena_B_val.transpose(); - variRefAB_ = new vari(Ad * Bd, false); - } + if (!is_constant::value) + arena_B.adj() += arena_A_val.transpose() * res_adj; + }); - virtual void chain() { - using Eigen::Map; + return res; +} - Map(variRefA_, size_).adj() - += variRefAB_->adj_ * Map(Bd_, size_); - } -}; +} /** * Return the product of two matrices. * - * @tparam Mat1 type of first matrix - * @tparam Mat2 type of second matrix + * This version does not handle row vector times column vector * - * @param[in] m1 Matrix - * @param[in] m2 Matrix - * @return Product of scalar and matrix. + * @tparam T1 type of first matrix + * @tparam T2 type of second matrix + * + * @param[in] A first matrix + * @param[in] B second matrix + * @return A * B */ -template * = nullptr, - require_any_eigen_vt* = nullptr, - require_not_eigen_row_and_col_t* = nullptr> -inline auto multiply(const Mat1& m1, const Mat2& m2) { - using Ta = value_type_t; - using Tb = value_type_t; - constexpr int Ra = Mat1::RowsAtCompileTime; - constexpr int Ca = Mat1::ColsAtCompileTime; - constexpr int Cb = Mat2::ColsAtCompileTime; - check_multiplicable("multiply", "m1", m1, "m2", m2); - const auto& m1_ref = to_ref(m1); - const auto& m2_ref = to_ref(m2); - check_not_nan("multiply", "m1", m1_ref); - check_not_nan("multiply", "m2", m2_ref); - - // Memory managed with the arena allocator. - multiply_mat_vari* baseVari - = new multiply_mat_vari(m1_ref, m2_ref); - Eigen::Matrix AB_v(m1.rows(), m2.cols()); - AB_v.vi() - = Eigen::Map(&baseVari->variRefAB_[0], m1.rows(), m2.cols()); - - return AB_v; +template * = nullptr, + require_any_vt_var* = nullptr, + require_not_eigen_row_and_col_t* = nullptr> +inline Eigen::Matrix +multiply(const T1& A, const T2& B) { + return internal::multiply_impl(A, B); } /** - * Return the scalar product of a row vector and - * a vector. + * Return the product of a row vector times a column vector as a scalar * - * @tparam RowVec type of row vector m1 - * @tparam ColVec type of column vector m2 + * @tparam T1 type of row vector + * @tparam T2 type of column vector * - * @param[in] m1 Row vector - * @param[in] m2 Column vector - * @return Scalar product of row vector and vector + * @param[in] A row vector + * @param[in] B column vector + * @return A * B as a scalar */ -template < - typename RowVec, typename ColVec, - require_any_var_t, value_type_t>* = nullptr, - require_eigen_row_and_col_t* = nullptr> -inline var multiply(const RowVec& m1, const ColVec& m2) { - using RowVecScalar = value_type_t; - using ColVecScalar = value_type_t; - constexpr int Ca = RowVec::ColsAtCompileTime; - check_multiplicable("multiply", "m1", m1, "m2", m2); - const auto& m1_ref = to_ref(m1); - const auto& m2_ref = to_ref(m2); - check_not_nan("multiply", "m1", m1_ref); - check_not_nan("multiply", "m2", m2_ref); - // Memory managed with the arena allocator. - multiply_mat_vari* baseVari - = new multiply_mat_vari(m1_ref, - m2_ref); - var AB_v; - AB_v.vi_ = baseVari->variRefAB_; - return AB_v; +template * = nullptr, + require_any_vt_var* = nullptr, + require_eigen_row_and_col_t* = nullptr> +inline var multiply(const T1& A, const T2& B) { + return internal::multiply_impl(A, B)(0, 0); } } // namespace math From 88b22dd6396e89df0f20b62d7c46e097cc0485ff Mon Sep 17 00:00:00 2001 From: Stan Jenkins Date: Sun, 30 Aug 2020 17:50:41 -0400 Subject: [PATCH 236/355] [Jenkins] auto-formatting by clang-format version 6.0.1-14 (tags/RELEASE_601/final) --- stan/math/prim/fun/log_sum_exp.hpp | 4 +-- stan/math/rev/fun/log_softmax.hpp | 31 ++++++++--------- stan/math/rev/fun/log_sum_exp.hpp | 17 ++++++---- stan/math/rev/fun/multiply.hpp | 53 +++++++++++++----------------- 4 files changed, 50 insertions(+), 55 deletions(-) diff --git a/stan/math/prim/fun/log_sum_exp.hpp b/stan/math/prim/fun/log_sum_exp.hpp index 2482c27a4b2..984edb00f4d 100644 --- a/stan/math/prim/fun/log_sum_exp.hpp +++ b/stan/math/prim/fun/log_sum_exp.hpp @@ -48,8 +48,8 @@ namespace math { * @param b the second variable */ template * = nullptr, - require_all_not_var_t* = nullptr> + require_all_stan_scalar_t* = nullptr, + require_all_not_var_t* = nullptr> inline return_type_t log_sum_exp(const T1& a, const T2& b) { if (a == NEGATIVE_INFTY) { return b; diff --git a/stan/math/rev/fun/log_softmax.hpp b/stan/math/rev/fun/log_softmax.hpp index 185cf13137b..4b40fef6cbe 100644 --- a/stan/math/rev/fun/log_softmax.hpp +++ b/stan/math/rev/fun/log_softmax.hpp @@ -32,25 +32,26 @@ namespace math { template * = nullptr> inline auto log_softmax(const T& x) { return apply_vector_unary>::apply( - to_ref(x), [](const auto& alpha) { - check_nonzero_size("log_softmax", "alpha", alpha); + to_ref(x), [](const auto& alpha) { + check_nonzero_size("log_softmax", "alpha", alpha); - const auto& alpha_col = as_column_vector_or_scalar(alpha); - const auto& alpha_val = to_ref(value_of(alpha_col)); - const auto& theta = to_ref(alpha_val.array() - alpha_val.maxCoeff()); - arena_matrix res_val = theta.array() - log(theta.exp().sum()); + const auto& alpha_col = as_column_vector_or_scalar(alpha); + const auto& alpha_val = to_ref(value_of(alpha_col)); + const auto& theta = to_ref(alpha_val.array() - alpha_val.maxCoeff()); + arena_matrix res_val + = theta.array() - log(theta.exp().sum()); - arena_matrix> res = res_val; - auto alpha_arena = to_arena(alpha_col); + arena_matrix> res = res_val; + auto alpha_arena = to_arena(alpha_col); - reverse_pass_callback([alpha_arena, res, res_val]() mutable { - const auto& res_adj = to_ref(res.adj()); - alpha_arena.adj() - += res_adj - (res_adj.sum() * res_val.array().exp()).matrix(); - }); + reverse_pass_callback([alpha_arena, res, res_val]() mutable { + const auto& res_adj = to_ref(res.adj()); + alpha_arena.adj() + += res_adj - (res_adj.sum() * res_val.array().exp()).matrix(); + }); - return plain_type_t(res); - }); + return plain_type_t(res); + }); } } // namespace math diff --git a/stan/math/rev/fun/log_sum_exp.hpp b/stan/math/rev/fun/log_sum_exp.hpp index 85cedf1f128..343e39c1f49 100644 --- a/stan/math/rev/fun/log_sum_exp.hpp +++ b/stan/math/rev/fun/log_sum_exp.hpp @@ -25,17 +25,19 @@ namespace math { * @return log of e^a + e^b */ template * = nullptr, - require_any_var_t* = nullptr> + require_all_stan_scalar_t* = nullptr, + require_any_var_t* = nullptr> inline var log_sum_exp(const T1& a, const T2& b) { var res = log_sum_exp(value_of(a), value_of(b)); reverse_pass_callback([a, b, res]() mutable { - if(!is_constant::value) - forward_as(a).adj() += res.adj() * inv_logit(value_of(a) - value_of(b)); + if (!is_constant::value) + forward_as(a).adj() + += res.adj() * inv_logit(value_of(a) - value_of(b)); - if(!is_constant::value) - forward_as(b).adj() += res.adj() * inv_logit(value_of(b) - value_of(a)); + if (!is_constant::value) + forward_as(b).adj() + += res.adj() * inv_logit(value_of(b) - value_of(a)); }); return res; @@ -56,7 +58,8 @@ inline auto log_sum_exp(const T& x) { auto arena_v = to_arena(v); reverse_pass_callback([arena_v, res]() mutable { - arena_v.adj() += res.adj() * (arena_v.array().val() - res.val()).exp().matrix(); + arena_v.adj() + += res.adj() * (arena_v.array().val() - res.val()).exp().matrix(); }); return res; diff --git a/stan/math/rev/fun/multiply.hpp b/stan/math/rev/fun/multiply.hpp index 3732cc32a88..7498a5db7e8 100644 --- a/stan/math/rev/fun/multiply.hpp +++ b/stan/math/rev/fun/multiply.hpp @@ -22,18 +22,15 @@ namespace internal { * @param[in] B second matrix * @return A * B */ -template * = nullptr, +template * = nullptr, require_any_vt_var* = nullptr> -inline Eigen::Matrix +inline Eigen::Matrix multiply_impl(const T1& A, const T2& B) { check_multiplicable("multiply", "A", A, "B", B); using A_ref_t = ref_type_t; using B_ref_t = ref_type_t; - + A_ref_t A_ref = A; B_ref_t B_ref = B; @@ -56,34 +53,32 @@ multiply_impl(const T1& A, const T2& B) { arena_A_val = value_of(A_ref); } - arena_matrix> res; + arena_matrix> + res; - if(!is_constant::value) { + if (!is_constant::value) { res = arena_A_val * arena_B_val; - } else if(!is_constant::value) { + } else if (!is_constant::value) { res = value_of(A_ref) * arena_B_val; - } else if(!is_constant::value) { + } else if (!is_constant::value) { res = arena_A_val * value_of(B_ref); } - reverse_pass_callback([arena_A, arena_B, - arena_A_val, arena_B_val, - res]() mutable { - auto res_adj = res.adj().eval(); + reverse_pass_callback( + [arena_A, arena_B, arena_A_val, arena_B_val, res]() mutable { + auto res_adj = res.adj().eval(); - if (!is_constant::value) - arena_A.adj() += res_adj * arena_B_val.transpose(); + if (!is_constant::value) + arena_A.adj() += res_adj * arena_B_val.transpose(); - if (!is_constant::value) - arena_B.adj() += arena_A_val.transpose() * res_adj; - }); + if (!is_constant::value) + arena_B.adj() += arena_A_val.transpose() * res_adj; + }); return res; } -} +} // namespace internal /** * Return the product of two matrices. @@ -97,13 +92,10 @@ multiply_impl(const T1& A, const T2& B) { * @param[in] B second matrix * @return A * B */ -template * = nullptr, +template * = nullptr, require_any_vt_var* = nullptr, - require_not_eigen_row_and_col_t* = nullptr> -inline Eigen::Matrix + require_not_eigen_row_and_col_t* = nullptr> +inline Eigen::Matrix multiply(const T1& A, const T2& B) { return internal::multiply_impl(A, B); } @@ -118,10 +110,9 @@ multiply(const T1& A, const T2& B) { * @param[in] B column vector * @return A * B as a scalar */ -template * = nullptr, +template * = nullptr, require_any_vt_var* = nullptr, - require_eigen_row_and_col_t* = nullptr> + require_eigen_row_and_col_t* = nullptr> inline var multiply(const T1& A, const T2& B) { return internal::multiply_impl(A, B)(0, 0); } From f7aff18d2d8f520c731fb5aff7661b93e6d314d7 Mon Sep 17 00:00:00 2001 From: Ben Date: Mon, 31 Aug 2020 14:11:09 -0400 Subject: [PATCH 237/355] Fixed indexing problem and added missing header (Issue #2018) --- stan/math/rev/fun.hpp | 1 + stan/math/rev/fun/gp_exp_quad_cov.hpp | 15 ++++++++------- stan/math/rev/fun/gp_periodic_cov.hpp | 18 +++++++++--------- 3 files changed, 18 insertions(+), 16 deletions(-) diff --git a/stan/math/rev/fun.hpp b/stan/math/rev/fun.hpp index ca0c09695f7..3fe7b07ee92 100644 --- a/stan/math/rev/fun.hpp +++ b/stan/math/rev/fun.hpp @@ -55,6 +55,7 @@ #include #include #include +#include #include #include #include diff --git a/stan/math/rev/fun/gp_exp_quad_cov.hpp b/stan/math/rev/fun/gp_exp_quad_cov.hpp index e907236c853..af57a758543 100644 --- a/stan/math/rev/fun/gp_exp_quad_cov.hpp +++ b/stan/math/rev/fun/gp_exp_quad_cov.hpp @@ -49,7 +49,8 @@ inline Eigen::Matrix gp_exp_quad_cov(const std::vector& x, double sigma_d = value_of(sigma); double sigma_sq_d = sigma_d * sigma_d; - size_t P = (x.size() * x.size() - x.size()) / 2 + x.size(); + size_t N = x.size(); + size_t P = (N * N - N) / 2 + N; arena_matrix dist(P); arena_matrix> arena_res(P); @@ -58,7 +59,7 @@ inline Eigen::Matrix gp_exp_quad_cov(const std::vector& x, double inv_half_sq_l_d = 0.5 / (l_d * l_d); size_t pos = 0; - for (size_t j = 0; j < x.size(); ++j) { + for (size_t j = 0; j < N; ++j) { for (size_t i = 0; i <= j; ++i) { if (i != j) { double dist_sq = squared_distance(value_of(x[i]), value_of(x[j])); @@ -73,25 +74,25 @@ inline Eigen::Matrix gp_exp_quad_cov(const std::vector& x, } } - Eigen::Matrix res(x.size(), x.size()); + Eigen::Matrix res(N, N); pos = 0; - for (size_t j = 0; j < res.cols(); ++j) + for (size_t j = 0; j < N; ++j) for (size_t i = 0; i <= j; ++i) { res.coeffRef(j, i) = res.coeffRef(i, j) = arena_res.coeff(pos); pos++; } reverse_pass_callback( - [arena_res, arena_x, dist, sigma, length_scale, sigma_d, l_d]() mutable { + [arena_res, arena_x, dist, sigma, length_scale, sigma_d, l_d, N]() mutable { size_t pos = 0; double sigma_adj = 0.0; double l_adj = 0.0; double inv_l_d_squared = 1.0 / (l_d * l_d); - + pos = 0; - for (size_t j = 0; j < arena_x.size(); ++j) { + for (size_t j = 0; j < N; ++j) { for (size_t i = 0; i <= j; ++i) { double adj_times_val = arena_res.coeff(pos).val() * arena_res.coeff(pos).adj(); diff --git a/stan/math/rev/fun/gp_periodic_cov.hpp b/stan/math/rev/fun/gp_periodic_cov.hpp index ad611565983..8966c9e13d8 100644 --- a/stan/math/rev/fun/gp_periodic_cov.hpp +++ b/stan/math/rev/fun/gp_periodic_cov.hpp @@ -49,12 +49,11 @@ Eigen::Matrix gp_periodic_cov( check_positive(fun, "length-scale", l); check_positive(fun, "period", p); - size_t x_size = x.size(); - for (size_t i = 0; i < x_size; ++i) { + for (size_t i = 0; i < x.size(); ++i) { check_not_nan(fun, "element of x", x[i]); } - if (x_size == 0) { + if (x.size() == 0) { return Eigen::Matrix(); } @@ -65,7 +64,8 @@ Eigen::Matrix gp_periodic_cov( double pi_over_p = pi() / p_d; double negative_two_over_l_squared = -2.0 / (l_d * l_d); - size_t P = (x.size() * x.size() - x.size()) / 2 + x.size(); + size_t N = x.size(); + size_t P = (N * N - N) / 2 + N; arena_matrix arena_dist(P); arena_matrix arena_sin_squared(P); arena_matrix arena_sin_squared_derivative(P); @@ -75,7 +75,7 @@ Eigen::Matrix gp_periodic_cov( size_t pos = 0; double inv_half_sq_l_d = 0.5 / (value_of(l) * value_of(l)); - for (size_t j = 0; j < x.size(); ++j) { + for (size_t j = 0; j < N; ++j) { for (size_t i = 0; i <= j; ++i) { if (i != j) { arena_dist.coeffRef(pos) = distance(value_of(x[i]), value_of(x[j])); @@ -102,16 +102,16 @@ Eigen::Matrix gp_periodic_cov( } } - Eigen::Matrix res(x.size(), x.size()); + Eigen::Matrix res(N, N); pos = 0; - for (size_t j = 0; j < res.cols(); ++j) + for (size_t j = 0; j < N; ++j) for (size_t i = 0; i <= j; ++i) { res.coeffRef(j, i) = res.coeffRef(i, j) = arena_res.coeff(pos); pos++; } - reverse_pass_callback([arena_res, arena_x, sigma, l, p, sigma_d, l_d, p_d, + reverse_pass_callback([arena_res, arena_x, sigma, l, p, sigma_d, l_d, p_d, N, pi_over_p, arena_dist, arena_sin_squared, arena_sin_squared_derivative]() mutable { double sigma_adj = 0.0; @@ -119,7 +119,7 @@ Eigen::Matrix gp_periodic_cov( double p_adj = 0.0; size_t pos = 0; - for (size_t i = 0; i < arena_x.size(); ++i) { + for (size_t i = 0; i < N; ++i) { for (size_t j = 0; j <= i; ++j) { double adj_times_val = arena_res.coeff(pos).val() * arena_res.coeff(pos).adj(); From 5add664961f64a00b9535bb782e7d8948fa25848 Mon Sep 17 00:00:00 2001 From: Stan Jenkins Date: Mon, 31 Aug 2020 14:12:24 -0400 Subject: [PATCH 238/355] [Jenkins] auto-formatting by clang-format version 6.0.1-14 (tags/RELEASE_601/final) --- stan/math/rev/fun/gp_exp_quad_cov.hpp | 66 +++++++++++++-------------- 1 file changed, 33 insertions(+), 33 deletions(-) diff --git a/stan/math/rev/fun/gp_exp_quad_cov.hpp b/stan/math/rev/fun/gp_exp_quad_cov.hpp index af57a758543..dc479d11c92 100644 --- a/stan/math/rev/fun/gp_exp_quad_cov.hpp +++ b/stan/math/rev/fun/gp_exp_quad_cov.hpp @@ -83,43 +83,43 @@ inline Eigen::Matrix gp_exp_quad_cov(const std::vector& x, pos++; } - reverse_pass_callback( - [arena_res, arena_x, dist, sigma, length_scale, sigma_d, l_d, N]() mutable { - size_t pos = 0; - - double sigma_adj = 0.0; - double l_adj = 0.0; - double inv_l_d_squared = 1.0 / (l_d * l_d); - - pos = 0; - for (size_t j = 0; j < N; ++j) { - for (size_t i = 0; i <= j; ++i) { - double adj_times_val - = arena_res.coeff(pos).val() * arena_res.coeff(pos).adj(); - - if (!is_constant::value) - sigma_adj += adj_times_val; - - if (!is_constant::value) - l_adj += dist.coeff(pos) * adj_times_val; - - if (!is_constant::value && i != j) { - auto adj = eval(-(value_of(arena_x[i]) - value_of(arena_x[j])) - * adj_times_val * inv_l_d_squared); - using T_x_var = promote_scalar_t; - forward_as(arena_x[i]).adj() += adj; - forward_as(arena_x[j]).adj() -= adj; - } - pos++; - } - } + reverse_pass_callback([arena_res, arena_x, dist, sigma, length_scale, sigma_d, + l_d, N]() mutable { + size_t pos = 0; + + double sigma_adj = 0.0; + double l_adj = 0.0; + double inv_l_d_squared = 1.0 / (l_d * l_d); + + pos = 0; + for (size_t j = 0; j < N; ++j) { + for (size_t i = 0; i <= j; ++i) { + double adj_times_val + = arena_res.coeff(pos).val() * arena_res.coeff(pos).adj(); if (!is_constant::value) - forward_as(sigma).adj() += 2.0 * sigma_adj / sigma_d; + sigma_adj += adj_times_val; if (!is_constant::value) - forward_as(length_scale).adj() += l_adj / (l_d * l_d * l_d); - }); + l_adj += dist.coeff(pos) * adj_times_val; + + if (!is_constant::value && i != j) { + auto adj = eval(-(value_of(arena_x[i]) - value_of(arena_x[j])) + * adj_times_val * inv_l_d_squared); + using T_x_var = promote_scalar_t; + forward_as(arena_x[i]).adj() += adj; + forward_as(arena_x[j]).adj() -= adj; + } + pos++; + } + } + + if (!is_constant::value) + forward_as(sigma).adj() += 2.0 * sigma_adj / sigma_d; + + if (!is_constant::value) + forward_as(length_scale).adj() += l_adj / (l_d * l_d * l_d); + }); return res; } From 147378c21dd0147b717a2b181af1431f7605d388 Mon Sep 17 00:00:00 2001 From: Ben Date: Mon, 31 Aug 2020 19:36:45 -0400 Subject: [PATCH 239/355] Converted some more functions (Issue #2018) --- stan/math/prim/fun/matrix_power.hpp | 6 +- stan/math/rev/fun/matrix_power.hpp | 175 +++--------- stan/math/rev/fun/mdivide_left.hpp | 247 +++-------------- stan/math/rev/fun/mdivide_left_spd.hpp | 250 +++--------------- stan/math/rev/fun/mdivide_left_tri.hpp | 99 +++---- test/unit/math/rev/fun/log_softmax_test.cpp | 34 +++ test/unit/math/rev/fun/matrix_power_test.cpp | 23 ++ test/unit/math/rev/fun/mdivide_left_test.cpp | 28 ++ .../math/rev/fun/mdivide_left_tri_test.cpp | 24 ++ 9 files changed, 260 insertions(+), 626 deletions(-) create mode 100644 test/unit/math/rev/fun/log_softmax_test.cpp create mode 100644 test/unit/math/rev/fun/matrix_power_test.cpp create mode 100644 test/unit/math/rev/fun/mdivide_left_test.cpp diff --git a/stan/math/prim/fun/matrix_power.hpp b/stan/math/prim/fun/matrix_power.hpp index 5e9dff9bb3d..2cc438bf87e 100644 --- a/stan/math/prim/fun/matrix_power.hpp +++ b/stan/math/prim/fun/matrix_power.hpp @@ -29,11 +29,9 @@ matrix_power(const EigMat& M, const int n) { constexpr int C = EigMat::ColsAtCompileTime; check_square("matrix_power", "M", M); - if (n < 0) - invalid_argument("matrix_power", "n", n, "is ", ", but must be >= 0!"); + check_nonnegative("matrix_power", "n", n); if (M.rows() == 0) - invalid_argument("matrix_power", "M.rows()", M.rows(), "is ", - ", but must be > 0!"); + return {}; Eigen::Matrix MM = M; check_finite("matrix_power", "M", MM); if (n == 0) diff --git a/stan/math/rev/fun/matrix_power.hpp b/stan/math/rev/fun/matrix_power.hpp index dcd1776d668..5d44ac37ce1 100644 --- a/stan/math/rev/fun/matrix_power.hpp +++ b/stan/math/rev/fun/matrix_power.hpp @@ -12,111 +12,6 @@ namespace stan { namespace math { -namespace internal { - -template -class matrix_product_vari_n0 : public vari { - public: - vari** adjMnRef_; - - explicit matrix_product_vari_n0(const Eigen::Matrix& M) - : vari(0.0), - adjMnRef_(ChainableStack::instance_->memalloc_.alloc_array( - M.rows() * M.cols())) { - matrix_d Mnd = Eigen::Matrix::Identity(M.rows(), M.cols()); - Eigen::Map(adjMnRef_, M.rows(), M.cols()) - = Mnd.unaryExpr([](double x) { return new vari(x, false); }); - } - - virtual void chain() { return; } -}; - -template -class matrix_product_vari_n1 : public vari { - public: - int rows_; - int cols_; - vari** adjMRef_; - vari** adjMnRef_; - - explicit matrix_product_vari_n1(const Eigen::Matrix& M) - : vari(0.0), - rows_(M.rows()), - cols_(M.cols()), - adjMRef_(ChainableStack::instance_->memalloc_.alloc_array( - M.rows() * M.cols())), - adjMnRef_(ChainableStack::instance_->memalloc_.alloc_array( - M.rows() * M.cols())) { - Eigen::Map(adjMRef_, rows_, cols_) = M.vi(); - Eigen::Map(adjMnRef_, M.rows(), M.cols()) - = M.val().unaryExpr([](double x) { return new vari(x, false); }); - } - - virtual void chain() { - Eigen::Map(adjMRef_, rows_, cols_).adj() - = Eigen::Map(adjMnRef_, rows_, cols_).adj(); - } -}; - -template -class matrix_product_vari : public vari { - public: - int rows_; - int cols_; - vari** adjMRef_; - vari** adjMnRef_; - std::vector > Mds; // M, M^2, ..., M^(n-1). - int n; - - explicit matrix_product_vari(const Eigen::Matrix& M, const int n) - : vari(0.0), - rows_(M.rows()), - cols_(M.cols()), - adjMRef_(ChainableStack::instance_->memalloc_.alloc_array( - M.rows() * M.cols())), - adjMnRef_(ChainableStack::instance_->memalloc_.alloc_array( - M.rows() * M.cols())), - n(n) { - Mds.resize(n - 1); - Mds[0] = M.val(); - Eigen::Map(adjMRef_, rows_, cols_) = M.vi(); - for (int i = 1; i < n - 1; i++) { - Mds[i] = Mds[i - 1] * Mds[0]; - } - Eigen::Matrix Mnd = Mds[n - 2] * Mds[0]; - Eigen::Map(adjMnRef_, rows_, cols_) - = Mnd.unaryExpr([](double x) { return new vari(x, false); }); - } - - virtual void chain() { - for (int j = 0; j < cols_; j++) { - for (int i = 0; i < rows_; i++) { - double dijdkl = 0.0; - Eigen::Matrix S - = Eigen::Matrix::Zero(rows_, cols_); - for (int l = 0; l < cols_; l++) { - S(i, l) += Mds[n - 2](j, l); - } - for (int nn = 1; nn < n - 1; nn++) { - for (int l = 0; l < cols_; l++) { - for (int k = 0; k < rows_; k++) { - S(k, l) += Mds[nn - 1](k, i) * Mds[n - nn - 2](j, l); - } - } - } - for (int k = 0; k < rows_; k++) { - S(k, j) += Mds[n - 2](k, i); - } - Eigen::Map(adjMRef_, rows_, cols_).adj()(i, j) - += (S.array() - * Eigen::Map(adjMnRef_, rows_, cols_).adj().array()) - .sum(); - } - } - } -}; - -} // namespace internal /** * Returns the nth power of the specific matrix. M^n = M * M * ... * M. @@ -130,38 +25,50 @@ class matrix_product_vari : public vari { * @throw std::invalid_argument if the exponent is negative or the matrix is not * square. */ -template * = nullptr> -inline Eigen::Matrix, EigMat::RowsAtCompileTime, - EigMat::ColsAtCompileTime> -matrix_power(const EigMat& M, const int n) { - using T = value_type_t; - constexpr int R = EigMat::RowsAtCompileTime; - constexpr int C = EigMat::ColsAtCompileTime; - - check_square("matrix_power", "M", M); - if (n < 0) - invalid_argument("matrix_power", "n", n, "is ", ", but must be >= 0!"); - if (M.rows() == 0) - invalid_argument("matrix_power", "M.rows()", M.rows(), "is ", - ", but must be > 0!"); +template * = nullptr> +inline Eigen::Matrix +matrix_power(const T& M, const int n) { const auto& M_ref = to_ref(M); + check_square("matrix_power", "M", M); + check_nonnegative("matrix_power", "n", n); check_finite("matrix_power", "M", M_ref); - if (n == 0) { - auto* baseVari = new internal::matrix_product_vari_n0(M_ref); - Eigen::Matrix Mn(M.rows(), M.cols()); - Mn.vi() = Eigen::Map(baseVari->adjMnRef_, M.rows(), M.cols()); - return Mn; - } else if (n == 1) { - auto* baseVari = new internal::matrix_product_vari_n1(M_ref); - Eigen::Matrix Mn(M.rows(), M.cols()); - Mn.vi() = Eigen::Map(baseVari->adjMnRef_, M.rows(), M.cols()); - return Mn; - } else { - auto* baseVari = new internal::matrix_product_vari(M_ref, n); - Eigen::Matrix Mn(M.rows(), M.cols()); - Mn.vi() = Eigen::Map(baseVari->adjMnRef_, M.rows(), M.cols()); - return Mn; + + if(M.size() == 0) + return {}; + + size_t N = M.rows(); + + if(n == 0) + return Eigen::MatrixXd::Identity(N, N); + + if(n == 1) + return M_ref; + + arena_t> powers(n + 1); + arena_matrix> arena_M = M_ref; + + powers[0] = Eigen::MatrixXd::Identity(N, N); + powers[1] = value_of(M_ref); + for(size_t i = 2; i <= n; ++i) { + powers[i] = powers[1] * powers[i - 1]; } + + arena_matrix> res = + powers[powers.size() - 1]; + + reverse_pass_callback([arena_M, n, N, res, powers]() mutable { + const auto& M_val = powers[1]; + Eigen::MatrixXd adj_C = res.adj(); + Eigen::MatrixXd adj_M = Eigen::MatrixXd::Zero(N, N); + for(size_t i = n; i > 1; --i) { + adj_M += adj_C * powers[i - 1].transpose(); + adj_C = (M_val.transpose() * adj_C).eval(); + } + adj_M += adj_C; + arena_M.adj() += adj_M; + }); + + return res; } } // namespace math diff --git a/stan/math/rev/fun/mdivide_left.hpp b/stan/math/rev/fun/mdivide_left.hpp index e0563f87745..5a8f5e49fd8 100644 --- a/stan/math/rev/fun/mdivide_left.hpp +++ b/stan/math/rev/fun/mdivide_left.hpp @@ -12,238 +12,51 @@ namespace stan { namespace math { -namespace internal { -template -class mdivide_left_vv_vari : public vari { - public: - int M_; // A.rows() = A.cols() = B.rows() - int N_; // B.cols() - double *A_; - double *C_; - vari **variRefA_; - vari **variRefB_; - vari **variRefC_; - - mdivide_left_vv_vari(const Eigen::Matrix &A, - const Eigen::Matrix &B) - : vari(0.0), - M_(A.rows()), - N_(B.cols()), - A_(reinterpret_cast( - ChainableStack::instance_->memalloc_.alloc(sizeof(double) * A.rows() - * A.cols()))), - C_(reinterpret_cast( - ChainableStack::instance_->memalloc_.alloc(sizeof(double) * B.rows() - * B.cols()))), - variRefA_(reinterpret_cast( - ChainableStack::instance_->memalloc_.alloc(sizeof(vari *) * A.rows() - * A.cols()))), - variRefB_(reinterpret_cast( - ChainableStack::instance_->memalloc_.alloc(sizeof(vari *) * B.rows() - * B.cols()))), - variRefC_(reinterpret_cast( - ChainableStack::instance_->memalloc_.alloc(sizeof(vari *) * B.rows() - * B.cols()))) { - using Eigen::Map; - - Map Ad(A_, M_, M_); - Map Cd(C_, M_, N_); - Ad = A.val(); - Cd = Ad.colPivHouseholderQr().solve(B.val()); - - Map(variRefA_, M_, M_) = A.vi(); - Map(variRefB_, M_, N_) = B.vi(); - Map(variRefC_, M_, N_) - = Cd.unaryExpr([](double x) { return new vari(x, false); }); - } - - virtual void chain() { - using Eigen::Map; - matrix_d adjB = Map(A_, M_, M_) - .transpose() - .colPivHouseholderQr() - .solve(Map(variRefC_, M_, N_).adj()); - - Map(variRefA_, M_, M_).adj() - -= adjB * Map(C_, M_, N_).transpose(); - Map(variRefB_, M_, N_).adj() += adjB; - } -}; - -template -class mdivide_left_dv_vari : public vari { - public: - int M_; // A.rows() = A.cols() = B.rows() - int N_; // B.cols() - double *A_; - double *C_; - vari **variRefB_; - vari **variRefC_; - - mdivide_left_dv_vari(const Eigen::Matrix &A, - const Eigen::Matrix &B) - : vari(0.0), - M_(A.rows()), - N_(B.cols()), - A_(reinterpret_cast( - ChainableStack::instance_->memalloc_.alloc(sizeof(double) * A.rows() - * A.cols()))), - C_(reinterpret_cast( - ChainableStack::instance_->memalloc_.alloc(sizeof(double) * B.rows() - * B.cols()))), - variRefB_(reinterpret_cast( - ChainableStack::instance_->memalloc_.alloc(sizeof(vari *) * B.rows() - * B.cols()))), - variRefC_(reinterpret_cast( - ChainableStack::instance_->memalloc_.alloc(sizeof(vari *) * B.rows() - * B.cols()))) { - using Eigen::Map; - - Map Ad(A_, M_, M_); - Map Cd(C_, M_, N_); - Ad = A; - Cd = Ad.colPivHouseholderQr().solve(B.val()); - Map(variRefB_, M_, N_) = B.vi(); - Map(variRefC_, M_, N_) - = Cd.unaryExpr([](double x) { return new vari(x, false); }); - } - - virtual void chain() { - using Eigen::Map; - - Map(variRefB_, M_, N_).adj() - += Map(A_, M_, M_) - .transpose() - .colPivHouseholderQr() - .solve(Map(variRefC_, M_, N_).adj()); - } -}; - -template -class mdivide_left_vd_vari : public vari { - public: - int M_; // A.rows() = A.cols() = B.rows() - int N_; // B.cols() - double *A_; - double *C_; - vari **variRefA_; - vari **variRefC_; - - mdivide_left_vd_vari(const Eigen::Matrix &A, - const Eigen::Matrix &B) - : vari(0.0), - M_(A.rows()), - N_(B.cols()), - A_(reinterpret_cast( - ChainableStack::instance_->memalloc_.alloc(sizeof(double) * A.rows() - * A.cols()))), - C_(reinterpret_cast( - ChainableStack::instance_->memalloc_.alloc(sizeof(double) * B.rows() - * B.cols()))), - variRefA_(reinterpret_cast( - ChainableStack::instance_->memalloc_.alloc(sizeof(vari *) * A.rows() - * A.cols()))), - variRefC_(reinterpret_cast( - ChainableStack::instance_->memalloc_.alloc(sizeof(vari *) * B.rows() - * B.cols()))) { - using Eigen::Map; - - Map(variRefA_, M_, M_) = A.vi(); - Map Ad(A_, M_, M_); - Map Cd(C_, M_, N_); - - Ad = A.val(); - Cd = Ad.colPivHouseholderQr().solve(B); - Map(variRefC_, M_, N_) - = Cd.unaryExpr([](double x) { return new vari(x, false); }); - } - - virtual void chain() { - using Eigen::Map; - - matrix_d adjC = Map(variRefC_, M_, N_).adj(); - - Map(variRefA_, M_, M_).adj() - -= Map(A_, M_, M_) - .transpose() - .colPivHouseholderQr() - .solve(adjC * Map(C_, M_, N_).transpose()); - } -}; -} // namespace internal - template * = nullptr> + require_all_eigen_t* = nullptr, + require_any_vt_var* = nullptr> inline Eigen::Matrix -mdivide_left(const T1 &A, const T2 &b) { +mdivide_left(const T1& A, const T2& B) { check_square("mdivide_left", "A", A); - check_multiplicable("mdivide_left", "A", A, "b", b); + check_multiplicable("mdivide_left", "A", A, "B", B); if (A.size() == 0) { - return {0, b.cols()}; + return {0, B.cols()}; } - // NOTE: this is not a memory leak, this vari is used in the - // expression graph to evaluate the adjoint, but is not needed - // for the returned matrix. Memory will be cleaned up with the - // arena allocator. - auto *baseVari = new internal::mdivide_left_vv_vari< - T1::RowsAtCompileTime, T1::ColsAtCompileTime, T2::RowsAtCompileTime, - T2::ColsAtCompileTime>(A, b); + using A_ref_t = ref_type_t; + using B_ref_t = ref_type_t; - Eigen::Matrix res( - b.rows(), b.cols()); - res.vi() = Eigen::Map(baseVari->variRefC_, res.rows(), res.cols()); + A_ref_t A_ref = A; + B_ref_t B_ref = B; - return res; -} + arena_matrix> arena_A; + arena_matrix> arena_B; -template * = nullptr, - require_eigen_vt * = nullptr> -inline Eigen::Matrix -mdivide_left(const T1 &A, const T2 &b) { - check_square("mdivide_left", "A", A); - check_multiplicable("mdivide_left", "A", A, "b", b); - if (A.size() == 0) { - return {0, b.cols()}; + if (!is_constant::value) { + arena_A = A_ref; } - // NOTE: this is not a memory leak, this vari is used in the - // expression graph to evaluate the adjoint, but is not needed - // for the returned matrix. Memory will be cleaned up with the - // arena allocator. - auto *baseVari = new internal::mdivide_left_vd_vari< - T1::RowsAtCompileTime, T1::ColsAtCompileTime, T2::RowsAtCompileTime, - T2::ColsAtCompileTime>(A, b); + if (!is_constant::value) { + arena_B = B_ref; + } - Eigen::Matrix res( - b.rows(), b.cols()); - res.vi() = Eigen::Map(baseVari->variRefC_, res.rows(), res.cols()); + arena_matrix arena_A_val = value_of(A_ref); + arena_matrix> + res = arena_A_val.colPivHouseholderQr().solve(value_of(B_ref)); - return res; -} - -template * = nullptr, - require_eigen_vt * = nullptr> -inline Eigen::Matrix -mdivide_left(const T1 &A, const T2 &b) { - check_square("mdivide_left", "A", A); - check_multiplicable("mdivide_left", "A", A, "b", b); - if (A.size() == 0) { - return {0, b.cols()}; - } + reverse_pass_callback([arena_A, arena_B, arena_A_val, res]() mutable { + Eigen::Matrix + adjB = arena_A_val.transpose() + .colPivHouseholderQr() + .solve(res.adj()); - // NOTE: this is not a memory leak, this vari is used in the - // expression graph to evaluate the adjoint, but is not needed - // for the returned matrix. Memory will be cleaned up with the - // arena allocator. - auto *baseVari = new internal::mdivide_left_dv_vari< - T1::RowsAtCompileTime, T1::ColsAtCompileTime, T2::RowsAtCompileTime, - T2::ColsAtCompileTime>(A, b); + if(!is_constant::value) + forward_as>(arena_A).adj() += + -adjB * res.val().transpose().eval(); - Eigen::Matrix res( - b.rows(), b.cols()); - res.vi() = Eigen::Map(baseVari->variRefC_, res.rows(), res.cols()); + if (!is_constant::value) + forward_as>(arena_B).adj() += adjB; + }); return res; } diff --git a/stan/math/rev/fun/mdivide_left_spd.hpp b/stan/math/rev/fun/mdivide_left_spd.hpp index 0d5d9a50694..fd2ce4ed410 100644 --- a/stan/math/rev/fun/mdivide_left_spd.hpp +++ b/stan/math/rev/fun/mdivide_left_spd.hpp @@ -12,228 +12,62 @@ namespace stan { namespace math { -namespace internal { - -template -class mdivide_left_spd_alloc : public chainable_alloc { - public: - virtual ~mdivide_left_spd_alloc() {} - - Eigen::LLT > llt_; - Eigen::Matrix C_; -}; - -template -class mdivide_left_spd_vv_vari : public vari { - public: - int M_; // A.rows() = A.cols() = B.rows() - int N_; // B.cols() - vari **variRefA_; - vari **variRefB_; - vari **variRefC_; - mdivide_left_spd_alloc *alloc_; - - mdivide_left_spd_vv_vari(const Eigen::Matrix &A, - const Eigen::Matrix &B) - : vari(0.0), - M_(A.rows()), - N_(B.cols()), - variRefA_(reinterpret_cast( - ChainableStack::instance_->memalloc_.alloc(sizeof(vari *) * A.rows() - * A.cols()))), - variRefB_(reinterpret_cast( - ChainableStack::instance_->memalloc_.alloc(sizeof(vari *) * B.rows() - * B.cols()))), - variRefC_(reinterpret_cast( - ChainableStack::instance_->memalloc_.alloc(sizeof(vari *) * B.rows() - * B.cols()))), - alloc_(new mdivide_left_spd_alloc()) { - Eigen::Map(variRefA_, M_, M_) = A.vi(); - Eigen::Map(variRefB_, M_, N_) = B.vi(); - alloc_->C_ = B.val(); - alloc_->llt_ = A.val().llt(); - check_pos_definite("mdivide_left_spd", "A", alloc_->llt_); - alloc_->llt_.solveInPlace(alloc_->C_); - - Eigen::Map(variRefC_, M_, N_) - = alloc_->C_.unaryExpr([](double x) { return new vari(x, false); }); - } - virtual void chain() { - matrix_d adjB = Eigen::Map(variRefC_, M_, N_).adj(); - alloc_->llt_.solveInPlace(adjB); - Eigen::Map(variRefA_, M_, M_).adj() - -= adjB * alloc_->C_.transpose(); - Eigen::Map(variRefB_, M_, N_).adj() += adjB; - } -}; - -template -class mdivide_left_spd_dv_vari : public vari { - public: - int M_; // A.rows() = A.cols() = B.rows() - int N_; // B.cols() - vari **variRefB_; - vari **variRefC_; - mdivide_left_spd_alloc *alloc_; - - mdivide_left_spd_dv_vari(const Eigen::Matrix &A, - const Eigen::Matrix &B) - : vari(0.0), - M_(A.rows()), - N_(B.cols()), - variRefB_(reinterpret_cast( - ChainableStack::instance_->memalloc_.alloc(sizeof(vari *) * B.rows() - * B.cols()))), - variRefC_(reinterpret_cast( - ChainableStack::instance_->memalloc_.alloc(sizeof(vari *) * B.rows() - * B.cols()))), - alloc_(new mdivide_left_spd_alloc()) { - alloc_->C_ = B.val(); - Eigen::Map(variRefB_, M_, N_) = B.vi(); - alloc_->llt_ = A.llt(); - check_pos_definite("mdivide_left_spd", "A", alloc_->llt_); - alloc_->llt_.solveInPlace(alloc_->C_); - - Eigen::Map(variRefC_, M_, N_) - = alloc_->C_.unaryExpr([](double x) { return new vari(x, false); }); - } +template * = nullptr, + require_any_vt_var* = nullptr> +inline Eigen::Matrix +mdivide_left_spd(const T1& A, const T2& B) { + check_symmetric("mdivide_left_spd", "A", A); + check_multiplicable("mdivide_left_spd", "A", A, "B", B); - virtual void chain() { - matrix_d adjB = Eigen::Map(variRefC_, M_, N_).adj(); - alloc_->llt_.solveInPlace(adjB); - Eigen::Map(variRefB_, M_, N_).adj() += adjB; - } -}; - -template -class mdivide_left_spd_vd_vari : public vari { - public: - int M_; // A.rows() = A.cols() = B.rows() - int N_; // B.cols() - vari **variRefA_; - vari **variRefC_; - mdivide_left_spd_alloc *alloc_; - - mdivide_left_spd_vd_vari(const Eigen::Matrix &A, - const Eigen::Matrix &B) - : vari(0.0), - M_(A.rows()), - N_(B.cols()), - variRefA_(reinterpret_cast( - ChainableStack::instance_->memalloc_.alloc(sizeof(vari *) * A.rows() - * A.cols()))), - variRefC_(reinterpret_cast( - ChainableStack::instance_->memalloc_.alloc(sizeof(vari *) * B.rows() - * B.cols()))), - alloc_(new mdivide_left_spd_alloc()) { - Eigen::Map(variRefA_, M_, M_) = A.vi(); - alloc_->llt_ = A.val().llt(); - check_pos_definite("mdivide_left_spd", "A", alloc_->llt_); - alloc_->C_ = alloc_->llt_.solve(B); - - Eigen::Map(variRefC_, M_, N_) - = alloc_->C_.unaryExpr([](double x) { return new vari(x, false); }); - } + using A_ref_t = ref_type_t; + using B_ref_t = ref_type_t; + + A_ref_t A_ref = A; + B_ref_t B_ref = B; + + check_not_nan("mdivide_left_spd", "A", A_ref); - virtual void chain() { - matrix_d adjC = Eigen::Map(variRefC_, M_, N_).adj(); - Eigen::Map(variRefA_, M_, M_).adj() - -= alloc_->llt_.solve(adjC * alloc_->C_.transpose()); - } -}; -} // namespace internal - -template < - typename EigMat1, typename EigMat2, - require_all_eigen_matrix_base_vt * = nullptr> -inline Eigen::Matrix -mdivide_left_spd(const EigMat1 &A, const EigMat2 &b) { - constexpr int R1 = EigMat1::RowsAtCompileTime; - constexpr int C1 = EigMat1::ColsAtCompileTime; - constexpr int R2 = EigMat2::RowsAtCompileTime; - constexpr int C2 = EigMat2::ColsAtCompileTime; - static const char *function = "mdivide_left_spd"; - check_multiplicable(function, "A", A, "b", b); - const auto &A_ref = to_ref(A); - check_symmetric(function, "A", A_ref); - check_not_nan(function, "A", A_ref); if (A.size() == 0) { - return {0, b.cols()}; + return {0, B.cols()}; } - // NOTE: this is not a memory leak, this vari is used in the - // expression graph to evaluate the adjoint, but is not needed - // for the returned matrix. Memory will be cleaned up with the - // arena allocator. - internal::mdivide_left_spd_vv_vari *baseVari - = new internal::mdivide_left_spd_vv_vari(A_ref, b); + arena_matrix> arena_A; + arena_matrix> arena_B; - Eigen::Matrix res(b.rows(), b.cols()); - res.vi() = Eigen::Map(&baseVari->variRefC_[0], b.rows(), b.cols()); - return res; -} + if (!is_constant::value) { + arena_A = A_ref; + } -template * = nullptr, - require_eigen_matrix_base_vt * = nullptr> -inline Eigen::Matrix -mdivide_left_spd(const EigMat1 &A, const EigMat2 &b) { - constexpr int R1 = EigMat1::RowsAtCompileTime; - constexpr int C1 = EigMat1::ColsAtCompileTime; - constexpr int R2 = EigMat2::RowsAtCompileTime; - constexpr int C2 = EigMat2::ColsAtCompileTime; - static const char *function = "mdivide_left_spd"; - check_multiplicable(function, "A", A, "b", b); - const auto &A_ref = to_ref(A); - check_symmetric(function, "A", A_ref); - check_not_nan(function, "A", A_ref); - if (A.size() == 0) { - return {0, b.cols()}; + if (!is_constant::value) { + arena_B = B_ref; } - // NOTE: this is not a memory leak, this vari is used in the - // expression graph to evaluate the adjoint, but is not needed - // for the returned matrix. Memory will be cleaned up with the - // arena allocator. - internal::mdivide_left_spd_vd_vari *baseVari - = new internal::mdivide_left_spd_vd_vari(A_ref, b); + auto A_llt = value_of(A_ref).llt(); + check_pos_definite("mdivide_left_spd", "A", A_llt); - Eigen::Matrix res(b.rows(), b.cols()); - res.vi() = Eigen::Map(&baseVari->variRefC_[0], b.rows(), b.cols()); - return res; -} + arena_matrix arena_A_llt(A.rows(), A.cols()); + arena_A_llt.template triangularView() = A_llt.matrixL(); + arena_A_llt.template triangularView() = arena_A_llt.transpose(); -template * = nullptr, - require_eigen_matrix_base_vt * = nullptr> -inline Eigen::Matrix -mdivide_left_spd(const EigMat1 &A, const EigMat2 &b) { - constexpr int R1 = EigMat1::RowsAtCompileTime; - constexpr int C1 = EigMat1::ColsAtCompileTime; - constexpr int R2 = EigMat2::RowsAtCompileTime; - constexpr int C2 = EigMat2::ColsAtCompileTime; - static const char *function = "mdivide_left_spd"; - check_multiplicable(function, "A", A, "b", b); - const auto &A_ref = to_ref(A); - check_symmetric(function, "A", A_ref); - check_not_nan(function, "A", A_ref); - if (A.size() == 0) { - return {0, b.cols()}; - } + arena_matrix> + res = A_llt.solve(value_of(B_ref)); + + reverse_pass_callback([arena_A, arena_B, arena_A_llt, res]() mutable { + Eigen::Matrix + adjB = res.adj(); + + arena_A_llt.template triangularView().solveInPlace(adjB); + arena_A_llt.template triangularView().solveInPlace(adjB); - // NOTE: this is not a memory leak, this vari is used in the - // expression graph to evaluate the adjoint, but is not needed - // for the returned matrix. Memory will be cleaned up with the - // arena allocator. - internal::mdivide_left_spd_dv_vari *baseVari - = new internal::mdivide_left_spd_dv_vari(A_ref, b); + if(!is_constant::value) + forward_as>(arena_A).adj() += + -adjB * res.val().transpose().eval(); - Eigen::Matrix res(b.rows(), b.cols()); - res.vi() = Eigen::Map(&baseVari->variRefC_[0], b.rows(), b.cols()); + if (!is_constant::value) + forward_as>(arena_B).adj() += adjB; + }); return res; } diff --git a/stan/math/rev/fun/mdivide_left_tri.hpp b/stan/math/rev/fun/mdivide_left_tri.hpp index 5858cace163..d541f1463ad 100644 --- a/stan/math/rev/fun/mdivide_left_tri.hpp +++ b/stan/math/rev/fun/mdivide_left_tri.hpp @@ -286,7 +286,7 @@ class mdivide_left_tri_vd_vari : public vari { #endif adjA.noalias() = -Map >(A_, M_, M_) - .template triangularView() + .template triangularView() .transpose() .solve(adjC * Map >(C_, M_, N_).transpose()); @@ -312,79 +312,52 @@ class mdivide_left_tri_vd_vari : public vari { } // namespace internal template * = nullptr> + require_all_eigen_t* = nullptr, + require_any_vt_var* = nullptr> inline Eigen::Matrix -mdivide_left_tri(const T1 &A, const T2 &b) { +mdivide_left_tri(const T1& A, const T2& B) { check_square("mdivide_left_tri", "A", A); - check_multiplicable("mdivide_left_tri", "A", A, "b", b); - if (A.rows() == 0) { - return {0, b.cols()}; + check_multiplicable("mdivide_left_tri", "A", A, "B", B); + if (A.size() == 0) { + return {0, B.cols()}; } - // NOTE: this is not a memory leak, this vari is used in the - // expression graph to evaluate the adjoint, but is not needed - // for the returned matrix. Memory will be cleaned up with the - // arena allocator. - auto *baseVari = new internal::mdivide_left_tri_vv_vari< - TriView, T1::RowsAtCompileTime, T1::ColsAtCompileTime, - T2::RowsAtCompileTime, T2::ColsAtCompileTime>(A, b); - - Eigen::Matrix res( - b.rows(), b.cols()); - res.vi() - = Eigen::Map(&(baseVari->variRefC_[0]), b.rows(), b.cols()); + using A_ref_t = ref_type_t; + using B_ref_t = ref_type_t; - return res; -} -template * = nullptr, - require_eigen_vt * = nullptr> -inline Eigen::Matrix -mdivide_left_tri(const T1 &A, const T2 &b) { - check_square("mdivide_left_tri", "A", A); - check_multiplicable("mdivide_left_tri", "A", A, "b", b); - if (A.rows() == 0) { - return {0, b.cols()}; - } + A_ref_t A_ref = A; + B_ref_t B_ref = B; - // NOTE: this is not a memory leak, this vari is used in the - // expression graph to evaluate the adjoint, but is not needed - // for the returned matrix. Memory will be cleaned up with the - // arena allocator. - auto *baseVari = new internal::mdivide_left_tri_dv_vari< - TriView, T1::RowsAtCompileTime, T1::ColsAtCompileTime, - T2::RowsAtCompileTime, T2::ColsAtCompileTime>(A, b); + arena_matrix> arena_A; + arena_matrix> arena_B; - Eigen::Matrix res( - b.rows(), b.cols()); - res.vi() - = Eigen::Map(&(baseVari->variRefC_[0]), b.rows(), b.cols()); + if (!is_constant::value) { + arena_A = A_ref; + } - return res; -} -template * = nullptr, - require_eigen_vt * = nullptr> -inline Eigen::Matrix -mdivide_left_tri(const T1 &A, const T2 &b) { - check_square("mdivide_left_tri", "A", A); - check_multiplicable("mdivide_left_tri", "A", A, "b", b); - if (A.rows() == 0) { - return {0, b.cols()}; + if (!is_constant::value) { + arena_B = B_ref; } - // NOTE: this is not a memory leak, this vari is used in the - // expression graph to evaluate the adjoint, but is not needed - // for the returned matrix. Memory will be cleaned up with the - // arena allocator. - auto *baseVari = new internal::mdivide_left_tri_vd_vari< - TriView, T1::RowsAtCompileTime, T1::ColsAtCompileTime, - T2::RowsAtCompileTime, T2::ColsAtCompileTime>(A, b); + arena_matrix arena_A_val = + value_of(A_ref).template triangularView(); + arena_matrix> + res = arena_A_val.template triangularView() + .solve(value_of(B_ref)); + + reverse_pass_callback([arena_A, arena_B, arena_A_val, res]() mutable { + Eigen::Matrix + adjB = arena_A_val.template triangularView() + .transpose() + .solve(res.adj()); - Eigen::Matrix res( - b.rows(), b.cols()); - res.vi() - = Eigen::Map(&(baseVari->variRefC_[0]), b.rows(), b.cols()); + if (!is_constant::value) + forward_as>(arena_B).adj() += adjB; + + if(!is_constant::value) + forward_as>(arena_A).adj() += + (-adjB * res.val().transpose().eval()).template triangularView(); + }); return res; } diff --git a/test/unit/math/rev/fun/log_softmax_test.cpp b/test/unit/math/rev/fun/log_softmax_test.cpp new file mode 100644 index 00000000000..3dbb1068fe4 --- /dev/null +++ b/test/unit/math/rev/fun/log_softmax_test.cpp @@ -0,0 +1,34 @@ +#include +#include +#include +#include + +TEST(log_sum_exp_tests, large_values) { + using stan::math::var; + + Eigen::VectorXd x = Eigen::VectorXd::Random(5); + stan::math::promote_scalar_t xv = x; + + auto y = stan::math::log_softmax(xv); + auto y_ref = stan::math::log(stan::math::softmax(xv)); + + for(size_t i = 0; i < 1/*y.size()*/; ++i) { + stan::math::set_zero_all_adjoints(); + y(i).grad(); + auto xadj1 = xv.adj().eval(); + + stan::math::set_zero_all_adjoints(); + y_ref(i).grad(); + auto xadj2 = xv.adj().eval(); + + EXPECT_FLOAT_EQ(y(i).val(), y_ref(i).val()) << + "values y_" << i << " not equal" << std::endl << + "values: " << y(i).val() << ", reference: " << y_ref(i).val() << std::endl; + + for(size_t j = 0; j < xadj1.size(); ++j) { + EXPECT_FLOAT_EQ(xadj1(j), xadj2(j)) << + "gradients dy_" << i << "/dx_" << j << " not equal" << std::endl << + "gradient: " << xadj1(j) << ", reference: " << xadj2(j) << std::endl; + } + } +} diff --git a/test/unit/math/rev/fun/matrix_power_test.cpp b/test/unit/math/rev/fun/matrix_power_test.cpp new file mode 100644 index 00000000000..3d2d128ebbd --- /dev/null +++ b/test/unit/math/rev/fun/matrix_power_test.cpp @@ -0,0 +1,23 @@ +#include +#include +#include +#include + +TEST(AgradRev, matrix_power_rev) { + using stan::math::var; + + Eigen::Matrix x = Eigen::MatrixXd::Random(1, 1); + + stan::math::set_zero_all_adjoints(); + auto y = stan::math::matrix_power(x, 2); + y(0, 0).grad(); + + auto adj = x.adj().eval(); + + stan::math::set_zero_all_adjoints(); + auto y_ref = stan::math::pow(x(0, 0), 2); + y_ref.grad(); + + EXPECT_FLOAT_EQ(y(0, 0).val(), y_ref.val()); + EXPECT_FLOAT_EQ(adj(0, 0), x.adj()(0, 0)); +} diff --git a/test/unit/math/rev/fun/mdivide_left_test.cpp b/test/unit/math/rev/fun/mdivide_left_test.cpp new file mode 100644 index 00000000000..9395bdc3572 --- /dev/null +++ b/test/unit/math/rev/fun/mdivide_left_test.cpp @@ -0,0 +1,28 @@ +#include +#include +#include +#include + +TEST(AgradRev, mdivide_left_rev) { + using stan::math::var; + + Eigen::Matrix A(2, 2); + A << 1.5, 0.7, + 0.3, 1.2; + Eigen::Matrix B(2); + B << 1.1, + -1.2; + + stan::math::set_zero_all_adjoints(); + var y = sum(mdivide_left(A, B)); + y.grad(); + + auto adj = A.adj().eval(); + + stan::math::set_zero_all_adjoints(); + var y_ref = sum(multiply(inverse(A), B)); + y_ref.grad(); + + EXPECT_FLOAT_EQ(y.val(), y_ref.val()); + EXPECT_FLOAT_EQ(adj(0, 0), A.adj()(0, 0)); +} diff --git a/test/unit/math/rev/fun/mdivide_left_tri_test.cpp b/test/unit/math/rev/fun/mdivide_left_tri_test.cpp index 42ff29f0fdb..06dca4d4276 100644 --- a/test/unit/math/rev/fun/mdivide_left_tri_test.cpp +++ b/test/unit/math/rev/fun/mdivide_left_tri_test.cpp @@ -4,6 +4,30 @@ #include #include +TEST(AgradRev, mdivide_left_tri_rev) { + using stan::math::var; + + Eigen::Matrix A(2, 2); + A << 1.5, 0.5, + 0.0, 1.2; + Eigen::Matrix B(2); + B << 1.1, + -1.2; + + stan::math::set_zero_all_adjoints(); + var y = sum(stan::math::mdivide_left_tri(A, B)); + y.grad(); + + auto adj = A.adj().eval(); + + stan::math::set_zero_all_adjoints(); + var y_ref = sum(multiply(inverse(A), B)); + y_ref.grad(); + + EXPECT_FLOAT_EQ(y.val(), y_ref.val()); + EXPECT_FLOAT_EQ(adj(0, 0), A.adj()(0, 0)); +} + // TODO(carpenter): move this to test framework; should be able to put // all this GPU config into the functor // TODO(carpenter): safer cleanup on resetting tuning_opts From 238ec78a217eeab234b1cb398c6ff851f9395c27 Mon Sep 17 00:00:00 2001 From: Stan Jenkins Date: Mon, 31 Aug 2020 19:45:22 -0400 Subject: [PATCH 240/355] [Jenkins] auto-formatting by clang-format version 6.0.1-14 (tags/RELEASE_601/final) --- stan/math/rev/fun/matrix_power.hpp | 23 ++++++------ stan/math/rev/fun/mdivide_left.hpp | 17 ++++----- stan/math/rev/fun/mdivide_left_spd.hpp | 19 +++++----- stan/math/rev/fun/mdivide_left_tri.hpp | 36 +++++++++---------- test/unit/math/rev/fun/log_softmax_test.cpp | 18 +++++----- test/unit/math/rev/fun/matrix_power_test.cpp | 3 +- test/unit/math/rev/fun/mdivide_left_test.cpp | 8 ++--- .../math/rev/fun/mdivide_left_tri_test.cpp | 8 ++--- 8 files changed, 64 insertions(+), 68 deletions(-) diff --git a/stan/math/rev/fun/matrix_power.hpp b/stan/math/rev/fun/matrix_power.hpp index 5d44ac37ce1..4b7f39ed1d9 100644 --- a/stan/math/rev/fun/matrix_power.hpp +++ b/stan/math/rev/fun/matrix_power.hpp @@ -26,41 +26,42 @@ namespace math { * square. */ template * = nullptr> -inline Eigen::Matrix -matrix_power(const T& M, const int n) { +inline Eigen::Matrix matrix_power( + const T& M, const int n) { const auto& M_ref = to_ref(M); check_square("matrix_power", "M", M); check_nonnegative("matrix_power", "n", n); check_finite("matrix_power", "M", M_ref); - if(M.size() == 0) + if (M.size() == 0) return {}; size_t N = M.rows(); - if(n == 0) + if (n == 0) return Eigen::MatrixXd::Identity(N, N); - if(n == 1) + if (n == 1) return M_ref; - + arena_t> powers(n + 1); - arena_matrix> arena_M = M_ref; + arena_matrix> arena_M + = M_ref; powers[0] = Eigen::MatrixXd::Identity(N, N); powers[1] = value_of(M_ref); - for(size_t i = 2; i <= n; ++i) { + for (size_t i = 2; i <= n; ++i) { powers[i] = powers[1] * powers[i - 1]; } - arena_matrix> res = - powers[powers.size() - 1]; + arena_matrix> res + = powers[powers.size() - 1]; reverse_pass_callback([arena_M, n, N, res, powers]() mutable { const auto& M_val = powers[1]; Eigen::MatrixXd adj_C = res.adj(); Eigen::MatrixXd adj_M = Eigen::MatrixXd::Zero(N, N); - for(size_t i = n; i > 1; --i) { + for (size_t i = n; i > 1; --i) { adj_M += adj_C * powers[i - 1].transpose(); adj_C = (M_val.transpose() * adj_C).eval(); } diff --git a/stan/math/rev/fun/mdivide_left.hpp b/stan/math/rev/fun/mdivide_left.hpp index 5a8f5e49fd8..a8e93c9839f 100644 --- a/stan/math/rev/fun/mdivide_left.hpp +++ b/stan/math/rev/fun/mdivide_left.hpp @@ -12,8 +12,7 @@ namespace stan { namespace math { -template * = nullptr, +template * = nullptr, require_any_vt_var* = nullptr> inline Eigen::Matrix mdivide_left(const T1& A, const T2& B) { @@ -42,17 +41,15 @@ mdivide_left(const T1& A, const T2& B) { arena_matrix arena_A_val = value_of(A_ref); arena_matrix> - res = arena_A_val.colPivHouseholderQr().solve(value_of(B_ref)); + res = arena_A_val.colPivHouseholderQr().solve(value_of(B_ref)); reverse_pass_callback([arena_A, arena_B, arena_A_val, res]() mutable { - Eigen::Matrix - adjB = arena_A_val.transpose() - .colPivHouseholderQr() - .solve(res.adj()); + Eigen::Matrix adjB + = arena_A_val.transpose().colPivHouseholderQr().solve(res.adj()); - if(!is_constant::value) - forward_as>(arena_A).adj() += - -adjB * res.val().transpose().eval(); + if (!is_constant::value) + forward_as>(arena_A).adj() + += -adjB * res.val().transpose().eval(); if (!is_constant::value) forward_as>(arena_B).adj() += adjB; diff --git a/stan/math/rev/fun/mdivide_left_spd.hpp b/stan/math/rev/fun/mdivide_left_spd.hpp index fd2ce4ed410..c9c0652fe11 100644 --- a/stan/math/rev/fun/mdivide_left_spd.hpp +++ b/stan/math/rev/fun/mdivide_left_spd.hpp @@ -13,8 +13,7 @@ namespace stan { namespace math { -template * = nullptr, +template * = nullptr, require_any_vt_var* = nullptr> inline Eigen::Matrix mdivide_left_spd(const T1& A, const T2& B) { @@ -26,7 +25,7 @@ mdivide_left_spd(const T1& A, const T2& B) { A_ref_t A_ref = A; B_ref_t B_ref = B; - + check_not_nan("mdivide_left_spd", "A", A_ref); if (A.size() == 0) { @@ -49,21 +48,21 @@ mdivide_left_spd(const T1& A, const T2& B) { arena_matrix arena_A_llt(A.rows(), A.cols()); arena_A_llt.template triangularView() = A_llt.matrixL(); - arena_A_llt.template triangularView() = arena_A_llt.transpose(); + arena_A_llt.template triangularView() = arena_A_llt.transpose(); arena_matrix> - res = A_llt.solve(value_of(B_ref)); + res = A_llt.solve(value_of(B_ref)); reverse_pass_callback([arena_A, arena_B, arena_A_llt, res]() mutable { - Eigen::Matrix - adjB = res.adj(); + Eigen::Matrix adjB + = res.adj(); arena_A_llt.template triangularView().solveInPlace(adjB); arena_A_llt.template triangularView().solveInPlace(adjB); - if(!is_constant::value) - forward_as>(arena_A).adj() += - -adjB * res.val().transpose().eval(); + if (!is_constant::value) + forward_as>(arena_A).adj() + += -adjB * res.val().transpose().eval(); if (!is_constant::value) forward_as>(arena_B).adj() += adjB; diff --git a/stan/math/rev/fun/mdivide_left_tri.hpp b/stan/math/rev/fun/mdivide_left_tri.hpp index d541f1463ad..e3af105357d 100644 --- a/stan/math/rev/fun/mdivide_left_tri.hpp +++ b/stan/math/rev/fun/mdivide_left_tri.hpp @@ -285,11 +285,11 @@ class mdivide_left_tri_vd_vari : public vari { } else { #endif adjA.noalias() - = -Map >(A_, M_, M_) - .template triangularView() + = -Map>(A_, M_, M_) + .template triangularView() .transpose() .solve(adjC - * Map >(C_, M_, N_).transpose()); + * Map>(C_, M_, N_).transpose()); #ifdef STAN_OPENCL } #endif @@ -312,10 +312,10 @@ class mdivide_left_tri_vd_vari : public vari { } // namespace internal template * = nullptr, - require_any_vt_var* = nullptr> + require_all_eigen_t * = nullptr, + require_any_vt_var * = nullptr> inline Eigen::Matrix -mdivide_left_tri(const T1& A, const T2& B) { +mdivide_left_tri(const T1 &A, const T2 &B) { check_square("mdivide_left_tri", "A", A); check_multiplicable("mdivide_left_tri", "A", A, "B", B); if (A.size() == 0) { @@ -339,24 +339,24 @@ mdivide_left_tri(const T1& A, const T2& B) { arena_B = B_ref; } - arena_matrix arena_A_val = - value_of(A_ref).template triangularView(); + arena_matrix arena_A_val + = value_of(A_ref).template triangularView(); arena_matrix> - res = arena_A_val.template triangularView() - .solve(value_of(B_ref)); + res + = arena_A_val.template triangularView().solve(value_of(B_ref)); reverse_pass_callback([arena_A, arena_B, arena_A_val, res]() mutable { - Eigen::Matrix - adjB = arena_A_val.template triangularView() - .transpose() - .solve(res.adj()); + Eigen::Matrix adjB + = arena_A_val.template triangularView().transpose().solve( + res.adj()); if (!is_constant::value) forward_as>(arena_B).adj() += adjB; - - if(!is_constant::value) - forward_as>(arena_A).adj() += - (-adjB * res.val().transpose().eval()).template triangularView(); + + if (!is_constant::value) + forward_as>(arena_A).adj() + += (-adjB * res.val().transpose().eval()) + .template triangularView(); }); return res; diff --git a/test/unit/math/rev/fun/log_softmax_test.cpp b/test/unit/math/rev/fun/log_softmax_test.cpp index 3dbb1068fe4..2ea40bacbf0 100644 --- a/test/unit/math/rev/fun/log_softmax_test.cpp +++ b/test/unit/math/rev/fun/log_softmax_test.cpp @@ -12,7 +12,7 @@ TEST(log_sum_exp_tests, large_values) { auto y = stan::math::log_softmax(xv); auto y_ref = stan::math::log(stan::math::softmax(xv)); - for(size_t i = 0; i < 1/*y.size()*/; ++i) { + for (size_t i = 0; i < 1 /*y.size()*/; ++i) { stan::math::set_zero_all_adjoints(); y(i).grad(); auto xadj1 = xv.adj().eval(); @@ -21,14 +21,16 @@ TEST(log_sum_exp_tests, large_values) { y_ref(i).grad(); auto xadj2 = xv.adj().eval(); - EXPECT_FLOAT_EQ(y(i).val(), y_ref(i).val()) << - "values y_" << i << " not equal" << std::endl << - "values: " << y(i).val() << ", reference: " << y_ref(i).val() << std::endl; + EXPECT_FLOAT_EQ(y(i).val(), y_ref(i).val()) + << "values y_" << i << " not equal" << std::endl + << "values: " << y(i).val() << ", reference: " << y_ref(i).val() + << std::endl; - for(size_t j = 0; j < xadj1.size(); ++j) { - EXPECT_FLOAT_EQ(xadj1(j), xadj2(j)) << - "gradients dy_" << i << "/dx_" << j << " not equal" << std::endl << - "gradient: " << xadj1(j) << ", reference: " << xadj2(j) << std::endl; + for (size_t j = 0; j < xadj1.size(); ++j) { + EXPECT_FLOAT_EQ(xadj1(j), xadj2(j)) + << "gradients dy_" << i << "/dx_" << j << " not equal" << std::endl + << "gradient: " << xadj1(j) << ", reference: " << xadj2(j) + << std::endl; } } } diff --git a/test/unit/math/rev/fun/matrix_power_test.cpp b/test/unit/math/rev/fun/matrix_power_test.cpp index 3d2d128ebbd..82b7dc3c94e 100644 --- a/test/unit/math/rev/fun/matrix_power_test.cpp +++ b/test/unit/math/rev/fun/matrix_power_test.cpp @@ -6,7 +6,8 @@ TEST(AgradRev, matrix_power_rev) { using stan::math::var; - Eigen::Matrix x = Eigen::MatrixXd::Random(1, 1); + Eigen::Matrix x + = Eigen::MatrixXd::Random(1, 1); stan::math::set_zero_all_adjoints(); auto y = stan::math::matrix_power(x, 2); diff --git a/test/unit/math/rev/fun/mdivide_left_test.cpp b/test/unit/math/rev/fun/mdivide_left_test.cpp index 9395bdc3572..5781730dd6e 100644 --- a/test/unit/math/rev/fun/mdivide_left_test.cpp +++ b/test/unit/math/rev/fun/mdivide_left_test.cpp @@ -7,12 +7,10 @@ TEST(AgradRev, mdivide_left_rev) { using stan::math::var; Eigen::Matrix A(2, 2); - A << 1.5, 0.7, - 0.3, 1.2; + A << 1.5, 0.7, 0.3, 1.2; Eigen::Matrix B(2); - B << 1.1, - -1.2; - + B << 1.1, -1.2; + stan::math::set_zero_all_adjoints(); var y = sum(mdivide_left(A, B)); y.grad(); diff --git a/test/unit/math/rev/fun/mdivide_left_tri_test.cpp b/test/unit/math/rev/fun/mdivide_left_tri_test.cpp index 06dca4d4276..9bee3d13a51 100644 --- a/test/unit/math/rev/fun/mdivide_left_tri_test.cpp +++ b/test/unit/math/rev/fun/mdivide_left_tri_test.cpp @@ -8,12 +8,10 @@ TEST(AgradRev, mdivide_left_tri_rev) { using stan::math::var; Eigen::Matrix A(2, 2); - A << 1.5, 0.5, - 0.0, 1.2; + A << 1.5, 0.5, 0.0, 1.2; Eigen::Matrix B(2); - B << 1.1, - -1.2; - + B << 1.1, -1.2; + stan::math::set_zero_all_adjoints(); var y = sum(stan::math::mdivide_left_tri(A, B)); y.grad(); From 62dfc61752298a5ebc2a5b3a7e74e6eecb40f086 Mon Sep 17 00:00:00 2001 From: Ben Date: Tue, 1 Sep 2020 18:37:38 -0400 Subject: [PATCH 241/355] Added some more functions (Issue #2018) --- stan/math/rev/fun/multiply.hpp | 14 +-- stan/math/rev/fun/sd.hpp | 41 +++---- stan/math/rev/fun/squared_distance.hpp | 162 ++++++++----------------- stan/math/rev/fun/variance.hpp | 70 ++++------- 4 files changed, 99 insertions(+), 188 deletions(-) diff --git a/stan/math/rev/fun/multiply.hpp b/stan/math/rev/fun/multiply.hpp index 7498a5db7e8..63c4ff3ec6b 100644 --- a/stan/math/rev/fun/multiply.hpp +++ b/stan/math/rev/fun/multiply.hpp @@ -37,8 +37,8 @@ multiply_impl(const T1& A, const T2& B) { check_not_nan("multiply", "A", A_ref); check_not_nan("multiply", "B", B_ref); - arena_matrix> arena_A_val = value_of(A_ref); - arena_matrix> arena_B_val = value_of(B_ref); + arena_matrix> arena_A_val; + arena_matrix> arena_B_val; arena_matrix> arena_A; arena_matrix> arena_B; @@ -56,12 +56,12 @@ multiply_impl(const T1& A, const T2& B) { arena_matrix> res; - if (!is_constant::value) { - res = arena_A_val * arena_B_val; - } else if (!is_constant::value) { - res = value_of(A_ref) * arena_B_val; - } else if (!is_constant::value) { + if(is_constant::value) { res = arena_A_val * value_of(B_ref); + } else if(is_constant::value) { + res = value_of(A_ref) * arena_B_val; + } else { + res = arena_A_val * arena_B_val; } reverse_pass_callback( diff --git a/stan/math/rev/fun/sd.hpp b/stan/math/rev/fun/sd.hpp index 83cbd52fe99..2dd778f3fff 100644 --- a/stan/math/rev/fun/sd.hpp +++ b/stan/math/rev/fun/sd.hpp @@ -3,6 +3,8 @@ #include #include +#include +#include #include #include #include @@ -30,32 +32,23 @@ var sd(const T& m) { return 0; } - return apply_vector_unary::reduce(m, [](const auto& dtrs_map) { - using std::sqrt; - using T_map = std::decay_t; - using T_vi = promote_scalar_t; - using T_d = promote_scalar_t; - vari** varis = ChainableStack::instance_->memalloc_.alloc_array( - dtrs_map.size()); - double* partials = ChainableStack::instance_->memalloc_.alloc_array( - dtrs_map.size()); - Eigen::Map varis_map(varis, dtrs_map.rows(), dtrs_map.cols()); - Eigen::Map partials_map(partials, dtrs_map.rows(), dtrs_map.cols()); + return apply_vector_unary::reduce(m, [](const auto& x) { + const auto& x_ref = to_ref(x); + arena_t arena_x = x_ref; + const auto& x_val = to_ref(value_of(x)); + double mean = x_val.mean(); + arena_matrix> + arena_diff = x_val.array() - mean; + double sum_of_squares = arena_diff.squaredNorm(); + double sd = sqrt(sum_of_squares / (x.size() - 1)); - varis_map = dtrs_map.vi(); - T_d dtrs_val = dtrs_map.val(); - double mean = dtrs_val.mean(); - T_d diff = dtrs_val.array() - mean; - double sum_of_squares = diff.squaredNorm(); - double size_m1 = dtrs_map.size() - 1; - double sd = sqrt(sum_of_squares / size_m1); + var res = sd; - if (sum_of_squares < 1e-20) { - partials_map.fill(inv_sqrt(static_cast(dtrs_map.size()))); - } else { - partials_map = diff.array() / (sd * size_m1); - } - return var(new stored_gradient_vari(sd, dtrs_map.size(), varis, partials)); + reverse_pass_callback([arena_x, res, arena_diff]() mutable { + arena_x.adj() += (res.adj() / (res.val() * (arena_x.size() - 1))) * arena_diff; + }); + + return res; }); } diff --git a/stan/math/rev/fun/squared_distance.hpp b/stan/math/rev/fun/squared_distance.hpp index 39655f6c08b..2ea1eb90413 100644 --- a/stan/math/rev/fun/squared_distance.hpp +++ b/stan/math/rev/fun/squared_distance.hpp @@ -13,131 +13,69 @@ namespace stan { namespace math { -class scal_squared_distance_vv_vari : public op_vv_vari { - public: - scal_squared_distance_vv_vari(vari* avi, vari* bvi) - : op_vv_vari(squared_distance(avi->val_, bvi->val_), avi, bvi) {} - void chain() { - double diff = avi_->val_ - bvi_->val_; - avi_->adj_ += adj_ * 2.0 * diff; - bvi_->adj_ -= adj_ * 2.0 * diff; - } -}; -class scal_squared_distance_vd_vari : public op_vd_vari { - public: - scal_squared_distance_vd_vari(vari* avi, double b) - : op_vd_vari(squared_distance(avi->val_, b), avi, b) {} - void chain() { avi_->adj_ += adj_ * 2 * (avi_->val_ - bd_); } -}; - /** * Returns the squared distance. */ -inline var squared_distance(const var& a, const var& b) { - return {new scal_squared_distance_vv_vari(a.vi_, b.vi_)}; +template * = nullptr, + require_any_var_t* = nullptr> +inline var squared_distance(const T1& a, const T2& b) { + double diff = value_of(a) - value_of(b); + var res = squared_distance(value_of(a), value_of(b)); + reverse_pass_callback( + [a, b, diff, res]() mutable { + if (!is_constant::value) + forward_as(a).adj() += 2.0 * res.adj() * diff; + + if (!is_constant::value) + forward_as(b).adj() += -2.0 * res.adj() * diff; + }); + return res; } -/** - * Returns the squared distance. - */ -inline var squared_distance(const var& a, double b) { - return {new scal_squared_distance_vd_vari(a.vi_, b)}; -} +template * = nullptr, + require_any_vt_var* = nullptr> +inline var squared_distance(const T1& A, const T2& B) { + check_matching_sizes("squared_distance", "A", A, "B", B); -/** - * Returns the squared distance. - */ -inline var squared_distance(double a, const var& b) { - return {new scal_squared_distance_vd_vari(b.vi_, a)}; -} + if(A.size() == 0) + return 0.0; + + using A_ref_t = ref_type_t; + using B_ref_t = ref_type_t; -namespace internal { - -class squared_distance_vv_vari : public vari { - protected: - vari** v1_; - vari** v2_; - size_t length_; - - public: - template < - typename EigVecVar1, typename EigVecVar2, - require_all_eigen_vector_vt* = nullptr> - squared_distance_vv_vari(const EigVecVar1& v1, const EigVecVar2& v2) - : vari((as_column_vector_or_scalar(v1).val() - - as_column_vector_or_scalar(v2).val()) - .squaredNorm()), - length_(v1.size()) { - v1_ = reinterpret_cast( - ChainableStack::instance_->memalloc_.alloc(length_ * sizeof(vari*))); - v2_ = reinterpret_cast( - ChainableStack::instance_->memalloc_.alloc(length_ * sizeof(vari*))); - Eigen::Map(v1_, length_) = v1.vi(); - Eigen::Map(v2_, length_) = v2.vi(); - } + A_ref_t A_ref = A; + B_ref_t B_ref = B; - virtual void chain() { - Eigen::Map v1_map(v1_, length_); - Eigen::Map v2_map(v2_, length_); - vector_d di = 2 * adj_ * (v1_map.val() - v2_map.val()); - v1_map.adj() += di; - v2_map.adj() -= di; - } -}; - -class squared_distance_vd_vari : public vari { - protected: - vari** v1_; - double* v2_; - size_t length_; - - public: - template * = nullptr, - require_eigen_vector_vt* = nullptr> - squared_distance_vd_vari(const EigVecVar& v1, const EigVecArith& v2) - : vari((as_column_vector_or_scalar(v1).val() - - as_column_vector_or_scalar(v2)) - .squaredNorm()), - length_(v1.size()) { - v1_ = reinterpret_cast( - ChainableStack::instance_->memalloc_.alloc(length_ * sizeof(vari*))); - v2_ = reinterpret_cast( - ChainableStack::instance_->memalloc_.alloc(length_ * sizeof(double))); - Eigen::Map(v1_, length_) = v1.vi(); - Eigen::Map(v2_, length_) = v2; + auto A_col = as_column_vector_or_scalar(A_ref); + auto B_col = as_column_vector_or_scalar(B_ref); + + auto arena_diff_val = to_arena(value_of(A_col) - value_of(B_col)); + + arena_matrix> arena_A; + arena_matrix> arena_B; + + if (!is_constant::value) { + arena_A = A_col; } - virtual void chain() { - Eigen::Map v1_map(v1_, length_); - v1_map.adj() - += 2 * adj_ * (v1_map.val() - Eigen::Map(v2_, length_)); + if (!is_constant::value) { + arena_B = B_col; } -}; -} // namespace internal - -template < - typename EigVecVar1, typename EigVecVar2, - require_all_eigen_vector_vt* = nullptr> -inline var squared_distance(const EigVecVar1& v1, const EigVecVar2& v2) { - check_matching_sizes("squared_distance", "v1", v1, "v2", v2); - return {new internal::squared_distance_vv_vari(to_ref(v1), to_ref(v2))}; -} -template * = nullptr, - require_eigen_vector_vt* = nullptr> -inline var squared_distance(const EigVecVar& v1, const EigVecArith& v2) { - check_matching_sizes("squared_distance", "v1", v1, "v2", v2); - return {new internal::squared_distance_vd_vari(to_ref(v1), to_ref(v2))}; -} + var res = arena_diff_val.squaredNorm(); + + reverse_pass_callback( + [arena_A, arena_B, arena_diff_val, res]() mutable { + if (!is_constant::value) + arena_A.adj() += 2.0 * res.adj() * arena_diff_val; + + if (!is_constant::value) + arena_B.adj() += -2.0 * res.adj() * arena_diff_val; + }); -template * = nullptr, - require_eigen_vector_vt* = nullptr> -inline var squared_distance(const EigVecArith& v1, const EigVecVar& v2) { - check_matching_sizes("squared_distance", "v1", v1, "v2", v2); - return {new internal::squared_distance_vd_vari(to_ref(v2), to_ref(v1))}; + return res; } } // namespace math diff --git a/stan/math/rev/fun/variance.hpp b/stan/math/rev/fun/variance.hpp index 6fe7e2b73bb..117a1ef1d48 100644 --- a/stan/math/rev/fun/variance.hpp +++ b/stan/math/rev/fun/variance.hpp @@ -11,59 +11,39 @@ namespace stan { namespace math { -namespace internal { - -inline var calc_variance(size_t size, const var* dtrs) { - vari** varis = ChainableStack::instance_->memalloc_.alloc_array(size); - double* partials - = ChainableStack::instance_->memalloc_.alloc_array(size); - - Eigen::Map dtrs_map(dtrs, size); - Eigen::Map(varis, size) = dtrs_map.vi(); - vector_d dtrs_vals = dtrs_map.val(); - - vector_d diff = dtrs_vals.array() - dtrs_vals.mean(); - double size_m1 = size - 1; - Eigen::Map(partials, size) = 2 * diff.array() / size_m1; - double variance = diff.squaredNorm() / size_m1; - - return var(new stored_gradient_vari(variance, size, varis, partials)); -} - -} // namespace internal /** * Return the sample variance of the specified standard - * vector. Raise domain error if size is not greater than zero. + * vector, Eigen vector, Eigen row vector, or Eigen matrix + * Raise domain error if size is not greater than zero. * - * @param[in] v a vector - * @return sample variance of specified vector + * @param[in] x a input + * @return sample variance of input */ -inline var variance(const std::vector& v) { - check_nonzero_size("variance", "v", v); - if (v.size() == 1) { +template * = nullptr> +inline var variance(const T& x) { + check_nonzero_size("variance", "x", x); + if (x.size() == 1) { return 0; } - return internal::calc_variance(v.size(), &v[0]); -} -/** - * Return the sample variance of the specified vector, row vector, - * or matrix. Raise domain error if size is not greater than - * zero. - * - * @tparam R number of rows, can be Eigen::Dynamic - * @tparam C number of columns, can be Eigen::Dynamic - * @param[in] m input matrix - * @return sample variance of specified matrix - */ -template -var variance(const Eigen::Matrix& m) { - check_nonzero_size("variance", "m", m); - if (m.size() == 1) { - return 0; - } - return internal::calc_variance(m.size(), &m(0)); + const auto& x_ref = to_ref(x); + const auto& x_array = as_array_or_scalar(x_ref); + arena_t arena_x = x_array; + + const auto& x_val = to_ref(value_of(x_array)); + double mean = x_val.mean(); + arena_matrix> + arena_diff = x_val.array() - mean; + + var res = arena_diff.matrix().squaredNorm() / (x_array.size() - 1); + + reverse_pass_callback([arena_x, res, arena_diff]() mutable { + arena_x.adj() += (2.0 * res.adj() / (arena_x.size() - 1)) * + arena_diff; + }); + + return res; } } // namespace math From 9d78471e115d43b8118ec7f3a8b91a53c7a505c6 Mon Sep 17 00:00:00 2001 From: Stan Jenkins Date: Tue, 1 Sep 2020 22:38:54 +0000 Subject: [PATCH 242/355] [Jenkins] auto-formatting by clang-format version 6.0.0-1ubuntu2~16.04.1 (tags/RELEASE_600/final) --- stan/math/rev/fun/multiply.hpp | 4 +-- stan/math/rev/fun/sd.hpp | 7 +++-- stan/math/rev/fun/squared_distance.hpp | 40 ++++++++++++-------------- stan/math/rev/fun/variance.hpp | 8 ++---- 4 files changed, 28 insertions(+), 31 deletions(-) diff --git a/stan/math/rev/fun/multiply.hpp b/stan/math/rev/fun/multiply.hpp index 63c4ff3ec6b..f7aae5bef2e 100644 --- a/stan/math/rev/fun/multiply.hpp +++ b/stan/math/rev/fun/multiply.hpp @@ -56,9 +56,9 @@ multiply_impl(const T1& A, const T2& B) { arena_matrix> res; - if(is_constant::value) { + if (is_constant::value) { res = arena_A_val * value_of(B_ref); - } else if(is_constant::value) { + } else if (is_constant::value) { res = value_of(A_ref) * arena_B_val; } else { res = arena_A_val * arena_B_val; diff --git a/stan/math/rev/fun/sd.hpp b/stan/math/rev/fun/sd.hpp index 2dd778f3fff..204fe730d19 100644 --- a/stan/math/rev/fun/sd.hpp +++ b/stan/math/rev/fun/sd.hpp @@ -37,15 +37,16 @@ var sd(const T& m) { arena_t arena_x = x_ref; const auto& x_val = to_ref(value_of(x)); double mean = x_val.mean(); - arena_matrix> - arena_diff = x_val.array() - mean; + arena_matrix> arena_diff + = x_val.array() - mean; double sum_of_squares = arena_diff.squaredNorm(); double sd = sqrt(sum_of_squares / (x.size() - 1)); var res = sd; reverse_pass_callback([arena_x, res, arena_diff]() mutable { - arena_x.adj() += (res.adj() / (res.val() * (arena_x.size() - 1))) * arena_diff; + arena_x.adj() + += (res.adj() / (res.val() * (arena_x.size() - 1))) * arena_diff; }); return res; diff --git a/stan/math/rev/fun/squared_distance.hpp b/stan/math/rev/fun/squared_distance.hpp index 2ea1eb90413..da6a1bad910 100644 --- a/stan/math/rev/fun/squared_distance.hpp +++ b/stan/math/rev/fun/squared_distance.hpp @@ -17,31 +17,30 @@ namespace math { * Returns the squared distance. */ template * = nullptr, - require_any_var_t* = nullptr> + require_all_stan_scalar_t* = nullptr, + require_any_var_t* = nullptr> inline var squared_distance(const T1& a, const T2& b) { double diff = value_of(a) - value_of(b); var res = squared_distance(value_of(a), value_of(b)); - reverse_pass_callback( - [a, b, diff, res]() mutable { - if (!is_constant::value) - forward_as(a).adj() += 2.0 * res.adj() * diff; - - if (!is_constant::value) - forward_as(b).adj() += -2.0 * res.adj() * diff; - }); + reverse_pass_callback([a, b, diff, res]() mutable { + if (!is_constant::value) + forward_as(a).adj() += 2.0 * res.adj() * diff; + + if (!is_constant::value) + forward_as(b).adj() += -2.0 * res.adj() * diff; + }); return res; } template * = nullptr, - require_any_vt_var* = nullptr> + require_all_eigen_vector_t* = nullptr, + require_any_vt_var* = nullptr> inline var squared_distance(const T1& A, const T2& B) { check_matching_sizes("squared_distance", "A", A, "B", B); - if(A.size() == 0) + if (A.size() == 0) return 0.0; - + using A_ref_t = ref_type_t; using B_ref_t = ref_type_t; @@ -66,14 +65,13 @@ inline var squared_distance(const T1& A, const T2& B) { var res = arena_diff_val.squaredNorm(); - reverse_pass_callback( - [arena_A, arena_B, arena_diff_val, res]() mutable { - if (!is_constant::value) - arena_A.adj() += 2.0 * res.adj() * arena_diff_val; + reverse_pass_callback([arena_A, arena_B, arena_diff_val, res]() mutable { + if (!is_constant::value) + arena_A.adj() += 2.0 * res.adj() * arena_diff_val; - if (!is_constant::value) - arena_B.adj() += -2.0 * res.adj() * arena_diff_val; - }); + if (!is_constant::value) + arena_B.adj() += -2.0 * res.adj() * arena_diff_val; + }); return res; } diff --git a/stan/math/rev/fun/variance.hpp b/stan/math/rev/fun/variance.hpp index 117a1ef1d48..1e28b4790fb 100644 --- a/stan/math/rev/fun/variance.hpp +++ b/stan/math/rev/fun/variance.hpp @@ -30,17 +30,15 @@ inline var variance(const T& x) { const auto& x_ref = to_ref(x); const auto& x_array = as_array_or_scalar(x_ref); arena_t arena_x = x_array; - + const auto& x_val = to_ref(value_of(x_array)); double mean = x_val.mean(); - arena_matrix> - arena_diff = x_val.array() - mean; + arena_matrix> arena_diff = x_val.array() - mean; var res = arena_diff.matrix().squaredNorm() / (x_array.size() - 1); reverse_pass_callback([arena_x, res, arena_diff]() mutable { - arena_x.adj() += (2.0 * res.adj() / (arena_x.size() - 1)) * - arena_diff; + arena_x.adj() += (2.0 * res.adj() / (arena_x.size() - 1)) * arena_diff; }); return res; From a946473753e02be53308273017563238386ec63b Mon Sep 17 00:00:00 2001 From: Ben Date: Tue, 1 Sep 2020 22:53:24 -0400 Subject: [PATCH 243/355] Added unit_vector_constrain and quad_form (Issue #2018) --- .../rev/fun/positive_ordered_constrain.hpp | 2 +- stan/math/rev/fun/quad_form.hpp | 157 ++++++++---------- stan/math/rev/fun/tcrossprod.hpp | 20 ++- stan/math/rev/fun/unit_vector_constrain.hpp | 33 ++-- 4 files changed, 98 insertions(+), 114 deletions(-) diff --git a/stan/math/rev/fun/positive_ordered_constrain.hpp b/stan/math/rev/fun/positive_ordered_constrain.hpp index 1dc0635b935..5f32e489475 100644 --- a/stan/math/rev/fun/positive_ordered_constrain.hpp +++ b/stan/math/rev/fun/positive_ordered_constrain.hpp @@ -42,7 +42,7 @@ inline Eigen::Matrix positive_ordered_constrain( arena_matrix> y = y_val; arena_matrix> arena_x = x; - reverse_pass_callback([=]() mutable { + reverse_pass_callback([arena_x, exp_x, N, y]() mutable { double rolling_adjoint_sum = 0.0; for (int n = N; --n >= 0;) { diff --git a/stan/math/rev/fun/quad_form.hpp b/stan/math/rev/fun/quad_form.hpp index 3eb41e00522..c1385c25664 100644 --- a/stan/math/rev/fun/quad_form.hpp +++ b/stan/math/rev/fun/quad_form.hpp @@ -14,85 +14,78 @@ namespace stan { namespace math { namespace internal { -template -class quad_form_vari_alloc : public chainable_alloc { - private: - inline void compute(const Eigen::Matrix& A, - const Eigen::Matrix& B) { - matrix_d Cd = B.transpose() * A * B; - for (int j = 0; j < C_.cols(); j++) { - for (int i = 0; i < C_.rows(); i++) { - if (sym_) { - C_(i, j) = var(new vari(0.5 * (Cd(i, j) + Cd(j, i)), false)); - } else { - C_(i, j) = var(new vari(Cd(i, j), false)); - } - } - } - } +/** + * Return the quadratic form \f$ B^T A B \f$. + * + * Symmetry of the resulting matrix is not guaranteed due to numerical + * precision. + * + * @tparam T1 type of the first (square) matrix + * @tparam T2 type of the second matrix + * + * @param A square matrix + * @param B second matrix + * @return The quadratic form, which is a symmetric matrix. + * @throws std::invalid_argument if A is not square, or if A cannot be + * multiplied by B + */ +template * = nullptr, + require_any_vt_var* = nullptr> +inline Eigen::Matrix +quad_form_impl(const T1& A, const T2& B) { + check_square("quad_form", "A", A); + check_multiplicable("quad_form", "A", A, "B", B); - public: - quad_form_vari_alloc(const Eigen::Matrix& A, - const Eigen::Matrix& B, - bool symmetric = false) - : A_(A), B_(B), C_(B_.cols(), B_.cols()), sym_(symmetric) { - compute(value_of(A), value_of(B)); - } + using A_ref_t = ref_type_t; + using B_ref_t = ref_type_t; - Eigen::Matrix A_; - Eigen::Matrix B_; - Eigen::Matrix C_; - bool sym_; -}; - -template -class quad_form_vari : public vari { - protected: - inline void chainA(Eigen::Matrix& A, - const Eigen::Matrix& Bd, - const Eigen::Matrix& adjC) {} - inline void chainB(Eigen::Matrix& B, - const Eigen::Matrix& Ad, - const Eigen::Matrix& Bd, - const Eigen::Matrix& adjC) {} - - inline void chainA(Eigen::Matrix& A, - const Eigen::Matrix& Bd, - const Eigen::Matrix& adjC) { - A.adj() += Bd * adjC * Bd.transpose(); - } - inline void chainB(Eigen::Matrix& B, - const Eigen::Matrix& Ad, - const Eigen::Matrix& Bd, - const Eigen::Matrix& adjC) { - B.adj() += Ad * Bd * adjC.transpose() + Ad.transpose() * Bd * adjC; - } + A_ref_t A_ref = A; + B_ref_t B_ref = B; + + check_not_nan("multiply", "A", A_ref); + check_not_nan("multiply", "B", B_ref); + + arena_matrix> arena_A_val; + arena_matrix> arena_B_val = value_of(B_ref); + + arena_matrix> arena_A; + arena_matrix> arena_B; - inline void chainAB(Eigen::Matrix& A, - Eigen::Matrix& B, - const Eigen::Matrix& Ad, - const Eigen::Matrix& Bd, - const Eigen::Matrix& adjC) { - chainA(A, Bd, adjC); - chainB(B, Ad, Bd, adjC); + if (!is_constant::value) { + arena_A = A_ref; } - public: - quad_form_vari(const Eigen::Matrix& A, - const Eigen::Matrix& B, bool symmetric = false) - : vari(0.0) { - impl_ = new quad_form_vari_alloc(A, B, symmetric); + if (!is_constant::value) { + arena_B = B_ref; + arena_A_val = value_of(A_ref); } - virtual void chain() { - matrix_d adjC = impl_->C_.adj(); + arena_matrix> + res; - chainAB(impl_->A_, impl_->B_, value_of(impl_->A_), value_of(impl_->B_), - adjC); + if(is_constant::value) { + res = arena_B_val.transpose() * value_of(A_ref) * arena_B_val; + } else { + res = arena_B_val.transpose() * arena_A_val * arena_B_val; } - quad_form_vari_alloc* impl_; -}; + reverse_pass_callback( + [arena_A, arena_B, arena_A_val, arena_B_val, res]() mutable { + auto C_adj = res.adj().eval(); + auto C_adj_B_t = (C_adj * arena_B_val.transpose()).eval(); + + if (!is_constant::value) + arena_A.adj() += arena_B_val * C_adj_B_t; + + if (!is_constant::value) + arena_B.adj() += arena_A_val * C_adj_B_t.transpose() + + arena_A_val.transpose() * arena_B_val * C_adj; + }); + + return res; +} + } // namespace internal /** @@ -114,17 +107,8 @@ template * = nullptr, require_not_eigen_col_vector_t* = nullptr, require_any_vt_var* = nullptr> -inline promote_scalar_t quad_form(const EigMat1& A, - const EigMat2& B) { - check_square("quad_form", "A", A); - check_multiplicable("quad_form", "A", A, "B", B); - - auto* baseVari = new internal::quad_form_vari< - value_type_t, EigMat1::RowsAtCompileTime, - EigMat1::ColsAtCompileTime, value_type_t, - EigMat2::RowsAtCompileTime, EigMat2::ColsAtCompileTime>(A, B); - - return baseVari->impl_->C_; +inline auto quad_form(const EigMat1& A, const EigMat2& B) { + return internal::quad_form_impl(A, B); } /** @@ -139,19 +123,12 @@ inline promote_scalar_t quad_form(const EigMat1& A, * @throws std::invalid_argument if A is not square, or if A cannot be * multiplied by B */ -template * = nullptr, +template * = nullptr, require_eigen_col_vector_t* = nullptr, require_any_vt_var* = nullptr> inline var quad_form(const EigMat& A, const ColVec& B) { - check_square("quad_form", "A", A); - check_multiplicable("quad_form", "A", A, "B", B); - - auto* baseVari = new internal::quad_form_vari< - value_type_t, EigMat::RowsAtCompileTime, - EigMat::ColsAtCompileTime, value_type_t, - ColVec::RowsAtCompileTime, 1>(A, B); - - return baseVari->impl_->C_(0, 0); + return internal::quad_form_impl(A, B)(0, 0); } } // namespace math diff --git a/stan/math/rev/fun/tcrossprod.hpp b/stan/math/rev/fun/tcrossprod.hpp index 228e96be0c8..e087bcd8bb1 100644 --- a/stan/math/rev/fun/tcrossprod.hpp +++ b/stan/math/rev/fun/tcrossprod.hpp @@ -31,13 +31,23 @@ tcrossprod(const T& M) { arena_matrix> arena_M = M; arena_matrix> arena_M_val = value_of(arena_M); - Eigen::MatrixXd res_val(M.rows(), M.rows()); - arena_matrix> res - = arena_M_val * arena_M_val.transpose(); + Eigen::Matrix res_val(M.rows(), M.rows()); + res_val.setZero().template selfadjointView().rankUpdate(arena_M_val); + + arena_matrix> res(M.rows(), M.rows()); + + for(size_t j = 0; j < res.cols(); ++j) { + for(size_t i = 0; i < j; ++i) { + res.coeffRef(i, j) = res.coeffRef(j, i) = res_val.coeff(i, j); + } + res.coeffRef(j, j) = res_val.coeff(j, j); + } reverse_pass_callback([res, arena_M, arena_M_val]() mutable { - ref_type_t adj = res.adj(); - arena_M.adj() += (adj.transpose() + adj) * arena_M_val; + Eigen::MatrixXd adj = res.adj(); + for(size_t i = 0; i < adj.cols(); ++i) + adj(i, i) *= 2.0; + arena_M.adj() += adj * arena_M_val; }); return res; diff --git a/stan/math/rev/fun/unit_vector_constrain.hpp b/stan/math/rev/fun/unit_vector_constrain.hpp index bddf27de848..bb76a94bd12 100644 --- a/stan/math/rev/fun/unit_vector_constrain.hpp +++ b/stan/math/rev/fun/unit_vector_constrain.hpp @@ -52,30 +52,27 @@ class unit_vector_elt_vari : public vari { * @param y vector of K unrestricted variables * @return Unit length vector of dimension K **/ -template -Eigen::Matrix unit_vector_constrain( - const Eigen::Matrix& y) { +template * = nullptr> +plain_type_t unit_vector_constrain(const T& y) { check_vector("unit_vector", "y", y); check_nonzero_size("unit_vector", "y", y); - vector_d y_d = y.val(); - vari** y_vi_array = reinterpret_cast( - ChainableStack::instance_->memalloc_.alloc(sizeof(vari*) * y.size())); - double* unit_vector_y_d_array = reinterpret_cast( - ChainableStack::instance_->memalloc_.alloc(sizeof(double) * y_d.size())); + const auto& y_ref = to_ref(y); + arena_matrix> y_val = value_of(y_ref); + arena_matrix> arena_y = y_ref; + + const double r = y_val.norm(); + const double r_cubed = r * r * r; + arena_matrix> res = y_val / r; - Eigen::Map(y_vi_array, y.size()) = y.vi(); - const double norm = y_d.norm(); + reverse_pass_callback([arena_y, res, r, r_cubed]() mutable { + const auto& adj = to_ref(res.adj()); - check_positive_finite("unit_vector", "norm", norm); - Eigen::Map unit_vecd(unit_vector_y_d_array, y.size()); - unit_vecd = y_d / norm; + arena_y.adj() += adj / r - y_val * (y_val.array() * adj.array()).sum() / r_cubed; + }); - Eigen::Matrix unit_vector_y(y.size()); - for (int k = 0; k < y.size(); ++k) - unit_vector_y.coeffRef(k) = var(new internal::unit_vector_elt_vari( - unit_vecd[k], y_vi_array, unit_vector_y_d_array, y.size(), k, norm)); - return unit_vector_y; + return res; } /** From df025af00550bf778b5b54821ee5bd3ef6d1a7b2 Mon Sep 17 00:00:00 2001 From: Ben Date: Tue, 1 Sep 2020 23:28:46 -0400 Subject: [PATCH 244/355] Added a couple more matrix functions (Issue #2018) --- stan/math/rev/fun/trace_gen_quad_form.hpp | 158 ++++++++++------------ stan/math/rev/fun/trace_quad_form.hpp | 101 +++++--------- 2 files changed, 106 insertions(+), 153 deletions(-) diff --git a/stan/math/rev/fun/trace_gen_quad_form.hpp b/stan/math/rev/fun/trace_gen_quad_form.hpp index 6c64d524054..d5b9c010bb3 100644 --- a/stan/math/rev/fun/trace_gen_quad_form.hpp +++ b/stan/math/rev/fun/trace_gen_quad_form.hpp @@ -14,104 +14,84 @@ namespace stan { namespace math { -namespace internal { - -template -class trace_gen_quad_form_vari_alloc : public chainable_alloc { - public: - trace_gen_quad_form_vari_alloc(const Eigen::Matrix& D, - const Eigen::Matrix& A, - const Eigen::Matrix& B) - : D_(D), A_(A), B_(B) {} - - double compute() { - return trace_gen_quad_form(value_of(D_), value_of(A_), value_of(B_)); - } - - Eigen::Matrix D_; - Eigen::Matrix A_; - Eigen::Matrix B_; -}; - -template -class trace_gen_quad_form_vari : public vari { - protected: - static inline void computeAdjoints(double adj, - const Eigen::Matrix& D, - const Eigen::Matrix& A, - const Eigen::Matrix& B, - Eigen::Matrix* varD, - Eigen::Matrix* varA, - Eigen::Matrix* varB) { - Eigen::Matrix AtB; - Eigen::Matrix BD; - if (varB || varA) { - BD.noalias() = B * D; - } - if (varB || varD) { - AtB.noalias() = A.transpose() * B; - } - - if (varB) { - (*varB).adj() += adj * (A * BD + AtB * D.transpose()); - } - if (varA) { - (*varA).adj() += adj * (B * BD.transpose()); - } - if (varD) { - (*varD).adj() += adj * (B.transpose() * AtB); - } - } - - public: - explicit trace_gen_quad_form_vari( - trace_gen_quad_form_vari_alloc* impl) - : vari(impl->compute()), impl_(impl) {} - - virtual void chain() { - computeAdjoints(adj_, value_of(impl_->D_), value_of(impl_->A_), - value_of(impl_->B_), - reinterpret_cast*>( - std::is_same::value ? (&impl_->D_) : NULL), - reinterpret_cast*>( - std::is_same::value ? (&impl_->A_) : NULL), - reinterpret_cast*>( - std::is_same::value ? (&impl_->B_) : NULL)); - } - - trace_gen_quad_form_vari_alloc* impl_; -}; -} // namespace internal template , value_type_t, - value_type_t>, - typename = require_all_eigen_t> + require_any_vt_var* = nullptr, + require_all_eigen_t* = nullptr> inline var trace_gen_quad_form(const Td& D, const Ta& A, const Tb& B) { - using Td_scal = value_type_t; - using Ta_scal = value_type_t; - using Tb_scal = value_type_t; - constexpr int Rd = Td::RowsAtCompileTime; - constexpr int Cd = Td::ColsAtCompileTime; - constexpr int Ra = Ta::RowsAtCompileTime; - constexpr int Ca = Ta::ColsAtCompileTime; - constexpr int Rb = Tb::RowsAtCompileTime; - constexpr int Cb = Tb::ColsAtCompileTime; check_square("trace_gen_quad_form", "A", A); check_square("trace_gen_quad_form", "D", D); check_multiplicable("trace_gen_quad_form", "A", A, "B", B); check_multiplicable("trace_gen_quad_form", "B", B, "D", D); - auto* baseVari - = new internal::trace_gen_quad_form_vari_alloc( - D, A, B); + using A_ref_t = ref_type_t; + using B_ref_t = ref_type_t; + using D_ref_t = ref_type_t; + + A_ref_t A_ref = A; + B_ref_t B_ref = B; + D_ref_t D_ref = D; + + arena_matrix> arena_A_val; + arena_matrix> arena_B_val = value_of(B_ref); + arena_matrix> arena_D_val; + + arena_matrix> arena_A; + arena_matrix> arena_B; + arena_matrix> arena_D; + + if (!is_constant::value) { + arena_A = A_ref; + } + + if (!is_constant::value) { + arena_B = B_ref; + } + + if (!is_constant::value) { + arena_D = D_ref; + } + + if (!is_constant::value) { + arena_A_val = value_of(A_ref); + } + + if (!is_constant::value) { + arena_D_val = value_of(D_ref); + } + + var res; + + if(!is_constant::value && + !is_constant::value && + is_constant::value) { + res = (value_of(D) * arena_B_val.transpose() * arena_A_val * arena_B_val).trace(); + } else if(is_constant::value && + !is_constant::value && + !is_constant::value) { + res = (arena_D_val * arena_B_val.transpose() * value_of(A) * arena_B_val).trace(); + } else { + res = (arena_D_val * arena_B_val.transpose() * arena_A_val * arena_B_val).trace(); + } + + reverse_pass_callback( + [arena_A, arena_B, arena_D, + arena_A_val, arena_B_val, arena_D_val, res]() mutable { + double C_adj = res.adj(); + + if (!is_constant::value) + arena_A.adj() += C_adj * arena_B_val * + arena_D_val.transpose() * arena_B_val.transpose(); + + if (!is_constant::value) + arena_B.adj() += C_adj * (arena_A_val * arena_B_val * arena_D_val + + arena_A_val.transpose() * arena_B_val * arena_D_val.transpose()); - return var( - new internal::trace_gen_quad_form_vari(baseVari)); + if (!is_constant::value) + arena_D.adj() += C_adj * ((arena_A_val * arena_B_val).transpose() * arena_B_val); + }); + + return res; } } // namespace math diff --git a/stan/math/rev/fun/trace_quad_form.hpp b/stan/math/rev/fun/trace_quad_form.hpp index 21b81356e5f..de4820fc29a 100644 --- a/stan/math/rev/fun/trace_quad_form.hpp +++ b/stan/math/rev/fun/trace_quad_form.hpp @@ -14,83 +14,56 @@ namespace stan { namespace math { -namespace internal { -template -class trace_quad_form_vari_alloc : public chainable_alloc { - public: - trace_quad_form_vari_alloc(const Eigen::Matrix& A, - const Eigen::Matrix& B) - : A_(A), B_(B) {} - double compute() { return trace_quad_form(value_of(A_), value_of(B_)); } +template * = nullptr, + require_any_vt_var* = nullptr> +inline var trace_quad_form(const EigMat1& A, const EigMat2& B) { + check_square("trace_quad_form", "A", A); + check_multiplicable("trace_quad_form", "A", A, "B", B); - Eigen::Matrix A_; - Eigen::Matrix B_; -}; + using A_ref_t = ref_type_t; + using B_ref_t = ref_type_t; -template -class trace_quad_form_vari : public vari { - protected: - static inline void chainA(Eigen::Matrix& A, - const Eigen::Matrix& Bd, - double adjC) {} - static inline void chainB(Eigen::Matrix& B, - const Eigen::Matrix& Ad, - const Eigen::Matrix& Bd, - double adjC) {} + A_ref_t A_ref = A; + B_ref_t B_ref = B; - static inline void chainA(Eigen::Matrix& A, - const Eigen::Matrix& Bd, - double adjC) { - A.adj() += adjC * Bd * Bd.transpose(); - } - static inline void chainB(Eigen::Matrix& B, - const Eigen::Matrix& Ad, - const Eigen::Matrix& Bd, - double adjC) { - B.adj() += adjC * (Ad + Ad.transpose()) * Bd; + arena_matrix> arena_A_val; + arena_matrix> arena_B_val = value_of(B_ref); + + arena_matrix> arena_A; + arena_matrix> arena_B; + + if (!is_constant::value) { + arena_A = A_ref; } - inline void chainAB(Eigen::Matrix& A, - Eigen::Matrix& B, - const Eigen::Matrix& Ad, - const Eigen::Matrix& Bd, double adjC) { - chainA(A, Bd, adjC); - chainB(B, Ad, Bd, adjC); + if (!is_constant::value) { + arena_B = B_ref; + arena_A_val = value_of(A_ref); } - public: - explicit trace_quad_form_vari( - trace_quad_form_vari_alloc* impl) - : vari(impl->compute()), impl_(impl) {} + var res; - virtual void chain() { - chainAB(impl_->A_, impl_->B_, value_of(impl_->A_), value_of(impl_->B_), - adj_); + if(is_constant::value) { + res = (arena_B_val.transpose() * value_of(A_ref) * arena_B_val).trace(); + } else { + res = (arena_B_val.transpose() * arena_A_val * arena_B_val).trace(); } - trace_quad_form_vari_alloc* impl_; -}; -} // namespace internal - -template > -inline return_type_t trace_quad_form(const EigMat1& A, - const EigMat2& B) { - using Ta = value_type_t; - using Tb = value_type_t; - constexpr int Ra = EigMat1::RowsAtCompileTime; - constexpr int Ca = EigMat1::ColsAtCompileTime; - constexpr int Rb = EigMat2::RowsAtCompileTime; - constexpr int Cb = EigMat2::ColsAtCompileTime; - check_square("trace_quad_form", "A", A); - check_multiplicable("trace_quad_form", "A", A, "B", B); + reverse_pass_callback( + [arena_A, arena_B, arena_A_val, arena_B_val, res]() mutable { + double C_adj = res.adj(); + + if (!is_constant::value) + arena_A.adj() += C_adj * arena_B_val * arena_B_val.transpose(); - auto* baseVari - = new internal::trace_quad_form_vari_alloc(A, B); + if (!is_constant::value) + arena_B.adj() += C_adj * (arena_A_val * arena_B_val + + arena_A_val.transpose() * arena_B_val); + }); - return var( - new internal::trace_quad_form_vari(baseVari)); + return res; } } // namespace math From 50caa5294b3362b4c317fc4c355f1bf540a05a79 Mon Sep 17 00:00:00 2001 From: Stan Jenkins Date: Tue, 1 Sep 2020 23:29:57 -0400 Subject: [PATCH 245/355] [Jenkins] auto-formatting by clang-format version 6.0.1-14 (tags/RELEASE_601/final) --- stan/math/rev/fun/quad_form.hpp | 16 +++--- stan/math/rev/fun/tcrossprod.hpp | 15 +++--- stan/math/rev/fun/trace_gen_quad_form.hpp | 55 +++++++++++---------- stan/math/rev/fun/trace_quad_form.hpp | 11 +++-- stan/math/rev/fun/unit_vector_constrain.hpp | 6 +-- 5 files changed, 54 insertions(+), 49 deletions(-) diff --git a/stan/math/rev/fun/quad_form.hpp b/stan/math/rev/fun/quad_form.hpp index c1385c25664..61e87c4b86b 100644 --- a/stan/math/rev/fun/quad_form.hpp +++ b/stan/math/rev/fun/quad_form.hpp @@ -29,8 +29,7 @@ namespace internal { * @throws std::invalid_argument if A is not square, or if A cannot be * multiplied by B */ -template * = nullptr, +template * = nullptr, require_any_vt_var* = nullptr> inline Eigen::Matrix quad_form_impl(const T1& A, const T2& B) { @@ -64,7 +63,7 @@ quad_form_impl(const T1& A, const T2& B) { arena_matrix> res; - if(is_constant::value) { + if (is_constant::value) { res = arena_B_val.transpose() * value_of(A_ref) * arena_B_val; } else { res = arena_B_val.transpose() * arena_A_val * arena_B_val; @@ -73,14 +72,14 @@ quad_form_impl(const T1& A, const T2& B) { reverse_pass_callback( [arena_A, arena_B, arena_A_val, arena_B_val, res]() mutable { auto C_adj = res.adj().eval(); - auto C_adj_B_t = (C_adj * arena_B_val.transpose()).eval(); - + auto C_adj_B_t = (C_adj * arena_B_val.transpose()).eval(); + if (!is_constant::value) arena_A.adj() += arena_B_val * C_adj_B_t; if (!is_constant::value) - arena_B.adj() += arena_A_val * C_adj_B_t.transpose() + - arena_A_val.transpose() * arena_B_val * C_adj; + arena_B.adj() += arena_A_val * C_adj_B_t.transpose() + + arena_A_val.transpose() * arena_B_val * C_adj; }); return res; @@ -123,8 +122,7 @@ inline auto quad_form(const EigMat1& A, const EigMat2& B) { * @throws std::invalid_argument if A is not square, or if A cannot be * multiplied by B */ -template * = nullptr, +template * = nullptr, require_eigen_col_vector_t* = nullptr, require_any_vt_var* = nullptr> inline var quad_form(const EigMat& A, const ColVec& B) { diff --git a/stan/math/rev/fun/tcrossprod.hpp b/stan/math/rev/fun/tcrossprod.hpp index e087bcd8bb1..2cfad186420 100644 --- a/stan/math/rev/fun/tcrossprod.hpp +++ b/stan/math/rev/fun/tcrossprod.hpp @@ -31,13 +31,16 @@ tcrossprod(const T& M) { arena_matrix> arena_M = M; arena_matrix> arena_M_val = value_of(arena_M); - Eigen::Matrix res_val(M.rows(), M.rows()); - res_val.setZero().template selfadjointView().rankUpdate(arena_M_val); + Eigen::Matrix res_val( + M.rows(), M.rows()); + res_val.setZero().template selfadjointView().rankUpdate( + arena_M_val); - arena_matrix> res(M.rows(), M.rows()); + arena_matrix> + res(M.rows(), M.rows()); - for(size_t j = 0; j < res.cols(); ++j) { - for(size_t i = 0; i < j; ++i) { + for (size_t j = 0; j < res.cols(); ++j) { + for (size_t i = 0; i < j; ++i) { res.coeffRef(i, j) = res.coeffRef(j, i) = res_val.coeff(i, j); } res.coeffRef(j, j) = res_val.coeff(j, j); @@ -45,7 +48,7 @@ tcrossprod(const T& M) { reverse_pass_callback([res, arena_M, arena_M_val]() mutable { Eigen::MatrixXd adj = res.adj(); - for(size_t i = 0; i < adj.cols(); ++i) + for (size_t i = 0; i < adj.cols(); ++i) adj(i, i) *= 2.0; arena_M.adj() += adj * arena_M_val; }); diff --git a/stan/math/rev/fun/trace_gen_quad_form.hpp b/stan/math/rev/fun/trace_gen_quad_form.hpp index d5b9c010bb3..f575060697c 100644 --- a/stan/math/rev/fun/trace_gen_quad_form.hpp +++ b/stan/math/rev/fun/trace_gen_quad_form.hpp @@ -62,35 +62,38 @@ inline var trace_gen_quad_form(const Td& D, const Ta& A, const Tb& B) { var res; - if(!is_constant::value && - !is_constant::value && - is_constant::value) { - res = (value_of(D) * arena_B_val.transpose() * arena_A_val * arena_B_val).trace(); - } else if(is_constant::value && - !is_constant::value && - !is_constant::value) { - res = (arena_D_val * arena_B_val.transpose() * value_of(A) * arena_B_val).trace(); + if (!is_constant::value && !is_constant::value + && is_constant::value) { + res = (value_of(D) * arena_B_val.transpose() * arena_A_val * arena_B_val) + .trace(); + } else if (is_constant::value && !is_constant::value + && !is_constant::value) { + res = (arena_D_val * arena_B_val.transpose() * value_of(A) * arena_B_val) + .trace(); } else { - res = (arena_D_val * arena_B_val.transpose() * arena_A_val * arena_B_val).trace(); + res = (arena_D_val * arena_B_val.transpose() * arena_A_val * arena_B_val) + .trace(); } - reverse_pass_callback( - [arena_A, arena_B, arena_D, - arena_A_val, arena_B_val, arena_D_val, res]() mutable { - double C_adj = res.adj(); - - if (!is_constant::value) - arena_A.adj() += C_adj * arena_B_val * - arena_D_val.transpose() * arena_B_val.transpose(); - - if (!is_constant::value) - arena_B.adj() += C_adj * (arena_A_val * arena_B_val * arena_D_val + - arena_A_val.transpose() * arena_B_val * arena_D_val.transpose()); - - if (!is_constant::value) - arena_D.adj() += C_adj * ((arena_A_val * arena_B_val).transpose() * arena_B_val); - }); - + reverse_pass_callback([arena_A, arena_B, arena_D, arena_A_val, arena_B_val, + arena_D_val, res]() mutable { + double C_adj = res.adj(); + + if (!is_constant::value) + arena_A.adj() += C_adj * arena_B_val * arena_D_val.transpose() + * arena_B_val.transpose(); + + if (!is_constant::value) + arena_B.adj() += C_adj + * (arena_A_val * arena_B_val * arena_D_val + + arena_A_val.transpose() * arena_B_val + * arena_D_val.transpose()); + + if (!is_constant::value) + arena_D.adj() + += C_adj * ((arena_A_val * arena_B_val).transpose() * arena_B_val); + }); + return res; } diff --git a/stan/math/rev/fun/trace_quad_form.hpp b/stan/math/rev/fun/trace_quad_form.hpp index de4820fc29a..232df072a8f 100644 --- a/stan/math/rev/fun/trace_quad_form.hpp +++ b/stan/math/rev/fun/trace_quad_form.hpp @@ -16,7 +16,7 @@ namespace stan { namespace math { template * = nullptr, + require_all_eigen_t* = nullptr, require_any_vt_var* = nullptr> inline var trace_quad_form(const EigMat1& A, const EigMat2& B) { check_square("trace_quad_form", "A", A); @@ -45,7 +45,7 @@ inline var trace_quad_form(const EigMat1& A, const EigMat2& B) { var res; - if(is_constant::value) { + if (is_constant::value) { res = (arena_B_val.transpose() * value_of(A_ref) * arena_B_val).trace(); } else { res = (arena_B_val.transpose() * arena_A_val * arena_B_val).trace(); @@ -54,13 +54,14 @@ inline var trace_quad_form(const EigMat1& A, const EigMat2& B) { reverse_pass_callback( [arena_A, arena_B, arena_A_val, arena_B_val, res]() mutable { double C_adj = res.adj(); - + if (!is_constant::value) arena_A.adj() += C_adj * arena_B_val * arena_B_val.transpose(); if (!is_constant::value) - arena_B.adj() += C_adj * (arena_A_val * arena_B_val + - arena_A_val.transpose() * arena_B_val); + arena_B.adj() += C_adj + * (arena_A_val * arena_B_val + + arena_A_val.transpose() * arena_B_val); }); return res; diff --git a/stan/math/rev/fun/unit_vector_constrain.hpp b/stan/math/rev/fun/unit_vector_constrain.hpp index bb76a94bd12..965f8933313 100644 --- a/stan/math/rev/fun/unit_vector_constrain.hpp +++ b/stan/math/rev/fun/unit_vector_constrain.hpp @@ -52,8 +52,7 @@ class unit_vector_elt_vari : public vari { * @param y vector of K unrestricted variables * @return Unit length vector of dimension K **/ -template * = nullptr> +template * = nullptr> plain_type_t unit_vector_constrain(const T& y) { check_vector("unit_vector", "y", y); check_nonzero_size("unit_vector", "y", y); @@ -69,7 +68,8 @@ plain_type_t unit_vector_constrain(const T& y) { reverse_pass_callback([arena_y, res, r, r_cubed]() mutable { const auto& adj = to_ref(res.adj()); - arena_y.adj() += adj / r - y_val * (y_val.array() * adj.array()).sum() / r_cubed; + arena_y.adj() + += adj / r - y_val * (y_val.array() * adj.array()).sum() / r_cubed; }); return res; From 5edb6beb77f910a467b1280878aa128bd95c6494 Mon Sep 17 00:00:00 2001 From: Ben Date: Wed, 2 Sep 2020 17:01:12 -0400 Subject: [PATCH 246/355] Converted Cholesky and re-enabled CPU tests for large factorizations (Issue #2018) --- stan/math/rev/fun/cholesky_decompose.hpp | 542 +++++------------- .../math/rev/fun/cholesky_decompose_test.cpp | 10 +- 2 files changed, 164 insertions(+), 388 deletions(-) diff --git a/stan/math/rev/fun/cholesky_decompose.hpp b/stan/math/rev/fun/cholesky_decompose.hpp index 886f76ce6e9..a303a887862 100644 --- a/stan/math/rev/fun/cholesky_decompose.hpp +++ b/stan/math/rev/fun/cholesky_decompose.hpp @@ -3,6 +3,8 @@ #include #include +#include +#include #include #include #include @@ -21,349 +23,6 @@ namespace stan { namespace math { -namespace internal { - -/** - * Set the lower right triangular of a var matrix given a set of vari** - * - * @param L Matrix of vars - * @param vari_ref Values to be set in lower right triangular of L. - * @return None, L modified by reference. - */ -inline void set_lower_tri_coeff_ref(Eigen::Matrix& L, - vari** vari_ref) { - size_t pos = 0; - vari* dummy = new vari(0.0, false); - - for (size_type j = 0; j < L.cols(); ++j) { - for (size_type i = j; i < L.cols(); ++i) { - L.coeffRef(i, j).vi_ = vari_ref[pos++]; - } - for (size_type k = 0; k < j; ++k) { - L.coeffRef(k, j).vi_ = dummy; - } - } - return; -} -} // namespace internal - -class cholesky_block : public vari { - public: - int M_; - int block_size_; - using Block_ = Eigen::Block; - vari** vari_ref_A_; - vari** vari_ref_L_; - - /** - * Constructor for Cholesky function. - * - * Stores varis for A. Instantiates and stores varis for L. - * Instantiates and stores dummy vari for upper triangular part of var - * result returned in cholesky_decompose function call - * - * variRefL aren't on the chainable autodiff stack, only used for storage - * and computation. Note that varis for L are constructed externally in - * cholesky_decompose. - * - * block_size_ determined using the same calculation Eigen/LLT.h - * - * @param A matrix - * @param L_A matrix, Cholesky factor of A - */ - cholesky_block(const Eigen::Matrix& A, - const Eigen::Matrix& L_A) - : vari(0.0), - M_(A.rows()), - vari_ref_A_(ChainableStack::instance_->memalloc_.alloc_array( - A.rows() * (A.rows() + 1) / 2)), - vari_ref_L_(ChainableStack::instance_->memalloc_.alloc_array( - A.rows() * (A.rows() + 1) / 2)) { - size_t pos = 0; - block_size_ = std::max(M_ / 8, 8); - block_size_ = std::min(block_size_, 128); - for (size_type j = 0; j < M_; ++j) { - for (size_type i = j; i < M_; ++i) { - vari_ref_A_[pos] = A.coeffRef(i, j).vi_; - vari_ref_L_[pos] = new vari(L_A.coeffRef(i, j), false); - ++pos; - } - } - } - - /** - * Symbolic adjoint calculation for Cholesky factor A - * - * @param L Cholesky factor - * @param L_adj matrix of adjoints of L - */ - inline void symbolic_rev(Block_& L, Block_& L_adj) { - using Eigen::Lower; - using Eigen::StrictlyUpper; - using Eigen::Upper; - L.transposeInPlace(); - L_adj = (L * L_adj.triangularView()).eval(); - L_adj.triangularView() - = L_adj.adjoint().triangularView(); - L.triangularView().solveInPlace(L_adj); - L.triangularView().solveInPlace(L_adj.transpose()); - } - - /** - * Reverse mode differentiation algorithm reference: - * - * Iain Murray: Differentiation of the Cholesky decomposition, 2016. - * - */ - virtual void chain() { - using Eigen::Block; - using Eigen::Lower; - using Eigen::MatrixXd; - using Eigen::StrictlyUpper; - using Eigen::Upper; - auto L_adj = Eigen::MatrixXd::Zero(M_, M_).eval(); - auto L = Eigen::MatrixXd::Zero(M_, M_).eval(); - size_t pos = 0; - for (size_type j = 0; j < M_; ++j) { - for (size_type i = j; i < M_; ++i) { - L_adj.coeffRef(i, j) = vari_ref_L_[pos]->adj_; - L.coeffRef(i, j) = vari_ref_L_[pos]->val_; - ++pos; - } - } - - for (int k = M_; k > 0; k -= block_size_) { - int j = std::max(0, k - block_size_); - Block_ R = L.block(j, 0, k - j, j); - Block_ D = L.block(j, j, k - j, k - j); - Block_ B = L.block(k, 0, M_ - k, j); - Block_ C = L.block(k, j, M_ - k, k - j); - Block_ R_adj = L_adj.block(j, 0, k - j, j); - Block_ D_adj = L_adj.block(j, j, k - j, k - j); - Block_ B_adj = L_adj.block(k, 0, M_ - k, j); - Block_ C_adj = L_adj.block(k, j, M_ - k, k - j); - if (C_adj.size() > 0) { - C_adj = D.transpose() - .triangularView() - .solve(C_adj.transpose()) - .transpose(); - B_adj.noalias() -= C_adj * R; - D_adj.noalias() -= C_adj.transpose() * C; - } - symbolic_rev(D, D_adj); - R_adj.noalias() -= C_adj.transpose() * B; - R_adj.noalias() -= D_adj.selfadjointView() * R; - D_adj.diagonal() *= 0.5; - D_adj.triangularView().setZero(); - } - pos = 0; - for (size_type j = 0; j < M_; ++j) { - for (size_type i = j; i < M_; ++i) { - vari_ref_A_[pos++]->adj_ += L_adj.coeffRef(i, j); - } - } - } -}; - -class cholesky_scalar : public vari { - public: - int M_; - vari** vari_ref_A_; - vari** vari_ref_L_; - - /** - * Constructor for Cholesky function. - * - * Stores varis for A. Instantiates and stores varis for L. Instantiates - * and stores dummy vari for upper triangular part of var result returned - * in cholesky_decompose function call - * - * variRefL aren't on the chainable autodiff stack, only used for storage - * and computation. Note that varis for L are constructed externally in - * cholesky_decompose. - * - * @param A matrix - * @param L_A matrix, Cholesky factor of A - */ - cholesky_scalar(const Eigen::Matrix& A, - const Eigen::Matrix& L_A) - : vari(0.0), - M_(A.rows()), - vari_ref_A_(ChainableStack::instance_->memalloc_.alloc_array( - A.rows() * (A.rows() + 1) / 2)), - vari_ref_L_(ChainableStack::instance_->memalloc_.alloc_array( - A.rows() * (A.rows() + 1) / 2)) { - size_t accum = 0; - size_t accum_i = accum; - for (size_type j = 0; j < M_; ++j) { - for (size_type i = j; i < M_; ++i) { - accum_i += i; - size_t pos = j + accum_i; - vari_ref_A_[pos] = A.coeffRef(i, j).vi_; - vari_ref_L_[pos] = new vari(L_A.coeffRef(i, j), false); - } - accum += j; - accum_i = accum; - } - } - - /** - * Reverse mode differentiation algorithm reference: - * - * Mike Giles. An extended collection of matrix derivative results for - * forward and reverse mode AD. Jan. 2008. - * - * Note algorithm as laid out in Giles is row-major, so Eigen::Matrices - * are explicitly storage order RowMajor, whereas Eigen defaults to - * ColumnMajor. Also note algorithm starts by calculating the adjoint for - * A(M_ - 1, M_ - 1), hence pos on line 94 is decremented to start at pos - * = M_ * (M_ + 1) / 2. - */ - virtual void chain() { - using Eigen::Matrix; - using Eigen::RowMajor; - Matrix adjL(M_, M_); - Matrix LA(M_, M_); - Matrix adjA(M_, M_); - size_t pos = 0; - for (size_type i = 0; i < M_; ++i) { - for (size_type j = 0; j <= i; ++j) { - adjL.coeffRef(i, j) = vari_ref_L_[pos]->adj_; - LA.coeffRef(i, j) = vari_ref_L_[pos]->val_; - ++pos; - } - } - - --pos; - for (int i = M_ - 1; i >= 0; --i) { - for (int j = i; j >= 0; --j) { - if (i == j) { - adjA.coeffRef(i, j) = 0.5 * adjL.coeff(i, j) / LA.coeff(i, j); - } else { - adjA.coeffRef(i, j) = adjL.coeff(i, j) / LA.coeff(j, j); - adjL.coeffRef(j, j) - -= adjL.coeff(i, j) * LA.coeff(i, j) / LA.coeff(j, j); - } - for (int k = j - 1; k >= 0; --k) { - adjL.coeffRef(i, k) -= adjA.coeff(i, j) * LA.coeff(j, k); - adjL.coeffRef(j, k) -= adjA.coeff(i, j) * LA.coeff(i, k); - } - vari_ref_A_[pos--]->adj_ += adjA.coeffRef(i, j); - } - } - } -}; - -#ifdef STAN_OPENCL -class cholesky_opencl : public vari { - public: - int M_; - vari** vari_ref_A_; - vari** vari_ref_L_; - - /** - * Constructor for OpenCL Cholesky function. - * - * Stores varis for A. Instantiates and stores varis for L. - * Instantiates and stores dummy vari for upper triangular part of var - * result returned in cholesky_decompose function call - * - * variRefL aren't on the chainable autodiff stack, only used for storage - * and computation. Note that varis for L are constructed externally in - * cholesky_decompose. - * - * @param A matrix - * @param L_A Cholesky factor of A - */ - cholesky_opencl(const Eigen::Matrix& A, - const Eigen::Matrix& L_A) - : vari(0.0), - M_(A.rows()), - vari_ref_A_(ChainableStack::instance_->memalloc_.alloc_array( - A.rows() * (A.rows() + 1) / 2)), - vari_ref_L_(ChainableStack::instance_->memalloc_.alloc_array( - A.rows() * (A.rows() + 1) / 2)) { - size_t pos = 0; - for (size_type j = 0; j < M_; ++j) { - for (size_type i = j; i < M_; ++i) { - vari_ref_A_[pos] = A.coeffRef(i, j).vi_; - vari_ref_L_[pos] = new vari(L_A.coeffRef(i, j), false); - ++pos; - } - } - } - - /** - * Symbolic adjoint calculation for Cholesky factor A - * - * @param L_val value of Cholesky factor - * @param L_adj adjoint of Cholesky factor - */ - inline void symbolic_rev(matrix_cl& L_val, matrix_cl& L_adj) { - L_adj = transpose(L_val) * L_adj; - L_adj.triangular_transpose(); - L_val = transpose(tri_inverse(L_val)); - L_adj = L_val * transpose(L_val * L_adj); - L_adj.triangular_transpose(); - } - - /** - * Reverse mode differentiation algorithm using OpenCL - * - * Reference: - * - * Iain Murray: Differentiation of the Cholesky decomposition, 2016. - * - */ - virtual void chain() { - const int packed_size = M_ * (M_ + 1) / 2; - Eigen::Map> L_cpu( - vari_ref_L_, M_ * (M_ + 1) / 2); - Eigen::VectorXd L_val_cpu = L_cpu.val(); - Eigen::VectorXd L_adj_cpu = L_cpu.adj(); - matrix_cl L_val = packed_copy(L_val_cpu, M_); - matrix_cl L_adj = packed_copy(L_adj_cpu, M_); - int block_size - = M_ / opencl_context.tuning_opts().cholesky_rev_block_partition; - block_size = std::max(block_size, 8); - block_size = std::min( - block_size, opencl_context.tuning_opts().cholesky_rev_min_block_size); - // The following is an OpenCL implementation of - // the chain() function from the cholesky_block - // vari class implementation - for (int k = M_; k > 0; k -= block_size) { - const int j = std::max(0, k - block_size); - const int k_j_ind = k - j; - const int m_k_ind = M_ - k; - - auto&& R_val = block(L_val, j, 0, k_j_ind, j); - auto&& R_adj = block(L_adj, j, 0, k_j_ind, j); - matrix_cl D_val = block(L_val, j, j, k_j_ind, k_j_ind); - matrix_cl D_adj = block(L_adj, j, j, k_j_ind, k_j_ind); - auto&& B_val = block(L_val, k, 0, m_k_ind, j); - auto&& B_adj = block(L_adj, k, 0, m_k_ind, j); - auto&& C_val = block(L_val, k, j, m_k_ind, k_j_ind); - auto&& C_adj = block(L_adj, k, j, m_k_ind, k_j_ind); - - C_adj = C_adj * tri_inverse(D_val); - B_adj = B_adj - C_adj * R_val; - D_adj = D_adj - transpose(C_adj) * C_val; - - symbolic_rev(D_val, D_adj); - - R_adj = R_adj - transpose(C_adj) * B_val - D_adj * R_val; - D_adj = diagonal_multiply(D_adj, 0.5); - - block(L_adj, j, j, k_j_ind, k_j_ind) = D_adj; - } - L_adj.view(matrix_cl_view::Lower); - std::vector L_adj_cpu_res = packed_copy(L_adj); - for (size_type j = 0; j < packed_size; ++j) { - vari_ref_A_[j]->adj_ += L_adj_cpu_res[j]; - } - } -}; -#endif /** * Reverse mode specialization of Cholesky decomposition @@ -380,55 +39,168 @@ template * = nullptr> inline Eigen::Matrix cholesky_decompose(const T& A) { const auto& A_ref = to_ref(A); - Eigen::Matrix L_A( - value_of_rec(A_ref)); - check_not_nan("cholesky_decompose", "A", L_A); -#ifdef STAN_OPENCL - L_A = cholesky_decompose(L_A); -#else - check_symmetric("cholesky_decompose", "A", L_A); - Eigen::LLT, Eigen::Lower> L_factor(L_A); + Eigen::MatrixXd L_A_val = value_of(A_ref); + + check_not_nan("cholesky_decompose", "A", L_A_val); + check_symmetric("cholesky_decompose", "A", L_A_val); + Eigen::LLT, Eigen::Lower> L_factor(L_A_val); check_pos_definite("cholesky_decompose", "A", L_factor); -#endif - // Memory allocated in arena. - // cholesky_scalar gradient faster for small matrices compared to - // cholesky_block - vari* dummy = new vari(0.0, false); - Eigen::Matrix L(A.rows(), - A.cols()); - if (L_A.rows() <= 35) { - cholesky_scalar* baseVari = new cholesky_scalar(A_ref, L_A); - size_t accum = 0; - size_t accum_i = accum; - for (size_type j = 0; j < L.cols(); ++j) { - for (size_type i = j; i < L.cols(); ++i) { - accum_i += i; - size_t pos = j + accum_i; - L.coeffRef(i, j).vi_ = baseVari->vari_ref_L_[pos]; - } - for (size_type k = 0; k < j; ++k) { - L.coeffRef(k, j).vi_ = dummy; + + int M = A.rows(); + int P = (M * M - M) / 2 + M; + Eigen::Matrix res_vars(P); + arena_matrix arena_A = A_ref; + arena_matrix res(M, M); + + var zero = 0.0; + if (L_A_val.rows() > 35) { + /** + * Reverse mode differentiation algorithm reference: + * + * Iain Murray: Differentiation of the Cholesky decomposition, 2016. + * + */ + size_t pos = 0; + for (size_type j = 0; j < M; ++j) { + for (size_type i = j; i < M; ++i) { + res_vars.coeffRef(pos) = L_A_val.coeff(i, j); + res.coeffRef(i, j) = res_vars.coeff(pos); + if(i != j) + res.coeffRef(j, i) = zero; + pos++; } - accum += j; - accum_i = accum; } + + reverse_pass_callback([arena_A, M, res_vars]() mutable { + using Eigen::Block; + using Eigen::Upper; + using Eigen::Lower; + using Eigen::StrictlyUpper; + using Eigen::MatrixXd; + using Block_ = Eigen::Block; + + int block_size = std::min(std::max(M / 8, 8), 128); + + /** + * Symbolic adjoint calculation for Cholesky factor A + * + * @param L Cholesky factor + * @param L_adj matrix of adjoints of L + */ + auto symbolic_rev = [](auto& L, auto& L_adj) { + using Eigen::Upper; + using Eigen::Lower; + using Eigen::StrictlyUpper; + L.transposeInPlace(); + L_adj = (L * L_adj.template triangularView()).eval(); + L_adj.template triangularView() + = L_adj.adjoint().template triangularView(); + L.template triangularView().solveInPlace(L_adj); + L.template triangularView().solveInPlace(L_adj.transpose()); + }; + + Eigen::MatrixXd L_adj = Eigen::MatrixXd::Zero(M, M); + Eigen::MatrixXd L = Eigen::MatrixXd::Zero(M, M); + size_t pos = 0; + for (size_type j = 0; j < M; ++j) { + for (size_type i = j; i < M; ++i) { + L_adj.coeffRef(i, j) = res_vars.coeff(pos).adj(); + L.coeffRef(i, j) = res_vars.coeff(pos).val(); + ++pos; + } + } + + for (int k = M; k > 0; k -= block_size) { + int j = std::max(0, k - block_size); + Block_ R = L.block(j, 0, k - j, j); + Block_ D = L.block(j, j, k - j, k - j); + Block_ B = L.block(k, 0, M - k, j); + Block_ C = L.block(k, j, M - k, k - j); + Block_ R_adj = L_adj.block(j, 0, k - j, j); + Block_ D_adj = L_adj.block(j, j, k - j, k - j); + Block_ B_adj = L_adj.block(k, 0, M - k, j); + Block_ C_adj = L_adj.block(k, j, M - k, k - j); + if (C_adj.size() > 0) { + C_adj = D.transpose() + .triangularView() + .solve(C_adj.transpose()) + .transpose(); + B_adj.noalias() -= C_adj * R; + D_adj.noalias() -= C_adj.transpose() * C; + } + symbolic_rev(D, D_adj); + R_adj.noalias() -= C_adj.transpose() * B; + R_adj.noalias() -= D_adj.selfadjointView() * R; + D_adj.diagonal() *= 0.5; + D_adj.triangularView().setZero(); + } + pos = 0; + + for (size_type j = 0; j < M; ++j) { + for (size_type i = j; i < M; ++i) { + arena_A(i, j).adj() += L_adj.coeffRef(i, j); + } + } + }); } else { -#ifdef STAN_OPENCL - if (L_A.rows() - > opencl_context.tuning_opts().cholesky_size_worth_transfer) { - cholesky_opencl* baseVari = new cholesky_opencl(A_ref, L_A); - internal::set_lower_tri_coeff_ref(L, baseVari->vari_ref_L_); - } else { - cholesky_block* baseVari = new cholesky_block(A_ref, L_A); - internal::set_lower_tri_coeff_ref(L, baseVari->vari_ref_L_); + /** + * Reverse mode differentiation algorithm reference: + * + * Mike Giles. An extended collection of matrix derivative results for + * forward and reverse mode AD. Jan. 2008. + * + * Note algorithm as laid out in Giles is row-major, so Eigen::Matrices + * are explicitly storage order RowMajor, whereas Eigen defaults to + * ColumnMajor. Also note algorithm starts by calculating the adjoint for + * A(M_ - 1, M_ - 1), hence pos on line 94 is decremented to start at pos + * = M_ * (M_ + 1) / 2. + */ + size_t pos = 0; + for (int i = 0; i < M; ++i) { + for (int j = 0; j <= i; ++j) { + res_vars.coeffRef(pos) = L_A_val.coeff(i, j); + res.coeffRef(i, j) = res_vars.coeff(pos); + if(i != j) + res.coeffRef(j, i) = zero; + pos++; + } } -#else - cholesky_block* baseVari = new cholesky_block(A_ref, L_A); - internal::set_lower_tri_coeff_ref(L, baseVari->vari_ref_L_); -#endif + + reverse_pass_callback([arena_A, M, res_vars]() mutable { + using RowMajorMatrixXd + = Eigen::Matrix; + RowMajorMatrixXd adjL(M, M); + RowMajorMatrixXd LA(M, M); + RowMajorMatrixXd adjA(M, M); + size_t pos = 0; + for (size_t i = 0; i < M; ++i) + for (size_t j = 0; j <= i; ++j) { + adjL.coeffRef(i, j) = res_vars.coeff(pos).adj(); + LA.coeffRef(i, j) = res_vars.coeff(pos).val(); + pos++; + } + + for (int i = M - 1; i >= 0; --i) { + for (int j = i; j >= 0; --j) { + if (i == j) { + adjA.coeffRef(i, j) = 0.5 * adjL.coeff(i, j) / LA.coeff(i, j); + } else { + adjA.coeffRef(i, j) = adjL.coeff(i, j) / LA.coeff(j, j); + adjL.coeffRef(j, j) + -= adjL.coeff(i, j) * LA.coeff(i, j) / LA.coeff(j, j); + } + for (int k = j - 1; k >= 0; --k) { + adjL.coeffRef(i, k) -= adjA.coeff(i, j) * LA.coeff(j, k); + adjL.coeffRef(j, k) -= adjA.coeff(i, j) * LA.coeff(i, k); + } + + arena_A.coeff(i, j).adj() += adjA.coeffRef(i, j); + } + } + }); } - return L; + return res; } } // namespace math diff --git a/test/unit/math/rev/fun/cholesky_decompose_test.cpp b/test/unit/math/rev/fun/cholesky_decompose_test.cpp index e0ba63b681f..97c6fb46e0b 100644 --- a/test/unit/math/rev/fun/cholesky_decompose_test.cpp +++ b/test/unit/math/rev/fun/cholesky_decompose_test.cpp @@ -237,9 +237,10 @@ double test_gradient(int size, double prec) { return grads_ad.sum(); } +TEST(AgradRevMatrix, mat_cholesky_1st_deriv_large_gradients) { #ifdef STAN_OPENCL -TEST(AgradRevMatrix, mat_cholesky_1st_deriv_large_gradients_opencl) { stan::math::opencl_context.tuning_opts().cholesky_size_worth_transfer = 25; +#endif test_gradient(51, 1e-08); test_gp_grad(1300, 1e-08); test_gp_grad(2000, 1e-08); @@ -248,13 +249,16 @@ TEST(AgradRevMatrix, mat_cholesky_1st_deriv_large_gradients_opencl) { // below the threshold test_gradient(10, 1e-08); test_gp_grad(10, 1e-08); + test_chol_mult(13, 1e-08); + test_simple_vec_mult(15, 1e-08); } -TEST(AgradRevMatrix, check_varis_on_stack_large_opencl) { +TEST(AgradRevMatrix, check_varis_on_stack_large) { +#ifdef STAN_OPENCL stan::math::opencl_context.tuning_opts().cholesky_size_worth_transfer = 25; +#endif stan::math::matrix_v m1 = stan::math::matrix_v::Random(50, 50); stan::math::matrix_v m1_pos_def = m1 * m1.transpose() + 50 * stan::math::matrix_v::Identity(50, 50); test::check_varis_on_stack(stan::math::cholesky_decompose(m1_pos_def)); } -#endif From d3c052550660d5325c7d65ea1fdac42c4379f464 Mon Sep 17 00:00:00 2001 From: Ben Date: Wed, 2 Sep 2020 18:39:08 -0400 Subject: [PATCH 247/355] More functions! (Issue #2018) --- stan/math/prim/fun/eigenvalues_sym.hpp | 3 +- stan/math/prim/fun/eigenvectors_sym.hpp | 3 +- stan/math/rev/fun/eigenvalues_sym.hpp | 98 ++++++--------------- stan/math/rev/fun/eigenvectors_sym.hpp | 111 ++++++++---------------- 4 files changed, 68 insertions(+), 147 deletions(-) diff --git a/stan/math/prim/fun/eigenvalues_sym.hpp b/stan/math/prim/fun/eigenvalues_sym.hpp index d4a89866840..524c3e9107d 100644 --- a/stan/math/prim/fun/eigenvalues_sym.hpp +++ b/stan/math/prim/fun/eigenvalues_sym.hpp @@ -19,7 +19,8 @@ namespace math { * @param m Specified matrix. * @return Eigenvalues of matrix. */ -template * = nullptr> +template * = nullptr, + require_not_vt_var* = nullptr> Eigen::Matrix, Eigen::Dynamic, 1> eigenvalues_sym( const EigMat& m) { using PlainMat = plain_type_t; diff --git a/stan/math/prim/fun/eigenvectors_sym.hpp b/stan/math/prim/fun/eigenvectors_sym.hpp index 4ed9dcc5d38..187829c5ffe 100644 --- a/stan/math/prim/fun/eigenvectors_sym.hpp +++ b/stan/math/prim/fun/eigenvectors_sym.hpp @@ -8,7 +8,8 @@ namespace stan { namespace math { -template * = nullptr> +template * = nullptr, + require_not_vt_var* = nullptr> Eigen::Matrix, Eigen::Dynamic, Eigen::Dynamic> eigenvectors_sym(const EigMat& m) { using PlainMat = plain_type_t; diff --git a/stan/math/rev/fun/eigenvalues_sym.hpp b/stan/math/rev/fun/eigenvalues_sym.hpp index 32ebefd455d..b43c883af37 100644 --- a/stan/math/rev/fun/eigenvalues_sym.hpp +++ b/stan/math/rev/fun/eigenvalues_sym.hpp @@ -3,7 +3,9 @@ #include #include -#include +#include +#include +#include #include #include #include @@ -14,80 +16,36 @@ namespace stan { namespace math { -namespace internal { -class eigenvalues_vari : public vari { - public: - int M_; // A.rows() = A.cols() - double *A_; - double *w_; // eigenvalues - double *v_; // eigenvectors - vari **vari_ref_A_; - vari **vari_ref_w_; - vari **vari_ref_v_; - - explicit eigenvalues_vari(const Eigen::Matrix &A) - : vari(0.0), - M_(A.rows()), - A_(ChainableStack::instance_->memalloc_.alloc_array( - A.rows() * A.cols())), - w_(ChainableStack::instance_->memalloc_.alloc_array(A.rows())), - v_(ChainableStack::instance_->memalloc_.alloc_array( - A.rows() * A.cols())), - vari_ref_A_(ChainableStack::instance_->memalloc_.alloc_array( - A.rows() * A.cols())), - vari_ref_w_(ChainableStack::instance_->memalloc_.alloc_array( - A.rows())) { - using Eigen::Map; - - Map Ad(A_, M_, M_); - Map wd(w_, M_, 1); - Map vd(v_, M_, M_); - Ad = A.val(); - Eigen::SelfAdjointEigenSolver solver(Ad); - wd = solver.eigenvalues(); - vd = solver.eigenvectors(); - - Map(vari_ref_A_, M_, M_) = A.vi(); - Map(vari_ref_w_, M_) - = wd.unaryExpr([](double x) { return new vari(x, false); }); - } - - /** - * Reverse mode differentiation algorithm reference: - * - * Mike Giles. An extended collection of matrix derivative results for - * forward and reverse mode AD. Jan. 2008. - * - * Section 3.1 Eigenvalues and eigenvectors. - */ - virtual void chain() { - using Eigen::Map; - - matrix_d adj_w = Map(vari_ref_w_, M_, 1).adj(); - Map v(v_, M_, M_); - - matrix_d adjA = v * adj_w.asDiagonal() * v.transpose(); - - Map(vari_ref_A_, M_, M_).adj() += adjA; - } -}; -} // namespace internal - /** * Return the eigenvalues of the specified symmetric matrix. *

See eigen_decompose() for more information. - * @param m Specified matrix. + * + * @tparam T type of input matrix + * @param m Input matrix. * @return Eigenvalues of matrix. */ -inline vector_v eigenvalues_sym(const matrix_v &m) { - matrix_d m_eval(value_of_rec(m)); - check_nonzero_size("eigenvalues_sym", "m", m_eval); - check_symmetric("eigenvalues_sym", "m", m_eval); - vector_v res(m.rows()); - internal::eigenvalues_vari *baseVari = new internal::eigenvalues_vari(m); - res.vi() - = Eigen::Map(baseVari->vari_ref_w_, res.rows(), res.cols()); - return res; +template * = nullptr> +inline Eigen::Matrix +eigenvalues_sym(const T &m) { + const auto& m_ref = to_ref(m); + arena_matrix> + arena_m = m_ref; + check_square("eigenvalues_sym", "m", m_ref); + Eigen::MatrixXd m_val = value_of(m_ref); + check_nonzero_size("eigenvalues_sym", "m", m_val); + check_symmetric("eigenvalues_sym", "m", m_val); + + Eigen::SelfAdjointEigenSolver solver(m_val); + arena_matrix> + eigenvalues = solver.eigenvalues(); + arena_matrix arena_eigenvectors_val = solver.eigenvectors(); + + reverse_pass_callback([arena_m, arena_eigenvectors_val, eigenvalues]() mutable { + arena_m.adj() += arena_eigenvectors_val * eigenvalues.adj().asDiagonal() * + arena_eigenvectors_val.transpose(); + }); + + return eigenvalues; } } // namespace math diff --git a/stan/math/rev/fun/eigenvectors_sym.hpp b/stan/math/rev/fun/eigenvectors_sym.hpp index 154e887d6e3..48afa2e0c9e 100644 --- a/stan/math/rev/fun/eigenvectors_sym.hpp +++ b/stan/math/rev/fun/eigenvectors_sym.hpp @@ -14,85 +14,46 @@ namespace stan { namespace math { -namespace internal { -class eigenvectors_vari : public vari { - public: - int M_; // A.rows() = A.cols() - double *A_; - double *w_; // eigenvalues - double *v_; // eigenvectors - vari **vari_ref_A_; - vari **vari_ref_w_; - vari **vari_ref_v_; - - explicit eigenvectors_vari(const Eigen::Matrix &A) - : vari(0.0), - M_(A.rows()), - A_(ChainableStack::instance_->memalloc_.alloc_array( - A.rows() * A.cols())), - w_(ChainableStack::instance_->memalloc_.alloc_array(A.rows())), - v_(ChainableStack::instance_->memalloc_.alloc_array( - A.rows() * A.cols())), - vari_ref_A_(ChainableStack::instance_->memalloc_.alloc_array( - A.rows() * A.cols())), - vari_ref_v_(ChainableStack::instance_->memalloc_.alloc_array( - A.rows() * A.cols())) { - using Eigen::Map; - - Map Ad(A_, M_, M_); - Map wd(w_, M_, 1); - Map vd(v_, M_, M_); - Ad = A.val(); - Eigen::SelfAdjointEigenSolver solver(Ad); - wd = solver.eigenvalues(); - vd = solver.eigenvectors(); - - Map(vari_ref_A_, M_, M_) = A.vi(); - Map(vari_ref_v_, M_, M_) - = vd.unaryExpr([](double x) { return new vari(x, false); }); - } - - /** - * Reverse mode differentiation algorithm reference: - * - * Mike Giles. An extended collection of matrix derivative results for - * forward and reverse mode AD. Jan. 2008. - * - * Section 3.1 Eigenvalues and eigenvectors. - */ - virtual void chain() { - using Eigen::Map; - - matrix_d adj_v = Map(vari_ref_v_, M_, M_).adj(); - Map w(w_, M_, M_); - Map v(v_, M_, M_); - - matrix_d f(M_, M_); - for (int i = 0; i < M_; i++) - for (int j = 0; j < M_; j++) - f.coeffRef(j, i) = (i != j ? 1 / (w.coeff(i) - w.coeff(j)) : 0); - - matrix_d adjA = v * f.cwiseProduct(v.transpose() * adj_v) * v.transpose(); - - Map(vari_ref_A_, M_, M_).adj() += adjA; - } -}; -} // namespace internal - /** * Return the eigenvectors of the specified symmetric matrix. *

See eigen_decompose() for more information. - * @param m Specified matrix. - * @return Eigenvectors of matrix. + * + * @tparam T Type of input matrix + * @param m Input matrix + * @return Eigenvectors of matrix */ -inline matrix_v eigenvectors_sym(const matrix_v &m) { - matrix_d m_eval(value_of_rec(m)); - check_nonzero_size("eigenvalues_sym", "m", m_eval); - check_symmetric("eigenvalues_sym", "m", m_eval); - matrix_v res(m.rows(), m.cols()); - internal::eigenvectors_vari *baseVari = new internal::eigenvectors_vari(m); - res.vi() - = Eigen::Map(baseVari->vari_ref_v_, res.rows(), res.cols()); +template * = nullptr> +inline Eigen::Matrix +eigenvectors_sym(const T &m) { + const auto& m_ref = to_ref(m); + arena_matrix> + arena_m = m_ref; + check_square("eigenvalues_sym", "m", m_ref); + Eigen::MatrixXd m_val = value_of(m_ref); + check_nonzero_size("eigenvalues_sym", "m", m_val); + check_symmetric("eigenvalues_sym", "m", m_val); + + Eigen::SelfAdjointEigenSolver solver(m_val); + arena_matrix arena_eigenvectors_val = solver.eigenvectors(); + arena_matrix> + res = arena_eigenvectors_val; + + int M = m_val.rows(); + arena_matrix arena_f(M, M); + for (int i = 0; i < M; i++) + for (int j = 0; j < M; j++) + arena_f.coeffRef(j, i) = (i != j ? 1 / + (solver.eigenvalues().coeff(i) - solver.eigenvalues().coeff(j)) : 0); + + reverse_pass_callback([arena_m, arena_eigenvectors_val, + arena_f, res]() mutable { + Eigen::MatrixXd adj = res.adj(); + Eigen::MatrixXd adj2 = arena_eigenvectors_val.transpose() * adj; + Eigen::MatrixXd tmp = arena_f.cwiseProduct(adj2); + arena_m.adj() += arena_eigenvectors_val * tmp * + arena_eigenvectors_val.transpose(); + }); + return res; } From 843ca080a37320a144d7ac74373f7d3d0dca7c1f Mon Sep 17 00:00:00 2001 From: Stan Jenkins Date: Wed, 2 Sep 2020 19:17:08 -0400 Subject: [PATCH 248/355] [Jenkins] auto-formatting by clang-format version 6.0.1-14 (tags/RELEASE_601/final) --- stan/math/prim/fun/eigenvalues_sym.hpp | 2 +- stan/math/prim/fun/eigenvectors_sym.hpp | 2 +- stan/math/prim/meta/forward_as.hpp | 7 +- stan/math/rev/fun/cholesky_decompose.hpp | 144 +++++++++++------------ stan/math/rev/fun/eigenvalues_sym.hpp | 20 ++-- stan/math/rev/fun/eigenvectors_sym.hpp | 28 +++-- 6 files changed, 103 insertions(+), 100 deletions(-) diff --git a/stan/math/prim/fun/eigenvalues_sym.hpp b/stan/math/prim/fun/eigenvalues_sym.hpp index 524c3e9107d..43c06abac2a 100644 --- a/stan/math/prim/fun/eigenvalues_sym.hpp +++ b/stan/math/prim/fun/eigenvalues_sym.hpp @@ -20,7 +20,7 @@ namespace math { * @return Eigenvalues of matrix. */ template * = nullptr, - require_not_vt_var* = nullptr> + require_not_vt_var* = nullptr> Eigen::Matrix, Eigen::Dynamic, 1> eigenvalues_sym( const EigMat& m) { using PlainMat = plain_type_t; diff --git a/stan/math/prim/fun/eigenvectors_sym.hpp b/stan/math/prim/fun/eigenvectors_sym.hpp index 187829c5ffe..5c303bda609 100644 --- a/stan/math/prim/fun/eigenvectors_sym.hpp +++ b/stan/math/prim/fun/eigenvectors_sym.hpp @@ -9,7 +9,7 @@ namespace stan { namespace math { template * = nullptr, - require_not_vt_var* = nullptr> + require_not_vt_var* = nullptr> Eigen::Matrix, Eigen::Dynamic, Eigen::Dynamic> eigenvectors_sym(const EigMat& m) { using PlainMat = plain_type_t; diff --git a/stan/math/prim/meta/forward_as.hpp b/stan/math/prim/meta/forward_as.hpp index 07ff0b1dea9..35e4378595c 100644 --- a/stan/math/prim/meta/forward_as.hpp +++ b/stan/math/prim/meta/forward_as.hpp @@ -30,9 +30,10 @@ constexpr bool eigen_static_size_match(T1 desired, T2 actual) { * @return the input value a */ template , - std::decay_t>::value - && !is_eigen::value>> + typename + = std::enable_if_t, + std::decay_t>::value + && !is_eigen::value>> inline T_actual&& forward_as(T_actual&& a) { // NOLINT return std::forward(a); } diff --git a/stan/math/rev/fun/cholesky_decompose.hpp b/stan/math/rev/fun/cholesky_decompose.hpp index a303a887862..e1a2be89c1f 100644 --- a/stan/math/rev/fun/cholesky_decompose.hpp +++ b/stan/math/rev/fun/cholesky_decompose.hpp @@ -40,7 +40,7 @@ inline Eigen::Matrix cholesky_decompose(const T& A) { const auto& A_ref = to_ref(A); Eigen::MatrixXd L_A_val = value_of(A_ref); - + check_not_nan("cholesky_decompose", "A", L_A_val); check_symmetric("cholesky_decompose", "A", L_A_val); Eigen::LLT, Eigen::Lower> L_factor(L_A_val); @@ -63,11 +63,11 @@ cholesky_decompose(const T& A) { size_t pos = 0; for (size_type j = 0; j < M; ++j) { for (size_type i = j; i < M; ++i) { - res_vars.coeffRef(pos) = L_A_val.coeff(i, j); - res.coeffRef(i, j) = res_vars.coeff(pos); - if(i != j) - res.coeffRef(j, i) = zero; - pos++; + res_vars.coeffRef(pos) = L_A_val.coeff(i, j); + res.coeffRef(i, j) = res_vars.coeff(pos); + if (i != j) + res.coeffRef(j, i) = zero; + pos++; } } @@ -88,58 +88,58 @@ cholesky_decompose(const T& A) { * @param L_adj matrix of adjoints of L */ auto symbolic_rev = [](auto& L, auto& L_adj) { - using Eigen::Upper; - using Eigen::Lower; - using Eigen::StrictlyUpper; - L.transposeInPlace(); - L_adj = (L * L_adj.template triangularView()).eval(); - L_adj.template triangularView() - = L_adj.adjoint().template triangularView(); - L.template triangularView().solveInPlace(L_adj); - L.template triangularView().solveInPlace(L_adj.transpose()); + using Eigen::Upper; + using Eigen::Lower; + using Eigen::StrictlyUpper; + L.transposeInPlace(); + L_adj = (L * L_adj.template triangularView()).eval(); + L_adj.template triangularView() + = L_adj.adjoint().template triangularView(); + L.template triangularView().solveInPlace(L_adj); + L.template triangularView().solveInPlace(L_adj.transpose()); }; Eigen::MatrixXd L_adj = Eigen::MatrixXd::Zero(M, M); Eigen::MatrixXd L = Eigen::MatrixXd::Zero(M, M); size_t pos = 0; for (size_type j = 0; j < M; ++j) { - for (size_type i = j; i < M; ++i) { - L_adj.coeffRef(i, j) = res_vars.coeff(pos).adj(); - L.coeffRef(i, j) = res_vars.coeff(pos).val(); - ++pos; - } + for (size_type i = j; i < M; ++i) { + L_adj.coeffRef(i, j) = res_vars.coeff(pos).adj(); + L.coeffRef(i, j) = res_vars.coeff(pos).val(); + ++pos; + } } for (int k = M; k > 0; k -= block_size) { - int j = std::max(0, k - block_size); - Block_ R = L.block(j, 0, k - j, j); - Block_ D = L.block(j, j, k - j, k - j); - Block_ B = L.block(k, 0, M - k, j); - Block_ C = L.block(k, j, M - k, k - j); - Block_ R_adj = L_adj.block(j, 0, k - j, j); - Block_ D_adj = L_adj.block(j, j, k - j, k - j); - Block_ B_adj = L_adj.block(k, 0, M - k, j); - Block_ C_adj = L_adj.block(k, j, M - k, k - j); - if (C_adj.size() > 0) { - C_adj = D.transpose() - .triangularView() - .solve(C_adj.transpose()) - .transpose(); - B_adj.noalias() -= C_adj * R; - D_adj.noalias() -= C_adj.transpose() * C; - } - symbolic_rev(D, D_adj); - R_adj.noalias() -= C_adj.transpose() * B; - R_adj.noalias() -= D_adj.selfadjointView() * R; - D_adj.diagonal() *= 0.5; - D_adj.triangularView().setZero(); + int j = std::max(0, k - block_size); + Block_ R = L.block(j, 0, k - j, j); + Block_ D = L.block(j, j, k - j, k - j); + Block_ B = L.block(k, 0, M - k, j); + Block_ C = L.block(k, j, M - k, k - j); + Block_ R_adj = L_adj.block(j, 0, k - j, j); + Block_ D_adj = L_adj.block(j, j, k - j, k - j); + Block_ B_adj = L_adj.block(k, 0, M - k, j); + Block_ C_adj = L_adj.block(k, j, M - k, k - j); + if (C_adj.size() > 0) { + C_adj = D.transpose() + .triangularView() + .solve(C_adj.transpose()) + .transpose(); + B_adj.noalias() -= C_adj * R; + D_adj.noalias() -= C_adj.transpose() * C; + } + symbolic_rev(D, D_adj); + R_adj.noalias() -= C_adj.transpose() * B; + R_adj.noalias() -= D_adj.selfadjointView() * R; + D_adj.diagonal() *= 0.5; + D_adj.triangularView().setZero(); } pos = 0; for (size_type j = 0; j < M; ++j) { - for (size_type i = j; i < M; ++i) { - arena_A(i, j).adj() += L_adj.coeffRef(i, j); - } + for (size_type i = j; i < M; ++i) { + arena_A(i, j).adj() += L_adj.coeffRef(i, j); + } } }); } else { @@ -158,44 +158,44 @@ cholesky_decompose(const T& A) { size_t pos = 0; for (int i = 0; i < M; ++i) { for (int j = 0; j <= i; ++j) { - res_vars.coeffRef(pos) = L_A_val.coeff(i, j); - res.coeffRef(i, j) = res_vars.coeff(pos); - if(i != j) - res.coeffRef(j, i) = zero; - pos++; + res_vars.coeffRef(pos) = L_A_val.coeff(i, j); + res.coeffRef(i, j) = res_vars.coeff(pos); + if (i != j) + res.coeffRef(j, i) = zero; + pos++; } } reverse_pass_callback([arena_A, M, res_vars]() mutable { - using RowMajorMatrixXd - = Eigen::Matrix; + using RowMajorMatrixXd = Eigen::Matrix; RowMajorMatrixXd adjL(M, M); RowMajorMatrixXd LA(M, M); RowMajorMatrixXd adjA(M, M); size_t pos = 0; for (size_t i = 0; i < M; ++i) - for (size_t j = 0; j <= i; ++j) { - adjL.coeffRef(i, j) = res_vars.coeff(pos).adj(); - LA.coeffRef(i, j) = res_vars.coeff(pos).val(); - pos++; - } + for (size_t j = 0; j <= i; ++j) { + adjL.coeffRef(i, j) = res_vars.coeff(pos).adj(); + LA.coeffRef(i, j) = res_vars.coeff(pos).val(); + pos++; + } for (int i = M - 1; i >= 0; --i) { - for (int j = i; j >= 0; --j) { - if (i == j) { - adjA.coeffRef(i, j) = 0.5 * adjL.coeff(i, j) / LA.coeff(i, j); - } else { - adjA.coeffRef(i, j) = adjL.coeff(i, j) / LA.coeff(j, j); - adjL.coeffRef(j, j) - -= adjL.coeff(i, j) * LA.coeff(i, j) / LA.coeff(j, j); - } - for (int k = j - 1; k >= 0; --k) { - adjL.coeffRef(i, k) -= adjA.coeff(i, j) * LA.coeff(j, k); - adjL.coeffRef(j, k) -= adjA.coeff(i, j) * LA.coeff(i, k); - } - - arena_A.coeff(i, j).adj() += adjA.coeffRef(i, j); - } + for (int j = i; j >= 0; --j) { + if (i == j) { + adjA.coeffRef(i, j) = 0.5 * adjL.coeff(i, j) / LA.coeff(i, j); + } else { + adjA.coeffRef(i, j) = adjL.coeff(i, j) / LA.coeff(j, j); + adjL.coeffRef(j, j) + -= adjL.coeff(i, j) * LA.coeff(i, j) / LA.coeff(j, j); + } + for (int k = j - 1; k >= 0; --k) { + adjL.coeffRef(i, k) -= adjA.coeff(i, j) * LA.coeff(j, k); + adjL.coeffRef(j, k) -= adjA.coeff(i, j) * LA.coeff(i, k); + } + + arena_A.coeff(i, j).adj() += adjA.coeffRef(i, j); + } } }); } diff --git a/stan/math/rev/fun/eigenvalues_sym.hpp b/stan/math/rev/fun/eigenvalues_sym.hpp index b43c883af37..1b0259b2e81 100644 --- a/stan/math/rev/fun/eigenvalues_sym.hpp +++ b/stan/math/rev/fun/eigenvalues_sym.hpp @@ -25,25 +25,25 @@ namespace math { * @return Eigenvalues of matrix. */ template * = nullptr> -inline Eigen::Matrix -eigenvalues_sym(const T &m) { +inline Eigen::Matrix eigenvalues_sym(const T& m) { const auto& m_ref = to_ref(m); - arena_matrix> - arena_m = m_ref; + arena_matrix> arena_m + = m_ref; check_square("eigenvalues_sym", "m", m_ref); Eigen::MatrixXd m_val = value_of(m_ref); check_nonzero_size("eigenvalues_sym", "m", m_val); check_symmetric("eigenvalues_sym", "m", m_val); Eigen::SelfAdjointEigenSolver solver(m_val); - arena_matrix> - eigenvalues = solver.eigenvalues(); + arena_matrix> eigenvalues + = solver.eigenvalues(); arena_matrix arena_eigenvectors_val = solver.eigenvectors(); - reverse_pass_callback([arena_m, arena_eigenvectors_val, eigenvalues]() mutable { - arena_m.adj() += arena_eigenvectors_val * eigenvalues.adj().asDiagonal() * - arena_eigenvectors_val.transpose(); - }); + reverse_pass_callback( + [arena_m, arena_eigenvectors_val, eigenvalues]() mutable { + arena_m.adj() += arena_eigenvectors_val * eigenvalues.adj().asDiagonal() + * arena_eigenvectors_val.transpose(); + }); return eigenvalues; } diff --git a/stan/math/rev/fun/eigenvectors_sym.hpp b/stan/math/rev/fun/eigenvectors_sym.hpp index 48afa2e0c9e..85b5350e1ab 100644 --- a/stan/math/rev/fun/eigenvectors_sym.hpp +++ b/stan/math/rev/fun/eigenvectors_sym.hpp @@ -23,11 +23,11 @@ namespace math { * @return Eigenvectors of matrix */ template * = nullptr> -inline Eigen::Matrix -eigenvectors_sym(const T &m) { +inline Eigen::Matrix eigenvectors_sym( + const T& m) { const auto& m_ref = to_ref(m); - arena_matrix> - arena_m = m_ref; + arena_matrix> arena_m + = m_ref; check_square("eigenvalues_sym", "m", m_ref); Eigen::MatrixXd m_val = value_of(m_ref); check_nonzero_size("eigenvalues_sym", "m", m_val); @@ -35,23 +35,25 @@ eigenvectors_sym(const T &m) { Eigen::SelfAdjointEigenSolver solver(m_val); arena_matrix arena_eigenvectors_val = solver.eigenvectors(); - arena_matrix> - res = arena_eigenvectors_val; - + arena_matrix> res + = arena_eigenvectors_val; + int M = m_val.rows(); arena_matrix arena_f(M, M); for (int i = 0; i < M; i++) for (int j = 0; j < M; j++) - arena_f.coeffRef(j, i) = (i != j ? 1 / - (solver.eigenvalues().coeff(i) - solver.eigenvalues().coeff(j)) : 0); + arena_f.coeffRef(j, i) = (i != j ? 1 + / (solver.eigenvalues().coeff(i) + - solver.eigenvalues().coeff(j)) + : 0); - reverse_pass_callback([arena_m, arena_eigenvectors_val, - arena_f, res]() mutable { + reverse_pass_callback([arena_m, arena_eigenvectors_val, arena_f, + res]() mutable { Eigen::MatrixXd adj = res.adj(); Eigen::MatrixXd adj2 = arena_eigenvectors_val.transpose() * adj; Eigen::MatrixXd tmp = arena_f.cwiseProduct(adj2); - arena_m.adj() += arena_eigenvectors_val * tmp * - arena_eigenvectors_val.transpose(); + arena_m.adj() + += arena_eigenvectors_val * tmp * arena_eigenvectors_val.transpose(); }); return res; From acd76941152a6201058acbe9ad991967fb053bac Mon Sep 17 00:00:00 2001 From: Ben Date: Thu, 10 Sep 2020 17:56:21 -0400 Subject: [PATCH 249/355] Added ldlt functions (Issue #2018) --- .../prim/fun/trace_gen_inv_quad_form_ldlt.hpp | 2 +- .../prim/fun/trace_inv_quad_form_ldlt.hpp | 2 +- stan/math/rev/fun/LDLT_alloc.hpp | 4 +- stan/math/rev/fun/log_determinant_ldlt.hpp | 33 +-- stan/math/rev/fun/mdivide_left_ldlt.hpp | 271 ++---------------- .../rev/fun/trace_gen_inv_quad_form_ldlt.hpp | 78 ++++- .../math/rev/fun/trace_inv_quad_form_ldlt.hpp | 186 +++--------- 7 files changed, 148 insertions(+), 428 deletions(-) diff --git a/stan/math/prim/fun/trace_gen_inv_quad_form_ldlt.hpp b/stan/math/prim/fun/trace_gen_inv_quad_form_ldlt.hpp index c6f0784e85e..181cc753001 100644 --- a/stan/math/prim/fun/trace_gen_inv_quad_form_ldlt.hpp +++ b/stan/math/prim/fun/trace_gen_inv_quad_form_ldlt.hpp @@ -33,7 +33,7 @@ namespace math { * be multiplied by D. */ template > + typename = require_all_not_st_var> inline return_type_t trace_gen_inv_quad_form_ldlt( const EigMat1& D, const LDLT_factor& A, const EigMat3& B) { check_square("trace_gen_inv_quad_form_ldlt", "D", D); diff --git a/stan/math/prim/fun/trace_inv_quad_form_ldlt.hpp b/stan/math/prim/fun/trace_inv_quad_form_ldlt.hpp index ae6f9c6249f..15de3399147 100644 --- a/stan/math/prim/fun/trace_inv_quad_form_ldlt.hpp +++ b/stan/math/prim/fun/trace_inv_quad_form_ldlt.hpp @@ -25,7 +25,7 @@ namespace math { * */ template > + require_all_not_st_var* = nullptr> inline return_type_t trace_inv_quad_form_ldlt( const LDLT_factor& A, const EigMat2& B) { check_multiplicable("trace_inv_quad_form_ldlt", "A", A, "B", B); diff --git a/stan/math/rev/fun/LDLT_alloc.hpp b/stan/math/rev/fun/LDLT_alloc.hpp index 887a2260161..6a2b2f734e2 100644 --- a/stan/math/rev/fun/LDLT_alloc.hpp +++ b/stan/math/rev/fun/LDLT_alloc.hpp @@ -36,7 +36,7 @@ class LDLT_alloc : public chainable_alloc { **/ inline void compute(const Eigen::Matrix &A) { N_ = A.rows(); - variA_ = A.vi(); + arena_A_ = A; ldlt_.compute(A.val()); } @@ -47,7 +47,7 @@ class LDLT_alloc : public chainable_alloc { size_t N_; Eigen::LDLT > ldlt_; - Eigen::Matrix variA_; + arena_matrix> arena_A_; }; } // namespace math diff --git a/stan/math/rev/fun/log_determinant_ldlt.hpp b/stan/math/rev/fun/log_determinant_ldlt.hpp index 8b7f9dbac8c..d5ebb737287 100644 --- a/stan/math/rev/fun/log_determinant_ldlt.hpp +++ b/stan/math/rev/fun/log_determinant_ldlt.hpp @@ -10,7 +10,6 @@ namespace stan { namespace math { -namespace internal { /** * Returns the log det of the matrix whose LDLT factorization is given @@ -21,33 +20,25 @@ namespace internal { * @tparam C number of columns, can be Eigen::Dynamic * @param A an LDLT_factor * @return ln(det(A)) - * @throws never */ -template -class log_det_ldlt_vari : public vari { - public: - explicit log_det_ldlt_vari(const LDLT_factor &A) - : vari(A.alloc_->log_abs_det()), alloc_ldlt_(A.alloc_) {} - - virtual void chain() { - Eigen::Matrix invA; - - // If we start computing Jacobians, this may be a bit inefficient - invA.setIdentity(alloc_ldlt_->N_, alloc_ldlt_->N_); - alloc_ldlt_->ldlt_.solveInPlace(invA); - const_cast(alloc_ldlt_->variA_).adj() += adj_ * invA; - } - const LDLT_alloc *alloc_ldlt_; -}; -} // namespace internal - template var log_determinant_ldlt(LDLT_factor &A) { if (A.rows() == 0) { return 0; } - return var(new internal::log_det_ldlt_vari(A)); + var log_det = A.alloc_->log_abs_det(); + + arena_matrix> arena_A_inv(A.rows(), A.cols()); + + arena_A_inv.setIdentity(); + A.alloc_->ldlt_.solveInPlace(arena_A_inv); + + reverse_pass_callback([A, log_det, arena_A_inv]() mutable { + A.alloc_->arena_A_.adj() += log_det.adj() * arena_A_inv; + }); + + return log_det; } } // namespace math diff --git a/stan/math/rev/fun/mdivide_left_ldlt.hpp b/stan/math/rev/fun/mdivide_left_ldlt.hpp index f281bc11f58..db901201937 100644 --- a/stan/math/rev/fun/mdivide_left_ldlt.hpp +++ b/stan/math/rev/fun/mdivide_left_ldlt.hpp @@ -13,183 +13,6 @@ namespace stan { namespace math { -namespace internal { - -template -class mdivide_left_ldlt_alloc : public chainable_alloc { - public: - virtual ~mdivide_left_ldlt_alloc() {} - - /** - * This share_ptr is used to prevent copying the LDLT factorizations - * for mdivide_left_ldlt(ldltA, b) when ldltA is a LDLT_factor. - * The pointer is shared with the LDLT_factor class. - **/ - std::shared_ptr > > ldltP_; - Eigen::Matrix C_; -}; - -/** - * The vari for mdivide_left_ldlt(A, b) which handles the chain() call - * for all elements of the result. This vari follows the pattern - * used in the other matrix operations where there is one "master" - * vari whose value is never used and a large number of "slave" varis - * whose chain() functions are never called because their adjoints are - * set by the "master" vari. - * - * This class handles the var/var case. - * - * @tparam R1 number of rows in the LDLT_factor, can be Eigen::Dynamic - * @tparam C1 number of columns in the LDLT_factor, can be Eigen::Dynamic - * @tparam R2 number of rows in the right-hand side matrix, can be - * Eigen::Dynamic - * @tparam C2 number of columns in the right-hand side matrix, can be - * Eigen::Dynamic - */ -template -class mdivide_left_ldlt_vv_vari : public vari { - public: - int M_; // A.rows() = A.cols() = B.rows() - int N_; // B.cols() - vari **variRefB_; - vari **variRefC_; - mdivide_left_ldlt_alloc *alloc_; - const LDLT_alloc *alloc_ldlt_; - - mdivide_left_ldlt_vv_vari(const LDLT_factor &A, - const Eigen::Matrix &B) - : vari(0.0), - M_(A.rows()), - N_(B.cols()), - variRefB_(reinterpret_cast( - ChainableStack::instance_->memalloc_.alloc(sizeof(vari *) * B.rows() - * B.cols()))), - variRefC_(reinterpret_cast( - ChainableStack::instance_->memalloc_.alloc(sizeof(vari *) * B.rows() - * B.cols()))), - alloc_(new mdivide_left_ldlt_alloc()), - alloc_ldlt_(A.alloc_) { - Eigen::Map(variRefB_, M_, N_) = B.vi(); - alloc_->C_ = B.val(); - alloc_ldlt_->ldlt_.solveInPlace(alloc_->C_); - Eigen::Map(variRefC_, M_, N_) - = alloc_->C_.unaryExpr([](double x) { return new vari(x, false); }); - } - - virtual void chain() { - matrix_d adjB = Eigen::Map(variRefC_, M_, N_).adj(); - - alloc_ldlt_->ldlt_.solveInPlace(adjB); - - const_cast(alloc_ldlt_->variA_).adj() - -= adjB * alloc_->C_.transpose(); - Eigen::Map(variRefB_, M_, N_).adj() += adjB; - } -}; - -/** - * The vari for mdivide_left_ldlt(A, b) which handles the chain() call - * for all elements of the result. This vari follows the pattern - * used in the other matrix operations where there is one "master" - * vari whose value is never used and a large number of "slave" varis - * whose chain() functions are never called because their adjoints are - * set by the "master" vari. - * - * This class handles the double/var case. - * - * @tparam R1 number of rows in the LDLT_factor, can be Eigen::Dynamic - * @tparam C1 number of columns in the LDLT_factor, can be Eigen::Dynamic - * @tparam R2 number of rows in the right-hand side matrix, can be - * Eigen::Dynamic - * @tparam C2 number of columns in the right-hand side matrix, can be - * Eigen::Dynamic - */ -template -class mdivide_left_ldlt_dv_vari : public vari { - public: - int M_; // A.rows() = A.cols() = B.rows() - int N_; // B.cols() - vari **variRefB_; - vari **variRefC_; - mdivide_left_ldlt_alloc *alloc_; - - mdivide_left_ldlt_dv_vari(const LDLT_factor &A, - const Eigen::Matrix &B) - : vari(0.0), - M_(A.rows()), - N_(B.cols()), - variRefB_(reinterpret_cast( - ChainableStack::instance_->memalloc_.alloc(sizeof(vari *) * B.rows() - * B.cols()))), - variRefC_(reinterpret_cast( - ChainableStack::instance_->memalloc_.alloc(sizeof(vari *) * B.rows() - * B.cols()))), - alloc_(new mdivide_left_ldlt_alloc()) { - Eigen::Map(variRefB_, M_, N_) = B.vi(); - alloc_->C_ = B.val(); - alloc_->ldltP_ = A.ldltP_; - alloc_->ldltP_->solveInPlace(alloc_->C_); - Eigen::Map(variRefC_, M_, N_) - = alloc_->C_.unaryExpr([](double x) { return new vari(x, false); }); - } - - virtual void chain() { - matrix_d adjB = Eigen::Map(variRefC_, M_, N_).adj(); - alloc_->ldltP_->solveInPlace(adjB); - Eigen::Map(variRefB_, M_, N_).adj() += adjB; - } -}; - -/** - * The vari for mdivide_left_ldlt(A, b) which handles the chain() call - * for all elements of the result. This vari follows the pattern - * used in the other matrix operations where there is one "master" - * vari whose value is never used and a large number of "slave" varis - * whose chain() functions are never called because their adjoints are - * set by the "master" vari. - * - * This class handles the var/double case. - * - * @tparam R1 number of rows in the LDLT_factor, can be Eigen::Dynamic - * @tparam C1 number of columns in the LDLT_factor, can be Eigen::Dynamic - * @tparam R2 number of rows in the right-hand side matrix, can be - * Eigen::Dynamic - * @tparam C2 number of columns in the right-hand side matrix, can be - * Eigen::Dynamic - */ -template -class mdivide_left_ldlt_vd_vari : public vari { - public: - int M_; // A.rows() = A.cols() = B.rows() - int N_; // B.cols() - vari **variRefC_; - mdivide_left_ldlt_alloc *alloc_; - const LDLT_alloc *alloc_ldlt_; - - mdivide_left_ldlt_vd_vari(const LDLT_factor &A, - const Eigen::Matrix &B) - : vari(0.0), - M_(A.rows()), - N_(B.cols()), - variRefC_(reinterpret_cast( - ChainableStack::instance_->memalloc_.alloc(sizeof(vari *) * B.rows() - * B.cols()))), - alloc_(new mdivide_left_ldlt_alloc()), - alloc_ldlt_(A.alloc_) { - alloc_->C_ = B; - alloc_ldlt_->ldlt_.solveInPlace(alloc_->C_); - Eigen::Map(variRefC_, M_, N_) - = alloc_->C_.unaryExpr([](double x) { return new vari(x, false); }); - } - - virtual void chain() { - matrix_d adjC = Eigen::Map(variRefC_, M_, N_).adj(); - - const_cast(alloc_ldlt_->variA_).adj() - -= alloc_ldlt_->ldlt_.solve(adjC * alloc_->C_.transpose()); - } -}; -} // namespace internal /** * Returns the solution of the system Ax=b given an LDLT_factor of A @@ -202,85 +25,43 @@ class mdivide_left_ldlt_vd_vari : public vari { * @return x = A^-1 b, solution of the linear system. * @throws std::domain_error if rows of b don't match the size of A. */ -template * = nullptr> -inline Eigen::Matrix mdivide_left_ldlt( - const LDLT_factor &A, const EigMat &b) { - constexpr int R2 = EigMat::RowsAtCompileTime; - constexpr int C2 = EigMat::ColsAtCompileTime; - check_multiplicable("mdivide_left_ldlt", "A", A, "b", b); - if (A.cols() == 0) { - return {0, b.cols()}; - } +template * = nullptr, + require_any_st_var* = nullptr> +inline Eigen::Matrix + mdivide_left_ldlt(const LDLT_factor &A, const T2& B) { + check_multiplicable("mdivide_left_ldlt", "A", A, "B", B); - auto *baseVari - = new internal::mdivide_left_ldlt_vv_vari(A, b); + using B_ref_t = ref_type_t; - Eigen::Matrix res(b.rows(), b.cols()); - res.vi() = Eigen::Map(baseVari->variRefC_, res.rows(), res.cols()); + B_ref_t B_ref = B; - return res; -} - -/** - * Returns the solution of the system Ax=b given an LDLT_factor of A - * - * @tparam R1 number of rows in the LDLT_factor, can be Eigen::Dynamic - * @tparam C1 number of columns in the LDLT_factor, can be Eigen::Dynamic - * - * @param A LDLT_factor - * @param b Right hand side matrix or vector. - * @return x = A^-1 b, solution of the linear system. - * @throws std::domain_error if rows of b don't match the size of A. - */ -template * = nullptr> -inline Eigen::Matrix mdivide_left_ldlt( - const LDLT_factor &A, const EigMat &b) { - constexpr int R2 = EigMat::RowsAtCompileTime; - constexpr int C2 = EigMat::ColsAtCompileTime; - check_multiplicable("mdivide_left_ldlt", "A", A, "b", b); if (A.cols() == 0) { - return {0, b.cols()}; + return {0, B.cols()}; } - auto *baseVari - = new internal::mdivide_left_ldlt_vd_vari(A, b); + arena_matrix> arena_B; - Eigen::Matrix res(b.rows(), b.cols()); - res.vi() = Eigen::Map(baseVari->variRefC_, res.rows(), res.cols()); - - return res; -} - -/** - * Returns the solution of the system Ax=b given an LDLT_factor of A - * - * @tparam R1 number of rows in the LDLT_factor, can be Eigen::Dynamic - * @tparam C1 number of columns in the LDLT_factor, can be Eigen::Dynamic - * - * @param A LDLT_factor - * @param b Right hand side matrix or vector. - * @return x = A^-1 b, solution of the linear system. - * @throws std::domain_error if rows of b don't match the size of A. - */ -template * = nullptr> -inline Eigen::Matrix mdivide_left_ldlt( - const LDLT_factor &A, const EigMat &b) { - constexpr int R2 = EigMat::RowsAtCompileTime; - constexpr int C2 = EigMat::ColsAtCompileTime; - check_multiplicable("mdivide_left_ldlt", "A", A, "b", b); - if (A.cols() == 0) { - return {0, b.cols()}; + if (!is_constant::value) { + arena_B = B_ref; } - auto *baseVari - = new internal::mdivide_left_ldlt_dv_vari(A, b); + arena_matrix> + res = A.solve(value_of(B_ref)); + + reverse_pass_callback([A, arena_B, res]() mutable { + Eigen::Matrix adjB + = A.solve(res.adj()); - Eigen::Matrix res(b.rows(), b.cols()); - res.vi() = Eigen::Map(baseVari->variRefC_, res.rows(), res.cols()); + if (!is_constant::value) + forward_as>(A).alloc_->arena_A_.adj() + += -adjB * res.val().transpose().eval(); + if (!is_constant::value) + forward_as>(arena_B).adj() += adjB; + }); + return res; } diff --git a/stan/math/rev/fun/trace_gen_inv_quad_form_ldlt.hpp b/stan/math/rev/fun/trace_gen_inv_quad_form_ldlt.hpp index 59a00e4aa56..a9b3b9b72f1 100644 --- a/stan/math/rev/fun/trace_gen_inv_quad_form_ldlt.hpp +++ b/stan/math/rev/fun/trace_gen_inv_quad_form_ldlt.hpp @@ -28,15 +28,13 @@ namespace math { * @param B a matrix * @return The trace of the inverse quadratic form. */ -template * = nullptr, - require_any_vt_var* = nullptr> -inline var trace_gen_inv_quad_form_ldlt(const EigMat1& D, - const LDLT_factor& A, - const EigMat3& B) { - using T3 = value_type_t; - constexpr int R3 = EigMat3::RowsAtCompileTime; - constexpr int C3 = EigMat3::ColsAtCompileTime; +template * = nullptr, + require_any_st_var* = nullptr> +inline var trace_gen_inv_quad_form_ldlt(const Td& D, + const LDLT_factor& A, + const Tb& B) { check_square("trace_gen_inv_quad_form_ldlt", "D", D); check_multiplicable("trace_gen_inv_quad_form_ldlt", "A", A, "B", B); check_multiplicable("trace_gen_inv_quad_form_ldlt", "B", B, "D", D); @@ -44,13 +42,63 @@ inline var trace_gen_inv_quad_form_ldlt(const EigMat1& D, return 0; } - auto* _impl - = new internal::trace_inv_quad_form_ldlt_impl( - D, A, B); + using B_ref_t = ref_type_t; + using D_ref_t = ref_type_t; - return var( - new internal::trace_inv_quad_form_ldlt_vari( - _impl)); + B_ref_t B_ref = B; + D_ref_t D_ref = D; + + arena_matrix> arena_B_val = value_of(B_ref); + arena_matrix> arena_D_val; + arena_matrix> AsolveB + = A.solve(arena_B_val); + + arena_matrix> arena_B; + arena_matrix> arena_D; + + if (!is_constant::value) { + arena_B = B_ref; + } + + if (!is_constant::value) { + arena_D = D_ref; + } + + if (!is_constant_all::value) { + arena_D_val = value_of(D_ref); + } + + var res; + + if (!is_constant_all::value) { + res = (arena_D_val * arena_B_val.transpose() * AsolveB) + .trace(); + } else { + res = (value_of(D) * arena_B_val.transpose() * AsolveB) + .trace(); + } + + reverse_pass_callback([A, AsolveB, + arena_B, arena_D, + arena_B_val, arena_D_val, + res]() mutable { + double C_adj = res.adj(); + + if (!is_constant::value) { + forward_as>(A).alloc_->arena_A_.adj() += + -C_adj * AsolveB * arena_D_val.transpose() * AsolveB.transpose(); + } + + if (!is_constant::value) + arena_B.adj() += C_adj * AsolveB + * (arena_D_val + arena_D_val.transpose()); + + if (!is_constant::value) + arena_D.adj() + += C_adj * arena_B_val.transpose() * AsolveB; + }); + + return res; } } // namespace math diff --git a/stan/math/rev/fun/trace_inv_quad_form_ldlt.hpp b/stan/math/rev/fun/trace_inv_quad_form_ldlt.hpp index 1803db2cdcc..0fd59fcb3e7 100644 --- a/stan/math/rev/fun/trace_inv_quad_form_ldlt.hpp +++ b/stan/math/rev/fun/trace_inv_quad_form_ldlt.hpp @@ -14,164 +14,64 @@ namespace stan { namespace math { -namespace internal { - -template -class trace_inv_quad_form_ldlt_impl : public chainable_alloc { - protected: - inline void initializeB(const Eigen::Matrix &B, bool haveD) { - matrix_d Bd = B.val(); - variB_ = B.vi(); - AinvB_ = ldlt_.solve(Bd); - if (haveD) { - C_.noalias() = Bd.transpose() * AinvB_; - } else { - value_ = (Bd.transpose() * AinvB_).trace(); - } - } - inline void initializeB(const Eigen::Matrix &B, bool haveD) { - AinvB_ = ldlt_.solve(B); - if (haveD) { - C_.noalias() = B.transpose() * AinvB_; - } else { - value_ = (B.transpose() * AinvB_).trace(); - } - } - - template - inline void initializeD(const Eigen::Matrix &D) { - D_ = D.val(); - variD_ = D.vi(); - } - template - inline void initializeD(const Eigen::Matrix &D) { - D_ = D; - } - - public: - template - trace_inv_quad_form_ldlt_impl(const Eigen::Matrix &D, - const LDLT_factor &A, - const Eigen::Matrix &B) - : Dtype_(stan::is_var::value), ldlt_(A) { - initializeB(B, true); - initializeD(D); - - value_ = (D_ * C_).trace(); - } - - trace_inv_quad_form_ldlt_impl(const LDLT_factor &A, - const Eigen::Matrix &B) - : Dtype_(2), ldlt_(A) { - initializeB(B, false); - } - - const int Dtype_; // 0 = double, 1 = var, 2 = missing - LDLT_factor ldlt_; - matrix_d D_; - matrix_vi variD_; - matrix_vi variB_; - matrix_d AinvB_; - matrix_d C_; - double value_; -}; - -template -class trace_inv_quad_form_ldlt_vari : public vari { - protected: - static inline void chainA( - double adj, - trace_inv_quad_form_ldlt_impl *impl) {} - static inline void chainB( - double adj, - trace_inv_quad_form_ldlt_impl *impl) {} - - static inline void chainA( - double adj, - trace_inv_quad_form_ldlt_impl *impl) { - Eigen::Matrix aA; - - if (impl->Dtype_ != 2) { - aA.noalias() - = -adj - * (impl->AinvB_ * impl->D_.transpose() * impl->AinvB_.transpose()); - } else { - aA.noalias() = -adj * (impl->AinvB_ * impl->AinvB_.transpose()); - } - - impl->ldlt_.alloc_->variA_.adj() += aA; - } - static inline void chainB( - double adj, - trace_inv_quad_form_ldlt_impl *impl) { - matrix_d aB; - - if (impl->Dtype_ != 2) { - aB.noalias() = adj * impl->AinvB_ * (impl->D_ + impl->D_.transpose()); - } else { - aB.noalias() = 2 * adj * impl->AinvB_; - } - - impl->variB_.adj() += aB; - } - - public: - explicit trace_inv_quad_form_ldlt_vari( - trace_inv_quad_form_ldlt_impl *impl) - : vari(impl->value_), impl_(impl) {} - - virtual void chain() { - // F = trace(D * B' * inv(A) * B) - // aA = -aF * inv(A') * B * D' * B' * inv(A') - // aB = aF*(inv(A) * B * D + inv(A') * B * D') - // aD = aF*(B' * inv(A) * B) - chainA(adj_, impl_); - - chainB(adj_, impl_); - - if (impl_->Dtype_ == 1) { - impl_->variD_.adj() += adj_ * impl_->C_; - } - } - - trace_inv_quad_form_ldlt_impl *impl_; -}; - -} // namespace internal /** - * Compute the trace of an inverse quadratic form. I.E., this computes + * Compute the trace of an inverse quadratic form premultiplied by a + * square matrix. This computes * trace(B^T A^-1 B) * where the LDLT_factor of A is provided. * * @tparam T type of elements in the LDLT_factor - * @tparam R number of rows, can be Eigen::Dynamic - * @tparam C number of columns, can be Eigen::Dynamic - * @tparam EigMat3 type of the second matrix + * @tparam R number of rows in the LDLT_factor, can be Eigen::Dynamic + * @tparam C number of columns in the LDLT_factor, can be Eigen::Dynamic + * @tparam EigMat type of the first matrix * * @param A an LDLT_factor * @param B a matrix * @return The trace of the inverse quadratic form. */ -template > -inline return_type_t trace_inv_quad_form_ldlt( - const LDLT_factor &A, const EigMat &B) { - using T2 = value_type_t; - constexpr int R2 = EigMat::RowsAtCompileTime; - constexpr int C2 = EigMat::ColsAtCompileTime; - check_multiplicable("trace_inv_quad_form_ldlt", "A", A, "B", B); - if (A.cols() == 0) { - return 0; +template * = nullptr, + require_any_st_var* = nullptr> +inline var trace_inv_quad_form_ldlt(const LDLT_factor& A, + const EigMat& B) { + check_multiplicable("trace_quad_form", "A", A, "B", B); + + if(A.rows() == 0) + return 0.0; + + using B_ref_t = ref_type_t; + + B_ref_t B_ref = B; + arena_matrix> arena_B_val = value_of(B_ref); + arena_matrix> arena_B; + arena_matrix> AsolveB + = A.solve(arena_B_val); + + if (!is_constant::value) { + arena_B = B_ref; } - auto *impl_ - = new internal::trace_inv_quad_form_ldlt_impl(A, B); + var res = (arena_B_val.transpose() * AsolveB).trace(); - return var( - new internal::trace_inv_quad_form_ldlt_vari(impl_)); -} + reverse_pass_callback([A, AsolveB, + arena_B, arena_B_val, + res]() mutable { + double C_adj = res.adj(); + if (!is_constant::value) { + forward_as>(A).alloc_->arena_A_.adj() + += -C_adj * AsolveB * AsolveB.transpose(); + } + + if (!is_constant::value) + arena_B.adj() += 2 * C_adj * AsolveB; + }); + + return res; +} + } // namespace math } // namespace stan #endif From 26e1740cb11578f5eda6c83373310df87a2eade9 Mon Sep 17 00:00:00 2001 From: Ben Date: Thu, 10 Sep 2020 18:22:41 -0400 Subject: [PATCH 250/355] Updated template logic in trace_gen_quad_form (Issue #2018) --- stan/math/rev/fun/trace_gen_quad_form.hpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/stan/math/rev/fun/trace_gen_quad_form.hpp b/stan/math/rev/fun/trace_gen_quad_form.hpp index f575060697c..b51de16168d 100644 --- a/stan/math/rev/fun/trace_gen_quad_form.hpp +++ b/stan/math/rev/fun/trace_gen_quad_form.hpp @@ -52,22 +52,22 @@ inline var trace_gen_quad_form(const Td& D, const Ta& A, const Tb& B) { arena_D = D_ref; } - if (!is_constant::value) { + if (!is_constant_all::value) { arena_A_val = value_of(A_ref); } - if (!is_constant::value) { + if (!is_constant_all::value) { arena_D_val = value_of(D_ref); } var res; - if (!is_constant::value && !is_constant::value - && is_constant::value) { + if (is_constant::value && is_constant::value + && !is_constant::value) { res = (value_of(D) * arena_B_val.transpose() * arena_A_val * arena_B_val) .trace(); - } else if (is_constant::value && !is_constant::value - && !is_constant::value) { + } else if (!is_constant::value && is_constant::value + && is_constant::value) { res = (arena_D_val * arena_B_val.transpose() * value_of(A) * arena_B_val) .trace(); } else { From 9558a58fcdac49705c728ca4f5b541f3f01e9fb0 Mon Sep 17 00:00:00 2001 From: Ben Date: Thu, 10 Sep 2020 18:37:43 -0400 Subject: [PATCH 251/355] Added const to log_determinant_ldlt (Issue #2018) --- stan/math/rev/fun/log_determinant_ldlt.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stan/math/rev/fun/log_determinant_ldlt.hpp b/stan/math/rev/fun/log_determinant_ldlt.hpp index d5ebb737287..3c8e9d6484e 100644 --- a/stan/math/rev/fun/log_determinant_ldlt.hpp +++ b/stan/math/rev/fun/log_determinant_ldlt.hpp @@ -22,7 +22,7 @@ namespace math { * @return ln(det(A)) */ template -var log_determinant_ldlt(LDLT_factor &A) { +var log_determinant_ldlt(const LDLT_factor &A) { if (A.rows() == 0) { return 0; } From 10566a05aae30a2ac7e81ff3ab871d4dd63be4d8 Mon Sep 17 00:00:00 2001 From: Stan Jenkins Date: Thu, 10 Sep 2020 22:38:19 +0000 Subject: [PATCH 252/355] [Jenkins] auto-formatting by clang-format version 6.0.0-1ubuntu2~16.04.1 (tags/RELEASE_600/final) --- stan/math/rev/fun/LDLT_alloc.hpp | 2 +- stan/math/rev/fun/log_determinant_ldlt.hpp | 2 +- stan/math/rev/fun/mdivide_left_ldlt.hpp | 21 ++++++------- .../rev/fun/trace_gen_inv_quad_form_ldlt.hpp | 30 ++++++++----------- .../math/rev/fun/trace_inv_quad_form_ldlt.hpp | 19 +++++------- 5 files changed, 31 insertions(+), 43 deletions(-) diff --git a/stan/math/rev/fun/LDLT_alloc.hpp b/stan/math/rev/fun/LDLT_alloc.hpp index 6a2b2f734e2..fa7c28ecc43 100644 --- a/stan/math/rev/fun/LDLT_alloc.hpp +++ b/stan/math/rev/fun/LDLT_alloc.hpp @@ -46,7 +46,7 @@ class LDLT_alloc : public chainable_alloc { } size_t N_; - Eigen::LDLT > ldlt_; + Eigen::LDLT> ldlt_; arena_matrix> arena_A_; }; diff --git a/stan/math/rev/fun/log_determinant_ldlt.hpp b/stan/math/rev/fun/log_determinant_ldlt.hpp index d5ebb737287..c70c29fe60a 100644 --- a/stan/math/rev/fun/log_determinant_ldlt.hpp +++ b/stan/math/rev/fun/log_determinant_ldlt.hpp @@ -37,7 +37,7 @@ var log_determinant_ldlt(LDLT_factor &A) { reverse_pass_callback([A, log_det, arena_A_inv]() mutable { A.alloc_->arena_A_.adj() += log_det.adj() * arena_A_inv; }); - + return log_det; } diff --git a/stan/math/rev/fun/mdivide_left_ldlt.hpp b/stan/math/rev/fun/mdivide_left_ldlt.hpp index db901201937..07f88c4cc65 100644 --- a/stan/math/rev/fun/mdivide_left_ldlt.hpp +++ b/stan/math/rev/fun/mdivide_left_ldlt.hpp @@ -25,12 +25,10 @@ namespace math { * @return x = A^-1 b, solution of the linear system. * @throws std::domain_error if rows of b don't match the size of A. */ -template * = nullptr, - require_any_st_var* = nullptr> -inline Eigen::Matrix - mdivide_left_ldlt(const LDLT_factor &A, const T2& B) { +template * = nullptr, require_any_st_var* = nullptr> +inline Eigen::Matrix mdivide_left_ldlt( + const LDLT_factor& A, const T2& B) { check_multiplicable("mdivide_left_ldlt", "A", A, "B", B); using B_ref_t = ref_type_t; @@ -47,21 +45,20 @@ inline Eigen::Matrix arena_B = B_ref; } - arena_matrix> - res = A.solve(value_of(B_ref)); + arena_matrix> res + = A.solve(value_of(B_ref)); reverse_pass_callback([A, arena_B, res]() mutable { - Eigen::Matrix adjB - = A.solve(res.adj()); + Eigen::Matrix adjB = A.solve(res.adj()); if (!is_constant::value) forward_as>(A).alloc_->arena_A_.adj() - += -adjB * res.val().transpose().eval(); + += -adjB * res.val().transpose().eval(); if (!is_constant::value) forward_as>(arena_B).adj() += adjB; }); - + return res; } diff --git a/stan/math/rev/fun/trace_gen_inv_quad_form_ldlt.hpp b/stan/math/rev/fun/trace_gen_inv_quad_form_ldlt.hpp index a9b3b9b72f1..e46cfc977f8 100644 --- a/stan/math/rev/fun/trace_gen_inv_quad_form_ldlt.hpp +++ b/stan/math/rev/fun/trace_gen_inv_quad_form_ldlt.hpp @@ -28,8 +28,7 @@ namespace math { * @param B a matrix * @return The trace of the inverse quadratic form. */ -template * = nullptr, require_any_st_var* = nullptr> inline var trace_gen_inv_quad_form_ldlt(const Td& D, @@ -51,7 +50,7 @@ inline var trace_gen_inv_quad_form_ldlt(const Td& D, arena_matrix> arena_B_val = value_of(B_ref); arena_matrix> arena_D_val; arena_matrix> AsolveB - = A.solve(arena_B_val); + = A.solve(arena_B_val); arena_matrix> arena_B; arena_matrix> arena_D; @@ -71,31 +70,26 @@ inline var trace_gen_inv_quad_form_ldlt(const Td& D, var res; if (!is_constant_all::value) { - res = (arena_D_val * arena_B_val.transpose() * AsolveB) - .trace(); + res = (arena_D_val * arena_B_val.transpose() * AsolveB).trace(); } else { - res = (value_of(D) * arena_B_val.transpose() * AsolveB) - .trace(); + res = (value_of(D) * arena_B_val.transpose() * AsolveB).trace(); } - reverse_pass_callback([A, AsolveB, - arena_B, arena_D, - arena_B_val, arena_D_val, - res]() mutable { - double C_adj = res.adj(); + reverse_pass_callback([A, AsolveB, arena_B, arena_D, arena_B_val, arena_D_val, + res]() mutable { + double C_adj = res.adj(); if (!is_constant::value) { - forward_as>(A).alloc_->arena_A_.adj() += - -C_adj * AsolveB * arena_D_val.transpose() * AsolveB.transpose(); + forward_as>(A).alloc_->arena_A_.adj() + += -C_adj * AsolveB * arena_D_val.transpose() * AsolveB.transpose(); } if (!is_constant::value) - arena_B.adj() += C_adj * AsolveB - * (arena_D_val + arena_D_val.transpose()); + arena_B.adj() + += C_adj * AsolveB * (arena_D_val + arena_D_val.transpose()); if (!is_constant::value) - arena_D.adj() - += C_adj * arena_B_val.transpose() * AsolveB; + arena_D.adj() += C_adj * arena_B_val.transpose() * AsolveB; }); return res; diff --git a/stan/math/rev/fun/trace_inv_quad_form_ldlt.hpp b/stan/math/rev/fun/trace_inv_quad_form_ldlt.hpp index 0fd59fcb3e7..3c2c77684df 100644 --- a/stan/math/rev/fun/trace_inv_quad_form_ldlt.hpp +++ b/stan/math/rev/fun/trace_inv_quad_form_ldlt.hpp @@ -30,24 +30,23 @@ namespace math { * @param B a matrix * @return The trace of the inverse quadratic form. */ -template * = nullptr, require_any_st_var* = nullptr> inline var trace_inv_quad_form_ldlt(const LDLT_factor& A, - const EigMat& B) { + const EigMat& B) { check_multiplicable("trace_quad_form", "A", A, "B", B); - if(A.rows() == 0) + if (A.rows() == 0) return 0.0; - + using B_ref_t = ref_type_t; B_ref_t B_ref = B; arena_matrix> arena_B_val = value_of(B_ref); arena_matrix> arena_B; arena_matrix> AsolveB - = A.solve(arena_B_val); + = A.solve(arena_B_val); if (!is_constant::value) { arena_B = B_ref; @@ -55,14 +54,12 @@ inline var trace_inv_quad_form_ldlt(const LDLT_factor& A, var res = (arena_B_val.transpose() * AsolveB).trace(); - reverse_pass_callback([A, AsolveB, - arena_B, arena_B_val, - res]() mutable { + reverse_pass_callback([A, AsolveB, arena_B, arena_B_val, res]() mutable { double C_adj = res.adj(); if (!is_constant::value) { forward_as>(A).alloc_->arena_A_.adj() - += -C_adj * AsolveB * AsolveB.transpose(); + += -C_adj * AsolveB * AsolveB.transpose(); } if (!is_constant::value) @@ -71,7 +68,7 @@ inline var trace_inv_quad_form_ldlt(const LDLT_factor& A, return res; } - + } // namespace math } // namespace stan #endif From b4258a5a0ccb15060a58cdca5cccce6a53284612 Mon Sep 17 00:00:00 2001 From: Ben Date: Thu, 10 Sep 2020 18:53:58 -0400 Subject: [PATCH 253/355] Removed extra consts (Issue #2018) --- stan/math/rev/fun/trace_gen_inv_quad_form_ldlt.hpp | 2 +- stan/math/rev/fun/trace_inv_quad_form_ldlt.hpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/stan/math/rev/fun/trace_gen_inv_quad_form_ldlt.hpp b/stan/math/rev/fun/trace_gen_inv_quad_form_ldlt.hpp index e46cfc977f8..3336a284b26 100644 --- a/stan/math/rev/fun/trace_gen_inv_quad_form_ldlt.hpp +++ b/stan/math/rev/fun/trace_gen_inv_quad_form_ldlt.hpp @@ -80,7 +80,7 @@ inline var trace_gen_inv_quad_form_ldlt(const Td& D, double C_adj = res.adj(); if (!is_constant::value) { - forward_as>(A).alloc_->arena_A_.adj() + forward_as>(A).alloc_->arena_A_.adj() += -C_adj * AsolveB * arena_D_val.transpose() * AsolveB.transpose(); } diff --git a/stan/math/rev/fun/trace_inv_quad_form_ldlt.hpp b/stan/math/rev/fun/trace_inv_quad_form_ldlt.hpp index 3c2c77684df..b6fd1ddbe66 100644 --- a/stan/math/rev/fun/trace_inv_quad_form_ldlt.hpp +++ b/stan/math/rev/fun/trace_inv_quad_form_ldlt.hpp @@ -58,7 +58,7 @@ inline var trace_inv_quad_form_ldlt(const LDLT_factor& A, double C_adj = res.adj(); if (!is_constant::value) { - forward_as>(A).alloc_->arena_A_.adj() + forward_as>(A).alloc_->arena_A_.adj() += -C_adj * AsolveB * AsolveB.transpose(); } From 160b6805b26fcfda066132d7b2587c7c1d9146be Mon Sep 17 00:00:00 2001 From: Ben Date: Fri, 11 Sep 2020 10:52:00 -0400 Subject: [PATCH 254/355] Added missing const (Issue #2018) --- stan/math/prim/fun/log_determinant_ldlt.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stan/math/prim/fun/log_determinant_ldlt.hpp b/stan/math/prim/fun/log_determinant_ldlt.hpp index b61510a2260..ba4cdb19432 100644 --- a/stan/math/prim/fun/log_determinant_ldlt.hpp +++ b/stan/math/prim/fun/log_determinant_ldlt.hpp @@ -17,7 +17,7 @@ namespace math { * @return the log(abs(det(A)) */ template -inline T log_determinant_ldlt(LDLT_factor &A) { +inline T log_determinant_ldlt(const LDLT_factor &A) { if (A.rows() == 0) { return 0; } From c93407a132c2f0c02157d1cc4f59ba1109ecf56e Mon Sep 17 00:00:00 2001 From: Ben Date: Fri, 11 Sep 2020 11:11:33 -0400 Subject: [PATCH 255/355] Removed extra const (Issue #2018) --- stan/math/rev/fun/mdivide_left_ldlt.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stan/math/rev/fun/mdivide_left_ldlt.hpp b/stan/math/rev/fun/mdivide_left_ldlt.hpp index 07f88c4cc65..8a9f46b6dc3 100644 --- a/stan/math/rev/fun/mdivide_left_ldlt.hpp +++ b/stan/math/rev/fun/mdivide_left_ldlt.hpp @@ -52,7 +52,7 @@ inline Eigen::Matrix mdivide_left_ldlt( Eigen::Matrix adjB = A.solve(res.adj()); if (!is_constant::value) - forward_as>(A).alloc_->arena_A_.adj() + forward_as>(A).alloc_->arena_A_.adj() += -adjB * res.val().transpose().eval(); if (!is_constant::value) From f55c0ae6f2df02e3bdb9118d40173e9c6f11dc64 Mon Sep 17 00:00:00 2001 From: Ben Date: Mon, 14 Sep 2020 17:27:50 -0400 Subject: [PATCH 256/355] Updates to doxygen/test names (Issue #2018) --- stan/math/rev/core/var.hpp | 10 ------ stan/math/rev/fun/cholesky_decompose.hpp | 34 ++++++++------------- stan/math/rev/fun/log_sum_exp.hpp | 20 ++++++------ stan/math/rev/fun/mdivide_left_ldlt.hpp | 6 ++-- test/unit/math/rev/fun/log_softmax_test.cpp | 4 +-- test/unit/math/rev/fun/log_sum_exp_test.cpp | 2 +- 6 files changed, 29 insertions(+), 47 deletions(-) diff --git a/stan/math/rev/core/var.hpp b/stan/math/rev/core/var.hpp index 72882ce4497..12a79dd8584 100644 --- a/stan/math/rev/core/var.hpp +++ b/stan/math/rev/core/var.hpp @@ -111,16 +111,6 @@ class var_value { */ inline auto& adj() const { return vi_->adj_; } - /** - * Return a reference to the derivative of the root expression with - * respect to this expression. This method only works - * after one of the `grad()` methods has been - * called. - * - * @return Adjoint for this variable. - */ - inline auto& adj() { return vi_->adj_; } - /** * Compute the gradient of this (dependent) variable with respect to * the specified vector of (independent) variables, assigning the diff --git a/stan/math/rev/fun/cholesky_decompose.hpp b/stan/math/rev/fun/cholesky_decompose.hpp index e1a2be89c1f..12ab37cd3e6 100644 --- a/stan/math/rev/fun/cholesky_decompose.hpp +++ b/stan/math/rev/fun/cholesky_decompose.hpp @@ -23,7 +23,7 @@ namespace stan { namespace math { - + /** * Reverse mode specialization of Cholesky decomposition * @@ -33,7 +33,8 @@ namespace math { * Note chainable stack varis are created below in Matrix * * @param A Matrix - * @return L Cholesky factor of A + * + * @return Cholesky factor of A */ template * = nullptr> inline Eigen::Matrix @@ -58,7 +59,6 @@ cholesky_decompose(const T& A) { * Reverse mode differentiation algorithm reference: * * Iain Murray: Differentiation of the Cholesky decomposition, 2016. - * */ size_t pos = 0; for (size_type j = 0; j < M; ++j) { @@ -81,24 +81,6 @@ cholesky_decompose(const T& A) { int block_size = std::min(std::max(M / 8, 8), 128); - /** - * Symbolic adjoint calculation for Cholesky factor A - * - * @param L Cholesky factor - * @param L_adj matrix of adjoints of L - */ - auto symbolic_rev = [](auto& L, auto& L_adj) { - using Eigen::Upper; - using Eigen::Lower; - using Eigen::StrictlyUpper; - L.transposeInPlace(); - L_adj = (L * L_adj.template triangularView()).eval(); - L_adj.template triangularView() - = L_adj.adjoint().template triangularView(); - L.template triangularView().solveInPlace(L_adj); - L.template triangularView().solveInPlace(L_adj.transpose()); - }; - Eigen::MatrixXd L_adj = Eigen::MatrixXd::Zero(M, M); Eigen::MatrixXd L = Eigen::MatrixXd::Zero(M, M); size_t pos = 0; @@ -128,7 +110,15 @@ cholesky_decompose(const T& A) { B_adj.noalias() -= C_adj * R; D_adj.noalias() -= C_adj.transpose() * C; } - symbolic_rev(D, D_adj); + + // Symbolic adjoint calculation for Cholesky factor A + D.transposeInPlace(); + D_adj = (D * D_adj.template triangularView()).eval(); + D_adj.template triangularView() + = D_adj.adjoint().template triangularView(); + D.template triangularView().solveInPlace(D_adj); + D.template triangularView().solveInPlace(D_adj.transpose()); + R_adj.noalias() -= C_adj.transpose() * B; R_adj.noalias() -= D_adj.selfadjointView() * R; D_adj.diagonal() *= 0.5; diff --git a/stan/math/rev/fun/log_sum_exp.hpp b/stan/math/rev/fun/log_sum_exp.hpp index df29b19fc16..732e5c56d74 100644 --- a/stan/math/rev/fun/log_sum_exp.hpp +++ b/stan/math/rev/fun/log_sum_exp.hpp @@ -28,16 +28,19 @@ template * = nullptr, require_any_var_t* = nullptr> inline var log_sum_exp(const T1& a, const T2& b) { - var res = log_sum_exp(value_of(a), value_of(b)); + double val_a = value_of(a); + double val_b = value_of(b); + double diff = val_a - val_b; + var res = log_sum_exp(val_a, val_b); - reverse_pass_callback([a, b, res]() mutable { + reverse_pass_callback([a, b, diff, res]() mutable { if (!is_constant::value) forward_as(a).adj() - += res.adj() * inv_logit(value_of(a) - value_of(b)); + += res.adj() * inv_logit(diff); if (!is_constant::value) forward_as(b).adj() - += res.adj() * inv_logit(value_of(b) - value_of(a)); + += res.adj() * inv_logit(-diff); }); return res; @@ -53,15 +56,14 @@ template * = nullptr> inline auto log_sum_exp(const T& x) { return apply_vector_unary::reduce(x, [](const auto& v) { const auto& v_ref = to_ref(v); - const auto& v_val = value_of(v_ref); - var res = log_sum_exp(v_val); + auto arena_v_val = to_arena(value_of(v_ref)); + var res = log_sum_exp(arena_v_val); auto arena_v = to_arena(v_ref); ->>>>>>> origin/develop - reverse_pass_callback([arena_v, res]() mutable { + reverse_pass_callback([arena_v, arena_v_val, res]() mutable { arena_v.adj() - += res.adj() * (arena_v.array().val() - res.val()).exp().matrix(); + += res.adj() * (arena_v_val.array() - res.val()).exp().matrix(); }); return res; diff --git a/stan/math/rev/fun/mdivide_left_ldlt.hpp b/stan/math/rev/fun/mdivide_left_ldlt.hpp index 8a9f46b6dc3..54c516580fb 100644 --- a/stan/math/rev/fun/mdivide_left_ldlt.hpp +++ b/stan/math/rev/fun/mdivide_left_ldlt.hpp @@ -21,9 +21,9 @@ namespace math { * @tparam C1 number of columns in the LDLT_factor, can be Eigen::Dynamic * * @param A LDLT_factor - * @param b Right hand side matrix or vector. - * @return x = A^-1 b, solution of the linear system. - * @throws std::domain_error if rows of b don't match the size of A. + * @param B Right hand side matrix or vector. + * @return x = A^-1 B, solution of the linear system. + * @throws std::domain_error if rows of B don't match the size of A. */ template * = nullptr, require_any_st_var* = nullptr> diff --git a/test/unit/math/rev/fun/log_softmax_test.cpp b/test/unit/math/rev/fun/log_softmax_test.cpp index 2ea40bacbf0..72c581b9b68 100644 --- a/test/unit/math/rev/fun/log_softmax_test.cpp +++ b/test/unit/math/rev/fun/log_softmax_test.cpp @@ -3,7 +3,7 @@ #include #include -TEST(log_sum_exp_tests, large_values) { +TEST(AgradRev, log_softmax_test) { using stan::math::var; Eigen::VectorXd x = Eigen::VectorXd::Random(5); @@ -12,7 +12,7 @@ TEST(log_sum_exp_tests, large_values) { auto y = stan::math::log_softmax(xv); auto y_ref = stan::math::log(stan::math::softmax(xv)); - for (size_t i = 0; i < 1 /*y.size()*/; ++i) { + for (size_t i = 0; i < y.size(); ++i) { stan::math::set_zero_all_adjoints(); y(i).grad(); auto xadj1 = xv.adj().eval(); diff --git a/test/unit/math/rev/fun/log_sum_exp_test.cpp b/test/unit/math/rev/fun/log_sum_exp_test.cpp index aa6d49f81a1..bfd0c94665c 100644 --- a/test/unit/math/rev/fun/log_sum_exp_test.cpp +++ b/test/unit/math/rev/fun/log_sum_exp_test.cpp @@ -3,7 +3,7 @@ #include #include -TEST(log_sum_exp_tests, large_values) { +TEST(AgradRev, log_sum_exp_tests) { using stan::math::var; // check autodiffing works with var types with large values From abbf6afb41e0369308f8bb4464e15dfc313e6ac9 Mon Sep 17 00:00:00 2001 From: Stan Jenkins Date: Mon, 14 Sep 2020 21:32:06 +0000 Subject: [PATCH 257/355] [Jenkins] auto-formatting by clang-format version 6.0.0-1ubuntu2~16.04.1 (tags/RELEASE_600/final) --- stan/math/rev/fun/cholesky_decompose.hpp | 16 ++++++++-------- stan/math/rev/fun/log_sum_exp.hpp | 8 +++----- 2 files changed, 11 insertions(+), 13 deletions(-) diff --git a/stan/math/rev/fun/cholesky_decompose.hpp b/stan/math/rev/fun/cholesky_decompose.hpp index 12ab37cd3e6..38cf142dcdf 100644 --- a/stan/math/rev/fun/cholesky_decompose.hpp +++ b/stan/math/rev/fun/cholesky_decompose.hpp @@ -23,7 +23,7 @@ namespace stan { namespace math { - + /** * Reverse mode specialization of Cholesky decomposition * @@ -111,13 +111,13 @@ cholesky_decompose(const T& A) { D_adj.noalias() -= C_adj.transpose() * C; } - // Symbolic adjoint calculation for Cholesky factor A - D.transposeInPlace(); - D_adj = (D * D_adj.template triangularView()).eval(); - D_adj.template triangularView() - = D_adj.adjoint().template triangularView(); - D.template triangularView().solveInPlace(D_adj); - D.template triangularView().solveInPlace(D_adj.transpose()); + // Symbolic adjoint calculation for Cholesky factor A + D.transposeInPlace(); + D_adj = (D * D_adj.template triangularView()).eval(); + D_adj.template triangularView() + = D_adj.adjoint().template triangularView(); + D.template triangularView().solveInPlace(D_adj); + D.template triangularView().solveInPlace(D_adj.transpose()); R_adj.noalias() -= C_adj.transpose() * B; R_adj.noalias() -= D_adj.selfadjointView() * R; diff --git a/stan/math/rev/fun/log_sum_exp.hpp b/stan/math/rev/fun/log_sum_exp.hpp index 732e5c56d74..f2a5f88d59c 100644 --- a/stan/math/rev/fun/log_sum_exp.hpp +++ b/stan/math/rev/fun/log_sum_exp.hpp @@ -35,12 +35,10 @@ inline var log_sum_exp(const T1& a, const T2& b) { reverse_pass_callback([a, b, diff, res]() mutable { if (!is_constant::value) - forward_as(a).adj() - += res.adj() * inv_logit(diff); + forward_as(a).adj() += res.adj() * inv_logit(diff); if (!is_constant::value) - forward_as(b).adj() - += res.adj() * inv_logit(-diff); + forward_as(b).adj() += res.adj() * inv_logit(-diff); }); return res; @@ -63,7 +61,7 @@ inline auto log_sum_exp(const T& x) { reverse_pass_callback([arena_v, arena_v_val, res]() mutable { arena_v.adj() - += res.adj() * (arena_v_val.array() - res.val()).exp().matrix(); + += res.adj() * (arena_v_val.array() - res.val()).exp().matrix(); }); return res; From 142d20c900138ddd44d994537a65d2f149e43796 Mon Sep 17 00:00:00 2001 From: Ben Date: Mon, 14 Sep 2020 19:35:47 -0400 Subject: [PATCH 258/355] Fixed headers problems (Issue #2018) --- stan/math/rev/fun/ordered_constrain.hpp | 1 + .../rev/fun/positive_ordered_constrain.hpp | 1 + stan/math/rev/fun/simplex_constrain.hpp | 1 + stan/math/rev/fun/unit_vector_constrain.hpp | 33 ++----------------- 4 files changed, 6 insertions(+), 30 deletions(-) diff --git a/stan/math/rev/fun/ordered_constrain.hpp b/stan/math/rev/fun/ordered_constrain.hpp index e875ddf908c..698af890517 100644 --- a/stan/math/rev/fun/ordered_constrain.hpp +++ b/stan/math/rev/fun/ordered_constrain.hpp @@ -4,6 +4,7 @@ #include #include #include +#include #include #include #include diff --git a/stan/math/rev/fun/positive_ordered_constrain.hpp b/stan/math/rev/fun/positive_ordered_constrain.hpp index 5f32e489475..5269ae36c3f 100644 --- a/stan/math/rev/fun/positive_ordered_constrain.hpp +++ b/stan/math/rev/fun/positive_ordered_constrain.hpp @@ -4,6 +4,7 @@ #include #include #include +#include #include #include #include diff --git a/stan/math/rev/fun/simplex_constrain.hpp b/stan/math/rev/fun/simplex_constrain.hpp index 14f7d206ddc..e81f275e1f8 100644 --- a/stan/math/rev/fun/simplex_constrain.hpp +++ b/stan/math/rev/fun/simplex_constrain.hpp @@ -4,6 +4,7 @@ #include #include #include +#include #include #include #include diff --git a/stan/math/rev/fun/unit_vector_constrain.hpp b/stan/math/rev/fun/unit_vector_constrain.hpp index 965f8933313..e4c94e0dcd2 100644 --- a/stan/math/rev/fun/unit_vector_constrain.hpp +++ b/stan/math/rev/fun/unit_vector_constrain.hpp @@ -3,7 +3,10 @@ #include #include +#include +#include #include +#include #include #include #include @@ -12,36 +15,6 @@ namespace stan { namespace math { -namespace internal { - -class unit_vector_elt_vari : public vari { - private: - vari** y_; - const double* unit_vector_y_; - const int size_; - const int idx_; - const double norm_; - - public: - unit_vector_elt_vari(double val, vari** y, const double* unit_vector_y, - int size, int idx, double norm) - : vari(val), - y_(y), - unit_vector_y_(unit_vector_y), - size_(size), - idx_(idx), - norm_(norm) {} - void chain() { - const double cubed_norm = std::pow(norm_, 3); - for (int m = 0; m < size_; ++m) { - y_[m]->adj_ - -= adj_ * unit_vector_y_[m] * unit_vector_y_[idx_] / cubed_norm; - if (m == idx_) - y_[m]->adj_ += adj_ / norm_; - } - } -}; -} // namespace internal /** * Return the unit length vector corresponding to the free vector y. From 1a255af93f31409952bbc049fce1c3a75aa96efc Mon Sep 17 00:00:00 2001 From: Ben Date: Tue, 15 Sep 2020 13:50:40 -0400 Subject: [PATCH 259/355] Removed selfadjointview in inv_wishart_lpdf (Issue #2018) --- stan/math/prim/prob/inv_wishart_lpdf.hpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/stan/math/prim/prob/inv_wishart_lpdf.hpp b/stan/math/prim/prob/inv_wishart_lpdf.hpp index 7feffd05a6a..b97a62fdc92 100644 --- a/stan/math/prim/prob/inv_wishart_lpdf.hpp +++ b/stan/math/prim/prob/inv_wishart_lpdf.hpp @@ -87,8 +87,7 @@ return_type_t inv_wishart_lpdf(const T_y& W, // &S(0), S.size(), 1); // lp -= 0.5 * dot_product(S_vec, W_inv_vec); // trace(S * W^-1) Eigen::Matrix, Eigen::Dynamic, Eigen::Dynamic> - Winv_S(mdivide_left_ldlt( - ldlt_W, S_ref.template selfadjointView())); + Winv_S(mdivide_left_ldlt(ldlt_W, S_ref)); lp -= 0.5 * trace(Winv_S); } if (include_summand::value) { From a88216a8b53acbf32c5f040543b5018f87fcb762 Mon Sep 17 00:00:00 2001 From: Ben Date: Wed, 16 Sep 2020 14:19:48 -0400 Subject: [PATCH 260/355] Changed path for arena_matrix includes --- stan/math/rev/fun/cholesky_decompose.hpp | 2 +- stan/math/rev/fun/columns_dot_product.hpp | 2 +- stan/math/rev/fun/determinant.hpp | 2 +- stan/math/rev/fun/eigenvalues_sym.hpp | 2 +- stan/math/rev/fun/gp_exp_quad_cov.hpp | 2 +- stan/math/rev/fun/gp_periodic_cov.hpp | 2 +- stan/math/rev/fun/inverse.hpp | 2 +- stan/math/rev/fun/log_determinant.hpp | 2 +- stan/math/rev/fun/log_determinant_spd.hpp | 2 +- stan/math/rev/fun/log_softmax.hpp | 2 +- stan/math/rev/fun/ordered_constrain.hpp | 2 +- stan/math/rev/fun/positive_ordered_constrain.hpp | 2 +- stan/math/rev/fun/sd.hpp | 2 +- stan/math/rev/fun/simplex_constrain.hpp | 2 +- stan/math/rev/fun/unit_vector_constrain.hpp | 2 +- 15 files changed, 15 insertions(+), 15 deletions(-) diff --git a/stan/math/rev/fun/cholesky_decompose.hpp b/stan/math/rev/fun/cholesky_decompose.hpp index 38cf142dcdf..03e0c23627b 100644 --- a/stan/math/rev/fun/cholesky_decompose.hpp +++ b/stan/math/rev/fun/cholesky_decompose.hpp @@ -4,7 +4,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/stan/math/rev/fun/columns_dot_product.hpp b/stan/math/rev/fun/columns_dot_product.hpp index f93365615bc..b4c1b2e5644 100644 --- a/stan/math/rev/fun/columns_dot_product.hpp +++ b/stan/math/rev/fun/columns_dot_product.hpp @@ -7,7 +7,7 @@ #include #include #include -#include +#include #include #include diff --git a/stan/math/rev/fun/determinant.hpp b/stan/math/rev/fun/determinant.hpp index 844bfd2aa10..cc4b0c77cac 100644 --- a/stan/math/rev/fun/determinant.hpp +++ b/stan/math/rev/fun/determinant.hpp @@ -4,7 +4,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/stan/math/rev/fun/eigenvalues_sym.hpp b/stan/math/rev/fun/eigenvalues_sym.hpp index 1b0259b2e81..bd3418de4e0 100644 --- a/stan/math/rev/fun/eigenvalues_sym.hpp +++ b/stan/math/rev/fun/eigenvalues_sym.hpp @@ -4,7 +4,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/stan/math/rev/fun/gp_exp_quad_cov.hpp b/stan/math/rev/fun/gp_exp_quad_cov.hpp index dc479d11c92..968185694d1 100644 --- a/stan/math/rev/fun/gp_exp_quad_cov.hpp +++ b/stan/math/rev/fun/gp_exp_quad_cov.hpp @@ -5,7 +5,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/stan/math/rev/fun/gp_periodic_cov.hpp b/stan/math/rev/fun/gp_periodic_cov.hpp index 8966c9e13d8..8035f857584 100644 --- a/stan/math/rev/fun/gp_periodic_cov.hpp +++ b/stan/math/rev/fun/gp_periodic_cov.hpp @@ -5,7 +5,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/stan/math/rev/fun/inverse.hpp b/stan/math/rev/fun/inverse.hpp index e59d0cd3e6e..99ca899b13d 100644 --- a/stan/math/rev/fun/inverse.hpp +++ b/stan/math/rev/fun/inverse.hpp @@ -6,7 +6,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/stan/math/rev/fun/log_determinant.hpp b/stan/math/rev/fun/log_determinant.hpp index 48ee0ba1831..d6d46c0d94c 100644 --- a/stan/math/rev/fun/log_determinant.hpp +++ b/stan/math/rev/fun/log_determinant.hpp @@ -5,7 +5,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/stan/math/rev/fun/log_determinant_spd.hpp b/stan/math/rev/fun/log_determinant_spd.hpp index a15e74029ae..8ef66b1627a 100644 --- a/stan/math/rev/fun/log_determinant_spd.hpp +++ b/stan/math/rev/fun/log_determinant_spd.hpp @@ -5,7 +5,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/stan/math/rev/fun/log_softmax.hpp b/stan/math/rev/fun/log_softmax.hpp index 4b40fef6cbe..9e97d2ec27b 100644 --- a/stan/math/rev/fun/log_softmax.hpp +++ b/stan/math/rev/fun/log_softmax.hpp @@ -4,7 +4,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/stan/math/rev/fun/ordered_constrain.hpp b/stan/math/rev/fun/ordered_constrain.hpp index 698af890517..4f5f16ceeed 100644 --- a/stan/math/rev/fun/ordered_constrain.hpp +++ b/stan/math/rev/fun/ordered_constrain.hpp @@ -3,7 +3,7 @@ #include #include -#include +#include #include #include #include diff --git a/stan/math/rev/fun/positive_ordered_constrain.hpp b/stan/math/rev/fun/positive_ordered_constrain.hpp index 5269ae36c3f..bbd326823d5 100644 --- a/stan/math/rev/fun/positive_ordered_constrain.hpp +++ b/stan/math/rev/fun/positive_ordered_constrain.hpp @@ -3,7 +3,7 @@ #include #include -#include +#include #include #include #include diff --git a/stan/math/rev/fun/sd.hpp b/stan/math/rev/fun/sd.hpp index 204fe730d19..a3cc064ff9e 100644 --- a/stan/math/rev/fun/sd.hpp +++ b/stan/math/rev/fun/sd.hpp @@ -4,7 +4,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/stan/math/rev/fun/simplex_constrain.hpp b/stan/math/rev/fun/simplex_constrain.hpp index e81f275e1f8..00cf1a465d1 100644 --- a/stan/math/rev/fun/simplex_constrain.hpp +++ b/stan/math/rev/fun/simplex_constrain.hpp @@ -3,7 +3,7 @@ #include #include -#include +#include #include #include #include diff --git a/stan/math/rev/fun/unit_vector_constrain.hpp b/stan/math/rev/fun/unit_vector_constrain.hpp index e4c94e0dcd2..1edc19bb09d 100644 --- a/stan/math/rev/fun/unit_vector_constrain.hpp +++ b/stan/math/rev/fun/unit_vector_constrain.hpp @@ -4,7 +4,7 @@ #include #include #include -#include +#include #include #include #include From 0e5f08f93af90a1812e46a4087de9c1f69394421 Mon Sep 17 00:00:00 2001 From: Ben Date: Fri, 18 Sep 2020 16:04:41 -0400 Subject: [PATCH 261/355] Updated error messages in cov_exp_quad tests (Issue #2018) --- test/unit/math/prim/fun/cov_exp_quad_test.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/test/unit/math/prim/fun/cov_exp_quad_test.cpp b/test/unit/math/prim/fun/cov_exp_quad_test.cpp index 2be0f111ccd..4ec8d88dff9 100644 --- a/test/unit/math/prim/fun/cov_exp_quad_test.cpp +++ b/test/unit/math/prim/fun/cov_exp_quad_test.cpp @@ -345,7 +345,7 @@ TEST(MathPrimMat, domain_error_training_sig_l_cov_exp_quad) { EXPECT_THROW_MSG(stan::math::cov_exp_quad(x, sigma, l_bad), std::domain_error, " length scale"); EXPECT_THROW_MSG(stan::math::cov_exp_quad(x, sigma_bad, l), std::domain_error, - " magnitude"); + " marginal standard deviation"); EXPECT_THROW(stan::math::cov_exp_quad(x, sigma_bad, l_bad), std::domain_error); @@ -396,7 +396,7 @@ TEST(MathPrimMat, nan_error_training_sig_l_cov_exp_quad) { EXPECT_THROW_MSG(stan::math::cov_exp_quad(x, sigma, l_bad), std::domain_error, " length scale"); EXPECT_THROW_MSG(stan::math::cov_exp_quad(x, sigma_bad, l), std::domain_error, - " magnitude"); + " marginal standard deviation"); EXPECT_THROW(stan::math::cov_exp_quad(x, sigma_bad, l_bad), std::domain_error); @@ -454,7 +454,7 @@ TEST(MathPrimMat, domain_error_cov_exp_quad2) { EXPECT_THROW_MSG(stan::math::cov_exp_quad(x1, x2, sigma, l_bad), std::domain_error, " length scale"); EXPECT_THROW_MSG(stan::math::cov_exp_quad(x1, x2, sigma_bad, l), - std::domain_error, " magnitude"); + std::domain_error, " marginal standard deviation"); EXPECT_THROW(stan::math::cov_exp_quad(x1, x2, sigma_bad, l_bad), std::domain_error); @@ -532,7 +532,7 @@ TEST(MathPrimMat, nan_domain_error_cov_exp_quad2) { EXPECT_THROW_MSG(stan::math::cov_exp_quad(x1, x2, sigma, l_bad), std::domain_error, " length scale"); EXPECT_THROW_MSG(stan::math::cov_exp_quad(x1, x2, sigma_bad, l), - std::domain_error, " magnitude"); + std::domain_error, " marginal standard deviation"); EXPECT_THROW(stan::math::cov_exp_quad(x1, x2, sigma_bad, l_bad), std::domain_error); From 3d149386012ffe1d10a1c638ebf43a8605e754ab Mon Sep 17 00:00:00 2001 From: Ben Date: Fri, 18 Sep 2020 17:16:23 -0400 Subject: [PATCH 262/355] Check inv_wishart inputs for symmetry (Issue #2018) --- stan/math/prim/prob/inv_wishart_lpdf.hpp | 4 +-- test/unit/math/prim/prob/inv_wishart_test.cpp | 33 ++++++++++--------- 2 files changed, 20 insertions(+), 17 deletions(-) diff --git a/stan/math/prim/prob/inv_wishart_lpdf.hpp b/stan/math/prim/prob/inv_wishart_lpdf.hpp index b97a62fdc92..266d26e4926 100644 --- a/stan/math/prim/prob/inv_wishart_lpdf.hpp +++ b/stan/math/prim/prob/inv_wishart_lpdf.hpp @@ -53,8 +53,8 @@ return_type_t inv_wishart_lpdf(const T_y& W, static const char* function = "inv_wishart_lpdf"; check_size_match(function, "Rows of random variable", W.rows(), "columns of scale parameter", S.rows()); - check_square(function, "random variable", W); - check_square(function, "scale parameter", S); + check_symmetric(function, "random variable", W); + check_symmetric(function, "scale parameter", S); Eigen::Index k = S.rows(); T_nu_ref nu_ref = nu; T_S_ref S_ref = S; diff --git a/test/unit/math/prim/prob/inv_wishart_test.cpp b/test/unit/math/prim/prob/inv_wishart_test.cpp index 835c591edf8..952ef05e47a 100644 --- a/test/unit/math/prim/prob/inv_wishart_test.cpp +++ b/test/unit/math/prim/prob/inv_wishart_test.cpp @@ -4,13 +4,11 @@ #include #include -TEST(ProbDistributionsInvWishart, LowerTriangular) { +TEST(ProbDistributionsInvWishart, SymmetricCheck) { using Eigen::Dynamic; using Eigen::Matrix; using stan::math::inv_wishart_log; - // Tests if only of the lower triangular portion of - // outcome and scale matrices are taken using Eigen::MatrixXd; using stan::math::inv_wishart_log; @@ -37,23 +35,26 @@ TEST(ProbDistributionsInvWishart, LowerTriangular) { unsigned int dof = 5; - EXPECT_EQ(inv_wishart_log(Y, dof, Sigma), inv_wishart_log(Y_sym, dof, Sigma)); - EXPECT_EQ(inv_wishart_log(Y, dof, Sigma), inv_wishart_log(Y, dof, Sigma_sym)); - EXPECT_EQ(inv_wishart_log(Y, dof, Sigma), - inv_wishart_log(Y_sym, dof, Sigma_sym)); + EXPECT_NO_THROW(inv_wishart_log(Y_sym, dof, Sigma_sym)); + EXPECT_THROW(inv_wishart_log(Y_sym, dof, Sigma), std::domain_error); + EXPECT_THROW(inv_wishart_log(Y, dof, Sigma_sym), std::domain_error); + EXPECT_THROW(inv_wishart_log(Y, dof, Sigma), std::domain_error); } + TEST(ProbDistributionsInvWishart, InvWishart) { using Eigen::Dynamic; using Eigen::Matrix; using stan::math::inv_wishart_log; Matrix Y(3, 3); - Y << 12.147233, -11.9036079, 1.0910458, -11.903608, 16.7585782, 0.8530256, - 1.091046, 0.8530256, 2.5786609; + Y << 12.147233, -11.903608, 1.091046, + -11.903608, 16.7585782, 0.8530256, + 1.091046, 0.8530256, 2.5786609; Matrix Sigma(3, 3); - Sigma << 7.785215, 3.0597878, 1.1071663, 3.059788, 10.3515035, -0.1232598, - 1.107166, -0.1232598, 7.7623386; + Sigma << 7.785215, 3.059788, 1.107166, + 3.059788, 10.3515035, -0.1232598, + 1.107166, -0.1232598, 7.7623386; double dof = 4.0; double log_p = log(2.008407e-08); @@ -66,12 +67,14 @@ TEST(ProbDistributionsInvWishart, Propto) { using stan::math::inv_wishart_log; Matrix Y(3, 3); - Y << 12.147233, -11.9036079, 1.0910458, -11.903608, 16.7585782, 0.8530256, - 1.091046, 0.8530256, 2.5786609; + Y << 12.147233, -11.903608, 1.091046, + -11.903608, 16.7585782, 0.8530256, + 1.091046, 0.8530256, 2.5786609; Matrix Sigma(3, 3); - Sigma << 7.785215, 3.0597878, 1.1071663, 3.059788, 10.3515035, -0.1232598, - 1.107166, -0.1232598, 7.7623386; + Sigma << 7.785215, 3.059788, 1.107166, + 3.059788, 10.3515035, -0.1232598, + 1.107166, -0.1232598, 7.7623386; double dof = 4.0; From 539fdfe0bd0267d5a75aff0f3b73a05c8d9fbd53 Mon Sep 17 00:00:00 2001 From: Ben Date: Fri, 18 Sep 2020 17:28:41 -0400 Subject: [PATCH 263/355] Check symmetry on input to inv_wishart_rng (Issue #2018) --- stan/math/prim/prob/inv_wishart_rng.hpp | 2 +- test/unit/math/prim/prob/inv_wishart_rng_test.cpp | 11 ++++++++++- 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/stan/math/prim/prob/inv_wishart_rng.hpp b/stan/math/prim/prob/inv_wishart_rng.hpp index 5bf3c61f54b..e81e7f11c44 100644 --- a/stan/math/prim/prob/inv_wishart_rng.hpp +++ b/stan/math/prim/prob/inv_wishart_rng.hpp @@ -16,7 +16,7 @@ inline Eigen::MatrixXd inv_wishart_rng(double nu, const Eigen::MatrixXd& S, static const char* function = "inv_wishart_rng"; index_type_t k = S.rows(); check_greater(function, "degrees of freedom > dims - 1", nu, k - 1); - check_square(function, "scale parameter", S); + check_symmetric(function, "scale parameter", S); MatrixXd S_inv = MatrixXd::Identity(k, k); S_inv = S.ldlt().solve(S_inv); diff --git a/test/unit/math/prim/prob/inv_wishart_rng_test.cpp b/test/unit/math/prim/prob/inv_wishart_rng_test.cpp index c1f83030b17..1bda9dc32dd 100644 --- a/test/unit/math/prim/prob/inv_wishart_rng_test.cpp +++ b/test/unit/math/prim/prob/inv_wishart_rng_test.cpp @@ -14,11 +14,20 @@ TEST(ProbDistributionsInvWishartRng, rng) { EXPECT_THROW(inv_wishart_rng(3.0, omega, rng), std::invalid_argument); MatrixXd sigma(3, 3); - sigma << 9.0, -3.0, 0.0, -3.0, 4.0, 0.0, 2.0, 1.0, 3.0; + sigma << 9.0, -3.0, 2.0, + -3.0, 4.0, 1.0, + 2.0, 1.0, 3.0; + + MatrixXd sigma_nonsymmetric(3, 3); + sigma << 9.0, -3.0, 0.0, + -3.0, 4.0, 1.0, + 2.0, 1.0, 3.0; EXPECT_NO_THROW(inv_wishart_rng(3.0, sigma, rng)); EXPECT_THROW(inv_wishart_rng(2, sigma, rng), std::domain_error); EXPECT_THROW(inv_wishart_rng(-1, sigma, rng), std::domain_error); + EXPECT_THROW(inv_wishart_rng(3.0, sigma_nonsymmetric, rng), std::domain_error); } + TEST(probdistributionsInvWishartRng, symmetry) { using Eigen::MatrixXd; using stan::math::inv_wishart_rng; From 62ba5fb297acf21ec13cc5e0009956b7d64a8832 Mon Sep 17 00:00:00 2001 From: Stan Jenkins Date: Fri, 18 Sep 2020 17:29:57 -0400 Subject: [PATCH 264/355] [Jenkins] auto-formatting by clang-format version 6.0.1-14 (tags/RELEASE_601/final) --- .../math/prim/prob/inv_wishart_rng_test.cpp | 11 ++++------ test/unit/math/prim/prob/inv_wishart_test.cpp | 21 +++++++------------ 2 files changed, 12 insertions(+), 20 deletions(-) diff --git a/test/unit/math/prim/prob/inv_wishart_rng_test.cpp b/test/unit/math/prim/prob/inv_wishart_rng_test.cpp index 1bda9dc32dd..8de4ae67f1d 100644 --- a/test/unit/math/prim/prob/inv_wishart_rng_test.cpp +++ b/test/unit/math/prim/prob/inv_wishart_rng_test.cpp @@ -14,18 +14,15 @@ TEST(ProbDistributionsInvWishartRng, rng) { EXPECT_THROW(inv_wishart_rng(3.0, omega, rng), std::invalid_argument); MatrixXd sigma(3, 3); - sigma << 9.0, -3.0, 2.0, - -3.0, 4.0, 1.0, - 2.0, 1.0, 3.0; + sigma << 9.0, -3.0, 2.0, -3.0, 4.0, 1.0, 2.0, 1.0, 3.0; MatrixXd sigma_nonsymmetric(3, 3); - sigma << 9.0, -3.0, 0.0, - -3.0, 4.0, 1.0, - 2.0, 1.0, 3.0; + sigma << 9.0, -3.0, 0.0, -3.0, 4.0, 1.0, 2.0, 1.0, 3.0; EXPECT_NO_THROW(inv_wishart_rng(3.0, sigma, rng)); EXPECT_THROW(inv_wishart_rng(2, sigma, rng), std::domain_error); EXPECT_THROW(inv_wishart_rng(-1, sigma, rng), std::domain_error); - EXPECT_THROW(inv_wishart_rng(3.0, sigma_nonsymmetric, rng), std::domain_error); + EXPECT_THROW(inv_wishart_rng(3.0, sigma_nonsymmetric, rng), + std::domain_error); } TEST(probdistributionsInvWishartRng, symmetry) { diff --git a/test/unit/math/prim/prob/inv_wishart_test.cpp b/test/unit/math/prim/prob/inv_wishart_test.cpp index 952ef05e47a..fc77b5df78a 100644 --- a/test/unit/math/prim/prob/inv_wishart_test.cpp +++ b/test/unit/math/prim/prob/inv_wishart_test.cpp @@ -8,7 +8,6 @@ TEST(ProbDistributionsInvWishart, SymmetricCheck) { using Eigen::Dynamic; using Eigen::Matrix; - using stan::math::inv_wishart_log; using Eigen::MatrixXd; using stan::math::inv_wishart_log; @@ -47,14 +46,12 @@ TEST(ProbDistributionsInvWishart, InvWishart) { using stan::math::inv_wishart_log; Matrix Y(3, 3); - Y << 12.147233, -11.903608, 1.091046, - -11.903608, 16.7585782, 0.8530256, - 1.091046, 0.8530256, 2.5786609; + Y << 12.147233, -11.903608, 1.091046, -11.903608, 16.7585782, 0.8530256, + 1.091046, 0.8530256, 2.5786609; Matrix Sigma(3, 3); - Sigma << 7.785215, 3.059788, 1.107166, - 3.059788, 10.3515035, -0.1232598, - 1.107166, -0.1232598, 7.7623386; + Sigma << 7.785215, 3.059788, 1.107166, 3.059788, 10.3515035, -0.1232598, + 1.107166, -0.1232598, 7.7623386; double dof = 4.0; double log_p = log(2.008407e-08); @@ -67,14 +64,12 @@ TEST(ProbDistributionsInvWishart, Propto) { using stan::math::inv_wishart_log; Matrix Y(3, 3); - Y << 12.147233, -11.903608, 1.091046, - -11.903608, 16.7585782, 0.8530256, - 1.091046, 0.8530256, 2.5786609; + Y << 12.147233, -11.903608, 1.091046, -11.903608, 16.7585782, 0.8530256, + 1.091046, 0.8530256, 2.5786609; Matrix Sigma(3, 3); - Sigma << 7.785215, 3.059788, 1.107166, - 3.059788, 10.3515035, -0.1232598, - 1.107166, -0.1232598, 7.7623386; + Sigma << 7.785215, 3.059788, 1.107166, 3.059788, 10.3515035, -0.1232598, + 1.107166, -0.1232598, 7.7623386; double dof = 4.0; From 0799b477102855bea365fbbcad86376fc3f5e9fd Mon Sep 17 00:00:00 2001 From: Ben Date: Fri, 18 Sep 2020 18:02:46 -0400 Subject: [PATCH 265/355] Fixed symmetric things in inv_wishart tests (Issue #2018) --- .../math/prim/prob/inv_wishart_log_test.cpp | 17 +++++++++++------ .../math/prim/prob/inv_wishart_rng_test.cpp | 2 +- 2 files changed, 12 insertions(+), 7 deletions(-) diff --git a/test/unit/math/prim/prob/inv_wishart_log_test.cpp b/test/unit/math/prim/prob/inv_wishart_log_test.cpp index 2868d66d1da..4b65aeb26a7 100644 --- a/test/unit/math/prim/prob/inv_wishart_log_test.cpp +++ b/test/unit/math/prim/prob/inv_wishart_log_test.cpp @@ -4,12 +4,17 @@ TEST(ProbInvWishart, log_matches_lpmf) { Eigen::MatrixXd Y(4, 4); Eigen::MatrixXd Sigma(4, 4); - Y << 7.988168, -10.955605, -14.47483, 4.395895, -9.555605, 44.750570, - 49.21577, -15.454186, -14.474830, 49.215769, 60.08987, -20.481079, - 4.395895, -18.454186, -21.48108, 7.885833; - Sigma << 2.9983662, 0.2898776, -2.650523, 0.1055911, 0.2898776, 11.4803610, - 7.157993, -3.1129955, -2.6505229, 7.1579931, 11.676181, -3.5866852, - 0.1055911, -3.1129955, -3.586685, 1.4482736; + + Y << 7.988168, -9.555605, -14.47483, 4.395895, + -9.555605, 44.750570, 49.21577, -18.454186, + -14.47483, 49.21577, 60.08987, -21.48108, + 4.395895, -18.454186, -21.48108, 7.885833; + + Sigma << 2.9983662, 0.2898776, -2.650523, 0.1055911, + 0.2898776, 11.4803610, 7.157993, -3.1129955, + -2.650523, 7.157993, 11.676181, -3.586685, + 0.1055911, -3.1129955, -3.586685, 1.4482736; + unsigned int dof = 5; EXPECT_FLOAT_EQ((stan::math::inv_wishart_lpdf(Y, dof, Sigma)), diff --git a/test/unit/math/prim/prob/inv_wishart_rng_test.cpp b/test/unit/math/prim/prob/inv_wishart_rng_test.cpp index 8de4ae67f1d..4b651a5e289 100644 --- a/test/unit/math/prim/prob/inv_wishart_rng_test.cpp +++ b/test/unit/math/prim/prob/inv_wishart_rng_test.cpp @@ -17,7 +17,7 @@ TEST(ProbDistributionsInvWishartRng, rng) { sigma << 9.0, -3.0, 2.0, -3.0, 4.0, 1.0, 2.0, 1.0, 3.0; MatrixXd sigma_nonsymmetric(3, 3); - sigma << 9.0, -3.0, 0.0, -3.0, 4.0, 1.0, 2.0, 1.0, 3.0; + sigma_nonsymmetric << 9.0, -3.0, 0.0, -3.0, 4.0, 1.0, 2.0, 1.0, 3.0; EXPECT_NO_THROW(inv_wishart_rng(3.0, sigma, rng)); EXPECT_THROW(inv_wishart_rng(2, sigma, rng), std::domain_error); EXPECT_THROW(inv_wishart_rng(-1, sigma, rng), std::domain_error); From b393aff0615c98a61616823bb7d227fe461038e9 Mon Sep 17 00:00:00 2001 From: Stan Jenkins Date: Fri, 18 Sep 2020 18:05:41 -0400 Subject: [PATCH 266/355] [Jenkins] auto-formatting by clang-format version 6.0.1-14 (tags/RELEASE_601/final) --- test/unit/math/prim/prob/inv_wishart_log_test.cpp | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/test/unit/math/prim/prob/inv_wishart_log_test.cpp b/test/unit/math/prim/prob/inv_wishart_log_test.cpp index 4b65aeb26a7..8f54c89558e 100644 --- a/test/unit/math/prim/prob/inv_wishart_log_test.cpp +++ b/test/unit/math/prim/prob/inv_wishart_log_test.cpp @@ -5,15 +5,13 @@ TEST(ProbInvWishart, log_matches_lpmf) { Eigen::MatrixXd Y(4, 4); Eigen::MatrixXd Sigma(4, 4); - Y << 7.988168, -9.555605, -14.47483, 4.395895, - -9.555605, 44.750570, 49.21577, -18.454186, - -14.47483, 49.21577, 60.08987, -21.48108, - 4.395895, -18.454186, -21.48108, 7.885833; + Y << 7.988168, -9.555605, -14.47483, 4.395895, -9.555605, 44.750570, 49.21577, + -18.454186, -14.47483, 49.21577, 60.08987, -21.48108, 4.395895, + -18.454186, -21.48108, 7.885833; - Sigma << 2.9983662, 0.2898776, -2.650523, 0.1055911, - 0.2898776, 11.4803610, 7.157993, -3.1129955, - -2.650523, 7.157993, 11.676181, -3.586685, - 0.1055911, -3.1129955, -3.586685, 1.4482736; + Sigma << 2.9983662, 0.2898776, -2.650523, 0.1055911, 0.2898776, 11.4803610, + 7.157993, -3.1129955, -2.650523, 7.157993, 11.676181, -3.586685, + 0.1055911, -3.1129955, -3.586685, 1.4482736; unsigned int dof = 5; From d502b1529ac5b85e35aa2e4023dc9d603e046d43 Mon Sep 17 00:00:00 2001 From: Ben Date: Mon, 21 Sep 2020 17:42:08 -0400 Subject: [PATCH 267/355] Updated inverse wishart tests to avoid non-symmetric matrices (Issue #2018) --- test/unit/math/fwd/prob/inv_wishart_test.cpp | 20 ++++++++++++-------- test/unit/math/mix/prob/inv_wishart_test.cpp | 20 ++++++++++++-------- 2 files changed, 24 insertions(+), 16 deletions(-) diff --git a/test/unit/math/fwd/prob/inv_wishart_test.cpp b/test/unit/math/fwd/prob/inv_wishart_test.cpp index a51749f169f..1ca58af216f 100644 --- a/test/unit/math/fwd/prob/inv_wishart_test.cpp +++ b/test/unit/math/fwd/prob/inv_wishart_test.cpp @@ -12,12 +12,14 @@ TEST(ProbDistributionsInvWishart, fvar_double) { using stan::math::inv_wishart_log; Matrix, Dynamic, Dynamic> Y(3, 3); - Y << 12.147233, -11.9036079, 1.0910458, -11.903608, 16.7585782, 0.8530256, - 1.091046, 0.8530256, 2.5786609; + Y << 12.147233, -11.903608, 1.091046, + -11.903608, 16.7585782, 0.8530256, + 1.091046, 0.8530256, 2.5786609; Matrix, Dynamic, Dynamic> Sigma(3, 3); - Sigma << 7.785215, 3.0597878, 1.1071663, 3.059788, 10.3515035, -0.1232598, - 1.107166, -0.1232598, 7.7623386; + Sigma << 7.785215, 3.059788, 1.107166, + 3.059788, 10.3515035, -0.1232598, + 1.107166, -0.1232598, 7.7623386; double dof = 4.0; double log_p = log(2.008407e-08); @@ -40,12 +42,14 @@ TEST(ProbDistributionsInvWishart, fvar_fvar_double) { using stan::math::inv_wishart_log; Matrix >, Dynamic, Dynamic> Y(3, 3); - Y << 12.147233, -11.9036079, 1.0910458, -11.903608, 16.7585782, 0.8530256, - 1.091046, 0.8530256, 2.5786609; + Y << 12.147233, -11.903608, 1.091046, + -11.903608, 16.7585782, 0.8530256, + 1.091046, 0.8530256, 2.5786609; Matrix >, Dynamic, Dynamic> Sigma(3, 3); - Sigma << 7.785215, 3.0597878, 1.1071663, 3.059788, 10.3515035, -0.1232598, - 1.107166, -0.1232598, 7.7623386; + Sigma << 7.785215, 3.059788, 1.107166, + 3.059788, 10.3515035, -0.1232598, + 1.107166, -0.1232598, 7.7623386; double dof = 4.0; double log_p = log(2.008407e-08); diff --git a/test/unit/math/mix/prob/inv_wishart_test.cpp b/test/unit/math/mix/prob/inv_wishart_test.cpp index 65d0cdc4fdf..532b96f4604 100644 --- a/test/unit/math/mix/prob/inv_wishart_test.cpp +++ b/test/unit/math/mix/prob/inv_wishart_test.cpp @@ -13,12 +13,14 @@ TEST(ProbDistributionsInvWishart, fvar_var) { using stan::math::var; Matrix, Dynamic, Dynamic> Y(3, 3); - Y << 12.147233, -11.9036079, 1.0910458, -11.903608, 16.7585782, 0.8530256, - 1.091046, 0.8530256, 2.5786609; + Y << 12.147233, -11.903608, 1.091046, + -11.903608, 16.7585782, 0.8530256, + 1.091046, 0.8530256, 2.5786609; Matrix, Dynamic, Dynamic> Sigma(3, 3); - Sigma << 7.785215, 3.0597878, 1.1071663, 3.059788, 10.3515035, -0.1232598, - 1.107166, -0.1232598, 7.7623386; + Sigma << 7.785215, 3.059788, 1.107166, + 3.059788, 10.3515035, -0.1232598, + 1.107166, -0.1232598, 7.7623386; double dof = 4.0; double log_p = log(2.008407e-08); @@ -43,12 +45,14 @@ TEST(ProbDistributionsInvWishart, fvar_fvar_var) { using stan::math::var; Matrix >, Dynamic, Dynamic> Y(3, 3); - Y << 12.147233, -11.9036079, 1.0910458, -11.903608, 16.7585782, 0.8530256, - 1.091046, 0.8530256, 2.5786609; + Y << 12.147233, -11.903608, 1.091046, + -11.903608, 16.7585782, 0.8530256, + 1.091046, 0.8530256, 2.5786609; Matrix >, Dynamic, Dynamic> Sigma(3, 3); - Sigma << 7.785215, 3.0597878, 1.1071663, 3.059788, 10.3515035, -0.1232598, - 1.107166, -0.1232598, 7.7623386; + Sigma << 7.785215, 3.059788, 1.107166, + 3.059788, 10.3515035, -0.1232598, + 1.107166, -0.1232598, 7.7623386; double dof = 4.0; double log_p = log(2.008407e-08); From a52c2695eee23c9b31ea78c0caf37d36f3c95432 Mon Sep 17 00:00:00 2001 From: Stan Jenkins Date: Mon, 21 Sep 2020 21:48:11 +0000 Subject: [PATCH 268/355] [Jenkins] auto-formatting by clang-format version 6.0.0-1ubuntu2~16.04.1 (tags/RELEASE_600/final) --- test/unit/math/fwd/prob/inv_wishart_test.cpp | 20 ++++++++------------ test/unit/math/mix/prob/inv_wishart_test.cpp | 20 ++++++++------------ 2 files changed, 16 insertions(+), 24 deletions(-) diff --git a/test/unit/math/fwd/prob/inv_wishart_test.cpp b/test/unit/math/fwd/prob/inv_wishart_test.cpp index 1ca58af216f..95510e14a0f 100644 --- a/test/unit/math/fwd/prob/inv_wishart_test.cpp +++ b/test/unit/math/fwd/prob/inv_wishart_test.cpp @@ -12,14 +12,12 @@ TEST(ProbDistributionsInvWishart, fvar_double) { using stan::math::inv_wishart_log; Matrix, Dynamic, Dynamic> Y(3, 3); - Y << 12.147233, -11.903608, 1.091046, - -11.903608, 16.7585782, 0.8530256, - 1.091046, 0.8530256, 2.5786609; + Y << 12.147233, -11.903608, 1.091046, -11.903608, 16.7585782, 0.8530256, + 1.091046, 0.8530256, 2.5786609; Matrix, Dynamic, Dynamic> Sigma(3, 3); - Sigma << 7.785215, 3.059788, 1.107166, - 3.059788, 10.3515035, -0.1232598, - 1.107166, -0.1232598, 7.7623386; + Sigma << 7.785215, 3.059788, 1.107166, 3.059788, 10.3515035, -0.1232598, + 1.107166, -0.1232598, 7.7623386; double dof = 4.0; double log_p = log(2.008407e-08); @@ -42,14 +40,12 @@ TEST(ProbDistributionsInvWishart, fvar_fvar_double) { using stan::math::inv_wishart_log; Matrix >, Dynamic, Dynamic> Y(3, 3); - Y << 12.147233, -11.903608, 1.091046, - -11.903608, 16.7585782, 0.8530256, - 1.091046, 0.8530256, 2.5786609; + Y << 12.147233, -11.903608, 1.091046, -11.903608, 16.7585782, 0.8530256, + 1.091046, 0.8530256, 2.5786609; Matrix >, Dynamic, Dynamic> Sigma(3, 3); - Sigma << 7.785215, 3.059788, 1.107166, - 3.059788, 10.3515035, -0.1232598, - 1.107166, -0.1232598, 7.7623386; + Sigma << 7.785215, 3.059788, 1.107166, 3.059788, 10.3515035, -0.1232598, + 1.107166, -0.1232598, 7.7623386; double dof = 4.0; double log_p = log(2.008407e-08); diff --git a/test/unit/math/mix/prob/inv_wishart_test.cpp b/test/unit/math/mix/prob/inv_wishart_test.cpp index 532b96f4604..8adc97d8e6f 100644 --- a/test/unit/math/mix/prob/inv_wishart_test.cpp +++ b/test/unit/math/mix/prob/inv_wishart_test.cpp @@ -13,14 +13,12 @@ TEST(ProbDistributionsInvWishart, fvar_var) { using stan::math::var; Matrix, Dynamic, Dynamic> Y(3, 3); - Y << 12.147233, -11.903608, 1.091046, - -11.903608, 16.7585782, 0.8530256, - 1.091046, 0.8530256, 2.5786609; + Y << 12.147233, -11.903608, 1.091046, -11.903608, 16.7585782, 0.8530256, + 1.091046, 0.8530256, 2.5786609; Matrix, Dynamic, Dynamic> Sigma(3, 3); - Sigma << 7.785215, 3.059788, 1.107166, - 3.059788, 10.3515035, -0.1232598, - 1.107166, -0.1232598, 7.7623386; + Sigma << 7.785215, 3.059788, 1.107166, 3.059788, 10.3515035, -0.1232598, + 1.107166, -0.1232598, 7.7623386; double dof = 4.0; double log_p = log(2.008407e-08); @@ -45,14 +43,12 @@ TEST(ProbDistributionsInvWishart, fvar_fvar_var) { using stan::math::var; Matrix >, Dynamic, Dynamic> Y(3, 3); - Y << 12.147233, -11.903608, 1.091046, - -11.903608, 16.7585782, 0.8530256, - 1.091046, 0.8530256, 2.5786609; + Y << 12.147233, -11.903608, 1.091046, -11.903608, 16.7585782, 0.8530256, + 1.091046, 0.8530256, 2.5786609; Matrix >, Dynamic, Dynamic> Sigma(3, 3); - Sigma << 7.785215, 3.059788, 1.107166, - 3.059788, 10.3515035, -0.1232598, - 1.107166, -0.1232598, 7.7623386; + Sigma << 7.785215, 3.059788, 1.107166, 3.059788, 10.3515035, -0.1232598, + 1.107166, -0.1232598, 7.7623386; double dof = 4.0; double log_p = log(2.008407e-08); From cd6cc70d879f6eb94d00021adbe8975e29181e84 Mon Sep 17 00:00:00 2001 From: Ben Date: Mon, 21 Sep 2020 23:22:53 -0400 Subject: [PATCH 269/355] Updated matrix power test (Issue #2018) --- test/unit/math/prim/fun/matrix_power_test.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/test/unit/math/prim/fun/matrix_power_test.cpp b/test/unit/math/prim/fun/matrix_power_test.cpp index 574971dcdb6..4ba20643d2b 100644 --- a/test/unit/math/prim/fun/matrix_power_test.cpp +++ b/test/unit/math/prim/fun/matrix_power_test.cpp @@ -60,7 +60,7 @@ TEST(MathMatrixPower, compare_to_simple_impl) { TEST(MathMatrixPower, zero_size) { using stan::math::matrix_power; Eigen::MatrixXd zero_size = Eigen::MatrixXd::Identity(0, 0); - EXPECT_THROW(matrix_power(zero_size, 2), std::invalid_argument); + EXPECT_NO_THROW(matrix_power(zero_size, 2)); } TEST(MathMatrixPower, not_square) { @@ -73,7 +73,7 @@ TEST(MathMatrixPower, negative_exponent) { using stan::math::matrix_power; Eigen::MatrixXd good = Eigen::MatrixXd::Identity(2, 2); EXPECT_NO_THROW(matrix_power(good, 2)); - EXPECT_THROW(matrix_power(good, -2), std::invalid_argument); + EXPECT_THROW(matrix_power(good, -2), std::domain_error); } TEST(MathMatrixPower, inf_and_nan) { @@ -102,7 +102,7 @@ TEST(MathMatrixPower, invalid_argument_vs_domain_error) { not_square(0, 0) = nan; good(0, 0) = nan; EXPECT_THROW(matrix_power(not_square, 2), std::invalid_argument); - EXPECT_THROW(matrix_power(good, -2), std::invalid_argument); + EXPECT_THROW(matrix_power(good, -2), std::domain_error); } TEST(MathMatrixPower, matrix_power_operator) { From b4f66a5ef3e32b857fdffddefc62287a4a183dff Mon Sep 17 00:00:00 2001 From: Ben Date: Tue, 22 Sep 2020 00:37:00 -0400 Subject: [PATCH 270/355] Updated symmetry tests in inv_wishart (Issue #2018) --- test/unit/math/rev/prob/inv_wishart2_test.cpp | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/test/unit/math/rev/prob/inv_wishart2_test.cpp b/test/unit/math/rev/prob/inv_wishart2_test.cpp index e9c66733105..82f163f567b 100644 --- a/test/unit/math/rev/prob/inv_wishart2_test.cpp +++ b/test/unit/math/rev/prob/inv_wishart2_test.cpp @@ -17,7 +17,8 @@ class AgradDistributionsInvWishart : public ::testing::Test { protected: virtual void SetUp() { Y1.resize(2, 2); - Y1 << 2.011108, -11.20661, -11.206611, 112.94139; + Y1 << 2.011108, -11.20661, + -11.20661, 112.94139; Y2.resize(2, 2); Y2 << 13.4, 12.2, 12.2, 11.5; @@ -25,7 +26,8 @@ class AgradDistributionsInvWishart : public ::testing::Test { nu2 = 5.3; S1.resize(2, 2); - S1 << 1.848220, 1.899623, 1.899623, 12.751941; + S1 << 1.848220, 1.899623, + 1.899623, 12.751941; S2.resize(2, 2); S2 << 3.0, 1.4, 1.4, 7.0; } @@ -78,7 +80,7 @@ TEST_F(AgradDistributionsInvWishart, ProptoSigma) { TEST(InvWishart, check_varis_on_stack) { using stan::math::to_var; Eigen::MatrixXd W(2, 2); - W << 2.011108, -11.20661, -11.206611, 112.94139; + W << 2.011108, -11.20661, -11.20661, 112.94139; double nu = 3; From e9c291cc2f40399ae7a27c88247c14612e43b188 Mon Sep 17 00:00:00 2001 From: Stan Jenkins Date: Tue, 22 Sep 2020 00:38:22 -0400 Subject: [PATCH 271/355] [Jenkins] auto-formatting by clang-format version 6.0.1-14 (tags/RELEASE_601/final) --- test/unit/math/rev/prob/inv_wishart2_test.cpp | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/test/unit/math/rev/prob/inv_wishart2_test.cpp b/test/unit/math/rev/prob/inv_wishart2_test.cpp index 82f163f567b..31c128081e9 100644 --- a/test/unit/math/rev/prob/inv_wishart2_test.cpp +++ b/test/unit/math/rev/prob/inv_wishart2_test.cpp @@ -17,8 +17,7 @@ class AgradDistributionsInvWishart : public ::testing::Test { protected: virtual void SetUp() { Y1.resize(2, 2); - Y1 << 2.011108, -11.20661, - -11.20661, 112.94139; + Y1 << 2.011108, -11.20661, -11.20661, 112.94139; Y2.resize(2, 2); Y2 << 13.4, 12.2, 12.2, 11.5; @@ -26,8 +25,7 @@ class AgradDistributionsInvWishart : public ::testing::Test { nu2 = 5.3; S1.resize(2, 2); - S1 << 1.848220, 1.899623, - 1.899623, 12.751941; + S1 << 1.848220, 1.899623, 1.899623, 12.751941; S2.resize(2, 2); S2 << 3.0, 1.4, 1.4, 7.0; } From 5219a9631f5726b19a3bbb25a4cd619f2b7b8b84 Mon Sep 17 00:00:00 2001 From: Ben Date: Tue, 22 Sep 2020 16:15:57 -0400 Subject: [PATCH 272/355] Updated cov exp quad error messages for tests (Issue #2018) --- test/unit/math/rev/fun/cov_exp_quad_test.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/test/unit/math/rev/fun/cov_exp_quad_test.cpp b/test/unit/math/rev/fun/cov_exp_quad_test.cpp index 90a3269ed3f..0c9f321382d 100644 --- a/test/unit/math/rev/fun/cov_exp_quad_test.cpp +++ b/test/unit/math/rev/fun/cov_exp_quad_test.cpp @@ -931,9 +931,9 @@ TEST(RevMath, cov_exp_quad_domain_error_training) { EXPECT_THROW_MSG(stan::math::cov_exp_quad(x, sigma, l_bad), std::domain_error, " length scale"); EXPECT_THROW_MSG(stan::math::cov_exp_quad(x, sigma_bad, l), std::domain_error, - " magnitude"); + " marginal standard deviation"); EXPECT_THROW_MSG(stan::math::cov_exp_quad(x, sigma_bad, l_bad), - std::domain_error, " magnitude"); + std::domain_error, " marginal standard deviation"); EXPECT_THROW(stan::math::cov_exp_quad(x_2, sigma, l_bad), std::domain_error); EXPECT_THROW(stan::math::cov_exp_quad(x_2, sigma_bad, l), std::domain_error); @@ -983,9 +983,9 @@ TEST(RevMath, cov_exp_quad_nan_error_training) { EXPECT_THROW_MSG(stan::math::cov_exp_quad(x, sigma, l_bad), std::domain_error, " length scale"); EXPECT_THROW_MSG(stan::math::cov_exp_quad(x, sigma_bad, l), std::domain_error, - " magnitude"); + " marginal standard deviation"); EXPECT_THROW_MSG(stan::math::cov_exp_quad(x, sigma_bad, l_bad), - std::domain_error, " magnitude"); + std::domain_error, " marginal standard deviation"); EXPECT_THROW(stan::math::cov_exp_quad(x_bad, sigma, l), std::domain_error); EXPECT_THROW(stan::math::cov_exp_quad(x_bad, sigma_bad, l), @@ -1042,9 +1042,9 @@ TEST(RevMath, cov_exp_quad_domain_error) { EXPECT_THROW_MSG(stan::math::cov_exp_quad(x1, x2, sigma, l_bad), std::domain_error, " length scale"); EXPECT_THROW_MSG(stan::math::cov_exp_quad(x1, x2, sigma_bad, l), - std::domain_error, " magnitude"); + std::domain_error, " marginal standard deviation"); EXPECT_THROW_MSG(stan::math::cov_exp_quad(x1, x2, sigma_bad, l_bad), - std::domain_error, " magnitude"); + std::domain_error, " marginal standard deviation"); std::vector > x_vec_1(3); for (size_t i = 0; i < x_vec_1.size(); ++i) { From cf8ee817e9c0dec930b08569cc457ed3a3020a7e Mon Sep 17 00:00:00 2001 From: Ben Date: Wed, 23 Sep 2020 14:29:27 -0400 Subject: [PATCH 273/355] Added back OpenCL cholesky decompose (Issue #2018) --- stan/math/rev/fun/cholesky_decompose.hpp | 168 +++++++++++++++++++++++ 1 file changed, 168 insertions(+) diff --git a/stan/math/rev/fun/cholesky_decompose.hpp b/stan/math/rev/fun/cholesky_decompose.hpp index 03e0c23627b..17974d7303d 100644 --- a/stan/math/rev/fun/cholesky_decompose.hpp +++ b/stan/math/rev/fun/cholesky_decompose.hpp @@ -24,6 +24,173 @@ namespace stan { namespace math { +#ifdef STAN_OPENCL +class cholesky_opencl : public vari { + public: + int M_; + vari** vari_ref_A_; + vari** vari_ref_L_; + + /** + * Constructor for OpenCL Cholesky function. + * + * Stores varis for A. Instantiates and stores varis for L. + * Instantiates and stores dummy vari for upper triangular part of var + * result returned in cholesky_decompose function call + * + * variRefL aren't on the chainable autodiff stack, only used for storage + * and computation. Note that varis for L are constructed externally in + * cholesky_decompose. + * + * @param A matrix + * @param L_A Cholesky factor of A + */ + cholesky_opencl(const Eigen::Matrix& A, + const Eigen::Matrix& L_A) + : vari(0.0), + M_(A.rows()), + vari_ref_A_(ChainableStack::instance_->memalloc_.alloc_array( + A.rows() * (A.rows() + 1) / 2)), + vari_ref_L_(ChainableStack::instance_->memalloc_.alloc_array( + A.rows() * (A.rows() + 1) / 2)) { + size_t pos = 0; + for (size_type j = 0; j < M_; ++j) { + for (size_type i = j; i < M_; ++i) { + vari_ref_A_[pos] = A.coeffRef(i, j).vi_; + vari_ref_L_[pos] = new vari(L_A.coeffRef(i, j), false); + ++pos; + } + } + } + + /** + * Symbolic adjoint calculation for Cholesky factor A + * + * @param L_val value of Cholesky factor + * @param L_adj adjoint of Cholesky factor + */ + inline void symbolic_rev(matrix_cl& L_val, matrix_cl& L_adj) { + L_adj = transpose(L_val) * L_adj; + L_adj.triangular_transpose(); + L_val = transpose(tri_inverse(L_val)); + L_adj = L_val * transpose(L_val * L_adj); + L_adj.triangular_transpose(); + } + + /** + * Reverse mode differentiation algorithm using OpenCL + * + * Reference: + * + * Iain Murray: Differentiation of the Cholesky decomposition, 2016. + * + */ + virtual void chain() { + const int packed_size = M_ * (M_ + 1) / 2; + Eigen::Map> L_cpu( + vari_ref_L_, M_ * (M_ + 1) / 2); + Eigen::VectorXd L_val_cpu = L_cpu.val(); + Eigen::VectorXd L_adj_cpu = L_cpu.adj(); + matrix_cl L_val = packed_copy(L_val_cpu, M_); + matrix_cl L_adj = packed_copy(L_adj_cpu, M_); + int block_size + = M_ / opencl_context.tuning_opts().cholesky_rev_block_partition; + block_size = std::max(block_size, 8); + block_size = std::min( + block_size, opencl_context.tuning_opts().cholesky_rev_min_block_size); + // The following is an OpenCL implementation of + // the chain() function from the cholesky_block + // vari class implementation + for (int k = M_; k > 0; k -= block_size) { + const int j = std::max(0, k - block_size); + const int k_j_ind = k - j; + const int m_k_ind = M_ - k; + + auto&& R_val = block(L_val, j, 0, k_j_ind, j); + auto&& R_adj = block(L_adj, j, 0, k_j_ind, j); + matrix_cl D_val = block(L_val, j, j, k_j_ind, k_j_ind); + matrix_cl D_adj = block(L_adj, j, j, k_j_ind, k_j_ind); + auto&& B_val = block(L_val, k, 0, m_k_ind, j); + auto&& B_adj = block(L_adj, k, 0, m_k_ind, j); + auto&& C_val = block(L_val, k, j, m_k_ind, k_j_ind); + auto&& C_adj = block(L_adj, k, j, m_k_ind, k_j_ind); + + C_adj = C_adj * tri_inverse(D_val); + B_adj = B_adj - C_adj * R_val; + D_adj = D_adj - transpose(C_adj) * C_val; + + symbolic_rev(D_val, D_adj); + + R_adj = R_adj - transpose(C_adj) * B_val - D_adj * R_val; + D_adj = diagonal_multiply(D_adj, 0.5); + + block(L_adj, j, j, k_j_ind, k_j_ind) = D_adj; + } + L_adj.view(matrix_cl_view::Lower); + std::vector L_adj_cpu_res = packed_copy(L_adj); + for (size_type j = 0; j < packed_size; ++j) { + vari_ref_A_[j]->adj_ += L_adj_cpu_res[j]; + } + } +}; + +/** + * Reverse mode specialization of Cholesky decomposition + * + * Internally calls Eigen::LLT rather than using + * stan::math::cholesky_decompose in order to use an inplace decomposition. + * + * Note chainable stack varis are created below in Matrix + * + * @param A Matrix + * @return L Cholesky factor of A + */ +template * = nullptr> +inline Eigen::Matrix +cholesky_decompose(const T& A) { + const auto& A_ref = to_ref(A); + Eigen::Matrix L_A( + value_of_rec(A_ref)); + check_not_nan("cholesky_decompose", "A", L_A); + L_A = cholesky_decompose(L_A); + // Memory allocated in arena. + // cholesky_scalar gradient faster for small matrices compared to + // cholesky_block + vari* dummy = new vari(0.0, false); + Eigen::Matrix L(A.rows(), + A.cols()); + if (L_A.rows() <= 35) { + cholesky_scalar* baseVari = new cholesky_scalar(A_ref, L_A); + size_t accum = 0; + size_t accum_i = accum; + for (size_type j = 0; j < L.cols(); ++j) { + for (size_type i = j; i < L.cols(); ++i) { + accum_i += i; + size_t pos = j + accum_i; + L.coeffRef(i, j).vi_ = baseVari->vari_ref_L_[pos]; + } + for (size_type k = 0; k < j; ++k) { + L.coeffRef(k, j).vi_ = dummy; + } + accum += j; + accum_i = accum; + } + } else { + if (L_A.rows() + > opencl_context.tuning_opts().cholesky_size_worth_transfer) { + cholesky_opencl* baseVari = new cholesky_opencl(A_ref, L_A); + internal::set_lower_tri_coeff_ref(L, baseVari->vari_ref_L_); + } else { + cholesky_block* baseVari = new cholesky_block(A_ref, L_A); + internal::set_lower_tri_coeff_ref(L, baseVari->vari_ref_L_); + } + cholesky_block* baseVari = new cholesky_block(A_ref, L_A); + internal::set_lower_tri_coeff_ref(L, baseVari->vari_ref_L_); + } + + return L; +} +#else /** * Reverse mode specialization of Cholesky decomposition * @@ -192,6 +359,7 @@ cholesky_decompose(const T& A) { return res; } +#endif } // namespace math } // namespace stan From 6b3495cf9ada9b38e0199057446a1df3afcc1caa Mon Sep 17 00:00:00 2001 From: Stan Jenkins Date: Wed, 23 Sep 2020 18:30:59 +0000 Subject: [PATCH 274/355] [Jenkins] auto-formatting by clang-format version 6.0.0-1ubuntu2~16.04.1 (tags/RELEASE_600/final) --- stan/math/rev/fun/cholesky_decompose.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stan/math/rev/fun/cholesky_decompose.hpp b/stan/math/rev/fun/cholesky_decompose.hpp index 17974d7303d..10e2785dd4a 100644 --- a/stan/math/rev/fun/cholesky_decompose.hpp +++ b/stan/math/rev/fun/cholesky_decompose.hpp @@ -190,7 +190,7 @@ cholesky_decompose(const T& A) { return L; } -#else +#else /** * Reverse mode specialization of Cholesky decomposition * From 7e5c2b49b854adbd84a70c7c4affd8f410e76c73 Mon Sep 17 00:00:00 2001 From: Ben Date: Wed, 23 Sep 2020 23:06:59 -0400 Subject: [PATCH 275/355] Added missing cholesky stuff (Issue #2018) --- stan/math/rev/fun/cholesky_decompose.hpp | 234 ++++++++++++++++++++++- 1 file changed, 232 insertions(+), 2 deletions(-) diff --git a/stan/math/rev/fun/cholesky_decompose.hpp b/stan/math/rev/fun/cholesky_decompose.hpp index 17974d7303d..b131a1b7acf 100644 --- a/stan/math/rev/fun/cholesky_decompose.hpp +++ b/stan/math/rev/fun/cholesky_decompose.hpp @@ -23,7 +23,239 @@ namespace stan { namespace math { +namespace internal { +/** + * Set the lower right triangular of a var matrix given a set of vari** + * + * @param L Matrix of vars + * @param vari_ref Values to be set in lower right triangular of L. + * @return None, L modified by reference. + */ +inline void set_lower_tri_coeff_ref(Eigen::Matrix& L, + vari** vari_ref) { + size_t pos = 0; + vari* dummy = new vari(0.0, false); + + for (size_type j = 0; j < L.cols(); ++j) { + for (size_type i = j; i < L.cols(); ++i) { + L.coeffRef(i, j).vi_ = vari_ref[pos++]; + } + for (size_type k = 0; k < j; ++k) { + L.coeffRef(k, j).vi_ = dummy; + } + } + return; +} +} // namespace internal + +class cholesky_block : public vari { + public: + int M_; + int block_size_; + using Block_ = Eigen::Block; + vari** vari_ref_A_; + vari** vari_ref_L_; + + /** + * Constructor for Cholesky function. + * + * Stores varis for A. Instantiates and stores varis for L. + * Instantiates and stores dummy vari for upper triangular part of var + * result returned in cholesky_decompose function call + * + * variRefL aren't on the chainable autodiff stack, only used for storage + * and computation. Note that varis for L are constructed externally in + * cholesky_decompose. + * + * block_size_ determined using the same calculation Eigen/LLT.h + * + * @param A matrix + * @param L_A matrix, Cholesky factor of A + */ + cholesky_block(const Eigen::Matrix& A, + const Eigen::Matrix& L_A) + : vari(0.0), + M_(A.rows()), + vari_ref_A_(ChainableStack::instance_->memalloc_.alloc_array( + A.rows() * (A.rows() + 1) / 2)), + vari_ref_L_(ChainableStack::instance_->memalloc_.alloc_array( + A.rows() * (A.rows() + 1) / 2)) { + size_t pos = 0; + block_size_ = std::max(M_ / 8, 8); + block_size_ = std::min(block_size_, 128); + for (size_type j = 0; j < M_; ++j) { + for (size_type i = j; i < M_; ++i) { + vari_ref_A_[pos] = A.coeffRef(i, j).vi_; + vari_ref_L_[pos] = new vari(L_A.coeffRef(i, j), false); + ++pos; + } + } + } + + /** + * Symbolic adjoint calculation for Cholesky factor A + * + * @param L Cholesky factor + * @param L_adj matrix of adjoints of L + */ + inline void symbolic_rev(Block_& L, Block_& L_adj) { + using Eigen::Lower; + using Eigen::StrictlyUpper; + using Eigen::Upper; + L.transposeInPlace(); + L_adj = (L * L_adj.triangularView()).eval(); + L_adj.triangularView() + = L_adj.adjoint().triangularView(); + L.triangularView().solveInPlace(L_adj); + L.triangularView().solveInPlace(L_adj.transpose()); + } + + /** + * Reverse mode differentiation algorithm reference: + * + * Iain Murray: Differentiation of the Cholesky decomposition, 2016. + * + */ + virtual void chain() { + using Eigen::Block; + using Eigen::Lower; + using Eigen::MatrixXd; + using Eigen::StrictlyUpper; + using Eigen::Upper; + auto L_adj = Eigen::MatrixXd::Zero(M_, M_).eval(); + auto L = Eigen::MatrixXd::Zero(M_, M_).eval(); + size_t pos = 0; + for (size_type j = 0; j < M_; ++j) { + for (size_type i = j; i < M_; ++i) { + L_adj.coeffRef(i, j) = vari_ref_L_[pos]->adj_; + L.coeffRef(i, j) = vari_ref_L_[pos]->val_; + ++pos; + } + } + + for (int k = M_; k > 0; k -= block_size_) { + int j = std::max(0, k - block_size_); + Block_ R = L.block(j, 0, k - j, j); + Block_ D = L.block(j, j, k - j, k - j); + Block_ B = L.block(k, 0, M_ - k, j); + Block_ C = L.block(k, j, M_ - k, k - j); + Block_ R_adj = L_adj.block(j, 0, k - j, j); + Block_ D_adj = L_adj.block(j, j, k - j, k - j); + Block_ B_adj = L_adj.block(k, 0, M_ - k, j); + Block_ C_adj = L_adj.block(k, j, M_ - k, k - j); + if (C_adj.size() > 0) { + C_adj = D.transpose() + .triangularView() + .solve(C_adj.transpose()) + .transpose(); + B_adj.noalias() -= C_adj * R; + D_adj.noalias() -= C_adj.transpose() * C; + } + symbolic_rev(D, D_adj); + R_adj.noalias() -= C_adj.transpose() * B; + R_adj.noalias() -= D_adj.selfadjointView() * R; + D_adj.diagonal() *= 0.5; + D_adj.triangularView().setZero(); + } + pos = 0; + for (size_type j = 0; j < M_; ++j) { + for (size_type i = j; i < M_; ++i) { + vari_ref_A_[pos++]->adj_ += L_adj.coeffRef(i, j); + } + } + } +}; + +class cholesky_scalar : public vari { + public: + int M_; + vari** vari_ref_A_; + vari** vari_ref_L_; + + /** + * Constructor for Cholesky function. + * + * Stores varis for A. Instantiates and stores varis for L. Instantiates + * and stores dummy vari for upper triangular part of var result returned + * in cholesky_decompose function call + * + * variRefL aren't on the chainable autodiff stack, only used for storage + * and computation. Note that varis for L are constructed externally in + * cholesky_decompose. + * + * @param A matrix + * @param L_A matrix, Cholesky factor of A + */ + cholesky_scalar(const Eigen::Matrix& A, + const Eigen::Matrix& L_A) + : vari(0.0), + M_(A.rows()), + vari_ref_A_(ChainableStack::instance_->memalloc_.alloc_array( + A.rows() * (A.rows() + 1) / 2)), + vari_ref_L_(ChainableStack::instance_->memalloc_.alloc_array( + A.rows() * (A.rows() + 1) / 2)) { + size_t accum = 0; + size_t accum_i = accum; + for (size_type j = 0; j < M_; ++j) { + for (size_type i = j; i < M_; ++i) { + accum_i += i; + size_t pos = j + accum_i; + vari_ref_A_[pos] = A.coeffRef(i, j).vi_; + vari_ref_L_[pos] = new vari(L_A.coeffRef(i, j), false); + } + accum += j; + accum_i = accum; + } + } + + /** + * Reverse mode differentiation algorithm reference: + * + * Mike Giles. An extended collection of matrix derivative results for + * forward and reverse mode AD. Jan. 2008. + * + * Note algorithm as laid out in Giles is row-major, so Eigen::Matrices + * are explicitly storage order RowMajor, whereas Eigen defaults to + * ColumnMajor. Also note algorithm starts by calculating the adjoint for + * A(M_ - 1, M_ - 1), hence pos on line 94 is decremented to start at pos + * = M_ * (M_ + 1) / 2. + */ + virtual void chain() { + using Eigen::Matrix; + using Eigen::RowMajor; + Matrix adjL(M_, M_); + Matrix LA(M_, M_); + Matrix adjA(M_, M_); + size_t pos = 0; + for (size_type i = 0; i < M_; ++i) { + for (size_type j = 0; j <= i; ++j) { + adjL.coeffRef(i, j) = vari_ref_L_[pos]->adj_; + LA.coeffRef(i, j) = vari_ref_L_[pos]->val_; + ++pos; + } + } + + --pos; + for (int i = M_ - 1; i >= 0; --i) { + for (int j = i; j >= 0; --j) { + if (i == j) { + adjA.coeffRef(i, j) = 0.5 * adjL.coeff(i, j) / LA.coeff(i, j); + } else { + adjA.coeffRef(i, j) = adjL.coeff(i, j) / LA.coeff(j, j); + adjL.coeffRef(j, j) + -= adjL.coeff(i, j) * LA.coeff(i, j) / LA.coeff(j, j); + } + for (int k = j - 1; k >= 0; --k) { + adjL.coeffRef(i, k) -= adjA.coeff(i, j) * LA.coeff(j, k); + adjL.coeffRef(j, k) -= adjA.coeff(i, j) * LA.coeff(i, k); + } + vari_ref_A_[pos--]->adj_ += adjA.coeffRef(i, j); + } + } + } +}; + #ifdef STAN_OPENCL class cholesky_opencl : public vari { public: @@ -184,8 +416,6 @@ cholesky_decompose(const T& A) { cholesky_block* baseVari = new cholesky_block(A_ref, L_A); internal::set_lower_tri_coeff_ref(L, baseVari->vari_ref_L_); } - cholesky_block* baseVari = new cholesky_block(A_ref, L_A); - internal::set_lower_tri_coeff_ref(L, baseVari->vari_ref_L_); } return L; From fbe1e7b86f1c3341b3bfe43718e48d07b39fcffb Mon Sep 17 00:00:00 2001 From: Stan Jenkins Date: Wed, 23 Sep 2020 23:20:42 -0400 Subject: [PATCH 276/355] [Jenkins] auto-formatting by clang-format version 6.0.1-14 (tags/RELEASE_601/final) --- stan/math/rev/fun/cholesky_decompose.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stan/math/rev/fun/cholesky_decompose.hpp b/stan/math/rev/fun/cholesky_decompose.hpp index 83b77950dd1..bd5de20adc9 100644 --- a/stan/math/rev/fun/cholesky_decompose.hpp +++ b/stan/math/rev/fun/cholesky_decompose.hpp @@ -255,7 +255,7 @@ class cholesky_scalar : public vari { } } }; - + #ifdef STAN_OPENCL class cholesky_opencl : public vari { public: From 0aaea95d30d6701a2ac70ca9a7aed1af01383aa4 Mon Sep 17 00:00:00 2001 From: Ben Date: Fri, 25 Sep 2020 15:26:49 -0400 Subject: [PATCH 277/355] Added missing variable to lambda capture (Issue #2018) --- stan/math/rev/fun/unit_vector_constrain.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stan/math/rev/fun/unit_vector_constrain.hpp b/stan/math/rev/fun/unit_vector_constrain.hpp index 1edc19bb09d..e424be5008b 100644 --- a/stan/math/rev/fun/unit_vector_constrain.hpp +++ b/stan/math/rev/fun/unit_vector_constrain.hpp @@ -38,7 +38,7 @@ plain_type_t unit_vector_constrain(const T& y) { const double r_cubed = r * r * r; arena_matrix> res = y_val / r; - reverse_pass_callback([arena_y, res, r, r_cubed]() mutable { + reverse_pass_callback([arena_y, res, r, r_cubed, y_val]() mutable { const auto& adj = to_ref(res.adj()); arena_y.adj() From abf99ec65a83ac3a6b298da219dbb28514a7b539 Mon Sep 17 00:00:00 2001 From: Steve Bronder Date: Fri, 25 Sep 2020 22:29:49 -0400 Subject: [PATCH 278/355] update gp_exp_quad_cov for the hotpath and fix headers in gp_periodic_cov --- stan/math/rev/fun/gp_exp_quad_cov.hpp | 175 ++++++++++++++++---------- stan/math/rev/fun/gp_periodic_cov.hpp | 5 +- 2 files changed, 115 insertions(+), 65 deletions(-) diff --git a/stan/math/rev/fun/gp_exp_quad_cov.hpp b/stan/math/rev/fun/gp_exp_quad_cov.hpp index 968185694d1..a1a6fc0d243 100644 --- a/stan/math/rev/fun/gp_exp_quad_cov.hpp +++ b/stan/math/rev/fun/gp_exp_quad_cov.hpp @@ -44,84 +44,133 @@ inline Eigen::Matrix gp_exp_quad_cov(const std::vector& x, if (x.size() == 0) { return Eigen::Matrix(); } - - double l_d = value_of(length_scale); - double sigma_d = value_of(sigma); - double sigma_sq_d = sigma_d * sigma_d; - - size_t N = x.size(); - size_t P = (N * N - N) / 2 + N; - arena_matrix dist(P); - arena_matrix> arena_res(P); - - auto arena_x = to_arena_if::value>(x); - - double inv_half_sq_l_d = 0.5 / (l_d * l_d); - - size_t pos = 0; - for (size_t j = 0; j < N; ++j) { - for (size_t i = 0; i <= j; ++i) { - if (i != j) { - double dist_sq = squared_distance(value_of(x[i]), value_of(x[j])); - dist.coeffRef(pos) = dist_sq; - arena_res.coeffRef(pos) - = sigma_sq_d * std::exp(-dist_sq * inv_half_sq_l_d); - } else { - dist.coeffRef(pos) = 0.0; - arena_res.coeffRef(pos) = sigma_sq_d; + if (is_constant::value && !is_constant::value && !is_constant::value) { + + const size_t N = x.size(); + const size_t P = (N * N - N) / 2 + N; + const double inv_half_sq_l_d = 0.5 / (value_of(length_scale) * value_of(length_scale)); + const double sigma_sq_d = value_of(sigma) * value_of(sigma); + arena_matrix> arena_res(N, N); + arena_matrix> arena_dist(P); + size_t pos = 0; + for (size_t j = 0; j < N; ++j) { + for (size_t i = 0; i <= j; ++i) { + if (unlikely(i == j)) { + arena_dist.coeffRef(pos) = 0.0; + arena_res.coeffRef(i, j) = sigma_sq_d; + } else { + const double dist_sq = squared_distance(value_of(x[i]), value_of(x[j])); + arena_dist.coeffRef(pos) = dist_sq; + arena_res.coeffRef(i, j) + = sigma_sq_d * std::exp(-dist_sq * inv_half_sq_l_d); + } + ++pos; } - pos++; } - } - - Eigen::Matrix res(N, N); - - pos = 0; - for (size_t j = 0; j < N; ++j) - for (size_t i = 0; i <= j; ++i) { - res.coeffRef(j, i) = res.coeffRef(i, j) = arena_res.coeff(pos); - pos++; + // if someone does A[1, 2] * 2 wont that also change A[2, 1]? + for (size_t j = 0; j < N; ++j) { + for (size_t i = 0; i <= j; ++i) { + arena_res.coeffRef(j, i) = arena_res.coeff(i, j); + } } + reverse_pass_callback([arena_res, arena_dist, sigma, length_scale, N]() mutable { - reverse_pass_callback([arena_res, arena_x, dist, sigma, length_scale, sigma_d, - l_d, N]() mutable { - size_t pos = 0; + const double l_d = value_of(length_scale); + auto& sigma_adj = forward_as(sigma).adj(); + auto& l_adj = forward_as(length_scale).adj(); - double sigma_adj = 0.0; - double l_adj = 0.0; - double inv_l_d_squared = 1.0 / (l_d * l_d); + size_t pos = 0; + for (size_t j = 0; j < N; ++j) { + for (size_t i = 0; i <= j; ++i) { + const double adj_times_val + = arena_res.coeff(i, j).val() * arena_res.coeff(i, j).adj(); + sigma_adj += adj_times_val; + l_adj += arena_dist.coeff(pos) * adj_times_val; + ++pos; + } + } + sigma_adj *= 2.0; + sigma_adj /= value_of(sigma); + l_adj /= (l_d * l_d * l_d); + }); + return arena_res; + } else { + double sigma_sq_d = value_of(sigma) * value_of(sigma); + double inv_half_sq_l_d = 0.5 / (value_of(length_scale) * value_of(length_scale)); + + size_t N = x.size(); + size_t P = (N * N - N) / 2 + N; + arena_matrix dist(P); + arena_matrix> arena_res(N, N); + auto arena_x = to_arena_if::value>(x); - pos = 0; + size_t pos = 0; for (size_t j = 0; j < N; ++j) { for (size_t i = 0; i <= j; ++i) { - double adj_times_val - = arena_res.coeff(pos).val() * arena_res.coeff(pos).adj(); - - if (!is_constant::value) - sigma_adj += adj_times_val; + if (i != j) { + const double dist_sq = squared_distance(value_of(x[i]), value_of(x[j])); + dist.coeffRef(pos) = dist_sq; + arena_res.coeffRef(i, j) + = sigma_sq_d * std::exp(-dist_sq * inv_half_sq_l_d); + } else { + dist.coeffRef(pos) = 0.0; + arena_res.coeffRef(i, j) = sigma_sq_d; + } + ++pos; + } + } - if (!is_constant::value) - l_adj += dist.coeff(pos) * adj_times_val; + // if someone does A[1, 2] * 2 wont that also change A[2, 1]? + for (size_t j = 0; j < N; ++j) { + for (size_t i = 0; i <= j; ++i) { + arena_res.coeffRef(j, i) = arena_res.coeff(i, j); + } + } - if (!is_constant::value && i != j) { - auto adj = eval(-(value_of(arena_x[i]) - value_of(arena_x[j])) - * adj_times_val * inv_l_d_squared); - using T_x_var = promote_scalar_t; - forward_as(arena_x[i]).adj() += adj; - forward_as(arena_x[j]).adj() -= adj; + reverse_pass_callback([arena_res, arena_x, dist, sigma, length_scale, N]() mutable { + + const double& l_d = value_of(length_scale); + const double inv_l_d_squared = 1.0 / (l_d * l_d); + + size_t pos = 0; + for (size_t j = 0; j < N; ++j) { + for (size_t i = 0; i <= j; ++i) { + const double adj_times_val + = arena_res.coeff(i, j).val() * arena_res.coeff(i, j).adj(); + + if (!is_constant::value) { + forward_as(sigma).adj() += adj_times_val; + } + + if (!is_constant::value) { + forward_as(length_scale).adj() += dist.coeff(pos) * adj_times_val; + } + + if (!is_constant::value) { + if (i != j) { + auto adj = eval(-(value_of(arena_x[i]) - value_of(arena_x[j])) + * adj_times_val * inv_l_d_squared); + using T_x_var = promote_scalar_t; + forward_as(arena_x[i]).adj() += adj; + forward_as(arena_x[j]).adj() -= adj; + } + } + ++pos; } - pos++; } - } - if (!is_constant::value) - forward_as(sigma).adj() += 2.0 * sigma_adj / sigma_d; + if (!is_constant::value) { + forward_as(sigma).adj() *= 2.0; + forward_as(sigma).adj() /= value_of(sigma); + } - if (!is_constant::value) - forward_as(length_scale).adj() += l_adj / (l_d * l_d * l_d); - }); + if (!is_constant::value) { + forward_as(length_scale).adj() /= (l_d * l_d * l_d); + } + }); - return res; + return arena_res; + } } } // namespace math diff --git a/stan/math/rev/fun/gp_periodic_cov.hpp b/stan/math/rev/fun/gp_periodic_cov.hpp index 8035f857584..02d998635b1 100644 --- a/stan/math/rev/fun/gp_periodic_cov.hpp +++ b/stan/math/rev/fun/gp_periodic_cov.hpp @@ -1,16 +1,18 @@ #ifndef STAN_MATH_REV_FUN_GP_PERIODIC_COV_HPP #define STAN_MATH_REV_FUN_GP_PERIODIC_COV_HPP +#include #include #include #include #include #include #include -#include #include #include #include +#include +#include #include #include #include @@ -56,7 +58,6 @@ Eigen::Matrix gp_periodic_cov( if (x.size() == 0) { return Eigen::Matrix(); } - double l_d = value_of(l); double p_d = value_of(p); double sigma_d = value_of(sigma); From a5af19a9a15bb16026f4889300ef4c0496014c2e Mon Sep 17 00:00:00 2001 From: Stan Jenkins Date: Sat, 26 Sep 2020 02:30:30 +0000 Subject: [PATCH 279/355] [Jenkins] auto-formatting by clang-format version 6.0.0-1ubuntu2~16.04.1 (tags/RELEASE_600/final) --- stan/math/rev/fun/gp_exp_quad_cov.hpp | 133 ++++++++++++++------------ 1 file changed, 70 insertions(+), 63 deletions(-) diff --git a/stan/math/rev/fun/gp_exp_quad_cov.hpp b/stan/math/rev/fun/gp_exp_quad_cov.hpp index a1a6fc0d243..dd448ac0e12 100644 --- a/stan/math/rev/fun/gp_exp_quad_cov.hpp +++ b/stan/math/rev/fun/gp_exp_quad_cov.hpp @@ -44,13 +44,15 @@ inline Eigen::Matrix gp_exp_quad_cov(const std::vector& x, if (x.size() == 0) { return Eigen::Matrix(); } - if (is_constant::value && !is_constant::value && !is_constant::value) { - + if (is_constant::value && !is_constant::value + && !is_constant::value) { const size_t N = x.size(); const size_t P = (N * N - N) / 2 + N; - const double inv_half_sq_l_d = 0.5 / (value_of(length_scale) * value_of(length_scale)); + const double inv_half_sq_l_d + = 0.5 / (value_of(length_scale) * value_of(length_scale)); const double sigma_sq_d = value_of(sigma) * value_of(sigma); - arena_matrix> arena_res(N, N); + arena_matrix> arena_res( + N, N); arena_matrix> arena_dist(P); size_t pos = 0; for (size_t j = 0; j < N; ++j) { @@ -59,7 +61,8 @@ inline Eigen::Matrix gp_exp_quad_cov(const std::vector& x, arena_dist.coeffRef(pos) = 0.0; arena_res.coeffRef(i, j) = sigma_sq_d; } else { - const double dist_sq = squared_distance(value_of(x[i]), value_of(x[j])); + const double dist_sq + = squared_distance(value_of(x[i]), value_of(x[j])); arena_dist.coeffRef(pos) = dist_sq; arena_res.coeffRef(i, j) = sigma_sq_d * std::exp(-dist_sq * inv_half_sq_l_d); @@ -73,42 +76,45 @@ inline Eigen::Matrix gp_exp_quad_cov(const std::vector& x, arena_res.coeffRef(j, i) = arena_res.coeff(i, j); } } - reverse_pass_callback([arena_res, arena_dist, sigma, length_scale, N]() mutable { - - const double l_d = value_of(length_scale); - auto& sigma_adj = forward_as(sigma).adj(); - auto& l_adj = forward_as(length_scale).adj(); - - size_t pos = 0; - for (size_t j = 0; j < N; ++j) { - for (size_t i = 0; i <= j; ++i) { - const double adj_times_val - = arena_res.coeff(i, j).val() * arena_res.coeff(i, j).adj(); - sigma_adj += adj_times_val; - l_adj += arena_dist.coeff(pos) * adj_times_val; - ++pos; - } - } - sigma_adj *= 2.0; - sigma_adj /= value_of(sigma); - l_adj /= (l_d * l_d * l_d); - }); + reverse_pass_callback( + [arena_res, arena_dist, sigma, length_scale, N]() mutable { + const double l_d = value_of(length_scale); + auto& sigma_adj = forward_as(sigma).adj(); + auto& l_adj = forward_as(length_scale).adj(); + + size_t pos = 0; + for (size_t j = 0; j < N; ++j) { + for (size_t i = 0; i <= j; ++i) { + const double adj_times_val + = arena_res.coeff(i, j).val() * arena_res.coeff(i, j).adj(); + sigma_adj += adj_times_val; + l_adj += arena_dist.coeff(pos) * adj_times_val; + ++pos; + } + } + sigma_adj *= 2.0; + sigma_adj /= value_of(sigma); + l_adj /= (l_d * l_d * l_d); + }); return arena_res; } else { double sigma_sq_d = value_of(sigma) * value_of(sigma); - double inv_half_sq_l_d = 0.5 / (value_of(length_scale) * value_of(length_scale)); + double inv_half_sq_l_d + = 0.5 / (value_of(length_scale) * value_of(length_scale)); size_t N = x.size(); size_t P = (N * N - N) / 2 + N; arena_matrix dist(P); - arena_matrix> arena_res(N, N); + arena_matrix> arena_res( + N, N); auto arena_x = to_arena_if::value>(x); size_t pos = 0; for (size_t j = 0; j < N; ++j) { for (size_t i = 0; i <= j; ++i) { if (i != j) { - const double dist_sq = squared_distance(value_of(x[i]), value_of(x[j])); + const double dist_sq + = squared_distance(value_of(x[i]), value_of(x[j])); dist.coeffRef(pos) = dist_sq; arena_res.coeffRef(i, j) = sigma_sq_d * std::exp(-dist_sq * inv_half_sq_l_d); @@ -127,47 +133,48 @@ inline Eigen::Matrix gp_exp_quad_cov(const std::vector& x, } } - reverse_pass_callback([arena_res, arena_x, dist, sigma, length_scale, N]() mutable { - - const double& l_d = value_of(length_scale); - const double inv_l_d_squared = 1.0 / (l_d * l_d); - - size_t pos = 0; - for (size_t j = 0; j < N; ++j) { - for (size_t i = 0; i <= j; ++i) { - const double adj_times_val - = arena_res.coeff(i, j).val() * arena_res.coeff(i, j).adj(); + reverse_pass_callback( + [arena_res, arena_x, dist, sigma, length_scale, N]() mutable { + const double& l_d = value_of(length_scale); + const double inv_l_d_squared = 1.0 / (l_d * l_d); + + size_t pos = 0; + for (size_t j = 0; j < N; ++j) { + for (size_t i = 0; i <= j; ++i) { + const double adj_times_val + = arena_res.coeff(i, j).val() * arena_res.coeff(i, j).adj(); + + if (!is_constant::value) { + forward_as(sigma).adj() += adj_times_val; + } + + if (!is_constant::value) { + forward_as(length_scale).adj() + += dist.coeff(pos) * adj_times_val; + } + + if (!is_constant::value) { + if (i != j) { + auto adj = eval(-(value_of(arena_x[i]) - value_of(arena_x[j])) + * adj_times_val * inv_l_d_squared); + using T_x_var = promote_scalar_t; + forward_as(arena_x[i]).adj() += adj; + forward_as(arena_x[j]).adj() -= adj; + } + } + ++pos; + } + } if (!is_constant::value) { - forward_as(sigma).adj() += adj_times_val; + forward_as(sigma).adj() *= 2.0; + forward_as(sigma).adj() /= value_of(sigma); } if (!is_constant::value) { - forward_as(length_scale).adj() += dist.coeff(pos) * adj_times_val; + forward_as(length_scale).adj() /= (l_d * l_d * l_d); } - - if (!is_constant::value) { - if (i != j) { - auto adj = eval(-(value_of(arena_x[i]) - value_of(arena_x[j])) - * adj_times_val * inv_l_d_squared); - using T_x_var = promote_scalar_t; - forward_as(arena_x[i]).adj() += adj; - forward_as(arena_x[j]).adj() -= adj; - } - } - ++pos; - } - } - - if (!is_constant::value) { - forward_as(sigma).adj() *= 2.0; - forward_as(sigma).adj() /= value_of(sigma); - } - - if (!is_constant::value) { - forward_as(length_scale).adj() /= (l_d * l_d * l_d); - } - }); + }); return arena_res; } From 4fef4ea2e4fbc57b2d3d52cafc83cf0453796c8d Mon Sep 17 00:00:00 2001 From: Ben Date: Tue, 29 Sep 2020 10:13:21 -0400 Subject: [PATCH 280/355] Updated functions to work with expressions (Issue #2018) --- stan/math/prim/fun/variance.hpp | 18 ++++++++++++------ stan/math/rev/fun/cholesky_decompose.hpp | 4 ++-- stan/math/rev/fun/columns_dot_self.hpp | 8 +++++--- stan/math/rev/fun/determinant.hpp | 8 +++++--- stan/math/rev/fun/divide.hpp | 9 ++++++--- stan/math/rev/fun/dot_self.hpp | 9 +++++---- stan/math/rev/fun/log_determinant.hpp | 6 ++++-- stan/math/rev/fun/sd.hpp | 4 +++- 8 files changed, 42 insertions(+), 24 deletions(-) diff --git a/stan/math/prim/fun/variance.hpp b/stan/math/prim/fun/variance.hpp index 4e38dcbc7d9..470302261fb 100644 --- a/stan/math/prim/fun/variance.hpp +++ b/stan/math/prim/fun/variance.hpp @@ -4,6 +4,7 @@ #include #include #include +#include #include namespace stan { @@ -45,20 +46,25 @@ inline return_type_t variance(const std::vector& v) { * @return sample variance of coefficients * @throw std::invalid_argument if the matrix has size zero */ -template -inline return_type_t variance(const Eigen::Matrix& m) { +template * = nullptr, + require_not_st_var* = nullptr> +inline return_type_t variance(const T& m) { check_nonzero_size("variance", "m", m); if (m.size() == 1) { return 0.0; } - return_type_t mn(mean(m)); + + const auto& m_ref = to_ref(m); + + return_type_t mn(mean(m_ref)); return_type_t sum_sq_diff(0); - for (int i = 0; i < m.size(); ++i) { - return_type_t diff = m(i) - mn; + for (int i = 0; i < m_ref.size(); ++i) { + return_type_t diff = m_ref(i) - mn; sum_sq_diff += diff * diff; } - return sum_sq_diff / (m.size() - 1); + return sum_sq_diff / (m_ref.size() - 1); } } // namespace math diff --git a/stan/math/rev/fun/cholesky_decompose.hpp b/stan/math/rev/fun/cholesky_decompose.hpp index bd5de20adc9..ee441f3edf9 100644 --- a/stan/math/rev/fun/cholesky_decompose.hpp +++ b/stan/math/rev/fun/cholesky_decompose.hpp @@ -447,8 +447,8 @@ cholesky_decompose(const T& A) { int M = A.rows(); int P = (M * M - M) / 2 + M; Eigen::Matrix res_vars(P); - arena_matrix arena_A = A_ref; - arena_matrix res(M, M); + arena_t> arena_A = A_ref; + arena_t> res(M, M); var zero = 0.0; if (L_A_val.rows() > 35) { diff --git a/stan/math/rev/fun/columns_dot_self.hpp b/stan/math/rev/fun/columns_dot_self.hpp index f1ac7f46abc..c9c2670454d 100644 --- a/stan/math/rev/fun/columns_dot_self.hpp +++ b/stan/math/rev/fun/columns_dot_self.hpp @@ -19,9 +19,11 @@ namespace math { template * = nullptr> inline Eigen::Matrix columns_dot_self( const Mat& x) { - Eigen::Matrix ret(1, x.cols()); - for (size_type i = 0; i < x.cols(); i++) { - ret(i) = dot_self(x.col(i)); + const auto& x_ref = to_ref(x); + + Eigen::Matrix ret(1, x_ref.cols()); + for (size_type i = 0; i < x_ref.cols(); i++) { + ret(i) = dot_self(x_ref.col(i)); } return ret; } diff --git a/stan/math/rev/fun/determinant.hpp b/stan/math/rev/fun/determinant.hpp index cc4b0c77cac..2a73a766f3a 100644 --- a/stan/math/rev/fun/determinant.hpp +++ b/stan/math/rev/fun/determinant.hpp @@ -15,20 +15,22 @@ namespace math { template * = nullptr> inline var determinant(const T& m) { check_square("determinant", "m", m); + if (m.size() == 0) { return 1; } - const auto& m_val = to_ref(m.val()); + const auto& m_ref = to_ref(m); + const auto& m_val = to_ref(m_ref.val()); double det_val = m_val.determinant(); - arena_matrix> arena_m = m; + arena_matrix> arena_m = m_ref; arena_matrix arena_m_inv_t = m_val.inverse().transpose(); var det = det_val; reverse_pass_callback([arena_m, det, arena_m_inv_t]() mutable { arena_m.adj() += (det.adj() * det.val()) * arena_m_inv_t; - }); + }); return det; } diff --git a/stan/math/rev/fun/divide.hpp b/stan/math/rev/fun/divide.hpp index 30e130ddcd7..e3886a33969 100644 --- a/stan/math/rev/fun/divide.hpp +++ b/stan/math/rev/fun/divide.hpp @@ -25,14 +25,17 @@ template * = nullptr, require_any_st_var* = nullptr> inline Eigen::Matrix divide(const Mat& m, const Scal& c) { - auto arena_m = to_arena_if::value>(m); + const auto& m_ref = to_ref(m); + const auto& c_ref = to_ref(c); - double invc = 1.0 / value_of(c); + auto arena_m = to_arena_if::value>(m_ref); + + double invc = 1.0 / value_of(c_ref); using Mat_v = Eigen::Matrix; - arena_matrix res = invc * value_of(m); + arena_matrix res = invc * value_of(arena_m); reverse_pass_callback([=]() mutable { if (!is_constant::value) { diff --git a/stan/math/rev/fun/dot_self.hpp b/stan/math/rev/fun/dot_self.hpp index 23246397913..8904f38b547 100644 --- a/stan/math/rev/fun/dot_self.hpp +++ b/stan/math/rev/fun/dot_self.hpp @@ -22,13 +22,14 @@ namespace math { */ template * = nullptr> inline var dot_self(const T& v) { - arena_matrix> v_val = value_of(v); - arena_matrix> arena_v = v; + const auto& v_ref = to_ref(v); + + arena_matrix> v_val = value_of(v_ref); + arena_matrix> arena_v = v_ref; var res = v_val.dot(v_val); - reverse_pass_callback( - [=]() mutable { arena_v.adj() += 2.0 * res.adj() * v_val; }); + reverse_pass_callback([arena_v, res, v_val]() mutable { arena_v.adj() += 2.0 * res.adj() * v_val; }); return res; } diff --git a/stan/math/rev/fun/log_determinant.hpp b/stan/math/rev/fun/log_determinant.hpp index d6d46c0d94c..ac11f425326 100644 --- a/stan/math/rev/fun/log_determinant.hpp +++ b/stan/math/rev/fun/log_determinant.hpp @@ -20,10 +20,12 @@ inline var log_determinant(const T& m) { return 0.0; } + const auto& m_ref = to_ref(m); + Eigen::FullPivHouseholderQR>> hh - = m.val().fullPivHouseholderQr(); + = m_ref.val().fullPivHouseholderQr(); - arena_matrix> arena_m = m; + arena_matrix> arena_m = m_ref; arena_matrix arena_hh_inv_t = hh.inverse().transpose(); var log_det = hh.logAbsDeterminant(); diff --git a/stan/math/rev/fun/sd.hpp b/stan/math/rev/fun/sd.hpp index a3cc064ff9e..aefc7993bfa 100644 --- a/stan/math/rev/fun/sd.hpp +++ b/stan/math/rev/fun/sd.hpp @@ -32,7 +32,9 @@ var sd(const T& m) { return 0; } - return apply_vector_unary::reduce(m, [](const auto& x) { + const auto& m_ref = to_ref(m); + + return apply_vector_unary::reduce(m_ref, [](const auto& x) { const auto& x_ref = to_ref(x); arena_t arena_x = x_ref; const auto& x_val = to_ref(value_of(x)); From 84383ec8b2bd56bfd06eef15108cb826531f951f Mon Sep 17 00:00:00 2001 From: Stan Jenkins Date: Tue, 29 Sep 2020 14:40:27 +0000 Subject: [PATCH 281/355] [Jenkins] auto-formatting by clang-format version 6.0.0-1ubuntu2~16.04.1 (tags/RELEASE_600/final) --- stan/math/prim/fun/variance.hpp | 7 +++---- stan/math/rev/fun/determinant.hpp | 5 +++-- stan/math/rev/fun/dot_self.hpp | 4 +++- stan/math/rev/fun/log_determinant.hpp | 3 ++- stan/math/rev/fun/quad_form.hpp | 9 ++++++--- stan/math/rev/fun/quad_form_sym.hpp | 26 ++++++++++++++------------ stan/math/rev/fun/sd.hpp | 2 +- 7 files changed, 32 insertions(+), 24 deletions(-) diff --git a/stan/math/prim/fun/variance.hpp b/stan/math/prim/fun/variance.hpp index 470302261fb..3acd5676c07 100644 --- a/stan/math/prim/fun/variance.hpp +++ b/stan/math/prim/fun/variance.hpp @@ -46,9 +46,8 @@ inline return_type_t variance(const std::vector& v) { * @return sample variance of coefficients * @throw std::invalid_argument if the matrix has size zero */ -template * = nullptr, - require_not_st_var* = nullptr> +template * = nullptr, + require_not_st_var* = nullptr> inline return_type_t variance(const T& m) { check_nonzero_size("variance", "m", m); @@ -57,7 +56,7 @@ inline return_type_t variance(const T& m) { } const auto& m_ref = to_ref(m); - + return_type_t mn(mean(m_ref)); return_type_t sum_sq_diff(0); for (int i = 0; i < m_ref.size(); ++i) { diff --git a/stan/math/rev/fun/determinant.hpp b/stan/math/rev/fun/determinant.hpp index 2a73a766f3a..fdfff839b71 100644 --- a/stan/math/rev/fun/determinant.hpp +++ b/stan/math/rev/fun/determinant.hpp @@ -23,14 +23,15 @@ inline var determinant(const T& m) { const auto& m_ref = to_ref(m); const auto& m_val = to_ref(m_ref.val()); double det_val = m_val.determinant(); - arena_matrix> arena_m = m_ref; + arena_matrix> arena_m + = m_ref; arena_matrix arena_m_inv_t = m_val.inverse().transpose(); var det = det_val; reverse_pass_callback([arena_m, det, arena_m_inv_t]() mutable { arena_m.adj() += (det.adj() * det.val()) * arena_m_inv_t; - }); + }); return det; } diff --git a/stan/math/rev/fun/dot_self.hpp b/stan/math/rev/fun/dot_self.hpp index 8904f38b547..280b85ff3d7 100644 --- a/stan/math/rev/fun/dot_self.hpp +++ b/stan/math/rev/fun/dot_self.hpp @@ -29,7 +29,9 @@ inline var dot_self(const T& v) { var res = v_val.dot(v_val); - reverse_pass_callback([arena_v, res, v_val]() mutable { arena_v.adj() += 2.0 * res.adj() * v_val; }); + reverse_pass_callback([arena_v, res, v_val]() mutable { + arena_v.adj() += 2.0 * res.adj() * v_val; + }); return res; } diff --git a/stan/math/rev/fun/log_determinant.hpp b/stan/math/rev/fun/log_determinant.hpp index ac11f425326..bc122170c60 100644 --- a/stan/math/rev/fun/log_determinant.hpp +++ b/stan/math/rev/fun/log_determinant.hpp @@ -25,7 +25,8 @@ inline var log_determinant(const T& m) { Eigen::FullPivHouseholderQR>> hh = m_ref.val().fullPivHouseholderQr(); - arena_matrix> arena_m = m_ref; + arena_matrix> arena_m + = m_ref; arena_matrix arena_hh_inv_t = hh.inverse().transpose(); var log_det = hh.logAbsDeterminant(); diff --git a/stan/math/rev/fun/quad_form.hpp b/stan/math/rev/fun/quad_form.hpp index 3db05f6ab45..48aa2fd28ea 100644 --- a/stan/math/rev/fun/quad_form.hpp +++ b/stan/math/rev/fun/quad_form.hpp @@ -29,9 +29,11 @@ namespace internal { * @throws std::invalid_argument if A is not square, or if A cannot be * multiplied by B */ -template * = nullptr, +template * = nullptr, require_any_vt_var* = nullptr> -inline Eigen::Matrix +inline Eigen::Matrix quad_form_impl(const EigMat1& A, const EigMat2& B) { check_square("quad_form", "A", A); check_multiplicable("quad_form", "A", A, "B", B); @@ -60,7 +62,8 @@ quad_form_impl(const EigMat1& A, const EigMat2& B) { arena_A_val = value_of(A_ref); } - arena_matrix> + arena_matrix> res; if (is_constant::value) { diff --git a/stan/math/rev/fun/quad_form_sym.hpp b/stan/math/rev/fun/quad_form_sym.hpp index 79e286d376e..133d3f9afc0 100644 --- a/stan/math/rev/fun/quad_form_sym.hpp +++ b/stan/math/rev/fun/quad_form_sym.hpp @@ -31,7 +31,8 @@ namespace math { template * = nullptr, require_any_vt_var* = nullptr> -inline Eigen::Matrix +inline Eigen::Matrix quad_form_sym(const EigMat1& A, const EigMat2& B) { check_multiplicable("quad_form_sym", "A", A, "B", B); @@ -69,21 +70,22 @@ quad_form_sym(const EigMat1& A, const EigMat2& B) { res_val = arena_B_val.transpose() * arena_A_val * arena_B_val; } - arena_matrix> - res = 0.5 * (res_val + res_val.transpose()); + arena_matrix> + res = 0.5 * (res_val + res_val.transpose()); reverse_pass_callback( - [arena_A, arena_B, arena_A_val, arena_B_val, res]() mutable { - auto C_adj = res.adj().eval(); - auto C_adj_B_t = (C_adj * arena_B_val.transpose()).eval(); + [arena_A, arena_B, arena_A_val, arena_B_val, res]() mutable { + auto C_adj = res.adj().eval(); + auto C_adj_B_t = (C_adj * arena_B_val.transpose()).eval(); - if (!is_constant::value) - arena_A.adj() += arena_B_val * C_adj_B_t; + if (!is_constant::value) + arena_A.adj() += arena_B_val * C_adj_B_t; - if (!is_constant::value) - arena_B.adj() += arena_A_val * C_adj_B_t.transpose() - + arena_A_val.transpose() * arena_B_val * C_adj; - }); + if (!is_constant::value) + arena_B.adj() += arena_A_val * C_adj_B_t.transpose() + + arena_A_val.transpose() * arena_B_val * C_adj; + }); return res; } diff --git a/stan/math/rev/fun/sd.hpp b/stan/math/rev/fun/sd.hpp index aefc7993bfa..5743d5a89c9 100644 --- a/stan/math/rev/fun/sd.hpp +++ b/stan/math/rev/fun/sd.hpp @@ -33,7 +33,7 @@ var sd(const T& m) { } const auto& m_ref = to_ref(m); - + return apply_vector_unary::reduce(m_ref, [](const auto& x) { const auto& x_ref = to_ref(x); arena_t arena_x = x_ref; From 2469c8c3bc38afaa6f7780d17835fe205cdfdc68 Mon Sep 17 00:00:00 2001 From: Steve Bronder Date: Tue, 29 Sep 2020 14:01:14 -0400 Subject: [PATCH 282/355] fix quad_form docs --- stan/math/rev/fun/quad_form.hpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/stan/math/rev/fun/quad_form.hpp b/stan/math/rev/fun/quad_form.hpp index 48aa2fd28ea..945202f48c3 100644 --- a/stan/math/rev/fun/quad_form.hpp +++ b/stan/math/rev/fun/quad_form.hpp @@ -101,7 +101,6 @@ quad_form_impl(const EigMat1& A, const EigMat2& B) { * * @param A square matrix * @param B second matrix - * @param symmetric indicates whether the output should be made symmetric * @return The quadratic form, which is a symmetric matrix. * @throws std::invalid_argument if A is not square, or if A cannot be * multiplied by B @@ -122,7 +121,6 @@ inline auto quad_form(const EigMat1& A, const EigMat2& B) { * * @param A square matrix * @param B vector - * @param symmetric indicates whether the output should be made symmetric * @return The quadratic form (a scalar). * @throws std::invalid_argument if A is not square, or if A cannot be * multiplied by B From 0e96c78d818730e2497e81953957a693156b4961 Mon Sep 17 00:00:00 2001 From: Ben Date: Wed, 30 Sep 2020 07:42:27 -0400 Subject: [PATCH 283/355] Updated divide function (Issue #2018) --- stan/math/rev/fun/divide.hpp | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/stan/math/rev/fun/divide.hpp b/stan/math/rev/fun/divide.hpp index e3886a33969..97b5654885b 100644 --- a/stan/math/rev/fun/divide.hpp +++ b/stan/math/rev/fun/divide.hpp @@ -32,18 +32,21 @@ divide(const Mat& m, const Scal& c) { double invc = 1.0 / value_of(c_ref); - using Mat_v - = Eigen::Matrix; + using Mat_d = promote_scalar_t; + using Mat_v = promote_scalar_t; + + arena_t res_val = invc * value_of(m_ref); + arena_t res = res_val; - arena_matrix res = invc * value_of(arena_m); + reverse_pass_callback([arena_m, c, res, res_val, invc]() mutable { + const auto& adj = to_ref(res.adj()); - reverse_pass_callback([=]() mutable { if (!is_constant::value) { - forward_as(arena_m).adj() += invc * res.adj(); + forward_as(arena_m).adj() += invc * adj; } if (!is_constant::value) { forward_as(c).adj() - += -invc * (res.adj().array() * res.val().array()).sum(); + += -invc * (adj.array() * res_val.array()).sum(); } }); From 19344b5f6b67cd7e3439e9a8b1525a252d88bfdb Mon Sep 17 00:00:00 2001 From: Stan Jenkins Date: Wed, 30 Sep 2020 11:45:53 +0000 Subject: [PATCH 284/355] [Jenkins] auto-formatting by clang-format version 6.0.0-1ubuntu2~16.04.1 (tags/RELEASE_600/final) --- stan/math/rev/fun/divide.hpp | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/stan/math/rev/fun/divide.hpp b/stan/math/rev/fun/divide.hpp index 97b5654885b..bdd06768543 100644 --- a/stan/math/rev/fun/divide.hpp +++ b/stan/math/rev/fun/divide.hpp @@ -34,7 +34,7 @@ divide(const Mat& m, const Scal& c) { using Mat_d = promote_scalar_t; using Mat_v = promote_scalar_t; - + arena_t res_val = invc * value_of(m_ref); arena_t res = res_val; @@ -45,8 +45,7 @@ divide(const Mat& m, const Scal& c) { forward_as(arena_m).adj() += invc * adj; } if (!is_constant::value) { - forward_as(c).adj() - += -invc * (adj.array() * res_val.array()).sum(); + forward_as(c).adj() += -invc * (adj.array() * res_val.array()).sum(); } }); From 7bcb0a887aa26bed6a5f44767c977247bef800eb Mon Sep 17 00:00:00 2001 From: Ben Date: Thu, 1 Oct 2020 11:01:56 -0400 Subject: [PATCH 285/355] Made quad_form_sym return a scalar when the outer variable is a vector (Issue #2018) --- stan/math/rev/fun/quad_form_sym.hpp | 50 +++++++++++++++++-- .../unit/math/prim/fun/quad_form_sym_test.cpp | 18 +++++++ 2 files changed, 65 insertions(+), 3 deletions(-) diff --git a/stan/math/rev/fun/quad_form_sym.hpp b/stan/math/rev/fun/quad_form_sym.hpp index 133d3f9afc0..cb99b4762b6 100644 --- a/stan/math/rev/fun/quad_form_sym.hpp +++ b/stan/math/rev/fun/quad_form_sym.hpp @@ -13,6 +13,7 @@ namespace stan { namespace math { +namespace internal { /** * Return the quadratic form \f$ B^T A B \f$ of a symmetric matrix. * @@ -23,8 +24,7 @@ namespace math { * * @param A symmetric matrix * @param B second matrix - * @return The quadratic form, which is a symmetric matrix of size Cb. - * If \c B is a column vector returns a scalar. + * @return the quadratic form as a matrix * @throws std::invalid_argument if A is not symmetric, or if A cannot be * multiplied by B */ @@ -33,7 +33,7 @@ template * = nullptr> inline Eigen::Matrix -quad_form_sym(const EigMat1& A, const EigMat2& B) { +quad_form_sym_impl(const EigMat1& A, const EigMat2& B) { check_multiplicable("quad_form_sym", "A", A, "B", B); using A_ref_t = ref_type_t; @@ -89,6 +89,50 @@ quad_form_sym(const EigMat1& A, const EigMat2& B) { return res; } +} // namespace internal + +/** + * Return the quadratic form \f$ B^T A B \f$ of a symmetric matrix. + * + * Symmetry of the resulting matrix is guaranteed. + * + * @tparam EigMat1 type of the first (symmetric) matrix + * @tparam EigMat2 type of the second matrix + * + * @param A symmetric matrix + * @param B second matrix + * @return the quadratic form as a matrix + * @throws std::invalid_argument if A is not symmetric, or if A cannot be + * multiplied by B + */ +template * = nullptr, + require_not_eigen_col_vector_t* = nullptr, + require_any_vt_var* = nullptr> +inline auto quad_form_sym(const EigMat1& A, const EigMat2& B) { + return internal::quad_form_sym_impl(A, B); +} + +/** + * Return the quadratic form \f$ b^T A b \f$ of a symmetric matrix. + * + * Symmetry of the resulting matrix is guaranteed. + * + * @tparam EigMat type of the symmetric matrix A + * @tparam ColVec type of the vector b + * + * @param A symmetric matrix + * @param b column vector + * @return the quadratic form as a scalar + * @throws std::invalid_argument if A is not symmetric, or if A cannot be + * multiplied by b + */ +template * = nullptr, + require_eigen_col_vector_t* = nullptr, + require_any_vt_var* = nullptr> +inline var quad_form_sym(const EigMat& A, const ColVec& B) { + return internal::quad_form_sym_impl(A, B)(0, 0); +} } // namespace math } // namespace stan diff --git a/test/unit/math/prim/fun/quad_form_sym_test.cpp b/test/unit/math/prim/fun/quad_form_sym_test.cpp index ca11b43c752..c122133d4be 100644 --- a/test/unit/math/prim/fun/quad_form_sym_test.cpp +++ b/test/unit/math/prim/fun/quad_form_sym_test.cpp @@ -111,3 +111,21 @@ TEST(MathMatrixPrim, quad_form_sym_2095) { matrix_d cd = stan::math::quad_form_sym(ad, bd); EXPECT_FLOAT_EQ(0, cd(1, 0) - cd(0, 1)); } + +TEST(AgradRev, quad_form_sym_return_types) { + using stan::math::quad_form_sym; + + double a = 5.0; + + Eigen::MatrixXd A(2, 2); + A << 1.0, 1.0, 1.0, 1.0; + + Eigen::VectorXd b(2); + b << 1.0, 1.0; + + Eigen::MatrixXd B(2, 1); + B << 1.0, 1.0; + + EXPECT_TRUE((std::is_same::value)); + EXPECT_TRUE((std::is_same::value)); +} From d0dba78111978c23acb5963d02c97543e8a316cb Mon Sep 17 00:00:00 2001 From: Stan Jenkins Date: Thu, 1 Oct 2020 15:04:14 +0000 Subject: [PATCH 286/355] [Jenkins] auto-formatting by clang-format version 6.0.0-1ubuntu2~16.04.1 (tags/RELEASE_600/final) --- test/unit/math/prim/fun/quad_form_sym_test.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/test/unit/math/prim/fun/quad_form_sym_test.cpp b/test/unit/math/prim/fun/quad_form_sym_test.cpp index c122133d4be..197a1768f1d 100644 --- a/test/unit/math/prim/fun/quad_form_sym_test.cpp +++ b/test/unit/math/prim/fun/quad_form_sym_test.cpp @@ -119,7 +119,7 @@ TEST(AgradRev, quad_form_sym_return_types) { Eigen::MatrixXd A(2, 2); A << 1.0, 1.0, 1.0, 1.0; - + Eigen::VectorXd b(2); b << 1.0, 1.0; @@ -127,5 +127,6 @@ TEST(AgradRev, quad_form_sym_return_types) { B << 1.0, 1.0; EXPECT_TRUE((std::is_same::value)); - EXPECT_TRUE((std::is_same::value)); + EXPECT_TRUE( + (std::is_same::value)); } From 0582b703550340adb38dc992321ad5d422bd0655 Mon Sep 17 00:00:00 2001 From: Ben Date: Thu, 1 Oct 2020 11:30:09 -0400 Subject: [PATCH 287/355] Changed quad_form_sym code to reflect docs (issue #2018) --- stan/math/rev/fun/quad_form_sym.hpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/stan/math/rev/fun/quad_form_sym.hpp b/stan/math/rev/fun/quad_form_sym.hpp index cb99b4762b6..185a100e6b6 100644 --- a/stan/math/rev/fun/quad_form_sym.hpp +++ b/stan/math/rev/fun/quad_form_sym.hpp @@ -130,8 +130,8 @@ inline auto quad_form_sym(const EigMat1& A, const EigMat2& B) { template * = nullptr, require_eigen_col_vector_t* = nullptr, require_any_vt_var* = nullptr> -inline var quad_form_sym(const EigMat& A, const ColVec& B) { - return internal::quad_form_sym_impl(A, B)(0, 0); +inline var quad_form_sym(const EigMat& A, const ColVec& b) { + return internal::quad_form_sym_impl(A, b)(0, 0); } } // namespace math From e2a27ce9c86e40ce19310327c04ecc02fd54433d Mon Sep 17 00:00:00 2001 From: Ben Date: Sat, 3 Oct 2020 12:09:46 -0400 Subject: [PATCH 288/355] Added missing test (Issue #2018) --- test/unit/math/rev/fun/quad_form_sym_test.cpp | 24 +++++++++++++++++++ 1 file changed, 24 insertions(+) create mode 100644 test/unit/math/rev/fun/quad_form_sym_test.cpp diff --git a/test/unit/math/rev/fun/quad_form_sym_test.cpp b/test/unit/math/rev/fun/quad_form_sym_test.cpp new file mode 100644 index 00000000000..ed62a320a8d --- /dev/null +++ b/test/unit/math/rev/fun/quad_form_sym_test.cpp @@ -0,0 +1,24 @@ +#include +#include +#include +#include +#include + +TEST(AgradRev, quad_form_sym_return_types) { + using stan::math::quad_form_sym; + using stan::math::var; + + var a = 5.0; + + Eigen::Matrix A(2, 2); + A << 1.0, 1.0, 1.0, 1.0; + + Eigen::Matrix b(2); + b << 1.0, 1.0; + + Eigen::Matrix B(2, 1); + B << 1.0, 1.0; + + EXPECT_TRUE((std::is_same::value)); + EXPECT_TRUE((std::is_same, decltype(quad_form_sym(A, B))>::value)); +} From 88ce53281cf863b75057347f5574c52b616e0bb0 Mon Sep 17 00:00:00 2001 From: Stan Jenkins Date: Sat, 3 Oct 2020 12:16:55 -0400 Subject: [PATCH 289/355] [Jenkins] auto-formatting by clang-format version 6.0.1-14 (tags/RELEASE_601/final) --- test/unit/math/rev/fun/quad_form_sym_test.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/test/unit/math/rev/fun/quad_form_sym_test.cpp b/test/unit/math/rev/fun/quad_form_sym_test.cpp index ed62a320a8d..dfd610e9585 100644 --- a/test/unit/math/rev/fun/quad_form_sym_test.cpp +++ b/test/unit/math/rev/fun/quad_form_sym_test.cpp @@ -12,7 +12,7 @@ TEST(AgradRev, quad_form_sym_return_types) { Eigen::Matrix A(2, 2); A << 1.0, 1.0, 1.0, 1.0; - + Eigen::Matrix b(2); b << 1.0, 1.0; @@ -20,5 +20,6 @@ TEST(AgradRev, quad_form_sym_return_types) { B << 1.0, 1.0; EXPECT_TRUE((std::is_same::value)); - EXPECT_TRUE((std::is_same, decltype(quad_form_sym(A, B))>::value)); + EXPECT_TRUE((std::is_same, + decltype(quad_form_sym(A, B))>::value)); } From 21894fb16e8c86ea3666fb1afc27bca365b7d4f2 Mon Sep 17 00:00:00 2001 From: Ben Date: Sat, 3 Oct 2020 13:07:05 -0400 Subject: [PATCH 290/355] Renamed tests (Issue #2018) --- test/unit/math/prim/fun/quad_form_sym_test.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/unit/math/prim/fun/quad_form_sym_test.cpp b/test/unit/math/prim/fun/quad_form_sym_test.cpp index 197a1768f1d..1634f5a5b63 100644 --- a/test/unit/math/prim/fun/quad_form_sym_test.cpp +++ b/test/unit/math/prim/fun/quad_form_sym_test.cpp @@ -112,7 +112,7 @@ TEST(MathMatrixPrim, quad_form_sym_2095) { EXPECT_FLOAT_EQ(0, cd(1, 0) - cd(0, 1)); } -TEST(AgradRev, quad_form_sym_return_types) { +TEST(MathMatrixPrim, quad_form_sym_return_types) { using stan::math::quad_form_sym; double a = 5.0; From 787e587b37b7200449e8a49f2a58d6a4623af280 Mon Sep 17 00:00:00 2001 From: Ben Date: Sat, 3 Oct 2020 13:23:55 -0400 Subject: [PATCH 291/355] Fixed performance for variance (Issue #2018) --- stan/math/rev/fun/variance.hpp | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/stan/math/rev/fun/variance.hpp b/stan/math/rev/fun/variance.hpp index 1e28b4790fb..e39d6cdbdae 100644 --- a/stan/math/rev/fun/variance.hpp +++ b/stan/math/rev/fun/variance.hpp @@ -23,22 +23,23 @@ namespace math { template * = nullptr> inline var variance(const T& x) { check_nonzero_size("variance", "x", x); + if (x.size() == 1) { return 0; } const auto& x_ref = to_ref(x); - const auto& x_array = as_array_or_scalar(x_ref); - arena_t arena_x = x_array; + auto arena_x = to_arena(x_ref); + + const auto& x_array = as_array_or_scalar(arena_x); const auto& x_val = to_ref(value_of(x_array)); - double mean = x_val.mean(); - arena_matrix> arena_diff = x_val.array() - mean; + auto arena_diff = to_arena(x_val.array() - x_val.mean()); var res = arena_diff.matrix().squaredNorm() / (x_array.size() - 1); reverse_pass_callback([arena_x, res, arena_diff]() mutable { - arena_x.adj() += (2.0 * res.adj() / (arena_x.size() - 1)) * arena_diff; + as_array_or_scalar(arena_x).adj() += (2.0 * res.adj() / (arena_x.size() - 1)) * arena_diff; }); return res; From 2bd2e4a31ab55439f2cd9888044f59b7abd0eb01 Mon Sep 17 00:00:00 2001 From: Stan Jenkins Date: Sat, 3 Oct 2020 14:33:32 -0400 Subject: [PATCH 292/355] [Jenkins] auto-formatting by clang-format version 6.0.1-14 (tags/RELEASE_601/final) --- stan/math/rev/fun/variance.hpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/stan/math/rev/fun/variance.hpp b/stan/math/rev/fun/variance.hpp index e39d6cdbdae..230eaf5c73a 100644 --- a/stan/math/rev/fun/variance.hpp +++ b/stan/math/rev/fun/variance.hpp @@ -39,7 +39,8 @@ inline var variance(const T& x) { var res = arena_diff.matrix().squaredNorm() / (x_array.size() - 1); reverse_pass_callback([arena_x, res, arena_diff]() mutable { - as_array_or_scalar(arena_x).adj() += (2.0 * res.adj() / (arena_x.size() - 1)) * arena_diff; + as_array_or_scalar(arena_x).adj() + += (2.0 * res.adj() / (arena_x.size() - 1)) * arena_diff; }); return res; From 345ccb3819bae263b53b4b5f8d779a9dffa334ff Mon Sep 17 00:00:00 2001 From: Ben Date: Sat, 3 Oct 2020 15:40:34 -0400 Subject: [PATCH 293/355] Updated multiply_lower_tri_self_transpose (Issue #2018) --- .../fun/multiply_lower_tri_self_transpose.hpp | 45 ++++++++++--------- ...multiply_lower_tri_self_transpose_test.cpp | 22 +++++++++ 2 files changed, 47 insertions(+), 20 deletions(-) create mode 100644 test/unit/math/rev/fun/multiply_lower_tri_self_transpose_test.cpp diff --git a/stan/math/rev/fun/multiply_lower_tri_self_transpose.hpp b/stan/math/rev/fun/multiply_lower_tri_self_transpose.hpp index a636e70fadb..2306d70a229 100644 --- a/stan/math/rev/fun/multiply_lower_tri_self_transpose.hpp +++ b/stan/math/rev/fun/multiply_lower_tri_self_transpose.hpp @@ -12,33 +12,38 @@ namespace stan { namespace math { template * = nullptr> -inline Eigen::Matrix -multiply_lower_tri_self_transpose(const T& L) { - using T_double = promote_scalar_t; - using T_var = promote_scalar_t; +inline auto multiply_lower_tri_self_transpose(const T& L) { + using ret_type = promote_scalar_t; - if (L.rows() == 0) - return T_var(); + if (L.size() == 0) + return ret_type(); - arena_matrix arena_L = L; - arena_matrix arena_L_val - = value_of(arena_L).template triangularView(); + arena_t arena_U = L.transpose(); - arena_matrix res = arena_L_val.template triangularView() - * arena_L_val.transpose(); + auto arena_U_val = to_arena(value_of(arena_U).template triangularView()); - reverse_pass_callback([res, arena_L, arena_L_val]() mutable { - ref_type_t adj = res.adj(); - Eigen::MatrixXd adjL = (adj.transpose() + adj) * arena_L_val; + if(L.size() > 16) { + arena_t res = arena_U_val.transpose() + * arena_U_val.template triangularView(); - for (size_t j = 1; j < adjL.cols(); ++j) - for (size_t i = 0; i < std::min(static_cast(adjL.rows()), j); ++i) - adjL(i, j) = 0.0; + reverse_pass_callback([res, arena_U, arena_U_val]() mutable { + const auto& adj = to_ref(res.adj()); + + arena_U.adj() += (arena_U_val.template triangularView() * (adj.transpose() + adj)).template triangularView(); + }); - arena_L.adj() += adjL; - }); + return ret_type(res); + } else { + arena_t res = arena_U_val.transpose().lazyProduct(arena_U_val); - return res; + reverse_pass_callback([res, arena_U, arena_U_val]() mutable { + const auto& adj = to_ref(res.adj()); + + arena_U.adj() += (arena_U_val.lazyProduct(adj.transpose() + adj)).template triangularView(); + }); + + return ret_type(res); + } } } // namespace math diff --git a/test/unit/math/rev/fun/multiply_lower_tri_self_transpose_test.cpp b/test/unit/math/rev/fun/multiply_lower_tri_self_transpose_test.cpp new file mode 100644 index 00000000000..7130797fcb0 --- /dev/null +++ b/test/unit/math/rev/fun/multiply_lower_tri_self_transpose_test.cpp @@ -0,0 +1,22 @@ +#include +#include +#include +#include +#include + +TEST(AgradRevMatrix, multiply_lower_tri_self_transpose_test_large) { + for(auto N : { 1, 2, 3, 5, 10 }) { + Eigen::MatrixXd A = Eigen::MatrixXd::Random(N, N).template triangularView(); + stan::math::promote_scalar_t Av = A; + + auto res = multiply_lower_tri_self_transpose(Av); + + stan::math::sum(res).grad(); + + Eigen::MatrixXd adjoint = (2 * Eigen::MatrixXd::Ones(N, N) * A).template triangularView(); + EXPECT_MATRIX_NEAR(res.val(), A * A.transpose(), 1e-8); + EXPECT_MATRIX_NEAR(Av.adj(), adjoint, 1e-8); + + stan::math::recover_memory(); + } +} From 36fb58dd18e5f7b82674d00a922be5cec3773951 Mon Sep 17 00:00:00 2001 From: Stan Jenkins Date: Sat, 3 Oct 2020 19:41:47 +0000 Subject: [PATCH 294/355] [Jenkins] auto-formatting by clang-format version 6.0.0-1ubuntu2~16.04.1 (tags/RELEASE_600/final) --- .../fun/multiply_lower_tri_self_transpose.hpp | 23 +++++++++++-------- ...multiply_lower_tri_self_transpose_test.cpp | 8 ++++--- 2 files changed, 19 insertions(+), 12 deletions(-) diff --git a/stan/math/rev/fun/multiply_lower_tri_self_transpose.hpp b/stan/math/rev/fun/multiply_lower_tri_self_transpose.hpp index 2306d70a229..02598aa3e48 100644 --- a/stan/math/rev/fun/multiply_lower_tri_self_transpose.hpp +++ b/stan/math/rev/fun/multiply_lower_tri_self_transpose.hpp @@ -20,16 +20,20 @@ inline auto multiply_lower_tri_self_transpose(const T& L) { arena_t arena_U = L.transpose(); - auto arena_U_val = to_arena(value_of(arena_U).template triangularView()); + auto arena_U_val + = to_arena(value_of(arena_U).template triangularView()); - if(L.size() > 16) { - arena_t res = arena_U_val.transpose() - * arena_U_val.template triangularView(); + if (L.size() > 16) { + arena_t res + = arena_U_val.transpose() + * arena_U_val.template triangularView(); reverse_pass_callback([res, arena_U, arena_U_val]() mutable { const auto& adj = to_ref(res.adj()); - - arena_U.adj() += (arena_U_val.template triangularView() * (adj.transpose() + adj)).template triangularView(); + + arena_U.adj() += (arena_U_val.template triangularView() + * (adj.transpose() + adj)) + .template triangularView(); }); return ret_type(res); @@ -38,9 +42,10 @@ inline auto multiply_lower_tri_self_transpose(const T& L) { reverse_pass_callback([res, arena_U, arena_U_val]() mutable { const auto& adj = to_ref(res.adj()); - - arena_U.adj() += (arena_U_val.lazyProduct(adj.transpose() + adj)).template triangularView(); - }); + + arena_U.adj() += (arena_U_val.lazyProduct(adj.transpose() + adj)) + .template triangularView(); + }); return ret_type(res); } diff --git a/test/unit/math/rev/fun/multiply_lower_tri_self_transpose_test.cpp b/test/unit/math/rev/fun/multiply_lower_tri_self_transpose_test.cpp index 7130797fcb0..746c8fe4968 100644 --- a/test/unit/math/rev/fun/multiply_lower_tri_self_transpose_test.cpp +++ b/test/unit/math/rev/fun/multiply_lower_tri_self_transpose_test.cpp @@ -5,15 +5,17 @@ #include TEST(AgradRevMatrix, multiply_lower_tri_self_transpose_test_large) { - for(auto N : { 1, 2, 3, 5, 10 }) { - Eigen::MatrixXd A = Eigen::MatrixXd::Random(N, N).template triangularView(); + for (auto N : {1, 2, 3, 5, 10}) { + Eigen::MatrixXd A + = Eigen::MatrixXd::Random(N, N).template triangularView(); stan::math::promote_scalar_t Av = A; auto res = multiply_lower_tri_self_transpose(Av); stan::math::sum(res).grad(); - Eigen::MatrixXd adjoint = (2 * Eigen::MatrixXd::Ones(N, N) * A).template triangularView(); + Eigen::MatrixXd adjoint = (2 * Eigen::MatrixXd::Ones(N, N) * A) + .template triangularView(); EXPECT_MATRIX_NEAR(res.val(), A * A.transpose(), 1e-8); EXPECT_MATRIX_NEAR(Av.adj(), adjoint, 1e-8); From 88de48383bfead38baf0dcf898a577d0457ca807 Mon Sep 17 00:00:00 2001 From: Ben Date: Sat, 3 Oct 2020 15:49:19 -0400 Subject: [PATCH 295/355] Cleaning up tcrossprod (Issue #2018) --- stan/math/rev/fun/tcrossprod.hpp | 36 ++++++++++---------------------- 1 file changed, 11 insertions(+), 25 deletions(-) diff --git a/stan/math/rev/fun/tcrossprod.hpp b/stan/math/rev/fun/tcrossprod.hpp index 2cfad186420..d7c272dd288 100644 --- a/stan/math/rev/fun/tcrossprod.hpp +++ b/stan/math/rev/fun/tcrossprod.hpp @@ -22,38 +22,24 @@ namespace math { * @return M times its transpose. */ template * = nullptr> -inline Eigen::Matrix -tcrossprod(const T& M) { - if (M.rows() == 0) { - return {}; - } - - arena_matrix> arena_M = M; - arena_matrix> arena_M_val = value_of(arena_M); +inline auto tcrossprod(const T& M) { + using ret_type = promote_scalar_t; - Eigen::Matrix res_val( - M.rows(), M.rows()); - res_val.setZero().template selfadjointView().rankUpdate( - arena_M_val); + if (M.size() == 0) { + return ret_type(); + } - arena_matrix> - res(M.rows(), M.rows()); + arena_t arena_M = M; + auto arena_M_val = to_arena(value_of(arena_M)); - for (size_t j = 0; j < res.cols(); ++j) { - for (size_t i = 0; i < j; ++i) { - res.coeffRef(i, j) = res.coeffRef(j, i) = res_val.coeff(i, j); - } - res.coeffRef(j, j) = res_val.coeff(j, j); - } + arena_t res = arena_M_val * arena_M_val.transpose(); reverse_pass_callback([res, arena_M, arena_M_val]() mutable { - Eigen::MatrixXd adj = res.adj(); - for (size_t i = 0; i < adj.cols(); ++i) - adj(i, i) *= 2.0; - arena_M.adj() += adj * arena_M_val; + const auto& adj = to_ref(res.adj()); + arena_M.adj() += (adj.transpose() + adj) * arena_M_val; }); - return res; + return ret_type(res); } } // namespace math From c4fceadcd1a1623d7793903212a59e819f5f6ecb Mon Sep 17 00:00:00 2001 From: Ben Date: Sat, 3 Oct 2020 17:06:38 -0400 Subject: [PATCH 296/355] Updated squared distance (Issue #2018) --- stan/math/rev/fun/squared_distance.hpp | 58 +++++++++++++------------- 1 file changed, 28 insertions(+), 30 deletions(-) diff --git a/stan/math/rev/fun/squared_distance.hpp b/stan/math/rev/fun/squared_distance.hpp index da6a1bad910..101b73a8077 100644 --- a/stan/math/rev/fun/squared_distance.hpp +++ b/stan/math/rev/fun/squared_distance.hpp @@ -20,15 +20,20 @@ template * = nullptr, require_any_var_t* = nullptr> inline var squared_distance(const T1& a, const T2& b) { + check_finite("squared_distance", "a", a); + check_finite("squared_distance", "b", b); + double diff = value_of(a) - value_of(b); - var res = squared_distance(value_of(a), value_of(b)); - reverse_pass_callback([a, b, diff, res]() mutable { - if (!is_constant::value) - forward_as(a).adj() += 2.0 * res.adj() * diff; + var res = diff * diff; - if (!is_constant::value) + reverse_pass_callback([a, b, res]() mutable { + double diff = value_of(a) - value_of(b); + if(!is_constant::value) + forward_as(a).adj() += 2.0 * res.adj() * diff; + if(!is_constant::value) forward_as(b).adj() += -2.0 * res.adj() * diff; }); + return res; } @@ -41,36 +46,29 @@ inline var squared_distance(const T1& A, const T2& B) { if (A.size() == 0) return 0.0; - using A_ref_t = ref_type_t; - using B_ref_t = ref_type_t; - - A_ref_t A_ref = A; - B_ref_t B_ref = B; - - auto A_col = as_column_vector_or_scalar(A_ref); - auto B_col = as_column_vector_or_scalar(B_ref); - - auto arena_diff_val = to_arena(value_of(A_col) - value_of(B_col)); - - arena_matrix> arena_A; - arena_matrix> arena_B; - - if (!is_constant::value) { - arena_A = A_col; - } + const auto& A_ref = to_ref(A); + const auto& B_ref = to_ref(B); - if (!is_constant::value) { - arena_B = B_col; + double res_val = 0.0; + for(size_t i = 0; i < A.size(); ++i) { + double diff = value_of(A_ref[i]) - value_of(B_ref[i]); + res_val += diff * diff; } - var res = arena_diff_val.squaredNorm(); + var res = res_val; - reverse_pass_callback([arena_A, arena_B, arena_diff_val, res]() mutable { - if (!is_constant::value) - arena_A.adj() += 2.0 * res.adj() * arena_diff_val; + auto arena_A = to_arena(A_ref); + auto arena_B = to_arena(B_ref); - if (!is_constant::value) - arena_B.adj() += -2.0 * res.adj() * arena_diff_val; + reverse_pass_callback([arena_A, arena_B, res]() mutable { + for(size_t i = 0; i < arena_A.size(); ++i) { + double diff = value_of(arena_A[i]) - + value_of(arena_B[i]); + if(!is_constant::value) + forward_as(arena_A[i]).adj() += 2.0 * res.adj() * diff; + if(!is_constant::value) + forward_as(arena_B[i]).adj() -= 2.0 * res.adj() * diff; + } }); return res; From 6aacb439a7d92605c539996c0a3b520d443ee971 Mon Sep 17 00:00:00 2001 From: Stan Jenkins Date: Sat, 3 Oct 2020 17:07:48 -0400 Subject: [PATCH 297/355] [Jenkins] auto-formatting by clang-format version 6.0.1-14 (tags/RELEASE_601/final) --- stan/math/rev/fun/squared_distance.hpp | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/stan/math/rev/fun/squared_distance.hpp b/stan/math/rev/fun/squared_distance.hpp index 101b73a8077..11878de2bdd 100644 --- a/stan/math/rev/fun/squared_distance.hpp +++ b/stan/math/rev/fun/squared_distance.hpp @@ -28,9 +28,9 @@ inline var squared_distance(const T1& a, const T2& b) { reverse_pass_callback([a, b, res]() mutable { double diff = value_of(a) - value_of(b); - if(!is_constant::value) + if (!is_constant::value) forward_as(a).adj() += 2.0 * res.adj() * diff; - if(!is_constant::value) + if (!is_constant::value) forward_as(b).adj() += -2.0 * res.adj() * diff; }); @@ -50,7 +50,7 @@ inline var squared_distance(const T1& A, const T2& B) { const auto& B_ref = to_ref(B); double res_val = 0.0; - for(size_t i = 0; i < A.size(); ++i) { + for (size_t i = 0; i < A.size(); ++i) { double diff = value_of(A_ref[i]) - value_of(B_ref[i]); res_val += diff * diff; } @@ -61,13 +61,12 @@ inline var squared_distance(const T1& A, const T2& B) { auto arena_B = to_arena(B_ref); reverse_pass_callback([arena_A, arena_B, res]() mutable { - for(size_t i = 0; i < arena_A.size(); ++i) { - double diff = value_of(arena_A[i]) - - value_of(arena_B[i]); - if(!is_constant::value) - forward_as(arena_A[i]).adj() += 2.0 * res.adj() * diff; - if(!is_constant::value) - forward_as(arena_B[i]).adj() -= 2.0 * res.adj() * diff; + for (size_t i = 0; i < arena_A.size(); ++i) { + double diff = value_of(arena_A[i]) - value_of(arena_B[i]); + if (!is_constant::value) + forward_as(arena_A[i]).adj() += 2.0 * res.adj() * diff; + if (!is_constant::value) + forward_as(arena_B[i]).adj() -= 2.0 * res.adj() * diff; } }); From be563139516cbf8799e1e9409104bb9b3a75eab3 Mon Sep 17 00:00:00 2001 From: Ben Date: Sat, 3 Oct 2020 17:41:34 -0400 Subject: [PATCH 298/355] Updated dot_self (Issue #2018) --- stan/math/rev/fun/dot_self.hpp | 104 +++++++++++++++++++++++++++++++-- 1 file changed, 98 insertions(+), 6 deletions(-) diff --git a/stan/math/rev/fun/dot_self.hpp b/stan/math/rev/fun/dot_self.hpp index 280b85ff3d7..2ff12f65671 100644 --- a/stan/math/rev/fun/dot_self.hpp +++ b/stan/math/rev/fun/dot_self.hpp @@ -12,6 +12,31 @@ namespace stan { namespace math { +namespace internal { +class dot_self_vari : public vari { +protected: + vari** v_; + size_t size_; + +public: + dot_self_vari(vari** v, size_t size) + : vari(Eigen::Map(v, size).val().squaredNorm()), + v_(v), + size_(size) {} + template * = nullptr> + explicit dot_self_vari(const T& v) + : vari(v.val().squaredNorm()), size_(v.size()) { + v_ = reinterpret_cast( + ChainableStack::instance_->memalloc_.alloc(size_ * sizeof(vari*))); + Eigen::Map(v_, v.rows(), v.cols()) = v.vi(); + } + virtual void chain() { + Eigen::Map v_map(v_, size_); + v_map.adj() += adj_ * 2.0 * v_map.val(); + } +}; +} + /** * Returns the dot product of a vector of var with itself. * @@ -22,18 +47,85 @@ namespace math { */ template * = nullptr> inline var dot_self(const T& v) { - const auto& v_ref = to_ref(v); + /* + -------------------------------------------------------------------- + Benchmark Time CPU Iterations + -------------------------------------------------------------------- + toss_me 10126264 ns 10125955 ns 70 + dot_self/2/manual_time 65.2 ns 161 ns 10681302 + dot_self/4/manual_time 66.7 ns 190 ns 10469218 + dot_self/8/manual_time 71.7 ns 260 ns 9693894 + dot_self/16/manual_time 84.3 ns 378 ns 8305816 + dot_self/32/manual_time 121 ns 635 ns 5814113 + dot_self/64/manual_time 186 ns 1119 ns 3757719 + dot_self/128/manual_time 326 ns 2105 ns 2150730 + dot_self/256/manual_time 611 ns 4212 ns 1142432 + dot_self/512/manual_time 1217 ns 8430 ns 574490 + dot_self/1024/manual_time 2548 ns 19862 ns 275469 + */ - arena_matrix> v_val = value_of(v_ref); - arena_matrix> arena_v = v_ref; + //const Eigen::Ref>& v_ref = v; + //return {new internal::dot_self_vari(v_ref)}; + + /* + -------------------------------------------------------------------- + Benchmark Time CPU Iterations + -------------------------------------------------------------------- + toss_me 10077101 ns 10076684 ns 69 + dot_self/2/manual_time 68.7 ns 164 ns 10057031 + dot_self/4/manual_time 69.2 ns 192 ns 10049326 + dot_self/8/manual_time 74.2 ns 263 ns 9370878 + dot_self/16/manual_time 89.4 ns 385 ns 7810417 + dot_self/32/manual_time 125 ns 671 ns 5615422 + dot_self/64/manual_time 195 ns 1149 ns 3584751 + dot_self/128/manual_time 348 ns 2166 ns 2008505 + dot_self/256/manual_time 651 ns 4508 ns 1069752 + dot_self/512/manual_time 1277 ns 8948 ns 544405 + dot_self/1024/manual_time 2648 ns 21018 ns 267065 + */ + + arena_t arena_v = v; - var res = v_val.dot(v_val); + var res = arena_v.val().squaredNorm(); - reverse_pass_callback([arena_v, res, v_val]() mutable { - arena_v.adj() += 2.0 * res.adj() * v_val; + reverse_pass_callback([arena_v, res]() { + for(size_t i = 0; i < arena_v.size(); ++i) { + arena_v.coeffRef(i).adj() += 2.0 * res.adj() * arena_v.coeff(i).val(); + } }); return res; + + + /* + -------------------------------------------------------------------- + Benchmark Time CPU Iterations + -------------------------------------------------------------------- + toss_me 10161766 ns 10160959 ns 70 + dot_self/2/manual_time 84.7 ns 180 ns 8201199 + dot_self/4/manual_time 85.6 ns 210 ns 8076649 + dot_self/8/manual_time 92.1 ns 286 ns 7451948 + dot_self/16/manual_time 103 ns 422 ns 6857630 + dot_self/32/manual_time 123 ns 675 ns 5680814 + dot_self/64/manual_time 172 ns 1210 ns 4071015 + dot_self/128/manual_time 276 ns 2272 ns 2544438 + dot_self/256/manual_time 505 ns 4629 ns 1384535 + dot_self/512/manual_time 992 ns 9303 ns 703375 + dot_self/1024/manual_time 2270 ns 20923 ns 308428 + */ + + /* + arena_t arena_v = v; + + auto arena_v_val = to_arena(value_of(arena_v)); + var res = arena_v_val.squaredNorm(); + + reverse_pass_callback([arena_v, res, arena_v_val]() mutable { + arena_v.adj() += (2.0 * res.adj()) * arena_v_val; + }); + + return res; + */ } } // namespace math From 4005e1158cf38a1c72c197b0b53eec9131f2c49a Mon Sep 17 00:00:00 2001 From: Stan Jenkins Date: Sat, 3 Oct 2020 17:42:40 -0400 Subject: [PATCH 299/355] [Jenkins] auto-formatting by clang-format version 6.0.1-14 (tags/RELEASE_601/final) --- stan/math/rev/fun/dot_self.hpp | 67 +++++++++++++++++----------------- 1 file changed, 33 insertions(+), 34 deletions(-) diff --git a/stan/math/rev/fun/dot_self.hpp b/stan/math/rev/fun/dot_self.hpp index 2ff12f65671..6bdc37438b1 100644 --- a/stan/math/rev/fun/dot_self.hpp +++ b/stan/math/rev/fun/dot_self.hpp @@ -12,31 +12,31 @@ namespace stan { namespace math { -namespace internal { -class dot_self_vari : public vari { -protected: - vari** v_; - size_t size_; - -public: - dot_self_vari(vari** v, size_t size) - : vari(Eigen::Map(v, size).val().squaredNorm()), - v_(v), - size_(size) {} - template * = nullptr> - explicit dot_self_vari(const T& v) - : vari(v.val().squaredNorm()), size_(v.size()) { - v_ = reinterpret_cast( - ChainableStack::instance_->memalloc_.alloc(size_ * sizeof(vari*))); - Eigen::Map(v_, v.rows(), v.cols()) = v.vi(); - } - virtual void chain() { - Eigen::Map v_map(v_, size_); - v_map.adj() += adj_ * 2.0 * v_map.val(); - } -}; -} - +namespace internal { +class dot_self_vari : public vari { + protected: + vari** v_; + size_t size_; + + public: + dot_self_vari(vari** v, size_t size) + : vari(Eigen::Map(v, size).val().squaredNorm()), + v_(v), + size_(size) {} + template * = nullptr> + explicit dot_self_vari(const T& v) + : vari(v.val().squaredNorm()), size_(v.size()) { + v_ = reinterpret_cast( + ChainableStack::instance_->memalloc_.alloc(size_ * sizeof(vari*))); + Eigen::Map(v_, v.rows(), v.cols()) = v.vi(); + } + virtual void chain() { + Eigen::Map v_map(v_, size_); + v_map.adj() += adj_ * 2.0 * v_map.val(); + } +}; +} // namespace internal + /** * Returns the dot product of a vector of var with itself. * @@ -64,9 +64,9 @@ inline var dot_self(const T& v) { dot_self/1024/manual_time 2548 ns 19862 ns 275469 */ - //const Eigen::Ref>& v_ref = v; - //return {new internal::dot_self_vari(v_ref)}; - + // const Eigen::Ref>& v_ref = v; + // return {new internal::dot_self_vari(v_ref)}; + /* -------------------------------------------------------------------- Benchmark Time CPU Iterations @@ -83,19 +83,18 @@ inline var dot_self(const T& v) { dot_self/512/manual_time 1277 ns 8948 ns 544405 dot_self/1024/manual_time 2648 ns 21018 ns 267065 */ - + arena_t arena_v = v; var res = arena_v.val().squaredNorm(); reverse_pass_callback([arena_v, res]() { - for(size_t i = 0; i < arena_v.size(); ++i) { + for (size_t i = 0; i < arena_v.size(); ++i) { arena_v.coeffRef(i).adj() += 2.0 * res.adj() * arena_v.coeff(i).val(); } }); return res; - /* -------------------------------------------------------------------- @@ -113,17 +112,17 @@ inline var dot_self(const T& v) { dot_self/512/manual_time 992 ns 9303 ns 703375 dot_self/1024/manual_time 2270 ns 20923 ns 308428 */ - + /* arena_t arena_v = v; auto arena_v_val = to_arena(value_of(arena_v)); var res = arena_v_val.squaredNorm(); - + reverse_pass_callback([arena_v, res, arena_v_val]() mutable { arena_v.adj() += (2.0 * res.adj()) * arena_v_val; }); - + return res; */ } From f5811a292ff803e028c01bee2452ef2f4441ee70 Mon Sep 17 00:00:00 2001 From: Ben Date: Sat, 3 Oct 2020 18:45:21 -0400 Subject: [PATCH 300/355] Switched to memory efficient dot_self (Issue #2018) --- stan/math/rev/fun/dot_self.hpp | 93 ---------------------------------- 1 file changed, 93 deletions(-) diff --git a/stan/math/rev/fun/dot_self.hpp b/stan/math/rev/fun/dot_self.hpp index 2ff12f65671..9f1d2e243a4 100644 --- a/stan/math/rev/fun/dot_self.hpp +++ b/stan/math/rev/fun/dot_self.hpp @@ -12,31 +12,6 @@ namespace stan { namespace math { -namespace internal { -class dot_self_vari : public vari { -protected: - vari** v_; - size_t size_; - -public: - dot_self_vari(vari** v, size_t size) - : vari(Eigen::Map(v, size).val().squaredNorm()), - v_(v), - size_(size) {} - template * = nullptr> - explicit dot_self_vari(const T& v) - : vari(v.val().squaredNorm()), size_(v.size()) { - v_ = reinterpret_cast( - ChainableStack::instance_->memalloc_.alloc(size_ * sizeof(vari*))); - Eigen::Map(v_, v.rows(), v.cols()) = v.vi(); - } - virtual void chain() { - Eigen::Map v_map(v_, size_); - v_map.adj() += adj_ * 2.0 * v_map.val(); - } -}; -} - /** * Returns the dot product of a vector of var with itself. * @@ -47,43 +22,6 @@ class dot_self_vari : public vari { */ template * = nullptr> inline var dot_self(const T& v) { - /* - -------------------------------------------------------------------- - Benchmark Time CPU Iterations - -------------------------------------------------------------------- - toss_me 10126264 ns 10125955 ns 70 - dot_self/2/manual_time 65.2 ns 161 ns 10681302 - dot_self/4/manual_time 66.7 ns 190 ns 10469218 - dot_self/8/manual_time 71.7 ns 260 ns 9693894 - dot_self/16/manual_time 84.3 ns 378 ns 8305816 - dot_self/32/manual_time 121 ns 635 ns 5814113 - dot_self/64/manual_time 186 ns 1119 ns 3757719 - dot_self/128/manual_time 326 ns 2105 ns 2150730 - dot_self/256/manual_time 611 ns 4212 ns 1142432 - dot_self/512/manual_time 1217 ns 8430 ns 574490 - dot_self/1024/manual_time 2548 ns 19862 ns 275469 - */ - - //const Eigen::Ref>& v_ref = v; - //return {new internal::dot_self_vari(v_ref)}; - - /* - -------------------------------------------------------------------- - Benchmark Time CPU Iterations - -------------------------------------------------------------------- - toss_me 10077101 ns 10076684 ns 69 - dot_self/2/manual_time 68.7 ns 164 ns 10057031 - dot_self/4/manual_time 69.2 ns 192 ns 10049326 - dot_self/8/manual_time 74.2 ns 263 ns 9370878 - dot_self/16/manual_time 89.4 ns 385 ns 7810417 - dot_self/32/manual_time 125 ns 671 ns 5615422 - dot_self/64/manual_time 195 ns 1149 ns 3584751 - dot_self/128/manual_time 348 ns 2166 ns 2008505 - dot_self/256/manual_time 651 ns 4508 ns 1069752 - dot_self/512/manual_time 1277 ns 8948 ns 544405 - dot_self/1024/manual_time 2648 ns 21018 ns 267065 - */ - arena_t arena_v = v; var res = arena_v.val().squaredNorm(); @@ -95,37 +33,6 @@ inline var dot_self(const T& v) { }); return res; - - - /* - -------------------------------------------------------------------- - Benchmark Time CPU Iterations - -------------------------------------------------------------------- - toss_me 10161766 ns 10160959 ns 70 - dot_self/2/manual_time 84.7 ns 180 ns 8201199 - dot_self/4/manual_time 85.6 ns 210 ns 8076649 - dot_self/8/manual_time 92.1 ns 286 ns 7451948 - dot_self/16/manual_time 103 ns 422 ns 6857630 - dot_self/32/manual_time 123 ns 675 ns 5680814 - dot_self/64/manual_time 172 ns 1210 ns 4071015 - dot_self/128/manual_time 276 ns 2272 ns 2544438 - dot_self/256/manual_time 505 ns 4629 ns 1384535 - dot_self/512/manual_time 992 ns 9303 ns 703375 - dot_self/1024/manual_time 2270 ns 20923 ns 308428 - */ - - /* - arena_t arena_v = v; - - auto arena_v_val = to_arena(value_of(arena_v)); - var res = arena_v_val.squaredNorm(); - - reverse_pass_callback([arena_v, res, arena_v_val]() mutable { - arena_v.adj() += (2.0 * res.adj()) * arena_v_val; - }); - - return res; - */ } } // namespace math From 67ee415e01be317f680d00435fb3c0be263059c6 Mon Sep 17 00:00:00 2001 From: Ben Date: Sun, 4 Oct 2020 11:02:44 -0400 Subject: [PATCH 301/355] Updated columns_dot_product (Issue #2018) --- stan/math/rev/fun/columns_dot_product.hpp | 62 +++++++++-------------- 1 file changed, 25 insertions(+), 37 deletions(-) diff --git a/stan/math/rev/fun/columns_dot_product.hpp b/stan/math/rev/fun/columns_dot_product.hpp index b4c1b2e5644..d7084e31f81 100644 --- a/stan/math/rev/fun/columns_dot_product.hpp +++ b/stan/math/rev/fun/columns_dot_product.hpp @@ -18,45 +18,33 @@ namespace math { template * = nullptr, require_any_eigen_vt* = nullptr> -inline Eigen::Matrix, 1, Mat1::ColsAtCompileTime> -columns_dot_product(const Mat1& v1, const Mat2& v2) { - check_matching_sizes("columns_dot_product", "v1", v1, "v2", v2); - - ref_type_t v1_ref = v1; - ref_type_t v2_ref = v2; - - arena_matrix> arena_v1_val = value_of(v1_ref); - arena_matrix> arena_v2_val = value_of(v2_ref); - - arena_matrix> arena_v1; - arena_matrix> arena_v2; - - if (!is_constant::value) { - arena_v1 = v1_ref; - } - - if (!is_constant::value) { - arena_v2 = v2_ref; - } +inline auto columns_dot_product(const Mat1& v1, const Mat2& v2) { + using ret_type = promote_scalar_t; + using mat1_var_type = promote_scalar_t; + using mat2_var_type = promote_scalar_t; - Eigen::RowVectorXd out_val(arena_v1_val.cols()); - for (size_t m = 0; m < arena_v1_val.cols(); ++m) - out_val.coeffRef(m) = arena_v1_val.col(m).dot(arena_v2_val.col(m)); - - arena_matrix> out = out_val; - - reverse_pass_callback( - [out, arena_v1, arena_v2, arena_v1_val, arena_v2_val]() mutable { - Eigen::RowVectorXd adj = out.adj(); - - if (!is_constant::value) - arena_v1.adj() += arena_v2_val * adj.asDiagonal(); - - if (!is_constant::value) - arena_v2.adj() += arena_v1_val * adj.asDiagonal(); - }); + check_matching_sizes("columns_dot_product", "v1", v1, "v2", v2); - return out; + auto arena_v1 = to_arena(v1); + auto arena_v2 = to_arena(v2); + + arena_t res = + (arena_v1.val().array() * arena_v2.val().array()).colwise().sum(); + + reverse_pass_callback([res, arena_v1, arena_v2]() mutable { + for(size_t j = 0; j < arena_v1.cols(); ++j) { + for(size_t i = 0; i < arena_v1.rows(); ++i) { + if(!is_constant::value) + forward_as(arena_v1.coeffRef(i, j)).adj() += + value_of(arena_v2.coeff(i, j)) * res.coeff(j).adj(); + if(!is_constant::value) + forward_as(arena_v2.coeffRef(i, j)).adj() += + value_of(arena_v1.coeff(i, j)) * res.coeff(j).adj(); + } + } + }); + + return ret_type(res); } } // namespace math From 079462c0a952e1cc18fa4736aee41f61ca750cdf Mon Sep 17 00:00:00 2001 From: Stan Jenkins Date: Sun, 4 Oct 2020 15:04:09 +0000 Subject: [PATCH 302/355] [Jenkins] auto-formatting by clang-format version 6.0.0-1ubuntu2~16.04.1 (tags/RELEASE_600/final) --- stan/math/rev/fun/columns_dot_product.hpp | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/stan/math/rev/fun/columns_dot_product.hpp b/stan/math/rev/fun/columns_dot_product.hpp index d7084e31f81..aaae3ed793f 100644 --- a/stan/math/rev/fun/columns_dot_product.hpp +++ b/stan/math/rev/fun/columns_dot_product.hpp @@ -28,18 +28,18 @@ inline auto columns_dot_product(const Mat1& v1, const Mat2& v2) { auto arena_v1 = to_arena(v1); auto arena_v2 = to_arena(v2); - arena_t res = - (arena_v1.val().array() * arena_v2.val().array()).colwise().sum(); + arena_t res + = (arena_v1.val().array() * arena_v2.val().array()).colwise().sum(); reverse_pass_callback([res, arena_v1, arena_v2]() mutable { - for(size_t j = 0; j < arena_v1.cols(); ++j) { - for(size_t i = 0; i < arena_v1.rows(); ++i) { - if(!is_constant::value) - forward_as(arena_v1.coeffRef(i, j)).adj() += - value_of(arena_v2.coeff(i, j)) * res.coeff(j).adj(); - if(!is_constant::value) - forward_as(arena_v2.coeffRef(i, j)).adj() += - value_of(arena_v1.coeff(i, j)) * res.coeff(j).adj(); + for (size_t j = 0; j < arena_v1.cols(); ++j) { + for (size_t i = 0; i < arena_v1.rows(); ++i) { + if (!is_constant::value) + forward_as(arena_v1.coeffRef(i, j)).adj() + += value_of(arena_v2.coeff(i, j)) * res.coeff(j).adj(); + if (!is_constant::value) + forward_as(arena_v2.coeffRef(i, j)).adj() + += value_of(arena_v1.coeff(i, j)) * res.coeff(j).adj(); } } }); From 4f3705c1386017faec72ebf852f0d1e754c3d863 Mon Sep 17 00:00:00 2001 From: Ben Date: Sun, 4 Oct 2020 11:40:53 -0400 Subject: [PATCH 303/355] Updated trace_quad_form to three different versions (Issue #2018) --- stan/math/rev/fun/trace_quad_form.hpp | 60 +++++++++++++-------------- 1 file changed, 28 insertions(+), 32 deletions(-) diff --git a/stan/math/rev/fun/trace_quad_form.hpp b/stan/math/rev/fun/trace_quad_form.hpp index 232df072a8f..57bd1ba3845 100644 --- a/stan/math/rev/fun/trace_quad_form.hpp +++ b/stan/math/rev/fun/trace_quad_form.hpp @@ -22,47 +22,43 @@ inline var trace_quad_form(const EigMat1& A, const EigMat2& B) { check_square("trace_quad_form", "A", A); check_multiplicable("trace_quad_form", "A", A, "B", B); - using A_ref_t = ref_type_t; - using B_ref_t = ref_type_t; + const auto& A_ref = to_ref(A); + const auto& B_ref = to_ref(B); - A_ref_t A_ref = A; - B_ref_t B_ref = B; - - arena_matrix> arena_A_val; - arena_matrix> arena_B_val = value_of(B_ref); - - arena_matrix> arena_A; - arena_matrix> arena_B; + auto arena_B_val = to_arena(value_of(B_ref)); + var res; + if(!is_constant::value && !is_constant::value) { + arena_t> arena_A = A_ref; + arena_t> arena_B = B_ref; + auto arena_A_val = to_arena(value_of(arena_A)); - if (!is_constant::value) { - arena_A = A_ref; - } + res = (arena_B_val.transpose() * arena_A_val * arena_B_val).trace(); - if (!is_constant::value) { - arena_B = B_ref; - arena_A_val = value_of(A_ref); - } + reverse_pass_callback([arena_A, arena_B, arena_A_val, arena_B_val, res]() mutable { + arena_A.adj() += res.adj() * arena_B_val * arena_B_val.transpose(); + arena_B.adj() += res.adj() + * (arena_A_val + arena_A_val.transpose()) * arena_B_val; + }); + } else if(!is_constant::value) { + arena_t> arena_A = A_ref; - var res; - - if (is_constant::value) { res = (arena_B_val.transpose() * value_of(A_ref) * arena_B_val).trace(); + + reverse_pass_callback([arena_A, arena_B_val, res]() mutable { + arena_A.adj() += res.adj() * arena_B_val * arena_B_val.transpose(); + }); } else { - res = (arena_B_val.transpose() * arena_A_val * arena_B_val).trace(); - } + arena_t> arena_B = B_ref; + auto arena_A_val = to_arena(value_of(A_ref)); - reverse_pass_callback( - [arena_A, arena_B, arena_A_val, arena_B_val, res]() mutable { - double C_adj = res.adj(); + res = (arena_B_val.transpose() * arena_A_val * arena_B_val).trace(); - if (!is_constant::value) - arena_A.adj() += C_adj * arena_B_val * arena_B_val.transpose(); + reverse_pass_callback([arena_B, arena_A_val, arena_B_val, res]() mutable { + double C_adj = res.adj(); - if (!is_constant::value) - arena_B.adj() += C_adj - * (arena_A_val * arena_B_val - + arena_A_val.transpose() * arena_B_val); - }); + arena_B.adj() += res.adj() * (arena_A_val + arena_A_val.transpose()) * arena_B_val; + }); + } return res; } From 15c9a4765c5237239e12635354eda59a68823356 Mon Sep 17 00:00:00 2001 From: Stan Jenkins Date: Sun, 4 Oct 2020 11:42:06 -0400 Subject: [PATCH 304/355] [Jenkins] auto-formatting by clang-format version 6.0.1-14 (tags/RELEASE_601/final) --- stan/math/rev/fun/trace_quad_form.hpp | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/stan/math/rev/fun/trace_quad_form.hpp b/stan/math/rev/fun/trace_quad_form.hpp index 57bd1ba3845..97a4de956bd 100644 --- a/stan/math/rev/fun/trace_quad_form.hpp +++ b/stan/math/rev/fun/trace_quad_form.hpp @@ -27,19 +27,20 @@ inline var trace_quad_form(const EigMat1& A, const EigMat2& B) { auto arena_B_val = to_arena(value_of(B_ref)); var res; - if(!is_constant::value && !is_constant::value) { + if (!is_constant::value && !is_constant::value) { arena_t> arena_A = A_ref; arena_t> arena_B = B_ref; auto arena_A_val = to_arena(value_of(arena_A)); res = (arena_B_val.transpose() * arena_A_val * arena_B_val).trace(); - reverse_pass_callback([arena_A, arena_B, arena_A_val, arena_B_val, res]() mutable { + reverse_pass_callback([arena_A, arena_B, arena_A_val, arena_B_val, + res]() mutable { arena_A.adj() += res.adj() * arena_B_val * arena_B_val.transpose(); - arena_B.adj() += res.adj() - * (arena_A_val + arena_A_val.transpose()) * arena_B_val; + arena_B.adj() + += res.adj() * (arena_A_val + arena_A_val.transpose()) * arena_B_val; }); - } else if(!is_constant::value) { + } else if (!is_constant::value) { arena_t> arena_A = A_ref; res = (arena_B_val.transpose() * value_of(A_ref) * arena_B_val).trace(); @@ -56,7 +57,8 @@ inline var trace_quad_form(const EigMat1& A, const EigMat2& B) { reverse_pass_callback([arena_B, arena_A_val, arena_B_val, res]() mutable { double C_adj = res.adj(); - arena_B.adj() += res.adj() * (arena_A_val + arena_A_val.transpose()) * arena_B_val; + arena_B.adj() + += res.adj() * (arena_A_val + arena_A_val.transpose()) * arena_B_val; }); } From 7d37479c8a77fba67dad29a2efafc302ecde387d Mon Sep 17 00:00:00 2001 From: Ben Date: Sun, 4 Oct 2020 11:48:51 -0400 Subject: [PATCH 305/355] Updated trace_quad_form (Issue #2018) --- stan/math/rev/fun/trace_quad_form.hpp | 48 +++++++++++++-------------- 1 file changed, 23 insertions(+), 25 deletions(-) diff --git a/stan/math/rev/fun/trace_quad_form.hpp b/stan/math/rev/fun/trace_quad_form.hpp index 57bd1ba3845..004864c5855 100644 --- a/stan/math/rev/fun/trace_quad_form.hpp +++ b/stan/math/rev/fun/trace_quad_form.hpp @@ -25,40 +25,38 @@ inline var trace_quad_form(const EigMat1& A, const EigMat2& B) { const auto& A_ref = to_ref(A); const auto& B_ref = to_ref(B); + arena_matrix> arena_A_val; auto arena_B_val = to_arena(value_of(B_ref)); - var res; - if(!is_constant::value && !is_constant::value) { - arena_t> arena_A = A_ref; - arena_t> arena_B = B_ref; - auto arena_A_val = to_arena(value_of(arena_A)); - res = (arena_B_val.transpose() * arena_A_val * arena_B_val).trace(); + arena_matrix> arena_A; + arena_matrix> arena_B; - reverse_pass_callback([arena_A, arena_B, arena_A_val, arena_B_val, res]() mutable { - arena_A.adj() += res.adj() * arena_B_val * arena_B_val.transpose(); - arena_B.adj() += res.adj() - * (arena_A_val + arena_A_val.transpose()) * arena_B_val; - }); - } else if(!is_constant::value) { - arena_t> arena_A = A_ref; + if (!is_constant::value) { + arena_A = A_ref; + } - res = (arena_B_val.transpose() * value_of(A_ref) * arena_B_val).trace(); + if (!is_constant::value) { + arena_B = B_ref; + arena_A_val = value_of(A_ref); + } - reverse_pass_callback([arena_A, arena_B_val, res]() mutable { - arena_A.adj() += res.adj() * arena_B_val * arena_B_val.transpose(); - }); - } else { - arena_t> arena_B = B_ref; - auto arena_A_val = to_arena(value_of(A_ref)); + var res; + if (is_constant::value) { + res = (arena_B_val.transpose() * value_of(A_ref) * arena_B_val).trace(); + } else { res = (arena_B_val.transpose() * arena_A_val * arena_B_val).trace(); + } - reverse_pass_callback([arena_B, arena_A_val, arena_B_val, res]() mutable { - double C_adj = res.adj(); + reverse_pass_callback( + [arena_A, arena_B, arena_A_val, arena_B_val, res]() mutable { + if (!is_constant::value) + arena_A.adj() += res.adj() * arena_B_val * arena_B_val.transpose(); - arena_B.adj() += res.adj() * (arena_A_val + arena_A_val.transpose()) * arena_B_val; - }); - } + if (!is_constant::value) + arena_B.adj() += res.adj() + * (arena_A_val + arena_A_val.transpose()) * arena_B_val; + }); return res; } From e8e91aa3b22e60ac78e1141be3ce74c70059e0be Mon Sep 17 00:00:00 2001 From: Stan Jenkins Date: Sun, 4 Oct 2020 11:51:35 -0400 Subject: [PATCH 306/355] [Jenkins] auto-formatting by clang-format version 6.0.1-14 (tags/RELEASE_601/final) --- stan/math/rev/fun/trace_quad_form.hpp | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/stan/math/rev/fun/trace_quad_form.hpp b/stan/math/rev/fun/trace_quad_form.hpp index 004864c5855..b4b5bac1d17 100644 --- a/stan/math/rev/fun/trace_quad_form.hpp +++ b/stan/math/rev/fun/trace_quad_form.hpp @@ -48,14 +48,14 @@ inline var trace_quad_form(const EigMat1& A, const EigMat2& B) { res = (arena_B_val.transpose() * arena_A_val * arena_B_val).trace(); } - reverse_pass_callback( - [arena_A, arena_B, arena_A_val, arena_B_val, res]() mutable { - if (!is_constant::value) - arena_A.adj() += res.adj() * arena_B_val * arena_B_val.transpose(); + reverse_pass_callback([arena_A, arena_B, arena_A_val, arena_B_val, + res]() mutable { + if (!is_constant::value) + arena_A.adj() += res.adj() * arena_B_val * arena_B_val.transpose(); - if (!is_constant::value) - arena_B.adj() += res.adj() - * (arena_A_val + arena_A_val.transpose()) * arena_B_val; + if (!is_constant::value) + arena_B.adj() + += res.adj() * (arena_A_val + arena_A_val.transpose()) * arena_B_val; }); return res; From 2c5b4c9b2a4d551386b7f457ac4ae25b48865182 Mon Sep 17 00:00:00 2001 From: Ben Date: Sun, 4 Oct 2020 12:39:33 -0400 Subject: [PATCH 307/355] Update log_softmax (Issue #2018) --- stan/math/rev/fun/log_softmax.hpp | 24 +++++++++++------------- 1 file changed, 11 insertions(+), 13 deletions(-) diff --git a/stan/math/rev/fun/log_softmax.hpp b/stan/math/rev/fun/log_softmax.hpp index 9e97d2ec27b..c5bd3e06d53 100644 --- a/stan/math/rev/fun/log_softmax.hpp +++ b/stan/math/rev/fun/log_softmax.hpp @@ -33,24 +33,22 @@ template * = nullptr> inline auto log_softmax(const T& x) { return apply_vector_unary>::apply( to_ref(x), [](const auto& alpha) { + using ret_type = plain_type_t; + check_nonzero_size("log_softmax", "alpha", alpha); - const auto& alpha_col = as_column_vector_or_scalar(alpha); - const auto& alpha_val = to_ref(value_of(alpha_col)); - const auto& theta = to_ref(alpha_val.array() - alpha_val.maxCoeff()); - arena_matrix res_val - = theta.array() - log(theta.exp().sum()); + auto arena_alpha = to_arena(to_ref(alpha)); + const auto& alpha_val = to_ref(value_of(arena_alpha).array()); + const auto& theta = to_ref(alpha_val - alpha_val.maxCoeff()); - arena_matrix> res = res_val; - auto alpha_arena = to_arena(alpha_col); + arena_t res = theta.array() - log(theta.exp().sum()); - reverse_pass_callback([alpha_arena, res, res_val]() mutable { - const auto& res_adj = to_ref(res.adj()); - alpha_arena.adj() - += res_adj - (res_adj.sum() * res_val.array().exp()).matrix(); - }); + reverse_pass_callback([arena_alpha, res]() mutable { + arena_alpha.adj() + += res.adj() - (res.adj().sum() * res.val().array().exp()).matrix(); + }); - return plain_type_t(res); + return ret_type(res); }); } From 7b3c3f480e132198f01c66932c7a672b7af14c7d Mon Sep 17 00:00:00 2001 From: Stan Jenkins Date: Sun, 4 Oct 2020 12:43:34 -0400 Subject: [PATCH 308/355] [Jenkins] auto-formatting by clang-format version 6.0.1-14 (tags/RELEASE_601/final) --- stan/math/rev/fun/log_softmax.hpp | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/stan/math/rev/fun/log_softmax.hpp b/stan/math/rev/fun/log_softmax.hpp index c5bd3e06d53..db00c5d9387 100644 --- a/stan/math/rev/fun/log_softmax.hpp +++ b/stan/math/rev/fun/log_softmax.hpp @@ -33,20 +33,21 @@ template * = nullptr> inline auto log_softmax(const T& x) { return apply_vector_unary>::apply( to_ref(x), [](const auto& alpha) { - using ret_type = plain_type_t; - + using ret_type = plain_type_t; + check_nonzero_size("log_softmax", "alpha", alpha); auto arena_alpha = to_arena(to_ref(alpha)); - const auto& alpha_val = to_ref(value_of(arena_alpha).array()); - const auto& theta = to_ref(alpha_val - alpha_val.maxCoeff()); + const auto& alpha_val = to_ref(value_of(arena_alpha).array()); + const auto& theta = to_ref(alpha_val - alpha_val.maxCoeff()); arena_t res = theta.array() - log(theta.exp().sum()); reverse_pass_callback([arena_alpha, res]() mutable { arena_alpha.adj() - += res.adj() - (res.adj().sum() * res.val().array().exp()).matrix(); - }); + += res.adj() + - (res.adj().sum() * res.val().array().exp()).matrix(); + }); return ret_type(res); }); From 9bae3f8e2389a26f1bb9f058b282ba341c10fb48 Mon Sep 17 00:00:00 2001 From: Ben Date: Sun, 4 Oct 2020 13:07:48 -0400 Subject: [PATCH 309/355] Updated trace_gen_quad_form (Issue #2018) --- stan/math/rev/fun/trace_gen_quad_form.hpp | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/stan/math/rev/fun/trace_gen_quad_form.hpp b/stan/math/rev/fun/trace_gen_quad_form.hpp index b51de16168d..4adae7e1aad 100644 --- a/stan/math/rev/fun/trace_gen_quad_form.hpp +++ b/stan/math/rev/fun/trace_gen_quad_form.hpp @@ -78,20 +78,23 @@ inline var trace_gen_quad_form(const Td& D, const Ta& A, const Tb& B) { reverse_pass_callback([arena_A, arena_B, arena_D, arena_A_val, arena_B_val, arena_D_val, res]() mutable { double C_adj = res.adj(); + auto BDT = to_ref_if::value> + (arena_B_val * arena_D_val.transpose()); + + auto AB = to_ref_if::value> + (arena_A_val * arena_B_val); if (!is_constant::value) - arena_A.adj() += C_adj * arena_B_val * arena_D_val.transpose() - * arena_B_val.transpose(); + arena_A.adj() += C_adj * BDT * arena_B_val.transpose(); if (!is_constant::value) arena_B.adj() += C_adj - * (arena_A_val * arena_B_val * arena_D_val - + arena_A_val.transpose() * arena_B_val - * arena_D_val.transpose()); + * (AB * arena_D_val + + arena_A_val.transpose() * BDT); if (!is_constant::value) arena_D.adj() - += C_adj * ((arena_A_val * arena_B_val).transpose() * arena_B_val); + += C_adj * (AB.transpose() * arena_B_val); }); return res; From e76f491e289cd317296dc8c97b0207eebdb38a68 Mon Sep 17 00:00:00 2001 From: Ben Date: Sun, 4 Oct 2020 13:15:48 -0400 Subject: [PATCH 310/355] Updated unit_vector_constrain (Issue #2018) --- stan/math/rev/fun/unit_vector_constrain.hpp | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/stan/math/rev/fun/unit_vector_constrain.hpp b/stan/math/rev/fun/unit_vector_constrain.hpp index e424be5008b..d76d9729cd4 100644 --- a/stan/math/rev/fun/unit_vector_constrain.hpp +++ b/stan/math/rev/fun/unit_vector_constrain.hpp @@ -26,26 +26,25 @@ namespace math { * @return Unit length vector of dimension K **/ template * = nullptr> -plain_type_t unit_vector_constrain(const T& y) { +auto unit_vector_constrain(const T& y) { + using ret_type = plain_type_t; + check_vector("unit_vector", "y", y); check_nonzero_size("unit_vector", "y", y); - const auto& y_ref = to_ref(y); - arena_matrix> y_val = value_of(y_ref); - arena_matrix> arena_y = y_ref; + arena_t arena_y = y_ref; + const auto& y_val = to_arena(value_of(arena_y)); const double r = y_val.norm(); const double r_cubed = r * r * r; - arena_matrix> res = y_val / r; + arena_t res = y_val / r; reverse_pass_callback([arena_y, res, r, r_cubed, y_val]() mutable { - const auto& adj = to_ref(res.adj()); - arena_y.adj() - += adj / r - y_val * (y_val.array() * adj.array()).sum() / r_cubed; + += res.adj() / r - y_val * ((y_val.array() * res.adj().array()).sum() / r_cubed); }); - return res; + return ret_type(res); } /** From 96064ae0a993e4c94c44b4a13f5764c889bcf630 Mon Sep 17 00:00:00 2001 From: Stan Jenkins Date: Sun, 4 Oct 2020 13:16:53 -0400 Subject: [PATCH 311/355] [Jenkins] auto-formatting by clang-format version 6.0.1-14 (tags/RELEASE_601/final) --- stan/math/rev/fun/trace_gen_quad_form.hpp | 16 +++++++--------- stan/math/rev/fun/unit_vector_constrain.hpp | 5 +++-- 2 files changed, 10 insertions(+), 11 deletions(-) diff --git a/stan/math/rev/fun/trace_gen_quad_form.hpp b/stan/math/rev/fun/trace_gen_quad_form.hpp index 4adae7e1aad..077b6c89460 100644 --- a/stan/math/rev/fun/trace_gen_quad_form.hpp +++ b/stan/math/rev/fun/trace_gen_quad_form.hpp @@ -78,23 +78,21 @@ inline var trace_gen_quad_form(const Td& D, const Ta& A, const Tb& B) { reverse_pass_callback([arena_A, arena_B, arena_D, arena_A_val, arena_B_val, arena_D_val, res]() mutable { double C_adj = res.adj(); - auto BDT = to_ref_if::value> - (arena_B_val * arena_D_val.transpose()); + auto BDT = to_ref_if::value>( + arena_B_val * arena_D_val.transpose()); - auto AB = to_ref_if::value> - (arena_A_val * arena_B_val); + auto AB + = to_ref_if::value>(arena_A_val * arena_B_val); if (!is_constant::value) arena_A.adj() += C_adj * BDT * arena_B_val.transpose(); if (!is_constant::value) - arena_B.adj() += C_adj - * (AB * arena_D_val - + arena_A_val.transpose() * BDT); + arena_B.adj() + += C_adj * (AB * arena_D_val + arena_A_val.transpose() * BDT); if (!is_constant::value) - arena_D.adj() - += C_adj * (AB.transpose() * arena_B_val); + arena_D.adj() += C_adj * (AB.transpose() * arena_B_val); }); return res; diff --git a/stan/math/rev/fun/unit_vector_constrain.hpp b/stan/math/rev/fun/unit_vector_constrain.hpp index d76d9729cd4..5a28c06b98b 100644 --- a/stan/math/rev/fun/unit_vector_constrain.hpp +++ b/stan/math/rev/fun/unit_vector_constrain.hpp @@ -28,7 +28,7 @@ namespace math { template * = nullptr> auto unit_vector_constrain(const T& y) { using ret_type = plain_type_t; - + check_vector("unit_vector", "y", y); check_nonzero_size("unit_vector", "y", y); @@ -41,7 +41,8 @@ auto unit_vector_constrain(const T& y) { reverse_pass_callback([arena_y, res, r, r_cubed, y_val]() mutable { arena_y.adj() - += res.adj() / r - y_val * ((y_val.array() * res.adj().array()).sum() / r_cubed); + += res.adj() / r + - y_val * ((y_val.array() * res.adj().array()).sum() / r_cubed); }); return ret_type(res); From 42d7ccb842a48ec18b39c7d51d3df8093a2c3396 Mon Sep 17 00:00:00 2001 From: Ben Date: Sun, 4 Oct 2020 13:39:49 -0400 Subject: [PATCH 312/355] Updated mdivide_left (Issue #2018) --- stan/math/rev/fun/mdivide_left.hpp | 36 ++++++++++++++---------------- 1 file changed, 17 insertions(+), 19 deletions(-) diff --git a/stan/math/rev/fun/mdivide_left.hpp b/stan/math/rev/fun/mdivide_left.hpp index a8e93c9839f..f62cae32cf2 100644 --- a/stan/math/rev/fun/mdivide_left.hpp +++ b/stan/math/rev/fun/mdivide_left.hpp @@ -14,22 +14,21 @@ namespace math { template * = nullptr, require_any_vt_var* = nullptr> -inline Eigen::Matrix -mdivide_left(const T1& A, const T2& B) { +inline auto mdivide_left(const T1& A, const T2& B) { + using ret_type = plain_type_t; + check_square("mdivide_left", "A", A); check_multiplicable("mdivide_left", "A", A, "B", B); + if (A.size() == 0) { - return {0, B.cols()}; + return ret_type(0, B.cols()); } - using A_ref_t = ref_type_t; - using B_ref_t = ref_type_t; - - A_ref_t A_ref = A; - B_ref_t B_ref = B; + const auto& A_ref = to_ref(A); + const auto& B_ref = to_ref(B); - arena_matrix> arena_A; - arena_matrix> arena_B; + arena_t> arena_A; + arena_t> arena_B; if (!is_constant::value) { arena_A = A_ref; @@ -39,23 +38,22 @@ mdivide_left(const T1& A, const T2& B) { arena_B = B_ref; } - arena_matrix arena_A_val = value_of(A_ref); - arena_matrix> - res = arena_A_val.colPivHouseholderQr().solve(value_of(B_ref)); + auto arena_A_val = to_arena(value_of(A_ref)); + arena_t + res = arena_A_val.householderQr().solve(value_of(B_ref)); reverse_pass_callback([arena_A, arena_B, arena_A_val, res]() mutable { - Eigen::Matrix adjB - = arena_A_val.transpose().colPivHouseholderQr().solve(res.adj()); + promote_scalar_t adjB + = arena_A_val.transpose().householderQr().solve(res.adj()); if (!is_constant::value) - forward_as>(arena_A).adj() - += -adjB * res.val().transpose().eval(); + arena_A.adj() += -adjB * res.val().transpose().eval(); if (!is_constant::value) - forward_as>(arena_B).adj() += adjB; + arena_B.adj() += adjB; }); - return res; + return ret_type(res); } } // namespace math From 20247893a8797f056276feee6e88553ea43d8064 Mon Sep 17 00:00:00 2001 From: Stan Jenkins Date: Sun, 4 Oct 2020 13:40:54 -0400 Subject: [PATCH 313/355] [Jenkins] auto-formatting by clang-format version 6.0.1-14 (tags/RELEASE_601/final) --- stan/math/rev/fun/mdivide_left.hpp | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/stan/math/rev/fun/mdivide_left.hpp b/stan/math/rev/fun/mdivide_left.hpp index f62cae32cf2..73653c1023c 100644 --- a/stan/math/rev/fun/mdivide_left.hpp +++ b/stan/math/rev/fun/mdivide_left.hpp @@ -16,7 +16,7 @@ template * = nullptr, require_any_vt_var* = nullptr> inline auto mdivide_left(const T1& A, const T2& B) { using ret_type = plain_type_t; - + check_square("mdivide_left", "A", A); check_multiplicable("mdivide_left", "A", A, "B", B); @@ -39,12 +39,11 @@ inline auto mdivide_left(const T1& A, const T2& B) { } auto arena_A_val = to_arena(value_of(A_ref)); - arena_t - res = arena_A_val.householderQr().solve(value_of(B_ref)); + arena_t res = arena_A_val.householderQr().solve(value_of(B_ref)); reverse_pass_callback([arena_A, arena_B, arena_A_val, res]() mutable { promote_scalar_t adjB - = arena_A_val.transpose().householderQr().solve(res.adj()); + = arena_A_val.transpose().householderQr().solve(res.adj()); if (!is_constant::value) arena_A.adj() += -adjB * res.val().transpose().eval(); From 1e25d97c33baca0a347ec107f3d878cc05de995a Mon Sep 17 00:00:00 2001 From: Ben Date: Sun, 4 Oct 2020 14:07:46 -0400 Subject: [PATCH 314/355] Updated mdivide_left_tri (Issue #2018) --- stan/math/rev/fun/mdivide_left_tri.hpp | 31 ++++++++++++-------------- 1 file changed, 14 insertions(+), 17 deletions(-) diff --git a/stan/math/rev/fun/mdivide_left_tri.hpp b/stan/math/rev/fun/mdivide_left_tri.hpp index e3af105357d..1c1c7364f25 100644 --- a/stan/math/rev/fun/mdivide_left_tri.hpp +++ b/stan/math/rev/fun/mdivide_left_tri.hpp @@ -314,19 +314,18 @@ class mdivide_left_tri_vd_vari : public vari { template * = nullptr, require_any_vt_var * = nullptr> -inline Eigen::Matrix -mdivide_left_tri(const T1 &A, const T2 &B) { +inline auto mdivide_left_tri(const T1 &A, const T2 &B) { + using ret_type = promote_scalar_t; + check_square("mdivide_left_tri", "A", A); check_multiplicable("mdivide_left_tri", "A", A, "B", B); + if (A.size() == 0) { - return {0, B.cols()}; + return ret_type(0, B.cols()); } - using A_ref_t = ref_type_t; - using B_ref_t = ref_type_t; - - A_ref_t A_ref = A; - B_ref_t B_ref = B; + const auto& A_ref = to_ref(A); + const auto& B_ref = to_ref(B); arena_matrix> arena_A; arena_matrix> arena_B; @@ -339,27 +338,25 @@ mdivide_left_tri(const T1 &A, const T2 &B) { arena_B = B_ref; } - arena_matrix arena_A_val + arena_t> arena_A_val = value_of(A_ref).template triangularView(); - arena_matrix> - res + arena_t res = arena_A_val.template triangularView().solve(value_of(B_ref)); reverse_pass_callback([arena_A, arena_B, arena_A_val, res]() mutable { - Eigen::Matrix adjB + promote_scalar_t adjB = arena_A_val.template triangularView().transpose().solve( res.adj()); if (!is_constant::value) - forward_as>(arena_B).adj() += adjB; + arena_B.adj() += adjB; if (!is_constant::value) - forward_as>(arena_A).adj() - += (-adjB * res.val().transpose().eval()) - .template triangularView(); + arena_A.adj() -= (adjB * res.val().transpose().eval()) + .template triangularView(); }); - return res; + return ret_type(res); } } // namespace math From 34a0f178112714503e126d1567795b3b3fe3bf95 Mon Sep 17 00:00:00 2001 From: Stan Jenkins Date: Sun, 4 Oct 2020 14:08:52 -0400 Subject: [PATCH 315/355] [Jenkins] auto-formatting by clang-format version 6.0.1-14 (tags/RELEASE_601/final) --- stan/math/rev/fun/mdivide_left_tri.hpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/stan/math/rev/fun/mdivide_left_tri.hpp b/stan/math/rev/fun/mdivide_left_tri.hpp index 1c1c7364f25..7a30e687c0f 100644 --- a/stan/math/rev/fun/mdivide_left_tri.hpp +++ b/stan/math/rev/fun/mdivide_left_tri.hpp @@ -324,8 +324,8 @@ inline auto mdivide_left_tri(const T1 &A, const T2 &B) { return ret_type(0, B.cols()); } - const auto& A_ref = to_ref(A); - const auto& B_ref = to_ref(B); + const auto &A_ref = to_ref(A); + const auto &B_ref = to_ref(B); arena_matrix> arena_A; arena_matrix> arena_B; @@ -353,7 +353,7 @@ inline auto mdivide_left_tri(const T1 &A, const T2 &B) { if (!is_constant::value) arena_A.adj() -= (adjB * res.val().transpose().eval()) - .template triangularView(); + .template triangularView(); }); return ret_type(res); From 6cab8589c549b125b832e6d13f12496fcbd4b5bf Mon Sep 17 00:00:00 2001 From: Ben Date: Sun, 4 Oct 2020 14:26:44 -0400 Subject: [PATCH 316/355] Updated determinant (Issue #2018) --- stan/math/rev/fun/determinant.hpp | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/stan/math/rev/fun/determinant.hpp b/stan/math/rev/fun/determinant.hpp index fdfff839b71..99c669c054a 100644 --- a/stan/math/rev/fun/determinant.hpp +++ b/stan/math/rev/fun/determinant.hpp @@ -20,17 +20,15 @@ inline var determinant(const T& m) { return 1; } - const auto& m_ref = to_ref(m); - const auto& m_val = to_ref(m_ref.val()); - double det_val = m_val.determinant(); - arena_matrix> arena_m - = m_ref; - arena_matrix arena_m_inv_t = m_val.inverse().transpose(); + auto arena_m = to_arena(m); + auto m_lu = arena_m.val().partialPivLu(); + + auto arena_m_inv_transpose = to_arena(m_lu.inverse().transpose()); - var det = det_val; + var det = m_lu.determinant(); - reverse_pass_callback([arena_m, det, arena_m_inv_t]() mutable { - arena_m.adj() += (det.adj() * det.val()) * arena_m_inv_t; + reverse_pass_callback([arena_m, det, arena_m_inv_transpose]() mutable { + arena_m.adj() += (det.adj() * det.val()) * arena_m_inv_transpose; }); return det; From 4848ad88cc15a58fc7940061fd143f4cac153b70 Mon Sep 17 00:00:00 2001 From: Stan Jenkins Date: Sun, 4 Oct 2020 14:28:09 -0400 Subject: [PATCH 317/355] [Jenkins] auto-formatting by clang-format version 6.0.1-14 (tags/RELEASE_601/final) --- stan/math/rev/fun/determinant.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stan/math/rev/fun/determinant.hpp b/stan/math/rev/fun/determinant.hpp index 99c669c054a..e4de0f34dc5 100644 --- a/stan/math/rev/fun/determinant.hpp +++ b/stan/math/rev/fun/determinant.hpp @@ -22,7 +22,7 @@ inline var determinant(const T& m) { auto arena_m = to_arena(m); auto m_lu = arena_m.val().partialPivLu(); - + auto arena_m_inv_transpose = to_arena(m_lu.inverse().transpose()); var det = m_lu.determinant(); From 8d294d6f04dd0f55d772192bb3e90ec4df97b3b6 Mon Sep 17 00:00:00 2001 From: Ben Date: Sun, 4 Oct 2020 14:39:09 -0400 Subject: [PATCH 318/355] Updated trace_gen_inv_quad_form_ldlt (Issue #2018) --- .../rev/fun/trace_gen_inv_quad_form_ldlt.hpp | 28 +++++++++---------- 1 file changed, 13 insertions(+), 15 deletions(-) diff --git a/stan/math/rev/fun/trace_gen_inv_quad_form_ldlt.hpp b/stan/math/rev/fun/trace_gen_inv_quad_form_ldlt.hpp index 3336a284b26..f2cb1ef71b5 100644 --- a/stan/math/rev/fun/trace_gen_inv_quad_form_ldlt.hpp +++ b/stan/math/rev/fun/trace_gen_inv_quad_form_ldlt.hpp @@ -37,23 +37,21 @@ inline var trace_gen_inv_quad_form_ldlt(const Td& D, check_square("trace_gen_inv_quad_form_ldlt", "D", D); check_multiplicable("trace_gen_inv_quad_form_ldlt", "A", A, "B", B); check_multiplicable("trace_gen_inv_quad_form_ldlt", "B", B, "D", D); + if (D.size() == 0 || A.cols() == 0) { return 0; } - using B_ref_t = ref_type_t; - using D_ref_t = ref_type_t; - - B_ref_t B_ref = B; - D_ref_t D_ref = D; + const auto& B_ref = to_ref(B); + const auto& D_ref = to_ref(D); - arena_matrix> arena_B_val = value_of(B_ref); - arena_matrix> arena_D_val; - arena_matrix> AsolveB - = A.solve(arena_B_val); + auto arena_B_val = to_arena(value_of(B_ref)); + arena_t> arena_D_val; + auto AsolveB = to_arena(A.solve(arena_B_val)); + auto BTAsolveB = to_arena(arena_B_val.transpose() * AsolveB); - arena_matrix> arena_B; - arena_matrix> arena_D; + arena_t> arena_B; + arena_t> arena_D; if (!is_constant::value) { arena_B = B_ref; @@ -70,12 +68,12 @@ inline var trace_gen_inv_quad_form_ldlt(const Td& D, var res; if (!is_constant_all::value) { - res = (arena_D_val * arena_B_val.transpose() * AsolveB).trace(); + res = (arena_D_val * BTAsolveB).trace(); } else { - res = (value_of(D) * arena_B_val.transpose() * AsolveB).trace(); + res = (value_of(D) * BTAsolveB).trace(); } - reverse_pass_callback([A, AsolveB, arena_B, arena_D, arena_B_val, arena_D_val, + reverse_pass_callback([A, BTAsolveB, AsolveB, arena_B, arena_D, arena_B_val, arena_D_val, res]() mutable { double C_adj = res.adj(); @@ -89,7 +87,7 @@ inline var trace_gen_inv_quad_form_ldlt(const Td& D, += C_adj * AsolveB * (arena_D_val + arena_D_val.transpose()); if (!is_constant::value) - arena_D.adj() += C_adj * arena_B_val.transpose() * AsolveB; + arena_D.adj() += C_adj * BTAsolveB; }); return res; From afcce6081ef12403e294bf44de357d39980c261d Mon Sep 17 00:00:00 2001 From: Ben Date: Sun, 4 Oct 2020 14:58:22 -0400 Subject: [PATCH 319/355] Updated mdivide_left_spd and mdivide_left (Issue #2018) --- stan/math/rev/fun/mdivide_left.hpp | 2 +- stan/math/rev/fun/mdivide_left_spd.hpp | 37 +++++++++++--------------- 2 files changed, 16 insertions(+), 23 deletions(-) diff --git a/stan/math/rev/fun/mdivide_left.hpp b/stan/math/rev/fun/mdivide_left.hpp index 73653c1023c..43ab72eb7e1 100644 --- a/stan/math/rev/fun/mdivide_left.hpp +++ b/stan/math/rev/fun/mdivide_left.hpp @@ -46,7 +46,7 @@ inline auto mdivide_left(const T1& A, const T2& B) { = arena_A_val.transpose().householderQr().solve(res.adj()); if (!is_constant::value) - arena_A.adj() += -adjB * res.val().transpose().eval(); + arena_A.adj() -= adjB * res.val().transpose().eval(); if (!is_constant::value) arena_B.adj() += adjB; diff --git a/stan/math/rev/fun/mdivide_left_spd.hpp b/stan/math/rev/fun/mdivide_left_spd.hpp index c9c0652fe11..08006935684 100644 --- a/stan/math/rev/fun/mdivide_left_spd.hpp +++ b/stan/math/rev/fun/mdivide_left_spd.hpp @@ -15,21 +15,19 @@ namespace math { template * = nullptr, require_any_vt_var* = nullptr> -inline Eigen::Matrix -mdivide_left_spd(const T1& A, const T2& B) { - check_symmetric("mdivide_left_spd", "A", A); - check_multiplicable("mdivide_left_spd", "A", A, "B", B); +inline auto mdivide_left_spd(const T1& A, const T2& B) { + using ret_type = promote_scalar_t; - using A_ref_t = ref_type_t; - using B_ref_t = ref_type_t; + check_multiplicable("mdivide_left_spd", "A", A, "B", B); - A_ref_t A_ref = A; - B_ref_t B_ref = B; + const auto& A_ref = to_ref(A); + const auto& B_ref = to_ref(B); + check_symmetric("mdivide_left_spd", "A", A_ref); check_not_nan("mdivide_left_spd", "A", A_ref); if (A.size() == 0) { - return {0, B.cols()}; + return ret_type(0, B.cols()); } arena_matrix> arena_A; @@ -44,31 +42,26 @@ mdivide_left_spd(const T1& A, const T2& B) { } auto A_llt = value_of(A_ref).llt(); - check_pos_definite("mdivide_left_spd", "A", A_llt); - arena_matrix arena_A_llt(A.rows(), A.cols()); - arena_A_llt.template triangularView() = A_llt.matrixL(); - arena_A_llt.template triangularView() = arena_A_llt.transpose(); + check_pos_definite("mdivide_left_spd", "A", A_llt); - arena_matrix> - res = A_llt.solve(value_of(B_ref)); + arena_t arena_A_llt = A_llt.matrixL(); + arena_t res = A_llt.solve(value_of(B_ref)); reverse_pass_callback([arena_A, arena_B, arena_A_llt, res]() mutable { - Eigen::Matrix adjB - = res.adj(); + promote_scalar_t adjB = res.adj(); arena_A_llt.template triangularView().solveInPlace(adjB); - arena_A_llt.template triangularView().solveInPlace(adjB); + arena_A_llt.template triangularView().transpose().solveInPlace(adjB); if (!is_constant::value) - forward_as>(arena_A).adj() - += -adjB * res.val().transpose().eval(); + arena_A.adj() -= adjB * res.val().transpose().eval(); if (!is_constant::value) - forward_as>(arena_B).adj() += adjB; + arena_B.adj() += adjB; }); - return res; + return ret_type(res); } } // namespace math From 4ec16f242d616036ee234c63eb569d30aa983002 Mon Sep 17 00:00:00 2001 From: Stan Jenkins Date: Sun, 4 Oct 2020 15:13:42 -0400 Subject: [PATCH 320/355] [Jenkins] auto-formatting by clang-format version 6.0.1-14 (tags/RELEASE_601/final) --- stan/math/rev/fun/mdivide_left_spd.hpp | 4 +++- stan/math/rev/fun/trace_gen_inv_quad_form_ldlt.hpp | 4 ++-- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/stan/math/rev/fun/mdivide_left_spd.hpp b/stan/math/rev/fun/mdivide_left_spd.hpp index 08006935684..4281bf7707b 100644 --- a/stan/math/rev/fun/mdivide_left_spd.hpp +++ b/stan/math/rev/fun/mdivide_left_spd.hpp @@ -52,7 +52,9 @@ inline auto mdivide_left_spd(const T1& A, const T2& B) { promote_scalar_t adjB = res.adj(); arena_A_llt.template triangularView().solveInPlace(adjB); - arena_A_llt.template triangularView().transpose().solveInPlace(adjB); + arena_A_llt.template triangularView() + .transpose() + .solveInPlace(adjB); if (!is_constant::value) arena_A.adj() -= adjB * res.val().transpose().eval(); diff --git a/stan/math/rev/fun/trace_gen_inv_quad_form_ldlt.hpp b/stan/math/rev/fun/trace_gen_inv_quad_form_ldlt.hpp index f2cb1ef71b5..09df71430d0 100644 --- a/stan/math/rev/fun/trace_gen_inv_quad_form_ldlt.hpp +++ b/stan/math/rev/fun/trace_gen_inv_quad_form_ldlt.hpp @@ -73,8 +73,8 @@ inline var trace_gen_inv_quad_form_ldlt(const Td& D, res = (value_of(D) * BTAsolveB).trace(); } - reverse_pass_callback([A, BTAsolveB, AsolveB, arena_B, arena_D, arena_B_val, arena_D_val, - res]() mutable { + reverse_pass_callback([A, BTAsolveB, AsolveB, arena_B, arena_D, arena_B_val, + arena_D_val, res]() mutable { double C_adj = res.adj(); if (!is_constant::value) { From 77478f5808bc6d9804db4c57fa865654b58897cc Mon Sep 17 00:00:00 2001 From: Ben Date: Mon, 5 Oct 2020 09:30:00 -0400 Subject: [PATCH 321/355] Updated gp_periodic_cov (Issue #2018) --- stan/math/rev/fun/gp_periodic_cov.hpp | 34 +++++++++++++++++++-------- 1 file changed, 24 insertions(+), 10 deletions(-) diff --git a/stan/math/rev/fun/gp_periodic_cov.hpp b/stan/math/rev/fun/gp_periodic_cov.hpp index 02d998635b1..53ba8cfde8a 100644 --- a/stan/math/rev/fun/gp_periodic_cov.hpp +++ b/stan/math/rev/fun/gp_periodic_cov.hpp @@ -10,7 +10,6 @@ #include #include #include -#include #include #include #include @@ -43,8 +42,10 @@ namespace math { template * = nullptr, require_any_st_var* = nullptr> -Eigen::Matrix gp_periodic_cov( +inline auto gp_periodic_cov( const std::vector& x, T_sigma sigma, T_l l, T_p p) { + using ret_type = promote_scalar_t; + const char* fun = "gp_periodic_cov"; check_positive(fun, "signal standard deviation", sigma); @@ -67,10 +68,11 @@ Eigen::Matrix gp_periodic_cov( size_t N = x.size(); size_t P = (N * N - N) / 2 + N; - arena_matrix arena_dist(P); - arena_matrix arena_sin_squared(P); - arena_matrix arena_sin_squared_derivative(P); - arena_matrix> arena_res(P); + + arena_t arena_dist(P); + arena_t arena_sin_squared(P); + arena_t arena_sin_squared_derivative(P); + arena_t> arena_res(P); auto arena_x = to_arena_if::value>(x); @@ -79,7 +81,15 @@ Eigen::Matrix gp_periodic_cov( for (size_t j = 0; j < N; ++j) { for (size_t i = 0; i <= j; ++i) { if (i != j) { - arena_dist.coeffRef(pos) = distance(value_of(x[i]), value_of(x[j])); + if(is_stan_scalar::value) + arena_dist.coeffRef(pos) = std::abs(forward_as(value_of(x[i])) - + forward_as(value_of(x[j]))); + else if(is_eigen_col_vector::value) + arena_dist.coeffRef(pos) = + forward_as(value_of(x[i]) - value_of(x[j])).norm(); + else if(is_eigen_row_vector::value) + arena_dist.coeffRef(pos) = + forward_as(value_of(x[i]) - value_of(x[j])).norm(); double sine = sin(pi_over_p * arena_dist.coeff(pos)); double cosine = cos(pi_over_p * arena_dist.coeff(pos)); @@ -103,7 +113,7 @@ Eigen::Matrix gp_periodic_cov( } } - Eigen::Matrix res(N, N); + arena_t res(N, N); pos = 0; for (size_t j = 0; j < N; ++j) @@ -112,9 +122,13 @@ Eigen::Matrix gp_periodic_cov( pos++; } - reverse_pass_callback([arena_res, arena_x, sigma, l, p, sigma_d, l_d, p_d, N, + reverse_pass_callback([arena_res, arena_x, sigma, l, p, N, pi_over_p, arena_dist, arena_sin_squared, arena_sin_squared_derivative]() mutable { + double sigma_d = value_of(sigma); + double l_d = value_of(l); + double p_d = value_of(p); + double sigma_adj = 0.0; double l_adj = 0.0; double p_adj = 0.0; @@ -158,7 +172,7 @@ Eigen::Matrix gp_periodic_cov( forward_as(p).adj() += 2 * pi() * p_adj / (p_d * p_d * l_d * l_d); }); - return res; + return ret_type(res); } } // namespace math From 6225297f077c3444fc54749c2491bddc703b8086 Mon Sep 17 00:00:00 2001 From: Stan Jenkins Date: Mon, 5 Oct 2020 09:35:01 -0400 Subject: [PATCH 322/355] [Jenkins] auto-formatting by clang-format version 6.0.1-14 (tags/RELEASE_601/final) --- stan/math/rev/fun/gp_periodic_cov.hpp | 31 +++++++++++++++------------ 1 file changed, 17 insertions(+), 14 deletions(-) diff --git a/stan/math/rev/fun/gp_periodic_cov.hpp b/stan/math/rev/fun/gp_periodic_cov.hpp index 53ba8cfde8a..36df86c856c 100644 --- a/stan/math/rev/fun/gp_periodic_cov.hpp +++ b/stan/math/rev/fun/gp_periodic_cov.hpp @@ -42,8 +42,8 @@ namespace math { template * = nullptr, require_any_st_var* = nullptr> -inline auto gp_periodic_cov( - const std::vector& x, T_sigma sigma, T_l l, T_p p) { +inline auto gp_periodic_cov(const std::vector& x, T_sigma sigma, T_l l, + T_p p) { using ret_type = promote_scalar_t; const char* fun = "gp_periodic_cov"; @@ -81,15 +81,18 @@ inline auto gp_periodic_cov( for (size_t j = 0; j < N; ++j) { for (size_t i = 0; i <= j; ++i) { if (i != j) { - if(is_stan_scalar::value) - arena_dist.coeffRef(pos) = std::abs(forward_as(value_of(x[i])) - - forward_as(value_of(x[j]))); - else if(is_eigen_col_vector::value) - arena_dist.coeffRef(pos) = - forward_as(value_of(x[i]) - value_of(x[j])).norm(); - else if(is_eigen_row_vector::value) - arena_dist.coeffRef(pos) = - forward_as(value_of(x[i]) - value_of(x[j])).norm(); + if (is_stan_scalar::value) + arena_dist.coeffRef(pos) + = std::abs(forward_as(value_of(x[i])) + - forward_as(value_of(x[j]))); + else if (is_eigen_col_vector::value) + arena_dist.coeffRef(pos) + = forward_as(value_of(x[i]) - value_of(x[j])) + .norm(); + else if (is_eigen_row_vector::value) + arena_dist.coeffRef(pos) + = forward_as(value_of(x[i]) - value_of(x[j])) + .norm(); double sine = sin(pi_over_p * arena_dist.coeff(pos)); double cosine = cos(pi_over_p * arena_dist.coeff(pos)); @@ -122,13 +125,13 @@ inline auto gp_periodic_cov( pos++; } - reverse_pass_callback([arena_res, arena_x, sigma, l, p, N, - pi_over_p, arena_dist, arena_sin_squared, + reverse_pass_callback([arena_res, arena_x, sigma, l, p, N, pi_over_p, + arena_dist, arena_sin_squared, arena_sin_squared_derivative]() mutable { double sigma_d = value_of(sigma); double l_d = value_of(l); double p_d = value_of(p); - + double sigma_adj = 0.0; double l_adj = 0.0; double p_adj = 0.0; From 0c81c0536110b2bced8470bca63538b8ad37e4a2 Mon Sep 17 00:00:00 2001 From: Ben Date: Mon, 5 Oct 2020 09:36:06 -0400 Subject: [PATCH 323/355] Updated sd (Issue #2018) --- stan/math/rev/fun/sd.hpp | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/stan/math/rev/fun/sd.hpp b/stan/math/rev/fun/sd.hpp index 5743d5a89c9..13ef44849cb 100644 --- a/stan/math/rev/fun/sd.hpp +++ b/stan/math/rev/fun/sd.hpp @@ -28,6 +28,7 @@ namespace math { template * = nullptr> var sd(const T& m) { check_nonzero_size("sd", "m", m); + if (m.size() == 1) { return 0; } @@ -35,14 +36,12 @@ var sd(const T& m) { const auto& m_ref = to_ref(m); return apply_vector_unary::reduce(m_ref, [](const auto& x) { - const auto& x_ref = to_ref(x); - arena_t arena_x = x_ref; - const auto& x_val = to_ref(value_of(x)); - double mean = x_val.mean(); - arena_matrix> arena_diff - = x_val.array() - mean; + auto arena_x = to_arena(x); + const auto& x_val = to_ref(value_of(arena_x)); + + auto arena_diff = to_arena((x_val.array() - x_val.mean()).matrix()); double sum_of_squares = arena_diff.squaredNorm(); - double sd = sqrt(sum_of_squares / (x.size() - 1)); + double sd = std::sqrt(sum_of_squares / (x.size() - 1)); var res = sd; From 821561aafd5ddf8e912859fc06874ca27c384675 Mon Sep 17 00:00:00 2001 From: Ben Date: Mon, 5 Oct 2020 10:02:12 -0400 Subject: [PATCH 324/355] Updated divide (Issue #2018) --- stan/math/rev/fun/divide.hpp | 30 +++++++++++------------------- 1 file changed, 11 insertions(+), 19 deletions(-) diff --git a/stan/math/rev/fun/divide.hpp b/stan/math/rev/fun/divide.hpp index bdd06768543..fde34304841 100644 --- a/stan/math/rev/fun/divide.hpp +++ b/stan/math/rev/fun/divide.hpp @@ -23,30 +23,22 @@ namespace math { template * = nullptr, require_stan_scalar_t* = nullptr, require_any_st_var* = nullptr> -inline Eigen::Matrix -divide(const Mat& m, const Scal& c) { +inline auto divide(const Mat& m, const Scal& c) { + using ret_type = promote_scalar_t; + const auto& m_ref = to_ref(m); - const auto& c_ref = to_ref(c); auto arena_m = to_arena_if::value>(m_ref); - double invc = 1.0 / value_of(c_ref); + double invc = 1.0 / value_of(c); - using Mat_d = promote_scalar_t; - using Mat_v = promote_scalar_t; - - arena_t res_val = invc * value_of(m_ref); - arena_t res = res_val; - - reverse_pass_callback([arena_m, c, res, res_val, invc]() mutable { - const auto& adj = to_ref(res.adj()); - - if (!is_constant::value) { - forward_as(arena_m).adj() += invc * adj; - } - if (!is_constant::value) { - forward_as(c).adj() += -invc * (adj.array() * res_val.array()).sum(); - } + arena_t res = invc * value_of(m_ref); + reverse_pass_callback([arena_m, c, res, invc]() mutable { + if(!is_constant::value) + forward_as(arena_m).adj() += invc * res.adj(); + if(!is_constant::value) + forward_as(c).adj() -= + invc * (res.adj().array() * res.val().array()).sum(); }); return res; From 2cd7f652fa049567c1d2f6c9376c015794a4e4c8 Mon Sep 17 00:00:00 2001 From: Stan Jenkins Date: Mon, 5 Oct 2020 14:08:08 +0000 Subject: [PATCH 325/355] [Jenkins] auto-formatting by clang-format version 6.0.0-1ubuntu2~16.04.1 (tags/RELEASE_600/final) --- stan/math/rev/fun/divide.hpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/stan/math/rev/fun/divide.hpp b/stan/math/rev/fun/divide.hpp index fde34304841..1f4249be8d2 100644 --- a/stan/math/rev/fun/divide.hpp +++ b/stan/math/rev/fun/divide.hpp @@ -25,7 +25,7 @@ template * = nullptr, require_any_st_var* = nullptr> inline auto divide(const Mat& m, const Scal& c) { using ret_type = promote_scalar_t; - + const auto& m_ref = to_ref(m); auto arena_m = to_arena_if::value>(m_ref); @@ -34,11 +34,11 @@ inline auto divide(const Mat& m, const Scal& c) { arena_t res = invc * value_of(m_ref); reverse_pass_callback([arena_m, c, res, invc]() mutable { - if(!is_constant::value) + if (!is_constant::value) forward_as(arena_m).adj() += invc * res.adj(); - if(!is_constant::value) - forward_as(c).adj() -= - invc * (res.adj().array() * res.val().array()).sum(); + if (!is_constant::value) + forward_as(c).adj() + -= invc * (res.adj().array() * res.val().array()).sum(); }); return res; From cd6168fa2ba771dbe88a59e4f43cffadf0a0b781 Mon Sep 17 00:00:00 2001 From: Ben Date: Mon, 5 Oct 2020 12:51:02 -0400 Subject: [PATCH 326/355] Updated ordered_constrain, eigenvalues_sym, eigenvectors_sym (Issue #2018) --- stan/math/prim/fun/ordered_constrain.hpp | 4 ++- stan/math/rev/fun/eigenvalues_sym.hpp | 23 +++++++-------- stan/math/rev/fun/eigenvectors_sym.hpp | 36 +++++++++++------------- stan/math/rev/fun/ordered_constrain.hpp | 29 ++++++++++--------- 4 files changed, 47 insertions(+), 45 deletions(-) diff --git a/stan/math/prim/fun/ordered_constrain.hpp b/stan/math/prim/fun/ordered_constrain.hpp index 959b749ae35..a5c91fd37ae 100644 --- a/stan/math/prim/fun/ordered_constrain.hpp +++ b/stan/math/prim/fun/ordered_constrain.hpp @@ -19,7 +19,9 @@ namespace math { * @return Positive, increasing ordered vector. * @tparam T Type of scalar. */ -template * = nullptr> +template * = nullptr, + require_not_st_var* = nullptr> plain_type_t ordered_constrain(const EigVec& x) { using Eigen::Dynamic; using Eigen::Matrix; diff --git a/stan/math/rev/fun/eigenvalues_sym.hpp b/stan/math/rev/fun/eigenvalues_sym.hpp index bd3418de4e0..e21da71a5e9 100644 --- a/stan/math/rev/fun/eigenvalues_sym.hpp +++ b/stan/math/rev/fun/eigenvalues_sym.hpp @@ -25,19 +25,20 @@ namespace math { * @return Eigenvalues of matrix. */ template * = nullptr> -inline Eigen::Matrix eigenvalues_sym(const T& m) { - const auto& m_ref = to_ref(m); - arena_matrix> arena_m - = m_ref; - check_square("eigenvalues_sym", "m", m_ref); - Eigen::MatrixXd m_val = value_of(m_ref); - check_nonzero_size("eigenvalues_sym", "m", m_val); +inline auto eigenvalues_sym(const T& m) { + using ret_type = promote_scalar_t; + + check_square("eigenvalues_sym", "m", m); + check_nonzero_size("eigenvalues_sym", "m", m); + + auto arena_m = to_arena(m); + Eigen::MatrixXd m_val = value_of(arena_m); + check_symmetric("eigenvalues_sym", "m", m_val); Eigen::SelfAdjointEigenSolver solver(m_val); - arena_matrix> eigenvalues - = solver.eigenvalues(); - arena_matrix arena_eigenvectors_val = solver.eigenvectors(); + arena_t eigenvalues = solver.eigenvalues(); + auto arena_eigenvectors_val = to_arena(solver.eigenvectors()); reverse_pass_callback( [arena_m, arena_eigenvectors_val, eigenvalues]() mutable { @@ -45,7 +46,7 @@ inline Eigen::Matrix eigenvalues_sym(const T& m) { * arena_eigenvectors_val.transpose(); }); - return eigenvalues; + return ret_type(eigenvalues); } } // namespace math diff --git a/stan/math/rev/fun/eigenvectors_sym.hpp b/stan/math/rev/fun/eigenvectors_sym.hpp index 85b5350e1ab..d2b5790d7e7 100644 --- a/stan/math/rev/fun/eigenvectors_sym.hpp +++ b/stan/math/rev/fun/eigenvectors_sym.hpp @@ -23,35 +23,33 @@ namespace math { * @return Eigenvectors of matrix */ template * = nullptr> -inline Eigen::Matrix eigenvectors_sym( - const T& m) { - const auto& m_ref = to_ref(m); - arena_matrix> arena_m - = m_ref; - check_square("eigenvalues_sym", "m", m_ref); - Eigen::MatrixXd m_val = value_of(m_ref); - check_nonzero_size("eigenvalues_sym", "m", m_val); +inline auto eigenvectors_sym(const T& m) { + using ret_type = promote_scalar_t; + + check_square("eigenvalues_sym", "m", m); + check_nonzero_size("eigenvalues_sym", "m", m); + + auto arena_m = to_arena(m); + Eigen::MatrixXd m_val = value_of(arena_m); + check_symmetric("eigenvalues_sym", "m", m_val); Eigen::SelfAdjointEigenSolver solver(m_val); - arena_matrix arena_eigenvectors_val = solver.eigenvectors(); - arena_matrix> res - = arena_eigenvectors_val; - + auto arena_eigenvectors_val = to_arena(solver.eigenvectors()); + arena_t res = arena_eigenvectors_val; + int M = m_val.rows(); - arena_matrix arena_f(M, M); + arena_t arena_f(M, M); for (int i = 0; i < M; i++) for (int j = 0; j < M; j++) arena_f.coeffRef(j, i) = (i != j ? 1 - / (solver.eigenvalues().coeff(i) - - solver.eigenvalues().coeff(j)) - : 0); + / (solver.eigenvalues().coeff(i) + - solver.eigenvalues().coeff(j)) + : 0); reverse_pass_callback([arena_m, arena_eigenvectors_val, arena_f, res]() mutable { - Eigen::MatrixXd adj = res.adj(); - Eigen::MatrixXd adj2 = arena_eigenvectors_val.transpose() * adj; - Eigen::MatrixXd tmp = arena_f.cwiseProduct(adj2); + Eigen::MatrixXd tmp = arena_f.cwiseProduct(arena_eigenvectors_val.transpose().eval() * res.adj_op()); arena_m.adj() += arena_eigenvectors_val * tmp * arena_eigenvectors_val.transpose(); }); diff --git a/stan/math/rev/fun/ordered_constrain.hpp b/stan/math/rev/fun/ordered_constrain.hpp index 4f5f16ceeed..f9b48d72c2e 100644 --- a/stan/math/rev/fun/ordered_constrain.hpp +++ b/stan/math/rev/fun/ordered_constrain.hpp @@ -21,8 +21,11 @@ namespace math { * @param x Free vector of scalars * @return Increasing ordered vector */ -inline Eigen::Matrix ordered_constrain( - const Eigen::Matrix& x) { +template * = nullptr> +inline auto ordered_constrain(const T& x) { + using ret_type = plain_type_t; + using std::exp; size_t N = x.size(); @@ -31,30 +34,28 @@ inline Eigen::Matrix ordered_constrain( } Eigen::VectorXd y_val(N); - arena_matrix exp_x(N - 1); + arena_t arena_x = x; + arena_t exp_x(N - 1); y_val.coeffRef(0) = value_of(x.coeff(0)); for (int n = 1; n < N; ++n) { - exp_x.coeffRef(n - 1) = exp(value_of(x.coeff(n))); + exp_x.coeffRef(n - 1) = exp(value_of(arena_x.coeff(n))); y_val.coeffRef(n) = y_val.coeff(n - 1) + exp_x.coeff(n - 1); } - arena_matrix> y = y_val; - arena_matrix> arena_x = x; + arena_t y = y_val; - reverse_pass_callback([=]() mutable { + reverse_pass_callback([arena_x, y, exp_x]() mutable { double rolling_adjoint_sum = 0.0; - if (N > 0) { - for (int n = N - 1; n > 0; --n) { - rolling_adjoint_sum += y.adj().coeff(n); - arena_x.adj().coeffRef(n) += exp_x.coeff(n - 1) * rolling_adjoint_sum; - } - arena_x.adj().coeffRef(0) += rolling_adjoint_sum + y.adj().coeff(0); + for (int n = arena_x.size() - 1; n > 0; --n) { + rolling_adjoint_sum += y.adj().coeff(n); + arena_x.adj().coeffRef(n) += exp_x.coeff(n - 1) * rolling_adjoint_sum; } + arena_x.adj().coeffRef(0) += rolling_adjoint_sum + y.adj().coeff(0); }); - return y; + return ret_type(y); } } // namespace math From e3fbee94afe349b1a8873ce7a57f717906dc3e8c Mon Sep 17 00:00:00 2001 From: Stan Jenkins Date: Mon, 5 Oct 2020 16:53:57 +0000 Subject: [PATCH 327/355] [Jenkins] auto-formatting by clang-format version 6.0.0-1ubuntu2~16.04.1 (tags/RELEASE_600/final) --- stan/math/prim/fun/ordered_constrain.hpp | 5 ++--- stan/math/rev/fun/eigenvalues_sym.hpp | 2 +- stan/math/rev/fun/eigenvectors_sym.hpp | 13 +++++++------ stan/math/rev/fun/ordered_constrain.hpp | 5 ++--- 4 files changed, 12 insertions(+), 13 deletions(-) diff --git a/stan/math/prim/fun/ordered_constrain.hpp b/stan/math/prim/fun/ordered_constrain.hpp index a5c91fd37ae..864d1a62595 100644 --- a/stan/math/prim/fun/ordered_constrain.hpp +++ b/stan/math/prim/fun/ordered_constrain.hpp @@ -19,9 +19,8 @@ namespace math { * @return Positive, increasing ordered vector. * @tparam T Type of scalar. */ -template * = nullptr, - require_not_st_var* = nullptr> +template * = nullptr, + require_not_st_var* = nullptr> plain_type_t ordered_constrain(const EigVec& x) { using Eigen::Dynamic; using Eigen::Matrix; diff --git a/stan/math/rev/fun/eigenvalues_sym.hpp b/stan/math/rev/fun/eigenvalues_sym.hpp index e21da71a5e9..708d1410cd7 100644 --- a/stan/math/rev/fun/eigenvalues_sym.hpp +++ b/stan/math/rev/fun/eigenvalues_sym.hpp @@ -30,7 +30,7 @@ inline auto eigenvalues_sym(const T& m) { check_square("eigenvalues_sym", "m", m); check_nonzero_size("eigenvalues_sym", "m", m); - + auto arena_m = to_arena(m); Eigen::MatrixXd m_val = value_of(arena_m); diff --git a/stan/math/rev/fun/eigenvectors_sym.hpp b/stan/math/rev/fun/eigenvectors_sym.hpp index d2b5790d7e7..aeb0c660c30 100644 --- a/stan/math/rev/fun/eigenvectors_sym.hpp +++ b/stan/math/rev/fun/eigenvectors_sym.hpp @@ -28,7 +28,7 @@ inline auto eigenvectors_sym(const T& m) { check_square("eigenvalues_sym", "m", m); check_nonzero_size("eigenvalues_sym", "m", m); - + auto arena_m = to_arena(m); Eigen::MatrixXd m_val = value_of(arena_m); @@ -37,19 +37,20 @@ inline auto eigenvectors_sym(const T& m) { Eigen::SelfAdjointEigenSolver solver(m_val); auto arena_eigenvectors_val = to_arena(solver.eigenvectors()); arena_t res = arena_eigenvectors_val; - + int M = m_val.rows(); arena_t arena_f(M, M); for (int i = 0; i < M; i++) for (int j = 0; j < M; j++) arena_f.coeffRef(j, i) = (i != j ? 1 - / (solver.eigenvalues().coeff(i) - - solver.eigenvalues().coeff(j)) - : 0); + / (solver.eigenvalues().coeff(i) + - solver.eigenvalues().coeff(j)) + : 0); reverse_pass_callback([arena_m, arena_eigenvectors_val, arena_f, res]() mutable { - Eigen::MatrixXd tmp = arena_f.cwiseProduct(arena_eigenvectors_val.transpose().eval() * res.adj_op()); + Eigen::MatrixXd tmp = arena_f.cwiseProduct( + arena_eigenvectors_val.transpose().eval() * res.adj_op()); arena_m.adj() += arena_eigenvectors_val * tmp * arena_eigenvectors_val.transpose(); }); diff --git a/stan/math/rev/fun/ordered_constrain.hpp b/stan/math/rev/fun/ordered_constrain.hpp index f9b48d72c2e..70ccc532180 100644 --- a/stan/math/rev/fun/ordered_constrain.hpp +++ b/stan/math/rev/fun/ordered_constrain.hpp @@ -21,11 +21,10 @@ namespace math { * @param x Free vector of scalars * @return Increasing ordered vector */ -template * = nullptr> +template * = nullptr> inline auto ordered_constrain(const T& x) { using ret_type = plain_type_t; - + using std::exp; size_t N = x.size(); From 0538fd9984c1fe6726e298ca6dd6c4453843df63 Mon Sep 17 00:00:00 2001 From: Ben Date: Mon, 5 Oct 2020 13:03:55 -0400 Subject: [PATCH 328/355] Updated log_sum_exp (Issue #2018) --- stan/math/rev/fun/log_sum_exp.hpp | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/stan/math/rev/fun/log_sum_exp.hpp b/stan/math/rev/fun/log_sum_exp.hpp index f2a5f88d59c..2bd330400e8 100644 --- a/stan/math/rev/fun/log_sum_exp.hpp +++ b/stan/math/rev/fun/log_sum_exp.hpp @@ -28,12 +28,11 @@ template * = nullptr, require_any_var_t* = nullptr> inline var log_sum_exp(const T1& a, const T2& b) { - double val_a = value_of(a); - double val_b = value_of(b); - double diff = val_a - val_b; - var res = log_sum_exp(val_a, val_b); + var res = log_sum_exp(value_of(a), value_of(b)); + + reverse_pass_callback([a, b, res]() mutable { + double diff = value_of(a) - value_of(b); - reverse_pass_callback([a, b, diff, res]() mutable { if (!is_constant::value) forward_as(a).adj() += res.adj() * inv_logit(diff); @@ -52,12 +51,12 @@ inline var log_sum_exp(const T1& a, const T2& b) { */ template * = nullptr> inline auto log_sum_exp(const T& x) { - return apply_vector_unary::reduce(x, [](const auto& v) { - const auto& v_ref = to_ref(v); + const auto& x_ref = to_ref(x); + return apply_vector_unary::reduce(x_ref, [](const auto& v) { + auto arena_v = to_arena(v); - auto arena_v_val = to_arena(value_of(v_ref)); + auto arena_v_val = to_arena(value_of(arena_v)); var res = log_sum_exp(arena_v_val); - auto arena_v = to_arena(v_ref); reverse_pass_callback([arena_v, arena_v_val, res]() mutable { arena_v.adj() From 2d11682ec5f0a956ca07539f4def89a0edbcfb2f Mon Sep 17 00:00:00 2001 From: Ben Date: Mon, 5 Oct 2020 13:15:53 -0400 Subject: [PATCH 329/355] Updated columns_dot_product (Issue #2018) --- stan/math/rev/fun/columns_dot_product.hpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/stan/math/rev/fun/columns_dot_product.hpp b/stan/math/rev/fun/columns_dot_product.hpp index aaae3ed793f..0684d36834e 100644 --- a/stan/math/rev/fun/columns_dot_product.hpp +++ b/stan/math/rev/fun/columns_dot_product.hpp @@ -20,8 +20,6 @@ template * = nullptr> inline auto columns_dot_product(const Mat1& v1, const Mat2& v2) { using ret_type = promote_scalar_t; - using mat1_var_type = promote_scalar_t; - using mat2_var_type = promote_scalar_t; check_matching_sizes("columns_dot_product", "v1", v1, "v2", v2); From 399d260bd4cb3dcb55d4fbc49da3e1bf480ed92b Mon Sep 17 00:00:00 2001 From: Ben Date: Mon, 5 Oct 2020 13:17:13 -0400 Subject: [PATCH 330/355] Updated log_determinant_ldlt (Issue #2018) --- stan/math/rev/fun/log_determinant_ldlt.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stan/math/rev/fun/log_determinant_ldlt.hpp b/stan/math/rev/fun/log_determinant_ldlt.hpp index a7ce5a64d1e..c37087d41de 100644 --- a/stan/math/rev/fun/log_determinant_ldlt.hpp +++ b/stan/math/rev/fun/log_determinant_ldlt.hpp @@ -29,7 +29,7 @@ var log_determinant_ldlt(const LDLT_factor &A) { var log_det = A.alloc_->log_abs_det(); - arena_matrix> arena_A_inv(A.rows(), A.cols()); + arena_t> arena_A_inv(A.rows(), A.cols()); arena_A_inv.setIdentity(); A.alloc_->ldlt_.solveInPlace(arena_A_inv); From fba227645bac2333437143c7948227c691b368da Mon Sep 17 00:00:00 2001 From: Ben Date: Mon, 5 Oct 2020 13:33:08 -0400 Subject: [PATCH 331/355] Updated log_determinant (Issue #2018) --- stan/math/rev/fun/log_determinant.hpp | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/stan/math/rev/fun/log_determinant.hpp b/stan/math/rev/fun/log_determinant.hpp index bc122170c60..331a68ff713 100644 --- a/stan/math/rev/fun/log_determinant.hpp +++ b/stan/math/rev/fun/log_determinant.hpp @@ -16,23 +16,21 @@ namespace math { template * = nullptr> inline var log_determinant(const T& m) { check_square("determinant", "m", m); + if (m.size() == 0) { return 0.0; } - const auto& m_ref = to_ref(m); + arena_t arena_m = m; - Eigen::FullPivHouseholderQR>> hh - = m_ref.val().fullPivHouseholderQr(); + auto m_lu = arena_m.val().partialPivLu(); - arena_matrix> arena_m - = m_ref; - arena_matrix arena_hh_inv_t = hh.inverse().transpose(); + auto arena_m_inv_transpose = to_arena(m_lu.inverse().transpose()); - var log_det = hh.logAbsDeterminant(); + var log_det = std::log(std::abs(m_lu.determinant())); - reverse_pass_callback([arena_m, log_det, arena_hh_inv_t]() mutable { - arena_m.adj() += log_det.adj() * arena_hh_inv_t; + reverse_pass_callback([arena_m, log_det, arena_m_inv_transpose]() mutable { + arena_m.adj() += log_det.adj() * arena_m_inv_transpose; }); return log_det; From 1ffe0f0f8173f9bb2c49964366951d14d889a811 Mon Sep 17 00:00:00 2001 From: Ben Date: Mon, 5 Oct 2020 13:38:09 -0400 Subject: [PATCH 332/355] Updated inverse (Issue #2018) --- stan/math/rev/fun/inverse.hpp | 22 ++++++++++++---------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/stan/math/rev/fun/inverse.hpp b/stan/math/rev/fun/inverse.hpp index 99ca899b13d..e164f863386 100644 --- a/stan/math/rev/fun/inverse.hpp +++ b/stan/math/rev/fun/inverse.hpp @@ -23,23 +23,25 @@ namespace math { * @throw std::invalid_argument if the matrix is not square. */ template * = nullptr> -inline Eigen::Matrix inverse(const T& m) { +inline auto inverse(const T& m) { + using ret_type = plain_type_t; + check_square("inverse", "m", m); + if (m.size() == 0) { - return {}; + return ret_type(0, 0); } - arena_matrix> arena_m = m; - arena_matrix res_val = value_of(arena_m).inverse(); - arena_matrix> res - = res_val; + arena_t arena_m = m; + auto arena_m_inv = to_arena(value_of(arena_m).inverse()); + arena_t res = arena_m_inv; - reverse_pass_callback([res, res_val, arena_m]() mutable { - Eigen::MatrixXd res_adj = res.adj(); - arena_m.adj() -= res_val.transpose() * res_adj * res_val.transpose(); + reverse_pass_callback([res, arena_m_inv, arena_m]() mutable { + arena_m.adj() -= + arena_m_inv.transpose() * res.adj_op() * arena_m_inv.transpose(); }); - return res; + return ret_type(res); } } // namespace math From f1c6912388fc756094b60454b656ed491b29a6de Mon Sep 17 00:00:00 2001 From: Ben Date: Mon, 5 Oct 2020 13:51:46 -0400 Subject: [PATCH 333/355] Updated log_determinant_spd (Issue #2018) --- stan/math/rev/fun/log_determinant_spd.hpp | 23 ++++++++++++----------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/stan/math/rev/fun/log_determinant_spd.hpp b/stan/math/rev/fun/log_determinant_spd.hpp index 8ef66b1627a..75826bf17b5 100644 --- a/stan/math/rev/fun/log_determinant_spd.hpp +++ b/stan/math/rev/fun/log_determinant_spd.hpp @@ -28,35 +28,36 @@ inline var log_determinant_spd(const T& m) { return 0; } - arena_matrix arena_m_d = m.val(); - check_symmetric("log_determinant_spd", "m", arena_m_d); + arena_t arena_m = m; + + auto arena_m_inv = to_arena(arena_m.val()); + check_symmetric("log_determinant_spd", "m", arena_m_inv); - Eigen::LDLT ldlt(arena_m_d); + const auto& ldlt = arena_m_inv.ldlt(); + if (ldlt.info() != Eigen::Success) { double y = 0; throw_domain_error("log_determinant_spd", "matrix argument", y, "failed LDLT factorization"); } - // compute the inverse of A (needed for the derivative) - arena_m_d.setIdentity(m.rows(), m.cols()); - ldlt.solveInPlace(arena_m_d); - if (ldlt.isNegative() || (ldlt.vectorD().array() <= 1e-16).any()) { double y = 0; throw_domain_error("log_determinant_spd", "matrix argument", y, "matrix is negative definite"); } + // compute the inverse of A (needed for the derivative) + arena_m_inv.setIdentity(m.rows(), m.cols()); + ldlt.solveInPlace(arena_m_inv); + var log_det = sum(log(ldlt.vectorD())); check_finite("log_determinant_spd", "log determininant of the matrix argument", log_det); - arena_matrix> arena_m = m; - - reverse_pass_callback([arena_m, log_det, arena_m_d]() mutable { - arena_m.adj() += log_det.adj() * arena_m_d; + reverse_pass_callback([arena_m, log_det, arena_m_inv]() mutable { + arena_m.adj() += log_det.adj() * arena_m_inv; }); return log_det; From e24de2ca93450f4e0f2ce9f3237101435552cd2c Mon Sep 17 00:00:00 2001 From: Stan Jenkins Date: Mon, 5 Oct 2020 13:52:47 -0400 Subject: [PATCH 334/355] [Jenkins] auto-formatting by clang-format version 6.0.1-14 (tags/RELEASE_601/final) --- stan/math/rev/fun/inverse.hpp | 6 +++--- stan/math/rev/fun/log_determinant_spd.hpp | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/stan/math/rev/fun/inverse.hpp b/stan/math/rev/fun/inverse.hpp index e164f863386..7b797af6013 100644 --- a/stan/math/rev/fun/inverse.hpp +++ b/stan/math/rev/fun/inverse.hpp @@ -25,7 +25,7 @@ namespace math { template * = nullptr> inline auto inverse(const T& m) { using ret_type = plain_type_t; - + check_square("inverse", "m", m); if (m.size() == 0) { @@ -37,8 +37,8 @@ inline auto inverse(const T& m) { arena_t res = arena_m_inv; reverse_pass_callback([res, arena_m_inv, arena_m]() mutable { - arena_m.adj() -= - arena_m_inv.transpose() * res.adj_op() * arena_m_inv.transpose(); + arena_m.adj() + -= arena_m_inv.transpose() * res.adj_op() * arena_m_inv.transpose(); }); return ret_type(res); diff --git a/stan/math/rev/fun/log_determinant_spd.hpp b/stan/math/rev/fun/log_determinant_spd.hpp index 75826bf17b5..a77bb3c1751 100644 --- a/stan/math/rev/fun/log_determinant_spd.hpp +++ b/stan/math/rev/fun/log_determinant_spd.hpp @@ -29,12 +29,12 @@ inline var log_determinant_spd(const T& m) { } arena_t arena_m = m; - + auto arena_m_inv = to_arena(arena_m.val()); check_symmetric("log_determinant_spd", "m", arena_m_inv); const auto& ldlt = arena_m_inv.ldlt(); - + if (ldlt.info() != Eigen::Success) { double y = 0; throw_domain_error("log_determinant_spd", "matrix argument", y, From 0d863511f1c8f443c8a40762ed271afe557078e3 Mon Sep 17 00:00:00 2001 From: Ben Date: Mon, 5 Oct 2020 14:03:32 -0400 Subject: [PATCH 335/355] Updated gp_exp_quad_cov (Issue #2018) --- stan/math/rev/fun/gp_exp_quad_cov.hpp | 48 +++++++++++++-------------- 1 file changed, 24 insertions(+), 24 deletions(-) diff --git a/stan/math/rev/fun/gp_exp_quad_cov.hpp b/stan/math/rev/fun/gp_exp_quad_cov.hpp index dd448ac0e12..ca6da0b4456 100644 --- a/stan/math/rev/fun/gp_exp_quad_cov.hpp +++ b/stan/math/rev/fun/gp_exp_quad_cov.hpp @@ -32,17 +32,20 @@ namespace math { template * = nullptr, require_any_st_var* = nullptr> -inline Eigen::Matrix gp_exp_quad_cov(const std::vector& x, - T_sigma sigma, - T_l length_scale) { +inline auto gp_exp_quad_cov(const std::vector& x, + T_sigma sigma, + T_l length_scale) { + using ret_type = Eigen::Matrix; + check_positive("gp_exp_quad_cov", "marginal standard deviation", sigma); check_positive("gp_exp_quad_cov", "length scale", length_scale); + for (size_t i = 0; i < x.size(); ++i) { check_not_nan("gp_exp_quad_cov", "x", x[i]); } if (x.size() == 0) { - return Eigen::Matrix(); + return ret_type(); } if (is_constant::value && !is_constant::value && !is_constant::value) { @@ -51,33 +54,32 @@ inline Eigen::Matrix gp_exp_quad_cov(const std::vector& x, const double inv_half_sq_l_d = 0.5 / (value_of(length_scale) * value_of(length_scale)); const double sigma_sq_d = value_of(sigma) * value_of(sigma); - arena_matrix> arena_res( - N, N); - arena_matrix> arena_dist(P); + arena_t res(N, N); + arena_t arena_dist(P); size_t pos = 0; for (size_t j = 0; j < N; ++j) { for (size_t i = 0; i <= j; ++i) { if (unlikely(i == j)) { arena_dist.coeffRef(pos) = 0.0; - arena_res.coeffRef(i, j) = sigma_sq_d; + res.coeffRef(i, j) = sigma_sq_d; } else { const double dist_sq = squared_distance(value_of(x[i]), value_of(x[j])); arena_dist.coeffRef(pos) = dist_sq; - arena_res.coeffRef(i, j) + res.coeffRef(i, j) = sigma_sq_d * std::exp(-dist_sq * inv_half_sq_l_d); } ++pos; } } - // if someone does A[1, 2] * 2 wont that also change A[2, 1]? + for (size_t j = 0; j < N; ++j) { for (size_t i = 0; i <= j; ++i) { - arena_res.coeffRef(j, i) = arena_res.coeff(i, j); + res.coeffRef(j, i) = res.coeff(i, j); } } reverse_pass_callback( - [arena_res, arena_dist, sigma, length_scale, N]() mutable { + [res, arena_dist, sigma, length_scale, N]() mutable { const double l_d = value_of(length_scale); auto& sigma_adj = forward_as(sigma).adj(); auto& l_adj = forward_as(length_scale).adj(); @@ -86,7 +88,7 @@ inline Eigen::Matrix gp_exp_quad_cov(const std::vector& x, for (size_t j = 0; j < N; ++j) { for (size_t i = 0; i <= j; ++i) { const double adj_times_val - = arena_res.coeff(i, j).val() * arena_res.coeff(i, j).adj(); + = res.coeff(i, j).val() * res.coeff(i, j).adj(); sigma_adj += adj_times_val; l_adj += arena_dist.coeff(pos) * adj_times_val; ++pos; @@ -96,7 +98,7 @@ inline Eigen::Matrix gp_exp_quad_cov(const std::vector& x, sigma_adj /= value_of(sigma); l_adj /= (l_d * l_d * l_d); }); - return arena_res; + return ret_type(res); } else { double sigma_sq_d = value_of(sigma) * value_of(sigma); double inv_half_sq_l_d @@ -104,9 +106,8 @@ inline Eigen::Matrix gp_exp_quad_cov(const std::vector& x, size_t N = x.size(); size_t P = (N * N - N) / 2 + N; - arena_matrix dist(P); - arena_matrix> arena_res( - N, N); + arena_t dist(P); + arena_t res(N, N); auto arena_x = to_arena_if::value>(x); size_t pos = 0; @@ -116,25 +117,24 @@ inline Eigen::Matrix gp_exp_quad_cov(const std::vector& x, const double dist_sq = squared_distance(value_of(x[i]), value_of(x[j])); dist.coeffRef(pos) = dist_sq; - arena_res.coeffRef(i, j) + res.coeffRef(i, j) = sigma_sq_d * std::exp(-dist_sq * inv_half_sq_l_d); } else { dist.coeffRef(pos) = 0.0; - arena_res.coeffRef(i, j) = sigma_sq_d; + res.coeffRef(i, j) = sigma_sq_d; } ++pos; } } - // if someone does A[1, 2] * 2 wont that also change A[2, 1]? for (size_t j = 0; j < N; ++j) { for (size_t i = 0; i <= j; ++i) { - arena_res.coeffRef(j, i) = arena_res.coeff(i, j); + res.coeffRef(j, i) = res.coeff(i, j); } } reverse_pass_callback( - [arena_res, arena_x, dist, sigma, length_scale, N]() mutable { + [res, arena_x, dist, sigma, length_scale, N]() mutable { const double& l_d = value_of(length_scale); const double inv_l_d_squared = 1.0 / (l_d * l_d); @@ -142,7 +142,7 @@ inline Eigen::Matrix gp_exp_quad_cov(const std::vector& x, for (size_t j = 0; j < N; ++j) { for (size_t i = 0; i <= j; ++i) { const double adj_times_val - = arena_res.coeff(i, j).val() * arena_res.coeff(i, j).adj(); + = res.coeff(i, j).val() * res.coeff(i, j).adj(); if (!is_constant::value) { forward_as(sigma).adj() += adj_times_val; @@ -176,7 +176,7 @@ inline Eigen::Matrix gp_exp_quad_cov(const std::vector& x, } }); - return arena_res; + return ret_type(res); } } From 2af284057da3dc78a6d6d6897a4aff94fc9d8979 Mon Sep 17 00:00:00 2001 From: Ben Date: Mon, 5 Oct 2020 14:29:33 -0400 Subject: [PATCH 336/355] Updated gp_exp_quad_cov (Issue #2018) --- stan/math/rev/fun/gp_exp_quad_cov.hpp | 28 +++++++++++++++++++++++---- 1 file changed, 24 insertions(+), 4 deletions(-) diff --git a/stan/math/rev/fun/gp_exp_quad_cov.hpp b/stan/math/rev/fun/gp_exp_quad_cov.hpp index ca6da0b4456..f1fdbe90b24 100644 --- a/stan/math/rev/fun/gp_exp_quad_cov.hpp +++ b/stan/math/rev/fun/gp_exp_quad_cov.hpp @@ -63,8 +63,18 @@ inline auto gp_exp_quad_cov(const std::vector& x, arena_dist.coeffRef(pos) = 0.0; res.coeffRef(i, j) = sigma_sq_d; } else { - const double dist_sq - = squared_distance(value_of(x[i]), value_of(x[j])); + double dist_sq; + + if (is_stan_scalar::value) { + double diff = forward_as(value_of(x[i]) - value_of(x[j])); + dist_sq = diff * diff; + } else if (is_eigen_col_vector::value) + dist_sq + = forward_as(value_of(x[i]) - value_of(x[j])).squaredNorm(); + else if (is_eigen_row_vector::value) + dist_sq + = forward_as(value_of(x[i]) - value_of(x[j])).squaredNorm(); + arena_dist.coeffRef(pos) = dist_sq; res.coeffRef(i, j) = sigma_sq_d * std::exp(-dist_sq * inv_half_sq_l_d); @@ -114,8 +124,18 @@ inline auto gp_exp_quad_cov(const std::vector& x, for (size_t j = 0; j < N; ++j) { for (size_t i = 0; i <= j; ++i) { if (i != j) { - const double dist_sq - = squared_distance(value_of(x[i]), value_of(x[j])); + double dist_sq; + + if (is_stan_scalar::value) { + double diff = forward_as(value_of(x[i]) - value_of(x[j])); + dist_sq = diff * diff; + } else if (is_eigen_col_vector::value) + dist_sq + = forward_as(value_of(x[i]) - value_of(x[j])).squaredNorm(); + else if (is_eigen_row_vector::value) + dist_sq + = forward_as(value_of(x[i]) - value_of(x[j])).squaredNorm(); + dist.coeffRef(pos) = dist_sq; res.coeffRef(i, j) = sigma_sq_d * std::exp(-dist_sq * inv_half_sq_l_d); From ff907449ebd3fa7ff19cd9195d67fecd29bc5aa0 Mon Sep 17 00:00:00 2001 From: Stan Jenkins Date: Mon, 5 Oct 2020 14:30:42 -0400 Subject: [PATCH 337/355] [Jenkins] auto-formatting by clang-format version 6.0.1-14 (tags/RELEASE_601/final) --- stan/math/rev/fun/gp_exp_quad_cov.hpp | 94 ++++++++++++++------------- 1 file changed, 48 insertions(+), 46 deletions(-) diff --git a/stan/math/rev/fun/gp_exp_quad_cov.hpp b/stan/math/rev/fun/gp_exp_quad_cov.hpp index f1fdbe90b24..ffe7d602abc 100644 --- a/stan/math/rev/fun/gp_exp_quad_cov.hpp +++ b/stan/math/rev/fun/gp_exp_quad_cov.hpp @@ -32,11 +32,10 @@ namespace math { template * = nullptr, require_any_st_var* = nullptr> -inline auto gp_exp_quad_cov(const std::vector& x, - T_sigma sigma, - T_l length_scale) { +inline auto gp_exp_quad_cov(const std::vector& x, T_sigma sigma, + T_l length_scale) { using ret_type = Eigen::Matrix; - + check_positive("gp_exp_quad_cov", "marginal standard deviation", sigma); check_positive("gp_exp_quad_cov", "length scale", length_scale); @@ -63,17 +62,19 @@ inline auto gp_exp_quad_cov(const std::vector& x, arena_dist.coeffRef(pos) = 0.0; res.coeffRef(i, j) = sigma_sq_d; } else { - double dist_sq; - - if (is_stan_scalar::value) { - double diff = forward_as(value_of(x[i]) - value_of(x[j])); - dist_sq = diff * diff; - } else if (is_eigen_col_vector::value) - dist_sq - = forward_as(value_of(x[i]) - value_of(x[j])).squaredNorm(); - else if (is_eigen_row_vector::value) - dist_sq - = forward_as(value_of(x[i]) - value_of(x[j])).squaredNorm(); + double dist_sq; + + if (is_stan_scalar::value) { + double diff = forward_as(value_of(x[i]) - value_of(x[j])); + dist_sq = diff * diff; + } else if (is_eigen_col_vector::value) + dist_sq + = forward_as(value_of(x[i]) - value_of(x[j])) + .squaredNorm(); + else if (is_eigen_row_vector::value) + dist_sq = forward_as(value_of(x[i]) + - value_of(x[j])) + .squaredNorm(); arena_dist.coeffRef(pos) = dist_sq; res.coeffRef(i, j) @@ -88,26 +89,25 @@ inline auto gp_exp_quad_cov(const std::vector& x, res.coeffRef(j, i) = res.coeff(i, j); } } - reverse_pass_callback( - [res, arena_dist, sigma, length_scale, N]() mutable { - const double l_d = value_of(length_scale); - auto& sigma_adj = forward_as(sigma).adj(); - auto& l_adj = forward_as(length_scale).adj(); - - size_t pos = 0; - for (size_t j = 0; j < N; ++j) { - for (size_t i = 0; i <= j; ++i) { - const double adj_times_val - = res.coeff(i, j).val() * res.coeff(i, j).adj(); - sigma_adj += adj_times_val; - l_adj += arena_dist.coeff(pos) * adj_times_val; - ++pos; - } - } - sigma_adj *= 2.0; - sigma_adj /= value_of(sigma); - l_adj /= (l_d * l_d * l_d); - }); + reverse_pass_callback([res, arena_dist, sigma, length_scale, N]() mutable { + const double l_d = value_of(length_scale); + auto& sigma_adj = forward_as(sigma).adj(); + auto& l_adj = forward_as(length_scale).adj(); + + size_t pos = 0; + for (size_t j = 0; j < N; ++j) { + for (size_t i = 0; i <= j; ++i) { + const double adj_times_val + = res.coeff(i, j).val() * res.coeff(i, j).adj(); + sigma_adj += adj_times_val; + l_adj += arena_dist.coeff(pos) * adj_times_val; + ++pos; + } + } + sigma_adj *= 2.0; + sigma_adj /= value_of(sigma); + l_adj /= (l_d * l_d * l_d); + }); return ret_type(res); } else { double sigma_sq_d = value_of(sigma) * value_of(sigma); @@ -124,17 +124,19 @@ inline auto gp_exp_quad_cov(const std::vector& x, for (size_t j = 0; j < N; ++j) { for (size_t i = 0; i <= j; ++i) { if (i != j) { - double dist_sq; - - if (is_stan_scalar::value) { - double diff = forward_as(value_of(x[i]) - value_of(x[j])); - dist_sq = diff * diff; - } else if (is_eigen_col_vector::value) - dist_sq - = forward_as(value_of(x[i]) - value_of(x[j])).squaredNorm(); - else if (is_eigen_row_vector::value) - dist_sq - = forward_as(value_of(x[i]) - value_of(x[j])).squaredNorm(); + double dist_sq; + + if (is_stan_scalar::value) { + double diff = forward_as(value_of(x[i]) - value_of(x[j])); + dist_sq = diff * diff; + } else if (is_eigen_col_vector::value) + dist_sq + = forward_as(value_of(x[i]) - value_of(x[j])) + .squaredNorm(); + else if (is_eigen_row_vector::value) + dist_sq = forward_as(value_of(x[i]) + - value_of(x[j])) + .squaredNorm(); dist.coeffRef(pos) = dist_sq; res.coeffRef(i, j) From a5ffbd437faccdf7e5a3ab4b9742c7aed5dc9c45 Mon Sep 17 00:00:00 2001 From: Ben Date: Mon, 5 Oct 2020 16:35:02 -0400 Subject: [PATCH 338/355] Updated simplex_constrain (Issue #2018) --- stan/math/prim/fun/simplex_constrain.hpp | 3 +- stan/math/rev/fun/simplex_constrain.hpp | 41 +++++++++++++----------- 2 files changed, 25 insertions(+), 19 deletions(-) diff --git a/stan/math/prim/fun/simplex_constrain.hpp b/stan/math/prim/fun/simplex_constrain.hpp index 0d2303d81a4..25c4237a6c3 100644 --- a/stan/math/prim/fun/simplex_constrain.hpp +++ b/stan/math/prim/fun/simplex_constrain.hpp @@ -24,7 +24,8 @@ namespace math { * @param y Free vector input of dimensionality K - 1. * @return Simplex of dimensionality K. */ -template * = nullptr> +template * = nullptr, + require_not_st_var* = nullptr> auto simplex_constrain(const ColVec& y) { // cut & paste simplex_constrain(Eigen::Matrix, T) w/o Jacobian using Eigen::Dynamic; diff --git a/stan/math/rev/fun/simplex_constrain.hpp b/stan/math/rev/fun/simplex_constrain.hpp index 00cf1a465d1..fb30ec981b3 100644 --- a/stan/math/rev/fun/simplex_constrain.hpp +++ b/stan/math/rev/fun/simplex_constrain.hpp @@ -25,44 +25,49 @@ namespace math { * @param y Free vector input of dimensionality K - 1 * @return Simplex of dimensionality K */ -inline Eigen::Matrix simplex_constrain( - const Eigen::Matrix& y) { +template* = nullptr> +inline auto simplex_constrain(const T& y) { + using ret_type = plain_type_t; + size_t N = y.size(); - arena_matrix diag(N); - arena_matrix z(N); + arena_t arena_y = y; + + arena_t diag(N); + arena_t z(N); Eigen::VectorXd x_val(N + 1); double stick_len(1.0); for (int k = 0; k < N; ++k) { double log_N_minus_k = std::log(N - k); - z.coeffRef(k) = inv_logit(value_of(y.coeff(k)) - log_N_minus_k); + z.coeffRef(k) = inv_logit(value_of(arena_y.coeff(k)) - log_N_minus_k); diag.coeffRef(k) = stick_len * z.coeff(k) - * inv_logit(log_N_minus_k - value_of(y.coeff(k))); + * inv_logit(log_N_minus_k - value_of(arena_y.coeff(k))); x_val.coeffRef(k) = stick_len * z.coeff(k); stick_len -= x_val(k); } x_val.coeffRef(N) = stick_len; - arena_matrix> x = x_val; - arena_matrix> arena_y = y; + arena_t x = x_val; - reverse_pass_callback([=]() mutable { - double acc = x.adj().coeff(N); + if(N > 0) { + reverse_pass_callback([arena_y, x, diag, z]() mutable { + size_t N = arena_y.size(); + double acc = x.adj().coeff(N); - if (N > 0) { arena_y.adj().coeffRef(N - 1) - += diag.coeff(N - 1) * (x.adj().coeff(N - 1) - acc); + += diag.coeff(N - 1) * (x.adj().coeff(N - 1) - acc); for (int n = N - 1; --n >= 0;) { - acc = x.adj().coeff(n + 1) * z.coeff(n + 1) - + (1 - z.coeff(n + 1)) * acc; - arena_y.adj().coeffRef(n) += diag.coeff(n) * (x.adj().coeff(n) - acc); + acc = x.adj().coeff(n + 1) * z.coeff(n + 1) + + (1 - z.coeff(n + 1)) * acc; + arena_y.adj().coeffRef(n) += diag.coeff(n) * (x.adj().coeff(n) - acc); } - } - }); + }); + } - return x; + return ret_type(x); } } // namespace math From 874dc50fa2a79e3e7dcbfe8cc9a6d4a9f6ed4748 Mon Sep 17 00:00:00 2001 From: Stan Jenkins Date: Mon, 5 Oct 2020 16:36:05 -0400 Subject: [PATCH 339/355] [Jenkins] auto-formatting by clang-format version 6.0.1-14 (tags/RELEASE_601/final) --- stan/math/prim/fun/simplex_constrain.hpp | 2 +- stan/math/rev/fun/simplex_constrain.hpp | 17 ++++++++--------- 2 files changed, 9 insertions(+), 10 deletions(-) diff --git a/stan/math/prim/fun/simplex_constrain.hpp b/stan/math/prim/fun/simplex_constrain.hpp index 25c4237a6c3..369d73d84ce 100644 --- a/stan/math/prim/fun/simplex_constrain.hpp +++ b/stan/math/prim/fun/simplex_constrain.hpp @@ -25,7 +25,7 @@ namespace math { * @return Simplex of dimensionality K. */ template * = nullptr, - require_not_st_var* = nullptr> + require_not_st_var* = nullptr> auto simplex_constrain(const ColVec& y) { // cut & paste simplex_constrain(Eigen::Matrix, T) w/o Jacobian using Eigen::Dynamic; diff --git a/stan/math/rev/fun/simplex_constrain.hpp b/stan/math/rev/fun/simplex_constrain.hpp index fb30ec981b3..19694c555e6 100644 --- a/stan/math/rev/fun/simplex_constrain.hpp +++ b/stan/math/rev/fun/simplex_constrain.hpp @@ -25,15 +25,14 @@ namespace math { * @param y Free vector input of dimensionality K - 1 * @return Simplex of dimensionality K */ -template* = nullptr> +template * = nullptr> inline auto simplex_constrain(const T& y) { using ret_type = plain_type_t; - + size_t N = y.size(); arena_t arena_y = y; - + arena_t diag(N); arena_t z(N); @@ -52,17 +51,17 @@ inline auto simplex_constrain(const T& y) { arena_t x = x_val; - if(N > 0) { + if (N > 0) { reverse_pass_callback([arena_y, x, diag, z]() mutable { size_t N = arena_y.size(); double acc = x.adj().coeff(N); arena_y.adj().coeffRef(N - 1) - += diag.coeff(N - 1) * (x.adj().coeff(N - 1) - acc); + += diag.coeff(N - 1) * (x.adj().coeff(N - 1) - acc); for (int n = N - 1; --n >= 0;) { - acc = x.adj().coeff(n + 1) * z.coeff(n + 1) - + (1 - z.coeff(n + 1)) * acc; - arena_y.adj().coeffRef(n) += diag.coeff(n) * (x.adj().coeff(n) - acc); + acc = x.adj().coeff(n + 1) * z.coeff(n + 1) + + (1 - z.coeff(n + 1)) * acc; + arena_y.adj().coeffRef(n) += diag.coeff(n) * (x.adj().coeff(n) - acc); } }); } From f51b74519861022d09dc37eaf88c992e82c21d2b Mon Sep 17 00:00:00 2001 From: Ben Date: Mon, 5 Oct 2020 16:56:47 -0400 Subject: [PATCH 340/355] Update mdivide_left_ldlt (Issue #2018) --- stan/math/rev/fun/mdivide_left_ldlt.hpp | 24 +++++++++++------------- 1 file changed, 11 insertions(+), 13 deletions(-) diff --git a/stan/math/rev/fun/mdivide_left_ldlt.hpp b/stan/math/rev/fun/mdivide_left_ldlt.hpp index 54c516580fb..e8ec21c3f1e 100644 --- a/stan/math/rev/fun/mdivide_left_ldlt.hpp +++ b/stan/math/rev/fun/mdivide_left_ldlt.hpp @@ -27,39 +27,37 @@ namespace math { */ template * = nullptr, require_any_st_var* = nullptr> -inline Eigen::Matrix mdivide_left_ldlt( - const LDLT_factor& A, const T2& B) { +inline auto mdivide_left_ldlt(const LDLT_factor& A, const T2& B) { + using ret_type = Eigen::Matrix; + check_multiplicable("mdivide_left_ldlt", "A", A, "B", B); - using B_ref_t = ref_type_t; - - B_ref_t B_ref = B; + const auto& B_ref = to_ref(B); if (A.cols() == 0) { - return {0, B.cols()}; + return ret_type(0, B.cols()); } - arena_matrix> arena_B; + arena_t> arena_B; if (!is_constant::value) { arena_B = B_ref; } - arena_matrix> res - = A.solve(value_of(B_ref)); + arena_t res = A.solve(value_of(B_ref)); reverse_pass_callback([A, arena_B, res]() mutable { - Eigen::Matrix adjB = A.solve(res.adj()); + promote_scalar_t adjB = A.solve(res.adj()); if (!is_constant::value) forward_as>(A).alloc_->arena_A_.adj() - += -adjB * res.val().transpose().eval(); + -= adjB * res.val().transpose().eval(); if (!is_constant::value) - forward_as>(arena_B).adj() += adjB; + arena_B.adj() += adjB; }); - return res; + return ret_type(res); } } // namespace math From 2f373f52aa96e765a0944fd79dc335797e55fd4a Mon Sep 17 00:00:00 2001 From: Stan Jenkins Date: Mon, 5 Oct 2020 16:57:59 -0400 Subject: [PATCH 341/355] [Jenkins] auto-formatting by clang-format version 6.0.1-14 (tags/RELEASE_601/final) --- stan/math/rev/fun/mdivide_left_ldlt.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stan/math/rev/fun/mdivide_left_ldlt.hpp b/stan/math/rev/fun/mdivide_left_ldlt.hpp index e8ec21c3f1e..f6aa1b87785 100644 --- a/stan/math/rev/fun/mdivide_left_ldlt.hpp +++ b/stan/math/rev/fun/mdivide_left_ldlt.hpp @@ -29,7 +29,7 @@ template * = nullptr, require_any_st_var* = nullptr> inline auto mdivide_left_ldlt(const LDLT_factor& A, const T2& B) { using ret_type = Eigen::Matrix; - + check_multiplicable("mdivide_left_ldlt", "A", A, "B", B); const auto& B_ref = to_ref(B); From 6108d99813938c975924f179ae031db18767a5df Mon Sep 17 00:00:00 2001 From: Ben Date: Mon, 5 Oct 2020 17:36:35 -0400 Subject: [PATCH 342/355] Updated rows_dot_product and positive_ordered_constrain (Issue #2018) --- .../prim/fun/positive_ordered_constrain.hpp | 3 +- .../rev/fun/positive_ordered_constrain.hpp | 25 ++++++----- stan/math/rev/fun/rows_dot_product.hpp | 44 ++++++++++--------- 3 files changed, 39 insertions(+), 33 deletions(-) diff --git a/stan/math/prim/fun/positive_ordered_constrain.hpp b/stan/math/prim/fun/positive_ordered_constrain.hpp index 017b2d76964..a5cf680e498 100644 --- a/stan/math/prim/fun/positive_ordered_constrain.hpp +++ b/stan/math/prim/fun/positive_ordered_constrain.hpp @@ -18,7 +18,8 @@ namespace math { * @param x Free vector of scalars. * @return Positive, increasing ordered vector. */ -template * = nullptr> +template * = nullptr, + require_not_st_var* = nullptr> Eigen::Matrix, Eigen::Dynamic, 1> positive_ordered_constrain(const EigVec& x) { using Eigen::Dynamic; diff --git a/stan/math/rev/fun/positive_ordered_constrain.hpp b/stan/math/rev/fun/positive_ordered_constrain.hpp index bbd326823d5..28f9b373c1b 100644 --- a/stan/math/rev/fun/positive_ordered_constrain.hpp +++ b/stan/math/rev/fun/positive_ordered_constrain.hpp @@ -21,29 +21,32 @@ namespace math { * @param x Free vector of scalars * @return Positive, increasing ordered vector */ -inline Eigen::Matrix positive_ordered_constrain( - const Eigen::Matrix& x) { - using std::exp; +template * = nullptr> +inline auto positive_ordered_constrain(const T& x) { + using ret_type = plain_type_t; size_t N = x.size(); + if (N == 0) { - return x; + return ret_type(); } + arena_t arena_x = x; Eigen::VectorXd y_val(N); - arena_matrix exp_x(N); + arena_t exp_x(N); - exp_x(0) = exp(value_of(x.coeff(0))); + exp_x(0) = std::exp(value_of(x.coeff(0))); y_val(0) = exp_x.coeff(0); for (int n = 1; n < N; ++n) { - exp_x(n) = exp(value_of(x.coeff(n))); + exp_x(n) = std::exp(value_of(x.coeff(n))); y_val(n) = y_val.coeff(n - 1) + exp_x.coeff(n); } - arena_matrix> y = y_val; - arena_matrix> arena_x = x; + arena_t y = y_val; - reverse_pass_callback([arena_x, exp_x, N, y]() mutable { + reverse_pass_callback([arena_x, exp_x, y]() mutable { + size_t N = arena_x.size(); double rolling_adjoint_sum = 0.0; for (int n = N; --n >= 0;) { @@ -52,7 +55,7 @@ inline Eigen::Matrix positive_ordered_constrain( } }); - return y; + return ret_type(y); } } // namespace math diff --git a/stan/math/rev/fun/rows_dot_product.hpp b/stan/math/rev/fun/rows_dot_product.hpp index a024992bb6a..be03287e25a 100644 --- a/stan/math/rev/fun/rows_dot_product.hpp +++ b/stan/math/rev/fun/rows_dot_product.hpp @@ -14,18 +14,19 @@ namespace math { template * = nullptr, require_any_eigen_vt* = nullptr> -inline Eigen::Matrix rows_dot_product( - const Mat1& v1, const Mat2& v2) { +inline auto rows_dot_product(const Mat1& v1, const Mat2& v2) { + using ret_type = promote_scalar_t; + check_matching_sizes("rows_dot_product", "v1", v1, "v2", v2); - ref_type_t v1_ref = v1; - ref_type_t v2_ref = v2; + const auto& v1_ref = to_ref(v1); + const auto& v2_ref = to_ref(v2); - arena_matrix> arena_v1_val = value_of(v1_ref); - arena_matrix> arena_v2_val = value_of(v2_ref); + auto arena_v1_val = to_arena(value_of(v1_ref)); + auto arena_v2_val = to_arena(value_of(v2_ref)); - arena_matrix> arena_v1; - arena_matrix> arena_v2; + arena_t arena_v1; + arena_t arena_v2; if (!is_constant::value) { arena_v1 = v1_ref; @@ -35,24 +36,25 @@ inline Eigen::Matrix rows_dot_product( arena_v2 = v2_ref; } - Eigen::VectorXd out_val(arena_v1_val.rows()); + arena_t res(arena_v1_val.rows()); for (size_t m = 0; m < arena_v1_val.rows(); ++m) - out_val.coeffRef(m) = arena_v1_val.row(m).dot(arena_v2_val.row(m)); - - arena_matrix> out = out_val; - - reverse_pass_callback( - [out, arena_v1, arena_v2, arena_v1_val, arena_v2_val]() mutable { - Eigen::VectorXd adj = out.adj(); + res.coeffRef(m) = arena_v1_val.row(m).dot(arena_v2_val.row(m)); + reverse_pass_callback([res, arena_v1, arena_v2, + arena_v1_val, arena_v2_val]() mutable { + for (size_t j = 0; j < arena_v1.cols(); ++j) { + for (size_t i = 0; i < arena_v1.rows(); ++i) { if (!is_constant::value) - arena_v1.adj() += adj.asDiagonal() * arena_v2_val; - + forward_as(arena_v1.coeffRef(i, j)).adj() + += value_of(arena_v2_val.coeff(i, j)) * res.coeff(i).adj(); if (!is_constant::value) - arena_v2.adj() += adj.asDiagonal() * arena_v1_val; - }); + forward_as(arena_v2.coeffRef(i, j)).adj() + += value_of(arena_v1_val.coeff(i, j)) * res.coeff(i).adj(); + } + } + }); - return out; + return ret_type(res); } } // namespace math From 00bd297f69eb172c45058d6eb43c3acefa528efe Mon Sep 17 00:00:00 2001 From: Stan Jenkins Date: Mon, 5 Oct 2020 17:37:44 -0400 Subject: [PATCH 343/355] [Jenkins] auto-formatting by clang-format version 6.0.1-14 (tags/RELEASE_601/final) --- .../prim/fun/positive_ordered_constrain.hpp | 2 +- .../rev/fun/positive_ordered_constrain.hpp | 3 +-- stan/math/rev/fun/rows_dot_product.hpp | 26 +++++++++---------- 3 files changed, 15 insertions(+), 16 deletions(-) diff --git a/stan/math/prim/fun/positive_ordered_constrain.hpp b/stan/math/prim/fun/positive_ordered_constrain.hpp index a5cf680e498..b1687d08979 100644 --- a/stan/math/prim/fun/positive_ordered_constrain.hpp +++ b/stan/math/prim/fun/positive_ordered_constrain.hpp @@ -19,7 +19,7 @@ namespace math { * @return Positive, increasing ordered vector. */ template * = nullptr, - require_not_st_var* = nullptr> + require_not_st_var* = nullptr> Eigen::Matrix, Eigen::Dynamic, 1> positive_ordered_constrain(const EigVec& x) { using Eigen::Dynamic; diff --git a/stan/math/rev/fun/positive_ordered_constrain.hpp b/stan/math/rev/fun/positive_ordered_constrain.hpp index 28f9b373c1b..75337ae8339 100644 --- a/stan/math/rev/fun/positive_ordered_constrain.hpp +++ b/stan/math/rev/fun/positive_ordered_constrain.hpp @@ -21,8 +21,7 @@ namespace math { * @param x Free vector of scalars * @return Positive, increasing ordered vector */ -template * = nullptr> +template * = nullptr> inline auto positive_ordered_constrain(const T& x) { using ret_type = plain_type_t; diff --git a/stan/math/rev/fun/rows_dot_product.hpp b/stan/math/rev/fun/rows_dot_product.hpp index be03287e25a..c2218231ee3 100644 --- a/stan/math/rev/fun/rows_dot_product.hpp +++ b/stan/math/rev/fun/rows_dot_product.hpp @@ -40,19 +40,19 @@ inline auto rows_dot_product(const Mat1& v1, const Mat2& v2) { for (size_t m = 0; m < arena_v1_val.rows(); ++m) res.coeffRef(m) = arena_v1_val.row(m).dot(arena_v2_val.row(m)); - reverse_pass_callback([res, arena_v1, arena_v2, - arena_v1_val, arena_v2_val]() mutable { - for (size_t j = 0; j < arena_v1.cols(); ++j) { - for (size_t i = 0; i < arena_v1.rows(); ++i) { - if (!is_constant::value) - forward_as(arena_v1.coeffRef(i, j)).adj() - += value_of(arena_v2_val.coeff(i, j)) * res.coeff(i).adj(); - if (!is_constant::value) - forward_as(arena_v2.coeffRef(i, j)).adj() - += value_of(arena_v1_val.coeff(i, j)) * res.coeff(i).adj(); - } - } - }); + reverse_pass_callback( + [res, arena_v1, arena_v2, arena_v1_val, arena_v2_val]() mutable { + for (size_t j = 0; j < arena_v1.cols(); ++j) { + for (size_t i = 0; i < arena_v1.rows(); ++i) { + if (!is_constant::value) + forward_as(arena_v1.coeffRef(i, j)).adj() + += value_of(arena_v2_val.coeff(i, j)) * res.coeff(i).adj(); + if (!is_constant::value) + forward_as(arena_v2.coeffRef(i, j)).adj() + += value_of(arena_v1_val.coeff(i, j)) * res.coeff(i).adj(); + } + } + }); return ret_type(res); } From 9a01a3841fc834b7e0c3e613e5e4e7369ef19342 Mon Sep 17 00:00:00 2001 From: Ben Date: Mon, 5 Oct 2020 17:42:34 -0400 Subject: [PATCH 344/355] Updated log_determinant (Issue #2018) --- stan/math/rev/fun/log_determinant.hpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/stan/math/rev/fun/log_determinant.hpp b/stan/math/rev/fun/log_determinant.hpp index 331a68ff713..c30b540fc23 100644 --- a/stan/math/rev/fun/log_determinant.hpp +++ b/stan/math/rev/fun/log_determinant.hpp @@ -23,11 +23,11 @@ inline var log_determinant(const T& m) { arena_t arena_m = m; - auto m_lu = arena_m.val().partialPivLu(); + auto m_hh = arena_m.val().fullPivHouseholderQr(); - auto arena_m_inv_transpose = to_arena(m_lu.inverse().transpose()); + auto arena_m_inv_transpose = to_arena(m_hh.inverse().transpose()); - var log_det = std::log(std::abs(m_lu.determinant())); + var log_det = m_hh.logAbsDeterminant(); reverse_pass_callback([arena_m, log_det, arena_m_inv_transpose]() mutable { arena_m.adj() += log_det.adj() * arena_m_inv_transpose; From 009503f7165dea6f4d3083646f6965b846bf83d7 Mon Sep 17 00:00:00 2001 From: Ben Date: Mon, 5 Oct 2020 17:56:42 -0400 Subject: [PATCH 345/355] Updated gp_cov_exp_quad (Issue #2018) --- stan/math/rev/fun/gp_exp_quad_cov.hpp | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/stan/math/rev/fun/gp_exp_quad_cov.hpp b/stan/math/rev/fun/gp_exp_quad_cov.hpp index ffe7d602abc..3e750519613 100644 --- a/stan/math/rev/fun/gp_exp_quad_cov.hpp +++ b/stan/math/rev/fun/gp_exp_quad_cov.hpp @@ -67,14 +67,15 @@ inline auto gp_exp_quad_cov(const std::vector& x, T_sigma sigma, if (is_stan_scalar::value) { double diff = forward_as(value_of(x[i]) - value_of(x[j])); dist_sq = diff * diff; - } else if (is_eigen_col_vector::value) + } else if (is_eigen_col_vector::value) { dist_sq = forward_as(value_of(x[i]) - value_of(x[j])) .squaredNorm(); - else if (is_eigen_row_vector::value) + } else if (is_eigen_row_vector::value) { dist_sq = forward_as(value_of(x[i]) - value_of(x[j])) .squaredNorm(); + } arena_dist.coeffRef(pos) = dist_sq; res.coeffRef(i, j) @@ -129,14 +130,15 @@ inline auto gp_exp_quad_cov(const std::vector& x, T_sigma sigma, if (is_stan_scalar::value) { double diff = forward_as(value_of(x[i]) - value_of(x[j])); dist_sq = diff * diff; - } else if (is_eigen_col_vector::value) + } else if (is_eigen_col_vector::value) { dist_sq = forward_as(value_of(x[i]) - value_of(x[j])) .squaredNorm(); - else if (is_eigen_row_vector::value) + } else if (is_eigen_row_vector::value) { dist_sq = forward_as(value_of(x[i]) - value_of(x[j])) .squaredNorm(); + } dist.coeffRef(pos) = dist_sq; res.coeffRef(i, j) From d7638944c582085f5df737c0a95495bc2839158d Mon Sep 17 00:00:00 2001 From: Stan Jenkins Date: Mon, 5 Oct 2020 22:00:31 +0000 Subject: [PATCH 346/355] [Jenkins] auto-formatting by clang-format version 6.0.0-1ubuntu2~16.04.1 (tags/RELEASE_600/final) --- stan/math/rev/fun/gp_exp_quad_cov.hpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/stan/math/rev/fun/gp_exp_quad_cov.hpp b/stan/math/rev/fun/gp_exp_quad_cov.hpp index 3e750519613..f9c219689fe 100644 --- a/stan/math/rev/fun/gp_exp_quad_cov.hpp +++ b/stan/math/rev/fun/gp_exp_quad_cov.hpp @@ -71,11 +71,11 @@ inline auto gp_exp_quad_cov(const std::vector& x, T_sigma sigma, dist_sq = forward_as(value_of(x[i]) - value_of(x[j])) .squaredNorm(); - } else if (is_eigen_row_vector::value) { + } else if (is_eigen_row_vector::value) { dist_sq = forward_as(value_of(x[i]) - value_of(x[j])) .squaredNorm(); - } + } arena_dist.coeffRef(pos) = dist_sq; res.coeffRef(i, j) @@ -134,11 +134,11 @@ inline auto gp_exp_quad_cov(const std::vector& x, T_sigma sigma, dist_sq = forward_as(value_of(x[i]) - value_of(x[j])) .squaredNorm(); - } else if (is_eigen_row_vector::value) { + } else if (is_eigen_row_vector::value) { dist_sq = forward_as(value_of(x[i]) - value_of(x[j])) .squaredNorm(); - } + } dist.coeffRef(pos) = dist_sq; res.coeffRef(i, j) From 1b0c26d587931dc18b144e09de9fd78def42437b Mon Sep 17 00:00:00 2001 From: Ben Date: Mon, 5 Oct 2020 19:09:16 -0400 Subject: [PATCH 347/355] Updated unit constrain (Issue #2018) --- stan/math/prim/fun/unit_vector_constrain.hpp | 16 +++++++++------- stan/math/rev/fun/unit_vector_constrain.hpp | 15 +++++++-------- 2 files changed, 16 insertions(+), 15 deletions(-) diff --git a/stan/math/prim/fun/unit_vector_constrain.hpp b/stan/math/prim/fun/unit_vector_constrain.hpp index bb6c3de29a0..1b3af16a68c 100644 --- a/stan/math/prim/fun/unit_vector_constrain.hpp +++ b/stan/math/prim/fun/unit_vector_constrain.hpp @@ -23,12 +23,13 @@ namespace math { * @param y vector of K unrestricted variables * @return Unit length vector of dimension K */ -template -Eigen::Matrix unit_vector_constrain(const Eigen::Matrix& y) { +template * = nullptr, + require_not_vt_var* = nullptr> +inline plain_type_t unit_vector_constrain(const T& y) { using std::sqrt; check_vector("unit_vector_constrain", "y", y); check_nonzero_size("unit_vector_constrain", "y", y); - T SN = dot_self(y); + scalar_type_t SN = dot_self(y); check_positive_finite("unit_vector_constrain", "norm", SN); return y / sqrt(SN); } @@ -45,13 +46,14 @@ Eigen::Matrix unit_vector_constrain(const Eigen::Matrix& y) { * @return Unit length vector of dimension K * @param lp Log probability reference to increment. */ -template -Eigen::Matrix unit_vector_constrain(const Eigen::Matrix& y, - T& lp) { +template * = nullptr, + require_all_not_vt_var* = nullptr> +inline plain_type_t unit_vector_constrain(const T1& y, T2& lp) { using std::sqrt; check_vector("unit_vector_constrain", "y", y); check_nonzero_size("unit_vector_constrain", "y", y); - T SN = dot_self(y); + scalar_type_t SN = dot_self(y); check_positive_finite("unit_vector_constrain", "norm", SN); lp -= 0.5 * SN; return y / sqrt(SN); diff --git a/stan/math/rev/fun/unit_vector_constrain.hpp b/stan/math/rev/fun/unit_vector_constrain.hpp index 5a28c06b98b..87a0ed9454b 100644 --- a/stan/math/rev/fun/unit_vector_constrain.hpp +++ b/stan/math/rev/fun/unit_vector_constrain.hpp @@ -1,5 +1,5 @@ -#ifndef STAN_MATH_PRIM_FUN_UNIT_VECTOR_CONSTRAIN_HPP -#define STAN_MATH_PRIM_FUN_UNIT_VECTOR_CONSTRAIN_HPP +#ifndef STAN_MATH_REV_FUN_UNIT_VECTOR_CONSTRAIN_HPP +#define STAN_MATH_REV_FUN_UNIT_VECTOR_CONSTRAIN_HPP #include #include @@ -26,13 +26,13 @@ namespace math { * @return Unit length vector of dimension K **/ template * = nullptr> -auto unit_vector_constrain(const T& y) { +inline auto unit_vector_constrain(const T& y) { using ret_type = plain_type_t; check_vector("unit_vector", "y", y); check_nonzero_size("unit_vector", "y", y); - arena_t arena_y = y_ref; + arena_t arena_y = y; const auto& y_val = to_arena(value_of(arena_y)); const double r = y_val.norm(); @@ -58,10 +58,9 @@ auto unit_vector_constrain(const T& y) { * @return Unit length vector of dimension K * @param lp Log probability reference to increment. **/ -template -Eigen::Matrix unit_vector_constrain( - const Eigen::Matrix& y, var& lp) { - Eigen::Matrix x = unit_vector_constrain(y); +template * = nullptr> +inline auto unit_vector_constrain(const T& y, var& lp) { + auto x = unit_vector_constrain(y); lp -= 0.5 * dot_self(y); return x; } From 0798e9edd615ad317d644166970c5d808bdd242d Mon Sep 17 00:00:00 2001 From: Stan Jenkins Date: Mon, 5 Oct 2020 19:12:16 -0400 Subject: [PATCH 348/355] [Jenkins] auto-formatting by clang-format version 6.0.1-14 (tags/RELEASE_601/final) --- stan/math/prim/fun/unit_vector_constrain.hpp | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/stan/math/prim/fun/unit_vector_constrain.hpp b/stan/math/prim/fun/unit_vector_constrain.hpp index 1b3af16a68c..44734296b96 100644 --- a/stan/math/prim/fun/unit_vector_constrain.hpp +++ b/stan/math/prim/fun/unit_vector_constrain.hpp @@ -24,7 +24,7 @@ namespace math { * @return Unit length vector of dimension K */ template * = nullptr, - require_not_vt_var* = nullptr> + require_not_vt_var* = nullptr> inline plain_type_t unit_vector_constrain(const T& y) { using std::sqrt; check_vector("unit_vector_constrain", "y", y); @@ -46,9 +46,8 @@ inline plain_type_t unit_vector_constrain(const T& y) { * @return Unit length vector of dimension K * @param lp Log probability reference to increment. */ -template * = nullptr, - require_all_not_vt_var* = nullptr> +template * = nullptr, + require_all_not_vt_var* = nullptr> inline plain_type_t unit_vector_constrain(const T1& y, T2& lp) { using std::sqrt; check_vector("unit_vector_constrain", "y", y); From 1c911b9a99a2a397e4aa118a8b4751e50cc66035 Mon Sep 17 00:00:00 2001 From: Ben Date: Mon, 5 Oct 2020 21:05:17 -0400 Subject: [PATCH 349/355] Added unit_vector_constrain to function header (Issue #2018) --- stan/math/rev/fun.hpp | 1 + 1 file changed, 1 insertion(+) diff --git a/stan/math/rev/fun.hpp b/stan/math/rev/fun.hpp index 3845da79061..423a44b7c67 100644 --- a/stan/math/rev/fun.hpp +++ b/stan/math/rev/fun.hpp @@ -150,6 +150,7 @@ #include #include #include +#include #include #include #include From 2d17c6e589f13af968467a6e9bed7feb3956f38c Mon Sep 17 00:00:00 2001 From: Ben Date: Mon, 5 Oct 2020 21:07:57 -0400 Subject: [PATCH 350/355] Updated log_determinant (Issue #2018) --- stan/math/rev/fun/log_determinant.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stan/math/rev/fun/log_determinant.hpp b/stan/math/rev/fun/log_determinant.hpp index c30b540fc23..9fdacad7766 100644 --- a/stan/math/rev/fun/log_determinant.hpp +++ b/stan/math/rev/fun/log_determinant.hpp @@ -23,7 +23,7 @@ inline var log_determinant(const T& m) { arena_t arena_m = m; - auto m_hh = arena_m.val().fullPivHouseholderQr(); + auto m_hh = arena_m.val().colPivHouseholderQr(); auto arena_m_inv_transpose = to_arena(m_hh.inverse().transpose()); From 708c590ac1a5eb376d387e13857d1739cb2cb77a Mon Sep 17 00:00:00 2001 From: Ben Date: Tue, 6 Oct 2020 09:16:36 -0400 Subject: [PATCH 351/355] Updated rows_dot_product (Issue #2018) --- stan/math/rev/fun/rows_dot_product.hpp | 83 +++++++++++++++++--------- 1 file changed, 56 insertions(+), 27 deletions(-) diff --git a/stan/math/rev/fun/rows_dot_product.hpp b/stan/math/rev/fun/rows_dot_product.hpp index c2218231ee3..1f6a30da72a 100644 --- a/stan/math/rev/fun/rows_dot_product.hpp +++ b/stan/math/rev/fun/rows_dot_product.hpp @@ -19,42 +19,71 @@ inline auto rows_dot_product(const Mat1& v1, const Mat2& v2) { check_matching_sizes("rows_dot_product", "v1", v1, "v2", v2); - const auto& v1_ref = to_ref(v1); - const auto& v2_ref = to_ref(v2); + if(!is_constant::value && !is_constant::value) { + arena_t> arena_v1 = v1; + arena_t> arena_v2 = v2; - auto arena_v1_val = to_arena(value_of(v1_ref)); - auto arena_v2_val = to_arena(value_of(v2_ref)); + auto arena_v1_val = to_arena(value_of(arena_v1)); + auto arena_v2_val = to_arena(value_of(arena_v2)); - arena_t arena_v1; - arena_t arena_v2; + arena_t res(arena_v1_val.rows()); + for (size_t m = 0; m < arena_v1_val.rows(); ++m) + res.coeffRef(m) = arena_v1_val.row(m).dot(arena_v2_val.row(m)); - if (!is_constant::value) { - arena_v1 = v1_ref; - } + reverse_pass_callback( + [res, arena_v1, arena_v2, arena_v1_val, arena_v2_val]() mutable { + for (size_t j = 0; j < arena_v1_val.cols(); ++j) { + for (size_t i = 0; i < arena_v1_val.rows(); ++i) { + arena_v1.coeffRef(i, j).adj() + += arena_v2_val.coeff(i, j) * res.coeff(i).adj(); + arena_v2.coeffRef(i, j).adj() + += arena_v1_val.coeff(i, j) * res.coeff(i).adj(); + } + } + }); - if (!is_constant::value) { - arena_v2 = v2_ref; - } + return ret_type(res); + } else if(!is_constant::value) { + arena_t> arena_v1 = v1; - arena_t res(arena_v1_val.rows()); - for (size_t m = 0; m < arena_v1_val.rows(); ++m) - res.coeffRef(m) = arena_v1_val.row(m).dot(arena_v2_val.row(m)); + auto arena_v2_val = to_arena(value_of(v2)); - reverse_pass_callback( - [res, arena_v1, arena_v2, arena_v1_val, arena_v2_val]() mutable { - for (size_t j = 0; j < arena_v1.cols(); ++j) { - for (size_t i = 0; i < arena_v1.rows(); ++i) { - if (!is_constant::value) - forward_as(arena_v1.coeffRef(i, j)).adj() - += value_of(arena_v2_val.coeff(i, j)) * res.coeff(i).adj(); - if (!is_constant::value) - forward_as(arena_v2.coeffRef(i, j)).adj() - += value_of(arena_v1_val.coeff(i, j)) * res.coeff(i).adj(); + arena_t res(arena_v2_val.rows()); + for (size_t m = 0; m < arena_v2_val.rows(); ++m) + res.coeffRef(m) = arena_v1.row(m).val().dot(arena_v2_val.row(m)); + + reverse_pass_callback( + [res, arena_v1, arena_v2_val]() mutable { + for (size_t j = 0; j < arena_v2_val.cols(); ++j) { + for (size_t i = 0; i < arena_v2_val.rows(); ++i) { + arena_v1.coeffRef(i, j).adj() + += arena_v2_val.coeff(i, j) * res.coeff(i).adj(); } - } + } }); - return ret_type(res); + return ret_type(res); + } else { + arena_t> arena_v2 = v2; + + auto arena_v1_val = to_arena(value_of(v1)); + + arena_t res(arena_v1_val.rows()); + for (size_t m = 0; m < arena_v1_val.rows(); ++m) + res.coeffRef(m) = arena_v1_val.row(m).dot(arena_v2.row(m).val()); + + reverse_pass_callback( + [res, arena_v2, arena_v1_val]() mutable { + for (size_t j = 0; j < arena_v1_val.cols(); ++j) { + for (size_t i = 0; i < arena_v1_val.rows(); ++i) { + arena_v2.coeffRef(i, j).adj() + += arena_v1_val.coeff(i, j) * res.coeff(i).adj(); + } + } + }); + + return ret_type(res); + } } } // namespace math From 00f171d0ef60141805475846b048e0c1c3dd501a Mon Sep 17 00:00:00 2001 From: Ben Date: Tue, 6 Oct 2020 09:25:39 -0400 Subject: [PATCH 352/355] Updated expressions list (Issue #2018) --- stan/math/rev/fun/dot_product.hpp | 7 +++++-- .../stan_math_sigs_exceptions.expected | 19 ------------------- 2 files changed, 5 insertions(+), 21 deletions(-) diff --git a/stan/math/rev/fun/dot_product.hpp b/stan/math/rev/fun/dot_product.hpp index 60aede6618e..5ea87f55c56 100644 --- a/stan/math/rev/fun/dot_product.hpp +++ b/stan/math/rev/fun/dot_product.hpp @@ -35,8 +35,11 @@ template * = nullptr, inline return_type_t dot_product(const T1& v1, const T2& v2) { check_matching_sizes("dot_product", "v1", v1, "v2", v2); - const auto& v1_col = as_column_vector_or_scalar(v1); - const auto& v2_col = as_column_vector_or_scalar(v2); + const auto& v1_ref = to_ref(v1); + const auto& v2_ref = to_ref(v2); + + const auto& v1_col = as_column_vector_or_scalar(v1_ref); + const auto& v2_col = as_column_vector_or_scalar(v2_ref); arena_t v1_val_arena = to_arena_if::value>(value_of(v1_col)); diff --git a/test/expressions/stan_math_sigs_exceptions.expected b/test/expressions/stan_math_sigs_exceptions.expected index 41bd5502916..4a98d1e74f1 100644 --- a/test/expressions/stan_math_sigs_exceptions.expected +++ b/test/expressions/stan_math_sigs_exceptions.expected @@ -146,12 +146,6 @@ int[] binomial_rng(int, row_vector) int[] binomial_rng(int[], vector) int[] binomial_rng(int[], row_vector) matrix block(matrix, int, int, int, int) -row_vector columns_dot_product(vector, vector) -row_vector columns_dot_product(row_vector, row_vector) -row_vector columns_dot_product(matrix, matrix) -row_vector columns_dot_self(vector) -row_vector columns_dot_self(row_vector) -row_vector columns_dot_self(matrix) int[] csr_extract_u(matrix) int[] csr_extract_v(matrix) vector csr_extract_w(matrix) @@ -194,11 +188,6 @@ real distance(vector, vector) real distance(vector, row_vector) real distance(row_vector, vector) real distance(row_vector, row_vector) -real dot_product(vector, vector) -real dot_product(vector, row_vector) -real dot_product(row_vector, vector) -real dot_product(row_vector, row_vector) -real dot_product(real[], real[]) int if_else(int, int, int) real if_else(int, real, real) vector if_else(int, vector, vector) @@ -287,11 +276,9 @@ matrix[,,,,,] lambert_wm1(matrix[,,,,,]) vector[,,,,,,] lambert_wm1(vector[,,,,,,]) row_vector[,,,,,,] lambert_wm1(row_vector[,,,,,,]) matrix[,,,,,,] lambert_wm1(matrix[,,,,,,]) -real log_determinant(matrix) vector map_rect((vector, vector, data real[], data int[]) => vector, vector, vector[], real[,], int[,]) matrix matrix_exp_multiply(matrix, matrix) -matrix multiply_lower_tri_self_transpose(matrix) real pareto_ccdf_log(real, real, vector) real pareto_ccdf_log(real, real, row_vector) real pareto_ccdf_log(real, vector, real) @@ -2536,13 +2523,7 @@ real[] pareto_type_2_rng(real[], int[], vector) real[] pareto_type_2_rng(real[], int[], row_vector) real[] pareto_type_2_rng(real[], real[], vector) real[] pareto_type_2_rng(real[], real[], row_vector) -vector rows_dot_product(vector, vector) -vector rows_dot_product(row_vector, row_vector) -vector rows_dot_product(matrix, matrix) matrix scale_matrix_exp_multiply(real, matrix, matrix) -real sd(vector) -real sd(row_vector) -real sd(matrix) real skew_normal_ccdf_log(real, real, real, vector) real skew_normal_ccdf_log(real, real, real, row_vector) real skew_normal_ccdf_log(real, real, vector, real) From ff4d4f6a3910e7f57e9be62b12c206c4a1f94bb0 Mon Sep 17 00:00:00 2001 From: Stan Jenkins Date: Tue, 6 Oct 2020 09:26:44 -0400 Subject: [PATCH 353/355] [Jenkins] auto-formatting by clang-format version 6.0.1-14 (tags/RELEASE_601/final) --- stan/math/rev/fun/dot_product.hpp | 2 +- stan/math/rev/fun/rows_dot_product.hpp | 56 +++++++++++++------------- 2 files changed, 28 insertions(+), 30 deletions(-) diff --git a/stan/math/rev/fun/dot_product.hpp b/stan/math/rev/fun/dot_product.hpp index 5ea87f55c56..fd23857f88c 100644 --- a/stan/math/rev/fun/dot_product.hpp +++ b/stan/math/rev/fun/dot_product.hpp @@ -37,7 +37,7 @@ inline return_type_t dot_product(const T1& v1, const T2& v2) { const auto& v1_ref = to_ref(v1); const auto& v2_ref = to_ref(v2); - + const auto& v1_col = as_column_vector_or_scalar(v1_ref); const auto& v2_col = as_column_vector_or_scalar(v2_ref); diff --git a/stan/math/rev/fun/rows_dot_product.hpp b/stan/math/rev/fun/rows_dot_product.hpp index 1f6a30da72a..2df9570c400 100644 --- a/stan/math/rev/fun/rows_dot_product.hpp +++ b/stan/math/rev/fun/rows_dot_product.hpp @@ -19,7 +19,7 @@ inline auto rows_dot_product(const Mat1& v1, const Mat2& v2) { check_matching_sizes("rows_dot_product", "v1", v1, "v2", v2); - if(!is_constant::value && !is_constant::value) { + if (!is_constant::value && !is_constant::value) { arena_t> arena_v1 = v1; arena_t> arena_v2 = v2; @@ -31,19 +31,19 @@ inline auto rows_dot_product(const Mat1& v1, const Mat2& v2) { res.coeffRef(m) = arena_v1_val.row(m).dot(arena_v2_val.row(m)); reverse_pass_callback( - [res, arena_v1, arena_v2, arena_v1_val, arena_v2_val]() mutable { - for (size_t j = 0; j < arena_v1_val.cols(); ++j) { - for (size_t i = 0; i < arena_v1_val.rows(); ++i) { - arena_v1.coeffRef(i, j).adj() - += arena_v2_val.coeff(i, j) * res.coeff(i).adj(); - arena_v2.coeffRef(i, j).adj() - += arena_v1_val.coeff(i, j) * res.coeff(i).adj(); + [res, arena_v1, arena_v2, arena_v1_val, arena_v2_val]() mutable { + for (size_t j = 0; j < arena_v1_val.cols(); ++j) { + for (size_t i = 0; i < arena_v1_val.rows(); ++i) { + arena_v1.coeffRef(i, j).adj() + += arena_v2_val.coeff(i, j) * res.coeff(i).adj(); + arena_v2.coeffRef(i, j).adj() + += arena_v1_val.coeff(i, j) * res.coeff(i).adj(); + } } - } - }); + }); return ret_type(res); - } else if(!is_constant::value) { + } else if (!is_constant::value) { arena_t> arena_v1 = v1; auto arena_v2_val = to_arena(value_of(v2)); @@ -52,15 +52,14 @@ inline auto rows_dot_product(const Mat1& v1, const Mat2& v2) { for (size_t m = 0; m < arena_v2_val.rows(); ++m) res.coeffRef(m) = arena_v1.row(m).val().dot(arena_v2_val.row(m)); - reverse_pass_callback( - [res, arena_v1, arena_v2_val]() mutable { - for (size_t j = 0; j < arena_v2_val.cols(); ++j) { - for (size_t i = 0; i < arena_v2_val.rows(); ++i) { - arena_v1.coeffRef(i, j).adj() - += arena_v2_val.coeff(i, j) * res.coeff(i).adj(); - } - } - }); + reverse_pass_callback([res, arena_v1, arena_v2_val]() mutable { + for (size_t j = 0; j < arena_v2_val.cols(); ++j) { + for (size_t i = 0; i < arena_v2_val.rows(); ++i) { + arena_v1.coeffRef(i, j).adj() + += arena_v2_val.coeff(i, j) * res.coeff(i).adj(); + } + } + }); return ret_type(res); } else { @@ -72,15 +71,14 @@ inline auto rows_dot_product(const Mat1& v1, const Mat2& v2) { for (size_t m = 0; m < arena_v1_val.rows(); ++m) res.coeffRef(m) = arena_v1_val.row(m).dot(arena_v2.row(m).val()); - reverse_pass_callback( - [res, arena_v2, arena_v1_val]() mutable { - for (size_t j = 0; j < arena_v1_val.cols(); ++j) { - for (size_t i = 0; i < arena_v1_val.rows(); ++i) { - arena_v2.coeffRef(i, j).adj() - += arena_v1_val.coeff(i, j) * res.coeff(i).adj(); - } - } - }); + reverse_pass_callback([res, arena_v2, arena_v1_val]() mutable { + for (size_t j = 0; j < arena_v1_val.cols(); ++j) { + for (size_t i = 0; i < arena_v1_val.rows(); ++i) { + arena_v2.coeffRef(i, j).adj() + += arena_v1_val.coeff(i, j) * res.coeff(i).adj(); + } + } + }); return ret_type(res); } From fe51835c7743c2384294c4b7ba8899259e56ee4f Mon Sep 17 00:00:00 2001 From: Ben Date: Tue, 6 Oct 2020 11:16:09 -0400 Subject: [PATCH 354/355] Updated trace_gen_quad_form (Issue #2018) --- stan/math/rev/fun/trace_gen_quad_form.hpp | 46 +++++++++++++++-------- 1 file changed, 31 insertions(+), 15 deletions(-) diff --git a/stan/math/rev/fun/trace_gen_quad_form.hpp b/stan/math/rev/fun/trace_gen_quad_form.hpp index 077b6c89460..19b8ffe0b40 100644 --- a/stan/math/rev/fun/trace_gen_quad_form.hpp +++ b/stan/math/rev/fun/trace_gen_quad_form.hpp @@ -75,26 +75,42 @@ inline var trace_gen_quad_form(const Td& D, const Ta& A, const Tb& B) { .trace(); } - reverse_pass_callback([arena_A, arena_B, arena_D, arena_A_val, arena_B_val, - arena_D_val, res]() mutable { - double C_adj = res.adj(); - auto BDT = to_ref_if::value>( - arena_B_val * arena_D_val.transpose()); + if(is_constant::value && + is_constant::value && + !is_constant::value) { + reverse_pass_callback([arena_D, arena_A_val, arena_B_val, res]() mutable { + arena_D.adj() += res.adj() * + ((arena_A_val * arena_B_val).transpose() * arena_B_val); + }); + } else if(!is_constant::value && + is_constant::value && + is_constant::value) { + reverse_pass_callback([arena_A, arena_B_val, arena_D_val, res]() mutable { + arena_A.adj() += res.adj() * + arena_B_val * arena_D_val.transpose() * arena_B_val.transpose(); + }); + } else { + reverse_pass_callback([arena_A, arena_B, arena_D, + arena_A_val, arena_B_val, + arena_D_val, res]() mutable { + double C_adj = res.adj(); + auto BDT = to_ref_if::value>(arena_B_val * arena_D_val.transpose()); - auto AB - = to_ref_if::value>(arena_A_val * arena_B_val); + auto AB + = to_ref_if::value>(arena_A_val * arena_B_val); - if (!is_constant::value) - arena_A.adj() += C_adj * BDT * arena_B_val.transpose(); + if (!is_constant::value) + arena_A.adj() += C_adj * BDT * arena_B_val.transpose(); - if (!is_constant::value) - arena_B.adj() + if (!is_constant::value) + arena_B.adj() += C_adj * (AB * arena_D_val + arena_A_val.transpose() * BDT); - if (!is_constant::value) - arena_D.adj() += C_adj * (AB.transpose() * arena_B_val); - }); - + if (!is_constant::value) + arena_D.adj() += C_adj * (AB.transpose() * arena_B_val); + }); + } + return res; } From 654aa5119a3d7870c527cb9f3cedb487b72474e3 Mon Sep 17 00:00:00 2001 From: Stan Jenkins Date: Tue, 6 Oct 2020 15:17:29 +0000 Subject: [PATCH 355/355] [Jenkins] auto-formatting by clang-format version 6.0.0-1ubuntu2~16.04.1 (tags/RELEASE_600/final) --- stan/math/rev/fun/trace_gen_quad_form.hpp | 41 +++++++++++------------ 1 file changed, 20 insertions(+), 21 deletions(-) diff --git a/stan/math/rev/fun/trace_gen_quad_form.hpp b/stan/math/rev/fun/trace_gen_quad_form.hpp index 19b8ffe0b40..b09c2c7ab3f 100644 --- a/stan/math/rev/fun/trace_gen_quad_form.hpp +++ b/stan/math/rev/fun/trace_gen_quad_form.hpp @@ -75,42 +75,41 @@ inline var trace_gen_quad_form(const Td& D, const Ta& A, const Tb& B) { .trace(); } - if(is_constant::value && - is_constant::value && - !is_constant::value) { + if (is_constant::value && is_constant::value + && !is_constant::value) { reverse_pass_callback([arena_D, arena_A_val, arena_B_val, res]() mutable { - arena_D.adj() += res.adj() * - ((arena_A_val * arena_B_val).transpose() * arena_B_val); + arena_D.adj() + += res.adj() + * ((arena_A_val * arena_B_val).transpose() * arena_B_val); }); - } else if(!is_constant::value && - is_constant::value && - is_constant::value) { + } else if (!is_constant::value && is_constant::value + && is_constant::value) { reverse_pass_callback([arena_A, arena_B_val, arena_D_val, res]() mutable { - arena_A.adj() += res.adj() * - arena_B_val * arena_D_val.transpose() * arena_B_val.transpose(); + arena_A.adj() += res.adj() * arena_B_val * arena_D_val.transpose() + * arena_B_val.transpose(); }); } else { - reverse_pass_callback([arena_A, arena_B, arena_D, - arena_A_val, arena_B_val, - arena_D_val, res]() mutable { + reverse_pass_callback([arena_A, arena_B, arena_D, arena_A_val, arena_B_val, + arena_D_val, res]() mutable { double C_adj = res.adj(); - auto BDT = to_ref_if::value>(arena_B_val * arena_D_val.transpose()); + auto BDT = to_ref_if::value>( + arena_B_val * arena_D_val.transpose()); - auto AB - = to_ref_if::value>(arena_A_val * arena_B_val); + auto AB = to_ref_if::value>(arena_A_val + * arena_B_val); if (!is_constant::value) - arena_A.adj() += C_adj * BDT * arena_B_val.transpose(); + arena_A.adj() += C_adj * BDT * arena_B_val.transpose(); if (!is_constant::value) - arena_B.adj() - += C_adj * (AB * arena_D_val + arena_A_val.transpose() * BDT); + arena_B.adj() + += C_adj * (AB * arena_D_val + arena_A_val.transpose() * BDT); if (!is_constant::value) - arena_D.adj() += C_adj * (AB.transpose() * arena_B_val); + arena_D.adj() += C_adj * (AB.transpose() * arena_B_val); }); } - + return res; }