Automatic Differentiation
 
Loading...
Searching...
No Matches
elementwise_check.hpp
Go to the documentation of this file.
1#ifndef STAN_MATH_PRIM_ERR_ELEMENTWISE_ERROR_CHECKER_HPP
2#define STAN_MATH_PRIM_ERR_ELEMENTWISE_ERROR_CHECKER_HPP
3
12#include <string>
13#include <sstream>
14#include <vector>
15
16namespace stan {
17namespace math {
18namespace internal {
19
26template <typename F>
27class Iser {
28 const F& is_good;
29
30 public:
34 explicit Iser(const F& is_good) : is_good(is_good) {}
35
42 template <typename T, typename = require_stan_scalar_t<T>>
43 bool is(const T& x) {
44 return is_good(value_of_rec(x));
45 }
46
53 template <typename T, typename = require_not_stan_scalar_t<T>,
54 typename = void>
55 bool is(const T& x) {
56 for (size_t i = 0; i < stan::math::size(x); ++i)
57 if (!is(stan::get(x, i)))
58 return false;
59 return true;
60 }
61};
62
66inline void pipe_in(std::stringstream& ss) {}
76template <typename Arg0, typename... Args>
77inline void pipe_in(std::stringstream& ss, Arg0 arg0, const Args... args) {
78 ss << arg0;
79 pipe_in(ss, args...);
80}
81
87template <typename... Args>
88void elementwise_throw_domain_error(const Args... args) {
89 std::stringstream ss;
90 pipe_in(ss, args...);
91 throw std::domain_error(ss.str());
92}
93
94} // namespace internal
95
114template <typename F, typename T, typename... Indexings,
115 require_stan_scalar_t<T>* = nullptr>
116inline void elementwise_check(const F& is_good, const char* function,
117 const char* name, const T& x, const char* must_be,
118 const Indexings&... indexings) {
119 if (unlikely(!is_good(value_of_rec(x)))) {
120 [&]() STAN_COLD_PATH {
121 internal::elementwise_throw_domain_error(function, ": ", name,
122 indexings..., " is ", x,
123 ", but must be ", must_be, "!");
124 }();
125 }
126}
145template <typename F, typename T, typename... Indexings,
146 require_eigen_t<T>* = nullptr,
147 std::enable_if_t<(Eigen::internal::traits<T>::Flags
148 & Eigen::LinearAccessBit)
149 || T::IsVectorAtCompileTime>* = nullptr>
150inline void elementwise_check(const F& is_good, const char* function,
151 const char* name, const T& x, const char* must_be,
152 const Indexings&... indexings) {
153 for (size_t i = 0; i < x.size(); i++) {
154 auto scal = value_of_rec(x.coeff(i));
155 if (unlikely(!is_good(scal))) {
156 [&]() STAN_COLD_PATH {
159 function, ": ", name, indexings..., "[", i + error_index::value,
160 "] is ", scal, ", but must be ", must_be, "!");
161 } else if (Eigen::internal::traits<T>::Flags & Eigen::RowMajorBit) {
163 function, ": ", name, indexings..., "[",
164 i / x.cols() + error_index::value, ", ",
165 i % x.cols() + error_index::value, "] is ", scal,
166 ", but must be ", must_be, "!");
167 } else {
169 function, ": ", name, indexings..., "[",
170 i % x.rows() + error_index::value, ", ",
171 i / x.rows() + error_index::value, "] is ", scal,
172 ", but must be ", must_be, "!");
173 }
174 }();
175 }
176 }
177}
178
197template <typename F, typename T, typename... Indexings,
198 require_eigen_t<T>* = nullptr,
199 std::enable_if_t<!(Eigen::internal::traits<T>::Flags
200 & Eigen::LinearAccessBit)
201 && !T::IsVectorAtCompileTime
202 && !(Eigen::internal::traits<T>::Flags
203 & Eigen::RowMajorBit)>* = nullptr>
204inline void elementwise_check(const F& is_good, const char* function,
205 const char* name, const T& x, const char* must_be,
206 const Indexings&... indexings) {
207 for (size_t i = 0; i < x.rows(); i++) {
208 for (size_t j = 0; j < x.cols(); j++) {
209 auto scal = value_of_rec(x.coeff(i, j));
210 if (unlikely(!is_good(scal))) {
211 [&]() STAN_COLD_PATH {
213 function, ": ", name, indexings..., "[", i + error_index::value,
214 ", ", j + error_index::value, "] is ", scal, ", but must be ",
215 must_be, "!");
216 }();
217 }
218 }
219 }
220}
221
240template <typename F, typename T, typename... Indexings,
241 require_eigen_t<T>* = nullptr,
242 std::enable_if_t<
243 !(Eigen::internal::traits<T>::Flags & Eigen::LinearAccessBit)
244 && !T::IsVectorAtCompileTime
245 && static_cast<bool>(Eigen::internal::traits<T>::Flags
246 & Eigen::RowMajorBit)>* = nullptr>
247inline void elementwise_check(const F& is_good, const char* function,
248 const char* name, const T& x, const char* must_be,
249 const Indexings&... indexings) {
250 for (size_t j = 0; j < x.cols(); j++) {
251 for (size_t i = 0; i < x.rows(); i++) {
252 auto scal = value_of_rec(x.coeff(i, j));
253 if (unlikely(!is_good(scal))) {
254 [&]() STAN_COLD_PATH {
256 function, ": ", name, indexings..., "[", i + error_index::value,
257 ", ", j + error_index::value, "] is ", scal, ", but must be ",
258 must_be, "!");
259 }();
260 }
261 }
262 }
263}
264
283template <typename F, typename T, typename... Indexings,
284 require_std_vector_t<T>* = nullptr>
285inline void elementwise_check(const F& is_good, const char* function,
286 const char* name, const T& x, const char* must_be,
287 const Indexings&... indexings) {
288 for (size_t j = 0; j < x.size(); j++) {
289 elementwise_check(is_good, function, name, x[j], must_be, indexings..., "[",
290 j + error_index::value, "]");
291 }
292}
293
312template <typename F, typename T, typename... Indexings,
313 require_var_matrix_t<T>* = nullptr>
314inline void elementwise_check(const F& is_good, const char* function,
315 const char* name, const T& x, const char* must_be,
316 const Indexings&... indexings) {
317 elementwise_check(is_good, function, name, x.val(), must_be, indexings...);
318}
319
332template <typename F, typename T>
333inline bool elementwise_is(const F& is_good, const T& x) {
334 return internal::Iser<F>{is_good}.is(x);
335}
336
337} // namespace math
338} // namespace stan
339#endif
bool is(const T &x)
Check all the scalars inside the container.
bool is(const T &x)
Check the scalar.
Apply an error check to a container, signal failure with false.
#define STAN_COLD_PATH
#define unlikely(x)
require_t< is_eigen< std::decay_t< T > > > require_eigen_t
Require type satisfies is_eigen.
Definition is_eigen.hpp:55
require_t< is_stan_scalar< std::decay_t< T > > > require_stan_scalar_t
Require type satisfies is_stan_scalar.
size_t size(const T &m)
Returns the size (number of the elements) of a matrix_cl or var_value<matrix_cl<T>>.
Definition size.hpp:18
T get(const T &x, size_t n)
Returns the provided element.
Definition get.hpp:23
void pipe_in(std::stringstream &ss)
No-op.
void elementwise_throw_domain_error(const Args... args)
Throws domain error with concatenation of arguments for the error message.
double value_of_rec(const fvar< T > &v)
Return the value of the specified variable.
void elementwise_check(const F &is_good, const char *function, const char *name, const T &x, const char *must_be, const Indexings &... indexings)
Check that the predicate holds for the value of x.
bool elementwise_is(const F &is_good, const T &x)
Check that the predicate holds for the value of x, working elementwise on containers.
The lgamma implementation in stan-math is based on either the reentrant safe lgamma_r implementation ...
Definition fvar.hpp:9
If the input type T is an eigen matrix with 1 column or 1 row at compile time this has a static membe...