I think this question might be mostly for @Bob_Carpenter and @mitzimorris, but it seemed like a good thing for public record.

I know that we can’t reassign to things that are declared `data`

in the Stan language. Is that information propagated down to Math in any form? It would be extremely useful for performance optimizations, such as not checking that a 200MB matrix is finite every leapfrog step (`check_finite`

on data matrices takes about 70% of execution time in `normal_id_glm_lpdf`

for example).

I had in mind a specialization for `finite`

(agreed name should be changed at some point) that would cache which data matrices it had already checked. This code assumes that all `Eigen::MatrixXd`

s are immutable - are there places that Stan generates code where this isn’t true? If not, then we might have our first time needing to write code that makes the Math library not really suitable for general-purpose use. Or else rewriting how we do checks substantially, or overriding functions like `check_finite`

in the Stan language and hiding the Math versions.

Specialization:

```
template <int R, int C>
struct finite<Eigen::Matrix<double, R, C>, true> {
static void check(const char* function, const char* name,
const Eigen::Matrix<double, R, C>& y) {
// TODO: Check if or make thread-safe
static std::set<const double *> cache;
if (cache.find(y.data()) == cache.end()) {
if (!value_of(y).allFinite()) {
for (int n = 0; n < y.size(); ++n) {
if (!(boost::math::isfinite)(y(n)))
domain_error_vec(function, name, y, n, "is ",
", but must be finite!");
}
}
cache.insert(y.data());
}
}
};
```

This reduces the `normal_id_glm_lpdf`

benchmark (see inspirational thread) time to about 25% of the time it takes without the specialization, a 4x speedup. Currently, math library tests for `is_finite`

are written to create a single matrix and then change its contents and continue passing them, so this fails those tests. But I think those tests may not reflect generated Stan code.