diff --git a/src/analysis_and_optimization/Dataflow_utils.ml b/src/analysis_and_optimization/Dataflow_utils.ml index 59a6b4147d..db15ad4125 100644 --- a/src/analysis_and_optimization/Dataflow_utils.ml +++ b/src/analysis_and_optimization/Dataflow_utils.ml @@ -137,7 +137,7 @@ let build_cf_graphs ?(flatten_loops = false) ?(blocks_after_body = true) is visited after substatements *) let substmt_preds = match stmt with - | Block _ when blocks_after_body -> in_state.exits + | (Block _ | Profile _) when blocks_after_body -> in_state.exits | _ -> Set.Poly.singleton label in (* The accumulated state after traversing substatements *) let substmt_state_unlooped, substmt_map = @@ -174,7 +174,7 @@ let build_cf_graphs ?(flatten_loops = false) ?(blocks_after_body = true) Set.Poly.diff substmt_state_unlooped.breaks in_state.breaks ] in ({substmt_state_unlooped with exits= loop_exits}, loop_predecessors) - | Block _ when blocks_after_body -> + | (Block _ | Profile _) when blocks_after_body -> (* Block statements are preceded by the natural exit points of the block body *) let block_predecessors = substmt_state_unlooped.exits in diff --git a/src/analysis_and_optimization/Mir_utils.ml b/src/analysis_and_optimization/Mir_utils.ml index 28d9b54aec..5c098ce1eb 100644 --- a/src/analysis_and_optimization/Mir_utils.ml +++ b/src/analysis_and_optimization/Mir_utils.ml @@ -109,7 +109,7 @@ let rec var_declarations Stmt.Fixed.{pattern; _} : string Set.Poly.t = | IfElse (_, s, None) | While (_, s) | For {body= s; _} -> var_declarations s | IfElse (_, s1, Some s2) -> Set.Poly.union (var_declarations s1) (var_declarations s2) - | Block slist | SList slist -> + | Block slist | SList slist | Profile (_, slist) -> Set.Poly.union_list (List.map ~f:var_declarations slist) | _ -> Set.Poly.empty @@ -431,6 +431,7 @@ let cleanup_empty_stmts stmts = let is_decl = function {pattern= Decl _; _} -> true | _ -> false in let flatten_block s = match s.pattern with + (* NB: Does not include Profile since we don't want to remove those blocks *) | SList ls | Block ls -> if List.for_all ~f:(Fn.non is_decl) ls then ls else [s] | _ -> [s] in diff --git a/src/middle/Stmt.ml b/src/middle/Stmt.ml index fa33ca2761..4b2c94e605 100644 --- a/src/middle/Stmt.ml +++ b/src/middle/Stmt.ml @@ -51,8 +51,10 @@ module Fixed = struct | For {loopvar; lower; upper; body} -> Fmt.pf ppf "for(%s in %a:%a) %a" loopvar pp_e lower pp_e upper pp_s body - | Profile (_, stmts) -> - Fmt.pf ppf "{@;<1 2>@[%a@]@;}" Fmt.(list pp_s ~sep:cut) stmts + | Profile (name, stmts) -> + Fmt.pf ppf "profile(%s){@;<1 2>@[%a@]@;}" name + Fmt.(list pp_s ~sep:cut) + stmts | Block stmts -> Fmt.pf ppf "{@;<1 2>@[%a@]@;}" Fmt.(list pp_s ~sep:cut) stmts | SList stmts -> Fmt.(list pp_s ~sep:cut |> vbox) ppf stmts diff --git a/test/integration/good/compiler-optimizations/copy-prop-profile.stan b/test/integration/good/compiler-optimizations/copy-prop-profile.stan new file mode 100644 index 0000000000..6f0403b276 --- /dev/null +++ b/test/integration/good/compiler-optimizations/copy-prop-profile.stan @@ -0,0 +1,26 @@ +data { + int N; +} +parameters { + matrix[N,N] X; +} + +model { + row_vector[N] vec; + + profile ("test") { + row_vector[N] vec2 = columns_dot_self(X); + vec = vec2; + } + + target += sum(vec); + + row_vector[N] vec3; + { + row_vector[N] vec4 = columns_dot_self(X); + vec3 = vec4; + } + + target += sum(vec3); + +} diff --git a/test/integration/good/compiler-optimizations/cpp.expected b/test/integration/good/compiler-optimizations/cpp.expected index 4b23b26e92..ac6f345221 100644 --- a/test/integration/good/compiler-optimizations/cpp.expected +++ b/test/integration/good/compiler-optimizations/cpp.expected @@ -4164,6 +4164,374 @@ new_model(stan::io::var_context& data_context, unsigned int seed, stan::math::profile_map& get_stan_profile_data() { return ad_levels_deep_model_namespace::profiles__; } +#endif + $ ../../../../../install/default/bin/stanc --O --print-cpp copy-prop-profile.stan +// Code generated by %%NAME%% %%VERSION%% +#include +namespace copy_prop_profile_model_namespace { +using stan::model::model_base_crtp; +using namespace stan::math; +stan::math::profile_map profiles__; +static constexpr std::array locations_array__ = + {" (found before start of program)", + " (in 'copy-prop-profile.stan', line 5, column 2 to column 16)", + " (in 'copy-prop-profile.stan', line 9, column 13 to column 14)", + " (in 'copy-prop-profile.stan', line 9, column 2 to column 20)", + " (in 'copy-prop-profile.stan', line 12, column 15 to column 16)", + " (in 'copy-prop-profile.stan', line 12, column 4 to column 45)", + " (in 'copy-prop-profile.stan', line 11, column 2 to line 14, column 3)", + " (in 'copy-prop-profile.stan', line 18, column 13 to column 14)", + " (in 'copy-prop-profile.stan', line 18, column 2 to column 21)", + " (in 'copy-prop-profile.stan', line 20, column 15 to column 16)", + " (in 'copy-prop-profile.stan', line 20, column 4 to column 45)", + " (in 'copy-prop-profile.stan', line 19, column 2 to line 22, column 3)", + " (in 'copy-prop-profile.stan', line 24, column 2 to column 22)", + " (in 'copy-prop-profile.stan', line 2, column 2 to column 17)", + " (in 'copy-prop-profile.stan', line 5, column 9 to column 10)", + " (in 'copy-prop-profile.stan', line 5, column 11 to column 12)"}; +class copy_prop_profile_model final : public model_base_crtp { + private: + int N; + public: + ~copy_prop_profile_model() {} + copy_prop_profile_model(stan::io::var_context& context__, unsigned int + random_seed__ = 0, std::ostream* + pstream__ = nullptr) : model_base_crtp(0) { + int current_statement__ = 0; + using local_scalar_t__ = double; + boost::ecuyer1988 base_rng__ = + stan::services::util::create_rng(random_seed__, 0); + // suppress unused var warning + (void) base_rng__; + static constexpr const char* function__ = + "copy_prop_profile_model_namespace::copy_prop_profile_model"; + // suppress unused var warning + (void) function__; + local_scalar_t__ DUMMY_VAR__(std::numeric_limits::quiet_NaN()); + // suppress unused var warning + (void) DUMMY_VAR__; + try { + int pos__; + pos__ = 1; + current_statement__ = 13; + context__.validate_dims("data initialization", "N", "int", + std::vector{}); + N = std::numeric_limits::min(); + current_statement__ = 13; + N = context__.vals_i("N")[(1 - 1)]; + current_statement__ = 13; + stan::math::check_greater_or_equal(function__, "N", N, 0); + current_statement__ = 14; + stan::math::validate_non_negative_index("X", "N", N); + current_statement__ = 15; + stan::math::validate_non_negative_index("X", "N", N); + } catch (const std::exception& e) { + stan::lang::rethrow_located(e, locations_array__[current_statement__]); + } + num_params_r__ = (N * N); + } + inline std::string model_name() const final { + return "copy_prop_profile_model"; + } + inline std::vector model_compile_info() const noexcept { + return std::vector{"stanc_version = %%NAME%%3 %%VERSION%%", + "stancflags = --O --print-cpp"}; + } + template * = nullptr, + stan::require_vector_like_vt* = nullptr> + inline stan::scalar_type_t + log_prob_impl(VecR& params_r__, VecI& params_i__, std::ostream* + pstream__ = nullptr) const { + using T__ = stan::scalar_type_t; + using local_scalar_t__ = T__; + T__ lp__(0.0); + stan::math::accumulator lp_accum__; + stan::io::deserializer in__(params_r__, params_i__); + int current_statement__ = 0; + local_scalar_t__ DUMMY_VAR__(std::numeric_limits::quiet_NaN()); + // suppress unused var warning + (void) DUMMY_VAR__; + static constexpr const char* function__ = + "copy_prop_profile_model_namespace::log_prob"; + // suppress unused var warning + (void) function__; + try { + local_scalar_t__ lcm_sym5__; + Eigen::Matrix lcm_sym4__; + Eigen::Matrix X; + current_statement__ = 1; + X = in__.template read>(N, N); + { + current_statement__ = 2; + stan::math::validate_non_negative_index("vec", "N", N); + Eigen::Matrix vec = + Eigen::Matrix::Constant(N, + std::numeric_limits::quiet_NaN()); + current_statement__ = 6; + { + stan::math::profile profile__("test", + const_cast(profiles__)); + current_statement__ = 4; + stan::math::validate_non_negative_index("vec2", "N", N); + Eigen::Matrix vec2 = + Eigen::Matrix::Constant(N, + std::numeric_limits::quiet_NaN()); + stan::model::assign(lcm_sym4__, stan::math::columns_dot_self(X), + "assigning variable lcm_sym4__"); + } + lcm_sym5__ = stan::math::sum(lcm_sym4__); + lp_accum__.add(lcm_sym5__); + current_statement__ = 7; + stan::math::validate_non_negative_index("vec3", "N", N); + Eigen::Matrix vec3 = + Eigen::Matrix::Constant(N, + std::numeric_limits::quiet_NaN()); + { + current_statement__ = 9; + stan::math::validate_non_negative_index("vec4", "N", N); + Eigen::Matrix vec4 = + Eigen::Matrix::Constant(N, + std::numeric_limits::quiet_NaN()); + } + current_statement__ = 12; + lp_accum__.add(lcm_sym5__); + } + } catch (const std::exception& e) { + stan::lang::rethrow_located(e, locations_array__[current_statement__]); + } + lp_accum__.add(lp__); + return lp_accum__.sum(); + } + template * = nullptr, stan::require_vector_like_vt* = nullptr, stan::require_vector_vt* = nullptr> + inline void + write_array_impl(RNG& base_rng__, VecR& params_r__, VecI& params_i__, + VecVar& vars__, const bool + emit_transformed_parameters__ = true, const bool + emit_generated_quantities__ = true, std::ostream* + pstream__ = nullptr) const { + using local_scalar_t__ = double; + stan::io::deserializer in__(params_r__, params_i__); + stan::io::serializer out__(vars__); + static constexpr bool propto__ = true; + // suppress unused var warning + (void) propto__; + double lp__ = 0.0; + // suppress unused var warning + (void) lp__; + int current_statement__ = 0; + stan::math::accumulator lp_accum__; + local_scalar_t__ DUMMY_VAR__(std::numeric_limits::quiet_NaN()); + // suppress unused var warning + (void) DUMMY_VAR__; + constexpr bool jacobian__ = false; + static constexpr const char* function__ = + "copy_prop_profile_model_namespace::write_array"; + // suppress unused var warning + (void) function__; + try { + int lcm_sym3__; + int lcm_sym2__; + Eigen::Matrix X; + current_statement__ = 1; + X = in__.template read>(N, N); + out__.write(X); + if (stan::math::logical_negation( + (stan::math::primitive_value(emit_transformed_parameters__) || + stan::math::primitive_value(emit_generated_quantities__)))) { + return ; + } + if (stan::math::logical_negation(emit_generated_quantities__)) { + return ; + } + } catch (const std::exception& e) { + stan::lang::rethrow_located(e, locations_array__[current_statement__]); + } + } + template * = nullptr, + stan::require_vector_like_vt* = nullptr> + inline void + transform_inits_impl(VecVar& params_r__, VecI& params_i__, VecVar& vars__, + std::ostream* pstream__ = nullptr) const { + using local_scalar_t__ = double; + stan::io::deserializer in__(params_r__, params_i__); + stan::io::serializer out__(vars__); + int current_statement__ = 0; + local_scalar_t__ DUMMY_VAR__(std::numeric_limits::quiet_NaN()); + // suppress unused var warning + (void) DUMMY_VAR__; + try { + int lcm_sym1__; + int pos__; + pos__ = 1; + Eigen::Matrix X = + Eigen::Matrix::Constant(N, N, DUMMY_VAR__); + lcm_sym1__ = stan::math::logical_gte(N, 1); + if (lcm_sym1__) { + if (lcm_sym1__) { + stan::model::assign(X, in__.read(), + "assigning variable X", stan::model::index_uni(1), + stan::model::index_uni(1)); + for (int sym2__ = 2; sym2__ <= N; ++sym2__) { + stan::model::assign(X, in__.read(), + "assigning variable X", stan::model::index_uni(sym2__), + stan::model::index_uni(1)); + } + } + for (int sym1__ = 2; sym1__ <= N; ++sym1__) { + if (lcm_sym1__) { + stan::model::assign(X, in__.read(), + "assigning variable X", stan::model::index_uni(1), + stan::model::index_uni(sym1__)); + for (int sym2__ = 2; sym2__ <= N; ++sym2__) { + stan::model::assign(X, in__.read(), + "assigning variable X", stan::model::index_uni(sym2__), + stan::model::index_uni(sym1__)); + } + } + } + } + out__.write(X); + } catch (const std::exception& e) { + stan::lang::rethrow_located(e, locations_array__[current_statement__]); + } + } + inline void get_param_names(std::vector& names__) const { + names__ = std::vector{"X"}; + } + inline void get_dims(std::vector>& dimss__) const { + dimss__ = std::vector>{std::vector{static_cast< + size_t>(N), + static_cast(N)}}; + } + inline void + constrained_param_names(std::vector& param_names__, bool + emit_transformed_parameters__ = true, bool + emit_generated_quantities__ = true) const final { + for (int sym6__ = 1; sym6__ <= N; ++sym6__) { + for (int sym7__ = 1; sym7__ <= N; ++sym7__) { + param_names__.emplace_back(std::string() + "X" + '.' + + std::to_string(sym7__) + '.' + std::to_string(sym6__)); + } + } + if (emit_transformed_parameters__) {} + if (emit_generated_quantities__) {} + } + inline void + unconstrained_param_names(std::vector& param_names__, bool + emit_transformed_parameters__ = true, bool + emit_generated_quantities__ = true) const final { + for (int sym6__ = 1; sym6__ <= N; ++sym6__) { + for (int sym7__ = 1; sym7__ <= N; ++sym7__) { + param_names__.emplace_back(std::string() + "X" + '.' + + std::to_string(sym7__) + '.' + std::to_string(sym6__)); + } + } + if (emit_transformed_parameters__) {} + if (emit_generated_quantities__) {} + } + inline std::string get_constrained_sizedtypes() const { + return std::string("[{\"name\":\"X\",\"type\":{\"name\":\"matrix\",\"rows\":" + std::to_string(N) + ",\"cols\":" + std::to_string(N) + "},\"block\":\"parameters\"}]"); + } + inline std::string get_unconstrained_sizedtypes() const { + return std::string("[{\"name\":\"X\",\"type\":{\"name\":\"matrix\",\"rows\":" + std::to_string(N) + ",\"cols\":" + std::to_string(N) + "},\"block\":\"parameters\"}]"); + } + // Begin method overload boilerplate + template inline void + write_array(RNG& base_rng, Eigen::Matrix& params_r, + Eigen::Matrix& vars, const bool + emit_transformed_parameters = true, const bool + emit_generated_quantities = true, std::ostream* + pstream = nullptr) const { + const size_t num_params__ = (N * N); + const size_t num_transformed = emit_transformed_parameters * (0); + const size_t num_gen_quantities = emit_generated_quantities * (0); + const size_t num_to_write = num_params__ + num_transformed + + num_gen_quantities; + std::vector params_i; + vars = Eigen::Matrix::Constant(num_to_write, + std::numeric_limits::quiet_NaN()); + write_array_impl(base_rng, params_r, params_i, vars, + emit_transformed_parameters, emit_generated_quantities, pstream); + } + template inline void + write_array(RNG& base_rng, std::vector& params_r, std::vector& + params_i, std::vector& vars, bool + emit_transformed_parameters = true, bool + emit_generated_quantities = true, std::ostream* + pstream = nullptr) const { + const size_t num_params__ = (N * N); + const size_t num_transformed = emit_transformed_parameters * (0); + const size_t num_gen_quantities = emit_generated_quantities * (0); + const size_t num_to_write = num_params__ + num_transformed + + num_gen_quantities; + vars = std::vector(num_to_write, + std::numeric_limits::quiet_NaN()); + write_array_impl(base_rng, params_r, params_i, vars, + emit_transformed_parameters, emit_generated_quantities, pstream); + } + template inline T_ + log_prob(Eigen::Matrix& params_r, std::ostream* pstream = nullptr) const { + Eigen::Matrix params_i; + return log_prob_impl(params_r, params_i, pstream); + } + template inline T_ + log_prob(std::vector& params_r, std::vector& params_i, + std::ostream* pstream = nullptr) const { + return log_prob_impl(params_r, params_i, pstream); + } + inline void + transform_inits(const stan::io::var_context& context, + Eigen::Matrix& params_r, std::ostream* + pstream = nullptr) const final { + std::vector params_r_vec(params_r.size()); + std::vector params_i; + transform_inits(context, params_i, params_r_vec, pstream); + params_r = Eigen::Map>(params_r_vec.data(), + params_r_vec.size()); + } + inline void + transform_inits(const stan::io::var_context& context, std::vector& + params_i, std::vector& vars, std::ostream* + pstream__ = nullptr) const { + constexpr std::array names__{"X"}; + const std::array constrain_param_sizes__{(N * N)}; + const auto num_constrained_params__ = + std::accumulate(constrain_param_sizes__.begin(), + constrain_param_sizes__.end(), 0); + std::vector params_r_flat__(num_constrained_params__); + Eigen::Index size_iter__ = 0; + Eigen::Index flat_iter__ = 0; + for (auto&& param_name__: names__) { + const auto param_vec__ = context.vals_r(param_name__); + for (Eigen::Index i = 0; i < constrain_param_sizes__[size_iter__]; ++i) { + params_r_flat__[flat_iter__] = param_vec__[i]; + ++flat_iter__; + } + ++size_iter__; + } + vars.resize(num_params_r__); + transform_inits_impl(params_r_flat__, params_i, vars, pstream__); + } +}; +} +using stan_model = copy_prop_profile_model_namespace::copy_prop_profile_model; +#ifndef USING_R +// Boilerplate +stan::model::model_base& +new_model(stan::io::var_context& data_context, unsigned int seed, + std::ostream* msg_stream) { + stan_model* m = new stan_model(data_context, seed, msg_stream); + return *m; +} +stan::math::profile_map& get_stan_profile_data() { + return copy_prop_profile_model_namespace::profiles__; +} #endif $ ../../../../../install/default/bin/stanc --O --print-cpp copy_fail.stan // Code generated by %%NAME%% %%VERSION%% diff --git a/test/integration/good/compiler-optimizations/cppO0.expected b/test/integration/good/compiler-optimizations/cppO0.expected index 7489517773..9bce916df5 100644 --- a/test/integration/good/compiler-optimizations/cppO0.expected +++ b/test/integration/good/compiler-optimizations/cppO0.expected @@ -1482,6 +1482,361 @@ new_model(stan::io::var_context& data_context, unsigned int seed, stan::math::profile_map& get_stan_profile_data() { return ad_levels_deep_model_namespace::profiles__; } +#endif + $ ../../../../../install/default/bin/stanc --print-cpp --O0 copy-prop-profile.stan +// Code generated by %%NAME%% %%VERSION%% +#include +namespace copy_prop_profile_model_namespace { +using stan::model::model_base_crtp; +using namespace stan::math; +stan::math::profile_map profiles__; +static constexpr std::array locations_array__ = + {" (found before start of program)", + " (in 'copy-prop-profile.stan', line 5, column 2 to column 16)", + " (in 'copy-prop-profile.stan', line 9, column 13 to column 14)", + " (in 'copy-prop-profile.stan', line 9, column 2 to column 20)", + " (in 'copy-prop-profile.stan', line 12, column 15 to column 16)", + " (in 'copy-prop-profile.stan', line 12, column 4 to column 45)", + " (in 'copy-prop-profile.stan', line 13, column 4 to column 15)", + " (in 'copy-prop-profile.stan', line 11, column 2 to line 14, column 3)", + " (in 'copy-prop-profile.stan', line 16, column 2 to column 21)", + " (in 'copy-prop-profile.stan', line 18, column 13 to column 14)", + " (in 'copy-prop-profile.stan', line 18, column 2 to column 21)", + " (in 'copy-prop-profile.stan', line 20, column 15 to column 16)", + " (in 'copy-prop-profile.stan', line 20, column 4 to column 45)", + " (in 'copy-prop-profile.stan', line 21, column 4 to column 16)", + " (in 'copy-prop-profile.stan', line 19, column 2 to line 22, column 3)", + " (in 'copy-prop-profile.stan', line 24, column 2 to column 22)", + " (in 'copy-prop-profile.stan', line 2, column 2 to column 17)", + " (in 'copy-prop-profile.stan', line 5, column 9 to column 10)", + " (in 'copy-prop-profile.stan', line 5, column 11 to column 12)"}; +class copy_prop_profile_model final : public model_base_crtp { + private: + int N; + public: + ~copy_prop_profile_model() {} + copy_prop_profile_model(stan::io::var_context& context__, unsigned int + random_seed__ = 0, std::ostream* + pstream__ = nullptr) : model_base_crtp(0) { + int current_statement__ = 0; + using local_scalar_t__ = double; + boost::ecuyer1988 base_rng__ = + stan::services::util::create_rng(random_seed__, 0); + // suppress unused var warning + (void) base_rng__; + static constexpr const char* function__ = + "copy_prop_profile_model_namespace::copy_prop_profile_model"; + // suppress unused var warning + (void) function__; + local_scalar_t__ DUMMY_VAR__(std::numeric_limits::quiet_NaN()); + // suppress unused var warning + (void) DUMMY_VAR__; + try { + int pos__ = std::numeric_limits::min(); + pos__ = 1; + current_statement__ = 16; + context__.validate_dims("data initialization", "N", "int", + std::vector{}); + N = std::numeric_limits::min(); + current_statement__ = 16; + N = context__.vals_i("N")[(1 - 1)]; + current_statement__ = 16; + stan::math::check_greater_or_equal(function__, "N", N, 0); + current_statement__ = 17; + stan::math::validate_non_negative_index("X", "N", N); + current_statement__ = 18; + stan::math::validate_non_negative_index("X", "N", N); + } catch (const std::exception& e) { + stan::lang::rethrow_located(e, locations_array__[current_statement__]); + } + num_params_r__ = (N * N); + } + inline std::string model_name() const final { + return "copy_prop_profile_model"; + } + inline std::vector model_compile_info() const noexcept { + return std::vector{"stanc_version = %%NAME%%3 %%VERSION%%", + "stancflags = --print-cpp --O0"}; + } + template * = nullptr, + stan::require_vector_like_vt* = nullptr> + inline stan::scalar_type_t + log_prob_impl(VecR& params_r__, VecI& params_i__, std::ostream* + pstream__ = nullptr) const { + using T__ = stan::scalar_type_t; + using local_scalar_t__ = T__; + T__ lp__(0.0); + stan::math::accumulator lp_accum__; + stan::io::deserializer in__(params_r__, params_i__); + int current_statement__ = 0; + local_scalar_t__ DUMMY_VAR__(std::numeric_limits::quiet_NaN()); + // suppress unused var warning + (void) DUMMY_VAR__; + static constexpr const char* function__ = + "copy_prop_profile_model_namespace::log_prob"; + // suppress unused var warning + (void) function__; + try { + Eigen::Matrix X = + Eigen::Matrix::Constant(N, N, DUMMY_VAR__); + current_statement__ = 1; + X = in__.template read>(N, N); + { + current_statement__ = 2; + stan::math::validate_non_negative_index("vec", "N", N); + Eigen::Matrix vec = + Eigen::Matrix::Constant(N, DUMMY_VAR__); + current_statement__ = 7; + { + stan::math::profile profile__("test", + const_cast(profiles__)); + current_statement__ = 4; + stan::math::validate_non_negative_index("vec2", "N", N); + Eigen::Matrix vec2 = + Eigen::Matrix::Constant(N, DUMMY_VAR__); + current_statement__ = 5; + stan::model::assign(vec2, stan::math::columns_dot_self(X), + "assigning variable vec2"); + current_statement__ = 6; + stan::model::assign(vec, vec2, "assigning variable vec"); + } + current_statement__ = 8; + lp_accum__.add(stan::math::sum(vec)); + current_statement__ = 9; + stan::math::validate_non_negative_index("vec3", "N", N); + Eigen::Matrix vec3 = + Eigen::Matrix::Constant(N, DUMMY_VAR__); + { + current_statement__ = 11; + stan::math::validate_non_negative_index("vec4", "N", N); + Eigen::Matrix vec4 = + Eigen::Matrix::Constant(N, DUMMY_VAR__); + current_statement__ = 12; + stan::model::assign(vec4, stan::math::columns_dot_self(X), + "assigning variable vec4"); + current_statement__ = 13; + stan::model::assign(vec3, vec4, "assigning variable vec3"); + } + current_statement__ = 15; + lp_accum__.add(stan::math::sum(vec3)); + } + } catch (const std::exception& e) { + stan::lang::rethrow_located(e, locations_array__[current_statement__]); + } + lp_accum__.add(lp__); + return lp_accum__.sum(); + } + template * = nullptr, stan::require_vector_like_vt* = nullptr, stan::require_vector_vt* = nullptr> + inline void + write_array_impl(RNG& base_rng__, VecR& params_r__, VecI& params_i__, + VecVar& vars__, const bool + emit_transformed_parameters__ = true, const bool + emit_generated_quantities__ = true, std::ostream* + pstream__ = nullptr) const { + using local_scalar_t__ = double; + stan::io::deserializer in__(params_r__, params_i__); + stan::io::serializer out__(vars__); + static constexpr bool propto__ = true; + // suppress unused var warning + (void) propto__; + double lp__ = 0.0; + // suppress unused var warning + (void) lp__; + int current_statement__ = 0; + stan::math::accumulator lp_accum__; + local_scalar_t__ DUMMY_VAR__(std::numeric_limits::quiet_NaN()); + // suppress unused var warning + (void) DUMMY_VAR__; + constexpr bool jacobian__ = false; + static constexpr const char* function__ = + "copy_prop_profile_model_namespace::write_array"; + // suppress unused var warning + (void) function__; + try { + Eigen::Matrix X = + Eigen::Matrix::Constant(N, N, + std::numeric_limits::quiet_NaN()); + current_statement__ = 1; + X = in__.template read>(N, N); + out__.write(X); + if (stan::math::logical_negation( + (stan::math::primitive_value(emit_transformed_parameters__) || + stan::math::primitive_value(emit_generated_quantities__)))) { + return ; + } + if (stan::math::logical_negation(emit_generated_quantities__)) { + return ; + } + } catch (const std::exception& e) { + stan::lang::rethrow_located(e, locations_array__[current_statement__]); + } + } + template * = nullptr, + stan::require_vector_like_vt* = nullptr> + inline void + transform_inits_impl(VecVar& params_r__, VecI& params_i__, VecVar& vars__, + std::ostream* pstream__ = nullptr) const { + using local_scalar_t__ = double; + stan::io::deserializer in__(params_r__, params_i__); + stan::io::serializer out__(vars__); + int current_statement__ = 0; + local_scalar_t__ DUMMY_VAR__(std::numeric_limits::quiet_NaN()); + // suppress unused var warning + (void) DUMMY_VAR__; + try { + int pos__ = std::numeric_limits::min(); + pos__ = 1; + Eigen::Matrix X = + Eigen::Matrix::Constant(N, N, DUMMY_VAR__); + for (int sym1__ = 1; sym1__ <= N; ++sym1__) { + for (int sym2__ = 1; sym2__ <= N; ++sym2__) { + stan::model::assign(X, in__.read(), + "assigning variable X", stan::model::index_uni(sym2__), + stan::model::index_uni(sym1__)); + } + } + out__.write(X); + } catch (const std::exception& e) { + stan::lang::rethrow_located(e, locations_array__[current_statement__]); + } + } + inline void get_param_names(std::vector& names__) const { + names__ = std::vector{"X"}; + } + inline void get_dims(std::vector>& dimss__) const { + dimss__ = std::vector>{std::vector{static_cast< + size_t>(N), + static_cast(N)}}; + } + inline void + constrained_param_names(std::vector& param_names__, bool + emit_transformed_parameters__ = true, bool + emit_generated_quantities__ = true) const final { + for (int sym1__ = 1; sym1__ <= N; ++sym1__) { + for (int sym2__ = 1; sym2__ <= N; ++sym2__) { + param_names__.emplace_back(std::string() + "X" + '.' + + std::to_string(sym2__) + '.' + std::to_string(sym1__)); + } + } + if (emit_transformed_parameters__) {} + if (emit_generated_quantities__) {} + } + inline void + unconstrained_param_names(std::vector& param_names__, bool + emit_transformed_parameters__ = true, bool + emit_generated_quantities__ = true) const final { + for (int sym1__ = 1; sym1__ <= N; ++sym1__) { + for (int sym2__ = 1; sym2__ <= N; ++sym2__) { + param_names__.emplace_back(std::string() + "X" + '.' + + std::to_string(sym2__) + '.' + std::to_string(sym1__)); + } + } + if (emit_transformed_parameters__) {} + if (emit_generated_quantities__) {} + } + inline std::string get_constrained_sizedtypes() const { + return std::string("[{\"name\":\"X\",\"type\":{\"name\":\"matrix\",\"rows\":" + std::to_string(N) + ",\"cols\":" + std::to_string(N) + "},\"block\":\"parameters\"}]"); + } + inline std::string get_unconstrained_sizedtypes() const { + return std::string("[{\"name\":\"X\",\"type\":{\"name\":\"matrix\",\"rows\":" + std::to_string(N) + ",\"cols\":" + std::to_string(N) + "},\"block\":\"parameters\"}]"); + } + // Begin method overload boilerplate + template inline void + write_array(RNG& base_rng, Eigen::Matrix& params_r, + Eigen::Matrix& vars, const bool + emit_transformed_parameters = true, const bool + emit_generated_quantities = true, std::ostream* + pstream = nullptr) const { + const size_t num_params__ = (N * N); + const size_t num_transformed = emit_transformed_parameters * (0); + const size_t num_gen_quantities = emit_generated_quantities * (0); + const size_t num_to_write = num_params__ + num_transformed + + num_gen_quantities; + std::vector params_i; + vars = Eigen::Matrix::Constant(num_to_write, + std::numeric_limits::quiet_NaN()); + write_array_impl(base_rng, params_r, params_i, vars, + emit_transformed_parameters, emit_generated_quantities, pstream); + } + template inline void + write_array(RNG& base_rng, std::vector& params_r, std::vector& + params_i, std::vector& vars, bool + emit_transformed_parameters = true, bool + emit_generated_quantities = true, std::ostream* + pstream = nullptr) const { + const size_t num_params__ = (N * N); + const size_t num_transformed = emit_transformed_parameters * (0); + const size_t num_gen_quantities = emit_generated_quantities * (0); + const size_t num_to_write = num_params__ + num_transformed + + num_gen_quantities; + vars = std::vector(num_to_write, + std::numeric_limits::quiet_NaN()); + write_array_impl(base_rng, params_r, params_i, vars, + emit_transformed_parameters, emit_generated_quantities, pstream); + } + template inline T_ + log_prob(Eigen::Matrix& params_r, std::ostream* pstream = nullptr) const { + Eigen::Matrix params_i; + return log_prob_impl(params_r, params_i, pstream); + } + template inline T_ + log_prob(std::vector& params_r, std::vector& params_i, + std::ostream* pstream = nullptr) const { + return log_prob_impl(params_r, params_i, pstream); + } + inline void + transform_inits(const stan::io::var_context& context, + Eigen::Matrix& params_r, std::ostream* + pstream = nullptr) const final { + std::vector params_r_vec(params_r.size()); + std::vector params_i; + transform_inits(context, params_i, params_r_vec, pstream); + params_r = Eigen::Map>(params_r_vec.data(), + params_r_vec.size()); + } + inline void + transform_inits(const stan::io::var_context& context, std::vector& + params_i, std::vector& vars, std::ostream* + pstream__ = nullptr) const { + constexpr std::array names__{"X"}; + const std::array constrain_param_sizes__{(N * N)}; + const auto num_constrained_params__ = + std::accumulate(constrain_param_sizes__.begin(), + constrain_param_sizes__.end(), 0); + std::vector params_r_flat__(num_constrained_params__); + Eigen::Index size_iter__ = 0; + Eigen::Index flat_iter__ = 0; + for (auto&& param_name__: names__) { + const auto param_vec__ = context.vals_r(param_name__); + for (Eigen::Index i = 0; i < constrain_param_sizes__[size_iter__]; ++i) { + params_r_flat__[flat_iter__] = param_vec__[i]; + ++flat_iter__; + } + ++size_iter__; + } + vars.resize(num_params_r__); + transform_inits_impl(params_r_flat__, params_i, vars, pstream__); + } +}; +} +using stan_model = copy_prop_profile_model_namespace::copy_prop_profile_model; +#ifndef USING_R +// Boilerplate +stan::model::model_base& +new_model(stan::io::var_context& data_context, unsigned int seed, + std::ostream* msg_stream) { + stan_model* m = new stan_model(data_context, seed, msg_stream); + return *m; +} +stan::math::profile_map& get_stan_profile_data() { + return copy_prop_profile_model_namespace::profiles__; +} #endif $ ../../../../../install/default/bin/stanc --print-cpp --O0 copy_fail.stan // Code generated by %%NAME%% %%VERSION%% diff --git a/test/integration/good/compiler-optimizations/cppO1.expected b/test/integration/good/compiler-optimizations/cppO1.expected index e7fbf942a9..8091f8f7db 100644 --- a/test/integration/good/compiler-optimizations/cppO1.expected +++ b/test/integration/good/compiler-optimizations/cppO1.expected @@ -1480,6 +1480,356 @@ new_model(stan::io::var_context& data_context, unsigned int seed, stan::math::profile_map& get_stan_profile_data() { return ad_levels_deep_model_namespace::profiles__; } +#endif + $ ../../../../../install/default/bin/stanc --O1 --print-cpp copy-prop-profile.stan +// Code generated by %%NAME%% %%VERSION%% +#include +namespace copy_prop_profile_model_namespace { +using stan::model::model_base_crtp; +using namespace stan::math; +stan::math::profile_map profiles__; +static constexpr std::array locations_array__ = + {" (found before start of program)", + " (in 'copy-prop-profile.stan', line 5, column 2 to column 16)", + " (in 'copy-prop-profile.stan', line 9, column 13 to column 14)", + " (in 'copy-prop-profile.stan', line 9, column 2 to column 20)", + " (in 'copy-prop-profile.stan', line 12, column 15 to column 16)", + " (in 'copy-prop-profile.stan', line 12, column 4 to column 45)", + " (in 'copy-prop-profile.stan', line 13, column 4 to column 15)", + " (in 'copy-prop-profile.stan', line 11, column 2 to line 14, column 3)", + " (in 'copy-prop-profile.stan', line 16, column 2 to column 21)", + " (in 'copy-prop-profile.stan', line 18, column 13 to column 14)", + " (in 'copy-prop-profile.stan', line 18, column 2 to column 21)", + " (in 'copy-prop-profile.stan', line 20, column 15 to column 16)", + " (in 'copy-prop-profile.stan', line 20, column 4 to column 45)", + " (in 'copy-prop-profile.stan', line 21, column 4 to column 16)", + " (in 'copy-prop-profile.stan', line 19, column 2 to line 22, column 3)", + " (in 'copy-prop-profile.stan', line 24, column 2 to column 22)", + " (in 'copy-prop-profile.stan', line 2, column 2 to column 17)", + " (in 'copy-prop-profile.stan', line 5, column 9 to column 10)", + " (in 'copy-prop-profile.stan', line 5, column 11 to column 12)"}; +class copy_prop_profile_model final : public model_base_crtp { + private: + int N; + public: + ~copy_prop_profile_model() {} + copy_prop_profile_model(stan::io::var_context& context__, unsigned int + random_seed__ = 0, std::ostream* + pstream__ = nullptr) : model_base_crtp(0) { + int current_statement__ = 0; + using local_scalar_t__ = double; + boost::ecuyer1988 base_rng__ = + stan::services::util::create_rng(random_seed__, 0); + // suppress unused var warning + (void) base_rng__; + static constexpr const char* function__ = + "copy_prop_profile_model_namespace::copy_prop_profile_model"; + // suppress unused var warning + (void) function__; + local_scalar_t__ DUMMY_VAR__(std::numeric_limits::quiet_NaN()); + // suppress unused var warning + (void) DUMMY_VAR__; + try { + int pos__; + pos__ = 1; + current_statement__ = 16; + context__.validate_dims("data initialization", "N", "int", + std::vector{}); + N = std::numeric_limits::min(); + current_statement__ = 16; + N = context__.vals_i("N")[(1 - 1)]; + current_statement__ = 16; + stan::math::check_greater_or_equal(function__, "N", N, 0); + current_statement__ = 17; + stan::math::validate_non_negative_index("X", "N", N); + current_statement__ = 18; + stan::math::validate_non_negative_index("X", "N", N); + } catch (const std::exception& e) { + stan::lang::rethrow_located(e, locations_array__[current_statement__]); + } + num_params_r__ = (N * N); + } + inline std::string model_name() const final { + return "copy_prop_profile_model"; + } + inline std::vector model_compile_info() const noexcept { + return std::vector{"stanc_version = %%NAME%%3 %%VERSION%%", + "stancflags = --O1 --print-cpp"}; + } + template * = nullptr, + stan::require_vector_like_vt* = nullptr> + inline stan::scalar_type_t + log_prob_impl(VecR& params_r__, VecI& params_i__, std::ostream* + pstream__ = nullptr) const { + using T__ = stan::scalar_type_t; + using local_scalar_t__ = T__; + T__ lp__(0.0); + stan::math::accumulator lp_accum__; + stan::io::deserializer in__(params_r__, params_i__); + int current_statement__ = 0; + local_scalar_t__ DUMMY_VAR__(std::numeric_limits::quiet_NaN()); + // suppress unused var warning + (void) DUMMY_VAR__; + static constexpr const char* function__ = + "copy_prop_profile_model_namespace::log_prob"; + // suppress unused var warning + (void) function__; + try { + Eigen::Matrix X; + current_statement__ = 1; + X = in__.template read>(N, N); + { + current_statement__ = 2; + stan::math::validate_non_negative_index("vec", "N", N); + Eigen::Matrix vec = + Eigen::Matrix::Constant(N, DUMMY_VAR__); + current_statement__ = 7; + { + stan::math::profile profile__("test", + const_cast(profiles__)); + current_statement__ = 4; + stan::math::validate_non_negative_index("vec2", "N", N); + Eigen::Matrix vec2; + current_statement__ = 5; + stan::model::assign(vec2, stan::math::columns_dot_self(X), + "assigning variable vec2"); + current_statement__ = 6; + stan::model::assign(vec, vec2, "assigning variable vec"); + } + current_statement__ = 8; + lp_accum__.add(stan::math::sum(vec)); + current_statement__ = 9; + stan::math::validate_non_negative_index("vec3", "N", N); + Eigen::Matrix vec3 = + Eigen::Matrix::Constant(N, DUMMY_VAR__); + { + current_statement__ = 11; + stan::math::validate_non_negative_index("vec4", "N", N); + Eigen::Matrix vec4; + current_statement__ = 12; + stan::model::assign(vec4, stan::math::columns_dot_self(X), + "assigning variable vec4"); + current_statement__ = 13; + stan::model::assign(vec3, vec4, "assigning variable vec3"); + } + current_statement__ = 15; + lp_accum__.add(stan::math::sum(vec3)); + } + } catch (const std::exception& e) { + stan::lang::rethrow_located(e, locations_array__[current_statement__]); + } + lp_accum__.add(lp__); + return lp_accum__.sum(); + } + template * = nullptr, stan::require_vector_like_vt* = nullptr, stan::require_vector_vt* = nullptr> + inline void + write_array_impl(RNG& base_rng__, VecR& params_r__, VecI& params_i__, + VecVar& vars__, const bool + emit_transformed_parameters__ = true, const bool + emit_generated_quantities__ = true, std::ostream* + pstream__ = nullptr) const { + using local_scalar_t__ = double; + stan::io::deserializer in__(params_r__, params_i__); + stan::io::serializer out__(vars__); + static constexpr bool propto__ = true; + // suppress unused var warning + (void) propto__; + double lp__ = 0.0; + // suppress unused var warning + (void) lp__; + int current_statement__ = 0; + stan::math::accumulator lp_accum__; + local_scalar_t__ DUMMY_VAR__(std::numeric_limits::quiet_NaN()); + // suppress unused var warning + (void) DUMMY_VAR__; + constexpr bool jacobian__ = false; + static constexpr const char* function__ = + "copy_prop_profile_model_namespace::write_array"; + // suppress unused var warning + (void) function__; + try { + Eigen::Matrix X; + current_statement__ = 1; + X = in__.template read>(N, N); + out__.write(X); + if (stan::math::logical_negation( + (stan::math::primitive_value(emit_transformed_parameters__) || + stan::math::primitive_value(emit_generated_quantities__)))) { + return ; + } + if (stan::math::logical_negation(emit_generated_quantities__)) { + return ; + } + } catch (const std::exception& e) { + stan::lang::rethrow_located(e, locations_array__[current_statement__]); + } + } + template * = nullptr, + stan::require_vector_like_vt* = nullptr> + inline void + transform_inits_impl(VecVar& params_r__, VecI& params_i__, VecVar& vars__, + std::ostream* pstream__ = nullptr) const { + using local_scalar_t__ = double; + stan::io::deserializer in__(params_r__, params_i__); + stan::io::serializer out__(vars__); + int current_statement__ = 0; + local_scalar_t__ DUMMY_VAR__(std::numeric_limits::quiet_NaN()); + // suppress unused var warning + (void) DUMMY_VAR__; + try { + int pos__; + pos__ = 1; + Eigen::Matrix X = + Eigen::Matrix::Constant(N, N, DUMMY_VAR__); + for (int sym1__ = 1; sym1__ <= N; ++sym1__) { + for (int sym2__ = 1; sym2__ <= N; ++sym2__) { + stan::model::assign(X, in__.read(), + "assigning variable X", stan::model::index_uni(sym2__), + stan::model::index_uni(sym1__)); + } + } + out__.write(X); + } catch (const std::exception& e) { + stan::lang::rethrow_located(e, locations_array__[current_statement__]); + } + } + inline void get_param_names(std::vector& names__) const { + names__ = std::vector{"X"}; + } + inline void get_dims(std::vector>& dimss__) const { + dimss__ = std::vector>{std::vector{static_cast< + size_t>(N), + static_cast(N)}}; + } + inline void + constrained_param_names(std::vector& param_names__, bool + emit_transformed_parameters__ = true, bool + emit_generated_quantities__ = true) const final { + for (int sym1__ = 1; sym1__ <= N; ++sym1__) { + for (int sym2__ = 1; sym2__ <= N; ++sym2__) { + param_names__.emplace_back(std::string() + "X" + '.' + + std::to_string(sym2__) + '.' + std::to_string(sym1__)); + } + } + if (emit_transformed_parameters__) {} + if (emit_generated_quantities__) {} + } + inline void + unconstrained_param_names(std::vector& param_names__, bool + emit_transformed_parameters__ = true, bool + emit_generated_quantities__ = true) const final { + for (int sym1__ = 1; sym1__ <= N; ++sym1__) { + for (int sym2__ = 1; sym2__ <= N; ++sym2__) { + param_names__.emplace_back(std::string() + "X" + '.' + + std::to_string(sym2__) + '.' + std::to_string(sym1__)); + } + } + if (emit_transformed_parameters__) {} + if (emit_generated_quantities__) {} + } + inline std::string get_constrained_sizedtypes() const { + return std::string("[{\"name\":\"X\",\"type\":{\"name\":\"matrix\",\"rows\":" + std::to_string(N) + ",\"cols\":" + std::to_string(N) + "},\"block\":\"parameters\"}]"); + } + inline std::string get_unconstrained_sizedtypes() const { + return std::string("[{\"name\":\"X\",\"type\":{\"name\":\"matrix\",\"rows\":" + std::to_string(N) + ",\"cols\":" + std::to_string(N) + "},\"block\":\"parameters\"}]"); + } + // Begin method overload boilerplate + template inline void + write_array(RNG& base_rng, Eigen::Matrix& params_r, + Eigen::Matrix& vars, const bool + emit_transformed_parameters = true, const bool + emit_generated_quantities = true, std::ostream* + pstream = nullptr) const { + const size_t num_params__ = (N * N); + const size_t num_transformed = emit_transformed_parameters * (0); + const size_t num_gen_quantities = emit_generated_quantities * (0); + const size_t num_to_write = num_params__ + num_transformed + + num_gen_quantities; + std::vector params_i; + vars = Eigen::Matrix::Constant(num_to_write, + std::numeric_limits::quiet_NaN()); + write_array_impl(base_rng, params_r, params_i, vars, + emit_transformed_parameters, emit_generated_quantities, pstream); + } + template inline void + write_array(RNG& base_rng, std::vector& params_r, std::vector& + params_i, std::vector& vars, bool + emit_transformed_parameters = true, bool + emit_generated_quantities = true, std::ostream* + pstream = nullptr) const { + const size_t num_params__ = (N * N); + const size_t num_transformed = emit_transformed_parameters * (0); + const size_t num_gen_quantities = emit_generated_quantities * (0); + const size_t num_to_write = num_params__ + num_transformed + + num_gen_quantities; + vars = std::vector(num_to_write, + std::numeric_limits::quiet_NaN()); + write_array_impl(base_rng, params_r, params_i, vars, + emit_transformed_parameters, emit_generated_quantities, pstream); + } + template inline T_ + log_prob(Eigen::Matrix& params_r, std::ostream* pstream = nullptr) const { + Eigen::Matrix params_i; + return log_prob_impl(params_r, params_i, pstream); + } + template inline T_ + log_prob(std::vector& params_r, std::vector& params_i, + std::ostream* pstream = nullptr) const { + return log_prob_impl(params_r, params_i, pstream); + } + inline void + transform_inits(const stan::io::var_context& context, + Eigen::Matrix& params_r, std::ostream* + pstream = nullptr) const final { + std::vector params_r_vec(params_r.size()); + std::vector params_i; + transform_inits(context, params_i, params_r_vec, pstream); + params_r = Eigen::Map>(params_r_vec.data(), + params_r_vec.size()); + } + inline void + transform_inits(const stan::io::var_context& context, std::vector& + params_i, std::vector& vars, std::ostream* + pstream__ = nullptr) const { + constexpr std::array names__{"X"}; + const std::array constrain_param_sizes__{(N * N)}; + const auto num_constrained_params__ = + std::accumulate(constrain_param_sizes__.begin(), + constrain_param_sizes__.end(), 0); + std::vector params_r_flat__(num_constrained_params__); + Eigen::Index size_iter__ = 0; + Eigen::Index flat_iter__ = 0; + for (auto&& param_name__: names__) { + const auto param_vec__ = context.vals_r(param_name__); + for (Eigen::Index i = 0; i < constrain_param_sizes__[size_iter__]; ++i) { + params_r_flat__[flat_iter__] = param_vec__[i]; + ++flat_iter__; + } + ++size_iter__; + } + vars.resize(num_params_r__); + transform_inits_impl(params_r_flat__, params_i, vars, pstream__); + } +}; +} +using stan_model = copy_prop_profile_model_namespace::copy_prop_profile_model; +#ifndef USING_R +// Boilerplate +stan::model::model_base& +new_model(stan::io::var_context& data_context, unsigned int seed, + std::ostream* msg_stream) { + stan_model* m = new stan_model(data_context, seed, msg_stream); + return *m; +} +stan::math::profile_map& get_stan_profile_data() { + return copy_prop_profile_model_namespace::profiles__; +} #endif $ ../../../../../install/default/bin/stanc --O1 --print-cpp copy_fail.stan // Code generated by %%NAME%% %%VERSION%%