Efficiency of loops and conditionals in probability functions

@stevebronder has been making some efficiency improvements in the distributions by pulling out conditions. Here’s a recent PR. I made a note on that PR that all those tests are static traits test. So the compiler should inline them. I’m not entirely sure if the generated code will be much different.

The big thing that would be great to do in some of these, maybe starting with normal_lpdf, would be to figure out (again with traits), when a bunch of additions can be replaced with a multiplication. For example, in evaluating

normal_lpdf(y | mu, sigma)

if y is a vector of size N and sigma is a scalar, then we should be able to do this:

if (log_sigma.size() == 1)
  lpdf -= N * log_sigma[0];
  for (int n = 0; n < N; ++n)
    lpdf -= log_sigma[n];

This is all primitive arithmetic, so it’s not going to be the kind of saving we’d get with autodiff (though it should be bigger for forward mode), I still think
replacing 100 additions with a single multiplication will be a win.

This might actually be a bit slower due to the multiply in the all-scalar case, so that again could be pulled out and evaluated separately.


Thanks Bob I’ll look into this! My main thing with that PR was just to clean up the code a bit as I was reading how scalar_seq_view etc. works.

Yes, I wasn’t talking about this PR, but what we need to do in the future for some added efficiency.