<commit_before>//===-- Timer.cpp - Interval Timing Support -------------------------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file was developed by the LLVM research group and is distributed under
// the University of Illinois Open Source License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// Interval Timing implementation.
//
//===----------------------------------------------------------------------===//

#include "llvm/Support/Timer.h"
#include "llvm/Support/CommandLine.h"
#include <algorithm>
#include <iostream>
#include <functional>
#include <fstream>
#include <map>
#include "llvm/Config/sys/resource.h"
#include "llvm/Config/sys/time.h"
#include "llvm/Config/unistd.h"
#include "llvm/Config/malloc.h"
#include "llvm/Config/windows.h"
using namespace llvm;

// GetLibSupportInfoOutputFile - Return a file stream to print our output on.
namespace llvm { extern std::ostream *GetLibSupportInfoOutputFile(); }

// getLibSupportInfoOutputFilename - This ugly hack is brought to you courtesy
// of constructor/destructor ordering being unspecified by C++.  Basically the
// problem is that a Statistic<> object gets destroyed, which ends up calling
// 'GetLibSupportInfoOutputFile()' (below), which calls this function.
// LibSupportInfoOutputFilename used to be a global variable, but sometimes it
// would get destroyed before the Statistic, causing havoc to ensue.  We "fix"
// this by creating the string the first time it is needed and never destroying
// it.
static std::string &getLibSupportInfoOutputFilename() {
  static std::string *LibSupportInfoOutputFilename = new std::string();
  return *LibSupportInfoOutputFilename;
}

namespace {
#ifdef HAVE_MALLINFO
  cl::opt<bool>
  TrackSpace("track-memory", cl::desc("Enable -time-passes memory "
                                      "tracking (this may be slow)"),
             cl::Hidden);
#endif

  cl::opt<std::string, true>
  InfoOutputFilename("info-output-file", cl::value_desc("filename"),
                     cl::desc("File to append -stats and -timer output to"),
                   cl::Hidden, cl::location(getLibSupportInfoOutputFilename()));
}

static TimerGroup *DefaultTimerGroup = 0;
static TimerGroup *getDefaultTimerGroup() {
  if (DefaultTimerGroup) return DefaultTimerGroup;
  return DefaultTimerGroup = new TimerGroup("Miscellaneous Ungrouped Timers");
}

Timer::Timer(const std::string &N)
  : Elapsed(0), UserTime(0), SystemTime(0), MemUsed(0), PeakMem(0), Name(N),
    Started(false), TG(getDefaultTimerGroup()) {
  TG->addTimer();
}

Timer::Timer(const std::string &N, TimerGroup &tg)
  : Elapsed(0), UserTime(0), SystemTime(0), MemUsed(0), PeakMem(0), Name(N),
    Started(false), TG(&tg) {
  TG->addTimer();
}

Timer::Timer(const Timer &T) {
  TG = T.TG;
  if (TG) TG->addTimer();
  operator=(T);
}

// Copy ctor, initialize with no TG member.
Timer::Timer(bool, const Timer &T) {
  TG = T.TG;     // Avoid assertion in operator=
  operator=(T);  // Copy contents
  TG = 0;
}

Timer::~Timer() {
  if (TG) {
    if (Started) {
      Started = false;
      TG->addTimerToPrint(*this);
    }
    TG->removeTimer();
  }
}

static long getMemUsage() {
#ifdef HAVE_MALLINFO
  if (TrackSpace) {
    struct mallinfo MI = mallinfo();
    return MI.uordblks/*+MI.hblkhd*/;
  }
#endif
  return 0;
}

struct TimeRecord {
  double Elapsed, UserTime, SystemTime;
  long MemUsed;
};

static TimeRecord getTimeRecord(bool Start) {
#if defined(HAVE_WINDOWS_H)
  unsigned __int64 ProcCreate, ProcExit, KernelTime, UserTime, CurTime;

  GetProcessTimes(GetCurrentProcess(), (FILETIME*)&ProcCreate,
                  (FILETIME*)&ProcExit, (FILETIME*)&KernelTime,
                  (FILETIME*)&UserTime);
  GetSystemTimeAsFileTime((FILETIME*)&CurTime);

  // FILETIME's are # of 100 nanosecond ticks.
  double ScaleFactor = 1.0/(10*1000*1000);

  TimeRecord Result;
  Result.Elapsed    = (CurTime-ProcCreate)*ScaleFactor;  // Wall time
  Result.UserTime   = UserTime*ScaleFactor;
  Result.SystemTime = KernelTime*ScaleFactor;
  return Result;
#elif defined(HAVE_GETRUSAGE)
  struct rusage RU;
  struct timeval T;
  long MemUsed = 0;
  if (Start) {
    MemUsed = getMemUsage();
    if (getrusage(RUSAGE_SELF, &RU))
      perror("getrusage call failed: -time-passes info incorrect!");
  }
  gettimeofday(&T, 0);

  if (!Start) {
    if (getrusage(RUSAGE_SELF, &RU))
      perror("getrusage call failed: -time-passes info incorrect!");
    MemUsed = getMemUsage();
  }

  TimeRecord Result;
  Result.Elapsed    =           T.tv_sec +           T.tv_usec/1000000.0;
  Result.UserTime   = RU.ru_utime.tv_sec + RU.ru_utime.tv_usec/1000000.0;
  Result.SystemTime = RU.ru_stime.tv_sec + RU.ru_stime.tv_usec/1000000.0;
  Result.MemUsed = MemUsed;
  return Result;
#else
  // Can't get resource usage.
  return TimeRecord();
#endif
}

static std::vector<Timer*> ActiveTimers;

void Timer::startTimer() {
  Started = true;
  TimeRecord TR = getTimeRecord(true);
  Elapsed    -= TR.Elapsed;
  UserTime   -= TR.UserTime;
  SystemTime -= TR.SystemTime;
  MemUsed    -= TR.MemUsed;
  PeakMemBase = TR.MemUsed;
  ActiveTimers.push_back(this);
}

void Timer::stopTimer() {
  TimeRecord TR = getTimeRecord(false);
  Elapsed    += TR.Elapsed;
  UserTime   += TR.UserTime;
  SystemTime += TR.SystemTime;
  MemUsed    += TR.MemUsed;

  if (ActiveTimers.back() == this) {
    ActiveTimers.pop_back();
  } else {
    std::vector<Timer*>::iterator I =
      std::find(ActiveTimers.begin(), ActiveTimers.end(), this);
    assert(I != ActiveTimers.end() && "stop but no startTimer?");
    ActiveTimers.erase(I);
  }
}

void Timer::sum(const Timer &T) {
  Elapsed    += T.Elapsed;
  UserTime   += T.UserTime;
  SystemTime += T.SystemTime;
  MemUsed    += T.MemUsed;
  PeakMem    += T.PeakMem;
}

/// addPeakMemoryMeasurement - This method should be called whenever memory
/// usage needs to be checked.  It adds a peak memory measurement to the
/// currently active timers, which will be printed when the timer group prints
///
void Timer::addPeakMemoryMeasurement() {
  long MemUsed = getMemUsage();

  for (std::vector<Timer*>::iterator I = ActiveTimers.begin(),
         E = ActiveTimers.end(); I != E; ++I)
    (*I)->PeakMem = std::max((*I)->PeakMem, MemUsed-(*I)->PeakMemBase);
}

//===----------------------------------------------------------------------===//
//   NamedRegionTimer Implementation
//===----------------------------------------------------------------------===//

static Timer &getNamedRegionTimer(const std::string &Name) {
  static std::map<std::string, Timer> NamedTimers;

  std::map<std::string, Timer>::iterator I = NamedTimers.lower_bound(Name);
  if (I != NamedTimers.end() && I->first == Name)
    return I->second;

  return NamedTimers.insert(I, std::make_pair(Name, Timer(Name)))->second;
}

NamedRegionTimer::NamedRegionTimer(const std::string &Name)
  : TimeRegion(getNamedRegionTimer(Name)) {}

//===----------------------------------------------------------------------===//
//   TimerGroup Implementation
//===----------------------------------------------------------------------===//

// printAlignedFP - Simulate the printf "%A.Bf" format, where A is the
// TotalWidth size, and B is the AfterDec size.
//
static void printAlignedFP(double Val, unsigned AfterDec, unsigned TotalWidth,
                           std::ostream &OS) {
  assert(TotalWidth >= AfterDec+1 && "Bad FP Format!");
  OS.width(TotalWidth-AfterDec-1);
  char OldFill = OS.fill();
  OS.fill(' ');
  OS << (int)Val;  // Integer part;
  OS << ".";
  OS.width(AfterDec);
  OS.fill('0');
  unsigned ResultFieldSize = 1;
  while (AfterDec--) ResultFieldSize *= 10;
  OS << (int)(Val*ResultFieldSize) % ResultFieldSize;
  OS.fill(OldFill);
}

static void printVal(double Val, double Total, std::ostream &OS) {
  if (Total < 1e-7)   // Avoid dividing by zero...
    OS << "        -----     ";
  else {
    OS << "  ";
    printAlignedFP(Val, 4, 7, OS);
    OS << " (";
    printAlignedFP(Val*100/Total, 1, 5, OS);
    OS << "%)";
  }
}

void Timer::print(const Timer &Total, std::ostream &OS) {
  if (Total.UserTime)
    printVal(UserTime, Total.UserTime, OS);
  if (Total.SystemTime)
    printVal(SystemTime, Total.SystemTime, OS);
  if (Total.getProcessTime())
    printVal(getProcessTime(), Total.getProcessTime(), OS);
  printVal(Elapsed, Total.Elapsed, OS);

  OS << "  ";

  if (Total.MemUsed) {
    OS.width(9);
    OS << MemUsed << "  ";
  }
  if (Total.PeakMem) {
    if (PeakMem) {
      OS.width(9);
      OS << PeakMem << "  ";
    } else
      OS << "           ";
  }
  OS << Name << "\n";

  Started = false;  // Once printed, don't print again
}

// GetLibSupportInfoOutputFile - Return a file stream to print our output on...
std::ostream *
llvm::GetLibSupportInfoOutputFile() {
  std::string &LibSupportInfoOutputFilename = getLibSupportInfoOutputFilename();
  if (LibSupportInfoOutputFilename.empty())
    return &std::cerr;
  if (LibSupportInfoOutputFilename == "-")
    return &std::cout;

  std::ostream *Result = new std::ofstream(LibSupportInfoOutputFilename.c_str(),
                                           std::ios::app);
  if (!Result->good()) {
    std::cerr << "Error opening info-output-file '"
              << LibSupportInfoOutputFilename << " for appending!\n";
    delete Result;
    return &std::cerr;
  }
  return Result;
}

void TimerGroup::removeTimer() {
  if (--NumTimers == 0 && !TimersToPrint.empty()) { // Print timing report...
    // Sort the timers in descending order by amount of time taken...
    std::sort(TimersToPrint.begin(), TimersToPrint.end(),
              std::greater<Timer>());

    // Figure out how many spaces to indent TimerGroup name...
    unsigned Padding = (80-Name.length())/2;
    if (Padding > 80) Padding = 0;         // Don't allow "negative" numbers

    std::ostream *OutStream = GetLibSupportInfoOutputFile();

    ++NumTimers;
    {  // Scope to contain Total timer... don't allow total timer to drop us to
       // zero timers...
      Timer Total("TOTAL");

      for (unsigned i = 0, e = TimersToPrint.size(); i != e; ++i)
        Total.sum(TimersToPrint[i]);

      // Print out timing header...
      *OutStream << "===" << std::string(73, '-') << "===\n"
                 << std::string(Padding, ' ') << Name << "\n"
                 << "===" << std::string(73, '-')
                 << "===\n  Total Execution Time: ";

      printAlignedFP(Total.getProcessTime(), 4, 5, *OutStream);
      *OutStream << " seconds (";
      printAlignedFP(Total.getWallTime(), 4, 5, *OutStream);
      *OutStream << " wall clock)\n\n";

      if (Total.UserTime)
        *OutStream << "   ---User Time---";
      if (Total.SystemTime)
        *OutStream << "   --System Time--";
      if (Total.getProcessTime())
        *OutStream << "   --User+System--";
      *OutStream << "   ---Wall Time---";
      if (Total.getMemUsed())
        *OutStream << "  ---Mem---";
      if (Total.getPeakMem())
        *OutStream << "  -PeakMem-";
      *OutStream << "  --- Name ---\n";

      // Loop through all of the timing data, printing it out...
      for (unsigned i = 0, e = TimersToPrint.size(); i != e; ++i)
        TimersToPrint[i].print(Total, *OutStream);

      Total.print(Total, *OutStream);
      *OutStream << std::endl;  // Flush output
    }
    --NumTimers;

    TimersToPrint.clear();

    if (OutStream != &std::cerr && OutStream != &std::cout)
      delete OutStream;   // Close the file...
  }

  // Delete default timer group!
  if (NumTimers == 0 && this == DefaultTimerGroup) {
    delete DefaultTimerGroup;
    DefaultTimerGroup = 0;
  }
}

<commit_msg>For PR351: * Move system dependent implementation out of this file. * Make implementation use sys::Process::GetMallocUsage where necessary. * Make implementation use sys::Process::GetTimeUsage where necessary.<commit_after>//===-- Timer.cpp - Interval Timing Support -------------------------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file was developed by the LLVM research group and is distributed under
// the University of Illinois Open Source License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// Interval Timing implementation.
//
//===----------------------------------------------------------------------===//

#include "llvm/Support/Timer.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/System/Process.h"
#include <fstream>
#include <iostream>
#include <map>

using namespace llvm;

// GetLibSupportInfoOutputFile - Return a file stream to print our output on.
namespace llvm { extern std::ostream *GetLibSupportInfoOutputFile(); }

// getLibSupportInfoOutputFilename - This ugly hack is brought to you courtesy
// of constructor/destructor ordering being unspecified by C++.  Basically the
// problem is that a Statistic<> object gets destroyed, which ends up calling
// 'GetLibSupportInfoOutputFile()' (below), which calls this function.
// LibSupportInfoOutputFilename used to be a global variable, but sometimes it
// would get destroyed before the Statistic, causing havoc to ensue.  We "fix"
// this by creating the string the first time it is needed and never destroying
// it.
static std::string &getLibSupportInfoOutputFilename() {
  static std::string *LibSupportInfoOutputFilename = new std::string();
  return *LibSupportInfoOutputFilename;
}

namespace {
  cl::opt<bool>
  TrackSpace("track-memory", cl::desc("Enable -time-passes memory "
                                      "tracking (this may be slow)"),
             cl::Hidden);

  cl::opt<std::string, true>
  InfoOutputFilename("info-output-file", cl::value_desc("filename"),
                     cl::desc("File to append -stats and -timer output to"),
                   cl::Hidden, cl::location(getLibSupportInfoOutputFilename()));
}

static TimerGroup *DefaultTimerGroup = 0;
static TimerGroup *getDefaultTimerGroup() {
  if (DefaultTimerGroup) return DefaultTimerGroup;
  return DefaultTimerGroup = new TimerGroup("Miscellaneous Ungrouped Timers");
}

Timer::Timer(const std::string &N)
  : Elapsed(0), UserTime(0), SystemTime(0), MemUsed(0), PeakMem(0), Name(N),
    Started(false), TG(getDefaultTimerGroup()) {
  TG->addTimer();
}

Timer::Timer(const std::string &N, TimerGroup &tg)
  : Elapsed(0), UserTime(0), SystemTime(0), MemUsed(0), PeakMem(0), Name(N),
    Started(false), TG(&tg) {
  TG->addTimer();
}

Timer::Timer(const Timer &T) {
  TG = T.TG;
  if (TG) TG->addTimer();
  operator=(T);
}

// Copy ctor, initialize with no TG member.
Timer::Timer(bool, const Timer &T) {
  TG = T.TG;     // Avoid assertion in operator=
  operator=(T);  // Copy contents
  TG = 0;
}

Timer::~Timer() {
  if (TG) {
    if (Started) {
      Started = false;
      TG->addTimerToPrint(*this);
    }
    TG->removeTimer();
  }
}

struct TimeRecord {
  double Elapsed, UserTime, SystemTime;
  long MemUsed;
};

static TimeRecord getTimeRecord(bool Start) {
  TimeRecord Result;

  sys::TimeValue now(0,0);
  sys::TimeValue user(0,0);
  sys::TimeValue sys(0,0);

  sys::Process::GetTimeUsage(now,user,sys);

  Result.Elapsed    = now.seconds()  + now.microseconds()  / 1000000.0;
  Result.UserTime   = user.seconds() + user.microseconds() / 1000000.0;
  Result.UserTime   = sys.seconds()  + sys.microseconds()  / 1000000.0;
  Result.MemUsed = sys::Process::GetMallocUsage();

  return Result;
}

static std::vector<Timer*> ActiveTimers;

void Timer::startTimer() {
  Started = true;
  TimeRecord TR = getTimeRecord(true);
  Elapsed    -= TR.Elapsed;
  UserTime   -= TR.UserTime;
  SystemTime -= TR.SystemTime;
  MemUsed    -= TR.MemUsed;
  PeakMemBase = TR.MemUsed;
  ActiveTimers.push_back(this);
}

void Timer::stopTimer() {
  TimeRecord TR = getTimeRecord(false);
  Elapsed    += TR.Elapsed;
  UserTime   += TR.UserTime;
  SystemTime += TR.SystemTime;
  MemUsed    += TR.MemUsed;

  if (ActiveTimers.back() == this) {
    ActiveTimers.pop_back();
  } else {
    std::vector<Timer*>::iterator I =
      std::find(ActiveTimers.begin(), ActiveTimers.end(), this);
    assert(I != ActiveTimers.end() && "stop but no startTimer?");
    ActiveTimers.erase(I);
  }
}

void Timer::sum(const Timer &T) {
  Elapsed    += T.Elapsed;
  UserTime   += T.UserTime;
  SystemTime += T.SystemTime;
  MemUsed    += T.MemUsed;
  PeakMem    += T.PeakMem;
}

/// addPeakMemoryMeasurement - This method should be called whenever memory
/// usage needs to be checked.  It adds a peak memory measurement to the
/// currently active timers, which will be printed when the timer group prints
///
void Timer::addPeakMemoryMeasurement() {
  long MemUsed = sys::Process::GetMallocUsage();

  for (std::vector<Timer*>::iterator I = ActiveTimers.begin(),
         E = ActiveTimers.end(); I != E; ++I)
    (*I)->PeakMem = std::max((*I)->PeakMem, MemUsed-(*I)->PeakMemBase);
}

//===----------------------------------------------------------------------===//
//   NamedRegionTimer Implementation
//===----------------------------------------------------------------------===//

static Timer &getNamedRegionTimer(const std::string &Name) {
  static std::map<std::string, Timer> NamedTimers;

  std::map<std::string, Timer>::iterator I = NamedTimers.lower_bound(Name);
  if (I != NamedTimers.end() && I->first == Name)
    return I->second;

  return NamedTimers.insert(I, std::make_pair(Name, Timer(Name)))->second;
}

NamedRegionTimer::NamedRegionTimer(const std::string &Name)
  : TimeRegion(getNamedRegionTimer(Name)) {}

//===----------------------------------------------------------------------===//
//   TimerGroup Implementation
//===----------------------------------------------------------------------===//

// printAlignedFP - Simulate the printf "%A.Bf" format, where A is the
// TotalWidth size, and B is the AfterDec size.
//
static void printAlignedFP(double Val, unsigned AfterDec, unsigned TotalWidth,
                           std::ostream &OS) {
  assert(TotalWidth >= AfterDec+1 && "Bad FP Format!");
  OS.width(TotalWidth-AfterDec-1);
  char OldFill = OS.fill();
  OS.fill(' ');
  OS << (int)Val;  // Integer part;
  OS << ".";
  OS.width(AfterDec);
  OS.fill('0');
  unsigned ResultFieldSize = 1;
  while (AfterDec--) ResultFieldSize *= 10;
  OS << (int)(Val*ResultFieldSize) % ResultFieldSize;
  OS.fill(OldFill);
}

static void printVal(double Val, double Total, std::ostream &OS) {
  if (Total < 1e-7)   // Avoid dividing by zero...
    OS << "        -----     ";
  else {
    OS << "  ";
    printAlignedFP(Val, 4, 7, OS);
    OS << " (";
    printAlignedFP(Val*100/Total, 1, 5, OS);
    OS << "%)";
  }
}

void Timer::print(const Timer &Total, std::ostream &OS) {
  if (Total.UserTime)
    printVal(UserTime, Total.UserTime, OS);
  if (Total.SystemTime)
    printVal(SystemTime, Total.SystemTime, OS);
  if (Total.getProcessTime())
    printVal(getProcessTime(), Total.getProcessTime(), OS);
  printVal(Elapsed, Total.Elapsed, OS);

  OS << "  ";

  if (Total.MemUsed) {
    OS.width(9);
    OS << MemUsed << "  ";
  }
  if (Total.PeakMem) {
    if (PeakMem) {
      OS.width(9);
      OS << PeakMem << "  ";
    } else
      OS << "           ";
  }
  OS << Name << "\n";

  Started = false;  // Once printed, don't print again
}

// GetLibSupportInfoOutputFile - Return a file stream to print our output on...
std::ostream *
llvm::GetLibSupportInfoOutputFile() {
  std::string &LibSupportInfoOutputFilename = getLibSupportInfoOutputFilename();
  if (LibSupportInfoOutputFilename.empty())
    return &std::cerr;
  if (LibSupportInfoOutputFilename == "-")
    return &std::cout;

  std::ostream *Result = new std::ofstream(LibSupportInfoOutputFilename.c_str(),
                                           std::ios::app);
  if (!Result->good()) {
    std::cerr << "Error opening info-output-file '"
              << LibSupportInfoOutputFilename << " for appending!\n";
    delete Result;
    return &std::cerr;
  }
  return Result;
}

void TimerGroup::removeTimer() {
  if (--NumTimers == 0 && !TimersToPrint.empty()) { // Print timing report...
    // Sort the timers in descending order by amount of time taken...
    std::sort(TimersToPrint.begin(), TimersToPrint.end(),
              std::greater<Timer>());

    // Figure out how many spaces to indent TimerGroup name...
    unsigned Padding = (80-Name.length())/2;
    if (Padding > 80) Padding = 0;         // Don't allow "negative" numbers

    std::ostream *OutStream = GetLibSupportInfoOutputFile();

    ++NumTimers;
    {  // Scope to contain Total timer... don't allow total timer to drop us to
       // zero timers...
      Timer Total("TOTAL");

      for (unsigned i = 0, e = TimersToPrint.size(); i != e; ++i)
        Total.sum(TimersToPrint[i]);

      // Print out timing header...
      *OutStream << "===" << std::string(73, '-') << "===\n"
                 << std::string(Padding, ' ') << Name << "\n"
                 << "===" << std::string(73, '-')
                 << "===\n  Total Execution Time: ";

      printAlignedFP(Total.getProcessTime(), 4, 5, *OutStream);
      *OutStream << " seconds (";
      printAlignedFP(Total.getWallTime(), 4, 5, *OutStream);
      *OutStream << " wall clock)\n\n";

      if (Total.UserTime)
        *OutStream << "   ---User Time---";
      if (Total.SystemTime)
        *OutStream << "   --System Time--";
      if (Total.getProcessTime())
        *OutStream << "   --User+System--";
      *OutStream << "   ---Wall Time---";
      if (Total.getMemUsed())
        *OutStream << "  ---Mem---";
      if (Total.getPeakMem())
        *OutStream << "  -PeakMem-";
      *OutStream << "  --- Name ---\n";

      // Loop through all of the timing data, printing it out...
      for (unsigned i = 0, e = TimersToPrint.size(); i != e; ++i)
        TimersToPrint[i].print(Total, *OutStream);

      Total.print(Total, *OutStream);
      *OutStream << std::endl;  // Flush output
    }
    --NumTimers;

    TimersToPrint.clear();

    if (OutStream != &std::cerr && OutStream != &std::cout)
      delete OutStream;   // Close the file...
  }

  // Delete default timer group!
  if (NumTimers == 0 && this == DefaultTimerGroup) {
    delete DefaultTimerGroup;
    DefaultTimerGroup = 0;
  }
}

<|endoftext|>


<commit_before>//===-- Timer.cpp - Interval Timing Support -------------------------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file was developed by the LLVM research group and is distributed under
// the University of Illinois Open Source License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// Interval Timing implementation.
//
//===----------------------------------------------------------------------===//

#include "llvm/Support/Timer.h"
#include "llvm/Support/CommandLine.h"
#include <algorithm>
#include <iostream>
#include <functional>
#include <fstream>
#include <map>
#include "llvm/Config/sys/resource.h"
#include "llvm/Config/sys/time.h"
#include "llvm/Config/unistd.h"
#include "llvm/Config/malloc.h"
#include "llvm/Config/windows.h"
using namespace llvm;

// GetLibSupportInfoOutputFile - Return a file stream to print our output on.
namespace llvm { extern std::ostream *GetLibSupportInfoOutputFile(); }

// getLibSupportInfoOutputFilename - This ugly hack is brought to you courtesy
// of constructor/destructor ordering being unspecified by C++.  Basically the
// problem is that a Statistic<> object gets destroyed, which ends up calling
// 'GetLibSupportInfoOutputFile()' (below), which calls this function.
// LibSupportInfoOutputFilename used to be a global variable, but sometimes it
// would get destroyed before the Statistic, causing havoc to ensue.  We "fix"
// this by creating the string the first time it is needed and never destroying
// it.
static std::string &getLibSupportInfoOutputFilename() {
  static std::string *LibSupportInfoOutputFilename = new std::string();
  return *LibSupportInfoOutputFilename;
}

namespace {
#ifdef HAVE_MALLINFO
  cl::opt<bool>
  TrackSpace("track-memory", cl::desc("Enable -time-passes memory "
                                      "tracking (this may be slow)"),
             cl::Hidden);
#endif

  cl::opt<std::string, true>
  InfoOutputFilename("info-output-file", cl::value_desc("filename"),
                     cl::desc("File to append -stats and -timer output to"),
                   cl::Hidden, cl::location(getLibSupportInfoOutputFilename()));
}

static TimerGroup *DefaultTimerGroup = 0;
static TimerGroup *getDefaultTimerGroup() {
  if (DefaultTimerGroup) return DefaultTimerGroup;
  return DefaultTimerGroup = new TimerGroup("Miscellaneous Ungrouped Timers");
}

Timer::Timer(const std::string &N)
  : Elapsed(0), UserTime(0), SystemTime(0), MemUsed(0), PeakMem(0), Name(N),
    Started(false), TG(getDefaultTimerGroup()) {
  TG->addTimer();
}

Timer::Timer(const std::string &N, TimerGroup &tg)
  : Elapsed(0), UserTime(0), SystemTime(0), MemUsed(0), PeakMem(0), Name(N),
    Started(false), TG(&tg) {
  TG->addTimer();
}

Timer::Timer(const Timer &T) {
  TG = T.TG;
  if (TG) TG->addTimer();
  operator=(T);
}

// Copy ctor, initialize with no TG member.
Timer::Timer(bool, const Timer &T) {
  TG = T.TG;     // Avoid assertion in operator=
  operator=(T);  // Copy contents
  TG = 0;
}

Timer::~Timer() {
  if (TG) {
    if (Started) {
      Started = false;
      TG->addTimerToPrint(*this);
    }
    TG->removeTimer();
  }
}

static long getMemUsage() {
#ifdef HAVE_MALLINFO
  if (TrackSpace) {
    struct mallinfo MI = mallinfo();
    return MI.uordblks/*+MI.hblkhd*/;
  }
#endif
  return 0;
}

struct TimeRecord {
  double Elapsed, UserTime, SystemTime;
  long MemUsed;
};

static TimeRecord getTimeRecord(bool Start) {
#if defined(HAVE_WINDOWS_H)
  unsigned __int64 ProcCreate, ProcExit, KernelTime, UserTime, CurTime;

  GetProcessTimes(GetCurrentProcess(), (FILETIME*)&ProcCreate,
                  (FILETIME*)&ProcExit, (FILETIME*)&KernelTime,
                  (FILETIME*)&UserTime);
  GetSystemTimeAsFileTime((FILETIME*)&CurTime);

  // FILETIME's are # of 100 nanosecond ticks.
  double ScaleFactor = 1.0/(10*1000*1000);

  TimeRecord Result;
  Result.Elapsed    = (CurTime-ProcCreate)*ScaleFactor;  // Wall time
  Result.UserTime   = UserTime*ScaleFactor;
  Result.SystemTime = KernelTime*ScaleFactor;
  return Result;
#elif defined(HAVE_GETRUSAGE)
  struct rusage RU;
  struct timeval T;
  long MemUsed = 0;
  if (Start) {
    MemUsed = getMemUsage();
    if (getrusage(RUSAGE_SELF, &RU))
      perror("getrusage call failed: -time-passes info incorrect!");
  }
  gettimeofday(&T, 0);

  if (!Start) {
    if (getrusage(RUSAGE_SELF, &RU))
      perror("getrusage call failed: -time-passes info incorrect!");
    MemUsed = getMemUsage();
  }

  TimeRecord Result;
  Result.Elapsed    =           T.tv_sec +           T.tv_usec/1000000.0;
  Result.UserTime   = RU.ru_utime.tv_sec + RU.ru_utime.tv_usec/1000000.0;
  Result.SystemTime = RU.ru_stime.tv_sec + RU.ru_stime.tv_usec/1000000.0;
  Result.MemUsed = MemUsed;
  return Result;
#else
  // Can't get resource usage.
  return TimeRecord();
#endif
}

static std::vector<Timer*> ActiveTimers;

void Timer::startTimer() {
  Started = true;
  TimeRecord TR = getTimeRecord(true);
  Elapsed    -= TR.Elapsed;
  UserTime   -= TR.UserTime;
  SystemTime -= TR.SystemTime;
  MemUsed    -= TR.MemUsed;
  PeakMemBase = TR.MemUsed;
  ActiveTimers.push_back(this);
}

void Timer::stopTimer() {
  TimeRecord TR = getTimeRecord(false);
  Elapsed    += TR.Elapsed;
  UserTime   += TR.UserTime;
  SystemTime += TR.SystemTime;
  MemUsed    += TR.MemUsed;

  if (ActiveTimers.back() == this) {
    ActiveTimers.pop_back();
  } else {
    std::vector<Timer*>::iterator I =
      std::find(ActiveTimers.begin(), ActiveTimers.end(), this);
    assert(I != ActiveTimers.end() && "stop but no startTimer?");
    ActiveTimers.erase(I);
  }
}

void Timer::sum(const Timer &T) {
  Elapsed    += T.Elapsed;
  UserTime   += T.UserTime;
  SystemTime += T.SystemTime;
  MemUsed    += T.MemUsed;
  PeakMem    += T.PeakMem;
}

/// addPeakMemoryMeasurement - This method should be called whenever memory
/// usage needs to be checked.  It adds a peak memory measurement to the
/// currently active timers, which will be printed when the timer group prints
///
void Timer::addPeakMemoryMeasurement() {
  long MemUsed = getMemUsage();

  for (std::vector<Timer*>::iterator I = ActiveTimers.begin(),
         E = ActiveTimers.end(); I != E; ++I)
    (*I)->PeakMem = std::max((*I)->PeakMem, MemUsed-(*I)->PeakMemBase);
}

//===----------------------------------------------------------------------===//
//   NamedRegionTimer Implementation
//===----------------------------------------------------------------------===//

static Timer &getNamedRegionTimer(const std::string &Name) {
  static std::map<std::string, Timer> NamedTimers;

  std::map<std::string, Timer>::iterator I = NamedTimers.lower_bound(Name);
  if (I != NamedTimers.end() && I->first == Name)
    return I->second;

  return NamedTimers.insert(I, std::make_pair(Name, Timer(Name)))->second;
}

NamedRegionTimer::NamedRegionTimer(const std::string &Name)
  : TimeRegion(getNamedRegionTimer(Name)) {}

//===----------------------------------------------------------------------===//
//   TimerGroup Implementation
//===----------------------------------------------------------------------===//

// printAlignedFP - Simulate the printf "%A.Bf" format, where A is the
// TotalWidth size, and B is the AfterDec size.
//
static void printAlignedFP(double Val, unsigned AfterDec, unsigned TotalWidth,
                           std::ostream &OS) {
  assert(TotalWidth >= AfterDec+1 && "Bad FP Format!");
  OS.width(TotalWidth-AfterDec-1);
  char OldFill = OS.fill();
  OS.fill(' ');
  OS << (int)Val;  // Integer part;
  OS << ".";
  OS.width(AfterDec);
  OS.fill('0');
  unsigned ResultFieldSize = 1;
  while (AfterDec--) ResultFieldSize *= 10;
  OS << (int)(Val*ResultFieldSize) % ResultFieldSize;
  OS.fill(OldFill);
}

static void printVal(double Val, double Total, std::ostream &OS) {
  if (Total < 1e-7)   // Avoid dividing by zero...
    OS << "        -----     ";
  else {
    OS << "  ";
    printAlignedFP(Val, 4, 7, OS);
    OS << " (";
    printAlignedFP(Val*100/Total, 1, 5, OS);
    OS << "%)";
  }
}

void Timer::print(const Timer &Total, std::ostream &OS) {
  if (Total.UserTime)
    printVal(UserTime, Total.UserTime, OS);
  if (Total.SystemTime)
    printVal(SystemTime, Total.SystemTime, OS);
  if (Total.getProcessTime())
    printVal(getProcessTime(), Total.getProcessTime(), OS);
  printVal(Elapsed, Total.Elapsed, OS);

  OS << "  ";

  if (Total.MemUsed) {
    OS.width(9);
    OS << MemUsed << "  ";
  }
  if (Total.PeakMem) {
    if (PeakMem) {
      OS.width(9);
      OS << PeakMem << "  ";
    } else
      OS << "           ";
  }
  OS << Name << "\n";

  Started = false;  // Once printed, don't print again
}

// GetLibSupportInfoOutputFile - Return a file stream to print our output on...
std::ostream *
llvm::GetLibSupportInfoOutputFile() {
  std::string &LibSupportInfoOutputFilename = getLibSupportInfoOutputFilename();
  if (LibSupportInfoOutputFilename.empty())
    return &std::cerr;
  if (LibSupportInfoOutputFilename == "-")
    return &std::cout;

  std::ostream *Result = new std::ofstream(LibSupportInfoOutputFilename.c_str(),
                                           std::ios::app);
  if (!Result->good()) {
    std::cerr << "Error opening info-output-file '"
              << LibSupportInfoOutputFilename << " for appending!\n";
    delete Result;
    return &std::cerr;
  }
  return Result;
}

void TimerGroup::removeTimer() {
  if (--NumTimers == 0 && !TimersToPrint.empty()) { // Print timing report...
    // Sort the timers in descending order by amount of time taken...
    std::sort(TimersToPrint.begin(), TimersToPrint.end(),
              std::greater<Timer>());

    // Figure out how many spaces to indent TimerGroup name...
    unsigned Padding = (80-Name.length())/2;
    if (Padding > 80) Padding = 0;         // Don't allow "negative" numbers

    std::ostream *OutStream = GetLibSupportInfoOutputFile();

    ++NumTimers;
    {  // Scope to contain Total timer... don't allow total timer to drop us to
       // zero timers...
      Timer Total("TOTAL");

      for (unsigned i = 0, e = TimersToPrint.size(); i != e; ++i)
        Total.sum(TimersToPrint[i]);

      // Print out timing header...
      *OutStream << "===" << std::string(73, '-') << "===\n"
                 << std::string(Padding, ' ') << Name << "\n"
                 << "===" << std::string(73, '-')
                 << "===\n  Total Execution Time: ";

      printAlignedFP(Total.getProcessTime(), 4, 5, *OutStream);
      *OutStream << " seconds (";
      printAlignedFP(Total.getWallTime(), 4, 5, *OutStream);
      *OutStream << " wall clock)\n\n";

      if (Total.UserTime)
        *OutStream << "   ---User Time---";
      if (Total.SystemTime)
        *OutStream << "   --System Time--";
      if (Total.getProcessTime())
        *OutStream << "   --User+System--";
      *OutStream << "   ---Wall Time---";
      if (Total.getMemUsed())
        *OutStream << "  ---Mem---";
      if (Total.getPeakMem())
        *OutStream << "  -PeakMem-";
      *OutStream << "  --- Name ---\n";

      // Loop through all of the timing data, printing it out...
      for (unsigned i = 0, e = TimersToPrint.size(); i != e; ++i)
        TimersToPrint[i].print(Total, *OutStream);

      Total.print(Total, *OutStream);
      *OutStream << std::endl;  // Flush output
    }
    --NumTimers;

    TimersToPrint.clear();

    if (OutStream != &std::cerr && OutStream != &std::cout)
      delete OutStream;   // Close the file...
  }

  // Delete default timer group!
  if (NumTimers == 0 && this == DefaultTimerGroup) {
    delete DefaultTimerGroup;
    DefaultTimerGroup = 0;
  }
}

<commit_msg>Make a cast explicit.<commit_after>//===-- Timer.cpp - Interval Timing Support -------------------------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file was developed by the LLVM research group and is distributed under
// the University of Illinois Open Source License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// Interval Timing implementation.
//
//===----------------------------------------------------------------------===//

#include "llvm/Support/Timer.h"
#include "llvm/Support/CommandLine.h"
#include <algorithm>
#include <iostream>
#include <functional>
#include <fstream>
#include <map>
#include "llvm/Config/sys/resource.h"
#include "llvm/Config/sys/time.h"
#include "llvm/Config/unistd.h"
#include "llvm/Config/malloc.h"
#include "llvm/Config/windows.h"
using namespace llvm;

// GetLibSupportInfoOutputFile - Return a file stream to print our output on.
namespace llvm { extern std::ostream *GetLibSupportInfoOutputFile(); }

// getLibSupportInfoOutputFilename - This ugly hack is brought to you courtesy
// of constructor/destructor ordering being unspecified by C++.  Basically the
// problem is that a Statistic<> object gets destroyed, which ends up calling
// 'GetLibSupportInfoOutputFile()' (below), which calls this function.
// LibSupportInfoOutputFilename used to be a global variable, but sometimes it
// would get destroyed before the Statistic, causing havoc to ensue.  We "fix"
// this by creating the string the first time it is needed and never destroying
// it.
static std::string &getLibSupportInfoOutputFilename() {
  static std::string *LibSupportInfoOutputFilename = new std::string();
  return *LibSupportInfoOutputFilename;
}

namespace {
#ifdef HAVE_MALLINFO
  cl::opt<bool>
  TrackSpace("track-memory", cl::desc("Enable -time-passes memory "
                                      "tracking (this may be slow)"),
             cl::Hidden);
#endif

  cl::opt<std::string, true>
  InfoOutputFilename("info-output-file", cl::value_desc("filename"),
                     cl::desc("File to append -stats and -timer output to"),
                   cl::Hidden, cl::location(getLibSupportInfoOutputFilename()));
}

static TimerGroup *DefaultTimerGroup = 0;
static TimerGroup *getDefaultTimerGroup() {
  if (DefaultTimerGroup) return DefaultTimerGroup;
  return DefaultTimerGroup = new TimerGroup("Miscellaneous Ungrouped Timers");
}

Timer::Timer(const std::string &N)
  : Elapsed(0), UserTime(0), SystemTime(0), MemUsed(0), PeakMem(0), Name(N),
    Started(false), TG(getDefaultTimerGroup()) {
  TG->addTimer();
}

Timer::Timer(const std::string &N, TimerGroup &tg)
  : Elapsed(0), UserTime(0), SystemTime(0), MemUsed(0), PeakMem(0), Name(N),
    Started(false), TG(&tg) {
  TG->addTimer();
}

Timer::Timer(const Timer &T) {
  TG = T.TG;
  if (TG) TG->addTimer();
  operator=(T);
}

// Copy ctor, initialize with no TG member.
Timer::Timer(bool, const Timer &T) {
  TG = T.TG;     // Avoid assertion in operator=
  operator=(T);  // Copy contents
  TG = 0;
}

Timer::~Timer() {
  if (TG) {
    if (Started) {
      Started = false;
      TG->addTimerToPrint(*this);
    }
    TG->removeTimer();
  }
}

static long getMemUsage() {
#ifdef HAVE_MALLINFO
  if (TrackSpace) {
    struct mallinfo MI = mallinfo();
    return MI.uordblks/*+MI.hblkhd*/;
  }
#endif
  return 0;
}

struct TimeRecord {
  double Elapsed, UserTime, SystemTime;
  long MemUsed;
};

static TimeRecord getTimeRecord(bool Start) {
#if defined(HAVE_WINDOWS_H)
  unsigned __int64 ProcCreate, ProcExit, KernelTime, UserTime, CurTime;

  GetProcessTimes(GetCurrentProcess(), (FILETIME*)&ProcCreate,
                  (FILETIME*)&ProcExit, (FILETIME*)&KernelTime,
                  (FILETIME*)&UserTime);
  GetSystemTimeAsFileTime((FILETIME*)&CurTime);

  // FILETIME's are # of 100 nanosecond ticks.
  double ScaleFactor = 1.0/(10*1000*1000);

  TimeRecord Result;
  Result.Elapsed    = (CurTime-ProcCreate)*ScaleFactor;  // Wall time
  Result.UserTime   = UserTime*ScaleFactor;
  Result.SystemTime = KernelTime*ScaleFactor;
  return Result;
#elif defined(HAVE_GETRUSAGE)
  struct rusage RU;
  struct timeval T;
  long MemUsed = 0;
  if (Start) {
    MemUsed = getMemUsage();
    if (getrusage(RUSAGE_SELF, &RU))
      perror("getrusage call failed: -time-passes info incorrect!");
  }
  gettimeofday(&T, 0);

  if (!Start) {
    if (getrusage(RUSAGE_SELF, &RU))
      perror("getrusage call failed: -time-passes info incorrect!");
    MemUsed = getMemUsage();
  }

  TimeRecord Result;
  Result.Elapsed    = double(T.tv_sec) + T.tv_usec/1000000.0;
  Result.UserTime   = RU.ru_utime.tv_sec + RU.ru_utime.tv_usec/1000000.0;
  Result.SystemTime = RU.ru_stime.tv_sec + RU.ru_stime.tv_usec/1000000.0;
  Result.MemUsed = MemUsed;
  return Result;
#else
  // Can't get resource usage.
  return TimeRecord();
#endif
}

static std::vector<Timer*> ActiveTimers;

void Timer::startTimer() {
  Started = true;
  TimeRecord TR = getTimeRecord(true);
  Elapsed    -= TR.Elapsed;
  UserTime   -= TR.UserTime;
  SystemTime -= TR.SystemTime;
  MemUsed    -= TR.MemUsed;
  PeakMemBase = TR.MemUsed;
  ActiveTimers.push_back(this);
}

void Timer::stopTimer() {
  TimeRecord TR = getTimeRecord(false);
  Elapsed    += TR.Elapsed;
  UserTime   += TR.UserTime;
  SystemTime += TR.SystemTime;
  MemUsed    += TR.MemUsed;

  if (ActiveTimers.back() == this) {
    ActiveTimers.pop_back();
  } else {
    std::vector<Timer*>::iterator I =
      std::find(ActiveTimers.begin(), ActiveTimers.end(), this);
    assert(I != ActiveTimers.end() && "stop but no startTimer?");
    ActiveTimers.erase(I);
  }
}

void Timer::sum(const Timer &T) {
  Elapsed    += T.Elapsed;
  UserTime   += T.UserTime;
  SystemTime += T.SystemTime;
  MemUsed    += T.MemUsed;
  PeakMem    += T.PeakMem;
}

/// addPeakMemoryMeasurement - This method should be called whenever memory
/// usage needs to be checked.  It adds a peak memory measurement to the
/// currently active timers, which will be printed when the timer group prints
///
void Timer::addPeakMemoryMeasurement() {
  long MemUsed = getMemUsage();

  for (std::vector<Timer*>::iterator I = ActiveTimers.begin(),
         E = ActiveTimers.end(); I != E; ++I)
    (*I)->PeakMem = std::max((*I)->PeakMem, MemUsed-(*I)->PeakMemBase);
}

//===----------------------------------------------------------------------===//
//   NamedRegionTimer Implementation
//===----------------------------------------------------------------------===//

static Timer &getNamedRegionTimer(const std::string &Name) {
  static std::map<std::string, Timer> NamedTimers;

  std::map<std::string, Timer>::iterator I = NamedTimers.lower_bound(Name);
  if (I != NamedTimers.end() && I->first == Name)
    return I->second;

  return NamedTimers.insert(I, std::make_pair(Name, Timer(Name)))->second;
}

NamedRegionTimer::NamedRegionTimer(const std::string &Name)
  : TimeRegion(getNamedRegionTimer(Name)) {}

//===----------------------------------------------------------------------===//
//   TimerGroup Implementation
//===----------------------------------------------------------------------===//

// printAlignedFP - Simulate the printf "%A.Bf" format, where A is the
// TotalWidth size, and B is the AfterDec size.
//
static void printAlignedFP(double Val, unsigned AfterDec, unsigned TotalWidth,
                           std::ostream &OS) {
  assert(TotalWidth >= AfterDec+1 && "Bad FP Format!");
  OS.width(TotalWidth-AfterDec-1);
  char OldFill = OS.fill();
  OS.fill(' ');
  OS << (int)Val;  // Integer part;
  OS << ".";
  OS.width(AfterDec);
  OS.fill('0');
  unsigned ResultFieldSize = 1;
  while (AfterDec--) ResultFieldSize *= 10;
  OS << (int)(Val*ResultFieldSize) % ResultFieldSize;
  OS.fill(OldFill);
}

static void printVal(double Val, double Total, std::ostream &OS) {
  if (Total < 1e-7)   // Avoid dividing by zero...
    OS << "        -----     ";
  else {
    OS << "  ";
    printAlignedFP(Val, 4, 7, OS);
    OS << " (";
    printAlignedFP(Val*100/Total, 1, 5, OS);
    OS << "%)";
  }
}

void Timer::print(const Timer &Total, std::ostream &OS) {
  if (Total.UserTime)
    printVal(UserTime, Total.UserTime, OS);
  if (Total.SystemTime)
    printVal(SystemTime, Total.SystemTime, OS);
  if (Total.getProcessTime())
    printVal(getProcessTime(), Total.getProcessTime(), OS);
  printVal(Elapsed, Total.Elapsed, OS);

  OS << "  ";

  if (Total.MemUsed) {
    OS.width(9);
    OS << MemUsed << "  ";
  }
  if (Total.PeakMem) {
    if (PeakMem) {
      OS.width(9);
      OS << PeakMem << "  ";
    } else
      OS << "           ";
  }
  OS << Name << "\n";

  Started = false;  // Once printed, don't print again
}

// GetLibSupportInfoOutputFile - Return a file stream to print our output on...
std::ostream *
llvm::GetLibSupportInfoOutputFile() {
  std::string &LibSupportInfoOutputFilename = getLibSupportInfoOutputFilename();
  if (LibSupportInfoOutputFilename.empty())
    return &std::cerr;
  if (LibSupportInfoOutputFilename == "-")
    return &std::cout;

  std::ostream *Result = new std::ofstream(LibSupportInfoOutputFilename.c_str(),
                                           std::ios::app);
  if (!Result->good()) {
    std::cerr << "Error opening info-output-file '"
              << LibSupportInfoOutputFilename << " for appending!\n";
    delete Result;
    return &std::cerr;
  }
  return Result;
}

void TimerGroup::removeTimer() {
  if (--NumTimers == 0 && !TimersToPrint.empty()) { // Print timing report...
    // Sort the timers in descending order by amount of time taken...
    std::sort(TimersToPrint.begin(), TimersToPrint.end(),
              std::greater<Timer>());

    // Figure out how many spaces to indent TimerGroup name...
    unsigned Padding = (80-Name.length())/2;
    if (Padding > 80) Padding = 0;         // Don't allow "negative" numbers

    std::ostream *OutStream = GetLibSupportInfoOutputFile();

    ++NumTimers;
    {  // Scope to contain Total timer... don't allow total timer to drop us to
       // zero timers...
      Timer Total("TOTAL");

      for (unsigned i = 0, e = TimersToPrint.size(); i != e; ++i)
        Total.sum(TimersToPrint[i]);

      // Print out timing header...
      *OutStream << "===" << std::string(73, '-') << "===\n"
                 << std::string(Padding, ' ') << Name << "\n"
                 << "===" << std::string(73, '-')
                 << "===\n  Total Execution Time: ";

      printAlignedFP(Total.getProcessTime(), 4, 5, *OutStream);
      *OutStream << " seconds (";
      printAlignedFP(Total.getWallTime(), 4, 5, *OutStream);
      *OutStream << " wall clock)\n\n";

      if (Total.UserTime)
        *OutStream << "   ---User Time---";
      if (Total.SystemTime)
        *OutStream << "   --System Time--";
      if (Total.getProcessTime())
        *OutStream << "   --User+System--";
      *OutStream << "   ---Wall Time---";
      if (Total.getMemUsed())
        *OutStream << "  ---Mem---";
      if (Total.getPeakMem())
        *OutStream << "  -PeakMem-";
      *OutStream << "  --- Name ---\n";

      // Loop through all of the timing data, printing it out...
      for (unsigned i = 0, e = TimersToPrint.size(); i != e; ++i)
        TimersToPrint[i].print(Total, *OutStream);

      Total.print(Total, *OutStream);
      *OutStream << std::endl;  // Flush output
    }
    --NumTimers;

    TimersToPrint.clear();

    if (OutStream != &std::cerr && OutStream != &std::cout)
      delete OutStream;   // Close the file...
  }

  // Delete default timer group!
  if (NumTimers == 0 && this == DefaultTimerGroup) {
    delete DefaultTimerGroup;
    DefaultTimerGroup = 0;
  }
}

<|endoftext|>


<commit_before>/*! \file swiftinterface.cxx
 *  \brief this file contains routines that allow the velociraptor library to interface with the swift N-body code from within swift.
 */

#include "swiftinterface.h"

Options libvelociraptorOpt;
void InitVelociraptor(char* configname, char* outputname, cosmoinfo c, unitinfo u, siminfo s)
{

#ifdef USEMPI
    //find out how big the SPMD world is
    MPI_Comm_size(MPI_COMM_WORLD,&NProcs);
    mpi_domain=new MPI_Domain[NProcs];
    //and this processes' rank is
    MPI_Comm_rank(MPI_COMM_WORLD,&ThisTask);
#endif
    cout<<"Initialising VELOCIraptor..."<< endl;

    libvelociraptorOpt.pname = configname;
    libvelociraptorOpt.outname = outputname;

    cout<<"Reading VELOCIraptor config file..."<< endl;
    GetParamFile(libvelociraptorOpt);
    cout<<"Setting cosmology, units, sim stuff "<<endl;
    ///set units, here idea is to convert internal units so that have kpc, km/s, solar mass
    libvelociraptorOpt.lengthtokpc=1.0;
    libvelociraptorOpt.velocitytokms=1.0;
    libvelociraptorOpt.masstosolarmass=1.0;
    libvelociraptorOpt.L=u.lengthtokpc;
    libvelociraptorOpt.M=u.masstosolarmass;
    libvelociraptorOpt.V=u.velocitytokms;
    ///these should be in units of kpc, km/s, and solar mass
    libvelociraptorOpt.G=u.gravity;
    libvelociraptorOpt.H=u.hubbleunit;
    ///set cosmology
    libvelociraptorOpt.a=c.atime;
    libvelociraptorOpt.h=c.littleh;
    libvelociraptorOpt.Omega_m=c.Omega_m;
    libvelociraptorOpt.Omega_b=c.Omega_b;
    libvelociraptorOpt.Omega_cdm=c.Omega_cdm;
    libvelociraptorOpt.Omega_Lambda=c.Omega_Lambda;
    libvelociraptorOpt.w_de=c.w_de;

    //if libvelociraptorOpt.virlevel<0, then use virial overdensity based on Bryan and Norman 1998 virialization level is given by
    if (libvelociraptorOpt.virlevel<0)
    {
        Double_t bnx=-((1-libvelociraptorOpt.Omega_m-libvelociraptorOpt.Omega_Lambda)*pow(libvelociraptorOpt.a,-2.0)+libvelociraptorOpt.Omega_Lambda)/((1-libvelociraptorOpt.Omega_m-libvelociraptorOpt.Omega_Lambda)*pow(libvelociraptorOpt.a,-2.0)+libvelociraptorOpt.Omega_m*pow(libvelociraptorOpt.a,-3.0)+libvelociraptorOpt.Omega_Lambda);
        libvelociraptorOpt.virlevel=(18.0*M_PI*M_PI+82.0*bnx-39*bnx*bnx)/libvelociraptorOpt.Omega_m;
    }
    //set some sim information
    libvelociraptorOpt.p=s.period;
    libvelociraptorOpt.zoomlowmassdm=s.zoomhigresolutionmass;
    libvelociraptorOpt.icosmologicalin=s.icosmologicalsim;
    libvelociraptorOpt.ellxscale=s.interparticlespacing;
    libvelociraptorOpt.uinfo.eps*=libvelociraptorOpt.ellxscale;
    if (libvelociraptorOpt.icosmologicalin) {
        libvelociraptorOpt.ellxscale*=libvelociraptorOpt.a;
        libvelociraptorOpt.uinfo.eps*=libvelociraptorOpt.a;
        double Hubble=libvelociraptorOpt.h*libvelociraptorOpt.H*sqrt((1-libvelociraptorOpt.Omega_m-libvelociraptorOpt.Omega_Lambda)*pow(libvelociraptorOpt.a,-2.0)+libvelociraptorOpt.Omega_m*pow(libvelociraptorOpt.a,-3.0)+libvelociraptorOpt.Omega_Lambda);
        libvelociraptorOpt.rhobg=3.*Hubble*Hubble/(8.0*M_PI*libvelociraptorOpt.G)*libvelociraptorOpt.Omega_m;
    }
    else {
        libvelociraptorOpt.rhobg=1.0;
    }
    //assume above is in comoving is cosmological simulation and then need to correct to physical
    if (libvelociraptorOpt.icosmologicalin) {
        libvelociraptorOpt.p*=libvelociraptorOpt.a;
        libvelociraptorOpt.ellxscale*=libvelociraptorOpt.a;
        libvelociraptorOpt.uinfo.eps*=libvelociraptorOpt.a;
    }
    libvelociraptorOpt.uinfo.icalculatepotential=false;
    cout<<"Finished initialising VELOCIraptor"<<endl;
    if (libvelociraptorOpt.HaloMinSize==-1) libvelociraptorOpt.HaloMinSize=libvelociraptorOpt.MinSize;

    //write velociraptor info
    WriteVELOCIraptorConfig(libvelociraptorOpt);
    WriteSimulationInfo(libvelociraptorOpt);
    WriteUnitInfo(libvelociraptorOpt);

}

void InvokeVelociraptor(const int num_gravity_parts, struct gpart *gravity_parts) {
#ifndef USEMPI
    int ThisTask=0;
    int NProcs=1;
    int Nlocal, Ntotal, Nmemlocal;
#endif
    int nthreads;
#ifdef USEOPENMP
#pragma omp parallel
{
    if (omp_get_thread_num()==0) nthreads=omp_get_num_threads();
}
#else
    nthreads=1;
#endif

    Particle *parts;
    Int_t *pfof,*numingroup,**pglist;
    Int_t ngroup, nhalos;
    //Int_t nbodies,nbaryons,ndark;
    //KDTree *tree;
    //to store information about the group
    PropData *pdata=NULL,*pdatahalos=NULL;
    double time1,time2;

    Nlocal=Nmemlocal=num_gravity_parts;
    Nmemlocal*=(1+libvelociraptorOpt.mpipartfac);
    parts=new Particle[Nmemlocal];
    cout<<"Copying particle data..."<< endl;
    for(auto i=0; i<Nlocal; i++) {
        parts[i] = Particle(gravity_parts[i], libvelociraptorOpt.L, libvelociraptorOpt.V, libvelociraptorOpt.M, libvelociraptorOpt.icosmologicalin,libvelociraptorOpt.a,libvelociraptorOpt.h);
    }
    cout<<"Finished copying particle data."<< endl;
#ifdef USEMPI
    MPI_Allreduce(&num_gravity_parts, &Ntotal, 1, MPI_Int_t, MPI_SUM, MPI_COMM_WORLD);
#endif
    Nlocal=num_gravity_parts;
    cout<<"TIME::"<<ThisTask<<" took "<<time1<<" to load "<<Nlocal<<" of "<<Ntotal<<endl;
    cout<<ThisTask<<" There are "<<Nlocal<<" particles and have allocated enough memory for "<<Nmemlocal<<" requiring "<<Nmemlocal*sizeof(Particle)/1024./1024./1024.<<"GB of memory "<<endl;
    //if (libvelociraptorOpt.iBaryonSearch>0) cout<<ThisTask<<"There are "<<Nlocalbaryon[0]<<" baryon particles and have allocated enough memory for "<<Nmemlocalbaryon<<" requiring "<<Nmemlocalbaryon*sizeof(Particle)/1024./1024./1024.<<"GB of memory "<<endl;
    cout<<ThisTask<<" will also require additional memory for FOF algorithms and substructure search. Largest mem needed for preliminary FOF search. Rough estimate is "<<Nlocal*(sizeof(Int_tree_t)*8)/1024./1024./1024.<<"GB of memory"<<endl;
    Coordinate minc,maxc,avec;
    for (auto j=0;j<3;j++) {maxc[j]=0;minc[j]=libvelociraptorOpt.p;avec[j]=0;}
    for(auto i=0; i<Nlocal; i++) {
        for (auto j=0;j<3;j++) {
            if (parts[i].GetPosition(j)>maxc[j]) maxc[j]=parts[i].GetPosition(j);
            if (parts[i].GetPosition(j)<minc[j]) minc[j]=parts[i].GetPosition(j);
            avec[j]+=parts[i].GetPosition(j);
        }
    }
    avec=avec*(1.0/(double)Nlocal);
    cout<<"Stats of positions (min,ave,max)"<<endl;
    for (auto j=0;j<3;j++) {
        cout<<j<<" : "<<minc[j]<<", "<<avec[j]<<", "<<maxc[j]<<endl;
    }
    time1=MyGetTime();
    pfof=SearchFullSet(libvelociraptorOpt,Nlocal,parts,ngroup);
    time1=MyGetTime()-time1;
    cout<<"TIME::"<<ThisTask<<" took "<<time1<<" to search "<<Nlocal<<" with "<<nthreads<<endl;
    nhalos=ngroup;
    //if caculating inclusive halo masses, then for simplicity, I assume halo id order NOT rearranged!
    //this is not necessarily true if baryons are searched for separately.
    if (libvelociraptorOpt.iInclusiveHalo) {
        pdatahalos=new PropData[nhalos+1];
        Int_t *numinhalos=BuildNumInGroup(Nlocal, nhalos, pfof);
        Int_t *sortvalhalos=new Int_t[Nlocal];
        Int_t *originalID=new Int_t[Nlocal];
        for (Int_t i=0;i<Nlocal;i++) {sortvalhalos[i]=pfof[i]*(pfof[i]>0)+Nlocal*(pfof[i]==0);originalID[i]=parts[i].GetID();parts[i].SetID(i);}
        Int_t *noffsethalos=BuildNoffset(Nlocal, parts, nhalos, numinhalos, sortvalhalos);
        GetInclusiveMasses(libvelociraptorOpt, Nlocal, parts, nhalos, pfof, numinhalos, pdatahalos, noffsethalos);
        qsort(parts,Nlocal,sizeof(Particle),IDCompare);
        delete[] numinhalos;
        delete[] sortvalhalos;
        delete[] noffsethalos;
        for (Int_t i=0;i<Nlocal;i++) parts[i].SetID(originalID[i]);
        delete[] originalID;
    }

    //now search for substructure
    if (libvelociraptorOpt.iSubSearch) {
        cout<<"Searching subset"<<endl;
        time1=MyGetTime();
        //if groups have been found (and localized to single MPI thread) then proceed to search for subsubstructures
        SearchSubSub(libvelociraptorOpt, Nlocal, parts, pfof,ngroup,nhalos,pdatahalos);
        time1=MyGetTime()-time1;
        cout<<"TIME::"<<ThisTask<<" took "<<time1<<" to search for substructures "<<Nlocal<<" with "<<nthreads<<endl;
    }
    pdata=new PropData[ngroup+1];
    //if inclusive halo mass required
    if (libvelociraptorOpt.iInclusiveHalo && ngroup>0) {
        CopyMasses(nhalos,pdatahalos,pdata);
        delete[] pdatahalos;
    }
    //need to add baryon interface

    //get mpi local hierarchy
    Int_t *nsub,*parentgid, *uparentgid,*stype;
    nsub=new Int_t[ngroup+1];
    parentgid=new Int_t[ngroup+1];
    uparentgid=new Int_t[ngroup+1];
    stype=new Int_t[ngroup+1];
    Int_t nhierarchy=GetHierarchy(libvelociraptorOpt,ngroup,nsub,parentgid,uparentgid,stype);
    CopyHierarchy(libvelociraptorOpt,pdata,ngroup,nsub,parentgid,uparentgid,stype);

    //calculate data and output
    numingroup=BuildNumInGroup(Nlocal, ngroup, pfof);
    pglist=SortAccordingtoBindingEnergy(libvelociraptorOpt,Nlocal,parts,ngroup,pfof,numingroup,pdata);//alters pglist so most bound particles first
    WriteProperties(libvelociraptorOpt,ngroup,pdata);
    WriteGroupCatalog(libvelociraptorOpt, ngroup, numingroup, pglist, parts);
    for (Int_t i=1;i<=ngroup;i++) delete[] pglist[i];
    delete[] pglist;

    delete[] parts;

    cout<<"VELOCIraptor returning."<< endl;
}
<commit_msg>Some debug statements<commit_after>/*! \file swiftinterface.cxx
 *  \brief this file contains routines that allow the velociraptor library to interface with the swift N-body code from within swift.
 */

#include "swiftinterface.h"

Options libvelociraptorOpt;
void InitVelociraptor(char* configname, char* outputname, cosmoinfo c, unitinfo u, siminfo s)
{

#ifdef USEMPI
    //find out how big the SPMD world is
    MPI_Comm_size(MPI_COMM_WORLD,&NProcs);
    mpi_domain=new MPI_Domain[NProcs];
    //and this processes' rank is
    MPI_Comm_rank(MPI_COMM_WORLD,&ThisTask);
#endif
    cout<<"Initialising VELOCIraptor..."<< endl;

    libvelociraptorOpt.pname = configname;
    libvelociraptorOpt.outname = outputname;

    cout<<"Reading VELOCIraptor config file..."<< endl;
    GetParamFile(libvelociraptorOpt);
    cout<<"Setting cosmology, units, sim stuff "<<endl;
    ///set units, here idea is to convert internal units so that have kpc, km/s, solar mass
    libvelociraptorOpt.lengthtokpc=1.0;
    libvelociraptorOpt.velocitytokms=1.0;
    libvelociraptorOpt.masstosolarmass=1.0;
    libvelociraptorOpt.L=u.lengthtokpc;
    libvelociraptorOpt.M=u.masstosolarmass;
    libvelociraptorOpt.V=u.velocitytokms;
    ///these should be in units of kpc, km/s, and solar mass
    libvelociraptorOpt.G=u.gravity;
    libvelociraptorOpt.H=u.hubbleunit;
    ///set cosmology
    libvelociraptorOpt.a=c.atime;
    libvelociraptorOpt.h=c.littleh;
    libvelociraptorOpt.Omega_m=c.Omega_m;
    libvelociraptorOpt.Omega_b=c.Omega_b;
    libvelociraptorOpt.Omega_cdm=c.Omega_cdm;
    libvelociraptorOpt.Omega_Lambda=c.Omega_Lambda;
    libvelociraptorOpt.w_de=c.w_de;

    //if libvelociraptorOpt.virlevel<0, then use virial overdensity based on Bryan and Norman 1998 virialization level is given by
    if (libvelociraptorOpt.virlevel<0)
    {
        Double_t bnx=-((1-libvelociraptorOpt.Omega_m-libvelociraptorOpt.Omega_Lambda)*pow(libvelociraptorOpt.a,-2.0)+libvelociraptorOpt.Omega_Lambda)/((1-libvelociraptorOpt.Omega_m-libvelociraptorOpt.Omega_Lambda)*pow(libvelociraptorOpt.a,-2.0)+libvelociraptorOpt.Omega_m*pow(libvelociraptorOpt.a,-3.0)+libvelociraptorOpt.Omega_Lambda);
        libvelociraptorOpt.virlevel=(18.0*M_PI*M_PI+82.0*bnx-39*bnx*bnx)/libvelociraptorOpt.Omega_m;
    }
    //set some sim information
    libvelociraptorOpt.p=s.period;
    libvelociraptorOpt.zoomlowmassdm=s.zoomhigresolutionmass;
    libvelociraptorOpt.icosmologicalin=s.icosmologicalsim;
    libvelociraptorOpt.ellxscale=s.interparticlespacing;
    libvelociraptorOpt.uinfo.eps*=libvelociraptorOpt.ellxscale;
    if (libvelociraptorOpt.icosmologicalin) {
        libvelociraptorOpt.ellxscale*=libvelociraptorOpt.a;
        libvelociraptorOpt.uinfo.eps*=libvelociraptorOpt.a;
        double Hubble=libvelociraptorOpt.h*libvelociraptorOpt.H*sqrt((1-libvelociraptorOpt.Omega_m-libvelociraptorOpt.Omega_Lambda)*pow(libvelociraptorOpt.a,-2.0)+libvelociraptorOpt.Omega_m*pow(libvelociraptorOpt.a,-3.0)+libvelociraptorOpt.Omega_Lambda);
        libvelociraptorOpt.rhobg=3.*Hubble*Hubble/(8.0*M_PI*libvelociraptorOpt.G)*libvelociraptorOpt.Omega_m;
    }
    else {
        libvelociraptorOpt.rhobg=1.0;
    }
    //assume above is in comoving is cosmological simulation and then need to correct to physical
    if (libvelociraptorOpt.icosmologicalin) {
        libvelociraptorOpt.p*=libvelociraptorOpt.a;
        libvelociraptorOpt.ellxscale*=libvelociraptorOpt.a;
        libvelociraptorOpt.uinfo.eps*=libvelociraptorOpt.a;
    }
    libvelociraptorOpt.uinfo.icalculatepotential=false;
    cout<<"Finished initialising VELOCIraptor"<<endl;
    if (libvelociraptorOpt.HaloMinSize==-1) libvelociraptorOpt.HaloMinSize=libvelociraptorOpt.MinSize;

    //write velociraptor info
    WriteVELOCIraptorConfig(libvelociraptorOpt);
    WriteSimulationInfo(libvelociraptorOpt);
    WriteUnitInfo(libvelociraptorOpt);

}

void InvokeVelociraptor(const int num_gravity_parts, struct gpart *gravity_parts) {
#ifndef USEMPI
    int ThisTask=0;
    int NProcs=1;
    int Nlocal, Ntotal, Nmemlocal;
#endif
    int nthreads;
#ifdef USEOPENMP
#pragma omp parallel
{
    if (omp_get_thread_num()==0) nthreads=omp_get_num_threads();
}
#else
    nthreads=1;
#endif

    Particle *parts;
    Int_t *pfof,*numingroup,**pglist;
    Int_t ngroup, nhalos;
    //Int_t nbodies,nbaryons,ndark;
    //KDTree *tree;
    //to store information about the group
    PropData *pdata=NULL,*pdatahalos=NULL;
    double time1,time2;

    Nlocal=Nmemlocal=num_gravity_parts;
    Nmemlocal*=(1+libvelociraptorOpt.mpipartfac);
    parts=new Particle[Nmemlocal];
    cout<<"Copying particle data..."<< endl;
    for(auto i=0; i<Nlocal; i++) {
        parts[i] = Particle(gravity_parts[i], libvelociraptorOpt.L, libvelociraptorOpt.V, libvelociraptorOpt.M, libvelociraptorOpt.icosmologicalin,libvelociraptorOpt.a,libvelociraptorOpt.h);
    }
    cout<<"Finished copying particle data."<< endl;
#ifdef USEMPI
    MPI_Allreduce(&num_gravity_parts, &Ntotal, 1, MPI_Int_t, MPI_SUM, MPI_COMM_WORLD);
#endif
    Nlocal=num_gravity_parts;
    cout<<"TIME::"<<ThisTask<<" took "<<time1<<" to load "<<Nlocal<<" of "<<Ntotal<<endl;
    cout<<ThisTask<<" There are "<<Nlocal<<" particles and have allocated enough memory for "<<Nmemlocal<<" requiring "<<Nmemlocal*sizeof(Particle)/1024./1024./1024.<<"GB of memory "<<endl;
    //if (libvelociraptorOpt.iBaryonSearch>0) cout<<ThisTask<<"There are "<<Nlocalbaryon[0]<<" baryon particles and have allocated enough memory for "<<Nmemlocalbaryon<<" requiring "<<Nmemlocalbaryon*sizeof(Particle)/1024./1024./1024.<<"GB of memory "<<endl;
    cout<<ThisTask<<" will also require additional memory for FOF algorithms and substructure search. Largest mem needed for preliminary FOF search. Rough estimate is "<<Nlocal*(sizeof(Int_tree_t)*8)/1024./1024./1024.<<"GB of memory"<<endl;
    Coordinate minc,maxc,avec;
    for (auto j=0;j<3;j++) {maxc[j]=0;minc[j]=libvelociraptorOpt.p;avec[j]=0;}
    for(auto i=0; i<Nlocal; i++) {
        for (auto j=0;j<3;j++) {
            if (parts[i].GetPosition(j)>maxc[j]) maxc[j]=parts[i].GetPosition(j);
            if (parts[i].GetPosition(j)<minc[j]) minc[j]=parts[i].GetPosition(j);
            avec[j]+=parts[i].GetPosition(j);
        }
    }
    avec=avec*(1.0/(double)Nlocal);
    cout<<"Stats of positions (min,ave,max)"<<endl;
    for (auto j=0;j<3;j++) {
        cout<<j<<" : "<<minc[j]<<", "<<avec[j]<<", "<<maxc[j]<<endl;
    }
    Double_t minphi,maxphi,avephi;
    minphi=1e16;maxphi=-1e16;avephi=0;
    for(auto i=0; i<Nlocal; i++) {
        if (parts[i].GetGravityPotential()>maxphi) maxphi=parts[i].GetGravityPotential();
        if (parts[i].GetGravityPotential()<minphi) minphi=parts[i].GetGravityPotential();
        avec+=parts[i].GetGravityPotential();
    }
    avephi=avephi*(1.0/(double)Nlocal);
    cout<<"Stats of potential "<<minphi<<" "<<maxphi<<" "<<avephi<<endl;

    time1=MyGetTime();
    pfof=SearchFullSet(libvelociraptorOpt,Nlocal,parts,ngroup);
    time1=MyGetTime()-time1;
    cout<<"TIME::"<<ThisTask<<" took "<<time1<<" to search "<<Nlocal<<" with "<<nthreads<<endl;
    nhalos=ngroup;
    //if caculating inclusive halo masses, then for simplicity, I assume halo id order NOT rearranged!
    //this is not necessarily true if baryons are searched for separately.
    if (libvelociraptorOpt.iInclusiveHalo) {
        pdatahalos=new PropData[nhalos+1];
        Int_t *numinhalos=BuildNumInGroup(Nlocal, nhalos, pfof);
        Int_t *sortvalhalos=new Int_t[Nlocal];
        Int_t *originalID=new Int_t[Nlocal];
        for (Int_t i=0;i<Nlocal;i++) {sortvalhalos[i]=pfof[i]*(pfof[i]>0)+Nlocal*(pfof[i]==0);originalID[i]=parts[i].GetID();parts[i].SetID(i);}
        Int_t *noffsethalos=BuildNoffset(Nlocal, parts, nhalos, numinhalos, sortvalhalos);
        GetInclusiveMasses(libvelociraptorOpt, Nlocal, parts, nhalos, pfof, numinhalos, pdatahalos, noffsethalos);
        qsort(parts,Nlocal,sizeof(Particle),IDCompare);
        delete[] numinhalos;
        delete[] sortvalhalos;
        delete[] noffsethalos;
        for (Int_t i=0;i<Nlocal;i++) parts[i].SetID(originalID[i]);
        delete[] originalID;
    }

    //now search for substructure
    if (libvelociraptorOpt.iSubSearch) {
        cout<<"Searching subset"<<endl;
        time1=MyGetTime();
        //if groups have been found (and localized to single MPI thread) then proceed to search for subsubstructures
        SearchSubSub(libvelociraptorOpt, Nlocal, parts, pfof,ngroup,nhalos,pdatahalos);
        time1=MyGetTime()-time1;
        cout<<"TIME::"<<ThisTask<<" took "<<time1<<" to search for substructures "<<Nlocal<<" with "<<nthreads<<endl;
    }
    pdata=new PropData[ngroup+1];
    //if inclusive halo mass required
    if (libvelociraptorOpt.iInclusiveHalo && ngroup>0) {
        CopyMasses(nhalos,pdatahalos,pdata);
        delete[] pdatahalos;
    }
    //need to add baryon interface

    //get mpi local hierarchy
    Int_t *nsub,*parentgid, *uparentgid,*stype;
    nsub=new Int_t[ngroup+1];
    parentgid=new Int_t[ngroup+1];
    uparentgid=new Int_t[ngroup+1];
    stype=new Int_t[ngroup+1];
    Int_t nhierarchy=GetHierarchy(libvelociraptorOpt,ngroup,nsub,parentgid,uparentgid,stype);
    CopyHierarchy(libvelociraptorOpt,pdata,ngroup,nsub,parentgid,uparentgid,stype);

    //calculate data and output
    numingroup=BuildNumInGroup(Nlocal, ngroup, pfof);
    pglist=SortAccordingtoBindingEnergy(libvelociraptorOpt,Nlocal,parts,ngroup,pfof,numingroup,pdata);//alters pglist so most bound particles first
    WriteProperties(libvelociraptorOpt,ngroup,pdata);
    WriteGroupCatalog(libvelociraptorOpt, ngroup, numingroup, pglist, parts);
    for (Int_t i=1;i<=ngroup;i++) delete[] pglist[i];
    delete[] pglist;

    delete[] parts;

    cout<<"VELOCIraptor returning."<< endl;
}
<|endoftext|>


<commit_before><commit_msg>cid#705946 dereference before null check<commit_after><|endoftext|>


<commit_before>#include "store-api.hh"
#include "profiles.hh"
#include "shared.hh"
#include "globals.hh"

#include <iostream>

using namespace nix;

std::string deleteOlderThan;
bool dryRun = false;

/* If `-d' was specified, remove all old generations of all profiles.
 * Of course, this makes rollbacks to before this point in time
 * impossible. */

void removeOldGenerations(std::string dir)
{
    if (access(dir.c_str(), R_OK) != 0) return;

    bool canWrite = access(dir.c_str(), W_OK) == 0;

    for (auto & i : readDirectory(dir)) {
        checkInterrupt();

        auto path = dir + "/" + i.name;
        auto type = i.type == DT_UNKNOWN ? getFileType(path) : i.type;

        if (type == DT_LNK && canWrite) {
            auto link = readLink(path);
            if (link.find("link") != string::npos) {
                printMsg(lvlInfo, format("removing old generations of profile %1%") % path);
                if (deleteOlderThan != "")
                    deleteGenerationsOlderThan(path, deleteOlderThan, dryRun);
                else
                    deleteOldGenerations(path, dryRun);
            }
        } else if (type == DT_DIR) {
            removeOldGenerations(path);
        }
    }
}

int main(int argc, char * * argv)
{
    bool removeOld = false;
    Strings extraArgs;

    return handleExceptions(argv[0], [&]() {
        initNix();

        parseCmdLine(argc, argv, [&](Strings::iterator & arg, const Strings::iterator & end) {
            if (*arg == "--help")
                showManPage("nix-collect-garbage");
            else if (*arg == "--version")
                printVersion("nix-collect-garbage");
            else if (*arg == "--delete-old" || *arg == "-d") removeOld = true;
            else if (*arg == "--delete-older-than") {
                removeOld = true;
                deleteOlderThan = getArg(*arg, arg, end);
            }
            else if (*arg == "--dry-run") dryRun = true;
            else
                extraArgs.push_back(*arg);
            return true;
        });

        auto profilesDir = settings.nixStateDir + "/profiles";
        if (removeOld) removeOldGenerations(profilesDir);

        // Run the actual garbage collector.
        if (!dryRun) {
            store = openStore(false);
            GCOptions options;
            options.action = GCOptions::gcDeleteDead;
            GCResults results;
            PrintFreed freed(true, results);
            store->collectGarbage(options, results);
        }
    });
}
<commit_msg>nix-collect-garbage: Handle ENOENT<commit_after>#include "store-api.hh"
#include "profiles.hh"
#include "shared.hh"
#include "globals.hh"

#include <iostream>

using namespace nix;

std::string deleteOlderThan;
bool dryRun = false;

/* If `-d' was specified, remove all old generations of all profiles.
 * Of course, this makes rollbacks to before this point in time
 * impossible. */

void removeOldGenerations(std::string dir)
{
    if (access(dir.c_str(), R_OK) != 0) return;

    bool canWrite = access(dir.c_str(), W_OK) == 0;

    for (auto & i : readDirectory(dir)) {
        checkInterrupt();

        auto path = dir + "/" + i.name;
        auto type = i.type == DT_UNKNOWN ? getFileType(path) : i.type;

        if (type == DT_LNK && canWrite) {
            std::string link;
            try {
                link = readLink(path);
            } catch (SysError & e) {
                if (e.errNo == ENOENT) continue;
            }
            if (link.find("link") != string::npos) {
                printMsg(lvlInfo, format("removing old generations of profile %1%") % path);
                if (deleteOlderThan != "")
                    deleteGenerationsOlderThan(path, deleteOlderThan, dryRun);
                else
                    deleteOldGenerations(path, dryRun);
            }
        } else if (type == DT_DIR) {
            removeOldGenerations(path);
        }
    }
}

int main(int argc, char * * argv)
{
    bool removeOld = false;
    Strings extraArgs;

    return handleExceptions(argv[0], [&]() {
        initNix();

        parseCmdLine(argc, argv, [&](Strings::iterator & arg, const Strings::iterator & end) {
            if (*arg == "--help")
                showManPage("nix-collect-garbage");
            else if (*arg == "--version")
                printVersion("nix-collect-garbage");
            else if (*arg == "--delete-old" || *arg == "-d") removeOld = true;
            else if (*arg == "--delete-older-than") {
                removeOld = true;
                deleteOlderThan = getArg(*arg, arg, end);
            }
            else if (*arg == "--dry-run") dryRun = true;
            else
                extraArgs.push_back(*arg);
            return true;
        });

        auto profilesDir = settings.nixStateDir + "/profiles";
        if (removeOld) removeOldGenerations(profilesDir);

        // Run the actual garbage collector.
        if (!dryRun) {
            store = openStore(false);
            GCOptions options;
            options.action = GCOptions::gcDeleteDead;
            GCResults results;
            PrintFreed freed(true, results);
            store->collectGarbage(options, results);
        }
    });
}
<|endoftext|>


<commit_before>/** @file
    @brief Implementation

    @date 2014

    @author
    Sensics, Inc.
    <http://sensics.com/osvr>
*/

// Copyright 2014 Sensics, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

// Internal Includes
#include <osvr/VRPNServer/VRPNDeviceRegistration.h>
#include <osvr/VRPNServer/GetVRPNConnection.h>
#include <osvr/Connection/ConnectionDevice.h>
#include <osvr/Connection/Connection.h>
#include <osvr/PluginHost/RegistrationContext.h>

// Library/third-party includes
// - none

// Standard includes
#include <algorithm>

namespace osvr {
namespace vrpnserver {
    class VRPNDeviceRegistration_impl : boost::noncopyable {
      public:
        VRPNDeviceRegistration_impl(
            pluginhost::PluginSpecificRegistrationContext &ctx)
            : m_ctx(ctx) {}

        pluginhost::PluginSpecificRegistrationContext &context() {
            return m_ctx;
        }

        std::string useDecoratedName(std::string const &name) {
            std::string ret = m_ctx.getName() + "/" + name;

            // Add if not already in the list.
            if (std::find(begin(m_names), end(m_names), ret) == end(m_names)) {
                m_names.push_back(ret);
            }
            return ret;
        }

        connection::ConnectionDevice::NameList const &getNames() const {
            return m_names;
        }

      private:
        pluginhost::PluginSpecificRegistrationContext &m_ctx;
        connection::ConnectionDevice::NameList m_names;
    };

    VRPNDeviceRegistration::VRPNDeviceRegistration(OSVR_PluginRegContext ctx)
        : m_ctx(pluginhost::PluginSpecificRegistrationContext::get(ctx)),
          m_impl(new VRPNDeviceRegistration_impl(m_ctx)) {}

    VRPNDeviceRegistration::VRPNDeviceRegistration(
        pluginhost::PluginSpecificRegistrationContext &context)
        : m_ctx(context), m_impl(new VRPNDeviceRegistration_impl(context)) {}

    /// Must be in .cpp file to handle pimpl deletion here.
    VRPNDeviceRegistration::~VRPNDeviceRegistration() {}

    std::string
    VRPNDeviceRegistration::useDecoratedName(std::string const &name) {
        return m_impl->useDecoratedName(name);
    }
    vrpn_Connection *VRPNDeviceRegistration::getVRPNConnection() {
        return ::osvr::vrpnserver::getVRPNConnection(m_ctx);
    }

    void VRPNDeviceRegistration::m_registerDevice(OSVR_DeviceUpdateCallback cb,
                                                  void *dev) {
        osvr::connection::ConnectionPtr conn =
            osvr::connection::Connection::retrieveConnection(m_ctx.getParent());

        auto names = m_impl->getNames();
        if (names.empty()) {
            throw std::logic_error(
                "Your VRPN device has to register at least one name!");
        }
        conn->registerAdvancedDevice(names, cb, dev);
    }

} // namespace vrpnserver
} // namespace osvr
<commit_msg>Move VRPN device registration into the impl class so we can store the ConnectionDevice pointer.<commit_after>/** @file
    @brief Implementation

    @date 2014

    @author
    Sensics, Inc.
    <http://sensics.com/osvr>
*/

// Copyright 2014 Sensics, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

// Internal Includes
#include <osvr/VRPNServer/VRPNDeviceRegistration.h>
#include <osvr/VRPNServer/GetVRPNConnection.h>
#include <osvr/Connection/ConnectionDevice.h>
#include <osvr/Connection/Connection.h>
#include <osvr/PluginHost/RegistrationContext.h>

// Library/third-party includes
// - none

// Standard includes
#include <algorithm>

namespace osvr {
namespace vrpnserver {
    class VRPNDeviceRegistration_impl : boost::noncopyable {
      public:
        VRPNDeviceRegistration_impl(
            pluginhost::PluginSpecificRegistrationContext &ctx)
            : m_ctx(ctx) {}

        pluginhost::PluginSpecificRegistrationContext &context() {
            return m_ctx;
        }

        std::string useDecoratedName(std::string const &name) {
            std::string ret = m_ctx.getName() + "/" + name;

            // Add if not already in the list.
            if (std::find(begin(m_names), end(m_names), ret) == end(m_names)) {
                m_names.push_back(ret);
            }
            return ret;
        }

        void registerDevice(OSVR_DeviceUpdateCallback cb,
            void *dev) {
            osvr::connection::ConnectionPtr conn =
                osvr::connection::Connection::retrieveConnection(m_ctx.getParent());

            auto const& names = getNames();
            if (names.empty()) {
                throw std::logic_error(
                    "Your VRPN device has to register at least one name!");
            }
            m_connDev = conn->registerAdvancedDevice(names, cb, dev);
        }

        connection::ConnectionDevice::NameList const &getNames() const {
            return m_names;
        }

      private:
        pluginhost::PluginSpecificRegistrationContext &m_ctx;
        connection::ConnectionDevice::NameList m_names;
        connection::ConnectionDevicePtr m_connDev;
    };

    VRPNDeviceRegistration::VRPNDeviceRegistration(OSVR_PluginRegContext ctx)
        : m_ctx(pluginhost::PluginSpecificRegistrationContext::get(ctx)),
          m_impl(new VRPNDeviceRegistration_impl(m_ctx)) {}

    VRPNDeviceRegistration::VRPNDeviceRegistration(
        pluginhost::PluginSpecificRegistrationContext &context)
        : m_ctx(context), m_impl(new VRPNDeviceRegistration_impl(context)) {}

    /// Must be in .cpp file to handle pimpl deletion here.
    VRPNDeviceRegistration::~VRPNDeviceRegistration() {}

    std::string
    VRPNDeviceRegistration::useDecoratedName(std::string const &name) {
        return m_impl->useDecoratedName(name);
    }
    vrpn_Connection *VRPNDeviceRegistration::getVRPNConnection() {
        return ::osvr::vrpnserver::getVRPNConnection(m_ctx);
    }

    void VRPNDeviceRegistration::m_registerDevice(OSVR_DeviceUpdateCallback cb,
                                                  void *dev) {
        m_impl->registerDevice(cb, dev);
    }

} // namespace vrpnserver
} // namespace osvr
<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: ConnectionPage.hxx,v $
 *
 *  $Revision: 1.5 $
 *
 *  last change: $Author: rt $ $Date: 2005-09-08 14:45:07 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    This library is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *    Lesser General Public License for more details.
 *
 *    You should have received a copy of the GNU Lesser General Public
 *    License along with this library; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/

#ifndef DBAUI_CONNECTIONPAGE_HXX
#define DBAUI_CONNECTIONPAGE_HXX

#ifndef DBAUI_CONNECTIONHELPER_HXX
#include "ConnectionHelper.hxx"
#endif
#ifndef _DBAUI_ADMINPAGES_HXX_
#include "adminpages.hxx"
#endif
#ifndef _UCBHELPER_CONTENT_HXX
#include <ucbhelper/content.hxx>
#endif
#ifndef _DBAUI_CURLEDIT_HXX_
#include "curledit.hxx"
#endif

//.........................................................................
namespace dbaui
{
//.........................................................................

    class IAdminHelper;
    //=========================================================================
    //= OConnectionTabPage
    //=========================================================================

    /** implements the connection page of teh data source properties dialog.
    */
    class OConnectionTabPage : public OConnectionHelper
    {
        ODsnTypeCollection* m_pCollection;  /// the DSN type collection instance
        sal_Bool            m_bUserGrabFocus : 1;
    protected:
        // connection
        FixedLine           m_aFL1;
        // user authentification
        FixedLine           m_aFL2;
        FixedText           m_aUserNameLabel;
        Edit                m_aUserName;
        CheckBox            m_aPasswordRequired;

        // jdbc driver
        FixedLine           m_aFL3;
        FixedText           m_aJavaDriverLabel;
        Edit                m_aJavaDriver;
        PushButton          m_aTestJavaDriver;

        // connection test
        PushButton          m_aTestConnection;

        // called when the test connection button was clicked
        DECL_LINK(OnBrowseConnections, PushButton*);
        DECL_LINK(OnTestJavaClickHdl,PushButton*);
        DECL_LINK(OnEditModified,Edit*);
    public:
        static  SfxTabPage* Create( Window* pParent, const SfxItemSet& _rAttrSet );
        virtual BOOL        FillItemSet (SfxItemSet& _rCoreAttrs);

        virtual void        implInitControls(const SfxItemSet& _rSet, sal_Bool _bSaveValue);

        virtual void SetServiceFactory(const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory > _rxORB)
        {
            OGenericAdministrationPage::SetServiceFactory(_rxORB);
            m_aET_Connection.initializeTypeCollection(m_xORB);
        }

        inline void enableConnectionURL() { m_aET_Connection.SetReadOnly(sal_False); }
        inline void disableConnectionURL() { m_aET_Connection.SetReadOnly(); }

        /** changes the connection URL.

The new URL must be of the type which is currently selected, only the parts which do not
            affect the type may be changed (compared to the previous URL).

        */
    protected:
        OConnectionTabPage(Window* pParent, const SfxItemSet& _rCoreAttrs);
            // nControlFlags ist eine Kombination der CBTP_xxx-Konstanten
        virtual ~OConnectionTabPage();

        // <method>OGenericAdministrationPage::fillControls</method>
        virtual void fillControls(::std::vector< ISaveValueWrapper* >& _rControlList);
        // <method>OGenericAdministrationPage::fillWindows</method>
        virtual void fillWindows(::std::vector< ISaveValueWrapper* >& _rControlList);
    private:
        // setting/retrieving the current connection URL
        // necessary because for some types, the URL must be decoded for display purposes

        /** enables the test connection button, if allowed
        */
        virtual bool checkTestConnection();

        /** opens the FileOpen dialog and asks for a FileName
            @param  _sFilterName
                The filter name.
            @param  _sExtension
                The filter extension.
        */
    };
//.........................................................................
}   // namespace dbaui
//.........................................................................

#endif // _DBAUI_DETAILPAGES_HXX_
<commit_msg>INTEGRATION: CWS dba23a (1.5.254); FILE MERGED 2007/03/13 08:42:12 fs 1.5.254.1: some slight re-factoring (class/method renaming), plus some rudimentary fix for #b6532894#<commit_after>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: ConnectionPage.hxx,v $
 *
 *  $Revision: 1.6 $
 *
 *  last change: $Author: kz $ $Date: 2007-05-10 10:21:49 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    This library is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *    Lesser General Public License for more details.
 *
 *    You should have received a copy of the GNU Lesser General Public
 *    License along with this library; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/

#ifndef DBAUI_CONNECTIONPAGE_HXX
#define DBAUI_CONNECTIONPAGE_HXX

#ifndef DBAUI_CONNECTIONHELPER_HXX
#include "ConnectionHelper.hxx"
#endif
#ifndef _DBAUI_ADMINPAGES_HXX_
#include "adminpages.hxx"
#endif
#ifndef _UCBHELPER_CONTENT_HXX
#include <ucbhelper/content.hxx>
#endif
#ifndef _DBAUI_CURLEDIT_HXX_
#include "curledit.hxx"
#endif

//.........................................................................
namespace dbaui
{
//.........................................................................

    class IDatabaseSettingsDialog;
    //=========================================================================
    //= OConnectionTabPage
    //=========================================================================

    /** implements the connection page of teh data source properties dialog.
    */
    class OConnectionTabPage : public OConnectionHelper
    {
        ODsnTypeCollection* m_pCollection;  /// the DSN type collection instance
        sal_Bool            m_bUserGrabFocus : 1;
    protected:
        // connection
        FixedLine           m_aFL1;
        // user authentification
        FixedLine           m_aFL2;
        FixedText           m_aUserNameLabel;
        Edit                m_aUserName;
        CheckBox            m_aPasswordRequired;

        // jdbc driver
        FixedLine           m_aFL3;
        FixedText           m_aJavaDriverLabel;
        Edit                m_aJavaDriver;
        PushButton          m_aTestJavaDriver;

        // connection test
        PushButton          m_aTestConnection;

        // called when the test connection button was clicked
        DECL_LINK(OnBrowseConnections, PushButton*);
        DECL_LINK(OnTestJavaClickHdl,PushButton*);
        DECL_LINK(OnEditModified,Edit*);

    public:
        static  SfxTabPage* Create( Window* pParent, const SfxItemSet& _rAttrSet );
        virtual BOOL        FillItemSet (SfxItemSet& _rCoreAttrs);

        virtual void        implInitControls(const SfxItemSet& _rSet, sal_Bool _bSaveValue);

        virtual void SetServiceFactory(const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory > _rxORB)
        {
            OGenericAdministrationPage::SetServiceFactory(_rxORB);
            m_aET_Connection.initializeTypeCollection(m_xORB);
        }

        inline void enableConnectionURL() { m_aET_Connection.SetReadOnly(sal_False); }
        inline void disableConnectionURL() { m_aET_Connection.SetReadOnly(); }

        /** changes the connection URL.

The new URL must be of the type which is currently selected, only the parts which do not
            affect the type may be changed (compared to the previous URL).

        */
    private:
        OConnectionTabPage(Window* pParent, const SfxItemSet& _rCoreAttrs);
            // nControlFlags ist eine Kombination der CBTP_xxx-Konstanten
        virtual ~OConnectionTabPage();

        // <method>OGenericAdministrationPage::fillControls</method>
        virtual void fillControls(::std::vector< ISaveValueWrapper* >& _rControlList);
        // <method>OGenericAdministrationPage::fillWindows</method>
        virtual void fillWindows(::std::vector< ISaveValueWrapper* >& _rControlList);

    private:
        /** enables the test connection button, if allowed
        */
        virtual bool checkTestConnection();
    };
//.........................................................................
}   // namespace dbaui
//.........................................................................

#endif // _DBAUI_DETAILPAGES_HXX_
<|endoftext|>


<commit_before>/*
* Copyright(c) Sophist Solutions, Inc. 1990-2017.  All rights reserved
*/
#ifndef _Stroika_Foundation_Math_Optimization_DownhillSimplexMinimization_inl_
#define _Stroika_Foundation_Math_Optimization_DownhillSimplexMinimization_inl_ 1

/*
 ********************************************************************************
 ***************************** Implementation Details ***************************
 ********************************************************************************
 */
#include "../LinearAlgebra/Matrix.h"
#include "../LinearAlgebra/Vector.h"

namespace Stroika {
    namespace Foundation {
        namespace Math {
            namespace Optimization {
                namespace DownhillSimplexMinimization {

                    /*
                     ********************************************************************************
                     ******************** DownhillSimplexMinimization::Run **************************
                     ********************************************************************************
                     */
                    template <typename FLOAT_TYPE>
                    Results<FLOAT_TYPE> Run (const MinimizationParametersType<FLOAT_TYPE>& initialValues, const TargetFunction<FLOAT_TYPE>& function2Minimize, const Options& options)
                    {
                        Results<FLOAT_TYPE> results{};

                        // Translated by hand from https://github.com/fchollet/nelder-mead/blob/master/nelder_mead.py - LGP 2017-02-20
                        auto nelder_mead = [](
                            const TargetFunction<FLOAT_TYPE>&             f,
                            const MinimizationParametersType<FLOAT_TYPE>& initialValues,
                            FLOAT_TYPE                                    step            = 0.1,
                            FLOAT_TYPE                                    no_improve_thr  = 10e-6,
                            unsigned int                                  no_improv_break = 10,
                            unsigned int                                  max_iter        = 0,
                            FLOAT_TYPE                                    alpha           = 1,
                            FLOAT_TYPE                                    gamma           = 2,
                            FLOAT_TYPE                                    rho             = -0.5,
                            FLOAT_TYPE                                    sigma           = 0.5) -> pair<MinimizationParametersType<FLOAT_TYPE>, FLOAT_TYPE> {

                            using namespace LinearAlgebra;

                            // init
                            size_t       dim       = x_start.size ();
                            FLOAT_TYPE   prev_best = f (x_start);
                            unsigned int no_improv = 0;
                            //Matrix res ()

                            //tmphack
                            return pair<MinimizationParametersType<FLOAT_TYPE>, FLOAT_TYPE>{};
                        };

                        return results;
                    }
                }
            }
        }
    }
}
#endif /*_Stroika_Foundation_Math_Optimization_DownhillSimplexMinimization_inl_*/
<commit_msg>a little progress on Optimization_DownhillSimplexMinimization<commit_after>/*
* Copyright(c) Sophist Solutions, Inc. 1990-2017.  All rights reserved
*/
#ifndef _Stroika_Foundation_Math_Optimization_DownhillSimplexMinimization_inl_
#define _Stroika_Foundation_Math_Optimization_DownhillSimplexMinimization_inl_ 1

/*
 ********************************************************************************
 ***************************** Implementation Details ***************************
 ********************************************************************************
 */
#include "../LinearAlgebra/Matrix.h"
#include "../LinearAlgebra/Vector.h"

namespace Stroika {
    namespace Foundation {
        namespace Math {
            namespace Optimization {
                namespace DownhillSimplexMinimization {

                    /*
                     ********************************************************************************
                     ******************** DownhillSimplexMinimization::Run **************************
                     ********************************************************************************
                     */
                    template <typename FLOAT_TYPE>
                    Results<FLOAT_TYPE> Run (const MinimizationParametersType<FLOAT_TYPE>& initialValues, const TargetFunction<FLOAT_TYPE>& function2Minimize, const Options& options)
                    {
                        Results<FLOAT_TYPE> results{};

                        // Translated by hand from https://github.com/fchollet/nelder-mead/blob/master/nelder_mead.py - LGP 2017-02-20
                        auto nelder_mead = [](
                            const TargetFunction<FLOAT_TYPE>&             f,
                            const MinimizationParametersType<FLOAT_TYPE>& x_start,
                            FLOAT_TYPE                                    step            = 0.1,
                            FLOAT_TYPE                                    no_improve_thr  = 10e-6,
                            unsigned int                                  no_improv_break = 10,
                            unsigned int                                  max_iter        = 0,
                            FLOAT_TYPE                                    alpha           = 1,
                            FLOAT_TYPE                                    gamma           = 2,
                            FLOAT_TYPE                                    rho             = -0.5,
                            FLOAT_TYPE                                    sigma           = 0.5) -> pair<MinimizationParametersType<FLOAT_TYPE>, FLOAT_TYPE> {

                            using namespace LinearAlgebra;

                            // init
                            size_t       dim       = x_start.size ();
                            FLOAT_TYPE   prev_best = f (x_start);
                            unsigned int no_improv = 0;

                            struct PartialResultType_ {
                                MinimizationParametersType<FLOAT_TYPE> fResults;
                                FLOAT_TYPE                             fScore;
                            };
                            vector<PartialResultType_> res = {PartialResultType_{x_start, prev_best}};
                            for (size_t i = 0; i != dim; ++i) {
                                MinimizationParametersType<FLOAT_TYPE> x = x_start;
                                x[i] += step;
                                FLOAT_TYPE score{f (x)};
                                res.push_back (PartialResultType_{x, score});
                            }

                            // Simplex iteration
                            while (true) {
                                std::sort (res.begin (), res.end (), [](auto l, auto r) { return l.fScore < r.fScore; });
                                FLOAT_TYPE best = res[0].fScore;

                                // break after max_iter
                                if (max_iter and iters >= max_iter) {
                                    return res[0];
                                }
                                iters += 1;
                            }

                            //tmphack
                            return pair<MinimizationParametersType<FLOAT_TYPE>, FLOAT_TYPE>{};
                        };

                        return results;
                    }
                }
            }
        }
    }
}
#endif /*_Stroika_Foundation_Math_Optimization_DownhillSimplexMinimization_inl_*/
<|endoftext|>