So Bob, Rob, and I have been looking at redesigning OperandsAndPartials, and we have a new interface that changes from exposing the partial derivative directly (op.d_x1[i] += adj) to exposing an increment method (op.increment_dx1(i, adj)). I then discovered there are a lot of *= uses of the partial in especially the CDFs, like in binomial_cdf.hpp:

for (size_t i = 0; i < size; i++) {
...
operands_and_partials.increment_dx1(i, - pow(theta_dbl, n_dbl)
* pow(1-theta_dbl, N_dbl-n_dbl-1) / betafunc / Pi);
}

and is then *='d like so:

if (!is_constant_struct<T_prob>::value) {
for (size_t i = 0; i < stan::length(theta); ++i)
operands_and_partials.d_x1[i] *= P;
}

Since I think theta's length and size are not always the same value, it’s not obvious to me how to combine these such that they can fit into the increment_dx1() call. @Bob_Carpenter or @rtrangucci, thoughts?

Okay, I think I will try setting the API back to exposing the data structures.

I can’t find any uses of OperandsAndPartials where we actually care about the size; can anyone confirm or deny this? If we don’t need it I can switch the API more easily leaving that functionality out. It’s really only weird in the multivariate case anyway.