<commit_before>#ifndef STAN_MATH_REV_CORE_VAR_HPP
#define STAN_MATH_REV_CORE_VAR_HPP

#include <stan/math/rev/core/vari.hpp>
#include <stan/math/rev/core/grad.hpp>
#include <stan/math/rev/core/chainable_alloc.hpp>
#include <stan/math/prim/meta.hpp>
#include <stan/math/rev/meta/is_vari.hpp>
#include <stan/math/rev/meta/arena_type.hpp>
#include <stan/math/rev/functor/reverse_pass_callback.hpp>
#include <ostream>
#include <vector>
#ifdef STAN_OPENCL
#include <stan/math/opencl/rev/vari.hpp>
#endif

namespace stan {
namespace math {

// forward declare
template <typename Vari>
static void grad(Vari* vi);

/**
 * Independent (input) and dependent (output) variables for gradients.
 *
 * This class acts as a smart pointer, with resources managed by
 * an arena-based memory manager scoped to a single gradient
 * calculation.
 *
 * A var is constructed with a type `T` and used like any
 * other scalar. Arithmetical functions like negation, addition,
 * and subtraction, as well as a range of mathematical functions
 * like exponentiation and powers are overridden to operate on
 * var values objects.
 * @tparam T An Floating point type.
 */
template <typename T>
class var_value {
  static_assert(
      std::is_floating_point<value_type_t<T>>::value,
      "The template for must be a floating point or a container holding"
      " floating point types");

 public:
  using value_type = std::decay_t<T>;  // type in vari_value.
  using vari_type = std::conditional_t<is_plain_type<value_type>::value,
                                       vari_value<value_type>, vari_view<T>>;

  static constexpr int RowsAtCompileTime{vari_type::RowsAtCompileTime};
  static constexpr int ColsAtCompileTime{vari_type::ColsAtCompileTime};

  /**
   * Pointer to the implementation of this variable.
   *
   * This value should not be modified, but may be accessed in
   * <code>var</code> operators to construct `vari_value<T>`
   * instances.
   */
  vari_type* vi_;

  /**
   * Return `true` if this variable has been
   * declared, but not been defined.  Any attempt to use an
   * undefined variable's value or adjoint will result in a
   * segmentation fault.
   *
   * @return <code>true</code> if this variable does not yet have
   * a defined variable.
   */
  inline bool is_uninitialized() { return (vi_ == nullptr); }

  /**
   * Construct a variable for later assignment.
   *
   * This is implemented as a no-op, leaving the underlying implementation
   * dangling.  Before an assignment, the behavior is thus undefined just
   * as for a basic double.
   */
  var_value() : vi_(nullptr) {}

  /**
   * Construct a variable from the specified floating point argument
   * by constructing a new `vari_value<value_type>`. This constructor is only
   * valid when `S` is convertible to this `vari_value`'s `value_type`.
   * @tparam S A type that is convertible to `value_type`.
   * @param x Value of the variable.
   */
  template <typename S, require_convertible_t<S&, value_type>* = nullptr>
  var_value(S&& x) : vi_(new vari_type(std::forward<S>(x), false)) {}  // NOLINT

  /**
   * Construct a variable from a pointer to a variable implementation.
   * @param vi A vari_value pointer.
   */
  var_value(vari_type* vi) : vi_(vi) {}  // NOLINT

  /**
   * Construct a `var_value` with an inner plain matrix type from a `var_value`
   *  holding an expression.
   * @tparam S a non-plain eigen expression type
   * @param other an eigen expression
   */
  template <typename S, typename T_ = T, require_convertible_t<S&, value_type>* = nullptr,
            require_plain_type_t<T_>* = nullptr,
            require_not_same_t<T, S>* = nullptr>
  var_value(const var_value<S>& other) : vi_(new vari_type(other.vi_->val_)) {
    reverse_pass_callback(
        [this_vi = this->vi_, other_vi = other.vi_]() mutable {
          other_vi->adj_ += this_vi->adj_;
        });
  }

  /**
   * Return a constant reference to the value of this variable.
   *
   * @return The value of this variable.
   */
  inline const auto& val() const { return vi_->val_; }

  /**
   * Return a const reference of the derivative of the root expression with
   * respect to this expression.  This method only works
   * after one of the `grad()` methods has been
   * called.
   *
   * @return Adjoint for this variable.
   */
  inline const auto& adj() const { return vi_->adj_; }

  /**
   * Return a reference to the derivative of the root expression with
   * respect to this expression.  This method only works
   * after one of the `grad()` methods has been
   * called.
   *
   * @return Adjoint for this variable.
   */
  inline auto& adj() { return vi_->adj_; }

  /**
   * Compute the gradient of this (dependent) variable with respect to
   * the specified vector of (independent) variables, assigning the
   * specified vector to the gradient.
   *
   * The grad() function does <i>not</i> recover memory.  In Stan
   * 2.4 and earlier, this function did recover memory.
   *
   * @tparam CheckContainer Not set by user. The default value of value_type
   *  is used to require that grad is only available for scalar `var_value`
   *  types.
   * @param x Vector of independent variables.
   * @param g Gradient vector of partial derivatives of this
   * variable with respect to x.
   */
  template <typename CheckContainer = value_type,
            require_not_container_t<CheckContainer>* = nullptr>
  inline void grad(std::vector<var_value<T>>& x, std::vector<value_type>& g) {
    stan::math::grad(vi_);
    g.resize(x.size());
    for (size_t i = 0; i < x.size(); ++i) {
      g[i] = x[i].vi_->adj_;
    }
  }

  /**
   * Compute the gradient of this (dependent) variable with respect
   * to all (independent) variables.
   *
   * @tparam CheckContainer Not set by user. The default value of value_type
   *  is used to require that grad is only available for scalar `var_value`
   *  types.
   * The grad() function does <i>not</i> recover memory.
   */
  template <typename CheckContainer = value_type,
            require_not_container_t<CheckContainer>* = nullptr>
  void grad() {
    stan::math::grad(vi_);
  }

  // POINTER OVERRIDES

  /**
   * Return a reference to underlying implementation of this variable.
   *
   * If <code>x</code> is of type <code>var</code>, then applying
   * this operator, <code>*x</code>, has the same behavior as
   * <code>*(x.vi_)</code>.
   *
   * <i>Warning</i>:  The returned reference does not track changes to
   * this variable.
   *
   * @return variable
   */
  inline vari_type& operator*() { return *vi_; }

  /**
   * Return a pointer to the underlying implementation of this variable.
   *
   * If <code>x</code> is of type <code>var</code>, then applying
   * this operator, <code>x-&gt;</code>, behaves the same way as
   * <code>x.vi_-&gt;</code>.
   *
   * <i>Warning</i>: The returned result does not track changes to
   * this variable.
   */
  inline vari_type* operator->() { return vi_; }

  // COMPOUND ASSIGNMENT OPERATORS

  /**
   * The compound add/assignment operator for variables (C++).
   *
   * If this variable is a and the argument is the variable b,
   * then (a += b) behaves exactly the same way as (a = a + b),
   * creating an intermediate variable representing (a + b).
   *
   * @param b The variable to add to this variable.
   * @return The result of adding the specified variable to this variable.
   */
  inline var_value<T>& operator+=(const var_value<T>& b);

  /**
   * The compound add/assignment operator for scalars (C++).
   *
   * If this variable is a and the argument is the scalar b, then
   * (a += b) behaves exactly the same way as (a = a + b).  Note
   * that the result is an assignable lvalue.
   *
   * @param b The scalar to add to this variable.
   * @return The result of adding the specified variable to this variable.
   */
  inline var_value<T>& operator+=(T b);

  /**
   * The compound subtract/assignment operator for variables (C++).
   *
   * If this variable is a and the argument is the variable b,
   * then (a -= b) behaves exactly the same way as (a = a - b).
   * Note that the result is an assignable lvalue.
   *
   * @param b The variable to subtract from this variable.
   * @return The result of subtracting the specified variable from
   * this variable.
   */
  inline var_value<T>& operator-=(const var_value<T>& b);

  /**
   * The compound subtract/assignment operator for scalars (C++).
   *
   * If this variable is a and the argument is the scalar b, then
   * (a -= b) behaves exactly the same way as (a = a - b).  Note
   * that the result is an assignable lvalue.
   *
   * @param b The scalar to subtract from this variable.
   * @return The result of subtracting the specified variable from this
   * variable.
   */
  inline var_value<T>& operator-=(T b);

  /**
   * The compound multiply/assignment operator for variables (C++).
   *
   * If this variable is a and the argument is the variable b,
   * then (a *= b) behaves exactly the same way as (a = a * b).
   * Note that the result is an assignable lvalue.
   *
   * @param b The variable to multiply this variable by.
   * @return The result of multiplying this variable by the
   * specified variable.
   */
  inline var_value<T>& operator*=(const var_value<T>& b);

  /**
   * The compound multiply/assignment operator for scalars (C++).
   *
   * If this variable is a and the argument is the scalar b, then
   * (a *= b) behaves exactly the same way as (a = a * b).  Note
   * that the result is an assignable lvalue.
   *
   * @param b The scalar to multiply this variable by.
   * @return The result of multiplying this variable by the specified
   * variable.
   */
  inline var_value<T>& operator*=(T b);

  /**
   * The compound divide/assignment operator for variables (C++).  If this
   * variable is a and the argument is the variable b, then (a /= b)
   * behaves exactly the same way as (a = a / b).  Note that the
   * result is an assignable lvalue.
   *
   * @param b The variable to divide this variable by.
   * @return The result of dividing this variable by the
   * specified variable.
   */
  inline var_value<T>& operator/=(const var_value<T>& b);

  /**
   * The compound divide/assignment operator for scalars (C++).
   *
   * If this variable is a and the argument is the scalar b, then
   * (a /= b) behaves exactly the same way as (a = a / b).  Note
   * that the result is an assignable lvalue.
   *
   * @param b The scalar to divide this variable by.
   * @return The result of dividing this variable by the specified
   * variable.
   */
  inline var_value<T>& operator/=(T b);

  /**
   * A block view of the underlying Eigen matrices.
   * @param start_row Starting row of block.
   * @param start_col Starting columns of block.
   * @param num_rows Number of rows to return.
   * @param num_cols Number of columns to return.
   */
  inline auto block(Eigen::Index start_row, Eigen::Index start_col,
                    Eigen::Index num_rows, Eigen::Index num_cols) const {
    using vari_sub
        = decltype(vi_->block(start_row, start_col, num_rows, num_cols));
    using var_sub = var_value<typename vari_sub::value_type>;
    return var_sub(
        new vari_sub(vi_->block(start_row, start_col, num_rows, num_cols)));
  }

  /**
   * View of the head of Eigen vector types.
   * @param n Number of elements to return from top of vector.
   */
  inline auto head(Eigen::Index n) const {
    using vari_sub = decltype(vi_->head(n));
    using var_sub = var_value<typename vari_sub::value_type>;
    return var_sub(new vari_sub(vi_->head(n)));
  }

  /**
   * View of the tail of the Eigen vector types.
   * @param n Number of elements to return from bottom of vector.
   */
  inline auto tail(Eigen::Index n) const {
    using vari_sub = decltype(vi_->tail(n));
    using var_sub = var_value<typename vari_sub::value_type>;
    return var_sub(new vari_sub(vi_->tail(n)));
  }

  /**
   * View block of N elements starting at position `i`
   * @param i Starting position of block.
   * @param n Number of elements in block
   */
  inline auto segment(Eigen::Index i, Eigen::Index n) const {
    using vari_sub = decltype(vi_->segment(i, n));
    using var_sub = var_value<typename vari_sub::value_type>;
    return var_sub(new vari_sub(vi_->segment(i, n)));
  }

  /**
   * View row of eigen matrices.
   * @param i Row index to slice.
   */
  inline auto row(Eigen::Index i) const {
    using vari_sub = decltype(vi_->row(i));
    using var_sub = var_value<typename vari_sub::value_type>;
    return var_sub(new vari_sub(vi_->row(i)));
  }

  /**
   * View column of eigen matrices
   * @param i Column index to slice
   */
  inline auto col(Eigen::Index i) const {
    using vari_sub = decltype(vi_->col(i));
    using var_sub = var_value<typename vari_sub::value_type>;
    return var_sub(new vari_sub(vi_->col(i)));
  }

  /**
   * View element of eigen matrices
   * @param i Element to access
   */
  inline auto coeff(Eigen::Index i) const {
    using vari_coeff_type = decltype(vi_->coeff(i));
    auto* vari_coeff = new vari_coeff_type(vi_->coeff(i));
    reverse_pass_callback([vari_coeff, this, i]() mutable {
      this->vi_->adj_(i) += vari_coeff->adj_;
    });
    return var_value<double>(vari_coeff);
  }

  /**
   * View element of eigen matrices
   * @param i Row to access
   * @param j Column to access
   */
  inline auto coeff(Eigen::Index i, Eigen::Index j) const {
    using vari_coeff_type = decltype(vi_->coeff(i, j));
    auto* vari_coeff = new vari_coeff_type(vi_->coeff(i, j));
    reverse_pass_callback([vari_coeff, this, i, j]() mutable {
      this->vi_->adj_(i, j) += vari_coeff->adj_;
    });
    return var_value<double>(vari_coeff);
  }

  /**
   * View element of eigen matrices
   * @param i Element to access
   */
  inline auto operator()(Eigen::Index i) const { return this->coeff(i); }

  /**
   * View element of eigen matrices
   * @param i Row to access
   * @param j Column to access
   */
  inline auto operator()(Eigen::Index i, Eigen::Index j) const {
    return this->coeff(i, j);
  }

  /**
   * Write the value of this autodiff variable and its adjoint to
   * the specified output stream.
   *
   * @param os Output stream to which to write.
   * @param v Variable to write.
   * @return Reference to the specified output stream.
   */
  friend std::ostream& operator<<(std::ostream& os, const var_value<T>& v) {
    if (v.vi_ == nullptr) {
      return os << "uninitialized";
    }
    return os << v.val();
  }

  /**
   * Assignment of another plain var value, when this also contains a plain
   * type.
   * @tparam S type of the value in the `var_value` to assing
   * @param other the value to assign
   * @return this
   */
  template <typename S, require_convertible_t<S&, value_type>* = nullptr,
            require_all_plain_type_t<T, S>* = nullptr>
  var_value<T> operator=(const var_value<S>& other) {
    vi_ = other.vi_;
    return *this;
  }

  /**
   * Assignment of another var value, when either this or the other one does not
   * contain a plain type.
   * @tparam S type of the value in the `var_value` to assing
   * @param other the value to assign
   * @return this
   */
  template <typename S, require_convertible_t<S&, value_type>* = nullptr,
            require_any_not_plain_type_t<T, S>* = nullptr>
  var_value<T> operator=(const var_value<S>& other) {
    arena_t<plain_type_t<T>> prev_val = vi_->val_;
    vi_->val_ = other.val();
    // no need to change any adjoints - these are just zeros before the reverse
    // pass

    reverse_pass_callback(
        [this_vi = this->vi_, other_vi = other.vi_, prev_val]() mutable {
          this_vi->val_ = prev_val;

          // we have no way of detecting aliasing between this->vi_->adj_ and
          // other.vi_->adj_, so we must copy adjoint before reseting to zero

          // we can reuse prev_val instead of allocating a new matrix
          prev_val = this_vi->adj_;
          this_vi->adj_.setZero();
          other_vi->adj_ += prev_val;
        });
    return *this;
  }

  /**
   * Copy assignment operator delegates to general assignment operator.
   * @param other the value to assing
   * @return this
   */
  var_value<T> operator=(const var_value<T>& other) {
    return operator=<T>(other);
  }
};

// For backwards compatability the default value is double
using var = var_value<double>;

}  // namespace math

/**
 * Template specialization defining the scalar type of
 * values stored in var_value.
 *
 * @tparam T type to check.
 * @ingroup type_trait
 */
template <typename T>
struct scalar_type<math::var_value<T>> {
  using type = math::var_value<scalar_type_t<T>>;
};

}  // namespace stan
#endif
<commit_msg>[Jenkins] auto-formatting by clang-format version 6.0.1-14 (tags/RELEASE_601/final)<commit_after>#ifndef STAN_MATH_REV_CORE_VAR_HPP
#define STAN_MATH_REV_CORE_VAR_HPP

#include <stan/math/rev/core/vari.hpp>
#include <stan/math/rev/core/grad.hpp>
#include <stan/math/rev/core/chainable_alloc.hpp>
#include <stan/math/prim/meta.hpp>
#include <stan/math/rev/meta/is_vari.hpp>
#include <stan/math/rev/meta/arena_type.hpp>
#include <stan/math/rev/functor/reverse_pass_callback.hpp>
#include <ostream>
#include <vector>
#ifdef STAN_OPENCL
#include <stan/math/opencl/rev/vari.hpp>
#endif

namespace stan {
namespace math {

// forward declare
template <typename Vari>
static void grad(Vari* vi);

/**
 * Independent (input) and dependent (output) variables for gradients.
 *
 * This class acts as a smart pointer, with resources managed by
 * an arena-based memory manager scoped to a single gradient
 * calculation.
 *
 * A var is constructed with a type `T` and used like any
 * other scalar. Arithmetical functions like negation, addition,
 * and subtraction, as well as a range of mathematical functions
 * like exponentiation and powers are overridden to operate on
 * var values objects.
 * @tparam T An Floating point type.
 */
template <typename T>
class var_value {
  static_assert(
      std::is_floating_point<value_type_t<T>>::value,
      "The template for must be a floating point or a container holding"
      " floating point types");

 public:
  using value_type = std::decay_t<T>;  // type in vari_value.
  using vari_type = std::conditional_t<is_plain_type<value_type>::value,
                                       vari_value<value_type>, vari_view<T>>;

  static constexpr int RowsAtCompileTime{vari_type::RowsAtCompileTime};
  static constexpr int ColsAtCompileTime{vari_type::ColsAtCompileTime};

  /**
   * Pointer to the implementation of this variable.
   *
   * This value should not be modified, but may be accessed in
   * <code>var</code> operators to construct `vari_value<T>`
   * instances.
   */
  vari_type* vi_;

  /**
   * Return `true` if this variable has been
   * declared, but not been defined.  Any attempt to use an
   * undefined variable's value or adjoint will result in a
   * segmentation fault.
   *
   * @return <code>true</code> if this variable does not yet have
   * a defined variable.
   */
  inline bool is_uninitialized() { return (vi_ == nullptr); }

  /**
   * Construct a variable for later assignment.
   *
   * This is implemented as a no-op, leaving the underlying implementation
   * dangling.  Before an assignment, the behavior is thus undefined just
   * as for a basic double.
   */
  var_value() : vi_(nullptr) {}

  /**
   * Construct a variable from the specified floating point argument
   * by constructing a new `vari_value<value_type>`. This constructor is only
   * valid when `S` is convertible to this `vari_value`'s `value_type`.
   * @tparam S A type that is convertible to `value_type`.
   * @param x Value of the variable.
   */
  template <typename S, require_convertible_t<S&, value_type>* = nullptr>
  var_value(S&& x) : vi_(new vari_type(std::forward<S>(x), false)) {}  // NOLINT

  /**
   * Construct a variable from a pointer to a variable implementation.
   * @param vi A vari_value pointer.
   */
  var_value(vari_type* vi) : vi_(vi) {}  // NOLINT

  /**
   * Construct a `var_value` with an inner plain matrix type from a `var_value`
   *  holding an expression.
   * @tparam S a non-plain eigen expression type
   * @param other an eigen expression
   */
  template <typename S, typename T_ = T,
            require_convertible_t<S&, value_type>* = nullptr,
            require_plain_type_t<T_>* = nullptr,
            require_not_same_t<T, S>* = nullptr>
  var_value(const var_value<S>& other) : vi_(new vari_type(other.vi_->val_)) {
    reverse_pass_callback(
        [this_vi = this->vi_, other_vi = other.vi_]() mutable {
          other_vi->adj_ += this_vi->adj_;
        });
  }

  /**
   * Return a constant reference to the value of this variable.
   *
   * @return The value of this variable.
   */
  inline const auto& val() const { return vi_->val_; }

  /**
   * Return a const reference of the derivative of the root expression with
   * respect to this expression.  This method only works
   * after one of the `grad()` methods has been
   * called.
   *
   * @return Adjoint for this variable.
   */
  inline const auto& adj() const { return vi_->adj_; }

  /**
   * Return a reference to the derivative of the root expression with
   * respect to this expression.  This method only works
   * after one of the `grad()` methods has been
   * called.
   *
   * @return Adjoint for this variable.
   */
  inline auto& adj() { return vi_->adj_; }

  /**
   * Compute the gradient of this (dependent) variable with respect to
   * the specified vector of (independent) variables, assigning the
   * specified vector to the gradient.
   *
   * The grad() function does <i>not</i> recover memory.  In Stan
   * 2.4 and earlier, this function did recover memory.
   *
   * @tparam CheckContainer Not set by user. The default value of value_type
   *  is used to require that grad is only available for scalar `var_value`
   *  types.
   * @param x Vector of independent variables.
   * @param g Gradient vector of partial derivatives of this
   * variable with respect to x.
   */
  template <typename CheckContainer = value_type,
            require_not_container_t<CheckContainer>* = nullptr>
  inline void grad(std::vector<var_value<T>>& x, std::vector<value_type>& g) {
    stan::math::grad(vi_);
    g.resize(x.size());
    for (size_t i = 0; i < x.size(); ++i) {
      g[i] = x[i].vi_->adj_;
    }
  }

  /**
   * Compute the gradient of this (dependent) variable with respect
   * to all (independent) variables.
   *
   * @tparam CheckContainer Not set by user. The default value of value_type
   *  is used to require that grad is only available for scalar `var_value`
   *  types.
   * The grad() function does <i>not</i> recover memory.
   */
  template <typename CheckContainer = value_type,
            require_not_container_t<CheckContainer>* = nullptr>
  void grad() {
    stan::math::grad(vi_);
  }

  // POINTER OVERRIDES

  /**
   * Return a reference to underlying implementation of this variable.
   *
   * If <code>x</code> is of type <code>var</code>, then applying
   * this operator, <code>*x</code>, has the same behavior as
   * <code>*(x.vi_)</code>.
   *
   * <i>Warning</i>:  The returned reference does not track changes to
   * this variable.
   *
   * @return variable
   */
  inline vari_type& operator*() { return *vi_; }

  /**
   * Return a pointer to the underlying implementation of this variable.
   *
   * If <code>x</code> is of type <code>var</code>, then applying
   * this operator, <code>x-&gt;</code>, behaves the same way as
   * <code>x.vi_-&gt;</code>.
   *
   * <i>Warning</i>: The returned result does not track changes to
   * this variable.
   */
  inline vari_type* operator->() { return vi_; }

  // COMPOUND ASSIGNMENT OPERATORS

  /**
   * The compound add/assignment operator for variables (C++).
   *
   * If this variable is a and the argument is the variable b,
   * then (a += b) behaves exactly the same way as (a = a + b),
   * creating an intermediate variable representing (a + b).
   *
   * @param b The variable to add to this variable.
   * @return The result of adding the specified variable to this variable.
   */
  inline var_value<T>& operator+=(const var_value<T>& b);

  /**
   * The compound add/assignment operator for scalars (C++).
   *
   * If this variable is a and the argument is the scalar b, then
   * (a += b) behaves exactly the same way as (a = a + b).  Note
   * that the result is an assignable lvalue.
   *
   * @param b The scalar to add to this variable.
   * @return The result of adding the specified variable to this variable.
   */
  inline var_value<T>& operator+=(T b);

  /**
   * The compound subtract/assignment operator for variables (C++).
   *
   * If this variable is a and the argument is the variable b,
   * then (a -= b) behaves exactly the same way as (a = a - b).
   * Note that the result is an assignable lvalue.
   *
   * @param b The variable to subtract from this variable.
   * @return The result of subtracting the specified variable from
   * this variable.
   */
  inline var_value<T>& operator-=(const var_value<T>& b);

  /**
   * The compound subtract/assignment operator for scalars (C++).
   *
   * If this variable is a and the argument is the scalar b, then
   * (a -= b) behaves exactly the same way as (a = a - b).  Note
   * that the result is an assignable lvalue.
   *
   * @param b The scalar to subtract from this variable.
   * @return The result of subtracting the specified variable from this
   * variable.
   */
  inline var_value<T>& operator-=(T b);

  /**
   * The compound multiply/assignment operator for variables (C++).
   *
   * If this variable is a and the argument is the variable b,
   * then (a *= b) behaves exactly the same way as (a = a * b).
   * Note that the result is an assignable lvalue.
   *
   * @param b The variable to multiply this variable by.
   * @return The result of multiplying this variable by the
   * specified variable.
   */
  inline var_value<T>& operator*=(const var_value<T>& b);

  /**
   * The compound multiply/assignment operator for scalars (C++).
   *
   * If this variable is a and the argument is the scalar b, then
   * (a *= b) behaves exactly the same way as (a = a * b).  Note
   * that the result is an assignable lvalue.
   *
   * @param b The scalar to multiply this variable by.
   * @return The result of multiplying this variable by the specified
   * variable.
   */
  inline var_value<T>& operator*=(T b);

  /**
   * The compound divide/assignment operator for variables (C++).  If this
   * variable is a and the argument is the variable b, then (a /= b)
   * behaves exactly the same way as (a = a / b).  Note that the
   * result is an assignable lvalue.
   *
   * @param b The variable to divide this variable by.
   * @return The result of dividing this variable by the
   * specified variable.
   */
  inline var_value<T>& operator/=(const var_value<T>& b);

  /**
   * The compound divide/assignment operator for scalars (C++).
   *
   * If this variable is a and the argument is the scalar b, then
   * (a /= b) behaves exactly the same way as (a = a / b).  Note
   * that the result is an assignable lvalue.
   *
   * @param b The scalar to divide this variable by.
   * @return The result of dividing this variable by the specified
   * variable.
   */
  inline var_value<T>& operator/=(T b);

  /**
   * A block view of the underlying Eigen matrices.
   * @param start_row Starting row of block.
   * @param start_col Starting columns of block.
   * @param num_rows Number of rows to return.
   * @param num_cols Number of columns to return.
   */
  inline auto block(Eigen::Index start_row, Eigen::Index start_col,
                    Eigen::Index num_rows, Eigen::Index num_cols) const {
    using vari_sub
        = decltype(vi_->block(start_row, start_col, num_rows, num_cols));
    using var_sub = var_value<typename vari_sub::value_type>;
    return var_sub(
        new vari_sub(vi_->block(start_row, start_col, num_rows, num_cols)));
  }

  /**
   * View of the head of Eigen vector types.
   * @param n Number of elements to return from top of vector.
   */
  inline auto head(Eigen::Index n) const {
    using vari_sub = decltype(vi_->head(n));
    using var_sub = var_value<typename vari_sub::value_type>;
    return var_sub(new vari_sub(vi_->head(n)));
  }

  /**
   * View of the tail of the Eigen vector types.
   * @param n Number of elements to return from bottom of vector.
   */
  inline auto tail(Eigen::Index n) const {
    using vari_sub = decltype(vi_->tail(n));
    using var_sub = var_value<typename vari_sub::value_type>;
    return var_sub(new vari_sub(vi_->tail(n)));
  }

  /**
   * View block of N elements starting at position `i`
   * @param i Starting position of block.
   * @param n Number of elements in block
   */
  inline auto segment(Eigen::Index i, Eigen::Index n) const {
    using vari_sub = decltype(vi_->segment(i, n));
    using var_sub = var_value<typename vari_sub::value_type>;
    return var_sub(new vari_sub(vi_->segment(i, n)));
  }

  /**
   * View row of eigen matrices.
   * @param i Row index to slice.
   */
  inline auto row(Eigen::Index i) const {
    using vari_sub = decltype(vi_->row(i));
    using var_sub = var_value<typename vari_sub::value_type>;
    return var_sub(new vari_sub(vi_->row(i)));
  }

  /**
   * View column of eigen matrices
   * @param i Column index to slice
   */
  inline auto col(Eigen::Index i) const {
    using vari_sub = decltype(vi_->col(i));
    using var_sub = var_value<typename vari_sub::value_type>;
    return var_sub(new vari_sub(vi_->col(i)));
  }

  /**
   * View element of eigen matrices
   * @param i Element to access
   */
  inline auto coeff(Eigen::Index i) const {
    using vari_coeff_type = decltype(vi_->coeff(i));
    auto* vari_coeff = new vari_coeff_type(vi_->coeff(i));
    reverse_pass_callback([vari_coeff, this, i]() mutable {
      this->vi_->adj_(i) += vari_coeff->adj_;
    });
    return var_value<double>(vari_coeff);
  }

  /**
   * View element of eigen matrices
   * @param i Row to access
   * @param j Column to access
   */
  inline auto coeff(Eigen::Index i, Eigen::Index j) const {
    using vari_coeff_type = decltype(vi_->coeff(i, j));
    auto* vari_coeff = new vari_coeff_type(vi_->coeff(i, j));
    reverse_pass_callback([vari_coeff, this, i, j]() mutable {
      this->vi_->adj_(i, j) += vari_coeff->adj_;
    });
    return var_value<double>(vari_coeff);
  }

  /**
   * View element of eigen matrices
   * @param i Element to access
   */
  inline auto operator()(Eigen::Index i) const { return this->coeff(i); }

  /**
   * View element of eigen matrices
   * @param i Row to access
   * @param j Column to access
   */
  inline auto operator()(Eigen::Index i, Eigen::Index j) const {
    return this->coeff(i, j);
  }

  /**
   * Write the value of this autodiff variable and its adjoint to
   * the specified output stream.
   *
   * @param os Output stream to which to write.
   * @param v Variable to write.
   * @return Reference to the specified output stream.
   */
  friend std::ostream& operator<<(std::ostream& os, const var_value<T>& v) {
    if (v.vi_ == nullptr) {
      return os << "uninitialized";
    }
    return os << v.val();
  }

  /**
   * Assignment of another plain var value, when this also contains a plain
   * type.
   * @tparam S type of the value in the `var_value` to assing
   * @param other the value to assign
   * @return this
   */
  template <typename S, require_convertible_t<S&, value_type>* = nullptr,
            require_all_plain_type_t<T, S>* = nullptr>
  var_value<T> operator=(const var_value<S>& other) {
    vi_ = other.vi_;
    return *this;
  }

  /**
   * Assignment of another var value, when either this or the other one does not
   * contain a plain type.
   * @tparam S type of the value in the `var_value` to assing
   * @param other the value to assign
   * @return this
   */
  template <typename S, require_convertible_t<S&, value_type>* = nullptr,
            require_any_not_plain_type_t<T, S>* = nullptr>
  var_value<T> operator=(const var_value<S>& other) {
    arena_t<plain_type_t<T>> prev_val = vi_->val_;
    vi_->val_ = other.val();
    // no need to change any adjoints - these are just zeros before the reverse
    // pass

    reverse_pass_callback(
        [this_vi = this->vi_, other_vi = other.vi_, prev_val]() mutable {
          this_vi->val_ = prev_val;

          // we have no way of detecting aliasing between this->vi_->adj_ and
          // other.vi_->adj_, so we must copy adjoint before reseting to zero

          // we can reuse prev_val instead of allocating a new matrix
          prev_val = this_vi->adj_;
          this_vi->adj_.setZero();
          other_vi->adj_ += prev_val;
        });
    return *this;
  }

  /**
   * Copy assignment operator delegates to general assignment operator.
   * @param other the value to assing
   * @return this
   */
  var_value<T> operator=(const var_value<T>& other) {
    return operator=<T>(other);
  }
};

// For backwards compatability the default value is double
using var = var_value<double>;

}  // namespace math

/**
 * Template specialization defining the scalar type of
 * values stored in var_value.
 *
 * @tparam T type to check.
 * @ingroup type_trait
 */
template <typename T>
struct scalar_type<math::var_value<T>> {
  using type = math::var_value<scalar_type_t<T>>;
};

}  // namespace stan
#endif

{'fraction_non_alphanumeric': 0.11031826595808204, 'fraction_numerical': 0.00041798531080193465, 'mean_word_length': 3.0355421686746986, 'pattern_counts': {'":': 0, '<': 229, '<?xml version=': 0, '>': 301, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 2, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4410195', 'n_tokens_mistral': 10528, 'n_tokens_neox': 10297, 'n_words': 3740}