diff --git a/stan/math/fwd/mat/meta/operands_and_partials.hpp b/stan/math/fwd/mat/meta/operands_and_partials.hpp index ac6b1d2f9eb46e6e93f4118b679d39d17c02a254..695e26f3c7ce0ba5e2165d0281255afc495b5f3a 100644 --- a/stan/math/fwd/mat/meta/operands_and_partials.hpp +++ b/stan/math/fwd/mat/meta/operands_and_partials.hpp @@ -9,35 +9,34 @@ namespace stan { namespace math { namespace detail { - template <typename ViewElt, typename Op, typename Dx> - class ops_partials_edge_vec_fwd - : public ops_partials_edge_mat_prim<ViewElt, Op, -1, 1> { + // Vectorized Univariate + template <typename ViewElt, typename Dx> + class ops_partials_edge<ViewElt, std::vector<fvar<Dx> > > + : public ops_partials_edge_mat_prim<ViewElt, std::vector<fvar<Dx> >, -1, 1> { public: - ops_partials_edge_vec_fwd(const Op& ops) - : ops_partials_edge_mat_prim<ViewElt, Op, -1, 1>(ops) {} + explicit ops_partials_edge(const std::vector<fvar<Dx> >& ops) + : ops_partials_edge_mat_prim<ViewElt, std::vector<fvar<Dx> >, -1, 1>(ops) {} Dx dx() { Dx derivative(0); for (int i = 0; i < this->size(); ++i) { - derivative += this->partials[i] * this->operands[i].d_; + derivative += this->partials(i) * this->operands[i].d_; } return derivative; } }; - - // Vectorized Univariate - template <typename ViewElt, typename Dx> - class ops_partials_edge<ViewElt, std::vector<fvar<Dx> > > - : public ops_partials_edge_vec_fwd<ViewElt, std::vector<fvar<Dx> >, Dx> { - public: - explicit ops_partials_edge(const std::vector<fvar<Dx> >& ops) - : ops_partials_edge_vec_fwd<ViewElt, std::vector<fvar<Dx> >, Dx>(ops) {} - }; template <typename ViewElt, typename Dx, int R, int C> class ops_partials_edge<ViewElt, Eigen::Matrix<fvar<Dx>, R, C> > - : public ops_partials_edge_vec_fwd<ViewElt, Eigen::Matrix<fvar<Dx>, R, C>, Dx> { + : public ops_partials_edge_mat_prim<ViewElt, Eigen::Matrix<fvar<Dx>, R, C>, R, C> { public: explicit ops_partials_edge(const Eigen::Matrix<fvar<Dx>, R, C>& ops) - : ops_partials_edge_vec_fwd<ViewElt, Eigen::Matrix<fvar<Dx>, R, C>, Dx>(ops) {} + : ops_partials_edge_mat_prim<ViewElt, Eigen::Matrix<fvar<Dx>, R, C>, R, C>(ops) {} + Dx dx() { + Dx derivative(0); + for (int i = 0; i < this->size(); ++i) { + derivative += this->partials(i) * this->operands(i).d_; + } + return derivative; + } }; // Multivariate; vectors of eigen types diff --git a/stan/math/fwd/scal/meta/OperandsAndPartials.hpp b/stan/math/fwd/scal/meta/OperandsAndPartials.hpp deleted file mode 100644 index 61a269c0fd3e51e08e26757075cc7dc429c80555..0000000000000000000000000000000000000000 --- a/stan/math/fwd/scal/meta/OperandsAndPartials.hpp +++ /dev/null @@ -1,183 +0,0 @@ -#ifndef STAN_MATH_FWD_SCAL_META_OPERANDSANDPARTIALS_HPP -#define STAN_MATH_FWD_SCAL_META_OPERANDSANDPARTIALS_HPP - -#include <stan/math/prim/scal/meta/is_constant_struct.hpp> -#include <stan/math/prim/scal/meta/length.hpp> -#include <stan/math/prim/scal/meta/OperandsAndPartials.hpp> -#include <stan/math/fwd/core.hpp> - -namespace stan { - namespace math { - - namespace { - template <typename T_derivative, - typename T, - typename T_partials, - bool is_vec = is_vector<T>::value, - bool is_const = is_constant_struct<T>::value> - struct increment_derivative { - inline T_derivative operator()(const T& x, - const T_partials& d_dx) { - return 0; - } - }; - - template <typename T_derivative, - typename T, - typename T_partials> - struct increment_derivative<T_derivative, T, T_partials, false, false> { - inline T_derivative operator()(const T& x, - const T_partials& d_dx) { - return d_dx[0] * x.d_; - } - }; - - template <typename T_derivative, - typename T, - typename T_partials> - struct increment_derivative<T_derivative, T, T_partials, true, false> { - inline T_derivative operator()(const T& x, - const T_partials& d_dx) { - T_derivative derivative(0); - for (size_t n = 0; n < length(x); n++) - derivative += d_dx[n] * x[n].d_; - return derivative; - } - }; - - template <typename T, - typename T1, typename D1, typename T2, typename D2, - typename T3, typename D3, typename T4, typename D4, - typename T5, typename D5, typename T6, typename D6> - fvar<T> partials_to_fvar(T& logp, - const T1& x1, D1& d_x1, - const T2& x2, D2& d_x2, - const T3& x3, D3& d_x3, - const T4& x4, D4& d_x4, - const T5& x5, D5& d_x5, - const T6& x6, D6& d_x6) { - T deriv = 0; - if (!is_constant_struct<T1>::value) - deriv += increment_derivative<T, T1, D1>()(x1, d_x1); - if (!is_constant_struct<T2>::value) - deriv += increment_derivative<T, T2, D2>()(x2, d_x2); - if (!is_constant_struct<T3>::value) - deriv += increment_derivative<T, T3, D3>()(x3, d_x3); - if (!is_constant_struct<T4>::value) - deriv += increment_derivative<T, T4, D4>()(x4, d_x4); - if (!is_constant_struct<T5>::value) - deriv += increment_derivative<T, T5, D5>()(x5, d_x5); - if (!is_constant_struct<T6>::value) - deriv += increment_derivative<T, T6, D6>()(x6, d_x6); - return fvar<T>(logp, deriv); - } - } - - /** - * This class builds partial derivatives with respect to a set of - * operands. There are two reason for the generality of this - * class. The first is to handle vector and scalar arguments - * without needing to write additional code. The second is to use - * this class for writing probability distributions that handle - * primitives, reverse mode, and forward mode variables - * seamlessly. - * - * This is the partial template specialization for when the return - * type is fvar<T>. - * - * @tparam T1 First set of operands. - * @tparam T2 Second set of operands. - * @tparam T3 Third set of operands. - * @tparam T4 Fourth set of operands. - * @tparam T5 Fifth set of operands. - * @tparam T6 Sixth set of operands. - * @tparam T_return_type Return type of the expression. This defaults - * to a template metaprogram that calculates the scalar promotion of - * T1 -- T6. - */ - template<typename T1, typename T2, typename T3, - typename T4, typename T5, typename T6, - typename T_partials_return> - struct OperandsAndPartials<T1, T2, T3, T4, T5, T6, - fvar<T_partials_return> > { - typedef fvar<T_partials_return> T_return_type; - - const T1& x1_; - const T2& x2_; - const T3& x3_; - const T4& x4_; - const T5& x5_; - const T6& x6_; - - size_t n_partials; - T_partials_return* all_partials; - - VectorView<T_partials_return, - is_vector<T1>::value, - is_constant_struct<T1>::value> d_x1; - VectorView<T_partials_return, - is_vector<T2>::value, - is_constant_struct<T2>::value> d_x2; - VectorView<T_partials_return, - is_vector<T3>::value, - is_constant_struct<T3>::value> d_x3; - VectorView<T_partials_return, - is_vector<T4>::value, - is_constant_struct<T4>::value> d_x4; - VectorView<T_partials_return, - is_vector<T5>::value, - is_constant_struct<T5>::value> d_x5; - VectorView<T_partials_return, - is_vector<T6>::value, - is_constant_struct<T6>::value> d_x6; - - OperandsAndPartials(const T1& x1 = 0, const T2& x2 = 0, const T3& x3 = 0, - const T4& x4 = 0, const T5& x5 = 0, const T6& x6 = 0) - : x1_(x1), x2_(x2), x3_(x3), x4_(x4), x5_(x5), x6_(x6), - n_partials(!is_constant_struct<T1>::value * length(x1) + - !is_constant_struct<T2>::value * length(x2) + - !is_constant_struct<T3>::value * length(x3) + - !is_constant_struct<T4>::value * length(x4) + - !is_constant_struct<T5>::value * length(x5) + - !is_constant_struct<T6>::value * length(x6)), - all_partials(new T_partials_return[n_partials]), - d_x1(all_partials), - d_x2(all_partials - + (!is_constant_struct<T1>::value) * length(x1)), - d_x3(all_partials - + (!is_constant_struct<T1>::value) * length(x1) - + (!is_constant_struct<T2>::value) * length(x2)), - d_x4(all_partials - + (!is_constant_struct<T1>::value) * length(x1) - + (!is_constant_struct<T2>::value) * length(x2) - + (!is_constant_struct<T3>::value) * length(x3)), - d_x5(all_partials - + (!is_constant_struct<T1>::value) * length(x1) - + (!is_constant_struct<T2>::value) * length(x2) - + (!is_constant_struct<T3>::value) * length(x3) - + (!is_constant_struct<T4>::value) * length(x4)), - d_x6(all_partials - + (!is_constant_struct<T1>::value) * length(x1) - + (!is_constant_struct<T2>::value) * length(x2) - + (!is_constant_struct<T3>::value) * length(x3) - + (!is_constant_struct<T4>::value) * length(x4) - + (!is_constant_struct<T5>::value) * length(x5)) { - std::fill(all_partials, all_partials + n_partials, 0); - } - - T_return_type - value(T_partials_return value) { - return partials_to_fvar(value, - x1_, d_x1, x2_, d_x2, - x3_, d_x3, x4_, d_x4, - x5_, d_x4, x6_, d_x5); - } - - ~OperandsAndPartials() { - delete[] all_partials; - } - }; - - } -} -#endif diff --git a/stan/math/fwd/scal/meta/operands_and_partials.hpp b/stan/math/fwd/scal/meta/operands_and_partials.hpp index 77fc9b0c286d8d156948765a572db7fbadb3f3fb..c9dc55bed7ee174ffea85c26846fabfdb81a342c 100644 --- a/stan/math/fwd/scal/meta/operands_and_partials.hpp +++ b/stan/math/fwd/scal/meta/operands_and_partials.hpp @@ -15,80 +15,40 @@ namespace stan { ops_partials_edge(const fvar<Dx>& op) : ops_partials_edge_singular<ViewElt, fvar<Dx> >(op) {} Dx dx() { - return this->partial * this->operand.d_; + return this->partials[0] * this->operand.d_; } }; + } // end namespace detail + template <typename Op1, typename Op2, typename Op3, typename Op4, + typename Dx> + class operands_and_partials<Op1, Op2, Op3, Op4, fvar<Dx> > { + public: + // these are going to be stack local and get collected + detail::ops_partials_edge<Dx, Op1> edge1_; + detail::ops_partials_edge<Dx, Op2> edge2_; + detail::ops_partials_edge<Dx, Op3> edge3_; + detail::ops_partials_edge<Dx, Op4> edge4_; + typedef fvar<Dx> T_return_type; + operands_and_partials(const Op1& o1) + : edge1_(o1) { } + operands_and_partials(const Op1& o1, const Op2& o2) + : edge1_(o1), edge2_(o2) { } + operands_and_partials(const Op1& o1, const Op2& o2, const Op3& o3) + : edge1_(o1), edge2_(o2), edge3_(o3) { } + operands_and_partials(const Op1& o1, const Op2& o2, const Op3& o3, const Op4& o4) + : edge1_(o1), edge2_(o2), edge3_(o3), edge4_(o4) { } - template <typename Op1, typename Op2, typename Op3, typename Op4, - typename Dx> - class operands_and_partials<Op1, Op2, Op3, Op4, fvar<Dx> > { - public: - typedef fvar<Dx> T_return_type; - operands_and_partials(const Op1& o1) - : edge1_(o1) { } - operands_and_partials(const Op1& o1, const Op2& o2) - : edge1_(o1), edge2_(o2) { } - operands_and_partials(const Op1& o1, const Op2& o2, const Op3& o3) - : edge1_(o1), edge2_(o2), edge3_(o3) { } - operands_and_partials(const Op1& o1, const Op2& o2, const Op3& o3, const Op4& o4) - : edge1_(o1), edge2_(o2), edge3_(o3), edge4_(o4) { } - - void increment_dx1(const int n, const Dx& adj) { - edge1_.increment_dx(n, adj); - } - void increment_dx2(const int n, const Dx& adj) { - edge2_.increment_dx(n, adj); - } - void increment_dx3(const int n, const Dx& adj) { - edge3_.increment_dx(n, adj); - } - void increment_dx4(const int n, const Dx& adj) { - edge4_.increment_dx(n, adj); - } - - template<typename T> - typename boost::enable_if_c<is_vector_like<Op1>::value - && is_vector_like<T>::value, void>::type - increment_dx1_vector(const int n, const T& adj) { - edge1_.increment_dx_vector(n, adj); - } - template<typename T> - typename boost::enable_if_c<is_vector_like<Op2>::value - && is_vector_like<T>::value, void>::type - increment_dx2_vector(const int n, const T& adj) { - edge2_.increment_dx_vector(n, adj); - } - template<typename T> - typename boost::enable_if_c<is_vector_like<Op3>::value - && is_vector_like<T>::value, void>::type - increment_dx3_vector(const int n, const T& adj) { - edge3_.increment_dx_vector(n, adj); - } - template<typename T> - typename boost::enable_if_c<is_vector_like<Op4>::value - && is_vector_like<T>::value, void>::type - increment_dx4_vector(const int n, const T& adj) { - edge4_.increment_dx_vector(n, adj); - } - - // this is what matters in terms of going on autodiff stack - T_return_type build(Dx value) { - // Just call chain here and end up with an fvar(val, adj) - Dx deriv = 0; - deriv += edge1_.dx(); - deriv += edge2_.dx(); - deriv += edge3_.dx(); - deriv += edge4_.dx(); - return T_return_type(value, deriv); - }; - private: - // these are going to be stack local and get collected - ops_partials_edge<Dx, Op1> edge1_; - ops_partials_edge<Dx, Op2> edge2_; - ops_partials_edge<Dx, Op3> edge3_; - ops_partials_edge<Dx, Op4> edge4_; + // this is what matters in terms of going on autodiff stack + T_return_type build(Dx value) { + // Just call chain here and end up with an fvar(val, adj) + Dx deriv = 0; + deriv += edge1_.dx(); + deriv += edge2_.dx(); + deriv += edge3_.dx(); + deriv += edge4_.dx(); + return T_return_type(value, deriv); }; - } // end namespace detail + }; } } diff --git a/stan/math/prim/arr/meta/VectorView.hpp b/stan/math/prim/arr/meta/VectorView.hpp deleted file mode 100644 index 4759217b2477129d1f7c31bc78785f986bd745f2..0000000000000000000000000000000000000000 --- a/stan/math/prim/arr/meta/VectorView.hpp +++ /dev/null @@ -1,42 +0,0 @@ -#ifndef STAN_MATH_ARR_SCAL_META_VECTORVIEW_HPP -#define STAN_MATH_ARR_SCAL_META_VECTORVIEW_HPP - -#include <stan/math/prim/scal/meta/VectorView.hpp> -#include <vector> - -namespace stan { - - template <typename T> - class VectorView<std::vector<T>, true, false> { - public: - typedef typename scalar_type<T>::type scalar_t; - - template <typename X> - explicit VectorView(X& x) : x_(&x[0]) { } - - scalar_t& operator[](int i) { - return x_[i]; - } - - private: - scalar_t* x_; - }; - - template <typename T> - class VectorView<const std::vector<T>, true, false> { - public: - typedef typename boost::add_const<typename scalar_type<T>::type>::type - scalar_t; - - template <typename X> - explicit VectorView(X& x) : x_(&x[0]) { } - - scalar_t& operator[](int i) const { - return x_[i]; - } - private: - scalar_t* x_; - }; - -} -#endif diff --git a/stan/math/prim/mat/meta/VectorView.hpp b/stan/math/prim/mat/meta/VectorView.hpp deleted file mode 100644 index d1fe67d9e932f2cb2bc8f0accc45e895b226ad2d..0000000000000000000000000000000000000000 --- a/stan/math/prim/mat/meta/VectorView.hpp +++ /dev/null @@ -1,43 +0,0 @@ -#ifndef STAN_MATH_MAT_SCAL_META_VECTORVIEW_HPP -#define STAN_MATH_MAT_SCAL_META_VECTORVIEW_HPP - -#include <stan/math/prim/mat/fun/Eigen.hpp> -#include <stan/math/prim/mat/meta/scalar_type.hpp> -#include <stan/math/prim/scal/meta/VectorView.hpp> -#include <boost/type_traits.hpp> - -namespace stan { - - template <typename T, int R, int C> - class VectorView<Eigen::Matrix<T, R, C>, true, false> { - public: - typedef typename scalar_type<T>::type scalar_t; - - template <typename X> - explicit VectorView(X& x) : x_(x.data()) { } - - scalar_t& operator[](int i) { - return x_[i]; - } - private: - scalar_t* x_; - }; - - template <typename T, int R, int C> - class VectorView<const Eigen::Matrix<T, R, C>, true, false> { - public: - typedef typename boost::add_const<typename scalar_type<T>::type>::type - scalar_t; - - template <typename X> - explicit VectorView(X& x) : x_(x.data()) { } - - scalar_t& operator[](int i) const { - return x_[i]; - } - private: - scalar_t* x_; - }; - -} -#endif diff --git a/stan/math/prim/mat/meta/operands_and_partials.hpp b/stan/math/prim/mat/meta/operands_and_partials.hpp index 79106441f6d3b4078f3714a6976a0ba228fbf6b5..56c49c9143c8d66bd4087f475c552ecafa038025 100644 --- a/stan/math/prim/mat/meta/operands_and_partials.hpp +++ b/stan/math/prim/mat/meta/operands_and_partials.hpp @@ -3,30 +3,48 @@ #include <stan/math/prim/mat/fun/typedefs.hpp> #include <stan/math/prim/scal/meta/operands_and_partials.hpp> +#include <stan/math/prim/scal/meta/broadcast_array.hpp> #include <vector> namespace stan { namespace math { namespace detail { + template <typename T, typename Orig, int R, int C> + struct zero_vec_or_mat { + typedef Eigen::Matrix<T, R, C> ret; + static ret zero(const Orig& in) { + return ret::Zero(in.rows(), in.cols()); + } + }; + template <typename T, typename Orig> + struct zero_vec_or_mat<T, Orig, -1, 1> { + typedef Eigen::Matrix<T, -1, 1> ret; + static ret zero(const Orig& in) { + return ret::Zero(in.size(), 1); + } + }; + template <typename T, typename Orig> + struct zero_vec_or_mat<T, Orig, 1, -1> { + typedef Eigen::Matrix<T, 1, -1> ret; + static ret zero(const Orig& in) { + return ret::Zero(1, in.size()); + } + }; + // Handles all the vectorized cases for "views of scalars": // ViewElt = double, Arg = std::vector<var> d_ holds vector<double> // ViewElt = double, Arg = std::vector<double> d_ holds dummy // Op will always be some container of vars template <typename ViewElt, typename Op, int R, int C> class ops_partials_edge_mat_prim { - protected: + public: typedef Eigen::Matrix<ViewElt, R, C> partials_t; const Op& operands; partials_t partials; - public: + broadcast_array<partials_t> partials_vec; ops_partials_edge_mat_prim(const Op& ops) - : operands(ops), partials(partials_t::Zero(ops.size())) {} - void increment_dx(int n, const ViewElt& adj) { - partials[n] += adj; - } - void increment_dx_vector(int /*n*/, const partials_t& adj) { - partials += adj; - } + : operands(ops), partials(zero_vec_or_mat<ViewElt, Op, R, C>::zero(ops)), + partials_vec(partials) {} void dump_partials(double* partials) { for (int i = 0; i < this->partials.size(); ++i) { partials[i] = this->partials(i); @@ -41,21 +59,17 @@ namespace stan { class ops_partials_edge_multivariate_prim { public: typedef Eigen::Matrix<ViewElt, Eigen::Dynamic, Eigen::Dynamic> partial_t; + std::vector<partial_t> partials_vec; + const std::vector<Op>& operands; ops_partials_edge_multivariate_prim(const std::vector<Op>& ops) - : partials(ops.size()), operands(ops) { + : partials_vec(ops.size()), operands(ops) { for (size_t i = 0; i < ops.size(); ++i) { - partials[i] = partial_t::Zero(ops[i].rows(), ops[i].cols()); + partials_vec[i] = partial_t::Zero(ops[i].rows(), ops[i].cols()); } } - void increment_dx_vector(int n, const partial_t& adj) { - partials[n] += adj; - } int size() { return this->operands.size() * this->operands[0].size(); } - protected: - std::vector<partial_t> partials; - const std::vector<Op>& operands; }; } } diff --git a/stan/math/prim/scal/meta/OperandsAndPartials.hpp b/stan/math/prim/scal/meta/OperandsAndPartials.hpp deleted file mode 100644 index 0d5e684c364b2e75fa338c986710342e5d45b8d6..0000000000000000000000000000000000000000 --- a/stan/math/prim/scal/meta/OperandsAndPartials.hpp +++ /dev/null @@ -1,74 +0,0 @@ -#ifndef STAN_MATH_PRIM_SCAL_META_OPERANDSANDPARTIALS_HPP -#define STAN_MATH_PRIM_SCAL_META_OPERANDSANDPARTIALS_HPP - -#include <stan/math/prim/scal/meta/return_type.hpp> -#include <stan/math/prim/scal/meta/VectorView.hpp> - -namespace stan { - namespace math { - - /** - * This class builds partial derivatives with respect to a set of - * operands. There are two reason for the generality of this - * class. The first is to handle vector and scalar arguments - * without needing to write additional code. The second is to use - * this class for writing probability distributions that handle - * primitives, reverse mode, and forward mode variables - * seamlessly. - * - * The default template class handles the case where the arguments - * are primitive. There are template specializations for reverse - * mode and forward mode. - * - * @tparam T1 First set of operands. - * @tparam T2 Second set of operands. - * @tparam T3 Third set of operands. - * @tparam T4 Fourth set of operands. - * @tparam T5 Fifth set of operands. - * @tparam T6 Sixth set of operands. - * @tparam T_return_type Return type of the expression. This defaults - * to a template metaprogram that calculates the scalar promotion of - * T1 -- T6. - */ - template<typename T1 = double, typename T2 = double, typename T3 = double, - typename T4 = double, typename T5 = double, typename T6 = double, - typename T_return_type - = typename stan::return_type<T1, T2, T3, T4, T5, T6>::type> - struct OperandsAndPartials { - VectorView<T_return_type, false, true> d_x1; - VectorView<T_return_type, false, true> d_x2; - VectorView<T_return_type, false, true> d_x3; - VectorView<T_return_type, false, true> d_x4; - VectorView<T_return_type, false, true> d_x5; - VectorView<T_return_type, false, true> d_x6; - - /** - * Constructor. - * - * @param x1 first set of operands - * @param x2 second set of operands - * @param x3 third set of operands - * @param x4 fourth set of operands - * @param x5 fifth set of operands - * @param x6 sixth set of operands - */ - OperandsAndPartials(const T1& x1 = 0, const T2& x2 = 0, - const T3& x3 = 0, const T4& x4 = 0, - const T5& x5 = 0, const T6& x6 = 0) { } - - /** - * Returns a T_return_type with the value specified with - * the partial derivatves. - * - * @param[in] value Value of the variable - * @returns a variable with the appropriate value - */ - T_return_type - value(double value) { - return value; - } - }; - - } -} -#endif diff --git a/stan/math/prim/scal/meta/VectorView.hpp b/stan/math/prim/scal/meta/VectorView.hpp deleted file mode 100644 index 1a34b3c1e5a5c9f514195657834763987b13e604..0000000000000000000000000000000000000000 --- a/stan/math/prim/scal/meta/VectorView.hpp +++ /dev/null @@ -1,144 +0,0 @@ -#ifndef STAN_MATH_PRIM_SCAL_META_VECTORVIEW_HPP -#define STAN_MATH_PRIM_SCAL_META_VECTORVIEW_HPP - -#include <stan/math/prim/scal/meta/scalar_type.hpp> -#include <stan/math/prim/scal/meta/is_vector_like.hpp> -#include <boost/type_traits.hpp> -#include <stdexcept> - -namespace stan { - - /** - * VectorView is a template expression that is constructed with a - * container or scalar, which it then allows to be used as an array - * using <code>operator[]</code>. - * - * For a scalar value, any index returns the reference or pointer - * used to construct the view. - * - * For a container, the index returns a reference to the position in - * the underlying container used to construct the view. WARNING: - * There is no bounds checking for container indices and they will - * segfault if accessed beyond their boundaries. - * - * The first use is to read arguments to prob functions as vectors, - * even if scalars, so they can be read by common code (and scalars - * automatically broadcast up to behave like vectors) : VectorView - * of immutable const array of double* (no allocation). - * - * The second use is to build up derivatives into common storage : - * VectorView of mutable shared array (no allocation because - * allocated on auto-diff arena memory). - * - * Because it deals with references to its inputs, it is up to the - * client of VectorView to ensure that the container being wrapped - * is not modified while the VectorView is in use in such a way as - * to disrupt the indexing. Similarly, because it deals with - * references, it cannot be constructed with a literal or expression. - * - * @tparam T Type of scalar or container being wrapped. - * @tparam is_array True if underlying type T can be indexed with - * operator[]. - * @tparam throw_if_accessed True if the behavior is to throw an - * exception whenever <code>operator[]</code> is called. - */ - template <typename T, - bool is_array = stan::is_vector_like<T>::value, - bool throw_if_accessed = false> - class VectorView { - public: - typedef typename - boost::conditional<boost::is_const<T>::value, - typename boost::add_const< - typename scalar_type<T>::type>::type, - typename scalar_type<T>::type>::type scalar_t; - - template <typename X> - explicit VectorView(X x) { - throw std::logic_error("VectorView: the default template " - "specialization not implemented"); - } - - scalar_t& operator[](int i) { - throw std::logic_error("VectorView: the default template " - "specialization not implemented"); - } - - scalar_t& operator[](int i) const { - throw std::logic_error("VectorView: the default template " - "specialization not implemented"); - } - }; - - template <typename T, bool is_array> - class VectorView<T, is_array, true> { - public: - typedef typename - boost::conditional<boost::is_const<T>::value, - typename boost::add_const< - typename scalar_type<T>::type>::type, - typename scalar_type<T>::type>::type scalar_t; - VectorView() { } - - template <typename X> - explicit VectorView(X x) { } - - scalar_t& operator[](int i) { - throw std::logic_error("VectorView: this cannot be accessed"); - } - - scalar_t& operator[](int i) const { - throw std::logic_error("VectorView: this cannot be accessed"); - } - }; - - // this covers non-vectors: double - template <typename T> - class VectorView<T, false, false> { - public: - typedef typename - boost::conditional<boost::is_const<T>::value, - typename boost::add_const< - typename scalar_type<T>::type>::type, - typename scalar_type<T>::type>::type scalar_t; - - explicit VectorView(scalar_t& x) : x_(&x) { } - - explicit VectorView(scalar_t* x) : x_(x) { } - - scalar_t& operator[](int i) { - return *x_; - } - - scalar_t& operator[](int i) const { - return *x_; - } - private: - scalar_t* x_; - }; - - // this covers raw memory: double* - template <typename T> - class VectorView<T, true, false> { - public: - typedef typename - boost::conditional<boost::is_const<T>::value, - typename boost::add_const< - typename scalar_type<T>::type>::type, - typename scalar_type<T>::type>::type scalar_t; - - explicit VectorView(scalar_t* x) : x_(x) { } - - scalar_t& operator[](int i) { - return x_[i]; - } - - scalar_t& operator[](int i) const { - return x_[i]; - } - - private: - scalar_t* x_; - }; -} -#endif diff --git a/stan/math/prim/scal/meta/broadcast_array.hpp b/stan/math/prim/scal/meta/broadcast_array.hpp new file mode 100644 index 0000000000000000000000000000000000000000..6be607e4c38d3399c446dd15390cc72eb0949262 --- /dev/null +++ b/stan/math/prim/scal/meta/broadcast_array.hpp @@ -0,0 +1,34 @@ +#ifndef STAN_MATH_PRIM_SCAL_META_BROADCAST_ARRAY_HPP +#define STAN_MATH_PRIM_SCAL_META_BROADCAST_ARRAY_HPP + +namespace stan { + namespace math { + namespace detail { + template <typename T> + class broadcast_array { + private: + T& prim_; + + public: + explicit broadcast_array(T& prim): prim_(prim) {} + + T& operator[] (int /*i*/) { + return prim_; + } + int size() { return 1; } + }; + + template <> + class broadcast_array<void> { + public: + explicit broadcast_array() {} + double& operator[] (int /*i*/) { + throw std::logic_error("Don't do this"); + } + int size() { return 0; } + }; + } // end namespace detail + } // end namespace math +} // end namespace stan + +#endif diff --git a/stan/math/prim/scal/meta/operands_and_partials.hpp b/stan/math/prim/scal/meta/operands_and_partials.hpp index a14a0e98427f959391753f766e87dcc0fe36c606..b49195a9565073d0c0e70090af4dd20f899bb8e3 100644 --- a/stan/math/prim/scal/meta/operands_and_partials.hpp +++ b/stan/math/prim/scal/meta/operands_and_partials.hpp @@ -2,6 +2,7 @@ #define STAN_MATH_PRIM_SCAL_META_OPERANDS_AND_PARTIALS_HPP #include <stan/math/prim/scal/meta/return_type.hpp> +#include <stan/math/prim/scal/meta/broadcast_array.hpp> namespace stan { namespace math { @@ -52,40 +53,10 @@ namespace stan { public: ops_partials_edge() { } ops_partials_edge(const Op& /* a */){ } - void increment_dx(int /* n */, const ViewElt& /* adj */) {} void dump_partials(ViewElt* /* partials */) {} // used for vars void dump_operands(void* /* operands */) {} // also used for reverse mode double dx() const { return 0; } //used for fvars - int size() {return 0; } - }; - - template <typename Op1 = double, typename Op2 = double, - typename Op3 = double, typename Op4 = double, - typename T_return_type = typename return_type<Op1, Op2, Op3, Op4>::type> - class operands_and_partials { - public: - operands_and_partials(const Op1& op1) {} - operands_and_partials(const Op1& op1, const Op2& op2) {} - operands_and_partials(const Op1& op1, const Op2& op2, const Op3& op3) {} - operands_and_partials(const Op1& op1, const Op2& op2, const Op3& op3, const Op4& op4) {} - - void increment_dx1(int, double) {} - void increment_dx2(int, double) {} - void increment_dx3(int, double) {} - void increment_dx4(int, double) {} - - template <typename PartialVec> - void increment_dx1_vector(int, PartialVec) {} - template <typename PartialVec> - void increment_dx2_vector(int, PartialVec) {} - template <typename PartialVec> - void increment_dx3_vector(int, PartialVec) {} - template <typename PartialVec> - void increment_dx4_vector(int, PartialVec) {} - - double build(const double value) { - return value; - } + int size() { return 0; } }; // Base class shared between fvar and var specializations of uni- and @@ -93,21 +64,45 @@ namespace stan { // Singular version - underlying Var is the same as Op, so there's just one. template <typename ViewElt, typename Op> class ops_partials_edge_singular { - protected: + public: const Op& operand; ViewElt partial; - - public: - ops_partials_edge_singular(const Op& a) : operand(a), partial(0) { } - void increment_dx(int /*n*/, const ViewElt& adj) { - partial += adj; - } + broadcast_array<ViewElt> partials; + ops_partials_edge_singular(const Op& a) : operand(a), partial(0), partials(partial) { } // dump_operands implemented in specialization - int size() { - return 1; - } + int size() { return 1; } + }; + + template<> + struct ops_partials_edge<double, double> { + ops_partials_edge() {} + ops_partials_edge(const double& /* a */) {} + broadcast_array<void> partials; + void dump_operands(void*) {} + void dump_partials(void*) {} + double dx() { return 0; } + int size() { return 0; } }; } // end namespace detail + template <typename Op1 = double, typename Op2 = double, + typename Op3 = double, typename Op4 = double, + typename T_return_type = typename return_type<Op1, Op2, Op3, Op4>::type> + class operands_and_partials { + public: + operands_and_partials(const Op1& op1) {} + operands_and_partials(const Op1& op1, const Op2& op2) {} + operands_and_partials(const Op1& op1, const Op2& op2, const Op3& op3) {} + operands_and_partials(const Op1& op1, const Op2& op2, const Op3& op3, const Op4& op4) {} + + double build(const double value) { + return value; + } + + detail::ops_partials_edge<double, Op1> edge1_; + detail::ops_partials_edge<double, Op2> edge2_; + detail::ops_partials_edge<double, Op3> edge3_; + detail::ops_partials_edge<double, Op4> edge4_; + }; } // end namespace math } // end namespace stan #endif diff --git a/stan/math/prim/scal/meta/partials_return_type.hpp b/stan/math/prim/scal/meta/partials_return_type.hpp index a173265cd4eb42c707bf3169ade103f2e8fdd747..9d068f4c4d98cee17a3fa466d0a7d055ec60b29b 100644 --- a/stan/math/prim/scal/meta/partials_return_type.hpp +++ b/stan/math/prim/scal/meta/partials_return_type.hpp @@ -25,7 +25,5 @@ namespace stan { ::type type; }; - } #endif - diff --git a/stan/math/prim/scal/meta/partials_type.hpp b/stan/math/prim/scal/meta/partials_type.hpp index 0a56a8418862ef8e235def667d01519615403dd4..dd23d4275cb5200ca4cb5a6b365ed43ab4a3ba5a 100644 --- a/stan/math/prim/scal/meta/partials_type.hpp +++ b/stan/math/prim/scal/meta/partials_type.hpp @@ -10,4 +10,3 @@ namespace stan { } #endif - diff --git a/stan/math/rev/mat/meta/operands_and_partials.hpp b/stan/math/rev/mat/meta/operands_and_partials.hpp index 4322d5817af7b57af866724f08aaed4e9c7f2666..d12477e97b016a3d01b4a57dd121364e7320823d 100644 --- a/stan/math/rev/mat/meta/operands_and_partials.hpp +++ b/stan/math/rev/mat/meta/operands_and_partials.hpp @@ -9,51 +9,31 @@ namespace stan { namespace math { namespace detail { - template <typename ViewElt, typename Op> - class ops_partials_edge_vec_rev - : public ops_partials_edge_mat_prim<ViewElt, Op, -1, 1> { - public: - ops_partials_edge_vec_rev(const Op& ops) - : ops_partials_edge_mat_prim<ViewElt, Op, -1, 1>(ops) {} - void dump_partials(double* partials) { - for (int i = 0; i < this->size(); ++i) { - partials[i] = this->partials[i]; - } - } - void dump_operands(vari** varis) { - for (int i = 0; i < this->size(); ++i) { - varis[i] = this->operands[i].vi_; - } - } - }; - + // Vectorized Univariate // ViewElt = double, Arg = std::vector<var> d_ holds vector<double> template <typename ViewElt> class ops_partials_edge<ViewElt, std::vector<var> > - : public ops_partials_edge_vec_rev<ViewElt, std::vector<var> > { + : public ops_partials_edge_mat_prim<ViewElt, std::vector<var>, -1, 1> { public: explicit ops_partials_edge(const std::vector<var>& ops) - : ops_partials_edge_vec_rev<ViewElt, std::vector<var> >(ops) {} - }; - - // ViewElt = double, Arg = vector_v d_ holds vector<double> - // ViewElt = double, Arg = VectorXd d_ holds dummy - template <typename ViewElt> - class ops_partials_edge<ViewElt, vector_v > - : public ops_partials_edge_vec_rev<ViewElt, vector_v > { - public: - explicit ops_partials_edge(const vector_v& ops) - : ops_partials_edge_vec_rev<ViewElt, vector_v>(ops) {} + : ops_partials_edge_mat_prim<ViewElt, std::vector<var>, -1, 1>(ops) {} + void dump_operands(vari** varis) { + for (size_t i = 0; i < this->operands.size(); ++i) { + varis[i] = this->operands[i].vi_; + } + } }; - - // ViewElt = double, Arg = row_vector_v d_ holds = vector<double> - // ViewElt = double, Arg = RowVectorXd, d_ holds dummy - template <typename ViewElt> - class ops_partials_edge<ViewElt, row_vector_v > - : public ops_partials_edge_vec_rev<ViewElt, row_vector_v > { + template <typename ViewElt, int R, int C> + class ops_partials_edge<ViewElt, Eigen::Matrix<var, R, C> > + : public ops_partials_edge_mat_prim<ViewElt, Eigen::Matrix<var, R, C>, R, C> { public: - explicit ops_partials_edge(const row_vector_v& ops) - : ops_partials_edge_vec_rev<ViewElt, row_vector_v>(ops) {} + explicit ops_partials_edge(const Eigen::Matrix<var, R, C>& ops) + : ops_partials_edge_mat_prim<ViewElt, Eigen::Matrix<var, R, C>, R, C>(ops) {} + void dump_operands(vari** varis) { + for (int i = 0; i < this->operands.size(); ++i) { + varis[i] = this->operands(i).vi_; + } + } }; // MULTIVARIATE @@ -70,9 +50,9 @@ namespace stan { : ops_partials_edge_multivariate_prim<ViewElt, Op>(ops) {} void dump_partials(double* partials) { int p_i = 0; - for (size_t r = 0; r < this->partials.size(); ++r) { - for (int c = 0; c < this->partials[r].size(); ++c, ++p_i) { - partials[p_i] = this->partials[r](c); + for (size_t r = 0; r < this->partials_vec.size(); ++r) { + for (int c = 0; c < this->partials_vec[r].size(); ++c, ++p_i) { + partials[p_i] = this->partials_vec[r](c); } } } @@ -102,38 +82,6 @@ namespace stan { : ops_partials_edge_multi_rev<ViewElt, vector_v>(ops) {} }; - // VIEWS of MATRICES (R = -1, C = -1) - // ===================== - // ViewElt = MatrixXd, Arg = matrix_v, d_ holds MatrixXd - // ViewElt = MatrixXd, Arg = MatrixXd d_ holds dummy - template <typename ViewElt, int R, int C> - class ops_partials_edge<ViewElt, Eigen::Matrix<var, R, C> > { - public: - typedef Eigen::Matrix<ViewElt, R, C> partials_t; - typedef Eigen::Matrix<var, R, C> operands_t; - ops_partials_edge(const operands_t& ops) - : operands(ops), partials(partials_t::Zero(ops.rows(), ops.cols())) {} - void increment_dx_vector(int /*n*/, const partials_t& adj) { - partials += adj; - } - void dump_partials(double* partials) { - for (int i = 0; i < this->partials.size(); ++i) { - partials[i] = this->partials(i); - } - } - void dump_operands(vari** varis) { - for (int i = 0; i < this->operands.size(); ++i) { - varis[i] = this->operands(i).vi_; - } - } - int size() { - return this->operands.size(); - } - protected: - const operands_t& operands; - partials_t partials; - }; - // ViewElt = MatrixXd, Arg = vector<matrix_v> d_ holds vector<MatriXd> // ViewElt = MatrixXd, Arg = vector<MatrixXd> d_ holds dummy template <typename ViewElt> diff --git a/stan/math/rev/scal/meta/OperandsAndPartials.hpp b/stan/math/rev/scal/meta/OperandsAndPartials.hpp deleted file mode 100644 index d978dedec92b3b43a21899008ee28b323cbde523..0000000000000000000000000000000000000000 --- a/stan/math/rev/scal/meta/OperandsAndPartials.hpp +++ /dev/null @@ -1,191 +0,0 @@ -#ifndef STAN_MATH_REV_SCAL_META_OPERANDSANDPARTIALS_HPP -#define STAN_MATH_REV_SCAL_META_OPERANDSANDPARTIALS_HPP - -#include <stan/math/prim/scal/meta/is_constant_struct.hpp> -#include <stan/math/prim/scal/meta/length.hpp> -#include <stan/math/prim/scal/meta/OperandsAndPartials.hpp> -#include <stan/math/prim/scal/meta/VectorView.hpp> -#include <stan/math/rev/core.hpp> - -namespace stan { - namespace math { - - namespace { - class partials_vari : public vari { - private: - const size_t N_; - vari** operands_; - double* partials_; - public: - partials_vari(double value, - size_t N, - vari** operands, double* partials) - : vari(value), - N_(N), - operands_(operands), - partials_(partials) { } - void chain() { - for (size_t n = 0; n < N_; ++n) - operands_[n]->adj_ += adj_ * partials_[n]; - } - }; - - var partials_to_var(double logp, size_t nvaris, - vari** all_varis, - double* all_partials) { - return var(new partials_vari(logp, nvaris, all_varis, - all_partials)); - } - - template<typename T, - bool is_vec = is_vector<T>::value, - bool is_const = is_constant_struct<T>::value> - struct set_varis { - inline size_t set(vari** /*varis*/, const T& /*x*/) { - return 0U; - } - }; - template<typename T> - struct set_varis<T, true, false> { - inline size_t set(vari** varis, const T& x) { - for (size_t n = 0; n < length(x); n++) - varis[n] = x[n].vi_; - return length(x); - } - }; - template<> - struct set_varis<var, false, false> { - inline size_t set(vari** varis, const var& x) { - varis[0] = x.vi_; - return (1); - } - }; - } - - /** - * This class builds partial derivatives with respect to a set of - * operands. There are two reason for the generality of this - * class. The first is to handle vector and scalar arguments - * without needing to write additional code. The second is to use - * this class for writing probability distributions that handle - * primitives, reverse mode, and forward mode variables - * seamlessly. - * - * This is the partial template specialization for when the return - * type is stan::math::var. - * - * @tparam T1 First set of operands. - * @tparam T2 Second set of operands. - * @tparam T3 Third set of operands. - * @tparam T4 Fourth set of operands. - * @tparam T5 Fifth set of operands. - * @tparam T6 Sixth set of operands. - * @tparam T_return_type Return type of the expression. This defaults - * to a template metaprogram that calculates the scalar promotion of - * T1 -- T6. - */ - template<typename T1, typename T2, typename T3, - typename T4, typename T5, typename T6> - struct OperandsAndPartials<T1, T2, T3, T4, T5, T6, stan::math::var> { - size_t nvaris; - vari** all_varis; - double* all_partials; - - VectorView<double, - is_vector<T1>::value, - is_constant_struct<T1>::value> d_x1; - VectorView<double, - is_vector<T2>::value, - is_constant_struct<T2>::value> d_x2; - VectorView<double, - is_vector<T3>::value, - is_constant_struct<T3>::value> d_x3; - VectorView<double, - is_vector<T4>::value, - is_constant_struct<T4>::value> d_x4; - VectorView<double, - is_vector<T5>::value, - is_constant_struct<T5>::value> d_x5; - VectorView<double, - is_vector<T6>::value, - is_constant_struct<T6>::value> d_x6; - - /** - * Constructor. - * - * @param x1 first set of operands - * @param x2 second set of operands - * @param x3 third set of operands - * @param x4 fourth set of operands - * @param x5 fifth set of operands - * @param x6 sixth set of operands - */ - OperandsAndPartials(const T1& x1 = 0, const T2& x2 = 0, const T3& x3 = 0, - const T4& x4 = 0, const T5& x5 = 0, const T6& x6 = 0) - : nvaris(!is_constant_struct<T1>::value * length(x1) + - !is_constant_struct<T2>::value * length(x2) + - !is_constant_struct<T3>::value * length(x3) + - !is_constant_struct<T4>::value * length(x4) + - !is_constant_struct<T5>::value * length(x5) + - !is_constant_struct<T6>::value * length(x6)), - // TODO(carpenter): replace with array allocation fun - all_varis(static_cast<vari**> - (vari::operator new - (sizeof(vari*) * nvaris))), - all_partials(static_cast<double*> - (vari::operator new - (sizeof(double) * nvaris))), - d_x1(all_partials), - d_x2(all_partials - + (!is_constant_struct<T1>::value) * length(x1)), - d_x3(all_partials - + (!is_constant_struct<T1>::value) * length(x1) - + (!is_constant_struct<T2>::value) * length(x2)), - d_x4(all_partials - + (!is_constant_struct<T1>::value) * length(x1) - + (!is_constant_struct<T2>::value) * length(x2) - + (!is_constant_struct<T3>::value) * length(x3)), - d_x5(all_partials - + (!is_constant_struct<T1>::value) * length(x1) - + (!is_constant_struct<T2>::value) * length(x2) - + (!is_constant_struct<T3>::value) * length(x3) - + (!is_constant_struct<T4>::value) * length(x4)), - d_x6(all_partials - + (!is_constant_struct<T1>::value) * length(x1) - + (!is_constant_struct<T2>::value) * length(x2) - + (!is_constant_struct<T3>::value) * length(x3) - + (!is_constant_struct<T4>::value) * length(x4) - + (!is_constant_struct<T5>::value) * length(x5)) { - size_t base = 0; - if (!is_constant_struct<T1>::value) - base += set_varis<T1>().set(&all_varis[base], x1); - if (!is_constant_struct<T2>::value) - base += set_varis<T2>().set(&all_varis[base], x2); - if (!is_constant_struct<T3>::value) - base += set_varis<T3>().set(&all_varis[base], x3); - if (!is_constant_struct<T4>::value) - base += set_varis<T4>().set(&all_varis[base], x4); - if (!is_constant_struct<T5>::value) - base += set_varis<T5>().set(&all_varis[base], x5); - if (!is_constant_struct<T6>::value) - set_varis<T6>().set(&all_varis[base], x6); - std::fill(all_partials, all_partials+nvaris, 0); - } - - /** - * Returns a T_return_type with the value specified with - * the partial derivatves. - * - * @param[in] value Value of the variable - * @returns a variable with the appropriate value and - * the adjoints set for reverse mode autodiff - */ - stan::math::var value(double value) { - return partials_to_var(value, nvaris, all_varis, - all_partials); - } - }; - - } -} -#endif diff --git a/stan/math/rev/scal/meta/operands_and_partials.hpp b/stan/math/rev/scal/meta/operands_and_partials.hpp index 16d59ba07beb91523baf25fc21fb4eff6ee4a82b..64f02a596c24c040ed4fbc89422c3c86a5656b1d 100644 --- a/stan/math/rev/scal/meta/operands_and_partials.hpp +++ b/stan/math/rev/scal/meta/operands_and_partials.hpp @@ -19,83 +19,50 @@ namespace stan { ops_partials_edge(const var& op) : ops_partials_edge_singular<ViewElt, var>(op) {} void dump_partials(ViewElt* partials) { - *partials = this->partial; + *partials = this->partials[0]; } void dump_operands(vari** varis) { *varis = this->operand.vi_; } }; + } // end namespace detail + template <typename Op1, typename Op2, typename Op3, typename Op4> + class operands_and_partials<Op1, Op2, Op3, Op4, var> { + public: + // these are going to be stack local and get collected + detail::ops_partials_edge<double, Op1> edge1_; + detail::ops_partials_edge<double, Op2> edge2_; + detail::ops_partials_edge<double, Op3> edge3_; + detail::ops_partials_edge<double, Op4> edge4_; + operands_and_partials(const Op1& o1) + : edge1_(o1) { } + operands_and_partials(const Op1& o1, const Op2& o2) + : edge1_(o1), edge2_(o2) { } + operands_and_partials(const Op1& o1, const Op2& o2, const Op3& o3) + : edge1_(o1), edge2_(o2), edge3_(o3) { } + operands_and_partials(const Op1& o1, const Op2& o2, const Op3& o3, const Op4& o4) + : edge1_(o1), edge2_(o2), edge3_(o3), edge4_(o4) { } - template <typename Op1, typename Op2, typename Op3, typename Op4> - class operands_and_partials<Op1, Op2, Op3, Op4, var> { - public: - operands_and_partials(const Op1& o1) - : edge1_(o1) { } - operands_and_partials(const Op1& o1, const Op2& o2) - : edge1_(o1), edge2_(o2) { } - operands_and_partials(const Op1& o1, const Op2& o2, const Op3& o3) - : edge1_(o1), edge2_(o2), edge3_(o3) { } - operands_and_partials(const Op1& o1, const Op2& o2, const Op3& o3, const Op4& o4) - : edge1_(o1), edge2_(o2), edge3_(o3), edge4_(o4) { } - - void increment_dx1(const int n, const double adj) { edge1_.increment_dx(n, adj); } - void increment_dx2(const int n, const double adj) { edge2_.increment_dx(n, adj); } - void increment_dx3(const int n, const double adj) { edge3_.increment_dx(n, adj); } - void increment_dx4(const int n, const double adj) { edge4_.increment_dx(n, adj); } - - template<typename T> - typename boost::enable_if_c<is_vector_like<Op1>::value - && is_vector_like<T>::value, void>::type - increment_dx1_vector(const int n, const T& adj) { - edge1_.increment_dx_vector(n, adj); - } - template<typename T> - typename boost::enable_if_c<is_vector_like<Op2>::value - && is_vector_like<T>::value, void>::type - increment_dx2_vector(const int n, const T& adj) { - edge2_.increment_dx_vector(n, adj); - } - template<typename T> - typename boost::enable_if_c<is_vector_like<Op3>::value - && is_vector_like<T>::value, void>::type - increment_dx3_vector(const int n, const T& adj) { - edge3_.increment_dx_vector(n, adj); - } - template<typename T> - typename boost::enable_if_c<is_vector_like<Op4>::value - && is_vector_like<T>::value, void>::type - increment_dx4_vector(const int n, const T& adj) { - edge4_.increment_dx_vector(n, adj); - } - - // this is what matters in terms of going on autodiff stack - var build(double value) { - size_t size = edge1_.size() + edge2_.size() + edge3_.size() + edge4_.size(); - vari** varis = ChainableStack::memalloc_.alloc_array<vari*>(size); - int idx = 0; - edge1_.dump_operands(&varis[idx]); - edge2_.dump_operands(&varis[idx += edge1_.size()]); - edge3_.dump_operands(&varis[idx += edge2_.size()]); - edge4_.dump_operands(&varis[idx += edge3_.size()]); + // this is what matters in terms of going on autodiff stack + var build(double value) { + size_t size = edge1_.size() + edge2_.size() + edge3_.size() + edge4_.size(); + vari** varis = ChainableStack::memalloc_.alloc_array<vari*>(size); + int idx = 0; + edge1_.dump_operands(&varis[idx]); + edge2_.dump_operands(&varis[idx += edge1_.size()]); + edge3_.dump_operands(&varis[idx += edge2_.size()]); + edge4_.dump_operands(&varis[idx += edge3_.size()]); - double* partials = ChainableStack::memalloc_.alloc_array<double>(size); - idx = 0; - edge1_.dump_partials(&partials[idx]); - edge2_.dump_partials(&partials[idx += edge1_.size()]); - edge3_.dump_partials(&partials[idx += edge2_.size()]); - edge4_.dump_partials(&partials[idx += edge3_.size()]); + double* partials = ChainableStack::memalloc_.alloc_array<double>(size); + idx = 0; + edge1_.dump_partials(&partials[idx]); + edge2_.dump_partials(&partials[idx += edge1_.size()]); + edge3_.dump_partials(&partials[idx += edge2_.size()]); + edge4_.dump_partials(&partials[idx += edge3_.size()]); - return var(new precomputed_gradients_vari(value, size, varis, partials)); - }; - private: - // these are going to be stack local and get collected - // TODO(sean): should we pass in ViewElt somehow? shape of it? - ops_partials_edge<double, Op1> edge1_; - ops_partials_edge<double, Op2> edge2_; - ops_partials_edge<double, Op3> edge3_; - ops_partials_edge<double, Op4> edge4_; + return var(new precomputed_gradients_vari(value, size, varis, partials)); }; - } // end namespace detail + }; } } #endif diff --git a/test/foo_test.cpp b/test/foo_test.cpp deleted file mode 100644 index b7368fbb9bfb5865df54aeba57b7b45ce3aa3875..0000000000000000000000000000000000000000 --- a/test/foo_test.cpp +++ /dev/null @@ -1,11 +0,0 @@ -#include <stan/math/mix/scal.hpp> -#include <gtest/gtest.h> - -TEST(foo, bar) { - double y = 0; - double mu = 0; - stan::math::fvar<stan::math::var> sigma = 1; - - - stan::math::fvar<stan::math::var> lp = normal_lpdf(y, mu, sigma); -} diff --git a/test/unit/math/fwd/arr/meta/OperandsAndPartials_test.cpp b/test/unit/math/fwd/arr/meta/OperandsAndPartials_test.cpp deleted file mode 100644 index 3cdc0d1406fd9c80d6c69c994b6fc313766b3dc8..0000000000000000000000000000000000000000 --- a/test/unit/math/fwd/arr/meta/OperandsAndPartials_test.cpp +++ /dev/null @@ -1,58 +0,0 @@ -#include <stan/math/fwd/arr.hpp> -#include <gtest/gtest.h> - -TEST(AgradPartialsVari, OperandsAndPartialsFvarVec) { - using stan::math::OperandsAndPartials; - using stan::math::fvar; - - std::vector<fvar<double> > x1; - x1.push_back(fvar<double>(2.0,2.0)); - x1.push_back(fvar<double>(1.0,3.0)); - - fvar<double> x2 = 3.0; - fvar<double> x3 = 5.0; - x2.d_ = -1.0; - x3.d_ = 4.0; - - OperandsAndPartials<std::vector<fvar<double> >,fvar<double>,fvar<double> > o(x1, x2, x3); - o.d_x1[0] += 17.0; - o.d_x1[1] += 13.0; - o.d_x2[0] += 19.0; - o.d_x2[0] += 19.0; - o.d_x3[0] += 23.0; - o.d_x3[0] += 23.0; - fvar<double> y = o.value(-1.0); - - EXPECT_FLOAT_EQ(2*17 + 3*13 - 2*19 + 2*4*23,y.d_); - EXPECT_FLOAT_EQ(-1,y.val_); -} - -// TEST(AgradPartialsVari, incr_deriv_vec_fvar) { -// using stan::VectorView; -// using stan::math::incr_deriv; -// using stan::is_vector; -// using stan::is_constant_struct; -// using stan::math::fvar; - -// fvar<double> c(1,1); - -// std::vector<fvar<double> > d; -// d.push_back(c); -// d.push_back(c); - -// std::vector<double> d_deriv; -// d_deriv.push_back(3); -// d_deriv.push_back(4); - -// VectorView<std::vector<double>, -// stan::is_vector<std::vector<fvar<double> > >::value, -// stan::is_constant_struct<std::vector<fvar<double> > >::value> -// d_d(d_deriv); - -// double result3 = incr_deriv<VectorView<std::vector<double>, -// is_vector<std::vector<fvar<double> > >::value, -// is_constant_struct<std::vector<fvar<double> > >::value>, -// std::vector<fvar<double> >,double>().incr(d_d,d); - -// EXPECT_FLOAT_EQ(7, result3); -// } diff --git a/test/unit/math/fwd/mat/meta/operands_and_partials_test.cpp b/test/unit/math/fwd/mat/meta/operands_and_partials_test.cpp index 9e79c13daf2d5a41b37e6230c21d91e8809fbe35..66e1e65d19f9424ec292af473bcf4058d23a3de6 100644 --- a/test/unit/math/fwd/mat/meta/operands_and_partials_test.cpp +++ b/test/unit/math/fwd/mat/meta/operands_and_partials_test.cpp @@ -2,7 +2,7 @@ #include <gtest/gtest.h> TEST(AgradPartialsVari, OperandsAndPartialsFvarVec) { - using stan::math::detail::operands_and_partials; + using stan::math::operands_and_partials; using stan::math::fvar; std::vector<fvar<double> > x1; @@ -18,11 +18,11 @@ TEST(AgradPartialsVari, OperandsAndPartialsFvarVec) { dx1 << 17.0, 13.0; operands_and_partials<std::vector<fvar<double> >,fvar<double>,fvar<double> > o(x1, x2, x3); - o.increment_dx1_vector(0, dx1); - o.increment_dx2(0, 19.0); - o.increment_dx2(0, 19.0); - o.increment_dx3(0, 23.0); - o.increment_dx3(0, 23.0); + o.edge1_.partials_vec[0] += dx1; + o.edge2_.partials[0] += 19.0; + o.edge2_.partials[0] += 19.0; + o.edge3_.partials[0] += 23.0; + o.edge3_.partials[0] += 23.0; fvar<double> y = o.build(-1.0); EXPECT_FLOAT_EQ(2*17 + 3*13 - 2*19 + 2*4*23,y.d_); diff --git a/test/unit/math/fwd/scal/meta/OperandsAndPartials_test.cpp b/test/unit/math/fwd/scal/meta/OperandsAndPartials_test.cpp deleted file mode 100644 index 44150748c1f4c13b984ed612d315c86a212f999b..0000000000000000000000000000000000000000 --- a/test/unit/math/fwd/scal/meta/OperandsAndPartials_test.cpp +++ /dev/null @@ -1,48 +0,0 @@ -#include <stan/math/fwd/scal.hpp> -#include <gtest/gtest.h> - -TEST(AgradPartialsVari, OperandsAndPartialsFvar) { - using stan::math::OperandsAndPartials; - using stan::math::fvar; - - fvar<double> x1 = 2.0; - fvar<double> x2 = 3.0; - fvar<double> x3 = 5.0; - x1.d_ = 2.0; - x2.d_ = -1.0; - x3.d_ = 4.0; - - OperandsAndPartials<fvar<double>,fvar<double>,fvar<double> > o(x1, x2, x3); - o.d_x1[0] += 17.0; - o.d_x2[0] += 19.0; - o.d_x3[0] += 23.0; - - fvar<double> y = o.value(-1.0); - EXPECT_FLOAT_EQ(107,y.d_); - EXPECT_FLOAT_EQ(-1,y.val_); -} - -// TEST(AgradPartialsVari, incr_deriv_fvar) { -// using stan::VectorView; -// using stan::math::incr_deriv; -// using stan::is_vector; -// using stan::is_constant_struct; -// using stan::math::fvar; - -// fvar<double> c; -// c.val_ = 1.0; -// c.d_ = 1.0; - -// double c_deriv = 2; -// VectorView<const double, -// stan::is_vector<fvar<double> >::value, -// stan::is_constant_struct<fvar<double> >::value> -// d_c(c_deriv); - -// double result2 = incr_deriv<VectorView<const double, -// is_vector<fvar<double> >::value, -// is_constant_struct<fvar<double> >::value>, -// fvar<double>,double>().incr(d_c,c); - -// EXPECT_FLOAT_EQ(2, result2); -// } diff --git a/test/unit/math/fwd/scal/meta/operands_and_partials_test.cpp b/test/unit/math/fwd/scal/meta/operands_and_partials_test.cpp index 24f22bb15bee61c3f230713ec495db826693511e..719fea335e273b892dbf16b87baaec177b06777c 100644 --- a/test/unit/math/fwd/scal/meta/operands_and_partials_test.cpp +++ b/test/unit/math/fwd/scal/meta/operands_and_partials_test.cpp @@ -2,7 +2,7 @@ #include <gtest/gtest.h> TEST(AgradPartialsVari, OperandsAndPartialsFvar) { - using stan::math::detail::operands_and_partials; + using stan::math::operands_and_partials; using stan::math::fvar; fvar<double> x1 = 2.0; @@ -13,9 +13,9 @@ TEST(AgradPartialsVari, OperandsAndPartialsFvar) { x3.d_ = 4.0; operands_and_partials<fvar<double>,fvar<double>,fvar<double> > o(x1, x2, x3); - o.increment_dx1(0, 17.0); - o.increment_dx2(0, 19.0); - o.increment_dx3(0, 23.0); + o.edge1_.partials[0] += 17.0; + o.edge2_.partials[0] += 19.0; + o.edge3_.partials[0] += 23.0; fvar<double> y = o.build(-1.0); EXPECT_FLOAT_EQ(107,y.d_); diff --git a/test/unit/math/mix/scal/meta/broadcast_array_test.cpp b/test/unit/math/mix/scal/meta/broadcast_array_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..ff6cfbff0e25453622192d2392ec9ff2c3dd9786 --- /dev/null +++ b/test/unit/math/mix/scal/meta/broadcast_array_test.cpp @@ -0,0 +1,15 @@ +#include <gtest/gtest.h> +#include <stan/math/fwd/core/fvar.hpp> +#include <stan/math/rev/core/var.hpp> +#include <stan/math/prim/scal/meta/broadcast_array.hpp> + +TEST(foo, bar) { + using stan::math::detail::broadcast_array; + using stan::math::fvar; + using stan::math::var; + + fvar<var> fv(0.0); + broadcast_array<fvar<var> > ba(fv); + EXPECT_EQ(0.0, ba[0].val_.vi_->val_); + EXPECT_EQ(0.0, ba[2].val_.vi_->val_); +} diff --git a/test/unit/math/prim/arr/meta/OperandsAndPartials_test.cpp b/test/unit/math/prim/arr/meta/OperandsAndPartials_test.cpp deleted file mode 100644 index f49dcf8540e4257eae8fe9488a2871590a9573af..0000000000000000000000000000000000000000 --- a/test/unit/math/prim/arr/meta/OperandsAndPartials_test.cpp +++ /dev/null @@ -1,41 +0,0 @@ -#include <stan/math/prim/arr.hpp> -#include <gtest/gtest.h> - -// TEST(AgradPartialsVari, incr_deriv_vec_double) { -// using stan::VectorView; -// using stan::math::incr_deriv; -// using stan::is_vector; -// using stan::is_constant_struct; - -// std::vector<double> b; -// b.push_back(1); -// b.push_back(1); - -// VectorView<const std::vector<double>, -// stan::is_vector<std::vector<double> >::value, -// stan::is_constant_struct<std::vector<double> >::value> -// d_b(stan::length(b) * 0); - -// double result = incr_deriv<VectorView<const std::vector<double>, -// is_vector<std::vector<double> >::value, -// is_constant_struct<std::vector<double> >::value>, -// std::vector<double>,double>().incr(d_b,b); - -// EXPECT_FLOAT_EQ(0, result); -// } - -TEST(AgradPartialsVari, OperandsAndPartials_check_throw) { - using stan::math::OperandsAndPartials; - using std::vector; - - vector<double> D; - - OperandsAndPartials<vector<double>,vector<double>,vector<double>, - vector<double>,vector<double>,vector<double> > o3(D,D,D,D,D,D); - EXPECT_THROW(o3.d_x1[0], std::logic_error); - EXPECT_THROW(o3.d_x2[0], std::logic_error); - EXPECT_THROW(o3.d_x3[0], std::logic_error); - EXPECT_THROW(o3.d_x4[0], std::logic_error); - EXPECT_THROW(o3.d_x5[0], std::logic_error); - EXPECT_THROW(o3.d_x6[0], std::logic_error); -} diff --git a/test/unit/math/prim/scal/meta/OperandsAndPartials_test.cpp b/test/unit/math/prim/scal/meta/OperandsAndPartials_test.cpp deleted file mode 100644 index d37c4b96f15d0df143ec53d70496d9fe9da0e0c2..0000000000000000000000000000000000000000 --- a/test/unit/math/prim/scal/meta/OperandsAndPartials_test.cpp +++ /dev/null @@ -1,46 +0,0 @@ -#include <stan/math/prim/scal.hpp> -#include <gtest/gtest.h> - -TEST(AgradPartialsVari, OperandsAndPartials) { - using stan::math::OperandsAndPartials; - - OperandsAndPartials<double> o1; - OperandsAndPartials<double,double,double,double> o2; - - SUCCEED() << "Construction should be ok."; -} - -// TEST(AgradPartialsVari, incr_deriv_double) { -// using stan::VectorView; -// using stan::math::incr_deriv; -// using stan::is_vector; -// using stan::is_constant_struct; - -// double a = 1; - -// VectorView<const double,stan::is_vector<double>::value, -// stan::is_constant_struct<double>::value> d_a(stan::length(a) * 0); - - - -// double result = incr_deriv<VectorView<const double, -// is_vector<double>::value, -// is_constant_struct<double>::value>, -// double,double>().incr(d_a,a); -// EXPECT_FLOAT_EQ(0, result); -// } - - -TEST(AgradPartialsVari, OperandsAndPartials_check_throw) { - using stan::math::OperandsAndPartials; - - double d; - - OperandsAndPartials<> o1(d,d,d,d,d,d); - EXPECT_THROW(o1.d_x1[0], std::logic_error); - EXPECT_THROW(o1.d_x2[0], std::logic_error); - EXPECT_THROW(o1.d_x3[0], std::logic_error); - EXPECT_THROW(o1.d_x4[0], std::logic_error); - EXPECT_THROW(o1.d_x5[0], std::logic_error); - EXPECT_THROW(o1.d_x6[0], std::logic_error); -} diff --git a/test/unit/math/prim/scal/meta/operands_and_partials_test.cpp b/test/unit/math/prim/scal/meta/operands_and_partials_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..d79c625c43fd9cea69c511b28b45d19f810a4db3 --- /dev/null +++ b/test/unit/math/prim/scal/meta/operands_and_partials_test.cpp @@ -0,0 +1,14 @@ +#include <stan/math/prim/scal.hpp> +#include <gtest/gtest.h> + +TEST(AgradPartialsVari, OperandsAndPartials) { + using stan::math::OperandsAndPartials; + + OperandsAndPartials<double> o1; + OperandsAndPartials<double,double,double,double> o2; + + // TODO(Sean): Learn why it's size 6 + EXPECT_GT(sizeof(&o2), sizeof(o2)); + + SUCCEED() << "Construction should be ok."; +} diff --git a/test/unit/math/rev/arr/meta/OperandsAndPartials_test.cpp b/test/unit/math/rev/arr/meta/OperandsAndPartials_test.cpp deleted file mode 100644 index 7fe30453d6c9dbad245e0bf6b67eb05d25fce283..0000000000000000000000000000000000000000 --- a/test/unit/math/rev/arr/meta/OperandsAndPartials_test.cpp +++ /dev/null @@ -1,49 +0,0 @@ -#include <stan/math/rev/arr.hpp> -#include <gtest/gtest.h> - -TEST(AgradPartialsVari, OperandsAndPartials) { - using stan::math::OperandsAndPartials; - using stan::math::var; - - std::vector<double> d_vec(4); - OperandsAndPartials<std::vector<double> > o3(d_vec); - std::vector<var> v_vec; - v_vec.push_back(var(0.0)); - v_vec.push_back(var(1.0)); - v_vec.push_back(var(2.0)); - v_vec.push_back(var(3.0)); - - std::vector<double> grad; - - OperandsAndPartials<std::vector<var> > o4(v_vec); - o4.d_x1[0] = 10.0; - o4.d_x1[1] = 20.0; - o4.d_x1[2] = 30.0; - o4.d_x1[3] = 40.0; - - var v = o4.value(10.0); - v.grad(v_vec, grad); - EXPECT_EQ(4U, o4.nvaris); - EXPECT_FLOAT_EQ(10.0, v.val()); - EXPECT_FLOAT_EQ(10.0, grad[0]); - EXPECT_FLOAT_EQ(20.0, grad[1]); - EXPECT_FLOAT_EQ(30.0, grad[2]); - EXPECT_FLOAT_EQ(40.0, grad[3]); -} - -TEST(AgradPartialsVari, OperandsAndPartials_check_throw) { - using stan::math::OperandsAndPartials; - using stan::math::var; - using std::vector; - - vector<var> V; - - OperandsAndPartials<vector<var>,vector<var>,vector<var>, - vector<var>,vector<var>,vector<var> > o4(V,V,V,V,V,V); - EXPECT_NO_THROW(o4.d_x1[0]); - EXPECT_NO_THROW(o4.d_x2[0]); - EXPECT_NO_THROW(o4.d_x3[0]); - EXPECT_NO_THROW(o4.d_x4[0]); - EXPECT_NO_THROW(o4.d_x5[0]); - EXPECT_NO_THROW(o4.d_x6[0]); -} diff --git a/test/unit/math/rev/mat/meta/operands_and_partials_test.cpp b/test/unit/math/rev/mat/meta/operands_and_partials_test.cpp index 491c1337672033121059f71bd27166bce9d4fc65..a3d4ff3b10130d136323ed6d3112bbddd83a2b86 100644 --- a/test/unit/math/rev/mat/meta/operands_and_partials_test.cpp +++ b/test/unit/math/rev/mat/meta/operands_and_partials_test.cpp @@ -5,14 +5,14 @@ #include <iostream> TEST(AgradPartialsVari, OperandsAndPartialsVec) { - using stan::math::detail::operands_and_partials; + using stan::math::operands_and_partials; using stan::math::var; using stan::math::vector_v; using stan::math::vector_d; vector_d d_vec(4); operands_and_partials<vector_d > o3(d_vec); - EXPECT_EQ(1, sizeof(o3)); + EXPECT_EQ(4, sizeof(o3)); vector_v v_vec(4); var v1 = var(0.0); @@ -28,10 +28,10 @@ TEST(AgradPartialsVari, OperandsAndPartialsVec) { v_stdvec.push_back(v4); operands_and_partials<vector_v > o4(v_vec); - o4.increment_dx1(0, 10.0); - o4.increment_dx1(1, 20.0); - o4.increment_dx1(2, 30.0); - o4.increment_dx1(3, 40.0); + o4.edge1_.partials[0] += 10.0; + o4.edge1_.partials[1] += 20.0; + o4.edge1_.partials[2] += 30.0; + o4.edge1_.partials[3] += 40.0; std::vector<double> grad; var v = o4.build(10.0); @@ -43,8 +43,43 @@ TEST(AgradPartialsVari, OperandsAndPartialsVec) { EXPECT_FLOAT_EQ(40.0, grad[3]); } +TEST(AgradPartialsVari, OperandsAndPartialsStdVec) { + using stan::math::operands_and_partials; + using stan::math::var; + + std::vector<double> d_vec(4); + operands_and_partials<std::vector<double> > o3(d_vec); + EXPECT_EQ(4, sizeof(o3)); + + std::vector<var> v_vec; + var v1 = var(0.0); + var v2 = var(1.0); + var v3 = var(2.0); + var v4 = var(3.0); + v_vec.push_back(v1); + v_vec.push_back(v2); + v_vec.push_back(v3); + v_vec.push_back(v4); + + operands_and_partials<std::vector<var> > o4(v_vec); + o4.edge1_.partials[0] += 10.0; + o4.edge1_.partials[1] += 20.0; + o4.edge1_.partials[2] += 30.0; + o4.edge1_.partials[3] += 40.0; + + std::vector<double> grad; + var v = o4.build(10.0); + v.grad(v_vec, grad); + EXPECT_FLOAT_EQ(10.0, v.val()); + EXPECT_FLOAT_EQ(10.0, grad[0]); + EXPECT_FLOAT_EQ(20.0, grad[1]); + EXPECT_FLOAT_EQ(30.0, grad[2]); + EXPECT_FLOAT_EQ(40.0, grad[3]); +} + + TEST(AgradPartialsVari, OperandsAndPartialsMat) { - using stan::math::detail::operands_and_partials; + using stan::math::operands_and_partials; using stan::math::var; using stan::math::matrix_v; using stan::math::matrix_d; @@ -53,7 +88,7 @@ TEST(AgradPartialsVari, OperandsAndPartialsMat) { d_mat << 10.0, 20.0, 30.0, 40.0; operands_and_partials<matrix_d > o3(d_mat); - EXPECT_EQ(1, sizeof(o3)); + EXPECT_EQ(4, sizeof(o3)); matrix_v v_mat(2, 2); var v1 = var(0.0); @@ -69,22 +104,22 @@ TEST(AgradPartialsVari, OperandsAndPartialsMat) { v_stdvec.push_back(v4); operands_and_partials<matrix_v > o4(v_mat); - // TODO(Sean): Check assumption that Matrices are only used in the multivariate cases - o4.increment_dx1_vector(1, d_mat); - o4.increment_dx1_vector(27, d_mat); // Should affect the same vars as the call above + o4.edge1_.partials += d_mat; + o4.edge1_.partials_vec[1] += d_mat; + o4.edge1_.partials_vec[27] += d_mat; // Should affect the same vars as the call above std::vector<double> grad; var v = o4.build(10.0); v.grad(v_stdvec, grad); EXPECT_FLOAT_EQ(10.0, v.val()); - EXPECT_FLOAT_EQ(20.0, grad[0]); - EXPECT_FLOAT_EQ(40.0, grad[1]); - EXPECT_FLOAT_EQ(60.0, grad[2]); - EXPECT_FLOAT_EQ(80.0, grad[3]); + EXPECT_FLOAT_EQ(30.0, grad[0]); + EXPECT_FLOAT_EQ(60.0, grad[1]); + EXPECT_FLOAT_EQ(90.0, grad[2]); + EXPECT_FLOAT_EQ(120.0, grad[3]); } TEST(AgradPartialsVari, OperandsAndPartialsMatMultivar) { - using stan::math::detail::operands_and_partials; + using stan::math::operands_and_partials; using stan::math::var; using stan::math::matrix_v; using stan::math::matrix_d; @@ -95,7 +130,7 @@ TEST(AgradPartialsVari, OperandsAndPartialsMatMultivar) { d_mat_vec.push_back(d_mat); operands_and_partials<std::vector<matrix_d> > o3(d_mat_vec); - EXPECT_EQ(1, sizeof(o3)); + EXPECT_EQ(4, sizeof(o3)); matrix_v v_mat1(2, 2); var v1 = var(0.0); @@ -126,9 +161,9 @@ TEST(AgradPartialsVari, OperandsAndPartialsMatMultivar) { v_stdvec.push_back(v8); operands_and_partials<std::vector<matrix_v> > o4(v_mat_vec); - o4.increment_dx1_vector(0, d_mat); - o4.increment_dx1_vector(1, d_mat); // Should NOT affect the same vars as the call above - o4.increment_dx1_vector(1, d_mat); + o4.edge1_.partials_vec[0] += d_mat; + o4.edge1_.partials_vec[1] += d_mat; // Should NOT affect the same vars as the call above + o4.edge1_.partials_vec[1] += d_mat; std::vector<double> grad; var v = o4.build(10.0); @@ -145,7 +180,7 @@ TEST(AgradPartialsVari, OperandsAndPartialsMatMultivar) { } TEST(AgradPartialsVari, OperandsAndPartialsMultivar) { - using stan::math::detail::operands_and_partials; + using stan::math::operands_and_partials; using stan::math::var; using stan::math::vector_v; using stan::math::vector_d; @@ -159,7 +194,7 @@ TEST(AgradPartialsVari, OperandsAndPartialsMultivar) { d_vec_vec.push_back(d_vec2); operands_and_partials<std::vector<vector_d> > o3(d_vec_vec); - EXPECT_EQ(1, sizeof(o3)); + EXPECT_EQ(4, sizeof(o3)); vector_v v_vec1(2); var v1 = var(0.0); @@ -180,8 +215,8 @@ TEST(AgradPartialsVari, OperandsAndPartialsMultivar) { v_stdvec.push_back(v4); operands_and_partials<std::vector<vector_v> > o4(v_vec); - o4.increment_dx1_vector(0, d_vec1); - o4.increment_dx1_vector(1, d_vec2); + o4.edge1_.partials_vec[0] += d_vec1; + o4.edge1_.partials_vec[1] += d_vec2; std::vector<double> grad; var v = o4.build(10.0); @@ -195,7 +230,7 @@ TEST(AgradPartialsVari, OperandsAndPartialsMultivar) { // XXX Test mixed - operands_and_partials<std::vector<matrix_v>, vector_d, vector_v> TEST(AgradPartialsVari, OperandsAndPartialsMultivarMixed) { - using stan::math::detail::operands_and_partials; + using stan::math::operands_and_partials; using stan::math::var; using stan::math::vector_v; using stan::math::vector_d; @@ -229,11 +264,11 @@ TEST(AgradPartialsVari, OperandsAndPartialsMultivarMixed) { operands_and_partials<std::vector<vector_v>, std::vector<vector_d>, vector_v> o4(v_vec, d_vec_vec, v_vec2); - o4.increment_dx1_vector(0, d_vec1); - o4.increment_dx3_vector(0, d_vec2); + o4.edge1_.partials_vec[0] += d_vec1; + o4.edge3_.partials_vec[0] += d_vec2; - // 2 partials stdvecs, 3 pointers to edges, 2 pointers to operands vecs - EXPECT_EQ(2*sizeof(d_vec1) + 5*sizeof(&v_vec), sizeof(o4)); + // 2 partials stdvecs, 4 pointers to edges, 2 pointers to operands vecs + EXPECT_EQ(2*sizeof(d_vec1) + 6*sizeof(&v_vec), sizeof(o4)); std::vector<double> grad; var v = o4.build(10.0); diff --git a/test/unit/math/rev/scal/meta/OperandsAndPartials_test.cpp b/test/unit/math/rev/scal/meta/OperandsAndPartials_test.cpp deleted file mode 100644 index ef5345ad0818a706ff3a69f29c93f5d814da8266..0000000000000000000000000000000000000000 --- a/test/unit/math/rev/scal/meta/OperandsAndPartials_test.cpp +++ /dev/null @@ -1,73 +0,0 @@ -#include <stan/math/rev/scal.hpp> -#include <gtest/gtest.h> - -TEST(AgradPartialsVari,OperandsAndPartials1) { - using stan::math::vari; - using stan::math::OperandsAndPartials; - using stan::math::var; - - var x = 2.0; - var z = -3.0 * x; // dz/dx = -3 - OperandsAndPartials<var> o(z); - o.d_x1[0] += 5.0; // dy/dz = 5 - - var y = o.value(-1.0); - - stan::math::grad(y.vi_); - EXPECT_FLOAT_EQ(-15.0, x.adj()); // dy/dx = -15 -} -TEST(AgradPartialsVari,OperandsAndPartials2) { - using stan::math::OperandsAndPartials; - using stan::math::vari; - using stan::math::var; - - var x1 = 2.0; - var x2 = 3.0; - var z1 = -5.0 * x1; // dz1/dx1 = -5 - var z2 = -7.0 * x2; // dz2/dx2 = -7 - OperandsAndPartials<var,var> o(z1,z2); - o.d_x1[0] += 11.0; // dy/dz1 = 11.0 - o.d_x2[0] += 13.0; // dy/dz2 = 13.0 - var y = o.value(-1.0); - - stan::math::grad(y.vi_); - EXPECT_FLOAT_EQ(-55.0, x1.adj()); // dy/dx1 = -55 - EXPECT_FLOAT_EQ(-91.0, x2.adj()); // dy/dx2 = -91 -} -TEST(AgradPartialsVari, OperandsAndPartials3) { - using stan::math::OperandsAndPartials; - using stan::math::vari; - using stan::math::var; - - var x1 = 2.0; - var x2 = 3.0; - var x3 = 5.0; - var z1 = -7.0 * x1; // dz1/dx1 = -5 - var z2 = -9.0 * x2; // dz2/dx2 = -7 - var z3 = -11.0 * x3; // dz3/dx3 = -11 - - OperandsAndPartials<var,var,var> o(z1, z2, z3); - o.d_x1[0] += 17.0; // dy/dz1 = 17.0 - o.d_x2[0] += 19.0; // dy/dz2 = 19.0 - o.d_x3[0] += 23.0; // dy/dz3 = 23.0 - var y = o.value(-1.0); - - stan::math::grad(y.vi_); - EXPECT_FLOAT_EQ(-119.0, x1.adj()); // dy/dx1 = -119 - EXPECT_FLOAT_EQ(-171.0, x2.adj()); // dy/dx2 = -133 - EXPECT_FLOAT_EQ(-253.0, x3.adj()); // dy/dx2 = -253 -} -TEST(AgradPartialsVari, OperandsAndPartials_check_throw) { - using stan::math::OperandsAndPartials; - using stan::math::var; - - var v; - - OperandsAndPartials<var,var,var,var,var,var> o2(v,v,v,v,v,v); - EXPECT_NO_THROW(o2.d_x1[0]); - EXPECT_NO_THROW(o2.d_x2[0]); - EXPECT_NO_THROW(o2.d_x3[0]); - EXPECT_NO_THROW(o2.d_x4[0]); - EXPECT_NO_THROW(o2.d_x5[0]); - EXPECT_NO_THROW(o2.d_x6[0]); -}