<commit_before>#include <iostream>
#include <list>

#include "core/Halite.hpp"

inline std::istream& operator>>(std::istream& i,
                                std::pair<signed int, signed int>& p) {
    i >> p.first >> p.second;
    return i;
}

inline std::ostream& operator<<(std::ostream& o,
                                const std::pair<signed int, signed int>& p) {
    o << p.first << ' ' << p.second;
    return o;
}

#include <tclap/CmdLine.h>

namespace TCLAP {
    template<>
    struct ArgTraits<std::pair<signed int, signed int> > {
        typedef TCLAP::ValueLike ValueCategory;
    };
}

bool quiet_output =
    false; //Need to be passed to a bunch of classes; extern is cleaner.
Halite*
    my_game; //Is a pointer to avoid problems with assignment, dynamic memory, and default constructors.

Networking promptNetworking();
void promptDimensions(unsigned short& w, unsigned short& h);

int main(int argc, char** argv) {
    srand(time(NULL)); //For all non-seeded randomness.

    Networking networking;
    std::vector<std::string>* names = NULL;
    unsigned int id =
        std::chrono::duration_cast<std::chrono::seconds>(std::chrono::high_resolution_clock().now().time_since_epoch()).count();

    TCLAP::CmdLine cmd("Halite Game Environment", ' ', "1.2");

    //Switch Args.
    TCLAP::SwitchArg quietSwitch("q",
                                 "quiet",
                                 "Runs game in quiet mode, producing machine-parsable output.",
                                 cmd,
                                 false);
    TCLAP::SwitchArg overrideSwitch("o",
                                    "override",
                                    "Overrides player-sent names using cmd args [SERVER ONLY].",
                                    cmd,
                                    false);
    TCLAP::SwitchArg timeoutSwitch("t",
                                   "timeout",
                                   "Causes game environment to ignore timeouts (give all bots infinite time).",
                                   cmd,
                                   false);
    TCLAP::SwitchArg noReplaySwitch
        ("r", "noreplay", "Turns off the replay generation.", cmd, false);

    //Value Args
    TCLAP::ValueArg<unsigned int> nPlayersArg("n",
                                              "nplayers",
                                              "Create a map that will accommodate n players [SINGLE PLAYER MODE ONLY].",
                                              false,
                                              1,
                                              "{1,2,3,4,5,6}",
                                              cmd);
    TCLAP::ValueArg<std::pair<signed int, signed int> > dimensionArgs("d",
                                                                      "dimensions",
                                                                      "The dimensions of the map.",
                                                                      false,
                                                                      { 0,
                                                                        0 },
                                                                      "a string containing two space-seprated positive integers",
                                                                      cmd);
    TCLAP::ValueArg<unsigned int> seedArg("s",
                                          "seed",
                                          "The seed for the map generator.",
                                          false,
                                          0,
                                          "positive integer",
                                          cmd);
    TCLAP::ValueArg<std::string> replayDirectoryArg("i",
                                                    "replaydirectory",
                                                    "The path to directory for replay output.",
                                                    false,
                                                    ".",
                                                    "path to directory",
                                                    cmd);

    //Remaining Args, be they start commands and/or override names. Description only includes start commands since it will only be seen on local testing.
    TCLAP::UnlabeledMultiArg<std::string> otherArgs("NonspecifiedArgs",
                                                    "Start commands for bots.",
                                                    false,
                                                    "Array of strings",
                                                    cmd);

    cmd.parse(argc, argv);

    unsigned short mapWidth = dimensionArgs.getValue().first;
    unsigned short mapHeight = dimensionArgs.getValue().second;

    unsigned int seed;
    if (seedArg.getValue() != 0) seed = seedArg.getValue();
    else
        seed =
            (std::chrono::duration_cast<std::chrono::microseconds>(std::chrono::system_clock::now().time_since_epoch()).count()
                % 4294967295);

    unsigned short n_players_for_map_creation = nPlayersArg.getValue();

    quiet_output = quietSwitch.getValue();
    bool override_names = overrideSwitch.getValue();
    bool ignore_timeout = timeoutSwitch.getValue();

    std::vector<std::string> unlabeledArgsVector = otherArgs.getValue();
    std::list<std::string> unlabeledArgs;
    for (auto a = unlabeledArgsVector.begin(); a != unlabeledArgsVector.end();
         a++) {
        unlabeledArgs.push_back(*a);
    }

    if (mapWidth == 0 && mapHeight == 0) {
        std::vector<unsigned short> mapSizeChoices =
            { 100, 125, 128, 150, 175, 200, 225, 250, 256 };
        std::mt19937 prg(seed);
        std::uniform_int_distribution<unsigned short> size_dist(0, mapSizeChoices.size() - 1);
        auto random_choice = size_dist(prg);
        mapWidth = mapSizeChoices[random_choice];
        mapHeight = mapWidth;
    }

    if (override_names) {
        if (unlabeledArgs.size() < 4 || unlabeledArgs.size() % 2 != 0) {
            std::cout
                << "Invalid number of player parameters with override switch enabled.  Override intended for server use only."
                << std::endl;
            exit(1);
        } else {
            try {
                names = new std::vector<std::string>();
                while (!unlabeledArgs.empty()) {
                    networking.launch_bot(unlabeledArgs.front());
                    unlabeledArgs.pop_front();
                    names->push_back(unlabeledArgs.front());
                    unlabeledArgs.pop_front();
                }
            }
            catch (...) {
                std::cout
                    << "Invalid player parameters with override switch enabled.  Override intended for server use only."
                    << std::endl;
                delete names;
                names = NULL;
                exit(1);
            }
        }
    } else {
        if (unlabeledArgs.size() < 1) {
            std::cout
                << "Please provide the launch command string for at least one bot."
                << std::endl
                << "Use the --help flag for usage details.\n";
            exit(1);
        }
        try {
            while (!unlabeledArgs.empty()) {
                std::cout << unlabeledArgs.front() << std::endl;
                networking.launch_bot(unlabeledArgs.front());
                unlabeledArgs.pop_front();
            }
        }
        catch (...) {
            std::cout
                << "One or more of your bot launch command strings failed.  Please check for correctness and try again."
                << std::endl;
            exit(1);
        }
    }

    if (networking.player_count() > 1 && n_players_for_map_creation != 1) {
        std::cout << std::endl
                  << "Only single-player mode enables specified n-player maps.  When entering multiple bots, please do not try to specify n."
                  << std::endl << std::endl;
        exit(1);
    }

    if (networking.player_count() > 1)
        n_players_for_map_creation = networking.player_count();

    if (n_players_for_map_creation > 6 || n_players_for_map_creation < 1) {
        std::cout << std::endl
                  << "A map can only accommodate between 1 and 6 players."
                  << std::endl << std::endl;
        exit(1);
    }

    //Create game. Null parameters will be ignored.
    my_game = new Halite(mapWidth,
                         mapHeight,
                         seed,
                         n_players_for_map_creation,
                         networking,
                         ignore_timeout);

    std::string outputFilename = replayDirectoryArg.getValue();
#ifdef _WIN32
    if(outputFilename.back() != '\\') outputFilename.push_back('\\');
#else
    if (outputFilename.back() != '/') outputFilename.push_back('/');
#endif
    GameStatistics stats = my_game->run_game(names,
                                             seed,
                                             id,
                                             !noReplaySwitch.getValue(),
                                             outputFilename);
    if (names != NULL) delete names;

    std::string victoryOut;
    if (quiet_output) {
        std::cout << stats;
    } else {
        for (unsigned int player_id = 0;
             player_id < stats.player_statistics.size(); player_id++) {
            auto& player_stats = stats.player_statistics[player_id];
            std::cout
                << "Player #" << player_stats.tag << ", "
                << my_game->get_name(player_stats.tag)
                << ", came in rank #" << player_stats.rank
                << " and was last alive on frame #"
                << player_stats.last_frame_alive
                << ", producing " << player_stats.total_ship_count << " ships"
                << " and dealing " << player_stats.damage_dealt << " damage"
                << "!\n";
        }
    }

    delete my_game;

    return 0;
}
<commit_msg>Add flag to configure drag at runtime<commit_after>#include <iostream>
#include <list>

#include "core/Halite.hpp"

inline std::istream& operator>>(std::istream& i,
                                std::pair<signed int, signed int>& p) {
    i >> p.first >> p.second;
    return i;
}

inline std::ostream& operator<<(std::ostream& o,
                                const std::pair<signed int, signed int>& p) {
    o << p.first << ' ' << p.second;
    return o;
}

#include <tclap/CmdLine.h>

namespace TCLAP {
    template<>
    struct ArgTraits<std::pair<signed int, signed int> > {
        typedef TCLAP::ValueLike ValueCategory;
    };
}

bool quiet_output =
    false; //Need to be passed to a bunch of classes; extern is cleaner.
Halite*
    my_game; //Is a pointer to avoid problems with assignment, dynamic memory, and default constructors.

Networking promptNetworking();
void promptDimensions(unsigned short& w, unsigned short& h);

int main(int argc, char** argv) {
    srand(time(NULL)); //For all non-seeded randomness.

    Networking networking;
    std::vector<std::string>* names = NULL;
    unsigned int id =
        std::chrono::duration_cast<std::chrono::seconds>(std::chrono::high_resolution_clock().now().time_since_epoch()).count();

    TCLAP::CmdLine cmd("Halite Game Environment", ' ', "1.2");

    //Switch Args.
    TCLAP::SwitchArg quietSwitch("q",
                                 "quiet",
                                 "Runs game in quiet mode, producing machine-parsable output.",
                                 cmd,
                                 false);
    TCLAP::SwitchArg overrideSwitch("o",
                                    "override",
                                    "Overrides player-sent names using cmd args [SERVER ONLY].",
                                    cmd,
                                    false);
    TCLAP::SwitchArg timeoutSwitch("t",
                                   "timeout",
                                   "Causes game environment to ignore timeouts (give all bots infinite time).",
                                   cmd,
                                   false);
    TCLAP::SwitchArg noReplaySwitch
        ("r", "noreplay", "Turns off the replay generation.", cmd, false);

    //Value Args
    TCLAP::ValueArg<unsigned int> nPlayersArg("n",
                                              "nplayers",
                                              "Create a map that will accommodate n players [SINGLE PLAYER MODE ONLY].",
                                              false,
                                              1,
                                              "{1,2,3,4,5,6}",
                                              cmd);
    TCLAP::ValueArg<std::pair<signed int, signed int> > dimensionArgs("d",
                                                                      "dimensions",
                                                                      "The dimensions of the map.",
                                                                      false,
                                                                      { 0,
                                                                        0 },
                                                                      "a string containing two space-seprated positive integers",
                                                                      cmd);
    TCLAP::ValueArg<unsigned int> seedArg("s",
                                          "seed",
                                          "The seed for the map generator.",
                                          false,
                                          0,
                                          "positive integer",
                                          cmd);
    TCLAP::ValueArg<std::string> replayDirectoryArg("i",
                                                    "replaydirectory",
                                                    "The path to directory for replay output.",
                                                    false,
                                                    ".",
                                                    "path to directory",
                                                    cmd);
    TCLAP::ValueArg<int> dragArg(
        "",
        "drag",
        "Drag applied to all ship velocities",
        false,
        hlt::GameConstants::get().DRAG,
        "integer",
        cmd
    );

    //Remaining Args, be they start commands and/or override names. Description only includes start commands since it will only be seen on local testing.
    TCLAP::UnlabeledMultiArg<std::string> otherArgs("NonspecifiedArgs",
                                                    "Start commands for bots.",
                                                    false,
                                                    "Array of strings",
                                                    cmd);

    cmd.parse(argc, argv);

    unsigned short mapWidth = dimensionArgs.getValue().first;
    unsigned short mapHeight = dimensionArgs.getValue().second;

    unsigned int seed;
    if (seedArg.getValue() != 0) seed = seedArg.getValue();
    else
        seed =
            (std::chrono::duration_cast<std::chrono::microseconds>(std::chrono::system_clock::now().time_since_epoch()).count()
                % 4294967295);

    unsigned short n_players_for_map_creation = nPlayersArg.getValue();

    quiet_output = quietSwitch.getValue();
    bool override_names = overrideSwitch.getValue();
    bool ignore_timeout = timeoutSwitch.getValue();

    // Update the game constants.
    auto& constants = hlt::GameConstants::get_mut();
    if (dragArg.isSet()) {
        constants.DRAG = dragArg.getValue();
    }

    if (!quiet_output) {
        std::cout
            << "Game constants: \n"
            << "\tDrag: " << constants.DRAG
            << (dragArg.isSet() ? " (user-set)" : " (default)") << '\n';
    }

    std::vector<std::string> unlabeledArgsVector = otherArgs.getValue();
    std::list<std::string> unlabeledArgs;
    for (auto a = unlabeledArgsVector.begin(); a != unlabeledArgsVector.end();
         a++) {
        unlabeledArgs.push_back(*a);
    }

    if (mapWidth == 0 && mapHeight == 0) {
        std::vector<unsigned short> mapSizeChoices =
            { 100, 125, 128, 150, 175, 200, 225, 250, 256 };
        std::mt19937 prg(seed);
        std::uniform_int_distribution<unsigned short> size_dist(0, mapSizeChoices.size() - 1);
        auto random_choice = size_dist(prg);
        mapWidth = mapSizeChoices[random_choice];
        mapHeight = mapWidth;
    }

    if (override_names) {
        if (unlabeledArgs.size() < 4 || unlabeledArgs.size() % 2 != 0) {
            std::cout
                << "Invalid number of player parameters with override switch enabled.  Override intended for server use only."
                << std::endl;
            exit(1);
        } else {
            try {
                names = new std::vector<std::string>();
                while (!unlabeledArgs.empty()) {
                    networking.launch_bot(unlabeledArgs.front());
                    unlabeledArgs.pop_front();
                    names->push_back(unlabeledArgs.front());
                    unlabeledArgs.pop_front();
                }
            }
            catch (...) {
                std::cout
                    << "Invalid player parameters with override switch enabled.  Override intended for server use only."
                    << std::endl;
                delete names;
                names = NULL;
                exit(1);
            }
        }
    } else {
        if (unlabeledArgs.size() < 1) {
            std::cout
                << "Please provide the launch command string for at least one bot."
                << std::endl
                << "Use the --help flag for usage details.\n";
            exit(1);
        }
        try {
            while (!unlabeledArgs.empty()) {
                std::cout << unlabeledArgs.front() << std::endl;
                networking.launch_bot(unlabeledArgs.front());
                unlabeledArgs.pop_front();
            }
        }
        catch (...) {
            std::cout
                << "One or more of your bot launch command strings failed.  Please check for correctness and try again."
                << std::endl;
            exit(1);
        }
    }

    if (networking.player_count() > 1 && n_players_for_map_creation != 1) {
        std::cout << std::endl
                  << "Only single-player mode enables specified n-player maps.  When entering multiple bots, please do not try to specify n."
                  << std::endl << std::endl;
        exit(1);
    }

    if (networking.player_count() > 1)
        n_players_for_map_creation = networking.player_count();

    if (n_players_for_map_creation > 6 || n_players_for_map_creation < 1) {
        std::cout << std::endl
                  << "A map can only accommodate between 1 and 6 players."
                  << std::endl << std::endl;
        exit(1);
    }

    //Create game. Null parameters will be ignored.
    my_game = new Halite(mapWidth,
                         mapHeight,
                         seed,
                         n_players_for_map_creation,
                         networking,
                         ignore_timeout);

    std::string outputFilename = replayDirectoryArg.getValue();
#ifdef _WIN32
    if(outputFilename.back() != '\\') outputFilename.push_back('\\');
#else
    if (outputFilename.back() != '/') outputFilename.push_back('/');
#endif
    GameStatistics stats = my_game->run_game(names,
                                             seed,
                                             id,
                                             !noReplaySwitch.getValue(),
                                             outputFilename);
    if (names != NULL) delete names;

    std::string victoryOut;
    if (quiet_output) {
        std::cout << stats;
    } else {
        for (unsigned int player_id = 0;
             player_id < stats.player_statistics.size(); player_id++) {
            auto& player_stats = stats.player_statistics[player_id];
            std::cout
                << "Player #" << player_stats.tag << ", "
                << my_game->get_name(player_stats.tag)
                << ", came in rank #" << player_stats.rank
                << " and was last alive on frame #"
                << player_stats.last_frame_alive
                << ", producing " << player_stats.total_ship_count << " ships"
                << " and dealing " << player_stats.damage_dealt << " damage"
                << "!\n";
        }
    }

    delete my_game;

    return 0;
}
<|endoftext|>


<commit_before>#pragma once

#include "trajectory.hpp"

#include <list>
#include <map>

#include "geometry/named_quantities.hpp"
#include "glog/logging.h"
#include "physics/oblate_body.hpp"

using principia::base::check_not_null;
using principia::geometry::Instant;

namespace principia {
namespace physics {

template<typename Frame>
Trajectory<Frame>::Trajectory(not_null<Body const*> const body)
    : body_(check_not_null(body)),
      parent_(nullptr) {
  CHECK(body_->is_compatible_with<Frame>())
      << "Oblate body not in the same frame as the trajectory";
}

template<typename Frame>
typename Trajectory<Frame>::NativeIterator Trajectory<Frame>::first() const {
  NativeIterator it;
  it.InitializeFirst(this);
  return it;
}

template<typename Frame>
typename Trajectory<Frame>::NativeIterator Trajectory<Frame>::on_or_after(
    Instant const& time) const {
  NativeIterator it;
  it.InitializeOnOrAfter(time, this);
  return it;
}

template<typename Frame>
typename Trajectory<Frame>::NativeIterator Trajectory<Frame>::last() const {
  NativeIterator it;
  it.InitializeLast(this);
  return it;
}

template<typename Frame>
template<typename ToFrame>
typename Trajectory<Frame>::TEMPLATE TransformingIterator<ToFrame>
Trajectory<Frame>::first_with_transform(
    Transform<ToFrame> const& transform) const {
  TransformingIterator<ToFrame> it(transform);
  it.InitializeFirst(this);
  return it;
}

template<typename Frame>
template<typename ToFrame>
typename Trajectory<Frame>::TEMPLATE TransformingIterator<ToFrame>
Trajectory<Frame>::on_or_after_with_transform(
    Instant const& time,
    Transform<ToFrame> const& transform) const {
  TransformingIterator<ToFrame> it(transform);
  it.InitializeOnOrAfter(time, this);
  return it;
}

template<typename Frame>
template<typename ToFrame>
typename Trajectory<Frame>::TEMPLATE TransformingIterator<ToFrame>
Trajectory<Frame>::last_with_transform(
    Transform<ToFrame> const& transform) const {
  TransformingIterator<ToFrame> it(transform);
  it.InitializeLast(this);
  return it;
}

template<typename Frame>
std::map<Instant, Position<Frame>> Trajectory<Frame>::Positions() const {
  std::map<Instant, Position<Frame>> result;
  for (NativeIterator it = first(); !it.at_end(); ++it) {
    Instant const& time = it.time();
    result.emplace_hint(result.end(), time, it.degrees_of_freedom().position());
  }
  return result;
}

template<typename Frame>
std::map<Instant, Velocity<Frame>> Trajectory<Frame>::Velocities() const {
  std::map<Instant, Velocity<Frame>> result;
  for (NativeIterator it = first(); !it.at_end(); ++it) {
    Instant const& time = it.time();
    result.emplace_hint(result.end(), time, it.degrees_of_freedom().velocity());
  }
  return result;
}

template<typename Frame>
std::list<Instant> Trajectory<Frame>::Times() const {
  std::list<Instant> result;
  for (NativeIterator it = first(); !it.at_end(); ++it) {
    result.push_back(it.time());
  }
  return result;
}

template<typename Frame>
void Trajectory<Frame>::Append(
    Instant 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(Instant 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";
  }

  // Each of these blocks gets an iterator denoting the first entry with
  // time > |time|.  It then removes that entry and all the entries that follow
  // it.  This preserve any entry with time == |time|.
  {
    auto const it = timeline_.upper_bound(time);
    timeline_.erase(it, timeline_.end());
  }
  {
    auto const it = children_.upper_bound(time);
    children_.erase(it, children_.end());
  }
}

template<typename Frame>
void Trajectory<Frame>::ForgetBefore(Instant const& time) {
  // Check that this is a root.
  CHECK(is_root()) << "ForgetBefore on a nonroot trajectory";
  // Check that |time| is the time of one of our Timeline or the time of fork.
  CHECK(timeline_.find(time) != timeline_.end())
      << "ForgetBefore a nonexistent time";
  {
    auto it = timeline_.upper_bound(time);
    timeline_.erase(timeline_.begin(), it);
  }
  {
    auto it = children_.upper_bound(time);
    children_.erase(children_.begin(), it);
  }
}

template<typename Frame>
Trajectory<Frame>* Trajectory<Frame>::Fork(Instant const& time) {
  auto fork_it = timeline_.find(time);
  CHECK(fork_it != timeline_.end()) << "Fork at nonexistent time";
  // Can't use make_unique below.
  std::unique_ptr<Trajectory<Frame>> child(
      new Trajectory(body_, check_not_null(this) /*parent*/, fork_it));
  child->timeline_.insert(++fork_it, timeline_.end());
  auto const child_it = children_.emplace(time, std::move(child));
  return child_it->second.get();
}

template<typename Frame>
void Trajectory<Frame>::DeleteFork(Trajectory** const fork) {
  CHECK_NOTNULL(fork);
  CHECK_NOTNULL(*fork);
  Instant const* const fork_time = (*fork)->fork_time();
  CHECK_NOTNULL(fork_time);
  // Find the position of |*fork| among our children and remove it.
  auto const range = children_.equal_range(*fork_time);
  for (auto it = range.first; it != range.second; ++it) {
    if (it->second.get() == *fork) {
      children_.erase(it);
      *fork = nullptr;
      return;
    }
  }
  LOG(FATAL) << "fork is not a child of this trajectory";
}

template<typename Frame>
bool Trajectory<Frame>::is_root() const {
  return parent_ == nullptr;
}

template<typename Frame>
Trajectory<Frame> const* Trajectory<Frame>::root() const {
  Trajectory const* ancestor = this;
  while (ancestor->parent_ != nullptr) {
    ancestor = ancestor->parent_;
  }
  return ancestor;
}

template<typename Frame>
Trajectory<Frame>* Trajectory<Frame>::root() {
  Trajectory* ancestor = this;
  while (ancestor->parent_ != nullptr) {
    ancestor = ancestor->parent_;
  }
  return ancestor;
}

template<typename Frame>
Instant const* Trajectory<Frame>::fork_time() const {
  if (parent_ == nullptr) {
    return nullptr;
  } else {
    return &((*fork_)->first);
  }
}

template<typename Frame>
template<typename B>
std::enable_if_t<std::is_base_of<Body, B>::value, not_null<B const*>>
Trajectory<Frame>::body() const {
// Dynamic casting is expensive, as in 3x slower for the benchmarks.  Do that in
// debug mode to catch bugs, but not in optimized mode where we want all the
// performance we can get.
#ifdef _DEBUG
  return check_not_null(
      dynamic_cast<B const*>(static_cast<Body const*>(body_)));
#else
  return check_not_null(static_cast<B const*>(static_cast<Body const*>(body_)));
#endif
}

template<typename Frame>
void Trajectory<Frame>::set_intrinsic_acceleration(
    IntrinsicAcceleration const acceleration) {
  CHECK(body_->is_massless()) << "Trajectory is for a massive body";
  CHECK(intrinsic_acceleration_ == nullptr)
      << "Trajectory already has an intrinsic acceleration";
  intrinsic_acceleration_ =
      std::make_unique<IntrinsicAcceleration>(acceleration);
}

template<typename Frame>
void Trajectory<Frame>::clear_intrinsic_acceleration() {
  intrinsic_acceleration_.reset();
}

template<typename Frame>
bool Trajectory<Frame>::has_intrinsic_acceleration() const {
  return intrinsic_acceleration_ != nullptr;
}

template<typename Frame>
Vector<Acceleration, Frame> Trajectory<Frame>::evaluate_intrinsic_acceleration(
    Instant const& time) const {
  if (intrinsic_acceleration_ != nullptr &&
      (fork_ == nullptr || time > (*fork_)->first)) {
    return (*intrinsic_acceleration_)(time);
  } else {
    return Vector<Acceleration, Frame>({0 * SIUnit<Acceleration>(),
                                        0 * SIUnit<Acceleration>(),
                                        0 * SIUnit<Acceleration>()});
  }
}

template<typename Frame>
typename Trajectory<Frame>::Iterator&
Trajectory<Frame>::Iterator::operator++() {
  if (!forks_.empty() && current_ == forks_.front()) {
    ancestry_.pop_front();
    forks_.pop_front();
    current_ = ancestry_.front()->timeline_.begin();
  } else {
    CHECK(current_ != ancestry_.front()->timeline_.end())
        << "Incrementing beyond end of trajectory";
    ++current_;
  }
  return *this;
}

template<typename Frame>
bool Trajectory<Frame>::Iterator::at_end() const {
  return forks_.empty() && current_ == ancestry_.front()->timeline_.end();
}

template<typename Frame>
Instant const& Trajectory<Frame>::Iterator::time() const {
  return current_->first;
}

template<typename Frame>
void Trajectory<Frame>::Iterator::InitializeFirst(
    Trajectory const* trajectory) {
  CHECK_NOTNULL(trajectory);
  Trajectory const* ancestor = trajectory;
  while (ancestor->parent_ != nullptr) {
    ancestry_.push_front(ancestor);
    forks_.push_front(*ancestor->fork_);
    ancestor = ancestor->parent_;
  }
  ancestry_.push_front(ancestor);
  current_ = ancestor->timeline_.begin();
}

template<typename Frame>
void Trajectory<Frame>::Iterator::InitializeOnOrAfter(
  Instant const& time, Trajectory const* trajectory) {
  CHECK_NOTNULL(trajectory);
  Trajectory const* ancestor = trajectory;
  while (ancestor->fork_ != nullptr && time <= (*ancestor->fork_)->first) {
    ancestry_.push_front(ancestor);
    forks_.push_front(*ancestor->fork_);
    ancestor = ancestor->parent_;
  }
  ancestry_.push_front(ancestor);
  current_ = ancestor->timeline_.lower_bound(time);
}

template<typename Frame>
void Trajectory<Frame>::Iterator::InitializeLast(
    Trajectory const* trajectory) {
  CHECK_NOTNULL(trajectory);
  // We don't need to really keep track of the forks or of the ancestry.
  if (trajectory->timeline_.empty()) {
    CHECK(trajectory->fork_ != nullptr) << "Empty trajectory";
    ancestry_.push_front(trajectory->parent_);
    current_ = *trajectory->fork_;
  } else {
    ancestry_.push_front(trajectory);
    current_ = --trajectory->timeline_.end();
  }
}

template<typename Frame>
typename Trajectory<Frame>::Timeline::const_iterator
Trajectory<Frame>::Iterator::current() const {
  return current_;
}

template<typename Frame>
Trajectory<Frame> const* Trajectory<Frame>::Iterator::trajectory() const {
  return ancestry_.back();
}

template<typename Frame>
DegreesOfFreedom<Frame> const&
Trajectory<Frame>::NativeIterator::degrees_of_freedom() const {
  return this->current()->second;
}

template<typename Frame>
template<typename ToFrame>
DegreesOfFreedom<ToFrame>
Trajectory<Frame>::TransformingIterator<ToFrame>::degrees_of_freedom() const {
  auto it = this->current();
  return transform_(it->first, it->second, this->trajectory());
}

template<typename Frame>
template<typename ToFrame>
Trajectory<Frame>::TransformingIterator<ToFrame>::TransformingIterator(
    Transform<ToFrame> const& transform)
    : Iterator(),
      transform_(transform) {}

template<typename Frame>
Trajectory<Frame>::Trajectory(not_null<Body const*> const body,
                              not_null<Trajectory*> const parent,
                              typename Timeline::iterator const& fork)
    : body_(check_not_null(body)),
      parent_(parent),
      fork_(new typename Timeline::iterator(fork)) {}

}  // namespace physics
}  // namespace principia
<commit_msg>Useless check_not_null.<commit_after>#pragma once

#include "trajectory.hpp"

#include <list>
#include <map>

#include "geometry/named_quantities.hpp"
#include "glog/logging.h"
#include "physics/oblate_body.hpp"

using principia::base::check_not_null;
using principia::geometry::Instant;

namespace principia {
namespace physics {

template<typename Frame>
Trajectory<Frame>::Trajectory(not_null<Body const*> const body)
    : body_(body),
      parent_(nullptr) {
  CHECK(body_->is_compatible_with<Frame>())
      << "Oblate body not in the same frame as the trajectory";
}

template<typename Frame>
typename Trajectory<Frame>::NativeIterator Trajectory<Frame>::first() const {
  NativeIterator it;
  it.InitializeFirst(this);
  return it;
}

template<typename Frame>
typename Trajectory<Frame>::NativeIterator Trajectory<Frame>::on_or_after(
    Instant const& time) const {
  NativeIterator it;
  it.InitializeOnOrAfter(time, this);
  return it;
}

template<typename Frame>
typename Trajectory<Frame>::NativeIterator Trajectory<Frame>::last() const {
  NativeIterator it;
  it.InitializeLast(this);
  return it;
}

template<typename Frame>
template<typename ToFrame>
typename Trajectory<Frame>::TEMPLATE TransformingIterator<ToFrame>
Trajectory<Frame>::first_with_transform(
    Transform<ToFrame> const& transform) const {
  TransformingIterator<ToFrame> it(transform);
  it.InitializeFirst(this);
  return it;
}

template<typename Frame>
template<typename ToFrame>
typename Trajectory<Frame>::TEMPLATE TransformingIterator<ToFrame>
Trajectory<Frame>::on_or_after_with_transform(
    Instant const& time,
    Transform<ToFrame> const& transform) const {
  TransformingIterator<ToFrame> it(transform);
  it.InitializeOnOrAfter(time, this);
  return it;
}

template<typename Frame>
template<typename ToFrame>
typename Trajectory<Frame>::TEMPLATE TransformingIterator<ToFrame>
Trajectory<Frame>::last_with_transform(
    Transform<ToFrame> const& transform) const {
  TransformingIterator<ToFrame> it(transform);
  it.InitializeLast(this);
  return it;
}

template<typename Frame>
std::map<Instant, Position<Frame>> Trajectory<Frame>::Positions() const {
  std::map<Instant, Position<Frame>> result;
  for (NativeIterator it = first(); !it.at_end(); ++it) {
    Instant const& time = it.time();
    result.emplace_hint(result.end(), time, it.degrees_of_freedom().position());
  }
  return result;
}

template<typename Frame>
std::map<Instant, Velocity<Frame>> Trajectory<Frame>::Velocities() const {
  std::map<Instant, Velocity<Frame>> result;
  for (NativeIterator it = first(); !it.at_end(); ++it) {
    Instant const& time = it.time();
    result.emplace_hint(result.end(), time, it.degrees_of_freedom().velocity());
  }
  return result;
}

template<typename Frame>
std::list<Instant> Trajectory<Frame>::Times() const {
  std::list<Instant> result;
  for (NativeIterator it = first(); !it.at_end(); ++it) {
    result.push_back(it.time());
  }
  return result;
}

template<typename Frame>
void Trajectory<Frame>::Append(
    Instant 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(Instant 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";
  }

  // Each of these blocks gets an iterator denoting the first entry with
  // time > |time|.  It then removes that entry and all the entries that follow
  // it.  This preserve any entry with time == |time|.
  {
    auto const it = timeline_.upper_bound(time);
    timeline_.erase(it, timeline_.end());
  }
  {
    auto const it = children_.upper_bound(time);
    children_.erase(it, children_.end());
  }
}

template<typename Frame>
void Trajectory<Frame>::ForgetBefore(Instant const& time) {
  // Check that this is a root.
  CHECK(is_root()) << "ForgetBefore on a nonroot trajectory";
  // Check that |time| is the time of one of our Timeline or the time of fork.
  CHECK(timeline_.find(time) != timeline_.end())
      << "ForgetBefore a nonexistent time";
  {
    auto it = timeline_.upper_bound(time);
    timeline_.erase(timeline_.begin(), it);
  }
  {
    auto it = children_.upper_bound(time);
    children_.erase(children_.begin(), it);
  }
}

template<typename Frame>
Trajectory<Frame>* Trajectory<Frame>::Fork(Instant const& time) {
  auto fork_it = timeline_.find(time);
  CHECK(fork_it != timeline_.end()) << "Fork at nonexistent time";
  // Can't use make_unique below.
  std::unique_ptr<Trajectory<Frame>> child(
      new Trajectory(body_, check_not_null(this) /*parent*/, fork_it));
  child->timeline_.insert(++fork_it, timeline_.end());
  auto const child_it = children_.emplace(time, std::move(child));
  return child_it->second.get();
}

template<typename Frame>
void Trajectory<Frame>::DeleteFork(Trajectory** const fork) {
  CHECK_NOTNULL(fork);
  CHECK_NOTNULL(*fork);
  Instant const* const fork_time = (*fork)->fork_time();
  CHECK_NOTNULL(fork_time);
  // Find the position of |*fork| among our children and remove it.
  auto const range = children_.equal_range(*fork_time);
  for (auto it = range.first; it != range.second; ++it) {
    if (it->second.get() == *fork) {
      children_.erase(it);
      *fork = nullptr;
      return;
    }
  }
  LOG(FATAL) << "fork is not a child of this trajectory";
}

template<typename Frame>
bool Trajectory<Frame>::is_root() const {
  return parent_ == nullptr;
}

template<typename Frame>
Trajectory<Frame> const* Trajectory<Frame>::root() const {
  Trajectory const* ancestor = this;
  while (ancestor->parent_ != nullptr) {
    ancestor = ancestor->parent_;
  }
  return ancestor;
}

template<typename Frame>
Trajectory<Frame>* Trajectory<Frame>::root() {
  Trajectory* ancestor = this;
  while (ancestor->parent_ != nullptr) {
    ancestor = ancestor->parent_;
  }
  return ancestor;
}

template<typename Frame>
Instant const* Trajectory<Frame>::fork_time() const {
  if (parent_ == nullptr) {
    return nullptr;
  } else {
    return &((*fork_)->first);
  }
}

template<typename Frame>
template<typename B>
std::enable_if_t<std::is_base_of<Body, B>::value, not_null<B const*>>
Trajectory<Frame>::body() const {
// Dynamic casting is expensive, as in 3x slower for the benchmarks.  Do that in
// debug mode to catch bugs, but not in optimized mode where we want all the
// performance we can get.
#ifdef _DEBUG
  return check_not_null(
      dynamic_cast<B const*>(static_cast<Body const*>(body_)));
#else
  return check_not_null(static_cast<B const*>(static_cast<Body const*>(body_)));
#endif
}

template<typename Frame>
void Trajectory<Frame>::set_intrinsic_acceleration(
    IntrinsicAcceleration const acceleration) {
  CHECK(body_->is_massless()) << "Trajectory is for a massive body";
  CHECK(intrinsic_acceleration_ == nullptr)
      << "Trajectory already has an intrinsic acceleration";
  intrinsic_acceleration_ =
      std::make_unique<IntrinsicAcceleration>(acceleration);
}

template<typename Frame>
void Trajectory<Frame>::clear_intrinsic_acceleration() {
  intrinsic_acceleration_.reset();
}

template<typename Frame>
bool Trajectory<Frame>::has_intrinsic_acceleration() const {
  return intrinsic_acceleration_ != nullptr;
}

template<typename Frame>
Vector<Acceleration, Frame> Trajectory<Frame>::evaluate_intrinsic_acceleration(
    Instant const& time) const {
  if (intrinsic_acceleration_ != nullptr &&
      (fork_ == nullptr || time > (*fork_)->first)) {
    return (*intrinsic_acceleration_)(time);
  } else {
    return Vector<Acceleration, Frame>({0 * SIUnit<Acceleration>(),
                                        0 * SIUnit<Acceleration>(),
                                        0 * SIUnit<Acceleration>()});
  }
}

template<typename Frame>
typename Trajectory<Frame>::Iterator&
Trajectory<Frame>::Iterator::operator++() {
  if (!forks_.empty() && current_ == forks_.front()) {
    ancestry_.pop_front();
    forks_.pop_front();
    current_ = ancestry_.front()->timeline_.begin();
  } else {
    CHECK(current_ != ancestry_.front()->timeline_.end())
        << "Incrementing beyond end of trajectory";
    ++current_;
  }
  return *this;
}

template<typename Frame>
bool Trajectory<Frame>::Iterator::at_end() const {
  return forks_.empty() && current_ == ancestry_.front()->timeline_.end();
}

template<typename Frame>
Instant const& Trajectory<Frame>::Iterator::time() const {
  return current_->first;
}

template<typename Frame>
void Trajectory<Frame>::Iterator::InitializeFirst(
    Trajectory const* trajectory) {
  CHECK_NOTNULL(trajectory);
  Trajectory const* ancestor = trajectory;
  while (ancestor->parent_ != nullptr) {
    ancestry_.push_front(ancestor);
    forks_.push_front(*ancestor->fork_);
    ancestor = ancestor->parent_;
  }
  ancestry_.push_front(ancestor);
  current_ = ancestor->timeline_.begin();
}

template<typename Frame>
void Trajectory<Frame>::Iterator::InitializeOnOrAfter(
  Instant const& time, Trajectory const* trajectory) {
  CHECK_NOTNULL(trajectory);
  Trajectory const* ancestor = trajectory;
  while (ancestor->fork_ != nullptr && time <= (*ancestor->fork_)->first) {
    ancestry_.push_front(ancestor);
    forks_.push_front(*ancestor->fork_);
    ancestor = ancestor->parent_;
  }
  ancestry_.push_front(ancestor);
  current_ = ancestor->timeline_.lower_bound(time);
}

template<typename Frame>
void Trajectory<Frame>::Iterator::InitializeLast(
    Trajectory const* trajectory) {
  CHECK_NOTNULL(trajectory);
  // We don't need to really keep track of the forks or of the ancestry.
  if (trajectory->timeline_.empty()) {
    CHECK(trajectory->fork_ != nullptr) << "Empty trajectory";
    ancestry_.push_front(trajectory->parent_);
    current_ = *trajectory->fork_;
  } else {
    ancestry_.push_front(trajectory);
    current_ = --trajectory->timeline_.end();
  }
}

template<typename Frame>
typename Trajectory<Frame>::Timeline::const_iterator
Trajectory<Frame>::Iterator::current() const {
  return current_;
}

template<typename Frame>
Trajectory<Frame> const* Trajectory<Frame>::Iterator::trajectory() const {
  return ancestry_.back();
}

template<typename Frame>
DegreesOfFreedom<Frame> const&
Trajectory<Frame>::NativeIterator::degrees_of_freedom() const {
  return this->current()->second;
}

template<typename Frame>
template<typename ToFrame>
DegreesOfFreedom<ToFrame>
Trajectory<Frame>::TransformingIterator<ToFrame>::degrees_of_freedom() const {
  auto it = this->current();
  return transform_(it->first, it->second, this->trajectory());
}

template<typename Frame>
template<typename ToFrame>
Trajectory<Frame>::TransformingIterator<ToFrame>::TransformingIterator(
    Transform<ToFrame> const& transform)
    : Iterator(),
      transform_(transform) {}

template<typename Frame>
Trajectory<Frame>::Trajectory(not_null<Body const*> const body,
                              not_null<Trajectory*> const parent,
                              typename Timeline::iterator const& fork)
    : body_(body),
      parent_(parent),
      fork_(new typename Timeline::iterator(fork)) {}

}  // namespace physics
}  // namespace principia
<|endoftext|>


<commit_before>#pragma once

#include "physics/transforms.hpp"

#include "geometry/affine_map.hpp"
#include "geometry/grassmann.hpp"
#include "geometry/identity.hpp"
#include "geometry/named_quantities.hpp"
#include "geometry/permutation.hpp"
#include "geometry/r3x3_matrix.hpp"
#include "geometry/rotation.hpp"
#include "glog/logging.h"
#include "physics/massive_body.hpp"
#include "quantities/named_quantities.hpp"
#include "quantities/si.hpp"

using principia::geometry::AffineMap;
using principia::geometry::Bivector;
using principia::geometry::Displacement;
using principia::geometry::Identity;
using principia::geometry::Permutation;
using principia::geometry::Position;
using principia::geometry::R3x3Matrix;
using principia::geometry::Rotation;
using principia::geometry::Wedge;
using principia::quantities::AngularFrequency;
using principia::si::Radian;

namespace principia {
namespace physics {

namespace {

//TODO(phl):Fix
// Fills |*matrix| with the rotation matrix that maps the standard basis to the
// basis of the barycentric frame.  Fills |*angular_frequency| with the
// corresponding angular velocity.  These pointers must be nonnul, and there is
// no transfer of ownership.  |barycentre_degrees_of_freedom| must be a convex
// combination of the two other degrees of freedom.
// TODO(phl): All of this should be strongly typed.  It's awfully confusing as
// it stands.  In particular, the sign of the bivector may or may not be
// correct.
template<typename FromFrame, typename ToFrame>
void FromBasisOfBarycentricFrameToStandardBasis(
    DegreesOfFreedom<FromFrame> const& barycentre_degrees_of_freedom,
    DegreesOfFreedom<FromFrame> const& primary_degrees_of_freedom,
    DegreesOfFreedom<FromFrame> const& secondary_degrees_of_freedom,
    Rotation<FromFrame, ToFrame>* rotation,
    Bivector<AngularFrequency, FromFrame>* angular_frequency) {
  CHECK_NOTNULL(rotation);
  CHECK_NOTNULL(angular_frequency);
  Displacement<FromFrame> const reference_direction =
      primary_degrees_of_freedom.position -
      barycentre_degrees_of_freedom.position;
  Vector<double, FromFrame> const normalized_reference_direction =
      Normalize(reference_direction);
  Velocity<FromFrame> const reference_coplanar =
      primary_degrees_of_freedom.velocity -
      barycentre_degrees_of_freedom.velocity;
  // Modified Gram-Schmidt.
  Velocity<FromFrame> const reference_normal =
      reference_coplanar -
      InnerProduct(reference_coplanar, normalized_reference_direction) *
          normalized_reference_direction;
  Vector<double, FromFrame> const normalized_reference_normal =
      Normalize(reference_normal);
  // TODO(egg): should we normalize this?
  Bivector<double, FromFrame> const normalized_reference_binormal =
      Wedge(normalized_reference_direction, normalized_reference_normal);
  *rotation = Rotation<FromFrame, ToFrame>(
                  R3x3Matrix(normalized_reference_direction.coordinates(),
                             normalized_reference_normal.coordinates(),
                             normalized_reference_binormal.coordinates()));
  *angular_frequency =
      (1 * Radian * reference_normal.Norm() / reference_direction.Norm()) *
          normalized_reference_binormal;
}

}  // namespace

template<typename FromFrame, typename ThroughFrame, typename ToFrame>
std::unique_ptr<Transforms<FromFrame, ThroughFrame, ToFrame>>
Transforms<FromFrame, ThroughFrame, ToFrame>::BodyCentredNonRotating(
    Trajectory<FromFrame> const& from_centre_trajectory,
    Trajectory<ToFrame> const& to_centre_trajectory) {
  std::unique_ptr<Transforms> transforms(new Transforms);

  // From the perspective of the lambda the following variable is really |this|,
  // hence the name.
  Transforms* that = transforms.get();
  transforms->first_ =
      [&from_centre_trajectory, that](
          Instant const& t,
          DegreesOfFreedom<FromFrame> const& from_degrees_of_freedom,
          Trajectory<FromFrame> const* trajectory) ->
      DegreesOfFreedom<ThroughFrame> {
    // First check if the result is cached.
    auto cache_it = that->first_cache_.find(std::make_pair(trajectory, t));
    if (cache_it != that->first_cache_.end()) {
      return cache_it->second;
    }

    // on_or_after() is Ln(N), but it doesn't matter unless the map gets very
    // big, in which case we'll have cache misses anyway.
    Trajectory<FromFrame>::NativeIterator const centre_it =
        from_centre_trajectory.on_or_after(t);
    CHECK_EQ(centre_it.time(), t)
        << "Time " << t << " not in centre trajectory";
    DegreesOfFreedom<FromFrame> const& centre_degrees_of_freedom =
        centre_it.degrees_of_freedom();

    AffineMap<FromFrame, ThroughFrame, Length, Identity> position_map(
        centre_degrees_of_freedom.position,
        ThroughFrame::origin,
        Identity<FromFrame, ThroughFrame>());
    Identity<FromFrame, ThroughFrame> velocity_map;
    DegreesOfFreedom<ThroughFrame> through_degrees_of_freedom =
        {position_map(from_degrees_of_freedom.position),
         velocity_map(from_degrees_of_freedom.velocity -
                      centre_degrees_of_freedom.velocity)};

    // Cache the result before returning it.
    that->first_cache_.emplace(std::make_pair(trajectory, t),
                               through_degrees_of_freedom);
    return std::move(through_degrees_of_freedom);
  };

  transforms->second_ =
      [&to_centre_trajectory](
          Instant const& t,
          DegreesOfFreedom<ThroughFrame> const& through_degrees_of_freedom,
          Trajectory<ThroughFrame> const* trajectory) ->
      DegreesOfFreedom<ToFrame> {
    DegreesOfFreedom<ToFrame> const& last_centre_degrees_of_freedom =
        to_centre_trajectory.last().degrees_of_freedom();

    AffineMap<ThroughFrame, ToFrame, Length, Identity> position_map(
        ThroughFrame::origin,
        last_centre_degrees_of_freedom.position,
        Identity<ThroughFrame, ToFrame>());
    Identity<ThroughFrame, ToFrame> velocity_map;
    return {position_map(through_degrees_of_freedom.position),
            velocity_map(through_degrees_of_freedom.velocity)};
  };

  return transforms;
}

template<typename FromFrame, typename ThroughFrame, typename ToFrame>
std::unique_ptr<Transforms<FromFrame, ThroughFrame, ToFrame>>
Transforms<FromFrame, ThroughFrame, ToFrame>::BarycentricRotating(
      Trajectory<FromFrame> const& from_primary_trajectory,
      Trajectory<ToFrame> const& to_primary_trajectory,
      Trajectory<FromFrame> const& from_secondary_trajectory,
      Trajectory<ToFrame> const& to_secondary_trajectory) {
  std::unique_ptr<Transforms> transforms(new Transforms);

  // From the perspective of the lambda the following variable is really |this|,
  // hence the name.
  Transforms* that = transforms.get();
  transforms->first_ =
      [&from_primary_trajectory, &from_secondary_trajectory, that](
          Instant const& t,
          DegreesOfFreedom<FromFrame> const& from_degrees_of_freedom,
          Trajectory<FromFrame> const* trajectory) ->
      DegreesOfFreedom<ThroughFrame> {
    // First check if the result is cached.
    auto cache_it = that->first_cache_.find(std::make_pair(trajectory, t));
    if (cache_it != that->first_cache_.end()) {
      return cache_it->second;
    }

    // on_or_after() is Ln(N).
    Trajectory<FromFrame>::NativeIterator const primary_it =
        from_primary_trajectory.on_or_after(t);
    CHECK_EQ(primary_it.time(), t)
        << "Time " << t << " not in primary trajectory";
    Trajectory<FromFrame>::NativeIterator secondary_it =
        from_secondary_trajectory.on_or_after(t);
    CHECK_EQ(secondary_it.time(), t)
        << "Time " << t << " not in secondary trajectory";

    DegreesOfFreedom<FromFrame> const& primary_degrees_of_freedom =
        primary_it.degrees_of_freedom();
    DegreesOfFreedom<FromFrame> const& secondary_degrees_of_freedom =
        secondary_it.degrees_of_freedom();
    DegreesOfFreedom<FromFrame> const barycentre_degrees_of_freedom =
        Barycentre<FromFrame, GravitationalParameter>(
            {primary_degrees_of_freedom,
             secondary_degrees_of_freedom},
            {from_primary_trajectory.body<MassiveBody>().
                 gravitational_parameter(),
             from_secondary_trajectory.body<MassiveBody>().
                 gravitational_parameter()});
    Rotation<FromFrame, ThroughFrame>
        from_basis_of_barycentric_frame_to_standard_basis;
    Bivector<AngularFrequency, FromFrame> angular_frequency;
    FromBasisOfBarycentricFrameToStandardBasis(
        barycentre_degrees_of_freedom,
        primary_degrees_of_freedom,
        secondary_degrees_of_freedom,
        &from_basis_of_barycentric_frame_to_standard_basis,
        &angular_frequency);
    AffineMap<FromFrame, ThroughFrame, Length, Rotation> position_map(
        barycentre_degrees_of_freedom.position,
        ThroughFrame::origin,
        from_basis_of_barycentric_frame_to_standard_basis);
    // TODO(phl): Could we represent this as a map?
    Velocity<ThroughFrame> const velocity_in_standard_basis =
        from_basis_of_barycentric_frame_to_standard_basis(
            from_degrees_of_freedom.velocity -
                barycentre_degrees_of_freedom.velocity -
                angular_frequency *
                    (from_degrees_of_freedom.position -
                     barycentre_degrees_of_freedom.position) /
                         (1 * Radian));
    DegreesOfFreedom<ThroughFrame> through_degrees_of_freedom =
        {position_map(from_degrees_of_freedom.position),
         velocity_in_standard_basis};

    // Cache the result before returning it.
    that->first_cache_.emplace(std::make_pair(trajectory, t),
                               through_degrees_of_freedom);
    return std::move(through_degrees_of_freedom);
  };

  transforms->second_ =
      [&to_primary_trajectory, &to_secondary_trajectory](
          Instant const& t,
          DegreesOfFreedom<ThroughFrame> const& through_degrees_of_freedom,
          Trajectory<ThroughFrame> const* trajectory) ->
      DegreesOfFreedom<ToFrame> {
    DegreesOfFreedom<ToFrame> const& last_primary_degrees_of_freedom =
        to_primary_trajectory.last().degrees_of_freedom();
    DegreesOfFreedom<ToFrame> const& last_secondary_degrees_of_freedom =
        to_secondary_trajectory.last().degrees_of_freedom();
    DegreesOfFreedom<ToFrame> const last_barycentre_degrees_of_freedom =
        Barycentre<ToFrame, GravitationalParameter>(
            {last_primary_degrees_of_freedom,
             last_secondary_degrees_of_freedom},
            {to_primary_trajectory.body<MassiveBody>().
                 gravitational_parameter(),
             to_secondary_trajectory.body<MassiveBody>().
                 gravitational_parameter()});
    Rotation<ToFrame, ThroughFrame>
        from_basis_of_last_barycentric_frame_to_standard_basis;
    Bivector<AngularFrequency, ToFrame> angular_frequency;
    FromBasisOfBarycentricFrameToStandardBasis(
        last_barycentre_degrees_of_freedom,
        last_primary_degrees_of_freedom,
        last_secondary_degrees_of_freedom,
        &from_basis_of_last_barycentric_frame_to_standard_basis,
        &angular_frequency);
    Rotation<ThroughFrame, ToFrame> const
        from_standard_basis_to_basis_of_last_barycentric_frame =
            from_basis_of_last_barycentric_frame_to_standard_basis.Inverse();
    AffineMap<ThroughFrame, ToFrame, Length, Rotation> position_map(
        ThroughFrame::origin,
        last_barycentre_degrees_of_freedom.position,
        from_standard_basis_to_basis_of_last_barycentric_frame);
    // TODO(phl): There should be an affine map here too, once we have properly
    // 'framed' the matrix.
    Velocity<ToFrame> const velocity_in_last_barycentric_basis =
        from_standard_basis_to_basis_of_last_barycentric_frame(
            through_degrees_of_freedom.velocity);
    return {position_map(through_degrees_of_freedom.position),
            velocity_in_last_barycentric_basis};
  };

  return transforms;
}

template<typename FromFrame, typename ThroughFrame, typename ToFrame>
typename Trajectory<FromFrame>::template TransformingIterator<ThroughFrame>
Transforms<FromFrame, ThroughFrame, ToFrame>::first(
    Trajectory<FromFrame> const* from_trajectory) {
  return CHECK_NOTNULL(from_trajectory)->first_with_transform(first_);
}

template<typename FromFrame, typename ThroughFrame, typename ToFrame>
typename Trajectory<ThroughFrame>::template TransformingIterator<ToFrame>
Transforms<FromFrame, ThroughFrame, ToFrame>::second(
    Trajectory<ThroughFrame> const* through_trajectory) {
  return CHECK_NOTNULL(through_trajectory)->
             first_with_transform(second_);
}

}  // namespace physics
}  // namespace principia
<commit_msg>Velocity map.<commit_after>#pragma once

#include "physics/transforms.hpp"

#include "geometry/affine_map.hpp"
#include "geometry/grassmann.hpp"
#include "geometry/identity.hpp"
#include "geometry/named_quantities.hpp"
#include "geometry/permutation.hpp"
#include "geometry/r3x3_matrix.hpp"
#include "geometry/rotation.hpp"
#include "glog/logging.h"
#include "physics/massive_body.hpp"
#include "quantities/named_quantities.hpp"
#include "quantities/si.hpp"

using principia::geometry::AffineMap;
using principia::geometry::Bivector;
using principia::geometry::Displacement;
using principia::geometry::Identity;
using principia::geometry::Permutation;
using principia::geometry::Position;
using principia::geometry::R3x3Matrix;
using principia::geometry::Rotation;
using principia::geometry::Wedge;
using principia::quantities::AngularFrequency;
using principia::si::Radian;

namespace principia {
namespace physics {

namespace {

//TODO(phl):Fix
// Fills |*matrix| with the rotation matrix that maps the standard basis to the
// basis of the barycentric frame.  Fills |*angular_frequency| with the
// corresponding angular velocity.  These pointers must be nonnul, and there is
// no transfer of ownership.  |barycentre_degrees_of_freedom| must be a convex
// combination of the two other degrees of freedom.
// TODO(phl): All of this should be strongly typed.  It's awfully confusing as
// it stands.  In particular, the sign of the bivector may or may not be
// correct.
template<typename FromFrame, typename ToFrame>
void FromBasisOfBarycentricFrameToStandardBasis(
    DegreesOfFreedom<FromFrame> const& barycentre_degrees_of_freedom,
    DegreesOfFreedom<FromFrame> const& primary_degrees_of_freedom,
    DegreesOfFreedom<FromFrame> const& secondary_degrees_of_freedom,
    Rotation<FromFrame, ToFrame>* rotation,
    Bivector<AngularFrequency, FromFrame>* angular_frequency) {
  CHECK_NOTNULL(rotation);
  CHECK_NOTNULL(angular_frequency);
  Displacement<FromFrame> const reference_direction =
      primary_degrees_of_freedom.position -
      barycentre_degrees_of_freedom.position;
  Vector<double, FromFrame> const normalized_reference_direction =
      Normalize(reference_direction);
  Velocity<FromFrame> const reference_coplanar =
      primary_degrees_of_freedom.velocity -
      barycentre_degrees_of_freedom.velocity;
  // Modified Gram-Schmidt.
  Velocity<FromFrame> const reference_normal =
      reference_coplanar -
      InnerProduct(reference_coplanar, normalized_reference_direction) *
          normalized_reference_direction;
  Vector<double, FromFrame> const normalized_reference_normal =
      Normalize(reference_normal);
  // TODO(egg): should we normalize this?
  Bivector<double, FromFrame> const normalized_reference_binormal =
      Wedge(normalized_reference_direction, normalized_reference_normal);
  *rotation = Rotation<FromFrame, ToFrame>(
                  R3x3Matrix(normalized_reference_direction.coordinates(),
                             normalized_reference_normal.coordinates(),
                             normalized_reference_binormal.coordinates()));
  *angular_frequency =
      (Radian * reference_normal.Norm() / reference_direction.Norm()) *
          normalized_reference_binormal;
}

}  // namespace

template<typename FromFrame, typename ThroughFrame, typename ToFrame>
std::unique_ptr<Transforms<FromFrame, ThroughFrame, ToFrame>>
Transforms<FromFrame, ThroughFrame, ToFrame>::BodyCentredNonRotating(
    Trajectory<FromFrame> const& from_centre_trajectory,
    Trajectory<ToFrame> const& to_centre_trajectory) {
  std::unique_ptr<Transforms> transforms(new Transforms);

  // From the perspective of the lambda the following variable is really |this|,
  // hence the name.
  Transforms* that = transforms.get();
  transforms->first_ =
      [&from_centre_trajectory, that](
          Instant const& t,
          DegreesOfFreedom<FromFrame> const& from_degrees_of_freedom,
          Trajectory<FromFrame> const* trajectory) ->
      DegreesOfFreedom<ThroughFrame> {
    // First check if the result is cached.
    auto cache_it = that->first_cache_.find(std::make_pair(trajectory, t));
    if (cache_it != that->first_cache_.end()) {
      return cache_it->second;
    }

    // on_or_after() is Ln(N), but it doesn't matter unless the map gets very
    // big, in which case we'll have cache misses anyway.
    Trajectory<FromFrame>::NativeIterator const centre_it =
        from_centre_trajectory.on_or_after(t);
    CHECK_EQ(centre_it.time(), t)
        << "Time " << t << " not in centre trajectory";
    DegreesOfFreedom<FromFrame> const& centre_degrees_of_freedom =
        centre_it.degrees_of_freedom();

    AffineMap<FromFrame, ThroughFrame, Length, Identity> const position_map(
        centre_degrees_of_freedom.position,
        ThroughFrame::origin,
        Identity<FromFrame, ThroughFrame>());
    // TODO(phl): Should |velocity_map| be an affine map?
    Identity<FromFrame, ThroughFrame> const velocity_map;
    DegreesOfFreedom<ThroughFrame> through_degrees_of_freedom =
        {position_map(from_degrees_of_freedom.position),
         velocity_map(from_degrees_of_freedom.velocity -
                      centre_degrees_of_freedom.velocity)};

    // Cache the result before returning it.
    that->first_cache_.emplace(std::make_pair(trajectory, t),
                               through_degrees_of_freedom);
    return std::move(through_degrees_of_freedom);
  };

  transforms->second_ =
      [&to_centre_trajectory](
          Instant const& t,
          DegreesOfFreedom<ThroughFrame> const& through_degrees_of_freedom,
          Trajectory<ThroughFrame> const* trajectory) ->
      DegreesOfFreedom<ToFrame> {
    DegreesOfFreedom<ToFrame> const& last_centre_degrees_of_freedom =
        to_centre_trajectory.last().degrees_of_freedom();

    AffineMap<ThroughFrame, ToFrame, Length, Identity> const position_map(
        ThroughFrame::origin,
        last_centre_degrees_of_freedom.position,
        Identity<ThroughFrame, ToFrame>());
    Identity<ThroughFrame, ToFrame> const velocity_map;
    return {position_map(through_degrees_of_freedom.position),
            velocity_map(through_degrees_of_freedom.velocity)};
  };

  return transforms;
}

template<typename FromFrame, typename ThroughFrame, typename ToFrame>
std::unique_ptr<Transforms<FromFrame, ThroughFrame, ToFrame>>
Transforms<FromFrame, ThroughFrame, ToFrame>::BarycentricRotating(
      Trajectory<FromFrame> const& from_primary_trajectory,
      Trajectory<ToFrame> const& to_primary_trajectory,
      Trajectory<FromFrame> const& from_secondary_trajectory,
      Trajectory<ToFrame> const& to_secondary_trajectory) {
  std::unique_ptr<Transforms> transforms(new Transforms);

  // From the perspective of the lambda the following variable is really |this|,
  // hence the name.
  Transforms* that = transforms.get();
  transforms->first_ =
      [&from_primary_trajectory, &from_secondary_trajectory, that](
          Instant const& t,
          DegreesOfFreedom<FromFrame> const& from_degrees_of_freedom,
          Trajectory<FromFrame> const* trajectory) ->
      DegreesOfFreedom<ThroughFrame> {
    // First check if the result is cached.
    auto cache_it = that->first_cache_.find(std::make_pair(trajectory, t));
    if (cache_it != that->first_cache_.end()) {
      return cache_it->second;
    }

    // on_or_after() is Ln(N).
    Trajectory<FromFrame>::NativeIterator const primary_it =
        from_primary_trajectory.on_or_after(t);
    CHECK_EQ(primary_it.time(), t)
        << "Time " << t << " not in primary trajectory";
    Trajectory<FromFrame>::NativeIterator secondary_it =
        from_secondary_trajectory.on_or_after(t);
    CHECK_EQ(secondary_it.time(), t)
        << "Time " << t << " not in secondary trajectory";

    DegreesOfFreedom<FromFrame> const& primary_degrees_of_freedom =
        primary_it.degrees_of_freedom();
    DegreesOfFreedom<FromFrame> const& secondary_degrees_of_freedom =
        secondary_it.degrees_of_freedom();
    DegreesOfFreedom<FromFrame> const barycentre_degrees_of_freedom =
        Barycentre<FromFrame, GravitationalParameter>(
            {primary_degrees_of_freedom,
             secondary_degrees_of_freedom},
            {from_primary_trajectory.body<MassiveBody>().
                 gravitational_parameter(),
             from_secondary_trajectory.body<MassiveBody>().
                 gravitational_parameter()});
    Rotation<FromFrame, ThroughFrame>
        from_basis_of_barycentric_frame_to_standard_basis;
    Bivector<AngularFrequency, FromFrame> angular_frequency;
    FromBasisOfBarycentricFrameToStandardBasis(
        barycentre_degrees_of_freedom,
        primary_degrees_of_freedom,
        secondary_degrees_of_freedom,
        &from_basis_of_barycentric_frame_to_standard_basis,
        &angular_frequency);

    AffineMap<FromFrame, ThroughFrame, Length, Rotation> const position_map(
        barycentre_degrees_of_freedom.position,
        ThroughFrame::origin,
        from_basis_of_barycentric_frame_to_standard_basis);
    // TODO(phl): This is where we wonder if |velocity_map| should be an affine
    // map.  Also the filioque.
    Rotation<FromFrame, ThroughFrame> const& velocity_map =
        from_basis_of_barycentric_frame_to_standard_basis;
    DegreesOfFreedom<ThroughFrame> through_degrees_of_freedom =
        {position_map(from_degrees_of_freedom.position),
         velocity_map(from_degrees_of_freedom.velocity -
                      barycentre_degrees_of_freedom.velocity -
                        angular_frequency *
                          (from_degrees_of_freedom.position -
                           barycentre_degrees_of_freedom.position) / Radian)};

    // Cache the result before returning it.
    that->first_cache_.emplace(std::make_pair(trajectory, t),
                               through_degrees_of_freedom);
    return std::move(through_degrees_of_freedom);
  };

  transforms->second_ =
      [&to_primary_trajectory, &to_secondary_trajectory](
          Instant const& t,
          DegreesOfFreedom<ThroughFrame> const& through_degrees_of_freedom,
          Trajectory<ThroughFrame> const* trajectory) ->
      DegreesOfFreedom<ToFrame> {
    DegreesOfFreedom<ToFrame> const& last_primary_degrees_of_freedom =
        to_primary_trajectory.last().degrees_of_freedom();
    DegreesOfFreedom<ToFrame> const& last_secondary_degrees_of_freedom =
        to_secondary_trajectory.last().degrees_of_freedom();
    DegreesOfFreedom<ToFrame> const last_barycentre_degrees_of_freedom =
        Barycentre<ToFrame, GravitationalParameter>(
            {last_primary_degrees_of_freedom,
             last_secondary_degrees_of_freedom},
            {to_primary_trajectory.body<MassiveBody>().
                 gravitational_parameter(),
             to_secondary_trajectory.body<MassiveBody>().
                 gravitational_parameter()});
    Rotation<ToFrame, ThroughFrame>
        from_basis_of_last_barycentric_frame_to_standard_basis;
    Bivector<AngularFrequency, ToFrame> angular_frequency;
    FromBasisOfBarycentricFrameToStandardBasis(
        last_barycentre_degrees_of_freedom,
        last_primary_degrees_of_freedom,
        last_secondary_degrees_of_freedom,
        &from_basis_of_last_barycentric_frame_to_standard_basis,
        &angular_frequency);
    Rotation<ThroughFrame, ToFrame> const
        from_standard_basis_to_basis_of_last_barycentric_frame =
            from_basis_of_last_barycentric_frame_to_standard_basis.Inverse();

    AffineMap<ThroughFrame, ToFrame, Length, Rotation> const position_map(
        ThroughFrame::origin,
        last_barycentre_degrees_of_freedom.position,
        from_standard_basis_to_basis_of_last_barycentric_frame);
    Rotation<ThroughFrame, ToFrame> const& velocity_map =
        from_standard_basis_to_basis_of_last_barycentric_frame;
    return {position_map(through_degrees_of_freedom.position),
            velocity_map(through_degrees_of_freedom.velocity)};
  };

  return transforms;
}

template<typename FromFrame, typename ThroughFrame, typename ToFrame>
typename Trajectory<FromFrame>::template TransformingIterator<ThroughFrame>
Transforms<FromFrame, ThroughFrame, ToFrame>::first(
    Trajectory<FromFrame> const* from_trajectory) {
  return CHECK_NOTNULL(from_trajectory)->first_with_transform(first_);
}

template<typename FromFrame, typename ThroughFrame, typename ToFrame>
typename Trajectory<ThroughFrame>::template TransformingIterator<ToFrame>
Transforms<FromFrame, ThroughFrame, ToFrame>::second(
    Trajectory<ThroughFrame> const* through_trajectory) {
  return CHECK_NOTNULL(through_trajectory)->
             first_with_transform(second_);
}

}  // namespace physics
}  // namespace principia
<|endoftext|>


<commit_before>// @(#)root/base:$Name$:$Id$
// Author: Christian Bormann  13/10/97

/*************************************************************************
 * Copyright (C) 1995-2000, Rene Brun and Fons Rademakers.               *
 * All rights reserved.                                                  *
 *                                                                       *
 * For the licensing terms see $ROOTSYS/LICENSE.                         *
 * For the list of contributors see $ROOTSYS/README/CREDITS.             *
 *************************************************************************/

//////////////////////////////////////////////////////////////////////////
//                                                                      //
// TSystemDirectory                                                     //
//                                                                      //
// Describes an Operating System directory for the browser.             //
//                                                                      //
// Author: Christian Bormann  30/09/97                                  //
//         http://www.ikf.physik.uni-frankfurt.de/~bormann/             //
//                                                                      //
//////////////////////////////////////////////////////////////////////////

#include "TSystemDirectory.h"
#include "TSystem.h"
#include "TBrowser.h"
#include "TOrdCollection.h"

ClassImp(TSystemDirectory)

//______________________________________________________________________________
TSystemDirectory::TSystemDirectory()
{
   // Create a system directory object.

   fDirsInBrowser  = 0;
   fFilesInBrowser = 0;
}

//______________________________________________________________________________
TSystemDirectory::TSystemDirectory(const char *dirname, const char *path) :
   TSystemFile(dirname, path)
{
   // Create a system directory object.

   fDirsInBrowser  = 0;
   fFilesInBrowser = 0;
}

//______________________________________________________________________________
TSystemDirectory::~TSystemDirectory()
{
   // Delete system directory object.

   delete fDirsInBrowser;
   delete fFilesInBrowser;
}

//______________________________________________________________________________
void TSystemDirectory::SetDirectory(const char *name)
{
   // Create a system directory object.

   SetName(name);
   SetTitle(name);
}

//______________________________________________________________________________
Bool_t TSystemDirectory::IsDirectory(const char* name)
{
   // Check if name is a directory.

   Long_t id, size, flags, modtime;
   const char *dirfile = GetTitle();

   gSystem->ChangeDirectory(dirfile);
   flags = id = size = modtime = 0;
   gSystem->GetPathInfo(name, &id, &size, &flags, &modtime);
   Int_t isdir = (Int_t)flags & 2;

   // this is a directory
   if (isdir) return kTRUE;
   return kFALSE;
}

//______________________________________________________________________________
void TSystemDirectory::Browse(TBrowser *b)
{
   // Browse OS system directories.

   // Collections to keep track of all browser objects that have been generated.
   // It's main goal is to prevent the contineous allocations of new
   // objects with the same names during browsing.
   if (!fDirsInBrowser)  fDirsInBrowser  = new TOrdCollection;
   if (!fFilesInBrowser) fFilesInBrowser = new TOrdCollection(10);

   const char *name = GetTitle();
   TSystemFile *sfile;
   TSystemDirectory *sdir;
   const char *file;

   gSystem->ChangeDirectory(name);

#ifdef WIN32
//      gSystem->Exec("explorer .");
#endif

   void *dir = gSystem->OpenDirectory(name);

   if (dir) {
      while ((file = gSystem->GetDirEntry(dir))) {
         if (!strcmp(file,".") || !strcmp(file,"..")) continue;
         if (IsDirectory(file)) {
            TString sdirname(name);
            sdirname = sdirname + "/";
            sdirname = sdirname + file;

            if ((sdir = FindDirObj(sdirname.Data())) == 0) {
               sdir = new TSystemDirectory(file, sdirname.Data());
               fDirsInBrowser->Add(sdir);
            }
            b->Add(sdir, file);
         } else {
            if ((sfile = FindFileObj(file, gSystem->WorkingDirectory())) == 0) {
               sfile = new TSystemFile(file, gSystem->WorkingDirectory());
               fFilesInBrowser->Add(sfile);
            }
            b->Add(sfile, file);
         }
      }
      gSystem->FreeDirectory(dir);
      return;
   }
}

//______________________________________________________________________________
TSystemDirectory *TSystemDirectory::FindDirObj(const char *name)
{
   // Static function that returns system directory object if it
   // exists in list, 0 otherwise.

   int size = fDirsInBrowser->GetSize();
   for (int i = 0; i < size; i++) {
      TSystemDirectory *obj = (TSystemDirectory *) fDirsInBrowser->At(i);
      if (!strcmp(name, obj->GetTitle()))
         return obj;
   }
   return 0;
}

//______________________________________________________________________________
TSystemFile *TSystemDirectory::FindFileObj(const char *name, const char *dir)
{
   // Static function that returns system file object if it exists in
   // list, 0 otherwise.

   int size = fFilesInBrowser->GetSize();
   for (int i = 0; i < size; i++) {
      TSystemFile *obj = (TSystemFile *) fFilesInBrowser->At(i);
      if (!strcmp(name, obj->GetName()) && !strcmp(dir, obj->GetTitle()))
         return obj;
   }
   return 0;
}
<commit_msg>correction in some comments.<commit_after>// @(#)root/base:$Name:  $:$Id: TSystemDirectory.cxx,v 1.1.1.1 2000/05/16 17:00:39 rdm Exp $
// Author: Christian Bormann  13/10/97

/*************************************************************************
 * Copyright (C) 1995-2000, Rene Brun and Fons Rademakers.               *
 * All rights reserved.                                                  *
 *                                                                       *
 * For the licensing terms see $ROOTSYS/LICENSE.                         *
 * For the list of contributors see $ROOTSYS/README/CREDITS.             *
 *************************************************************************/

//////////////////////////////////////////////////////////////////////////
//                                                                      //
// TSystemDirectory                                                     //
//                                                                      //
// Describes an Operating System directory for the browser.             //
//                                                                      //
// Author: Christian Bormann  30/09/97                                  //
//         http://www.ikf.physik.uni-frankfurt.de/~bormann/             //
//                                                                      //
//////////////////////////////////////////////////////////////////////////

#include "TSystemDirectory.h"
#include "TSystem.h"
#include "TBrowser.h"
#include "TOrdCollection.h"

ClassImp(TSystemDirectory)

//______________________________________________________________________________
TSystemDirectory::TSystemDirectory()
{
   // Create a system directory object.

   fDirsInBrowser  = 0;
   fFilesInBrowser = 0;
}

//______________________________________________________________________________
TSystemDirectory::TSystemDirectory(const char *dirname, const char *path) :
   TSystemFile(dirname, path)
{
   // Create a system directory object.

   fDirsInBrowser  = 0;
   fFilesInBrowser = 0;
}

//______________________________________________________________________________
TSystemDirectory::~TSystemDirectory()
{
   // Delete system directory object.

   delete fDirsInBrowser;
   delete fFilesInBrowser;
}

//______________________________________________________________________________
void TSystemDirectory::SetDirectory(const char *name)
{
   // Create a system directory object.

   SetName(name);
   SetTitle(name);
}

//______________________________________________________________________________
Bool_t TSystemDirectory::IsDirectory(const char* name)
{
   // Check if name is a directory.

   Long_t id, size, flags, modtime;
   const char *dirfile = GetTitle();

   gSystem->ChangeDirectory(dirfile);
   flags = id = size = modtime = 0;
   gSystem->GetPathInfo(name, &id, &size, &flags, &modtime);
   Int_t isdir = (Int_t)flags & 2;

   // this is a directory
   if (isdir) return kTRUE;
   return kFALSE;
}

//______________________________________________________________________________
void TSystemDirectory::Browse(TBrowser *b)
{
   // Browse OS system directories.

   // Collections to keep track of all browser objects that have been generated.
   // It's main goal is to prevent the contineous allocations of new
   // objects with the same names during browsing.
   if (!fDirsInBrowser)  fDirsInBrowser  = new TOrdCollection;
   if (!fFilesInBrowser) fFilesInBrowser = new TOrdCollection(10);

   const char *name = GetTitle();
   TSystemFile *sfile;
   TSystemDirectory *sdir;
   const char *file;

   gSystem->ChangeDirectory(name);

#ifdef WIN32
//      gSystem->Exec("explorer .");
#endif

   void *dir = gSystem->OpenDirectory(name);

   if (dir) {
      while ((file = gSystem->GetDirEntry(dir))) {
         if (!strcmp(file,".") || !strcmp(file,"..")) continue;
         if (IsDirectory(file)) {
            TString sdirname(name);
            sdirname = sdirname + "/";
            sdirname = sdirname + file;

            if ((sdir = FindDirObj(sdirname.Data())) == 0) {
               sdir = new TSystemDirectory(file, sdirname.Data());
               fDirsInBrowser->Add(sdir);
            }
            b->Add(sdir, file);
         } else {
            if ((sfile = FindFileObj(file, gSystem->WorkingDirectory())) == 0) {
               sfile = new TSystemFile(file, gSystem->WorkingDirectory());
               fFilesInBrowser->Add(sfile);
            }
            b->Add(sfile, file);
         }
      }
      gSystem->FreeDirectory(dir);
      return;
   }
}

//______________________________________________________________________________
TSystemDirectory *TSystemDirectory::FindDirObj(const char *name)
{
   // Method that returns system directory object if it
   // exists in list, 0 otherwise.

   int size = fDirsInBrowser->GetSize();
   for (int i = 0; i < size; i++) {
      TSystemDirectory *obj = (TSystemDirectory *) fDirsInBrowser->At(i);
      if (!strcmp(name, obj->GetTitle()))
         return obj;
   }
   return 0;
}

//______________________________________________________________________________
TSystemFile *TSystemDirectory::FindFileObj(const char *name, const char *dir)
{
   // Method that returns system file object if it exists in
   // list, 0 otherwise.

   int size = fFilesInBrowser->GetSize();
   for (int i = 0; i < size; i++) {
      TSystemFile *obj = (TSystemFile *) fFilesInBrowser->At(i);
      if (!strcmp(name, obj->GetName()) && !strcmp(dir, obj->GetTitle()))
         return obj;
   }
   return 0;
}
<|endoftext|>


<commit_before>#include"FrameTable.h"
#include<iostream>
using namespace std;
FrameTable::FrameTable()
{
	init(MEMORYSIZE);
}

FrameTable::FrameTable(long long _length)
{
	init(_length);
}

void FrameTable::init(long long _length)
{
	FrameTable::length = _length;
	Table = new ISVALID[_length];
	for (int i = 0; i< _length; i++)
		FrameTable::Table[i] = VALID;
	FrameTable::ValCount = length;
}

ISVALID FrameTable::isThisAvaid(long long index)
{
	return FrameTable::Table[index];
}

void FrameTable::SetThisValid(long long index)
{
	if (Table[index] != VALID)
	{
		Table[index] = VALID;
		ValCount++;
	}
}

void FrameTable::SetThisInvalid(long long index)
{
	if (Table[index] != INVALID)
	{
		Table[index] = INVALID;
		ValCount--;
	}
}

long long FrameTable::FindValframe()
{
	if (ValCount >0)
	for (int i = 0; i < length; i++)
	{
		if (Table[i] == VALID)
			return i;
	}
	else
		throw 1;
	return -1;
}

void FrameTable::FreeMemory(PageTable &pt)
{
	for (int i = 0; i<pt.GetSize(); i++)
	{
		FrameTable::SetThisValid(pt.GetFrame(i));
	}

}

void FrameTable::AllocMemory(PageTable &pt, long long pn, list<long long> &record, TLB &tlb)
{
	try
	{

			pt.SetFrame(pn, FrameTable::FindValframe());
			tlb.insert(pn, FrameTable::FindValframe());
			FrameTable::FrameList.push_back(FrameTable::FindValframe());
			SetThisInvalid(FrameTable::FindValframe());

	}
	catch (int)
	{
		long long FrameNum = *FrameList.begin();
		FrameTable::FrameList.pop_front();
		pt.SetFrame(pn, FrameNum);
		tlb.insert(pn, FrameNum);
		FrameTable::FrameList.push_back(FrameNum);
		record.push_back(FrameNum);
	}
}

void FrameTable::updateList(long long FrameNum){
	FrameList.remove(FrameNum);
	FrameList.push_back(FrameNum);
}<commit_msg>Delete FrameTable.cpp<commit_after><|endoftext|>