text:
#ifndef FITTING_HPP
#define FITTING_HPP

#include <stdio.h>
#include <iostream>
#include <iomanip>
#include <vector>
#include <algorithm>
#include <ctime>
#include <random>

#include <math.h>
#include <dlib/optimization.h>
#include <dlib/global_optimization.h>
#include <omp.h>

#include "densegp_gpu.hpp"
#include "multioutputgp_gpu.hpp"

typedef dlib::matrix<double,0,1> column_vector;

class GPWrapper {
  // class that will translate dlib column vectors into eigen vectors and vice
  // versa, such that the gp's logpost and logpost_deriv methods can be used
  // with dlib.

private:
  DenseGP_GPU& gp;

public:
// constructor
  GPWrapper(DenseGP_GPU& _gp) : gp(_gp) {}

  double logpost(column_vector theta) {
    std::vector<REAL> new_theta(theta.begin(), theta.end());
    double* ptr = &new_theta[0];
    vec theta_vec = Eigen::Map<vec>(ptr, new_theta.size());
    return gp.get_logpost(theta_vec);
  }

  column_vector logpost_deriv(column_vector theta) {
    std::vector<REAL> new_theta(theta.begin(), theta.end());
    double* ptr = &new_theta[0];
    vec theta_vec = Eigen::Map<vec>(ptr, new_theta.size());
    vec deriv(theta_vec.size());
    gp.logpost_deriv(deriv);
    std::vector<double> lpderiv(deriv.data(), deriv.data()+deriv.size());

    column_vector logpostderiv(lpderiv.size());
    // (is there really no better way of initializing dlib vector??)
    for (unsigned int i=0; i<lpderiv.size(); ++i) logpostderiv(i) = lpderiv[i];
    return logpostderiv;
  }

  vec theta() {
    return gp.get_theta();
  }

};

void fit_single_GP_MAP(DenseGP_GPU& gp, const int n_tries=15, const std::vector<double> theta0=std::vector<double>()) {
  // Fit the hyperparameters of a Gaussian Process by minimizing the
  // negative log-posterior.
  GPWrapper gpw(gp);

  std::vector< std::vector<double> > all_params;
  // if we're given an initial set of theta values, put this at the start of all_params
  if (theta0.size() > 0) {
    if (theta0.size() != gp.get_n_params() )
      throw std::runtime_error("length of theta0 must equal n_params of GP.");
    all_params.push_back(theta0);
  }

  // generate random starting values for theta
  std::random_device rd;
  std::mt19937 e2(rd());

  std::uniform_real_distribution<> dist(-2.5, 2.5);

  for (int itry=all_params.size(); itry<n_tries; ++itry) {
    std::vector<REAL> v(gp.get_n_params());
    std::generate(v.begin(), v.end(), [&dist, &e2](){ return dist(e2);});

    all_params.push_back(v);
  }

  std::vector<double> minvals;
  std::vector<vec> thetavals;
  for (auto it = all_params.begin(); it != all_params.end(); it++) {

    double minf; // minimum objective function from optimizer
    /// copy the std::vector into dlib column_matrix
    column_vector theta((*it).size());
    for (unsigned int i=0; i<(*it).size(); ++i) theta(i) = (*it)[i];
    try {
      minf = find_min(dlib::bfgs_search_strategy(),  // Use BFGS search algorithm
             dlib::objective_delta_stop_strategy(1e-9), // Stop when the change in func value is less than 1e-7
             [&gpw](const column_vector& a) {
              return gpw.logpost(a);
            },
            [&gpw](const column_vector& b) {
              return gpw.logpost_deriv(b);
            },
            theta, -1);
      minvals.push_back(minf);
      thetavals.push_back(gpw.theta());
    } catch(std::exception &e) {
      std::cout << "dlib optimization failed: " << e.what() << std::endl;
    }
  }

  if (minvals.size() == 0) {
    std::cout<<"All minimization tries failed"<<std::endl;
    gp.reset_theta_fit_status();
  } else {
      int minvalIndex = std::min_element(minvals.begin(),minvals.end()) - minvals.begin();
      vec best_theta = thetavals.at(minvalIndex);
      gp.fit(best_theta);

  }

  return;
}

void fit_GP_MAP(MultiOutputGP_GPU& mogp, const int n_tries=15, const std::vector<double> theta0=std::vector<double>()) {
  #pragma omp parallel for
  for (unsigned int i=0; i< mogp.n_emulators(); ++i) {
    fit_single_GP_MAP(*(mogp.get_emulator(i)), n_tries, theta0);
  }
  return;
}

#endif

max_stars_repo_name: EXAUQ/mogp-emulator

max_issues_repo_name: EXAUQ/mogp-emulator

max_forks_repo_name: EXAUQ/mogp-emulator


text:
/// @brief gazebo_ros_controlプラグインのバグ修正版(本家へマージ予定)
/*
Copyright (c) 2017 TOYOTA MOTOR CORPORATION
All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted (subject to the limitations in the disclaimer
below) provided that the following conditions are met:

* Redistributions of source code must retain the above copyright notice, this
  list of conditions and the following disclaimer.

* Redistributions in binary form must reproduce the above copyright notice,
  this list of conditions and the following disclaimer in the documentation
  and/or other materials provided with the distribution.

* Neither the name of the copyright holder nor the names of its contributors may be used
  to endorse or promote products derived from this software without specific
  prior written permission.

NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED BY THIS
LICENSE. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
DAMAGE.
*/
#include <boost/bind.hpp>
#include "hsrb_gazebo_ros_control_plugin.hpp"

namespace hsrb_gazebo_plugins {

void HsrbGazeboRosControlPlugin::Load(gazebo::physics::ModelPtr parent, sdf::ElementPtr sdf) {
  GazeboRosControlPlugin::Load(parent, sdf);
  ROS_INFO_STREAM_NAMED("hsrb_gazebo_ros_control", "Loading hsrb_gazebo_ros_control plugin");
  // Reconnect the world update event
#if GAZEBO_MAJOR_VERSION >= 8
  update_connection_.reset();
#else
  gazebo::event::Events::DisconnectWorldUpdateBegin(update_connection_);
#endif
  update_connection_ = gazebo::event::Events::ConnectWorldUpdateBegin(boost::bind(&HsrbGazeboRosControlPlugin::Update,
                                                                                this));
}

void HsrbGazeboRosControlPlugin::Update() {
#if GAZEBO_MAJOR_VERSION >= 8
  gazebo::common::Time gz_time_now = parent_model_->GetWorld()->SimTime();
#else
  gazebo::common::Time gz_time_now = parent_model_->GetWorld()->GetSimTime();
#endif
  ros::Time sim_time_ros(gz_time_now.sec, gz_time_now.nsec);

  // This is only the difference from the original gazebo_ros_control
  // We call the readSim() function before the every update loop
  robot_hw_sim_->readSim(sim_time_ros, sim_time_ros - last_write_sim_time_ros_);

  GazeboRosControlPlugin::Update();
}

// Register this plugin with the simulator
GZ_REGISTER_MODEL_PLUGIN(HsrbGazeboRosControlPlugin);

}  // namespace hsrb_gazebo_plugins

ext: cpp


text:
#include "buffer-string.h"

#include <string>
#include <boost/algorithm/string.hpp>

namespace readline {

void BufferString::PopBack() {
  if (content_.length() > 0) {
    content_.pop_back();
  }
}

const std::wstring& BufferString::WStr() const {
  return content_;
}

BufferString& BufferString::operator=(const std::wstring& content) {
  content_ = content;

  return *this;
}

BufferString& BufferString::operator=(const std::string& content) {
  content_ = str2wstr(content);

  return *this;
}

BufferString operator+(const BufferString& bufstr, wchar_t c) {
  std::wstring str = bufstr.content_ + c;

  return BufferString(str);
}

BufferString& BufferString::operator+=(wchar_t c) {
  content_ += c;

  return *this;
}

void BufferString::RemoveChar(int n) {
  if (n >= int(content_.length() - 1)) {
    content_.pop_back();
  } else if (n == 0) {
    content_ = content_.substr(1);
  } else if (n > 0 && n < int(content_.length())) {
    content_ = content_.substr(0, n) + content_.substr(n+1);
  }
}

void BufferString::AddChar(wchar_t c, int n) {
  if (content_.empty()) {
    content_ = c;
    return;
  }

  if (n >= int(content_.length())) {
    content_ += c;
  } else if (n == 0) {
    content_ = c + content_;
  } else if (n > 0 && n < int(content_.length())) {
    content_ = content_.substr(0, n) + c + content_.substr(n);
  }
}

void BufferString::AddString(const std::wstring str, int n) {
  if (content_.empty()) {
    content_ = str;
    return;
  }

  if (n >= int(content_.length())) {
    content_ += str;
  } else if (n == 0) {
    content_ = str + content_;
  } else if (n > 0 && n < int(content_.length())) {
    content_ = content_.substr(0, n) + str + content_.substr(n);
  }
}

void BufferString::ReplaceStringInterval(const std::wstring str,
    int start, int end) {
  if (content_.empty()) {
    content_ = str;
    return;
  }

  if (end >= int(content_.length()) && start <= 0) {
    content_ = str;
  } else if (end >= int(content_.length())) {
    content_ = content_.substr(0, start) + str;
  } else if (start <= 0) {
    content_ = str + content_.substr(end);
  } else {
    content_ = content_.substr(0, start) + str + content_.substr(end);
  }
}

bool BufferString::IsTokenSeparator(int pos) {
  if (pos >= static_cast<int>(content_.length()) || pos < 0) {
    return true;
  }

  char c = content_[pos];
  if ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') ||
      (c >= '0' && c <= '9')) {
    return false;
  }

  if (pos > 1 && pos < static_cast<int>(content_.length() - 1)) {
    if ((c == '\\' && content_[pos + 1] == ' ') ||
        (c == ' ' && content_[pos - 1] == '\\')) {
      return false;
    }
  }

  return true;
}

int BufferString::EndTokenPos(int n) {
  bool start_space = true;
  int pos = n;

  while ((start_space || !IsTokenSeparator(pos)) &&
      (pos <= static_cast<int>(content_.length()))) {
    if (content_[pos] != ' ') {
      start_space = false;
    }

    ++pos;
  }

  if (pos >= static_cast<int>(content_.length())) {
    return content_.length();
  }

  return pos;
}

int BufferString::StartTokenPos(int n) {
  if (n <= 1) {
    return 0;
  }

  bool start_space = true;
  int pos = n;

  while ((start_space || !IsTokenSeparator(pos - 1)) && (pos > 0)) {
    if (content_[pos - 1] != ' ') {
      start_space = false;
    }

    --pos;
  }

  return pos;
}

bool BufferString::IsLastToken(int n) {
  int pos = EndTokenPos(n);

  if (pos == content_.length()) {
    return true;
  }

  return false;
}

bool BufferString::IsEscapeSpace(int n) {
  if (content_.length() <= 1) {
    return false;
  }

  if (n > static_cast<int>(content_.length() - 1)) {
    n = content_.length() - 1;
  }

  if (content_[n] == ' ' && content_[n] == '\\') {
    return true;
  }

  return false;
}

int BufferString::StartArgPos(int n) {
  if (n <= 1) {
    return 0;
  }

  int pos = n;

  // to avoid problems in the case where you have spaces in front of the
  // argument, and start arg will get the next arg, and the arg we want
  // is the arg before
  if (pos > 0) {
    if (content_[pos] == ' ' && content_[pos - 1] != ' ') {
      --pos;
    } else if (content_[pos] == ' ' && content_[pos - 1] == ' ') {
      // if the current selected char is a whitespace, and the back char
      // is a whitespace too, return the current position
      return pos;
    }
  }

  while ((content_[pos] != ' ' ||IsEscapeSpace(pos)) && (pos > 0)) {
    --pos;
  }

  // when pos is not zero, is counts the whitespace
  // so it 'eat' one whitespace
  return (pos > 0? pos + 1:0);
}

int BufferString::EndArgPos(int n) {
  int pos = n;

  while ((content_[pos] != ' ' ||IsEscapeSpace(pos)) &&
      (pos <= static_cast<int>(content_.length()))) {
    ++pos;
  }

  if (pos >= static_cast<int>(content_.length())) {
    return content_.length();
  }

  return pos;
}

std::wstring BufferString::GetTrimToken(int n) {
  int start = StartArgPos(n);
  int end = EndArgPos(n);
  std::wstring str = content_.substr(start, end - start);
  boost::trim(str);
  return str;
}

std::wstring BufferString::GetSlice(int start, int end) {
  return content_.substr(start, end - start);
}

void BufferString::RemoveSubStr(int from, int to) {
  content_ = content_.erase(from, to - from);
}

std::wostream& operator<<(std::wostream& stream, BufferString& buf_str) {
  stream  << buf_str.content_;

  return stream;
}

}  // namespace readline

ext: cc


text:
#include <networklib/stream.hpp>

#include <memory>
#include <string>
#include <utility>

#include <boost/asio.hpp>
#include <boost/date_time/posix_time/posix_time_types.hpp>
#include <boost/system/error_code.hpp>

#include <networklib/detail/encode.hpp>
#include <networklib/detail/headers.hpp>
#include <networklib/detail/read_socket.hpp>
#include <networklib/detail/status_line.hpp>
#include <networklib/response.hpp>
#include <networklib/socket.hpp>

namespace network {

auto Stream::Stream_impl::launch(Request const& request, Callback callback)
    -> std::shared_ptr<Stream_impl>
{
    auto stream_ptr = std::make_shared<Stream_impl>(
        request.host, request.HTTP_protocol, std::move(callback));

    // Storing a shared_ptr to the stream so actions_ and socket_ are not
    // destroyed before this handler is.
    boost::asio::async_write(
        stream_ptr->socket_.get(), boost::asio::buffer(to_string(request)),
        [stream_ptr](auto ec, auto) { stream_ptr->process_chunks(ec); });

    return stream_ptr;
}

void Stream::Stream_impl::kill() { alive_ = false; }

Stream::Stream_impl::Stream_impl(std::string const& host,
                                 std::string const& service,
                                 Callback callback)
    : socket_{Socket::make_connection(host, service)},
      callback_{std::move(callback)}
{}

void Stream::Stream_impl::process_chunks(boost::system::error_code ec)
{
    if (ec != boost::system::errc::success)
        throw boost::system::system_error{ec};

    auto read_buffer = boost::asio::streambuf{};

    check_status(detail::parse_status_line(
        detail::read_status_line_bytes(socket_, read_buffer)));

    {  // Read headers and verify tranfer-encoding is chunked.
        auto const headers = detail::parse_headers(
            detail::read_header_field_bytes(socket_, read_buffer));
        if (get(headers, "transfer-encoding") != "chunked")
            throw std::runtime_error{"Stream: transfer-encoding not chunked."};
    }

    auto message_str = std::string{};
    while (alive_) {
        auto pos = std::string::npos;
        while (pos == std::string::npos) {
            message_str.append(detail::read_chunk(socket_, read_buffer));
            pos = message_str.find("\r\n");
        }

        if (pos > 1)
            callback_(Response{message_str.substr(0, pos)});

        message_str.erase(0, pos + 2);
    }
}

auto Stream::launch(Request const& request, Callback callback) -> Stream
{
    return Stream{Stream_impl::launch(request, std::move(callback))};
}

Stream::Stream(std::shared_ptr<Stream_impl> ptr) : ptr_{std::move(ptr)} {}

Stream::~Stream() { ptr_->kill(); }

}  // namespace network


text:
#include "DoubleOutputRedirect.h"
#include <vector>
#include <string>
#include <cstring>

#include <iostream>
#include <unistd.h>
#include <stdio.h>
#include <sys/wait.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <stdlib.h>
#include <fcntl.h>

#include <algorithm>
#include <boost/algorithm/string.hpp>

using namespace std;
using namespace boost;

// class DoubleOutputRedirect : public Connector {
//  public:

// Default Constructor
DoubleOutputRedirect::DoubleOutputRedirect() : Connector() {
    data = "";
}

// Constructor: Sets the left and right-hand sides of the >> connector.
DoubleOutputRedirect::DoubleOutputRedirect(Base* left, Base* right) {
    lhs = left;
    rhs = right;
    data = ">>";
}

void DoubleOutputRedirect::setdoutVector(std::string str1) {

  std::string str2 = " ";
  for(unsigned i = 0; i < str1.length(); ++i) {
      if(str1.at(i) == ';') {
        str1.insert(i, str2);
        i++;
      }
  }

  typedef vector< string > split_vector_type;

  split_vector_type cnts;
  split( cnts, str1, is_any_of(" "), token_compress_on );
  for(unsigned i = 0; i < cnts.size(); ++i) {
      douts.push_back(cnts.at(i));
  }

  for(unsigned i = 0; i < douts.size(); ++i ) {
    if(douts.at(i) == ">>") {
        tempDOR.push_back(douts.at(i));
    }
  }

  doutV.reserve(tempDOR.size());
  for(unsigned index = 0; index < tempDOR.size(); ++index) {
      doutV.push_back((char*)tempDOR[index].c_str());
  }
}

// Passes in rhs as input and standard output(1)
// Calls execute on lhs to execute the actual command.
bool DoubleOutputRedirect::execute() {
    // Sets input to the rhs
    int out = open((rhs->getData()).c_str(), O_WRONLY | O_APPEND | O_CREAT, S_IRUSR | S_IRGRP | S_IWGRP | S_IWUSR);

    pid_t pid = fork();
    if(pid == 0) {
        if(dup2(out, 1) == -1) {
            close(out);
            exit(1);
        }
        if(lhs->execute() == false) {
            close(out);
            exit(1);
        }
        exit(0);
    } else if(pid > 0) { // Parent Process
        int status;
        waitpid(pid, &status, 0);
        if(WEXITSTATUS(status) == 1) {
            return false;
        }
    } else {
        // cout << "ENTERED PERR" << endl;
        perror("Fork Failed"); // Failed
        exit(1);
    }

    close(out);

    return true;
}

void DoubleOutputRedirect::display() {
    for(unsigned i = 0; i < doutV.size(); ++i) {
        std::cout << doutV.at(i) << std::endl;
    }
}

max_stars_repo_name: jschopick/HammerShell

max_issues_repo_name: jschopick/HammerShell

max_forks_repo_name: jschopick/HammerShell


text:
/////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Ion Gaztanaga  2006-2013
//
// Distributed under the Boost Software License, Version 1.0.
//    (See accompanying file LICENSE_1_0.txt or copy at
//          http://www.boost.org/LICENSE_1_0.txt)
//
// See http://www.boost.org/libs/intrusive for documentation.
//
/////////////////////////////////////////////////////////////////////////////

#ifndef BOOST_CONFIG_HPP
#include <boost/config.hpp>
#endif

#ifdef BOOST_MSVC

   #pragma warning (push)
   //
   //'function' : resolved overload was found by argument-dependent lookup
   //A function found by argument-dependent lookup (Koenig lookup) was eventually
   //chosen by overload resolution.
   //
   //In Visual C++ .NET and earlier compilers, a different function would have
   //been called. To pick the original function, use an explicitly qualified name.
   //

   //warning C4275: non dll-interface class 'x' used as base for
   //dll-interface class 'Y'
   #pragma warning (disable : 4275)
   //warning C4251: 'x' : class 'y' needs to have dll-interface to
   //be used by clients of class 'z'
   #pragma warning (disable : 4251)
   #pragma warning (disable : 4675)
   #pragma warning (disable : 4996)
   #pragma warning (disable : 4503)
   #pragma warning (disable : 4284) // odd return type for operator->
   #pragma warning (disable : 4244) // possible loss of data
   #pragma warning (disable : 4521) ////Disable "multiple copy constructors specified"
   #pragma warning (disable : 4127) //conditional expression is constant
   #pragma warning (disable : 4146)
   #pragma warning (disable : 4267) //conversion from 'X' to 'Y', possible loss of data
   #pragma warning (disable : 4541) //'typeid' used on polymorphic type 'boost::exception' with /GR-
   #pragma warning (disable : 4512) //'typeid' used on polymorphic type 'boost::exception' with /GR-
   #pragma warning (disable : 4522)
   #pragma warning (disable : 4706) //assignment within conditional expression
   #pragma warning (disable : 4710) // function not inlined
   #pragma warning (disable : 4714) // "function": marked as __forceinline not inlined
   #pragma warning (disable : 4711) // function selected for automatic inline expansion
   #pragma warning (disable : 4786) // identifier truncated in debug info
   #pragma warning (disable : 4996) // "function": was declared deprecated
#endif

//#define BOOST_INTRUSIVE_USE_ITERATOR_FACADE
//#define BOOST_INTRUSIVE_USE_ITERATOR_ENABLE_IF_CONVERTIBLE

ext: hpp

max_stars_repo_name: rudylee/expo

max_issues_repo_name: rudylee/expo

max_forks_repo_name: rudylee/expo


text:
#include <document.h>
#include <error/en.h>
#include <filereadstream.h>
#include <writer.h>

#include <boost/algorithm/string/replace.hpp>
#include <boost/regex.hpp>
#include <fstream>
#include <geojson.hpp>
#include <iostream>
#include <string>

int main() {
  constexpr char geoData[]{
      "~/Documents/PlatformIO/Projects/LED Clock "
      "GPS/SDCard/combined-with-oceans.json"};
  constexpr char tzFile[]{
      "~/Documents/PlatformIO/Projects/GeoJson/"
      "data/zones.json"};
  constexpr char outDir[]{
      "~/Documents/PlatformIO/Projects/LED Clock "
      "GPS/SDCard/TimeZoneJson/"};

  geojson_t geojson;
  if (!geojson.convert(geoData)) {
    return -1;
  }

  std::cout << "parsed geojson" << std::endl;

  const auto fp = fopen(tzFile, "r");
  if (!fp) {
    std::cout << "cannot open " << tzFile << std::endl;
    return -1;
  }

  char readBuffer[65536];
  rapidjson::FileReadStream is(fp, readBuffer, sizeof(readBuffer));

  rapidjson::Document tzJson;
  if (tzJson.ParseStream(is).HasParseError()) {
    fprintf(stderr, "Error(offset %u): %s\n",
            (unsigned)tzJson.GetErrorOffset(),
            GetParseError_En(tzJson.GetParseError()));
    return -1;
  }
  fclose(fp);

  std::cout << "loaded time zone data " << std::endl;

  for (const auto& feature : geojson.m_feature) {
    const auto geometry = feature.m_geometry[0];

    std::cout << feature.m_tzid << std::endl;

    rapidjson::Document json;
    json.SetObject();
    auto jAlloc { json.GetAllocator() };

    json.AddMember("tzName", rapidjson::StringRef(feature.m_tzid), jAlloc);
    json.AddMember("posix", rapidjson::StringRef(tzJson[feature.m_tzid].GetString()), jAlloc);

    rapidjson::Value limitList(rapidjson::kArrayType);
    rapidjson::Value polygonList(rapidjson::kArrayType);

    for (uint32_t polygonNum{0}; const auto& polygon : geometry.m_polygons) {
      std::string minLong{"181.0"}, minLat{"91.0"};
      std::string maxLong{"-181.0"}, maxLat{"-91.0"};
      rapidjson::Value paths(rapidjson::kArrayType);
      for (bool firstPath{true}; const auto& path : polygon) {
        rapidjson::Value coords(rapidjson::kArrayType);
        for (const auto& p : path) {
          rapidjson::Value coord(rapidjson::kObjectType);
          coord.AddMember("lat", rapidjson::StringRef(p.latStr), jAlloc);
          coord.AddMember("long", rapidjson::StringRef(p.longStr), jAlloc);
          coords.PushBack(coord, jAlloc);
          if (firstPath) {
            minLong = (std::stod(minLong) < p.longNum) ? minLong : p.longStr;
            maxLong = (std::stod(maxLong) > p.longNum) ? maxLong : p.longStr;
            minLat = (std::stod(minLat) < p.latNum) ? minLat : p.latStr;
            maxLat = (std::stod(maxLat) > p.latNum) ? maxLat : p.latStr;
          }
        }
        firstPath = false;
        paths.PushBack(coords, jAlloc);
      }

      const auto polygonID = "polygon" + std::to_string(polygonNum++);
      rapidjson::Value limit(rapidjson::kObjectType);
      limit.AddMember("minLat", rapidjson::StringRef(minLat), jAlloc);
      limit.AddMember("minLong", rapidjson::StringRef(minLong), jAlloc);
      limit.AddMember("maxLat", rapidjson::StringRef(maxLat), jAlloc);
      limit.AddMember("maxLong", rapidjson::StringRef(maxLong), jAlloc);
      limit.AddMember("id", rapidjson::StringRef(polygonID), jAlloc);
      limitList.PushBack(limit, jAlloc);
      rapidjson::Value polygonN(rapidjson::kObjectType);
      polygonN.AddMember(rapidjson::Value(polygonID, jAlloc).Move(), paths, jAlloc);
      polygonList.PushBack(polygonN, jAlloc);
    }

    json.AddMember("limit", limitList, jAlloc);
    json.AddMember("polygon", polygonList, jAlloc);

    rapidjson::StringBuffer buffer;
    rapidjson::Writer<rapidjson::StringBuffer> writer(buffer);
    json.Accept(writer);

    std::string jsonData { buffer.GetString(), buffer.GetSize() };

    boost::regex numStr(R"re("([-.0-9]+)")re");
    auto outJson = boost::regex_replace(jsonData, numStr, "$1");

    std::ofstream outFile(
        outDir +
        boost::replace_all_copy(feature.m_tzid, "/", "-") +
        ".json");
    outFile << outJson << std::endl;
  }

  return 0;
}

max_stars_repo_name: abaskin/ESPGPSTimeZone

max_issues_repo_name: abaskin/ESPGPSTimeZone

max_forks_repo_name: abaskin/ESPGPSTimeZone


text:
// The Open Trading Project - open-trading.org
//
// Copyright (c) 2011 Martin Tapia - martin.tapia@open-trading.org
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
//    * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
//
//    * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

#ifndef __SERVER_SERVER__
#define __SERVER_SERVER__

#include <boost/noncopyable.hpp>
#include <QApplication>

namespace Conf
{
    class Conf;
}

namespace Server
{
    namespace Qt
    {
        class Network;
    }
    class Ui;
    class TradingManager;

    class Server :
        private boost::noncopyable
    {
        public:
            explicit Server(int& ac, char** av);
            ~Server();
            int Run();
            Conf::Conf& GetConf();
            Ui& GetUi();
            Qt::Network& GetNetwork();
            TradingManager& GetTradingManager();
        private:
            Conf::Conf* _conf;
            QCoreApplication* _app;
            Ui* _ui;
            Qt::Network* _network;
            TradingManager* _tradingManager;
    };
}

#endif

max_stars_repo_name: paps/Open-Trading

max_issues_repo_name: paps/Open-Trading

max_forks_repo_name: paps/Open-Trading


text:
#include "scene.h"
#include "sphere.h"
#include "plane.h"

#include <Eigen/Geometry>
#include <filesystem/resolver.h>

Scene::Scene(const PropertyList& props) {
    m_backgroundColor = props.getColor("background", Color3f(0.6));
}

void Scene::clear()
{
    m_shapeList.clear();
    m_lightList.clear();
    if(m_camera)
        delete m_camera;
    m_camera = nullptr;
    if(m_integrator)
        delete m_integrator;
    m_integrator = nullptr;
}

/** Search for the nearest intersection between the ray and the object list */
void Scene::intersect(const Ray& ray, Hit& hit) const
{
    /// TODO: iterate on the object list and test for intersection
    ///       => if any, keep the closest one

    for (Shape* s: this->shapeList()){
        s->intersect(ray, hit);
    }
}

void Scene::addChild(Object *obj) {
    switch (obj->getClassType()) {
        case EShape: {
                Shape *shape = static_cast<Shape *>(obj);
                m_shapeList.push_back(shape);
            }
            break;

        case ELight: {
                Light *light = static_cast<Light *>(obj);
                m_lightList.push_back(light);
            }
            break;

        case ECamera:
            if (m_camera)
                throw RTException("There can only be one camera per scene!");
            m_camera = static_cast<Camera *>(obj);
            break;

        case EIntegrator:
            if (m_integrator)
                throw RTException("There can only be one integrator per scene!");
            m_integrator = static_cast<Integrator *>(obj);
            break;

        default:
            throw RTException("Scene::addChild(<%s>) is not supported!",
                classTypeName(obj->getClassType()));
    }
}

std::string Scene::toString() const {
    std::string shapes;
    for (size_t i=0; i<m_shapeList.size(); ++i) {
        shapes += std::string("  ") + indent(m_shapeList[i]->toString(), 2);
        if (i + 1 < m_shapeList.size())
            shapes += ",";
        shapes += "\n";
    }
    std::string lights;
    for (size_t i=0; i<m_lightList.size(); ++i) {
        lights += std::string("  ") + indent(m_lightList[i]->toString(), 2);
        if (i + 1 < m_lightList.size())
            lights += ",";
        lights += "\n";
    }

    return tfm::format(
        "Scene[\n"
        "  background = %s,\n"
        "  integrator = %s,\n"
        "  camera = %s,\n"
        "  shapes = {\n"
        "  %s  }\n"
        "  lights = {\n"
        "  %s  }\n"
        "]",
        m_backgroundColor.toString(),
        indent(m_integrator->toString()),
        indent(m_camera->toString()),
        indent(shapes, 2),
        indent(lights, 2)
    );
}

REGISTER_CLASS(Scene, "scene")


text:
#include "Generic/common/leak_detection.h"

#include <string>
#include <set>

#include "Generic/common/Symbol.h"
#include "DistributionalKnowledgeTable.h"
#include "DistributionalKnowledgeClass.h"
#include <boost/shared_ptr.hpp>

#include "DistributionalUtil.h"
#include "DistributionalClusterClass.h"
#include "DistributionalAssocPropClass.h"
#include "DistributionalCausalClass.h"
#include "DistributionalAnchorArgClass.h"

/*
  10/15/2013 : Yee Seng Chan
  The *Fea variables are temporarily there for an alternative way of representing scores, as a set of inequalities,
  instead of as bins as currently represented by the *SB variables.
*/

// distributional knowledge is not yet populated. This is invoked from the default constructor of EventAAObservation
DistributionalKnowledgeClass DistributionalKnowledgeClass::nullDistributionalKnowledge() {
	DistributionalKnowledgeClass c;

	c._anchor = Symbol();
	c._mappedAnchor = Symbol();
	c._anchorPosTag = Symbol();
	c._arg = Symbol();
	c._argPosTag = Symbol();
	c._eventType = Symbol();
	c._useFeatureVariant = Symbol();

	return c;
}

// default constructor
DistributionalKnowledgeClass::DistributionalKnowledgeClass() {}

// populates the following variables:
// _useFeatureVariant
// _anchor	_anchorPosTag	_arg	_argPosTag	_eventType
// _mappedAnchor
// _subScore , _objScore , _avgSubObjScore , _maxSubObjScore
// _subScoreFea , _subScoreSB , _objScoreFea , _objScoreSB , _avgSubObjScoreFea , _avgSubObjScoreSB , _maxSubObjScoreFea , _maxSubObjScoreSB
// _anchorArgSim , _anchorArgSimFea , _anchorArgSimSB
// _anchorArgPmi , _anchorArgPmiFea , _anchorArgPmiSB
// _anchorSubCid , _anchorObjCid , _anchorAllSubCids , _anchorAllObjCids
DistributionalKnowledgeClass::DistributionalKnowledgeClass(const Symbol& anchor, const Symbol& anchorPosTag, const Symbol& arg, const Symbol& argPosTag, const Symbol& eventType) {
	_useFeatureVariant = Symbol(L"anchor SB");		// plausible values: 'anchor SB' , 'anchor bins'

	_anchor = anchor;
	_anchorPosTag = anchorPosTag;	// pos-tag of anchor
	_arg = arg;
	_argPosTag = argPosTag;		// pos-tag of candidate argument
	_eventType = eventType;

	// is the anchor a noun, verb, adjective, or others
	Symbol anchorPosType = DistributionalUtil::determinePosType(_anchorPosTag);

	_mappedAnchor = assignMappedAnchor(_anchor, anchorPosType);

	// let's now set the different types of scores
	_dCluster = boost::shared_ptr<DistributionalClusterClass>(_new DistributionalClusterClass(_mappedAnchor, _arg));

	_dAssocProp = boost::shared_ptr<DistributionalAssocPropClass>(_new DistributionalAssocPropClass(_mappedAnchor, _arg));

	_dCausal = boost::shared_ptr<DistributionalCausalClass>(_new DistributionalCausalClass(_mappedAnchor, _arg));

	_dAnchorArg = boost::shared_ptr<DistributionalAnchorArgClass>(_new DistributionalAnchorArgClass(_mappedAnchor, anchorPosTag, _arg, argPosTag));
}

// populates: _causalScore , _causalScoreFea , _causalScoreSB
void DistributionalKnowledgeClass::assignCausalFeatures(const std::set<SymbolPair>& feas) {
	_dCausal->assignCausalFeatures(feas);
}

// populates: _assocPropSim , _assocPropSimFea , _assocPropSimSB , _assocPropPmi , _assocPropPmiFea , _assocPropPmiSB
void DistributionalKnowledgeClass::assignAssocPropFeatures(const std::set<SymbolPair>& feas) {
	_dAssocProp->assignAssocPropFeatures(feas);
}

bool DistributionalKnowledgeClass::useFeatureVariant(const Symbol& fv) {
	if(fv == _useFeatureVariant)
		return true;
	else
		return false;
}

// as mentioned in the header file, we currently always set _mappedAnchor to _anchor
Symbol DistributionalKnowledgeClass::assignMappedAnchor(const Symbol& anchor, const Symbol& posType) {
	return anchor;
}

max_stars_repo_name: BBN-E/serif

max_issues_repo_name: BBN-E/serif

max_forks_repo_name: BBN-E/serif


text:
#include "geometryfunc.h"

#include <pybind11/eigen.h>
#include <pybind11/numpy.h>
#include <pybind11/stl.h>

#include <Eigen/Dense>

#include <isce3/antenna/Frame.h>
#include <isce3/antenna/geometryfunc.h>
#include <isce3/core/Ellipsoid.h>
#include <isce3/core/Quaternion.h>
#include <isce3/core/Vector.h>
#include <isce3/geometry/DEMInterpolator.h>

// Aliases
namespace py = pybind11;
namespace ant = isce3::antenna;
using namespace isce3::core;
using namespace isce3::geometry;

// Functions binding
void addbinding_geometryfunc(py::module& m)
{

    m.def(
            "ant2rgdop",
            [](double el_theta, double az_phi, const Vec3& pos_ecef,
                    const Vec3& vel_ecef, const Quaternion& quat,
                    double wavelength, const DEMInterpolator& dem_interp = {},
                    double abs_tol = 0.5, int max_iter = 10,
                    const ant::Frame& frame = {},
                    const Ellipsoid& ellips = {}) {
                // (slantrange, doppler, convergence)
                return ant::ant2rgdop(el_theta, az_phi, pos_ecef, vel_ecef,
                        quat, wavelength, dem_interp, abs_tol, max_iter, frame,
                        ellips);
            },
            py::arg("el_theta"), py::arg("az_phi"), py::arg("pos_ecef"),
            py::arg("vel_ecef"), py::arg("quaternion"), py::arg("wavelength"),
            py::arg_v("dem_interp", DEMInterpolator(), "0.0"),
            py::arg("abs_tol") = 0.5, py::arg("max_iter") = 10,
            py::arg_v("frame", ant::Frame(), "EL_AND_AZ"),
            py::arg_v("ellips", Ellipsoid(), "WGS84"),
            R"(
Estimate Radar products, Slant range and Doppler centroid, from
spherical angles in antenna body-fixed domain for a certain spacecraft
position, velocity,and attitude at a certain height w.r.t. an ellipsoid.

Parameters
----------
el_theta : float
    either elevation or theta angle in radians
    depending on the 'frame' object.
az_phi : float
    either azimuth or phi angle in radians depending
    on the 'frame' object.
pos_ecef : isce3.core.Vec3
    antenna/spacecraft position in ECEF (m,m,m).
vel_ecef : isce3.core.Vec3
    spacecraft velocity in ECEF (m/s,m/s,m/s).
quaternion : isce3.core.Quaternion
    quaternion object for transformation from antenna
    body-fixed to ECEF.
wavelength : float
    Radar wavelength in (m).
dem_interp : isce3.geometry.DEMInterpolator, default=0.0
    isce3 DEMInterpolator object.
abs_tol : float, default=0.5
    Abs error/tolerance in height estimation (m) between desired
    input height and final output height.
max_iter : int, default=10
    Max number of iterations in height estimation.
frame : isce3.antenna.Frame, default=EL_AND_AZ
   isce3 Frame object to define antenna spherical coordinate system.
ellips : isce3.core.Ellipsoid, default=WGS84
   isce3 Ellipsoid object defining the ellipsoidal planet.

Returns
-------
float
    slant range in (m).
float
    Doppler centroid in (Hz).
bool
    convergence, true if height tolerance is met,false otherwise.

Raises
------
InvalidArgument
    for bad input argument
RuntimeError
    for non-positive slant range

Notes
-----
See reference [1]_ for algorithm and equations

References
----------
.. [1] https://github.jpl.nasa.gov/SALSA-REE/REE_DOC/blob/master/REE_TECHNICAL_DESCRIPTION.pdf
)");

    m.def(
            "ant2rgdop",
            [](const Eigen::Ref<const Eigen::VectorXd>& el_theta, double az_phi,
                    const Vec3& pos_ecef, const Vec3& vel_ecef,
                    const Quaternion& quat, double wavelength,
                    const DEMInterpolator& dem_interp = {},
                    double abs_tol = 0.5, int max_iter = 10,
                    const ant::Frame& frame = {},
                    const Ellipsoid& ellips = {}) {
                return ant::ant2rgdop(el_theta, az_phi, pos_ecef, vel_ecef,
                        quat, wavelength, dem_interp, abs_tol, max_iter, frame,
                        ellips);
            },
            py::arg("el_theta"), py::arg("az_phi"), py::arg("pos_ecef"),
            py::arg("vel_ecef"), py::arg("quaternion"), py::arg("wavelength"),
            py::arg_v("dem_interp", DEMInterpolator(), "0.0"),
            py::arg("abs_tol") = 0.5, py::arg("max_iter") = 10,
            py::arg_v("frame", ant::Frame(), "EL_AND_AZ"),
            py::arg_v("ellips", Ellipsoid(), "WGS84"),
            R"(
Estimate Radar products, Slant range and Doppler centroid, from
spherical angles in antenna body-fixed domain for a certain spacecraft
position, velocity,and attitude at a certain height w.r.t. an ellipsoid.
Parameters
----------
el_theta : list(float)
    a list of either elevation or theta angles in radians
    depending on the 'frame' object.
az_phi : float
    either azimuth or phi angle in radians depending
    on the 'frame' object.
pos_ecef : isce3.core.Vec3
    antenna/spacecraft position in ECEF (m,m,m).
vel_ecef : isce3.core.Vec3
    spacecraft velocity in ECEF (m/s,m/s,m/s).
quaternion : isce3.core.Quaternion
    quaternion object for transformation from antenna
    body-fixed to ECEF.
wavelength : float
    Radar wavelength in (m).
dem_interp : isce3.geometry.DEMInterpolator, default=0.0
    isce3 DEMInterpolator object.
abs_tol : float, default=0.5
    Abs error/tolerance in height estimation (m) between desired
    input height and final output height.
max_iter : int, default=10
    Max number of iterations in height estimation.
frame : isce3.antenna.Frame, default=EL_AND_AZ
   isce3 Frame object to define antenna spherical coordinate system.
ellips : isce3.core.Ellipsoid, default=WGS84
   isce3 Ellipsoid object defining the ellipsoidal planet.

Returns
-------
numpy.ndarray(float)
    Array of slant ranges in (m).
numpy.ndarray(float)
    Array of Doppler centroids in (Hz).
bool
    convergence, true if all height tolerances is met,false otherwise.

Raises
------
InvalidArgument
    for bad input argument
RuntimeError
    for non-positive slant range

Notes
-----
See reference [1]_ for algorithm and equations

References
----------
.. [1] https://github.jpl.nasa.gov/SALSA-REE/REE_DOC/blob/master/REE_TECHNICAL_DESCRIPTION.pdf

)");

    m.def(
            "ant2geo",
            [](double el_theta, double az_phi, const Vec3& pos_ecef,
                    const Quaternion& quat,
                    const DEMInterpolator& dem_interp = {},
                    double abs_tol = 0.5, int max_iter = 10,
                    const ant::Frame& frame = {},
                    const Ellipsoid& ellips = {}) {
                // (pos_llh, convergence)
                return ant::ant2geo(el_theta, az_phi, pos_ecef, quat,
                        dem_interp, abs_tol, max_iter, frame, ellips);
            },
            py::arg("el_theta"), py::arg("az_phi"), py::arg("pos_ecef"),
            py::arg("quaternion"),
            py::arg_v("dem_interp", DEMInterpolator(), "0.0"),
            py::arg("abs_tol") = 0.5, py::arg("max_iter") = 10,
            py::arg_v("frame", ant::Frame(), "EL_AND_AZ"),
            py::arg_v("ellips", Ellipsoid(), "WGS84"),
            R"(
Estimate geodetic geolocation (longitude, latitude, height) from
spherical angles in antenna body-fixed domain for a certain spacecraft
position and attitude at a certain height w.r.t. an ellipsoid.

Parameters
----------
el_theta : float
    either elevation or theta angle in radians
    depending on the 'frame' object.
az_phi : float
    either azimuth or phi angle in radians depending
    on the 'frame' object.
pos_ecef : isce3.core.Vec3
    antenna/spacecraft position in ECEF (m,m,m).
quaternion : isce3.core.Quaternion
    quaternion object for transformation from antenna
    body-fixed to ECEF.
dem_interp : isce3.geometry.DEMInterpolator, default=0.0
    isce3 DEMInterpolator object.
abs_tol : float, default=0.5
    Abs error/tolerance in height estimation (m) between desired
    input height and final output height.
max_iter : int, default=10
    Max number of iterations in height estimation.
frame : isce3.antenna.Frame, default=EL_AND_AZ
   isce3 Frame object to define antenna spherical coordinate system.
ellips : isce3.core.Ellipsoid, default=WGS84
   isce3 Ellipsoid object defining the ellipsoidal planet.

Returns
-------
numpy.ndarray(float)
    geodetic (longitude, latitude, height) in (rad,rad,m).
bool
    convergence, true if height tolerance is met, false otherwise.

Raises
------
InvalidArgument
    for bad input argument
RuntimeError
    for non-positive slant range

Notes
-----
See reference [1]_ for algorithm and equations

References
----------
.. [1] https://github.jpl.nasa.gov/SALSA-REE/REE_DOC/blob/master/REE_TECHNICAL_DESCRIPTION.pdf

)");

    m.def(
            "ant2geo",
            [](const Eigen::Ref<const Eigen::VectorXd>& el_theta, double az_phi,
                    const Vec3& pos_ecef, const Quaternion& quat,
                    const DEMInterpolator& dem_interp = {},
                    double abs_tol = 0.5, int max_iter = 10,
                    const ant::Frame& frame = {},
                    const Ellipsoid& ellips = {}) {
                return ant::ant2geo(el_theta, az_phi, pos_ecef, quat,
                        dem_interp, abs_tol, max_iter, frame, ellips);
            },
            py::arg("el_theta"), py::arg("az_phi"), py::arg("pos_ecef"),
            py::arg("quaternion"),
            py::arg_v("dem_interp", DEMInterpolator(), "0.0"),
            py::arg("abs_tol") = 0.5, py::arg("max_iter") = 10,
            py::arg_v("frame", ant::Frame(), "EL_AND_AZ"),
            py::arg_v("ellips", Ellipsoid(), "WGS84"),
            R"(
Estimate geodetic geolocation (longitude, latitude, height) from
spherical angles in antenna body-fixed domain for a certain spacecraft
position and attitude at a certain height w.r.t. an ellipsoid.

Parameters
----------
el_theta : list(float)
    a list of either elevation or theta angles in radians
    depending on the 'frame' object.
az_phi : float
    either azimuth or phi angle in radians depending
    on the 'frame' object.
pos_ecef : isce3.core.Vec3
    antenna/spacecraft position in ECEF (m,m,m).
quaternion : isce3.core.Quaternion
    quaternion object for transformation from antenna
    body-fixed to ECEF.
dem_interp : isce3.geometry.DEMInterpolator, default=0.0
    isce3 DEMInterpolator object.
abs_tol : float, default=0.5
    Abs error/tolerance in height estimation (m) between desired
    input height and final output height.
max_iter : int, default=10
    Max number of iterations in height estimation.
frame : isce3.antenna.Frame, default=EL_AND_AZ
   isce3 Frame object to define antenna spherical coordinate system.
ellips : isce3.core.Ellipsoid, default=WGS84
   isce3 Ellipsoid object defining the ellipsoidal planet.

Returns
-------
list(numpy.ndarray(float))
    a list of geodetic (longitude, latitude, height) in (rad,rad,m).
bool
    convergence, true if height tolerance is met, false otherwise.

Raises
------
InvalidArgument
    for bad input argument
RuntimeError
    for non-positive slant range

Notes
-----
See reference [1]_ for algorithm and equations

References
----------
.. [1] https://github.jpl.nasa.gov/SALSA-REE/REE_DOC/blob/master/REE_TECHNICAL_DESCRIPTION.pdf

)");
}


text:
//   GAMBIT: Global and Modular BSM Inference Tool
//   *********************************************
///  \file
///
///  CosmoBit routines relating to setting input parameters
///    for the Boltzmann solvers.
///
///  *********************************************
///
///  Authors (add name and date if you modify):
///
///  \author Selim C. Hotinli
///          (selim.hotinli14@pimperial.ac.uk)
///  \date 2017 Jul
///  \date 2018 May
///  \date 2018 Aug - Sep
///
///  \author Patrick Stoecker
///          (stoecker@physik.rwth-aachen.de)
///  \date 2017 Nov
///  \date 2018 Jan - May
///  \date 2019 Jan, Feb, June, Nov
///
///  \author Janina Renk
///          (janina.renk@fysik.su.se)
///  \date 2018 June
///  \date 2019 Mar,June
///  \date 2020 July
///
///  \author Sanjay Bloor
///          (sanjay.bloor12@imperial.ac.uk)
///  \date 2019 June, Nov
///
///  \author Sebastian Hoof
///          (hoof@uni-goettingen.de)
///  \date 2020 Mar
///
///  \author Pat Scott
///          (pat.scott@uq.edu.au)
///  \date 2018 Mar
///  \date 2019 Jul
///  \date 2020 Apr
///
///  *********************************************

#include <boost/algorithm/string/trim.hpp>

#include "gambit/Elements/gambit_module_headers.hpp"
#include "gambit/CosmoBit/CosmoBit_rollcall.hpp"
#include "gambit/CosmoBit/CosmoBit_types.hpp"

namespace Gambit
{

  namespace CosmoBit
  {

    using namespace LogTags;

    #ifdef HAVE_PYBIND11

      /*****************/
      /* Classy inputs */
      /*****************/

      /// Create a Python dictionary with the inputs that have to be passed to class.
      /// Setting parameters related to (massive) neutrinos & non-CDM components.
      void set_classy_NuMasses_Nur_input(pybind11::dict &result)
      {
        using namespace Pipes::set_classy_NuMasses_Nur_input;

        // Make sure dict is empty
        result.clear();

        // Set number of ultra relativistic species
        result["N_ur"] = *Dep::N_ur;

        // Get the neutrino masses
        // The units of StandardModel_SLHA2 are GeV; here we are using eV.
        std::vector<double> nuMasses{
          1e9*(*Param["mNu1"]), 1e9*(*Param["mNu2"]), 1e9*(*Param["mNu3"])
        };

        // Count the nonzero entries
        auto isNonZero = [](double i) {return i > 0.;};
        int N_ncdm = std::count_if(nuMasses.begin(), nuMasses.end(), isNonZero);

        // if nonzero, a mass & temperature for each species has to be
        // passed to class
        if (N_ncdm > 0.)
        {
          result["N_ncdm"] = N_ncdm;

          std::vector<double> m_ncdm(N_ncdm);
          std::copy_if(nuMasses.begin(), nuMasses.end(), m_ncdm.begin(), isNonZero);

          // NOTE: this explicitly assumed that all non-CDM components have the same temperature!
          std::vector<double> T_ncdm(N_ncdm,*Dep::T_ncdm);

          // Create one string with m_ncdm masses and
          // T_ncdm temperatures, separated by commas.
          // This matches the input format of CLASS.
          std::ostringstream ss1, ss2;
          std::string separator;
          for (auto x : m_ncdm)
          {
            ss1 << separator << x;
            separator = ",";
          }
          separator = "";
          for (auto x : T_ncdm)
          {
            ss2 << separator << x;
            separator = ",";
          }

          result["m_ncdm"] = ss1.str();
          result["T_ncdm"] = ss2.str();
        }
      }

      /// Set the classy parameters for an LCDM run with a parametrised primordial power spectrum.
      void set_classy_parameters_parametrised_ps(pybind11::dict& result)
      {
        using namespace Pipes::set_classy_parameters_parametrised_ps;

        // Clean the input container
        result.clear();

        // Now need to pass the primordial power spectrum
        result["n_s"] = *Param["n_s"];
        result["ln10^{10}A_s"] = *Param["ln10A_s"];

        // Pass pivot scale of external spectrum to CLASS
        result["P_k_ini type"] = "analytic_Pk";
        result["k_pivot"] = *Dep::k_pivot;

        // If r = 0 only compute scalar modes, else tensor modes as well
        //
        // => Don't explicitly set "modes" to 's' since it defaults to it. If you set it here anyways
        // you won't be able to run CLASS when only requesting background quantities (e.g. for BAO & SNe likelihoods)
        // as the perturbations module won't run and therefore the entry "modes" won't be read.
        if(*Param["r"] == 0){}
        else
        {
          // Don't set 'r' to zero in CLASS dictionary, as it won't be read if no tensor modes are requested
          result["r"] = *Param["r"];
          result["modes"] = "t,s";
        }

        // Set helium abundance
        result["YHe"] = *Dep::helium_abundance;
      }

      /// Set the classy parameters for an LCDM run with an explicit non-parametric primordial power spectrum.
      void set_classy_parameters_primordial_ps(pybind11::dict& result)
      {
        using namespace Pipes::set_classy_parameters_primordial_ps;

        // Clean the input container
        result.clear();

        // Now need to pass the primordial power spectrum
        static Primordial_ps pps{};
        pps = *Dep::primordial_power_spectrum;
        result["modes"] = "t,s";
        result["P_k_ini type"] = "pointer_to_Pk";
        result["k_array"] = memaddress_to_uint(pps.get_k().data());
        result["pks_array"] = memaddress_to_uint(pps.get_P_s().data());
        result["pkt_array"] = memaddress_to_uint(pps.get_P_t().data());
        result["lnk_size" ] = pps.get_vec_size(); // makes this consistent with multimodecode (rather than hardcoding it)

        // Pass pivot scale of external spectrum to CLASS
        result["k_pivot"] = *Dep::k_pivot;

        // Set helium abundance
        result["YHe"] = *Dep::helium_abundance;
      }

      /// Create a Python dictionary with the standard inputs that have to be passed
      /// to CLASS: cosmological parameters ([H0/100*theta_s],omega_b,tau_reio,omega_cdm) & add
      /// model-dependent results for N_ur, neutrino masses & helium abundance.
      /// Also read in any extra input options from the YAML file to pass to CLASS.
      void set_classy_input_params(Classy_input &result)
      {
        using namespace Pipes::set_classy_input_params;

        if (ModelInUse("LCDM") and ModelInUse("LCDM_theta"))
        {
          CosmoBit_error().raise(LOCAL_INFO, "You have requested to scan both LCDM and LCDM_theta.\n"
                                             "This is not allowed. Please select one in your YAML file.");
        }

        // Make sure dict is empty
        result.clear();

        // Keep track if it is the first run: if so, perform some
        // extra consistency checks to make sure no contradicting
        // values are in the classy python input dictionary.
        static bool first_run = true;

        // Get the dictionary with inputs for the neutrino masses and merge it
        // into Classy_Input dictionary
        result.merge_input_dicts(*Dep::classy_MPLike_input);
        result.merge_input_dicts(*Dep::classy_NuMasses_Nur_input);
        result.merge_input_dicts(*Dep::classy_primordial_input);

        // Standard cosmological parameters (common to all CDM-like models)
        result.add_entry("T_cmb"      , *Param["T_cmb"]);
        result.add_entry("omega_b"    , *Param["omega_b"]);
        result.add_entry("tau_reio"   , *Param["tau_reio"]);
        result.add_entry("omega_cdm"  , *Param["omega_cdm"]);

        // Depending on parametrisation, pass either Hubble or the acoustic scale
        if (ModelInUse("LCDM")) result.add_entry("H0", *Param["H0"]);
        else result.add_entry("100*theta_s", *Param["100theta_s"]);

        // add energy-injection-related CLASS input parameters
        // Note: if one of the models below is in use, an "exo" version of CLASS needs
        // to be used. Otherwise the features for energy injection are not available.
        // To ensure this, there is a check in the classy frontends that cannot
        // handle energy injection. In that case, a fatal error is thrown and
        // the user is told to use exoCLASS (and how to install it).
        if (ModelInUse("DecayingDM_general") || ModelInUse("AnnihilatingDM_general"))
        {
          // Add decaying/annihilating DM-specific options to Python dictionary passed to CLASS (consistency checks only executed in first run).
          result.merge_input_dicts(*Dep::classy_parameters_EnergyInjection);
        }

        // Other CLASS input direct from the YAML file.
        // Check if these are already contained in the input dictionary -- if so throw an error.
        // Only do this for the first run...
        static pybind11::dict yaml_input;
        if(first_run)
        {
          YAML::Node classy_dict;
          if (runOptions->hasKey("classy_dict"))
          {
            classy_dict = runOptions->getValue<YAML::Node>("classy_dict");
            for (auto it=classy_dict.begin(); it != classy_dict.end(); it++)
            {
              std::string name = it->first.as<std::string>();
              std::string value = it->second.as<std::string>();
              // Check if the key exists in the dictionary
              if (not result.has_key(name.c_str()))
              {
                yaml_input[name.c_str()] = value;
              }
              // If it does, throw an error, there's some YAML conflict going on.
              else
              {
                CosmoBit_error().raise(LOCAL_INFO, "The key '" + name + "' already "
                  "exists in the CLASSY dictionary. You are probably trying to override a model parameter. If you really"
                  "want to do this you should define an extra function to set the class parameters for the model you "
                  "are considering.");
              }
            }
            // Make sure that user did not try to pass k_pivot, N_star or P_k_ini type through class dictionary.
            // These are fixed by capabilities to ensure consistent use throughout the code
            if (yaml_input.contains("k_pivot") || yaml_input.contains("N_star"))
            {
              CosmoBit_error().raise(LOCAL_INFO,
                    "You tried to pass 'k_pivot' and/or 'N_star' to CLASS. These values must \n"
                    "be set consistently throughout the code. N_pivot is set automatically\n"
                    "by the assumption of instant reheating, or as an explicit model parameter.\n"
                    "k_pivot can be set by adding\n "
                    "  - capability: k_pivot\n    function: set_k_pivot\n    options:\n"
                    "      k_pivot: 0.02\n"
                    "to the Rules section of your YAML file.");
            }
            if (yaml_input.contains("P_k_ini type"))
            {
              CosmoBit_error().raise(LOCAL_INFO,
                "GAMBIT will take care of setting all CLASS inputs regarding the primordial power spectrum consistently.\n"
                "Please remove the option 'P_k_ini type' for the capability 'classy_baseline_params'.");
            }
          }
        // Only want to do the gnarly stuff once!
        first_run = false;
        }

        // Add YAML options to python dictionary passed to CLASS; consistency checks only executed on first run
        result.merge_input_dicts(yaml_input);

        // If the Planck likelihood is used, add the following relevant input parameters to the CLASS dictionary:
        // - output: 'lCl, pCl, tCl'
        // - lensing: yes
        // - non linear: halofit
        // - l_max_scalars: 2508

        // NOTE: this if performed *after* the YAML options are read in, since it would trigger an error of duplicated
        // keys in the event the user specifies one of the options themselves. The 'merge_input_dicts' routine will properly
        // deal with concatenating the output values and choosing the maximum passed value for l_max_scalars. Contradictions
        // in the lensing or non-linear choice will rightfully trigger an error.
        if (ModelInUse("cosmo_nuisance_Planck_lite") || ModelInUse("cosmo_nuisance_Planck_TTTEEE") || ModelInUse("cosmo_nuisance_Planck_TT"))
        {
          // add Planck-likelihood-specific options to python dictionary passed to CLASS; consistency checks only executed on first run
          result.merge_input_dicts(*Dep::classy_PlanckLike_input);
        }

      }

      /// Initialises the container within CosmoBit from classy. This holds
      /// an instance of the classy class Class() (Yep, I know...)
      /// which can be handed over to MontePython, or just used to compute
      /// some observables.
      void set_classy_input_no_MPLike(pybind11::dict& result)
      {
        using namespace Pipes::set_classy_input_no_MPLike;

        // Make sure nobody is trying to use MP downstream (prevents segfaults).
        if (Downstream::neededFor("MP_LogLikes"))
        {
          std::ostringstream ss;
          ss << "Sorry, you cannot use the function CosmoBit::set_classy_input with MontePython." << endl
             << "Please modify the Rules section of your YAML file to instead point to the function" << endl
             << "CosmoBit::set_classy_input_with_MPLike. An appropriate rule would look like this:" << endl << endl
             << "  - capability: classy_final_input" << endl
             << "    function: set_classy_input_with_MPLike" << endl;
          CosmoBit_error().raise(LOCAL_INFO, ss.str());
        }

        // If the above check passes, nothing to do here.
        pybind11::dict r;
        result = r;
      }

      /// Initialises the container within CosmoBit from classy, but designed specifically
      /// to be used when MontePython is in use. This will ensure additional outputs are
      /// computed by classy CLASS to be passed to MontePython:
      /// When initialising the MontePython Likelihood objects they add the output that needs to be computed by class
      /// to the input dictionary. We need to get these before starting the class run
      /// e.g. for Planck_SZ likelihood the entries {'output': ' mPk ', 'P_k_max_h/Mpc': '1.'} need to be added
      /// to compute all needed observables, these entries are collected here.
      void set_classy_input_with_MPLike(pybind11::dict& result)
      {
        using namespace Pipes::set_classy_input_with_MPLike;
        static bool first = true;

        // Only do this this first time through, and if something actually needs info from MP downstream
        if (first and Downstream::neededFor("MP_LogLikes"))
        {
          // Get extra cosmo_arguments from MP (gives a dictionary with output values that need
          // to be set for the class run)
          pybind11::dict tmp_dict = std::get<0>(*Dep::MP_objects).attr("cosmo_arguments");
          // Stringify all values in the dictionary and strip off leading and trailing whitespaces
          for (auto it: tmp_dict)
          {
            std::string key = (pybind11::str(it.first)).cast<std::string>();
            std::string val = (pybind11::str(it.second)).cast<std::string>();
            boost::algorithm::trim(val);
            result[key.c_str()] = val.c_str();
          }
          logger() << LogTags::debug << "Extra cosmo_arguments needed from MP Likelihoods: ";
          logger() << pybind11::repr(result) << EOM;
          first = false;
        }
      }

      /// Set the parameters for exoCLASS for a scenario with annihilating dark matter.
      void set_classy_parameters_EnergyInjection_AnnihilatingDM(pybind11::dict &result)
      {
        using namespace Pipes::set_classy_parameters_EnergyInjection_AnnihilatingDM;

        // Make sure nothing from previous run is contained
        result.clear();

         // Set relevant inputs for the scenario of s-wave annihilating DM
         result["DM_annihilation_cross_section"] = *Param["sigmav"];
         result["DM_annihilation_mass"] = *Param["mass"];

        // Get the results from the DarkAges tables that hold extra information to be passed to the CLASS thermodynamics structure
        static DarkAges::Energy_injection_efficiency_table fz;
        static DarkAges::Energy_injection_efficiency_table cached_fz;

        fz = *Dep::energy_injection_efficiency;
        bool f_eff_mode = fz.f_eff_mode;

        // Flag passed to CLASS to signal that the energy_deposition_function is coming from GAMBIT
        // we patched exoCLASS to accept this. An alternative way without patching would be to write the tables to disk &
        // just have CLASS read in the file. To avoid the repeated file writing & deleting we pass pointers to the vector/arrays
        // to CLASS instead
        if (f_eff_mode)
        {
          result["f_eff_type"] = "pointer_to_fz_eff";
        }
        else
        {
          result["f_eff_type"] = "pointer_to_fz_channel";
        }

        // Set the lengths of the input tables (since we are passing pointers to arrays CLASS has to know how long they are)
        result["energyinj_coef_num_lines"] = fz.redshift.size();

        // Add the pointers to arrays class needs to know about to input dictionary
        // NOTE: memory addresses are passed as strings (the Python wrapper for CLASS
        // converts every entry to a string internally so we need to do that for the
        // memory addresses, before Python casts them to something else)
        result["energyinj_coef_z"] = memaddress_to_uint(fz.redshift.data());
        if (f_eff_mode)
        {
          result["energyinj_coef_tot"] = memaddress_to_uint(fz.f_eff.data());
        }
        else
        {
          result["energyinj_coef_heat"] = memaddress_to_uint(fz.f_heat.data());
          result["energyinj_coef_lya"] = memaddress_to_uint(fz.f_lya.data());
          result["energyinj_coef_ionH"] = memaddress_to_uint(fz.f_hion.data());
          result["energyinj_coef_ionHe"] = memaddress_to_uint(fz.f_heion.data());
          result["energyinj_coef_lowE"] = memaddress_to_uint(fz.f_lowe.data());
        }

        // Check if the table has changed compared to the previous iteration.
        // If so, notify class by adding {"EnergyInjection_changed":"yes"}
        // to the dictionary.
        // The classy frontend will just look for the key - the value is not important here.
        if (fz != cached_fz)
          result["EnergyInjection_changed"] = "yes";

        // Copy fz to cache
        cached_fz = fz;
      }

      /// Set the parameters for exoCLASS for a scenario with decaying dark matter.
      void set_classy_parameters_EnergyInjection_DecayingDM(pybind11::dict &result)
      {
        using namespace Pipes::set_classy_parameters_EnergyInjection_DecayingDM;

        // Make sure nothing from previous run is contained
        result.clear();

        // Set relevant inputs for the scenario of decaying DM
        const ModelParameters& NP_params = *Dep::DecayingDM_general_parameters;
        result["DM_decay_tau"] = NP_params.at("lifetime");
        result["DM_decay_fraction"] = NP_params.at("fraction");

        // Get the results from the DarkAges tables that hold extra information to be passed to the CLASS thermodynamics structure
        static DarkAges::Energy_injection_efficiency_table fz;
        static DarkAges::Energy_injection_efficiency_table cached_fz;

        fz = *Dep::energy_injection_efficiency;
        bool f_eff_mode = fz.f_eff_mode;

        // Flag passed to CLASS to signal that the energy_deposition_function is coming from GAMBIT
        // (exoCLASS has been patched to accept this). An alternative way without patching would be
        // to write the tables to disk & just have CLASS read in the file. To avoid the repeated
        // file writing & deleting we pass pointers to the vector/arrays to CLASS instead.
        if (f_eff_mode)
        {
          result["f_eff_type"] = "pointer_to_fz_eff";
        }
        else
        {
          result["f_eff_type"] = "pointer_to_fz_channel";
        }

        // Set the lengths of the input tables (since we are passing pointers to arrays CLASS has to know how long they are)
        result["energyinj_coef_num_lines"] = fz.redshift.size();

        // Add the pointers to arrays class needs to know about to input dictionary
        // NOTE: memory addresses are passed as strings (the Python wrapper for CLASS
        // converts every entry to a string internally so we need to do that for the
        // memory addresses, before Python casts them to something else)
        result["energyinj_coef_z"] = memaddress_to_uint(fz.redshift.data());
        if (f_eff_mode)
        {
          result["energyinj_coef_tot"] = memaddress_to_uint(fz.f_eff.data());
        }
        else
        {
          result["energyinj_coef_heat"] = memaddress_to_uint(fz.f_heat.data());
          result["energyinj_coef_lya"] = memaddress_to_uint(fz.f_lya.data());
          result["energyinj_coef_ionH"] = memaddress_to_uint(fz.f_hion.data());
          result["energyinj_coef_ionHe"] = memaddress_to_uint(fz.f_heion.data());
          result["energyinj_coef_lowE"] = memaddress_to_uint(fz.f_lowe.data());
        }

        // Check if the table has changed compared to the previous iteration.
        // If not, notify class by adding {"EnergyInjection_changed":"yes"}
        // to the dictionary.
        // The classy frontend will just look for the key - the value is not important here.
        if (fz != cached_fz)
          result["EnergyInjection_changed"] = "yes";

        // Copy fz to cache
        cached_fz = fz;
      }

      /// Add all inputs for CLASS needed to produce the correct output to be
      /// able to compute the Planck CMB likelihoods
      void set_classy_PlanckLike_input(pybind11::dict &result)
      {
        using namespace Pipes::set_classy_PlanckLike_input;

        // Make sure nothing from previous run is contained
        result.clear();

        static std::ostringstream output;
        static std::ostringstream l_max_scalars;

        static bool first = true;
        if(first)
        {
          int lmax = -1;
          bool needs_tCl = false;
          bool needs_pCl = false;

          // Get requirements of the loaded likelihoods in the plc backend
          BEreq::plc_required_Cl(lmax,needs_tCl,needs_pCl);

          // Prepare the classy input for "output"
          // -- The likelihoods need the lensed Cl such that lensing is required everytime
          output << "lCl";
          // -- Are additional Cl, other to Cl_phiphi, required?
          if (needs_tCl)
            output << ", tCl";
          if (needs_pCl)
            output << ", pCl";

          // Prepare the classy input for "l_max_scalars"
          l_max_scalars << lmax;

          first = false;
        }

        result["lensing"] = "yes";
        result["non linear"] = "halofit";
        result["output"] = output.str();
        result["l_max_scalars"] = l_max_scalars.str();
      }

  #endif

  } // namespace CosmoBit

} // namespace Gambit


text:
#ifndef BENCH_COMMON_HPP
#define BENCH_COMMON_HPP

#include "benchmark.h"
#include "benchmark_config.hpp"

#include <algorithm>
#include <boost/intrusive/set.hpp>
#include <chrono>
#include <draup.hpp>
#include <iostream>
#include <random>
#include <vector>

#ifdef USEPAPI
#include <papi.h>
#endif

// Draup Registration
#define REGISTER(BaseClass, Method)                                            \
	DRAUP_REGISTER(BaseClass##_##Method##_Benchmark)

// Experiment Names
constexpr auto delete_experiment_c = BOOST_HANA_STRING("Delete");
using DeleteExperiment = decltype(delete_experiment_c);
constexpr auto erase_experiment_c = BOOST_HANA_STRING("Erase");
using EraseExperiment = decltype(erase_experiment_c);
constexpr auto move_experiment_c = BOOST_HANA_STRING("Move");
using MoveExperiment = decltype(move_experiment_c);
constexpr auto insert_experiment_c = BOOST_HANA_STRING("Insert");
using InsertExperiment = decltype(insert_experiment_c);
constexpr auto search_experiment_c = BOOST_HANA_STRING("Search");
using SearchExperiment = decltype(search_experiment_c);

std::vector<std::string> PAPI_MEASUREMENTS;
bool PAPI_STATS_WRITTEN;

class Clock {
public:
	void
	start()
	{
		this->started = std::chrono::steady_clock::now();
	};

	double
	get()
	{
		auto stopped = std::chrono::steady_clock::now();
		long int ret = std::chrono::duration_cast<std::chrono::nanoseconds>(
		                   stopped - this->started)
		                   .count();
		return static_cast<double>(ret) / 1000000000.0;
	};

private:
	std::chrono::time_point<std::chrono::steady_clock> started;
};

class PointerCountCallback {
public:
	static void
	start()
	{
		PointerCountCallback::running = true;
	}
	static void
	stop()
	{
		PointerCountCallback::running = false;
	}

	static void
	get_left()
	{
		if (PointerCountCallback::running)
			PointerCountCallback::get_left_c++;
	}
	static void
	get_right()
	{
		if (PointerCountCallback::running)
			PointerCountCallback::get_right_c++;
	}
	static void
	get_parent()
	{
		if (PointerCountCallback::running)
			PointerCountCallback::get_parent_c++;
	}
	static void
	set_left()
	{
		if (PointerCountCallback::running)
			PointerCountCallback::set_left_c++;
	}
	static void
	set_right()
	{
		if (PointerCountCallback::running)
			PointerCountCallback::set_right_c++;
	}
	static void
	set_parent()
	{
		if (PointerCountCallback::running)
			PointerCountCallback::set_parent_c++;
	}

	static void
	reset()
	{
		PointerCountCallback::get_left_c = 0;
		PointerCountCallback::get_right_c = 0;
		PointerCountCallback::get_parent_c = 0;
		PointerCountCallback::set_left_c = 0;
		PointerCountCallback::set_right_c = 0;
		PointerCountCallback::set_parent_c = 0;
		PointerCountCallback::running = false;
	}

	static void
	report(::benchmark::State & state)
	{
#ifdef COUNTOPS
		state.counters["GET_RIGHT"] = ::benchmark::Counter(
		    static_cast<double>(PointerCountCallback::get_right_c),
		    ::benchmark::Counter::Flags::kAvgIterations);
		state.counters["GET_LEFT"] = ::benchmark::Counter(
		    static_cast<double>(PointerCountCallback::get_left_c),
		    ::benchmark::Counter::Flags::kAvgIterations);
		state.counters["GET_PARENT"] = ::benchmark::Counter(
		    static_cast<double>(PointerCountCallback::get_parent_c),
		    ::benchmark::Counter::Flags::kAvgIterations);
		state.counters["GET_TOTAL"] = ::benchmark::Counter(
		    static_cast<double>(PointerCountCallback::get_parent_c +
		                        PointerCountCallback::get_left_c +
		                        PointerCountCallback::get_right_c),
		    ::benchmark::Counter::Flags::kAvgIterations);

		state.counters["SET_RIGHT"] = ::benchmark::Counter(
		    static_cast<double>(PointerCountCallback::set_right_c),
		    ::benchmark::Counter::Flags::kAvgIterations);
		state.counters["SET_LEFT"] = ::benchmark::Counter(
		    static_cast<double>(PointerCountCallback::set_left_c),
		    ::benchmark::Counter::Flags::kAvgIterations);
		state.counters["SET_PARENT"] = ::benchmark::Counter(
		    static_cast<double>(PointerCountCallback::set_parent_c),
		    ::benchmark::Counter::Flags::kAvgIterations);
		state.counters["SET_TOTAL"] = ::benchmark::Counter(
		    static_cast<double>(PointerCountCallback::set_parent_c +
		                        PointerCountCallback::set_left_c +
		                        PointerCountCallback::set_right_c),
		    ::benchmark::Counter::Flags::kAvgIterations);
#else
		(void)state;
#endif
	}

private:
	static bool running;
	static size_t get_left_c;
	static size_t get_right_c;
	static size_t get_parent_c;
	static size_t set_left_c;
	static size_t set_right_c;
	static size_t set_parent_c;
};

bool PointerCountCallback::running;
size_t PointerCountCallback::get_left_c;
size_t PointerCountCallback::get_right_c;
size_t PointerCountCallback::get_parent_c;
size_t PointerCountCallback::set_left_c;
size_t PointerCountCallback::set_right_c;
size_t PointerCountCallback::set_parent_c;

class PapiMeasurements {
public:
	void
	initialize()
	{
#ifdef USEPAPI
		if (!this->initialized) {
			this->initialized = true;

			int num_counters = PAPI_num_counters();
			if (!PAPI_STATS_WRITTEN) {
				std::cout << "## Your system has " << num_counters
				          << " PAPI counters.\n";
			}

			if (num_counters == 0) {
				std::cout
				    << "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n";
				std::cout
				    << "!!        Warning: No PAPI counters available!       !!\n";
				std::cout << "!! Use the avail and component_avail tools !!\n";
				std::cout
				    << "!! to figure out why. If you are on Linux, you most  !!\n";
				std::cout
				    << "!! probably need to set                              !!\n";
				std::cout
				    << "!! /proc/sys/kernel/perf_event_paranoid to 0         !!\n";
				std::cout
				    << "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n";
			}

			int event_code;
			event_code = 0 | PAPI_NATIVE_MASK;

			this->selected_events.clear();
			for (const std::string & event_str : PAPI_MEASUREMENTS) {
				if (PAPI_event_name_to_code(event_str.c_str(), &event_code) !=
				    PAPI_OK) {
					std::cerr << "PAPI event " << event_str << " not found!\n";
					exit(-1);
				}

				this->selected_events.push_back(event_code);
				if (!PAPI_STATS_WRITTEN) {
					std::cout << "## Registering PAPI event " << event_str << " (ID "
					          << event_code << ")\n";
				}
			}
			PAPI_STATS_WRITTEN = true;
		}

		this->event_counts.resize(this->selected_events.size());
		this->event_count_accu.resize(this->selected_events.size());
		std::fill(this->event_count_accu.begin(), this->event_count_accu.end(), 0);
#endif
	}

	void
	start()
	{
#ifdef USEPAPI
		// TODO error handling
		PAPI_start_counters(this->selected_events.data(),
		                    static_cast<int>(this->selected_events.size()));
#endif
	}

	void
	stop()
	{
#ifdef USEPAPI
		// TODO error handling
		PAPI_stop_counters(this->event_counts.data(),
		                   static_cast<int>(this->event_counts.size()));
		std::transform(this->event_counts.begin(), this->event_counts.end(),
		               this->event_count_accu.begin(),
		               this->event_count_accu.begin(), std::plus<long long>());
#endif
	}

	void
	report_and_reset(::benchmark::State & state)
	{
#ifdef USEPAPI
		for (size_t i = 0; i < PAPI_MEASUREMENTS.size(); ++i) {
			state.counters[PAPI_MEASUREMENTS[i]] =
			    ::benchmark::Counter(static_cast<double>(this->event_count_accu[i]),
			                         ::benchmark::Counter::Flags::kAvgIterations);
		}
		std::fill(this->event_count_accu.begin(), this->event_count_accu.end(), 0);
#else
		(void)state;
#endif
	}

private:
#ifdef USEPAPI
	std::vector<int> selected_events;
	std::vector<long long> event_counts;
	std::vector<long long> event_count_accu;
	bool initialized = false;
#endif
};

#endif

max_stars_repo_name: ktprime/ygg

max_issues_repo_name: ktprime/ygg

max_forks_repo_name: ktprime/ygg


text:
/**
 * Copyright (C) 2019-2022 polistern
 *
 * This file is part of pboted and licensed under BSD3
 *
 * See full license text in LICENSE file at top of project tree
 */

#include <boost/filesystem.hpp>
#include <chrono>
#include <cstring>
#include <fstream>
#include <iterator>
#include <cstdio>

#include "ConfigParser.h"
#include "DHTStorage.h"

namespace pbote
{
namespace kademlia
{

void
DHTStorage::update ()
{
  loadLocalIndexPackets ();
  loadLocalEmailPackets ();
  loadLocalContactPackets ();

  update_storage_usage ();

  /// There is no need to check this too often
  if (update_counter > 20)
  {
    index_mutex.lock ();
    email_mutex.lock ();
    contact_mutex.lock ();

    remove_old_packets ();
    update_counter = 0;

    LogPrint (eLogDebug, "DHTStorage: update: ",
             " index: ", local_index_packets.size (),
             ", emails: ", local_email_packets.size (),
             ", contacts: ", local_contact_packets.size ());

    index_mutex.unlock();
    email_mutex.unlock();
    contact_mutex.unlock();
  }

  update_counter++;
}

int
DHTStorage::safe(const std::vector<uint8_t>& data)
{
  uint8_t dataType = data[0];
  int success = 0;
  uint8_t key[32];
  memcpy(key, data.data () + 2, 32);
  i2p::data::Tag<32> dht_key (key);

  index_mutex.lock ();
  email_mutex.lock ();
  contact_mutex.lock ();

  switch (dataType) {
    case ((uint8_t) 'I'):
      success = safeIndex (dht_key, data);
      break;
    case ((uint8_t) 'E'):
      success = safeEmail (dht_key, data);
      break;
    case ((uint8_t) 'C'):
      success = safeContact (dht_key, data);
      break;
    default:
      break;
  }

  index_mutex.unlock();
  email_mutex.unlock();
  contact_mutex.unlock();

  update ();
  return success;
}

bool
DHTStorage::deleteIndex(i2p::data::Tag<32> key)
{
  if(exist(pbote::type::DataI, key)) {
    std::string packet_path = pbote::fs::DataDirPath("DHTindex", key.ToBase64() + ".dat");

    int status = std::remove(packet_path.c_str());

    if (status == 0) {
      LogPrint(eLogInfo, "DHTStorage: deleteIndex: File ", packet_path, " removed");
      update_storage_usage();
      return true;
    } else {
      LogPrint(eLogError, "DHTStorage: deleteIndex: Can't remove file ", packet_path);
      return false;
    }
  }
  return false;
}

bool
DHTStorage::deleteEmail (i2p::data::Tag<32> key)
{
  if(exist(pbote::type::DataE, key))
    {
      std::string packet_path = pbote::fs::DataDirPath("DHTemail", key.ToBase64() + ".dat");

      int status = std::remove(packet_path.c_str());

      if (status == 0)
        {
          LogPrint(eLogInfo, "DHTStorage: deleteEmail: File ", packet_path, " removed");
          update_storage_usage();
          return true;
        }
      else
        {
          LogPrint(eLogError, "DHTStorage: deleteEmail: Can't remove file ", packet_path);
          return false;
        }
    }
  return false;
}

std::vector<uint8_t>
DHTStorage::getIndex(i2p::data::Tag<32> key)
{
  if(exist(pbote::type::DataI, key))
    {
      return getPacket(pbote::type::DataI, key);
    }
  return {};
}

std::vector<uint8_t>
DHTStorage::getEmail(i2p::data::Tag<32> key)
{
  if(exist(pbote::type::DataE, key))
    {
      return getPacket(pbote::type::DataE, key);
    }
  return {};
}

std::vector<uint8_t>
DHTStorage::getContact(i2p::data::Tag<32> key)
{
  if(exist(pbote::type::DataC, key))
    {
      return getPacket(pbote::type::DataC, key);
    }
  return {};
}

bool
DHTStorage::limit_reached(size_t data_size)
{
  LogPrint(eLogDebug, "DHTStorage: limit_reached: ",
           (limit < (used + data_size)) ? "true" : "false");
  return limit <= (used + data_size);
}

std::vector<uint8_t>
DHTStorage::getPacket(pbote::type type, i2p::data::Tag<32> key)
{
  std::string dir_path;
  std::vector<std::string> local_list;

  switch(type) {
    case pbote::type::DataI:
      dir_path = pbote::fs::DataDirPath("DHTindex");
      local_list = local_index_packets;
      break;
    case pbote::type::DataE:
      dir_path = pbote::fs::DataDirPath("DHTemail");
      local_list = local_email_packets;
      break;
    case pbote::type::DataC:
      dir_path = pbote::fs::DataDirPath("DHTdirectory");
      local_list = local_contact_packets;
      break;
    default:
      return {};
  }

  if (!local_list.empty())
    {
      LogPrint(eLogDebug, "DHTStorage: getPacket: try to find packet");
      for (const auto& filename : local_list)
        {
          i2p::data::Tag<32> filekey = {};
          filekey.FromBase64(filename);
          if ( filekey == key)
            {
              LogPrint(eLogDebug, "DHTStorage: getPacket: found packet with key: ", key.ToBase64());

              std::string filepath(dir_path);
              filepath.append("/");
              filepath.append(filename);
              filepath.append(DEFAULT_FILE_EXTENSION);

              std::ifstream file(filepath, std::ios::binary);

              if (!file.is_open())
                {
                  LogPrint(eLogError, "DHTStorage: getPacket: can't open file ", filepath);
                  return {};
                }

              std::vector<uint8_t> bytes((std::istreambuf_iterator<char>(file)), (std::istreambuf_iterator<char>()));
              file.close();

              return bytes;
            }
        }
      LogPrint(eLogWarning, "DHTStorage: getPacket: have no file with key: ", key.ToBase64());
      return {};
    }
  else
    {
      LogPrint(eLogWarning, "DHTStorage: getPacket: have no files for search");
      return {};
    }
}

bool
DHTStorage::exist(pbote::type type, i2p::data::Tag<32> key)
{
  switch(type) {
    case pbote::type::DataI:
      return find(local_index_packets, key);
    case pbote::type::DataE:
      return find(local_email_packets, key);
    case pbote::type::DataC:
      return find(local_contact_packets, key);
    default:
      return false;
  }
}

bool
DHTStorage::find(const std::vector<std::string>& list, i2p::data::Tag<32> key)
{
  if(std::any_of(list.cbegin(), list.cend(), [key](const std::string& y) { return memcmp(y.data(), key.data(), 32); }))
    return true;
  return false;
}

int
DHTStorage::safeIndex(i2p::data::Tag<32> key, const std::vector<uint8_t>& data)
{
  std::string packetPath = pbote::fs::DataDirPath("DHTindex", key.ToBase64() + ".dat");

  if (pbote::fs::Exists(packetPath))
    {
      int status = update_index(key, data);
      if (status == STORE_FILE_EXIST)
        {
          LogPrint(eLogDebug, "DHTStorage: safeIndex: packet already exist: ", packetPath);
          return STORE_FILE_EXIST;
        }
      if (status == STORE_FILE_OPEN_ERROR)
        {
          LogPrint(eLogWarning, "DHTStorage: safeIndex: packet can't open file ", packetPath);
          return STORE_FILE_OPEN_ERROR;
        }
      LogPrint(eLogDebug, "DHTStorage: safeIndex: saved: ", packetPath);
      return STORE_SUCCESS;
    }

  LogPrint(eLogDebug, "DHTStorage: safeIndex: save packet to ", packetPath);
  std::ofstream file(packetPath, std::ofstream::binary | std::ofstream::out);
  if (!file.is_open())
    {
      LogPrint(eLogError, "DHTStorage: safeIndex: can't open file ", packetPath);
      return STORE_FILE_OPEN_ERROR;
    }

  file.write(reinterpret_cast<const char *>(data.data()), data.size());
  file.close();

  update_storage_usage();

  return STORE_SUCCESS;
}

int
DHTStorage::safeEmail(i2p::data::Tag<32> key, const std::vector<uint8_t>& data)
{
  std::string packetPath = pbote::fs::DataDirPath("DHTemail", key.ToBase64() + ".dat");

  if (pbote::fs::Exists(packetPath))
    {
      LogPrint(eLogDebug, "DHTStorage: safeEmail: packet already exist: ", packetPath);
      return STORE_FILE_EXIST;
    }

  LogPrint(eLogDebug, "DHTStorage: safeEmail: save packet to ", packetPath);
  std::ofstream file(packetPath, std::ofstream::binary | std::ofstream::out);
  if (!file.is_open())
    {
      LogPrint(eLogError, "DHTStorage: safeEmail: can't open file ", packetPath);
      return STORE_FILE_OPEN_ERROR;
    }

  EmailEncryptedPacket email_packet = {};
  email_packet.fromBuffer(const_cast<uint8_t *>(data.data()), data.size(), true);
  const auto time_now = std::chrono::system_clock::now();
  email_packet.stored_time = (int32_t)std::chrono::duration_cast<std::chrono::seconds>(time_now.time_since_epoch()).count();
  auto packet_bytes = email_packet.toByte();

  file.write(reinterpret_cast<const char *>(packet_bytes.data()), (long)packet_bytes.size());
  file.close();

  update_storage_usage();

  return STORE_SUCCESS;
}

int
DHTStorage::safeContact(i2p::data::Tag<32> key, const std::vector<uint8_t>& data)
{
  std::string packetPath = pbote::fs::DataDirPath("DHTdirectory", key.ToBase64() + ".dat");

  if (pbote::fs::Exists(packetPath))
    {
      LogPrint(eLogDebug, "DHTStorage: safeContact: packet already exist: ", packetPath);
      return STORE_FILE_EXIST;
    }

  LogPrint(eLogDebug, "DHTStorage: safeContact: save packet to ", packetPath);
  std::ofstream file(packetPath, std::ofstream::binary | std::ofstream::out);
  if (!file.is_open())
    {
      LogPrint(eLogError, "DHTStorage: safeContact: can't open file ", packetPath);
      return STORE_FILE_OPEN_ERROR;
    }

  file.write(reinterpret_cast<const char *>(data.data()), data.size());
  file.close();

  update_storage_usage();

  return STORE_SUCCESS;
}

int
DHTStorage::update_index(i2p::data::Tag<32> key, const std::vector<uint8_t>& data)
{
  IndexPacket new_packet, old_packet;
  new_packet.fromBuffer(data, true);

  auto old_data = getIndex(key);
  if (old_data.empty())
    {
      LogPrint(eLogError, "DHTStorage: update_index: can't open old index ", key.ToBase64());
      return -1;
    }

  old_packet.fromBuffer(old_data, true);
  size_t duplicated = 0, added = 0;

  for (auto entry : new_packet.data)
    {
      if (std::find(old_packet.data.begin(), old_packet.data.end(), entry) != old_packet.data.end())
        {
          duplicated++;
        }
      else
        {
          old_packet.data.push_back(entry);
          added++;
        }
    }

  LogPrint(eLogDebug, "DHTStorage: update_index: new entries: ",
           new_packet.data.size(), ", duplicated :", duplicated,
           ", added: ", added);

  if (duplicated == new_packet.data.size())
    return -2;

  return 0;
}

void
DHTStorage::loadLocalIndexPackets()
{
  index_mutex.lock ();
  local_index_packets = std::vector<std::string>();
  std::string indexPacketPath = pbote::fs::DataDirPath("DHTindex");
  std::vector<std::string> packets_path;
  auto result = pbote::fs::ReadDir(indexPacketPath, packets_path);

  if (result)
    {
      for (const auto &path : packets_path)
        {
          auto filename = remove_extension(base_name(path));
          local_index_packets.push_back(filename);
        }

      LogPrint(eLogDebug, "DHTStorage: loadLocalIndexPackets: index loaded: ", local_index_packets.size());
    }
  else
    {
      LogPrint(eLogWarning, "DHTStorage: loadLocalIndexPackets: have no index files");
    }
  index_mutex.unlock ();
}

void
DHTStorage::loadLocalEmailPackets()
{
  email_mutex.lock ();
  local_email_packets = std::vector<std::string>();
  std::string email_packet_path = pbote::fs::DataDirPath("DHTemail");
  std::vector<std::string> packets_path;
  auto result = pbote::fs::ReadDir(email_packet_path, packets_path);

  if (result)
    {
      for (const auto &path : packets_path)
        {
          auto filename = remove_extension(base_name(path));
          local_email_packets.push_back(filename);
        }

      LogPrint(eLogDebug, "DHTStorage: loadLocalEmailPackets: mails loaded: ", local_email_packets.size());
    }
  else
    {
      LogPrint(eLogWarning, "DHTStorage: loadLocalEmailPackets: have no mail files");
    }
  email_mutex.unlock ();
}

void
DHTStorage::loadLocalContactPackets()
{
  contact_mutex.lock ();
  local_contact_packets = std::vector<std::string>();
  std::string email_packet_path = pbote::fs::DataDirPath("DHTdirectory");
  std::vector<std::string> packets_path;
  auto result = pbote::fs::ReadDir(email_packet_path, packets_path);

  if (result)
    {
      for (const auto &path : packets_path)
        {
          auto filename = remove_extension(base_name(path));
          local_contact_packets.push_back(filename);
        }

      LogPrint(eLogDebug, "DHTStorage: loadLocalContactPackets: contacts loaded: ", local_contact_packets.size());
    }
  else
    {
      LogPrint(eLogWarning, "DHTStorage: loadLocalContactPackets: have no contact files");
    }
  contact_mutex.unlock ();
}

size_t
DHTStorage::suffix_to_multiplier(const std::string &size_str)
{
  std::vector<std::string> sizes = { "B", "KB", "MB", "GB", "TB" };
  std::string suffix = size_str;
  std::size_t pos = suffix.find(' ');

  if (pos != std::string::npos)
    {
      suffix.erase(0, pos + 1);
    }
  else
    {
      LogPrint(eLogError,
               "DHTStorage: suffix_to_multiplier: can't parse data size suffix: ",
               size_str);
      suffix = "MB";
    }

  size_t iexp = 0;

  for (size_t i = 0; i < sizes.size(); i++)
    {
      if (sizes[i] == suffix)
        {
          /// Because first element is 0
          iexp = i;
          break;
      }
    }

  return (size_t)std::pow(1024, iexp);
}

void
DHTStorage::set_storage_limit()
{
  std::string limit_str;
  pbote::config::GetOption("storage", limit_str);

  size_t multiplier = suffix_to_multiplier(limit_str);

  std::size_t pos = limit_str.find(' ');
  limit_str.erase(pos, limit_str.size() - pos);

  size_t base = std::stoi(limit_str);
  limit = base * multiplier;
  LogPrint(eLogDebug, "DHTStorage: set_storage_limit: limit: ", limit);
}

void
DHTStorage::update_storage_usage()
{
  std::vector<std::string> dirs = {"DHTindex", "DHTemail", "DHTdirectory"};
  used = 0;

  for (const auto& dir : dirs)
    {
      std::string dir_path = pbote::fs::DataDirPath(dir);
      for (boost::filesystem::recursive_directory_iterator it(dir_path);
           it != boost::filesystem::recursive_directory_iterator(); ++it)
        {
          if (!boost::filesystem::is_directory(*it))
            used += boost::filesystem::file_size(*it);
        }
      /*LogPrint(eLogDebug, "DHTStorage: update_storage_usage: directory: ",
             dir, ", used: ", used);*/
    }
}

void
DHTStorage::remove_old_packets()
{
  size_t removed_count = 0;

  const auto time_now = std::chrono::system_clock::now();
  const auto current_timestamp =
    (int32_t)std::chrono::duration_cast<std::chrono::seconds>(time_now.time_since_epoch()).count();

  std::string dir_path = pbote::fs::DataDirPath("DHTemail");

  if (boost::filesystem::is_empty(dir_path.c_str()))
    {
      LogPrint(eLogDebug, "DHTStorage: remove_old_packets: DHTemail directory is empty");
      return;
    }

  std::vector<std::string> paths;

  for (auto& entry : boost::filesystem::recursive_directory_iterator(dir_path))
    {
      if (boost::filesystem::is_directory(entry))
        continue;
      std::stringstream buffer;
      buffer << entry.path();
      paths.push_back (buffer.str ());
    }

  for (auto& path : paths)
    {
      //LogPrint(eLogDebug, "DHTStorage: remove_old_packets: checking file: ", path);

      std::ifstream file(path.c_str (), std::ios::binary);
      if (!file.is_open())
        {
          LogPrint(eLogError, "DHTStorage: remove_old_packets: can't open file ", path);
          continue;
        }

      uint8_t * bytes = (uint8_t *) malloc(38);

      file.read(reinterpret_cast<char*>(bytes), 38);
      file.close();

      uint8_t type;
      uint8_t version;
      uint8_t key[32]{};
      int32_t stored_time{};

      size_t offset = 0;
      memcpy(&type, bytes, 1);
      offset += 1;
      memcpy(&version, bytes + offset, 1);
      offset += 1;
      memcpy(&key, bytes + offset, 32);
      offset += 32;
      memcpy(&stored_time, bytes + offset, 4);

      stored_time = (int32_t)ntohl((uint32_t)stored_time);

      LogPrint(eLogDebug, "DHTStorage: remove_old_packets: current_timestamp: ", current_timestamp);
      LogPrint(eLogDebug, "DHTStorage: remove_old_packets: packet_timestamp:  ", stored_time + store_duration);

      if (stored_time + store_duration < current_timestamp)
        {
          LogPrint(eLogDebug, "DHTStorage: remove_old_packets: remove: ", path);

          auto filename = remove_extension (base_name (path));
          i2p::data::Tag<32> dht_key(key);

          if (filename != dht_key.ToBase64 ())
            {
              LogPrint(eLogWarning, "DHTStorage: remove_old_packets: filename and DHT key mismatch",
                ", key: ", dht_key.ToBase64 (),
                ", filename: ", filename);
              dht_key.FromBase64 (filename);
            }

          if (deleteEmail(dht_key))
            removed_count++;
          else
            LogPrint(eLogError, "DHTStorage: remove_old_packets: can't remove file: ", path);
        }
      else
        {
          LogPrint(eLogDebug, "DHTStorage: remove_old_packets: packet ", path, " is too young to die.");
        }
    }

  LogPrint(eLogDebug, "DHTStorage: remove_old_packets: packets removed: ", removed_count);
}

} // kademlia
} // pbote

max_stars_repo_name: polistern/pboted

max_issues_repo_name: polistern/pboted

max_forks_repo_name: polistern/pboted