Skip to content

Add reverse #1650

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 8 commits into from
Jan 30, 2020
Merged

Add reverse #1650

merged 8 commits into from
Jan 30, 2020

Conversation

mcol
Copy link
Contributor

@mcol mcol commented Jan 28, 2020

Summary

This add the implementation of reverse for vectors, row vectors and arrays. Fixes #344.

Tests

Added some basic prim and mix tests.

Side Effects

None.

Checklist

  • Math issue add reverse() function for arrays and vectors #344

  • Copyright holder: Marco Colombo

    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

    • unit tests pass (to run, use: ./runTests.py test/unit)
    • header checks pass, (make test-headers)
    • docs build, (make doxygen)
    • code passes the built in C++ standards checks (make cpplint)
  • the code is written in idiomatic C++ and changes are documented in the doxygen

  • the new changes are tested

Copy link
Collaborator

@andrjohns andrjohns left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks great! Only a couple of minor things from me

std::reverse_copy(x.begin(), x.end(), rev.begin());
return rev;
}

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You could replace the three definitions with a single apply_vector_unary here:

template <typename T>
inline auto reverse(const T& x) {
  return apply_vector_unary<T>::apply(x, [&](const auto& v) {
    return v.reverse();
  });
}

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I should note that this would also implicitly allow for reverse with nested arrays (e.g. reverse(std::vector<VectorXd>)) which returns an array with each vector reversed

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good to know! But for std::vector, will this make a copy?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It has the same cost as the current implementations, where the result is evaluated into a vector which is then returned. Eigen::Map is used to evaluate directly into an std::vector and avoid the need for an intermediary copy

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I should note that this would also implicitly allow for reverse with nested arrays

I think this would be super confusing. I think there should be a reverse function that works the same for any type T[], namely by reversing the elements. If the T is a container type, I don't think it should switch to working elementwise.

If there really needs to be a form of reverse that reverses containers within a list, I think it should get a different name.

I feel very strongly that this pattern of behavior should hold everywhere.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sounds good to me, @mcol can you revert this change (sorry for the detour!). You could instead collapse the two Eigen definitions, so that you just have one definition for Eigen vectors (row or col) and one for std::vectors:

template <typename T>
inline std::vector<T> reverse(const std::vector<T>& x) {
  std::vector<T> rev(x.size());
  std::reverse_copy(x.begin(), x.end(), rev.begin());
  return rev;
}

template <typename T, require_eigen_vector_t<T>>
inline auto reverse(const T& x) {
  return x.reverse();
}

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No worries, if anything I learned about apply_vector_unary! :)

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry to be a pain, but that eigen definition should have had an .eval() at the end, otherwise it could cause the same issues as #1644:

template <typename T, require_eigen_vector_t<T>>
inline auto reverse(const T& x) {
  return x.reverse().eval();
}

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks! After posting, I wanted to make sure I wasn't around the bend on this one, so I took an informal poll of the non-computer scientists in my office (I won't name names) and they expected a top-level reverse only, not an elementwise one.

Copy link
Member

@bob-carpenter bob-carpenter left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The vectorized definition should not work elementwise. If we want an elementwise reverse, it should be a different function.

@bob-carpenter
Copy link
Member

I'm overreviewing this one because I feel very strongly it would be wrong to have reverse apply elementwise to a real[ , ] or to vector[] or row_vector[] in Stan.

@mcol mcol requested a review from bob-carpenter January 29, 2020 11:40
@stan-buildbot
Copy link
Contributor


Name Old Result New Result Ratio Performance change( 1 - new / old )
gp_pois_regr/gp_pois_regr.stan 4.85 4.89 0.99 -0.73% slower
low_dim_corr_gauss/low_dim_corr_gauss.stan 0.02 0.02 1.01 0.56% faster
eight_schools/eight_schools.stan 0.09 0.1 0.91 -9.68% slower
gp_regr/gp_regr.stan 0.22 0.22 0.99 -0.68% slower
irt_2pl/irt_2pl.stan 6.07 6.06 1.0 0.04% faster
performance.compilation 87.76 86.57 1.01 1.36% faster
low_dim_gauss_mix_collapse/low_dim_gauss_mix_collapse.stan 7.3 7.34 0.99 -0.54% slower
pkpd/one_comp_mm_elim_abs.stan 20.85 20.7 1.01 0.68% faster
sir/sir.stan 99.92 96.93 1.03 3.0% faster
gp_regr/gen_gp_data.stan 0.05 0.05 0.97 -3.58% slower
low_dim_gauss_mix/low_dim_gauss_mix.stan 2.96 2.96 1.0 -0.15% slower
pkpd/sim_one_comp_mm_elim_abs.stan 0.33 0.32 1.05 4.66% faster
arK/arK.stan 1.8 1.75 1.03 2.53% faster
arma/arma.stan 0.8 0.8 0.99 -0.75% slower
garch/garch.stan 0.58 0.59 0.99 -0.99% slower
Mean result: 0.998081910098

Jenkins Console Log
Blue Ocean
Commit hash: 5d67cb9


Machine information ProductName: Mac OS X ProductVersion: 10.11.6 BuildVersion: 15G22010

CPU:
Intel(R) Xeon(R) CPU E5-1680 v2 @ 3.00GHz

G++:
Configured with: --prefix=/Applications/Xcode.app/Contents/Developer/usr --with-gxx-include-dir=/usr/include/c++/4.2.1
Apple LLVM version 7.0.2 (clang-700.1.81)
Target: x86_64-apple-darwin15.6.0
Thread model: posix

Clang:
Apple LLVM version 7.0.2 (clang-700.1.81)
Target: x86_64-apple-darwin15.6.0
Thread model: posix

@mcol mcol requested a review from andrjohns January 29, 2020 23:51
Copy link
Collaborator

@andrjohns andrjohns left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lgtm!

@mcol mcol merged commit 5b6bd37 into develop Jan 30, 2020
@mcol mcol deleted the feature/344-reverse branch January 30, 2020 08:03
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

add reverse() function for arrays and vectors
4 participants