Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: mockingbirdnest/Principia
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: ef5bfb27dd8c
Choose a base ref
...
head repository: mockingbirdnest/Principia
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: 4c78a00b0706
Choose a head ref
  • 4 commits
  • 2 files changed
  • 1 contributor

Commits on Feb 4, 2018

  1. Unverified

    This user has not yet uploaded their public signing key.
    Copy the full SHA
    6d3a71e View commit details
  2. Cleanup and comments.

    pleroy committed Feb 4, 2018

    Unverified

    This user has not yet uploaded their public signing key.
    Copy the full SHA
    3344993 View commit details
  3. Comments.

    pleroy committed Feb 4, 2018

    Unverified

    This user has not yet uploaded their public signing key.
    Copy the full SHA
    2644607 View commit details
  4. Merge pull request #1712 from pleroy/LastAccessed

    Cache the index of the last accessed polynomial
    pleroy authored Feb 4, 2018

    Verified

    This commit was signed with the committer’s verified signature. The key has expired.
    chris-huxtable Chris Huxtable
    Copy the full SHA
    4c78a00 View commit details
Showing with 44 additions and 13 deletions.
  1. +17 −0 physics/continuous_trajectory.hpp
  2. +27 −13 physics/continuous_trajectory_body.hpp
17 changes: 17 additions & 0 deletions physics/continuous_trajectory.hpp
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@

#pragma once

#include <atomic>
#include <experimental/optional>
#include <utility>
#include <vector>
@@ -193,6 +194,22 @@ class ContinuousTrajectory : public Trajectory<Frame> {
// The polynomials are in increasing time order.
InstantPolynomialPairs polynomials_;

// Lookups into |polynomials_| are expensive because they entail a binary
// search into a vector that grows over time. In benchmarks, this can be as
// costly as the polynomial evaluation itself. The accesses are not random,
// though, they are clustered in time and (slowly) increasing. To take
// advantage of this, we keep track of the index of the last accessed
// polynomial and first try to see if the new lookup is for the same
// polynomial. This makes us O(1) instead of O(Log N) most of the time and it
// speeds up the lookup by a factor of 7. This member is atomic because of
// multithreading in the ephemeris, and is mutable to maintain the fiction
// that evaluation has no side effects. In the presence of multithreading it
// may be that different threads would want to access polynomials at different
// indices, but by and large the threads progress in parallel, and benchmarks
// show that there is no adverse performance effects. Any value in the range
// of |polynomials_| or 0 is correct.
mutable std::atomic_int last_accessed_polynomial_ = 0;

// The time at which this trajectory starts. Set for a nonempty trajectory.
std::experimental::optional<Instant> first_time_;

40 changes: 27 additions & 13 deletions physics/continuous_trajectory_body.hpp
Original file line number Diff line number Diff line change
@@ -57,7 +57,7 @@ bool ContinuousTrajectory<Frame>::empty() const {

template<typename Frame>
double ContinuousTrajectory<Frame>::average_degree() const {
if (empty()) {
if (polynomials_.empty()) {
return 0;
} else {
double total = 0;
@@ -130,22 +130,24 @@ void ContinuousTrajectory<Frame>::ForgetBefore(Instant const& time) {
if (polynomials_.empty()) {
first_time_ = std::experimental::nullopt;
last_points_.clear();
last_accessed_polynomial_ = 0;
} else {
first_time_ = time;
last_accessed_polynomial_ = polynomials_.size() - 1;
}
}

template<typename Frame>
Instant ContinuousTrajectory<Frame>::t_min() const {
if (empty()) {
if (polynomials_.empty()) {
return astronomy::InfiniteFuture;
}
return *first_time_;
}

template<typename Frame>
Instant ContinuousTrajectory<Frame>::t_max() const {
if (empty()) {
if (polynomials_.empty()) {
return astronomy::InfinitePast;
}
return polynomials_.crbegin()->t_max;
@@ -452,16 +454,28 @@ template<typename Frame>
typename ContinuousTrajectory<Frame>::InstantPolynomialPairs::const_iterator
ContinuousTrajectory<Frame>::FindPolynomialForInstant(
Instant const& time) const {
// Need to use |lower_bound|, not |upper_bound|, because it allows
// heterogeneous arguments. This returns the first polynomial |p| such that
// |time <= p.t_max()|.
auto const it = std::lower_bound(
polynomials_.begin(), polynomials_.end(), time,
[](InstantPolynomialPair const& left,
Instant const& right) {
return left.t_max < right;
});
return it;
// This returns the first polynomial |p| such that |time <= p.t_max|.
{
auto const begin = polynomials_.begin();
auto const it = begin + last_accessed_polynomial_;
int const last_accessed_polynomial = last_accessed_polynomial_;
if (it != polynomials_.end() && time <= it->t_max &&
(it == begin || std::prev(it)->t_max < time)) {
return it;
}
}
{
auto const it =
std::lower_bound(polynomials_.begin(),
polynomials_.end(),
time,
[](InstantPolynomialPair const& left,
Instant const& right) {
return left.t_max < right;
});
last_accessed_polynomial_ = it - polynomials_.begin();
return it;
}
}

} // namespace internal_continuous_trajectory