text:
/*
Copyright 2014 Sairam Gurajada

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

#include <processor/TriADProcessor.hpp>
#include <boost/dynamic_bitset.hpp>
using namespace std;
using namespace rg;
using namespace mpi2;

struct TriADMain {
	inline static string id() {
		return "_TRIAD_MAIN_";
	}

	inline static void run(Channel ch, TaskInfo info) {
		TaskManager& tm = TaskManager::getInstance();
		boost::mpi::communicator& world = tm.world();

		unsigned rank = world.rank();

		if(rank == 0)
			return;

		TriADProcessor *localProcessor = new TriADProcessor();
		vector<Channel> channels = info.pairwiseChannels();
		unsigned pbits; bool silent;
		ch.recv(pbits);
		ch.recv(silent);
		localProcessor->db->set_pbits(pbits);
		// % DEBUG
		// LOG4CXX_INFO(TriADProcessor::logger, "pbits: " << pbits << " at rank " << rank);

		//Build per node triple index
		if(world.rank() != 0)
			localProcessor->buildPerNodeDatabase(ch);

		//Listen and process queries
		bool nextQuery = false;
		vector<unsigned> results;
		unsigned numVars;
		while (true) {
			ch.recv(nextQuery);
			if (!nextQuery) {
				break;
			}

			//results = 0;
			localProcessor->executePerNodeQuery(ch,channels,results,numVars);

			// Send "finish" to master
			ch.send(true);

			// Send "results"
			if(!silent){
				std::cout << "Results: " << results.size() << " width " << numVars << endl;
				ch.send(numVars);
				ch.send(results);
			}

		}
		return;

	} // END of RUN
};

int main(int argc, char* argv[]){

	// initialize mpi2
		boost::mpi::communicator& world = mpi2init(argc, argv);

	// environment variable
		Env & env = mpi2::env();

	// initialize the channels needed for communication with the nodes
		CHANNEL channels;

	// register AddTask (this is required to be able to actually run it!)
		TaskManager& tm = TaskManager::getInstance();

	registerTask<TriADMain>();

	// fire up task managers (this blocks on all but the root node)

		mpi2start();
		boost::this_thread::sleep(boost::posix_time::milliseconds(100)); // just to ensure output in right order

	if (world.rank() == 0) {

		if (argc < 2) {
			LOG4CXX_ERROR(TriADProcessor::logger,
                                        "Usage Basic Mode..... " << argv[0] << " [location of folder containing .n3/.nt files]");
			LOG4CXX_ERROR(TriADProcessor::logger,
					"Usage Summary Mode..... " << argv[0] << " [location of folder containing .n3/.nt files] [.part.* file] [.g_dict file]");
		} else {

			// start the task managers on the nodes
			tm.spawnAll<TriADMain>(1, channels, true);

			//LOG4CXX_DEBUG(TriADProcessor::logger, "Test..");

			TriADProcessor *masterProcessor = new TriADProcessor();

			masterProcessor->parseArgument(argc, argv);

			masterProcessor->startIndexTask(channels);

			masterProcessor->startQueryTask(channels);
		}
	}

	// shut down task managers
		mpi2stop();

	// shut down mpi2 and mpi
		mpi2finalize();

	return 1;

}

max_issues_repo_name: sairamgv/triad-rdf


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

#include "json_printer.hpp"

#include "composition.hpp"
#include "device.hpp"
#include "sensor_configuration.hpp"
#include "version.h"

#include <dlib/sockets.h>

#include <nlohmann/json.hpp>

#include <cstdlib>
#include <set>
#include <sstream>

using namespace std;
using json = nlohmann::json;

namespace mtconnect
{
  JsonPrinter::JsonPrinter(const string version, bool pretty)
      : Printer(pretty), m_schemaVersion(version)
  {
    char appVersion[32] = {0};
    std::sprintf(appVersion, "%d.%d.%d.%d", AGENT_VERSION_MAJOR, AGENT_VERSION_MINOR,
                 AGENT_VERSION_PATCH, AGENT_VERSION_BUILD);
    m_version = appVersion;
  }

  static inline std::string ltrim(std::string s)
  {
    s.erase(s.begin(), std::find_if(s.begin(), s.end(), [](int ch) { return !std::isspace(ch); }));
    return s;
  }

  // trim from end (in place)
  static inline std::string rtrim(std::string s)
  {
    s.erase(std::find_if(s.rbegin(), s.rend(), [](int ch) { return !std::isspace(ch); }).base(),
            s.end());
    return s;
  }

  // trim from both ends (in place)
  static inline std::string trim(std::string s)
  {
    return rtrim(ltrim(s));
  }

  const string &JsonPrinter::hostname() const
  {
    if (m_hostname.empty())
    {
      string name;
      if (dlib::get_local_hostname(name))
        name = "localhost";
      // Breaking the rules, this is a one off
      const_cast<JsonPrinter *>(this)->m_hostname = name;
    }

    return m_hostname;
  }

  inline std::string print(json &doc, bool pretty)
  {
    stringstream buffer;
    if (pretty)
      buffer << std::setw(2);
    buffer << doc;
    if (pretty)
      buffer << "\n";
    return buffer.str();
  }

  static inline void addAttributes(json &doc, const map<string, string> &attrs)
  {
    for (const auto &attr : attrs)
      doc[attr.first] = attr.second;
  }

  static inline void add(json &doc, const char *key, const string &value)
  {
    if (!value.empty())
      doc[key] = value;
  }

  static inline void addDouble(json &doc, const char *key, const string &value)
  {
    if (!value.empty())
      doc[key] = atof(value.c_str());
  }

  static inline void addText(json &doc, const std::string &text)
  {
    add(doc, "text", trim(text));
  }

  inline json header(const string &version, const string &hostname, const unsigned int instanceId,
                     const unsigned int bufferSize, const string &schemaVersion)
  {
    json doc = json::object({{"version", version},
                             {"creationTime", getCurrentTime(GMT)},
                             {"testIndicator", false},
                             {"instanceId", instanceId},
                             {"sender", hostname},
                             {"schemaVersion", schemaVersion}});
    if (bufferSize > 0)
      doc["bufferSize"] = bufferSize;
    return doc;
  }

  inline json probeAssetHeader(const string &version, const string &hostname,
                               const unsigned int instanceId, const unsigned int bufferSize,
                               const unsigned int assetBufferSize, const unsigned int assetCount,
                               const string &schemaVersion)
  {
    json doc = header(version, hostname, instanceId, bufferSize, schemaVersion);
    doc["assetBufferSize"] = assetBufferSize;
    doc["assetCount"] = assetCount;

    return doc;
  }

  inline json streamHeader(const string &version, const string &hostname,
                           const unsigned int instanceId, const unsigned int bufferSize,
                           const uint64_t nextSequence, const uint64_t firstSequence,
                           const uint64_t lastSequence, const string &schemaVersion)
  {
    json doc = header(version, hostname, instanceId, bufferSize, schemaVersion);
    doc["nextSequence"] = nextSequence;
    doc["lastSequence"] = lastSequence;
    doc["firstSequence"] = firstSequence;
    return doc;
  }

  std::string JsonPrinter::printError(const unsigned int instanceId, const unsigned int bufferSize,
                                      const uint64_t nextSeq, const std::string &errorCode,
                                      const std::string &errorText) const
  {
    json doc = json::object(
        {{"MTConnectError",
          {{"Header", header(m_version, hostname(), instanceId, bufferSize, m_schemaVersion)},
           {"Errors", {{"Error", {{"errorCode", errorCode}, {"text", trim(errorText)}}}}}}}});

    return print(doc, m_pretty);
  }

  static inline json toJson(DataItem *item)
  {
    json obj = json::object();
    addAttributes(obj, item->getAttributes());

    // Data Item Source
    json source = json::object();
    addText(source, item->getSource());
    add(source, "dataItemId", item->getSourceDataItemId());
    add(source, "componentId", item->getSourceComponentId());
    add(source, "compositionId", item->getSourceCompositionId());

    if (source.begin() != source.end())
      obj["Source"] = source;

    // Data Item Constraints
    if (item->hasConstraints())
    {
      json constraints = json::object();
      addDouble(constraints, "Maximum", item->getMaximum());
      addDouble(constraints, "Minimum", item->getMinimum());

      if (!item->getConstrainedValues().empty())
      {
        json values(item->getConstrainedValues());
        constraints["value"] = values;
      }

      obj["Constraints"] = constraints;
    }

    if (item->hasMinimumDelta() or item->hasMinimumPeriod())
    {
      json filters = json::array();
      if (item->hasMinimumDelta())
        filters.emplace_back(json::object(
            {{"Filter", {{"value", item->getFilterValue()}, {"type", "MINIMUM_DELTA"}}}}));
      if (item->hasMinimumPeriod())
        filters.emplace_back(
            json::object({{"Filter", {{"value", item->getFilterPeriod()}, {"type", "PERIOD"}}}}));
      obj["Filters"] = filters;
    }

    if (item->hasInitialValue())
    {
      char *ep;
      obj["InitialValue"] = strtod(item->getInitialValue().c_str(), &ep);
    }

    json dataItem = json::object({{"DataItem", obj}});

    return dataItem;
  }

  static inline json toJson(Composition *composition)
  {
    json obj = json::object();

    addAttributes(obj, composition->getAttributes());
    if (composition->getDescription() != nullptr)
    {
      json desc = json::object();
      addAttributes(desc, composition->getDescription()->getAttributes());
      addText(desc, composition->getDescription()->getBody());
      obj["Description"] = desc;
    }

    json comp = json::object({{"Composition", obj}});

    return comp;
  }

  static inline json jsonReference(const Component::Reference &reference)
  {
    json ref = json::object({{"idRef", reference.m_id}});
    add(ref, "name", reference.m_name);
    return ref;
  }

  static inline json toJson(const Component::Reference &reference)
  {
    json obj;
    if (reference.m_type == reference.DATA_ITEM)
      obj["DataItemRef"] = jsonReference(reference);
    else if (reference.m_type == reference.COMPONENT)
      obj["ComponentRef"] = jsonReference(reference);

    return obj;
  }

  template <class T>
  inline void toJson(json &parent, const string &collection, T &list)
  {
    json obj;
    if (!list.empty())
    {
      json items = json::array();
      for (auto &item : list)
        items.emplace_back(toJson(item));

      parent[collection] = items;
    }
  }

  inline void toJson(json &parent, const SensorConfiguration::Calibration &cal)
  {
    if (!cal.m_date.empty())
      parent["CalibrationDate"] = cal.m_date;
    if (!cal.m_nextDate.empty())
      parent["NextCalibrationDate"] = cal.m_nextDate;
    if (!cal.m_initials.empty())
      parent["CalibrationInitials"] = cal.m_initials;
  }

  inline void toJson(json &parent, const ComponentConfiguration *config)
  {
    if (typeid(*config) == typeid(SensorConfiguration))
    {
      auto obj = static_cast<const SensorConfiguration *>(config);
      json sensor = json::object();
      if (!obj->getFirmwareVersion().empty())
        sensor["FirmwareVersion"] = obj->getFirmwareVersion();
      auto &cal = obj->getCalibration();
      toJson(sensor, cal);

      if (!obj->getChannels().empty())
      {
        json channels = json::array();

        for (auto &channel : obj->getChannels())
        {
          json chan = json::object();
          addAttributes(chan, channel.getAttributes());

          if (!channel.getDescription().empty())
            chan["Description"] = channel.getDescription();

          auto &cal = channel.getCalibration();
          toJson(chan, cal);

          json chanObj = json::object({{"Channel", chan}});
          channels.emplace_back(chanObj);
        }

        sensor["Channels"] = channels;
      }
      parent["Configuration"] = json::object({{"SensorConfiguration", sensor}});
    }
    else if (typeid(*config) == typeid(ExtendedComponentConfiguration))
    {
      auto obj = static_cast<const ExtendedComponentConfiguration *>(config);
      parent["Configuration"] = obj->getContent();
    }
  }

  static json toJson(Component *component)
  {
    json desc = json::object();
    addAttributes(desc, component->getDescription());
    addText(desc, component->getDescriptionBody());

    json comp = json::object();
    addAttributes(comp, component->getAttributes());

    if (desc.begin() != desc.end())
      comp["Description"] = desc;

    if (component->getConfiguration())
      toJson(comp, component->getConfiguration());
    toJson(comp, "DataItems", component->getDataItems());
    toJson(comp, "Components", component->getChildren());
    toJson(comp, "Compositions", component->getCompositions());
    toJson(comp, "References", component->getReferences());

    json doc = json::object({{component->getClass(), comp}});

    return doc;
  }

  std::string JsonPrinter::printProbe(const unsigned int instanceId, const unsigned int bufferSize,
                                      const uint64_t nextSeq, const unsigned int assetBufferSize,
                                      const unsigned int assetCount,
                                      const std::vector<Device *> &devices,
                                      const std::map<std::string, int> *count) const
  {
    json devicesDoc = json::array();
    for (const auto device : devices)
      devicesDoc.emplace_back(toJson(device));

    json doc =
        json::object({{"MTConnectDevices",
                       {{"Header", probeAssetHeader(m_version, hostname(), instanceId, bufferSize,
                                                    assetBufferSize, assetCount, m_schemaVersion)},
                        {"Devices", devicesDoc}}}});

    return print(doc, m_pretty);
  }

  inline json toJson(const ObservationPtr &observation)
  {
    auto dataItem = observation->getDataItem();
    string name;

    if (dataItem->isCondition())
    {
      name = observation->getLevelString();
    }
    else
    {
      if (!dataItem->getPrefix().empty())
      {
        name = dataItem->getPrefixedElementName();
      }

      if (name.empty())
        name = dataItem->getElementName();
    }

    json value;

    if (observation->isTimeSeries() && observation->getValue() != "UNAVAILABLE")
    {
      ostringstream ostr;
      ostr.precision(6);
      const auto &v = observation->getTimeSeries();

      value = json::array();

      for (auto &e : v)
        value.emplace_back(e);
    }
    else if (observation->isDataSet() && observation->getValue() != "UNAVAILABLE")
    {
      value = json::object();

      const DataSet &set = observation->getDataSet();
      for (auto &e : set)
      {
        if (e.m_removed)
        {
          value[e.m_key] = json::object({{"removed", true}});
        }
        else
        {
          value[e.m_key] = e.m_value;
        }
      }
    }
    else if (!observation->getValue().empty())
    {
      if (dataItem->getCategory() == DataItem::SAMPLE)
      {
        if (dataItem->is3D())
        {
          value = json::array();
          stringstream s(observation->getValue());
          int i;
          for (i = 0; s && i < 3; i++)
          {
            double v;
            s >> v;
            value.emplace_back(v);
          }
          if (i < 3)
          {
            for (; i < 3; i++)
              value.emplace_back(0.0);
          }
        }
        else
        {
          char *ep;
          value = strtod(observation->getValue().c_str(), &ep);
        }
      }
      else
      {
        value = observation->getValue();
      }
    }

    json obj = json::object();
    for (const auto &attr : observation->getAttributes())
    {
      if (strcmp(attr.first, "sequence") == 0)
      {
        obj["sequence"] = observation->getSequence();
      }
      else if (strcmp(attr.first, "sampleCount") == 0 or strcmp(attr.first, "sampleRate") == 0 or
               strcmp(attr.first, "duration") == 0)
      {
        char *ep;
        obj[attr.first] = strtod(attr.second.c_str(), &ep);
      }
      else
      {
        obj[attr.first] = attr.second;
      }
    }
    obj["value"] = value;

    return json::object({{name, obj}});
  }

  class CategoryRef
  {
   public:
    CategoryRef(const char *cat) : m_category(cat)
    {
    }
    CategoryRef(const CategoryRef &other) : m_category(other.m_category), m_events(other.m_events)
    {
    }

    bool addObservation(const ObservationPtr &observation)
    {
      m_events.emplace_back(observation);
      return true;
    }

    bool isCategory(const char *cat)
    {
      return m_category == cat;
    }

    pair<string, json> toJson()
    {
      pair<string, json> ret;
      if (!m_category.empty())
      {
        json items = json::array();
        for (auto &event : m_events)
          items.emplace_back(::mtconnect::toJson(event));

        ret = make_pair(m_category, items);
      }
      return ret;
    }

   protected:
    string m_category;
    vector<ObservationPtr> m_events;
  };

  class ComponentRef
  {
   public:
    ComponentRef(const Component *component) : m_component(component), m_categoryRef(nullptr)
    {
    }
    ComponentRef(const ComponentRef &other)
        : m_component(other.m_component), m_categories(other.m_categories), m_categoryRef(nullptr)
    {
    }

    bool isComponent(const Component *component)
    {
      return m_component == component;
    }

    bool addObservation(const ObservationPtr &observation, const Component *component,
                        const DataItem *dataItem)
    {
      if (m_component == component)
      {
        auto cat = dataItem->getCategoryText();
        if (m_categoryRef == nullptr || !m_categoryRef->isCategory(cat))
        {
          m_categories.emplace_back(cat);
          m_categoryRef = &m_categories.back();
        }

        if (m_categoryRef != nullptr)
          return m_categoryRef->addObservation(observation);
      }
      return false;
    }

    json toJson()
    {
      json ret;
      if (m_component != nullptr && !m_categories.empty())
      {
        json obj = json::object(
            {{"component", m_component->getClass()}, {"componentId", m_component->getId()}});

        if (!m_component->getName().empty())
          obj["name"] = m_component->getName();

        for (auto &cat : m_categories)
        {
          auto c = cat.toJson();
          if (!c.first.empty())
            obj[c.first] = c.second;
        }

        ret = json::object({{"ComponentStream", obj}});
      }
      return ret;
    }

   protected:
    const Component *m_component;
    vector<CategoryRef> m_categories;
    CategoryRef *m_categoryRef;
  };

  class DeviceRef
  {
   public:
    DeviceRef(const Device *device) : m_device(device), m_componentRef(nullptr)
    {
    }
    DeviceRef(const DeviceRef &other) : m_device(other.m_device), m_components(other.m_components)
    {
    }

    bool isDevice(const Device *device)
    {
      return device == m_device;
    }

    bool addObservation(const ObservationPtr &observation, const Device *device,
                        const Component *component, const DataItem *dataItem)
    {
      if (m_device == device)
      {
        if (m_componentRef == nullptr || !m_componentRef->isComponent(component))
        {
          m_components.emplace_back(component);
          m_componentRef = &m_components.back();
        }

        if (m_componentRef != nullptr)
          return m_componentRef->addObservation(observation, component, dataItem);
      }
      return false;
    }

    json toJson()
    {
      json ret;
      if (m_device != nullptr && !m_components.empty())
      {
        json obj = json::object({{"name", m_device->getName()}, {"uuid", m_device->getUuid()}});
        json items = json::array();
        for (auto &comp : m_components)
          items.emplace_back(comp.toJson());
        obj["ComponentStreams"] = items;
        ret = json::object({{"DeviceStream", obj}});
      }
      return ret;
    }

   protected:
    const Device *m_device;
    vector<ComponentRef> m_components;
    ComponentRef *m_componentRef;
  };

  std::string JsonPrinter::printSample(const unsigned int instanceId, const unsigned int bufferSize,
                                       const uint64_t nextSeq, const uint64_t firstSeq,
                                       const uint64_t lastSeq,
                                       ObservationPtrArray &observations) const
  {
    json streams = json::array();

    if (observations.size() > 0)
    {
      dlib::qsort_array<ObservationPtrArray, ObservationComparer>(
          observations, 0ul, observations.size() - 1ul, ObservationCompare);

      vector<DeviceRef> devices;
      DeviceRef *deviceRef = nullptr;

      for (auto &observation : observations)
      {
        const auto dataItem = observation->getDataItem();
        const auto component = dataItem->getComponent();
        const auto device = component->getDevice();

        if (deviceRef == nullptr || !deviceRef->isDevice(device))
        {
          devices.emplace_back(device);
          deviceRef = &devices.back();
        }

        deviceRef->addObservation(observation, device, component, dataItem);
      }

      for (auto &ref : devices)
        streams.emplace_back(ref.toJson());
    }

    json doc =
        json::object({{"MTConnectStreams",
                       {{"Header", streamHeader(m_version, hostname(), instanceId, bufferSize,
                                                nextSeq, firstSeq, lastSeq, m_schemaVersion)},
                        {"Streams", streams}}}});

    return print(doc, m_pretty);

    return print(doc, m_pretty);
  }

  inline static json split(const string &v, const char s = ',')
  {
    json array = json::array();
    stringstream ss(v);
    while (ss.good())
    {
      string ele;
      getline(ss, ele, s);
      if (!ele.empty())
        array.emplace_back(ele);
    }

    return array;
  }

  inline static void addIdentity(json &obj, Asset *asset)
  {
    auto &identity = asset->getIdentity();
    for (auto &key : identity)
    {
      obj[key.first] = key.second;
    }
  }

  inline static void addCuttingToolIdentity(json &obj, const AssetKeys &identity)
  {
    for (auto &key : identity)
    {
      if (key.first == "manufacturers")
      {
        obj["manufacturers"] = split(key.second);
      }
      else
        obj[key.first] = key.second;
    }
  }

  static set<string> IntegerKeys = {"negativeOverlap", "positiveOverlap",  "Location",
                                    "maximumCount",    "ReconditionCount", "significantDigits",
                                    "ToolLife"};

  static set<string> DoubleKeys = {
      "maximum", "minimum", "nominal", "ProcessSpindleSpeed", "ProcessFeedRate", "Measurement"};

  inline static void addValue(json &obj, const string &key, const string &value, bool attr)
  {
    string name = attr ? key : "value";
    if (IntegerKeys.count(key) > 0)
      obj[name] = atoi(value.c_str());
    else if (DoubleKeys.count(key) > 0)
    {
      char *ep;
      obj[name] = strtod(value.c_str(), &ep);
    }
    else
    {
      obj[name] = value;
    }
  }

  inline static json toJson(CuttingToolValuePtr &value, const std::string &kind = "")
  {
    json obj = json::object();
    string type = kind.empty() ? value->m_key : kind;
    for (auto &p : value->m_properties)
      addValue(obj, p.first, p.second, true);
    if (!value->m_value.empty())
      addValue(obj, type, value->m_value, false);
    return obj;
  }

  inline static json toJson(CuttingItemPtr &item)
  {
    json obj = json::object();

    addCuttingToolIdentity(obj, item->m_identity);

    for (auto &prop : item->m_values)
      obj[prop.first] = toJson(prop.second);

    if (!item->m_lives.empty())
    {
      json lives = json::array();
      for (auto &s : item->m_lives)
      {
        lives.emplace_back(toJson(s));
      }
      obj["ItemLife"] = lives;
    }

    if (!item->m_measurements.empty())
    {
      json measurements = json::array();
      for (auto &m : item->m_measurements)
      {
        measurements.emplace_back(json::object({{m.first, toJson(m.second, "Measurement")}}));
      }

      obj["Measurements"] = measurements;
    }

    return json::object({{"CuttingItem", obj}});
  }

  inline static json toJson(CuttingTool *tool)
  {
    json obj = json::object();
    if (!tool->m_status.empty())
    {
      json status = json::array();
      for (auto &s : tool->m_status)
        status.emplace_back(s);
      obj["CutterStatus"] = status;
    }

    if (!tool->m_lives.empty())
    {
      json lives = json::array();
      for (auto &s : tool->m_lives)
      {
        lives.emplace_back(toJson(s));
      }
      obj["ToolLife"] = lives;
    }

    for (auto &prop : tool->m_values)
    {
      if (prop.first != "CuttingToolDefinition")
        obj[prop.first] = toJson(prop.second);
    }

    if (!tool->m_measurements.empty())
    {
      json measurements = json::array();
      for (auto &m : tool->m_measurements)
      {
        measurements.emplace_back(json::object({{m.first, toJson(m.second, "Measurement")}}));
      }

      obj["Measurements"] = measurements;
    }

    if (!tool->m_items.empty())
    {
      json items = json::array();
      for (auto &item : tool->m_items)
        items.emplace_back(toJson(item));

      obj["CuttingItems"] = items;
    }

    return obj;
  }

  inline static json toJson(AssetPtr asset)
  {
    json obj =
        json::object({{"assetId", asset->getAssetId()}, {"timestamp", asset->getTimestamp()}});

    if (!asset->getDeviceUuid().empty())
      obj["deviceUuid"] = asset->getDeviceUuid();

    if (asset->getType() == "CuttingTool" || asset->getType() == "CuttingToolArchetype")
    {
      CuttingTool *tool = dynamic_cast<CuttingTool *>(asset.getObject());
      addCuttingToolIdentity(obj, tool->getIdentity());
      obj["Description"] = tool->getDescription();

      if (tool->m_values.count("CuttingToolDefinition") > 0)
      {
        auto &def = tool->m_values["CuttingToolDefinition"];
        obj["CuttingToolDefinition"] =
            json::object({{"format", def->m_properties["format"]}, {"text", def->m_value}});
      }
      auto life = toJson(tool);
      if (!life.empty())
        obj["CuttingToolLifeCycle"] = toJson(tool);
    }
    else
    {
      addIdentity(obj, asset.getObject());
      obj["text"] = asset->getContent(nullptr);
    }

    json doc = json::object({{asset->getType(), obj}});

    return doc;
  }

  std::string JsonPrinter::printAssets(const unsigned int instanceId, const unsigned int bufferSize,
                                       const unsigned int assetCount,
                                       std::vector<AssetPtr> const &assets) const
  {
    json assetDoc = json::array();
    for (const auto asset : assets)
      assetDoc.emplace_back(toJson(asset));

    json doc =
        json::object({{"MTConnectAssets",
                       {{"Header", probeAssetHeader(m_version, hostname(), instanceId, 0,
                                                    bufferSize, assetCount, m_schemaVersion)},
                        {"Assets", assetDoc}}}});

    return print(doc, m_pretty);
  }

  std::string JsonPrinter::printCuttingTool(CuttingToolPtr const tool) const
  {
    AssetPtr asset(tool);
    return toJson(asset);
  }
}  // namespace mtconnect

ext: cpp

max_stars_repo_name: gsbecerrag/cppagent

max_issues_repo_name: gsbecerrag/cppagent

max_forks_repo_name: gsbecerrag/cppagent


text:
//
// Copyright (c) 2012 Juan Palacios juan.palacios.puyana@gmail.com
// This file is part of minimathlibs.
// Subject to the BSD 2-Clause License
// - see < http://opensource.org/licenses/BSD-2-Clause>
//
#define BOOST_TEST_DYN_LINK
#define BOOST_TEST_MODULE TestRotation3DZYX
#include <boost/test/unit_test.hpp>
#include <iostream>
#include <cmath>
#include "minimath/rotation3d.hpp"
#include "minimath/point3d.hpp"
#include "Defines.h"
#include "TestRotation3DUtils.h"

using namespace minimath;

BOOST_AUTO_TEST_SUITE(TestRotation3DZYX)

namespace
{

//
// Check that a RotationZYX defined by angles phi, theta, psi has the same
// effect on a point as individual Z, Y and X rotations.
//
bool testRotationZYX(const minimath::pointxyzd& point,
                     double phi,
                     double theta,
                     double psi)
{
  rotation3dzyx<double> rot1(phi, theta, psi);
  pointxyzd ref = rotation3dx<double>(psi) *
      ( rotation3dy<double>(theta) * (rotation3dz<double>(phi)*point) );
  return rot1*point == ref;
}

} // namespace

BOOST_AUTO_TEST_CASE(testInstantiation)
{
  rotation3dzyx<double> rot1, rot2;
}

BOOST_AUTO_TEST_CASE(testDefaultEquality)
{
  BOOST_CHECK(rotation3dzyx<double>() == rotation3dzyx<double>());
}

BOOST_AUTO_TEST_CASE(testCopyConstruction)
{
  rotation3dzyx<double> rot1;
  rotation3dzyx<double> rot2(rot1);
  BOOST_CHECK(rot1 == rot2);
}

BOOST_AUTO_TEST_CASE(testAssignment)
{
  rotation3dzyx<double> rot1, rot2;
  rot2 = rot1;
  BOOST_CHECK(rot1 == rot2);
}

BOOST_AUTO_TEST_CASE(testNullRotation)
{
  rotation3dzyx<double> rot;
  pointxyzd pTest = rot*p100;
  BOOST_CHECK(pTest == pointxyzd(1., 0., 0.));

  pTest = rot*p010;
  BOOST_CHECK(pTest == pointxyzd(0., 1., 0.));

  pTest = rot*p001;
  BOOST_CHECK(pTest == pointxyzd(0., 0., 1.));
}

BOOST_AUTO_TEST_CASE(testRotatePoint45X)
{
  rotation3dzyx<double> rot(0, 0, PI/4.); // 45 degree rotation about X
  pointxyzd pTest = rot*p100;
  BOOST_CHECK(pTest == pointxyzd(1., 0., 0.));

  pTest = rot*p010;
  BOOST_CHECK(pTest == pointxyzd(0., cos45, cos45));

  pTest = rot*p001;
  BOOST_CHECK(pTest == pointxyzd(0., -cos45, cos45));
}

BOOST_AUTO_TEST_CASE(testRotatePoint90X)
{
  rotation3dzyx<double> rot(0, 0, PI/2.); // 90 degree rotation about X
  pointxyzd pTest = rot*p100;
  BOOST_CHECK(pTest == pointxyzd(1., 0., 0.));

  pTest = rot*p010;
  BOOST_CHECK(pTest == pointxyzd(0., 0., 1.));

  pTest = rot*p001;
  BOOST_CHECK(pTest == pointxyzd(0., -1., 0.));
}

BOOST_AUTO_TEST_CASE(testRotatePoint180X)
{
  rotation3dzyx<double> rot(0, 0, PI); // 180 degree rotation about X

  pointxyzd pTest = rot*p100;
  BOOST_CHECK(pTest == pointxyzd(1., 0., 0.));

  pTest = rot*p010;
  BOOST_CHECK(pTest == pointxyzd(0., -1., 0.));

  pTest = rot*p001;
  BOOST_CHECK(pTest == pointxyzd(0., 0., -1.));
}

BOOST_AUTO_TEST_CASE(testRotatePoint45Y)
{
  rotation3dzyx<double> rot(0, PI/4., 0); // 45 degree rotation about X
  pointxyzd pTest = rot*p100;
  BOOST_CHECK(pTest == pointxyzd(cos45, 0., -cos45));

  pTest = rot*p010;
  BOOST_CHECK(pTest == pointxyzd(0., 1., 0));

  pTest = rot*p001;
  BOOST_CHECK(pTest == pointxyzd(cos45, 0, cos45));
}

BOOST_AUTO_TEST_CASE(testRotatePoint90Y)
{
  rotation3dzyx<double> rot(0, PI/2., 0); // 90 degree rotation about X
  pointxyzd pTest = rot*p100;
  BOOST_CHECK(pTest == pointxyzd(0., 0., -1.));

  pTest = rot*p010;
  BOOST_CHECK(pTest == pointxyzd(0., 1., 0.));

  pTest = rot*p001;
  BOOST_CHECK(pTest == pointxyzd(1., 0., 0.));
}

BOOST_AUTO_TEST_CASE(testRotatePoint180Y)
{
  rotation3dzyx<double> rot(0, PI, 0); // 180 degree rotation about X

  pointxyzd pTest = rot*p100;
  BOOST_CHECK(pTest == pointxyzd(-1., 0., 0.));

  pTest = rot*p010;
  BOOST_CHECK(pTest == pointxyzd(0., 1., 0.));

  pTest = rot*p001;
  BOOST_CHECK(pTest == pointxyzd(0., 0., -1.));
}

BOOST_AUTO_TEST_CASE(testRotatePoint45Z)
{
  rotation3dzyx<double> rot(PI/4., 0, 0); // 45 degree rotation about Z
  pointxyzd pTest = rot*p100;
  BOOST_CHECK(pTest == pointxyzd(cos45, cos45, 0.));

  pTest = rot*p010;
  BOOST_CHECK(pTest == pointxyzd(-cos45, cos45, 0));

  pTest = rot*p001;
  BOOST_CHECK(pTest == pointxyzd(0, 0, 1));
}

BOOST_AUTO_TEST_CASE(testRotatePoint90Z)
{
  rotation3dzyx<double> rot(PI/2., 0, 0); // 90 degree rotation about Z
  pointxyzd pTest = rot*p100;
  BOOST_CHECK(pTest == pointxyzd(0., 1., 0.));

  pTest = rot*p010;
  BOOST_CHECK(pTest == pointxyzd(-1., 0., 0.));

  pTest = rot*p001;
  BOOST_CHECK(pTest == pointxyzd(0., 0., 1.));
}

BOOST_AUTO_TEST_CASE(testRotatePoint180Z)
{
  rotation3dzyx<double> rot(PI, 0, 0); // 180 degree rotation about Z

  pointxyzd pTest = rot*p100;
  BOOST_CHECK(pTest == pointxyzd(-1., 0., 0.));

  pTest = rot*p010;
  BOOST_CHECK(pTest == pointxyzd(0., -1., 0.));

  pTest = rot*p001;
  BOOST_CHECK(pTest == pointxyzd(0., 0., 1.));
}

BOOST_AUTO_TEST_CASE(testAssignRotation3DX)
{
  for (int i = 1; i < 9; ++i) {
    BOOST_CHECK(rotation3dzyx<double>(0, 0, PI/i) == rotation3dx<double>(PI/i));
  }
}

BOOST_AUTO_TEST_CASE(testAssignRotation3DY)
{
  for (int i = 1; i < 9; ++i) {
    BOOST_CHECK(rotation3dzyx<double>(0, PI/i, 0) == rotation3dy<double>(PI/i));
  }
}

BOOST_AUTO_TEST_CASE(testAssignRotation3DZ)
{
  for (int i = 1; i < 9; ++i) {
    BOOST_CHECK(rotation3dzyx<double>(PI/i, 0, 0) == rotation3dz<double>(PI/i));
  }
}

BOOST_AUTO_TEST_CASE(testZYXRotations)
{
  for (int i = 1; i < 9; ++i) {

    const double angle = PI/i;

    BOOST_CHECK(testRotationZYX(p100, angle, angle, angle));
    BOOST_CHECK(testRotationZYX(p010, angle, angle, angle));
    BOOST_CHECK(testRotationZYX(p001, angle, angle, angle));

    BOOST_CHECK(testRotationZYX(p100, -angle, angle, angle));
    BOOST_CHECK(testRotationZYX(p010, angle, angle, angle));
    BOOST_CHECK(testRotationZYX(p001, angle, angle, angle));

    BOOST_CHECK(testRotationZYX(p100, angle, angle, angle));
    BOOST_CHECK(testRotationZYX(p010, -angle, angle, angle));
    BOOST_CHECK(testRotationZYX(p001, angle, angle, angle));

    BOOST_CHECK(testRotationZYX(p100, angle, -angle, angle));
    BOOST_CHECK(testRotationZYX(p010, angle, -angle, angle));
    BOOST_CHECK(testRotationZYX(p001, angle, -angle, angle));

    BOOST_CHECK(testRotationZYX(p100, -angle, -angle, -angle));
    BOOST_CHECK(testRotationZYX(p010, -angle, -angle, -angle));
    BOOST_CHECK(testRotationZYX(p001, -angle, -angle, -angle));

  }
}

BOOST_AUTO_TEST_CASE(testInverse)
{
  BOOST_CHECK(TestUtils::testInverseRotation3DZYX<rotation3dx<double> >());
  BOOST_CHECK(TestUtils::testInverseRotation3DZYX<rotation3dy<double> >());
  BOOST_CHECK(TestUtils::testInverseRotation3DZYX<rotation3dz<double> >());
}

BOOST_AUTO_TEST_CASE(testInvert)
{
  BOOST_CHECK(TestUtils::testInvertRotation3DZYX<rotation3dx<double> >());
  BOOST_CHECK(TestUtils::testInvertRotation3DZYX<rotation3dy<double> >());
  BOOST_CHECK(TestUtils::testInvertRotation3DZYX<rotation3dz<double> >());
}

BOOST_AUTO_TEST_SUITE_END()

max_stars_repo_name: XPsoud/minimathlibs

max_issues_repo_name: XPsoud/minimathlibs

max_forks_repo_name: XPsoud/minimathlibs


text:
/*
 * Copyright (c) 2018, Zuse Institute Berlin.
 *
 * Licensed under the New BSD License, see LICENSE file for details.
 *
 */

#include "fuse_operations.h"
#include "logging.h"
#include "mount_options.h"
#include "posix_io_rpc_client.h"

#include <fuse.h>
#include <boost/filesystem.hpp>
#include <cerrno>
#include <cstdlib>
#include <exception>
#include <iostream>
#include <string>

int main(int argc, char *argv[]) {
  // parse command line without being strict, because we might just have to
  // display help or version
  paciofs::mount::options::MountOptions options;
  try {
    options.ParseCommandLine(argc, argv, false);
  } catch (std::invalid_argument &e) {
    // non-strictness only swallows missing required options only
    std::cerr << e.what() << std::endl;
    options.PrintHelp(std::string(argv[0]));
    return EXIT_FAILURE;
  }

  // only show help
  if (options.Help()) {
    options.PrintHelp(std::string(argv[0]));
    return EXIT_SUCCESS;
  }

  // declare here because we cannot pass nullptr to fuse_main
  struct fuse_operations operations = {};

  // only show version
  if (options.Version()) {
    std::cout << "PacioFS " << PACIOFS_VERSION << std::endl;

    // print fuse version as well
    return fuse_main(argc, argv, &operations, nullptr);
  }

  // now that we did not exit early, we have to be strict
  try {
    options.ParseCommandLine(argc, argv, true);
  } catch (std::invalid_argument &e) {
    std::cerr << e.what() << std::endl;
    options.PrintHelp(std::string(argv[0]));
    return EXIT_FAILURE;
  }

  paciofs::logging::Initialize(options.LogLevel(), options.LogFile());
  paciofs::logging::Logger logger;

  // log invocation for later inspection
  logger.Debug([argc, argv](auto &out) {
    out << argv[0];
    for (int i = 1; i < argc; ++i) {
      out << " " << argv[i];
    }
  });

  // make sure mount point exists and is empty
  boost::filesystem::path mount_point(options.MountPoint());
  if (!boost::filesystem::exists(mount_point) ||
      !boost::filesystem::is_empty(mount_point)) {
    logger.Fatal([mount_point](auto &out) {
      out << "Mount point " << mount_point << " is not an empty directory";
    });
    return EXIT_FAILURE;
  }

  // construct arguments to pass to fuse
  struct fuse_args args = FUSE_ARGS_INIT(0, nullptr);

  // set binary name, it is ignored anyway
  fuse_opt_add_arg(&args, argv[0]);

  // convert all fuse options
  for (std::string const &arg : options.FuseOptions()) {
    fuse_opt_add_arg(&args, "-o");
    fuse_opt_add_arg(&args, arg.c_str());
  }

  // log arguments before checking them
  logger.Debug([args](auto &out) {
    out << "Invoking fuse as:";
    for (int i = 0; i < args.argc; ++i) {
      out << " " << args.argv[i];
    }
  });

  // sanity check arguments
  int error = fuse_opt_parse(&args, nullptr, nullptr, nullptr);
  if (error != 0) {
    logger.Fatal(
        [error](auto &out) { out << "fuse_opt_parse returned " << error; });
    fuse_opt_free_args(&args);
    return EXIT_FAILURE;
  }

  // client to talk to I/O service
  std::string const &endpoint = options.Endpoint();
  paciofs::io::posix::grpc::PosixIoRpcClient rpc_client(
      endpoint, options.VolumeName(), options.AsyncWrites(),
      options.PemCertChain(), options.PemPrivateKey(), options.PemRootCerts());

  // make sure we can talk to the service
  if (!rpc_client.Ping()) {
    logger.Fatal([endpoint](auto &out) {
      out << "Could not ping service at " << endpoint;
    });
    fuse_opt_free_args(&args);
    return EXIT_FAILURE;
  }

  // set up the operations
  InitializeFuseOperations(&rpc_client, operations);

  // no mask for newly created files
  umask(0);

  // create mount
  struct fuse_chan *chan = fuse_mount(mount_point.c_str(), &args);
  if (chan == nullptr) {
    error = errno;
    logger.Fatal([error](auto &out) {
      out << "fuse_mount returned " << std::strerror(error);
    });
    fuse_opt_free_args(&args);
    return EXIT_FAILURE;
  }

  // finally create the file system
  struct fuse *fs =
      fuse_new(chan, &args, &operations, sizeof(operations), nullptr);
  if (fs == nullptr) {
    error = errno;
    logger.Fatal([error](auto &out) {
      out << "fuse_new returned " << std::strerror(error);
    });
    fuse_opt_free_args(&args);
    fuse_unmount(mount_point.c_str(), chan);
    return EXIT_FAILURE;
  }

  fuse_opt_free_args(&args);

  // exit on HUP, TERM, INT and ignore PIPE
  error = fuse_set_signal_handlers(fuse_get_session(fs));
  if (error != 0) {
    logger.Warning([error](auto &out) {
      out << "fuse_set_signal_handlers returned " << error;
    });
  }

  // main loop
  error = fuse_loop_mt(fs);
  if (error != 0) {
    logger.Warning(
        [error](auto &out) { out << "fuse_loop_mt returned " << error; });
  }

  // what fuse_teardown does, except freeing the mount point
  fuse_remove_signal_handlers(fuse_get_session(fs));
  fuse_unmount(mount_point.c_str(), chan);
  fuse_destroy(fs);

  return EXIT_SUCCESS;
}

max_stars_repo_name: jonasspenger/paciofs

max_issues_repo_name: jonasspenger/paciofs

max_forks_repo_name: jonasspenger/paciofs


text:
// *****************************************************************************
//
// Copyright (c) 2014, Southwest Research Institute® (SwRI®)
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//     * Redistributions of source code must retain the above copyright
//       notice, this list of conditions and the following disclaimer.
//     * Redistributions in binary form must reproduce the above copyright
//       notice, this list of conditions and the following disclaimer in the
//       documentation and/or other materials provided with the distribution.
//     * Neither the name of Southwest Research Institute® (SwRI®) nor the
//       names of its contributors may be used to endorse or promote products
//       derived from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// *****************************************************************************

#include <swri_image_util/geometry_util.h>

#include <cmath>
#include <limits>
#include <vector>

#include <QPolygonF>
#include <QPointF>

#include <opencv2/imgproc/imgproc.hpp>

#include <Eigen/Dense>
#include <Eigen/SVD>

#include <swri_math_util/constants.h>

namespace swri_image_util
{
  bool Intersects(const BoundingBox& box1, const BoundingBox& box2)
  {
    return (box1 & box2).area() > 0;
  }

  double GetOverlappingArea(const cv::Rect& rect, const cv::Mat& rigid_transform)
  {
    // List of points corresponding to the input rectangle.
    std::vector<cv::Vec2f> points;

    // List of points correspondng to the transformed rectangle.
    std::vector<cv::Vec2f> points_t;

    // Create a point for each corner of the input rectangle.
    points.push_back(cv::Vec2f(rect.x, rect.y));
    points.push_back(cv::Vec2f(rect.x + rect.width, rect.y));
    points.push_back(cv::Vec2f(rect.x + rect.width, rect.y + rect.height));
    points.push_back(cv::Vec2f(rect.x, rect.y + rect.height));

    // Transform the input points to the transformed points using the rigid
    // transform.
    cv::transform(cv::InputArray(points), cv::OutputArray(points_t), rigid_transform);

    // Use the QPolygon object to get the intersecting area of the input
    // rectangle and the transformed rectangle.

    // Build the polygon corresponding to the input rectangle.
    QPolygonF polygon;
    polygon << QPointF(points[0][0], points[0][1]);
    polygon << QPointF(points[1][0], points[1][1]);
    polygon << QPointF(points[2][0], points[2][1]);
    polygon << QPointF(points[3][0], points[3][1]);
    polygon << QPointF(points[0][0], points[0][1]);

    // Build the polygon corresponding to the transformed rectangle.
    QPolygonF transformed_polygon;
    transformed_polygon << QPointF(points_t[0][0], points_t[0][1]);
    transformed_polygon << QPointF(points_t[1][0], points_t[1][1]);
    transformed_polygon << QPointF(points_t[2][0], points_t[2][1]);
    transformed_polygon << QPointF(points_t[3][0], points_t[3][1]);
    transformed_polygon << QPointF(points_t[0][0], points_t[0][1]);

    // Get the polygon representing the intersection of the input rectangle and
    // the transformed rectangle.
    QPolygonF intersection = polygon.intersected(transformed_polygon);

    // If the intersection is empty, then just return 0 area.
    if (intersection.size() == 0)
    {
      return 0;
    }

    // Build an OpenCV contour to measure the area of the intersection.
    std::vector<cv::Point2f> contour;
    for (int i = 0; i < intersection.size(); i++)
    {
      contour.push_back(cv::Point2f(intersection[i].x(), intersection[i].y()));
    }

    // Scale the area based on the scale factor to get the correct value.
    return cv::contourArea(contour);
  }

  cv::Mat ProjectEllipsoid(const cv::Mat& ellipsoid)
  {
    cv::Mat ellipse;

    if (ellipsoid.rows == 3 && ellipsoid.cols == 3 && ellipsoid.type() == CV_32FC1)
    {
      if (ellipsoid.at<float>(2, 2) >= std::numeric_limits<double>::max() * 0.5)
      {
        ellipse.create(2, 2, CV_32FC1);
        ellipse.at<float>(0, 0) = ellipsoid.at<float>(0, 0);
        ellipse.at<float>(0, 1) = ellipsoid.at<float>(0, 1);
        ellipse.at<float>(1, 0) = ellipsoid.at<float>(1, 0);
        ellipse.at<float>(1, 1) = ellipsoid.at<float>(1, 1);

        return ellipse;
      }

      Eigen::Matrix3d A;
      for (size_t r = 0; r < 3; r++)
      {
        for (size_t c = 0; c < 3; c++)
        {
          A(r, c) = ellipsoid.at<float>(r, c);
        }
      }

      // Specify the main vector directions (x and y)
      Eigen::Vector3d ax1;
      Eigen::Vector3d ax2;
      ax1 << 1, 0, 0;
      ax2 << 0, 1, 0;

      // Initialize the normal vector (here the normal vector, in the state
      // space is in the theta direction).
      Eigen::Vector3d n_ax;
      n_ax << 0, 0, 1;

      ///////////////////////
      // Calculate A prime //
      ///////////////////////

      Eigen::Matrix3d A_sym_temp = A.transpose() + A;

      // N_ax_temp = (n_ax*n_ax')
      Eigen::Matrix3d N_ax_temp = n_ax * n_ax.transpose();

      // A_prime_1 = A_sym_temp*N_ax_temp
      //           = (A+A')*(n_ax*n_ax')
      Eigen::Matrix3d A_prime_1 = A_sym_temp * N_ax_temp;

      // A_prime_2 = A_prime_1*A_sym_temp
      //           = (A+A')*(n_ax*n_ax')*(A+A')
      Eigen::Matrix3d A_prime_2 = A_prime_1 * A_sym_temp;

      // scale_1 = n_ax'*A
      Eigen::RowVector3d scale_1 = n_ax.transpose() * A;

      // scale_2 = (scale_1*n_ax)*-4
      //         = (n_ax'*A*n_ax)*-4
      double scale = (scale_1 * n_ax)(0,0) * -4.0;

      // A_temp = scale*A_temp
      //        = scale_2*A = -4*(n_ax'*A*n_ax)*A
      Eigen::Matrix3d A_temp = A * scale;

      // Aprime = A_prime_2 + A_temp
      //        = (A+A')*(n_ax*n_ax')*(A+A') - 4*(n_ax'*A*n_ax)*A
      Eigen::Matrix3d Aprime = A_prime_2 + A_temp;

      ///////////////////////
      // Calculate C prime //
      ///////////////////////

      // C_temp = n_ax'*A
      Eigen::RowVector3d C_temp = n_ax.transpose() * A;

      // Cprime = -4.0*C_temp*n_ax
      //        = -4.0*n_ax'*A*n_ax
      double cp = (-4.0 * C_temp) * n_ax;

      // Bprime = Aprime/Cprime;
      Eigen::Matrix3d Bprime = Aprime / cp;

      // Jp = axes_def;
      //    = [ax1(:),ax2(:)] = [1,0;0,1;0,0];
      Eigen::Matrix<double, 3, 2> Jp;
      Jp << 1, 0,
            0, 1,
            0, 0;

      ///////////////////////
      // Calculate D prime //
      ///////////////////////

      // Dprime_temp = Jp'*Bprime
      Eigen::Matrix<double, 2, 3> Dprime_temp = Jp.transpose() * Bprime;

      // Dprime = Dprime_temp * Jp
      //        = Jp'*Bprime*Jp
      Eigen::Matrix2d Dprime = Dprime_temp * Jp;

      for (size_t r = 0; r < 2; r++)
      {
        for (size_t c = 0; c < 2; c++)
        {
          if (Dprime(r, c) != Dprime(r, c))
          {
            return ellipse;
          }
        }
      }

      ellipse.create(2, 2, CV_32FC1);
      ellipse.at<float>(0, 0) = Dprime(0, 0);
      ellipse.at<float>(0, 1) = Dprime(0, 1);
      ellipse.at<float>(1, 0) = Dprime(1, 0);
      ellipse.at<float>(1, 1) = Dprime(1, 1);
    }

    return ellipse;
  }

  std::vector<tf::Vector3> GetEllipsePoints(
      const cv::Mat& ellipse,
      const tf::Vector3& center,
      double scale,
      int32_t num_points)
  {
    std::vector<tf::Vector3> perimeter;

    if (ellipse.rows == 2 && ellipse.cols == 2 && ellipse.type() == CV_32FC1 &&
        num_points > 2)
    {
      Eigen::Matrix2d Dprime;
      Dprime(0, 0) = ellipse.at<float>(0, 0);
      Dprime(0, 1) = ellipse.at<float>(0, 1);
      Dprime(1, 0) = ellipse.at<float>(1, 0);
      Dprime(1, 1) = ellipse.at<float>(1, 1);

      Eigen::JacobiSVD<Eigen::Matrix2d> svd(Dprime, Eigen::ComputeFullV);

      Eigen::Vector2d Sigma = svd.singularValues();
      Eigen::Matrix2d Vt = svd.matrixV().transpose();

      double xprime_scale = std::sqrt(Sigma(0));
      double yprime_scale = std::sqrt(Sigma(1));

      if (xprime_scale <= 0 || yprime_scale <= 0)
      {
        return perimeter;
      }

      Eigen::MatrixX2d Xp1(num_points, 2);
      for (int32_t i = 0; i < num_points; i++)
      {
        double phi =
            (static_cast<double>(i) / static_cast<double>(num_points))
            * swri_math_util::_2pi;

        Xp1(i, 0) = xprime_scale * std::cos(phi) * scale;
        Xp1(i, 1) = yprime_scale * std::sin(phi) * scale;
      }

      // Xell = Xp1*(V')'
      Eigen::MatrixX2d Xell = Xp1 * Vt;

      perimeter.resize(num_points);
      for (int32_t i = 0; i < num_points; i++)
      {
        perimeter[i].setX(Xell(i, 0) + center.x());
        perimeter[i].setY(Xell(i, 1) + center.y());
      }
    }

    return perimeter;
  }
}


text:
//
// Created by Harold on 2022/1/12.
//

#pragma warning(disable : 4996)
#pragma warning(disable : 4819)

#include <vtkNamedColors.h>
#include <vtkNew.h>
#include <vtkOBJImporter.h>
#include <vtkPolyData.h>
#include <vtkPolyDataMapper.h>
#include <vtkRenderWindow.h>
#include <vtkRenderWindowInteractor.h>
#include <vtkRenderer.h>
#include <vtkTexture.h>

#include <vtkSmartPointer.h>
#include <vtkObjectFactory.h>
#include <vtkInteractorStyleTrackballCamera.h>

#include <vtkSmartPointer.h>
#include <vtkAxesActor.h>
#include <vtkOrientationMarkerWidget.h>

#include <vtkPoints.h>
#include <vtkLine.h>
#include <vtkCellArray.h>
#include <vtkCellData.h>
#include <vtkUnsignedCharArray.h>
#include <vtkProperty.h>

#include <sstream>
#include <boost/filesystem.hpp>

// handle key press events
class KeyPressInteractorStyle : public vtkInteractorStyleTrackballCamera
{
public:
    static KeyPressInteractorStyle *New();
    vtkTypeMacro(KeyPressInteractorStyle, vtkInteractorStyleTrackballCamera);

    virtual void OnKeyPress() override
    {
        vtkRenderWindowInteractor *rwi = this->Interactor;
        std::string key = rwi->GetKeySym();
        // remove one texture and corresponding camera pose lines
        if (key == "Up")
        {
            if (cursor > 0)
            {
                this->GetCurrentRenderer()->RemoveActor(texture_and_cam_pairs[cursor].first);
                this->GetCurrentRenderer()->RemoveActor(texture_and_cam_pairs[cursor].second);
                cursor--;
            }
        }
        // add one texture and corresponding camera pose lines
        if (key == "Down")
        {
            if (cursor >= 0 && cursor < int(texture_and_cam_pairs.size()) - 1)
            {
                cursor++;
                this->GetCurrentRenderer()->AddActor(texture_and_cam_pairs[cursor].first);
                this->GetCurrentRenderer()->AddActor(texture_and_cam_pairs[cursor].second);
            }
        }
        vtkInteractorStyleTrackballCamera::OnKeyPress();
        this->GetCurrentRenderer()->GetRenderWindow()->Render();
    }

    void SetTextureAndCamPairs(std::vector<std::pair<vtkSmartPointer<vtkActor>, vtkSmartPointer<vtkActor>>> texture_and_cam_pairs_)
    {
        texture_and_cam_pairs = texture_and_cam_pairs_;
    }
private:
    std::vector<std::pair<vtkSmartPointer<vtkActor>, vtkSmartPointer<vtkActor>>> texture_and_cam_pairs;
    int cursor = 0;
};
vtkStandardNewMacro(KeyPressInteractorStyle);

// axis
vtkSmartPointer<vtkOrientationMarkerWidget> SetUpAxesWidget(vtkRenderWindowInteractor* interactor);

// draw 5-points camera
vtkSmartPointer<vtkActor> DrawCamera(std::string const& camera_file_path);

int main(int argc, char *argv[])
{
    if (argc < 3)
    {
        std::cout
            << "Usage: " << argv[0]
            << " objfile mtlfile texturepath e.g. xx.obj"
            << std::endl;
        return EXIT_FAILURE;
    }

    std::string objpath;
    if (boost::filesystem::extension(argv[1]) == ".obj")
        objpath = argv[1];
    else
    {
        std::cerr << "only support .obj file with .mtl" << std::endl;
        return EXIT_FAILURE;
    }
    std::string mtlpath = boost::filesystem::path(objpath).replace_extension(".mtl").string();

    vtkNew<vtkOBJImporter> importer;
    importer->SetFileName(objpath.c_str());
    importer->SetFileNameMTL(mtlpath.c_str());  // assume .mtl is within the same folder with .obj
    importer->SetTexturePath("");  // assume texture filepaths in .mtl are absolute paths

    vtkNew<vtkNamedColors> colors;

    vtkNew<vtkRenderer> renderer;
    vtkNew<vtkRenderWindow> renWin;
    vtkNew<vtkRenderWindowInteractor> iren;
    vtkNew<KeyPressInteractorStyle> style;
    iren->SetInteractorStyle(style);
    style->SetCurrentRenderer(renderer);

    renderer->SetBackground2(colors->GetColor3d("Silver").GetData());
    renderer->SetBackground(colors->GetColor3d("Gold").GetData());
    renderer->GradientBackgroundOn();
    renWin->AddRenderer(renderer);
    renderer->UseHiddenLineRemovalOn();
    renWin->AddRenderer(renderer);
    renWin->SetSize(2000, 1000);
    renWin->SetWindowName("DisplayOBJ");

    iren->SetRenderWindow(renWin);
    importer->SetRenderWindow(renWin);
    importer->Update();

    // textures
    auto actors = renderer->GetActors();
    actors->InitTraversal();
    auto textures_number = actors->GetNumberOfItems();
    // std::cout << "There are " << textures_number << " textures" << std::endl;

    std::vector<std::pair<vtkSmartPointer<vtkActor>, vtkSmartPointer<vtkActor>>> texture_and_cam_pairs;
    texture_and_cam_pairs.reserve(textures_number - 1);
    for (vtkIdType a = 0; a < textures_number; ++a)
    {
        vtkSmartPointer<vtkActor> actor = actors->GetNextActor();
        // if (actor->GetTexture())
        // {
        //   actor->GetTexture()->InterpolateOn();  // turns texture interpolation on
        // }
        // vtkPolyData *pd = dynamic_cast<vtkPolyData *>(actor->GetMapper()->GetInput());
        // vtkPolyDataMapper *mapper = dynamic_cast<vtkPolyDataMapper *>(actor->GetMapper());
        // mapper->SetInputData(pd);

        // camera
        if (a < textures_number - 1)
        {
            auto info_str = importer->GetOutputDescription(a);
            std::string const pattern1 = "file ";
            std::string const pattern2 = " diffuse";
            auto start = info_str.find(pattern1) + pattern1.size();
            auto end = info_str.find(pattern2, start);
            auto texture_path = info_str.substr(start, end - start);
            //std::cout << texture_path << std::endl;
            auto cam_file_path = boost::filesystem::path(texture_path).replace_extension(".cam").string();
            texture_and_cam_pairs.emplace_back(actor, DrawCamera(cam_file_path));

            //std::cout << "removed: " << importer->GetOutputDescription(a) << std::endl;
            renderer->RemoveActor(actor);
        }
    }
    style->SetTextureAndCamPairs(texture_and_cam_pairs);

    // axes
    auto widget = SetUpAxesWidget(iren);
    widget->SetEnabled(1);
    widget->InteractiveOn();

    renWin->Render();
    iren->Start();

    return EXIT_SUCCESS;
}

vtkSmartPointer<vtkOrientationMarkerWidget> SetUpAxesWidget(vtkRenderWindowInteractor* interactor)
{
    vtkNew<vtkNamedColors> colors;
    // axes
    vtkNew<vtkAxesActor> axes;
    axes->SetCylinderRadius(0.03);
    axes->SetShaftTypeToCylinder();
    axes->SetTotalLength(1.5, 1.5, 1.5);

    // widget
    vtkNew<vtkOrientationMarkerWidget> widget;
    double rgba[4]{0.0, 0.0, 0.0, 0.0};
    colors->GetColor("Carrot", rgba);
    widget->SetOutlineColor(rgba[0], rgba[1], rgba[2]);
    widget->SetOrientationMarker(axes);
    widget->SetInteractor(interactor);
    widget->SetViewport(0.0, 0.0, 0.4, 0.4);
    return widget;
}

// 8 lines
vtkSmartPointer<vtkActor> DrawCamera(std::string const& camera_file_path)
{
    vtkNew<vtkActor> actor;
    std::ifstream ifs;
    ifs.open(camera_file_path.c_str(), std::ios::in);
    if (!ifs.is_open())
    {
        std::cerr << "Error opening file: " << camera_file_path << std::endl;
        return actor;
    }

    vtkNew<vtkPolyData> linesPolyData;
    vtkNew<vtkPoints> pts;
    std::string line;
    char c;
    double x = 0, y = 0, z = 0;
    // line 1
    while (std::getline(ifs, line))
    {
        std::stringstream ss(line);
        ss >> c >> x >> c >> y >> c >> z;
        pts->InsertNextPoint(x, y, z);
        ss >> c >> c >> x >> c >> y >> c >> z;
        pts->InsertNextPoint(x, y, z);
    }
    linesPolyData->SetPoints(pts);

    vtkNew<vtkLine> line1, line2, line3, line4, line5, line6, line7, line8;
    line1->GetPointIds()->SetId(0, 0);
    line1->GetPointIds()->SetId(1, 1);
    line2->GetPointIds()->SetId(0, 2);
    line2->GetPointIds()->SetId(1, 3);
    line3->GetPointIds()->SetId(0, 4);
    line3->GetPointIds()->SetId(1, 5);
    line4->GetPointIds()->SetId(0, 6);
    line4->GetPointIds()->SetId(1, 7);
    line5->GetPointIds()->SetId(0, 8);
    line5->GetPointIds()->SetId(1, 9);
    line6->GetPointIds()->SetId(0, 10);
    line6->GetPointIds()->SetId(1, 11);
    line7->GetPointIds()->SetId(0, 12);
    line7->GetPointIds()->SetId(1, 13);
    line8->GetPointIds()->SetId(0, 14);
    line8->GetPointIds()->SetId(1, 15);

    vtkNew<vtkCellArray> lines;
    lines->InsertNextCell(line1);
    lines->InsertNextCell(line2);
    lines->InsertNextCell(line3);
    lines->InsertNextCell(line4);
    lines->InsertNextCell(line5);
    lines->InsertNextCell(line6);
    lines->InsertNextCell(line7);
    lines->InsertNextCell(line8);
    linesPolyData->SetLines(lines);

    vtkNew<vtkNamedColors> namedColors;
    vtkNew<vtkUnsignedCharArray> colors;
    colors->SetNumberOfComponents(3);
    colors->InsertNextTypedTuple(namedColors->GetColor3ub("Tomato").GetData());
    colors->InsertNextTypedTuple(namedColors->GetColor3ub("Tomato").GetData());
    colors->InsertNextTypedTuple(namedColors->GetColor3ub("Tomato").GetData());
    colors->InsertNextTypedTuple(namedColors->GetColor3ub("Tomato").GetData());
    colors->InsertNextTypedTuple(namedColors->GetColor3ub("Tomato").GetData());
    colors->InsertNextTypedTuple(namedColors->GetColor3ub("Tomato").GetData());
    colors->InsertNextTypedTuple(namedColors->GetColor3ub("Tomato").GetData());
    colors->InsertNextTypedTuple(namedColors->GetColor3ub("Tomato").GetData());
    linesPolyData->GetCellData()->SetScalars(colors);

    vtkNew<vtkPolyDataMapper> mapper;
    mapper->SetInputData(linesPolyData);
    actor->SetMapper(mapper);
    actor->GetProperty()->SetLineWidth(4);
    actor->GetProperty()->SetOpacity(0.5);
    return actor;
}


text:
/*
Copyright 2013, 2015 Rogier van Dalen.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

#define BOOST_TEST_MODULE test_range_reverse
#include "utility/test/boost_unit_test.hpp"

#include "range/reverse.hpp"

#include <vector>
#include <list>
#include <tuple>

#include <boost/mpl/assert.hpp>

#include "range/std/container.hpp"
#include "range/std/tuple.hpp"

#include "rime/check/check_equal.hpp"

BOOST_AUTO_TEST_SUITE(test_range_reverse)

using range::reverse;
using range::front;
using range::back;

using range::default_direction;
using range::front;

using range::empty;
using range::size;
using range::first;
using range::drop;
using range::is_homogeneous;

BOOST_AUTO_TEST_CASE (test_range_reverse_static) {
    BOOST_MPL_ASSERT_NOT ((range::has <range::callable::reverse (int)>));
    BOOST_MPL_ASSERT_NOT ((range::has <range::callable::reverse ()>));
    BOOST_MPL_ASSERT ((
        range::has <range::callable::reverse (std::vector <int> &)>));
}

BOOST_AUTO_TEST_CASE (test_range_reverse_homogeneous) {
    /* std::vector. */
    {
        std::vector <int> v;
        BOOST_CHECK (default_direction (reverse (v)) == default_direction (v));

        BOOST_CHECK (empty (reverse (v)));
        BOOST_CHECK (empty (reverse (v), front));
        BOOST_CHECK (empty (reverse (v), back));

        BOOST_CHECK_EQUAL (size (reverse (v)), 0u);
        BOOST_CHECK_EQUAL (size (reverse (v), front), 0u);
        BOOST_CHECK_EQUAL (size (reverse (v), back), 0u);

        v.push_back (7);
        // v == reverse (v) == { 7 }.

        BOOST_CHECK (!empty (reverse (v)));
        BOOST_CHECK (!empty (reverse (v), front));
        BOOST_CHECK (!empty (reverse (v), back));

        BOOST_CHECK_EQUAL (size (reverse (v)), 1u);
        BOOST_CHECK_EQUAL (size (reverse (v), front), 1u);
        BOOST_CHECK_EQUAL (size (reverse (v), back), 1u);

        BOOST_CHECK_EQUAL (first (reverse (v)), 7);
        BOOST_CHECK_EQUAL (first (reverse (v), front), 7);
        BOOST_CHECK_EQUAL (first (reverse (v), back), 7);

        BOOST_CHECK (empty (drop (reverse (v))));
        BOOST_CHECK (empty (drop (reverse (v), front)));
        BOOST_CHECK (empty (drop (reverse (v), back)));

        v.push_back (18);
        // v == {7, 18}; reverse (v) == { 18, 7 }.

        BOOST_CHECK (!empty (reverse (v)));
        BOOST_CHECK (!empty (reverse (v), front));
        BOOST_CHECK (!empty (reverse (v), back));

        BOOST_CHECK_EQUAL (size (reverse (v)), 2u);
        BOOST_CHECK_EQUAL (size (reverse (v), front), 2u);
        BOOST_CHECK_EQUAL (size (reverse (v), back), 2u);

        BOOST_CHECK_EQUAL (first (reverse (v)), 18);
        BOOST_CHECK_EQUAL (first (reverse (v), front), 18);
        BOOST_CHECK_EQUAL (first (reverse (v), back), 7);

        BOOST_CHECK (!empty (drop (reverse (v))));
        BOOST_CHECK (!empty (drop (reverse (v), front)));
        BOOST_CHECK (!empty (drop (reverse (v), back)));

        BOOST_CHECK_EQUAL (first (drop (reverse (v))), 7);
        BOOST_CHECK_EQUAL (first (drop (reverse (v), front), front), 7);
        BOOST_CHECK_EQUAL (first (drop (reverse (v), back), front), 18);
        BOOST_CHECK_EQUAL (first (drop (reverse (v), front), back), 7);
        BOOST_CHECK_EQUAL (first (drop (reverse (v), back), back), 18);

        BOOST_CHECK_EQUAL (first (drop (reverse (v), 1)), 7);
        BOOST_CHECK_EQUAL (first (drop (reverse (v), 1, front), front), 7);
        BOOST_CHECK_EQUAL (first (drop (reverse (v), 1, back), front), 18);
        BOOST_CHECK_EQUAL (first (drop (reverse (v), 1, front), back), 7);
        BOOST_CHECK_EQUAL (first (drop (reverse (v), 1, back), back), 18);

        BOOST_CHECK (empty (drop (reverse (v), 2)));
        BOOST_CHECK (empty (drop (reverse (v), 2, front)));
        BOOST_CHECK (empty (drop (reverse (v), 2, back)));

        v.push_back (29);
        // v == {7, 18, 29}; reverse (v) == { 29, 18, 7 }.

        BOOST_CHECK (!empty (reverse (v)));
        BOOST_CHECK (!empty (reverse (v), front));
        BOOST_CHECK (!empty (reverse (v), back));

        BOOST_CHECK_EQUAL (size (reverse (v)), 3u);
        BOOST_CHECK_EQUAL (size (reverse (v), front), 3u);
        BOOST_CHECK_EQUAL (size (reverse (v), back), 3u);

        BOOST_CHECK_EQUAL (first (reverse (v)), 29);
        BOOST_CHECK_EQUAL (first (reverse (v), front), 29);
        BOOST_CHECK_EQUAL (first (reverse (v), back), 7);

        BOOST_CHECK (!empty (drop (reverse (v))));
        BOOST_CHECK (!empty (drop (reverse (v), front)));
        BOOST_CHECK (!empty (drop (reverse (v), back)));

        BOOST_CHECK_EQUAL (size (drop (reverse (v))), 2u);
        BOOST_CHECK_EQUAL (first (drop (reverse (v))), 18);
        BOOST_CHECK_EQUAL (size (drop (reverse (v), 1)), 2u);
        BOOST_CHECK_EQUAL (first (drop (reverse (v), 1)), 18);
        BOOST_CHECK_EQUAL (size (drop (reverse (v), 2)), 1u);
        BOOST_CHECK_EQUAL (first (drop (reverse (v), 2)), 7);
        BOOST_CHECK_EQUAL (size (drop (reverse (v), 3)), 0u);
        BOOST_CHECK (empty (drop (reverse (v), 3)));

        BOOST_CHECK_EQUAL (size (drop (reverse (v), back), back), 2u);
        BOOST_CHECK_EQUAL (first (drop (reverse (v), back), back), 18);
        BOOST_CHECK_EQUAL (size (drop (reverse (v), 1, back), back), 2u);
        BOOST_CHECK_EQUAL (first (drop (reverse (v), 1, back), back), 18);
        BOOST_CHECK_EQUAL (size (drop (reverse (v), 2, back), back), 1u);
        BOOST_CHECK_EQUAL (first (drop (reverse (v), 2, back), back), 29);
        BOOST_CHECK_EQUAL (size (drop (reverse (v), 3, back), back), 0u);
        BOOST_CHECK (empty (drop (reverse (v), 3, back), back));

        // Mutability.
        first (reverse (v)) = 40;
        BOOST_CHECK_EQUAL (v [2], 40);
        first (drop (reverse (v))) = 50;
        BOOST_CHECK_EQUAL (v [1], 50);
    }

    /* std::list. */
    {
        std::list <char> l;

        auto r = reverse (l);
        static_assert (
            !range::has <range::callable::size (decltype (r))>::value, "");
        static_assert (
            !range::has <range::callable::drop (int, decltype (r))>::value, "");

        BOOST_CHECK (empty (r));

        l.push_back ('H');
        r = reverse (l);

        BOOST_CHECK (!empty (r));
        BOOST_CHECK_EQUAL (first (r), 'H');
        BOOST_CHECK (empty (drop (r)));

        l.push_back ('e');
        r = reverse (l);

        BOOST_CHECK (!empty (r));
        BOOST_CHECK_EQUAL (first (r), 'e');
        BOOST_CHECK_EQUAL (first (drop (r)), 'H');
        BOOST_CHECK (empty (drop (drop (r))));

        BOOST_CHECK_EQUAL (first (r, back), 'H');
        BOOST_CHECK_EQUAL (first (drop (r, back), back), 'e');
        BOOST_CHECK (empty (drop (drop (r, back), back)));

        l.push_back ('l');
        r = reverse (l);

        BOOST_CHECK (!empty (r));
        BOOST_CHECK_EQUAL (first (r), 'l');
        BOOST_CHECK_EQUAL (first (drop (r)), 'e');
        BOOST_CHECK_EQUAL (first (drop (drop (r))), 'H');
        BOOST_CHECK (empty (drop (drop (drop (r)))));

        BOOST_CHECK_EQUAL (first (r, back), 'H');
        BOOST_CHECK_EQUAL (first (drop (r, back), back), 'e');
        BOOST_CHECK_EQUAL (first (drop (drop (r, back), back), back), 'l');
        BOOST_CHECK (empty (drop (drop (drop (r, back), back)), back));
    }
}

BOOST_AUTO_TEST_CASE (test_range_reverse_heterogeneous) {
    {
        std::tuple<> t;

        RIME_CHECK_EQUAL (empty (reverse (t)), rime::true_);
        RIME_CHECK_EQUAL (size (reverse (t)), rime::size_t <0u>());
    }

    {
        std::tuple <int> t (4);
        auto r = reverse (t);

        RIME_CHECK_EQUAL (empty (r), rime::false_);
        RIME_CHECK_EQUAL (size (r), rime::size_t <1u>());

        BOOST_CHECK_EQUAL (first (r), 4);
        first (r) += 5;
        BOOST_CHECK_EQUAL (first (t), 9);

        RIME_CHECK_EQUAL (empty (drop (r, rime::size_t <1u>())), rime::true_);
    }

    {
        std::tuple <int, double> t (4, 7.25);
        auto r = reverse (t);

        RIME_CHECK_EQUAL (empty (r), rime::false_);
        RIME_CHECK_EQUAL (size (r), rime::size_t <2u>());

        RIME_CHECK_EQUAL (first (r), 7.25);
        first (r) += 5;
        RIME_CHECK_EQUAL (first (drop (t)), 12.25);
        RIME_CHECK_EQUAL (first (drop (r)), 4);

        RIME_CHECK_EQUAL (first (drop (r, rime::size_t <1u>(), back), back),
            12.25);
        RIME_CHECK_EQUAL (empty (drop (r, rime::size_t <2u>())), rime::true_);
    }

    {
        std::tuple <int, double, bool> t (4, 7.25, false);
        auto r = reverse (t);

        RIME_CHECK_EQUAL (empty (r), rime::false_);
        RIME_CHECK_EQUAL (size (r), rime::size_t <3u>());

        RIME_CHECK_EQUAL (first (r), false);
        RIME_CHECK_EQUAL (first (drop (r)), 7.25);
        RIME_CHECK_EQUAL (first (drop (r, rime::size_t <2u>())), 4);
        first (drop (r, rime::size_t <2u>())) -= 3;
        BOOST_CHECK_EQUAL (first (t), 1);

        RIME_CHECK_EQUAL (first (drop (r, rime::size_t <2u>(), back), back),
            false);

        RIME_CHECK_EQUAL (empty (drop (r, rime::size_t <3u>())), rime::true_);
    }

}

BOOST_AUTO_TEST_SUITE_END()

max_stars_repo_name: rogiervd/range

max_issues_repo_name: rogiervd/range

max_forks_repo_name: rogiervd/range


text:
#include <boost/test/unit_test.hpp>
#include <staticdb/values.hpp>
#include <staticdb/bit_sink.hpp>
#include <staticdb/storage.hpp>
#include <staticdb/expressions.hpp>

BOOST_AUTO_TEST_CASE(tuple_at)
{
	auto argument = Si::make_unique<staticdb::expressions::expression>(staticdb::expressions::argument());
	auto zero = Si::make_unique<staticdb::expressions::expression>(
	    staticdb::expressions::literal(staticdb::values::make_unsigned_integer<std::uint8_t>(0)));
	auto first =
	    staticdb::expressions::expression(staticdb::expressions::tuple_at(std::move(argument), std::move(zero)));

	std::vector<staticdb::values::value> root_elements;
	root_elements.emplace_back(staticdb::values::make_unsigned_integer<std::uint8_t>(23));
	root_elements.emplace_back(staticdb::values::make_unsigned_integer<std::uint8_t>(42));
	staticdb::values::value root = staticdb::values::tuple(std::move(root_elements));

	staticdb::values::value const result =
	    staticdb::expressions::execute(first, root, staticdb::values::value(staticdb::values::unit()));
	staticdb::values::tuple const *const result_tuple = Si::try_get_ptr<staticdb::values::tuple>(result);
	BOOST_REQUIRE(result_tuple);
	Si::optional<std::uint8_t> const parsed_result =
	    staticdb::values::parse_unsigned_integer<std::uint8_t>(*result_tuple);
	BOOST_CHECK_EQUAL(Si::optional<std::uint8_t>(23), parsed_result);
}

max_stars_repo_name: TyRoXx/staticdb

max_issues_repo_name: TyRoXx/staticdb

max_forks_repo_name: TyRoXx/staticdb


text:
// Copyright © 2016-2021 Thomas Nagler and Thibault Vatter
//
// This file is part of the vinecopulib library and licensed under the terms of
// the MIT license. For a copy, see the LICENSE file in the root directory of
// vinecopulib or https://vinecopulib.github.io/vinecopulib/.

#pragma once

#include <Eigen/Dense>
#include <vector>
#include <vinecopulib/bicop/class.hpp>

namespace vinecopulib {
namespace tools_select {

std::vector<Bicop>
create_candidate_bicops(const Eigen::MatrixXd& data,
                        const FitControlsBicop& controls);

std::vector<BicopFamily>
get_candidate_families(const FitControlsBicop& controls);

void
preselect_candidates(std::vector<Bicop>& bicops,
                     const Eigen::MatrixXd& data,
                     double tau,
                     const Eigen::VectorXd& weights);

std::vector<double>
get_c1c2(const Eigen::MatrixXd& data,
         double tau,
         const Eigen::VectorXd& weights);

bool
preselect_family(std::vector<double> c, double tau, const Bicop& bicop);
}
}

#include <vinecopulib/bicop/implementation/tools_select.ipp>

ext: hpp

max_stars_repo_name: tvatter/vinecoplib

max_issues_repo_name: vinecopulib/vinecopulib

max_forks_repo_name: tvatter/vinecoplib