![]() |
Stan Math Library
5.3.0
Automatic Differentiation
|
Evaluator for .select() expressions that evaluates only the branch chosen by the condition, restoring the Eigen 3.x Select semantics.
Eigen 5 implements select as a CwiseTernaryOp whose evaluator computes the then-branch, else-branch, and condition coefficients eagerly before applying the cond == 0 ? b : a functor. For plain arithmetic scalars the discarded branch is dead arithmetic, but for reverse-mode autodiff scalars evaluating a branch has a side effect: it allocates varis on the autodiff stack. chain() runs on every vari during the reverse pass, including orphans whose adjoint is zero, so an orphan whose chain rule multiplies its adjoint by a value-derived quantity (e.g. exp: adj * exp(val) with val = +INF) injects 0 * INF = NaN into the adjoint of a live input. Distribution code throughout stan/math/prim/prob relies on .select() to guard exactly such numerically dangerous expressions.
This base class provides the lazy coefficient access; the Eigen::internal::ternary_evaluator partial specializations for scalar_boolean_select_op on var (rev/core/Eigen_NumTraits.hpp) and fvar<T> (fwd/fun/Eigen_NumTraits.hpp) derive from it. Specializing ternary_evaluator also intercepts Eigen's fused (a < b).select(c, d) evaluator, which derives from ternary_evaluator after rebuilding the expression.
The packet (vectorized) path needs no override: for autodiff scalars functor_traits<scalar_boolean_select_op>::PacketAccess is false, and Flags below additionally masks out PacketAccessBit.
| TernaryOp | the select functor, Eigen::internal::scalar_boolean_select_op<Scalar, Scalar, CondScalar> |
| Arg1 | type of the then-branch expression |
| Arg2 | type of the else-branch expression |
| Arg3 | type of the condition expression |
Definition at line 46 of file lazy_select_evaluator.hpp.
#include <lazy_select_evaluator.hpp>
Inheritance diagram for stan::math::internal::lazy_select_evaluator< TernaryOp, Arg1, Arg2, Arg3 >:Classes | |
| struct | Data |
Public Types | |
| enum | { CoeffReadCost , Arg1Flags = Eigen::internal::evaluator<Arg1>::Flags , Arg2Flags = Eigen::internal::evaluator<Arg2>::Flags , Arg3Flags = Eigen::internal::evaluator<Arg3>::Flags , StorageOrdersAgree , Flags0 , Flags = (Flags0 & ~Eigen::RowMajorBit) | (Arg1Flags & Eigen::RowMajorBit) , Alignment } |
| using | XprType = Eigen::CwiseTernaryOp< TernaryOp, Arg1, Arg2, Arg3 > |
| using | CoeffReturnType = typename XprType::CoeffReturnType |
| using | CondScalar = typename Arg3::Scalar |
Public Member Functions | |
| lazy_select_evaluator (const XprType &xpr) | |
| CoeffReturnType | coeff (Eigen::Index row, Eigen::Index col) const |
| CoeffReturnType | coeff (Eigen::Index index) const |
Protected Attributes | |
| Data | m_d |