<commit_before>#pragma once

#include "trajectory.hpp"

#include <list>
#include <map>

#include "glog/logging.h"

namespace principia {
namespace physics {

template<typename Frame>
Trajectory<Frame>::Trajectory(Body const& body)
    : body_(body),
      parent_(nullptr) {}

template<typename Frame>
std::map<Time, Vector<Length, Frame>> Trajectory<Frame>::Positions() const {
  return ApplyToDegreesOfFreedom<Vector<Length, Frame>>(
      [](DegreesOfFreedom<Frame> const& s) { return s.position; });
}

template<typename Frame>
std::map<Time, Vector<Speed, Frame>> Trajectory<Frame>::Velocities() const {
  return ApplyToDegreesOfFreedom<Vector<Speed, Frame>>(
      [](DegreesOfFreedom<Frame> const& s) { return s.velocity; });
}

template<typename Frame>
std::list<Time> Trajectory<Frame>::Times() const {
  std::list<Time> result;

  // Our own data points in increasing time order.
  for (const auto it : timeline_) {
    Time const& time = it.first;
    result.push_back(time);
  }

  // The data points of our ancestors in decreasing time order.
  Trajectory const* ancestor = this;
  while (ancestor->parent_ != nullptr) {
    Timeline::iterator it = *ancestor->fork_;
    do {
      Time const& time = it->first;
      result.push_front(time);
    } while (it-- !=  // Postdecrement to process begin.
             ancestor->parent_->timeline_.begin());
    ancestor = ancestor->parent_;
  }

  return result;
}

template<typename Frame>
Vector<Length, Frame> const& Trajectory<Frame>::last_position() const {
  if (timeline_.empty()) {
    CHECK(fork_ != nullptr) << "Empty trajectory";
    return (*fork_)->second.position;
  } else {
    return timeline_.rbegin()->second.position;
  }
}

template<typename Frame>
Vector<Speed, Frame> const& Trajectory<Frame>::last_velocity() const {
  if (timeline_.empty()) {
    CHECK(fork_ != nullptr) << "Empty trajectory";
    return (*fork_)->second.velocity;
  } else {
    return timeline_.rbegin()->second.velocity;
  }
}

template<typename Frame>
Time const& Trajectory<Frame>::last_time() const {
  if (timeline_.empty()) {
    CHECK(fork_ != nullptr) << "Empty trajectory";
    return (*fork_)->first;
  } else {
    return timeline_.rbegin()->first;
  }
}

template<typename Frame>
void Trajectory<Frame>::Append(
    Time const& time,
    DegreesOfFreedom<Frame> const& degrees_of_freedom) {
  // TODO(phl): Could we move?
  auto inserted = timeline_.insert(std::make_pair(time, degrees_of_freedom));
  CHECK(timeline_.end() == ++inserted.first) << "Append out of order";
  CHECK(inserted.second) << "Append at existing time";
}

template<typename Frame>
void Trajectory<Frame>::ForgetAfter(Time const& time) {
  // Check that |time| is the time of one of our Timeline or the time of fork.
  auto const it = timeline_.find(time);
  if (it == timeline_.end()) {
    CHECK(fork_ != nullptr)
        << "ForgetAfter a nonexistent time for a root trajectory";
    CHECK_EQ((*fork_)->first, time)
        << "ForgetAfter a nonexistent time for a nonroot trajectory";
  }
<commit_msg>Append.<commit_after>#pragma once

#include "trajectory.hpp"

#include <list>
#include <map>

#include "glog/logging.h"

namespace principia {
namespace physics {

template<typename Frame>
Trajectory<Frame>::Trajectory(Body const& body)
    : body_(body),
      parent_(nullptr) {}

template<typename Frame>
std::map<Time, Vector<Length, Frame>> Trajectory<Frame>::Positions() const {
  return ApplyToDegreesOfFreedom<Vector<Length, Frame>>(
      [](DegreesOfFreedom<Frame> const& s) { return s.position; });
}

template<typename Frame>
std::map<Time, Vector<Speed, Frame>> Trajectory<Frame>::Velocities() const {
  return ApplyToDegreesOfFreedom<Vector<Speed, Frame>>(
      [](DegreesOfFreedom<Frame> const& s) { return s.velocity; });
}

template<typename Frame>
std::list<Time> Trajectory<Frame>::Times() const {
  std::list<Time> result;

  // Our own data points in increasing time order.
  for (const auto it : timeline_) {
    Time const& time = it.first;
    result.push_back(time);
  }

  // The data points of our ancestors in decreasing time order.
  Trajectory const* ancestor = this;
  while (ancestor->parent_ != nullptr) {
    Timeline::iterator it = *ancestor->fork_;
    do {
      Time const& time = it->first;
      result.push_front(time);
    } while (it-- !=  // Postdecrement to process begin.
             ancestor->parent_->timeline_.begin());
    ancestor = ancestor->parent_;
  }

  return result;
}

template<typename Frame>
Vector<Length, Frame> const& Trajectory<Frame>::last_position() const {
  if (timeline_.empty()) {
    CHECK(fork_ != nullptr) << "Empty trajectory";
    return (*fork_)->second.position;
  } else {
    return timeline_.rbegin()->second.position;
  }
}

template<typename Frame>
Vector<Speed, Frame> const& Trajectory<Frame>::last_velocity() const {
  if (timeline_.empty()) {
    CHECK(fork_ != nullptr) << "Empty trajectory";
    return (*fork_)->second.velocity;
  } else {
    return timeline_.rbegin()->second.velocity;
  }
}

template<typename Frame>
Time const& Trajectory<Frame>::last_time() const {
  if (timeline_.empty()) {
    CHECK(fork_ != nullptr) << "Empty trajectory";
    return (*fork_)->first;
  } else {
    return timeline_.rbegin()->first;
  }
}

template<typename Frame>
void Trajectory<Frame>::Append(
    Time const& time,
    DegreesOfFreedom<Frame> const& degrees_of_freedom) {
  auto inserted = timeline_.emplace(time, degrees_of_freedom);
  CHECK(timeline_.end() == ++inserted.first) << "Append out of order";
  CHECK(inserted.second) << "Append at existing time";
}

template<typename Frame>
void Trajectory<Frame>::ForgetAfter(Time const& time) {
  // Check that |time| is the time of one of our Timeline or the time of fork.
  auto const it = timeline_.find(time);
  if (it == timeline_.end()) {
    CHECK(fork_ != nullptr)
        << "ForgetAfter a nonexistent time for a root trajectory";
    CHECK_EQ((*fork_)->first, time)
        << "ForgetAfter a nonexistent time for a nonroot trajectory";
  }

{'fraction_non_alphanumeric': 0.14411276948590382, 'fraction_numerical': 0.0, 'mean_word_length': 4.221645021645021, 'pattern_counts': {'":': 0, '<': 101, '<?xml version=': 0, '>': 99, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6930870', 'n_tokens_mistral': 1956, 'n_tokens_neox': 1881, 'n_words': 484}