<commit_before>#include "CullWorker.h"
#include "layers/Layer.h"
#include "renderers/MapRenderer.h"
#include "utils/Const.h"
#include "utils/GeomUtils.h"
#include "utils/Log.h"
#include "utils/ThreadUtils.h"

namespace carto {

    CullWorker::CullWorker() :
        _layerWakeupMap(),
        _firstCull(true),
        _envelope(),
        _viewState(),
        _mapRenderer(),
        _stop(false),
        _idle(false),
        _condition(),
        _mutex()
    {
    }

    CullWorker::~CullWorker() {
    }

    void CullWorker::setComponents(const std::weak_ptr<MapRenderer>& mapRenderer, const std::shared_ptr<CullWorker>& worker) {
        _mapRenderer = mapRenderer;
        // When the map component gets destroyed all threads get detatched. Detatched threads need their worker objects to be alive,
        // so worker objects need to keep references to themselves, until the loop finishes.
        _worker = worker;
    }

    void CullWorker::init(const std::shared_ptr<Layer>& layer, int delayTime) {
        {
            std::lock_guard<std::mutex> lock(_mutex);

            std::chrono::steady_clock::time_point wakeupTime = std::chrono::steady_clock::now() + std::chrono::milliseconds(delayTime);
            if (_layerWakeupMap.find(layer) != _layerWakeupMap.end()) {
                if (_layerWakeupMap[layer] <= wakeupTime)
                    return;
            }
            _layerWakeupMap[layer] = wakeupTime;
        }

        std::lock_guard<std::mutex> lock(_mutex);
        _idle = false;
        _condition.notify_one();
    }

    void CullWorker::stop() {
        std::lock_guard<std::mutex> lock(_mutex);
        _stop = true;
        _condition.notify_all();
    }

    bool CullWorker::isIdle() const {
        std::lock_guard<std::mutex> lock(_mutex);
        return _idle;
    }

    void CullWorker::operator ()() {
        run();
        _worker.reset();
    }

    void CullWorker::run() {
        ThreadUtils::SetThreadPriority(ThreadPriority::LOW);
        while (true) {
            std::vector<std::shared_ptr<Layer> > layers;
            {
                std::unique_lock<std::mutex> lock(_mutex);

                if (_stop) {
                    return;
                }

                std::chrono::steady_clock::time_point currentTime = std::chrono::steady_clock::now();
                std::chrono::steady_clock::time_point wakeupTime = std::chrono::steady_clock::now() + std::chrono::hours(24);
                for (auto it = _layerWakeupMap.begin(); it != _layerWakeupMap.end(); ) {
                    if (it->second - currentTime < std::chrono::milliseconds(1)) {
                        layers.push_back(it->first);
                        _layerWakeupMap.erase(it++);
                    } else {
                        wakeupTime = std::min(wakeupTime, it->second);
                        it++;
                    }
                }

                if (layers.empty()) {
                    _idle = _layerWakeupMap.empty();
                    _condition.wait_for(lock, wakeupTime - std::chrono::steady_clock::now());
                    _idle = false;
                }
            }

            if (!layers.empty()) {
                const std::shared_ptr<MapRenderer>& mapRenderer = _mapRenderer.lock();
                if (!mapRenderer) {
                    return;
                }

                // Get view state
                const ViewState& viewState = mapRenderer->getViewState();

                // Check if view state has changed
                if (_firstCull || viewState.getModelviewProjectionMat() != _viewState.getModelviewProjectionMat()) {
                    _firstCull = false;
                    _viewState = viewState;

                    // Calculate tiles
                    calculateCullState();
                }

                // Update layers
                updateLayers(layers);
            }
        }
    }

    void CullWorker::calculateCullState() {
        // Calculate envelope for the visible frustum
        calculateEnvelope();
    }

    void CullWorker::calculateEnvelope() {
        cglib::mat4x4<double> invMVPMat = cglib::inverse(_viewState.getModelviewProjectionMat());

        // Iterate over all edges and find intersection with ground plane
        std::vector<MapPos> hullPoints;
        hullPoints.reserve(12);
        for (int i = 0; i < 12; i++) {
            int ax = (i >> 2) & 3;
            int as = (4-ax) >> 2;
            int bs = (5-ax) >> 2;
            int va = ((i&1) << as) | ((i&2) << bs);
            int vb = va | (1 << ax);

            // Calculate vertex 0
            double xa = (va & 1) == 0 ? VIEWPORT_SCALE : -VIEWPORT_SCALE;
            double ya = (va & 2) == 0 ? VIEWPORT_SCALE : -VIEWPORT_SCALE;
            double za = (va & 4) == 0 ? 1 : -1;
            cglib::vec3<double> p0 = cglib::transform_point(cglib::vec3<double>(xa, ya, za), invMVPMat);

            // Calculate vertex 1
            double xb = (vb & 1) == 0 ? VIEWPORT_SCALE : -VIEWPORT_SCALE;
            double yb = (vb & 2) == 0 ? VIEWPORT_SCALE : -VIEWPORT_SCALE;
            double zb = (vb & 4) == 0 ? 1 : -1;
            cglib::vec3<double> p1 = cglib::transform_point(cglib::vec3<double>(xb, yb, zb), invMVPMat);

            // Calculate intersection between z=0 plane and line p0<->p1
            cglib::vec3<double> dp = p1 - p0;
            if (dp(2) != 0) {
                double t = -p0(2) / dp(2);

                // If the intersection point is inside of the frustum, add it to the list of candidate points
                if (t >= 0 && t <= 1) {
                    cglib::vec3<double> hullPoint = p0 + dp * t;
                    hullPoints.emplace_back(hullPoint(0), hullPoint(1), 0);
                }
            }
        }

        // Calculate convex hull of the resulting point set
        std::vector<MapPos> convexHull = GeomUtils::CalculateConvexHull(hullPoints);
        _envelope = MapEnvelope(convexHull);
    }

    void CullWorker::updateLayers(const std::vector<std::shared_ptr<Layer> >& layers) {
        for (const std::shared_ptr<Layer>& layer : layers) {
            layer->update(std::make_shared<CullState>(_envelope, _viewState));
        }
    }

    const float CullWorker::VIEWPORT_SCALE = 1.1f; // enlarge viewport envelope by approx. 10%
}
<commit_msg>Tweaks<commit_after>#include "CullWorker.h"
#include "layers/Layer.h"
#include "renderers/MapRenderer.h"
#include "utils/Const.h"
#include "utils/GeomUtils.h"
#include "utils/Log.h"
#include "utils/ThreadUtils.h"

namespace carto {

    CullWorker::CullWorker() :
        _layerWakeupMap(),
        _firstCull(true),
        _envelope(),
        _viewState(),
        _mapRenderer(),
        _stop(false),
        _idle(false),
        _condition(),
        _mutex()
    {
    }

    CullWorker::~CullWorker() {
    }

    void CullWorker::setComponents(const std::weak_ptr<MapRenderer>& mapRenderer, const std::shared_ptr<CullWorker>& worker) {
        _mapRenderer = mapRenderer;
        // When the map component gets destroyed all threads get detatched. Detatched threads need their worker objects to be alive,
        // so worker objects need to keep references to themselves, until the loop finishes.
        _worker = worker;
    }

    void CullWorker::init(const std::shared_ptr<Layer>& layer, int delayTime) {
        std::lock_guard<std::mutex> lock(_mutex);

        std::chrono::steady_clock::time_point wakeupTime = std::chrono::steady_clock::now() + std::chrono::milliseconds(delayTime);
        if (_layerWakeupMap.find(layer) != _layerWakeupMap.end()) {
            if (_layerWakeupMap[layer] <= wakeupTime) {
                return;
            }
        }
        _layerWakeupMap[layer] = wakeupTime;
        _idle = false;
        _condition.notify_one();
    }

    void CullWorker::stop() {
        std::lock_guard<std::mutex> lock(_mutex);
        _stop = true;
        _condition.notify_all();
    }

    bool CullWorker::isIdle() const {
        std::lock_guard<std::mutex> lock(_mutex);
        return _idle;
    }

    void CullWorker::operator ()() {
        run();
        _worker.reset();
    }

    void CullWorker::run() {
        ThreadUtils::SetThreadPriority(ThreadPriority::LOW);
        while (true) {
            std::vector<std::shared_ptr<Layer> > layers;
            {
                std::unique_lock<std::mutex> lock(_mutex);

                if (_stop) {
                    return;
                }

                std::chrono::steady_clock::time_point currentTime = std::chrono::steady_clock::now();
                std::chrono::steady_clock::time_point wakeupTime = std::chrono::steady_clock::now() + std::chrono::hours(24);
                for (auto it = _layerWakeupMap.begin(); it != _layerWakeupMap.end(); ) {
                    if (it->second - currentTime < std::chrono::milliseconds(1)) {
                        layers.push_back(it->first);
                        it = _layerWakeupMap.erase(it);
                    } else {
                        wakeupTime = std::min(wakeupTime, it->second);
                        it++;
                    }
                }

                if (layers.empty()) {
                    _idle = _layerWakeupMap.empty();
                    _condition.wait_for(lock, wakeupTime - std::chrono::steady_clock::now());
                    _idle = false;
                }
            }

            if (!layers.empty()) {
                const std::shared_ptr<MapRenderer>& mapRenderer = _mapRenderer.lock();
                if (!mapRenderer) {
                    return;
                }

                // Get view state
                const ViewState& viewState = mapRenderer->getViewState();

                // Check if view state has changed
                if (_firstCull || viewState.getModelviewProjectionMat() != _viewState.getModelviewProjectionMat()) {
                    _firstCull = false;
                    _viewState = viewState;

                    // Calculate tiles
                    calculateCullState();
                }

                // Update layers
                updateLayers(layers);
            }
        }
    }

    void CullWorker::calculateCullState() {
        // Calculate envelope for the visible frustum
        calculateEnvelope();
    }

    void CullWorker::calculateEnvelope() {
        cglib::mat4x4<double> invMVPMat = cglib::inverse(_viewState.getModelviewProjectionMat());

        // Iterate over all edges and find intersection with ground plane
        std::vector<MapPos> hullPoints;
        hullPoints.reserve(12);
        for (int i = 0; i < 12; i++) {
            int ax = (i >> 2) & 3;
            int as = (4-ax) >> 2;
            int bs = (5-ax) >> 2;
            int va = ((i&1) << as) | ((i&2) << bs);
            int vb = va | (1 << ax);

            // Calculate vertex 0
            double xa = (va & 1) == 0 ? VIEWPORT_SCALE : -VIEWPORT_SCALE;
            double ya = (va & 2) == 0 ? VIEWPORT_SCALE : -VIEWPORT_SCALE;
            double za = (va & 4) == 0 ? 1 : -1;
            cglib::vec3<double> p0 = cglib::transform_point(cglib::vec3<double>(xa, ya, za), invMVPMat);

            // Calculate vertex 1
            double xb = (vb & 1) == 0 ? VIEWPORT_SCALE : -VIEWPORT_SCALE;
            double yb = (vb & 2) == 0 ? VIEWPORT_SCALE : -VIEWPORT_SCALE;
            double zb = (vb & 4) == 0 ? 1 : -1;
            cglib::vec3<double> p1 = cglib::transform_point(cglib::vec3<double>(xb, yb, zb), invMVPMat);

            // Calculate intersection between z=0 plane and line p0<->p1
            cglib::vec3<double> dp = p1 - p0;
            if (dp(2) != 0) {
                double t = -p0(2) / dp(2);

                // If the intersection point is inside of the frustum, add it to the list of candidate points
                if (t >= 0 && t <= 1) {
                    cglib::vec3<double> hullPoint = p0 + dp * t;
                    hullPoints.emplace_back(hullPoint(0), hullPoint(1), 0);
                }
            }
        }

        // Calculate convex hull of the resulting point set
        std::vector<MapPos> convexHull = GeomUtils::CalculateConvexHull(hullPoints);
        _envelope = MapEnvelope(convexHull);
    }

    void CullWorker::updateLayers(const std::vector<std::shared_ptr<Layer> >& layers) {
        for (const std::shared_ptr<Layer>& layer : layers) {
            layer->update(std::make_shared<CullState>(_envelope, _viewState));
        }
    }

    const float CullWorker::VIEWPORT_SCALE = 1.1f; // enlarge viewport envelope by approx. 10%
}
<|endoftext|>


<commit_before>#include "cookiejar.h"

CookieJar::CookieJar(QObject *parent) :
    QNetworkCookieJar(parent)
{
    jarfile = new QFile("/tmp/test", this);
    if (jarfile->open(QIODevice::ReadWrite | QIODevice::Append | QIODevice::Text))
    {
        //Lägg till en massa cookies
        //QNetworkCookie nc()
    }

}

bool CookieJar::setCookiesFromUrl(const QList<QNetworkCookie> &cookieList, const QUrl &url)
{
    if (jarfile->isOpen())
    {
        QTextStream jf(jarfile);

        jf << "----\n";
        foreach(QNetworkCookie nc, cookieList)
        {
            if (!nc.isSessionCookie())
            {
                //QString data(nc.toRawForm());
                //jf << data << "\n";
            }
        }
    }

    return QNetworkCookieJar::setCookiesFromUrl(cookieList, url);
}
<commit_msg>kakor<commit_after>#include "cookiejar.h"

CookieJar::CookieJar(QObject *parent) :
  QNetworkCookieJar(parent)
{
  jarfile = new QFile("/tmp/kaktuskakor", this);
  if (jarfile->open(QIODevice::ReadWrite | QIODevice::Text))
  {
    //Lägg till en massa cookies
    QTextStream jf(jarfile);
    setAllCookies(QNetworkCookie::parseCookies(jf.readAll().toAscii()));
  }
}

bool CookieJar::setCookiesFromUrl(const QList<QNetworkCookie> &cookieList, const QUrl &url)
{
  if (jarfile->isOpen())
  {
    QTextStream jf(jarfile);

    foreach(QNetworkCookie nc, cookieList)
    {
      if (!nc.isSessionCookie())
      {
        QString data(nc.toRawForm());
        jf << data << "\n";
      }
    }
  }

  return QNetworkCookieJar::setCookiesFromUrl(cookieList, url);
}
<|endoftext|>


<commit_before>/*
This file is part of the ORK library.
Full copyright and license terms can be found in the LICENSE.txt file.
*/
#include "ork/geometry.hpp"

#include "ork/test/catch_include.hpp"

#include "glm/vec3.hpp"

using namespace ork;

TEST_CASE("Length conversion", "[geometry]")
{
    const double dmm = 50.8;
    const double din = 3.0;

    const double rin = 2.0;
    const double rmm = 76.2;

    REQUIRE(mm2inch(dmm) == rin);
    REQUIRE(inch2mm(din) == rmm);
}

TEST_CASE("Simple angles", "[geometry]")
{
    const double angle1 = 136.0;
    const double angle2 = 395.0;
    const double angle3 = -172.0;

    const double sangle1 = 136.0;
    const double sangle2 = 35.0;
    const double sangle3 = 188.0;

    REQUIRE(simple_angle(angle1) == sangle1);
    REQUIRE(simple_angle(angle2) == sangle2);
    REQUIRE(simple_angle(angle3) == sangle3);
}
<commit_msg>Changed FP comparisons to approx<commit_after>/*
This file is part of the ORK library.
Full copyright and license terms can be found in the LICENSE.txt file.
*/
#include "ork/geometry.hpp"
#include "ork/glm.hpp"

#include "ork/test/catch_include.hpp"

#include "glm/vec3.hpp"

using namespace ork;

TEST_CASE("Length conversion", "[geometry]")
{
    const double dmm = 50.8;
    const double din = 3.0;

    const double rin = 2.0;
    const double rmm = 76.2;

    REQUIRE(ork::GLM::equal(mm2inch(dmm), rin));
    REQUIRE(ork::GLM::equal(inch2mm(din), rmm));
}

TEST_CASE("Simple angles", "[geometry]")
{
    const double angle1 = 136.0;
    const double angle2 = 395.0;
    const double angle3 = -172.0;
    const double angle4 = 2.6 * M_PI;

    const double sangle1 = 136.0;
    const double sangle2 = 35.0;
    const double sangle3 = 188.0;
    const double sangle4 = 0.6 * M_PI;

    REQUIRE(ork::GLM::equal(simple_angle<angle::degree>(angle1), sangle1));
    REQUIRE(ork::GLM::equal(simple_angle<angle::degree>(angle2), sangle2));
    REQUIRE(ork::GLM::equal(simple_angle(angle3, angle::degree), sangle3));
    REQUIRE(ork::GLM::equal(simple_angle(angle4, angle::radian), sangle4));
}
}
<|endoftext|>


<commit_before>/*

This file is part of VROOM.

Copyright (c) 2015-2022, Julien Coupey.
All rights reserved (see LICENSE).

*/

#include <mutex>
#include <set>
#include <thread>

#include "algorithms/heuristics/heuristics.h"
#include "algorithms/local_search/local_search.h"
#include "problems/vrptw/operators/cross_exchange.h"
#include "problems/vrptw/operators/intra_cross_exchange.h"
#include "problems/vrptw/operators/intra_exchange.h"
#include "problems/vrptw/operators/intra_mixed_exchange.h"
#include "problems/vrptw/operators/intra_or_opt.h"
#include "problems/vrptw/operators/intra_relocate.h"
#include "problems/vrptw/operators/intra_two_opt.h"
#include "problems/vrptw/operators/mixed_exchange.h"
#include "problems/vrptw/operators/or_opt.h"
#include "problems/vrptw/operators/pd_shift.h"
#include "problems/vrptw/operators/relocate.h"
#include "problems/vrptw/operators/reverse_two_opt.h"
#include "problems/vrptw/operators/route_exchange.h"
#include "problems/vrptw/operators/swap_star.h"
#include "problems/vrptw/operators/two_opt.h"
#include "problems/vrptw/operators/unassigned_exchange.h"
#include "problems/vrptw/vrptw.h"
#include "utils/helpers.h"

namespace vroom {

using TWSolution = std::vector<TWRoute>;

namespace vrptw {

using LocalSearch = ls::LocalSearch<TWRoute,
                                    vrptw::UnassignedExchange,
                                    vrptw::SwapStar,
                                    vrptw::CrossExchange,
                                    vrptw::MixedExchange,
                                    vrptw::TwoOpt,
                                    vrptw::ReverseTwoOpt,
                                    vrptw::Relocate,
                                    vrptw::OrOpt,
                                    vrptw::IntraExchange,
                                    vrptw::IntraCrossExchange,
                                    vrptw::IntraMixedExchange,
                                    vrptw::IntraRelocate,
                                    vrptw::IntraOrOpt,
                                    vrptw::IntraTwoOpt,
                                    vrptw::PDShift,
                                    vrptw::RouteExchange>;
} // namespace vrptw

const std::vector<HeuristicParameters> VRPTW::homogeneous_parameters =
  {HeuristicParameters(HEURISTIC::BASIC, INIT::HIGHER_AMOUNT, 0.3),
   HeuristicParameters(HEURISTIC::BASIC, INIT::HIGHER_AMOUNT, 0.4),
   HeuristicParameters(HEURISTIC::BASIC, INIT::EARLIEST_DEADLINE, 0.2),
   HeuristicParameters(HEURISTIC::BASIC, INIT::FURTHEST, 0.3),

   HeuristicParameters(HEURISTIC::BASIC, INIT::NONE, 0.4),
   HeuristicParameters(HEURISTIC::BASIC, INIT::HIGHER_AMOUNT, 0.5),
   HeuristicParameters(HEURISTIC::BASIC, INIT::FURTHEST, 0.4),
   HeuristicParameters(HEURISTIC::BASIC, INIT::FURTHEST, 0.5),

   HeuristicParameters(HEURISTIC::BASIC, INIT::HIGHER_AMOUNT, 0.1),
   HeuristicParameters(HEURISTIC::BASIC, INIT::HIGHER_AMOUNT, 0.6),
   HeuristicParameters(HEURISTIC::BASIC, INIT::FURTHEST, 0.2),
   HeuristicParameters(HEURISTIC::BASIC, INIT::FURTHEST, 0.7),

   HeuristicParameters(HEURISTIC::BASIC, INIT::HIGHER_AMOUNT, 0.2),
   HeuristicParameters(HEURISTIC::BASIC, INIT::HIGHER_AMOUNT, 0.7),
   HeuristicParameters(HEURISTIC::BASIC, INIT::HIGHER_AMOUNT, 1.4),
   HeuristicParameters(HEURISTIC::BASIC, INIT::FURTHEST, 0.1),

   HeuristicParameters(HEURISTIC::BASIC, INIT::NONE, 0),
   HeuristicParameters(HEURISTIC::BASIC, INIT::NONE, 0.1),
   HeuristicParameters(HEURISTIC::BASIC, INIT::NONE, 0.3),
   HeuristicParameters(HEURISTIC::BASIC, INIT::NONE, 0.8),

   HeuristicParameters(HEURISTIC::BASIC, INIT::EARLIEST_DEADLINE, 0.5),
   HeuristicParameters(HEURISTIC::BASIC, INIT::EARLIEST_DEADLINE, 0.8),
   HeuristicParameters(HEURISTIC::BASIC, INIT::EARLIEST_DEADLINE, 2.4),
   HeuristicParameters(HEURISTIC::BASIC, INIT::FURTHEST, 1.2),

   HeuristicParameters(HEURISTIC::BASIC, INIT::NONE, 1),
   HeuristicParameters(HEURISTIC::BASIC, INIT::HIGHER_AMOUNT, 1.3),
   HeuristicParameters(HEURISTIC::BASIC, INIT::EARLIEST_DEADLINE, 0),
   HeuristicParameters(HEURISTIC::BASIC, INIT::EARLIEST_DEADLINE, 0.3),

   HeuristicParameters(HEURISTIC::BASIC, INIT::EARLIEST_DEADLINE, 2),
   HeuristicParameters(HEURISTIC::BASIC, INIT::FURTHEST, 0),
   HeuristicParameters(HEURISTIC::BASIC, INIT::FURTHEST, 0.9),
   HeuristicParameters(HEURISTIC::BASIC, INIT::FURTHEST, 1)};

const std::vector<HeuristicParameters> VRPTW::heterogeneous_parameters =
  {HeuristicParameters(HEURISTIC::DYNAMIC, INIT::HIGHER_AMOUNT, 0.5),
   HeuristicParameters(HEURISTIC::DYNAMIC, INIT::HIGHER_AMOUNT, 0.9),
   HeuristicParameters(HEURISTIC::DYNAMIC, INIT::EARLIEST_DEADLINE, 0.4),
   HeuristicParameters(HEURISTIC::DYNAMIC, INIT::FURTHEST, 0.4),

   HeuristicParameters(HEURISTIC::DYNAMIC, INIT::HIGHER_AMOUNT, 0.8),
   HeuristicParameters(HEURISTIC::DYNAMIC, INIT::EARLIEST_DEADLINE, 0.6),
   HeuristicParameters(HEURISTIC::DYNAMIC, INIT::EARLIEST_DEADLINE, 0.9),
   HeuristicParameters(HEURISTIC::DYNAMIC, INIT::FURTHEST, 0.6),

   HeuristicParameters(HEURISTIC::DYNAMIC, INIT::HIGHER_AMOUNT, 1.8),
   HeuristicParameters(HEURISTIC::DYNAMIC, INIT::EARLIEST_DEADLINE, 1.1),
   HeuristicParameters(HEURISTIC::DYNAMIC, INIT::EARLIEST_DEADLINE, 1.4),
   HeuristicParameters(HEURISTIC::DYNAMIC, INIT::FURTHEST, 0.7),

   HeuristicParameters(HEURISTIC::DYNAMIC, INIT::NONE, 1.3),
   HeuristicParameters(HEURISTIC::DYNAMIC, INIT::HIGHER_AMOUNT, 2.4),
   HeuristicParameters(HEURISTIC::DYNAMIC, INIT::EARLIEST_DEADLINE, 0.3),
   HeuristicParameters(HEURISTIC::DYNAMIC, INIT::FURTHEST, 1.2),

   HeuristicParameters(HEURISTIC::DYNAMIC, INIT::NONE, 1.2),
   HeuristicParameters(HEURISTIC::DYNAMIC, INIT::HIGHER_AMOUNT, 0.6),
   HeuristicParameters(HEURISTIC::DYNAMIC, INIT::HIGHER_AMOUNT, 1.6),
   HeuristicParameters(HEURISTIC::DYNAMIC, INIT::EARLIEST_DEADLINE, 0.2),

   HeuristicParameters(HEURISTIC::DYNAMIC, INIT::EARLIEST_DEADLINE, 1.7),
   HeuristicParameters(HEURISTIC::DYNAMIC, INIT::EARLIEST_DEADLINE, 2),
   HeuristicParameters(HEURISTIC::DYNAMIC, INIT::FURTHEST, 0.5),
   HeuristicParameters(HEURISTIC::DYNAMIC, INIT::FURTHEST, 1.5),

   HeuristicParameters(HEURISTIC::DYNAMIC, INIT::NONE, 1.5),
   HeuristicParameters(HEURISTIC::DYNAMIC, INIT::NONE, 2.2),
   HeuristicParameters(HEURISTIC::DYNAMIC, INIT::HIGHER_AMOUNT, 2.1),
   HeuristicParameters(HEURISTIC::DYNAMIC, INIT::EARLIEST_DEADLINE, 0.5),

   HeuristicParameters(HEURISTIC::DYNAMIC, INIT::EARLIEST_DEADLINE, 1.2),
   HeuristicParameters(HEURISTIC::DYNAMIC, INIT::FURTHEST, 0.1),
   HeuristicParameters(HEURISTIC::DYNAMIC, INIT::FURTHEST, 0.9),
   HeuristicParameters(HEURISTIC::DYNAMIC, INIT::FURTHEST, 1.1)};

VRPTW::VRPTW(const Input& input) : VRP(input) {
}

Solution VRPTW::solve(unsigned exploration_level,
                      unsigned nb_threads,
                      const Timeout& timeout,
                      const std::vector<HeuristicParameters>& h_param) const {
  // Use vector of parameters when passed for debugging, else use
  // predefined parameter set.
  const auto& parameters = (!h_param.empty())
                             ? h_param
                             : (_input.has_homogeneous_locations())
                                 ? homogeneous_parameters
                                 : heterogeneous_parameters;
  unsigned max_nb_jobs_removal = exploration_level;
  unsigned nb_init_solutions = h_param.size();

  if (nb_init_solutions == 0) {
    // Local search parameter.
    nb_init_solutions = 4 * (exploration_level + 1);
    if (exploration_level >= 4) {
      nb_init_solutions += 4;
    }
    if (exploration_level >= 5) {
      nb_init_solutions += 4;
    }
  }
  assert(nb_init_solutions <= parameters.size());

  std::vector<TWSolution> tw_solutions(nb_init_solutions);

  // Split the heuristic parameters among threads.
  std::vector<std::vector<std::size_t>>
    thread_ranks(nb_threads, std::vector<std::size_t>());
  for (std::size_t i = 0; i < nb_init_solutions; ++i) {
    thread_ranks[i % nb_threads].push_back(i);
  }

  std::exception_ptr ep = nullptr;
  std::mutex ep_m;

  auto run_heuristics = [&](const std::vector<std::size_t>& param_ranks) {
    try {
      for (auto rank : param_ranks) {
        auto& p = parameters[rank];

        switch (p.heuristic) {
        case HEURISTIC::INIT_ROUTES:
          tw_solutions[rank] = heuristics::initial_routes<TWSolution>(_input);
          break;
        case HEURISTIC::BASIC:
          tw_solutions[rank] =
            heuristics::basic<TWSolution>(_input, p.init, p.regret_coeff);
          break;
        case HEURISTIC::DYNAMIC:
          tw_solutions[rank] =
            heuristics::dynamic_vehicle_choice<TWSolution>(_input,
                                                           p.init,
                                                           p.regret_coeff);
          break;
        }
      }
    } catch (...) {
      ep_m.lock();
      ep = std::current_exception();
      ep_m.unlock();
    }
  };

  std::vector<std::thread> heuristics_threads;

  for (const auto& param_ranks : thread_ranks) {
    if (!param_ranks.empty()) {
      heuristics_threads.emplace_back(run_heuristics, param_ranks);
    }
  }

  for (auto& t : heuristics_threads) {
    t.join();
  }

  if (ep != nullptr) {
    std::rethrow_exception(ep);
  }

  // Filter out duplicate heuristics solutions.
  std::set<utils::SolutionIndicators<TWRoute>> unique_indicators;
  std::vector<unsigned> to_remove;
  for (unsigned i = 0; i < tw_solutions.size(); ++i) {
    const auto result = unique_indicators.emplace(_input, tw_solutions[i]);
    if (!result.second) {
      // No insertion means an equivalent solution already exists.
      to_remove.push_back(i);
    }
  }

  for (auto remove_rank = to_remove.rbegin(); remove_rank != to_remove.rend();
       remove_rank++) {
    tw_solutions.erase(tw_solutions.begin() + *remove_rank);
  }

  // Split local searches across threads.
  unsigned nb_solutions = tw_solutions.size();
  std::vector<utils::SolutionIndicators<TWRoute>> sol_indicators(nb_solutions);
#ifdef LOG_LS_OPERATORS
  std::vector<std::array<ls::OperatorStats, OperatorName::MAX>> ls_stats(
    nb_solutions);
#endif

  std::fill(thread_ranks.begin(),
            thread_ranks.end(),
            std::vector<std::size_t>());
  for (std::size_t i = 0; i < nb_solutions; ++i) {
    thread_ranks[i % nb_threads].push_back(i);
  }

  auto run_ls = [&](const std::vector<std::size_t>& sol_ranks) {
    try {
      // Decide time allocated for each search.
      Timeout search_time;
      if (timeout.has_value()) {
        search_time = timeout.value() / sol_ranks.size();
      }

      for (auto rank : sol_ranks) {
        // Local search phase.
        vrptw::LocalSearch ls(_input,
                              tw_solutions[rank],
                              max_nb_jobs_removal,
                              search_time);
        ls.run();

        // Store solution indicators.
        sol_indicators[rank] = ls.indicators();
#ifdef LOG_LS_OPERATORS
        ls_stats[rank] = ls.get_stats();
#endif
      }
    } catch (...) {
      ep_m.lock();
      ep = std::current_exception();
      ep_m.unlock();
    }
  };

  std::vector<std::thread> ls_threads;

  for (const auto& sol_ranks : thread_ranks) {
    if (!sol_ranks.empty()) {
      ls_threads.emplace_back(run_ls, sol_ranks);
    }
  }

  for (auto& t : ls_threads) {
    t.join();
  }

  if (ep != nullptr) {
    std::rethrow_exception(ep);
  }

#ifdef LOG_LS_OPERATORS
  utils::log_LS_operators(ls_stats);
#endif

  auto best_indic =
    std::min_element(sol_indicators.cbegin(), sol_indicators.cend());

  return utils::format_solution(_input,
                                tw_solutions[std::distance(sol_indicators
                                                             .cbegin(),
                                                           best_indic)]);
}

} // namespace vroom
<commit_msg>Change VRPTW to use VRP::solve()<commit_after>/*

This file is part of VROOM.

Copyright (c) 2015-2022, Julien Coupey.
All rights reserved (see LICENSE).

*/

#include <mutex>
#include <set>
#include <thread>

#include "algorithms/heuristics/heuristics.h"
#include "algorithms/local_search/local_search.h"
#include "problems/vrptw/operators/cross_exchange.h"
#include "problems/vrptw/operators/intra_cross_exchange.h"
#include "problems/vrptw/operators/intra_exchange.h"
#include "problems/vrptw/operators/intra_mixed_exchange.h"
#include "problems/vrptw/operators/intra_or_opt.h"
#include "problems/vrptw/operators/intra_relocate.h"
#include "problems/vrptw/operators/intra_two_opt.h"
#include "problems/vrptw/operators/mixed_exchange.h"
#include "problems/vrptw/operators/or_opt.h"
#include "problems/vrptw/operators/pd_shift.h"
#include "problems/vrptw/operators/relocate.h"
#include "problems/vrptw/operators/reverse_two_opt.h"
#include "problems/vrptw/operators/route_exchange.h"
#include "problems/vrptw/operators/swap_star.h"
#include "problems/vrptw/operators/two_opt.h"
#include "problems/vrptw/operators/unassigned_exchange.h"
#include "problems/vrptw/vrptw.h"
#include "utils/helpers.h"

namespace vroom {

using TWSolution = std::vector<TWRoute>;

namespace vrptw {

using LocalSearch = ls::LocalSearch<TWRoute,
                                    vrptw::UnassignedExchange,
                                    vrptw::SwapStar,
                                    vrptw::CrossExchange,
                                    vrptw::MixedExchange,
                                    vrptw::TwoOpt,
                                    vrptw::ReverseTwoOpt,
                                    vrptw::Relocate,
                                    vrptw::OrOpt,
                                    vrptw::IntraExchange,
                                    vrptw::IntraCrossExchange,
                                    vrptw::IntraMixedExchange,
                                    vrptw::IntraRelocate,
                                    vrptw::IntraOrOpt,
                                    vrptw::IntraTwoOpt,
                                    vrptw::PDShift,
                                    vrptw::RouteExchange>;
} // namespace vrptw

const std::vector<HeuristicParameters> VRPTW::homogeneous_parameters =
  {HeuristicParameters(HEURISTIC::BASIC, INIT::HIGHER_AMOUNT, 0.3),
   HeuristicParameters(HEURISTIC::BASIC, INIT::HIGHER_AMOUNT, 0.4),
   HeuristicParameters(HEURISTIC::BASIC, INIT::EARLIEST_DEADLINE, 0.2),
   HeuristicParameters(HEURISTIC::BASIC, INIT::FURTHEST, 0.3),

   HeuristicParameters(HEURISTIC::BASIC, INIT::NONE, 0.4),
   HeuristicParameters(HEURISTIC::BASIC, INIT::HIGHER_AMOUNT, 0.5),
   HeuristicParameters(HEURISTIC::BASIC, INIT::FURTHEST, 0.4),
   HeuristicParameters(HEURISTIC::BASIC, INIT::FURTHEST, 0.5),

   HeuristicParameters(HEURISTIC::BASIC, INIT::HIGHER_AMOUNT, 0.1),
   HeuristicParameters(HEURISTIC::BASIC, INIT::HIGHER_AMOUNT, 0.6),
   HeuristicParameters(HEURISTIC::BASIC, INIT::FURTHEST, 0.2),
   HeuristicParameters(HEURISTIC::BASIC, INIT::FURTHEST, 0.7),

   HeuristicParameters(HEURISTIC::BASIC, INIT::HIGHER_AMOUNT, 0.2),
   HeuristicParameters(HEURISTIC::BASIC, INIT::HIGHER_AMOUNT, 0.7),
   HeuristicParameters(HEURISTIC::BASIC, INIT::HIGHER_AMOUNT, 1.4),
   HeuristicParameters(HEURISTIC::BASIC, INIT::FURTHEST, 0.1),

   HeuristicParameters(HEURISTIC::BASIC, INIT::NONE, 0),
   HeuristicParameters(HEURISTIC::BASIC, INIT::NONE, 0.1),
   HeuristicParameters(HEURISTIC::BASIC, INIT::NONE, 0.3),
   HeuristicParameters(HEURISTIC::BASIC, INIT::NONE, 0.8),

   HeuristicParameters(HEURISTIC::BASIC, INIT::EARLIEST_DEADLINE, 0.5),
   HeuristicParameters(HEURISTIC::BASIC, INIT::EARLIEST_DEADLINE, 0.8),
   HeuristicParameters(HEURISTIC::BASIC, INIT::EARLIEST_DEADLINE, 2.4),
   HeuristicParameters(HEURISTIC::BASIC, INIT::FURTHEST, 1.2),

   HeuristicParameters(HEURISTIC::BASIC, INIT::NONE, 1),
   HeuristicParameters(HEURISTIC::BASIC, INIT::HIGHER_AMOUNT, 1.3),
   HeuristicParameters(HEURISTIC::BASIC, INIT::EARLIEST_DEADLINE, 0),
   HeuristicParameters(HEURISTIC::BASIC, INIT::EARLIEST_DEADLINE, 0.3),

   HeuristicParameters(HEURISTIC::BASIC, INIT::EARLIEST_DEADLINE, 2),
   HeuristicParameters(HEURISTIC::BASIC, INIT::FURTHEST, 0),
   HeuristicParameters(HEURISTIC::BASIC, INIT::FURTHEST, 0.9),
   HeuristicParameters(HEURISTIC::BASIC, INIT::FURTHEST, 1)};

const std::vector<HeuristicParameters> VRPTW::heterogeneous_parameters =
  {HeuristicParameters(HEURISTIC::DYNAMIC, INIT::HIGHER_AMOUNT, 0.5),
   HeuristicParameters(HEURISTIC::DYNAMIC, INIT::HIGHER_AMOUNT, 0.9),
   HeuristicParameters(HEURISTIC::DYNAMIC, INIT::EARLIEST_DEADLINE, 0.4),
   HeuristicParameters(HEURISTIC::DYNAMIC, INIT::FURTHEST, 0.4),

   HeuristicParameters(HEURISTIC::DYNAMIC, INIT::HIGHER_AMOUNT, 0.8),
   HeuristicParameters(HEURISTIC::DYNAMIC, INIT::EARLIEST_DEADLINE, 0.6),
   HeuristicParameters(HEURISTIC::DYNAMIC, INIT::EARLIEST_DEADLINE, 0.9),
   HeuristicParameters(HEURISTIC::DYNAMIC, INIT::FURTHEST, 0.6),

   HeuristicParameters(HEURISTIC::DYNAMIC, INIT::HIGHER_AMOUNT, 1.8),
   HeuristicParameters(HEURISTIC::DYNAMIC, INIT::EARLIEST_DEADLINE, 1.1),
   HeuristicParameters(HEURISTIC::DYNAMIC, INIT::EARLIEST_DEADLINE, 1.4),
   HeuristicParameters(HEURISTIC::DYNAMIC, INIT::FURTHEST, 0.7),

   HeuristicParameters(HEURISTIC::DYNAMIC, INIT::NONE, 1.3),
   HeuristicParameters(HEURISTIC::DYNAMIC, INIT::HIGHER_AMOUNT, 2.4),
   HeuristicParameters(HEURISTIC::DYNAMIC, INIT::EARLIEST_DEADLINE, 0.3),
   HeuristicParameters(HEURISTIC::DYNAMIC, INIT::FURTHEST, 1.2),

   HeuristicParameters(HEURISTIC::DYNAMIC, INIT::NONE, 1.2),
   HeuristicParameters(HEURISTIC::DYNAMIC, INIT::HIGHER_AMOUNT, 0.6),
   HeuristicParameters(HEURISTIC::DYNAMIC, INIT::HIGHER_AMOUNT, 1.6),
   HeuristicParameters(HEURISTIC::DYNAMIC, INIT::EARLIEST_DEADLINE, 0.2),

   HeuristicParameters(HEURISTIC::DYNAMIC, INIT::EARLIEST_DEADLINE, 1.7),
   HeuristicParameters(HEURISTIC::DYNAMIC, INIT::EARLIEST_DEADLINE, 2),
   HeuristicParameters(HEURISTIC::DYNAMIC, INIT::FURTHEST, 0.5),
   HeuristicParameters(HEURISTIC::DYNAMIC, INIT::FURTHEST, 1.5),

   HeuristicParameters(HEURISTIC::DYNAMIC, INIT::NONE, 1.5),
   HeuristicParameters(HEURISTIC::DYNAMIC, INIT::NONE, 2.2),
   HeuristicParameters(HEURISTIC::DYNAMIC, INIT::HIGHER_AMOUNT, 2.1),
   HeuristicParameters(HEURISTIC::DYNAMIC, INIT::EARLIEST_DEADLINE, 0.5),

   HeuristicParameters(HEURISTIC::DYNAMIC, INIT::EARLIEST_DEADLINE, 1.2),
   HeuristicParameters(HEURISTIC::DYNAMIC, INIT::FURTHEST, 0.1),
   HeuristicParameters(HEURISTIC::DYNAMIC, INIT::FURTHEST, 0.9),
   HeuristicParameters(HEURISTIC::DYNAMIC, INIT::FURTHEST, 1.1)};

VRPTW::VRPTW(const Input& input) : VRP(input) {
}

Solution VRPTW::solve(unsigned exploration_level,
                      unsigned nb_threads,
                      const Timeout& timeout,
                      const std::vector<HeuristicParameters>& h_param) const {
  return VRP::solve<TWRoute, TWSolution, vrptw::LocalSearch>(exploration_level, nb_threads, timeout, h_param, homogeneous_parameters, heterogeneous_parameters);
}

} // namespace vroom
<|endoftext|>


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

  Program:   Insight Segmentation & Registration Toolkit
  Module:    itkDummyImageToListAdaptorTest.cxx
  Language:  C++
  Date:      $Date$
  Version:   $Revision$

  Copyright (c) 2002 Insight Consortium. All rights reserved.
  See ITKCopyright.txt or http://www.itk.org/HTML/Copyright.htm for details.

     This software is distributed WITHOUT ANY WARRANTY; without even
     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
     PURPOSE.  See the above copyright notices for more information.

=========================================================================*/
#include <time.h>

#include "itkFixedArray.h"
#include "itkImage.h"
#include "itkImageAdaptor.h"
#include "itkImageRegionIterator.h"
#include "itkPixelTraits.h"

#include "itkListSampleBase.h"
#include "itkImageToListAdaptor.h"
#include "itkScalarToArrayCastImageFilter.h"

#include "itkImage.h"
#include "itkObject.h"
#include "itkMacro.h"
#include "itkPixelTraits.h"

template < class TImage, class TMeasurementVector = ITK_TYPENAME TImage::PixelType >
class ITK_EXPORT DummyImageToListAdaptor :
  public itk::Statistics::ListSampleBase< TMeasurementVector >
{
public:
  typedef DummyImageToListAdaptor Self ;
  typedef itk::Statistics::ListSampleBase< TMeasurementVector > Superclass ;

  typedef itk::SmartPointer< Self > Pointer ;
  typedef itk::SmartPointer< const Self > ConstPointer ;

  itkTypeMacro( DummyImageToListAdaptor, Object ) ;
  itkNewMacro( Self ) ;

  typedef typename TImage::PixelType PixelType ;
  typedef typename itk::PixelTraits< PixelType >::ValueType MeasurementType ;
  itkStaticConstMacro( MeasurementVectorSize, unsigned int,
                       itk::PixelTraits< PixelType >::Dimension ) ;

  typedef TMeasurementVector MeasurementVectorType ;

  unsigned int Size() const
  { return 1 ;}

  float GetTotalFrequency() const
  { return 1 ;}

  float GetFrequency(const unsigned long& id) const
  { return id ; }

  virtual MeasurementVectorType GetMeasurementVector(const unsigned long& id)
  {
    if( m_UseBuffer )
      {
      return *(reinterpret_cast< MeasurementVectorType* >
               (&(*m_ImageBuffer)[id]))  ;
      }
    else
      {
      return *(reinterpret_cast< MeasurementVectorType* >
               (&(m_Image->GetPixel( m_Image->ComputeIndex( id ))) ) )   ;
      }
  }

  void SetImage( TImage* image )
  {
    m_Image = image ;
    m_ImageBuffer = m_Image->GetPixelContainer() ;
    if ( strcmp( m_Image->GetNameOfClass(), "Image" ) != 0 )
      {
      m_UseBuffer = false ;
      }
    else
      {
      m_UseBuffer = true ;
      }
  }

protected:
  DummyImageToListAdaptor()
  { m_Image = 0 ; }

  virtual ~DummyImageToListAdaptor() {}

  typename TImage::Pointer m_Image ;
  typename TImage::PixelContainer* m_ImageBuffer ;
  MeasurementVectorType m_TempVector ;
  bool m_UseBuffer ;

private:
  DummyImageToListAdaptor(const Self&) ;
  void operator=(const Self&) ;

} ;

template < class TImage >
class ITK_EXPORT DummyScalarImageToListAdaptor :
  public DummyImageToListAdaptor< TImage, itk::FixedArray< typename TImage::PixelType, 1> >
{
public:
  typedef DummyScalarImageToListAdaptor Self ;
  typedef DummyImageToListAdaptor<
    TImage, itk::FixedArray< typename TImage::PixelType, 1> > Superclass ;

  typedef itk::SmartPointer< Self > Pointer ;
  typedef itk::SmartPointer< const Self > ConstPointer ;

  itkTypeMacro( DummyScalarImageToListAdaptor, DummyImageToListAdaptor ) ;
  itkNewMacro( Self ) ;

  typedef typename Superclass::MeasurementVectorType MeasurementVectorType ;

  MeasurementVectorType GetMeasurementVector(const unsigned long& id)
  {
    if( m_UseBuffer )
      {
      m_TempVector[0] = (*m_ImageBuffer)[id] ;
      }
    else
      {
      m_TempVector[0] = m_Image->GetPixel( m_Image->ComputeIndex( id ) )  ;
      }
    return m_TempVector  ;
  }
protected:
  DummyScalarImageToListAdaptor() {}
  virtual ~DummyScalarImageToListAdaptor() {}
} ; // end of class

template< class TImage, class TCoordRep >
struct ImageJointDomainTraits
{
  typedef ImageJointDomainTraits Self ;

  typedef itk::PixelTraits< typename TImage::PixelType > PixelTraitsType ;
  itkStaticConstMacro(Size,
                      unsigned int,
                      TImage::ImageDimension +
                      PixelTraitsType::Dimension ) ;
  typedef itk::JoinTraits<
    TCoordRep,
    PixelTraitsType::ValueType > JoinTraitsType ;

  typedef JoinTraitsType::ValueType MeasurementType ;

  typedef itk::FixedArray< MeasurementType, itkGetStaticConstMacro(Size) >
  MeasurementVectorType ;
} ; // end of ImageJointDomainTraits

template < class TImage, class TCoordRep >
class ITK_EXPORT DummyJointDomainImageToListAdaptor :
  public DummyImageToListAdaptor< TImage,
                                  ImageJointDomainTraits<
  TImage, TCoordRep >::MeasurementVectorType >
{
public:
  typedef DummyJointDomainImageToListAdaptor Self ;
  typedef DummyImageToListAdaptor< TImage,
                                   ImageJointDomainTraits< TImage, TCoordRep >::MeasurementVectorType >
  Superclass ;

  typedef itk::SmartPointer< Self > Pointer ;
  typedef itk::SmartPointer< const Self > ConstPointer ;

  itkTypeMacro( DummyJointDomainImageToListAdaptor, DummyImageToListAdaptor ) ;
  itkNewMacro( Self ) ;

  typedef typename Superclass::MeasurementType MeasurementType ;
  typedef typename Superclass::MeasurementVectorType MeasurementVectorType ;

  itkStaticConstMacro(RangeDomainDimension,
                      unsigned int,
                      itk::PixelTraits<
                      typename TImage::PixelType >::Dimension) ;
  typedef typename itk::FixedArray<
    MeasurementType,
    itkGetStaticConstMacro( RangeDomainDimension ) >
  RangeDomainMeasurementVectorType ;

  MeasurementVectorType GetMeasurementVector(const unsigned long& id)
  {
    typename itk::Point<MeasurementType, TImage::ImageDimension> point ;
    typename TImage::IndexType index = m_Image->ComputeIndex( id ) ;
    m_Image->TransformIndexToPhysicalPoint( index, point ) ;

    for ( unsigned int i = 0 ; i < TImage::ImageDimension ; ++i )
      {
      m_TempVector[i] = point[i] ;
      }

    if( m_UseBuffer )
      {
      m_TempVector2 =
        *(reinterpret_cast< RangeDomainMeasurementVectorType* >
          (&(*m_ImageBuffer)[id]))  ;
      }
    else
      {
      m_TempVector2 =
        *(reinterpret_cast< RangeDomainMeasurementVectorType* >
          (&(m_Image->GetPixel( m_Image->ComputeIndex( id ) ) ) ) ) ;
      }

    for ( unsigned int i = TImage::ImageDimension ; i < MeasurementVectorType::Length ; ++i )
      {
      m_TempVector[i]= m_TempVector2[i - TImage::ImageDimension] ;
      }
    return m_TempVector ;
  }
protected:
  DummyJointDomainImageToListAdaptor() {}
  virtual ~DummyJointDomainImageToListAdaptor() {}
  RangeDomainMeasurementVectorType m_TempVector2 ;
} ; // end of class

int itkDummyImageToListAdaptorTest(int, char* [] )
{
  typedef int ScalarPixelType ;
  typedef itk::FixedArray< ScalarPixelType, 1 > ArrayPixelType ;
  typedef itk::Vector< ScalarPixelType, 2 > VectorPixelType ;

  typedef itk::Image< ScalarPixelType, 3 > ScalarImageType ;
  typedef itk::Image< ArrayPixelType, 3 > ArrayImageType ;
  typedef itk::Image< VectorPixelType, 3 > VectorImageType ;

  typedef itk::ImageRegionIterator< ScalarImageType > ScalarImageIteratorType ;
  typedef itk::ImageRegionIterator< ArrayImageType > ArrayImageIteratorType ;
  typedef itk::ImageRegionIterator< VectorImageType > VectorImageIteratorType ;

  itk::Size< 3 > size ;
  size.Fill(10) ;

  ScalarImageType::Pointer scalarImage = ScalarImageType::New() ;
  scalarImage->SetRegions(size) ;
  scalarImage->Allocate() ;

  int count = 0 ;
  ScalarImageIteratorType s_iter =
    ScalarImageIteratorType(scalarImage,
                            scalarImage->GetLargestPossibleRegion() ) ;
  while ( !s_iter.IsAtEnd() )
    {
    s_iter.Set(count) ;
    ++count ;
    ++s_iter ;
    }

  VectorImageType::Pointer vectorImage = VectorImageType::New() ;
  vectorImage->SetRegions(size) ;
  vectorImage->Allocate() ;
  count = 0 ;
  VectorImageType::PixelType vPixel ;
  VectorImageIteratorType v_iter =
    VectorImageIteratorType(vectorImage,
                            vectorImage->GetLargestPossibleRegion()) ;
  while ( !v_iter.IsAtEnd() )
    {
    vPixel[0] = count ;
    vPixel[1] = count ;
    v_iter.Set( vPixel ) ;
    ++count ;
    ++v_iter ;
    }

  typedef DummyScalarImageToListAdaptor< ScalarImageType > ScalarListType ;
  ScalarListType::Pointer sList = ScalarListType::New() ;
  sList->SetImage( scalarImage ) ;

  typedef DummyImageToListAdaptor< VectorImageType > VectorListType ;
  VectorListType::Pointer vList = VectorListType::New() ;
  vList->SetImage( vectorImage ) ;

  typedef itk::ScalarToArrayCastImageFilter< ScalarImageType, ArrayImageType > CasterType ;
  CasterType::Pointer caster = CasterType::New() ;
  caster->SetInput( scalarImage ) ;
  caster->Update() ;

  typedef itk::Statistics::ImageToListAdaptor< ArrayImageType > ImageListType ;
  ImageListType::Pointer imageList = ImageListType::New() ;
  imageList->SetImage( caster->GetOutput() ) ;

  typedef DummyJointDomainImageToListAdaptor< VectorImageType,
    float > JointDomainImageListType ;
  JointDomainImageListType::Pointer jointDomainImageList =
    JointDomainImageListType::New() ;
  jointDomainImageList->SetImage( vectorImage ) ;

  std::cout << "Testing the each measurement values:" << std::endl ;
  for ( unsigned long i = 0 ; i < size[0] * size[1] * size[2] ; ++i )
    {
    if ( sList->GetMeasurementVector( i )[0] !=
         vList->GetMeasurementVector( i )[0]
         || sList->GetMeasurementVector( i )[0] !=
         imageList->GetMeasurementVector( i )[0]
         || sList->GetMeasurementVector( i )[0] !=
         jointDomainImageList->GetMeasurementVector( i )[3]
      )
      {
      std::cout << "ERROR: measurement mismatch!!!" << std::endl ;
      return EXIT_FAILURE ;
      }
    }
  std::cout << std::endl ;

  std::cout << "Scalar image (casted) pixel access performance test:" << std::endl ;
  time_t begin = clock() ;
  for ( unsigned long i = 0 ; i < size[0] * size[1] * size[2] ; ++i )
    {
    imageList->GetMeasurementVector( i )  ;
    }
  time_t end = clock() ;

  std::cout << "time: "
            << (double(end - begin) /CLOCKS_PER_SEC)
            << " seconds" << std::endl ;

  std::cout << "Scalar image pixel access performance test:" << std::endl ;
  begin = clock() ;
  for ( unsigned long i = 0 ; i < size[0] * size[1] * size[2] ; ++i )
    {
    sList->GetMeasurementVector( i )  ;
    }
  end = clock() ;

  std::cout << "time: "
            << (double(end - begin) /CLOCKS_PER_SEC)
            << " seconds" << std::endl ;

  std::cout << "Vector image pixel access performance test:" << std::endl ;
  begin = clock() ;
  for ( unsigned long i = 0 ; i < size[0] * size[1] * size[2] ; ++i )
    {
    vList->GetMeasurementVector( i )  ;
    }
  end = clock() ;

  std::cout << "time: "
            << (double(end - begin) /CLOCKS_PER_SEC)
            << " seconds" << std::endl ;

  std::cout << "Joint Domain Vector image pixel access performance test:" << std::endl ;
  begin = clock() ;
  for ( unsigned long i = 0 ; i < size[0] * size[1] * size[2] ; ++i )
    {
    std::cout << jointDomainImageList->GetMeasurementVector( i )
              << std::endl ;
    }
  end = clock() ;

  std::cout << "time: "
            << (double(end - begin) /CLOCKS_PER_SEC)
            << " seconds" << std::endl ;

  return EXIT_SUCCESS ;
}
<commit_msg><commit_after>/*=========================================================================

  Program:   Insight Segmentation & Registration Toolkit
  Module:    itkDummyImageToListAdaptorTest.cxx
  Language:  C++
  Date:      $Date$
  Version:   $Revision$

  Copyright (c) 2002 Insight Consortium. All rights reserved.
  See ITKCopyright.txt or http://www.itk.org/HTML/Copyright.htm for details.

     This software is distributed WITHOUT ANY WARRANTY; without even
     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
     PURPOSE.  See the above copyright notices for more information.

=========================================================================*/
#include <time.h>

#include "itkFixedArray.h"
#include "itkImage.h"
#include "itkImageAdaptor.h"
#include "itkImageRegionIterator.h"
#include "itkPixelTraits.h"

#include "itkListSampleBase.h"
#include "itkImageToListAdaptor.h"
#include "itkScalarToArrayCastImageFilter.h"

#include "itkImage.h"
#include "itkObject.h"
#include "itkMacro.h"
#include "itkPixelTraits.h"

template < class TImage, class TMeasurementVector = ITK_TYPENAME TImage::PixelType >
class ITK_EXPORT DummyImageToListAdaptor :
  public itk::Statistics::ListSampleBase< TMeasurementVector >
{
public:
  typedef DummyImageToListAdaptor Self ;
  typedef itk::Statistics::ListSampleBase< TMeasurementVector > Superclass ;

  typedef itk::SmartPointer< Self > Pointer ;
  typedef itk::SmartPointer< const Self > ConstPointer ;

  itkTypeMacro( DummyImageToListAdaptor, Object ) ;
  itkNewMacro( Self ) ;

  typedef typename TImage::PixelType PixelType ;
  typedef typename itk::PixelTraits< PixelType >::ValueType MeasurementType ;
  itkStaticConstMacro( MeasurementVectorSize, unsigned int,
                       itk::PixelTraits< PixelType >::Dimension ) ;

  typedef TMeasurementVector MeasurementVectorType ;

  unsigned int Size() const
  { return 1 ;}

  float GetTotalFrequency() const
  { return 1 ;}

  float GetFrequency(const unsigned long& id) const
  { return id ; }

  virtual MeasurementVectorType GetMeasurementVector(const unsigned long& id)
  {
    if( m_UseBuffer )
      {
      return *(reinterpret_cast< MeasurementVectorType* >
               (&(*m_ImageBuffer)[id]))  ;
      }
    else
      {
      return *(reinterpret_cast< MeasurementVectorType* >
               (&(m_Image->GetPixel( m_Image->ComputeIndex( id ))) ) )   ;
      }
  }

  void SetImage( TImage* image )
  {
    m_Image = image ;
    m_ImageBuffer = m_Image->GetPixelContainer() ;
    if ( strcmp( m_Image->GetNameOfClass(), "Image" ) != 0 )
      {
      m_UseBuffer = false ;
      }
    else
      {
      m_UseBuffer = true ;
      }
  }

protected:
  DummyImageToListAdaptor()
  { m_Image = 0 ; }

  virtual ~DummyImageToListAdaptor() {}

  typename TImage::Pointer m_Image ;
  typename TImage::PixelContainer* m_ImageBuffer ;
  MeasurementVectorType m_TempVector ;
  bool m_UseBuffer ;

private:
  DummyImageToListAdaptor(const Self&) ;
  void operator=(const Self&) ;

} ;

template < class TImage >
class ITK_EXPORT DummyScalarImageToListAdaptor :
  public DummyImageToListAdaptor< TImage, itk::FixedArray< typename TImage::PixelType, 1> >
{
public:
  typedef DummyScalarImageToListAdaptor Self ;
  typedef DummyImageToListAdaptor<
    TImage, itk::FixedArray< typename TImage::PixelType, 1> > Superclass ;

  typedef itk::SmartPointer< Self > Pointer ;
  typedef itk::SmartPointer< const Self > ConstPointer ;

  itkTypeMacro( DummyScalarImageToListAdaptor, DummyImageToListAdaptor ) ;
  itkNewMacro( Self ) ;

  typedef typename Superclass::MeasurementVectorType MeasurementVectorType ;

  MeasurementVectorType GetMeasurementVector(const unsigned long& id)
  {
    if( m_UseBuffer )
      {
      m_TempVector[0] = (*m_ImageBuffer)[id] ;
      }
    else
      {
      m_TempVector[0] = m_Image->GetPixel( m_Image->ComputeIndex( id ) )  ;
      }
    return m_TempVector  ;
  }
protected:
  DummyScalarImageToListAdaptor() {}
  virtual ~DummyScalarImageToListAdaptor() {}
} ; // end of class

template< class TImage, class TCoordRep >
struct ImageJointDomainTraits
{
  typedef ImageJointDomainTraits Self ;

  typedef itk::PixelTraits< typename TImage::PixelType > PixelTraitsType ;
  itkStaticConstMacro(Size,
                      unsigned int,
                      TImage::ImageDimension +
                      PixelTraitsType::Dimension ) ;
  typedef itk::JoinTraits<
    TCoordRep,
    typename PixelTraitsType::ValueType > JoinTraitsType ;

  typedef typename JoinTraitsType::ValueType MeasurementType ;

  typedef itk::FixedArray< MeasurementType, itkGetStaticConstMacro(Size) >
  MeasurementVectorType ;
} ; // end of ImageJointDomainTraits

template < class TImage, class TCoordRep >
class ITK_EXPORT DummyJointDomainImageToListAdaptor :
  public DummyImageToListAdaptor< TImage,
                                  typename ImageJointDomainTraits<
  TImage, TCoordRep >::MeasurementVectorType >
{
public:
  typedef DummyJointDomainImageToListAdaptor Self ;
  typedef DummyImageToListAdaptor< TImage,
                                   typename ImageJointDomainTraits< TImage, TCoordRep >::MeasurementVectorType >
  Superclass ;

  typedef itk::SmartPointer< Self > Pointer ;
  typedef itk::SmartPointer< const Self > ConstPointer ;

  itkTypeMacro( DummyJointDomainImageToListAdaptor, DummyImageToListAdaptor ) ;
  itkNewMacro( Self ) ;

  typedef typename Superclass::MeasurementType MeasurementType ;
  typedef typename Superclass::MeasurementVectorType MeasurementVectorType ;

  itkStaticConstMacro(RangeDomainDimension,
                      unsigned int,
                      itk::PixelTraits<
                      typename TImage::PixelType >::Dimension) ;
  typedef typename itk::FixedArray<
    MeasurementType,
    itkGetStaticConstMacro( RangeDomainDimension ) >
  RangeDomainMeasurementVectorType ;

  MeasurementVectorType GetMeasurementVector(const unsigned long& id)
  {
    typename itk::Point<MeasurementType, TImage::ImageDimension> point ;
    typename TImage::IndexType index = m_Image->ComputeIndex( id ) ;
    m_Image->TransformIndexToPhysicalPoint( index, point ) ;

    for ( unsigned int i = 0 ; i < TImage::ImageDimension ; ++i )
      {
      m_TempVector[i] = point[i] ;
      }

    if( m_UseBuffer )
      {
      m_TempVector2 =
        *(reinterpret_cast< RangeDomainMeasurementVectorType* >
          (&(*m_ImageBuffer)[id]))  ;
      }
    else
      {
      m_TempVector2 =
        *(reinterpret_cast< RangeDomainMeasurementVectorType* >
          (&(m_Image->GetPixel( m_Image->ComputeIndex( id ) ) ) ) ) ;
      }

    for ( unsigned int i = TImage::ImageDimension ; i < MeasurementVectorType::Length ; ++i )
      {
      m_TempVector[i]= m_TempVector2[i - TImage::ImageDimension] ;
      }
    return m_TempVector ;
  }
protected:
  DummyJointDomainImageToListAdaptor() {}
  virtual ~DummyJointDomainImageToListAdaptor() {}
  RangeDomainMeasurementVectorType m_TempVector2 ;
} ; // end of class

int itkDummyImageToListAdaptorTest(int, char* [] )
{
  typedef int ScalarPixelType ;
  typedef itk::FixedArray< ScalarPixelType, 1 > ArrayPixelType ;
  typedef itk::Vector< ScalarPixelType, 2 > VectorPixelType ;

  typedef itk::Image< ScalarPixelType, 3 > ScalarImageType ;
  typedef itk::Image< ArrayPixelType, 3 > ArrayImageType ;
  typedef itk::Image< VectorPixelType, 3 > VectorImageType ;

  typedef itk::ImageRegionIterator< ScalarImageType > ScalarImageIteratorType ;
  typedef itk::ImageRegionIterator< ArrayImageType > ArrayImageIteratorType ;
  typedef itk::ImageRegionIterator< VectorImageType > VectorImageIteratorType ;

  itk::Size< 3 > size ;
  size.Fill(10) ;

  ScalarImageType::Pointer scalarImage = ScalarImageType::New() ;
  scalarImage->SetRegions(size) ;
  scalarImage->Allocate() ;

  int count = 0 ;
  ScalarImageIteratorType s_iter =
    ScalarImageIteratorType(scalarImage,
                            scalarImage->GetLargestPossibleRegion() ) ;
  while ( !s_iter.IsAtEnd() )
    {
    s_iter.Set(count) ;
    ++count ;
    ++s_iter ;
    }

  VectorImageType::Pointer vectorImage = VectorImageType::New() ;
  vectorImage->SetRegions(size) ;
  vectorImage->Allocate() ;
  count = 0 ;
  VectorImageType::PixelType vPixel ;
  VectorImageIteratorType v_iter =
    VectorImageIteratorType(vectorImage,
                            vectorImage->GetLargestPossibleRegion()) ;
  while ( !v_iter.IsAtEnd() )
    {
    vPixel[0] = count ;
    vPixel[1] = count ;
    v_iter.Set( vPixel ) ;
    ++count ;
    ++v_iter ;
    }

  typedef DummyScalarImageToListAdaptor< ScalarImageType > ScalarListType ;
  ScalarListType::Pointer sList = ScalarListType::New() ;
  sList->SetImage( scalarImage ) ;

  typedef DummyImageToListAdaptor< VectorImageType > VectorListType ;
  VectorListType::Pointer vList = VectorListType::New() ;
  vList->SetImage( vectorImage ) ;

  typedef itk::ScalarToArrayCastImageFilter< ScalarImageType, ArrayImageType > CasterType ;
  CasterType::Pointer caster = CasterType::New() ;
  caster->SetInput( scalarImage ) ;
  caster->Update() ;

  typedef itk::Statistics::ImageToListAdaptor< ArrayImageType > ImageListType ;
  ImageListType::Pointer imageList = ImageListType::New() ;
  imageList->SetImage( caster->GetOutput() ) ;

  typedef DummyJointDomainImageToListAdaptor< VectorImageType,
    float > JointDomainImageListType ;
  JointDomainImageListType::Pointer jointDomainImageList =
    JointDomainImageListType::New() ;
  jointDomainImageList->SetImage( vectorImage ) ;

  std::cout << "Testing the each measurement values:" << std::endl ;
  for ( unsigned long i = 0 ; i < size[0] * size[1] * size[2] ; ++i )
    {
    if ( sList->GetMeasurementVector( i )[0] !=
         vList->GetMeasurementVector( i )[0]
         || sList->GetMeasurementVector( i )[0] !=
         imageList->GetMeasurementVector( i )[0]
         || sList->GetMeasurementVector( i )[0] !=
         jointDomainImageList->GetMeasurementVector( i )[3]
      )
      {
      std::cout << "ERROR: measurement mismatch!!!" << std::endl ;
      return EXIT_FAILURE ;
      }
    }
  std::cout << std::endl ;

  std::cout << "Scalar image (casted) pixel access performance test:" << std::endl ;
  time_t begin = clock() ;
  for ( unsigned long i = 0 ; i < size[0] * size[1] * size[2] ; ++i )
    {
    imageList->GetMeasurementVector( i )  ;
    }
  time_t end = clock() ;

  std::cout << "time: "
            << (double(end - begin) /CLOCKS_PER_SEC)
            << " seconds" << std::endl ;

  std::cout << "Scalar image pixel access performance test:" << std::endl ;
  begin = clock() ;
  for ( unsigned long i = 0 ; i < size[0] * size[1] * size[2] ; ++i )
    {
    sList->GetMeasurementVector( i )  ;
    }
  end = clock() ;

  std::cout << "time: "
            << (double(end - begin) /CLOCKS_PER_SEC)
            << " seconds" << std::endl ;

  std::cout << "Vector image pixel access performance test:" << std::endl ;
  begin = clock() ;
  for ( unsigned long i = 0 ; i < size[0] * size[1] * size[2] ; ++i )
    {
    vList->GetMeasurementVector( i )  ;
    }
  end = clock() ;

  std::cout << "time: "
            << (double(end - begin) /CLOCKS_PER_SEC)
            << " seconds" << std::endl ;

  std::cout << "Joint Domain Vector image pixel access performance test:" << std::endl ;
  begin = clock() ;
  for ( unsigned long i = 0 ; i < size[0] * size[1] * size[2] ; ++i )
    {
    std::cout << jointDomainImageList->GetMeasurementVector( i )
              << std::endl ;
    }
  end = clock() ;

  std::cout << "time: "
            << (double(end - begin) /CLOCKS_PER_SEC)
            << " seconds" << std::endl ;

  return EXIT_SUCCESS ;
}
<|endoftext|>


<commit_before>#include <blackhole/formatter/string.hpp>
#include <blackhole/log.hpp>
#include <blackhole/logger.hpp>
#include <blackhole/logger/wrapper.hpp>
#include <blackhole/record.hpp>
#include <blackhole/sink/stream.hpp>

#include "global.hpp"

using namespace blackhole;

namespace {

class logger_factory_t {
public:
    template<class Logger>
    static Logger create() {
        Logger logger;
        auto formatter = utils::make_unique<
            formatter::string_t
        >("[%(timestamp)s]: %(message)s");

        auto sink = utils::make_unique<
            sink::stream_t
        >(sink::stream_t::output_t::stdout);

        auto frontend = utils::make_unique<
            frontend_t<
                formatter::string_t,
                sink::stream_t
            >
        >(std::move(formatter), std::move(sink));

        logger.add_frontend(std::move(frontend));
        return logger;
    }
};

} // namespace

TEST(Wrapper, Class) {
    verbose_logger_t<testing::level> log;
    wrapper_t<verbose_logger_t<testing::level>> wrapper(log, log::attributes_t({
        attribute::make("answer", 42)
    }));
    UNUSED(wrapper);
}

TEST(Wrapper, Usage) {
    auto log = logger_factory_t::create<logger_base_t>();
    log.add_attribute(attribute::make("id", 100500));

    {
        wrapper_t<logger_base_t> wrapper(log, log::attributes_t({
            attribute::make("answer", 42)
        }));

        auto record = log.open_record();
        ASSERT_EQ(1, record.attributes.count("id"));
        EXPECT_EQ(log::attribute_value_t(100500), record.attributes["id"].value);
        EXPECT_EQ(0, record.attributes.count("answer"));

        record = wrapper.open_record();
        ASSERT_EQ(1, record.attributes.count("id"));
        EXPECT_EQ(log::attribute_value_t(100500), record.attributes["id"].value);
        ASSERT_EQ(1, record.attributes.count("answer"));
        EXPECT_EQ(log::attribute_value_t(42), record.attributes["answer"].value);
    }

    auto record = log.open_record();
    ASSERT_EQ(1, record.attributes.count("id"));
    EXPECT_EQ(log::attribute_value_t(100500), record.attributes["id"].value);
    EXPECT_EQ(0, record.attributes.count("answer"));
}

TEST(Wrapper, UsageWithVerboseLogger) {
    auto log = logger_factory_t::create<verbose_logger_t<testing::level>>();
    log.add_attribute(attribute::make("id", 100500));

    {
        wrapper_t<verbose_logger_t<testing::level>> wrapper(
            log,
            log::attributes_t({
                attribute::make("answer", 42)
            })
        );

        auto record = log.open_record(testing::info);
        ASSERT_EQ(1, record.attributes.count("id"));
        EXPECT_EQ(log::attribute_value_t(100500), record.attributes["id"].value);

        ASSERT_EQ(1, record.attributes.count("severity"));
        EXPECT_EQ(testing::info,
                  boost::get<
                        aux::underlying_type<testing::level>::type
                  >(record.attributes["severity"].value)
                );

        EXPECT_EQ(0, record.attributes.count("answer"));

        record = wrapper.open_record(testing::info);
        ASSERT_EQ(1, record.attributes.count("id"));
        EXPECT_EQ(log::attribute_value_t(100500), record.attributes["id"].value);

        ASSERT_EQ(1, record.attributes.count("severity"));
        EXPECT_EQ(testing::info,
                  boost::get<
                        aux::underlying_type<testing::level>::type
                  >(record.attributes["severity"].value)
                );

        ASSERT_EQ(1, record.attributes.count("answer"));
        EXPECT_EQ(log::attribute_value_t(42), record.attributes["answer"].value);
    }

    auto record = log.open_record(testing::info);
    ASSERT_EQ(1, record.attributes.count("id"));
    EXPECT_EQ(log::attribute_value_t(100500), record.attributes["id"].value);

    ASSERT_EQ(1, record.attributes.count("severity"));
    EXPECT_EQ(testing::info,
              boost::get<
                    aux::underlying_type<testing::level>::type
              >(record.attributes["severity"].value)
            );

    EXPECT_EQ(0, record.attributes.count("answer"));
}

TEST(Wrapper, MacroUsage) {
    auto log = logger_factory_t::create<verbose_logger_t<testing::level>>();
    log.add_attribute(attribute::make("id", 100500));

    {
        wrapper_t<verbose_logger_t<testing::level>> wrapper(
            log,
            log::attributes_t({
                attribute::make("answer", 42)
            })
        );

        BH_LOG(wrapper, testing::info, "everything is bad");
    }
}
<commit_msg>[Unit Testing] No more spam from testing logger.<commit_after>#include <blackhole/formatter/string.hpp>
#include <blackhole/log.hpp>
#include <blackhole/logger.hpp>
#include <blackhole/logger/wrapper.hpp>
#include <blackhole/record.hpp>
#include <blackhole/sink/null.hpp>

#include "global.hpp"

using namespace blackhole;

namespace {

class logger_factory_t {
public:
    template<class Logger>
    static Logger create() {
        Logger logger;
        auto formatter = utils::make_unique<
            formatter::string_t
        >("[%(timestamp)s]: %(message)s");

        auto sink = utils::make_unique<
            sink::null_t
        >();

        auto frontend = utils::make_unique<
            frontend_t<
                formatter::string_t,
                sink::null_t
            >
        >(std::move(formatter), std::move(sink));

        logger.add_frontend(std::move(frontend));
        return logger;
    }
};

} // namespace

TEST(Wrapper, Class) {
    verbose_logger_t<testing::level> log;
    wrapper_t<verbose_logger_t<testing::level>> wrapper(log, log::attributes_t({
        attribute::make("answer", 42)
    }));
    UNUSED(wrapper);
}

TEST(Wrapper, Usage) {
    auto log = logger_factory_t::create<logger_base_t>();
    log.add_attribute(attribute::make("id", 100500));

    {
        wrapper_t<logger_base_t> wrapper(log, log::attributes_t({
            attribute::make("answer", 42)
        }));

        auto record = log.open_record();
        ASSERT_EQ(1, record.attributes.count("id"));
        EXPECT_EQ(log::attribute_value_t(100500), record.attributes["id"].value);
        EXPECT_EQ(0, record.attributes.count("answer"));

        record = wrapper.open_record();
        ASSERT_EQ(1, record.attributes.count("id"));
        EXPECT_EQ(log::attribute_value_t(100500), record.attributes["id"].value);
        ASSERT_EQ(1, record.attributes.count("answer"));
        EXPECT_EQ(log::attribute_value_t(42), record.attributes["answer"].value);
    }

    auto record = log.open_record();
    ASSERT_EQ(1, record.attributes.count("id"));
    EXPECT_EQ(log::attribute_value_t(100500), record.attributes["id"].value);
    EXPECT_EQ(0, record.attributes.count("answer"));
}

TEST(Wrapper, UsageWithVerboseLogger) {
    auto log = logger_factory_t::create<verbose_logger_t<testing::level>>();
    log.add_attribute(attribute::make("id", 100500));

    {
        wrapper_t<verbose_logger_t<testing::level>> wrapper(
            log,
            log::attributes_t({
                attribute::make("answer", 42)
            })
        );

        auto record = log.open_record(testing::info);
        ASSERT_EQ(1, record.attributes.count("id"));
        EXPECT_EQ(log::attribute_value_t(100500), record.attributes["id"].value);

        ASSERT_EQ(1, record.attributes.count("severity"));
        EXPECT_EQ(testing::info,
                  boost::get<
                        aux::underlying_type<testing::level>::type
                  >(record.attributes["severity"].value)
                );

        EXPECT_EQ(0, record.attributes.count("answer"));

        record = wrapper.open_record(testing::info);
        ASSERT_EQ(1, record.attributes.count("id"));
        EXPECT_EQ(log::attribute_value_t(100500), record.attributes["id"].value);

        ASSERT_EQ(1, record.attributes.count("severity"));
        EXPECT_EQ(testing::info,
                  boost::get<
                        aux::underlying_type<testing::level>::type
                  >(record.attributes["severity"].value)
                );

        ASSERT_EQ(1, record.attributes.count("answer"));
        EXPECT_EQ(log::attribute_value_t(42), record.attributes["answer"].value);
    }

    auto record = log.open_record(testing::info);
    ASSERT_EQ(1, record.attributes.count("id"));
    EXPECT_EQ(log::attribute_value_t(100500), record.attributes["id"].value);

    ASSERT_EQ(1, record.attributes.count("severity"));
    EXPECT_EQ(testing::info,
              boost::get<
                    aux::underlying_type<testing::level>::type
              >(record.attributes["severity"].value)
            );

    EXPECT_EQ(0, record.attributes.count("answer"));
}

TEST(Wrapper, MacroUsage) {
    auto log = logger_factory_t::create<verbose_logger_t<testing::level>>();
    log.add_attribute(attribute::make("id", 100500));

    {
        wrapper_t<verbose_logger_t<testing::level>> wrapper(
            log,
            log::attributes_t({
                attribute::make("answer", 42)
            })
        );

        BH_LOG(wrapper, testing::info, "everything is bad");
    }
}
<|endoftext|>


<commit_before>#include <possumwood_sdk/node_implementation.h>

#include <CGAL/squared_distance_3.h>

#include <CGAL/Surface_mesh_simplification/edge_collapse.h>

#include <CGAL/Surface_mesh_simplification/Policies/Edge_collapse/Count_stop_predicate.h>
#include <CGAL/Surface_mesh_simplification/Policies/Edge_collapse/Count_ratio_stop_predicate.h>
#include <CGAL/Surface_mesh_simplification/Policies/Edge_collapse/Edge_length_stop_predicate.h>

#include <CGAL/Surface_mesh_simplification/Policies/Edge_collapse/Edge_length_cost.h>
#include <CGAL/Surface_mesh_simplification/Policies/Edge_collapse/LindstromTurk_cost.h>

#include <CGAL/Surface_mesh_simplification/Policies/Edge_collapse/Midpoint_placement.h>

#include "possumwood_sdk/datatypes/enum.h"

#include "datatypes/polyhedron.h"

#include "cgal.h"

namespace SMS = CGAL::Surface_mesh_simplification;
using namespace std::placeholders;

namespace {

dependency_graph::InAttr<std::shared_ptr<const possumwood::CGALPolyhedron>> a_inMesh;
dependency_graph::InAttr<float> a_stopParam;
dependency_graph::InAttr<possumwood::Enum> a_stopCondition, a_cost;
dependency_graph::OutAttr<std::shared_ptr<const possumwood::CGALPolyhedron>> a_outMesh;

dependency_graph::State compute(dependency_graph::Values& data) {
	std::shared_ptr<const possumwood::CGALPolyhedron> inMesh = data.get(a_inMesh);
	const float stopCondition = data.get(a_stopParam);
	const unsigned algorithmId = data.get(a_stopCondition).intValue() + data.get(a_cost).intValue();

	if(inMesh) {
		std::unique_ptr<possumwood::CGALPolyhedron> mesh(new possumwood::CGALPolyhedron(*inMesh));

		switch(algorithmId) {
			case 11:
				SMS::edge_collapse(*mesh, SMS::Count_stop_predicate<possumwood::CGALPolyhedron>(stopCondition),
				                   CGAL::parameters::get_cost(SMS::Edge_length_cost<possumwood::CGALPolyhedron>())
				                       .get_placement(SMS::Midpoint_placement<possumwood::CGALPolyhedron>()));
				break;

			case 12:
				SMS::edge_collapse(*mesh, SMS::Count_ratio_stop_predicate<possumwood::CGALPolyhedron>(stopCondition),
				                   CGAL::parameters::get_cost(SMS::Edge_length_cost<possumwood::CGALPolyhedron>())
				                       .get_placement(SMS::Midpoint_placement<possumwood::CGALPolyhedron>()));
				break;

			case 13:
				SMS::edge_collapse(*mesh, SMS::Edge_length_stop_predicate<float>(stopCondition),
				                   CGAL::parameters::get_cost(SMS::Edge_length_cost<possumwood::CGALPolyhedron>())
				                       .get_placement(SMS::Midpoint_placement<possumwood::CGALPolyhedron>()));
				break;
			case 21:
				SMS::edge_collapse(*mesh, SMS::Count_stop_predicate<possumwood::CGALPolyhedron>(stopCondition),
				                   CGAL::parameters::get_cost(SMS::LindstromTurk_cost<possumwood::CGALPolyhedron>())
				                       .get_placement(SMS::Midpoint_placement<possumwood::CGALPolyhedron>()));
				break;

			case 22:
				SMS::edge_collapse(*mesh, SMS::Count_ratio_stop_predicate<possumwood::CGALPolyhedron>(stopCondition),
				                   CGAL::parameters::get_cost(SMS::LindstromTurk_cost<possumwood::CGALPolyhedron>())
				                       .get_placement(SMS::Midpoint_placement<possumwood::CGALPolyhedron>()));
				break;

			case 23:
				SMS::edge_collapse(*mesh, SMS::Edge_length_stop_predicate<float>(stopCondition),
				                   CGAL::parameters::get_cost(SMS::LindstromTurk_cost<possumwood::CGALPolyhedron>())
				                       .get_placement(SMS::Midpoint_placement<possumwood::CGALPolyhedron>()));
				break;
		}

		data.set(a_outMesh, std::shared_ptr<const possumwood::CGALPolyhedron>(mesh.release()));
	}
	else
		data.set(a_outMesh, std::shared_ptr<const possumwood::CGALPolyhedron>());

	return dependency_graph::State();
}

void init(possumwood::Metadata& meta) {
	meta.addAttribute(a_inMesh, "input");
	meta.addAttribute(
	    a_stopCondition, "stop_condition",
	    possumwood::Enum({std::make_pair("Count_stop_predicate", 1), std::make_pair("Count_ratio_stop_predicate", 2),
	                      std::make_pair("Edge_length_stop_predicate", 3)}));
	meta.addAttribute(a_cost, "cost", possumwood::Enum({std::make_pair("Edge_length_cost", 10),
	                                                    std::make_pair("LindstromTurk_cost", 20)}));
	meta.addAttribute(a_stopParam, "stop_parameter", 1000.0f);
	meta.addAttribute(a_outMesh, "output");

	meta.addInfluence(a_inMesh, a_outMesh);
	meta.addInfluence(a_stopCondition, a_outMesh);
	meta.addInfluence(a_cost, a_outMesh);
	meta.addInfluence(a_stopParam, a_outMesh);

	meta.setCompute(compute);
}

possumwood::NodeImplementation s_impl("cgal/simplification/simplification", init);
}
<commit_msg>Added placement dropdown to CGAL mesh simplification<commit_after>#include <possumwood_sdk/node_implementation.h>

#include <CGAL/squared_distance_3.h>

#include <CGAL/Surface_mesh_simplification/edge_collapse.h>

#include <CGAL/Surface_mesh_simplification/Policies/Edge_collapse/Count_stop_predicate.h>
#include <CGAL/Surface_mesh_simplification/Policies/Edge_collapse/Count_ratio_stop_predicate.h>
#include <CGAL/Surface_mesh_simplification/Policies/Edge_collapse/Edge_length_stop_predicate.h>

#include <CGAL/Surface_mesh_simplification/Policies/Edge_collapse/Edge_length_cost.h>
#include <CGAL/Surface_mesh_simplification/Policies/Edge_collapse/LindstromTurk_cost.h>

#include <CGAL/Surface_mesh_simplification/Policies/Edge_collapse/Midpoint_placement.h>
#include <CGAL/Surface_mesh_simplification/Policies/Edge_collapse/LindstromTurk_placement.h>
// #include <CGAL/Surface_mesh_simplification/Policies/Edge_collapse/Constrained_placement.h>
// #include <CGAL/Surface_mesh_simplification/Policies/Edge_collapse/Bounded_normal_change_placement.h>

#include "possumwood_sdk/datatypes/enum.h"

#include "datatypes/polyhedron.h"

#include "cgal.h"

namespace SMS = CGAL::Surface_mesh_simplification;
using namespace std::placeholders;

namespace {

dependency_graph::InAttr<std::shared_ptr<const possumwood::CGALPolyhedron>> a_inMesh;
dependency_graph::InAttr<float> a_stopParam;
dependency_graph::InAttr<possumwood::Enum> a_stopCondition, a_cost, a_placement;
dependency_graph::OutAttr<std::shared_ptr<const possumwood::CGALPolyhedron>> a_outMesh;

dependency_graph::State compute(dependency_graph::Values& data) {
	std::shared_ptr<const possumwood::CGALPolyhedron> inMesh = data.get(a_inMesh);
	const float stopCondition = data.get(a_stopParam);
	const unsigned algorithmId =
	    data.get(a_stopCondition).intValue() + data.get(a_cost).intValue() + data.get(a_placement).intValue();

	if(inMesh) {
		std::unique_ptr<possumwood::CGALPolyhedron> mesh(new possumwood::CGALPolyhedron(*inMesh));

		// this is just horrible - need to find a better way
		switch(algorithmId) {
			case 111:
				SMS::edge_collapse(*mesh, SMS::Count_stop_predicate<possumwood::CGALPolyhedron>(stopCondition),
				                   CGAL::parameters::get_cost(SMS::Edge_length_cost<possumwood::CGALPolyhedron>())
				                       .get_placement(SMS::Midpoint_placement<possumwood::CGALPolyhedron>()));
				break;

			case 112:
				SMS::edge_collapse(*mesh, SMS::Count_ratio_stop_predicate<possumwood::CGALPolyhedron>(stopCondition),
				                   CGAL::parameters::get_cost(SMS::Edge_length_cost<possumwood::CGALPolyhedron>())
				                       .get_placement(SMS::Midpoint_placement<possumwood::CGALPolyhedron>()));
				break;

			case 113:
				SMS::edge_collapse(*mesh, SMS::Edge_length_stop_predicate<float>(stopCondition),
				                   CGAL::parameters::get_cost(SMS::Edge_length_cost<possumwood::CGALPolyhedron>())
				                       .get_placement(SMS::Midpoint_placement<possumwood::CGALPolyhedron>()));
				break;
			case 121:
				SMS::edge_collapse(*mesh, SMS::Count_stop_predicate<possumwood::CGALPolyhedron>(stopCondition),
				                   CGAL::parameters::get_cost(SMS::LindstromTurk_cost<possumwood::CGALPolyhedron>())
				                       .get_placement(SMS::Midpoint_placement<possumwood::CGALPolyhedron>()));
				break;

			case 122:
				SMS::edge_collapse(*mesh, SMS::Count_ratio_stop_predicate<possumwood::CGALPolyhedron>(stopCondition),
				                   CGAL::parameters::get_cost(SMS::LindstromTurk_cost<possumwood::CGALPolyhedron>())
				                       .get_placement(SMS::Midpoint_placement<possumwood::CGALPolyhedron>()));
				break;

			case 123:
				SMS::edge_collapse(*mesh, SMS::Edge_length_stop_predicate<float>(stopCondition),
				                   CGAL::parameters::get_cost(SMS::LindstromTurk_cost<possumwood::CGALPolyhedron>())
				                       .get_placement(SMS::Midpoint_placement<possumwood::CGALPolyhedron>()));
				break;

			case 211:
				SMS::edge_collapse(*mesh, SMS::Count_stop_predicate<possumwood::CGALPolyhedron>(stopCondition),
				                   CGAL::parameters::get_cost(SMS::Edge_length_cost<possumwood::CGALPolyhedron>())
				                       .get_placement(SMS::LindstromTurk_placement<possumwood::CGALPolyhedron>()));
				break;

			case 212:
				SMS::edge_collapse(*mesh, SMS::Count_ratio_stop_predicate<possumwood::CGALPolyhedron>(stopCondition),
				                   CGAL::parameters::get_cost(SMS::Edge_length_cost<possumwood::CGALPolyhedron>())
				                       .get_placement(SMS::LindstromTurk_placement<possumwood::CGALPolyhedron>()));
				break;

			case 213:
				SMS::edge_collapse(*mesh, SMS::Edge_length_stop_predicate<float>(stopCondition),
				                   CGAL::parameters::get_cost(SMS::Edge_length_cost<possumwood::CGALPolyhedron>())
				                       .get_placement(SMS::LindstromTurk_placement<possumwood::CGALPolyhedron>()));
				break;
			case 221:
				SMS::edge_collapse(*mesh, SMS::Count_stop_predicate<possumwood::CGALPolyhedron>(stopCondition),
				                   CGAL::parameters::get_cost(SMS::LindstromTurk_cost<possumwood::CGALPolyhedron>())
				                       .get_placement(SMS::LindstromTurk_placement<possumwood::CGALPolyhedron>()));
				break;

			case 222:
				SMS::edge_collapse(*mesh, SMS::Count_ratio_stop_predicate<possumwood::CGALPolyhedron>(stopCondition),
				                   CGAL::parameters::get_cost(SMS::LindstromTurk_cost<possumwood::CGALPolyhedron>())
				                       .get_placement(SMS::LindstromTurk_placement<possumwood::CGALPolyhedron>()));
				break;

			case 223:
				SMS::edge_collapse(*mesh, SMS::Edge_length_stop_predicate<float>(stopCondition),
				                   CGAL::parameters::get_cost(SMS::LindstromTurk_cost<possumwood::CGALPolyhedron>())
				                       .get_placement(SMS::LindstromTurk_placement<possumwood::CGALPolyhedron>()));
				break;
		}

		data.set(a_outMesh, std::shared_ptr<const possumwood::CGALPolyhedron>(mesh.release()));
	}
	else
		data.set(a_outMesh, std::shared_ptr<const possumwood::CGALPolyhedron>());

	return dependency_graph::State();
}

void init(possumwood::Metadata& meta) {
	meta.addAttribute(a_inMesh, "input");
	meta.addAttribute(
	    a_stopCondition, "stop_condition",
	    possumwood::Enum({std::make_pair("Count_stop_predicate", 1), std::make_pair("Count_ratio_stop_predicate", 2),
	                      std::make_pair("Edge_length_stop_predicate", 3)}));
	meta.addAttribute(a_cost, "cost", possumwood::Enum({std::make_pair("Edge_length_cost", 10),
	                                                    std::make_pair("LindstromTurk_cost", 20)}));
	meta.addAttribute(a_placement, "placement", possumwood::Enum({std::make_pair("Midpoint_placement", 100),
	                                                              std::make_pair("LindstromTurk_placement", 200)}));
	meta.addAttribute(a_stopParam, "stop_parameter", 1000.0f);
	meta.addAttribute(a_outMesh, "output");

	meta.addInfluence(a_inMesh, a_outMesh);
	meta.addInfluence(a_stopCondition, a_outMesh);
	meta.addInfluence(a_cost, a_outMesh);
	meta.addInfluence(a_placement, a_outMesh);
	meta.addInfluence(a_stopParam, a_outMesh);

	meta.setCompute(compute);
}

possumwood::NodeImplementation s_impl("cgal/simplification/simplification", init);
}
<|endoftext|>


<commit_before>/*
 *******************************************************************************
 *
 *   Copyright (C) 1999-2001, International Business Machines
 *   Corporation and others.  All Rights Reserved.
 *
 *******************************************************************************
 *   file name:  scrptrun.cpp
 *
 *   created on: 10/17/2001
 *   created by: Eric R. Mader
 *
 * NOTE: This file is copied from ICU.
 * http://source.icu-project.org/repos/icu/icu/trunk/license.html
 */

#pragma GCC diagnostic push
#include <mapnik/warning_ignore.hpp>
#include <unicode/utypes.h>
#include <unicode/uscript.h>
#pragma GCC diagnostic pop

#include <mapnik/text/scrptrun.hpp>

#define ARRAY_SIZE(array) (sizeof array  / sizeof array[0])

UChar32 ScriptRun::pairedChars[] = {
    0x0028, 0x0029, // ascii paired punctuation
    0x003c, 0x003e,
    0x005b, 0x005d,
    0x007b, 0x007d,
    0x00ab, 0x00bb, // guillemets
    0x2018, 0x2019, // general punctuation
    0x201c, 0x201d,
    0x2039, 0x203a,
    0x3008, 0x3009, // chinese paired punctuation
    0x300a, 0x300b,
    0x300c, 0x300d,
    0x300e, 0x300f,
    0x3010, 0x3011,
    0x3014, 0x3015,
    0x3016, 0x3017,
    0x3018, 0x3019,
    0x301a, 0x301b
};

const int32_t ScriptRun::pairedCharCount = ARRAY_SIZE(pairedChars);
const int32_t ScriptRun::pairedCharPower = 1 << highBit(pairedCharCount);
const int32_t ScriptRun::pairedCharExtra = pairedCharCount - pairedCharPower;

int8_t ScriptRun::highBit(int32_t value)
{
    if (value <= 0) {
        return -32;
    }

    int8_t bit = 0;

    if (value >= 1 << 16) {
        value >>= 16;
        bit += 16;
    }

    if (value >= 1 << 8) {
        value >>= 8;
        bit += 8;
    }

    if (value >= 1 << 4) {
        value >>= 4;
        bit += 4;
    }

    if (value >= 1 << 2) {
        value >>= 2;
        bit += 2;
    }

    if (value >= 1 << 1) {
        value >>= 1;
        bit += 1;
    }

    return bit;
}

int32_t ScriptRun::getPairIndex(UChar32 ch)
{
    int32_t probe = pairedCharPower;
    int32_t index = 0;

    if (ch >= pairedChars[pairedCharExtra]) {
        index = pairedCharExtra;
    }

    while (probe > (1 << 0)) {
        probe >>= 1;

        if (ch >= pairedChars[index + probe]) {
            index += probe;
        }
    }

    if (pairedChars[index] != ch) {
        index = -1;
    }

    return index;
}

UBool ScriptRun::sameScript(int32_t scriptOne, int32_t scriptTwo)
{
    return scriptOne <= USCRIPT_INHERITED || scriptTwo <= USCRIPT_INHERITED || scriptOne == scriptTwo;
}

UBool ScriptRun::next()
{
    int32_t startSP  = parenSP;  // used to find the first new open character
    UErrorCode error = U_ZERO_ERROR;

    // if we've fallen off the end of the text, we're done
    if (scriptEnd >= charLimit) {
        return false;
    }

    scriptCode = USCRIPT_COMMON;

    for (scriptStart = scriptEnd; scriptEnd < charLimit; scriptEnd += 1) {
        UChar   high = charArray[scriptEnd];
        UChar32 ch   = high;

        // if the character is a high surrogate and it's not the last one
        // in the text, see if it's followed by a low surrogate
        if (high >= 0xD800 && high <= 0xDBFF && scriptEnd < charLimit - 1)
        {
            UChar low = charArray[scriptEnd + 1];

            // if it is followed by a low surrogate,
            // consume it and form the full character
            if (low >= 0xDC00 && low <= 0xDFFF) {
                ch = (high - 0xD800) * 0x0400 + low - 0xDC00 + 0x10000;
                scriptEnd += 1;
            }
        }

        UScriptCode sc = uscript_getScript(ch, &error);
        int32_t pairIndex = getPairIndex(ch);

        // Paired character handling:
        //
        // if it's an open character, push it onto the stack.
        // if it's a close character, find the matching open on the
        // stack, and use that script code. Any non-matching open
        // characters above it on the stack will be poped.
        if (pairIndex >= 0) {
            if ((pairIndex & 1) == 0) {
                parenStack[++parenSP].pairIndex = pairIndex;
                parenStack[parenSP].scriptCode  = scriptCode;
            } else if (parenSP >= 0) {
                int32_t pi = pairIndex & ~1;

                while (parenSP >= 0 && parenStack[parenSP].pairIndex != pi) {
                    parenSP -= 1;
                }

                if (parenSP < startSP) {
                    startSP = parenSP;
                }

                if (parenSP >= 0) {
                    sc = parenStack[parenSP].scriptCode;
                }
            }
        }

        if (sameScript(scriptCode, sc)) {
            if (scriptCode <= USCRIPT_INHERITED && sc > USCRIPT_INHERITED) {
                scriptCode = sc;

                // now that we have a final script code, fix any open
                // characters we pushed before we knew the script code.
                while (startSP < parenSP) {
                    parenStack[++startSP].scriptCode = scriptCode;
                }
            }

            // if this character is a close paired character,
            // pop it from the stack
            if (pairIndex >= 0 && (pairIndex & 1) != 0 && parenSP >= 0) {
                parenSP -= 1;
                startSP -= 1;
            }
        } else {
            // if the run broke on a surrogate pair,
            // end it before the high surrogate
            if (ch >= 0x10000) {
                scriptEnd -= 1;
            }

            break;
        }
    }

    return true;
}

<commit_msg>Fix buffer overflow<commit_after>/*
 *******************************************************************************
 *
 *   Copyright (C) 1999-2001, International Business Machines
 *   Corporation and others.  All Rights Reserved.
 *
 *******************************************************************************
 *   file name:  scrptrun.cpp
 *
 *   created on: 10/17/2001
 *   created by: Eric R. Mader
 *
 * NOTE: This file is copied from ICU.
 * http://source.icu-project.org/repos/icu/icu/trunk/license.html
 */

#pragma GCC diagnostic push
#include <mapnik/warning_ignore.hpp>
#include <unicode/utypes.h>
#include <unicode/uscript.h>
#pragma GCC diagnostic pop

#include <mapnik/text/scrptrun.hpp>
#include <algorithm>

#define ARRAY_SIZE(array) (sizeof array  / sizeof array[0])

UChar32 ScriptRun::pairedChars[] = {
    0x0028, 0x0029, // ascii paired punctuation
    0x003c, 0x003e,
    0x005b, 0x005d,
    0x007b, 0x007d,
    0x00ab, 0x00bb, // guillemets
    0x2018, 0x2019, // general punctuation
    0x201c, 0x201d,
    0x2039, 0x203a,
    0x3008, 0x3009, // chinese paired punctuation
    0x300a, 0x300b,
    0x300c, 0x300d,
    0x300e, 0x300f,
    0x3010, 0x3011,
    0x3014, 0x3015,
    0x3016, 0x3017,
    0x3018, 0x3019,
    0x301a, 0x301b
};

const int32_t ScriptRun::pairedCharCount = ARRAY_SIZE(pairedChars);
const int32_t ScriptRun::pairedCharPower = 1 << highBit(pairedCharCount);
const int32_t ScriptRun::pairedCharExtra = pairedCharCount - pairedCharPower;

int8_t ScriptRun::highBit(int32_t value)
{
    if (value <= 0) {
        return -32;
    }

    int8_t bit = 0;

    if (value >= 1 << 16) {
        value >>= 16;
        bit += 16;
    }

    if (value >= 1 << 8) {
        value >>= 8;
        bit += 8;
    }

    if (value >= 1 << 4) {
        value >>= 4;
        bit += 4;
    }

    if (value >= 1 << 2) {
        value >>= 2;
        bit += 2;
    }

    if (value >= 1 << 1) {
        value >>= 1;
        bit += 1;
    }

    return bit;
}

int32_t ScriptRun::getPairIndex(UChar32 ch)
{
    int32_t probe = pairedCharPower;
    int32_t index = 0;

    if (ch >= pairedChars[pairedCharExtra]) {
        index = pairedCharExtra;
    }

    while (probe > (1 << 0)) {
        probe >>= 1;

        if (ch >= pairedChars[index + probe]) {
            index += probe;
        }
    }

    if (pairedChars[index] != ch) {
        index = -1;
    }

    return index;
}

UBool ScriptRun::sameScript(int32_t scriptOne, int32_t scriptTwo)
{
    return scriptOne <= USCRIPT_INHERITED || scriptTwo <= USCRIPT_INHERITED || scriptOne == scriptTwo;
}

UBool ScriptRun::next()
{
    int32_t startSP  = parenSP;  // used to find the first new open character
    UErrorCode error = U_ZERO_ERROR;

    // if we've fallen off the end of the text, we're done
    if (scriptEnd >= charLimit) {
        return false;
    }

    scriptCode = USCRIPT_COMMON;

    for (scriptStart = scriptEnd; scriptEnd < charLimit; scriptEnd += 1) {
        UChar   high = charArray[scriptEnd];
        UChar32 ch   = high;

        // if the character is a high surrogate and it's not the last one
        // in the text, see if it's followed by a low surrogate
        if (high >= 0xD800 && high <= 0xDBFF && scriptEnd < charLimit - 1)
        {
            UChar low = charArray[scriptEnd + 1];

            // if it is followed by a low surrogate,
            // consume it and form the full character
            if (low >= 0xDC00 && low <= 0xDFFF) {
                ch = (high - 0xD800) * 0x0400 + low - 0xDC00 + 0x10000;
                scriptEnd += 1;
            }
        }

        UScriptCode sc = uscript_getScript(ch, &error);
        int32_t pairIndex = getPairIndex(ch);

        // Paired character handling:
        //
        // if it's an open character, push it onto the stack.
        // if it's a close character, find the matching open on the
        // stack, and use that script code. Any non-matching open
        // characters above it on the stack will be poped.
        if (pairIndex >= 0) {
            if ((pairIndex & 1) == 0) {
                parenStack[++parenSP].pairIndex = pairIndex;
                parenStack[parenSP].scriptCode  = scriptCode;
            } else if (parenSP >= 0) {
                int32_t pi = pairIndex & ~1;

                while (parenSP >= 0 && parenStack[parenSP].pairIndex != pi) {
                    parenSP -= 1;
                }

                if (parenSP < startSP) {
                    startSP = parenSP;
                }

                if (parenSP >= 0) {
                    sc = parenStack[parenSP].scriptCode;
                }
            }
        }

        if (sameScript(scriptCode, sc)) {
            if (scriptCode <= USCRIPT_INHERITED && sc > USCRIPT_INHERITED) {
                scriptCode = sc;

                // now that we have a final script code, fix any open
                // characters we pushed before we knew the script code.
                while (startSP < parenSP) {
                    parenStack[++startSP].scriptCode = scriptCode;
                }
            }

            // if this character is a close paired character,
            // pop it from the stack
            if (pairIndex >= 0 && (pairIndex & 1) != 0 && parenSP >= 0) {
                parenSP -= 1;
                startSP = std::max(-1, startSP - 1);
            }
        } else {
            // if the run broke on a surrogate pair,
            // end it before the high surrogate
            if (ch >= 0x10000) {
                scriptEnd -= 1;
            }

            break;
        }
    }

    return true;
}

<|endoftext|>


<commit_before><commit_msg>No need to trim capacity any more; it's allocated to the exact size.<commit_after><|endoftext|>