text:
#include <Eigen/Core>
#include "problem.h"
#include "random.h"
#include "so3.h"

#include <math.h>

void compute_error( const Eigen::Matrix3d &R, const Eigen::Vector3d &t,
                   const Eigen::Matrix3d &Rsoln, const Eigen::Vector3d &tsoln,
                  double &rot_angle_err, double &trans_angle_err, double &trans_scale_err )
{
    Eigen::Matrix3d Rdiff = R*Rsoln.transpose();
    Eigen::Vector3d rdiff = so3ln(Rdiff);
    rot_angle_err = rdiff.norm();

    trans_angle_err = acos(t.dot(tsoln)/t.norm()/tsoln.norm());

    if ( isnan(trans_angle_err) ) trans_angle_err = 0;
    trans_scale_err = tsoln.norm()/t.norm();
}

void generateProblem( double trans_mag, double angle, double noise, Problem &prob, int nrays )
{
    Eigen::Vector3d X;    // 3D points
    Eigen::Vector3d cu;   // camera centers for first multi-camera rig
    Eigen::Vector3d cv;   // camera centers for second multi-camera rig
    Eigen::Vector3d PX;   // 3D points after R,t transformation
    Ray u;                // observations in first multi-camera rig
    Ray v;                // observations in second multi-camera rig

    Eigen::Vector3d w = rand3f();
    w = w/w.norm();
    double theta = angle*M_PI/180;
    prob.R = so3exp(w*theta);                // random rotation
    prob.t = rand3f();                       // random translation
    while ( prob.t.norm() < 1e-10 ) prob.t = rand3f();
    prob.t = prob.t/prob.t.norm()*trans_mag;

    prob.ray_pairs.clear();

    for ( size_t i = 0; i < nrays; i++ ) {
        X = rand3f();    // sample random point
        while ( X.norm() == 0 ) X = rand3f();
        X = X/X.norm();
        double scale_factor = ((double)rand()/RAND_MAX) * 4 + 4;
        X *= scale_factor;

        cu = rand3f();        // sample random camera locations
        cv = rand3f(); // inter-camera
        //cv = cu;    // intra-camera

        PX = prob.R*X+prob.t;    // transform point
        u.x = X-cu;    // make observation rays
        u.c = cu;
        v.x = PX-cv;
        v.c = cv;

        if ( noise > 0. )    // add noise with requested standard deviation
        {
            double unorm = u.x.norm();
            Eigen::Vector3d uproj = u.x/u.x(2);
            uproj.head(2) += grand2f()*noise;
            uproj /= uproj.norm();
            uproj *= unorm;
            if ( (X-cu).dot(uproj) < 0 ) uproj = -uproj;
            u.x = uproj;

            double vnorm = v.x.norm();
            Eigen::Vector3d vproj = v.x/v.x(2);
            vproj.head(2) += grand2f()*noise;
            vproj /= vproj.norm();
            vproj *= vnorm;
            if ( (PX-cv).dot(vproj) < 0 ) vproj = -vproj;
            v.x = vproj;
        }

        prob.ray_pairs.push_back( RayPair( u, v ) );
    }
}

ext: cpp

max_stars_repo_name: MikhailTerekhov/multi-camera-motion

max_issues_repo_name: MikhailTerekhov/multi-camera-motion

max_forks_repo_name: MikhailTerekhov/multi-camera-motion


text:
#ifndef MATHTOOLBOX_SOM_HPP
#define MATHTOOLBOX_SOM_HPP

#include <Eigen/Core>
#include <memory>

namespace mathtoolbox
{
    class DataNormalizer;

    class Som
    {
    public:
        /// \param data An n-by-m matrix representing m data points lying in an n-dimensional space.
        ///
        /// \param latent_num_dims The dimensionality of the latent (map) space. It should be either 1 or 2.
        Som(const Eigen::MatrixXd& data,
            const int              latent_num_dims      = 2,
            const int              resolution           = 10,
            const double           init_var             = 0.50,
            const double           min_var              = 0.01,
            const double           var_decreasing_speed = 20.0,
            const bool             normalize_data       = true);

        const Eigen::MatrixXd& GetLatentSpaceNodePositions() const { return m_latent_node_positions; }
        const Eigen::MatrixXd& GetLatentSpaceDataPositions() const { return m_Z; }

        Eigen::MatrixXd GetDataSpaceNodePositions() const;

        void Step();

    private:
        const int m_latent_num_dims;
        const int m_resolution;

        const double m_init_var;
        const double m_min_var;
        const double m_var_decreasing_speed;

        const bool m_normalize_data;

        /// \brief Grid node positions in the latent space.
        const Eigen::MatrixXd m_latent_node_positions;

        int m_iter_count;

        /// \brief Observed data points.
        Eigen::MatrixXd m_X;

        /// \brief Vector values on grid nodes.
        Eigen::MatrixXd m_Y;

        /// \brief Embeded data points.
        Eigen::MatrixXd m_Z;

        std::shared_ptr<const DataNormalizer> m_data_normalizer;

        /// \brief Perform normalization for the current data.
        void NormalizeData();

        /// \brief Perform initialization.
        ///
        /// \details Currently, only the random initialization strategy is implemented.
        void PerformInitialization();
    };
} // namespace mathtoolbox

#endif // MATHTOOLBOX_SOM_HPP

ext: hpp

max_stars_repo_name: yuki-koyama/mathtoolbox


text:
#include "CommodityHand.hpp"
#include <stdexcept>
#include <boost/lexical_cast.hpp>

CommodityHand::CommodityHand() : m_Hand()
{
}

CommodityHand::CommodityHand(const CommodityHand &i_right) :
  m_Hand(i_right.m_Hand)
{
}

CommodityHand &CommodityHand::operator=(const CommodityHand &i_right)
{
  if (&i_right != this)
  {
    m_Hand = i_right.m_Hand;
  }
  return *this;
}

int CommodityHand::GetHandWeight(bool i_SmallResearch,bool i_SmallMicro) const
{
  int result = 0;
  size_t i;

  for (i = 0 ; i < m_Hand.size() ; ++i)
  {
    if (m_Hand[i].GetType() == RESEARCH_COMMODITY && i_SmallResearch) continue;
    if (m_Hand[i].GetType() == MICROBIOTICS_COMMODITY && i_SmallMicro) continue;

    result += (m_Hand[i].IsMega() ? 4 : 1);
  }
  return result;
}

int CommodityHand::GetHandValue() const
{
  int result = 0;
  size_t i;

  for (i = 0 ; i < m_Hand.size() ; ++i)
  {
    result += m_Hand[i].GetValue();
  }
  return result;
}

int CommodityHand::GetNumResearch() const
{
  int result = 0;
  size_t i;

  for (i = 0 ; i < m_Hand.size() ; ++i)
  {
    if (m_Hand[i].GetType() == RESEARCH_COMMODITY)
    {
      if (m_Hand[i].IsMega()) result += 4;
      else                    result += 1;
    }
  }
  return result;
}

struct CommSorter
{
  bool operator()(const Commodity &i_left,const Commodity &i_right)
  {
    if (i_left.GetType() != i_right.GetType())
    {
      return (int)i_left.GetType() > (int)i_right.GetType();
    }
    if (i_left.IsMega() != i_right.IsMega())
    {
      return i_left.IsMega();
    }
    if (i_left.IsAverage() != i_right.IsAverage())
    {
      return i_right.IsAverage();
    }
    return i_left.GetValue() > i_right.GetValue();
  }
};

void CommodityHand::AddCommodity(Commodity i_com)
{
  m_Hand.push_back(i_com);
  std::sort(m_Hand.begin(),m_Hand.end(),CommSorter());
}

// takes a string of 0 and 1, and deletes all records from
// m_Hand where the corresponding index at i_deletes is 1.
// -1 size mismatch
// -2 illegal string
//  0 ok.

int CommodityHand::ApplyDeletes(const std::string &i_deletes,std::vector<Commodity> &o_deletes)
{
  if (m_Hand.size() != i_deletes.size())
  {
    return -1;
  }
  size_t i;
  for (i = 0 ; i < i_deletes.size() ; ++i)
  {
    if (i_deletes[i] != '0' && i_deletes[i] != '1') return -2;
  }

  std::vector<Commodity> newhand;
  for (i = 0 ; i < i_deletes.size() ; ++i)
  {
    if (i_deletes[i] == '1')
    {
      o_deletes.push_back(m_Hand[i]);
    }
    else
    {
      newhand.push_back(m_Hand[i]);
    }
  }
  m_Hand = newhand;
  return 0;
}

std::string CommodityHand::GetHandDescription(bool i_showPrivate,bool i_showNew) const
{
  std::string result;
  size_t i;

  result += "|";

  for (i = 0 ; i < m_Hand.size() ; ++i)
  {
    if (i != 0) result += "-";

    switch(m_Hand[i].GetType())
    {
    case ORE_COMMODITY:              result += "OR"; break;
    case WATER_COMMODITY:            result += "WA"; break;
    case TITANIUM_COMMODITY:         result += "TI"; break;
    case RESEARCH_COMMODITY:         result += "RE"; break;
    case MICROBIOTICS_COMMODITY:     result += "MI"; break;
    case NEW_CHEMICALS_COMMODITY:    result += "NE"; break;
    case ORBITAL_MEDICINE_COMMODITY: result += "OM"; break;
    case RING_ORE_COMMODITY:         result += "RO"; break;
    case MOON_ORE_COMMODITY:         result += "MO"; break;
    default: throw std::out_of_range("Bad Commodity Type");
    }

    // megas and average always get shown.
    if (m_Hand[i].IsMega() ||
        m_Hand[i].IsAverage())
    {
      result += boost::lexical_cast<std::string>(m_Hand[i].GetValue());
    }
    // if it's not mega or average..
    // if we're not showing private, it gets a star
    else if (!i_showPrivate)
    {
      result += "*";
    }
    // if we get here, its neither mega nor average, and we're showing private
    // if show new is true, we show new (and we always show old)
    else if (i_showNew)
    {
      result += boost::lexical_cast<std::string>(m_Hand[i].GetValue());
    }
    // if we get here, its neither mega nor average, we're showing private, and we don't show new.
    else if (m_Hand[i].IsNew())
    {
      result += "*";
    }
    else
    {
      result += boost::lexical_cast<std::string>(m_Hand[i].GetValue());
    }

    if (m_Hand[i].IsMega()) result += "M";
    if (m_Hand[i].IsAverage()) result += "A";
  }
  result += "|";
  return result;
}

const std::vector<Commodity>& CommodityHand::GetHand() const
{
  return m_Hand;
}

void CommodityHand::AgeHand()
{
  size_t i;
  for (i = 0 ; i < m_Hand.size() ; ++i)
  {
    m_Hand[i].MakeOld();
  }
}

max_stars_repo_name: chiendarrendor/AlbertsGameMachine

max_issues_repo_name: chiendarrendor/AlbertsGameMachine

max_forks_repo_name: chiendarrendor/AlbertsGameMachine


text:
#pragma once

#include <vector>
#include <deal.II/base/index_set.h>

namespace boltzmann {
/**
 * @brief this is used for graph coloring
 *
 * @param index_in
 * @param nrep      replicate every index nrep times, i.e. map a single index i to the range
 * [i*nrep, (i+1)*nrep)
 *
 * @return
 */
dealii::IndexSet
replicate_index_set(const dealii::IndexSet& index_in, const unsigned int nrep);

}  // end namespace boltzmann


text:
/*
 *  nextpnr -- Next Generation Place and Route
 *
 *  Copyright (C) 2018  Clifford Wolf <clifford@symbioticeda.com>
 *  Copyright (C) 2018  Serge Bazanski <q3k@symbioticeda.com>
 *
 *  Permission to use, copy, modify, and/or distribute this software for any
 *  purpose with or without fee is hereby granted, provided that the above
 *  copyright notice and this permission notice appear in all copies.
 *
 *  THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 *  WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 *  MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
 *  ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 *  WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 *  ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 *  OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 *
 */

#include <algorithm>
#include <boost/iostreams/device/mapped_file.hpp>
#include <cmath>
#include "cells.h"
#include "gfx.h"
#include "log.h"
#include "nextpnr.h"
#include "placer1.h"
#include "placer_heap.h"
#include "router1.h"
#include "timing_opt.h"
#include "util.h"
NEXTPNR_NAMESPACE_BEGIN

// -----------------------------------------------------------------------

void IdString::initialize_arch(const BaseCtx *ctx)
{
#define X(t) initialize_add(ctx, #t, ID_##t);
#include "constids.inc"
#undef X
}

// -----------------------------------------------------------------------

static const ChipInfoPOD *get_chip_info(const RelPtr<ChipInfoPOD> *ptr) { return ptr->get(); }

#if defined(_MSC_VER)
void load_chipdb();
#endif

#if defined(EXTERNAL_CHIPDB_ROOT)
const char *chipdb_blob_384 = nullptr;
const char *chipdb_blob_1k = nullptr;
const char *chipdb_blob_5k = nullptr;
const char *chipdb_blob_u4k = nullptr;
const char *chipdb_blob_8k = nullptr;

boost::iostreams::mapped_file_source blob_files[5];

const char *mmap_file(int index, const char *filename)
{
    try {
        blob_files[index].open(filename);
        if (!blob_files[index].is_open())
            log_error("Unable to read chipdb %s\n", filename);
        return (const char *)blob_files[index].data();
    } catch (...) {
        log_error("Unable to read chipdb %s\n", filename);
    }
}

void load_chipdb()
{
    chipdb_blob_384 = mmap_file(0, EXTERNAL_CHIPDB_ROOT "/ice40/chipdb-384.bin");
    chipdb_blob_1k = mmap_file(1, EXTERNAL_CHIPDB_ROOT "/ice40/chipdb-1k.bin");
    chipdb_blob_5k = mmap_file(2, EXTERNAL_CHIPDB_ROOT "/ice40/chipdb-5k.bin");
    chipdb_blob_u4k = mmap_file(3, EXTERNAL_CHIPDB_ROOT "/ice40/chipdb-u4k.bin");
    chipdb_blob_8k = mmap_file(4, EXTERNAL_CHIPDB_ROOT "/ice40/chipdb-8k.bin");
}
#endif
Arch::Arch(ArchArgs args) : args(args)
{
#if defined(_MSC_VER) || defined(EXTERNAL_CHIPDB_ROOT)
    load_chipdb();
#endif

#ifdef ICE40_HX1K_ONLY
    if (args.type == ArchArgs::HX1K) {
        fast_part = true;
        chip_info = get_chip_info(reinterpret_cast<const RelPtr<ChipInfoPOD> *>(chipdb_blob_1k));
    } else {
        log_error("Unsupported iCE40 chip type.\n");
    }
#else
    if (args.type == ArchArgs::LP384) {
        fast_part = false;
        chip_info = get_chip_info(reinterpret_cast<const RelPtr<ChipInfoPOD> *>(chipdb_blob_384));
    } else if (args.type == ArchArgs::LP1K || args.type == ArchArgs::HX1K) {
        fast_part = args.type == ArchArgs::HX1K;
        chip_info = get_chip_info(reinterpret_cast<const RelPtr<ChipInfoPOD> *>(chipdb_blob_1k));
    } else if (args.type == ArchArgs::UP5K) {
        fast_part = false;
        chip_info = get_chip_info(reinterpret_cast<const RelPtr<ChipInfoPOD> *>(chipdb_blob_5k));
    } else if (args.type == ArchArgs::U4K) {
        fast_part = false;
        chip_info = get_chip_info(reinterpret_cast<const RelPtr<ChipInfoPOD> *>(chipdb_blob_u4k));
    } else if (args.type == ArchArgs::LP8K || args.type == ArchArgs::HX8K) {
        fast_part = args.type == ArchArgs::HX8K;
        chip_info = get_chip_info(reinterpret_cast<const RelPtr<ChipInfoPOD> *>(chipdb_blob_8k));
    } else {
        log_error("Unsupported iCE40 chip type.\n");
    }
#endif

    package_info = nullptr;
    for (int i = 0; i < chip_info->num_packages; i++) {
        if (chip_info->packages_data[i].name.get() == args.package) {
            package_info = &(chip_info->packages_data[i]);
            break;
        }
    }
    if (package_info == nullptr)
        log_error("Unsupported package '%s'.\n", args.package.c_str());

    bel_carry.resize(chip_info->num_bels);
    bel_to_cell.resize(chip_info->num_bels);
    wire_to_net.resize(chip_info->num_wires);
    pip_to_net.resize(chip_info->num_pips);
    switches_locked.resize(chip_info->num_switches);
}

// -----------------------------------------------------------------------

std::string Arch::getChipName() const
{
#ifdef ICE40_HX1K_ONLY
    if (args.type == ArchArgs::HX1K) {
        return "Lattice LP1K";
    } else {
        log_error("Unsupported iCE40 chip type.\n");
    }
#else
    if (args.type == ArchArgs::LP384) {
        return "Lattice LP384";
    } else if (args.type == ArchArgs::LP1K) {
        return "Lattice LP1K";
    } else if (args.type == ArchArgs::HX1K) {
        return "Lattice HX1K";
    } else if (args.type == ArchArgs::UP5K) {
        return "Lattice UP5K";
    } else if (args.type == ArchArgs::U4K) {
        return "Lattice U4K";
    } else if (args.type == ArchArgs::LP8K) {
        return "Lattice LP8K";
    } else if (args.type == ArchArgs::HX8K) {
        return "Lattice HX8K";
    } else {
        log_error("Unknown chip\n");
    }
#endif
}

// -----------------------------------------------------------------------

IdString Arch::archArgsToId(ArchArgs args) const
{
    if (args.type == ArchArgs::LP384)
        return id("lp384");
    if (args.type == ArchArgs::LP1K)
        return id("lp1k");
    if (args.type == ArchArgs::HX1K)
        return id("hx1k");
    if (args.type == ArchArgs::UP5K)
        return id("up5k");
    if (args.type == ArchArgs::U4K)
        return id("u4k");
    if (args.type == ArchArgs::LP8K)
        return id("lp8k");
    if (args.type == ArchArgs::HX8K)
        return id("hx8k");
    return IdString();
}

// -----------------------------------------------------------------------

BelId Arch::getBelByName(IdString name) const
{
    BelId ret;

    if (bel_by_name.empty()) {
        for (int i = 0; i < chip_info->num_bels; i++)
            bel_by_name[id(chip_info->bel_data[i].name.get())] = i;
    }

    auto it = bel_by_name.find(name);
    if (it != bel_by_name.end())
        ret.index = it->second;

    return ret;
}

BelId Arch::getBelByLocation(Loc loc) const
{
    BelId bel;

    if (bel_by_loc.empty()) {
        for (int i = 0; i < chip_info->num_bels; i++) {
            BelId b;
            b.index = i;
            bel_by_loc[getBelLocation(b)] = i;
        }
    }

    auto it = bel_by_loc.find(loc);
    if (it != bel_by_loc.end())
        bel.index = it->second;

    return bel;
}

BelRange Arch::getBelsByTile(int x, int y) const
{
    // In iCE40 chipdb bels at the same tile are consecutive and dense z ordinates
    // are used
    BelRange br;

    br.b.cursor = Arch::getBelByLocation(Loc(x, y, 0)).index;
    br.e.cursor = br.b.cursor;

    if (br.e.cursor != -1) {
        while (br.e.cursor < chip_info->num_bels && chip_info->bel_data[br.e.cursor].x == x &&
               chip_info->bel_data[br.e.cursor].y == y)
            br.e.cursor++;
    }

    return br;
}

PortType Arch::getBelPinType(BelId bel, IdString pin) const
{
    NPNR_ASSERT(bel != BelId());

    int num_bel_wires = chip_info->bel_data[bel.index].num_bel_wires;
    const BelWirePOD *bel_wires = chip_info->bel_data[bel.index].bel_wires.get();

    if (num_bel_wires < 7) {
        for (int i = 0; i < num_bel_wires; i++) {
            if (bel_wires[i].port == pin.index)
                return PortType(bel_wires[i].type);
        }
    } else {
        int b = 0, e = num_bel_wires - 1;
        while (b <= e) {
            int i = (b + e) / 2;
            if (bel_wires[i].port == pin.index)
                return PortType(bel_wires[i].type);
            if (bel_wires[i].port > pin.index)
                e = i - 1;
            else
                b = i + 1;
        }
    }

    return PORT_INOUT;
}

std::vector<std::pair<IdString, std::string>> Arch::getBelAttrs(BelId bel) const
{
    std::vector<std::pair<IdString, std::string>> ret;

    ret.push_back(std::make_pair(id("INDEX"), stringf("%d", bel.index)));

    return ret;
}

WireId Arch::getBelPinWire(BelId bel, IdString pin) const
{
    WireId ret;

    NPNR_ASSERT(bel != BelId());

    int num_bel_wires = chip_info->bel_data[bel.index].num_bel_wires;
    const BelWirePOD *bel_wires = chip_info->bel_data[bel.index].bel_wires.get();

    if (num_bel_wires < 7) {
        for (int i = 0; i < num_bel_wires; i++) {
            if (bel_wires[i].port == pin.index) {
                ret.index = bel_wires[i].wire_index;
                break;
            }
        }
    } else {
        int b = 0, e = num_bel_wires - 1;
        while (b <= e) {
            int i = (b + e) / 2;
            if (bel_wires[i].port == pin.index) {
                ret.index = bel_wires[i].wire_index;
                break;
            }
            if (bel_wires[i].port > pin.index)
                e = i - 1;
            else
                b = i + 1;
        }
    }

    return ret;
}

std::vector<IdString> Arch::getBelPins(BelId bel) const
{
    std::vector<IdString> ret;

    NPNR_ASSERT(bel != BelId());

    int num_bel_wires = chip_info->bel_data[bel.index].num_bel_wires;
    const BelWirePOD *bel_wires = chip_info->bel_data[bel.index].bel_wires.get();

    for (int i = 0; i < num_bel_wires; i++)
        ret.push_back(IdString(bel_wires[i].port));

    return ret;
}

bool Arch::isBelLocked(BelId bel) const
{
    const BelConfigPOD *bel_config = nullptr;
    for (int i = 0; i < chip_info->num_belcfgs; i++) {
        if (chip_info->bel_config[i].bel_index == bel.index) {
            bel_config = &chip_info->bel_config[i];
            break;
        }
    }
    NPNR_ASSERT(bel_config != nullptr);
    for (int i = 0; i < bel_config->num_entries; i++) {
        if (strcmp("LOCKED", bel_config->entries[i].cbit_name.get()))
            continue;
        if ("LOCKED_" + archArgs().package == bel_config->entries[i].entry_name.get())
            return true;
    }
    return false;
}

// -----------------------------------------------------------------------

WireId Arch::getWireByName(IdString name) const
{
    WireId ret;

    if (wire_by_name.empty()) {
        for (int i = 0; i < chip_info->num_wires; i++)
            wire_by_name[id(chip_info->wire_data[i].name.get())] = i;
    }

    auto it = wire_by_name.find(name);
    if (it != wire_by_name.end())
        ret.index = it->second;

    return ret;
}

IdString Arch::getWireType(WireId wire) const
{
    NPNR_ASSERT(wire != WireId());
    switch (chip_info->wire_data[wire.index].type) {
    case WireInfoPOD::WIRE_TYPE_NONE:
        return IdString();
    case WireInfoPOD::WIRE_TYPE_GLB2LOCAL:
        return id("GLB2LOCAL");
    case WireInfoPOD::WIRE_TYPE_GLB_NETWK:
        return id("GLB_NETWK");
    case WireInfoPOD::WIRE_TYPE_LOCAL:
        return id("LOCAL");
    case WireInfoPOD::WIRE_TYPE_LUTFF_IN:
        return id("LUTFF_IN");
    case WireInfoPOD::WIRE_TYPE_LUTFF_IN_LUT:
        return id("LUTFF_IN_LUT");
    case WireInfoPOD::WIRE_TYPE_LUTFF_LOUT:
        return id("LUTFF_LOUT");
    case WireInfoPOD::WIRE_TYPE_LUTFF_OUT:
        return id("LUTFF_OUT");
    case WireInfoPOD::WIRE_TYPE_LUTFF_COUT:
        return id("LUTFF_COUT");
    case WireInfoPOD::WIRE_TYPE_LUTFF_GLOBAL:
        return id("LUTFF_GLOBAL");
    case WireInfoPOD::WIRE_TYPE_CARRY_IN_MUX:
        return id("CARRY_IN_MUX");
    case WireInfoPOD::WIRE_TYPE_SP4_V:
        return id("SP4_V");
    case WireInfoPOD::WIRE_TYPE_SP4_H:
        return id("SP4_H");
    case WireInfoPOD::WIRE_TYPE_SP12_V:
        return id("SP12_V");
    case WireInfoPOD::WIRE_TYPE_SP12_H:
        return id("SP12_H");
    }
    return IdString();
}

std::vector<std::pair<IdString, std::string>> Arch::getWireAttrs(WireId wire) const
{
    std::vector<std::pair<IdString, std::string>> ret;
    auto &wi = chip_info->wire_data[wire.index];

    ret.push_back(std::make_pair(id("INDEX"), stringf("%d", wire.index)));

    ret.push_back(std::make_pair(id("GRID_X"), stringf("%d", wi.x)));
    ret.push_back(std::make_pair(id("GRID_Y"), stringf("%d", wi.y)));
    ret.push_back(std::make_pair(id("GRID_Z"), stringf("%d", wi.z)));

#if 0
    for (int i = 0; i < wi.num_segments; i++) {
        auto &si = wi.segments[i];
        ret.push_back(std::make_pair(id(stringf("segment[%d]", i)),
                                     stringf("X%d/Y%d/%s", si.x, si.y, chip_info->tile_wire_names[si.index].get())));
    }
#endif

    return ret;
}

// -----------------------------------------------------------------------

PipId Arch::getPipByName(IdString name) const
{
    PipId ret;

    if (pip_by_name.empty()) {
        for (int i = 0; i < chip_info->num_pips; i++) {
            PipId pip;
            pip.index = i;
            pip_by_name[getPipName(pip)] = i;
        }
    }

    auto it = pip_by_name.find(name);
    if (it != pip_by_name.end())
        ret.index = it->second;

    return ret;
}

IdString Arch::getPipName(PipId pip) const
{
    NPNR_ASSERT(pip != PipId());

#if 1
    int x = chip_info->pip_data[pip.index].x;
    int y = chip_info->pip_data[pip.index].y;

    std::string src_name = chip_info->wire_data[chip_info->pip_data[pip.index].src].name.get();
    std::replace(src_name.begin(), src_name.end(), '/', '.');

    std::string dst_name = chip_info->wire_data[chip_info->pip_data[pip.index].dst].name.get();
    std::replace(dst_name.begin(), dst_name.end(), '/', '.');

    return id("X" + std::to_string(x) + "/Y" + std::to_string(y) + "/" + src_name + ".->." + dst_name);
#else
    return id(chip_info->pip_data[pip.index].name.get());
#endif
}

IdString Arch::getPipType(PipId pip) const { return IdString(); }

std::vector<std::pair<IdString, std::string>> Arch::getPipAttrs(PipId pip) const
{
    std::vector<std::pair<IdString, std::string>> ret;

    ret.push_back(std::make_pair(id("INDEX"), stringf("%d", pip.index)));

    return ret;
}

// -----------------------------------------------------------------------

BelId Arch::getPackagePinBel(const std::string &pin) const
{
    for (int i = 0; i < package_info->num_pins; i++) {
        if (package_info->pins[i].name.get() == pin) {
            BelId id;
            id.index = package_info->pins[i].bel_index;
            return id;
        }
    }
    return BelId();
}

std::string Arch::getBelPackagePin(BelId bel) const
{
    for (int i = 0; i < package_info->num_pins; i++) {
        if (package_info->pins[i].bel_index == bel.index) {
            return std::string(package_info->pins[i].name.get());
        }
    }
    return "";
}

// -----------------------------------------------------------------------

GroupId Arch::getGroupByName(IdString name) const
{
    for (auto g : getGroups())
        if (getGroupName(g) == name)
            return g;
    return GroupId();
}

IdString Arch::getGroupName(GroupId group) const
{
    std::string suffix;

    switch (group.type) {
    case GroupId::TYPE_FRAME:
        suffix = "tile";
        break;
    case GroupId::TYPE_MAIN_SW:
        suffix = "main_sw";
        break;
    case GroupId::TYPE_LOCAL_SW:
        suffix = "local_sw";
        break;
    case GroupId::TYPE_LC0_SW:
        suffix = "lc0_sw";
        break;
    case GroupId::TYPE_LC1_SW:
        suffix = "lc1_sw";
        break;
    case GroupId::TYPE_LC2_SW:
        suffix = "lc2_sw";
        break;
    case GroupId::TYPE_LC3_SW:
        suffix = "lc3_sw";
        break;
    case GroupId::TYPE_LC4_SW:
        suffix = "lc4_sw";
        break;
    case GroupId::TYPE_LC5_SW:
        suffix = "lc5_sw";
        break;
    case GroupId::TYPE_LC6_SW:
        suffix = "lc6_sw";
        break;
    case GroupId::TYPE_LC7_SW:
        suffix = "lc7_sw";
        break;
    default:
        return IdString();
    }

    return id("X" + std::to_string(group.x) + "/Y" + std::to_string(group.y) + "/" + suffix);
}

std::vector<GroupId> Arch::getGroups() const
{
    std::vector<GroupId> ret;

    for (int y = 0; y < chip_info->height; y++) {
        for (int x = 0; x < chip_info->width; x++) {
            TileType type = chip_info->tile_grid[y * chip_info->width + x];
            if (type == TILE_NONE)
                continue;

            GroupId group;
            group.type = GroupId::TYPE_FRAME;
            group.x = x;
            group.y = y;
            // ret.push_back(group);

            group.type = GroupId::TYPE_MAIN_SW;
            ret.push_back(group);

            group.type = GroupId::TYPE_LOCAL_SW;
            ret.push_back(group);

            if (type == TILE_LOGIC) {
                group.type = GroupId::TYPE_LC0_SW;
                ret.push_back(group);

                group.type = GroupId::TYPE_LC1_SW;
                ret.push_back(group);

                group.type = GroupId::TYPE_LC2_SW;
                ret.push_back(group);

                group.type = GroupId::TYPE_LC3_SW;
                ret.push_back(group);

                group.type = GroupId::TYPE_LC4_SW;
                ret.push_back(group);

                group.type = GroupId::TYPE_LC5_SW;
                ret.push_back(group);

                group.type = GroupId::TYPE_LC6_SW;
                ret.push_back(group);

                group.type = GroupId::TYPE_LC7_SW;
                ret.push_back(group);
            }
        }
    }
    return ret;
}

std::vector<BelId> Arch::getGroupBels(GroupId group) const
{
    std::vector<BelId> ret;
    return ret;
}

std::vector<WireId> Arch::getGroupWires(GroupId group) const
{
    std::vector<WireId> ret;
    return ret;
}

std::vector<PipId> Arch::getGroupPips(GroupId group) const
{
    std::vector<PipId> ret;
    return ret;
}

std::vector<GroupId> Arch::getGroupGroups(GroupId group) const
{
    std::vector<GroupId> ret;
    return ret;
}

// -----------------------------------------------------------------------

bool Arch::getBudgetOverride(const NetInfo *net_info, const PortRef &sink, delay_t &budget) const
{
    const auto &driver = net_info->driver;
    if (driver.port == id_COUT) {
        NPNR_ASSERT(sink.port == id_CIN || sink.port == id_I3);
        NPNR_ASSERT(driver.cell->constr_abs_z);
        bool cin = sink.port == id_CIN;
        bool same_y = driver.cell->constr_z < 7;
        if (cin && same_y)
            budget = 0;
        else {
            switch (args.type) {
#ifndef ICE40_HX1K_ONLY
            case ArchArgs::HX8K:
#endif
            case ArchArgs::HX1K:
                budget = cin ? 190 : (same_y ? 260 : 560);
                break;
#ifndef ICE40_HX1K_ONLY
            case ArchArgs::LP384:
            case ArchArgs::LP1K:
            case ArchArgs::LP8K:
                budget = cin ? 290 : (same_y ? 380 : 670);
                break;
            case ArchArgs::UP5K:
            case ArchArgs::U4K:
                budget = cin ? 560 : (same_y ? 660 : 1220);
                break;
#endif
            default:
                log_error("Unsupported iCE40 chip type.\n");
            }
        }
        return true;
    }
    return false;
}

// -----------------------------------------------------------------------

bool Arch::place()
{
    std::string placer = str_or_default(settings, id("placer"), defaultPlacer);
    if (placer == "heap") {
        PlacerHeapCfg cfg(getCtx());
        cfg.ioBufTypes.insert(id_SB_IO);
        if (!placer_heap(getCtx(), cfg))
            return false;
    } else if (placer == "sa") {
        if (!placer1(getCtx(), Placer1Cfg(getCtx())))
            return false;
    } else {
        log_error("iCE40 architecture does not support placer '%s'\n", placer.c_str());
    }
    if (bool_or_default(settings, id("opt_timing"), false)) {
        TimingOptCfg tocfg(getCtx());
        tocfg.cellTypes.insert(id_ICESTORM_LC);
        return timing_opt(getCtx(), tocfg);
    } else {
        return true;
    }
}

bool Arch::route() { return router1(getCtx(), Router1Cfg(getCtx())); }

// -----------------------------------------------------------------------

DecalXY Arch::getBelDecal(BelId bel) const
{
    DecalXY decalxy;
    decalxy.decal.type = DecalId::TYPE_BEL;
    decalxy.decal.index = bel.index;
    decalxy.decal.active = bel_to_cell.at(bel.index) != nullptr;
    return decalxy;
}

DecalXY Arch::getWireDecal(WireId wire) const
{
    DecalXY decalxy;
    decalxy.decal.type = DecalId::TYPE_WIRE;
    decalxy.decal.index = wire.index;
    decalxy.decal.active = wire_to_net.at(wire.index) != nullptr;
    return decalxy;
}

DecalXY Arch::getPipDecal(PipId pip) const
{
    DecalXY decalxy;
    decalxy.decal.type = DecalId::TYPE_PIP;
    decalxy.decal.index = pip.index;
    decalxy.decal.active = pip_to_net.at(pip.index) != nullptr;
    return decalxy;
};

DecalXY Arch::getGroupDecal(GroupId group) const
{
    DecalXY decalxy;
    decalxy.decal.type = DecalId::TYPE_GROUP;
    decalxy.decal.index = (group.type << 16) | (group.x << 8) | (group.y);
    decalxy.decal.active = true;
    return decalxy;
};

std::vector<GraphicElement> Arch::getDecalGraphics(DecalId decal) const
{
    std::vector<GraphicElement> ret;

    if (decal.type == DecalId::TYPE_GROUP) {
        int type = (decal.index >> 16) & 255;
        int x = (decal.index >> 8) & 255;
        int y = decal.index & 255;

        if (type == GroupId::TYPE_FRAME) {
            GraphicElement el;
            el.type = GraphicElement::TYPE_LINE;
            el.style = GraphicElement::STYLE_FRAME;

            el.x1 = x + 0.01, el.x2 = x + 0.02, el.y1 = y + 0.01, el.y2 = y + 0.01;
            ret.push_back(el);
            el.x1 = x + 0.01, el.x2 = x + 0.01, el.y1 = y + 0.01, el.y2 = y + 0.02;
            ret.push_back(el);

            el.x1 = x + 0.99, el.x2 = x + 0.98, el.y1 = y + 0.01, el.y2 = y + 0.01;
            ret.push_back(el);
            el.x1 = x + 0.99, el.x2 = x + 0.99, el.y1 = y + 0.01, el.y2 = y + 0.02;
            ret.push_back(el);

            el.x1 = x + 0.99, el.x2 = x + 0.98, el.y1 = y + 0.99, el.y2 = y + 0.99;
            ret.push_back(el);
            el.x1 = x + 0.99, el.x2 = x + 0.99, el.y1 = y + 0.99, el.y2 = y + 0.98;
            ret.push_back(el);

            el.x1 = x + 0.01, el.x2 = x + 0.02, el.y1 = y + 0.99, el.y2 = y + 0.99;
            ret.push_back(el);
            el.x1 = x + 0.01, el.x2 = x + 0.01, el.y1 = y + 0.99, el.y2 = y + 0.98;
            ret.push_back(el);
        }

        if (type == GroupId::TYPE_MAIN_SW) {
            GraphicElement el;
            el.type = GraphicElement::TYPE_BOX;
            el.style = GraphicElement::STYLE_FRAME;

            el.x1 = x + main_swbox_x1;
            el.x2 = x + main_swbox_x2;
            el.y1 = y + main_swbox_y1;
            el.y2 = y + main_swbox_y2;
            ret.push_back(el);
        }

        if (type == GroupId::TYPE_LOCAL_SW) {
            GraphicElement el;
            el.type = GraphicElement::TYPE_BOX;
            el.style = GraphicElement::STYLE_FRAME;

            el.x1 = x + local_swbox_x1;
            el.x2 = x + local_swbox_x2;
            el.y1 = y + local_swbox_y1;
            el.y2 = y + local_swbox_y2;
            ret.push_back(el);
        }

        if (GroupId::TYPE_LC0_SW <= type && type <= GroupId::TYPE_LC7_SW) {
            GraphicElement el;
            el.type = GraphicElement::TYPE_BOX;
            el.style = GraphicElement::STYLE_FRAME;

            el.x1 = x + lut_swbox_x1;
            el.x2 = x + lut_swbox_x2;
            el.y1 = y + logic_cell_y1 + logic_cell_pitch * (type - GroupId::TYPE_LC0_SW);
            el.y2 = y + logic_cell_y2 + logic_cell_pitch * (type - GroupId::TYPE_LC0_SW);
            ret.push_back(el);
        }
    }

    if (decal.type == DecalId::TYPE_WIRE) {
        int n = chip_info->wire_data[decal.index].num_segments;
        const WireSegmentPOD *p = chip_info->wire_data[decal.index].segments.get();

        GraphicElement::style_t style = decal.active ? GraphicElement::STYLE_ACTIVE : GraphicElement::STYLE_INACTIVE;

        for (int i = 0; i < n; i++)
            gfxTileWire(ret, p[i].x, p[i].y, chip_info->width, chip_info->height, GfxTileWireId(p[i].index), style);

#if 0
        if (ret.empty()) {
            WireId wire;
            wire.index = decal.index;
            log_warning("No gfx decal for wire %s (%d).\n", getWireName(wire).c_str(getCtx()), decal.index);
        }
#endif
    }

    if (decal.type == DecalId::TYPE_PIP) {
        const PipInfoPOD &p = chip_info->pip_data[decal.index];
        GraphicElement::style_t style = decal.active ? GraphicElement::STYLE_ACTIVE : GraphicElement::STYLE_HIDDEN;
        gfxTilePip(ret, p.x, p.y, GfxTileWireId(p.src_seg), GfxTileWireId(p.dst_seg), style);

#if 0
        if (ret.empty()) {
            PipId pip;
            pip.index = decal.index;
            log_warning("No gfx decal for pip %s (%d).\n", getPipName(pip).c_str(getCtx()), decal.index);
        }
#endif
    }

    if (decal.type == DecalId::TYPE_BEL) {
        BelId bel;
        bel.index = decal.index;

        auto bel_type = getBelType(bel);

        if (bel_type == id_ICESTORM_LC) {
            GraphicElement el;
            el.type = GraphicElement::TYPE_BOX;
            el.style = decal.active ? GraphicElement::STYLE_ACTIVE : GraphicElement::STYLE_INACTIVE;
            el.x1 = chip_info->bel_data[bel.index].x + logic_cell_x1;
            el.x2 = chip_info->bel_data[bel.index].x + logic_cell_x2;
            el.y1 = chip_info->bel_data[bel.index].y + logic_cell_y1 +
                    (chip_info->bel_data[bel.index].z) * logic_cell_pitch;
            el.y2 = chip_info->bel_data[bel.index].y + logic_cell_y2 +
                    (chip_info->bel_data[bel.index].z) * logic_cell_pitch;
            ret.push_back(el);
        }

        if (bel_type == id_SB_IO) {
            GraphicElement el;
            el.type = GraphicElement::TYPE_BOX;
            el.style = decal.active ? GraphicElement::STYLE_ACTIVE : GraphicElement::STYLE_INACTIVE;
            el.x1 = chip_info->bel_data[bel.index].x + lut_swbox_x1;
            el.x2 = chip_info->bel_data[bel.index].x + logic_cell_x2;
            el.y1 = chip_info->bel_data[bel.index].y + logic_cell_y1 +
                    (4 * chip_info->bel_data[bel.index].z) * logic_cell_pitch;
            el.y2 = chip_info->bel_data[bel.index].y + logic_cell_y2 +
                    (4 * chip_info->bel_data[bel.index].z + 3) * logic_cell_pitch;
            ret.push_back(el);
        }

        if (bel_type == id_ICESTORM_RAM) {
            for (int i = 0; i < 2; i++) {
                GraphicElement el;
                el.type = GraphicElement::TYPE_BOX;
                el.style = decal.active ? GraphicElement::STYLE_ACTIVE : GraphicElement::STYLE_INACTIVE;
                el.x1 = chip_info->bel_data[bel.index].x + lut_swbox_x1;
                el.x2 = chip_info->bel_data[bel.index].x + logic_cell_x2;
                el.y1 = chip_info->bel_data[bel.index].y + logic_cell_y1 + i;
                el.y2 = chip_info->bel_data[bel.index].y + logic_cell_y2 + i + 7 * logic_cell_pitch;
                ret.push_back(el);
            }
        }

        if (bel_type == id_SB_GB) {
            GraphicElement el;
            el.type = GraphicElement::TYPE_BOX;
            el.style = decal.active ? GraphicElement::STYLE_ACTIVE : GraphicElement::STYLE_INACTIVE;
            el.x1 = chip_info->bel_data[bel.index].x + local_swbox_x1 + 0.05;
            el.x2 = chip_info->bel_data[bel.index].x + logic_cell_x2 - 0.05;
            el.y1 = chip_info->bel_data[bel.index].y + main_swbox_y2 - 0.05;
            el.y2 = chip_info->bel_data[bel.index].y + main_swbox_y2 - 0.10;
            ret.push_back(el);
        }

        if (bel_type == id_ICESTORM_PLL || bel_type == id_SB_WARMBOOT) {
            GraphicElement el;
            el.type = GraphicElement::TYPE_BOX;
            el.style = decal.active ? GraphicElement::STYLE_ACTIVE : GraphicElement::STYLE_INACTIVE;
            el.x1 = chip_info->bel_data[bel.index].x + local_swbox_x1 + 0.05;
            el.x2 = chip_info->bel_data[bel.index].x + logic_cell_x2 - 0.05;
            el.y1 = chip_info->bel_data[bel.index].y + main_swbox_y2;
            el.y2 = chip_info->bel_data[bel.index].y + main_swbox_y2 + 0.05;
            ret.push_back(el);
        }

#if 0
        if (ret.empty()) {
            BelId bel;
            bel.index = decal.index;
            log_warning("No gfx decal for bel %s (%d).\n", getBelName(bel).c_str(getCtx()), decal.index);
        }
#endif
    }

    return ret;
}

// -----------------------------------------------------------------------

bool Arch::getCellDelay(const CellInfo *cell, IdString fromPort, IdString toPort, DelayInfo &delay) const
{
    if (cell->type == id_ICESTORM_LC && cell->lcInfo.dffEnable) {
        if (toPort == id_O)
            return false;
    } else if (cell->type == id_ICESTORM_RAM || cell->type == id_ICESTORM_SPRAM) {
        return false;
    }
    return getCellDelayInternal(cell, fromPort, toPort, delay);
}

bool Arch::getCellDelayInternal(const CellInfo *cell, IdString fromPort, IdString toPort, DelayInfo &delay) const
{
    for (int i = 0; i < chip_info->num_timing_cells; i++) {
        const auto &tc = chip_info->cell_timing[i];
        if (tc.type == cell->type.index) {
            for (int j = 0; j < tc.num_paths; j++) {
                const auto &path = tc.path_delays[j];
                if (path.from_port == fromPort.index && path.to_port == toPort.index) {
                    if (fast_part)
                        delay.delay = path.fast_delay;
                    else
                        delay.delay = path.slow_delay;
                    return true;
                }
            }
            break;
        }
    }
    return false;
}

// Get the port class, also setting clockPort to associated clock if applicable
TimingPortClass Arch::getPortTimingClass(const CellInfo *cell, IdString port, int &clockInfoCount) const
{
    clockInfoCount = 0;
    if (cell->type == id_ICESTORM_LC) {
        if (port == id_CLK)
            return TMG_CLOCK_INPUT;
        if (port == id_CIN)
            return TMG_COMB_INPUT;
        if (port == id_COUT || port == id_LO)
            return TMG_COMB_OUTPUT;
        if (port == id_O) {
            // LCs with no inputs are constant drivers
            if (cell->lcInfo.inputCount == 0)
                return TMG_IGNORE;
            if (cell->lcInfo.dffEnable) {
                clockInfoCount = 1;
                return TMG_REGISTER_OUTPUT;
            } else
                return TMG_COMB_OUTPUT;
        } else {
            if (cell->lcInfo.dffEnable) {
                clockInfoCount = 1;
                return TMG_REGISTER_INPUT;
            } else
                return TMG_COMB_INPUT;
        }
    } else if (cell->type == id_ICESTORM_RAM) {

        if (port == id_RCLK || port == id_WCLK)
            return TMG_CLOCK_INPUT;

        clockInfoCount = 1;

        if (cell->ports.at(port).type == PORT_OUT)
            return TMG_REGISTER_OUTPUT;
        else
            return TMG_REGISTER_INPUT;
    } else if (cell->type == id_ICESTORM_DSP || cell->type == id_ICESTORM_SPRAM) {
        if (port == id_CLK || port == id_CLOCK)
            return TMG_CLOCK_INPUT;
        else {
            clockInfoCount = 1;
            if (cell->ports.at(port).type == PORT_OUT)
                return TMG_REGISTER_OUTPUT;
            else
                return TMG_REGISTER_INPUT;
        }
    } else if (cell->type == id_SB_IO) {
        if (port == id_INPUT_CLK || port == id_OUTPUT_CLK)
            return TMG_CLOCK_INPUT;
        if (port == id_CLOCK_ENABLE) {
            clockInfoCount = 2;
            return TMG_REGISTER_INPUT;
        }
        if ((port == id_D_IN_0 && !(cell->ioInfo.pintype & 0x1)) || port == id_D_IN_1) {
            clockInfoCount = 1;
            return TMG_REGISTER_OUTPUT;
        } else if (port == id_D_IN_0) {
            return TMG_STARTPOINT;
        }
        if (port == id_D_OUT_0 || port == id_D_OUT_1) {
            if ((cell->ioInfo.pintype & 0xC) == 0x8) {
                return TMG_ENDPOINT;
            } else {
                clockInfoCount = 1;
                return TMG_REGISTER_INPUT;
            }
        }
        if (port == id_OUTPUT_ENABLE) {
            if ((cell->ioInfo.pintype & 0x18) == 0x18) {
                return TMG_REGISTER_INPUT;
            } else {
                return TMG_ENDPOINT;
            }
        }

        return TMG_IGNORE;
    } else if (cell->type == id_ICESTORM_PLL) {
        if (port == id_PLLOUT_A || port == id_PLLOUT_B || port == id_PLLOUT_A_GLOBAL || port == id_PLLOUT_B_GLOBAL)
            return TMG_GEN_CLOCK;
        return TMG_IGNORE;
    } else if (cell->type == id_ICESTORM_LFOSC) {
        if (port == id_CLKLF)
            return TMG_GEN_CLOCK;
        return TMG_IGNORE;
    } else if (cell->type == id_ICESTORM_HFOSC) {
        if (port == id_CLKHF)
            return TMG_GEN_CLOCK;
        return TMG_IGNORE;
    } else if (cell->type == id_SB_GB) {
        if (port == id_GLOBAL_BUFFER_OUTPUT)
            return cell->gbInfo.forPadIn ? TMG_GEN_CLOCK : TMG_COMB_OUTPUT;
        return TMG_COMB_INPUT;
    } else if (cell->type == id_SB_WARMBOOT) {
        return TMG_ENDPOINT;
    } else if (cell->type == id_SB_RGBA_DRV) {
        if (port == id_RGB0 || port == id_RGB1 || port == id_RGB2)
            return TMG_IGNORE;
        return TMG_ENDPOINT;
    } else if (cell->type == id_SB_LEDDA_IP) {
        if (port == id_CLK || port == id_CLOCK)
            return TMG_CLOCK_INPUT;
        return TMG_IGNORE;
    } else if (cell->type == id_SB_I2C || cell->type == id_SB_SPI) {
        if (port == this->id("SBCLKI"))
            return TMG_CLOCK_INPUT;

        clockInfoCount = 1;

        if (cell->ports.at(port).type == PORT_OUT)
            return TMG_REGISTER_OUTPUT;
        else
            return TMG_REGISTER_INPUT;
    }
    log_error("cell type '%s' is unsupported (instantiated as '%s')\n", cell->type.c_str(this), cell->name.c_str(this));
}

TimingClockingInfo Arch::getPortClockingInfo(const CellInfo *cell, IdString port, int index) const
{
    TimingClockingInfo info;
    if (cell->type == id_ICESTORM_LC) {
        info.clock_port = id_CLK;
        info.edge = cell->lcInfo.negClk ? FALLING_EDGE : RISING_EDGE;
        if (port == id_O) {
            bool has_clktoq = getCellDelayInternal(cell, id_CLK, id_O, info.clockToQ);
            NPNR_ASSERT(has_clktoq);
        } else {
            if (port == id_I0 || port == id_I1 || port == id_I2 || port == id_I3) {
                DelayInfo dlut;
                bool has_ld = getCellDelayInternal(cell, port, id_O, dlut);
                NPNR_ASSERT(has_ld);
                if (args.type == ArchArgs::LP1K || args.type == ArchArgs::LP8K || args.type == ArchArgs::LP384) {
                    info.setup.delay = 30 + dlut.delay;
                } else if (args.type == ArchArgs::UP5K || args.type == ArchArgs::U4K) { // XXX verify u4k
                    info.setup.delay = dlut.delay - 50;
                } else {
                    info.setup.delay = 20 + dlut.delay;
                }
            } else {
                info.setup.delay = 100;
            }
            info.hold.delay = 0;
        }
    } else if (cell->type == id_ICESTORM_RAM) {
        if (port.str(this)[0] == 'R') {
            info.clock_port = id_RCLK;
            info.edge = bool_or_default(cell->params, id("NEG_CLK_R")) ? FALLING_EDGE : RISING_EDGE;
        } else {
            info.clock_port = id_WCLK;
            info.edge = bool_or_default(cell->params, id("NEG_CLK_W")) ? FALLING_EDGE : RISING_EDGE;
        }
        if (cell->ports.at(port).type == PORT_OUT) {
            bool has_clktoq = getCellDelayInternal(cell, info.clock_port, port, info.clockToQ);
            NPNR_ASSERT(has_clktoq);
        } else {
            info.setup.delay = 100;
            info.hold.delay = 0;
        }
    } else if (cell->type == id_SB_IO) {
        delay_t io_setup = 80, io_clktoq = 140;
        if (args.type == ArchArgs::LP1K || args.type == ArchArgs::LP8K || args.type == ArchArgs::LP384) {
            io_setup = 115;
            io_clktoq = 210;
        } else if (args.type == ArchArgs::UP5K || args.type == ArchArgs::U4K) {
            io_setup = 205;
            io_clktoq = 1005;
        }
        if (port == id_CLOCK_ENABLE) {
            info.clock_port = (index == 1) ? id_OUTPUT_CLK : id_INPUT_CLK;
            info.edge = cell->ioInfo.negtrig ? FALLING_EDGE : RISING_EDGE;
            info.setup.delay = io_setup;
            info.hold.delay = 0;
        } else if (port == id_D_OUT_0 || port == id_OUTPUT_ENABLE) {
            info.clock_port = id_OUTPUT_CLK;
            info.edge = cell->ioInfo.negtrig ? FALLING_EDGE : RISING_EDGE;
            info.setup.delay = io_setup;
            info.hold.delay = 0;
        } else if (port == id_D_OUT_1) {
            info.clock_port = id_OUTPUT_CLK;
            info.edge = cell->ioInfo.negtrig ? RISING_EDGE : FALLING_EDGE;
            info.setup.delay = io_setup;
            info.hold.delay = 0;
        } else if (port == id_D_IN_0) {
            info.clock_port = id_INPUT_CLK;
            info.edge = cell->ioInfo.negtrig ? FALLING_EDGE : RISING_EDGE;
            info.clockToQ.delay = io_clktoq;
        } else if (port == id_D_IN_1) {
            info.clock_port = id_INPUT_CLK;
            info.edge = cell->ioInfo.negtrig ? RISING_EDGE : FALLING_EDGE;
            info.clockToQ.delay = io_clktoq;
        } else {
            NPNR_ASSERT_FALSE("no clock data for IO cell port");
        }
    } else if (cell->type == id_ICESTORM_DSP || cell->type == id_ICESTORM_SPRAM) {
        info.clock_port = cell->type == id_ICESTORM_SPRAM ? id_CLOCK : id_CLK;
        info.edge = RISING_EDGE;
        if (cell->ports.at(port).type == PORT_OUT) {
            bool has_clktoq = getCellDelayInternal(cell, info.clock_port, port, info.clockToQ);
            if (!has_clktoq)
                info.clockToQ.delay = 100;
        } else {
            info.setup.delay = 100;
            info.hold.delay = 0;
        }
    } else if (cell->type == id_SB_I2C || cell->type == id_SB_SPI) {
        info.clock_port = this->id("SBCLKI");
        info.edge = RISING_EDGE;
        if (cell->ports.at(port).type == PORT_OUT) {
            /* Dummy number */
            info.clockToQ.delay = 1500;
        } else {
            /* Dummy number */
            info.setup.delay = 1500;
            info.hold.delay = 0;
        }
    } else {
        NPNR_ASSERT_FALSE("unhandled cell type in getPortClockingInfo");
    }
    return info;
}

bool Arch::isGlobalNet(const NetInfo *net) const
{
    if (net == nullptr)
        return false;
    return net->driver.cell != nullptr && net->driver.port == id_GLOBAL_BUFFER_OUTPUT;
}

// Assign arch arg info
void Arch::assignArchInfo()
{
    for (auto &net : getCtx()->nets) {
        NetInfo *ni = net.second.get();
        if (isGlobalNet(ni))
            ni->is_global = true;
        ni->is_enable = false;
        ni->is_reset = false;
        for (auto usr : ni->users) {
            if (is_enable_port(this, usr))
                ni->is_enable = true;
            if (is_reset_port(this, usr))
                ni->is_reset = true;
        }
    }
    for (auto &cell : getCtx()->cells) {
        CellInfo *ci = cell.second.get();
        assignCellInfo(ci);
    }
}

void Arch::assignCellInfo(CellInfo *cell)
{
    if (cell->type == id_ICESTORM_LC) {
        cell->lcInfo.dffEnable = bool_or_default(cell->params, id_DFF_ENABLE);
        cell->lcInfo.carryEnable = bool_or_default(cell->params, id_CARRY_ENABLE);
        cell->lcInfo.negClk = bool_or_default(cell->params, id_NEG_CLK);
        cell->lcInfo.clk = get_net_or_empty(cell, id_CLK);
        cell->lcInfo.cen = get_net_or_empty(cell, id_CEN);
        cell->lcInfo.sr = get_net_or_empty(cell, id_SR);
        cell->lcInfo.inputCount = 0;
        if (get_net_or_empty(cell, id_I0))
            cell->lcInfo.inputCount++;
        if (get_net_or_empty(cell, id_I1))
            cell->lcInfo.inputCount++;
        if (get_net_or_empty(cell, id_I2))
            cell->lcInfo.inputCount++;
        if (get_net_or_empty(cell, id_I3))
            cell->lcInfo.inputCount++;
    } else if (cell->type == id_SB_IO) {
        cell->ioInfo.lvds = str_or_default(cell->params, id_IO_STANDARD, "SB_LVCMOS") == "SB_LVDS_INPUT";
        cell->ioInfo.global = bool_or_default(cell->attrs, this->id("GLOBAL"));
        cell->ioInfo.pintype = int_or_default(cell->params, this->id("PIN_TYPE"));
        cell->ioInfo.negtrig = bool_or_default(cell->params, this->id("NEG_TRIGGER"));

    } else if (cell->type == id_SB_GB) {
        cell->gbInfo.forPadIn = bool_or_default(cell->attrs, this->id("FOR_PAD_IN"));
    }
}

const std::string Arch::defaultPlacer = "sa";

const std::vector<std::string> Arch::availablePlacers = {"sa",
#ifdef WITH_HEAP
                                                         "heap"
#endif
};

NEXTPNR_NAMESPACE_END

ext: cc

max_stars_repo_name: jboone/nextpnr

max_issues_repo_name: jboone/nextpnr

max_forks_repo_name: jboone/nextpnr


text:
/*
Created:        --
Last Updated:    7 May 2018

Dan Marley
daniel.edison.marley@cernSPAMNOT.ch
Texas A&M University
-----

Basic steering macro for running CyMiniAna
 - Make flat ntuples for machine learning
 - Make histograms to compare features
*/
#include "TROOT.h"
#include "TFile.h"
#include "TTree.h"
#include "TChain.h"
#include "TH1.h"
#include "TSystem.h"
#include "TMath.h"
#include "TTreeReader.h"
#include "TTreeReaderValue.h"
#include "TTreeReaderArray.h"

#include <iostream>
#include <sstream>
#include <stdio.h>
#include <map>
#include <fstream>
#include <string>
#include <math.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <boost/algorithm/string/join.hpp>

#include "Analysis/CyMiniAna/interface/configuration.h"
#include "Analysis/CyMiniAna/interface/Event.h"
#include "Analysis/CyMiniAna/interface/eventSelection.h"
#include "Analysis/CyMiniAna/interface/flatTree4ML.h"
#include "Analysis/CyMiniAna/interface/tools.h"
#include "Analysis/CyMiniAna/interface/histogrammer4ML.h"

int main(int argc, char** argv) {
    /* Steering macro for CyMiniAna */
    if (argc < 2) {
        cma::HELP();
        return -1;
    }

    unsigned long long maxEntriesToRun(0);     // maximum number of entries in TTree
    unsigned int numberOfEventsToRun(0);       // number of events to run

    // configuration
    configuration config(argv[1]);                         // configuration file
    config.initialize();

    long long nEvents(config.nEventsToProcess());                    // requested number of events to run
    std::string outpath(config.outputFilePath());                    // directory for output files
    std::string outpathBase(config.outputFilePath());                // directory for output files (base name to modify)
    unsigned long long firstEvent(config.firstEvent());              // first event to begin running over
    std::vector<std::string> filenames  = config.filesToProcess();
    std::vector<std::string> treenames  = config.treeNames();
    std::vector<std::string> selections = config.selections();
    std::vector<std::string> cutfiles   = config.cutsfiles();
    std::string selection = boost::algorithm::join(selections, "-");

    bool generateCutsFiles = (cutfiles.size()!=selections.size());   // user did not provide different cuts files
    std::string treename( treenames.at(0) );

    std::string customDirectory( config.customDirectory() );
    if (customDirectory.length()>0  && customDirectory.substr(0,1).compare("_")!=0){
        customDirectory = "_"+customDirectory; // add '_' to beginning of string, if needed
    }

    // event selection(s) -- support for multiple event selections simulataneously
    std::vector<eventSelection> evtSels;
    std::vector<unsigned int> ncuts;                         // number of cuts in selection
    std::vector< std::vector<std::string> > namesOfCuts;     // names of cuts in selection
    for (unsigned int ss=0, size=selections.size(); ss<size; ss++) {
        std::string sel      = selections.at(ss);
        std::string cutsfile = (generateCutsFiles) ? "config/cuts_"+sel+".txt" : cutfiles.at(ss);

        eventSelection evtSel_tmp( config );
        evtSel_tmp.initialize( sel, cutsfile );

        evtSels.push_back(evtSel_tmp);
        ncuts.push_back(evtSel_tmp.numberOfCuts());
        namesOfCuts.push_back( evtSel_tmp.cutNames() );
    }

    // --------------- //
    // -- File loop -- //
    // --------------- //
    unsigned int numberOfFiles(filenames.size());
    unsigned int currentFileNumber(0);
    cma::INFO("RUNML : *** Starting file loop *** ");
    for (const auto& filename : filenames) {

        ++currentFileNumber;
        cma::INFO("RUNML :   Opening "+filename+"   ("+std::to_string(currentFileNumber)+"/"+std::to_string(numberOfFiles)+")");

        auto file = TFile::Open(filename.c_str());
        if (!file || file->IsZombie()){
            cma::WARNING("RUNML :  -- File: "+filename);
            cma::WARNING("RUNML :     does not exist or it is a Zombie. ");
            cma::WARNING("RUNML :     Continuing to next file. ");
            continue;
        }

        // Inspecting the file
        std::vector<std::string> fileKeys;
        cma::getListOfKeys(file,fileKeys);                  // keep track of ttrees in file

        std::string metadata_treename("tree/metadata");     // hard-coded for now
        std::vector<std::string> metadata_names;
        cma::split(metadata_treename, '/', metadata_names);
        if (std::find(fileKeys.begin(), fileKeys.end(), metadata_treename) == fileKeys.end())
            metadata_treename = "";  // metadata TTree doesn't exist, set this so "config" won't look for it
        config.inspectFile( *file,metadata_treename );      // check the type of file being processed
        Sample s = config.sample();

        // -- Output file -- //
        // CMS doesn't use 'mcChannelNumber', need to keep the same file names
        // therefore, make new directories for the different selections
        struct stat dirBuffer;
        std::string outpath = outpathBase+"/"+selection+customDirectory;
        if ( !(stat((outpath).c_str(),&dirBuffer)==0 && S_ISDIR(dirBuffer.st_mode)) ){
            cma::DEBUG("RUNML : Creating directory for storing output: "+outpath);
            system( ("mkdir "+outpath).c_str() );  // make the directory so the files are grouped together
        }

        std::size_t pos   = filename.find_last_of(".");     // the last ".", i.e., ".root"
        std::size_t found = filename.find_last_of("/");     // the last "/"
        std::string outputFilename = filename.substr(found+1,pos-1-found); // betwee "/" and "."
        // hopefully this returns: "diboson_WW_361082" given something like:
        // "/some/path/to/file/diboson_WW_361082.root"

        std::string fullOutputFilename = outpath+"/"+outputFilename+".root";
        std::unique_ptr<TFile> outputFile(TFile::Open( fullOutputFilename.c_str(), "RECREATE"));
        cma::INFO("RUNML :   >> Saving to "+fullOutputFilename);

        histogrammer4ML histMaker(config,"ML");      // initialize histogrammer
        histMaker.initialize( *outputFile );

        for (auto& x : evtSels) x.setCutflowHistograms( *outputFile );  // setup cutflow histograms

        // check that the ttree exists in this file before proceeding
        if (std::find(fileKeys.begin(), fileKeys.end(), treename) == fileKeys.end()){
            cma::INFO("RUNML : TTree "+treename+" is not present in this file, continuing to next TTree");
            continue;
        }

        // -- Load TTree to loop over
        cma::INFO("RUNML :      TTree "+treename);
        TTreeReader myReader(treename.c_str(), file);

        // -- Make new Tree in Root file
        flatTree4ML miniTTree(config);          // initialize TTree for new file
        miniTTree.initialize( *outputFile );

        // -- Number of Entries to Process -- //
        maxEntriesToRun = myReader.GetEntries(true);
        if (maxEntriesToRun<1) // skip files with no entries
            continue;

        if (nEvents < 0 || ((unsigned int)nEvents+firstEvent) > maxEntriesToRun)
            numberOfEventsToRun = maxEntriesToRun - firstEvent;
        else
            numberOfEventsToRun = nEvents;

        // ---------------- //
        // -- Event Loop -- //
        // ---------------- //
        Long64_t imod = 1;                     // print to the terminal
        Event event = Event(myReader, config);

        Long64_t eventCounter = 0;    // counting the events processed
        Long64_t entry = firstEvent;  // start at a different event!
        while (myReader.Next()) {

            if (eventCounter+1 > numberOfEventsToRun){
                cma::INFO("RUNML : Processed the desired number of events: "+std::to_string(eventCounter)+"/"+std::to_string(numberOfEventsToRun));
                break;
            }

            if (entry%imod==0){
                cma::INFO("RUNML :       Processing event "+std::to_string(entry) );
                if(imod<2e4) imod *=10;
            }

            // -- Build Event -- //
            cma::DEBUG("RUNML : Execute event");
            event.execute(entry);
            // now we have event object that has the event-level objects in it
            // pass this to the selection tools

            // -- Event Selection -- //
            // can do separate cutflows by creating multiple instances of eventSelection()
            cma::DEBUG("RUNML : Apply event selection");
            std::vector<unsigned int> passEvents;
            unsigned int passedEvents(0);
            for (unsigned int ss=0,size=selections.size();ss<size;ss++){
                bool passEvent = evtSels.at(ss).applySelection(event);
                cma::DEBUG("RUNML : Event selection "+selections.at(ss)+" = "+std::to_string(passEvent));
                passEvents.push_back( passEvent );
                passedEvents += passEvent;
            }

            if (passedEvents>0){
                cma::DEBUG("RUNML : Passed selection, now save information");
                std::map<std::string,double> features2save;        // save features related to neutrino pz

                std::map<std::string,double> features = event.deepLearningFeatures();
                if (features.size()>0) { // only save information if we have features to save!

                    for (const auto& x : features )
                        features2save[x.first] = x.second;

                    features2save["xsection"] = s.XSection;
                    features2save["kfactor"]  = s.KFactor;
                    features2save["sumOfWeights"]   = s.sumOfWeights;
                    features2save["nominal_weight"] = event.nominal_weight();
                    features2save["weight"] = 1.;  // weight the entries in the network in some way

                    miniTTree.saveEvent(features2save);
                    histMaker.fill(features2save);
                }
            }

            // iterate the entry and number of events processed
            ++entry;
            ++eventCounter;
        } // end event loop

        event.finalize();
        miniTTree.finalize();

        // put overflow/underflow content into the first and last bins
        histMaker.overUnderFlow();

        cma::INFO("RUNML :   END Running  "+filename);
        cma::INFO("RUNML :   >> Output at "+fullOutputFilename);

        outputFile->Write();
        outputFile->Close();

        // -- Clean-up stuff
        delete file;          // free up some memory
        file = ((TFile *)0);  // (no errors for too many root files open)
    } // end file loop

    cma::INFO("RUNML : *** End of file loop *** ");
    cma::INFO("RUNML : Program finished. ");
}

// THE END

ext: cxx

max_stars_repo_name: jsiado/CyMiniAna

max_issues_repo_name: jsiado/CyMiniAna

max_forks_repo_name: jsiado/CyMiniAna


text:
/*
 * Copyright 2019 GridGain Systems, Inc. and Contributors.
 *
 * Licensed under the GridGain Community Edition License (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     https://www.gridgain.com/products/software/community-edition/gridgain-community-edition-license
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include <boost/test/unit_test.hpp>

#include "ignite/impl/handle_registry.h"

using namespace ignite::common::concurrent;
using namespace ignite::impl;

struct HandleRegistryTestProbe
{
    bool deleted;

    HandleRegistryTestProbe()
    {
        deleted = false;
    }
};

class HandleRegistryTestEntry
{
public:
    HandleRegistryTestEntry(HandleRegistryTestProbe* probe) : probe(probe)
    {
        // No-op.
    }

    virtual ~HandleRegistryTestEntry()
    {
        probe->deleted = true;
    }

private:
    HandleRegistryTestProbe* probe;
};

BOOST_AUTO_TEST_SUITE(HandleRegistryTestSuite)

BOOST_AUTO_TEST_CASE(TestCritical)
{
    HandleRegistry reg(2, 1);

    HandleRegistryTestProbe probe0;
    HandleRegistryTestProbe probe1;
    HandleRegistryTestProbe probe2;

    HandleRegistryTestEntry* entry0 = new HandleRegistryTestEntry(&probe0);
    HandleRegistryTestEntry* entry1 = new HandleRegistryTestEntry(&probe1);
    HandleRegistryTestEntry* entry2 = new HandleRegistryTestEntry(&probe2);

    int64_t hnd0 = reg.AllocateCritical(SharedPointer<HandleRegistryTestEntry>(entry0));
    int64_t hnd1 = reg.AllocateCritical(SharedPointer<HandleRegistryTestEntry>(entry1));
    int64_t hnd2 = reg.AllocateCritical(SharedPointer<HandleRegistryTestEntry>(entry2));

    BOOST_REQUIRE(reg.Get(hnd0).Get() == entry0);
    BOOST_REQUIRE(!probe0.deleted);

    BOOST_REQUIRE(reg.Get(hnd1).Get() == entry1);
    BOOST_REQUIRE(!probe1.deleted);

    BOOST_REQUIRE(reg.Get(hnd2).Get() == entry2);
    BOOST_REQUIRE(!probe2.deleted);

    reg.Release(hnd0);

    BOOST_REQUIRE(reg.Get(hnd0).Get() == NULL);
    BOOST_REQUIRE(probe0.deleted);

    BOOST_REQUIRE(reg.Get(hnd1).Get() == entry1);
    BOOST_REQUIRE(!probe1.deleted);

    BOOST_REQUIRE(reg.Get(hnd2).Get() == entry2);
    BOOST_REQUIRE(!probe2.deleted);

    reg.Close();

    BOOST_REQUIRE(reg.Get(hnd0).Get() == NULL);
    BOOST_REQUIRE(probe0.deleted);

    BOOST_REQUIRE(reg.Get(hnd1).Get() == NULL);
    BOOST_REQUIRE(probe1.deleted);

    BOOST_REQUIRE(reg.Get(hnd2).Get() == NULL);
    BOOST_REQUIRE(probe2.deleted);

    HandleRegistry closedReg(2, 1);

    closedReg.Close();

    HandleRegistryTestProbe closedProbe;
    HandleRegistryTestEntry* closedEntry = new HandleRegistryTestEntry(&closedProbe);

    int64_t closedHnd = closedReg.AllocateCritical(SharedPointer<HandleRegistryTestEntry>(closedEntry));
    BOOST_REQUIRE(closedHnd == -1);
    BOOST_REQUIRE(closedProbe.deleted);
}

BOOST_AUTO_TEST_CASE(TestNonCritical)
{
    HandleRegistry reg(0, 2);

    HandleRegistryTestProbe probe0;
    HandleRegistryTestProbe probe1;
    HandleRegistryTestProbe probe2;

    HandleRegistryTestEntry* entry0 = new HandleRegistryTestEntry(&probe0);
    HandleRegistryTestEntry* entry1 = new HandleRegistryTestEntry(&probe1);
    HandleRegistryTestEntry* entry2 = new HandleRegistryTestEntry(&probe2);

    int64_t hnd0 = reg.AllocateCritical(SharedPointer<HandleRegistryTestEntry>(entry0));
    int64_t hnd1 = reg.Allocate(SharedPointer<HandleRegistryTestEntry>(entry1));
    int64_t hnd2 = reg.Allocate(SharedPointer<HandleRegistryTestEntry>(entry2));

    BOOST_REQUIRE(reg.Get(hnd0).Get() == entry0);
    BOOST_REQUIRE(!probe0.deleted);

    BOOST_REQUIRE(reg.Get(hnd1).Get() == entry1);
    BOOST_REQUIRE(!probe1.deleted);

    BOOST_REQUIRE(reg.Get(hnd2).Get() == entry2);
    BOOST_REQUIRE(!probe2.deleted);

    reg.Release(hnd0);

    BOOST_REQUIRE(reg.Get(hnd0).Get() == NULL);
    BOOST_REQUIRE(probe0.deleted);

    BOOST_REQUIRE(reg.Get(hnd1).Get() == entry1);
    BOOST_REQUIRE(!probe1.deleted);

    BOOST_REQUIRE(reg.Get(hnd2).Get() == entry2);
    BOOST_REQUIRE(!probe2.deleted);

    reg.Close();

    BOOST_REQUIRE(reg.Get(hnd0).Get() == NULL);
    BOOST_REQUIRE(probe0.deleted);

    BOOST_REQUIRE(reg.Get(hnd1).Get() == NULL);
    BOOST_REQUIRE(probe1.deleted);

    BOOST_REQUIRE(reg.Get(hnd2).Get() == NULL);
    BOOST_REQUIRE(probe2.deleted);

    HandleRegistry closedReg(0, 2);

    closedReg.Close();

    HandleRegistryTestProbe closedProbe;
    HandleRegistryTestEntry* closedEntry = new HandleRegistryTestEntry(&closedProbe);

    int64_t closedHnd = closedReg.Allocate(SharedPointer<HandleRegistryTestEntry>(closedEntry));
    BOOST_REQUIRE(closedHnd == -1);
    BOOST_REQUIRE(closedProbe.deleted);
}

BOOST_AUTO_TEST_SUITE_END()

max_stars_repo_name: FedorUporov/gridgain

max_issues_repo_name: FedorUporov/gridgain

max_forks_repo_name: FedorUporov/gridgain


text:
#include "layout/archive.hpp"

#include <fmt/core.h>
#include <spdlog/spdlog.h>

#include <filesystem>
#include <fstream>
#include <memory>
#include <stdexcept>
#include <string>

#include <boost/json/array.hpp>
#include <boost/json/impl/array.hpp>
#include <boost/json/object.hpp>
#include <boost/json/parse.hpp>
#include <boost/json/string.hpp>
#include <boost/json/system_error.hpp>
#include <boost/json/value.hpp>

#include "layout/interval.hpp"
#include "util/file.hpp"
#include "util/json.hpp"

namespace hisui::layout {

std::shared_ptr<Archive> parse_archive(const std::string& filename) {
  auto json_path_result = hisui::util::find_file(filename);
  if (!json_path_result.found) {
    throw std::invalid_argument(json_path_result.message);
  }
  std::ifstream i(json_path_result.path);
  if (!i.is_open()) {
    throw std::runtime_error(
        fmt::format("failed to open metadata json file: {}", filename));
  }
  std::string string_json((std::istreambuf_iterator<char>(i)),
                          std::istreambuf_iterator<char>());
  boost::json::error_code ec;
  boost::json::value jv = boost::json::parse(string_json, ec);
  if (ec) {
    throw std::runtime_error(fmt::format(
        "failed to parse metadata json file: message", ec.message()));
  }

  const auto current_path = std::filesystem::current_path();
  std::filesystem::current_path(json_path_result.path.parent_path());

  boost::json::object j;
  if (jv.is_object()) {
    j = jv.as_object();
  } else {
    throw std::runtime_error("jv is not object");
  }

  auto connection_id =
      hisui::util::get_string_from_json_object(j, "connection_id");
  auto start_time = hisui::util::get_double_from_json_object(j, "start_time");
  auto stop_time = hisui::util::get_double_from_json_object(j, "stop_time");

  // filename から webm ファイルの path を解決する
  auto filename_string =
      hisui::util::get_string_from_json_object(j, "filename");
  auto filename_result = hisui::util::find_file(std::string(filename_string));
  std::filesystem::path file_path;
  if (filename_result.found) {
    file_path = filename_result.path;
  } else {
    // filename でうまくいかなかったら file_path から webm ファイルの path を解決する
    auto file_path_string =
        hisui::util::get_string_from_json_object(j, "file_path");
    auto file_path_result =
        hisui::util::find_file(std::string(file_path_string));
    if (file_path_result.found) {
      file_path = file_path_result.path;
    } else {
      throw std::invalid_argument(
          fmt::format("filename() and file_path() do not exsit", filename,
                      file_path_string));
    }
  }

  std::filesystem::current_path(current_path);

  return std::make_shared<Archive>(
      ArchiveParameters{.path = json_path_result.path,
                        .file_path = file_path,
                        .connection_id = std::string(connection_id),
                        .start_time = start_time,
                        .stop_time = stop_time});
}

Archive::Archive(const ArchiveParameters& params)
    : m_path(params.path),
      m_file_path(params.file_path),
      m_connection_id(params.connection_id),
      m_start_time(params.start_time),
      m_stop_time(params.stop_time) {}

void Archive::dump() const {
  spdlog::debug("path: {}", m_path.string());
  spdlog::debug("file_path: {}", m_file_path.string());
  spdlog::debug("connection_id: {}", m_connection_id);
  spdlog::debug("start_time: {}", m_start_time);
  spdlog::debug("stop_time: {}", m_stop_time);
}

const SourceParameters Archive::getSourceParameters(
    const std::size_t index) const {
  return SourceParameters{
      .file_path = m_file_path,
      .index = index,
      .connection_id = m_connection_id,
      .start_time = m_start_time,
      .end_time = m_stop_time,
  };
}

void Archive::substructTrimIntervals(const TrimIntervals& params) {
  auto interval = substruct_trim_intervals(
      {.interval = getInterval(), .trim_intervals = params.trim_intervals});
  m_start_time = interval.start_time;
  m_stop_time = interval.end_time;
}

Interval Archive::getInterval() const {
  return {.start_time = m_start_time, .end_time = m_stop_time};
}

hisui::ArchiveItem Archive::getArchiveItem() const {
  return hisui::ArchiveItem(m_file_path, m_connection_id, m_start_time,
                            m_stop_time);
}

}  // namespace hisui::layout

max_stars_repo_name: kounoike/hisui

max_issues_repo_name: kounoike/hisui

max_forks_repo_name: kounoike/hisui


text:
//////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Ion Gaztanaga 2005-2014. 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/interprocess for documentation.
//
//////////////////////////////////////////////////////////////////////////////

#ifndef BOOST_INTERPROCESS_OFFSET_PTR_HPP
#define BOOST_INTERPROCESS_OFFSET_PTR_HPP

#ifndef BOOST_CONFIG_HPP
#  include <boost/config.hpp>
#endif
#
#if defined(BOOST_HAS_PRAGMA_ONCE)
#  pragma once
#endif

#include <boost/interprocess/detail/config_begin.hpp>
#include <boost/interprocess/detail/workaround.hpp>

#include <boost/interprocess/interprocess_fwd.hpp>
#include <boost/interprocess/detail/utilities.hpp>
#include <boost/interprocess/detail/cast_tags.hpp>
#include <boost/interprocess/detail/mpl.hpp>
#include <boost/container/detail/type_traits.hpp>  //alignment_of, aligned_storage
#include <boost/assert.hpp>
#include <iosfwd>

//!\file
//!Describes a smart pointer that stores the offset between this pointer and
//!target pointee, called offset_ptr.

namespace boost {

#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)

//Predeclarations
template <class T>
struct has_trivial_destructor;

#endif   //#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)

namespace interprocess {

#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
namespace ipcdetail {

   template<class OffsetType, std::size_t OffsetAlignment>
   union offset_ptr_internal
   {
      explicit offset_ptr_internal(OffsetType off)
         : m_offset(off)
      {}
      OffsetType m_offset; //Distance between this object and pointee address
      typename ::boost::container::container_detail::aligned_storage
         < sizeof(OffsetType)
         , (OffsetAlignment == offset_type_alignment) ?
            ::boost::container::container_detail::alignment_of<OffsetType>::value : OffsetAlignment
         >::type alignment_helper;
   };

   //Note: using the address of a local variable to point to another address
   //is not standard conforming and this can be optimized-away by the compiler.
   //Non-inlining is a method to remain illegal but correct

   //Undef BOOST_INTERPROCESS_OFFSET_PTR_INLINE_XXX if your compiler can inline
   //this code without breaking the library

   ////////////////////////////////////////////////////////////////////////
   //
   //                      offset_ptr_to_raw_pointer
   //
   ////////////////////////////////////////////////////////////////////////
   #define BOOST_INTERPROCESS_OFFSET_PTR_INLINE_TO_PTR
   #if defined(_MSC_VER) && (_MSC_VER >= 1800) && (defined(_M_AMD64) || defined(_M_X64))
      //Visual 2013 x64 optimizes more than we desire, so disable branchless option
   #else
      #define BOOST_INTERPROCESS_OFFSET_PTR_BRANCHLESS_TO_PTR
   #endif
   template<int Dummy>
   #ifndef BOOST_INTERPROCESS_OFFSET_PTR_INLINE_TO_PTR
      BOOST_NOINLINE
   #elif defined(NDEBUG)
      inline
   #endif
   void * offset_ptr_to_raw_pointer(const volatile void *this_ptr, std::size_t offset)
   {
      typedef pointer_size_t_caster<void*> caster_t;
      #ifndef BOOST_INTERPROCESS_OFFSET_PTR_BRANCHLESS_TO_PTR
         if(offset == 1){
            return 0;
         }
         else{
            const caster_t caster((void*)this_ptr);
            return caster_t(caster.size() + offset).pointer();
         }
      #else
         const caster_t caster((void*)this_ptr);
         std::size_t target_offset = caster.size() + offset;
         std::size_t mask = -std::size_t(offset != 1);
         target_offset &= mask;
         return caster_t(target_offset).pointer();
      #endif
   }

   #ifdef BOOST_INTERPROCESS_OFFSET_PTR_INLINE_TO_PTR
      #undef BOOST_INTERPROCESS_OFFSET_PTR_INLINE_TO_PTR
   #endif
   #ifdef BOOST_INTERPROCESS_OFFSET_PTR_BRANCHLESS_TO_PTR
      #undef BOOST_INTERPROCESS_OFFSET_PTR_BRANCHLESS_TO_PTR
   #endif

   ////////////////////////////////////////////////////////////////////////
   //
   //                      offset_ptr_to_offset
   //
   ////////////////////////////////////////////////////////////////////////
   #define BOOST_INTERPROCESS_OFFSET_PTR_INLINE_TO_OFF
   //Branchless seems slower in x86
   #define BOOST_INTERPROCESS_OFFSET_PTR_BRANCHLESS_TO_OFF

   template<int Dummy>
   #ifndef BOOST_INTERPROCESS_OFFSET_PTR_INLINE_TO_OFF
      BOOST_NOINLINE
   #elif defined(NDEBUG)
      inline
   #endif
   std::size_t offset_ptr_to_offset(const volatile void *ptr, const volatile void *this_ptr)
   {
      typedef pointer_size_t_caster<void*> caster_t;
      #ifndef BOOST_INTERPROCESS_OFFSET_PTR_BRANCHLESS_TO_OFF
         //offset == 1 && ptr != 0 is not legal for this pointer
         if(!ptr){
            return 1;
         }
         else{
            const caster_t this_caster((void*)this_ptr);
            const caster_t ptr_caster((void*)ptr);
            std::size_t offset = ptr_caster.size() - this_caster.size();
            BOOST_ASSERT(offset != 1);
            return offset;
         }
      #else
         const caster_t this_caster((void*)this_ptr);
         const caster_t ptr_caster((void*)ptr);
         //std::size_t other = -std::size_t(ptr != 0);
         //std::size_t offset = (ptr_caster.size() - this_caster.size()) & other;
         //return offset + !other;
         //
         std::size_t offset = (ptr_caster.size() - this_caster.size() - 1) & -std::size_t(ptr != 0);
         return ++offset;
      #endif
   }

   #ifdef BOOST_INTERPROCESS_OFFSET_PTR_INLINE_TO_OFF
      #undef BOOST_INTERPROCESS_OFFSET_PTR_INLINE_TO_OFF
   #endif
   #ifdef BOOST_INTERPROCESS_OFFSET_PTR_BRANCHLESS_TO_OFF
      #undef BOOST_INTERPROCESS_OFFSET_PTR_BRANCHLESS_TO_OFF
   #endif

   ////////////////////////////////////////////////////////////////////////
   //
   //                      offset_ptr_to_offset_from_other
   //
   ////////////////////////////////////////////////////////////////////////
   #define BOOST_INTERPROCESS_OFFSET_PTR_INLINE_TO_OFF_FROM_OTHER
   //Branchless seems slower in x86
   #define BOOST_INTERPROCESS_OFFSET_PTR_BRANCHLESS_TO_OFF_FROM_OTHER

   template<int Dummy>
   #ifndef BOOST_INTERPROCESS_OFFSET_PTR_INLINE_TO_OFF_FROM_OTHER
      BOOST_NOINLINE
   #elif defined(NDEBUG)
      inline
   #endif
   std::size_t offset_ptr_to_offset_from_other
      (const volatile void *this_ptr, const volatile void *other_ptr, std::size_t other_offset)
   {
      typedef pointer_size_t_caster<void*> caster_t;
      #ifndef BOOST_INTERPROCESS_OFFSET_PTR_BRANCHLESS_TO_OFF_FROM_OTHER
      if(other_offset == 1){
         return 1;
      }
      else{
         const caster_t this_caster((void*)this_ptr);
         const caster_t other_caster((void*)other_ptr);
         std::size_t offset = other_caster.size() - this_caster.size() + other_offset;
         BOOST_ASSERT(offset != 1);
         return offset;
      }
      #else
      const caster_t this_caster((void*)this_ptr);
      const caster_t other_caster((void*)other_ptr);
      return ((other_caster.size() - this_caster.size()) & -std::size_t(other_offset != 1)) + other_offset;
      #endif
   }

   #ifdef BOOST_INTERPROCESS_OFFSET_PTR_INLINE_TO_OFF_FROM_OTHER
      #undef BOOST_INTERPROCESS_OFFSET_PTR_INLINE_TO_OFF_FROM_OTHER
   #endif
   #ifdef BOOST_INTERPROCESS_OFFSET_PTR_BRANCHLESS_TO_OFF_FROM_OTHER
      #undef BOOST_INTERPROCESS_OFFSET_PTR_BRANCHLESS_TO_OFF_FROM_OTHER
   #endif

   ////////////////////////////////////////////////////////////////////////
   //
   // Let's assume cast to void and cv cast don't change any target address
   //
   ////////////////////////////////////////////////////////////////////////
   template<class From, class To>
   struct offset_ptr_maintains_address
   {
      static const bool value =    ipcdetail::is_cv_same<From, To>::value
                                || ipcdetail::is_cv_same<void, To>::value;
   };

}  //namespace ipcdetail {
#endif   //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED

//!A smart pointer that stores the offset between between the pointer and the
//!the object it points. This allows offset allows special properties, since
//!the pointer is independent from the address address of the pointee, if the
//!pointer and the pointee are still separated by the same offset. This feature
//!converts offset_ptr in a smart pointer that can be placed in shared memory and
//!memory mapped files mapped in different addresses in every process.
//!
//! \tparam PointedType The type of the pointee.
//! \tparam DifferenceType A signed integer type that can represent the arithmetic operations on the pointer
//! \tparam OffsetType An unsigned integer type that can represent the
//!   distance between two pointers reinterpret_cast-ed as unsigned integers. In general this type
//!   should be at least of the same size of std::uintptr_t. In some systems it's possible to communicate
//!   between 32 and 64 bit processes using 64 bit offsets.
//! \tparam OffsetAlignment Alignment of the OffsetType stored inside. In some systems might be necessary
//!   to align it to 64 bits in order to communicate 32 and 64 bit processes using 64 bit offsets.
template <class PointedType, class DifferenceType, class OffsetType, std::size_t OffsetAlignment>
class offset_ptr
{
   #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
   typedef offset_ptr<PointedType, DifferenceType, OffsetType, OffsetAlignment>   self_t;
   void unspecified_bool_type_func() const {}
   typedef void (self_t::*unspecified_bool_type)() const;
   #endif   //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED

   public:
   typedef PointedType                       element_type;
   typedef PointedType *                     pointer;
   typedef typename ipcdetail::
      add_reference<PointedType>::type       reference;
   typedef typename ipcdetail::
      remove_volatile<typename ipcdetail::
         remove_const<PointedType>::type
            >::type                          value_type;
   typedef DifferenceType                    difference_type;
   typedef std::random_access_iterator_tag   iterator_category;
   typedef OffsetType                        offset_type;

   public:   //Public Functions

   //!Default constructor (null pointer).
   //!Never throws.
   offset_ptr()
      : internal(1)
   {}

   //!Constructor from raw pointer (allows "0" pointer conversion).
   //!Never throws.
   offset_ptr(pointer ptr)
      : internal(static_cast<OffsetType>(ipcdetail::offset_ptr_to_offset<0>(ptr, this)))
   {}

   //!Constructor from other pointer.
   //!Never throws.
   template <class T>
   offset_ptr( T *ptr
             , typename ipcdetail::enable_if< ipcdetail::is_convertible<T*, PointedType*> >::type * = 0)
      : internal(static_cast<OffsetType>
         (ipcdetail::offset_ptr_to_offset<0>(static_cast<PointedType*>(ptr), this)))
   {}

   //!Constructor from other offset_ptr
   //!Never throws.
   offset_ptr(const offset_ptr& ptr)
      : internal(static_cast<OffsetType>
         (ipcdetail::offset_ptr_to_offset_from_other<0>(this, &ptr, ptr.internal.m_offset)))
   {}

   //!Constructor from other offset_ptr. If pointers of pointee types are
   //!convertible, offset_ptrs will be convertibles. Never throws.
   template<class T2>
   offset_ptr( const offset_ptr<T2, DifferenceType, OffsetType, OffsetAlignment> &ptr
             #ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
             , typename ipcdetail::enable_if_c< ipcdetail::is_convertible<T2*, PointedType*>::value
               && ipcdetail::offset_ptr_maintains_address<T2, PointedType>::value
             >::type * = 0
             #endif
             )
      : internal(static_cast<OffsetType>
         (ipcdetail::offset_ptr_to_offset_from_other<0>(this, &ptr, ptr.get_offset())))
   {}

   #ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED

   //!Constructor from other offset_ptr. If pointers of pointee types are
   //!convertible, offset_ptrs will be convertibles. Never throws.
   template<class T2>
   offset_ptr( const offset_ptr<T2, DifferenceType, OffsetType, OffsetAlignment> &ptr
             , typename ipcdetail::enable_if_c< ipcdetail::is_convertible<T2*, PointedType*>::value
               && !ipcdetail::offset_ptr_maintains_address<T2, PointedType>::value
             >::type * = 0)
      : internal(static_cast<OffsetType>
         (ipcdetail::offset_ptr_to_offset<0>(static_cast<PointedType*>(ptr.get()), this)))
   {}

   #endif

   //!Emulates static_cast operator.
   //!Never throws.
   template<class T2, class P2, class O2, std::size_t A2>
   offset_ptr(const offset_ptr<T2, P2, O2, A2> & r, ipcdetail::static_cast_tag)
      : internal(static_cast<OffsetType>
         (ipcdetail::offset_ptr_to_offset<0>(static_cast<PointedType*>(r.get()), this)))
   {}

   //!Emulates const_cast operator.
   //!Never throws.
   template<class T2, class P2, class O2, std::size_t A2>
   offset_ptr(const offset_ptr<T2, P2, O2, A2> & r, ipcdetail::const_cast_tag)
      : internal(static_cast<OffsetType>
         (ipcdetail::offset_ptr_to_offset<0>(const_cast<PointedType*>(r.get()), this)))
   {}

   //!Emulates dynamic_cast operator.
   //!Never throws.
   template<class T2, class P2, class O2, std::size_t A2>
   offset_ptr(const offset_ptr<T2, P2, O2, A2> & r, ipcdetail::dynamic_cast_tag)
      : internal(static_cast<OffsetType>
         (ipcdetail::offset_ptr_to_offset<0>(dynamic_cast<PointedType*>(r.get()), this)))
   {}

   //!Emulates reinterpret_cast operator.
   //!Never throws.
   template<class T2, class P2, class O2, std::size_t A2>
   offset_ptr(const offset_ptr<T2, P2, O2, A2> & r, ipcdetail::reinterpret_cast_tag)
      : internal(static_cast<OffsetType>
      (ipcdetail::offset_ptr_to_offset<0>(reinterpret_cast<PointedType*>(r.get()), this)))
   {}

   //!Obtains raw pointer from offset.
   //!Never throws.
   pointer get() const
   {  return (pointer)ipcdetail::offset_ptr_to_raw_pointer<0>(this, this->internal.m_offset);   }

   offset_type get_offset() const
   {  return this->internal.m_offset;  }

   //!Pointer-like -> operator. It can return 0 pointer.
   //!Never throws.
   pointer operator->() const
   {  return this->get(); }

   //!Dereferencing operator, if it is a null offset_ptr behavior
   //!   is undefined. Never throws.
   reference operator* () const
   {
      pointer p = this->get();
      reference r = *p;
      return r;
   }

   //!Indexing operator.
   //!Never throws.
   reference operator[](difference_type idx) const
   {  return this->get()[idx];  }

   //!Assignment from pointer (saves extra conversion).
   //!Never throws.
   offset_ptr& operator= (pointer from)
   {
      this->internal.m_offset =
         static_cast<OffsetType>(ipcdetail::offset_ptr_to_offset<0>(from, this));
      return *this;
   }

   //!Assignment from other offset_ptr.
   //!Never throws.
   offset_ptr& operator= (const offset_ptr & ptr)
   {
      this->internal.m_offset =
         static_cast<OffsetType>(ipcdetail::offset_ptr_to_offset_from_other<0>(this, &ptr, ptr.internal.m_offset));
      return *this;
   }

   //!Assignment from related offset_ptr. If pointers of pointee types
   //!   are assignable, offset_ptrs will be assignable. Never throws.
   template<class T2>
   #ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
   typename ipcdetail::enable_if_c< ipcdetail::is_convertible<T2*, PointedType*>::value
                                    && ipcdetail::offset_ptr_maintains_address<T2, PointedType>::value
                                  , offset_ptr&>::type
   #else
   offset_ptr&
   #endif
      operator= (const offset_ptr<T2, DifferenceType, OffsetType, OffsetAlignment> &ptr)
   {
      this->internal.m_offset =
         static_cast<OffsetType>(ipcdetail::offset_ptr_to_offset_from_other<0>(this, &ptr, ptr.get_offset()));
      return *this;
   }

   #ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
   template<class T2>
   typename ipcdetail::enable_if_c<ipcdetail::is_convertible<T2*, PointedType*>::value
                                   && !ipcdetail::offset_ptr_maintains_address<T2, PointedType>::value
                                 , offset_ptr&>::type
      operator= (const offset_ptr<T2, DifferenceType, OffsetType, OffsetAlignment> &ptr)
   {
      this->internal.m_offset =
         static_cast<OffsetType>(ipcdetail::offset_ptr_to_offset<0>(static_cast<PointedType*>(ptr.get()), this));
      return *this;
   }
   #endif

   //!offset_ptr += difference_type.
   //!Never throws.
   offset_ptr &operator+= (difference_type offset)
   {  this->inc_offset(offset * sizeof (PointedType));   return *this;  }

   //!offset_ptr -= difference_type.
   //!Never throws.
   offset_ptr &operator-= (difference_type offset)
   {  this->dec_offset(offset * sizeof (PointedType));   return *this;  }

   //!++offset_ptr.
   //!Never throws.
   offset_ptr& operator++ (void)
   {  this->inc_offset(sizeof (PointedType));   return *this;  }

   //!offset_ptr++.
   //!Never throws.
   offset_ptr operator++ (int)
   {
      offset_ptr tmp(*this);
      this->inc_offset(sizeof (PointedType));
      return tmp;
   }

   //!--offset_ptr.
   //!Never throws.
   offset_ptr& operator-- (void)
   {  this->dec_offset(sizeof (PointedType));   return *this;  }

   //!offset_ptr--.
   //!Never throws.
   offset_ptr operator-- (int)
   {
      offset_ptr tmp(*this);
      this->dec_offset(sizeof (PointedType));
      return tmp;
   }

   //!safe bool conversion operator.
   //!Never throws.
   operator unspecified_bool_type() const
   {  return this->internal.m_offset != 1? &self_t::unspecified_bool_type_func : 0;   }

   //!Not operator. Not needed in theory, but improves portability.
   //!Never throws
   bool operator! () const
   {  return this->internal.m_offset == 1;   }

   //!Compatibility with pointer_traits
   //!
   template <class U>
   struct rebind
   {  typedef offset_ptr<U, DifferenceType, OffsetType, OffsetAlignment> other;  };

   //!Compatibility with pointer_traits
   //!
   static offset_ptr pointer_to(reference r)
   { return offset_ptr(&r); }

   //!difference_type + offset_ptr
   //!operation
   friend offset_ptr operator+(difference_type diff, offset_ptr right)
   {  right += diff;  return right;  }

   //!offset_ptr + difference_type
   //!operation
   friend offset_ptr operator+(offset_ptr left, difference_type diff)
   {  left += diff;  return left; }

   //!offset_ptr - diff
   //!operation
   friend offset_ptr operator-(offset_ptr left, difference_type diff)
   {  left -= diff;  return left; }

   //!offset_ptr - diff
   //!operation
   friend offset_ptr operator-(difference_type diff, offset_ptr right)
   {  right -= diff; return right; }

   //!offset_ptr - offset_ptr
   //!operation
   friend difference_type operator-(const offset_ptr &pt, const offset_ptr &pt2)
   {  return difference_type(pt.get()- pt2.get());   }

   //Comparison
   friend bool operator== (const offset_ptr &pt1, const offset_ptr &pt2)
   {  return pt1.get() == pt2.get();  }

   friend bool operator!= (const offset_ptr &pt1, const offset_ptr &pt2)
   {  return pt1.get() != pt2.get();  }

   friend bool operator<(const offset_ptr &pt1, const offset_ptr &pt2)
   {  return pt1.get() < pt2.get();  }

   friend bool operator<=(const offset_ptr &pt1, const offset_ptr &pt2)
   {  return pt1.get() <= pt2.get();  }

   friend bool operator>(const offset_ptr &pt1, const offset_ptr &pt2)
   {  return pt1.get() > pt2.get();  }

   friend bool operator>=(const offset_ptr &pt1, const offset_ptr &pt2)
   {  return pt1.get() >= pt2.get();  }

   //Comparison to raw ptr to support literal 0
   friend bool operator== (pointer pt1, const offset_ptr &pt2)
   {  return pt1 == pt2.get();  }

   friend bool operator!= (pointer pt1, const offset_ptr &pt2)
   {  return pt1 != pt2.get();  }

   friend bool operator<(pointer pt1, const offset_ptr &pt2)
   {  return pt1 < pt2.get();  }

   friend bool operator<=(pointer pt1, const offset_ptr &pt2)
   {  return pt1 <= pt2.get();  }

   friend bool operator>(pointer pt1, const offset_ptr &pt2)
   {  return pt1 > pt2.get();  }

   friend bool operator>=(pointer pt1, const offset_ptr &pt2)
   {  return pt1 >= pt2.get();  }

   //Comparison
   friend bool operator== (const offset_ptr &pt1, pointer pt2)
   {  return pt1.get() == pt2;  }

   friend bool operator!= (const offset_ptr &pt1, pointer pt2)
   {  return pt1.get() != pt2;  }

   friend bool operator<(const offset_ptr &pt1, pointer pt2)
   {  return pt1.get() < pt2;  }

   friend bool operator<=(const offset_ptr &pt1, pointer pt2)
   {  return pt1.get() <= pt2;  }

   friend bool operator>(const offset_ptr &pt1, pointer pt2)
   {  return pt1.get() > pt2;  }

   friend bool operator>=(const offset_ptr &pt1, pointer pt2)
   {  return pt1.get() >= pt2;  }

   friend void swap(offset_ptr &left, offset_ptr &right)
   {
      pointer ptr = right.get();
      right = left;
      left = ptr;
   }

   private:
   #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
   void inc_offset(DifferenceType bytes)
   {  internal.m_offset += bytes;   }

   void dec_offset(DifferenceType bytes)
   {  internal.m_offset -= bytes;   }

   ipcdetail::offset_ptr_internal<OffsetType, OffsetAlignment> internal;
   #endif   //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
};

//!operator<<
//!for offset ptr
template<class E, class T, class W, class X, class Y, std::size_t Z>
inline std::basic_ostream<E, T> & operator<<
   (std::basic_ostream<E, T> & os, offset_ptr<W, X, Y, Z> const & p)
{  return os << p.get_offset();   }

//!operator>>
//!for offset ptr
template<class E, class T, class W, class X, class Y, std::size_t Z>
inline std::basic_istream<E, T> & operator>>
   (std::basic_istream<E, T> & is, offset_ptr<W, X, Y, Z> & p)
{  return is >> p.get_offset();  }

//!Simulation of static_cast between pointers. Never throws.
template<class T1, class P1, class O1, std::size_t A1, class T2, class P2, class O2, std::size_t A2>
inline boost::interprocess::offset_ptr<T1, P1, O1, A1>
   static_pointer_cast(const boost::interprocess::offset_ptr<T2, P2, O2, A2> & r)
{
   return boost::interprocess::offset_ptr<T1, P1, O1, A1>
            (r, boost::interprocess::ipcdetail::static_cast_tag());
}

//!Simulation of const_cast between pointers. Never throws.
template<class T1, class P1, class O1, std::size_t A1, class T2, class P2, class O2, std::size_t A2>
inline boost::interprocess::offset_ptr<T1, P1, O1, A1>
   const_pointer_cast(const boost::interprocess::offset_ptr<T2, P2, O2, A2> & r)
{
   return boost::interprocess::offset_ptr<T1, P1, O1, A1>
            (r, boost::interprocess::ipcdetail::const_cast_tag());
}

//!Simulation of dynamic_cast between pointers. Never throws.
template<class T1, class P1, class O1, std::size_t A1, class T2, class P2, class O2, std::size_t A2>
inline boost::interprocess::offset_ptr<T1, P1, O1, A1>
   dynamic_pointer_cast(const boost::interprocess::offset_ptr<T2, P2, O2, A2> & r)
{
   return boost::interprocess::offset_ptr<T1, P1, O1, A1>
            (r, boost::interprocess::ipcdetail::dynamic_cast_tag());
}

//!Simulation of reinterpret_cast between pointers. Never throws.
template<class T1, class P1, class O1, std::size_t A1, class T2, class P2, class O2, std::size_t A2>
inline boost::interprocess::offset_ptr<T1, P1, O1, A1>
   reinterpret_pointer_cast(const boost::interprocess::offset_ptr<T2, P2, O2, A2> & r)
{
   return boost::interprocess::offset_ptr<T1, P1, O1, A1>
            (r, boost::interprocess::ipcdetail::reinterpret_cast_tag());
}

}  //namespace interprocess {

#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)

///has_trivial_destructor<> == true_type specialization for optimizations
template <class T, class P, class O, std::size_t A>
struct has_trivial_destructor< ::boost::interprocess::offset_ptr<T, P, O, A> >
{
   static const bool value = true;
};

namespace move_detail {

///has_trivial_destructor<> == true_type specialization for optimizations
template <class T, class P, class O, std::size_t A>
struct is_trivially_destructible< ::boost::interprocess::offset_ptr<T, P, O, A> >
{
   static const bool value = true;
};

}  //namespace move_detail {

namespace interprocess {

//!to_raw_pointer() enables boost::mem_fn to recognize offset_ptr.
//!Never throws.
template <class T, class P, class O, std::size_t A>
inline T * to_raw_pointer(boost::interprocess::offset_ptr<T, P, O, A> const & p)
{  return ipcdetail::to_raw_pointer(p);   }

}  //namespace interprocess

#endif   //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
}  //namespace boost {

#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)

namespace boost{

//This is to support embedding a bit in the pointer
//for intrusive containers, saving space
namespace intrusive {

//Predeclaration to avoid including header
template<class VoidPointer, std::size_t N>
struct max_pointer_plus_bits;

template<std::size_t OffsetAlignment, class P, class O, std::size_t A>
struct max_pointer_plus_bits<boost::interprocess::offset_ptr<void, P, O, A>, OffsetAlignment>
{
   //The offset ptr can embed one bit less than the alignment since it
   //uses offset == 1 to store the null pointer.
   static const std::size_t value = ::boost::interprocess::ipcdetail::ls_zeros<OffsetAlignment>::value - 1;
};

//Predeclaration
template<class Pointer, std::size_t NumBits>
struct pointer_plus_bits;

template<class T, class P, class O, std::size_t A, std::size_t NumBits>
struct pointer_plus_bits<boost::interprocess::offset_ptr<T, P, O, A>, NumBits>
{
   typedef boost::interprocess::offset_ptr<T, P, O, A>      pointer;
   typedef ::boost::interprocess::pointer_size_t_caster<T*> caster_t;
   //Bits are stored in the lower bits of the pointer except the LSB,
   //because this bit is used to represent the null pointer.
   static const std::size_t Mask = ((std::size_t(1) << NumBits) - 1) << 1u;

   static pointer get_pointer(const pointer &n)
   {
      caster_t caster(n.get());
      return pointer(caster_t(caster.size() & ~Mask).pointer());
   }

   static void set_pointer(pointer &n, const pointer &p)
   {
      caster_t n_caster(n.get());
      caster_t p_caster(p.get());
      BOOST_ASSERT(0 == (p_caster.size() & Mask));
      n = caster_t(p_caster.size() | (n_caster.size() & Mask)).pointer();
   }

   static std::size_t get_bits(const pointer &n)
   {  return (caster_t(n.get()).size() & Mask) >> 1u;  }

   static void set_bits(pointer &n, std::size_t b)
   {
      BOOST_ASSERT(b < (std::size_t(1) << NumBits));
      caster_t n_caster(n.get());
      n = caster_t((n_caster.size() & ~Mask) | (b << 1u)).pointer();
   }
};

}  //namespace intrusive

//Predeclaration
template<class T, class U>
struct pointer_to_other;

//Backwards compatibility with pointer_to_other
template <class PointedType, class DifferenceType, class OffsetType, std::size_t OffsetAlignment, class U>
struct pointer_to_other
   < ::boost::interprocess::offset_ptr<PointedType, DifferenceType, OffsetType, OffsetAlignment>, U >
{
   typedef ::boost::interprocess::offset_ptr<U, DifferenceType, OffsetType, OffsetAlignment> type;
};

}  //namespace boost{
#endif   //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED

#include <boost/interprocess/detail/config_end.hpp>

#endif //#ifndef BOOST_INTERPROCESS_OFFSET_PTR_HPP

max_stars_repo_name: multi-os-engine/cinder-natj-binding

max_issues_repo_name: multi-os-engine/cinder-natj-binding

max_forks_repo_name: multi-os-engine/cinder-natj-binding