// Generated by rstantools.  Do not edit by hand.

/*
    decontX is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    decontX is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with decontX.  If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef MODELS_HPP
#define MODELS_HPP
#define STAN__SERVICES__COMMAND_HPP
#ifndef USE_STANC3
#define USE_STANC3
#endif
#include <rstan/rstaninc.hpp>
// Code generated by stanc v2.32.2
#include <stan/model/model_header.hpp>
namespace model_shrinkage_namespace {
using stan::model::model_base_crtp;
using namespace stan::math;
stan::math::profile_map profiles__;
static constexpr std::array<const char*, 46> locations_array__ =
  {" (found before start of program)",
  " (in 'shrinkage', line 14, column 2 to column 24)",
  " (in 'shrinkage', line 15, column 2 to column 56)",
  " (in 'shrinkage', line 16, column 2 to column 49)",
  " (in 'shrinkage', line 17, column 2 to column 45)",
  " (in 'shrinkage', line 18, column 2 to column 52)",
  " (in 'shrinkage', line 19, column 2 to column 24)",
  " (in 'shrinkage', line 20, column 2 to column 24)",
  " (in 'shrinkage', line 23, column 2 to column 30)",
  " (in 'shrinkage', line 24, column 2 to column 35)",
  " (in 'shrinkage', line 26, column 4 to column 44)",
  " (in 'shrinkage', line 25, column 15 to line 27, column 3)",
  " (in 'shrinkage', line 25, column 2 to line 27, column 3)",
  " (in 'shrinkage', line 30, column 4 to column 54)",
  " (in 'shrinkage', line 29, column 15 to line 31, column 3)",
  " (in 'shrinkage', line 29, column 2 to line 31, column 3)",
  " (in 'shrinkage', line 36, column 8 to line 38, column 55)",
  " (in 'shrinkage', line 35, column 19 to line 39, column 7)",
  " (in 'shrinkage', line 35, column 6 to line 39, column 7)",
  " (in 'shrinkage', line 34, column 17 to line 40, column 5)",
  " (in 'shrinkage', line 34, column 4 to line 40, column 5)",
  " (in 'shrinkage', line 33, column 26 to line 41, column 3)",
  " (in 'shrinkage', line 33, column 2 to line 41, column 3)",
  " (in 'shrinkage', line 2, column 2 to column 8)",
  " (in 'shrinkage', line 3, column 2 to column 8)",
  " (in 'shrinkage', line 4, column 2 to column 8)",
  " (in 'shrinkage', line 5, column 8 to column 9)",
  " (in 'shrinkage', line 5, column 2 to column 36)",
  " (in 'shrinkage', line 6, column 8 to column 9)",
  " (in 'shrinkage', line 6, column 11 to column 12)",
  " (in 'shrinkage', line 6, column 2 to column 36)",
  " (in 'shrinkage', line 7, column 8 to column 9)",
  " (in 'shrinkage', line 7, column 2 to column 29)",
  " (in 'shrinkage', line 8, column 2 to column 43)",
  " (in 'shrinkage', line 9, column 10 to column 11)",
  " (in 'shrinkage', line 9, column 2 to column 15)",
  " (in 'shrinkage', line 10, column 2 to column 16)",
  " (in 'shrinkage', line 11, column 2 to column 21)",
  " (in 'shrinkage', line 14, column 8 to column 9)",
  " (in 'shrinkage', line 14, column 19 to column 20)",
  " (in 'shrinkage', line 15, column 8 to column 9)",
  " (in 'shrinkage', line 15, column 42 to column 43)",
  " (in 'shrinkage', line 16, column 8 to column 9)",
  " (in 'shrinkage', line 16, column 40 to column 41)",
  " (in 'shrinkage', line 17, column 31 to column 32)",
  " (in 'shrinkage', line 18, column 33 to column 34)"};
#include <stan_meta_header.hpp>
class model_shrinkage final : public model_base_crtp<model_shrinkage> {
private:
  int N;
  int M;
  int K;
  std::vector<int> cell_type;
  std::vector<std::vector<int>> counts;
  std::vector<int> OC;
  int run_estimation;
  Eigen::Matrix<double,-1,1> p_data__;
  double delta_sd;
  double background_sd;
  Eigen::Map<Eigen::Matrix<double,-1,1>> p{nullptr, 0};
public:
  ~model_shrinkage() {}
  model_shrinkage(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_shrinkage_namespace::model_shrinkage";
    // 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__ = 23;
      context__.validate_dims("data initialization", "N", "int",
        std::vector<size_t>{});
      N = std::numeric_limits<int>::min();
      current_statement__ = 23;
      N = context__.vals_i("N")[(1 - 1)];
      current_statement__ = 24;
      context__.validate_dims("data initialization", "M", "int",
        std::vector<size_t>{});
      M = std::numeric_limits<int>::min();
      current_statement__ = 24;
      M = context__.vals_i("M")[(1 - 1)];
      current_statement__ = 25;
      context__.validate_dims("data initialization", "K", "int",
        std::vector<size_t>{});
      K = std::numeric_limits<int>::min();
      current_statement__ = 25;
      K = context__.vals_i("K")[(1 - 1)];
      current_statement__ = 26;
      stan::math::validate_non_negative_index("cell_type", "M", M);
      current_statement__ = 27;
      context__.validate_dims("data initialization", "cell_type", "int",
        std::vector<size_t>{static_cast<size_t>(M)});
      cell_type = std::vector<int>(M, std::numeric_limits<int>::min());
      current_statement__ = 27;
      cell_type = context__.vals_i("cell_type");
      current_statement__ = 27;
      stan::math::check_greater_or_equal(function__, "cell_type", cell_type,
        1);
      current_statement__ = 28;
      stan::math::validate_non_negative_index("counts", "N", N);
      current_statement__ = 29;
      stan::math::validate_non_negative_index("counts", "M", M);
      current_statement__ = 30;
      context__.validate_dims("data initialization", "counts", "int",
        std::vector<size_t>{static_cast<size_t>(N), static_cast<size_t>(M)});
      counts = std::vector<std::vector<int>>(N,
                 std::vector<int>(M, std::numeric_limits<int>::min()));
      {
        std::vector<int> counts_flat__;
        current_statement__ = 30;
        counts_flat__ = context__.vals_i("counts");
        current_statement__ = 30;
        pos__ = 1;
        current_statement__ = 30;
        for (int sym1__ = 1; sym1__ <= M; ++sym1__) {
          current_statement__ = 30;
          for (int sym2__ = 1; sym2__ <= N; ++sym2__) {
            current_statement__ = 30;
            stan::model::assign(counts, counts_flat__[(pos__ - 1)],
              "assigning variable counts", stan::model::index_uni(sym2__),
              stan::model::index_uni(sym1__));
            current_statement__ = 30;
            pos__ = (pos__ + 1);
          }
        }
      }
      current_statement__ = 30;
      stan::math::check_greater_or_equal(function__, "counts", counts, 0);
      current_statement__ = 31;
      stan::math::validate_non_negative_index("OC", "M", M);
      current_statement__ = 32;
      context__.validate_dims("data initialization", "OC", "int",
        std::vector<size_t>{static_cast<size_t>(M)});
      OC = std::vector<int>(M, std::numeric_limits<int>::min());
      current_statement__ = 32;
      OC = context__.vals_i("OC");
      current_statement__ = 32;
      stan::math::check_greater_or_equal(function__, "OC", OC, 1);
      current_statement__ = 33;
      context__.validate_dims("data initialization", "run_estimation", "int",
        std::vector<size_t>{});
      run_estimation = std::numeric_limits<int>::min();
      current_statement__ = 33;
      run_estimation = context__.vals_i("run_estimation")[(1 - 1)];
      current_statement__ = 33;
      stan::math::check_greater_or_equal(function__, "run_estimation",
        run_estimation, 0);
      current_statement__ = 33;
      stan::math::check_less_or_equal(function__, "run_estimation",
        run_estimation, 1);
      current_statement__ = 34;
      stan::math::validate_non_negative_index("p", "N", N);
      current_statement__ = 35;
      context__.validate_dims("data initialization", "p", "double",
        std::vector<size_t>{static_cast<size_t>(N)});
      p_data__ = Eigen::Matrix<double,-1,1>::Constant(N,
                   std::numeric_limits<double>::quiet_NaN());
      new (&p) Eigen::Map<Eigen::Matrix<double,-1,1>>(p_data__.data(), N);
      {
        std::vector<local_scalar_t__> p_flat__;
        current_statement__ = 35;
        p_flat__ = context__.vals_r("p");
        current_statement__ = 35;
        pos__ = 1;
        current_statement__ = 35;
        for (int sym1__ = 1; sym1__ <= N; ++sym1__) {
          current_statement__ = 35;
          stan::model::assign(p, p_flat__[(pos__ - 1)],
            "assigning variable p", stan::model::index_uni(sym1__));
          current_statement__ = 35;
          pos__ = (pos__ + 1);
        }
      }
      current_statement__ = 35;
      stan::math::check_simplex(function__, "p", p);
      current_statement__ = 36;
      context__.validate_dims("data initialization", "delta_sd", "double",
        std::vector<size_t>{});
      delta_sd = std::numeric_limits<double>::quiet_NaN();
      current_statement__ = 36;
      delta_sd = context__.vals_r("delta_sd")[(1 - 1)];
      current_statement__ = 37;
      context__.validate_dims("data initialization", "background_sd",
        "double", std::vector<size_t>{});
      background_sd = std::numeric_limits<double>::quiet_NaN();
      current_statement__ = 37;
      background_sd = context__.vals_r("background_sd")[(1 - 1)];
      current_statement__ = 38;
      stan::math::validate_non_negative_index("r", "K", K);
      current_statement__ = 39;
      stan::math::validate_positive_index("r", "N", N);
      current_statement__ = 40;
      stan::math::validate_non_negative_index("background", "N", N);
      current_statement__ = 41;
      stan::math::validate_non_negative_index("background", "M", M);
      current_statement__ = 42;
      stan::math::validate_non_negative_index("delta", "M", M);
      current_statement__ = 43;
      stan::math::validate_non_negative_index("delta", "N", N);
      current_statement__ = 44;
      stan::math::validate_non_negative_index("delta_mean", "M", M);
      current_statement__ = 45;
      stan::math::validate_non_negative_index("background_mean", "N", N);
    } catch (const std::exception& e) {
      stan::lang::rethrow_located(e, locations_array__[current_statement__]);
    }
    num_params_r__ = (K * (N - 1)) + (N * M) + (M * N) + M + N + 1 + 1;
  }
  inline std::string model_name() const final {
    return "model_shrinkage";
  }
  inline std::vector<std::string> model_compile_info() const noexcept {
    return std::vector<std::string>{"stanc_version = stanc3 v2.32.2",
             "stancflags = --allow-undefined"};
  }
  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_shrinkage_namespace::log_prob";
    // suppress unused var warning
    (void) function__;
    try {
      std::vector<Eigen::Matrix<local_scalar_t__,-1,1>> r =
        std::vector<Eigen::Matrix<local_scalar_t__,-1,1>>(K,
          Eigen::Matrix<local_scalar_t__,-1,1>::Constant(N, DUMMY_VAR__));
      current_statement__ = 1;
      r = in__.template read_constrain_simplex<
            std::vector<Eigen::Matrix<local_scalar_t__,-1,1>>,
            jacobian__>(lp__, K, N);
      std::vector<Eigen::Matrix<local_scalar_t__,-1,1>> background =
        std::vector<Eigen::Matrix<local_scalar_t__,-1,1>>(N,
          Eigen::Matrix<local_scalar_t__,-1,1>::Constant(M, DUMMY_VAR__));
      current_statement__ = 2;
      background = in__.template read_constrain_lub<
                     std::vector<Eigen::Matrix<local_scalar_t__,-1,1>>,
                     jacobian__>(0, 0.5, lp__, N, M);
      std::vector<Eigen::Matrix<local_scalar_t__,-1,1>> delta =
        std::vector<Eigen::Matrix<local_scalar_t__,-1,1>>(M,
          Eigen::Matrix<local_scalar_t__,-1,1>::Constant(N, DUMMY_VAR__));
      current_statement__ = 3;
      delta = in__.template read_constrain_lub<
                std::vector<Eigen::Matrix<local_scalar_t__,-1,1>>,
                jacobian__>(0, 1, lp__, M, N);
      Eigen::Matrix<local_scalar_t__,-1,1> delta_mean =
        Eigen::Matrix<local_scalar_t__,-1,1>::Constant(M, DUMMY_VAR__);
      current_statement__ = 4;
      delta_mean = in__.template read_constrain_lub<
                     Eigen::Matrix<local_scalar_t__,-1,1>, jacobian__>(0, 1,
                     lp__, M);
      Eigen::Matrix<local_scalar_t__,-1,1> background_mean =
        Eigen::Matrix<local_scalar_t__,-1,1>::Constant(N, DUMMY_VAR__);
      current_statement__ = 5;
      background_mean = in__.template read_constrain_lub<
                          Eigen::Matrix<local_scalar_t__,-1,1>,
                          jacobian__>(0, 0.5, lp__, N);
      local_scalar_t__ tau_a = DUMMY_VAR__;
      current_statement__ = 6;
      tau_a = in__.template read_constrain_lb<local_scalar_t__,
                jacobian__>(0, lp__);
      local_scalar_t__ tau_b = DUMMY_VAR__;
      current_statement__ = 7;
      tau_b = in__.template read_constrain_lb<local_scalar_t__,
                jacobian__>(0, lp__);
      {
        current_statement__ = 8;
        lp_accum__.add(stan::math::normal_lpdf<propto__>(tau_a, 0, delta_sd));
        current_statement__ = 9;
        lp_accum__.add(stan::math::normal_lpdf<propto__>(tau_b, 0,
                         background_sd));
        current_statement__ = 12;
        for (int m = 1; m <= M; ++m) {
          current_statement__ = 10;
          lp_accum__.add(stan::math::normal_lpdf<propto__>(
                           stan::model::rvalue(delta, "delta",
                             stan::model::index_uni(m)),
                           stan::model::rvalue(delta_mean, "delta_mean",
                             stan::model::index_uni(m)), tau_a));
        }
        current_statement__ = 15;
        for (int n = 1; n <= N; ++n) {
          current_statement__ = 13;
          lp_accum__.add(stan::math::normal_lpdf<propto__>(
                           stan::model::rvalue(background, "background",
                             stan::model::index_uni(n)),
                           stan::model::rvalue(background_mean,
                             "background_mean", stan::model::index_uni(n)),
                           tau_b));
        }
        current_statement__ = 22;
        if (stan::math::logical_eq(run_estimation, 1)) {
          current_statement__ = 20;
          for (int n = 1; n <= N; ++n) {
            current_statement__ = 18;
            for (int m = 1; m <= M; ++m) {
              current_statement__ = 16;
              lp_accum__.add(stan::math::poisson_lpmf<propto__>(
                               stan::model::rvalue(counts, "counts",
                                 stan::model::index_uni(n),
                                 stan::model::index_uni(m)),
                               (((((stan::model::rvalue(OC, "OC",
                                      stan::model::index_uni(m)) * (1 -
                               stan::model::rvalue(background, "background",
                                 stan::model::index_uni(n),
                                 stan::model::index_uni(m)))) *
                               stan::model::rvalue(delta, "delta",
                                 stan::model::index_uni(m),
                                 stan::model::index_uni(n))) *
                               stan::model::rvalue(p, "p",
                                 stan::model::index_uni(n))) +
                               (((stan::model::rvalue(OC, "OC",
                                    stan::model::index_uni(m)) * (1 -
                               stan::model::rvalue(background, "background",
                                 stan::model::index_uni(n),
                                 stan::model::index_uni(m)))) * (1 -
                               stan::model::rvalue(delta, "delta",
                                 stan::model::index_uni(m),
                                 stan::model::index_uni(n)))) *
                               stan::model::rvalue(r, "r",
                                 stan::model::index_uni(
                                   stan::model::rvalue(cell_type,
                                     "cell_type", stan::model::index_uni(m))),
                                 stan::model::index_uni(n)))) +
                               (stan::model::rvalue(OC, "OC",
                                  stan::model::index_uni(m)) *
                               stan::model::rvalue(background, "background",
                                 stan::model::index_uni(n),
                                 stan::model::index_uni(m))))));
            }
          }
        }
      }
    } 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_shrinkage_namespace::write_array";
    // suppress unused var warning
    (void) function__;
    try {
      std::vector<Eigen::Matrix<double,-1,1>> r =
        std::vector<Eigen::Matrix<double,-1,1>>(K,
          Eigen::Matrix<double,-1,1>::Constant(N,
            std::numeric_limits<double>::quiet_NaN()));
      current_statement__ = 1;
      r = in__.template read_constrain_simplex<
            std::vector<Eigen::Matrix<local_scalar_t__,-1,1>>,
            jacobian__>(lp__, K, N);
      std::vector<Eigen::Matrix<double,-1,1>> background =
        std::vector<Eigen::Matrix<double,-1,1>>(N,
          Eigen::Matrix<double,-1,1>::Constant(M,
            std::numeric_limits<double>::quiet_NaN()));
      current_statement__ = 2;
      background = in__.template read_constrain_lub<
                     std::vector<Eigen::Matrix<local_scalar_t__,-1,1>>,
                     jacobian__>(0, 0.5, lp__, N, M);
      std::vector<Eigen::Matrix<double,-1,1>> delta =
        std::vector<Eigen::Matrix<double,-1,1>>(M,
          Eigen::Matrix<double,-1,1>::Constant(N,
            std::numeric_limits<double>::quiet_NaN()));
      current_statement__ = 3;
      delta = in__.template read_constrain_lub<
                std::vector<Eigen::Matrix<local_scalar_t__,-1,1>>,
                jacobian__>(0, 1, lp__, M, N);
      Eigen::Matrix<double,-1,1> delta_mean =
        Eigen::Matrix<double,-1,1>::Constant(M,
          std::numeric_limits<double>::quiet_NaN());
      current_statement__ = 4;
      delta_mean = in__.template read_constrain_lub<
                     Eigen::Matrix<local_scalar_t__,-1,1>, jacobian__>(0, 1,
                     lp__, M);
      Eigen::Matrix<double,-1,1> background_mean =
        Eigen::Matrix<double,-1,1>::Constant(N,
          std::numeric_limits<double>::quiet_NaN());
      current_statement__ = 5;
      background_mean = in__.template read_constrain_lub<
                          Eigen::Matrix<local_scalar_t__,-1,1>,
                          jacobian__>(0, 0.5, lp__, N);
      double tau_a = std::numeric_limits<double>::quiet_NaN();
      current_statement__ = 6;
      tau_a = in__.template read_constrain_lb<local_scalar_t__,
                jacobian__>(0, lp__);
      double tau_b = std::numeric_limits<double>::quiet_NaN();
      current_statement__ = 7;
      tau_b = in__.template read_constrain_lb<local_scalar_t__,
                jacobian__>(0, lp__);
      for (int sym1__ = 1; sym1__ <= N; ++sym1__) {
        for (int sym2__ = 1; sym2__ <= K; ++sym2__) {
          out__.write(r[(sym2__ - 1)][(sym1__ - 1)]);
        }
      }
      for (int sym1__ = 1; sym1__ <= M; ++sym1__) {
        for (int sym2__ = 1; sym2__ <= N; ++sym2__) {
          out__.write(background[(sym2__ - 1)][(sym1__ - 1)]);
        }
      }
      for (int sym1__ = 1; sym1__ <= N; ++sym1__) {
        for (int sym2__ = 1; sym2__ <= M; ++sym2__) {
          out__.write(delta[(sym2__ - 1)][(sym1__ - 1)]);
        }
      }
      out__.write(delta_mean);
      out__.write(background_mean);
      out__.write(tau_a);
      out__.write(tau_b);
      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;
      std::vector<Eigen::Matrix<local_scalar_t__,-1,1>> r =
        std::vector<Eigen::Matrix<local_scalar_t__,-1,1>>(K,
          Eigen::Matrix<local_scalar_t__,-1,1>::Constant(N, DUMMY_VAR__));
      current_statement__ = 1;
      for (int sym1__ = 1; sym1__ <= N; ++sym1__) {
        current_statement__ = 1;
        for (int sym2__ = 1; sym2__ <= K; ++sym2__) {
          current_statement__ = 1;
          stan::model::assign(r, in__.read<local_scalar_t__>(),
            "assigning variable r", stan::model::index_uni(sym2__),
            stan::model::index_uni(sym1__));
        }
      }
      out__.write_free_simplex(r);
      std::vector<Eigen::Matrix<local_scalar_t__,-1,1>> background =
        std::vector<Eigen::Matrix<local_scalar_t__,-1,1>>(N,
          Eigen::Matrix<local_scalar_t__,-1,1>::Constant(M, DUMMY_VAR__));
      current_statement__ = 2;
      for (int sym1__ = 1; sym1__ <= M; ++sym1__) {
        current_statement__ = 2;
        for (int sym2__ = 1; sym2__ <= N; ++sym2__) {
          current_statement__ = 2;
          stan::model::assign(background, in__.read<local_scalar_t__>(),
            "assigning variable background", stan::model::index_uni(sym2__),
            stan::model::index_uni(sym1__));
        }
      }
      out__.write_free_lub(0, 0.5, background);
      std::vector<Eigen::Matrix<local_scalar_t__,-1,1>> delta =
        std::vector<Eigen::Matrix<local_scalar_t__,-1,1>>(M,
          Eigen::Matrix<local_scalar_t__,-1,1>::Constant(N, DUMMY_VAR__));
      current_statement__ = 3;
      for (int sym1__ = 1; sym1__ <= N; ++sym1__) {
        current_statement__ = 3;
        for (int sym2__ = 1; sym2__ <= M; ++sym2__) {
          current_statement__ = 3;
          stan::model::assign(delta, in__.read<local_scalar_t__>(),
            "assigning variable delta", stan::model::index_uni(sym2__),
            stan::model::index_uni(sym1__));
        }
      }
      out__.write_free_lub(0, 1, delta);
      Eigen::Matrix<local_scalar_t__,-1,1> delta_mean =
        Eigen::Matrix<local_scalar_t__,-1,1>::Constant(M, DUMMY_VAR__);
      current_statement__ = 4;
      stan::model::assign(delta_mean,
        in__.read<Eigen::Matrix<local_scalar_t__,-1,1>>(M),
        "assigning variable delta_mean");
      out__.write_free_lub(0, 1, delta_mean);
      Eigen::Matrix<local_scalar_t__,-1,1> background_mean =
        Eigen::Matrix<local_scalar_t__,-1,1>::Constant(N, DUMMY_VAR__);
      current_statement__ = 5;
      stan::model::assign(background_mean,
        in__.read<Eigen::Matrix<local_scalar_t__,-1,1>>(N),
        "assigning variable background_mean");
      out__.write_free_lub(0, 0.5, background_mean);
      local_scalar_t__ tau_a = DUMMY_VAR__;
      current_statement__ = 6;
      tau_a = in__.read<local_scalar_t__>();
      out__.write_free_lb(0, tau_a);
      local_scalar_t__ tau_b = DUMMY_VAR__;
      current_statement__ = 7;
      tau_b = in__.read<local_scalar_t__>();
      out__.write_free_lb(0, tau_b);
    } 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", "r", "double",
        std::vector<size_t>{static_cast<size_t>(K), static_cast<size_t>(N)});
      current_statement__ = 2;
      context__.validate_dims("parameter initialization", "background",
        "double",
        std::vector<size_t>{static_cast<size_t>(N), static_cast<size_t>(M)});
      current_statement__ = 3;
      context__.validate_dims("parameter initialization", "delta", "double",
        std::vector<size_t>{static_cast<size_t>(M), static_cast<size_t>(N)});
      current_statement__ = 4;
      context__.validate_dims("parameter initialization", "delta_mean",
        "double", std::vector<size_t>{static_cast<size_t>(M)});
      current_statement__ = 5;
      context__.validate_dims("parameter initialization", "background_mean",
        "double", std::vector<size_t>{static_cast<size_t>(N)});
      current_statement__ = 6;
      context__.validate_dims("parameter initialization", "tau_a", "double",
        std::vector<size_t>{});
      current_statement__ = 7;
      context__.validate_dims("parameter initialization", "tau_b", "double",
        std::vector<size_t>{});
      int pos__ = std::numeric_limits<int>::min();
      pos__ = 1;
      std::vector<Eigen::Matrix<local_scalar_t__,-1,1>> r =
        std::vector<Eigen::Matrix<local_scalar_t__,-1,1>>(K,
          Eigen::Matrix<local_scalar_t__,-1,1>::Constant(N, DUMMY_VAR__));
      {
        std::vector<local_scalar_t__> r_flat__;
        current_statement__ = 1;
        r_flat__ = context__.vals_r("r");
        current_statement__ = 1;
        pos__ = 1;
        current_statement__ = 1;
        for (int sym1__ = 1; sym1__ <= N; ++sym1__) {
          current_statement__ = 1;
          for (int sym2__ = 1; sym2__ <= K; ++sym2__) {
            current_statement__ = 1;
            stan::model::assign(r, r_flat__[(pos__ - 1)],
              "assigning variable r", stan::model::index_uni(sym2__),
              stan::model::index_uni(sym1__));
            current_statement__ = 1;
            pos__ = (pos__ + 1);
          }
        }
      }
      out__.write_free_simplex(r);
      std::vector<Eigen::Matrix<local_scalar_t__,-1,1>> background =
        std::vector<Eigen::Matrix<local_scalar_t__,-1,1>>(N,
          Eigen::Matrix<local_scalar_t__,-1,1>::Constant(M, DUMMY_VAR__));
      {
        std::vector<local_scalar_t__> background_flat__;
        current_statement__ = 2;
        background_flat__ = context__.vals_r("background");
        current_statement__ = 2;
        pos__ = 1;
        current_statement__ = 2;
        for (int sym1__ = 1; sym1__ <= M; ++sym1__) {
          current_statement__ = 2;
          for (int sym2__ = 1; sym2__ <= N; ++sym2__) {
            current_statement__ = 2;
            stan::model::assign(background, background_flat__[(pos__ - 1)],
              "assigning variable background",
              stan::model::index_uni(sym2__), stan::model::index_uni(sym1__));
            current_statement__ = 2;
            pos__ = (pos__ + 1);
          }
        }
      }
      out__.write_free_lub(0, 0.5, background);
      std::vector<Eigen::Matrix<local_scalar_t__,-1,1>> delta =
        std::vector<Eigen::Matrix<local_scalar_t__,-1,1>>(M,
          Eigen::Matrix<local_scalar_t__,-1,1>::Constant(N, DUMMY_VAR__));
      {
        std::vector<local_scalar_t__> delta_flat__;
        current_statement__ = 3;
        delta_flat__ = context__.vals_r("delta");
        current_statement__ = 3;
        pos__ = 1;
        current_statement__ = 3;
        for (int sym1__ = 1; sym1__ <= N; ++sym1__) {
          current_statement__ = 3;
          for (int sym2__ = 1; sym2__ <= M; ++sym2__) {
            current_statement__ = 3;
            stan::model::assign(delta, delta_flat__[(pos__ - 1)],
              "assigning variable delta", stan::model::index_uni(sym2__),
              stan::model::index_uni(sym1__));
            current_statement__ = 3;
            pos__ = (pos__ + 1);
          }
        }
      }
      out__.write_free_lub(0, 1, delta);
      Eigen::Matrix<local_scalar_t__,-1,1> delta_mean =
        Eigen::Matrix<local_scalar_t__,-1,1>::Constant(M, DUMMY_VAR__);
      {
        std::vector<local_scalar_t__> delta_mean_flat__;
        current_statement__ = 4;
        delta_mean_flat__ = context__.vals_r("delta_mean");
        current_statement__ = 4;
        pos__ = 1;
        current_statement__ = 4;
        for (int sym1__ = 1; sym1__ <= M; ++sym1__) {
          current_statement__ = 4;
          stan::model::assign(delta_mean, delta_mean_flat__[(pos__ - 1)],
            "assigning variable delta_mean", stan::model::index_uni(sym1__));
          current_statement__ = 4;
          pos__ = (pos__ + 1);
        }
      }
      out__.write_free_lub(0, 1, delta_mean);
      Eigen::Matrix<local_scalar_t__,-1,1> background_mean =
        Eigen::Matrix<local_scalar_t__,-1,1>::Constant(N, DUMMY_VAR__);
      {
        std::vector<local_scalar_t__> background_mean_flat__;
        current_statement__ = 5;
        background_mean_flat__ = context__.vals_r("background_mean");
        current_statement__ = 5;
        pos__ = 1;
        current_statement__ = 5;
        for (int sym1__ = 1; sym1__ <= N; ++sym1__) {
          current_statement__ = 5;
          stan::model::assign(background_mean, background_mean_flat__[(pos__
            - 1)], "assigning variable background_mean",
            stan::model::index_uni(sym1__));
          current_statement__ = 5;
          pos__ = (pos__ + 1);
        }
      }
      out__.write_free_lub(0, 0.5, background_mean);
      local_scalar_t__ tau_a = DUMMY_VAR__;
      current_statement__ = 6;
      tau_a = context__.vals_r("tau_a")[(1 - 1)];
      out__.write_free_lb(0, tau_a);
      local_scalar_t__ tau_b = DUMMY_VAR__;
      current_statement__ = 7;
      tau_b = context__.vals_r("tau_b")[(1 - 1)];
      out__.write_free_lb(0, tau_b);
    } 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 {
    names__ = std::vector<std::string>{"r", "background", "delta",
                "delta_mean", "background_mean", "tau_a", "tau_b"};
    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 {
    dimss__ = std::vector<std::vector<size_t>>{std::vector<size_t>{static_cast<
                                                                    size_t>(K),
                                                 static_cast<size_t>(N)},
                std::vector<size_t>{static_cast<size_t>(N),
                  static_cast<size_t>(M)},
                std::vector<size_t>{static_cast<size_t>(M),
                  static_cast<size_t>(N)},
                std::vector<size_t>{static_cast<size_t>(M)},
                std::vector<size_t>{static_cast<size_t>(N)},
                std::vector<size_t>{}, std::vector<size_t>{}};
    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__) {
      for (int sym2__ = 1; sym2__ <= K; ++sym2__) {
        param_names__.emplace_back(std::string() + "r" + '.' +
          std::to_string(sym2__) + '.' + std::to_string(sym1__));
      }
    }
    for (int sym1__ = 1; sym1__ <= M; ++sym1__) {
      for (int sym2__ = 1; sym2__ <= N; ++sym2__) {
        param_names__.emplace_back(std::string() + "background" + '.' +
          std::to_string(sym2__) + '.' + std::to_string(sym1__));
      }
    }
    for (int sym1__ = 1; sym1__ <= N; ++sym1__) {
      for (int sym2__ = 1; sym2__ <= M; ++sym2__) {
        param_names__.emplace_back(std::string() + "delta" + '.' +
          std::to_string(sym2__) + '.' + std::to_string(sym1__));
      }
    }
    for (int sym1__ = 1; sym1__ <= M; ++sym1__) {
      param_names__.emplace_back(std::string() + "delta_mean" + '.' +
        std::to_string(sym1__));
    }
    for (int sym1__ = 1; sym1__ <= N; ++sym1__) {
      param_names__.emplace_back(std::string() + "background_mean" + '.' +
        std::to_string(sym1__));
    }
    param_names__.emplace_back(std::string() + "tau_a");
    param_names__.emplace_back(std::string() + "tau_b");
    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 - 1); ++sym1__) {
      for (int sym2__ = 1; sym2__ <= K; ++sym2__) {
        param_names__.emplace_back(std::string() + "r" + '.' +
          std::to_string(sym2__) + '.' + std::to_string(sym1__));
      }
    }
    for (int sym1__ = 1; sym1__ <= M; ++sym1__) {
      for (int sym2__ = 1; sym2__ <= N; ++sym2__) {
        param_names__.emplace_back(std::string() + "background" + '.' +
          std::to_string(sym2__) + '.' + std::to_string(sym1__));
      }
    }
    for (int sym1__ = 1; sym1__ <= N; ++sym1__) {
      for (int sym2__ = 1; sym2__ <= M; ++sym2__) {
        param_names__.emplace_back(std::string() + "delta" + '.' +
          std::to_string(sym2__) + '.' + std::to_string(sym1__));
      }
    }
    for (int sym1__ = 1; sym1__ <= M; ++sym1__) {
      param_names__.emplace_back(std::string() + "delta_mean" + '.' +
        std::to_string(sym1__));
    }
    for (int sym1__ = 1; sym1__ <= N; ++sym1__) {
      param_names__.emplace_back(std::string() + "background_mean" + '.' +
        std::to_string(sym1__));
    }
    param_names__.emplace_back(std::string() + "tau_a");
    param_names__.emplace_back(std::string() + "tau_b");
    if (emit_transformed_parameters__) {}
    if (emit_generated_quantities__) {}
  }
  inline std::string get_constrained_sizedtypes() const {
    return std::string("[{\"name\":\"r\",\"type\":{\"name\":\"array\",\"length\":" + std::to_string(K) + ",\"element_type\":{\"name\":\"vector\",\"length\":" + std::to_string(N) + "}},\"block\":\"parameters\"},{\"name\":\"background\",\"type\":{\"name\":\"array\",\"length\":" + std::to_string(N) + ",\"element_type\":{\"name\":\"vector\",\"length\":" + std::to_string(M) + "}},\"block\":\"parameters\"},{\"name\":\"delta\",\"type\":{\"name\":\"array\",\"length\":" + std::to_string(M) + ",\"element_type\":{\"name\":\"vector\",\"length\":" + std::to_string(N) + "}},\"block\":\"parameters\"},{\"name\":\"delta_mean\",\"type\":{\"name\":\"vector\",\"length\":" + std::to_string(M) + "},\"block\":\"parameters\"},{\"name\":\"background_mean\",\"type\":{\"name\":\"vector\",\"length\":" + std::to_string(N) + "},\"block\":\"parameters\"},{\"name\":\"tau_a\",\"type\":{\"name\":\"real\"},\"block\":\"parameters\"},{\"name\":\"tau_b\",\"type\":{\"name\":\"real\"},\"block\":\"parameters\"}]");
  }
  inline std::string get_unconstrained_sizedtypes() const {
    return std::string("[{\"name\":\"r\",\"type\":{\"name\":\"array\",\"length\":" + std::to_string(K) + ",\"element_type\":{\"name\":\"vector\",\"length\":" + std::to_string((N -1)) + "}},\"block\":\"parameters\"},{\"name\":\"background\",\"type\":{\"name\":\"array\",\"length\":" + std::to_string(N) + ",\"element_type\":{\"name\":\"vector\",\"length\":" + std::to_string(M) + "}},\"block\":\"parameters\"},{\"name\":\"delta\",\"type\":{\"name\":\"array\",\"length\":" + std::to_string(M) + ",\"element_type\":{\"name\":\"vector\",\"length\":" + std::to_string(N) + "}},\"block\":\"parameters\"},{\"name\":\"delta_mean\",\"type\":{\"name\":\"vector\",\"length\":" + std::to_string(M) + "},\"block\":\"parameters\"},{\"name\":\"background_mean\",\"type\":{\"name\":\"vector\",\"length\":" + std::to_string(N) + "},\"block\":\"parameters\"},{\"name\":\"tau_a\",\"type\":{\"name\":\"real\"},\"block\":\"parameters\"},{\"name\":\"tau_b\",\"type\":{\"name\":\"real\"},\"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__ = (((((((K * N) + (N * M)) + (M * N)) + M) + N)
      + 1) + 1);
    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__ = (((((((K * N) + (N * M)) + (M * N)) + M) + N)
      + 1) + 1);
    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_shrinkage_namespace::model_shrinkage;
#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_shrinkage_namespace::profiles__;
}
#endif
#endif
