<commit_before>/*============================================================================

The Medical Imaging Interaction Toolkit (MITK)

Copyright (c) German Cancer Research Center (DKFZ)
All rights reserved.

Use of this source code is governed by a 3-clause BSD license that can be
found in the LICENSE file.

============================================================================*/

#include <mitkLabelSetImageHelper.h>

#include <mitkLabelSetImage.h>
#include <mitkExceptionMacro.h>
#include <mitkProperties.h>

#include <array>
#include <regex>
#include <vector>

namespace
{
  template <typename T>
  std::array<int, 3> QuantizeColor(const T* color)
  {
    return {
      static_cast<int>(std::round(color[0] * 255)),
      static_cast<int>(std::round(color[1] * 255)),
      static_cast<int>(std::round(color[2] * 255)) };
  }

  mitk::Color FromLookupTableColor(const double* lookupTableColor)
  {
    mitk::Color color;
    color.Set(
      static_cast<float>(lookupTableColor[0]),
      static_cast<float>(lookupTableColor[1]),
      static_cast<float>(lookupTableColor[2]));
    return color;
  }
}

mitk::DataNode::Pointer mitk::LabelSetImageHelper::CreateNewSegmentationNode(const DataNode* referenceNode,
  const Image* initialSegmentationImage, const std::string& segmentationName)
{
  std::string newSegmentationName = segmentationName;
  if (newSegmentationName.empty())
  {
    newSegmentationName = referenceNode->GetName();
    newSegmentationName.append("-labels");
  }

  if (nullptr == initialSegmentationImage)
  {
    return nullptr;
  }

  auto newLabelSetImage = mitk::LabelSetImage::New();
  try
  {
    newLabelSetImage->Initialize(initialSegmentationImage);
  }
  catch (mitk::Exception &e)
  {
    mitkReThrow(e) << "Could not initialize new label set image.";
    return nullptr;
  }

  auto newSegmentationNode = mitk::DataNode::New();
  newSegmentationNode->SetData(newLabelSetImage);
  newSegmentationNode->SetName(newSegmentationName);

  // set additional image information
  newLabelSetImage->GetExteriorLabel()->SetProperty("name.parent", mitk::StringProperty::New(referenceNode->GetName()));
  newLabelSetImage->GetExteriorLabel()->SetProperty("name.image", mitk::StringProperty::New(newSegmentationName));

  // initialize "showVolume"-property to false to prevent recalculating the volume while working on the segmentation
  newSegmentationNode->SetProperty("showVolume", mitk::BoolProperty::New(false));

  return newSegmentationNode;
}

mitk::Label::Pointer mitk::LabelSetImageHelper::CreateNewLabel(const LabelSetImage* labelSetImage)
{
  if (nullptr == labelSetImage)
    return nullptr;

  const std::regex genericLabelNameRegEx("New label ([1-9][0-9]*)");
  int maxGenericLabelNumber = 0;

  std::vector<std::array<int, 3>> colorsInUse;

  const auto numLabelSets = labelSetImage->GetNumberOfLayers();

  for (std::remove_const_t<decltype(numLabelSets)> i = 0; i < numLabelSets; ++i)
  {
    auto labelSet = labelSetImage->GetLabelSet(i);
    auto labelEndIter = labelSet->IteratorConstEnd();

    for (auto labelIter = labelSet->IteratorConstBegin(); labelIter != labelEndIter; ++labelIter)
    {
      auto label = labelIter->second;
      auto labelName = label->GetName();
      std::smatch match;

      if (std::regex_match(labelName, match, genericLabelNameRegEx))
        maxGenericLabelNumber = std::max(maxGenericLabelNumber, std::stoi(match[1].str()));

      const auto quantizedLabelColor = QuantizeColor(label->GetColor().data());

      if (std::find(colorsInUse.begin(), colorsInUse.end(), quantizedLabelColor) == std::end(colorsInUse))
        colorsInUse.push_back(quantizedLabelColor);
    }
  }

  auto newLabel = mitk::Label::New();
  newLabel->SetName("New label " + std::to_string(maxGenericLabelNumber + 1));

  auto lookupTable = mitk::LookupTable::New();
  lookupTable->SetType(mitk::LookupTable::LookupTableType::MULTILABEL);

  std::array<double, 3> lookupTableColor;
  const int maxTries = 25;
  bool newColorFound = false;

  for (int i = 0; i < maxTries; ++i)
  {
    lookupTable->GetColor(i, lookupTableColor.data());

    auto quantizedLookupTableColor = QuantizeColor(lookupTableColor.data());

    if (std::find(colorsInUse.begin(), colorsInUse.end(), quantizedLookupTableColor) == std::end(colorsInUse))
    {
      newLabel->SetColor(FromLookupTableColor(lookupTableColor.data()));
      newColorFound = true;
      break;
    }
  }

  if (!newColorFound)
  {
    lookupTable->GetColor(labelSetImage->GetTotalNumberOfLabels(), lookupTableColor.data());
    newLabel->SetColor(FromLookupTableColor(lookupTableColor.data()));
  }

  return newLabel;
}
<commit_msg>Simplify label naming for automatically created labels<commit_after>/*============================================================================

The Medical Imaging Interaction Toolkit (MITK)

Copyright (c) German Cancer Research Center (DKFZ)
All rights reserved.

Use of this source code is governed by a 3-clause BSD license that can be
found in the LICENSE file.

============================================================================*/

#include <mitkLabelSetImageHelper.h>

#include <mitkLabelSetImage.h>
#include <mitkExceptionMacro.h>
#include <mitkProperties.h>

#include <array>
#include <regex>
#include <vector>

namespace
{
  template <typename T>
  std::array<int, 3> QuantizeColor(const T* color)
  {
    return {
      static_cast<int>(std::round(color[0] * 255)),
      static_cast<int>(std::round(color[1] * 255)),
      static_cast<int>(std::round(color[2] * 255)) };
  }

  mitk::Color FromLookupTableColor(const double* lookupTableColor)
  {
    mitk::Color color;
    color.Set(
      static_cast<float>(lookupTableColor[0]),
      static_cast<float>(lookupTableColor[1]),
      static_cast<float>(lookupTableColor[2]));
    return color;
  }
}

mitk::DataNode::Pointer mitk::LabelSetImageHelper::CreateNewSegmentationNode(const DataNode* referenceNode,
  const Image* initialSegmentationImage, const std::string& segmentationName)
{
  std::string newSegmentationName = segmentationName;
  if (newSegmentationName.empty())
  {
    newSegmentationName = referenceNode->GetName();
    newSegmentationName.append("-labels");
  }

  if (nullptr == initialSegmentationImage)
  {
    return nullptr;
  }

  auto newLabelSetImage = mitk::LabelSetImage::New();
  try
  {
    newLabelSetImage->Initialize(initialSegmentationImage);
  }
  catch (mitk::Exception &e)
  {
    mitkReThrow(e) << "Could not initialize new label set image.";
    return nullptr;
  }

  auto newSegmentationNode = mitk::DataNode::New();
  newSegmentationNode->SetData(newLabelSetImage);
  newSegmentationNode->SetName(newSegmentationName);

  // set additional image information
  newLabelSetImage->GetExteriorLabel()->SetProperty("name.parent", mitk::StringProperty::New(referenceNode->GetName()));
  newLabelSetImage->GetExteriorLabel()->SetProperty("name.image", mitk::StringProperty::New(newSegmentationName));

  // initialize "showVolume"-property to false to prevent recalculating the volume while working on the segmentation
  newSegmentationNode->SetProperty("showVolume", mitk::BoolProperty::New(false));

  return newSegmentationNode;
}

mitk::Label::Pointer mitk::LabelSetImageHelper::CreateNewLabel(const LabelSetImage* labelSetImage)
{
  if (nullptr == labelSetImage)
    return nullptr;

  const std::regex genericLabelNameRegEx("Label ([1-9][0-9]*)");
  int maxGenericLabelNumber = 0;

  std::vector<std::array<int, 3>> colorsInUse;

  const auto numLabelSets = labelSetImage->GetNumberOfLayers();

  for (std::remove_const_t<decltype(numLabelSets)> i = 0; i < numLabelSets; ++i)
  {
    auto labelSet = labelSetImage->GetLabelSet(i);
    auto labelEndIter = labelSet->IteratorConstEnd();

    for (auto labelIter = labelSet->IteratorConstBegin(); labelIter != labelEndIter; ++labelIter)
    {
      auto label = labelIter->second;
      auto labelName = label->GetName();
      std::smatch match;

      if (std::regex_match(labelName, match, genericLabelNameRegEx))
        maxGenericLabelNumber = std::max(maxGenericLabelNumber, std::stoi(match[1].str()));

      const auto quantizedLabelColor = QuantizeColor(label->GetColor().data());

      if (std::find(colorsInUse.begin(), colorsInUse.end(), quantizedLabelColor) == std::end(colorsInUse))
        colorsInUse.push_back(quantizedLabelColor);
    }
  }

  auto newLabel = mitk::Label::New();
  newLabel->SetName("Label " + std::to_string(maxGenericLabelNumber + 1));

  auto lookupTable = mitk::LookupTable::New();
  lookupTable->SetType(mitk::LookupTable::LookupTableType::MULTILABEL);

  std::array<double, 3> lookupTableColor;
  const int maxTries = 25;
  bool newColorFound = false;

  for (int i = 0; i < maxTries; ++i)
  {
    lookupTable->GetColor(i, lookupTableColor.data());

    auto quantizedLookupTableColor = QuantizeColor(lookupTableColor.data());

    if (std::find(colorsInUse.begin(), colorsInUse.end(), quantizedLookupTableColor) == std::end(colorsInUse))
    {
      newLabel->SetColor(FromLookupTableColor(lookupTableColor.data()));
      newColorFound = true;
      break;
    }
  }

  if (!newColorFound)
  {
    lookupTable->GetColor(labelSetImage->GetTotalNumberOfLabels(), lookupTableColor.data());
    newLabel->SetColor(FromLookupTableColor(lookupTableColor.data()));
  }

  return newLabel;
}
<|endoftext|>


<commit_before>// Demonstration of calculating Elmore delay with a graph
// to accompany "Analyzing On-Chip Interconnect with Modern C++"
// Author: Jeff Trull <edaskel@att.net>

/*
Copyright (c) 2014 Jeffrey E. Trull

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/

#include <iostream>

#include <boost/graph/visitors.hpp>
#include <boost/graph/undirected_dfs.hpp>
#include <boost/units/systems/si/time.hpp>

#include "ckt_graph.h"

// For Elmore we need two visitors:
// 1) To calculate total capacitance at and "below" each node
// 2) To sum resistor delays to each node from a chosen input

template<typename Graph>
struct cap_summing_visitor : boost::default_dfs_visitor {
    typedef typename boost::graph_traits<Graph>::edge_descriptor edge_t;
    typedef typename boost::graph_traits<Graph>::vertex_descriptor vertex_t;

    // This edge variant visitor returns the correct contribution for an edge
    // to a downstream node: the value on the edge, if a capacitor, or
    // the supplied downstream capacitance, if a resistor.
    struct cap_summer : boost::static_visitor<capacitor_value_t> {
        capacitor_value_t operator()(resistor_value_t const&) const {
            return downstream_;   // count downstream, not edge
        }
        capacitor_value_t operator()(capacitor_value_t const& c) const {
            return c;             // count edge but not downstream (i.e., lump to gnd)
        }
        cap_summer(capacitor_value_t downstream) : downstream_(downstream) {}
    private:
        capacitor_value_t downstream_;
    };

    void tree_edge(edge_t e, Graph const& g) {
        // remember the predecessor so later we can avoid summing up capacitance from back edges
        predecessors_[target(e, g)] = source(e, g);
    }

    void finish_vertex(vertex_t u, Graph const& g) {
        // We want to sum only *downstream* capacitance
        // However, circuits are undirected, and the downstreamness of our search
        // is only due to the order in which we encountered vertices
        // a "tree edge" is downstream, and a "back edge" is upstream

        downstream_caps_[u] = capacitor_value_t();
        for (auto e : boost::make_iterator_range(out_edges(u, g))) {
            // detect back edge, i.e., an edge to an already-visited node
            // this won't work correctly for circuits with resistive loops
            if ((predecessors_[target(e, g)] == u) || (target(e, g) == g.gnd())) {
                // our first time at this node, OR the node is gnd, in which case this is normal
                capacitor_value_t contr = boost::apply_visitor(cap_summer(downstream_caps_[target(e, g)]), g[e]);
                downstream_caps_[u] += contr;
            }
        }
    }

    // finish_edge never seems to get called

    cap_summing_visitor(std::vector<capacitor_value_t>& capsvec)
        : downstream_caps_(capsvec), predecessors_(capsvec.size()) {}

private:
    std::vector<capacitor_value_t>& downstream_caps_;
    std::vector<vertex_t> predecessors_;
};

typedef quantity<si::time> delay_t;

// adds up delays.  To be run on filtered (R-only) graph
template<typename Graph>
struct delay_calculating_visitor : boost::default_dfs_visitor {
    typedef typename boost::graph_traits<Graph>::edge_descriptor edge_t;
    typedef typename boost::graph_traits<Graph>::vertex_descriptor vertex_t;

    void start_vertex(vertex_t u, Graph const&) {
        // this hook is called once at the beginning;
        // we can use it to initialize the delay from the tree root
        delays_[u] = delay_t();
    }

    struct res_summer : boost::static_visitor<resistor_value_t> {
        resistor_value_t operator()(resistor_value_t const& r) const {
            return r;
        }
        resistor_value_t operator()(capacitor_value_t const&) const {
            assert(0);   // program bug - we should operate on a filtered graph
            return resistor_value_t();
        }
    };

    void tree_edge(edge_t e, Graph const& g) {
        delays_[target(e, g)] = delays_[source(e, g)] +
            boost::apply_visitor(res_summer(), g[e]) *
            downstream_caps_[target(e, g)];
    }

    void back_edge(edge_t, Graph const&) {
        // Resistive loops will break this algorithm - you could put a check here
    }

    delay_calculating_visitor(std::vector<capacitor_value_t>& capsvec,
                              std::vector<delay_t>& delays)
        : downstream_caps_(capsvec), delays_(delays) {}

private:
    std::vector<capacitor_value_t>& downstream_caps_;   // bottom-up
    std::vector<delay_t>&          delays_;            // top-down
};

int main() {
    using namespace boost;
    using namespace std;

    quantity<si::resistance> kohm(1.0 * units::si::kilo  * units::si::ohms);
    quantity<si::capacitance> ff(1.0 * units::si::femto * units::si::farads);

    // Coupling test case
    ckt_graph_t coupling_test;
    auto gnd = coupling_test.gnd();

    auto vagg = add_vertex("vagg", coupling_test);   // driver voltage source
    auto n1   = add_vertex("n1",   coupling_test);
    add_edge(vagg, n1, 0.1*kohm,   coupling_test);   // driver impedance
    auto n2   = add_vertex("n2",   coupling_test);   // central node - where coupling occurs
    add_edge(n1, n2, 1.0*kohm,     coupling_test);   // first "pi" model, aggressor side
    add_edge(n1, gnd, 50.0*ff,     coupling_test);   // caps for first "pi"
    add_edge(n2, gnd, 50.0*ff,     coupling_test);
    auto n3   = add_vertex("n3",   coupling_test);   // aggressor-side receiver
    add_edge(n2, n3, 1.0*kohm,     coupling_test);   // second "pi" model, aggressor side
    add_edge(n2, gnd, 50.0*ff,     coupling_test);   // caps for first "pi"
    add_edge(n3, gnd, 50.0*ff,     coupling_test);
    add_edge(n3, gnd, 20.0*ff,     coupling_test);   // aggressor side receiver load

    // then the same thing over again for the victim side
    auto vvic = add_vertex("vvic", coupling_test);   // driver voltage source
    auto n5   = add_vertex("n5",   coupling_test);
    add_edge(vvic, n5, 0.1*kohm,   coupling_test);   // driver impedance
    auto n6   = add_vertex("n6",   coupling_test);   // central node
    add_edge(n5, n6, 1.0*kohm,     coupling_test);   // first "pi" model
    add_edge(n5, gnd, 50.0*ff,     coupling_test);
    add_edge(n6, gnd, 50.0*ff,     coupling_test);
    auto n7   = add_vertex("n7",   coupling_test);   // victim-side receiver
    add_edge(n6, n7, 1.0*kohm,     coupling_test);   // second "pi" model
    add_edge(n6, gnd, 50.0*ff,     coupling_test);
    add_edge(n7, gnd, 50.0*ff,     coupling_test);
    add_edge(n7, gnd, 20.0*ff,     coupling_test);   // victim side receiver load

    // coupling capacitor between the two signal traces
    add_edge(n2, n6, 100.0*ff,     coupling_test);

    // calculate Elmore delay
    // Create visitors
    vector<capacitor_value_t> downstream_caps(num_vertices(coupling_test));
    cap_summing_visitor<ckt_graph_t> capvis(downstream_caps);

    // undirected DFS requires edge color map
    map<ckt_graph_t::edge_descriptor, default_color_type> edge_colors;
    auto cpmap = make_assoc_property_map(edge_colors);

    // perform first pass and sum capacitances
    undirected_dfs(coupling_test, edge_color_map(cpmap).visitor(capvis).root_vertex(vagg));

    typedef filtered_graph<ckt_graph_t, resistors_only> resonly_graph_t;
    resonly_graph_t res_graph(coupling_test, resistors_only(&coupling_test));

    vector<delay_t>          delays(num_vertices(coupling_test));
    delay_calculating_visitor<resonly_graph_t>
                                     delvis(downstream_caps, delays);

    // create *vertex* color map for depth_first_visit
    auto vindex_map = typed_identity_property_map<size_t>();
    vector<default_color_type> colorvec(num_vertices(coupling_test));   // underlying storage
    auto cvpmap = make_iterator_property_map(colorvec.begin(), vindex_map);

    depth_first_visit(res_graph, vagg, delvis, cvpmap);

    cout << "Elmore delay of aggressor net: " << delays.at(n3) << endl;

    // If you want to calculate the delay from a different node you have to recalculate
    // both capacitance and delays starting with that new node
}
<commit_msg>add (commented out) example of debugging with Graphviz<commit_after>// Demonstration of calculating Elmore delay with a graph
// to accompany "Analyzing On-Chip Interconnect with Modern C++"
// Author: Jeff Trull <edaskel@att.net>

/*
Copyright (c) 2014 Jeffrey E. Trull

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/

#include <iostream>
#include <fstream>

#include <boost/graph/visitors.hpp>
#include <boost/graph/undirected_dfs.hpp>
#include <boost/graph/graphviz.hpp>
#include <boost/units/systems/si/time.hpp>

#include "ckt_graph.h"

// For Elmore we need two visitors:
// 1) To calculate total capacitance at and "below" each node
// 2) To sum resistor delays to each node from a chosen input

template<typename Graph>
struct cap_summing_visitor : boost::default_dfs_visitor {
    typedef typename boost::graph_traits<Graph>::edge_descriptor edge_t;
    typedef typename boost::graph_traits<Graph>::vertex_descriptor vertex_t;

    // This edge variant visitor returns the correct contribution for an edge
    // to a downstream node: the value on the edge, if a capacitor, or
    // the supplied downstream capacitance, if a resistor.
    struct cap_summer : boost::static_visitor<capacitor_value_t> {
        capacitor_value_t operator()(resistor_value_t const&) const {
            return downstream_;   // count downstream, not edge
        }
        capacitor_value_t operator()(capacitor_value_t const& c) const {
            return c;             // count edge but not downstream (i.e., lump to gnd)
        }
        cap_summer(capacitor_value_t downstream) : downstream_(downstream) {}
    private:
        capacitor_value_t downstream_;
    };

    void tree_edge(edge_t e, Graph const& g) {
        // remember the predecessor so later we can avoid summing up capacitance from back edges
        predecessors_[target(e, g)] = source(e, g);
    }

    void finish_vertex(vertex_t u, Graph const& g) {
        // We want to sum only *downstream* capacitance
        // However, circuits are undirected, and the downstreamness of our search
        // is only due to the order in which we encountered vertices
        // a "tree edge" is downstream, and a "back edge" is upstream

        downstream_caps_[u] = capacitor_value_t();
        for (auto e : boost::make_iterator_range(out_edges(u, g))) {
            // detect back edge, i.e., an edge to an already-visited node
            // this won't work correctly for circuits with resistive loops
            if ((predecessors_[target(e, g)] == u) || (target(e, g) == g.gnd())) {
                // our first time at this node, OR the node is gnd, in which case this is normal
                capacitor_value_t contr = boost::apply_visitor(cap_summer(downstream_caps_[target(e, g)]), g[e]);
                downstream_caps_[u] += contr;
            }
        }
    }

    // finish_edge never seems to get called

    cap_summing_visitor(std::vector<capacitor_value_t>& capsvec)
        : downstream_caps_(capsvec), predecessors_(capsvec.size()) {}

private:
    std::vector<capacitor_value_t>& downstream_caps_;
    std::vector<vertex_t> predecessors_;
};

typedef quantity<si::time> delay_t;

// adds up delays.  To be run on filtered (R-only) graph
template<typename Graph>
struct delay_calculating_visitor : boost::default_dfs_visitor {
    typedef typename boost::graph_traits<Graph>::edge_descriptor edge_t;
    typedef typename boost::graph_traits<Graph>::vertex_descriptor vertex_t;

    void start_vertex(vertex_t u, Graph const&) {
        // this hook is called once at the beginning;
        // we can use it to initialize the delay from the tree root
        delays_[u] = delay_t();
    }

    struct res_summer : boost::static_visitor<resistor_value_t> {
        resistor_value_t operator()(resistor_value_t const& r) const {
            return r;
        }
        resistor_value_t operator()(capacitor_value_t const&) const {
            assert(0);   // program bug - we should operate on a filtered graph
            return resistor_value_t();
        }
    };

    void tree_edge(edge_t e, Graph const& g) {
        delays_[target(e, g)] = delays_[source(e, g)] +
            boost::apply_visitor(res_summer(), g[e]) *
            downstream_caps_[target(e, g)];
    }

    void back_edge(edge_t, Graph const&) {
        // Resistive loops will break this algorithm - you could put a check here
    }

    delay_calculating_visitor(std::vector<capacitor_value_t>& capsvec,
                              std::vector<delay_t>& delays)
        : downstream_caps_(capsvec), delays_(delays) {}

private:
    std::vector<capacitor_value_t>& downstream_caps_;   // bottom-up
    std::vector<delay_t>&          delays_;            // top-down
};

int main() {
    using namespace boost;
    using namespace std;

    quantity<si::resistance> kohm(1.0 * units::si::kilo  * units::si::ohms);
    quantity<si::capacitance> ff(1.0 * units::si::femto * units::si::farads);

    // Coupling test case
    ckt_graph_t coupling_test;
    auto gnd = coupling_test.gnd();

    auto vagg = add_vertex("vagg", coupling_test);   // driver voltage source
    auto n1   = add_vertex("n1",   coupling_test);
    add_edge(vagg, n1, 0.1*kohm,   coupling_test);   // driver impedance
    auto n2   = add_vertex("n2",   coupling_test);   // central node - where coupling occurs
    add_edge(n1, n2, 1.0*kohm,     coupling_test);   // first "pi" model, aggressor side
    add_edge(n1, gnd, 50.0*ff,     coupling_test);   // caps for first "pi"
    add_edge(n2, gnd, 50.0*ff,     coupling_test);
    auto n3   = add_vertex("n3",   coupling_test);   // aggressor-side receiver
    add_edge(n2, n3, 1.0*kohm,     coupling_test);   // second "pi" model, aggressor side
    add_edge(n2, gnd, 50.0*ff,     coupling_test);   // caps for first "pi"
    add_edge(n3, gnd, 50.0*ff,     coupling_test);
    add_edge(n3, gnd, 20.0*ff,     coupling_test);   // aggressor side receiver load

    // then the same thing over again for the victim side
    auto vvic = add_vertex("vvic", coupling_test);   // driver voltage source
    auto n5   = add_vertex("n5",   coupling_test);
    add_edge(vvic, n5, 0.1*kohm,   coupling_test);   // driver impedance
    auto n6   = add_vertex("n6",   coupling_test);   // central node
    add_edge(n5, n6, 1.0*kohm,     coupling_test);   // first "pi" model
    add_edge(n5, gnd, 50.0*ff,     coupling_test);
    add_edge(n6, gnd, 50.0*ff,     coupling_test);
    auto n7   = add_vertex("n7",   coupling_test);   // victim-side receiver
    add_edge(n6, n7, 1.0*kohm,     coupling_test);   // second "pi" model
    add_edge(n6, gnd, 50.0*ff,     coupling_test);
    add_edge(n7, gnd, 50.0*ff,     coupling_test);
    add_edge(n7, gnd, 20.0*ff,     coupling_test);   // victim side receiver load

    // coupling capacitor between the two signal traces
    add_edge(n2, n6, 100.0*ff,     coupling_test);

    // debug output via Dot
    /*
    ofstream dbg("/tmp/coupling_test.dot");
    write_graphviz(dbg, coupling_test,
                   make_label_writer(get(vertex_bundle, coupling_test)),
                   make_label_writer(get(edge_bundle, coupling_test)));
    */

    // calculate Elmore delay
    // Create visitors
    vector<capacitor_value_t> downstream_caps(num_vertices(coupling_test));
    cap_summing_visitor<ckt_graph_t> capvis(downstream_caps);

    // undirected DFS requires edge color map
    map<ckt_graph_t::edge_descriptor, default_color_type> edge_colors;
    auto cpmap = make_assoc_property_map(edge_colors);

    // perform first pass and sum capacitances
    undirected_dfs(coupling_test, edge_color_map(cpmap).visitor(capvis).root_vertex(vagg));

    typedef filtered_graph<ckt_graph_t, resistors_only> resonly_graph_t;
    resonly_graph_t res_graph(coupling_test, resistors_only(&coupling_test));

    vector<delay_t>          delays(num_vertices(coupling_test));
    delay_calculating_visitor<resonly_graph_t>
                                     delvis(downstream_caps, delays);

    // create *vertex* color map for depth_first_visit
    auto vindex_map = typed_identity_property_map<size_t>();
    vector<default_color_type> colorvec(num_vertices(coupling_test));   // underlying storage
    auto cvpmap = make_iterator_property_map(colorvec.begin(), vindex_map);

    depth_first_visit(res_graph, vagg, delvis, cvpmap);

    cout << "Elmore delay of aggressor net: " << delays.at(n3) << endl;

    // If you want to calculate the delay from a different node you have to recalculate
    // both capacitance and delays starting with that new node
}
<|endoftext|>


<commit_before>//
//  Graph.cpp
//  zombies
//
//  Created by Sunil on 4/17/17.
//  Copyright © 2017 Sunil. All rights reserved.
//

#include "Graph.h"

#include <set>
#include <queue>
#include <algorithm>

using namespace std;

template <class T>
Graph<T>::Graph() {

}

template <class T>
Graph<T>::~Graph() {
    //dtor
}

template <class T>
void Graph<T>::addEdge(T v1, T v2, int weight) {

    if (weight == -1) {
        // no edge. ignore
        return;
    }

    for (int i = 0; i < vertices.size(); i++) {
        if(vertices[i].name != v1)
            continue;

        for (int j = 0; j < vertices.size(); j++) {
            if(vertices[j].name != v2 || i == j) continue;

            adjVertex<T> av;
            av.v = &vertices[j];
            av.weight = weight;
            vertices[i].adj.push_back(av);

            //add edge in the other direction
            //vertices[i].adj.push_back(av);
            //another vertex for edge in other direction

            //adjVertex<T> av2;
            //av2.v = &vertices[i];
            //av2.weight = weight;
            //vertices[j].adj.push_back(av2);
        }
    }
}

template <class T>
void Graph<T>::addVertex(T n) {
    bool found = false;
    for (int i = 0; i < vertices.size(); i++) {
        if (vertices[i].name == n) {
            found = true;
            cout << vertices[i].name << " found." << endl;
        }
    }

    if (found == false){
        vertex<T> v;
        v.name = n;
        vertices.push_back(v);

    }
}

template <class T>
void Graph<T>::displayEdges(){
    //loop through all vertices and adjacent vertices
    for (auto& city : vertices) {
        cout << city.name << "-->";

        for (auto& adjCity : city.adj) {
            cout << adjCity.v->name << "***";
        }

        cout << endl;
    }
}

template <class T>
void Graph<T>::displayVertices() {
    for (auto& city : vertices) {
        cout << city.districtId << ":" << city.name << "->";

        auto hasMultipleEntries = false;

        // print the adjacent cities.
        for (auto& adjCity : city.adj) {
            if (adjCity.weight == -1) continue;
            if (hasMultipleEntries) cout << "***";
            cout << adjCity.v->name;
            hasMultipleEntries = true;
        }

        cout << endl;
    }
}

template <class T>
void Graph<T>::assignDistrictIds() {
    int districtId = 1;
    for (auto& city : vertices) {
        // check if this city has district id assigned.
        if (city.districtId == -1) {
            // if district id not assigned, then do bfs to assign id to
            // it's connected cities.
            bfsAssignId(city, districtId);

            // increment the id
            districtId++;
        }
    }
}

template <class T>
void Graph<T>::bfsAssignId(vertex<T>& city, int id) {
    // do a bfs iterative traversal.

    // very important to have a queue of pointers.
    // otherwise district id would be assigned only to local copies.
    deque<vertex<T>*> queue;
    queue.push_back(&city);

    while(!queue.empty()) {
        auto city = queue.front();
        queue.pop_front();

        city->districtId = id;

        for (auto& adjCity : city->adj) {
            // ignore the current city.
            // Verify: Is this taken care while adding a edge ?
            if (adjCity.v->name == city->name) {
                continue;
            }

            // Add the adjacent city if it doesn't have a district id assigned.
            // I could have used a variable like visited in vertex to track if it's
            // already visited or not. But i can get away with checking district id.
            if (adjCity.v->districtId == -1) {
                queue.push_back(adjCity.v);
            }
        }
    }
}

template <class T>
vertex<T>* Graph<T>::findCity(string cityName) {
    // use stl algorithm find_if with lambda expression to specify search criteria
    auto iter = std::find_if(begin(vertices), end(vertices), [&cityName](vertex<T>& item) {
        return item.name == cityName;
    });

    auto found = iter != end(vertices) ? &(*iter) : nullptr;
    return found;
}

template <class T>
void Graph<T>::findShortestPath(std::string src, std::string dest) {

    auto srcCity = findCity(src);
    auto destCity = findCity(dest);

    if (!srcCity || !destCity) {
        // One or both cities not found:
        cout << "One or more cities doesn't exist" << endl;
        return;
    }

    if (srcCity->districtId == -1 || destCity->districtId == -1) {
        // Districts not set yet
        cout << "Please identify the districts before checking distances" << endl;
        return;
    }

    if (srcCity->districtId != destCity->districtId) {
        // Cities in different districts:
        cout << "No safe path between cities" << endl;
        return;
    }

    // if source and dest are same. Nothing to do.
    if (srcCity->name == destCity->name) {
        cout << "0, " << src << ", " << dest << endl;
        return;
    }

    // run a dijkstra's algorithm here to find the shortest path.
    dijkstra(src, dest);
}

template <class T>
int Graph<T>::length(vertex<T>* u, string v) {

    for (auto adjCity : u->adj) {
        if (adjCity.v->name == v) {
            auto weight = adjCity.weight;
            return weight == -1 ? INFINITY : weight;
        }
    }

    return INFINITY;
}

template <class T>
void Graph<T>::dijkstra(string dest, string src) {
    // I swap the parameters to get the output in right format.
    // By swapping src, dest. It doesn't change anything.

    // cout << "Run dijkstra's algorithm here" << endl;
    // reference: https://en.wikipedia.org/wiki/Dijkstra%27s_algorithm

    map<string, int> dist;
    map<string, string> prev;
    set<vertex<T>*> q;

    // Initialization
    for (auto& v : vertices) {
        dist[v.name] = INFINITY;    // Unknown distance from source to v
        prev[v.name] = UNDEFINED;   // Previous node in optimal path from source
        q.insert(&v);               // All nodes initially in Q (unvisited nodes)
    }

    // Distance from source to source
    dist[src] = 0;

    auto minDist = [](set<vertex<T>*> q, map<string, int> dist) {
        vertex<T>* min = nullptr;
        double d = INFINITY;
        for (auto e : q) {
            if (!min) {
                min = e;
            }

            if (dist[e->name] < d) {
                d = dist[e->name];
                min = e;
            }
        }

        return min;
    };

    while (!q.empty()) {
        // Node with the least distance will be selected first
        auto u = minDist(q, dist);

        if (u->name == dest) {
            break;
        }

        // remove u from Q
        q.erase(u);

        // where v is still in Q.
        for (auto& adj : u->adj) {
            auto v = adj.v->name;
            auto alt = dist[u->name] + length(u, v);

            if (alt < dist[v]) {
                dist[v] = alt;
                prev[v] = u->name;
            }
        }
    }

    // Now we can read the shortest path from
    // source to target by reverse iteration.
    printPath(dest, dist, prev);
}

template <class T>
void Graph<T>::printPath(string u, map<string, int>& dist, map<string, string>& prev) {
    // print distance.
    cout << dist[u] << ", ";

    while (prev[u] != UNDEFINED) {
        cout << u << ", ";
        u = prev[u];
    }

    cout << u << endl;
}
<commit_msg>show hop count and not actual dist.<commit_after>//
//  Graph.cpp
//  zombies
//
//  Created by Sunil on 4/17/17.
//  Copyright © 2017 Sunil. All rights reserved.
//

#include "Graph.h"

#include <set>
#include <queue>
#include <sstream>
#include <algorithm>

using namespace std;

template <class T>
Graph<T>::Graph() {

}

template <class T>
Graph<T>::~Graph() {
    //dtor
}

template <class T>
void Graph<T>::addEdge(T v1, T v2, int weight) {

    if (weight == -1) {
        // no edge. ignore
        return;
    }

    for (int i = 0; i < vertices.size(); i++) {
        if(vertices[i].name != v1)
            continue;

        for (int j = 0; j < vertices.size(); j++) {
            if(vertices[j].name != v2 || i == j) continue;

            adjVertex<T> av;
            av.v = &vertices[j];
            av.weight = weight;
            vertices[i].adj.push_back(av);

            //add edge in the other direction
            //vertices[i].adj.push_back(av);
            //another vertex for edge in other direction

            //adjVertex<T> av2;
            //av2.v = &vertices[i];
            //av2.weight = weight;
            //vertices[j].adj.push_back(av2);
        }
    }
}

template <class T>
void Graph<T>::addVertex(T n) {
    bool found = false;
    for (int i = 0; i < vertices.size(); i++) {
        if (vertices[i].name == n) {
            found = true;
            cout << vertices[i].name << " found." << endl;
        }
    }

    if (found == false){
        vertex<T> v;
        v.name = n;
        vertices.push_back(v);

    }
}

template <class T>
void Graph<T>::displayEdges(){
    //loop through all vertices and adjacent vertices
    for (auto& city : vertices) {
        cout << city.name << "-->";

        for (auto& adjCity : city.adj) {
            cout << adjCity.v->name << "***";
        }

        cout << endl;
    }
}

template <class T>
void Graph<T>::displayVertices() {
    for (auto& city : vertices) {
        cout << city.districtId << ":" << city.name << "->";

        auto hasMultipleEntries = false;

        // print the adjacent cities.
        for (auto& adjCity : city.adj) {
            if (adjCity.weight == -1) continue;
            if (hasMultipleEntries) cout << "***";
            cout << adjCity.v->name;
            hasMultipleEntries = true;
        }

        cout << endl;
    }
}

template <class T>
void Graph<T>::assignDistrictIds() {
    int districtId = 1;
    for (auto& city : vertices) {
        // check if this city has district id assigned.
        if (city.districtId == -1) {
            // if district id not assigned, then do bfs to assign id to
            // it's connected cities.
            bfsAssignId(city, districtId);

            // increment the id
            districtId++;
        }
    }
}

template <class T>
void Graph<T>::bfsAssignId(vertex<T>& city, int id) {
    // do a bfs iterative traversal.

    // very important to have a queue of pointers.
    // otherwise district id would be assigned only to local copies.
    deque<vertex<T>*> queue;
    queue.push_back(&city);

    while(!queue.empty()) {
        auto city = queue.front();
        queue.pop_front();

        city->districtId = id;

        for (auto& adjCity : city->adj) {
            // ignore the current city.
            // Verify: Is this taken care while adding a edge ?
            if (adjCity.v->name == city->name) {
                continue;
            }

            // Add the adjacent city if it doesn't have a district id assigned.
            // I could have used a variable like visited in vertex to track if it's
            // already visited or not. But i can get away with checking district id.
            if (adjCity.v->districtId == -1) {
                queue.push_back(adjCity.v);
            }
        }
    }
}

template <class T>
vertex<T>* Graph<T>::findCity(string cityName) {
    // use stl algorithm find_if with lambda expression to specify search criteria
    auto iter = std::find_if(begin(vertices), end(vertices), [&cityName](vertex<T>& item) {
        return item.name == cityName;
    });

    auto found = iter != end(vertices) ? &(*iter) : nullptr;
    return found;
}

template <class T>
void Graph<T>::findShortestPath(std::string src, std::string dest) {

    auto srcCity = findCity(src);
    auto destCity = findCity(dest);

    if (!srcCity || !destCity) {
        // One or both cities not found:
        cout << "One or more cities doesn't exist" << endl;
        return;
    }

    if (srcCity->districtId == -1 || destCity->districtId == -1) {
        // Districts not set yet
        cout << "Please identify the districts before checking distances" << endl;
        return;
    }

    if (srcCity->districtId != destCity->districtId) {
        // Cities in different districts:
        cout << "No safe path between cities" << endl;
        return;
    }

    // if source and dest are same. Nothing to do.
    if (srcCity->name == destCity->name) {
        cout << "0, " << src << ", " << dest << endl;
        return;
    }

    // run a dijkstra's algorithm here to find the shortest path.
    dijkstra(src, dest);
}

template <class T>
int Graph<T>::length(vertex<T>* u, string v) {

    for (auto adjCity : u->adj) {
        if (adjCity.v->name == v) {
            auto weight = adjCity.weight;
            return weight == -1 ? INFINITY : weight;
        }
    }

    return INFINITY;
}

template <class T>
void Graph<T>::dijkstra(string dest, string src) {
    // I swap the parameters to get the output in right format.
    // By swapping src, dest. It doesn't change anything.

    // cout << "Run dijkstra's algorithm here" << endl;
    // reference: https://en.wikipedia.org/wiki/Dijkstra%27s_algorithm

    map<string, int> dist;
    map<string, string> prev;
    set<vertex<T>*> q;

    // Initialization
    for (auto& v : vertices) {
        dist[v.name] = INFINITY;    // Unknown distance from source to v
        prev[v.name] = UNDEFINED;   // Previous node in optimal path from source
        q.insert(&v);               // All nodes initially in Q (unvisited nodes)
    }

    // Distance from source to source
    dist[src] = 0;

    auto minDist = [](set<vertex<T>*> q, map<string, int> dist) {
        vertex<T>* min = nullptr;
        double d = INFINITY;
        for (auto e : q) {
            if (!min) {
                min = e;
            }

            if (dist[e->name] < d) {
                d = dist[e->name];
                min = e;
            }
        }

        return min;
    };

    while (!q.empty()) {
        // Node with the least distance will be selected first
        auto u = minDist(q, dist);

        if (u->name == dest) {
            break;
        }

        // remove u from Q
        q.erase(u);

        // where v is still in Q.
        for (auto& adj : u->adj) {
            auto v = adj.v->name;
            auto alt = dist[u->name] + length(u, v);

            if (alt < dist[v]) {
                dist[v] = alt;
                prev[v] = u->name;
            }
        }
    }

    // Now we can read the shortest path from
    // source to target by reverse iteration.
    printPath(dest, dist, prev);
}

template <class T>
void Graph<T>::printPath(string u, map<string, int>& dist, map<string, string>& prev) {
    // print hop count.
    stringstream path;

    // actual distance.
    // cout << dist[u] << ", ";

    auto hops = 0;
    while (prev[u] != UNDEFINED) {
        path << u << ", ";
        hops++;
        u = prev[u];
    }

    path << u << endl;

    cout << hops << ", " << path.str();
}
<|endoftext|>


<commit_before>#include <cassert>
#include <cstdio>
#include <iostream>
#include <set>
#include <string>
#include <map>
#include <vector>

using namespace std;

#define TRACE(x) cerr << #x << " " << x << endl
#define _ << " " <<

struct node;

struct edge {

  int src_loc, quality;
  string s;

  node* dest;

  edge() {
    quality = 0;
    dest = NULL;
  }

  edge(int _sl, int _qual, string _s) {
    src_loc = _sl;
    quality = _qual;
    s = _s;
  }

};

struct node {

  int loc;
  string kmer;
  vector <edge*> edges;

  void trace_dfs() {
    cout << "Backbone_id; " << loc << ", node_str: " << kmer << endl;
    for (auto e : edges) {
      assert(e != NULL);
      cout << "edge from id: " << e->src_loc << " with edge_str: " << e->s
           << " and quality: " << e->quality << endl;
      e->dest->trace_dfs();
    }
  }

};

int k = 2, g = 3;

string backbone, read, read_quality;

node *kmer_graph;

map <pair<int, string>, node*> V;
map <pair<int, string>, edge*> E;

void build_backbone(node *root) {
  int it = 0;
  while (it + k <= (int) backbone.size()) {

    root->loc = it;
    root->kmer = backbone.substr(it, k);

    V[make_pair(root->loc, root->kmer)] = root;

    it += k;
    if (it + g > (int) backbone.size())
      break;

    string edge_str = backbone.substr(it, g);
    edge* e = new edge(root->loc, 1, edge_str);

    it += g - k;

    e->dest = new node();
    root->edges.push_back(e);
    E[make_pair(root->loc, edge_str)] = e;

    root = e->dest;
  }
}

void add_path(int offset) {

  string kmer = read.substr(0, k);

  assert(V.find(make_pair(offset, kmer)) != V.end());
  assert(offset + read.size() <= backbone.size());

  node *curr = V[make_pair(offset, kmer)];

  int it = k;
  while (it + g <= read.size()) {

    TRACE(it);

    string edge_str = read.substr(it, g);
    string next_kmer = edge_str.substr(g - k, k);

    node* nxt = NULL;
    edge* link = NULL;

    if (V.find(make_pair(it + g - k, next_kmer)) != V.end())
      nxt = V[make_pair(it + g - k, next_kmer)];

    if (nxt == NULL) {
      nxt = new node();
      nxt->loc = curr->loc + g;
      nxt->kmer = next_kmer;
      V[make_pair(nxt->loc, nxt->kmer)] = nxt;
    }

    for (auto e : curr->edges)
      if (e->s == edge_str)
        link = e;

    if (link == NULL) {
      link = new edge(curr->loc, 0, edge_str);
      link->dest = nxt;
      curr->edges.push_back(link);
    }

    link->quality++;

    curr = nxt;
    it += g;

  }

}

int main(void) {

  ios_base::sync_with_stdio(false);
  kmer_graph = new node();

  cin >> backbone;
  build_backbone(kmer_graph);

  int read_cnt;
  cin >> read_cnt;

  while (read_cnt --> 0) {
    int offset;
    cin >> read;
    cin >> read_quality;
    cin >> offset;
    add_path(offset);
  }

  kmer_graph->trace_dfs();

  return 0;

}
<commit_msg>Added longest path reconstruction<commit_after>#include <cassert>
#include <cstdio>
#include <iostream>
#include <set>
#include <stack>
#include <string>
#include <map>
#include <queue>
#include <vector>

using namespace std;

#define TRACE(x) cerr << #x << " " << x << endl
#define _ << " " <<

const int INF = (int) 1e9;

struct node;

struct edge {

  int src_loc, quality;
  string s;

  node* dest;

  edge() {
    quality = 0;
    dest = NULL;
  }

  edge(int _sl, int _qual, string _s) {
    src_loc = _sl;
    quality = _qual;
    s = _s;
  }

};

struct node {

  int loc, score;
  string kmer;
  vector <edge*> edges;

  void trace_dfs() {
    cout << "Backbone_id; " << loc << ", node_str: " << kmer << endl;
    for (auto e : edges) {
      assert(e != NULL);
      cout << "edge from id: " << e->src_loc << " with edge_str: " << e->s
           << " and quality: " << e->quality << endl;
      if (e->dest != NULL)
        e->dest->trace_dfs();
    }
  }

  node () {
    score = -1;
  }

};

int k = 2, g = 3;
int skipped = 0;

string backbone, read, read_quality;

node *kmer_graph;

map <pair<int, string>, node*> V;
map <pair<int, string>, edge*> E;

map <node*, pair<node*, edge*>> dad;

void build_backbone(node *root) {
  int it = 0;
  while (it + k <= (int) backbone.size()) {

    root->loc = it;
    root->kmer = backbone.substr(it, k);

    V[make_pair(root->loc, root->kmer)] = root;

    it += k;
    if (it + g > (int) backbone.size())
      break;

    string edge_str = backbone.substr(it, g);
    edge* e = new edge(root->loc, 1, edge_str);

    it += g - k;

    e->dest = new node();
    root->edges.push_back(e);
    E[make_pair(root->loc, edge_str)] = e;

    root = e->dest;
  }
}

void add_path(int offset) {

  node *curr;
  string kmer = read.substr(0, k);

  if (offset % g != 0) {
    ++skipped;
    cerr << "Skipping path with offset = " << offset << endl;
    return;
  }

  if (V.find(make_pair(offset, kmer)) == V.end()) {
    curr = new node();
    curr->loc = offset;
    curr->kmer = kmer;
  } else {
    curr = V[make_pair(offset, kmer)];
  }

//  assert(V.find(make_pair(offset, kmer)) != V.end());
//  assert(offset + read.size() <= backbone.size());

  cerr << "Building path with offset = " << offset << endl;

  int it = k;
  while (it + g <= read.size()) {

    string edge_str = read.substr(it, g);
    string next_kmer = edge_str.substr(g - k, k);

    node* nxt = NULL;
    edge* link = NULL;

    if (V.find(make_pair(curr->loc + g - k, next_kmer)) != V.end())
      nxt = V[make_pair(curr->loc + g - k, next_kmer)];

    if (nxt == NULL) {
      nxt = new node();
      nxt->loc = curr->loc + g;
      nxt->kmer = next_kmer;
      V[make_pair(nxt->loc, nxt->kmer)] = nxt;
    }

    for (auto e : curr->edges)
      if (e->s == edge_str)
        link = e;

    if (link == NULL) {
      link = new edge(curr->loc, 0, edge_str);
      link->dest = nxt;
      curr->edges.push_back(link);
    }

    link->quality++;

    curr = nxt;
    it += g;

  }

  cerr << "Path with offset: " << offset << " built successfully!" << endl;

}

void reconstruct_genome(node *root) {

  node *leaf = new node();

  queue <node*> Q;
  Q.push(root);
  root->score = 0;

  while (!Q.empty()) {

    node *curr = Q.front();
    Q.pop();

    if (curr->score > leaf->score)
      leaf = curr;

    for (auto e : curr->edges) {
      if (e->dest->score == -1)
        Q.push(e->dest);
      if (e->dest->score < curr->score + e->quality) {
        e->dest->score = curr->score + e->quality;
        dad[e->dest] = make_pair(curr, e);
      }
    }

  }

  cout << "Found path with quality = " << leaf->score << endl;

  stack <string> S;
  while (dad.find(leaf) != dad.end()) {
    auto p = dad[leaf];
    S.push(p.second->s);
    assert(p.first->loc < leaf->loc);
    leaf = p.first;
  }

  cout << leaf->kmer;
  while (!S.empty()) {
    cout << S.top();
    S.pop();
  }

  cout << endl;

}

int main(void) {

  ios_base::sync_with_stdio(false);
  kmer_graph = new node();

  cin >> backbone;
  build_backbone(kmer_graph);

  cerr << "Backbone built successfully!" << endl;

  while (cin >> read) {
    int offset;
    cin >> read_quality;
    cin >> offset;
    --offset;
    add_path(offset);
  }

  reconstruct_genome(kmer_graph);
  TRACE(skipped);

  return 0;

}
<|endoftext|>


<commit_before>/*
 * =====================================================================================
 *
 *       Filename:  segment.cc
 *
 *    Description:  some segment algorithms
 *
 *        Version:  1.0
 *        Created:  01/22/2015 09:43:30 AM
 *       Revision:  none
 *       Compiler:  gcc
 *
 *         Author:   (Qi Liu), liuqi.edward@gmail.com
 *   Organization:  antq.com
 *
 * =====================================================================================
 */

#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <time.h>
#include <float.h>
#include <cmath>

const int32_t CLOCKWISE_SIGNAL = 1;
const int32_t COUNTER_CLOCKWISE_SIGNAL = -1;
const int32_t COLLINEAR = 0;
#define SAME_SIGN(x, y) (((x) > 0) ^ ((y) < 0))
typedef struct _Point{
	double x;
	double y;
}Point_t;
typedef struct _Line{
	Point_t start;
	Point_t end;
}Line_t;

typedef struct _CrossPoint{
	Point_t point;
	double cross_mult;
}CrossPoint_t;

typedef struct _PointArray{
	Point_t* points;
	int32_t size;
}PointArray_t;

double Distance(Point_t p1, Point_t p2)
{
	return sqrt(pow(p1.x-p2.x, 2)+pow(p1.y-p2.y, 2));
}

double CrossMultiply(Point_t p1, Point_t p2, Point_t p0)
{
	return (p1.x-p0.x)*(p2.y-p0.y) - (p2.x-p0.x)*(p1.y-p0.y);
}

int ComparePolarAngel(const void* first,const void* second)
{
	int ret = 0;
	CrossPoint_t* cp1 = (CrossPoint_t*)first;
	CrossPoint_t* cp2 = (CrossPoint_t*)second;
	if(cp1->cross_mult == cp2->cross_mult)
		ret = 0;
	else if(cp1->cross_mult == 0)
		return -1;
	else if(cp2->cross_mult == 0)
		return 1;
	else if((cp1->cross_mult > 0 && cp2->cross_mult > 0) ||
			(cp1->cross_mult < 0 && cp2->cross_mult < 0))
	{
		if(cp1->cross_mult < cp2->cross_mult)
			ret = -1;
		else
			ret = 1;
	}
	else if(cp1->cross_mult < 0)
		ret = 1;
	else
		ret = -1;

	return ret;
}
/*
 * Sort points by polar angel related to points[0]
 * If more than one point has same polar angel,
 * remove all but the one that is farthest from points[0]
 */
PointArray_t SortPointsByPolarAngel(Point_t* points, int32_t size)
{
	int32_t i, j;
	double x;
	CrossPoint_t* cpoints = (CrossPoint_t*)malloc(size*sizeof(CrossPoint_t));
	PointArray_t ps;
	ps.points = (Point_t*)malloc(size*sizeof(Point_t));
	for(i = 1; i < size; ++i)
	{
		x = points[i].x - points[0].x;
		cpoints[i].point = points[i];
		if(x == 0)
			cpoints[i].cross_mult = DBL_MAX;
		else
			cpoints[i].cross_mult = (points[i].y - points[0].y)/x;
	}
	qsort(cpoints+1, size-1, sizeof(CrossPoint_t), ComparePolarAngel);
	ps.points[0] = points[0];
	ps.points[1] = cpoints[1].point;
	for(i = 2, j = 1; i < size; ++i)
	{
		if(cpoints[i].cross_mult == cpoints[j].cross_mult)
		{
			if(Distance(points[0], ps.points[j]) < Distance(points[0],
						cpoints[i].point))
				ps.points[j] = cpoints[i].point;
		}
		else
			ps.points[++j] = cpoints[i].point;
	}
	ps.size = j+1;
	free(cpoints);

	return ps;
}
/*
 * Find the left-bottom point of the points array
 */
void FindLeftBottomPoint(Point_t* points, int32_t size)
{
	int i;
	Point_t p = points[0];
	for(i = 1; i < size; ++i)
	{
		if((points[i].y < p.y) || (points[i].y == p.y && points[i].x < p.x))
		{
			p = points[i];
			points[i] = points[0];
			points[0] = p;
		}
	}
}

/*
 * Judge the direction of second line related to first line
 * @RET
 *     1  for clockwise
 *     -1 for counter clockwise
 *     0  for collinear
 */
int32_t JudgeDirection(const Point_t origin, const Point_t first, const Point_t second)
{
	double vx = (first.x - origin.x) * (second.y - origin.y);
	double vy = (first.y - origin.y) * (second.x - origin.x);
	vx -= vy;
	if(vx < 0)
		return CLOCKWISE_SIGNAL;
	else if(vx > 0)
		return COUNTER_CLOCKWISE_SIGNAL;
	else
		return COLLINEAR;
}
/*
 * Graham scan algorithm for finding the convex hull
 */
void GrahamScan(Point_t* points, int32_t size, PointArray_t* stack)
{
	int i, top, new_size;
	PointArray_t points_array;
	Point_t* rpoints;

	FindLeftBottomPoint(points, size);
	points_array = SortPointsByPolarAngel(points, size);

	rpoints = points_array.points;
	new_size = points_array.size;

	top = 0;
	stack->points[top++] = rpoints[0];
	stack->points[top++] = rpoints[1];
	stack->points[top++] = rpoints[2];

	for(i = 3; i < new_size; ++i)
	{
		if(JudgeDirection(stack->points[top-2], stack->points[top-1],
					rpoints[i]) != COUNTER_CLOCKWISE_SIGNAL)
		{
			top--;
		}
		stack->points[top++] = rpoints[i];
	}
	stack->size = top;

	free(rpoints);
}

bool OnSegment(const Point_t p1, const Point_t p2, const Point_t p0)
{
	if(((p0.x > p1.x) && (p0.x < p2.x)) || ((p0.x < p1.x) && (p0.x > p2.x)))
		return true;
	else if(((p0.y > p1.y) && (p0.y < p2.y)) || ((p0.y < p1.y) && (p0.y > p2.y)))
		return true;
	else
		return false;
}
/*
 * Judge whether tow lines intersect
 */
bool JudgeIntersection(const Line_t first, const Line_t second)
{
	bool ret = false;
	int32_t start2first = JudgeDirection(first.start, first.end, second.start);
	int32_t end2first = JudgeDirection(first.start, first.end, second.end);
	int32_t start2second = JudgeDirection(second.start, second.end, first.start);
	int32_t end2second = JudgeDirection(second.start, second.end, first.end);

	if(((start2first > 0 && end2first < 0) ||  (start2first < 0 && end2first > 0)) &&
				((start2second > 0 && end2second < 0) || (start2second < 0 && end2second > 0)))
		ret = true;
	else if((start2first == 0) && OnSegment(first.start, first.end, second.start))
		ret = true;
	else if((end2first == 0) && OnSegment(first.start, first.end, second.end))
		ret = true;
	else if((start2second == 0) && OnSegment(second.start, second.end, first.start))
		ret = true;
	else if((end2second == 0) && OnSegment(second.start, second.end, first.end))
		ret = true;

	return ret;
}

Point_t* ReadPointsData(const char* file_name, int32_t* size)
{
	int i, count;
	Point_t* points;
	freopen(file_name, "r", stdin);
	scanf("%d", size);
	count = *size;
	points = (Point_t*)malloc(count * sizeof(Point_t));
	for(i = 0; i < count; ++i)
	{
		scanf("%lf %lf", &(points[i].x), &(points[i].y));
	}
	return points;
}

int main()
{
	int32_t start;
	Point_t first, second;
	Line_t line1, line2;

	first.x = 1;
	first.y = 1;
	second.x = 3;
	second.y = 3;
	line1.start = first;
	line1.end = second;

	first.x = 1;
	first.y = 0;
	second.x = 1;
	second.y = 6;
	line2.start = first;
	line2.end = second;

	fprintf(stdout, "Line Ans: %d\n", JudgeIntersection(line1, line2));

	//Test Graham scan algorithm
	int size;
	Point_t* points;
	PointArray_t stack;

	const char* file_name = "points.data";
	points = ReadPointsData(file_name, &size);
	stack.size = 0;
	stack.points = (Point_t*)malloc(size*sizeof(Point_t));
	start = clock();
	GrahamScan(points, size, &stack);
	fprintf(stdout, "Time : %.3lf\n", double(clock()-start)/CLOCKS_PER_SEC);
	fprintf(stdout, "Convex Hull Size: %d \n", stack.size);
	free(points);
	free(stack.points);
	return 0;
}
<commit_msg>Add the part to deal with special variables of graham scan algorithm<commit_after>/*
 * =====================================================================================
 *
 *       Filename:  segment.cc
 *
 *    Description:  some segment algorithms
 *
 *        Version:  1.0
 *        Created:  01/22/2015 09:43:30 AM
 *       Revision:  none
 *       Compiler:  gcc
 *
 *         Author:   (Qi Liu), liuqi.edward@gmail.com
 *   Organization:  antq.com
 *
 * =====================================================================================
 */

#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <time.h>
#include <float.h>
#include <cmath>

const int32_t CLOCKWISE_SIGNAL = 1;
const int32_t COUNTER_CLOCKWISE_SIGNAL = -1;
const int32_t COLLINEAR = 0;
#define SAME_SIGN(x, y) (((x) > 0) ^ ((y) < 0))
typedef struct _Point{
	double x;
	double y;
}Point_t;
typedef struct _Line{
	Point_t start;
	Point_t end;
}Line_t;

typedef struct _CrossPoint{
	Point_t point;
	double cross_mult;
}CrossPoint_t;

typedef struct _PointArray{
	Point_t* points;
	int32_t size;
}PointArray_t;

double Distance(Point_t p1, Point_t p2)
{
	return sqrt(pow(p1.x-p2.x, 2)+pow(p1.y-p2.y, 2));
}

double CrossMultiply(Point_t p1, Point_t p2, Point_t p0)
{
	return (p1.x-p0.x)*(p2.y-p0.y) - (p2.x-p0.x)*(p1.y-p0.y);
}

int ComparePolarAngel(const void* first,const void* second)
{
	int ret = 0;
	CrossPoint_t* cp1 = (CrossPoint_t*)first;
	CrossPoint_t* cp2 = (CrossPoint_t*)second;
	if(cp1->cross_mult == cp2->cross_mult)
		ret = 0;
	else if(cp1->cross_mult == 0)
		return -1;
	else if(cp2->cross_mult == 0)
		return 1;
	else if((cp1->cross_mult > 0 && cp2->cross_mult > 0) ||
			(cp1->cross_mult < 0 && cp2->cross_mult < 0))
	{
		if(cp1->cross_mult < cp2->cross_mult)
			ret = -1;
		else
			ret = 1;
	}
	else if(cp1->cross_mult < 0)
		ret = 1;
	else
		ret = -1;

	return ret;
}
/*
 * Sort points by polar angel related to points[0]
 * If more than one point has same polar angel,
 * remove all but the one that is farthest from points[0]
 */
PointArray_t SortPointsByPolarAngel(Point_t* points, int32_t size)
{
	int32_t i, j;
	double x;
	CrossPoint_t* cpoints = (CrossPoint_t*)malloc(size*sizeof(CrossPoint_t));
	PointArray_t ps;
	ps.points = (Point_t*)malloc(size*sizeof(Point_t));
	for(i = 1; i < size; ++i)
	{
		x = points[i].x - points[0].x;
		cpoints[i].point = points[i];
		if(x == 0)
			cpoints[i].cross_mult = DBL_MAX;
		else
			cpoints[i].cross_mult = (points[i].y - points[0].y)/x;
	}
	qsort(cpoints+1, size-1, sizeof(CrossPoint_t), ComparePolarAngel);
	ps.points[0] = points[0];
	ps.points[1] = cpoints[1].point;
	for(i = 2, j = 1; i < size; ++i)
	{
		if(cpoints[i].cross_mult == cpoints[j].cross_mult)
		{
			if(Distance(points[0], ps.points[j]) < Distance(points[0],
						cpoints[i].point))
				ps.points[j] = cpoints[i].point;
		}
		else
			ps.points[++j] = cpoints[i].point;
	}
	ps.size = j+1;
	free(cpoints);

	return ps;
}
/*
 * Find the left-bottom point of the points array
 */
void FindLeftBottomPoint(Point_t* points, int32_t size)
{
	int i;
	Point_t p = points[0];
	for(i = 1; i < size; ++i)
	{
		if((points[i].y < p.y) || (points[i].y == p.y && points[i].x < p.x))
		{
			p = points[i];
			points[i] = points[0];
			points[0] = p;
		}
	}
}

/*
 * Judge the direction of second line related to first line
 * @RET
 *     1  for clockwise
 *     -1 for counter clockwise
 *     0  for collinear
 */
int32_t JudgeDirection(const Point_t origin, const Point_t first, const Point_t second)
{
	double vx = (first.x - origin.x) * (second.y - origin.y);
	double vy = (first.y - origin.y) * (second.x - origin.x);
	vx -= vy;
	if(vx < 0)
		return CLOCKWISE_SIGNAL;
	else if(vx > 0)
		return COUNTER_CLOCKWISE_SIGNAL;
	else
		return COLLINEAR;
}
/*
 * Graham scan algorithm for finding the convex hull
 */
void GrahamScan(Point_t* points, int32_t size, PointArray_t* stack)
{
	if(points == NULL || size <=0 || stack == NULL)
		return;
	int i, top, new_size;
	PointArray_t points_array;
	Point_t* rpoints;

	FindLeftBottomPoint(points, size);
	points_array = SortPointsByPolarAngel(points, size);

	rpoints = points_array.points;
	new_size = points_array.size;

	if(new_size < 3)
	{
		free(rpoints);
		return;
	}

	top = 0;
	stack->points[top++] = rpoints[0];
	stack->points[top++] = rpoints[1];
	stack->points[top++] = rpoints[2];

	for(i = 3; i < new_size; ++i)
	{
		if(JudgeDirection(stack->points[top-2], stack->points[top-1],
					rpoints[i]) != COUNTER_CLOCKWISE_SIGNAL)
		{
			top--;
		}
		stack->points[top++] = rpoints[i];
	}
	stack->size = top;

	free(rpoints);
}

bool OnSegment(const Point_t p1, const Point_t p2, const Point_t p0)
{
	if(((p0.x > p1.x) && (p0.x < p2.x)) || ((p0.x < p1.x) && (p0.x > p2.x)))
		return true;
	else if(((p0.y > p1.y) && (p0.y < p2.y)) || ((p0.y < p1.y) && (p0.y > p2.y)))
		return true;
	else
		return false;
}
/*
 * Judge whether tow lines intersect
 */
bool JudgeIntersection(const Line_t first, const Line_t second)
{
	bool ret = false;
	int32_t start2first = JudgeDirection(first.start, first.end, second.start);
	int32_t end2first = JudgeDirection(first.start, first.end, second.end);
	int32_t start2second = JudgeDirection(second.start, second.end, first.start);
	int32_t end2second = JudgeDirection(second.start, second.end, first.end);

	if(((start2first > 0 && end2first < 0) ||  (start2first < 0 && end2first > 0)) &&
				((start2second > 0 && end2second < 0) || (start2second < 0 && end2second > 0)))
		ret = true;
	else if((start2first == 0) && OnSegment(first.start, first.end, second.start))
		ret = true;
	else if((end2first == 0) && OnSegment(first.start, first.end, second.end))
		ret = true;
	else if((start2second == 0) && OnSegment(second.start, second.end, first.start))
		ret = true;
	else if((end2second == 0) && OnSegment(second.start, second.end, first.end))
		ret = true;

	return ret;
}

Point_t* ReadPointsData(const char* file_name, int32_t* size)
{
	int i, count;
	Point_t* points;
	freopen(file_name, "r", stdin);
	scanf("%d", size);
	count = *size;
	points = (Point_t*)malloc(count * sizeof(Point_t));
	for(i = 0; i < count; ++i)
	{
		scanf("%lf %lf", &(points[i].x), &(points[i].y));
	}
	return points;
}

int main()
{
	int32_t start;
	Point_t first, second;
	Line_t line1, line2;

	first.x = 1;
	first.y = 1;
	second.x = 3;
	second.y = 3;
	line1.start = first;
	line1.end = second;

	first.x = 1;
	first.y = 0;
	second.x = 1;
	second.y = 6;
	line2.start = first;
	line2.end = second;

	fprintf(stdout, "Line Ans: %d\n", JudgeIntersection(line1, line2));

	//Test Graham scan algorithm
	int size;
	Point_t* points;
	PointArray_t stack;

	const char* file_name = "points.data";
	points = ReadPointsData(file_name, &size);
	stack.size = 0;
	stack.points = (Point_t*)malloc(size*sizeof(Point_t));
	start = clock();
	GrahamScan(points, size, &stack);
	fprintf(stdout, "Time : %.3lf\n", double(clock()-start)/CLOCKS_PER_SEC);
	fprintf(stdout, "Convex Hull Size: %d \n", stack.size);
	free(points);
	free(stack.points);
	return 0;
}
<|endoftext|>


<commit_before>#pragma once
//=====================================================================//
/*! @file
    @brief  波形描画テンプレート・クラス
    @author 平松邦仁 (hira@rvf-rc45.net)
	@copyright	Copyright (C) 2017, 2018 Kunihito Hiramatsu @n
				Released under the MIT license @n
				https://github.com/hirakuni45/RX/blob/master/LICENSE
*/
//=====================================================================//
#include <vector>
#include "gl_fw/glutils.hpp"

namespace view {

	//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
	/*!
		@brief  render_waves template class
		@param[in]	UNIT	波形の型
		@param[in]	LIMIT	最大波形数
		@param[in]	CHN		チャネル数
	*/
	//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
	template <typename UNIT, uint32_t LIMIT, uint32_t CHN>
	class render_waves {
	public:
		//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
		/*!
			@brief  チャネル描画パラメーター
		*/
		//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
		struct chr_param {
			img::rgba8	color_;		///< 描画色
			int32_t		offset_;	///< 垂直オフセット（電圧）
			float		gain_;		///< 垂直ゲイン（電圧）

			bool		update_;	///< 描画の更新「true」

			chr_param() : color_(img::rgba8(255, 255)),
				offset_(0), gain_(1.0f), update_(false)
			{ }
		};

		//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
		/*!
			@brief  インフォメーション描画パラメーター
		*/
		//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
		class info_param {
		public:
			img::rgba8	grid_color_;	///< グリッド・カラー
			int32_t		grid_step_;		///< グリッド・ステップ
			uint16_t	grid_stipple_;	///< グリッド・破線パターン
			bool		grid_enable_;	///< グリッド有効

			img::rgba8	time_color_;	///< 時間軸カラー
			int32_t		time_org_;		///< 時間軸開始
			int32_t		time_len_;		///< 時間軸長さ
			uint16_t	time_stipple_;	///< 時間軸破線パターン
			bool		time_enable_;	///< 時間軸有効
//			bool		time_anime_;	///< 時間軸アニメーション

			img::rgba8	volt_color_;	///< 電圧軸カラー
			int32_t		volt_org_;		///< 電圧軸開始
			int32_t		volt_len_;		///< 電圧軸長さ
			uint16_t	volt_stipple_;	///< 電圧軸破線パターン
			bool		volt_enable_;	///< 電圧軸有効
//			bool		volt_anime_;	///< 電圧軸アニメーション

		private:
			vtx::sposs	grid_;
			vtx::sposs	time_;
			vtx::sposs	volt_;
			vtx::ipos	size_;

			uint32_t	count_;

			static void rotate_(uint16_t& bits) {
				auto mod = bits & 0x8000;
				bits <<= 1;
				if(mod) bits |= 1;
			}

		public:
			info_param() : grid_color_(img::rgba8(255, 255, 255, 96)), grid_step_(30),
				grid_stipple_(0b1111000011110000), grid_enable_(true),

				time_color_(img::rgba8(255, 255, 128, 192)),
				time_org_(0), time_len_(0),
				time_stipple_(0b1110110011101100), time_enable_(true),

				volt_color_(img::rgba8(128, 255, 128, 192)),
				volt_org_(0), volt_len_(0),
				volt_stipple_(0b1110110011101100), volt_enable_(true),
				grid_(), time_(), volt_(), size_(), count_(0)
			{ }

			void build(const vtx::ipos& size)
			{
				if(size == size_) return;
				size_ = size;

				grid_.clear();
				for(int h = 0; h < size.x; h += grid_step_) {  // |||
					grid_.push_back(vtx::spos(h, 0));
					grid_.push_back(vtx::spos(h, size.y));
				}
				for(int v = 0; v < size.y; v += grid_step_) {  // ---
					grid_.push_back(vtx::spos(0, v));
					grid_.push_back(vtx::spos(size.x, v));
				}

				time_.clear();
				time_.push_back(vtx::spos(0, 0));
				time_.push_back(vtx::spos(0, size.y));

				volt_.clear();
				volt_.push_back(vtx::spos(0, 0));
				volt_.push_back(vtx::spos(size.x, 0));
			}

			void render()
			{
				glEnable(GL_LINE_STIPPLE);
				if(!grid_.empty() && grid_enable_) {
					glLineStipple(1, grid_stipple_);
					gl::glColor(grid_color_);
					gl::draw_lines(grid_);
				}
				if(time_enable_) {
					glLineStipple(1, time_stipple_);
					glPushMatrix();
					gl::glTranslate(time_org_, 0);
					gl::glColor(time_color_);
					gl::draw_lines(time_);
					gl::glTranslate(time_len_, 0);
					gl::draw_lines(time_);
					glPopMatrix();
				}
				if(volt_enable_) {
					glLineStipple(1, volt_stipple_);
					glPushMatrix();
					gl::glTranslate(0, volt_org_);
					gl::glColor(volt_color_);
					gl::draw_lines(volt_);
					gl::glTranslate(0, volt_len_);
					gl::draw_lines(volt_);
					glPopMatrix();
				}
				if(count_ > 0) {
					--count_;
				} else {
					rotate_(time_stipple_);
					rotate_(volt_stipple_);
					count_ = 3;
				}
				glDisable(GL_LINE_STIPPLE);
			}
		};

	private:
		typedef std::vector<UNIT> UNITS;

		struct ch_t {
			chr_param	param_;
			uint32_t	tstep_;
			UNITS		units_;
			vtx::sposs	lines_;

			ch_t() : param_(), tstep_(0), units_(), lines_()
			{ }
		};

		info_param	info_;

		ch_t		ch_[CHN];
		double		div_;

		vtx::ipos	win_size_;

	public:
		//-----------------------------------------------------------------//
		/*!
			@brief  コンストラクター
		*/
		//-----------------------------------------------------------------//
		render_waves() : ch_{ }, div_(0.0), win_size_(0) { }

		//-----------------------------------------------------------------//
		/*!
			@brief  パラメーターを取得
			@param[in]	ch	チャネル
			@return パラメーター
		*/
		//-----------------------------------------------------------------//
		const chr_param& get_param(uint32_t ch) const
		{
			if(ch >= CHN) {
				static chr_param p;
				return p;
			}
			return ch_[ch].param_;
		}

		//-----------------------------------------------------------------//
		/*!
			@brief  パラメーターを参照
			@param[in]	ch	チャネル
			@return パラメーター
		*/
		//-----------------------------------------------------------------//
		chr_param& at_param(uint32_t ch)
		{
			if(ch >= CHN) {
				static chr_param p;
				return p;
			}
			return ch_[ch].param_;
		}

		//-----------------------------------------------------------------//
		/*!
			@brief  情報パラメーターを取得
			@return 情報パラメーター
		*/
		//-----------------------------------------------------------------//
		const info_param& get_info() const {
			return info_;
		}

		//-----------------------------------------------------------------//
		/*!
			@brief  情報パラメーターを参照
			@return 情報パラメーター
		*/
		//-----------------------------------------------------------------//
		info_param& at_info() {
			return info_;
		}

		//-----------------------------------------------------------------//
		/*!
			@brief  波形生成
			@param[in]	time	生成時間 [sec]
			@param[in]	div		分解能 [sec]
			@return 生成した数
		*/
		//-----------------------------------------------------------------//
		uint32_t create_buffer(double time, double div)
		{
			if(div <= 0.0 || time <= 0.0) return 0;

			auto n = time / div;

			if(n <= 0.0) return 0;
			else if(n > static_cast<double>(LIMIT)) return 0;

			for(int i = 0; i < CHN; ++i) {
				ch_[i].units_.resize(static_cast<uint32_t>(n));
			}
			div_ = div;  // 分解能

			return n;
		}

		//-----------------------------------------------------------------//
		/*!
			@brief  テスト波形生成
			@param[in]	frq		周波数 [Hz]
		*/
		//-----------------------------------------------------------------//
		void build_sin(double frq)
		{
#if 0
			for(uint32_t i = 0; i < units_.size(); ++i) {
//				double t = 1.0 / frq;
				double t = 1.0 / 1024.0;
				units_[i] = 32768 - static_cast<UNIT>(sin(2.0 * vtx::get_pi<double>() * t * i) * 32767.0);
			}
#endif
		}

		//-----------------------------------------------------------------//
		/*!
			@brief  波形コピー
			@param[in]	ch		チャネル
			@param[in]	src		波形ソース
			@param[in]	len		波形数
		*/
		//-----------------------------------------------------------------//
		void copy(uint32_t ch, const UNIT* src, uint32_t len)
		{
			if(len > ch_[ch].units_.size()) len = ch_[ch].units_.size();
			for(uint32_t i = 0; i < len; ++i) {
				ch_[ch].units_[i] = *src++;
			}
			ch_[ch].param_.update_ = true;
		}

		//-----------------------------------------------------------------//
		/*!
			@brief  レンダリング
   			@param[in]	size	描画サイズ（ピクセル）
			@param[in]	step	時間軸ステップ（65536を1.0）
		*/
		//-----------------------------------------------------------------//
		void render(const vtx::ipos& size, uint32_t tstep)
		{
			bool update_win = win_size_ != size;
			win_size_ = size;
			for(uint32_t n = 0; n < CHN; ++n) {
				ch_t& t = ch_[n];
				bool update = update_win;
				if(t.units_.empty()) update = false;
				else {
					if(t.lines_.size() != size.x) {
						t.lines_.resize(size.x);
					}
					if(t.tstep_ != tstep) {
						t.tstep_ = tstep;
						update = true;
					}
				}
				if(update || t.param_.update_) {
					float gain = t.param_.gain_;
					uint32_t ts = 0;
					for(uint32_t i = 0; i < size.x; ++i) {
						float v = static_cast<float>(t.units_[ts >> 16]);
						t.lines_[i] = vtx::spos(i, v * gain);
						ts += tstep;
					}
					t.param_.update_ = false;
				}
				if(!t.lines_.empty()) {
					glPushMatrix();
					gl::glTranslate(0, t.param_.offset_);
					gl::glColor(t.param_.color_);
					gl::draw_line_strip(t.lines_);
					glPopMatrix();
				}
			}

			info_.build(size);

			info_.render();
		}
	};
}
<commit_msg>update: time scale, time offset manage<commit_after>#pragma once
//=====================================================================//
/*! @file
    @brief  波形描画テンプレート・クラス
    @author 平松邦仁 (hira@rvf-rc45.net)
	@copyright	Copyright (C) 2017, 2018 Kunihito Hiramatsu @n
				Released under the MIT license @n
				https://github.com/hirakuni45/RX/blob/master/LICENSE
*/
//=====================================================================//
#include <vector>
#include "gl_fw/glutils.hpp"

namespace view {

	//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
	/*!
		@brief  render_waves template class
		@param[in]	UNIT	波形の型
		@param[in]	LIMIT	最大波形数
		@param[in]	CHN		チャネル数
	*/
	//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
	template <typename UNIT, uint32_t LIMIT, uint32_t CHN>
	class render_waves {
	public:
		//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
		/*!
			@brief  チャネル描画パラメーター
		*/
		//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
		struct chr_param {
			img::rgba8	color_;		///< 描画色
			vtx::ipos	offset_;	///< オフセット
			float		gain_;		///< 垂直ゲイン（電圧）

			bool		update_;	///< 描画の更新「true」

			chr_param() : color_(img::rgba8(255, 255)),
				offset_(0), gain_(1.0f), update_(false)
			{ }
		};

		//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
		/*!
			@brief  インフォメーション描画パラメーター
		*/
		//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
		class info_param {
		public:
			img::rgba8	grid_color_;	///< グリッド・カラー
			int32_t		grid_step_;		///< グリッド・ステップ
			uint16_t	grid_stipple_;	///< グリッド・破線パターン
			bool		grid_enable_;	///< グリッド有効

			img::rgba8	time_color_;	///< 時間軸カラー
			int32_t		time_org_;		///< 時間軸開始
			int32_t		time_len_;		///< 時間軸長さ
			uint16_t	time_stipple_;	///< 時間軸破線パターン
			bool		time_enable_;	///< 時間軸有効
//			bool		time_anime_;	///< 時間軸アニメーション

			img::rgba8	volt_color_;	///< 電圧軸カラー
			int32_t		volt_org_;		///< 電圧軸開始
			int32_t		volt_len_;		///< 電圧軸長さ
			uint16_t	volt_stipple_;	///< 電圧軸破線パターン
			bool		volt_enable_;	///< 電圧軸有効
//			bool		volt_anime_;	///< 電圧軸アニメーション

		private:
			vtx::sposs	grid_;
			vtx::sposs	time_;
			vtx::sposs	volt_;
			vtx::ipos	size_;

			uint32_t	count_;

			static void rotate_(uint16_t& bits) {
				auto mod = bits & 0x8000;
				bits <<= 1;
				if(mod) bits |= 1;
			}

		public:
			info_param() : grid_color_(img::rgba8(255, 255, 255, 96)), grid_step_(30),
				grid_stipple_(0b1111000011110000), grid_enable_(true),

				time_color_(img::rgba8(255, 255, 128, 192)),
				time_org_(0), time_len_(0),
				time_stipple_(0b1110110011101100), time_enable_(true),

				volt_color_(img::rgba8(128, 255, 128, 192)),
				volt_org_(0), volt_len_(0),
				volt_stipple_(0b1110110011101100), volt_enable_(true),
				grid_(), time_(), volt_(), size_(), count_(0)
			{ }

			void build(const vtx::ipos& size)
			{
				if(size == size_) return;
				size_ = size;

				grid_.clear();
				for(int h = 0; h < size.x; h += grid_step_) {  // |||
					grid_.push_back(vtx::spos(h, 0));
					grid_.push_back(vtx::spos(h, size.y));
				}
				for(int v = 0; v < size.y; v += grid_step_) {  // ---
					grid_.push_back(vtx::spos(0, v));
					grid_.push_back(vtx::spos(size.x, v));
				}

				time_.clear();
				time_.push_back(vtx::spos(0, 0));
				time_.push_back(vtx::spos(0, size.y));

				volt_.clear();
				volt_.push_back(vtx::spos(0, 0));
				volt_.push_back(vtx::spos(size.x, 0));
			}

			void render()
			{
				glEnable(GL_LINE_STIPPLE);
				if(!grid_.empty() && grid_enable_) {
					glLineStipple(1, grid_stipple_);
					gl::glColor(grid_color_);
					gl::draw_lines(grid_);
				}
				if(time_enable_) {
					glLineStipple(1, time_stipple_);
					glPushMatrix();
					gl::glTranslate(time_org_, 0);
					gl::glColor(time_color_);
					gl::draw_lines(time_);
					gl::glTranslate(time_len_, 0);
					gl::draw_lines(time_);
					glPopMatrix();
				}
				if(volt_enable_) {
					glLineStipple(1, volt_stipple_);
					glPushMatrix();
					gl::glTranslate(0, volt_org_);
					gl::glColor(volt_color_);
					gl::draw_lines(volt_);
					gl::glTranslate(0, volt_len_);
					gl::draw_lines(volt_);
					glPopMatrix();
				}
				if(count_ > 0) {
					--count_;
				} else {
					rotate_(time_stipple_);
					rotate_(volt_stipple_);
					count_ = 3;
				}
				glDisable(GL_LINE_STIPPLE);
			}
		};

	private:
		typedef std::vector<UNIT> UNITS;

		struct ch_t {
			chr_param	param_;
			uint32_t	tstep_;
			UNITS		units_;
			vtx::sposs	lines_;

			ch_t() : param_(), tstep_(0), units_(), lines_()
			{ }
		};

		info_param	info_;

		ch_t		ch_[CHN];
		double		div_;

		vtx::ipos	win_size_;

	public:
		//-----------------------------------------------------------------//
		/*!
			@brief  コンストラクター
		*/
		//-----------------------------------------------------------------//
		render_waves() : ch_{ }, div_(0.0), win_size_(0) { }

		//-----------------------------------------------------------------//
		/*!
			@brief  波形の最大数を取得
			@return 波形の最大数
		*/
		//-----------------------------------------------------------------//
		uint32_t size() const { return LIMIT; }

		//-----------------------------------------------------------------//
		/*!
			@brief  パラメーターを取得
			@param[in]	ch	チャネル
			@return パラメーター
		*/
		//-----------------------------------------------------------------//
		const chr_param& get_param(uint32_t ch) const
		{
			if(ch >= CHN) {
				static chr_param p;
				return p;
			}
			return ch_[ch].param_;
		}

		//-----------------------------------------------------------------//
		/*!
			@brief  パラメーターを参照
			@param[in]	ch	チャネル
			@return パラメーター
		*/
		//-----------------------------------------------------------------//
		chr_param& at_param(uint32_t ch)
		{
			if(ch >= CHN) {
				static chr_param p;
				return p;
			}
			return ch_[ch].param_;
		}

		//-----------------------------------------------------------------//
		/*!
			@brief  情報パラメーターを取得
			@return 情報パラメーター
		*/
		//-----------------------------------------------------------------//
		const info_param& get_info() const {
			return info_;
		}

		//-----------------------------------------------------------------//
		/*!
			@brief  情報パラメーターを参照
			@return 情報パラメーター
		*/
		//-----------------------------------------------------------------//
		info_param& at_info() {
			return info_;
		}

		//-----------------------------------------------------------------//
		/*!
			@brief  波形生成
		*/
		//-----------------------------------------------------------------//
		void create_buffer()
		{
			for(int i = 0; i < CHN; ++i) {
				ch_[i].units_.resize(size());
			}
		}

		//-----------------------------------------------------------------//
		/*!
			@brief  テスト波形生成
			@param[in]	frq		周波数 [Hz]
		*/
		//-----------------------------------------------------------------//
		void build_sin(double frq)
		{
#if 0
			for(uint32_t i = 0; i < units_.size(); ++i) {
//				double t = 1.0 / frq;
				double t = 1.0 / 1024.0;
				units_[i] = 32768 - static_cast<UNIT>(sin(2.0 * vtx::get_pi<double>() * t * i) * 32767.0);
			}
#endif
		}

		//-----------------------------------------------------------------//
		/*!
			@brief  波形コピー
			@param[in]	ch		チャネル
			@param[in]	src		波形ソース
			@param[in]	len		波形数
		*/
		//-----------------------------------------------------------------//
		void copy(uint32_t ch, const UNIT* src, uint32_t len)
		{
			if(len > ch_[ch].units_.size()) len = ch_[ch].units_.size();
			for(uint32_t i = 0; i < len; ++i) {
				ch_[ch].units_[i] = *src++;
			}
			ch_[ch].param_.update_ = true;
		}

		//-----------------------------------------------------------------//
		/*!
			@brief  レンダリング
   			@param[in]	size	描画サイズ（ピクセル）
			@param[in]	step	時間軸ステップ（65536を1.0）
		*/
		//-----------------------------------------------------------------//
		void render(const vtx::ipos& size, uint32_t tstep)
		{
			bool update_win = win_size_ != size;
			win_size_ = size;
			for(uint32_t n = 0; n < CHN; ++n) {
				ch_t& t = ch_[n];
				bool update = update_win;
				if(t.units_.empty()) update = false;
				else {
					if(t.lines_.size() != size.x) {
						t.lines_.resize(size.x);
					}
					if(t.tstep_ != tstep) {
						t.tstep_ = tstep;
						update = true;
					}
				}
				int mod_x = 0;
				if(update || t.param_.update_) {
					float gain = t.param_.gain_;
					uint32_t tsc = t.param_.offset_.x * tstep;
					for(uint32_t i = 0; i < size.x; ++i) {
						uint32_t idx = (tsc >> 16) % t.units_.size();
						float v = static_cast<float>(t.units_[idx]);
						t.lines_[i] = vtx::spos(i, v * gain);
						tsc += tstep;
					}
					t.param_.update_ = false;
				}
				if(!t.lines_.empty()) {
					glPushMatrix();
					gl::glTranslate(mod_x, t.param_.offset_.y);
					gl::glColor(t.param_.color_);
					gl::draw_line_strip(t.lines_);
					glPopMatrix();
				}
			}

			info_.build(size);

			info_.render();
		}
	};
}
<|endoftext|>


<commit_before>//===-- Specializer.cpp ------ Performs Generic Specialization ------------===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2015 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See http://swift.org/LICENSE.txt for license information
// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//

#define DEBUG_TYPE "specialization"

#include "swift/SILPasses/Utils/Generics.h"
#include "swift/SILPasses/Passes.h"

#include "swift/AST/ASTContext.h"

#include "swift/SIL/SILDebugScope.h"
#include "swift/SIL/SILFunction.h"
#include "swift/SIL/SILInstruction.h"
#include "swift/SIL/SILModule.h"
#include "swift/SILAnalysis/CallGraphAnalysis.h"
#include "swift/SILPasses/Utils/Local.h"
#include "swift/SILPasses/Transforms.h"
#include "llvm/ADT/MapVector.h"
#include "llvm/ADT/StringSet.h"
#include "llvm/ADT/SmallString.h"
using namespace swift;

namespace {
class SILGenericSpecializerTransform : public SILModuleTransform {
public:
  SILGenericSpecializerTransform() {}

  void run() override {
    CallGraphAnalysis* CGA = PM->getAnalysis<CallGraphAnalysis>();

    // Collect a call-graph bottom-up list of functions and specialize the
    // functions in reverse order.
    auto &CG = CGA->getCallGraph();
    auto GS = GenericSpecializer(getModule());

    // Try to specialize generic calls.
    bool Changed = GS.specialize(CG.getBottomUpFunctionOrder());

    if (Changed) {
      // Schedule another iteration of the transformation pipe.
      PM->scheduleAnotherIteration();

      // Invalidate the call graph.
      invalidateAnalysis(SILAnalysis::PreserveKind::Nothing);
    }
  }

  StringRef getName() override { return "Generic Specialization"; }
};
} // end anonymous namespace

SILTransform *swift::createGenericSpecializer() {
  return new SILGenericSpecializerTransform();
}
<commit_msg>Teach the generic specializer to report that it preserves branch information.<commit_after>//===-- Specializer.cpp ------ Performs Generic Specialization ------------===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2015 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See http://swift.org/LICENSE.txt for license information
// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//

#define DEBUG_TYPE "specialization"

#include "swift/SILPasses/Utils/Generics.h"
#include "swift/SILPasses/Passes.h"

#include "swift/AST/ASTContext.h"

#include "swift/SIL/SILDebugScope.h"
#include "swift/SIL/SILFunction.h"
#include "swift/SIL/SILInstruction.h"
#include "swift/SIL/SILModule.h"
#include "swift/SILAnalysis/CallGraphAnalysis.h"
#include "swift/SILPasses/Utils/Local.h"
#include "swift/SILPasses/Transforms.h"
#include "llvm/ADT/MapVector.h"
#include "llvm/ADT/StringSet.h"
#include "llvm/ADT/SmallString.h"
using namespace swift;

namespace {
class SILGenericSpecializerTransform : public SILModuleTransform {
public:
  SILGenericSpecializerTransform() {}

  void run() override {
    CallGraphAnalysis* CGA = PM->getAnalysis<CallGraphAnalysis>();

    // Collect a call-graph bottom-up list of functions and specialize the
    // functions in reverse order.
    auto &CG = CGA->getCallGraph();
    auto GS = GenericSpecializer(getModule());

    // Try to specialize generic calls.
    bool Changed = GS.specialize(CG.getBottomUpFunctionOrder());

    if (Changed) {
      // Schedule another iteration of the transformation pipe.
      PM->scheduleAnotherIteration();

      // We are creating new functions and modifying calls, but we are
      // preserving the branches in the existing functions.
      invalidateAnalysis(SILAnalysis::PreserveKind::Branches);
    }
  }

  StringRef getName() override { return "Generic Specialization"; }
};
} // end anonymous namespace

SILTransform *swift::createGenericSpecializer() {
  return new SILGenericSpecializerTransform();
}
<|endoftext|>