<commit_before>/*
 *            Copyright 2009-2020 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.
 *
 */

// Local VOTCA includes
#include "votca/xtp/rpa.h"
#include "votca/xtp/aomatrix.h"
#include "votca/xtp/threecenter.h"
#include "votca/xtp/vc2index.h"

namespace votca {
namespace xtp {

void RPA::UpdateRPAInputEnergies(const Eigen::VectorXd& dftenergies,
                                 const Eigen::VectorXd& gwaenergies,
                                 Index qpmin) {
  Index rpatotal = _rpamax - _rpamin + 1;
  _energies = dftenergies.segment(_rpamin, rpatotal);
  Index gwsize = Index(gwaenergies.size());
  Index lumo = _homo + 1;

  Index qpmax = qpmin + gwsize - 1;
  _energies.segment(qpmin - _rpamin, gwsize) = gwaenergies;

  Eigen::VectorXd corrections_occ =
      _energies.segment(qpmin - _rpamin, lumo - qpmin) -
      dftenergies.segment(qpmin - _rpamin, lumo - qpmin);
  Eigen::VectorXd corrections_virt =
      _energies.segment(lumo - qpmin, gwsize - (lumo - qpmin)) -
      dftenergies.segment(lumo - qpmin, gwsize - (lumo - qpmin));
  double max_correction_occ = (corrections_occ.cwiseAbs()).maxCoeff();
  double max_correction_virt = (corrections_virt.cwiseAbs()).maxCoeff();

  Index levelaboveqpmax = _rpamax - qpmax;
  Index levelbelowqpmin = qpmin - _rpamin;

  _energies.segment(0, levelbelowqpmin).array() -= max_correction_occ;
  _energies.segment(qpmax + 1 - _rpamin, levelaboveqpmax).array() +=
      max_correction_virt;
}

template <bool imag>
Eigen::MatrixXd RPA::calculate_epsilon(double frequency) const {
  const Index size = _Mmn.auxsize();

  Eigen::MatrixXd result = Eigen::MatrixXd::Identity(size, size);

  const Index lumo = _homo + 1;
  const Index n_occ = lumo - _rpamin;
  const Index n_unocc = _rpamax - lumo + 1;
  const double freq2 = frequency * frequency;
  const double eta2 = _eta * _eta;

  for (Index m_level = 0; m_level < n_occ; m_level++) {
    const double qp_energy_m = _energies(m_level);

    const Eigen::MatrixXd Mmn_RPA = _Mmn[m_level].bottomRows(n_unocc);

    const Eigen::ArrayXd deltaE = _energies.tail(n_unocc).array() - qp_energy_m;
    Eigen::VectorXd denom;
    if (imag) {
      denom = 4 * deltaE / (deltaE.square() + freq2);
    } else {
      Eigen::ArrayXd deltEf = deltaE - frequency;
      Eigen::ArrayXd sum = deltEf / (deltEf.square() + eta2);
      deltEf = deltaE + frequency;
      sum += deltEf / (deltEf.square() + eta2);
      denom = 2 * sum;
    }
    result += Mmn_RPA.transpose() * denom.asDiagonal() * Mmn_RPA;
  }

  return result;
}

template Eigen::MatrixXd RPA::calculate_epsilon<true>(double frequency) const;
template Eigen::MatrixXd RPA::calculate_epsilon<false>(double frequency) const;

Eigen::MatrixXd RPA::calculate_epsilon_r(std::complex<double> frequency) const {

  const Index size = _Mmn.auxsize();
  //std::vector<Eigen::MatrixXd> thread_result = std::vector<Eigen::MatrixXd>(
  //    OPENMP::getMaxThreads(), Eigen::MatrixXd::Zero(size, size));
Eigen::MatrixXd result = Eigen::MatrixXd::Identity(size, size);

  const Index lumo = _homo + 1;
  const Index n_occ = lumo - _rpamin;
  const Index n_unocc = _rpamax - lumo + 1;

//#pragma omp parallel for schedule(guided)
#pragma omp parallel for schedule(dynamic) reduction(+ : result)
  for (Index m_level = 0; m_level < n_occ; m_level++) {
    const double qp_energy_m = _energies(m_level);
    const Eigen::MatrixXd Mmn_RPA =
        _Mmn[m_level].block(n_occ, 0, n_unocc, size);
    const Eigen::ArrayXd deltaE =
        _energies.segment(n_occ, n_unocc).array() - qp_energy_m;

    Eigen::VectorXd chi;
    Eigen::ArrayXd deltaEm = frequency.real() - deltaE;
    Eigen::ArrayXd deltaEp = frequency.real() + deltaE;

    double sigma_1 = std::pow(frequency.imag() + _eta, 2);
    double sigma_2 = std::pow(frequency.imag() - _eta, 2);

    chi = deltaEm * (deltaEm.cwiseAbs2() + sigma_1).cwiseInverse() -
          deltaEp * (deltaEp.cwiseAbs2() + sigma_2).cwiseInverse();
    //Eigen::MatrixXd tempresult =
    //    Mmn_RPA.transpose() * chi.asDiagonal() * Mmn_RPA;
    result += Mmn_RPA.transpose() * chi.asDiagonal() * Mmn_RPA;

    //thread_result[OPENMP::getThreadId()] += tempresult;
  }

  //Eigen::MatrixXd result = Eigen::MatrixXd::Identity(size, size);

  //for (const auto& mat : thread_result) {
  //  result -= 2 * mat;
  //}
  return -2*result;
}

Eigen::MatrixXcd RPA::calculate_epsilon_complex(
    std::complex<double> frequency) const {
  const Index size = _Mmn.auxsize();
  std::vector<Eigen::MatrixXcd> thread_result = std::vector<Eigen::MatrixXcd>(
      OPENMP::getMaxThreads(), Eigen::MatrixXcd::Zero(size, size));
  const Index lumo = _homo + 1;
  const Index n_occ = lumo - _rpamin;
  const Index n_unocc = _rpamax - lumo + 1;

  std::complex<double> eta(0.0, _eta);

#pragma omp parallel for schedule(guided)
  for (Index m_level = 0; m_level < n_occ; m_level++) {
    const double qp_energy_m = _energies(m_level);
    const Eigen::MatrixXd Mmn_RPA =
        _Mmn[m_level].block(n_occ, 0, n_unocc, size);
    const Eigen::ArrayXcd deltaE =
        _energies.segment(n_occ, n_unocc).array() - qp_energy_m;

    Eigen::VectorXcd chi;
    Eigen::ArrayXcd deltaEm = frequency - deltaE + eta;
    Eigen::ArrayXcd deltaEp = frequency + deltaE - eta;

    chi = deltaEm.cwiseInverse() - deltaEp.cwiseInverse();
    Eigen::MatrixXcd tempresult =
        Mmn_RPA.transpose() * chi.asDiagonal() * Mmn_RPA;

    thread_result[OPENMP::getThreadId()] += tempresult;
  }

  Eigen::MatrixXcd result = Eigen::MatrixXcd::Identity(size, size);

  for (const auto& mat : thread_result) {
    result -= 2. * mat;
  }
  return result;
}

RPA::rpa_eigensolution RPA::Diagonalize_H2p() const {
  const Index lumo = _homo + 1;
  const Index n_occ = lumo - _rpamin;
  const Index n_unocc = _rpamax - lumo + 1;
  const Index rpasize = n_occ * n_unocc;

  Eigen::VectorXd AmB = Calculate_H2p_AmB();
  Eigen::MatrixXd ApB = Calculate_H2p_ApB();

  RPA::rpa_eigensolution sol;
  sol.ERPA_correlation = -0.25 * (ApB.trace() + AmB.sum());

  // C = AmB^1/2 * ApB * AmB^1/2
  Eigen::MatrixXd& C = ApB;
  C.applyOnTheLeft(AmB.cwiseSqrt().asDiagonal());
  C.applyOnTheRight(AmB.cwiseSqrt().asDiagonal());

  Eigen::SelfAdjointEigenSolver<Eigen::MatrixXd> es = Diagonalize_H2p_C(C);

  // Do not remove this line! It has to be there for MKL to not crash
  sol.omega = Eigen::VectorXd::Zero(es.eigenvalues().size());
  sol.omega = es.eigenvalues().cwiseSqrt();
  sol.ERPA_correlation += 0.5 * sol.omega.sum();

  XTP_LOG(Log::info, _log) << TimeStamp()
                           << " Lowest neutral excitation energy (eV): "
                           << tools::conv::hrt2ev * sol.omega.minCoeff()
                           << std::flush;

  // RPA correlation energy calculated from Eq.9 of J. Chem. Phys. 132, 234114
  // (2010)
  XTP_LOG(Log::error, _log)
      << TimeStamp()
      << " RPA correlation energy (Hartree): " << sol.ERPA_correlation
      << std::flush;

  sol.XpY = Eigen::MatrixXd(rpasize, rpasize);

  Eigen::VectorXd AmB_sqrt = AmB.cwiseSqrt();
  Eigen::VectorXd Omega_sqrt_inv = sol.omega.cwiseSqrt().cwiseInverse();
  for (int s = 0; s < rpasize; s++) {
    sol.XpY.col(s) =
        Omega_sqrt_inv(s) * AmB_sqrt.cwiseProduct(es.eigenvectors().col(s));
  }

  return sol;
}

Eigen::VectorXd RPA::Calculate_H2p_AmB() const {
  const Index lumo = _homo + 1;
  const Index n_occ = lumo - _rpamin;
  const Index n_unocc = _rpamax - lumo + 1;
  const Index rpasize = n_occ * n_unocc;
  vc2index vc = vc2index(0, 0, n_unocc);
  Eigen::VectorXd AmB = Eigen::VectorXd::Zero(rpasize);
  for (Index v = 0; v < n_occ; v++) {
    Index i = vc.I(v, 0);
    AmB.segment(i, n_unocc) =
        _energies.segment(n_occ, n_unocc).array() - _energies(v);
  }
  return AmB;
}

Eigen::MatrixXd RPA::Calculate_H2p_ApB() const {
  const Index lumo = _homo + 1;
  const Index n_occ = lumo - _rpamin;
  const Index n_unocc = _rpamax - lumo + 1;
  const Index rpasize = n_occ * n_unocc;
  const Index auxsize = _Mmn.auxsize();
  vc2index vc = vc2index(0, 0, n_unocc);
  Eigen::MatrixXd ApB = Eigen::MatrixXd::Zero(rpasize, rpasize);
#pragma omp parallel for schedule(guided)
  for (Index v2 = 0; v2 < n_occ; v2++) {
    Index i2 = vc.I(v2, 0);
    const Eigen::MatrixXd Mmn_v2T =
        _Mmn[v2].block(n_occ, 0, n_unocc, auxsize).transpose();
    for (Index v1 = v2; v1 < n_occ; v1++) {
      Index i1 = vc.I(v1, 0);
      // Multiply with factor 2 to sum over both (identical) spin states
      ApB.block(i1, i2, n_unocc, n_unocc) =
          2 * 2 * _Mmn[v1].block(n_occ, 0, n_unocc, auxsize) * Mmn_v2T;
    }
  }
  ApB.diagonal() += Calculate_H2p_AmB();
  return ApB;
}

Eigen::SelfAdjointEigenSolver<Eigen::MatrixXd> RPA::Diagonalize_H2p_C(
    const Eigen::MatrixXd& C) const {
  XTP_LOG(Log::error, _log)
      << TimeStamp() << " Diagonalizing two-particle Hamiltonian "
      << std::flush;
  Eigen::SelfAdjointEigenSolver<Eigen::MatrixXd> es(C);  // Uses lower triangle
  XTP_LOG(Log::error, _log)
      << TimeStamp() << " Diagonalization done " << std::flush;
  double minCoeff = es.eigenvalues().minCoeff();
  if (minCoeff <= 0.0) {
    XTP_LOG(Log::error, _log)
        << TimeStamp() << " Detected non-positive eigenvalue: " << minCoeff
        << std::flush;
    throw std::runtime_error("Detected non-positive eigenvalue.");
  }
  return es;
}

}  // namespace xtp
}  // namespace votca
<commit_msg>eigen reductions and cleanup<commit_after>/*
 *            Copyright 2009-2020 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.
 *
 */

// Local VOTCA includes
#include "votca/xtp/rpa.h"
#include "votca/xtp/aomatrix.h"
#include "votca/xtp/threecenter.h"
#include "votca/xtp/vc2index.h"

namespace votca {
namespace xtp {

void RPA::UpdateRPAInputEnergies(const Eigen::VectorXd& dftenergies,
                                 const Eigen::VectorXd& gwaenergies,
                                 Index qpmin) {
  Index rpatotal = _rpamax - _rpamin + 1;
  _energies = dftenergies.segment(_rpamin, rpatotal);
  Index gwsize = Index(gwaenergies.size());
  Index lumo = _homo + 1;

  Index qpmax = qpmin + gwsize - 1;
  _energies.segment(qpmin - _rpamin, gwsize) = gwaenergies;

  Eigen::VectorXd corrections_occ =
      _energies.segment(qpmin - _rpamin, lumo - qpmin) -
      dftenergies.segment(qpmin - _rpamin, lumo - qpmin);
  Eigen::VectorXd corrections_virt =
      _energies.segment(lumo - qpmin, gwsize - (lumo - qpmin)) -
      dftenergies.segment(lumo - qpmin, gwsize - (lumo - qpmin));
  double max_correction_occ = (corrections_occ.cwiseAbs()).maxCoeff();
  double max_correction_virt = (corrections_virt.cwiseAbs()).maxCoeff();

  Index levelaboveqpmax = _rpamax - qpmax;
  Index levelbelowqpmin = qpmin - _rpamin;

  _energies.segment(0, levelbelowqpmin).array() -= max_correction_occ;
  _energies.segment(qpmax + 1 - _rpamin, levelaboveqpmax).array() +=
      max_correction_virt;
}

template <bool imag>
Eigen::MatrixXd RPA::calculate_epsilon(double frequency) const {
  const Index size = _Mmn.auxsize();

  Eigen::MatrixXd result = Eigen::MatrixXd::Identity(size, size);

  const Index lumo = _homo + 1;
  const Index n_occ = lumo - _rpamin;
  const Index n_unocc = _rpamax - lumo + 1;
  const double freq2 = frequency * frequency;
  const double eta2 = _eta * _eta;

  for (Index m_level = 0; m_level < n_occ; m_level++) {
    const double qp_energy_m = _energies(m_level);

    const Eigen::MatrixXd Mmn_RPA = _Mmn[m_level].bottomRows(n_unocc);

    const Eigen::ArrayXd deltaE = _energies.tail(n_unocc).array() - qp_energy_m;
    Eigen::VectorXd denom;
    if (imag) {
      denom = 4 * deltaE / (deltaE.square() + freq2);
    } else {
      Eigen::ArrayXd deltEf = deltaE - frequency;
      Eigen::ArrayXd sum = deltEf / (deltEf.square() + eta2);
      deltEf = deltaE + frequency;
      sum += deltEf / (deltEf.square() + eta2);
      denom = 2 * sum;
    }
    result += Mmn_RPA.transpose() * denom.asDiagonal() * Mmn_RPA;
  }

  return result;
}

template Eigen::MatrixXd RPA::calculate_epsilon<true>(double frequency) const;
template Eigen::MatrixXd RPA::calculate_epsilon<false>(double frequency) const;

Eigen::MatrixXd RPA::calculate_epsilon_r(std::complex<double> frequency) const {

  const Index size = _Mmn.auxsize();
  Eigen::MatrixXd result = Eigen::MatrixXd::Identity(size, size);

  const Index lumo = _homo + 1;
  const Index n_occ = lumo - _rpamin;
  const Index n_unocc = _rpamax - lumo + 1;

#pragma omp parallel for schedule(dynamic) reduction(+ : result)
  for (Index m_level = 0; m_level < n_occ; m_level++) {
    const double qp_energy_m = _energies(m_level);
    const Eigen::MatrixXd Mmn_RPA = _Mmn[m_level].bottomRows(n_unocc);
    const Eigen::ArrayXd deltaE = _energies.tail(n_unocc).array() - qp_energy_m;

    Eigen::VectorXd chi;
    Eigen::ArrayXd deltaEm = frequency.real() - deltaE;
    Eigen::ArrayXd deltaEp = frequency.real() + deltaE;

    double sigma_1 = std::pow(frequency.imag() + _eta, 2);
    double sigma_2 = std::pow(frequency.imag() - _eta, 2);

    chi = deltaEm * (deltaEm.cwiseAbs2() + sigma_1).cwiseInverse() -
          deltaEp * (deltaEp.cwiseAbs2() + sigma_2).cwiseInverse();
    result += -2 * Mmn_RPA.transpose() * chi.asDiagonal() * Mmn_RPA;
  }

  return result;
}

Eigen::MatrixXcd RPA::calculate_epsilon_complex(
    std::complex<double> frequency) const {
  const Index size = _Mmn.auxsize();
  std::vector<Eigen::MatrixXcd> thread_result = std::vector<Eigen::MatrixXcd>(
      OPENMP::getMaxThreads(), Eigen::MatrixXcd::Zero(size, size));
  const Index lumo = _homo + 1;
  const Index n_occ = lumo - _rpamin;
  const Index n_unocc = _rpamax - lumo + 1;

  std::complex<double> eta(0.0, _eta);

#pragma omp parallel for schedule(guided)
  for (Index m_level = 0; m_level < n_occ; m_level++) {
    const double qp_energy_m = _energies(m_level);
    const Eigen::MatrixXd Mmn_RPA =
        _Mmn[m_level].block(n_occ, 0, n_unocc, size);
    const Eigen::ArrayXcd deltaE =
        _energies.segment(n_occ, n_unocc).array() - qp_energy_m;

    Eigen::VectorXcd chi;
    Eigen::ArrayXcd deltaEm = frequency - deltaE + eta;
    Eigen::ArrayXcd deltaEp = frequency + deltaE - eta;

    chi = deltaEm.cwiseInverse() - deltaEp.cwiseInverse();
    Eigen::MatrixXcd tempresult =
        Mmn_RPA.transpose() * chi.asDiagonal() * Mmn_RPA;

    thread_result[OPENMP::getThreadId()] += tempresult;
  }

  Eigen::MatrixXcd result = Eigen::MatrixXcd::Identity(size, size);

  for (const auto& mat : thread_result) {
    result -= 2. * mat;
  }
  return result;
}

RPA::rpa_eigensolution RPA::Diagonalize_H2p() const {
  const Index lumo = _homo + 1;
  const Index n_occ = lumo - _rpamin;
  const Index n_unocc = _rpamax - lumo + 1;
  const Index rpasize = n_occ * n_unocc;

  Eigen::VectorXd AmB = Calculate_H2p_AmB();
  Eigen::MatrixXd ApB = Calculate_H2p_ApB();

  RPA::rpa_eigensolution sol;
  sol.ERPA_correlation = -0.25 * (ApB.trace() + AmB.sum());

  // C = AmB^1/2 * ApB * AmB^1/2
  Eigen::MatrixXd& C = ApB;
  C.applyOnTheLeft(AmB.cwiseSqrt().asDiagonal());
  C.applyOnTheRight(AmB.cwiseSqrt().asDiagonal());

  Eigen::SelfAdjointEigenSolver<Eigen::MatrixXd> es = Diagonalize_H2p_C(C);

  // Do not remove this line! It has to be there for MKL to not crash
  sol.omega = Eigen::VectorXd::Zero(es.eigenvalues().size());
  sol.omega = es.eigenvalues().cwiseSqrt();
  sol.ERPA_correlation += 0.5 * sol.omega.sum();

  XTP_LOG(Log::info, _log) << TimeStamp()
                           << " Lowest neutral excitation energy (eV): "
                           << tools::conv::hrt2ev * sol.omega.minCoeff()
                           << std::flush;

  // RPA correlation energy calculated from Eq.9 of J. Chem. Phys. 132, 234114
  // (2010)
  XTP_LOG(Log::error, _log)
      << TimeStamp()
      << " RPA correlation energy (Hartree): " << sol.ERPA_correlation
      << std::flush;

  sol.XpY = Eigen::MatrixXd(rpasize, rpasize);

  Eigen::VectorXd AmB_sqrt = AmB.cwiseSqrt();
  Eigen::VectorXd Omega_sqrt_inv = sol.omega.cwiseSqrt().cwiseInverse();
  for (int s = 0; s < rpasize; s++) {
    sol.XpY.col(s) =
        Omega_sqrt_inv(s) * AmB_sqrt.cwiseProduct(es.eigenvectors().col(s));
  }

  return sol;
}

Eigen::VectorXd RPA::Calculate_H2p_AmB() const {
  const Index lumo = _homo + 1;
  const Index n_occ = lumo - _rpamin;
  const Index n_unocc = _rpamax - lumo + 1;
  const Index rpasize = n_occ * n_unocc;
  vc2index vc = vc2index(0, 0, n_unocc);
  Eigen::VectorXd AmB = Eigen::VectorXd::Zero(rpasize);
  for (Index v = 0; v < n_occ; v++) {
    Index i = vc.I(v, 0);
    AmB.segment(i, n_unocc) =
        _energies.segment(n_occ, n_unocc).array() - _energies(v);
  }
  return AmB;
}

Eigen::MatrixXd RPA::Calculate_H2p_ApB() const {
  const Index lumo = _homo + 1;
  const Index n_occ = lumo - _rpamin;
  const Index n_unocc = _rpamax - lumo + 1;
  const Index rpasize = n_occ * n_unocc;
  const Index auxsize = _Mmn.auxsize();
  vc2index vc = vc2index(0, 0, n_unocc);
  Eigen::MatrixXd ApB = Eigen::MatrixXd::Zero(rpasize, rpasize);
#pragma omp parallel for schedule(guided)
  for (Index v2 = 0; v2 < n_occ; v2++) {
    Index i2 = vc.I(v2, 0);
    const Eigen::MatrixXd Mmn_v2T =
        _Mmn[v2].block(n_occ, 0, n_unocc, auxsize).transpose();
    for (Index v1 = v2; v1 < n_occ; v1++) {
      Index i1 = vc.I(v1, 0);
      // Multiply with factor 2 to sum over both (identical) spin states
      ApB.block(i1, i2, n_unocc, n_unocc) =
          2 * 2 * _Mmn[v1].block(n_occ, 0, n_unocc, auxsize) * Mmn_v2T;
    }
  }
  ApB.diagonal() += Calculate_H2p_AmB();
  return ApB;
}

Eigen::SelfAdjointEigenSolver<Eigen::MatrixXd> RPA::Diagonalize_H2p_C(
    const Eigen::MatrixXd& C) const {
  XTP_LOG(Log::error, _log)
      << TimeStamp() << " Diagonalizing two-particle Hamiltonian "
      << std::flush;
  Eigen::SelfAdjointEigenSolver<Eigen::MatrixXd> es(C);  // Uses lower triangle
  XTP_LOG(Log::error, _log)
      << TimeStamp() << " Diagonalization done " << std::flush;
  double minCoeff = es.eigenvalues().minCoeff();
  if (minCoeff <= 0.0) {
    XTP_LOG(Log::error, _log)
        << TimeStamp() << " Detected non-positive eigenvalue: " << minCoeff
        << std::flush;
    throw std::runtime_error("Detected non-positive eigenvalue.");
  }
  return es;
}

}  // namespace xtp
}  // namespace votca
<|endoftext|>


<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.
 *
 */
/// For an earlier history see ctp repo commit 77795ea591b29e664153f9404c8655ba28dc14e9

#include <votca/ctp/polarfrag.h>
#include <votca/ctp/dmaspace.h>

namespace votca {
namespace ctp {

PolarFrag::~PolarFrag()  {
    clear(); /* Polar sites cleaned by PolarSeg */
    if (_indu_cg_site != NULL) delete _indu_cg_site;
    if (_perm_cg_site != NULL) delete _perm_cg_site;
}

const votca::tools::vec &PolarFrag::CalcPosCenterOfGeom() {
    _pos = votca::tools::vec(0,0,0);
    for (unsigned int i = 0; i < this->size(); ++i) {
        _pos += (*this)[i]->getPos();
    }
    if (this->size() > 0) _pos /= double(this->size());
    return _pos;
}

const votca::tools::vec &PolarFrag::CalcPosPolarWeights() {
    // Establish total weights
    double sum_iso_p = 0.0;
    double sum_abs_q = 0.0;
    for (unsigned int i = 0; i < this->size(); ++i) {
        sum_iso_p += (*this)[i]->getIsoP();
        sum_abs_q += std::abs((*this)[i]->getQ00());
    }

    _pos = votca::tools::vec(0,0,0);
    // Any polar sites in here? If not, return (0,0,0)
    if (this->size() < 1) ;
    // Noteworthy charge and polarizability? If not, return CoG
    else if (sum_abs_q <= 1e-2 && sum_iso_p <= 1e-2) {
        _pos = this->CalcPosCenterOfGeom();
    }
    // Else: return weighted 0.5*(center-of-polarity + center-of-charge)
    else {
        for (unsigned int i = 0; i < this->size(); ++i) {
            double weight = 0.0;
            if (sum_abs_q < 1e-2) {
                assert(sum_iso_p >= 1e-2 && "<CalcPosPolarWeights> P-ERROR");
                weight = (*this)[i]->getIsoP()/sum_iso_p;
            }
            else if (sum_iso_p < 1e-2) {
                assert(sum_abs_q >= 1e-2 && "<CalcPosPolarWeights> Q-ERROR");
                weight = std::abs((*this)[i]->getQ00())/sum_abs_q;
            }
            else {
                weight = 0.5 * (
                    (*this)[i]->getIsoP()/sum_iso_p
                  + std::abs((*this)[i]->getQ00())/sum_abs_q);
            }
            _pos += (*this)[i]->getPos() * weight;
        }
    }
    return _pos;
}

void PolarFrag::GeneratePermInduCgSite(bool do_cg_polarizabilities) {
    // ATTENTION The same method appears in <PolarSeg>
    assert(!do_cg_polarizabilities && "NOT IMPLEMENTED, NOT NEEDED?");
    // Collapse multipole moments : position, rank L
    vec target_pos = _pos;
    int state = 0;
    int L = 2;
    vector<double> QCG(L*L+2*L+1, 0.0);  // permanent
    vector<double> uQCG(L*L+2*L+1, 0.0); // induced

    for (PolarFrag::iterator pit = begin();
        pit < end(); ++pit) {
        // PERMANENT MOMENTS
        // Convert real to complex moments
        vector<double> Qlm = (*pit)->getQs(0);
        DMA::ComplexSphericalMoments Xlm(Qlm);
        // Shift moments
        DMA::MomentShift mshift;
        vec shift = target_pos - (*pit)->getPos();
        DMA::RegularSphericalHarmonics Clm(-shift);
        vector<DMA::cmplx> Xlm_shifted = mshift.Shift(Xlm, Clm);
        // Convert complex to real moments & add to base
        DMA::RealSphericalMoments Qlm_shifted(Xlm_shifted);
        Qlm_shifted.AddToVector(QCG);

        // INDUCED MOMENTS
        // Convert real to complex moments
        vec u1 = (*pit)->getU1();
        vector<double> uQlm(L*L+2*L+1, 0.0);
        uQlm[1] = u1.getZ(); // NOTE order is z-x-y == 10-11c-11s
        uQlm[2] = u1.getX();
        uQlm[3] = u1.getY();
        DMA::ComplexSphericalMoments uXlm(uQlm);
        // Shift moments
        DMA::RegularSphericalHarmonics uClm(-shift);
        vector<DMA::cmplx> uXlm_shifted = mshift.Shift(uXlm, uClm);
        // Convert complex to real moments & add to base
        DMA::RealSphericalMoments uQlm_shifted(uXlm_shifted);
        uQlm_shifted.AddToVector(uQCG);
    }

    // Collapse polarizabilities
    votca::tools::matrix PCG;
    PCG.ZeroMatrix();

    // Zero induced dipole
    vec u1_cg_red = vec(0,0,0);

    // Generate new coarse-grained site from the above
    APolarSite *indu_cg_site = new APolarSite(this->getId(), "FGU");
    APolarSite *perm_cg_site = new APolarSite(this->getId(), "FGP");

    indu_cg_site->setResolution(APolarSite::coarsegrained);
    indu_cg_site->setPos(target_pos);
    indu_cg_site->setRank(L);

    perm_cg_site->setResolution(APolarSite::coarsegrained);
    perm_cg_site->setPos(target_pos);
    perm_cg_site->setRank(L);

    // ATTENTION Save INDUCED   moments as PERMANENT moments (<indu_cg_site>)
    // ATTENTION Save PERMANENT moments as PERMANENT moments (<perm_cg_site>)
    indu_cg_site->setQs(uQCG, state);
    indu_cg_site->setPs(PCG, state);
    indu_cg_site->setU1(u1_cg_red);
    indu_cg_site->Charge(state);

    perm_cg_site->setQs(QCG, state);
    perm_cg_site->setPs(PCG, state);
    perm_cg_site->setU1(u1_cg_red);
    perm_cg_site->Charge(state);

    // Deallocate previously allocated sites
    if (_indu_cg_site != NULL) delete _indu_cg_site;
    if (_perm_cg_site != NULL) delete _perm_cg_site;
    _indu_cg_site = indu_cg_site;
    _perm_cg_site = perm_cg_site;
    return;
}

}}
<commit_msg>polarfrag.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.
 *
 */
/// For an earlier history see ctp repo commit 77795ea591b29e664153f9404c8655ba28dc14e9

#include <votca/xtp/polarfrag.h>
#include <votca/xtp/dmaspace.h>

namespace votca {
namespace xtp {

PolarFrag::~PolarFrag()  {
    clear(); /* Polar sites cleaned by PolarSeg */
    if (_indu_cg_site != NULL) delete _indu_cg_site;
    if (_perm_cg_site != NULL) delete _perm_cg_site;
}

const votca::tools::vec &PolarFrag::CalcPosCenterOfGeom() {
    _pos = votca::tools::vec(0,0,0);
    for (unsigned int i = 0; i < this->size(); ++i) {
        _pos += (*this)[i]->getPos();
    }
    if (this->size() > 0) _pos /= double(this->size());
    return _pos;
}

const votca::tools::vec &PolarFrag::CalcPosPolarWeights() {
    // Establish total weights
    double sum_iso_p = 0.0;
    double sum_abs_q = 0.0;
    for (unsigned int i = 0; i < this->size(); ++i) {
        sum_iso_p += (*this)[i]->getIsoP();
        sum_abs_q += std::abs((*this)[i]->getQ00());
    }

    _pos = votca::tools::vec(0,0,0);
    // Any polar sites in here? If not, return (0,0,0)
    if (this->size() < 1) ;
    // Noteworthy charge and polarizability? If not, return CoG
    else if (sum_abs_q <= 1e-2 && sum_iso_p <= 1e-2) {
        _pos = this->CalcPosCenterOfGeom();
    }
    // Else: return weighted 0.5*(center-of-polarity + center-of-charge)
    else {
        for (unsigned int i = 0; i < this->size(); ++i) {
            double weight = 0.0;
            if (sum_abs_q < 1e-2) {
                assert(sum_iso_p >= 1e-2 && "<CalcPosPolarWeights> P-ERROR");
                weight = (*this)[i]->getIsoP()/sum_iso_p;
            }
            else if (sum_iso_p < 1e-2) {
                assert(sum_abs_q >= 1e-2 && "<CalcPosPolarWeights> Q-ERROR");
                weight = std::abs((*this)[i]->getQ00())/sum_abs_q;
            }
            else {
                weight = 0.5 * (
                    (*this)[i]->getIsoP()/sum_iso_p
                  + std::abs((*this)[i]->getQ00())/sum_abs_q);
            }
            _pos += (*this)[i]->getPos() * weight;
        }
    }
    return _pos;
}

void PolarFrag::GeneratePermInduCgSite(bool do_cg_polarizabilities) {
    // ATTENTION The same method appears in <PolarSeg>
    assert(!do_cg_polarizabilities && "NOT IMPLEMENTED, NOT NEEDED?");
    // Collapse multipole moments : position, rank L
    vec target_pos = _pos;
    int state = 0;
    int L = 2;
    vector<double> QCG(L*L+2*L+1, 0.0);  // permanent
    vector<double> uQCG(L*L+2*L+1, 0.0); // induced

    for (PolarFrag::iterator pit = begin();
        pit < end(); ++pit) {
        // PERMANENT MOMENTS
        // Convert real to complex moments
        vector<double> Qlm = (*pit)->getQs(0);
        DMA::ComplexSphericalMoments Xlm(Qlm);
        // Shift moments
        DMA::MomentShift mshift;
        vec shift = target_pos - (*pit)->getPos();
        DMA::RegularSphericalHarmonics Clm(-shift);
        vector<DMA::cmplx> Xlm_shifted = mshift.Shift(Xlm, Clm);
        // Convert complex to real moments & add to base
        DMA::RealSphericalMoments Qlm_shifted(Xlm_shifted);
        Qlm_shifted.AddToVector(QCG);

        // INDUCED MOMENTS
        // Convert real to complex moments
        vec u1 = (*pit)->getU1();
        vector<double> uQlm(L*L+2*L+1, 0.0);
        uQlm[1] = u1.getZ(); // NOTE order is z-x-y == 10-11c-11s
        uQlm[2] = u1.getX();
        uQlm[3] = u1.getY();
        DMA::ComplexSphericalMoments uXlm(uQlm);
        // Shift moments
        DMA::RegularSphericalHarmonics uClm(-shift);
        vector<DMA::cmplx> uXlm_shifted = mshift.Shift(uXlm, uClm);
        // Convert complex to real moments & add to base
        DMA::RealSphericalMoments uQlm_shifted(uXlm_shifted);
        uQlm_shifted.AddToVector(uQCG);
    }

    // Collapse polarizabilities
    votca::tools::matrix PCG;
    PCG.ZeroMatrix();

    // Zero induced dipole
    vec u1_cg_red = vec(0,0,0);

    // Generate new coarse-grained site from the above
    APolarSite *indu_cg_site = new APolarSite(this->getId(), "FGU");
    APolarSite *perm_cg_site = new APolarSite(this->getId(), "FGP");

    indu_cg_site->setResolution(APolarSite::coarsegrained);
    indu_cg_site->setPos(target_pos);
    indu_cg_site->setRank(L);

    perm_cg_site->setResolution(APolarSite::coarsegrained);
    perm_cg_site->setPos(target_pos);
    perm_cg_site->setRank(L);

    // ATTENTION Save INDUCED   moments as PERMANENT moments (<indu_cg_site>)
    // ATTENTION Save PERMANENT moments as PERMANENT moments (<perm_cg_site>)
    indu_cg_site->setQs(uQCG, state);
    indu_cg_site->setPs(PCG, state);
    indu_cg_site->setU1(u1_cg_red);
    indu_cg_site->Charge(state);

    perm_cg_site->setQs(QCG, state);
    perm_cg_site->setPs(PCG, state);
    perm_cg_site->setU1(u1_cg_red);
    perm_cg_site->Charge(state);

    // Deallocate previously allocated sites
    if (_indu_cg_site != NULL) delete _indu_cg_site;
    if (_perm_cg_site != NULL) delete _perm_cg_site;
    _indu_cg_site = indu_cg_site;
    _perm_cg_site = perm_cg_site;
    return;
}

}}
<|endoftext|>


<commit_before>/**
 * Copyright (c) 2016 zScale Technology GmbH <legal@zscale.io>
 * Authors:
 *   - Paul Asmuth <paul@zscale.io>
 *
 * This program is free software: you can redistribute it and/or modify it under
 * the terms of the GNU Affero General Public License ("the license") as
 * published by the Free Software Foundation, either version 3 of the License,
 * or any later version.
 *
 * In accordance with Section 7(e) of the license, the licensing of the Program
 * under the license does not imply a trademark license. Therefore any rights,
 * title and interest in our trademarks remain entirely with us.
 *
 * This program 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 license for more details.
 *
 * You can be released from the requirements of the license by purchasing a
 * commercial license. Buying such a license is mandatory as soon as you develop
 * commercial activities involving this program without disclosing the source
 * code of your own applications
 */
#include <eventql/transport/http/http_auth.h>
#include "eventql/util/http/cookies.h"

namespace eventql {

const char HTTPAuth::kSessionCookieKey[] = "__dxa_session";
const uint64_t HTTPAuth::kSessionLifetimeMicros = 365 * kMicrosPerDay;

Option<AnalyticsSession> HTTPAuth::authenticateRequest(
    const http::HTTPRequest& request,
    AnalyticsAuth* auth) {
  try {
    String cookie;

    if (request.hasHeader("Authorization")) {
      static const String hdrprefix = "Token ";
      auto hdrval = request.getHeader("Authorization");
      if (StringUtil::beginsWith(hdrval, hdrprefix)) {
        cookie = URI::urlDecode(hdrval.substr(hdrprefix.size()));
      }
    }

    if (cookie.empty()) {
      const auto& cookies = request.cookies();
      http::Cookies::getCookie(cookies, kSessionCookieKey, &cookie);
    }

    if (cookie.empty()) {
      return None<AnalyticsSession>();
    }

    return auth->decodeAuthToken(cookie);
  } catch (const StandardException& e) {
    logDebug("analyticsd", e, "authentication failed because of error");
    return None<AnalyticsSession>();
  }
}

Status HTTPAuth::authenticateRequest(
    Session* session,
    ClientAuth* client_auth,
    const http::HTTPRequest& request) {
  HashMap<String, String> auth_data;

  if (request.hasHeader("Authorization")) {
    static const String hdrprefix = "Token ";
    auto hdrval = request.getHeader("Authorization");
    if (StringUtil::beginsWith(hdrval, hdrprefix)) {
      auth_data.emplace(
          "auth_token",
          URI::urlDecode(hdrval.substr(hdrprefix.size())));
    }
  }

  return client_auth->authenticateSession(session, auth_data);
}

}
<commit_msg>http basic auth<commit_after>/**
 * Copyright (c) 2016 zScale Technology GmbH <legal@zscale.io>
 * Authors:
 *   - Paul Asmuth <paul@zscale.io>
 *
 * This program is free software: you can redistribute it and/or modify it under
 * the terms of the GNU Affero General Public License ("the license") as
 * published by the Free Software Foundation, either version 3 of the License,
 * or any later version.
 *
 * In accordance with Section 7(e) of the license, the licensing of the Program
 * under the license does not imply a trademark license. Therefore any rights,
 * title and interest in our trademarks remain entirely with us.
 *
 * This program 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 license for more details.
 *
 * You can be released from the requirements of the license by purchasing a
 * commercial license. Buying such a license is mandatory as soon as you develop
 * commercial activities involving this program without disclosing the source
 * code of your own applications
 */
#include <eventql/transport/http/http_auth.h>
#include "eventql/util/http/cookies.h"
#include "eventql/util/util/Base64.h"

namespace eventql {

const char HTTPAuth::kSessionCookieKey[] = "__dxa_session";
const uint64_t HTTPAuth::kSessionLifetimeMicros = 365 * kMicrosPerDay;

Option<AnalyticsSession> HTTPAuth::authenticateRequest(
    const http::HTTPRequest& request,
    AnalyticsAuth* auth) {
  try {
    String cookie;

    if (request.hasHeader("Authorization")) {
      static const String hdrprefix = "Token ";
      auto hdrval = request.getHeader("Authorization");
      if (StringUtil::beginsWith(hdrval, hdrprefix)) {
        cookie = URI::urlDecode(hdrval.substr(hdrprefix.size()));
      }
    }

    if (cookie.empty()) {
      const auto& cookies = request.cookies();
      http::Cookies::getCookie(cookies, kSessionCookieKey, &cookie);
    }

    if (cookie.empty()) {
      return None<AnalyticsSession>();
    }

    return auth->decodeAuthToken(cookie);
  } catch (const StandardException& e) {
    logDebug("analyticsd", e, "authentication failed because of error");
    return None<AnalyticsSession>();
  }
}

Status HTTPAuth::authenticateRequest(
    Session* session,
    ClientAuth* client_auth,
    const http::HTTPRequest& request) {
  HashMap<String, String> auth_data;

  if (request.hasHeader("Authorization")) {
    auto hdrval = request.getHeader("Authorization");

    {
      static const String hdrprefix = "Token ";
      if (StringUtil::beginsWith(hdrval, hdrprefix)) {
        auth_data.emplace(
            "auth_token",
            URI::urlDecode(hdrval.substr(hdrprefix.size())));
      }
    }

    {
      static const String hdrprefix = "Basic ";
      if (StringUtil::beginsWith(hdrval, hdrprefix)) {
        String basic_auth;
        util::Base64::decode(hdrval.substr(hdrprefix.size()), &basic_auth);
        auto sep_pos = basic_auth.find(":");
        if (sep_pos == String::npos) {
          auth_data.emplace("user", basic_auth);
        } else {
          auth_data.emplace("user", basic_auth.substr(0, sep_pos));
          auth_data.emplace("password", basic_auth.substr(sep_pos + 1));
        }
      }
    }
  }

  return client_auth->authenticateSession(session, auth_data);
}

}
<|endoftext|>


<commit_before>///
/// @file  FactorTable.cpp
/// @see   FactorTable.hpp for documentation.
///
/// Copyright (C) 2014 Kim Walisch, <kim.walisch@gmail.com>
///
/// This file is distributed under the BSD License. See the COPYING
/// file in the top level directory.
///

#include <FactorTable.hpp>
#include <pmath.hpp>

#include <limits>
#include <stdexcept>
#include <stdint.h>
#include <vector>

using namespace std;

namespace primecount {

const uint8_t FactorTable::numbers_[48] =
{
    1,  11,  13,  17,  19,  23,
   29,  31,  37,  41,  43,  47,
   53,  59,  61,  67,  71,  73,
   79,  83,  89,  97, 101, 103,
  107, 109, 113, 121, 127, 131,
  137, 139, 143, 149, 151, 157,
  163, 167, 169, 173, 179, 181,
  187, 191, 193, 197, 199, 209
};

const int8_t FactorTable::indexes_[210] =
{
  -1,  0,  0,  0,  0,  0,  0,  0,
   0,  0,  0,  1,  1,  2,  2,  2,
   2,  3,  3,  4,  4,  4,  4,  5,
   5,  5,  5,  5,  5,  6,  6,  7,
   7,  7,  7,  7,  7,  8,  8,  8,
   8,  9,  9, 10, 10, 10, 10, 11,
  11, 11, 11, 11, 11, 12, 12, 12,
  12, 12, 12, 13, 13, 14, 14, 14,
  14, 14, 14, 15, 15, 15, 15, 16,
  16, 17, 17, 17, 17, 17, 17, 18,
  18, 18, 18, 19, 19, 19, 19, 19,
  19, 20, 20, 20, 20, 20, 20, 20,
  20, 21, 21, 21, 21, 22, 22, 23,
  23, 23, 23, 24, 24, 25, 25, 25,
  25, 26, 26, 26, 26, 26, 26, 26,
  26, 27, 27, 27, 27, 27, 27, 28,
  28, 28, 28, 29, 29, 29, 29, 29,
  29, 30, 30, 31, 31, 31, 31, 32,
  32, 32, 32, 32, 32, 33, 33, 34,
  34, 34, 34, 34, 34, 35, 35, 35,
  35, 35, 35, 36, 36, 36, 36, 37,
  37, 38, 38, 38, 38, 39, 39, 39,
  39, 39, 39, 40, 40, 41, 41, 41,
  41, 41, 41, 42, 42, 42, 42, 43,
  43, 44, 44, 44, 44, 45, 45, 46,
  46, 46, 46, 46, 46, 46, 46, 46,
  46, 47
};

FactorTable::FactorTable(int64_t max) :
  max_(max)
{
  if (isqrt(max) >= numeric_limits<uint16_t>::max())
    throw runtime_error("FactorTable: sqrt(max) must be < max(uint16_t).");
  init();
}

void FactorTable::init()
{
  int64_t max_index = get_index(max_);
  factor_table_.resize(max_index + 1, 0xffff);

  for (size_t i = 1; i < factor_table_.size(); i++)
  {
    if (factor_table_[i] == 0xffff)
    {
      int64_t prime = get_number(i);
      int64_t multiple = prime * get_number(1), j = 2;

      if (prime < 0xffff)
        factor_table_[i] = (uint16_t) prime;

      for (; multiple <= max_; multiple = prime * get_number(j++))
      {
        int64_t index = get_index(multiple);

        // prime is the smallest factor
        if (factor_table_[index] == 0xffff)
          factor_table_[index] = (uint16_t) prime;
        // the least significant bit indicates whether multiple has
        // an even (0) or odd (1) number of prime factors
        else if (factor_table_[index] > 0)
          factor_table_[index] ^= 1;
      }

      // Moebius function is 0 if n has a squared prime factor
      multiple = prime * prime * get_number(0), j = 1;
      for (; multiple <= max_; multiple = prime * prime * get_number(j++))
        factor_table_[get_index(multiple)] = 0;
    }
  }
}

} // namespace
<commit_msg>Fix minimum bug<commit_after>///
/// @file  FactorTable.cpp
/// @see   FactorTable.hpp for documentation.
///
/// Copyright (C) 2014 Kim Walisch, <kim.walisch@gmail.com>
///
/// This file is distributed under the BSD License. See the COPYING
/// file in the top level directory.
///

#include <FactorTable.hpp>
#include <pmath.hpp>

#include <limits>
#include <stdexcept>
#include <stdint.h>
#include <vector>

using namespace std;

namespace primecount {

const uint8_t FactorTable::numbers_[48] =
{
    1,  11,  13,  17,  19,  23,
   29,  31,  37,  41,  43,  47,
   53,  59,  61,  67,  71,  73,
   79,  83,  89,  97, 101, 103,
  107, 109, 113, 121, 127, 131,
  137, 139, 143, 149, 151, 157,
  163, 167, 169, 173, 179, 181,
  187, 191, 193, 197, 199, 209
};

const int8_t FactorTable::indexes_[210] =
{
  -1,  0,  0,  0,  0,  0,  0,  0,
   0,  0,  0,  1,  1,  2,  2,  2,
   2,  3,  3,  4,  4,  4,  4,  5,
   5,  5,  5,  5,  5,  6,  6,  7,
   7,  7,  7,  7,  7,  8,  8,  8,
   8,  9,  9, 10, 10, 10, 10, 11,
  11, 11, 11, 11, 11, 12, 12, 12,
  12, 12, 12, 13, 13, 14, 14, 14,
  14, 14, 14, 15, 15, 15, 15, 16,
  16, 17, 17, 17, 17, 17, 17, 18,
  18, 18, 18, 19, 19, 19, 19, 19,
  19, 20, 20, 20, 20, 20, 20, 20,
  20, 21, 21, 21, 21, 22, 22, 23,
  23, 23, 23, 24, 24, 25, 25, 25,
  25, 26, 26, 26, 26, 26, 26, 26,
  26, 27, 27, 27, 27, 27, 27, 28,
  28, 28, 28, 29, 29, 29, 29, 29,
  29, 30, 30, 31, 31, 31, 31, 32,
  32, 32, 32, 32, 32, 33, 33, 34,
  34, 34, 34, 34, 34, 35, 35, 35,
  35, 35, 35, 36, 36, 36, 36, 37,
  37, 38, 38, 38, 38, 39, 39, 39,
  39, 39, 39, 40, 40, 41, 41, 41,
  41, 41, 41, 42, 42, 42, 42, 43,
  43, 44, 44, 44, 44, 45, 45, 46,
  46, 46, 46, 46, 46, 46, 46, 46,
  46, 47
};

FactorTable::FactorTable(int64_t max) :
  max_((max < 8) ? 8 : max)
{
  if (isqrt(max_) >= numeric_limits<uint16_t>::max())
    throw runtime_error("FactorTable: sqrt(max) must be < max(uint16_t).");
  init();
}

void FactorTable::init()
{
  int64_t max_index = get_index(max_);
  factor_table_.resize(max_index + 1, 0xffff);

  for (size_t i = 1; i < factor_table_.size(); i++)
  {
    if (factor_table_[i] == 0xffff)
    {
      int64_t prime = get_number(i);
      int64_t multiple = prime * get_number(1), j = 2;

      if (prime < 0xffff)
        factor_table_[i] = (uint16_t) prime;

      for (; multiple <= max_; multiple = prime * get_number(j++))
      {
        int64_t index = get_index(multiple);

        // prime is the smallest factor
        if (factor_table_[index] == 0xffff)
          factor_table_[index] = (uint16_t) prime;
        // the least significant bit indicates whether multiple has
        // an even (0) or odd (1) number of prime factors
        else if (factor_table_[index] > 0)
          factor_table_[index] ^= 1;
      }

      // Moebius function is 0 if n has a squared prime factor
      multiple = prime * prime * get_number(0), j = 1;
      for (; multiple <= max_; multiple = prime * prime * get_number(j++))
        factor_table_[get_index(multiple)] = 0;
    }
  }
}

} // namespace
<|endoftext|>


<commit_before>#include "lola/PoseService.h"
#include "boost/thread.hpp"

#include <cstring>
#include <iostream>

void PoseService::read_handler(
    boost::system::error_code const& ec,
    std::size_t bytes_transferred) {
  std::cerr << "Pose Service: Received " << bytes_transferred << std::endl;
  if (bytes_transferred != sizeof(HR_Pose)) {
    std::cerr << "Pose Service: Error: Invalid datagram size."
              << "Expected " << sizeof(HR_Pose) << std::endl;
    return;
  }
  boost::shared_ptr<HR_Pose> new_pose(new HR_Pose);
  // The copy is thread safe since nothing can be writing to the recv_buffer
  // at this point. No new async read is queued until this callback is complete.
  memcpy(&*new_pose, &recv_buffer_[0], sizeof(HR_Pose));
  // This performs an atomic update of the pointer, making it a lock-free,
  // thread-safe operation.
  pose_ = new_pose;
  std::cerr << "Pose Service: Updated current pose" << std::endl;
  queue_recv();
}

void PoseService::service_thread() {
  std::cerr << "Pose Service: Thread started" << std::endl;
  io_service_.run();
}

void PoseService::queue_recv() {
  socket_.async_receive(
      boost::asio::buffer(recv_buffer_),
      boost::bind(&PoseService::read_handler, this, _1, _2));
}

void PoseService::bind() {
  boost::system::error_code error;
  socket_.open(boost::asio::ip::udp::v4(), error);
  boost::asio::ip::udp::endpoint local(
      boost::asio::ip::address::from_string(host_),
      port_);
  socket_.bind(local);
}

void PoseService::start() {
  bind();
  queue_recv();
  // Start the thread that will run the associated I/O service.
  boost::thread(boost::bind(&PoseService::service_thread, this));
}

HR_Pose PoseService::getCurrentPose() const {
  // This does an atomic copy of the pointer (the refcount is atomically updated)
  // There can be no race condition since if the service needs to update the
  // pointer, it will do so atomically and the reader also obtains a copy of the
  // pointer atomically.
  boost::shared_ptr<HR_Pose> p = pose_;
  // Now we are safe to manipulate the object itself, since nothing else needs
  // to directly touch the instance itself and we have safely obtained a
  // reference to it.
  // We just return the object (but this involves a non-atomic copy, hence the
  // pointer dance).

  if (p) {
    return *p;
  } else {
    HR_Pose pose = {0};
    return pose;
  }
}
<commit_msg>LOLA(PoseService): If the datagram is invalid, queue another receive<commit_after>#include "lola/PoseService.h"
#include "boost/thread.hpp"

#include <cstring>
#include <iostream>

void PoseService::read_handler(
    boost::system::error_code const& ec,
    std::size_t bytes_transferred) {
  std::cerr << "Pose Service: Received " << bytes_transferred << std::endl;
  if (bytes_transferred != sizeof(HR_Pose)) {
    std::cerr << "Pose Service: Error: Invalid datagram size."
              << "Expected " << sizeof(HR_Pose) << std::endl;
    // If this one fails, we still queue another receive...
    queue_recv();
    return;
  }
  boost::shared_ptr<HR_Pose> new_pose(new HR_Pose);
  // The copy is thread safe since nothing can be writing to the recv_buffer
  // at this point. No new async read is queued until this callback is complete.
  memcpy(&*new_pose, &recv_buffer_[0], sizeof(HR_Pose));
  // This performs an atomic update of the pointer, making it a lock-free,
  // thread-safe operation.
  pose_ = new_pose;
  std::cerr << "Pose Service: Updated current pose" << std::endl;
  queue_recv();
}

void PoseService::service_thread() {
  std::cerr << "Pose Service: Thread started" << std::endl;
  io_service_.run();
}

void PoseService::queue_recv() {
  socket_.async_receive(
      boost::asio::buffer(recv_buffer_),
      boost::bind(&PoseService::read_handler, this, _1, _2));
}

void PoseService::bind() {
  boost::system::error_code error;
  socket_.open(boost::asio::ip::udp::v4(), error);
  boost::asio::ip::udp::endpoint local(
      boost::asio::ip::address::from_string(host_),
      port_);
  socket_.bind(local);
}

void PoseService::start() {
  bind();
  queue_recv();
  // Start the thread that will run the associated I/O service.
  boost::thread(boost::bind(&PoseService::service_thread, this));
}

HR_Pose PoseService::getCurrentPose() const {
  // This does an atomic copy of the pointer (the refcount is atomically updated)
  // There can be no race condition since if the service needs to update the
  // pointer, it will do so atomically and the reader also obtains a copy of the
  // pointer atomically.
  boost::shared_ptr<HR_Pose> p = pose_;
  // Now we are safe to manipulate the object itself, since nothing else needs
  // to directly touch the instance itself and we have safely obtained a
  // reference to it.
  // We just return the object (but this involves a non-atomic copy, hence the
  // pointer dance).

  if (p) {
    return *p;
  } else {
    HR_Pose pose = {0};
    return pose;
  }
}
<|endoftext|>


<commit_before>
#ifndef __LIBPYTHON_HPP__
#define __LIBPYTHON_HPP__

#include <string>
#include <cstdint>

#ifndef LIBPYTHON_CPP
#define LIBPYTHON_EXTERN extern
#else
#define LIBPYTHON_EXTERN
#endif

#define _PYTHON_API_VERSION 1013
#define _PYTHON3_ABI_VERSION 3

// bitness detection
#if INTPTR_MAX == INT64_MAX
#define LIBPYTHON_64_BIT 1
#elif INTPTR_MAX == INT32_MAX
#define LIBPYTHON_32_BIT 1
#else
#error Unknown pointer size or missing size macros!
#endif

#if _WIN32 || _WIN64
#if LIBPYTHON_64_BIT
typedef __int64 Py_ssize_t;
#else
typedef int Py_ssize_t;
#endif
#else
typedef long Py_ssize_t;
#endif

typedef struct _object PyObject;

#define METH_VARARGS  0x0001
#define METH_KEYWORDS 0x0002

#define __PyObject_HEAD_EXTRA
#define __PyObject_EXTRA_INIT

#define _PyObject_HEAD  \
__PyObject_HEAD_EXTRA   \
  Py_ssize_t ob_refcnt; \
struct __typeobject *ob_type;

#define _PyObject_VAR_HEAD               \
_PyObject_HEAD                           \
  Py_ssize_t ob_size;

typedef struct __typeobject {
_PyObject_VAR_HEAD
  const char *tp_name;
  Py_ssize_t tp_basicsize, tp_itemsize;
} _PyTypeObject;

typedef struct __object {
_PyObject_HEAD
} _PyObject;

typedef struct {
_PyObject_VAR_HEAD
} _PyVarObject;

typedef _PyObject *(*_PyCFunction)(PyObject *, PyObject *);

struct _PyMethodDef {
  const char	*ml_name;
  _PyCFunction  ml_meth;
  int		 ml_flags;
  const char	*ml_doc;
};
typedef struct _PyMethodDef _PyMethodDef;

#define _PyObject_HEAD3 _PyObject ob_base;

#define _PyObject_HEAD_INIT(type) \
{ __PyObject_EXTRA_INIT           \
  1, type },

#define _PyModuleDef_HEAD_INIT { \
_PyObject_HEAD_INIT(NULL) \
  NULL, \
  0, \
  NULL, \
}

typedef int (*_inquiry)(PyObject *);
typedef int (*_visitproc)(PyObject *, void *);
typedef int (*_traverseproc)(PyObject *, _visitproc, void *);
typedef void (*_freefunc)(void *);

typedef struct _PyModuleDef_Base {
  _PyObject_HEAD3
  _PyObject* (*m_init)(void);
  Py_ssize_t m_index;
  _PyObject* m_copy;
} _PyModuleDef_Base;

typedef struct _PyModuleDef{
  _PyModuleDef_Base m_base;
  const char* m_name;
  const char* m_doc;
  Py_ssize_t m_size;
  _PyMethodDef *m_methods;
  _inquiry m_reload;
  _traverseproc m_traverse;
  _inquiry m_clear;
  _freefunc m_free;
} _PyModuleDef;

LIBPYTHON_EXTERN _PyTypeObject* _PyFunction_Type;
LIBPYTHON_EXTERN _PyTypeObject* _PyModule_Type;

LIBPYTHON_EXTERN PyObject* _Py_None;
LIBPYTHON_EXTERN PyObject* _Py_Unicode;
LIBPYTHON_EXTERN PyObject* _Py_String;
LIBPYTHON_EXTERN PyObject* _Py_Int;
LIBPYTHON_EXTERN PyObject* _Py_Long;
LIBPYTHON_EXTERN PyObject* _Py_Bool;
LIBPYTHON_EXTERN PyObject* _Py_True;
LIBPYTHON_EXTERN PyObject* _Py_False;
LIBPYTHON_EXTERN PyObject* _Py_Dict;
LIBPYTHON_EXTERN PyObject* _Py_Float;
LIBPYTHON_EXTERN PyObject* _Py_List;
LIBPYTHON_EXTERN PyObject* _Py_Tuple;
LIBPYTHON_EXTERN PyObject* _Py_Complex;

#define _Py_TYPE(ob) (((PyObject*)(ob))->ob_type)

#define _PyUnicode_Check(o) (_Py_TYPE(o) == _Py_TYPE(_Py_Unicode))
#define _PyString_Check(o) (_Py_TYPE(o) == _Py_TYPE(_Py_String))
#define _PyInt_Check(o)  (_Py_TYPE(o) == _Py_TYPE(_Py_Int))
#define _PyLong_Check(o)  (_Py_TYPE(o) == _Py_TYPE(_Py_Long))
#define _PyBool_Check(o) ((o == _Py_False) | (o == _Py_True))
#define _PyDict_Check(o) (_Py_TYPE(o) == _Py_TYPE(_Py_Dict))
#define _PyFloat_Check(o) (_Py_TYPE(o) == _Py_TYPE(_Py_Float))
#define _PyFunction_Check(op) ((_PyTypeObject*)(_Py_TYPE(op)) == _PyFunction_Type)
#define _PyTuple_Check(o) (_Py_TYPE(o) == _Py_TYPE(_Py_Tuple))
#define _PyList_Check(o) (_Py_TYPE(o) == _Py_TYPE(_Py_List))
#define _PyComplex_Check(o) (_Py_TYPE(o) == _Py_TYPE(_Py_Complex))

LIBPYTHON_EXTERN void (*_Py_Initialize)();

LIBPYTHON_EXTERN PyObject* (*_Py_InitModule4)(const char *name, _PyMethodDef *methods,
           const char *doc, PyObject *self,
           int apiver);

LIBPYTHON_EXTERN PyObject* (*_PyImport_ImportModule)(const char *name);

LIBPYTHON_EXTERN PyObject* (*_PyModule_Create2)(_PyModuleDef *def, int);
LIBPYTHON_EXTERN int (*_PyImport_AppendInittab)(const char *name, PyObject* (*initfunc)());

LIBPYTHON_EXTERN PyObject* (*_Py_BuildValue)(const char *format, ...);

LIBPYTHON_EXTERN void (*_Py_IncRef)(PyObject *);
LIBPYTHON_EXTERN void (*_Py_DecRef)(PyObject *);

LIBPYTHON_EXTERN PyObject* (*__PyObject_Str)(PyObject *);

LIBPYTHON_EXTERN int (*_PyObject_IsInstance)(PyObject *object, PyObject *typeorclass);

LIBPYTHON_EXTERN PyObject* (*_PyObject_Dir)(PyObject *);

LIBPYTHON_EXTERN PyObject* (*_PyObject_Call)(PyObject *callable_object,
           PyObject *args, PyObject *kw);
LIBPYTHON_EXTERN PyObject* (*_PyObject_CallFunctionObjArgs)(PyObject *callable,
           ...);

LIBPYTHON_EXTERN PyObject* (*_PyObject_GetAttrString)(PyObject*, const char *);
LIBPYTHON_EXTERN int (*_PyObject_HasAttrString)(PyObject*, const char *);

LIBPYTHON_EXTERN Py_ssize_t (*_PyTuple_Size)(PyObject *);
LIBPYTHON_EXTERN PyObject* (*_PyTuple_GetItem)(PyObject *, Py_ssize_t);
LIBPYTHON_EXTERN PyObject* (*_PyTuple_New)(Py_ssize_t size);
LIBPYTHON_EXTERN int (*_PyTuple_SetItem)(PyObject *, Py_ssize_t, PyObject *);
LIBPYTHON_EXTERN PyObject* (*_PyTuple_GetSlice)(PyObject *, Py_ssize_t, Py_ssize_t);

LIBPYTHON_EXTERN PyObject* (*_PyList_New)(Py_ssize_t size);
LIBPYTHON_EXTERN Py_ssize_t (*_PyList_Size)(PyObject *);
LIBPYTHON_EXTERN PyObject* (*_PyList_GetItem)(PyObject *, Py_ssize_t);
LIBPYTHON_EXTERN int (*_PyList_SetItem)(PyObject *, Py_ssize_t, PyObject *);

LIBPYTHON_EXTERN int (*_PyString_AsStringAndSize)(
    register PyObject *obj,	/* string or Unicode object */
    register char **s,		/* pointer to buffer variable */
    register Py_ssize_t *len	/* pointer to length variable or NULL
  (only possible for 0-terminated
  strings) */
);

LIBPYTHON_EXTERN PyObject* (*_PyString_FromString)(const char *);
LIBPYTHON_EXTERN PyObject* (*_PyString_FromStringAndSize)(const char *, Py_ssize_t);

LIBPYTHON_EXTERN PyObject* (*_PyUnicode_EncodeLocale)(PyObject *unicode, const char *errors);
LIBPYTHON_EXTERN int (*_PyBytes_AsStringAndSize)(
    PyObject *obj,      /* string or Unicode object */
    char **s,           /* pointer to buffer variable */
    Py_ssize_t *len     /* pointer to length variable or NULL
  (only possible for 0-terminated
  strings) */
);
LIBPYTHON_EXTERN PyObject* (*_PyBytes_FromStringAndSize)(const char *, Py_ssize_t);
LIBPYTHON_EXTERN PyObject* (*_PyUnicode_FromString)(const char *u);

LIBPYTHON_EXTERN void (*_PyErr_Fetch)(PyObject **, PyObject **, PyObject **);
LIBPYTHON_EXTERN PyObject* (*_PyErr_Occurred)(void);
LIBPYTHON_EXTERN void (*_PyErr_NormalizeException)(PyObject**, PyObject**, PyObject**);

LIBPYTHON_EXTERN int (*_PyCallable_Check)(PyObject *);

LIBPYTHON_EXTERN PyObject* (*_PyModule_GetDict)(PyObject *);
LIBPYTHON_EXTERN PyObject* (*_PyImport_AddModule)(const char *);

LIBPYTHON_EXTERN PyObject* (*_PyRun_StringFlags)(const char *, int, PyObject*, PyObject*, void*);
LIBPYTHON_EXTERN int (*_PyRun_SimpleFileExFlags)(FILE *, const char *, int, void *);

LIBPYTHON_EXTERN PyObject* (*_PyObject_GetIter)(PyObject *);
LIBPYTHON_EXTERN PyObject* (*_PyIter_Next)(PyObject *);

LIBPYTHON_EXTERN void (*_PySys_SetArgv)(int, char **);
LIBPYTHON_EXTERN void (*_PySys_SetArgv_v3)(int, wchar_t **);

typedef void (*_PyCapsule_Destructor)(PyObject *);
LIBPYTHON_EXTERN PyObject* (*_PyCapsule_New)(void *pointer, const char *name, _PyCapsule_Destructor destructor);
LIBPYTHON_EXTERN void* (*_PyCapsule_GetPointer)(PyObject *capsule, const char *name);

LIBPYTHON_EXTERN PyObject* (*_PyDict_New)(void);
LIBPYTHON_EXTERN int (*_PyDict_SetItem)(PyObject *mp, PyObject *key, PyObject *item);
LIBPYTHON_EXTERN int (*_PyDict_SetItemString)(PyObject *dp, const char *key, PyObject *item);
LIBPYTHON_EXTERN int (*__PyDict_Next)(
    PyObject *mp, Py_ssize_t *pos, PyObject **key, PyObject **value);

LIBPYTHON_EXTERN PyObject* (*_PyInt_FromLong)(long);
LIBPYTHON_EXTERN long (*_PyInt_AsLong)(PyObject *);
LIBPYTHON_EXTERN PyObject* (*_PyLong_FromLong)(long);
LIBPYTHON_EXTERN long (*_PyLong_AsLong)(PyObject *);

LIBPYTHON_EXTERN PyObject* (*_PyBool_FromLong)(long);

LIBPYTHON_EXTERN PyObject* (*_PyFloat_FromDouble)(double);
LIBPYTHON_EXTERN double (*_PyFloat_AsDouble)(PyObject *);

LIBPYTHON_EXTERN PyObject* (*_PyComplex_FromDoubles)(double real, double imag);
LIBPYTHON_EXTERN double (*_PyComplex_RealAsDouble)(PyObject *op);
LIBPYTHON_EXTERN double (*_PyComplex_ImagAsDouble)(PyObject *op);

enum _NPY_TYPES {
  _NPY_BOOL=0,
  _NPY_BYTE, _NPY_UBYTE,
  _NPY_SHORT, _NPY_USHORT,
  _NPY_INT, _NPY_UINT,
  _NPY_LONG, _NPY_ULONG,
  _NPY_LONGLONG, _NPY_ULONGLONG,
  _NPY_FLOAT, _NPY_DOUBLE, _NPY_LONGDOUBLE,
  _NPY_CFLOAT, _NPY_CDOUBLE, _NPY_CLONGDOUBLE,
  _NPY_OBJECT=17,
  _NPY_STRING, _NPY_UNICODE,
  _NPY_VOID,
  _NPY_DATETIME, _NPY_TIMEDELTA, _NPY_HALF,
  _NPY_NTYPES,
  _NPY_NOTYPE,
  _NPY_CHAR,
  _NPY_USERDEF=256,
  _NPY_NTYPES_ABI_COMPATIBLE=21
};

// int is still 32 bits on all relevant 64-bit platforms
#define _NPY_INT32 _NPY_INT

class SharedLibrary {

public:
  bool load(const std::string& libPath, bool python3, std::string* pError);
  bool unload(std::string* pError);
  virtual ~SharedLibrary() {}

private:
  virtual bool loadSymbols(bool python3, std::string* pError) = 0;

protected:
  SharedLibrary() : pLib_(NULL) {}
private:
  SharedLibrary(const SharedLibrary&);

protected:
  void* pLib_;
};

class LibPython : public SharedLibrary {
private:
  LibPython() : SharedLibrary() {}
  friend SharedLibrary& libPython();
  virtual bool loadSymbols(bool python3, std::string* pError);
};

inline SharedLibrary& libPython() {
  static LibPython instance;
  return instance;
}

class LibNumPy : public SharedLibrary {
private:
  LibNumPy() : SharedLibrary() {}
  friend SharedLibrary& libNumPy();
  virtual bool loadSymbols(bool python3, std::string* pError);
};

inline SharedLibrary& libNumPy() {
  static LibNumPy instance;
  return instance;
}

#endif

<commit_msg>no 64-bitness detection (required C++11)<commit_after>
#ifndef __LIBPYTHON_HPP__
#define __LIBPYTHON_HPP__

#include <string>

#ifndef LIBPYTHON_CPP
#define LIBPYTHON_EXTERN extern
#else
#define LIBPYTHON_EXTERN
#endif

#define _PYTHON_API_VERSION 1013
#define _PYTHON3_ABI_VERSION 3

#if _WIN32 || _WIN64
#if _WIN64
typedef __int64 Py_ssize_t;
#else
typedef int Py_ssize_t;
#endif
#else
typedef long Py_ssize_t;
#endif

typedef struct _object PyObject;

#define METH_VARARGS  0x0001
#define METH_KEYWORDS 0x0002

#define __PyObject_HEAD_EXTRA
#define __PyObject_EXTRA_INIT

#define _PyObject_HEAD  \
__PyObject_HEAD_EXTRA   \
  Py_ssize_t ob_refcnt; \
struct __typeobject *ob_type;

#define _PyObject_VAR_HEAD               \
_PyObject_HEAD                           \
  Py_ssize_t ob_size;

typedef struct __typeobject {
_PyObject_VAR_HEAD
  const char *tp_name;
  Py_ssize_t tp_basicsize, tp_itemsize;
} _PyTypeObject;

typedef struct __object {
_PyObject_HEAD
} _PyObject;

typedef struct {
_PyObject_VAR_HEAD
} _PyVarObject;

typedef _PyObject *(*_PyCFunction)(PyObject *, PyObject *);

struct _PyMethodDef {
  const char	*ml_name;
  _PyCFunction  ml_meth;
  int		 ml_flags;
  const char	*ml_doc;
};
typedef struct _PyMethodDef _PyMethodDef;

#define _PyObject_HEAD3 _PyObject ob_base;

#define _PyObject_HEAD_INIT(type) \
{ __PyObject_EXTRA_INIT           \
  1, type },

#define _PyModuleDef_HEAD_INIT { \
_PyObject_HEAD_INIT(NULL) \
  NULL, \
  0, \
  NULL, \
}

typedef int (*_inquiry)(PyObject *);
typedef int (*_visitproc)(PyObject *, void *);
typedef int (*_traverseproc)(PyObject *, _visitproc, void *);
typedef void (*_freefunc)(void *);

typedef struct _PyModuleDef_Base {
  _PyObject_HEAD3
  _PyObject* (*m_init)(void);
  Py_ssize_t m_index;
  _PyObject* m_copy;
} _PyModuleDef_Base;

typedef struct _PyModuleDef{
  _PyModuleDef_Base m_base;
  const char* m_name;
  const char* m_doc;
  Py_ssize_t m_size;
  _PyMethodDef *m_methods;
  _inquiry m_reload;
  _traverseproc m_traverse;
  _inquiry m_clear;
  _freefunc m_free;
} _PyModuleDef;

LIBPYTHON_EXTERN _PyTypeObject* _PyFunction_Type;
LIBPYTHON_EXTERN _PyTypeObject* _PyModule_Type;

LIBPYTHON_EXTERN PyObject* _Py_None;
LIBPYTHON_EXTERN PyObject* _Py_Unicode;
LIBPYTHON_EXTERN PyObject* _Py_String;
LIBPYTHON_EXTERN PyObject* _Py_Int;
LIBPYTHON_EXTERN PyObject* _Py_Long;
LIBPYTHON_EXTERN PyObject* _Py_Bool;
LIBPYTHON_EXTERN PyObject* _Py_True;
LIBPYTHON_EXTERN PyObject* _Py_False;
LIBPYTHON_EXTERN PyObject* _Py_Dict;
LIBPYTHON_EXTERN PyObject* _Py_Float;
LIBPYTHON_EXTERN PyObject* _Py_List;
LIBPYTHON_EXTERN PyObject* _Py_Tuple;
LIBPYTHON_EXTERN PyObject* _Py_Complex;

#define _Py_TYPE(ob) (((PyObject*)(ob))->ob_type)

#define _PyUnicode_Check(o) (_Py_TYPE(o) == _Py_TYPE(_Py_Unicode))
#define _PyString_Check(o) (_Py_TYPE(o) == _Py_TYPE(_Py_String))
#define _PyInt_Check(o)  (_Py_TYPE(o) == _Py_TYPE(_Py_Int))
#define _PyLong_Check(o)  (_Py_TYPE(o) == _Py_TYPE(_Py_Long))
#define _PyBool_Check(o) ((o == _Py_False) | (o == _Py_True))
#define _PyDict_Check(o) (_Py_TYPE(o) == _Py_TYPE(_Py_Dict))
#define _PyFloat_Check(o) (_Py_TYPE(o) == _Py_TYPE(_Py_Float))
#define _PyFunction_Check(op) ((_PyTypeObject*)(_Py_TYPE(op)) == _PyFunction_Type)
#define _PyTuple_Check(o) (_Py_TYPE(o) == _Py_TYPE(_Py_Tuple))
#define _PyList_Check(o) (_Py_TYPE(o) == _Py_TYPE(_Py_List))
#define _PyComplex_Check(o) (_Py_TYPE(o) == _Py_TYPE(_Py_Complex))

LIBPYTHON_EXTERN void (*_Py_Initialize)();

LIBPYTHON_EXTERN PyObject* (*_Py_InitModule4)(const char *name, _PyMethodDef *methods,
           const char *doc, PyObject *self,
           int apiver);

LIBPYTHON_EXTERN PyObject* (*_PyImport_ImportModule)(const char *name);

LIBPYTHON_EXTERN PyObject* (*_PyModule_Create2)(_PyModuleDef *def, int);
LIBPYTHON_EXTERN int (*_PyImport_AppendInittab)(const char *name, PyObject* (*initfunc)());

LIBPYTHON_EXTERN PyObject* (*_Py_BuildValue)(const char *format, ...);

LIBPYTHON_EXTERN void (*_Py_IncRef)(PyObject *);
LIBPYTHON_EXTERN void (*_Py_DecRef)(PyObject *);

LIBPYTHON_EXTERN PyObject* (*__PyObject_Str)(PyObject *);

LIBPYTHON_EXTERN int (*_PyObject_IsInstance)(PyObject *object, PyObject *typeorclass);

LIBPYTHON_EXTERN PyObject* (*_PyObject_Dir)(PyObject *);

LIBPYTHON_EXTERN PyObject* (*_PyObject_Call)(PyObject *callable_object,
           PyObject *args, PyObject *kw);
LIBPYTHON_EXTERN PyObject* (*_PyObject_CallFunctionObjArgs)(PyObject *callable,
           ...);

LIBPYTHON_EXTERN PyObject* (*_PyObject_GetAttrString)(PyObject*, const char *);
LIBPYTHON_EXTERN int (*_PyObject_HasAttrString)(PyObject*, const char *);

LIBPYTHON_EXTERN Py_ssize_t (*_PyTuple_Size)(PyObject *);
LIBPYTHON_EXTERN PyObject* (*_PyTuple_GetItem)(PyObject *, Py_ssize_t);
LIBPYTHON_EXTERN PyObject* (*_PyTuple_New)(Py_ssize_t size);
LIBPYTHON_EXTERN int (*_PyTuple_SetItem)(PyObject *, Py_ssize_t, PyObject *);
LIBPYTHON_EXTERN PyObject* (*_PyTuple_GetSlice)(PyObject *, Py_ssize_t, Py_ssize_t);

LIBPYTHON_EXTERN PyObject* (*_PyList_New)(Py_ssize_t size);
LIBPYTHON_EXTERN Py_ssize_t (*_PyList_Size)(PyObject *);
LIBPYTHON_EXTERN PyObject* (*_PyList_GetItem)(PyObject *, Py_ssize_t);
LIBPYTHON_EXTERN int (*_PyList_SetItem)(PyObject *, Py_ssize_t, PyObject *);

LIBPYTHON_EXTERN int (*_PyString_AsStringAndSize)(
    register PyObject *obj,	/* string or Unicode object */
    register char **s,		/* pointer to buffer variable */
    register Py_ssize_t *len	/* pointer to length variable or NULL
  (only possible for 0-terminated
  strings) */
);

LIBPYTHON_EXTERN PyObject* (*_PyString_FromString)(const char *);
LIBPYTHON_EXTERN PyObject* (*_PyString_FromStringAndSize)(const char *, Py_ssize_t);

LIBPYTHON_EXTERN PyObject* (*_PyUnicode_EncodeLocale)(PyObject *unicode, const char *errors);
LIBPYTHON_EXTERN int (*_PyBytes_AsStringAndSize)(
    PyObject *obj,      /* string or Unicode object */
    char **s,           /* pointer to buffer variable */
    Py_ssize_t *len     /* pointer to length variable or NULL
  (only possible for 0-terminated
  strings) */
);
LIBPYTHON_EXTERN PyObject* (*_PyBytes_FromStringAndSize)(const char *, Py_ssize_t);
LIBPYTHON_EXTERN PyObject* (*_PyUnicode_FromString)(const char *u);

LIBPYTHON_EXTERN void (*_PyErr_Fetch)(PyObject **, PyObject **, PyObject **);
LIBPYTHON_EXTERN PyObject* (*_PyErr_Occurred)(void);
LIBPYTHON_EXTERN void (*_PyErr_NormalizeException)(PyObject**, PyObject**, PyObject**);

LIBPYTHON_EXTERN int (*_PyCallable_Check)(PyObject *);

LIBPYTHON_EXTERN PyObject* (*_PyModule_GetDict)(PyObject *);
LIBPYTHON_EXTERN PyObject* (*_PyImport_AddModule)(const char *);

LIBPYTHON_EXTERN PyObject* (*_PyRun_StringFlags)(const char *, int, PyObject*, PyObject*, void*);
LIBPYTHON_EXTERN int (*_PyRun_SimpleFileExFlags)(FILE *, const char *, int, void *);

LIBPYTHON_EXTERN PyObject* (*_PyObject_GetIter)(PyObject *);
LIBPYTHON_EXTERN PyObject* (*_PyIter_Next)(PyObject *);

LIBPYTHON_EXTERN void (*_PySys_SetArgv)(int, char **);
LIBPYTHON_EXTERN void (*_PySys_SetArgv_v3)(int, wchar_t **);

typedef void (*_PyCapsule_Destructor)(PyObject *);
LIBPYTHON_EXTERN PyObject* (*_PyCapsule_New)(void *pointer, const char *name, _PyCapsule_Destructor destructor);
LIBPYTHON_EXTERN void* (*_PyCapsule_GetPointer)(PyObject *capsule, const char *name);

LIBPYTHON_EXTERN PyObject* (*_PyDict_New)(void);
LIBPYTHON_EXTERN int (*_PyDict_SetItem)(PyObject *mp, PyObject *key, PyObject *item);
LIBPYTHON_EXTERN int (*_PyDict_SetItemString)(PyObject *dp, const char *key, PyObject *item);
LIBPYTHON_EXTERN int (*__PyDict_Next)(
    PyObject *mp, Py_ssize_t *pos, PyObject **key, PyObject **value);

LIBPYTHON_EXTERN PyObject* (*_PyInt_FromLong)(long);
LIBPYTHON_EXTERN long (*_PyInt_AsLong)(PyObject *);
LIBPYTHON_EXTERN PyObject* (*_PyLong_FromLong)(long);
LIBPYTHON_EXTERN long (*_PyLong_AsLong)(PyObject *);

LIBPYTHON_EXTERN PyObject* (*_PyBool_FromLong)(long);

LIBPYTHON_EXTERN PyObject* (*_PyFloat_FromDouble)(double);
LIBPYTHON_EXTERN double (*_PyFloat_AsDouble)(PyObject *);

LIBPYTHON_EXTERN PyObject* (*_PyComplex_FromDoubles)(double real, double imag);
LIBPYTHON_EXTERN double (*_PyComplex_RealAsDouble)(PyObject *op);
LIBPYTHON_EXTERN double (*_PyComplex_ImagAsDouble)(PyObject *op);

enum _NPY_TYPES {
  _NPY_BOOL=0,
  _NPY_BYTE, _NPY_UBYTE,
  _NPY_SHORT, _NPY_USHORT,
  _NPY_INT, _NPY_UINT,
  _NPY_LONG, _NPY_ULONG,
  _NPY_LONGLONG, _NPY_ULONGLONG,
  _NPY_FLOAT, _NPY_DOUBLE, _NPY_LONGDOUBLE,
  _NPY_CFLOAT, _NPY_CDOUBLE, _NPY_CLONGDOUBLE,
  _NPY_OBJECT=17,
  _NPY_STRING, _NPY_UNICODE,
  _NPY_VOID,
  _NPY_DATETIME, _NPY_TIMEDELTA, _NPY_HALF,
  _NPY_NTYPES,
  _NPY_NOTYPE,
  _NPY_CHAR,
  _NPY_USERDEF=256,
  _NPY_NTYPES_ABI_COMPATIBLE=21
};

// int is still 32 bits on all relevant 64-bit platforms
#define _NPY_INT32 _NPY_INT

class SharedLibrary {

public:
  bool load(const std::string& libPath, bool python3, std::string* pError);
  bool unload(std::string* pError);
  virtual ~SharedLibrary() {}

private:
  virtual bool loadSymbols(bool python3, std::string* pError) = 0;

protected:
  SharedLibrary() : pLib_(NULL) {}
private:
  SharedLibrary(const SharedLibrary&);

protected:
  void* pLib_;
};

class LibPython : public SharedLibrary {
private:
  LibPython() : SharedLibrary() {}
  friend SharedLibrary& libPython();
  virtual bool loadSymbols(bool python3, std::string* pError);
};

inline SharedLibrary& libPython() {
  static LibPython instance;
  return instance;
}

class LibNumPy : public SharedLibrary {
private:
  LibNumPy() : SharedLibrary() {}
  friend SharedLibrary& libNumPy();
  virtual bool loadSymbols(bool python3, std::string* pError);
};

inline SharedLibrary& libNumPy() {
  static LibNumPy instance;
  return instance;
}

#endif

<|endoftext|>


<commit_before>/* mbed Microcontroller Library
 * Copyright (c) 2006-2013 ARM Limited
 *
 * 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.
 */

#ifdef YOTTA_CFG_MBED_OS
    #include "mbed-drivers/mbed.h"
#else
    #include "mbed.h"
#endif
#include "nRF5xn.h"
#include "ble/blecommon.h"
#include "nrf_soc.h"

#include "btle/btle.h"
#include "btle/custom/custom_helper.h"
#include "nrf_delay.h"

extern "C" {
#include "softdevice_handler.h"
}

#include "nRF5xPalGattClient.h"

/**
 * The singleton which represents the nRF51822 transport for the BLE.
 */
static nRF5xn& getDeviceInstance() {
    static nRF5xn deviceInstance;
    return deviceInstance;
}

/**
 * BLE-API requires an implementation of the following function in order to
 * obtain its transport handle.
 */
BLEInstanceBase *
createBLEInstance(void)
{
    return &nRF5xn::Instance(BLE::DEFAULT_INSTANCE);
}

nRF5xn& nRF5xn::Instance(BLE::InstanceID_t instanceId)
{
    return getDeviceInstance();
}

nRF5xn::nRF5xn(void) :
    initialized(false),
    instanceID(BLE::DEFAULT_INSTANCE),
    gapInstance(),
    gattServerInstance(NULL),
    gattClient(&(ble::pal::vendor::nordic::nRF5xGattClient::get_client()))
{
}

nRF5xn::~nRF5xn(void)
{
}

const char *nRF5xn::getVersion(void)
{
    if (!initialized) {
        return "INITIALIZATION_INCOMPLETE";
    }

    static char versionString[32];
    static bool versionFetched = false;

    if (!versionFetched) {
        ble_version_t version;
        if ((sd_ble_version_get(&version) == NRF_SUCCESS) && (version.company_id == 0x0059)) {
            switch (version.version_number) {
                case 0x07:
                case 0x08:
                    snprintf(versionString, sizeof(versionString), "Nordic BLE4.1 ver:%u fw:%04x", version.version_number, version.subversion_number);
                    break;
                default:
                    snprintf(versionString, sizeof(versionString), "Nordic (spec unknown) ver:%u fw:%04x", version.version_number, version.subversion_number);
                    break;
            }
            versionFetched = true;
        } else {
            strncpy(versionString, "unknown", sizeof(versionString));
        }
    }

    return versionString;
}

/**************************************************************************/
/*!
    @brief  Initialize the BLE stack.

    @returns    ble_error_t

    @retval     BLE_ERROR_NONE if everything executed properly and
                BLE_ERROR_ALREADY_INITIALIZED if the stack has already
                been initialized (possibly through a call to nRF5xn::init()).
                BLE_ERROR_INTERNAL_STACK_FAILURE is returned if initialization
                of the internal stack (SoftDevice) failed.

*/
/**************************************************************************/
ble_error_t nRF5xn::init(BLE::InstanceID_t instanceID, FunctionPointerWithContext<BLE::InitializationCompleteCallbackContext *> callback)
{
    if (initialized) {
        BLE::InitializationCompleteCallbackContext context = {
            BLE::Instance(instanceID),
            BLE_ERROR_ALREADY_INITIALIZED
        };
        callback.call(&context);
        return BLE_ERROR_ALREADY_INITIALIZED;
    }

    this->instanceID = instanceID;

    /* ToDo: Clear memory contents, reset the SD, etc. */
    if (btle_init() != ERROR_NONE) {
        return BLE_ERROR_INTERNAL_STACK_FAILURE;
    }

    initialized = true;
    BLE::InitializationCompleteCallbackContext context = {
        BLE::Instance(instanceID),
        BLE_ERROR_NONE
    };
    callback.call(&context);
    return BLE_ERROR_NONE;
}

/**************************************************************************/
/*!
    @brief  Purge the BLE stack of GATT and GAP state.

    @returns    ble_error_t

    @retval     BLE_ERROR_NONE
                Everything executed properly

    @note  When using S110, GattClient::shutdown() will not be called
           since Gatt client features are not supported.
*/
/**************************************************************************/
ble_error_t nRF5xn::shutdown(void)
{
    if (!initialized) {
        return BLE_ERROR_INITIALIZATION_INCOMPLETE;
    }

    /*
     * Shutdown the SoftDevice first. This is because we need to disable all
     * interrupts. Otherwise if we clear the BLE API and glue code first there
     * will be many NULL references and no config information which could lead
     * to errors if the shutdown process is interrupted.
     */
    if (softdevice_handler_sd_disable() != NRF_SUCCESS) {
        return BLE_STACK_BUSY;
    }

    /* Shutdown the BLE API and nRF51 glue code */
    ble_error_t error;

    if (gattServerInstance != NULL) {
        error = gattServerInstance->reset();
        if (error != BLE_ERROR_NONE) {
            return error;
        }
    }

    /* S110 does not support BLE client features, nothing to reset. */
#if !defined(TARGET_MCU_NRF51_16K_S110) && !defined(TARGET_MCU_NRF51_32K_S110)
    error = getGattClient().reset();
    if (error != BLE_ERROR_NONE) {
        return error;
    }
#endif

    /* Gap instance is always present */
    error = gapInstance.reset();
    if (error != BLE_ERROR_NONE) {
        return error;
    }

    custom_reset_128bits_uuid_table();

    initialized = false;
    return BLE_ERROR_NONE;
}

SecurityManager& nRF5xn::getSecurityManager()
{
    const nRF5xn* self = this;
    return const_cast<SecurityManager&>(self->getSecurityManager());
}

const SecurityManager& nRF5xn::getSecurityManager() const
{
    static ble::pal::MemorySecurityDb m_db;
    ble::pal::vendor::nordic::nRF5xSecurityManager &m_pal =
        ble::pal::vendor::nordic::nRF5xSecurityManager::get_security_manager();
    static struct : ble::pal::SigningEventMonitor {
        virtual void set_signing_event_handler(EventHandler *signing_event_handler) { }
    } dummy_signing_event_monitor;

    static ble::generic::GenericSecurityManager m_instance(
        m_pal,
        m_db,
        const_cast<nRF5xGap&>(getGap()),
        dummy_signing_event_monitor
    );

    return m_instance;
}

void
nRF5xn::waitForEvent(void)
{
    processEvents();
    sd_app_evt_wait();
}

void nRF5xn::processEvents() {
    if (isEventsSignaled) {
        isEventsSignaled = false;
        intern_softdevice_events_execute();
    }
}
<commit_msg>Nordic BLE: Protect event signaled flag.<commit_after>/* mbed Microcontroller Library
 * Copyright (c) 2006-2013 ARM Limited
 *
 * 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.
 */

#ifdef YOTTA_CFG_MBED_OS
    #include "mbed-drivers/mbed.h"
#else
    #include "mbed.h"
#endif
#include "nRF5xn.h"
#include "ble/blecommon.h"
#include "nrf_soc.h"

#include "btle/btle.h"
#include "btle/custom/custom_helper.h"
#include "nrf_delay.h"

extern "C" {
#include "softdevice_handler.h"
}

#include "nRF5xPalGattClient.h"

/**
 * The singleton which represents the nRF51822 transport for the BLE.
 */
static nRF5xn& getDeviceInstance() {
    static nRF5xn deviceInstance;
    return deviceInstance;
}

/**
 * BLE-API requires an implementation of the following function in order to
 * obtain its transport handle.
 */
BLEInstanceBase *
createBLEInstance(void)
{
    return &nRF5xn::Instance(BLE::DEFAULT_INSTANCE);
}

nRF5xn& nRF5xn::Instance(BLE::InstanceID_t instanceId)
{
    return getDeviceInstance();
}

nRF5xn::nRF5xn(void) :
    initialized(false),
    instanceID(BLE::DEFAULT_INSTANCE),
    gapInstance(),
    gattServerInstance(NULL),
    gattClient(&(ble::pal::vendor::nordic::nRF5xGattClient::get_client()))
{
}

nRF5xn::~nRF5xn(void)
{
}

const char *nRF5xn::getVersion(void)
{
    if (!initialized) {
        return "INITIALIZATION_INCOMPLETE";
    }

    static char versionString[32];
    static bool versionFetched = false;

    if (!versionFetched) {
        ble_version_t version;
        if ((sd_ble_version_get(&version) == NRF_SUCCESS) && (version.company_id == 0x0059)) {
            switch (version.version_number) {
                case 0x07:
                case 0x08:
                    snprintf(versionString, sizeof(versionString), "Nordic BLE4.1 ver:%u fw:%04x", version.version_number, version.subversion_number);
                    break;
                default:
                    snprintf(versionString, sizeof(versionString), "Nordic (spec unknown) ver:%u fw:%04x", version.version_number, version.subversion_number);
                    break;
            }
            versionFetched = true;
        } else {
            strncpy(versionString, "unknown", sizeof(versionString));
        }
    }

    return versionString;
}

/**************************************************************************/
/*!
    @brief  Initialize the BLE stack.

    @returns    ble_error_t

    @retval     BLE_ERROR_NONE if everything executed properly and
                BLE_ERROR_ALREADY_INITIALIZED if the stack has already
                been initialized (possibly through a call to nRF5xn::init()).
                BLE_ERROR_INTERNAL_STACK_FAILURE is returned if initialization
                of the internal stack (SoftDevice) failed.

*/
/**************************************************************************/
ble_error_t nRF5xn::init(BLE::InstanceID_t instanceID, FunctionPointerWithContext<BLE::InitializationCompleteCallbackContext *> callback)
{
    if (initialized) {
        BLE::InitializationCompleteCallbackContext context = {
            BLE::Instance(instanceID),
            BLE_ERROR_ALREADY_INITIALIZED
        };
        callback.call(&context);
        return BLE_ERROR_ALREADY_INITIALIZED;
    }

    this->instanceID = instanceID;

    /* ToDo: Clear memory contents, reset the SD, etc. */
    if (btle_init() != ERROR_NONE) {
        return BLE_ERROR_INTERNAL_STACK_FAILURE;
    }

    initialized = true;
    BLE::InitializationCompleteCallbackContext context = {
        BLE::Instance(instanceID),
        BLE_ERROR_NONE
    };
    callback.call(&context);
    return BLE_ERROR_NONE;
}

/**************************************************************************/
/*!
    @brief  Purge the BLE stack of GATT and GAP state.

    @returns    ble_error_t

    @retval     BLE_ERROR_NONE
                Everything executed properly

    @note  When using S110, GattClient::shutdown() will not be called
           since Gatt client features are not supported.
*/
/**************************************************************************/
ble_error_t nRF5xn::shutdown(void)
{
    if (!initialized) {
        return BLE_ERROR_INITIALIZATION_INCOMPLETE;
    }

    /*
     * Shutdown the SoftDevice first. This is because we need to disable all
     * interrupts. Otherwise if we clear the BLE API and glue code first there
     * will be many NULL references and no config information which could lead
     * to errors if the shutdown process is interrupted.
     */
    if (softdevice_handler_sd_disable() != NRF_SUCCESS) {
        return BLE_STACK_BUSY;
    }

    /* Shutdown the BLE API and nRF51 glue code */
    ble_error_t error;

    if (gattServerInstance != NULL) {
        error = gattServerInstance->reset();
        if (error != BLE_ERROR_NONE) {
            return error;
        }
    }

    /* S110 does not support BLE client features, nothing to reset. */
#if !defined(TARGET_MCU_NRF51_16K_S110) && !defined(TARGET_MCU_NRF51_32K_S110)
    error = getGattClient().reset();
    if (error != BLE_ERROR_NONE) {
        return error;
    }
#endif

    /* Gap instance is always present */
    error = gapInstance.reset();
    if (error != BLE_ERROR_NONE) {
        return error;
    }

    custom_reset_128bits_uuid_table();

    initialized = false;
    return BLE_ERROR_NONE;
}

SecurityManager& nRF5xn::getSecurityManager()
{
    const nRF5xn* self = this;
    return const_cast<SecurityManager&>(self->getSecurityManager());
}

const SecurityManager& nRF5xn::getSecurityManager() const
{
    static ble::pal::MemorySecurityDb m_db;
    ble::pal::vendor::nordic::nRF5xSecurityManager &m_pal =
        ble::pal::vendor::nordic::nRF5xSecurityManager::get_security_manager();
    static struct : ble::pal::SigningEventMonitor {
        virtual void set_signing_event_handler(EventHandler *signing_event_handler) { }
    } dummy_signing_event_monitor;

    static ble::generic::GenericSecurityManager m_instance(
        m_pal,
        m_db,
        const_cast<nRF5xGap&>(getGap()),
        dummy_signing_event_monitor
    );

    return m_instance;
}

void
nRF5xn::waitForEvent(void)
{
    processEvents();
    sd_app_evt_wait();
}

void nRF5xn::processEvents() {
    core_util_critical_section_enter();
    if (isEventsSignaled) {
        isEventsSignaled = false;
        core_util_critical_section_exit();
        intern_softdevice_events_execute();
    } else {
        core_util_critical_section_exit();
    }
}
<|endoftext|>