Whoa… this got complicated real quick! That’s great! I’m glad we’re having this discussion.
@seantalts, when I said the decision to limit the Math API hasn’t been made, I really don’t think it has. Ideally, we’d start a different thread that’s titled something appropriate like “Limiting the Math API to reverse mode” or something like that so it’s clear. This thread is now 38 responses deep and counting. It’s not clear what the decision is and who has made it. So… for now, the Math library’s API is what we’ve supported so far. We can change that! Just not in a way that obfuscates the decision.
There are a lot of good reasons for splitting the Math library into prim
, rev
, fwd
, and mix
. At this point, I don’t think there are good reasons for splitting each of these into scal
, arr
, and mat
. (I remember we split into the scal
, arr
, mat
distinction based on user requests… back when it was hard to compile Eigen and Boost together, but we’re way past that with what’s easy to install with compilers. We also didn’t understand the maintenance burden of that decision at the time.)
@sakrejda and @Bob_Carpenter are talking about problems that we’ve actually faced in the past. Before we had these 12 headers, we actually did have a lot of trouble compiling. We would have template metaprogramming issues that would lead to the wrong specialization being called (unintuitively) or things not compiling due to having a trait instantiated in the wrong order. This was really hard on new devs understanding how to develop for the Math library. Since splitting into the 12 headers, we haven’t had many of these problems.
@seantalts, thanks for coming at this from a different angle. One of the things you’re suggesting is something that I hadn’t considered for a long time. In the last couple posts, you’ve suggested only running with rev and mix. (If that’s what you meant from the very start, that wasn’t clear at all; it really sounded like all you wanted was reverse mode.) That’s an interesting proposal that we’ll need to evaluate, but it can be evaluated.
Before we split this into 12 headers, we actually did have 4 headers. We split it this way because the different toolchains we were supporting could not handle the compilation. If I recall correctly, we couldn’t even include the mix
header and only instantiate reverse mode. That might have been a mistake on our part or it might have been compiler limitations… We could be well past that with the upgraded C++ compilers everywhere. If we are, then I think what we could consider are either what you’re suggesting or I’d even take it a step further and say we can unify it all. It’d be much simpler to have the generic template definition along with all the specializations in the same file. In theory, we should be able to include everything as long as we don’t instantiate more than what we need.
My guess, though, is that the sweet spot is splitting this into prim
, rev
, fwd
, and mix
. But once again, we could evaluate this. (I don’t know if we can actually get everything included in the right order and not instantiated until we want to; maybe it’s possible?)