Add map-like helpers - #3346
Conversation
Jenkins Console Log Machine informationNo LSB modules are available. Distributor ID: Ubuntu Description: Ubuntu 20.04.3 LTS Release: 20.04 Codename: focalCPU: G++: Clang: |
Jenkins Console Log Machine informationNo LSB modules are available. Distributor ID: Ubuntu Description: Ubuntu 20.04.3 LTS Release: 20.04 Codename: focalCPU: G++: Clang: |
WardBrian
left a comment
There was a problem hiding this comment.
Thanks @florence-bockting -- a few comments on items that stood out to me
| * Expensive Eigen expressions in `args...` are each evaluated once via | ||
| * `to_ref` before the column loop. |
There was a problem hiding this comment.
This kind of comment is unnecessary since we do this always
| * Unlike `col_map`, this overload only zips matrices and does not accept | ||
| * additional shared trailing arguments. |
There was a problem hiding this comment.
I realize this was in @SteveBronder's original proposal, but without closures in the language this is a pretty big usability hazard since you won't be able to have any data or anything else inform the function you're mapping over.
Perhaps we should accept the matrices as a tuple, and trailing ...args are still up to the user?
There was a problem hiding this comment.
Not necessary for this first PR IMO, but tagging @SteveBronder to ask if he thinks a SoA specialization for these functions would make sense
There was a problem hiding this comment.
Idt we need it for a first pass, but for the row and column ones I think that makes sense.
|
It might also be useful if |
|
Yes I agree. I'm cool with that either happening in this PR or another PR |
Jenkins Console Log Machine informationNo LSB modules are available. Distributor ID: Ubuntu Description: Ubuntu 20.04.3 LTS Release: 20.04 Codename: focalCPU: G++: Clang: |
| namespace internal { | ||
|
|
||
| template <typename F, typename Tuple, typename Callback> | ||
| inline decltype(auto) with_tuple_prefix(F& f, Tuple& tup, Callback&& callback) { |
There was a problem hiding this comment.
@SteveBronder am I reading this correctly that the user will write a function like
vector mapper(real mu, real sigma, vector x1, vector x2) and call it like
col_mapN((mu,sigma), x1, x2)?
That feels sort of counter-intuitive compared to the other variadic functions. If we swapped the tuple and the arg pack, so that you had to pass the matrices together as a tuple, that would make slightly more sense to me
There was a problem hiding this comment.
idt there is any precedent on this in particular, but I like having the matrices first and then everything else after, then unpacking. So the signature would look like the following.
vector mapper(vector vec1, vector vec2, real mu, real sigma)
and the user call site would look like
col_mapN(mapper, (matrix1, matrix2), mu, sigma)
Summary
Fixes #3339
This PR adds elementwise and row-/columnwise map helpers for
std::vectorand Eigen matrices:map,mapN,row_map,col_map,row_mapN, andcol_mapN.Implementation details:
map(f, x, args...): apply f to each element of a std::vector, with optional shared argsmapN(f, xs...): zip ≥2 equal-sized std::vectors and apply f elementwiserow_map/col_map: apply f to each row/column of an Eigen matrix, with optional shared argsrow_mapN/col_mapN: zip ≥2 equal-dimension Eigen matrices and apply f rowwise/columnwisestan/math/prim/functor.hppUncertainties:
Tests
test/unit/math/prim/functor/map_test.cppSide Effects
I am not aware of any.
Release notes
map,mapN,row_map,col_map,row_mapN, andcol_mapNfunctors for elementwise and rowwise/columnwise mapping over std::vector and Eigen matrices.Checklist
Copyright holder: Aalto University
The copyright holder is typically you or your assignee, such as a university or company. By submitting this pull request, the copyright holder is agreeing to the license the submitted work under the following licenses:
- Code: BSD 3-clause (https://opensource.org/licenses/BSD-3-Clause)
- Documentation: CC-BY 4.0 (https://creativecommons.org/licenses/by/4.0/)
the basic tests are passing
./runTests.py test/unit)make test-headers)make test-math-dependencies)make doxygen)make cpplint)the code is written in idiomatic C++ and changes are documented in the doxygen
the new changes are tested
AI-Disclosure: I used AI-assistance to draft the PR (Cursor)