// Code generated by Stan version 2.17.0

#include <stan/model/model_header.hpp>

namespace model24d279588d9b_cfb328cb1cc3c4dfe650ba42c7f8951a_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;

typedef Eigen::Matrix<double,Eigen::Dynamic,1> vector_d;
typedef Eigen::Matrix<double,1,Eigen::Dynamic> row_vector_d;
typedef Eigen::Matrix<double,Eigen::Dynamic,Eigen::Dynamic> matrix_d;

static int current_statement_begin__;

stan::io::program_reader prog_reader__() {
    stan::io::program_reader reader;
    reader.add_event(0, 0, "start", "model24d279588d9b_cfb328cb1cc3c4dfe650ba42c7f8951a");
    reader.add_event(32, 32, "end", "model24d279588d9b_cfb328cb1cc3c4dfe650ba42c7f8951a");
    return reader;
}

class model24d279588d9b_cfb328cb1cc3c4dfe650ba42c7f8951a : public prob_grad {
private:
    int N;
    int p;
    vector_d y;
    matrix_d x;
public:
    model24d279588d9b_cfb328cb1cc3c4dfe650ba42c7f8951a(stan::io::var_context& context__,
        std::ostream* pstream__ = 0)
        : prob_grad(0) {
        ctor_body(context__, 0, pstream__);
    }

    model24d279588d9b_cfb328cb1cc3c4dfe650ba42c7f8951a(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__) {
        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__ = "model24d279588d9b_cfb328cb1cc3c4dfe650ba42c7f8951a_namespace::model24d279588d9b_cfb328cb1cc3c4dfe650ba42c7f8951a";
        (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__;
        double DUMMY_VAR__(std::numeric_limits<double>::quiet_NaN());
        (void) DUMMY_VAR__;  // suppress unused var warning

        // initialize member variables
        try {
            current_statement_begin__ = 3;
            context__.validate_dims("data initialization", "N", "int", context__.to_vec());
            N = int(0);
            vals_i__ = context__.vals_i("N");
            pos__ = 0;
            N = vals_i__[pos__++];
            current_statement_begin__ = 4;
            context__.validate_dims("data initialization", "p", "int", context__.to_vec());
            p = int(0);
            vals_i__ = context__.vals_i("p");
            pos__ = 0;
            p = vals_i__[pos__++];
            current_statement_begin__ = 5;
            validate_non_negative_index("y", "N", N);
            context__.validate_dims("data initialization", "y", "vector_d", context__.to_vec(N));
            validate_non_negative_index("y", "N", N);
            y = vector_d(static_cast<Eigen::VectorXd::Index>(N));
            vals_r__ = context__.vals_r("y");
            pos__ = 0;
            size_t y_i_vec_lim__ = N;
            for (size_t i_vec__ = 0; i_vec__ < y_i_vec_lim__; ++i_vec__) {
                y[i_vec__] = vals_r__[pos__++];
            }
            current_statement_begin__ = 6;
            validate_non_negative_index("x", "N", N);
            validate_non_negative_index("x", "p", p);
            context__.validate_dims("data initialization", "x", "matrix_d", context__.to_vec(N,p));
            validate_non_negative_index("x", "N", N);
            validate_non_negative_index("x", "p", p);
            x = matrix_d(static_cast<Eigen::VectorXd::Index>(N),static_cast<Eigen::VectorXd::Index>(p));
            vals_r__ = context__.vals_r("x");
            pos__ = 0;
            size_t x_m_mat_lim__ = N;
            size_t x_n_mat_lim__ = p;
            for (size_t n_mat__ = 0; n_mat__ < x_n_mat_lim__; ++n_mat__) {
                for (size_t m_mat__ = 0; m_mat__ < x_m_mat_lim__; ++m_mat__) {
                    x(m_mat__,n_mat__) = vals_r__[pos__++];
                }
            }

            // validate, data variables
            current_statement_begin__ = 3;
            current_statement_begin__ = 4;
            current_statement_begin__ = 5;
            current_statement_begin__ = 6;
            // initialize data variables


            // validate transformed data

            // validate, set parameter ranges
            num_params_r__ = 0U;
            param_ranges_i__.clear();
            current_statement_begin__ = 9;
            ++num_params_r__;
            current_statement_begin__ = 10;
            validate_non_negative_index("d_beta", "p", p);
            num_params_r__ += p;
            current_statement_begin__ = 11;
            validate_non_negative_index("d_a", "p", p);
            num_params_r__ += p;
            current_statement_begin__ = 12;
            validate_non_negative_index("d_b", "p", p);
            num_params_r__ += p;
            current_statement_begin__ = 13;
            ++num_params_r__;
            current_statement_begin__ = 14;
            ++num_params_r__;
            current_statement_begin__ = 15;
            ++num_params_r__;
        } 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 ***");
        }
    }

    ~model24d279588d9b_cfb328cb1cc3c4dfe650ba42c7f8951a() { }


    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__;

        if (!(context__.contains_r("b0")))
            throw std::runtime_error("variable b0 missing");
        vals_r__ = context__.vals_r("b0");
        pos__ = 0U;
        context__.validate_dims("initialization", "b0", "double", context__.to_vec());
        double b0(0);
        b0 = vals_r__[pos__++];
        try {
            writer__.scalar_unconstrain(b0);
        } catch (const std::exception& e) { 
            throw std::runtime_error(std::string("Error transforming variable b0: ") + e.what());
        }

        if (!(context__.contains_r("d_beta")))
            throw std::runtime_error("variable d_beta missing");
        vals_r__ = context__.vals_r("d_beta");
        pos__ = 0U;
        validate_non_negative_index("d_beta", "p", p);
        context__.validate_dims("initialization", "d_beta", "vector_d", context__.to_vec(p));
        vector_d d_beta(static_cast<Eigen::VectorXd::Index>(p));
        for (int j1__ = 0U; j1__ < p; ++j1__)
            d_beta(j1__) = vals_r__[pos__++];
        try {
            writer__.vector_unconstrain(d_beta);
        } catch (const std::exception& e) { 
            throw std::runtime_error(std::string("Error transforming variable d_beta: ") + e.what());
        }

        if (!(context__.contains_r("d_a")))
            throw std::runtime_error("variable d_a missing");
        vals_r__ = context__.vals_r("d_a");
        pos__ = 0U;
        validate_non_negative_index("d_a", "p", p);
        context__.validate_dims("initialization", "d_a", "vector_d", context__.to_vec(p));
        vector_d d_a(static_cast<Eigen::VectorXd::Index>(p));
        for (int j1__ = 0U; j1__ < p; ++j1__)
            d_a(j1__) = vals_r__[pos__++];
        try {
            writer__.vector_unconstrain(d_a);
        } catch (const std::exception& e) { 
            throw std::runtime_error(std::string("Error transforming variable d_a: ") + e.what());
        }

        if (!(context__.contains_r("d_b")))
            throw std::runtime_error("variable d_b missing");
        vals_r__ = context__.vals_r("d_b");
        pos__ = 0U;
        validate_non_negative_index("d_b", "p", p);
        context__.validate_dims("initialization", "d_b", "vector_d", context__.to_vec(p));
        vector_d d_b(static_cast<Eigen::VectorXd::Index>(p));
        for (int j1__ = 0U; j1__ < p; ++j1__)
            d_b(j1__) = vals_r__[pos__++];
        try {
            writer__.vector_lb_unconstrain(0,d_b);
        } catch (const std::exception& e) { 
            throw std::runtime_error(std::string("Error transforming variable d_b: ") + e.what());
        }

        if (!(context__.contains_r("tau")))
            throw std::runtime_error("variable tau missing");
        vals_r__ = context__.vals_r("tau");
        pos__ = 0U;
        context__.validate_dims("initialization", "tau", "double", context__.to_vec());
        double tau(0);
        tau = vals_r__[pos__++];
        try {
            writer__.scalar_lub_unconstrain(0,1,tau);
        } catch (const std::exception& e) { 
            throw std::runtime_error(std::string("Error transforming variable tau: ") + e.what());
        }

        if (!(context__.contains_r("sigma")))
            throw std::runtime_error("variable sigma missing");
        vals_r__ = context__.vals_r("sigma");
        pos__ = 0U;
        context__.validate_dims("initialization", "sigma", "double", context__.to_vec());
        double sigma(0);
        sigma = vals_r__[pos__++];
        try {
            writer__.scalar_lb_unconstrain(0,sigma);
        } catch (const std::exception& e) { 
            throw std::runtime_error(std::string("Error transforming variable sigma: ") + e.what());
        }

        if (!(context__.contains_r("nu")))
            throw std::runtime_error("variable nu missing");
        vals_r__ = context__.vals_r("nu");
        pos__ = 0U;
        context__.validate_dims("initialization", "nu", "double", context__.to_vec());
        double nu(0);
        nu = vals_r__[pos__++];
        try {
            writer__.scalar_lb_unconstrain(0,nu);
        } catch (const std::exception& e) { 
            throw std::runtime_error(std::string("Error transforming variable nu: ") + e.what());
        }

        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 {

        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<T__> in__(params_r__,params_i__);

            T__ b0;
            (void) b0;  // dummy to suppress unused var warning
            if (jacobian__)
                b0 = in__.scalar_constrain(lp__);
            else
                b0 = in__.scalar_constrain();

            Eigen::Matrix<T__,Eigen::Dynamic,1>  d_beta;
            (void) d_beta;  // dummy to suppress unused var warning
            if (jacobian__)
                d_beta = in__.vector_constrain(p,lp__);
            else
                d_beta = in__.vector_constrain(p);

            Eigen::Matrix<T__,Eigen::Dynamic,1>  d_a;
            (void) d_a;  // dummy to suppress unused var warning
            if (jacobian__)
                d_a = in__.vector_constrain(p,lp__);
            else
                d_a = in__.vector_constrain(p);

            Eigen::Matrix<T__,Eigen::Dynamic,1>  d_b;
            (void) d_b;  // dummy to suppress unused var warning
            if (jacobian__)
                d_b = in__.vector_lb_constrain(0,p,lp__);
            else
                d_b = in__.vector_lb_constrain(0,p);

            T__ tau;
            (void) tau;  // dummy to suppress unused var warning
            if (jacobian__)
                tau = in__.scalar_lub_constrain(0,1,lp__);
            else
                tau = in__.scalar_lub_constrain(0,1);

            T__ sigma;
            (void) sigma;  // dummy to suppress unused var warning
            if (jacobian__)
                sigma = in__.scalar_lb_constrain(0,lp__);
            else
                sigma = in__.scalar_lb_constrain(0);

            T__ nu;
            (void) nu;  // dummy to suppress unused var warning
            if (jacobian__)
                nu = in__.scalar_lb_constrain(0,lp__);
            else
                nu = in__.scalar_lb_constrain(0);


            // transformed parameters
            current_statement_begin__ = 18;
            validate_non_negative_index("beta", "p", p);
            Eigen::Matrix<T__,Eigen::Dynamic,1>  beta(static_cast<Eigen::VectorXd::Index>(p));
            (void) beta;  // dummy to suppress unused var warning

            stan::math::initialize(beta, DUMMY_VAR__);
            stan::math::fill(beta,DUMMY_VAR__);


            current_statement_begin__ = 19;
            stan::math::assign(beta, multiply(elt_multiply(elt_multiply(d_beta,d_a),sqrt(d_b)),tau));

            // validate transformed parameters
            for (int i0__ = 0; i0__ < p; ++i0__) {
                if (stan::math::is_uninitialized(beta(i0__))) {
                    std::stringstream msg__;
                    msg__ << "Undefined transformed parameter: beta" << '[' << i0__ << ']';
                    throw std::runtime_error(msg__.str());
                }
            }

            const char* function__ = "validate transformed params";
            (void) function__;  // dummy to suppress unused var warning
            current_statement_begin__ = 18;

            // model body

            current_statement_begin__ = 22;
            lp_accum__.add(normal_log<propto__>(y, add(b0,multiply(x,beta)), sigma));
            current_statement_begin__ = 24;
            lp_accum__.add(normal_log<propto__>(d_beta, 0, 1));
            current_statement_begin__ = 25;
            lp_accum__.add(normal_log<propto__>(d_a, 0, 1));
            current_statement_begin__ = 26;
            lp_accum__.add(inv_gamma_log<propto__>(d_b, (0.5 * nu), (0.5 * nu)));
            current_statement_begin__ = 29;
            lp_accum__.add(normal_log<propto__>(sigma, 0, 10));
            current_statement_begin__ = 31;
            lp_accum__.add(normal_log<propto__>(nu, 0, 20));

        } 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);
        names__.push_back("b0");
        names__.push_back("d_beta");
        names__.push_back("d_a");
        names__.push_back("d_b");
        names__.push_back("tau");
        names__.push_back("sigma");
        names__.push_back("nu");
        names__.push_back("beta");
    }


    void get_dims(std::vector<std::vector<size_t> >& dimss__) const {
        dimss__.resize(0);
        std::vector<size_t> dims__;
        dims__.resize(0);
        dimss__.push_back(dims__);
        dims__.resize(0);
        dims__.push_back(p);
        dimss__.push_back(dims__);
        dims__.resize(0);
        dims__.push_back(p);
        dimss__.push_back(dims__);
        dims__.resize(0);
        dims__.push_back(p);
        dimss__.push_back(dims__);
        dims__.resize(0);
        dimss__.push_back(dims__);
        dims__.resize(0);
        dimss__.push_back(dims__);
        dims__.resize(0);
        dimss__.push_back(dims__);
        dims__.resize(0);
        dims__.push_back(p);
        dimss__.push_back(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 {
        vars__.resize(0);
        stan::io::reader<double> in__(params_r__,params_i__);
        static const char* function__ = "model24d279588d9b_cfb328cb1cc3c4dfe650ba42c7f8951a_namespace::write_array";
        (void) function__;  // dummy to suppress unused var warning
        // read-transform, write parameters
        double b0 = in__.scalar_constrain();
        vector_d d_beta = in__.vector_constrain(p);
        vector_d d_a = in__.vector_constrain(p);
        vector_d d_b = in__.vector_lb_constrain(0,p);
        double tau = in__.scalar_lub_constrain(0,1);
        double sigma = in__.scalar_lb_constrain(0);
        double nu = in__.scalar_lb_constrain(0);
        vars__.push_back(b0);
            for (int k_0__ = 0; k_0__ < p; ++k_0__) {
            vars__.push_back(d_beta[k_0__]);
            }
            for (int k_0__ = 0; k_0__ < p; ++k_0__) {
            vars__.push_back(d_a[k_0__]);
            }
            for (int k_0__ = 0; k_0__ < p; ++k_0__) {
            vars__.push_back(d_b[k_0__]);
            }
        vars__.push_back(tau);
        vars__.push_back(sigma);
        vars__.push_back(nu);

        if (!include_tparams__) return;
        // declare and define transformed parameters
        double lp__ = 0.0;
        (void) lp__;  // dummy to suppress unused var warning
        stan::math::accumulator<double> lp_accum__;

        double DUMMY_VAR__(std::numeric_limits<double>::quiet_NaN());
        (void) DUMMY_VAR__;  // suppress unused var warning

        try {
            current_statement_begin__ = 18;
            validate_non_negative_index("beta", "p", p);
            vector_d beta(static_cast<Eigen::VectorXd::Index>(p));
            (void) beta;  // dummy to suppress unused var warning

            stan::math::initialize(beta, std::numeric_limits<double>::quiet_NaN());
            stan::math::fill(beta,DUMMY_VAR__);


            current_statement_begin__ = 19;
            stan::math::assign(beta, multiply(elt_multiply(elt_multiply(d_beta,d_a),sqrt(d_b)),tau));

            // validate transformed parameters
            current_statement_begin__ = 18;

            // write transformed parameters
            for (int k_0__ = 0; k_0__ < p; ++k_0__) {
            vars__.push_back(beta[k_0__]);
            }

            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 "model24d279588d9b_cfb328cb1cc3c4dfe650ba42c7f8951a";
    }


    void constrained_param_names(std::vector<std::string>& param_names__,
                                 bool include_tparams__ = true,
                                 bool include_gqs__ = true) const {
        std::stringstream param_name_stream__;
        param_name_stream__.str(std::string());
        param_name_stream__ << "b0";
        param_names__.push_back(param_name_stream__.str());
        for (int k_0__ = 1; k_0__ <= p; ++k_0__) {
            param_name_stream__.str(std::string());
            param_name_stream__ << "d_beta" << '.' << k_0__;
            param_names__.push_back(param_name_stream__.str());
        }
        for (int k_0__ = 1; k_0__ <= p; ++k_0__) {
            param_name_stream__.str(std::string());
            param_name_stream__ << "d_a" << '.' << k_0__;
            param_names__.push_back(param_name_stream__.str());
        }
        for (int k_0__ = 1; k_0__ <= p; ++k_0__) {
            param_name_stream__.str(std::string());
            param_name_stream__ << "d_b" << '.' << k_0__;
            param_names__.push_back(param_name_stream__.str());
        }
        param_name_stream__.str(std::string());
        param_name_stream__ << "tau";
        param_names__.push_back(param_name_stream__.str());
        param_name_stream__.str(std::string());
        param_name_stream__ << "sigma";
        param_names__.push_back(param_name_stream__.str());
        param_name_stream__.str(std::string());
        param_name_stream__ << "nu";
        param_names__.push_back(param_name_stream__.str());

        if (!include_gqs__ && !include_tparams__) return;
        for (int k_0__ = 1; k_0__ <= p; ++k_0__) {
            param_name_stream__.str(std::string());
            param_name_stream__ << "beta" << '.' << k_0__;
            param_names__.push_back(param_name_stream__.str());
        }

        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__;
        param_name_stream__.str(std::string());
        param_name_stream__ << "b0";
        param_names__.push_back(param_name_stream__.str());
        for (int k_0__ = 1; k_0__ <= p; ++k_0__) {
            param_name_stream__.str(std::string());
            param_name_stream__ << "d_beta" << '.' << k_0__;
            param_names__.push_back(param_name_stream__.str());
        }
        for (int k_0__ = 1; k_0__ <= p; ++k_0__) {
            param_name_stream__.str(std::string());
            param_name_stream__ << "d_a" << '.' << k_0__;
            param_names__.push_back(param_name_stream__.str());
        }
        for (int k_0__ = 1; k_0__ <= p; ++k_0__) {
            param_name_stream__.str(std::string());
            param_name_stream__ << "d_b" << '.' << k_0__;
            param_names__.push_back(param_name_stream__.str());
        }
        param_name_stream__.str(std::string());
        param_name_stream__ << "tau";
        param_names__.push_back(param_name_stream__.str());
        param_name_stream__.str(std::string());
        param_name_stream__ << "sigma";
        param_names__.push_back(param_name_stream__.str());
        param_name_stream__.str(std::string());
        param_name_stream__ << "nu";
        param_names__.push_back(param_name_stream__.str());

        if (!include_gqs__ && !include_tparams__) return;
        for (int k_0__ = 1; k_0__ <= p; ++k_0__) {
            param_name_stream__.str(std::string());
            param_name_stream__ << "beta" << '.' << k_0__;
            param_names__.push_back(param_name_stream__.str());
        }

        if (!include_gqs__) return;
    }

}; // model

}

typedef model24d279588d9b_cfb328cb1cc3c4dfe650ba42c7f8951a_namespace::model24d279588d9b_cfb328cb1cc3c4dfe650ba42c7f8951a stan_model;