<commit_before>/*
 *            Copyright 2009-2018 The VOTCA Development Team
 *                       (http://www.votca.org)
 *
 *      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 <vector>
#include <string>

#include <votca/xtp/polarsite.h>
#include <votca/xtp/apolarsite.h>
#include <votca/xtp/atom.h>
#include <votca/xtp/fragment.h>
#include <votca/xtp/segment.h>
#include <votca/xtp/segmenttype.h>
#include <votca/tools/vec.h>

using namespace std;
using namespace votca::tools;

namespace votca {
namespace xtp {

/// Default constructor
Segment::Segment(int id, string name)
    : _id(id),
      _name(name),
      _has_e(false),
      _has_h(false),
      _has_s(false),
      _has_t(false) {
  _eMpoles.resize(5);
}

// This constructor creates a copy of the stencil segment, without
// adding it to any containers further up in the hierarchy; i.e. the topology
// and molecules will neither know about the existence of this segment, nor
// be able to access it. Used for creating the ghost in PB corrected pairs.
Segment::Segment(Segment *stencil)
    : _id(stencil->getId()),
      _name(stencil->getName() + "_ghost"),
      _typ(stencil->getType()),
      _top(NULL),
      _mol(NULL),
      _CoM(stencil->getPos()),
      _has_e(false),
      _has_h(false),
      _has_s(false),
      _has_t(false) {
  _eMpoles.resize(5);

  vector<Fragment *>::iterator fit;
  for (fit = stencil->Fragments().begin(); fit < stencil->Fragments().end();
       fit++) {

    Fragment *newFrag = new Fragment(*fit);
    this->AddFragment(newFrag);

    vector<Atom *>::iterator ait;
    for (ait = newFrag->Atoms().begin(); ait < newFrag->Atoms().end(); ait++) {
      this->AddAtom(*ait);
    }
  }
}

Segment::~Segment() {

  vector<Fragment *>::iterator fragit;
  for (fragit = this->Fragments().begin(); fragit < this->Fragments().end();
       fragit++) {
    delete *fragit;
  }
  _fragments.clear();
  _atoms.clear();

  _eMpoles.clear();
  _polarSites.clear();
}

void Segment::TranslateBy(const vec &shift) {

  _CoM = _CoM + shift;

  vector<Fragment *>::iterator fit;
  for (fit = _fragments.begin(); fit < _fragments.end(); fit++) {

    (*fit)->TranslateBy(shift);
  }
}

void Segment::setHasState(bool yesno, int state) {

  if (state == -1) {
    _has_e = yesno;
  } else if (state == +1) {
    _has_h = yesno;
  } else if (state == +2) {
    _has_s = yesno;
  } else if (state == +3) {
    _has_t = yesno;
  } else {
    throw runtime_error(" ERROR CODE whe__00e11h__");
  }
}

bool Segment::hasState(int state) {
  bool result;
  if (state == -1) {
    result = _has_e;
  } else if (state == +1) {
    result = _has_h;
  } else if (state == +2) {
    result = _has_s;
  } else if (state == +3) {
    result = _has_t;
  } else {
    throw runtime_error(" ERROR CODE whe__00s11o__");
  }
  return result;
}

void Segment::setOcc(double occ, int e_h_s_t) {

  if (e_h_s_t == -1) {
    _occ_e = occ;
  } else if (e_h_s_t == +1) {
    _occ_h = occ;
  } else if (e_h_s_t == +2) {
    _occ_s = occ;
  } else if (e_h_s_t == +3) {
    _occ_t = occ;
  } else {
    throw runtime_error(" ERROR CODE whe__00s11o__");
  }
}

double Segment::getOcc(int e_h_s_t) {
  double result;
  if (e_h_s_t == -1) {
    result = _occ_e;
  } else if (e_h_s_t == +1) {
    result = _occ_h;
  } else if (e_h_s_t == +2) {
    result = _occ_s;
  } else if (e_h_s_t == +3) {
    result = _occ_t;
  } else {
    throw runtime_error(
        " ERROR CODE whe__00s11o__");  // blabla what do I do here?
  }
  return result;
}

void Segment::setU_cC_nN(double dU, int state) {

  if (state == -1) {
    _U_cC_nN_e = dU;
  } else if (state == +1) {
    _U_cC_nN_h = dU;
  } else {
    throw runtime_error(" ERROR CODE whe__00u11a__");
  }
}

void Segment::setU_nC_nN(double dU, int state) {

  if (state == -1) {
    _U_nC_nN_e = dU;
  } else if (state == +1) {
    _U_nC_nN_h = dU;
  } else {
    throw runtime_error(" ERROR CODE whe__00u11b__");
  }
}

void Segment::setU_cN_cC(double dU, int state) {

  if (state == -1) {
    _U_cN_cC_e = dU;
  } else if (state == +1) {
    _U_cN_cC_h = dU;
  } else {
    throw runtime_error(" ERROR CODE whe__00u11c__");
  }
}

void Segment::setU_xX_nN(double dU, int state) {

  if (state == +2) {
    _U_xX_nN_s = dU;
  } else if (state == +3) {
    _U_xX_nN_t = dU;
  } else {
    throw runtime_error(
        " ERROR CODE whe__00u11d__");  // blabla?? What do I do here?
  }
}

void Segment::setU_nX_nN(double dU, int state) {

  if (state == +2) {
    _U_nX_nN_s = dU;
  } else if (state == +3) {
    _U_nX_nN_t = dU;
  } else {
    throw runtime_error(
        " ERROR CODE whe__00u11d__");  // blabla?? What do I do here?
  }
}

void Segment::setU_xN_xX(double dU, int state) {

  if (state == +2) {
    _U_xN_xX_s = dU;
  } else if (state == +3) {
    _U_xN_xX_t = dU;
  } else {
    throw runtime_error(
        " ERROR CODE whe__00u11d__");  // blabla?? What do I do here?
  }
}

const double &Segment::getU_xX_nN(int state) {

  return (state == +3) ? _U_xX_nN_t : _U_xX_nN_s;
}

const double &Segment::getU_nX_nN(int state) {

  return (state == +3) ? _U_nX_nN_t : _U_nX_nN_s;
}

const double &Segment::getU_xN_xX(int state) {

  return (state == +3) ? _U_xN_xX_t : _U_xN_xX_s;
}

const double &Segment::getU_cC_nN(int state) {

  return (state == -1) ? _U_cC_nN_e : _U_cC_nN_h;
}

const double &Segment::getU_nC_nN(int state) {

  return (state == -1) ? _U_nC_nN_e : _U_nC_nN_h;
}

const double &Segment::getU_cN_cC(int state) {

  return (state == -1) ? _U_cN_cC_e : _U_cN_cC_h;
}

double Segment::getSiteEnergy(int state) {

  double result;
  if (state == -1) {
    result = getEMpoles(state) + _U_cC_nN_e;
  } else if (state == +1) {
    result = getEMpoles(state) + _U_cC_nN_h;
  } else if (state == +2) {
    result = getEMpoles(state) + _U_xX_nN_s;
  } else if (state == +3) {
    result = getEMpoles(state) + _U_xX_nN_t;
  } else {
    throw runtime_error(
        " ERROR CODE whe__00s11o__");  // blabla what do I do here?
  }
  return result;
}

void Segment::setEMpoles(int state, double energy) {

  _hasChrgState.resize(5);
  _hasChrgState[state + 1] = true;
  _eMpoles[state + 1] = energy;
}

double Segment::getEMpoles(int state) {

  return _eMpoles[state + 1] - _eMpoles[1];
}

void Segment::AddFragment(Fragment *fragment) {
  _fragments.push_back(fragment);
  fragment->setSegment(this);
}

void Segment::AddAtom(Atom *atom) {
  _atoms.push_back(atom);
  atom->setSegment(this);
}

void Segment::AddPolarSite(PolarSite *pole) {

  _polarSites.push_back(pole);
  pole->setSegment(this);
}

void Segment::AddAPolarSite(APolarSite *pole) {

  _apolarSites.push_back(pole);
  pole->setSegment(this);
}

void Segment::calcPos() {
  vec pos = vec(0, 0, 0);
  double totWeight = 0.0;

  for (unsigned int i = 0; i < _atoms.size(); i++) {
    pos += _atoms[i]->getPos() * _atoms[i]->getWeight();
    totWeight += _atoms[i]->getWeight();
  }

  _CoM = pos / totWeight;
}

void Segment::calcApproxSize() {
  _approxsize = 0.0;

  tools::vec min = vec(numeric_limits<double>::max());
  tools::vec max = vec(numeric_limits<double>::min());
  vector<Fragment *>::iterator fragit1;
  for (fragit1 = Fragments().begin(); fragit1 < Fragments().end(); fragit1++) {
    const tools::vec &pos = (*fragit1)->getPos();
    if (pos.getX() > max.getX()) {
      max.x() = pos.getX();
    } else if (pos.getX() < min.getX()) {
      min.x() = pos.getX();
    }
    if (pos.getY() > max.getY()) {
      max.y() = pos.getY();
    } else if (pos.getY() < min.getY()) {
      min.y() = pos.getY();
    }
    if (pos.getZ() > max.getZ()) {
      max.z() = pos.getZ();
    } else if (pos.getZ() < min.getZ()) {
      min.z() = pos.getZ();
    }
  }

  _approxsize = abs(max - min);

  return;
}

void Segment::Rigidify() {

  if (this->getType()->canRigidify()) {
    // Establish which atoms to use to define local frame
    vector<Fragment *>::iterator fit;

    for (fit = this->Fragments().begin(); fit < this->Fragments().end();
         fit++) {
      (*fit)->Rigidify();
    }
  } else {
    return;
  }
}

}
}
<commit_msg>removed use of polar site from segment.cc<commit_after>/*
 *            Copyright 2009-2018 The VOTCA Development Team
 *                       (http://www.votca.org)
 *
 *      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 <vector>
#include <string>

#include <votca/xtp/apolarsite.h>
#include <votca/xtp/atom.h>
#include <votca/xtp/fragment.h>
#include <votca/xtp/segment.h>
#include <votca/xtp/segmenttype.h>
#include <votca/tools/vec.h>

using namespace std;
using namespace votca::tools;

namespace votca {
namespace xtp {

/// Default constructor
Segment::Segment(int id, string name)
    : _id(id),
      _name(name),
      _has_e(false),
      _has_h(false),
      _has_s(false),
      _has_t(false) {
  _eMpoles.resize(5);
}

// This constructor creates a copy of the stencil segment, without
// adding it to any containers further up in the hierarchy; i.e. the topology
// and molecules will neither know about the existence of this segment, nor
// be able to access it. Used for creating the ghost in PB corrected pairs.
Segment::Segment(Segment *stencil)
    : _id(stencil->getId()),
      _name(stencil->getName() + "_ghost"),
      _typ(stencil->getType()),
      _top(NULL),
      _mol(NULL),
      _CoM(stencil->getPos()),
      _has_e(false),
      _has_h(false),
      _has_s(false),
      _has_t(false) {
  _eMpoles.resize(5);

  vector<Fragment *>::iterator fit;
  for (fit = stencil->Fragments().begin(); fit < stencil->Fragments().end();
       fit++) {

    Fragment *newFrag = new Fragment(*fit);
    this->AddFragment(newFrag);

    vector<Atom *>::iterator ait;
    for (ait = newFrag->Atoms().begin(); ait < newFrag->Atoms().end(); ait++) {
      this->AddAtom(*ait);
    }
  }
}

Segment::~Segment() {

  vector<Fragment *>::iterator fragit;
  for (fragit = this->Fragments().begin(); fragit < this->Fragments().end();
       fragit++) {
    delete *fragit;
  }
  _fragments.clear();
  _atoms.clear();

  _eMpoles.clear();
  _apolarSites.clear();
}

void Segment::TranslateBy(const vec &shift) {

  _CoM = _CoM + shift;

  vector<Fragment *>::iterator fit;
  for (fit = _fragments.begin(); fit < _fragments.end(); fit++) {

    (*fit)->TranslateBy(shift);
  }
}

void Segment::setHasState(bool yesno, int state) {

  if (state == -1) {
    _has_e = yesno;
  } else if (state == +1) {
    _has_h = yesno;
  } else if (state == +2) {
    _has_s = yesno;
  } else if (state == +3) {
    _has_t = yesno;
  } else {
    throw runtime_error(" ERROR CODE whe__00e11h__");
  }
}

bool Segment::hasState(int state) {
  bool result;
  if (state == -1) {
    result = _has_e;
  } else if (state == +1) {
    result = _has_h;
  } else if (state == +2) {
    result = _has_s;
  } else if (state == +3) {
    result = _has_t;
  } else {
    throw runtime_error(" ERROR CODE whe__00s11o__");
  }
  return result;
}

void Segment::setOcc(double occ, int e_h_s_t) {

  if (e_h_s_t == -1) {
    _occ_e = occ;
  } else if (e_h_s_t == +1) {
    _occ_h = occ;
  } else if (e_h_s_t == +2) {
    _occ_s = occ;
  } else if (e_h_s_t == +3) {
    _occ_t = occ;
  } else {
    throw runtime_error(" ERROR CODE whe__00s11o__");
  }
}

double Segment::getOcc(int e_h_s_t) {
  double result;
  if (e_h_s_t == -1) {
    result = _occ_e;
  } else if (e_h_s_t == +1) {
    result = _occ_h;
  } else if (e_h_s_t == +2) {
    result = _occ_s;
  } else if (e_h_s_t == +3) {
    result = _occ_t;
  } else {
    throw runtime_error(
        " ERROR CODE whe__00s11o__");  // blabla what do I do here?
  }
  return result;
}

void Segment::setU_cC_nN(double dU, int state) {

  if (state == -1) {
    _U_cC_nN_e = dU;
  } else if (state == +1) {
    _U_cC_nN_h = dU;
  } else {
    throw runtime_error(" ERROR CODE whe__00u11a__");
  }
}

void Segment::setU_nC_nN(double dU, int state) {

  if (state == -1) {
    _U_nC_nN_e = dU;
  } else if (state == +1) {
    _U_nC_nN_h = dU;
  } else {
    throw runtime_error(" ERROR CODE whe__00u11b__");
  }
}

void Segment::setU_cN_cC(double dU, int state) {

  if (state == -1) {
    _U_cN_cC_e = dU;
  } else if (state == +1) {
    _U_cN_cC_h = dU;
  } else {
    throw runtime_error(" ERROR CODE whe__00u11c__");
  }
}

void Segment::setU_xX_nN(double dU, int state) {

  if (state == +2) {
    _U_xX_nN_s = dU;
  } else if (state == +3) {
    _U_xX_nN_t = dU;
  } else {
    throw runtime_error(
        " ERROR CODE whe__00u11d__");  // blabla?? What do I do here?
  }
}

void Segment::setU_nX_nN(double dU, int state) {

  if (state == +2) {
    _U_nX_nN_s = dU;
  } else if (state == +3) {
    _U_nX_nN_t = dU;
  } else {
    throw runtime_error(
        " ERROR CODE whe__00u11d__");  // blabla?? What do I do here?
  }
}

void Segment::setU_xN_xX(double dU, int state) {

  if (state == +2) {
    _U_xN_xX_s = dU;
  } else if (state == +3) {
    _U_xN_xX_t = dU;
  } else {
    throw runtime_error(
        " ERROR CODE whe__00u11d__");  // blabla?? What do I do here?
  }
}

const double &Segment::getU_xX_nN(int state) {

  return (state == +3) ? _U_xX_nN_t : _U_xX_nN_s;
}

const double &Segment::getU_nX_nN(int state) {

  return (state == +3) ? _U_nX_nN_t : _U_nX_nN_s;
}

const double &Segment::getU_xN_xX(int state) {

  return (state == +3) ? _U_xN_xX_t : _U_xN_xX_s;
}

const double &Segment::getU_cC_nN(int state) {

  return (state == -1) ? _U_cC_nN_e : _U_cC_nN_h;
}

const double &Segment::getU_nC_nN(int state) {

  return (state == -1) ? _U_nC_nN_e : _U_nC_nN_h;
}

const double &Segment::getU_cN_cC(int state) {

  return (state == -1) ? _U_cN_cC_e : _U_cN_cC_h;
}

double Segment::getSiteEnergy(int state) {

  double result;
  if (state == -1) {
    result = getEMpoles(state) + _U_cC_nN_e;
  } else if (state == +1) {
    result = getEMpoles(state) + _U_cC_nN_h;
  } else if (state == +2) {
    result = getEMpoles(state) + _U_xX_nN_s;
  } else if (state == +3) {
    result = getEMpoles(state) + _U_xX_nN_t;
  } else {
    throw runtime_error(
        " ERROR CODE whe__00s11o__");  // blabla what do I do here?
  }
  return result;
}

void Segment::setEMpoles(int state, double energy) {

  _hasChrgState.resize(5);
  _hasChrgState[state + 1] = true;
  _eMpoles[state + 1] = energy;
}

double Segment::getEMpoles(int state) {

  return _eMpoles[state + 1] - _eMpoles[1];
}

void Segment::AddFragment(Fragment *fragment) {
  _fragments.push_back(fragment);
  fragment->setSegment(this);
}

void Segment::AddAtom(Atom *atom) {
  _atoms.push_back(atom);
  atom->setSegment(this);
}

void Segment::AddAPolarSite(APolarSite *pole) {

  _apolarSites.push_back(pole);
  pole->setSegment(this);
}

void Segment::calcPos() {
  vec pos = vec(0, 0, 0);
  double totWeight = 0.0;

  for (unsigned int i = 0; i < _atoms.size(); i++) {
    pos += _atoms[i]->getPos() * _atoms[i]->getWeight();
    totWeight += _atoms[i]->getWeight();
  }

  _CoM = pos / totWeight;
}

void Segment::calcApproxSize() {
  _approxsize = 0.0;

  tools::vec min = vec(numeric_limits<double>::max());
  tools::vec max = vec(numeric_limits<double>::min());
  vector<Fragment *>::iterator fragit1;
  for (fragit1 = Fragments().begin(); fragit1 < Fragments().end(); fragit1++) {
    const tools::vec &pos = (*fragit1)->getPos();
    if (pos.getX() > max.getX()) {
      max.x() = pos.getX();
    } else if (pos.getX() < min.getX()) {
      min.x() = pos.getX();
    }
    if (pos.getY() > max.getY()) {
      max.y() = pos.getY();
    } else if (pos.getY() < min.getY()) {
      min.y() = pos.getY();
    }
    if (pos.getZ() > max.getZ()) {
      max.z() = pos.getZ();
    } else if (pos.getZ() < min.getZ()) {
      min.z() = pos.getZ();
    }
  }

  _approxsize = abs(max - min);

  return;
}

void Segment::Rigidify() {

  if (this->getType()->canRigidify()) {
    // Establish which atoms to use to define local frame
    vector<Fragment *>::iterator fit;

    for (fit = this->Fragments().begin(); fit < this->Fragments().end();
         fit++) {
      (*fit)->Rigidify();
    }
  } else {
    return;
  }
}

}
}
<|endoftext|>


<commit_before>#pragma once

#include <new>
#include <memory>
#include <utility>
#include <type_traits>
#include <chrono>
#include <uv.h>
#include "emitter.hpp"

#ifdef _WIN32
#include <ciso646>
#endif

namespace uvw {

namespace details {

enum class UVLoopOption: std::underlying_type_t<uv_loop_option> {
    BLOCK_SIGNAL = UV_LOOP_BLOCK_SIGNAL
};

enum class UVRunMode: std::underlying_type_t<uv_run_mode> {
    DEFAULT = UV_RUN_DEFAULT,
    ONCE = UV_RUN_ONCE,
    NOWAIT = UV_RUN_NOWAIT
};

}

/**
 * @brief Untyped handle class
 *
 * Handles' types are unknown from the point of view of the loop.

 * Anyway, a loop maintains a list of all the associated handles and let the
 * users walk them as untyped instances.

 * This can help to end all the pending requests by closing the handles.
 */
class BaseHandle {
public:
    /**
     * @brief Checks if the handle is active.
     *
     * What _active_ means depends on the type of handle:
     *
     * * An AsyncHandle handle is always active and cannot be deactivated,
     * except by closing it with uv_close().
     * * A PipeHandle, TcpHandle, UDPHandle, etc. handle - basically any handle
     * that deals with I/O - is active when it is doing something that involves
     * I/O, like reading, writing, connecting, accepting new connections, etc.
     * * A CheckHandle, IdleHandle, TimerHandle, etc. handle is active when it
     * has been started with a call to `start()`.
     *
     * Rule of thumb: if a handle of type `FooHandle` has a `start()` member
     * method, then it’s active from the moment that method is called. Likewise,
     * `stop()` deactivates the handle again.
     *
     * @return True if the handle is active, false otherwise.
     */
    virtual bool active() const noexcept = 0;

    /**
     * @brief Checks if a handle is closing or closed.
     *
     * This function should only be used between the initialization of the
     * handle and the arrival of the close callback.
     *
     * @return True if the handle is closing or closed, false otherwise.
     */
    virtual bool closing() const noexcept = 0;

    /**
     * @brief Reference the given handle.
     *
     * References are idempotent, that is, if a handle is already referenced
     * calling this function again will have no effect.
     */
    virtual void reference() noexcept = 0;

    /**
     * @brief Unreference the given handle.
     *
     * References are idempotent, that is, if a handle is not referenced calling
     * this function again will have no effect.
     */
    virtual void unreference() noexcept = 0;

    /**
     * @brief Checks if the given handle referenced.
     * @return True if the handle referenced, false otherwise.
     */
    virtual bool referenced() const noexcept = 0;

    /**
     * @brief Request handle to be closed.
     *
     * This **must** be called on each handle before memory is released.

     * In-progress requests are cancelled and this can result in an ErrorEvent
     * emitted.
     */
    virtual void close() noexcept = 0;
};

/**
 * @brief The Loop class.
 *
 * The event loop is the central part of `uvw`'s functionalities, as well as
 * libuv's ones.

 * It takes care of polling for I/O and scheduling callbacks to be run based on
 * different sources of events.
 */
class Loop final: public Emitter<Loop>, public std::enable_shared_from_this<Loop> {
    using Deleter = void(*)(uv_loop_t *);

    template<typename, typename>
    friend class Resource;

    Loop(std::unique_ptr<uv_loop_t, Deleter> ptr) noexcept
        : loop{std::move(ptr)}
    { }

public:
    using Time = std::chrono::milliseconds;
    using Configure = details::UVLoopOption;
    using Mode = details::UVRunMode;

    /**
     * @brief Initializes a new Loop instance.
     * @return A pointer to the newly created loop.
     */
    static std::shared_ptr<Loop> create() {
        auto ptr = std::unique_ptr<uv_loop_t, Deleter>{new uv_loop_t, [](uv_loop_t *l){ delete l; }};
        auto loop = std::shared_ptr<Loop>(new Loop{std::move(ptr)});

        if(uv_loop_init(loop->loop.get())) {
            loop = nullptr;
        }

        return loop;
    }

    /**
     * @brief Gets the initialized default loop.
     *
     * It may return an empty pointer in case of failure.

     * This function is just a convenient way for having a global loop
     * throughout an application, the default loop is in no way different than
     * the ones initialized with `create()`.

     * As such, the default loop can be closed with `close()` so the resources
     * associated with it are freed (even if it is not strictly necessary).
     *
     * @return The initialized default loop.
     */
    static std::shared_ptr<Loop> getDefault() {
        static std::weak_ptr<Loop> ref;
        std::shared_ptr<Loop> loop;

        if(ref.expired()) {
            auto def = uv_default_loop();

            if(def) {
                auto ptr = std::unique_ptr<uv_loop_t, Deleter>(def, [](uv_loop_t *){ });
                loop = std::shared_ptr<Loop>(new Loop{std::move(ptr)});
            }

            ref = loop;
        } else {
            loop = ref.lock();
        }

        return loop;
    }

    Loop(const Loop &) = delete;
    Loop(Loop &&other) = delete;
    Loop& operator=(const Loop &) = delete;
    Loop& operator=(Loop &&other) = delete;

    ~Loop() noexcept {
        if(loop) {
            close();
        }
    }

    /**
     * @brief Sets additional loop options.
     *
     * You should normally call this before the first call to uv_run() unless
     * mentioned otherwise.

     * Supported options:
     *
     * * `Loop::Configure::BLOCK_SIGNAL`: Block a signal when polling for new
     * events. A second argument is required and it is the signal number.
     *
     * An ErrorEvent will be emitted in case of errors.
     *
     * See the official
     * [documentation](http://docs.libuv.org/en/v1.x/loop.html#c.uv_loop_configure)
     * for further details.
     */
    template<typename... Args>
    void configure(Configure flag, Args... args) {
        auto err = uv_loop_configure(loop.get(), static_cast<std::underlying_type_t<Configure>>(flag), std::forward<Args>(args)...);
        if(err) { publish(ErrorEvent{err}); }
    }

    /**
     * @brief Creates resources of handles' types.
     *
     * This should be used as a default method to create resources.

     * The arguments are the ones required for the specific resource.
     *
     * Use it as `loop->resource<uvw::TimerHandle>()`.
     *
     * @return A pointer to the newly created resource.
     */
    template<typename R, typename... Args>
    std::enable_if_t<std::is_base_of<BaseHandle, R>::value, std::shared_ptr<R>>
    resource(Args&&... args) {
        auto ptr = R::create(shared_from_this(), std::forward<Args>(args)...);
        ptr = ptr->init() ? ptr : nullptr;
        return ptr;
    }

    /**
     * @brief Creates resources of types other than handles' ones.
     *
     * This should be used as a default method to create resources.

     * The arguments are the ones required for the specific resource.
     *
     * Use it as `loop->resource<uvw::WorkReq>()`.
     *
     * @return A pointer to the newly created resource.
     */
    template<typename R, typename... Args>
    std::enable_if_t<not std::is_base_of<BaseHandle, R>::value, std::shared_ptr<R>>
    resource(Args&&... args) {
        return R::create(shared_from_this(), std::forward<Args>(args)...);
    }

    /**
     * @brief Releases all internal loop resources.
     *
     * Call this function only when the loop has finished executing and all open
     * handles and requests have been closed, or the loop will emit an error.
     *
     * An ErrorEvent will be emitted in case of errors.
     */
    void close() {
        auto err = uv_loop_close(loop.get());
        if(err) { publish(ErrorEvent{err}); }
    }

    /**
     * @brief Runs the event loop.
     *
     * Available modes are:
     *
     * * `Loop::Mode::DEFAULT`: Runs the event loop until there are no more
     * active and referenced handles or requests.
     * * `Loop::Mode::ONCE`: Poll for i/o once. Note that this function blocks
     * if there are no pending callbacks.
     * * `Loop::Mode::NOWAIT`: Poll for i/o once but don’t block if there are no
     * pending callbacks.
     *
     * See the official
     * [documentation](http://docs.libuv.org/en/v1.x/loop.html#c.uv_run)
     * for further details.
     *
     * @return True when done, false in all other cases.
     */
    template<Mode mode = Mode::DEFAULT>
    bool run() noexcept {
        auto utm = static_cast<std::underlying_type_t<Mode>>(mode);
        auto uvrm = static_cast<uv_run_mode>(utm);
        return (uv_run(loop.get(), uvrm) == 0);
    }

    /**
     * @brief Checks if there are active resources.
     * @return True if there are active resources in the loop.
     */
    bool alive() const noexcept {
        return !(uv_loop_alive(loop.get()) == 0);
    }

    /**
     * @brief Stops the event loop.
     *
     * It causes `run()` to end as soon as possible.

     * This will happen not sooner than the next loop iteration.

     * If this function was called before blocking for I/O, the loop won’t block
     * for I/O on this iteration.
     */
    void stop() noexcept {
        uv_stop(loop.get());
    }

    /**
     * @brief Get backend file descriptor.
     *
     * Only kqueue, epoll and event ports are supported.

     * This can be used in conjunction with `run<Loop::Mode::NOWAIT>()` to poll
     * in one thread and run the event loop’s callbacks in another.
     *
     * @return The backend file descriptor.
     */
    int descriptor() const noexcept {
        return uv_backend_fd(loop.get());
    }

    /**
     * @brief Gets the poll timeout.
     * @return The return value is in milliseconds, or -1 for no timeout.
     */
    Time timeout() const noexcept {
        return Time{uv_backend_timeout(loop.get())};
    }

    /**
     * @brief Returns the current timestamp in milliseconds.
     *
     * The timestamp is cached at the start of the event loop tick.

     * The timestamp increases monotonically from some arbitrary point in
     * time.

     * Don’t make assumptions about the starting point, you will only get
     * disappointed.
     *
     * @return The current timestamp in milliseconds.
     */
    Time now() const noexcept {
        return Time{uv_now(loop.get())};
    }

    /**
     * @brief Updates the event loop’s concept of _now_.
     *
     * The current time is cached at the start of the event loop tick in order
     * to reduce the number of time-related system calls.

     * You won’t normally need to call this function unless you have callbacks
     * that block the event loop for longer periods of time, where _longer_ is
     * somewhat subjective but probably on the order of a millisecond or more.
     */
    void update() const noexcept {
        return uv_update_time(loop.get());
    }

    /**
     * @brief Walks the list of handles.
     *
     * The callback will be executed once for each handle that is still active.
     *
     * @param callback A function to be invoked once for each active handle.
     */
    void walk(std::function<void(BaseHandle &)> callback) {
        // remember: non-capturing lambdas decay to pointers to functions
        uv_walk(loop.get(), [](uv_handle_t *handle, void *func) {
            BaseHandle &ref = *static_cast<BaseHandle*>(handle->data);
            std::function<void(BaseHandle &)> &f =
                    *static_cast<std::function<void(BaseHandle &)>*>(func);
            f(ref);
        }, &callback);
    }

private:
    std::unique_ptr<uv_loop_t, Deleter> loop;
};

}
<commit_msg>Reorder header includes as per comment<commit_after>#pragma once

#ifdef _WIN32
#include <ciso646>
#endif
#include <new>
#include <memory>
#include <utility>
#include <type_traits>
#include <chrono>
#include <uv.h>
#include "emitter.hpp"

namespace uvw {

namespace details {

enum class UVLoopOption: std::underlying_type_t<uv_loop_option> {
    BLOCK_SIGNAL = UV_LOOP_BLOCK_SIGNAL
};

enum class UVRunMode: std::underlying_type_t<uv_run_mode> {
    DEFAULT = UV_RUN_DEFAULT,
    ONCE = UV_RUN_ONCE,
    NOWAIT = UV_RUN_NOWAIT
};

}

/**
 * @brief Untyped handle class
 *
 * Handles' types are unknown from the point of view of the loop.

 * Anyway, a loop maintains a list of all the associated handles and let the
 * users walk them as untyped instances.

 * This can help to end all the pending requests by closing the handles.
 */
class BaseHandle {
public:
    /**
     * @brief Checks if the handle is active.
     *
     * What _active_ means depends on the type of handle:
     *
     * * An AsyncHandle handle is always active and cannot be deactivated,
     * except by closing it with uv_close().
     * * A PipeHandle, TcpHandle, UDPHandle, etc. handle - basically any handle
     * that deals with I/O - is active when it is doing something that involves
     * I/O, like reading, writing, connecting, accepting new connections, etc.
     * * A CheckHandle, IdleHandle, TimerHandle, etc. handle is active when it
     * has been started with a call to `start()`.
     *
     * Rule of thumb: if a handle of type `FooHandle` has a `start()` member
     * method, then it’s active from the moment that method is called. Likewise,
     * `stop()` deactivates the handle again.
     *
     * @return True if the handle is active, false otherwise.
     */
    virtual bool active() const noexcept = 0;

    /**
     * @brief Checks if a handle is closing or closed.
     *
     * This function should only be used between the initialization of the
     * handle and the arrival of the close callback.
     *
     * @return True if the handle is closing or closed, false otherwise.
     */
    virtual bool closing() const noexcept = 0;

    /**
     * @brief Reference the given handle.
     *
     * References are idempotent, that is, if a handle is already referenced
     * calling this function again will have no effect.
     */
    virtual void reference() noexcept = 0;

    /**
     * @brief Unreference the given handle.
     *
     * References are idempotent, that is, if a handle is not referenced calling
     * this function again will have no effect.
     */
    virtual void unreference() noexcept = 0;

    /**
     * @brief Checks if the given handle referenced.
     * @return True if the handle referenced, false otherwise.
     */
    virtual bool referenced() const noexcept = 0;

    /**
     * @brief Request handle to be closed.
     *
     * This **must** be called on each handle before memory is released.

     * In-progress requests are cancelled and this can result in an ErrorEvent
     * emitted.
     */
    virtual void close() noexcept = 0;
};

/**
 * @brief The Loop class.
 *
 * The event loop is the central part of `uvw`'s functionalities, as well as
 * libuv's ones.

 * It takes care of polling for I/O and scheduling callbacks to be run based on
 * different sources of events.
 */
class Loop final: public Emitter<Loop>, public std::enable_shared_from_this<Loop> {
    using Deleter = void(*)(uv_loop_t *);

    template<typename, typename>
    friend class Resource;

    Loop(std::unique_ptr<uv_loop_t, Deleter> ptr) noexcept
        : loop{std::move(ptr)}
    { }

public:
    using Time = std::chrono::milliseconds;
    using Configure = details::UVLoopOption;
    using Mode = details::UVRunMode;

    /**
     * @brief Initializes a new Loop instance.
     * @return A pointer to the newly created loop.
     */
    static std::shared_ptr<Loop> create() {
        auto ptr = std::unique_ptr<uv_loop_t, Deleter>{new uv_loop_t, [](uv_loop_t *l){ delete l; }};
        auto loop = std::shared_ptr<Loop>(new Loop{std::move(ptr)});

        if(uv_loop_init(loop->loop.get())) {
            loop = nullptr;
        }

        return loop;
    }

    /**
     * @brief Gets the initialized default loop.
     *
     * It may return an empty pointer in case of failure.

     * This function is just a convenient way for having a global loop
     * throughout an application, the default loop is in no way different than
     * the ones initialized with `create()`.

     * As such, the default loop can be closed with `close()` so the resources
     * associated with it are freed (even if it is not strictly necessary).
     *
     * @return The initialized default loop.
     */
    static std::shared_ptr<Loop> getDefault() {
        static std::weak_ptr<Loop> ref;
        std::shared_ptr<Loop> loop;

        if(ref.expired()) {
            auto def = uv_default_loop();

            if(def) {
                auto ptr = std::unique_ptr<uv_loop_t, Deleter>(def, [](uv_loop_t *){ });
                loop = std::shared_ptr<Loop>(new Loop{std::move(ptr)});
            }

            ref = loop;
        } else {
            loop = ref.lock();
        }

        return loop;
    }

    Loop(const Loop &) = delete;
    Loop(Loop &&other) = delete;
    Loop& operator=(const Loop &) = delete;
    Loop& operator=(Loop &&other) = delete;

    ~Loop() noexcept {
        if(loop) {
            close();
        }
    }

    /**
     * @brief Sets additional loop options.
     *
     * You should normally call this before the first call to uv_run() unless
     * mentioned otherwise.

     * Supported options:
     *
     * * `Loop::Configure::BLOCK_SIGNAL`: Block a signal when polling for new
     * events. A second argument is required and it is the signal number.
     *
     * An ErrorEvent will be emitted in case of errors.
     *
     * See the official
     * [documentation](http://docs.libuv.org/en/v1.x/loop.html#c.uv_loop_configure)
     * for further details.
     */
    template<typename... Args>
    void configure(Configure flag, Args... args) {
        auto err = uv_loop_configure(loop.get(), static_cast<std::underlying_type_t<Configure>>(flag), std::forward<Args>(args)...);
        if(err) { publish(ErrorEvent{err}); }
    }

    /**
     * @brief Creates resources of handles' types.
     *
     * This should be used as a default method to create resources.

     * The arguments are the ones required for the specific resource.
     *
     * Use it as `loop->resource<uvw::TimerHandle>()`.
     *
     * @return A pointer to the newly created resource.
     */
    template<typename R, typename... Args>
    std::enable_if_t<std::is_base_of<BaseHandle, R>::value, std::shared_ptr<R>>
    resource(Args&&... args) {
        auto ptr = R::create(shared_from_this(), std::forward<Args>(args)...);
        ptr = ptr->init() ? ptr : nullptr;
        return ptr;
    }

    /**
     * @brief Creates resources of types other than handles' ones.
     *
     * This should be used as a default method to create resources.

     * The arguments are the ones required for the specific resource.
     *
     * Use it as `loop->resource<uvw::WorkReq>()`.
     *
     * @return A pointer to the newly created resource.
     */
    template<typename R, typename... Args>
    std::enable_if_t<not std::is_base_of<BaseHandle, R>::value, std::shared_ptr<R>>
    resource(Args&&... args) {
        return R::create(shared_from_this(), std::forward<Args>(args)...);
    }

    /**
     * @brief Releases all internal loop resources.
     *
     * Call this function only when the loop has finished executing and all open
     * handles and requests have been closed, or the loop will emit an error.
     *
     * An ErrorEvent will be emitted in case of errors.
     */
    void close() {
        auto err = uv_loop_close(loop.get());
        if(err) { publish(ErrorEvent{err}); }
    }

    /**
     * @brief Runs the event loop.
     *
     * Available modes are:
     *
     * * `Loop::Mode::DEFAULT`: Runs the event loop until there are no more
     * active and referenced handles or requests.
     * * `Loop::Mode::ONCE`: Poll for i/o once. Note that this function blocks
     * if there are no pending callbacks.
     * * `Loop::Mode::NOWAIT`: Poll for i/o once but don’t block if there are no
     * pending callbacks.
     *
     * See the official
     * [documentation](http://docs.libuv.org/en/v1.x/loop.html#c.uv_run)
     * for further details.
     *
     * @return True when done, false in all other cases.
     */
    template<Mode mode = Mode::DEFAULT>
    bool run() noexcept {
        auto utm = static_cast<std::underlying_type_t<Mode>>(mode);
        auto uvrm = static_cast<uv_run_mode>(utm);
        return (uv_run(loop.get(), uvrm) == 0);
    }

    /**
     * @brief Checks if there are active resources.
     * @return True if there are active resources in the loop.
     */
    bool alive() const noexcept {
        return !(uv_loop_alive(loop.get()) == 0);
    }

    /**
     * @brief Stops the event loop.
     *
     * It causes `run()` to end as soon as possible.

     * This will happen not sooner than the next loop iteration.

     * If this function was called before blocking for I/O, the loop won’t block
     * for I/O on this iteration.
     */
    void stop() noexcept {
        uv_stop(loop.get());
    }

    /**
     * @brief Get backend file descriptor.
     *
     * Only kqueue, epoll and event ports are supported.

     * This can be used in conjunction with `run<Loop::Mode::NOWAIT>()` to poll
     * in one thread and run the event loop’s callbacks in another.
     *
     * @return The backend file descriptor.
     */
    int descriptor() const noexcept {
        return uv_backend_fd(loop.get());
    }

    /**
     * @brief Gets the poll timeout.
     * @return The return value is in milliseconds, or -1 for no timeout.
     */
    Time timeout() const noexcept {
        return Time{uv_backend_timeout(loop.get())};
    }

    /**
     * @brief Returns the current timestamp in milliseconds.
     *
     * The timestamp is cached at the start of the event loop tick.

     * The timestamp increases monotonically from some arbitrary point in
     * time.

     * Don’t make assumptions about the starting point, you will only get
     * disappointed.
     *
     * @return The current timestamp in milliseconds.
     */
    Time now() const noexcept {
        return Time{uv_now(loop.get())};
    }

    /**
     * @brief Updates the event loop’s concept of _now_.
     *
     * The current time is cached at the start of the event loop tick in order
     * to reduce the number of time-related system calls.

     * You won’t normally need to call this function unless you have callbacks
     * that block the event loop for longer periods of time, where _longer_ is
     * somewhat subjective but probably on the order of a millisecond or more.
     */
    void update() const noexcept {
        return uv_update_time(loop.get());
    }

    /**
     * @brief Walks the list of handles.
     *
     * The callback will be executed once for each handle that is still active.
     *
     * @param callback A function to be invoked once for each active handle.
     */
    void walk(std::function<void(BaseHandle &)> callback) {
        // remember: non-capturing lambdas decay to pointers to functions
        uv_walk(loop.get(), [](uv_handle_t *handle, void *func) {
            BaseHandle &ref = *static_cast<BaseHandle*>(handle->data);
            std::function<void(BaseHandle &)> &f =
                    *static_cast<std::function<void(BaseHandle &)>*>(func);
            f(ref);
        }, &callback);
    }

private:
    std::unique_ptr<uv_loop_t, Deleter> loop;
};

}
<|endoftext|>


<commit_before>///
/// @file   popcount.cpp
/// @brief  Fast algorithm to count the number of 1 bits in an array.
///
/// Copyright (C) 2013 Kim Walisch, <kim.walisch@gmail.com>
///
/// This file is distributed under the BSD License. See the COPYING
/// file in the top level directory.
///

#if !defined(__STDC_CONSTANT_MACROS)
  #define __STDC_CONSTANT_MACROS
#endif

#include <stdint.h>

namespace primesieve {

/// This algorithm counts the number of 1 bits (population count) in
/// an array using 64-bit tree merging. To the best of my knowledge
/// this is the fastest integer arithmetic bit population count
/// algorithm, it uses only 8 operations for 8 bytes on 64-bit CPUs.
/// The 64-bit tree merging popcount algorithm is due to
/// Cdric Lauradoux, it is described in his paper:
/// http://perso.citi.insa-lyon.fr/claurado/ham/overview.pdf
/// http://perso.citi.insa-lyon.fr/claurado/hamming.html
///
uint64_t popcount(const uint64_t* array, uint64_t size)
{
  const uint64_t m1  = UINT64_C(0x5555555555555555);
  const uint64_t m2  = UINT64_C(0x3333333333333333);
  const uint64_t m4  = UINT64_C(0x0F0F0F0F0F0F0F0F);
  const uint64_t m8  = UINT64_C(0x00FF00FF00FF00FF);
  const uint64_t h01 = UINT64_C(0x0101010101010101);

  uint64_t limit30 = size - size % 30;
  uint64_t i, j;
  uint64_t count1, count2, half1, half2, acc;
  uint64_t bit_count = 0;
  uint64_t x;

  if (array == 0)
    return 0;

  // 64-bit tree merging (merging3)
  for (i = 0; i < limit30; i += 30, array += 30) {
    acc = 0;
    for (j = 0; j < 30; j += 3) {
      count1  =  array[j];
      count2  =  array[j+1];
      half1   =  array[j+2];
      half2   =  array[j+2];
      half1  &=  m1;
      half2   = (half2  >> 1) & m1;
      count1 -= (count1 >> 1) & m1;
      count2 -= (count2 >> 1) & m1;
      count1 +=  half1;
      count2 +=  half2;
      count1  = (count1 & m2) + ((count1 >> 2) & m2);
      count1 += (count2 & m2) + ((count2 >> 2) & m2);
      acc    += (count1 & m4) + ((count1 >> 4) & m4);
    }
    acc = (acc & m8) + ((acc >>  8) & m8);
    acc = (acc       +  (acc >> 16));
    acc = (acc       +  (acc >> 32));
    bit_count += acc & 0xffff;
  }

  // Count the bits of the remaining bytes (max 29*8 = 232)
  // http://en.wikipedia.org/wiki/Hamming_weight#Efficient_implementation
  for (i = 0; i < size - limit30; i++) {
    x = array[i];
    x =  x       - ((x >> 1)  & m1);
    x = (x & m2) + ((x >> 2)  & m2);
    x = (x       +  (x >> 4)) & m4;
    x = (x * h01) >> 56;
    bit_count += x;
  }

  return bit_count;
}

} // namespace primesieve
<commit_msg>Faster popcount algorithm (Harley-Seal 4th iteration)<commit_after>///
/// @file   popcount.cpp
/// @brief  Fast algorithm to count the number of 1 bits in an array
///         using only integer operations.
///
/// Copyright (C) 2015 Kim Walisch, <kim.walisch@gmail.com>
///
/// This file is distributed under the BSD License. See the COPYING
/// file in the top level directory.
///

#if !defined(__STDC_CONSTANT_MACROS)
  #define __STDC_CONSTANT_MACROS
#endif

#include <stdint.h>

namespace {

/// This uses fewer arithmetic operations than any other known
/// implementation on machines with fast multiplication.
/// It uses 12 arithmetic operations, one of which is a multiply.
/// http://en.wikipedia.org/wiki/Hamming_weight#Efficient_implementation
///
uint64_t popcount_mul(uint64_t x)
{
  const uint64_t m1  = UINT64_C(0x5555555555555555);
  const uint64_t m2  = UINT64_C(0x3333333333333333);
  const uint64_t m4  = UINT64_C(0x0F0F0F0F0F0F0F0F);
  const uint64_t h01 = UINT64_C(0x0101010101010101);

  x -=            (x >> 1)  & m1;
  x = (x & m2) + ((x >> 2)  & m2);
  x = (x +        (x >> 4)) & m4;
  return (x * h01) >> 56;
}

/// Carry-save adder (CSA).
/// @see Chapter 5 in "Hacker's Delight".
///
void CSA(uint64_t& h, uint64_t& l, uint64_t a, uint64_t b, uint64_t c)
{
  uint64_t u = a ^ b;
  h = (a & b) | (u & c);
  l = u ^ c;
}

/// Harley-Seal popcount (4th iteration).
/// The Harley-Seal popcount algorithm is one of the fastest algorithms
/// for counting 1 bits in an array using only integer operations.
/// This implementation uses only 5.69 instructions per 64-bit word.
/// @see Chapter 5 in "Hacker's Delight" 2nd edition.
///
uint64_t popcount_hs4(const uint64_t* array, uint64_t size)
{
  uint64_t total = 0;
  uint64_t ones = 0, twos = 0, fours = 0, eights = 0, sixteens = 0;
  uint64_t twosA, twosB, foursA, foursB, eightsA, eightsB;
  uint64_t limit = size - size % 16;
  uint64_t i = 0;

  for(; i < limit; i += 16)
  {
    CSA(twosA, ones, ones, array[i+0], array[i+1]);
    CSA(twosB, ones, ones, array[i+2], array[i+3]);
    CSA(foursA, twos, twos, twosA, twosB);
    CSA(twosA, ones, ones, array[i+4], array[i+5]);
    CSA(twosB, ones, ones, array[i+6], array[i+7]);
    CSA(foursB, twos, twos, twosA, twosB);
    CSA(eightsA,fours, fours, foursA, foursB);
    CSA(twosA, ones, ones, array[i+8], array[i+9]);
    CSA(twosB, ones, ones, array[i+10], array[i+11]);
    CSA(foursA, twos, twos, twosA, twosB);
    CSA(twosA, ones, ones, array[i+12], array[i+13]);
    CSA(twosB, ones, ones, array[i+14], array[i+15]);
    CSA(foursB, twos, twos, twosA, twosB);
    CSA(eightsB, fours, fours, foursA, foursB);
    CSA(sixteens, eights, eights, eightsA, eightsB);

    total += popcount_mul(sixteens);
  }

  total *= 16;
  total += 8 * popcount_mul(eights);
  total += 4 * popcount_mul(fours);
  total += 2 * popcount_mul(twos);
  total += 1 * popcount_mul(ones);

  for(; i < size; i++)
    total += popcount_mul(array[i]);

  return total;
}

} // namespace

namespace primesieve {

uint64_t popcount(const uint64_t* array, uint64_t size)
{
  return popcount_hs4(array, size);
}

} // namespace primesieve
<|endoftext|>


<commit_before>/*****************************************************************************
 *
 * This file is part of Mapnik (c++ mapping toolkit)
 *
 * Copyright (C) 2017 Artem Pavlenko
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 *
 *****************************************************************************/

// mapnik
#include <mapnik/geometry/boost_adapters.hpp>
#include <mapnik/geometry/box2d.hpp>
#include <mapnik/geometry/multi_point.hpp>
#include <mapnik/projection.hpp>
#include <mapnik/proj_transform.hpp>
#include <mapnik/coord.hpp>
#include <mapnik/util/is_clockwise.hpp>

// boost
#include <boost/geometry/algorithms/envelope.hpp>

#ifdef MAPNIK_USE_PROJ4
// proj4
#include <proj_api.h>
#endif

// stl
#include <vector>
#include <stdexcept>

namespace mapnik {

namespace { // (local)

// Returns points in clockwise order. This allows us to do anti-meridian checks.
template <typename T>
auto envelope_points(box2d<T> const& env, std::size_t num_points)
    -> geometry::multi_point<T>
{
    auto width = env.width();
    auto height = env.height();

    geometry::multi_point<T> coords;
    coords.reserve(num_points);

    // top side: left >>> right
    // gets extra point if (num_points % 4 >= 1)
    for (std::size_t i = 0, n = (num_points + 3) / 4; i < n; ++i)
    {
        auto x = env.minx() + (i * width) / n;
        coords.emplace_back(x, env.maxy());
    }

    // right side: top >>> bottom
    // gets extra point if (num_points % 4 >= 3)
    for (std::size_t i = 0, n = (num_points + 1) / 4; i < n; ++i)
    {
        auto y = env.maxy() - (i * height) / n;
        coords.emplace_back(env.maxx(), y);
    }

    // bottom side: right >>> left
    // gets extra point if (num_points % 4 >= 2)
    for (std::size_t i = 0, n = (num_points + 2) / 4; i < n; ++i)
    {
        auto x = env.maxx() - (i * width) / n;
        coords.emplace_back(x, env.miny());
    }

    // left side: bottom >>> top
    // never gets extra point
    for (std::size_t i = 0, n = (num_points + 0) / 4; i < n; ++i)
    {
        auto y = env.miny() + (i * height) / n;
        coords.emplace_back(env.minx(), y);
    }

    return coords;
}

} // namespace mapnik::(local)

proj_transform::proj_transform(projection const& source,
                               projection const& dest)
    : source_(source),
      dest_(dest),
      is_source_longlat_(false),
      is_dest_longlat_(false),
      is_source_equal_dest_(false),
      wgs84_to_merc_(false),
      merc_to_wgs84_(false)
{
    is_source_equal_dest_ = (source_ == dest_);
    if (!is_source_equal_dest_)
    {
        is_source_longlat_ = source_.is_geographic();
        is_dest_longlat_ = dest_.is_geographic();
        boost::optional<well_known_srs_e> src_k = source.well_known();
        boost::optional<well_known_srs_e> dest_k = dest.well_known();
        bool known_trans = false;
        if (src_k && dest_k)
        {
            if (*src_k == WGS_84 && *dest_k == G_MERC)
            {
                wgs84_to_merc_ = true;
                known_trans = true;
            }
            else if (*src_k == G_MERC && *dest_k == WGS_84)
            {
                merc_to_wgs84_ = true;
                known_trans = true;
            }
        }
        if (!known_trans)
        {
#ifdef MAPNIK_USE_PROJ4
            source_.init_proj4();
            dest_.init_proj4();
#else
            throw std::runtime_error(std::string("Cannot initialize proj_transform for given projections without proj4 support (-DMAPNIK_USE_PROJ4): '") + source_.params() + "'->'" + dest_.params() + "'");
#endif
        }
    }
}

bool proj_transform::equal() const
{
    return is_source_equal_dest_;
}

bool proj_transform::is_known() const
{
    return merc_to_wgs84_ || wgs84_to_merc_;
}

bool proj_transform::forward (double & x, double & y , double & z) const
{
    return forward(&x, &y, &z, 1);
}

bool proj_transform::forward (geometry::point<double> & p) const
{
    double z = 0;
    return forward(&(p.x), &(p.y), &z, 1);
}

unsigned int proj_transform::forward (std::vector<geometry::point<double>> & ls) const
{
    std::size_t size = ls.size();
    if (size == 0) return 0;

    if (is_source_equal_dest_)
        return 0;

    if (wgs84_to_merc_)
    {
        lonlat2merc(ls);
        return 0;
    }
    else if (merc_to_wgs84_)
    {
        merc2lonlat(ls);
        return 0;
    }

    geometry::point<double> * ptr = ls.data();
    double * x = reinterpret_cast<double*>(ptr);
    double * y = x + 1;
    double * z = nullptr;
    if(!forward(x, y, z, size, 2))
    {
        return size;
    }
    return 0;
}

bool proj_transform::forward (double * x, double * y , double * z, int point_count, int offset) const
{

    if (is_source_equal_dest_)
        return true;

    if (wgs84_to_merc_)
    {
        return lonlat2merc(x,y,point_count);
    }
    else if (merc_to_wgs84_)
    {
        return merc2lonlat(x,y,point_count);
    }

#ifdef MAPNIK_USE_PROJ4
    if (is_source_longlat_)
    {
        int i;
        for(i=0; i<point_count; i++) {
            x[i*offset] *= DEG_TO_RAD;
            y[i*offset] *= DEG_TO_RAD;
        }
    }

    if (pj_transform( source_.proj_, dest_.proj_, point_count,
                      offset, x,y,z) != 0)
    {
        return false;
    }

    for(int j=0; j<point_count; j++) {
        if (x[j] == HUGE_VAL || y[j] == HUGE_VAL)
        {
            return false;
        }
    }

    if (is_dest_longlat_)
    {
        int i;
        for(i=0; i<point_count; i++) {
            x[i*offset] *= RAD_TO_DEG;
            y[i*offset] *= RAD_TO_DEG;
        }
    }
#endif
    return true;
}

bool proj_transform::backward (double * x, double * y , double * z, int point_count, int offset) const
{
    if (is_source_equal_dest_)
        return true;

    if (wgs84_to_merc_)
    {
        return merc2lonlat(x,y,point_count);
    }
    else if (merc_to_wgs84_)
    {
        return lonlat2merc(x,y,point_count);
    }

#ifdef MAPNIK_USE_PROJ4
    if (is_dest_longlat_)
    {
        for (int i = 0; i < point_count; ++i)
        {
            x[i * offset] *= DEG_TO_RAD;
            y[i * offset] *= DEG_TO_RAD;
        }
    }

    if (pj_transform(dest_.proj_, source_.proj_, point_count,
                     offset, x, y, z) != 0)
    {
        return false;
    }

    for (int j = 0; j < point_count; ++j)
    {
        if (x[j] == HUGE_VAL || y[j] == HUGE_VAL)
        {
            return false;
        }
    }

    if (is_source_longlat_)
    {
        for (int i = 0; i < point_count; ++i)
        {
            x[i * offset] *= RAD_TO_DEG;
            y[i * offset] *= RAD_TO_DEG;
        }
    }
#endif
    return true;
}

bool proj_transform::backward (double & x, double & y , double & z) const
{
    return backward(&x, &y, &z, 1);
}

bool proj_transform::backward (geometry::point<double> & p) const
{
    double z = 0;
    return backward(&(p.x), &(p.y), &z, 1);
}

unsigned int proj_transform::backward (std::vector<geometry::point<double>> & ls) const
{
    std::size_t size = ls.size();
    if (size == 0) return 0;

    if (is_source_equal_dest_)
        return 0;

    if (wgs84_to_merc_)
    {
        merc2lonlat(ls);
        return 0;
    }
    else if (merc_to_wgs84_)
    {
        lonlat2merc(ls);
        return 0;
    }

    geometry::point<double> * ptr = ls.data();
    double * x = reinterpret_cast<double*>(ptr);
    double * y = x + 1;
    double * z = nullptr;
    if (!backward(x, y, z, size, 2))
    {
        return size;
    }
    return 0;
}

bool proj_transform::forward (box2d<double> & box) const
{
    if (is_source_equal_dest_)
        return true;

    double llx = box.minx();
    double ulx = box.minx();
    double lly = box.miny();
    double lry = box.miny();
    double lrx = box.maxx();
    double urx = box.maxx();
    double uly = box.maxy();
    double ury = box.maxy();
    double z = 0.0;
    if (!forward(llx,lly,z))
        return false;
    if (!forward(lrx,lry,z))
        return false;
    if (!forward(ulx,uly,z))
        return false;
    if (!forward(urx,ury,z))
        return false;

    double minx = std::min(ulx, llx);
    double miny = std::min(lly, lry);
    double maxx = std::max(urx, lrx);
    double maxy = std::max(ury, uly);
    box.init(minx,
             miny,
             maxx,
             maxy);
    return true;
}

bool proj_transform::backward (box2d<double> & box) const
{
    if (is_source_equal_dest_)
        return true;

    double x[4], y[4];
    x[0] = box.minx(); // llx 0
    y[0] = box.miny(); // lly 1
    x[1] = box.maxx(); // lrx 2
    y[1] = box.miny(); // lry 3
    x[2] = box.minx(); // ulx 4
    y[2] = box.maxy(); // uly 5
    x[3] = box.maxx(); // urx 6
    y[3] = box.maxy(); // ury 7

    if (!backward(x, y, nullptr, 4, 1))
        return false;

    double minx = std::min(x[0], x[2]);
    double miny = std::min(y[0], y[1]);
    double maxx = std::max(x[1], x[3]);
    double maxy = std::max(y[2], y[3]);
    box.init(minx, miny, maxx, maxy);
    return true;
}

// More robust, but expensive, bbox transform
// in the face of proj4 out of bounds conditions.
// Can result in 20 -> 10 r/s performance hit.
// Alternative is to provide proper clipping box
// in the target srs by setting map 'maximum-extent'

bool proj_transform::backward(box2d<double>& env, int points) const
{
    if (is_source_equal_dest_)
        return true;

    if (wgs84_to_merc_ || merc_to_wgs84_)
    {
        return backward(env);
    }

    auto coords = envelope_points(env, points);  // this is always clockwise

    for (auto & p : coords)
    {
        double z = 0;
        if (!backward(p.x, p.y, z))
            return false;
    }

    box2d<double> result;
    boost::geometry::envelope(coords, result);

    if (is_source_longlat_ && !util::is_clockwise(coords))
    {
        // we've gone to a geographic CS, and our clockwise envelope has
        // changed into an anticlockwise one. This means we've crossed the antimeridian, and
        // need to expand the X direction to +/-180 to include all the data. Once we can deal
        // with multiple bboxes in queries we can improve.
        double miny = result.miny();
        result.expand_to_include(-180.0, miny);
        result.expand_to_include(180.0, miny);
    }

    env.re_center(result.center().x, result.center().y);
    env.height(result.height());
    env.width(result.width());
    return true;
}

bool proj_transform::forward(box2d<double>& env, int points) const
{
    if (is_source_equal_dest_)
        return true;

    if (wgs84_to_merc_ || merc_to_wgs84_)
    {
        return forward(env);
    }

    auto coords = envelope_points(env, points);  // this is always clockwise

    for (auto & p : coords)
    {
        double z = 0;
        if (!forward(p.x, p.y, z))
            return false;
    }

    box2d<double> result;
    boost::geometry::envelope(coords, result);

    if (is_dest_longlat_ && !util::is_clockwise(coords))
    {
        // we've gone to a geographic CS, and our clockwise envelope has
        // changed into an anticlockwise one. This means we've crossed the antimeridian, and
        // need to expand the X direction to +/-180 to include all the data. Once we can deal
        // with multiple bboxes in queries we can improve.
        double miny = result.miny();
        result.expand_to_include(-180.0, miny);
        result.expand_to_include(180.0, miny);
    }

    env.re_center(result.center().x, result.center().y);
    env.height(result.height());
    env.width(result.width());

    return true;
}

mapnik::projection const& proj_transform::source() const
{
    return source_;
}
mapnik::projection const& proj_transform::dest() const
{
    return dest_;
}

}
<commit_msg>proj_transform: fix strided coordinate array transform<commit_after>/*****************************************************************************
 *
 * This file is part of Mapnik (c++ mapping toolkit)
 *
 * Copyright (C) 2017 Artem Pavlenko
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 *
 *****************************************************************************/

// mapnik
#include <mapnik/geometry/boost_adapters.hpp>
#include <mapnik/geometry/box2d.hpp>
#include <mapnik/geometry/multi_point.hpp>
#include <mapnik/projection.hpp>
#include <mapnik/proj_transform.hpp>
#include <mapnik/coord.hpp>
#include <mapnik/util/is_clockwise.hpp>

// boost
#include <boost/geometry/algorithms/envelope.hpp>

#ifdef MAPNIK_USE_PROJ4
// proj4
#include <proj_api.h>
#endif

// stl
#include <vector>
#include <stdexcept>

namespace mapnik {

namespace { // (local)

// Returns points in clockwise order. This allows us to do anti-meridian checks.
template <typename T>
auto envelope_points(box2d<T> const& env, std::size_t num_points)
    -> geometry::multi_point<T>
{
    auto width = env.width();
    auto height = env.height();

    geometry::multi_point<T> coords;
    coords.reserve(num_points);

    // top side: left >>> right
    // gets extra point if (num_points % 4 >= 1)
    for (std::size_t i = 0, n = (num_points + 3) / 4; i < n; ++i)
    {
        auto x = env.minx() + (i * width) / n;
        coords.emplace_back(x, env.maxy());
    }

    // right side: top >>> bottom
    // gets extra point if (num_points % 4 >= 3)
    for (std::size_t i = 0, n = (num_points + 1) / 4; i < n; ++i)
    {
        auto y = env.maxy() - (i * height) / n;
        coords.emplace_back(env.maxx(), y);
    }

    // bottom side: right >>> left
    // gets extra point if (num_points % 4 >= 2)
    for (std::size_t i = 0, n = (num_points + 2) / 4; i < n; ++i)
    {
        auto x = env.maxx() - (i * width) / n;
        coords.emplace_back(x, env.miny());
    }

    // left side: bottom >>> top
    // never gets extra point
    for (std::size_t i = 0, n = (num_points + 0) / 4; i < n; ++i)
    {
        auto y = env.miny() + (i * height) / n;
        coords.emplace_back(env.minx(), y);
    }

    return coords;
}

} // namespace mapnik::(local)

proj_transform::proj_transform(projection const& source,
                               projection const& dest)
    : source_(source),
      dest_(dest),
      is_source_longlat_(false),
      is_dest_longlat_(false),
      is_source_equal_dest_(false),
      wgs84_to_merc_(false),
      merc_to_wgs84_(false)
{
    is_source_equal_dest_ = (source_ == dest_);
    if (!is_source_equal_dest_)
    {
        is_source_longlat_ = source_.is_geographic();
        is_dest_longlat_ = dest_.is_geographic();
        boost::optional<well_known_srs_e> src_k = source.well_known();
        boost::optional<well_known_srs_e> dest_k = dest.well_known();
        bool known_trans = false;
        if (src_k && dest_k)
        {
            if (*src_k == WGS_84 && *dest_k == G_MERC)
            {
                wgs84_to_merc_ = true;
                known_trans = true;
            }
            else if (*src_k == G_MERC && *dest_k == WGS_84)
            {
                merc_to_wgs84_ = true;
                known_trans = true;
            }
        }
        if (!known_trans)
        {
#ifdef MAPNIK_USE_PROJ4
            source_.init_proj4();
            dest_.init_proj4();
#else
            throw std::runtime_error(std::string("Cannot initialize proj_transform for given projections without proj4 support (-DMAPNIK_USE_PROJ4): '") + source_.params() + "'->'" + dest_.params() + "'");
#endif
        }
    }
}

bool proj_transform::equal() const
{
    return is_source_equal_dest_;
}

bool proj_transform::is_known() const
{
    return merc_to_wgs84_ || wgs84_to_merc_;
}

bool proj_transform::forward (double & x, double & y , double & z) const
{
    return forward(&x, &y, &z, 1);
}

bool proj_transform::forward (geometry::point<double> & p) const
{
    double z = 0;
    return forward(&(p.x), &(p.y), &z, 1);
}

unsigned int proj_transform::forward (std::vector<geometry::point<double>> & ls) const
{
    std::size_t size = ls.size();
    if (size == 0) return 0;

    if (is_source_equal_dest_)
        return 0;

    if (wgs84_to_merc_)
    {
        lonlat2merc(ls);
        return 0;
    }
    else if (merc_to_wgs84_)
    {
        merc2lonlat(ls);
        return 0;
    }

    geometry::point<double> * ptr = ls.data();
    double * x = reinterpret_cast<double*>(ptr);
    double * y = x + 1;
    double * z = nullptr;
    if(!forward(x, y, z, size, 2))
    {
        return size;
    }
    return 0;
}

bool proj_transform::forward (double * x, double * y , double * z, int point_count, int offset) const
{

    if (is_source_equal_dest_)
        return true;

    if (wgs84_to_merc_)
    {
        return lonlat2merc(x, y, point_count, offset);
    }
    else if (merc_to_wgs84_)
    {
        return merc2lonlat(x, y, point_count, offset);
    }

#ifdef MAPNIK_USE_PROJ4
    if (is_source_longlat_)
    {
        int i;
        for(i=0; i<point_count; i++) {
            x[i*offset] *= DEG_TO_RAD;
            y[i*offset] *= DEG_TO_RAD;
        }
    }

    if (pj_transform( source_.proj_, dest_.proj_, point_count,
                      offset, x,y,z) != 0)
    {
        return false;
    }

    for(int j=0; j<point_count; j++) {
        if (x[j] == HUGE_VAL || y[j] == HUGE_VAL)
        {
            return false;
        }
    }

    if (is_dest_longlat_)
    {
        int i;
        for(i=0; i<point_count; i++) {
            x[i*offset] *= RAD_TO_DEG;
            y[i*offset] *= RAD_TO_DEG;
        }
    }
#endif
    return true;
}

bool proj_transform::backward (double * x, double * y , double * z, int point_count, int offset) const
{
    if (is_source_equal_dest_)
        return true;

    if (wgs84_to_merc_)
    {
        return merc2lonlat(x, y, point_count, offset);
    }
    else if (merc_to_wgs84_)
    {
        return lonlat2merc(x, y, point_count, offset);
    }

#ifdef MAPNIK_USE_PROJ4
    if (is_dest_longlat_)
    {
        for (int i = 0; i < point_count; ++i)
        {
            x[i * offset] *= DEG_TO_RAD;
            y[i * offset] *= DEG_TO_RAD;
        }
    }

    if (pj_transform(dest_.proj_, source_.proj_, point_count,
                     offset, x, y, z) != 0)
    {
        return false;
    }

    for (int j = 0; j < point_count; ++j)
    {
        if (x[j] == HUGE_VAL || y[j] == HUGE_VAL)
        {
            return false;
        }
    }

    if (is_source_longlat_)
    {
        for (int i = 0; i < point_count; ++i)
        {
            x[i * offset] *= RAD_TO_DEG;
            y[i * offset] *= RAD_TO_DEG;
        }
    }
#endif
    return true;
}

bool proj_transform::backward (double & x, double & y , double & z) const
{
    return backward(&x, &y, &z, 1);
}

bool proj_transform::backward (geometry::point<double> & p) const
{
    double z = 0;
    return backward(&(p.x), &(p.y), &z, 1);
}

unsigned int proj_transform::backward (std::vector<geometry::point<double>> & ls) const
{
    std::size_t size = ls.size();
    if (size == 0) return 0;

    if (is_source_equal_dest_)
        return 0;

    if (wgs84_to_merc_)
    {
        merc2lonlat(ls);
        return 0;
    }
    else if (merc_to_wgs84_)
    {
        lonlat2merc(ls);
        return 0;
    }

    geometry::point<double> * ptr = ls.data();
    double * x = reinterpret_cast<double*>(ptr);
    double * y = x + 1;
    double * z = nullptr;
    if (!backward(x, y, z, size, 2))
    {
        return size;
    }
    return 0;
}

bool proj_transform::forward (box2d<double> & box) const
{
    if (is_source_equal_dest_)
        return true;

    double llx = box.minx();
    double ulx = box.minx();
    double lly = box.miny();
    double lry = box.miny();
    double lrx = box.maxx();
    double urx = box.maxx();
    double uly = box.maxy();
    double ury = box.maxy();
    double z = 0.0;
    if (!forward(llx,lly,z))
        return false;
    if (!forward(lrx,lry,z))
        return false;
    if (!forward(ulx,uly,z))
        return false;
    if (!forward(urx,ury,z))
        return false;

    double minx = std::min(ulx, llx);
    double miny = std::min(lly, lry);
    double maxx = std::max(urx, lrx);
    double maxy = std::max(ury, uly);
    box.init(minx,
             miny,
             maxx,
             maxy);
    return true;
}

bool proj_transform::backward (box2d<double> & box) const
{
    if (is_source_equal_dest_)
        return true;

    double x[4], y[4];
    x[0] = box.minx(); // llx 0
    y[0] = box.miny(); // lly 1
    x[1] = box.maxx(); // lrx 2
    y[1] = box.miny(); // lry 3
    x[2] = box.minx(); // ulx 4
    y[2] = box.maxy(); // uly 5
    x[3] = box.maxx(); // urx 6
    y[3] = box.maxy(); // ury 7

    if (!backward(x, y, nullptr, 4, 1))
        return false;

    double minx = std::min(x[0], x[2]);
    double miny = std::min(y[0], y[1]);
    double maxx = std::max(x[1], x[3]);
    double maxy = std::max(y[2], y[3]);
    box.init(minx, miny, maxx, maxy);
    return true;
}

// More robust, but expensive, bbox transform
// in the face of proj4 out of bounds conditions.
// Can result in 20 -> 10 r/s performance hit.
// Alternative is to provide proper clipping box
// in the target srs by setting map 'maximum-extent'

bool proj_transform::backward(box2d<double>& env, int points) const
{
    if (is_source_equal_dest_)
        return true;

    if (wgs84_to_merc_ || merc_to_wgs84_)
    {
        return backward(env);
    }

    auto coords = envelope_points(env, points);  // this is always clockwise

    for (auto & p : coords)
    {
        double z = 0;
        if (!backward(p.x, p.y, z))
            return false;
    }

    box2d<double> result;
    boost::geometry::envelope(coords, result);

    if (is_source_longlat_ && !util::is_clockwise(coords))
    {
        // we've gone to a geographic CS, and our clockwise envelope has
        // changed into an anticlockwise one. This means we've crossed the antimeridian, and
        // need to expand the X direction to +/-180 to include all the data. Once we can deal
        // with multiple bboxes in queries we can improve.
        double miny = result.miny();
        result.expand_to_include(-180.0, miny);
        result.expand_to_include(180.0, miny);
    }

    env.re_center(result.center().x, result.center().y);
    env.height(result.height());
    env.width(result.width());
    return true;
}

bool proj_transform::forward(box2d<double>& env, int points) const
{
    if (is_source_equal_dest_)
        return true;

    if (wgs84_to_merc_ || merc_to_wgs84_)
    {
        return forward(env);
    }

    auto coords = envelope_points(env, points);  // this is always clockwise

    for (auto & p : coords)
    {
        double z = 0;
        if (!forward(p.x, p.y, z))
            return false;
    }

    box2d<double> result;
    boost::geometry::envelope(coords, result);

    if (is_dest_longlat_ && !util::is_clockwise(coords))
    {
        // we've gone to a geographic CS, and our clockwise envelope has
        // changed into an anticlockwise one. This means we've crossed the antimeridian, and
        // need to expand the X direction to +/-180 to include all the data. Once we can deal
        // with multiple bboxes in queries we can improve.
        double miny = result.miny();
        result.expand_to_include(-180.0, miny);
        result.expand_to_include(180.0, miny);
    }

    env.re_center(result.center().x, result.center().y);
    env.height(result.height());
    env.width(result.width());

    return true;
}

mapnik::projection const& proj_transform::source() const
{
    return source_;
}
mapnik::projection const& proj_transform::dest() const
{
    return dest_;
}

}
<|endoftext|>


<commit_before>#include <pylon_camera/internal/pylon_camera.h>

using namespace Pylon;

namespace pylon_camera
{

enum PYLON_CAM_TYPE
{
    GIGE = 1,
    USB = 2,
    DART = 3,
    UNKNOWN = -1,
};

PYLON_CAM_TYPE detectPylonCamType(CInstantCamera* cam)
{
    VersionInfo sfnc_version;
    try
    {
        sfnc_version = cam->GetSfncVersion();
    }
    catch (const GenICam::GenericException &e)
    {
        std::cerr << "An exception while detecting the pylon camera type from its SFNC-Version occurred:" << std::endl;
        std::cerr << e.GetDescription() << std::endl;
        return UNKNOWN;
    }

    switch (sfnc_version.getMinor())
    {
        case 0: // GigE Camera: Sfnc_2_0_0
            return GIGE;
        case 1: // USB Camera: Sfnc_2_1_0
            return USB;
        case 2: // DART Camera: Sfnc_2_2_0
            return DART;
        default:
            std::cerr << "Unknown Camera Type!" << std::endl;
            return UNKNOWN;
    }
}

PylonCamera* createFromDevice(PYLON_CAM_TYPE cam_type, IPylonDevice* device)
{
    switch (cam_type)
    {
        case GIGE:
            return new PylonGigECamera(device);
        case USB:
            return new PylonUSBCamera(device);
        case DART:
            return new PylonDARTCamera(device);
        case UNKNOWN:
        default:
            return NULL;
    }
}

PylonCamera* PylonCamera::create()
{
    try
    {
        CInstantCamera* cam = new CInstantCamera(CTlFactory::GetInstance().CreateFirstDevice());
        cam->Open();

        {
            GenApi::INodeMap& node_map = cam->GetNodeMap();
            GenApi::CStringPtr DeviceUserID(node_map.GetNode("DeviceUserID"));
            std::string device_user_id(DeviceUserID->GetValue());
            std::cout << "Using camera " << device_user_id << std::endl;
        }

        PYLON_CAM_TYPE cam_type = detectPylonCamType(cam);

        cam->Close();
        delete cam;
        return createFromDevice(cam_type, CTlFactory::GetInstance().CreateFirstDevice());
    }
    catch (const GenICam::GenericException &e)
    {
        std::cerr << "Error while PylonCamera::create(). Exception: " << e.what() << std::endl;
        return NULL;
    }
}

PylonCamera* PylonCamera::create(const std::string& name)
{
    if (name.empty() || name.compare("x") == 0)
    {
        return create();
    }
    try
    {
        // Get the transport layer factory.
        CTlFactory& transport_layer_factory = CTlFactory::GetInstance();

        // Get all attached devices and exit application if no device is found.
        DeviceInfoList_t device_info_list;

        if (transport_layer_factory.EnumerateDevices(device_info_list) == 0)
        {
            throw RUNTIME_EXCEPTION( "No camera present.");
            return NULL;
        }

        // Create an array of instant cameras for the found devices
        CInstantCameraArray camera_array(device_info_list.size());

        bool found_desired_device = false;

        // Create and attach all Pylon Devices.
        size_t cam_pos = -1;
        for (size_t i = 0; i < camera_array.GetSize(); ++i)
        {
            try
            {
                camera_array[i].Attach(transport_layer_factory.CreateDevice(device_info_list[i]));

                camera_array[i].Open();

                GenApi::INodeMap& node_map = camera_array[i].GetNodeMap();
                GenApi::CStringPtr DeviceUserID(node_map.GetNode("DeviceUserID"));
                std::string device_user_id(DeviceUserID->GetValue());

                camera_array[i].Close();

                if (device_user_id.compare(name) == 0 ||
                    device_user_id.compare(device_user_id.length() - name.length(), name.length(), name))
                {
                    found_desired_device = true;
                    cam_pos = i;
                    std::cout << "Found the desired Camera with Magazino ID: " << name
                              << ": "
                              << camera_array[cam_pos].GetDeviceInfo().GetModelName()
                              << std::endl;
                    break;
                }
            }
            catch (const GenICam::GenericException &e)
            {
                continue;
            }
        }

        if (!found_desired_device)
        {
            std::cerr << "Maybe the given magazino_cam_id ("
                      << name
                      << ") is wrong or has not yet been written to the camera using 'write_magazino_id_to_camera' ?!"
                      << std::endl;
            return NULL;
        }

        if (!camera_array[cam_pos].IsOpen())
        {
            camera_array[cam_pos].Open();
        }
        PYLON_CAM_TYPE cam_type = detectPylonCamType(&camera_array[cam_pos]);
        camera_array[cam_pos].Close();

        return createFromDevice(cam_type, transport_layer_factory.CreateDevice(camera_array[cam_pos].GetDeviceInfo()));
    }
    catch (GenICam::GenericException &e)
    {
        std::cerr << "An exception while opening the desired camera with Magazino ID: "
                  << name
                  << " occurred:"
                  << std::endl;
        std::cerr << e.GetDescription() << std::endl;
        return NULL;
    }
}

PylonCamera::PylonCamera()
    : img_rows_(-1)
    , img_cols_(-1)
    , height_aoi_(-1)
    , width_aoi_(-1)
    , offset_height_aoi_(-1)
    , offset_width_aoi_(-1)
    , img_size_byte_(-1)
    , max_framerate_(-1.0)
    , has_auto_exposure_(false)
    , last_exposure_val_(2000.0)
    , last_brightness_val_(-1)
    , is_ready_(false)
    , is_cam_removed_(false)
    , is_own_brightness_function_running_(false)
{
}

PylonCamera::~PylonCamera()
{
}

const int& PylonCamera::imageRows() const
{
    return img_rows_;
}

const int& PylonCamera::imageCols() const
{
    return img_cols_;
}

void PylonCamera::setImageSize(const int& size)
{
    img_size_byte_ = size;
}

const int& PylonCamera::imageSize() const
{
    return img_size_byte_;
}

const float& PylonCamera::maxPossibleFramerate() const
{
    return max_framerate_;
}

const bool& PylonCamera::hasAutoExposure() const
{
    return has_auto_exposure_;
}

const bool& PylonCamera::isCamRemoved() const
{
    return is_cam_removed_;
}

const double& PylonCamera::lastExposureValue() const
{
    return last_exposure_val_;
}

const bool& PylonCamera::isReady() const
{
    return is_ready_;
}

const int& PylonCamera::lastBrightnessValue() const
{
    return last_brightness_val_;
}

const std::vector<float>& PylonCamera::sequencerExposureTimes() const
{
    return seq_exp_times_;
}

const bool& PylonCamera::isOwnBrightnessFunctionRunning() const
{
    return is_own_brightness_function_running_;
}

}
<commit_msg>camera now also opens if no camera_name was written into it<commit_after>#include <pylon_camera/internal/pylon_camera.h>

using namespace Pylon;

namespace pylon_camera
{

enum PYLON_CAM_TYPE
{
    GIGE = 1,
    USB = 2,
    DART = 3,
    UNKNOWN = -1,
};

PYLON_CAM_TYPE detectPylonCamType(CInstantCamera* cam)
{
    VersionInfo sfnc_version;
    try
    {
        sfnc_version = cam->GetSfncVersion();
    }
    catch (const GenICam::GenericException &e)
    {
        std::cerr << "An exception while detecting the pylon camera type from its SFNC-Version occurred:" << std::endl;
        std::cerr << e.GetDescription() << std::endl;
        return UNKNOWN;
    }

    switch (sfnc_version.getMinor())
    {
        case 0: // GigE Camera: Sfnc_2_0_0
            return GIGE;
        case 1: // USB Camera: Sfnc_2_1_0
            return USB;
        case 2: // DART Camera: Sfnc_2_2_0
            return DART;
        default:
            std::cerr << "Unknown Camera Type!" << std::endl;
            return UNKNOWN;
    }
}

PylonCamera* createFromDevice(PYLON_CAM_TYPE cam_type, IPylonDevice* device)
{
    switch (cam_type)
    {
        case GIGE:
            return new PylonGigECamera(device);
        case USB:
            return new PylonUSBCamera(device);
        case DART:
            return new PylonDARTCamera(device);
        case UNKNOWN:
        default:
            return NULL;
    }
}

PylonCamera* PylonCamera::create()
{
    try
    {
        CInstantCamera* cam = new CInstantCamera(CTlFactory::GetInstance().CreateFirstDevice());
        cam->Open();

        {
            GenApi::INodeMap& node_map = cam->GetNodeMap();
            GenApi::CStringPtr DeviceUserID(node_map.GetNode("DeviceUserID"));
            std::string device_user_id(DeviceUserID->GetValue());
            std::cout << "Using camera " << device_user_id << std::endl;
        }

        PYLON_CAM_TYPE cam_type = detectPylonCamType(cam);

        cam->Close();
        delete cam;
        return createFromDevice(cam_type, CTlFactory::GetInstance().CreateFirstDevice());
    }
    catch (const GenICam::GenericException &e)
    {
        std::cerr << "Error while PylonCamera::create(). Exception: " << e.what() << std::endl;
        return NULL;
    }
}

PylonCamera* PylonCamera::create(const std::string& name)
{
    if (name.empty() || name.compare("x") == 0)
    {
        return create();
    }
    try
    {
        // Get the transport layer factory.
        CTlFactory& transport_layer_factory = CTlFactory::GetInstance();

        // Get all attached devices and exit application if no device is found.
        DeviceInfoList_t device_info_list;

        if (transport_layer_factory.EnumerateDevices(device_info_list) == 0)
        {
            throw RUNTIME_EXCEPTION( "No camera present.");
            return NULL;
        }

        // Create an array of instant cameras for the found devices
        CInstantCameraArray camera_array(device_info_list.size());

        bool found_desired_device = false;

        // Create and attach all Pylon Devices.
        size_t cam_pos = -1;
        for (size_t i = 0; i < camera_array.GetSize(); ++i)
        {
            try
            {
                camera_array[i].Attach(transport_layer_factory.CreateDevice(device_info_list[i]));

                camera_array[i].Open();

                GenApi::INodeMap& node_map = camera_array[i].GetNodeMap();
                GenApi::CStringPtr DeviceUserID(node_map.GetNode("DeviceUserID"));
                std::string device_user_id(DeviceUserID->GetValue());

                camera_array[i].Close();

//                std::cout << "device_user_id " << device_user_id << std::endl;
//                std::cout << "length " << device_user_id.size() << std::endl;

                if (device_user_id.compare(name) == 0) // ||
//                    device_user_id.compare(device_user_id.length() - name.length(), name.length(), name))
                {
                    found_desired_device = true;
                    cam_pos = i;
                    std::cout << "Found the desired Camera with Magazino ID: " << name
                              << ": "
                              << camera_array[cam_pos].GetDeviceInfo().GetModelName()
                              << std::endl;
                    break;
                }
            }
            catch (const GenICam::GenericException &e)
            {
                continue;
            }
        }

        if (!found_desired_device)
        {
            std::cerr << "Maybe the given magazino_cam_id ("
                      << name
                      << ") is wrong or has not yet been written to the camera using 'write_magazino_id_to_camera' ?!"
                      << std::endl;
            return NULL;
        }

        if (!camera_array[cam_pos].IsOpen())
        {
            camera_array[cam_pos].Open();
        }
        PYLON_CAM_TYPE cam_type = detectPylonCamType(&camera_array[cam_pos]);
        camera_array[cam_pos].Close();

        return createFromDevice(cam_type, transport_layer_factory.CreateDevice(camera_array[cam_pos].GetDeviceInfo()));
    }
    catch (GenICam::GenericException &e)
    {
        std::cerr << "An exception while opening the desired camera with Magazino ID: "
                  << name
                  << " occurred:"
                  << std::endl;
        std::cerr << e.GetDescription() << std::endl;
        return NULL;
    }
}

PylonCamera::PylonCamera()
    : img_rows_(-1)
    , img_cols_(-1)
    , height_aoi_(-1)
    , width_aoi_(-1)
    , offset_height_aoi_(-1)
    , offset_width_aoi_(-1)
    , img_size_byte_(-1)
    , max_framerate_(-1.0)
    , has_auto_exposure_(false)
    , last_exposure_val_(2000.0)
    , last_brightness_val_(-1)
    , is_ready_(false)
    , is_cam_removed_(false)
    , is_own_brightness_function_running_(false)
{
}

PylonCamera::~PylonCamera()
{
}

const int& PylonCamera::imageRows() const
{
    return img_rows_;
}

const int& PylonCamera::imageCols() const
{
    return img_cols_;
}

void PylonCamera::setImageSize(const int& size)
{
    img_size_byte_ = size;
}

const int& PylonCamera::imageSize() const
{
    return img_size_byte_;
}

const float& PylonCamera::maxPossibleFramerate() const
{
    return max_framerate_;
}

const bool& PylonCamera::hasAutoExposure() const
{
    return has_auto_exposure_;
}

const bool& PylonCamera::isCamRemoved() const
{
    return is_cam_removed_;
}

const double& PylonCamera::lastExposureValue() const
{
    return last_exposure_val_;
}

const bool& PylonCamera::isReady() const
{
    return is_ready_;
}

const int& PylonCamera::lastBrightnessValue() const
{
    return last_brightness_val_;
}

const std::vector<float>& PylonCamera::sequencerExposureTimes() const
{
    return seq_exp_times_;
}

const bool& PylonCamera::isOwnBrightnessFunctionRunning() const
{
    return is_own_brightness_function_running_;
}

}
<|endoftext|>


<commit_before>//=======================================================================
// Copyright Baptiste Wicht 2011.
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
//  http://www.boost.org/LICENSE_1_0.txt)
//=======================================================================

#include <iostream>

#include "AssemblyFileWriter.hpp"
#include "Functions.hpp"
#include "Context.hpp"
#include "Utils.hpp"

using namespace eddic;

using std::endl;
using std::shared_ptr;

std::string eddic::mangle(Type type){
    if(type == INT){
        return "I";
    } else {
        return "S";
    }
}

void MainDeclaration::write(AssemblyFileWriter& writer){
    writer.stream() << ".text" << endl
                    << ".globl main" << endl
                    << "\t.type main, @function" << endl;
}

void FunctionCall::checkFunctions(Program& program){
    m_function_mangled = mangle(m_function, m_values);

    if(!program.exists(m_function_mangled)){
        throw CompilerException("The function \"" + m_function + "()\" does not exists", token());
    }
}

void Function::addParameter(std::string name, Type type){
    shared_ptr<Parameter> param(new Parameter(name, type, m_currentPosition));
    m_parameters.push_back(param);

    m_currentPosition += size(type);
}

void Function::write(AssemblyFileWriter& writer){
    writer.stream() << endl << mangledName() << ":" << endl;

    writer.stream() << "pushl %ebp" << std::endl;
    writer.stream() << "movl %esp, %ebp" << std::endl;

    context()->write(writer);

    ParseNode::write(writer);

    context()->release(writer);

    writer.stream() << "leave" << std::endl;
    writer.stream() << "ret" << std::endl;
}

void FunctionCall::write(AssemblyFileWriter& writer){
    std::vector<std::shared_ptr<Value>>::reverse_iterator it = m_values.rbegin();
    std::vector<std::shared_ptr<Value>>::reverse_iterator end = m_values.rend();

    for( ; it != end; ++it){
        (*it)->write(writer);
    }

    writer.stream() << "call " << m_function_mangled << endl;
}
<commit_msg>Use for_each to simplify the management of Value<commit_after>//=======================================================================
// Copyright Baptiste Wicht 2011.
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
//  http://www.boost.org/LICENSE_1_0.txt)
//=======================================================================

#include <iostream>
#include <algorithm>

#include "AssemblyFileWriter.hpp"
#include "Functions.hpp"
#include "Context.hpp"
#include "Utils.hpp"

using namespace eddic;

using std::endl;
using std::shared_ptr;

std::string eddic::mangle(Type type){
    if(type == INT){
        return "I";
    } else {
        return "S";
    }
}

void MainDeclaration::write(AssemblyFileWriter& writer){
    writer.stream() << ".text" << endl
                    << ".globl main" << endl
                    << "\t.type main, @function" << endl;
}

void FunctionCall::checkFunctions(Program& program){
    m_function_mangled = mangle(m_function, m_values);

    if(!program.exists(m_function_mangled)){
        throw CompilerException("The function \"" + m_function + "()\" does not exists", token());
    }
}

void Function::addParameter(std::string name, Type type){
    shared_ptr<Parameter> param(new Parameter(name, type, m_currentPosition));
    m_parameters.push_back(param);

    m_currentPosition += size(type);
}

void Function::write(AssemblyFileWriter& writer){
    writer.stream() << endl << mangledName() << ":" << endl;

    writer.stream() << "pushl %ebp" << std::endl;
    writer.stream() << "movl %esp, %ebp" << std::endl;

    context()->write(writer);

    ParseNode::write(writer);

    context()->release(writer);

    writer.stream() << "leave" << std::endl;
    writer.stream() << "ret" << std::endl;
}

void FunctionCall::write(AssemblyFileWriter& writer){
    for_each(m_values.rbegin(), m_values.rend(), [&](std::shared_ptr<Value> v){ v->write(writer); });

    writer.stream() << "call " << m_function_mangled << endl;
}
<|endoftext|>