-
-
Notifications
You must be signed in to change notification settings - Fork 380
Open
Description
Summary:
The deep_copy
function is applied to right-hand sides of assignments to avoid aliasing. However, all of our array slicing makes a copy itself, so this isn't necessary.
Also, if we don't use deep_copy
anywhere else in the code base, we can remove the deep_copy
function too (I'm not sure if this is defined in this repo or in stan-dev/math
; if the latter, we'll need a new issue).
Reproducible Steps:
You can test this with:
parameters {
real<lower = 0, upper = 1> foo;
}
generated quantities {
vector[3] a = [1, 2, 3]';
a[2:3] += a[1:2];
}
and get the right answer in the current setup which forgot to include the deep_copy
,
Current Output:
mean
a[1] 1.00
a[2] 3.00
a[3] 5.00
Expected Output:
This is correct, so we don't need the deep_copy
. Here's the generated C++ to validate there's no deep copy happening:
// Code generated by Stan version 2.18.0
#include <stan/model/model_header.hpp>
namespace foo_model_namespace {
using std::istream;
using std::string;
using std::stringstream;
using std::vector;
using stan::io::dump;
using stan::math::lgamma;
using stan::model::prob_grad;
using namespace stan::math;
static int current_statement_begin__;
stan::io::program_reader prog_reader__() {
stan::io::program_reader reader;
reader.add_event(0, 0, "start", "/Users/carp/temp2/foo.stan");
reader.add_event(8, 6, "end", "/Users/carp/temp2/foo.stan");
return reader;
}
class foo_model : public prob_grad {
private:
int a;
public:
foo_model(stan::io::var_context& context__,
std::ostream* pstream__ = 0)
: prob_grad(0) {
ctor_body(context__, 0, pstream__);
}
foo_model(stan::io::var_context& context__,
unsigned int random_seed__,
std::ostream* pstream__ = 0)
: prob_grad(0) {
ctor_body(context__, random_seed__, pstream__);
}
void ctor_body(stan::io::var_context& context__,
unsigned int random_seed__,
std::ostream* pstream__) {
typedef double local_scalar_t__;
boost::ecuyer1988 base_rng__ =
stan::services::util::create_rng(random_seed__, 0);
(void) base_rng__; // suppress unused var warning
current_statement_begin__ = -1;
static const char* function__ = "foo_model_namespace::foo_model";
(void) function__; // dummy to suppress unused var warning
size_t pos__;
(void) pos__; // dummy to suppress unused var warning
std::vector<int> vals_i__;
std::vector<double> vals_r__;
local_scalar_t__ DUMMY_VAR__(std::numeric_limits<double>::quiet_NaN());
(void) DUMMY_VAR__; // suppress unused var warning
// initialize member variables
try {
// validate, data variables
// initialize data variables
current_statement_begin__ = 2;
a = int(0);
stan::math::fill(a, std::numeric_limits<int>::min());
{
current_statement_begin__ = 4;
validate_non_negative_index("b", "2", 2);
vector<local_scalar_t__> b(2);
stan::math::initialize(b, DUMMY_VAR__);
stan::math::fill(b,DUMMY_VAR__);
stan::math::assign(b,static_cast<std::vector<double> >(stan::math::array_builder<double >().add(3).add(4.0).array()));
}
// validate transformed data
current_statement_begin__ = 2;
// validate, set parameter ranges
num_params_r__ = 0U;
param_ranges_i__.clear();
} catch (const std::exception& e) {
stan::lang::rethrow_located(e, current_statement_begin__, prog_reader__());
// Next line prevents compiler griping about no return
throw std::runtime_error("*** IF YOU SEE THIS, PLEASE REPORT A BUG ***");
}
}
~foo_model() { }
void transform_inits(const stan::io::var_context& context__,
std::vector<int>& params_i__,
std::vector<double>& params_r__,
std::ostream* pstream__) const {
stan::io::writer<double> writer__(params_r__,params_i__);
size_t pos__;
(void) pos__; // dummy call to supress warning
std::vector<double> vals_r__;
std::vector<int> vals_i__;
params_r__ = writer__.data_r();
params_i__ = writer__.data_i();
}
void transform_inits(const stan::io::var_context& context,
Eigen::Matrix<double,Eigen::Dynamic,1>& params_r,
std::ostream* pstream__) const {
std::vector<double> params_r_vec;
std::vector<int> params_i_vec;
transform_inits(context, params_i_vec, params_r_vec, pstream__);
params_r.resize(params_r_vec.size());
for (int i = 0; i < params_r.size(); ++i)
params_r(i) = params_r_vec[i];
}
template <bool propto__, bool jacobian__, typename T__>
T__ log_prob(vector<T__>& params_r__,
vector<int>& params_i__,
std::ostream* pstream__ = 0) const {
typedef T__ local_scalar_t__;
local_scalar_t__ DUMMY_VAR__(std::numeric_limits<double>::quiet_NaN());
(void) DUMMY_VAR__; // suppress unused var warning
T__ lp__(0.0);
stan::math::accumulator<T__> lp_accum__;
try {
// model parameters
stan::io::reader<local_scalar_t__> in__(params_r__,params_i__);
// transformed parameters
// validate transformed parameters
const char* function__ = "validate transformed params";
(void) function__; // dummy to suppress unused var warning
// model body
} catch (const std::exception& e) {
stan::lang::rethrow_located(e, current_statement_begin__, prog_reader__());
// Next line prevents compiler griping about no return
throw std::runtime_error("*** IF YOU SEE THIS, PLEASE REPORT A BUG ***");
}
lp_accum__.add(lp__);
return lp_accum__.sum();
} // log_prob()
template <bool propto, bool jacobian, typename T_>
T_ log_prob(Eigen::Matrix<T_,Eigen::Dynamic,1>& params_r,
std::ostream* pstream = 0) const {
std::vector<T_> vec_params_r;
vec_params_r.reserve(params_r.size());
for (int i = 0; i < params_r.size(); ++i)
vec_params_r.push_back(params_r(i));
std::vector<int> vec_params_i;
return log_prob<propto,jacobian,T_>(vec_params_r, vec_params_i, pstream);
}
void get_param_names(std::vector<std::string>& names__) const {
names__.resize(0);
}
void get_dims(std::vector<std::vector<size_t> >& dimss__) const {
dimss__.resize(0);
std::vector<size_t> dims__;
}
template <typename RNG>
void write_array(RNG& base_rng__,
std::vector<double>& params_r__,
std::vector<int>& params_i__,
std::vector<double>& vars__,
bool include_tparams__ = true,
bool include_gqs__ = true,
std::ostream* pstream__ = 0) const {
typedef double local_scalar_t__;
vars__.resize(0);
stan::io::reader<local_scalar_t__> in__(params_r__,params_i__);
static const char* function__ = "foo_model_namespace::write_array";
(void) function__; // dummy to suppress unused var warning
// read-transform, write parameters
// declare and define transformed parameters
double lp__ = 0.0;
(void) lp__; // dummy to suppress unused var warning
stan::math::accumulator<double> lp_accum__;
local_scalar_t__ DUMMY_VAR__(std::numeric_limits<double>::quiet_NaN());
(void) DUMMY_VAR__; // suppress unused var warning
try {
// validate transformed parameters
// write transformed parameters
if (include_tparams__) {
}
if (!include_gqs__) return;
// declare and define generated quantities
// validate generated quantities
// write generated quantities
} catch (const std::exception& e) {
stan::lang::rethrow_located(e, current_statement_begin__, prog_reader__());
// Next line prevents compiler griping about no return
throw std::runtime_error("*** IF YOU SEE THIS, PLEASE REPORT A BUG ***");
}
}
template <typename RNG>
void write_array(RNG& base_rng,
Eigen::Matrix<double,Eigen::Dynamic,1>& params_r,
Eigen::Matrix<double,Eigen::Dynamic,1>& vars,
bool include_tparams = true,
bool include_gqs = true,
std::ostream* pstream = 0) const {
std::vector<double> params_r_vec(params_r.size());
for (int i = 0; i < params_r.size(); ++i)
params_r_vec[i] = params_r(i);
std::vector<double> vars_vec;
std::vector<int> params_i_vec;
write_array(base_rng,params_r_vec,params_i_vec,vars_vec,include_tparams,include_gqs,pstream);
vars.resize(vars_vec.size());
for (int i = 0; i < vars.size(); ++i)
vars(i) = vars_vec[i];
}
static std::string model_name() {
return "foo_model";
}
void constrained_param_names(std::vector<std::string>& param_names__,
bool include_tparams__ = true,
bool include_gqs__ = true) const {
std::stringstream param_name_stream__;
if (!include_gqs__ && !include_tparams__) return;
if (include_tparams__) {
}
if (!include_gqs__) return;
}
void unconstrained_param_names(std::vector<std::string>& param_names__,
bool include_tparams__ = true,
bool include_gqs__ = true) const {
std::stringstream param_name_stream__;
if (!include_gqs__ && !include_tparams__) return;
if (include_tparams__) {
}
if (!include_gqs__) return;
}
}; // model
}
typedef foo_model_namespace::foo_model stan_model;
Current Version:
v2.18.0