#define STAN__SERVICES__COMMAND_HPP
#include <rstan/rstaninc.hpp>
#include "custom_func.hpp"

#ifndef USE_STANC3
#define USE_STANC3
#endif
// Code generated by stanc v2.32.2
#include <stan/model/model_header.hpp>
namespace model_tmb_namespace {
using stan::model::model_base_crtp;
using namespace stan::math;
stan::math::profile_map profiles__;
static constexpr std::array<const char*, 17> locations_array__ =
  {" (found before start of program)",
  " (in 'tmb', line 18, column 2 to line 19, column 53)",
  " (in 'tmb', line 22, column 2 to column 19)",
  " (in 'tmb', line 12, column 2 to column 17)",
  " (in 'tmb', line 13, column 2 to column 35)",
  " (in 'tmb', line 14, column 9 to column 22)",
  " (in 'tmb', line 14, column 2 to column 36)",
  " (in 'tmb', line 15, column 9 to column 22)",
  " (in 'tmb', line 15, column 2 to column 36)",
  " (in 'tmb', line 19, column 48 to column 49)",
  " (in 'tmb', line 7, column 6 to column 22)",
  " (in 'tmb', line 6, column 11 to line 8, column 5)",
  " (in 'tmb', line 4, column 6 to column 79)",
  " (in 'tmb', line 5, column 6 to column 34)",
  " (in 'tmb', line 3, column 37 to line 6, column 5)",
  " (in 'tmb', line 3, column 4 to line 8, column 5)",
  " (in 'tmb', line 2, column 59 to line 9, column 3)"};
template <typename T0__,
          stan::require_all_t<stan::is_col_vector<T0__>,
                              stan::is_vt_not_complex<T0__>>* = nullptr>
Eigen::Matrix<stan::promote_args_t<stan::base_type_t<T0__>>,-1,1>
make_bounds(const T0__& bound_in_arg__, const int& N, const int& is_upper,
            std::ostream* pstream__);
template <typename T0__,
          stan::require_all_t<stan::is_col_vector<T0__>,
                              stan::is_vt_not_complex<T0__>>*>
Eigen::Matrix<stan::promote_args_t<stan::base_type_t<T0__>>,-1,1>
make_bounds(const T0__& bound_in_arg__, const int& N, const int& is_upper,
            std::ostream* pstream__) {
  using local_scalar_t__ = stan::promote_args_t<stan::base_type_t<T0__>>;
  int current_statement__ = 0;
  const auto& bound_in = stan::math::to_ref(bound_in_arg__);
  static constexpr bool propto__ = true;
  // suppress unused var warning
  (void) propto__;
  local_scalar_t__ DUMMY_VAR__(std::numeric_limits<double>::quiet_NaN());
  // suppress unused var warning
  (void) DUMMY_VAR__;
  try {
    current_statement__ = 15;
    if (stan::math::logical_eq(stan::math::num_elements(bound_in), 0)) {
      local_scalar_t__ bound = DUMMY_VAR__;
      current_statement__ = 12;
      bound = (stan::math::logical_eq(is_upper, 1) ? stan::math::positive_infinity(
                                                       ) : stan::math::negative_infinity(
                                                             ));
      current_statement__ = 13;
      return stan::math::rep_vector(bound, N);
    } else {
      current_statement__ = 10;
      return bound_in;
    }
  } catch (const std::exception& e) {
    stan::lang::rethrow_located(e, locations_array__[current_statement__]);
  }
}
class model_tmb final : public model_base_crtp<model_tmb> {
private:
  int N;
  int have_bounds;
  Eigen::Matrix<double,-1,1> lower_bound_data__;
  Eigen::Matrix<double,-1,1> upper_bound_data__;
  Eigen::Map<Eigen::Matrix<double,-1,1>> lower_bound{nullptr, 0};
  Eigen::Map<Eigen::Matrix<double,-1,1>> upper_bound{nullptr, 0};
public:
  ~model_tmb() {}
  model_tmb(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__ =
      "model_tmb_namespace::model_tmb";
    // suppress unused var warning
    (void) function__;
    local_scalar_t__ DUMMY_VAR__(std::numeric_limits<double>::quiet_NaN());
    // suppress unused var warning
    (void) DUMMY_VAR__;
    try {
      int pos__ = std::numeric_limits<int>::min();
      pos__ = 1;
      current_statement__ = 3;
      context__.validate_dims("data initialization", "N", "int",
        std::vector<size_t>{});
      N = std::numeric_limits<int>::min();
      current_statement__ = 3;
      N = context__.vals_i("N")[(1 - 1)];
      current_statement__ = 3;
      stan::math::check_greater_or_equal(function__, "N", N, 1);
      current_statement__ = 4;
      context__.validate_dims("data initialization", "have_bounds", "int",
        std::vector<size_t>{});
      have_bounds = std::numeric_limits<int>::min();
      current_statement__ = 4;
      have_bounds = context__.vals_i("have_bounds")[(1 - 1)];
      current_statement__ = 4;
      stan::math::check_greater_or_equal(function__, "have_bounds",
        have_bounds, 0);
      current_statement__ = 4;
      stan::math::check_less_or_equal(function__, "have_bounds", have_bounds,
        1);
      current_statement__ = 5;
      stan::math::validate_non_negative_index("lower_bound",
        "N * have_bounds", (N * have_bounds));
      current_statement__ = 6;
      context__.validate_dims("data initialization", "lower_bound", "double",
        std::vector<size_t>{static_cast<size_t>((N * have_bounds))});
      lower_bound_data__ = Eigen::Matrix<double,-1,1>::Constant((N *
                             have_bounds),
                             std::numeric_limits<double>::quiet_NaN());
      new (&lower_bound)
        Eigen::Map<Eigen::Matrix<double,-1,1>>(lower_bound_data__.data(), (N
        * have_bounds));
      {
        std::vector<local_scalar_t__> lower_bound_flat__;
        current_statement__ = 6;
        lower_bound_flat__ = context__.vals_r("lower_bound");
        current_statement__ = 6;
        pos__ = 1;
        current_statement__ = 6;
        for (int sym1__ = 1; sym1__ <= (N * have_bounds); ++sym1__) {
          current_statement__ = 6;
          stan::model::assign(lower_bound, lower_bound_flat__[(pos__ - 1)],
            "assigning variable lower_bound", stan::model::index_uni(sym1__));
          current_statement__ = 6;
          pos__ = (pos__ + 1);
        }
      }
      current_statement__ = 7;
      stan::math::validate_non_negative_index("upper_bound",
        "N * have_bounds", (N * have_bounds));
      current_statement__ = 8;
      context__.validate_dims("data initialization", "upper_bound", "double",
        std::vector<size_t>{static_cast<size_t>((N * have_bounds))});
      upper_bound_data__ = Eigen::Matrix<double,-1,1>::Constant((N *
                             have_bounds),
                             std::numeric_limits<double>::quiet_NaN());
      new (&upper_bound)
        Eigen::Map<Eigen::Matrix<double,-1,1>>(upper_bound_data__.data(), (N
        * have_bounds));
      {
        std::vector<local_scalar_t__> upper_bound_flat__;
        current_statement__ = 8;
        upper_bound_flat__ = context__.vals_r("upper_bound");
        current_statement__ = 8;
        pos__ = 1;
        current_statement__ = 8;
        for (int sym1__ = 1; sym1__ <= (N * have_bounds); ++sym1__) {
          current_statement__ = 8;
          stan::model::assign(upper_bound, upper_bound_flat__[(pos__ - 1)],
            "assigning variable upper_bound", stan::model::index_uni(sym1__));
          current_statement__ = 8;
          pos__ = (pos__ + 1);
        }
      }
      current_statement__ = 9;
      stan::math::validate_non_negative_index("y", "N", N);
    } catch (const std::exception& e) {
      stan::lang::rethrow_located(e, locations_array__[current_statement__]);
    }
    num_params_r__ = N;
  }
  inline std::string model_name() const final {
    return "model_tmb";
  }
  inline std::vector<std::string> model_compile_info() const noexcept {
    return std::vector<std::string>{"stanc_version = stanc3 v2.32.2",
             "stancflags = --"};
  }
  template <bool propto__, bool jacobian__, typename VecR, typename VecI,
            stan::require_vector_like_t<VecR>* = nullptr,
            stan::require_vector_like_vt<std::is_integral, VecI>* = nullptr>
  inline stan::scalar_type_t<VecR>
  log_prob_impl(VecR& params_r__, VecI& params_i__, std::ostream*
                pstream__ = nullptr) const {
    using T__ = stan::scalar_type_t<VecR>;
    using local_scalar_t__ = T__;
    T__ lp__(0.0);
    stan::math::accumulator<T__> lp_accum__;
    stan::io::deserializer<local_scalar_t__> in__(params_r__, params_i__);
    int current_statement__ = 0;
    local_scalar_t__ DUMMY_VAR__(std::numeric_limits<double>::quiet_NaN());
    // suppress unused var warning
    (void) DUMMY_VAR__;
    static constexpr const char* function__ = "model_tmb_namespace::log_prob";
    // suppress unused var warning
    (void) function__;
    try {
      Eigen::Matrix<local_scalar_t__,-1,1> y =
        Eigen::Matrix<local_scalar_t__,-1,1>::Constant(N, DUMMY_VAR__);
      current_statement__ = 1;
      y = in__.template read_constrain_lub<
            Eigen::Matrix<local_scalar_t__,-1,1>,
            jacobian__>(make_bounds(lower_bound, N, 0, pstream__),
            make_bounds(upper_bound, N, 1, pstream__), lp__, N);
      current_statement__ = 1;
      stan::math::check_matching_dims("constraint", "y", y, "lower",
        make_bounds(lower_bound, N, 0, pstream__));
      current_statement__ = 1;
      stan::math::check_matching_dims("constraint", "y", y, "upper",
        make_bounds(upper_bound, N, 1, pstream__));
      {
        current_statement__ = 2;

// ====== Custom Edit Begin
lp_accum__.add(custom_func::custom_func(y));
// ====== Custom Edit End

      }
    } catch (const std::exception& e) {
      stan::lang::rethrow_located(e, locations_array__[current_statement__]);
    }
    lp_accum__.add(lp__);
    return lp_accum__.sum();
  }
  template <typename RNG, typename VecR, typename VecI, typename VecVar,
            stan::require_vector_like_vt<std::is_floating_point,
            VecR>* = nullptr, stan::require_vector_like_vt<std::is_integral,
            VecI>* = nullptr, stan::require_vector_vt<std::is_floating_point,
            VecVar>* = 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<local_scalar_t__> in__(params_r__, params_i__);
    stan::io::serializer<local_scalar_t__> 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<double> lp_accum__;
    local_scalar_t__ DUMMY_VAR__(std::numeric_limits<double>::quiet_NaN());
    // suppress unused var warning
    (void) DUMMY_VAR__;
    constexpr bool jacobian__ = false;
    static constexpr const char* function__ =
      "model_tmb_namespace::write_array";
    // suppress unused var warning
    (void) function__;
    try {
      Eigen::Matrix<double,-1,1> y =
        Eigen::Matrix<double,-1,1>::Constant(N,
          std::numeric_limits<double>::quiet_NaN());
      current_statement__ = 1;
      y = in__.template read_constrain_lub<
            Eigen::Matrix<local_scalar_t__,-1,1>,
            jacobian__>(make_bounds(lower_bound, N, 0, pstream__),
            make_bounds(upper_bound, N, 1, pstream__), lp__, N);
      current_statement__ = 1;
      stan::math::check_matching_dims("constraint", "y", y, "lower",
        make_bounds(lower_bound, N, 0, pstream__));
      current_statement__ = 1;
      stan::math::check_matching_dims("constraint", "y", y, "upper",
        make_bounds(upper_bound, N, 1, pstream__));
      out__.write(y);
      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 <typename VecVar, typename VecI,
            stan::require_vector_t<VecVar>* = nullptr,
            stan::require_vector_like_vt<std::is_integral, VecI>* = nullptr>
  inline void
  unconstrain_array_impl(const VecVar& params_r__, const VecI& params_i__,
                         VecVar& vars__, std::ostream* pstream__ = nullptr) const {
    using local_scalar_t__ = double;
    stan::io::deserializer<local_scalar_t__> in__(params_r__, params_i__);
    stan::io::serializer<local_scalar_t__> out__(vars__);
    int current_statement__ = 0;
    local_scalar_t__ DUMMY_VAR__(std::numeric_limits<double>::quiet_NaN());
    // suppress unused var warning
    (void) DUMMY_VAR__;
    try {
      int pos__ = std::numeric_limits<int>::min();
      pos__ = 1;
      Eigen::Matrix<local_scalar_t__,-1,1> y =
        Eigen::Matrix<local_scalar_t__,-1,1>::Constant(N, DUMMY_VAR__);
      current_statement__ = 1;
      stan::model::assign(y,
        in__.read<Eigen::Matrix<local_scalar_t__,-1,1>>(N),
        "assigning variable y");
      out__.write_free_lub(make_bounds(lower_bound, N, 0, pstream__),
        make_bounds(upper_bound, N, 1, pstream__), y);
    } catch (const std::exception& e) {
      stan::lang::rethrow_located(e, locations_array__[current_statement__]);
    }
  }
  template <typename VecVar, stan::require_vector_t<VecVar>* = nullptr>
  inline void
  transform_inits_impl(const stan::io::var_context& context__, VecVar&
                       vars__, std::ostream* pstream__ = nullptr) const {
    using local_scalar_t__ = double;
    stan::io::serializer<local_scalar_t__> out__(vars__);
    int current_statement__ = 0;
    local_scalar_t__ DUMMY_VAR__(std::numeric_limits<double>::quiet_NaN());
    // suppress unused var warning
    (void) DUMMY_VAR__;
    try {
      current_statement__ = 1;
      context__.validate_dims("parameter initialization", "y", "double",
        std::vector<size_t>{static_cast<size_t>(N)});
      int pos__ = std::numeric_limits<int>::min();
      pos__ = 1;
      Eigen::Matrix<local_scalar_t__,-1,1> y =
        Eigen::Matrix<local_scalar_t__,-1,1>::Constant(N, DUMMY_VAR__);
      {
        std::vector<local_scalar_t__> y_flat__;
        current_statement__ = 1;
        y_flat__ = context__.vals_r("y");
        current_statement__ = 1;
        pos__ = 1;
        current_statement__ = 1;
        for (int sym1__ = 1; sym1__ <= N; ++sym1__) {
          current_statement__ = 1;
          stan::model::assign(y, y_flat__[(pos__ - 1)],
            "assigning variable y", stan::model::index_uni(sym1__));
          current_statement__ = 1;
          pos__ = (pos__ + 1);
        }
      }
      out__.write_free_lub(make_bounds(lower_bound, N, 0, pstream__),
        make_bounds(upper_bound, N, 1, pstream__), y);
    } catch (const std::exception& e) {
      stan::lang::rethrow_located(e, locations_array__[current_statement__]);
    }
  }
  inline void
  get_param_names(std::vector<std::string>& names__, const bool
                  emit_transformed_parameters__ = true, const bool
                  emit_generated_quantities__ = true) const {

// ====== Custom Edit Begin
SEXP shortpar_nam = R_getVar(Rf_install("shortpar_nam"), custom_func::R_env, static_cast<Rboolean>(0));
names__ = Rcpp::as<std::vector<std::string> >(shortpar_nam);
return;
// ====== Custom Edit End

    if (emit_transformed_parameters__) {}
    if (emit_generated_quantities__) {}
  }
  inline void
  get_dims(std::vector<std::vector<size_t>>& dimss__, const bool
           emit_transformed_parameters__ = true, const bool
           emit_generated_quantities__ = true) const {

// ====== Custom Edit Begin
SEXP shortpar_len = R_getVar(Rf_install("shortpar_len"), custom_func::R_env, static_cast<Rboolean>(0));
for(int i=0; i<LENGTH(shortpar_len); i++) {
  std::vector<size_t> dims__;
  dims__.resize(0);
  int len_i = INTEGER(shortpar_len)[i];
  if (len_i > 1) dims__.push_back(len_i);
  dimss__.push_back(dims__);
}
return;
// ====== Custom Edit End


    if (emit_transformed_parameters__) {}
    if (emit_generated_quantities__) {}
  }
  inline void
  constrained_param_names(std::vector<std::string>& param_names__, bool
                          emit_transformed_parameters__ = true, bool
                          emit_generated_quantities__ = true) const final {
    for (int sym1__ = 1; sym1__ <= N; ++sym1__) {
      param_names__.emplace_back(std::string() + "y" + '.' +
        std::to_string(sym1__));
    }
    if (emit_transformed_parameters__) {}
    if (emit_generated_quantities__) {}
  }
  inline void
  unconstrained_param_names(std::vector<std::string>& param_names__, bool
                            emit_transformed_parameters__ = true, bool
                            emit_generated_quantities__ = true) const final {
    for (int sym1__ = 1; sym1__ <= N; ++sym1__) {
      param_names__.emplace_back(std::string() + "y" + '.' +
        std::to_string(sym1__));
    }
    if (emit_transformed_parameters__) {}
    if (emit_generated_quantities__) {}
  }
  inline std::string get_constrained_sizedtypes() const {
    return std::string("[{\"name\":\"y\",\"type\":{\"name\":\"vector\",\"length\":" + std::to_string(N) + "},\"block\":\"parameters\"}]");
  }
  inline std::string get_unconstrained_sizedtypes() const {
    return std::string("[{\"name\":\"y\",\"type\":{\"name\":\"vector\",\"length\":" + std::to_string(N) + "},\"block\":\"parameters\"}]");
  }
  // Begin method overload boilerplate
  template <typename RNG> inline void
  write_array(RNG& base_rng, Eigen::Matrix<double,-1,1>& params_r,
              Eigen::Matrix<double,-1,1>& vars, const bool
              emit_transformed_parameters = true, const bool
              emit_generated_quantities = true, std::ostream*
              pstream = nullptr) const {
    const size_t num_params__ = 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<int> params_i;
    vars = Eigen::Matrix<double,-1,1>::Constant(num_to_write,
             std::numeric_limits<double>::quiet_NaN());
    write_array_impl(base_rng, params_r, params_i, vars,
      emit_transformed_parameters, emit_generated_quantities, pstream);
  }
  template <typename RNG> inline void
  write_array(RNG& base_rng, std::vector<double>& params_r, std::vector<int>&
              params_i, std::vector<double>& vars, bool
              emit_transformed_parameters = true, bool
              emit_generated_quantities = true, std::ostream*
              pstream = nullptr) const {
    const size_t num_params__ = 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<double>(num_to_write,
             std::numeric_limits<double>::quiet_NaN());
    write_array_impl(base_rng, params_r, params_i, vars,
      emit_transformed_parameters, emit_generated_quantities, pstream);
  }
  template <bool propto__, bool jacobian__, typename T_> inline T_
  log_prob(Eigen::Matrix<T_,-1,1>& params_r, std::ostream* pstream = nullptr) const {
    Eigen::Matrix<int,-1,1> params_i;
    return log_prob_impl<propto__, jacobian__>(params_r, params_i, pstream);
  }
  template <bool propto__, bool jacobian__, typename T_> inline T_
  log_prob(std::vector<T_>& params_r, std::vector<int>& params_i,
           std::ostream* pstream = nullptr) const {
    return log_prob_impl<propto__, jacobian__>(params_r, params_i, pstream);
  }
  inline void
  transform_inits(const stan::io::var_context& context,
                  Eigen::Matrix<double,-1,1>& params_r, std::ostream*
                  pstream = nullptr) const final {
    std::vector<double> params_r_vec(params_r.size());
    std::vector<int> params_i;
    transform_inits(context, params_i, params_r_vec, pstream);
    params_r = Eigen::Map<Eigen::Matrix<double,-1,1>>(params_r_vec.data(),
                 params_r_vec.size());
  }
  inline void
  transform_inits(const stan::io::var_context& context, std::vector<int>&
                  params_i, std::vector<double>& vars, std::ostream*
                  pstream__ = nullptr) const {
    vars.resize(num_params_r__);
    transform_inits_impl(context, vars, pstream__);
  }
  inline void
  unconstrain_array(const std::vector<double>& params_constrained,
                    std::vector<double>& params_unconstrained, std::ostream*
                    pstream = nullptr) const {
    const std::vector<int> params_i;
    params_unconstrained = std::vector<double>(num_params_r__,
                             std::numeric_limits<double>::quiet_NaN());
    unconstrain_array_impl(params_constrained, params_i,
      params_unconstrained, pstream);
  }
  inline void
  unconstrain_array(const Eigen::Matrix<double,-1,1>& params_constrained,
                    Eigen::Matrix<double,-1,1>& params_unconstrained,
                    std::ostream* pstream = nullptr) const {
    const std::vector<int> params_i;
    params_unconstrained = Eigen::Matrix<double,-1,1>::Constant(num_params_r__,
                             std::numeric_limits<double>::quiet_NaN());
    unconstrain_array_impl(params_constrained, params_i,
      params_unconstrained, pstream);
  }
};
}
using stan_model = model_tmb_namespace::model_tmb;
#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 model_tmb_namespace::profiles__;
}
#endif
