text:
/*
 * Copyright (c) 2011-2019, The DART development contributors
 * All rights reserved.
 *
 * The list of contributors can be found at:
 *   https://github.com/dartsim/dart/blob/master/LICENSE
 *
 * This file is provided under the following "BSD-style" License:
 *   Redistribution and use in source and binary forms, with or
 *   without modification, are permitted provided that the following
 *   conditions are met:
 *   * Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *   * Redistributions in binary form must reproduce the above
 *     copyright notice, this list of conditions and the following
 *     disclaimer in the documentation and/or other materials provided
 *     with the distribution.
 *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
 *   CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
 *   INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
 *   MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 *   DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
 *   CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
 *   USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
 *   AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 *   LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 *   ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 *   POSSIBILITY OF SUCH DAMAGE.
 */

#ifndef DART_MATH_GEOMETRY_HPP_
#define DART_MATH_GEOMETRY_HPP_

#include <Eigen/Dense>

#include "dart/common/Deprecated.hpp"
#include "dart/common/Memory.hpp"
#include "dart/math/Constants.hpp"
#include "dart/math/MathTypes.hpp"

namespace dart {
namespace math {

/// \brief
Eigen::Matrix3d makeSkewSymmetric(const Eigen::Vector3d& _v);

/// \brief
Eigen::Vector3d fromSkewSymmetric(const Eigen::Matrix3d& _m);

//------------------------------------------------------------------------------
/// \brief
Eigen::Quaterniond expToQuat(const Eigen::Vector3d& _v);

/// \brief
Eigen::Vector3d quatToExp(const Eigen::Quaterniond& _q);

/// \brief
Eigen::Vector3d rotatePoint(const Eigen::Quaterniond& _q,
                            const Eigen::Vector3d& _pt);

/// \brief
Eigen::Vector3d rotatePoint(const Eigen::Quaterniond& _q,
                            double _x, double _y, double _z);

/// \brief
Eigen::Matrix3d quatDeriv(const Eigen::Quaterniond& _q, int _el);

/// \brief
Eigen::Matrix3d quatSecondDeriv(const Eigen::Quaterniond& _q,
                                int _el1, int _el2);

//------------------------------------------------------------------------------
/// \brief Given Euler XYX angles, return a 3x3 rotation matrix, which is
/// equivalent to RotX(angle(0)) * RotY(angle(1)) * RotX(angle(2)).
Eigen::Matrix3d eulerXYXToMatrix(const Eigen::Vector3d& _angle);

/// \brief Given EulerXYZ angles, return a 3x3 rotation matrix, which is
/// equivalent to RotX(angle(0)) * RotY(angle(1)) * RotZ(angle(2)).
Eigen::Matrix3d eulerXYZToMatrix(const Eigen::Vector3d& _angle);

/// \brief Given EulerXZX angles, return a 3x3 rotation matrix, which is
/// equivalent to RotX(angle(0)) * RotZ(angle(1)) * RotX(angle(2)).
Eigen::Matrix3d eulerXZXToMatrix(const Eigen::Vector3d& _angle);

/// \brief Given EulerXZY angles, return a 3x3 rotation matrix, which is
/// equivalent to RotX(angle(0)) * RotZ(angle(1)) * RotY(angle(2)).
Eigen::Matrix3d eulerXZYToMatrix(const Eigen::Vector3d& _angle);

/// \brief Given EulerYXY angles, return a 3x3 rotation matrix, which is
/// equivalent to RotY(angle(0)) * RotX(angle(1)) * RotY(angle(2)).
Eigen::Matrix3d eulerYXYToMatrix(const Eigen::Vector3d& _angle);

/// \brief Given EulerYXZ angles, return a 3x3 rotation matrix, which is
/// equivalent to RotY(angle(0)) * RotX(angle(1)) * RotZ(angle(2)).
Eigen::Matrix3d eulerYXZToMatrix(const Eigen::Vector3d& _angle);

/// \brief Given EulerYZX angles, return a 3x3 rotation matrix, which is
/// equivalent to RotY(angle(0)) * RotZ(angle(1)) * RotX(angle(2)).
Eigen::Matrix3d eulerYZXToMatrix(const Eigen::Vector3d& _angle);

/// \brief Given EulerYZY angles, return a 3x3 rotation matrix, which is
/// equivalent to RotY(angle(0)) * RotZ(angle(1)) * RotY(angle(2)).
Eigen::Matrix3d eulerYZYToMatrix(const Eigen::Vector3d& _angle);

/// \brief Given EulerZXY angles, return a 3x3 rotation matrix, which is
/// equivalent to RotZ(angle(0)) * RotX(angle(1)) * RotY(angle(2)).
Eigen::Matrix3d eulerZXYToMatrix(const Eigen::Vector3d& _angle);

/// \brief Given EulerZYX angles, return a 3x3 rotation matrix, which is
/// equivalent to RotZ(angle(0)) * RotY(angle(1)) * RotX(angle(2)).
/// singularity : angle[1] = -+ 0.5*PI
Eigen::Matrix3d eulerZYXToMatrix(const Eigen::Vector3d& _angle);

/// \brief Given EulerZXZ angles, return a 3x3 rotation matrix, which is
/// equivalent to RotZ(angle(0)) * RotX(angle(1)) * RotZ(angle(2)).
Eigen::Matrix3d eulerZXZToMatrix(const Eigen::Vector3d& _angle);

/// \brief Given EulerZYZ angles, return a 3x3 rotation matrix, which is
/// equivalent to RotZ(angle(0)) * RotY(angle(1)) * RotZ(angle(2)).
/// singularity : angle[1] = 0, PI
Eigen::Matrix3d eulerZYZToMatrix(const Eigen::Vector3d& _angle);

//------------------------------------------------------------------------------
/// \brief get the Euler XYX angle from R
Eigen::Vector3d matrixToEulerXYX(const Eigen::Matrix3d& _R);

/// \brief get the Euler XYZ angle from R
Eigen::Vector3d matrixToEulerXYZ(const Eigen::Matrix3d& _R);

///// \brief get the Euler XZX angle from R
// Eigen::Vector3d matrixToEulerXZX(const Eigen::Matrix3d& R);

/// \brief get the Euler XZY angle from R
Eigen::Vector3d matrixToEulerXZY(const Eigen::Matrix3d& _R);

///// \brief get the Euler YXY angle from R
// Eigen::Vector3d matrixToEulerYXY(const Eigen::Matrix3d& R);

/// \brief get the Euler YXZ angle from R
Eigen::Vector3d matrixToEulerYXZ(const Eigen::Matrix3d& _R);

/// \brief get the Euler YZX angle from R
Eigen::Vector3d matrixToEulerYZX(const Eigen::Matrix3d& _R);

///// \brief get the Euler YZY angle from R
// Eigen::Vector3d matrixToEulerYZY(const Eigen::Matrix3d& R);

/// \brief get the Euler ZXY angle from R
Eigen::Vector3d matrixToEulerZXY(const Eigen::Matrix3d& _R);

/// \brief get the Euler ZYX angle from R
Eigen::Vector3d matrixToEulerZYX(const Eigen::Matrix3d& _R);

///// \brief get the Euler ZXZ angle from R
// Eigen::Vector3d matrixToEulerZXZ(const Eigen::Matrix3d& R);

///// \brief get the Euler ZYZ angle from R
// Eigen::Vector3d matrixToEulerZYZ(const Eigen::Matrix3d& R);

//------------------------------------------------------------------------------
/// \brief Exponential mapping
Eigen::Isometry3d expMap(const Eigen::Vector6d& _S);

/// \brief fast version of Exp(se3(s, 0))
/// \todo This expAngular() can be replaced by Eigen::AngleAxis() but we need
/// to verify that they have exactly same functionality.
/// See: https://github.com/dartsim/dart/issues/88
Eigen::Isometry3d expAngular(const Eigen::Vector3d& _s);

/// \brief Computes the Rotation matrix from a given expmap vector.
Eigen::Matrix3d expMapRot(const Eigen::Vector3d& _expmap);

/// \brief Computes the Jacobian of the expmap
Eigen::Matrix3d expMapJac(const Eigen::Vector3d& _expmap);

/// \brief Computes the time derivative of the expmap Jacobian.
Eigen::Matrix3d expMapJacDot(const Eigen::Vector3d& _expmap,
                             const Eigen::Vector3d& _qdot);

/// \brief computes the derivative of the Jacobian of the expmap wrt to _qi
/// indexed dof; _qi \in {0,1,2}
Eigen::Matrix3d expMapJacDeriv(const Eigen::Vector3d& _expmap, int _qi);

/// \brief Log mapping
/// \note When @f$|Log(R)| = @pi@f$, Exp(LogR(R) = Exp(-Log(R)).
/// The implementation returns only the positive one.
Eigen::Vector3d logMap(const Eigen::Matrix3d& _R);

/// \brief Log mapping
Eigen::Vector6d logMap(const Eigen::Isometry3d& _T);

//------------------------------------------------------------------------------
/// \brief Rectify the rotation part so as that it satifies the orthogonality
/// condition.
///
/// It is one step of @f$R_{i_1}=1/2(R_i + R_i^{-T})@f$.
/// Hence by calling this function iterativley, you can make the rotation part
/// closer to SO(3).
// SE3 Normalize(const SE3& T);

/// \brief reparameterize such as ||s'|| < M_PI and Exp(s) == Epx(s')
// Axis Reparameterize(const Axis& s);

//------------------------------------------------------------------------------
/// \brief adjoint mapping
/// \note @f$Ad_TV = ( Rw@,, ~p @times Rw + Rv)@f$,
/// where @f$T=(R,p)@in SE(3), @quad V=(w,v)@in se(3) @f$.
Eigen::Vector6d AdT(const Eigen::Isometry3d& _T, const Eigen::Vector6d& _V);

/// \brief Get linear transformation matrix of Adjoint mapping
Eigen::Matrix6d getAdTMatrix(const Eigen::Isometry3d& T);

/// Adjoint mapping for dynamic size Jacobian
template<typename Derived>
typename Derived::PlainObject AdTJac(const Eigen::Isometry3d& _T,
                                     const Eigen::MatrixBase<Derived>& _J)
{
  // Check the number of rows is 6 at compile time
  EIGEN_STATIC_ASSERT(Derived::RowsAtCompileTime == 6,
                      THIS_METHOD_IS_ONLY_FOR_MATRICES_OF_A_SPECIFIC_SIZE);

  typename Derived::PlainObject ret(_J.rows(), _J.cols());

  // Compute AdT column by column
  for (int i = 0; i < _J.cols(); ++i)
    ret.col(i) = AdT(_T, _J.col(i));

  return ret;
}

/// Adjoint mapping for fixed size Jacobian
template<typename Derived>
typename Derived::PlainObject AdTJacFixed(const Eigen::Isometry3d& _T,
                                          const Eigen::MatrixBase<Derived>& _J)
{
  // Check if _J is fixed size Jacobian
  EIGEN_STATIC_ASSERT_FIXED_SIZE(Derived);

  // Check the number of rows is 6 at compile time
  EIGEN_STATIC_ASSERT(Derived::RowsAtCompileTime == 6,
                      THIS_METHOD_IS_ONLY_FOR_MATRICES_OF_A_SPECIFIC_SIZE);

  typename Derived::PlainObject ret(_J.rows(), _J.cols());

  // Compute AdT
  ret.template topRows<3>().noalias() = _T.linear() * _J.template topRows<3>();
  ret.template bottomRows<3>().noalias()
      = -ret.template topRows<3>().colwise().cross(_T.translation())
        + _T.linear() * _J.template bottomRows<3>();

  return ret;
}

/// \brief Fast version of Ad([R 0; 0 1], V)
Eigen::Vector6d AdR(const Eigen::Isometry3d& _T, const Eigen::Vector6d& _V);

/// \brief fast version of Ad(T, se3(w, 0))
Eigen::Vector6d AdTAngular(const Eigen::Isometry3d& _T,
                           const Eigen::Vector3d& _w);

/// \brief fast version of Ad(T, se3(0, v))
Eigen::Vector6d AdTLinear(const Eigen::Isometry3d& _T,
                          const Eigen::Vector3d& _v);

///// \brief fast version of Ad([I p; 0 1], V)
// se3 AdP(const Vec3& p, const se3& s);

/// \brief Change coordinate Frame of a Jacobian
template<typename Derived>
typename Derived::PlainObject AdRJac(const Eigen::Isometry3d& _T,
                                     const Eigen::MatrixBase<Derived>& _J)
{
  EIGEN_STATIC_ASSERT(Derived::RowsAtCompileTime == 6,
                      THIS_METHOD_IS_ONLY_FOR_MATRICES_OF_A_SPECIFIC_SIZE);

  typename Derived::PlainObject ret(_J.rows(), _J.cols());

  ret.template topRows<3>().noalias() =
      _T.linear() * _J.template topRows<3>();

  ret.template bottomRows<3>().noalias() =
      _T.linear() * _J.template bottomRows<3>();

  return ret;
}

template<typename Derived>
typename Derived::PlainObject AdRInvJac(const Eigen::Isometry3d& _T,
                                        const Eigen::MatrixBase<Derived>& _J)
{
  EIGEN_STATIC_ASSERT(Derived::RowsAtCompileTime == 6,
                      THIS_METHOD_IS_ONLY_FOR_MATRICES_OF_A_SPECIFIC_SIZE);

  typename Derived::PlainObject ret(_J.rows(), _J.cols());

  ret.template topRows<3>().noalias() =
      _T.linear().transpose() * _J.template topRows<3>();

  ret.template bottomRows<3>().noalias() =
      _T.linear().transpose() * _J.template bottomRows<3>();

  return ret;
}

template<typename Derived>
typename Derived::PlainObject adJac(const Eigen::Vector6d& _V,
                                    const Eigen::MatrixBase<Derived>& _J)
{
  EIGEN_STATIC_ASSERT(Derived::RowsAtCompileTime == 6,
                      THIS_METHOD_IS_ONLY_FOR_MATRICES_OF_A_SPECIFIC_SIZE);

  typename Derived::PlainObject ret(_J.rows(), _J.cols());

  ret.template topRows<3>().noalias() =
      - _J.template topRows<3>().colwise().cross(_V.head<3>());

  ret.template bottomRows<3>().noalias() =
      - _J.template bottomRows<3>().colwise().cross(_V.head<3>())
      - _J.template topRows<3>().colwise().cross(_V.tail<3>());

  return ret;
}

/// \brief fast version of Ad(Inv(T), V)
Eigen::Vector6d AdInvT(const Eigen::Isometry3d& _T, const Eigen::Vector6d& _V);

/// Adjoint mapping for dynamic size Jacobian
template<typename Derived>
typename Derived::PlainObject AdInvTJac(const Eigen::Isometry3d& _T,
                                        const Eigen::MatrixBase<Derived>& _J)
{
  // Check the number of rows is 6 at compile time
  EIGEN_STATIC_ASSERT(Derived::RowsAtCompileTime == 6,
                      THIS_METHOD_IS_ONLY_FOR_MATRICES_OF_A_SPECIFIC_SIZE);

  typename Derived::PlainObject ret(_J.rows(), _J.cols());

  // Compute AdInvT column by column
  for (int i = 0; i < _J.cols(); ++i)
    ret.col(i) = AdInvT(_T, _J.col(i));

  return ret;
}

/// Adjoint mapping for fixed size Jacobian
template<typename Derived>
typename Derived::PlainObject AdInvTJacFixed(
    const Eigen::Isometry3d& _T,
    const Eigen::MatrixBase<Derived>& _J)
{
  // Check if _J is fixed size Jacobian
  EIGEN_STATIC_ASSERT_FIXED_SIZE(Derived);

  // Check the number of rows is 6 at compile time
  EIGEN_STATIC_ASSERT(Derived::RowsAtCompileTime == 6,
                      THIS_METHOD_IS_ONLY_FOR_MATRICES_OF_A_SPECIFIC_SIZE);

  typename Derived::PlainObject ret(_J.rows(), _J.cols());

  // Compute AdInvT
  ret.template topRows<3>().noalias()
      = _T.linear().transpose() * _J.template topRows<3>();
  ret.template bottomRows<3>().noalias()
      = _T.linear().transpose()
        * (_J.template bottomRows<3>()
           + _J.template topRows<3>().colwise().cross(_T.translation()));

  return ret;
}

///// \brief fast version of Ad(Inv(T), se3(Eigen_Vec3(0), v))
// Eigen::Vector3d AdInvTLinear(const Eigen::Isometry3d& T,
//                             const Eigen::Vector3d& v);

///// \brief fast version of Ad(Inv(T), se3(w, Eigen_Vec3(0)))
// Axis AdInvTAngular(const SE3& T, const Axis& w);

///// \brief Fast version of Ad(Inv([R 0; 0 1]), V)
// se3 AdInvR(const SE3& T, const se3& V);

/// \brief Fast version of Ad(Inv([R 0; 0 1]), se3(0, v))
Eigen::Vector6d AdInvRLinear(const Eigen::Isometry3d& _T,
                             const Eigen::Vector3d& _v);

/// \brief dual adjoint mapping
/// \note @f$Ad^{@,*}_TF = ( R^T (m - p@times f)@,,~ R^T f)@f$,
/// where @f$T=(R,p)@in SE(3), F=(m,f)@in se(3)^*@f$.
Eigen::Vector6d dAdT(const Eigen::Isometry3d& _T, const Eigen::Vector6d& _F);

///// \brief fast version of Ad(Inv(T), dse3(Eigen_Vec3(0), F))
// dse3 dAdTLinear(const SE3& T, const Vec3& F);

/// \brief fast version of dAd(Inv(T), F)
Eigen::Vector6d dAdInvT(const Eigen::Isometry3d& _T, const Eigen::Vector6d& _F);

/// \brief fast version of dAd(Inv([R 0; 0 1]), F)
Eigen::Vector6d dAdInvR(const Eigen::Isometry3d& _T, const Eigen::Vector6d& _F);

///// \brief fast version of dAd(Inv(SE3(p)), dse3(Eigen_Vec3(0), F))
// dse3 dAdInvPLinear(const Vec3& p, const Vec3& F);

/// \brief adjoint mapping
/// \note @f$ad_X Y = ( w_X @times w_Y@,,~w_X @times v_Y - w_Y @times v_X),@f$,
/// where @f$X=(w_X,v_X)@in se(3), @quad Y=(w_Y,v_Y)@in se(3) @f$.
Eigen::Vector6d ad(const Eigen::Vector6d& _X, const Eigen::Vector6d& _Y);

/// \brief fast version of ad(se3(Eigen_Vec3(0), v), S)
// Vec3 ad_Vec3_se3(const Vec3& v, const se3& S);

/// \brief fast version of ad(se3(w, 0), se3(v, 0)) -> check
// Axis ad_Axis_Axis(const Axis& w, const Axis& v);

/// \brief dual adjoint mapping
/// \note @f$ad^{@,*}_V F = (m @times w + f @times v@,,~ f @times w),@f$
/// , where @f$F=(m,f)@in se^{@,*}(3), @quad V=(w,v)@in se(3) @f$.
Eigen::Vector6d dad(const Eigen::Vector6d& _s, const Eigen::Vector6d& _t);

/// \brief
Inertia transformInertia(const Eigen::Isometry3d& _T, const Inertia& _AI);

/// Use the Parallel Axis Theorem to compute the moment of inertia of a body
/// whose center of mass has been shifted from the origin
Eigen::Matrix3d parallelAxisTheorem(const Eigen::Matrix3d& _original,
                                    const Eigen::Vector3d& _comShift,
                                    double _mass);

enum AxisType
{
  AXIS_X = 0,
  AXIS_Y = 1,
  AXIS_Z = 2
};

/// Compute a rotation matrix from a vector. One axis of the rotated coordinates
/// by the rotation matrix matches the input axis where the axis is specified
/// by axisType.
Eigen::Matrix3d computeRotation(const Eigen::Vector3d& axis,
                                AxisType axisType = AxisType::AXIS_X);

/// Compute a transform from a vector and a position. The rotation of the result
/// transform is computed by computeRotationMatrix(), and the translation is
/// just the input translation.
Eigen::Isometry3d computeTransform(const Eigen::Vector3d& axis,
                                   const Eigen::Vector3d& translation,
                                   AxisType axisType = AxisType::AXIS_X);

/// Generate frame given origin and z-axis
DART_DEPRECATED(6.0)
Eigen::Isometry3d getFrameOriginAxisZ(const Eigen::Vector3d& _origin,
                                      const Eigen::Vector3d& _axisZ);

/// \brief Check if determinant of _R is equat to 1 and all the elements are not
/// NaN values.
bool verifyRotation(const Eigen::Matrix3d& _R);

/// \brief Check if determinant of the rotational part of _T is equat to 1 and
/// all the elements are not NaN values.
bool verifyTransform(const Eigen::Isometry3d& _T);

/// Compute the angle (in the range of -pi to +pi) which ignores any full
/// rotations
inline double wrapToPi(double angle)
{
  constexpr auto pi = constantsd::pi();

  return std::fmod(angle+pi, 2*pi) - pi;
}

template <typename MatrixType, typename ReturnType>
void extractNullSpace(const Eigen::JacobiSVD<MatrixType>& _SVD, ReturnType& _NS)
{
#if EIGEN_VERSION_AT_LEAST(3,2,2)
  const int rank = _SVD.rank();
#else
  int rank = 0;
  if(_SVD.nonzeroSingularValues() > 0)
  {
    double thresh = std::max(_SVD.singularValues().coeff(0)*1e-10,
                             std::numeric_limits<double>::min());
    int i = _SVD.nonzeroSingularValues()-1;
    while( i >= 0 && _SVD.singularValues().coeff(i) < thresh )
      --i;
    rank = i+1;
  }
#endif

  const int cols = _SVD.matrixV().cols();
  const int rows = _SVD.matrixV().rows();
  _NS = _SVD.matrixV().block(0, rank, rows, cols-rank);
}

template <typename MatrixType, typename ReturnType>
void computeNullSpace(const MatrixType& _M, ReturnType& _NS)
{
  Eigen::JacobiSVD<MatrixType> svd(_M, Eigen::ComputeFullV);
  extractNullSpace(svd, _NS);
}

typedef std::vector<Eigen::Vector3d> SupportGeometry;

typedef common::aligned_vector<Eigen::Vector2d> SupportPolygon;

/// Project the support geometry points onto a plane with the given axes
/// and then compute their convex hull, which will take the form of a polgyon.
/// _axis1 and _axis2 must both have unit length for this function to work
/// correctly.
SupportPolygon computeSupportPolgyon(
    const SupportGeometry& _geometry,
    const Eigen::Vector3d& _axis1 = Eigen::Vector3d::UnitX(),
    const Eigen::Vector3d& _axis2 = Eigen::Vector3d::UnitY());

/// Same as computeSupportPolgyon, except you can pass in a std::vector<std::size_t>
/// which will have the same size as the returned SupportPolygon, and each entry
/// will contain the original index of each point in the SupportPolygon
SupportPolygon computeSupportPolgyon(
    std::vector<std::size_t>& _originalIndices,
    const SupportGeometry& _geometry,
    const Eigen::Vector3d& _axis1 = Eigen::Vector3d::UnitX(),
    const Eigen::Vector3d& _axis2 = Eigen::Vector3d::UnitY());

/// Computes the convex hull of a set of 2D points
SupportPolygon computeConvexHull(const SupportPolygon& _points);

/// Computes the convex hull of a set of 2D points and fills in _originalIndices
/// with the original index of each entry in the returned SupportPolygon
SupportPolygon computeConvexHull(std::vector<std::size_t>& _originalIndices,
                                 const SupportPolygon& _points);

/// Compute the centroid of a polygon, assuming the polygon is a convex hull
Eigen::Vector2d computeCentroidOfHull(const SupportPolygon& _convexHull);

/// Intersection_t is returned by the computeIntersection() function to indicate
/// whether there was a valid intersection between the two line segments
enum IntersectionResult {

  INTERSECTING = 0,   ///< An intersection was found
  PARALLEL,           ///< The line segments are parallel
  BEYOND_ENDPOINTS    ///< There is no intersection because the end points do not expand far enough

};

/// Compute the intersection between a line segment that goes from a1 -> a2 and
/// a line segment that goes from b1 -> b2.
IntersectionResult computeIntersection(
    Eigen::Vector2d& _intersectionPoint,
    const Eigen::Vector2d& a1,
    const Eigen::Vector2d& a2,
    const Eigen::Vector2d& b1,
    const Eigen::Vector2d& b2);

/// Compute a 2D cross product
double cross(const Eigen::Vector2d& _v1, const Eigen::Vector2d& _v2);

/// Returns true if the point _p is inside the support polygon
bool isInsideSupportPolygon(const Eigen::Vector2d& _p,
                            const SupportPolygon& _support,
                            bool _includeEdge = true);

/// Returns the point which is closest to _p that also lays on the line segment
/// that goes from _s1 -> _s2
Eigen::Vector2d computeClosestPointOnLineSegment(const Eigen::Vector2d& _p,
                                                 const Eigen::Vector2d& _s1,
                                                 const Eigen::Vector2d& _s2);

/// Returns the point which is closest to _p that also lays on the edge of the
/// support polygon
Eigen::Vector2d computeClosestPointOnSupportPolygon(
    const Eigen::Vector2d& _p,
    const SupportPolygon& _support);

/// Same as closestPointOnSupportPolygon, but also fills in _index1 and _index2
/// with the indices of the line segment
Eigen::Vector2d computeClosestPointOnSupportPolygon(
    std::size_t& _index1,
    std::size_t& _index2,
    const Eigen::Vector2d& _p,
    const SupportPolygon& _support);

// Represents a bounding box with minimum and maximum coordinates.
class BoundingBox {
    public:
        EIGEN_MAKE_ALIGNED_OPERATOR_NEW

        BoundingBox();
        BoundingBox(const Eigen::Vector3d& min, const Eigen::Vector3d& max);

        inline const Eigen::Vector3d& getMin() const {  return mMin; }
        inline const Eigen::Vector3d& getMax() const { return mMax; }

        inline void setMin(const Eigen::Vector3d& min) { mMin = min; }
        inline void setMax(const Eigen::Vector3d& max) { mMax = max; }

        // \brief Centroid of the bounding box (i.e average of min and max)
        inline Eigen::Vector3d computeCenter() const { return (mMax + mMin) * 0.5; }
        // \brief Coordinates of the maximum corner with respect to the centroid.
        inline Eigen::Vector3d computeHalfExtents() const { return (mMax - mMin) * 0.5; }
        // \brief Length of each of the sides of the bounding box.
        inline Eigen::Vector3d computeFullExtents() const { return (mMax - mMin); }

    protected:
        // \brief minimum coordinates of the bounding box
        Eigen::Vector3d mMin;
        // \brief maximum coordinates of the bounding box
        Eigen::Vector3d mMax;
};

}  // namespace math
}  // namespace dart

#endif  // DART_MATH_GEOMETRY_HPP_

max_stars_repo_name: vslavik/dart

max_issues_repo_name: vslavik/dart

max_forks_repo_name: vslavik/dart


text:
// @copyright 2017 - 2018 Shaun Ostoic
// Distributed under the MIT License.
// (See accompanying file LICENSE.md or copy at https://opensource.org/licenses/MIT)

#pragma once

#include <distant/agents/interface.hpp>

#include <boost/winapi/wait.hpp>
#include <distant/utility/meta/array.hpp>
#include <distant/utility/meta/tuple.hpp>

#include <chrono>
#include <tuple>

namespace distant::synch
{
	namespace detail
	{
		template <class... Ts>
		struct uniform_tuple
		{
			constexpr uniform_tuple(Ts&&... ts) noexcept
				: tuple_(std::forward<Ts>(ts)...)
			{}

		private:
			std::tuple<Ts&&...> tuple_;
		};
	}

	// Windows wait codes
	enum class state : long long int
	{
		abandoned = boost::winapi::WAIT_ABANDONED_, // Wait abandoned
		signaled = boost::winapi::WAIT_OBJECT_0_,	// Object returned from wait
		timeout = boost::winapi::WAIT_TIMEOUT_,		// Wait timed out
		failed = boost::winapi::WAIT_FAILED_,		// Bad call
		//io_completion = boost::winapi::WAIT_IO_COMPLETION_, // APC ended call
	};

	namespace detail
	{
		template <class Agent, class Time>
		state wait_single_impl(Agent&& object, const Time time)
		{
			using namespace std::chrono;
			using agents::native_handle_of;

			const auto handle = native_handle_of(std::forward<Agent>(object));

			if (handle == nullptr)
				throw std::invalid_argument("[synch::wait] Invalid handle");

#pragma warning(push)
#pragma warning(disable:4244)
			return static_cast<state>(boost::winapi::WaitForSingleObject(
				handle,
				time
			));
#pragma warning(pop)
		}

		template <class Time, class... Agents>
		state wait_multiple_impl(const std::tuple<Agents...>& objects, bool wait_for_all, const Time time)
		{
			using namespace std::chrono;
			namespace meta = utility::meta;

			const auto result = meta::tuple_transform(objects, [](auto&& object)
			{
				return native_handle_of(std::forward<decltype(object)>(object));
			});

			auto handles = meta::to_array(result);

#pragma warning(push)
#pragma warning(disable:4244)
			return static_cast<state>(boost::winapi::WaitForMultipleObjects(
				handles.size(),
				handles.data(),
				false,
				static_cast<boost::winapi::DWORD_>(time)
			));
#pragma warning(pop)
		}
	}

	template <class Agent, class Rep, class Period>
	state wait(Agent&& object, const std::chrono::duration<Rep, Period> time)
	{
		using namespace std::chrono;
		return detail::wait_single_impl(std::forward<Agent>(object), duration_cast<milliseconds>(time).count());
	}

	template <class Agent>
	state wait(Agent&& object)
	{
		return detail::wait_single_impl(std::forward<Agent>(object), boost::winapi::infinite);
	}

	template <class Rep, class Period, class... Agents>
	state wait(const std::tuple<Agents...>& tuple, bool wait_for_all, const std::chrono::duration<Rep, Period> time)
	{
		return wait_all(tuple, time);
	}

	template <class... Agents>
	state wait_all(const std::tuple<Agents...>& tuple)
	{
		using namespace std::chrono;
		return detail::wait_multiple_impl(tuple, true, boost::winapi::infinite);
	}

	template <class Rep, class Period, class... Agents>
	state wait_all(const std::tuple<Agents...>& tuple, const std::chrono::duration<Rep, Period> time)
	{
		using namespace std::chrono;
		return detail::wait_multiple_impl(tuple, true, duration_cast<milliseconds>(time).count());
	}

	template <class... Agents>
	state wait_any(const std::tuple<Agents...>& tuple)
	{
		using namespace std::chrono;
		return detail::wait_multiple_impl(tuple, false, boost::winapi::infinite);
	}

	template <class Rep, class Period, class... Agents>
	state wait_any(const std::tuple<Agents...>& tuple, const std::chrono::duration<Rep, Period> time)
	{
		using namespace std::chrono;
		return detail::wait_multiple_impl(tuple, false, duration_cast<milliseconds>(time).count());
	}

} // end namespace distant

namespace distant
{
	using synch::wait;
	using synch::wait_all;
	using synch::wait_any;
}

ext: hpp

max_stars_repo_name: Ostoic/distant

max_issues_repo_name: Ostoic/distant

max_forks_repo_name: Ostoic/distant


text:
#include <iostream>
#include <stdexcept>
#include <string>
#include <vector>
#include <fstream>

#include <spine/HTTP.h>

#include <boost/program_options.hpp>
#include <boost/filesystem.hpp>
#include <boost/asio.hpp>
#include <boost/foreach.hpp>
#include <boost/array.hpp>
#include <boost/bind.hpp>
#include <boost/date_time/posix_time/posix_time.hpp>
#include <boost/algorithm/string.hpp>

#include <macgyver/ThreadPool.h>

typedef Fmi::ThreadPool::ThreadPool<> pool;

using namespace std;

namespace fs = boost::filesystem;

namespace ip = boost::asio::ip;

namespace bp = boost::posix_time;

namespace po = boost::program_options;

pair<string, string> parseStatus(const boost::iterator_range<char*>& message)
{
  std::vector<boost::iterator_range<std::string::const_iterator> > headerTokens;
  vector<string> statusLineTokens(3);

  auto header_boundary = boost::algorithm::find_first(message, "\r\n\r\n");

  auto header_range = boost::make_iterator_range(message.begin(), header_boundary.begin());
  boost::algorithm::split(
      headerTokens, header_range, boost::is_any_of("\r\n"), boost::token_compress_on);

  if (headerTokens.empty())
  {
    return pair<string, string>();
  }

  auto startIt = headerTokens.begin();
  boost::algorithm::split(statusLineTokens, *startIt, boost::is_space(), boost::token_compress_on);

  string messageBody = string(header_boundary.end(), message.end());

  boost::algorithm::replace_all(messageBody, "\n", " ");
  boost::algorithm::replace_all(messageBody, "\r", " ");

  string code;
  try
  {
    code = statusLineTokens.at(1);
  }
  catch (...)
  {
    return pair<string, string>();
  }

  return make_pair(code, messageBody);
}

struct Request
{
  Request(string host, unsigned short port, string URI) : hostName(host), port(port), URI(URI) {}
  friend ostream& operator<<(ostream& stream, const Request& theReq)
  {
    stream << theReq.hostName << ":" << theReq.port << theReq.URI;
    return stream;
  }

  string hostName;

  unsigned short port;

  string URI;
};

struct Result
{
  Result(bp::ptime resTime, string URI, bp::time_duration duration, string status, string response)
      : resTime(resTime), URI(URI), duration(duration), status(status), response(response)
  {
  }

  friend ostream& operator<<(ostream& stream, const Result& theRes)
  {
    stream << theRes.resTime << "###" << theRes.URI << "###"
           << bp::to_simple_string(theRes.duration) << "###" << theRes.status << "###"
           << theRes.response;
    return stream;
  }

  bp::ptime resTime;

  string URI;

  bp::time_duration duration;

  string status;

  string response;
};

class Tester
{
 public:
  Tester(const string& requestFile,
         unsigned int threads,
         const string& hostname,
         unsigned short port)
      : itsHostName(hostname),
        itsPort(port),
        itsRequestFilePath(requestFile),
        itsThreadPool(new pool(threads)),
        itsSignals(itsIO),
        itsCurrentResultInd(0),
        itsPrintResults(false)
  {
    if (!fs::exists(itsRequestFilePath))
    {
      throw runtime_error("Request file not found");
    }

    readReqFile();

    itsResults.reserve(itsRequests.size());

    // Fill the pool prior to starting
    BOOST_FOREACH (const auto& req, itsRequests)
    {
      itsThreadPool->schedule(boost::bind(&Tester::performRequest, this, req));
    }

    itsSignals.add(SIGQUIT);

    itsSignals.async_wait(boost::bind(&Tester::handleSignal, this, _1, _2));

    itsTimer.reset(new boost::asio::deadline_timer(itsIO));

    itsThread.reset(
        new boost::thread(boost::bind(&boost::asio::io_service::run, boost::ref(itsIO))));
  }

  ~Tester()
  {
    if (itsThreadPool != NULL)
    {
      delete itsThreadPool;
      itsThreadPool = NULL;
    }
  }

  void run()
  {
    itsTimer->expires_from_now(bp::seconds(5));

    itsTimer->async_wait(boost::bind(&Tester::printProgress, this, _1));

    itsThreadPool->start();

    itsThreadPool->join();
  }

  void printResults()
  {
    boost::lock_guard<boost::mutex> lock(itsResultMutex);
    BOOST_FOREACH (const auto& res, itsResults)
    {
      cout << res << endl;
    }
  }

  bool getPrintResults() { return itsPrintResults; }
  void dumpRequests()
  {
    BOOST_FOREACH (const auto& req, itsRequests)
    {
      cout << req << endl;
    }
  }

  void probeRemote()
  {
    ip::tcp::resolver resolver(itsIO);

    ip::tcp::resolver::query query(itsHostName, to_string((long long unsigned int)itsPort));
    auto end_iterator = resolver.resolve(query);

    ip::tcp::socket socket(itsIO);
    boost::asio::connect(socket, end_iterator);

    string reqString = "GET / HTTP/1.0\r\n\r\n";

    // Send request
    boost::asio::write(socket, boost::asio::buffer(reqString));

    // Read at least something
    boost::array<char, 512> retArray;
    std::size_t size = 0;
    string tmp;
    string response;
    size =
        boost::asio::read(socket, boost::asio::buffer(retArray), boost::asio::transfer_at_least(8));

    // If no exceptions are thrown, the remote is succesfully contacted
  }

 private:
  const string itsHostName;

  unsigned int itsPort;

  fs::path itsRequestFilePath;

  pool* itsThreadPool;

  boost::asio::io_service itsIO;

  boost::asio::signal_set itsSignals;

  long itsCurrentResultInd;

  boost::scoped_ptr<boost::thread> itsThread;

  boost::scoped_ptr<boost::asio::deadline_timer> itsTimer;

  vector<Request> itsRequests;

  vector<Result> itsResults;

  boost::mutex itsResultMutex;

  bool itsPrintResults;

  void readReqFile()
  {
    ifstream inFile(itsRequestFilePath.string());

    string line;

    if (inFile.is_open())
    {
      while (getline(inFile, line))
      {
        boost::algorithm::replace_all(line, " ", "+");  //(At least spaces must be encoded
        itsRequests.emplace_back(itsHostName, itsPort, line);
      }

      // Shuffle the requests
      random_shuffle(itsRequests.begin(), itsRequests.end());
    }

    inFile.close();
  }

  void handleSignal(const boost::system::error_code& err, int signal_number)
  {
    itsIO.stop();
    itsThreadPool->shutdown();
    if (signal_number == 3)  // SigQuit should print results
    {
      itsPrintResults = true;
    }
  }

  void printProgress(const boost::system::error_code& err)
  {
    if (err != boost::asio::error::operation_aborted)
    {
      std::vector<Result> theseResults;
      {
        boost::lock_guard<boost::mutex> lock(itsResultMutex);
        theseResults.assign(itsResults.begin() + itsCurrentResultInd, itsResults.end());
        itsCurrentResultInd = itsResults.size();
      }

      if (!theseResults.empty())
      {
        std::size_t reqs = theseResults.size();

        long average_duration = 0;

        BOOST_FOREACH (const auto& res, theseResults)
        {
          average_duration += res.duration.total_milliseconds();
        }

        average_duration /= reqs;

        std::cerr << bp::second_clock::local_time() << " Completed " << reqs
                  << " requests with average response time of " << average_duration << " ms."
                  << std::endl;
      }
      else
      {
        std::cerr << bp::second_clock::local_time() << " No completed requests in this time slice"
                  << std::endl;
      }

      itsTimer->expires_from_now(bp::seconds(5));
      itsTimer->async_wait(boost::bind(&Tester::printProgress, this, _1));
    }
  }

  void performRequest(Request theReq)
  {
    ip::tcp::resolver resolver(itsIO);
    ip::tcp::resolver::query query(theReq.hostName, to_string((long long unsigned int)theReq.port));
    auto end_iterator = resolver.resolve(query);

    ip::tcp::socket socket(itsIO);
    boost::asio::connect(socket, end_iterator);

    string reqString = "GET " + theReq.URI + " HTTP/1.0\r\n\r\n";

    // Send request
    auto before = bp::microsec_clock::universal_time();
    boost::system::error_code err;
    boost::asio::write(socket, boost::asio::buffer(reqString), err);

    // Read at least something
    boost::array<char, 512> retArray;
    std::size_t size = 0;
    string errorCode;
    string response;
    if (!err)
    {
      size = boost::asio::read(
          socket, boost::asio::buffer(retArray), boost::asio::transfer_at_least(8), err);
      auto parsedResult =
          parseStatus(boost::make_iterator_range(retArray.begin(), retArray.begin() + size));
      errorCode = parsedResult.first;
      response = parsedResult.second;
    }
    else
    {
      // Don't include erroneus connects
      return;
    }

    auto after = bp::microsec_clock::universal_time();
    // This request is done

    boost::lock_guard<boost::mutex> lock(itsResultMutex);
    itsResults.emplace_back(before, theReq.URI, after - before, errorCode, response);
  }
};

void testRequest(Request theReq)
{
  boost::asio::io_service itsIO;
  ip::tcp::resolver resolver(itsIO);
  ip::tcp::resolver::query query(theReq.hostName, to_string((long long unsigned int)theReq.port));
  auto end_iterator = resolver.resolve(query);

  ip::tcp::socket socket(itsIO);
  boost::asio::connect(socket, end_iterator);

  string reqString = "GET " + theReq.URI + " HTTP/1.0\r\n\r\n";

  boost::asio::write(socket, boost::asio::buffer(reqString));

  boost::array<char, 512> retArray;

  // Read until retArray is full
  auto size =
      boost::asio::read(socket, boost::asio::buffer(retArray), boost::asio::transfer_at_least(8));
  // This request is done

  std::cout << string(retArray.begin(), retArray.begin() + size) << std::endl;
}

int main(int argc, const char* argv[])
{
  unsigned int threads;
  string host;
  unsigned short port;
  string suite_file;

  po::options_description desc("Allowed Options");

  desc.add_options()("help,h", "Print this help")(
      "host,H", po::value<string>(&host)->default_value("brainstormgw.fmi.fi"), "Host")(
      "port,p", po::value<unsigned short>(&port)->default_value(80), "Port")(
      "suite,s", po::value<string>(&suite_file), "File from which to read the suite")(
      "threads,t", po::value<unsigned int>(&threads)->default_value(5), "Number of worker threads");

  po::variables_map vmap;

  po::store(po::command_line_parser(argc, argv).options(desc).run(), vmap);

  po::notify(vmap);

  if (vmap.count("help"))
  {
    std::cout << "Usage: "
              << "tester [options]" << std::endl;
    std::cout << desc << std::endl;
    return 1;
  }

  if (vmap.count("suite") == 0)
  {
    std::cout << "Please provide the test suite file" << std::endl;
    std::cout << "Usage: "
              << "tester [options]" << std::endl;
    std::cout << desc << std::endl;

    return 1;
  }

  Tester theTester(vmap["suite"].as<string>(),
                   vmap["threads"].as<unsigned int>(),
                   vmap["host"].as<string>(),
                   vmap["port"].as<unsigned short>());

  std::cerr << "Probing the remote..." << std::endl;

  theTester.probeRemote();

  std::cerr << "Succesfully probed, running test..." << std::endl;

  theTester.run();

  if (theTester.getPrintResults())
  {
    theTester.printResults();
  }
}

ext: cpp


text:
#include "Helpers.hpp"
#include "Heuristics.hpp"
#include "Options.hpp"

#include <clang/AST/Decl.h>
#include <clang/AST/DeclCXX.h>
#include <llvm/Support/Casting.h>

#include <boost/optional.hpp>

namespace
{

CheckResult checkFunctionNameLength(const clang::FunctionDecl& functionDecl, const Options& options)
{
    const auto limit = options["km-1-1-limit"].as<int>();

    const auto name = getFunctionName(functionDecl);

    // ignore template parameter names
    const auto pos = name.find('<');
    const auto len = pos == std::string::npos ? name.length() : pos;

    // ignore operators
    if ((int)len > limit && name.find("operator ") == std::string::npos) {
        auto methodDecl = clang::dyn_cast<clang::CXXMethodDecl>(&functionDecl);

        // also ignore generated methods
        if (!methodDecl || methodDecl->isUserProvided()) {
            return {
                 loc(functionDecl),
                 "long function name",
                 "the name of function '" + name + "' is " + std::to_string(len) +
                 " characters long, which is more than " + std::to_string(limit) + " characters"
             };
        }
    }

    return {};
}

CheckResult checkParamCount(const clang::FunctionDecl& functionDecl, const Options& options)
{
    const auto limit = options["km-1-2-limit"].as<int>();

    if ((int)functionDecl.parameters().size() > limit) {
        return {
            loc(functionDecl),
             "too many parameters",
             "function '" + getFunctionName(functionDecl) + "' has " + std::to_string(functionDecl.parameters().size()) +
             " parameters, which are more than " + std::to_string(limit) + " parameters"
        };
    } else {
        return {};
    }
}

CheckResult checkConsecutiveParams(const clang::FunctionDecl& functionDecl, const Options& options)
{
    const auto limit = options["km-1-3-limit"].as<int>();

    auto check = [limit](const auto& params) -> boost::optional<std::string> {
        if ((int)params.size() > limit) {
            return std::to_string(params.size()) + " consecutive parameters of type " + params.back()->getOriginalType().getAsString();
        } else {
            return {};
        }
    };

    std::string msg;

    std::vector<clang::ParmVarDecl*> params;

    for (const auto param : functionDecl.parameters()) {

        if (!params.empty()) {
            if (params.back()->getOriginalType() != param->getOriginalType()) {
                if (auto res = check(params)) {
                    append(msg, *res, " and ");
                }

                params.clear();
            }
        }

        params.push_back(param);
    }

    if (auto res = check(params)) {
        append(msg, *res, " and ");
    }

    if (!msg.empty()) {
        msg += " (only " + std::to_string(limit) + " consecutive parameters of same type allowed)";

        return {
            loc(functionDecl),
            "too many consecutive parameters of same type",
            "function '" + getFunctionName(functionDecl) + "' has " + msg
        };
    } else {
        return {};
    }

}

} // ns

Heuristic createHeuristic_KM_1()
{
    return Heuristic(
        "KM-1", "The API should be easy to remember",
        {
            { 1, "Prefer short function names", &checkFunctionNameLength },
            { 2, "Avoid functions with many parameters", &checkParamCount },
            { 3, "Avoid functions with many consecutive parameters of the same type", &checkConsecutiveParams }
        }
    );
}

max_stars_repo_name: phitsc/check-cpp-api

max_issues_repo_name: phitsc/check-cpp-api

max_forks_repo_name: phitsc/check-cpp-api


text:
// Copyright (C) 2018 Internet Systems Consortium, Inc. ("ISC")
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.

#include <config.h>

#include <dhcp/packet_queue_ring.h>
#include <dhcp/tests/packet_queue_testutils.h>

#include <boost/shared_ptr.hpp>
#include <gtest/gtest.h>

using namespace std;
using namespace isc;
using namespace isc::dhcp;
using namespace isc::dhcp::test;

namespace {

/// @brief DHCPv4 queue with implements drop and eat logic
///
/// This class derives from the default DHCPv4 ring queue
/// and provies implementations for shouldDropPacket() and
/// eatPackets().  This permits a full exercising of the
/// PacketQueue interface as well as the basic v4 ring queue
/// mechanics.
class TestQueue4 : public PacketQueueRing4 {
public:
    /// @brief Constructor
    ///
    /// @param queue_size maximum number of packets the queue can hold
    TestQueue4(size_t queue_size)
        : PacketQueueRing4("kea-ring4", queue_size), drop_enabled_(false), eat_count_(0) {
    };

    /// @brief virtual Destructor
    virtual ~TestQueue4(){};

    /// @brief Determines is a packet should be dropped.
    ///
    /// If drop is enabled and either the packet transaction
    /// id or the socket source port are even numbers, drop the packet
    ///
    /// @param packet the packet under consideration
    /// @param source the socket the packet came from
    ///
    /// @return True if the packet should be dropped.
    virtual bool shouldDropPacket(Pkt4Ptr packet,
                            const SocketInfo& source) {
        if (drop_enabled_) {
            return ((packet->getTransid() % 2 == 0) ||
                    (source.port_ % 2 == 0));
        }

        return (false);
    }

    /// @brief Discards a number of packets from one end of the queue
    ///
    /// Dequeue and discard eat_count_ packets from the given end of
    /// the queue_.
    ///
    /// @param from end of the queue from which packets should discarded
    ///
    /// @return The number of packets discarded.
    virtual int eatPackets(const QueueEnd& from) {
        int eaten = 0;
        for ( ; eaten < eat_count_; ++eaten) {
            Pkt4Ptr pkt = popPacket(from);
            if (!pkt) {
                break;
            }
        }

        return (eaten);
    }

    bool drop_enabled_;
    int eat_count_;
};

// Verifies use of the generic PacketQueue interface to
// construct a queue implementation.
TEST(PacketQueueRing4, interfaceBasics) {
    // Verify we can create a queue
    PacketQueue4Ptr q(new PacketQueueRing4("kea-ring4",100));
    ASSERT_TRUE(q);

    // It should be empty.
    EXPECT_TRUE(q->empty());

    // Type should match.
    EXPECT_EQ("kea-ring4", q->getQueueType());

    // Fetch the queue info and verify it has all the expected values.
    checkInfo(q, "{ \"capacity\": 100, \"queue-type\": \"kea-ring4\", \"size\": 0 }");
}

// Verifies the higher level functions of queueing and dequeueing
// from the ring buffer.
TEST(PacketQueueRing4, enqueueDequeueTest) {
    PacketQueue4Ptr q(new PacketQueueRing4("kea-ring4", 3));

    // Fetch the queue info and verify it has all the expected values.
    checkInfo(q, "{ \"capacity\": 3, \"queue-type\": \"kea-ring4\", \"size\": 0 }");

    // Enqueue five packets.  The first two should be pushed off.
    SocketInfo sock1(isc::asiolink::IOAddress("127.0.0.1"), 777, 10);

    for (int i = 1; i < 6; ++i) {
        Pkt4Ptr pkt(new Pkt4(DHCPDISCOVER, 1000+i));
        ASSERT_NO_THROW(q->enqueuePacket(pkt, sock1));
    }

    // Fetch the queue info and verify it has all the expected values.
    checkInfo(q, "{ \"capacity\": 3, \"queue-type\": \"kea-ring4\", \"size\": 3 }");

    // We should have transids 1003,1004,1005
    Pkt4Ptr pkt;
    for (int i = 3; i < 6; ++i) {
        ASSERT_NO_THROW(pkt = q->dequeuePacket());
        ASSERT_TRUE(pkt);
        EXPECT_EQ(1000 + i, pkt->getTransid());
    }

    // Queue should be empty.
    ASSERT_TRUE(q->empty());

    // Dequeuing should fail safely, with an empty return.
    ASSERT_NO_THROW(pkt = q->dequeuePacket());
    ASSERT_FALSE(pkt);

    // Enqueue three more packets.
    for (int i = 0; i < 3; ++i) {
        Pkt4Ptr pkt(new Pkt4(DHCPDISCOVER, 1000+i));
        ASSERT_NO_THROW(q->enqueuePacket(pkt, sock1));
    }

    checkIntStat(q, "size", 3);

    // Let's flush the buffer and then verify it is empty.
    q->clear();
    EXPECT_TRUE(q->empty());
    checkIntStat(q, "size", 0);
}

// Verifies peeking, pushing, and popping  which
// are unique to PacketQueueRing<> derivations.
TEST(PacketQueueRing4, peekPushPopTest) {
    PacketQueueRing4 q("kea-ring4", 3);

    // Push five packets onto the end. The first two should get pushed off.
    for (int i = 1; i < 6; ++i) {
        Pkt4Ptr pkt(new Pkt4(DHCPDISCOVER, 1000+i));
        ASSERT_NO_THROW(q.pushPacket(pkt));
    }

    // We should have three.
    ASSERT_EQ(3, q.getSize());

    // We should have transids 1005,1004,1003  (back to front)

    // Peek front should be transid 1003.
    Pkt4Ptr pkt;
    ASSERT_NO_THROW(pkt = q.peek(QueueEnd::FRONT));
    ASSERT_TRUE(pkt);
    EXPECT_EQ(1003, pkt->getTransid());

    // Peek back should be transid 1005.
    ASSERT_NO_THROW(pkt = q.peek(QueueEnd::BACK));
    ASSERT_TRUE(pkt);
    EXPECT_EQ(1005, pkt->getTransid());

    // Pop front should return transid 1003.
    ASSERT_NO_THROW(pkt = q.popPacket(QueueEnd::FRONT));
    ASSERT_TRUE(pkt);
    EXPECT_EQ(1003, pkt->getTransid());

    // Pop back should return transid 1005.
    ASSERT_NO_THROW(pkt = q.popPacket(QueueEnd::BACK));
    ASSERT_TRUE(pkt);
    EXPECT_EQ(1005, pkt->getTransid());

    // Peek front should be transid 1004.
    ASSERT_NO_THROW(pkt = q.peek(QueueEnd::FRONT));
    ASSERT_TRUE(pkt);
    EXPECT_EQ(1004, pkt->getTransid());

    // Peek back should be transid 1004.
    ASSERT_NO_THROW(pkt = q.peek(QueueEnd::BACK));
    ASSERT_TRUE(pkt);
    EXPECT_EQ(1004, pkt->getTransid());

    // Pop front should return transid 1004.
    ASSERT_NO_THROW(pkt = q.popPacket(QueueEnd::FRONT));
    ASSERT_TRUE(pkt);
    EXPECT_EQ(1004, pkt->getTransid());

    // Pop front should return an empty pointer.
    ASSERT_NO_THROW(pkt = q.popPacket(QueueEnd::BACK));
    ASSERT_FALSE(pkt);
}

// Verifies enqueuing operations when drop logic is enabled.
// This accesses it's queue instance as a TestQueue4, rather than
// a PacketQueue4Ptr, to provide access to TestQueue4 specifics.
TEST(TestQueue4, shouldDropPacketTest) {
    TestQueue4 q(100);
    EXPECT_TRUE(q.empty());
    ASSERT_FALSE(q.drop_enabled_);
    ASSERT_EQ(0, q.eat_count_);

    SocketInfo sock_even(isc::asiolink::IOAddress("127.0.0.1"), 888, 10);
    SocketInfo sock_odd(isc::asiolink::IOAddress("127.0.0.1"), 777, 11);

    // Drop is not enabled.
    // We should be able to enqueue a packet with even numbered values.
    Pkt4Ptr pkt(new Pkt4(DHCPDISCOVER, 1002));
    ASSERT_NO_THROW(q.enqueuePacket(pkt, sock_even));
    ASSERT_EQ(1, q.getSize());

    // We should be able to enqueue a packet with odd numbered values.
    pkt.reset(new Pkt4(DHCPDISCOVER, 1003));
    ASSERT_NO_THROW(q.enqueuePacket(pkt, sock_odd));
    ASSERT_EQ(2, q.getSize());

    // Enable drop logic.
    q.drop_enabled_ = true;

    // We should not be able to add one with an even-numbered transid.
    pkt.reset(new Pkt4(DHCPDISCOVER, 1004));
    ASSERT_NO_THROW(q.enqueuePacket(pkt, sock_odd));
    ASSERT_EQ(2, q.getSize());

    // We should not be able to add one with from even-numbered port.
    pkt.reset(new Pkt4(DHCPDISCOVER, 1005));
    ASSERT_NO_THROW(q.enqueuePacket(pkt, sock_even));
    EXPECT_EQ(2, q.getSize());

    // We should be able to add one with an odd-numbered values.
    pkt.reset(new Pkt4(DHCPDISCOVER, 1007));
    ASSERT_NO_THROW(q.enqueuePacket(pkt, sock_odd));
    EXPECT_EQ(3, q.getSize());

    // Dequeue them and make sure they are as expected: 1002,1003, and 1007.
    ASSERT_NO_THROW(pkt = q.dequeuePacket());
    ASSERT_TRUE(pkt);
    EXPECT_EQ(1002, pkt->getTransid());

    ASSERT_NO_THROW(pkt = q.dequeuePacket());
    ASSERT_TRUE(pkt);
    EXPECT_EQ(1003, pkt->getTransid());

    ASSERT_NO_THROW(pkt = q.dequeuePacket());
    ASSERT_TRUE(pkt);
    EXPECT_EQ(1007, pkt->getTransid());

    // Queue should be empty.
    ASSERT_NO_THROW(pkt = q.dequeuePacket());
    ASSERT_FALSE(pkt);
}

// Verifies dequeuing operations when eat packets is enabled.
// This accesses it's queue instance as a TestQueue4, rather than
// a PacketQueue4Ptr, to provide access to TestQueue4 specifics.
TEST(TestQueue4, eatPacketsTest) {
    TestQueue4 q(100);
    EXPECT_TRUE(q.empty());
    ASSERT_FALSE(q.drop_enabled_);
    ASSERT_EQ(0, q.eat_count_);

    SocketInfo sock(isc::asiolink::IOAddress("127.0.0.1"), 888, 10);

    Pkt4Ptr pkt;
    // Let's add five packets.
    for (int i = 1; i < 6; ++i) {
        pkt.reset(new Pkt4(DHCPDISCOVER, 1000 + i));
        ASSERT_NO_THROW(q.enqueuePacket(pkt, sock));
        ASSERT_EQ(i, q.getSize());
    }

    // Setting eat count to two and dequeuing should discard 1001
    // and 1002, resulting in a dequeue of 1003.
    q.eat_count_ = 2;
    ASSERT_NO_THROW(pkt = q.dequeuePacket());
    ASSERT_TRUE(pkt);
    EXPECT_EQ(1003, pkt->getTransid());
    EXPECT_EQ(2, q.getSize());
}

} // end of anonymous namespace

ext: cc

max_stars_repo_name: svenauhagen/kea

max_issues_repo_name: jxiaobin/kea

max_forks_repo_name: jxiaobin/kea


text:
#include "stdafx.h"
#include <windows.h>
#include <stdlib.h>
#include <boost/thread.hpp>
#include "DataQueue.h"
#include "MessageType.h"
#include "StateRequestNpcAction.h"
#include "StateRequestMoveAction.h"
#include "CloudGetNumFiles.h"
#include "CloudRead.h"
#include "CloudWrite.h"
#include "InventorySack_AddItem.h"
#include "NpcDetectionHook.h"
#include "SaveTransferStash.h"
#include "Exports.h"
#include "CanUseDismantle.h"

#pragma region Variables
// Switches hook logging on/off
#if 1
#include "HookLog.h"
HookLog g_log;
#define LOG(streamdef) \
{ \
    std::string msg = (((std::ostringstream&)(std::ostringstream().flush() << streamdef)).str()); \
    g_log.out(msg); \
    msg += _T("\n"); \
    OutputDebugString(msg.c_str()); \
}
#else
#define LOG(streamdef) \
    __noop;
#endif

DWORD g_lastThreadTick = 0;
HANDLE g_hEvent;
HANDLE g_thread;

DataQueue g_dataQueue;

HWND g_targetWnd = NULL;

#pragma endregion

#pragma region CORE

/// Thread function that dispatches queued message blocks to the AOIA application.
void WorkerThreadMethod() {
    while ((g_hEvent != NULL) && (WaitForSingleObject(g_hEvent,INFINITE) == WAIT_OBJECT_0)) {
        if (g_hEvent == NULL) {
            break;
        }

        DWORD tick = GetTickCount();
        if (tick < g_lastThreadTick) {
            // Overflow
            g_lastThreadTick = tick;
        }

        if ((tick - g_lastThreadTick > 1000) || (g_targetWnd == NULL)) {
            // We either don't have a valid window target OR it has been more than 1 sec since we last update the target.
            g_targetWnd = FindWindow( "GDIAWindowClass", NULL);
            g_lastThreadTick = GetTickCount();
            LOG("FindWindow returned: " << g_targetWnd);
        }

        while (!g_dataQueue.empty()) {
            DataItemPtr item = g_dataQueue.pop();

            if (g_targetWnd == NULL) {
                // We have data, but no target window, so just delete the message
                continue;
            }

            COPYDATASTRUCT data;
            data.dwData = item->type();
            data.lpData = item->data();
            data.cbData = item->size();

            // To avoid blocking the main thread, we should not have a lock on the queue while we process the message.
			SendMessage( g_targetWnd, WM_COPYDATA, 0, ( LPARAM ) &data );
            LOG("After SendMessage error code is " << GetLastError());
        }
    }
}

unsigned __stdcall WorkerThreadMethodWrap(void* argss) {
	WorkerThreadMethod();
	return 0;
}
void StartWorkerThread() {
	LOG("Starting worker thread..");
	unsigned int pid;
	g_thread = (HANDLE)_beginthreadex(NULL, 0, &WorkerThreadMethodWrap, NULL, 0, &pid);

	DataItemPtr item(new DataItem(TYPE_REPORT_WORKER_THREAD_LAUNCHED, 0, NULL));
	g_dataQueue.push(item);
	SetEvent(g_hEvent);
	LOG("Started worker thread..");
}

void EndWorkerThread() {
	LOG("Ending worker thread..");
	if (g_hEvent != NULL) {
		SetEvent(g_hEvent);
		HANDLE h = g_hEvent;
		g_hEvent = NULL;
		CloseHandle(h);

		//WaitForSingleObject(g_thread, INFINITE);
		CloseHandle(g_thread);
	}
}

#pragma endregion

static void ConfigurePlayerPositionHooks(std::vector<BaseMethodHook*>& hooks) {
	hooks.push_back(new StateRequestMoveAction(&g_dataQueue, g_hEvent, REQUEST_MOVE_ACTION_MOVETO));
	hooks.push_back(new StateRequestMoveAction(&g_dataQueue, g_hEvent, REQUEST_MOVE_ACTION_IDLE));
	hooks.push_back(new StateRequestMoveAction(&g_dataQueue, g_hEvent, REQUEST_MOVE_ACTION_LONG_IDLE));
	hooks.push_back(new StateRequestMoveAction(&g_dataQueue, g_hEvent, REQUEST_MOVE_ACTION_MOVE_AND_SKILL));
	hooks.push_back(new StateRequestMoveAction(&g_dataQueue, g_hEvent, REQUEST_MOVE_ACTION_MOVE_ACTOR));

	hooks.push_back(new StateRequestMoveAction(&g_dataQueue, g_hEvent, REQUEST_MOVE_ACTION_MOVE_TO_SKILL));
	hooks.push_back(new StateRequestMoveAction(&g_dataQueue, g_hEvent, REQUEST_MOVE_ACTION_PICKUP));
	hooks.push_back(new StateRequestMoveAction(&g_dataQueue, g_hEvent, REQUEST_MOVE_ACTION_TALK_TO_NPC));
	hooks.push_back(new StateRequestMoveAction(&g_dataQueue, g_hEvent, REQUEST_MOVE_ACTION_SKILL));

	// For these, the target position could actually be the smuggler.
	hooks.push_back(new StateRequestNpcAction(&g_dataQueue, g_hEvent, REQUEST_NPC_ACTION_IDLE));
	hooks.push_back(new StateRequestNpcAction(&g_dataQueue, g_hEvent, REQUEST_NPC_ACTION_MOVETO));
	hooks.push_back(new StateRequestNpcAction(&g_dataQueue, g_hEvent, REQUEST_NPC_ACTION_JUMP_TO_SKILL));
	hooks.push_back(new StateRequestNpcAction(&g_dataQueue, g_hEvent, REQUEST_NPC_ACTION_LONG_IDLE));
	hooks.push_back(new StateRequestNpcAction(&g_dataQueue, g_hEvent, REQUEST_NPC_ACTION_MOVE_AND_SKILL));
	hooks.push_back(new StateRequestNpcAction(&g_dataQueue, g_hEvent, REQUEST_NPC_ACTION_MOVE_TO_ACTOR));
	hooks.push_back(new StateRequestNpcAction(&g_dataQueue, g_hEvent, REQUEST_NPC_ACTION_MOVE_TO_SKILL));
	hooks.push_back(new StateRequestNpcAction(&g_dataQueue, g_hEvent, REQUEST_NPC_ACTION_PICKUP_ITEM));
	hooks.push_back(new StateRequestNpcAction(&g_dataQueue, g_hEvent, REQUEST_NPC_ACTION_TALK_TO_NPC));
	hooks.push_back(new StateRequestNpcAction(&g_dataQueue, g_hEvent, REQUEST_NPC_ACTION_MOVE_TO_NPC));
}

// Cloud detection (is cloud enabled?) hooks
static void ConfigureCloudDetectionHooks(std::vector<BaseMethodHook*>& hooks) {
	hooks.push_back(new CloudGetNumFiles(&g_dataQueue, g_hEvent));
	hooks.push_back(new CloudRead(&g_dataQueue, g_hEvent));
	hooks.push_back(new CloudWrite(&g_dataQueue, g_hEvent));
}

static void ConfigureStashDetectionHooks(std::vector<BaseMethodHook*>& hooks) {
	// Stash detection hooks
	hooks.push_back(new NpcDetectionHook(&g_dataQueue, g_hEvent));
	hooks.push_back(new CanUseDismantle(&g_dataQueue, g_hEvent));
	hooks.push_back(new SaveTransferStash(&g_dataQueue, g_hEvent));
	hooks.push_back(new InventorySack_AddItem(&g_dataQueue, g_hEvent)); // Includes GetPrivateStash internally
}

std::vector<BaseMethodHook*> hooks;
int ProcessAttach(HINSTANCE _hModule) {
	LOG("Attatching to process..");
	g_hEvent = CreateEvent(NULL,FALSE,FALSE,"IA_Worker");

	LOG("Preparing hooks..");
	// Player position hooks
	ConfigurePlayerPositionHooks(hooks);
	ConfigureCloudDetectionHooks(hooks);
	ConfigureStashDetectionHooks(hooks);

	std::stringstream msg;
	msg << "Starting hook enabling.. " << hooks.size() << " hooks.";
	LOG(msg);
	for (unsigned int i = 0; i < hooks.size(); i++) {
		LOG("Enabling hook..");
		hooks[i]->EnableHook();
	}
	LOG("Hooking complete..");

    StartWorkerThread();
	LOG("Existing initialization..");
    return TRUE;
}

#pragma region Attach_Detatch
int ProcessDetach( HINSTANCE _hModule ) {
	// Signal that we are shutting down
	// This message is not at all guaranteed to get sent.

	OutputDebugString("ProcessDetach");

	for (unsigned int i = 0; i < hooks.size(); i++) {
		hooks[i]->DisableHook();
		delete hooks[i];
	}
	hooks.clear();

    EndWorkerThread();
    return TRUE;
}

BOOL APIENTRY DllMain(HINSTANCE hModule, DWORD  ul_reason_for_call, LPVOID lpReserved) {
    switch (ul_reason_for_call) {
	case DLL_PROCESS_ATTACH:
        return ProcessAttach( hModule );

	case DLL_PROCESS_DETACH:
        return ProcessDetach( hModule );
	}
    return TRUE;
}
#pragma endregion

max_stars_repo_name: Eradev/iagd

max_issues_repo_name: Eradev/iagd

max_forks_repo_name: Eradev/iagd


text:
//
// Created by Yohsuke Murase on 2020/02/10.
//

#define _USE_MATH_DEFINES
#include <iostream>
#include <array>
#include <cmath>
#include <cassert>
#include <random>
#include <Eigen/Dense>

class ReactiveStrategy {
  public:
  ReactiveStrategy(double _p, double _q) : p(_p), q(_q) {};
  double p, q;
  int Type(double R, double T, double S, double P, double epsilon) const { // 0: other, 1: partner, 2: rival
    // q*=min{1−(T−R)∕(R−S),(R−P)∕(T−P)}
    double q_star = std::min( 1.0-(T-R)/(R-S), (R-P)/(T-P) );
    double partner_d = 1.0 - p;
    if( q > q_star ) {
      partner_d = std::sqrt( (1.0-p)*(1.0-p) + (q-q_star)*(q-q_star) );
    }
    if( q < epsilon ) {
      if( partner_d < epsilon ) {
        return ( q <= partner_d ) ? 2 : 1;
      }
      else return 2;
    }
    else {
      if( partner_d < epsilon ) { return 1; }
    }
    return 0;
  }
  static std::pair<double,double> PartnerRivalFractions(double R, double T, double S, double P, double epsilon) {
    double q_star = std::min( 1.0-(T-R)/(R-S), (R-P)/(T-P) );
    if( q_star < epsilon ) { throw std::runtime_error("q_star is smaller than epsilon"); }
    double partner_area = 0.5 * epsilon * epsilon + (q_star-epsilon) * epsilon + M_PI * epsilon * epsilon * 0.25;
    double rival_area = (1.0-epsilon) * epsilon + 0.5 * epsilon * epsilon;
    return std::make_pair(partner_area, rival_area);
  }
  std::array<double,4> StationaryState(const ReactiveStrategy& other, double error = 0.0) const {
    Eigen::Matrix<double,4,4> A;
    // state 0: cc, 1: cd, 2: dc, 3: dd
    // calculate transition probability from j to i
    for(int j=0; j<4; j++) {
      double c_A = (j == 0 || j == 2) ? p : q;
      double c_B = (j == 0 || j == 1) ? other.p : other.q;
      // taking into account error
      c_A = (1.0-error) * c_A + error * (1.0 - c_A);
      c_B = (1.0-error) * c_B + error * (1.0 - c_B);
      A(0,j) = c_A * c_B;
      A(1,j) = c_A * (1.0-c_B);
      A(2,j) = (1.0-c_A) * c_B;
      A(3,j) = (1.0-c_A) * (1.0-c_B);
    }
    for(int i=0; i<4; i++) {
      A(i,i) -= 1.0;
    }
    for(int i=0; i<4; i++) {
      A(3,i) += 1.0;  // normalization condition
    }
    Eigen::VectorXd b(4);
    for(int i=0; i<4; i++) { b(i) = 0.0;}
    b(3) = 1.0;
    Eigen::VectorXd x = A.colPivHouseholderQr().solve(b);
    std::array<double,4> ans = {0};
    for(int i=0; i<4; i++) {
      ans[i] = x(i);
    }
    return ans;
  }
};

class ReactiveStrategyOrCAPRI {
  public:
  ReactiveStrategyOrCAPRI(int _is_capri_ta, double _p, double _q) : is_capri_ta(_is_capri_ta), reactive(_p,_q), stat_with_self_valid(false) {};
  int is_capri_ta; // 0: reactive, 1: capri, 2: tft-atft
  ReactiveStrategy reactive;
  std::array<double,4> stat_with_self;
  bool stat_with_self_valid;
  int Type(double R, double T, double S, double P, double epsilon) const { // 0: other, 1: partner, 2: rival, 3: capri, 4: tft-atft
    if( is_capri_ta == 1 ) { return 3; }
    else if( is_capri_ta == 2 ) { return 4; }
    else {
      return reactive.Type(R,T,S,P,epsilon);
    }
  }
  std::array<double,4> StationaryStateWithSelf(double error) {
    if(!stat_with_self_valid) {
      stat_with_self = StationaryState(*this, error);
      stat_with_self_valid = true;
    }
    return stat_with_self;
  }
  std::array<double,4> StationaryState(const ReactiveStrategyOrCAPRI& other, double error) const {
    if( is_capri_ta == 0 && other.is_capri_ta == 0 ) {
      return reactive.StationaryState(other.reactive, error);
    }
    else {
      // CAPRI : cdddcdddcdcddddddcddcdddddddddddcdcdcdcdddddddddddddcdccddddddcd
      const double CAPRI_P[64] = {
        1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0,
        1.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0,
        0.0, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0,
        0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,
        1.0, 0.0, 1.0, 0.0, 1.0, 0.0, 1.0, 0.0,
        0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,
        0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 1.0, 1.0,
        0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0
      };
      // TFT-ATFT : cdcdcdcddccddccdcdcccdccdccddccdcdcdcdcddccddccdcdcccdccdccddccd
      const double TFTATFT_P[64] = {
        1.0, 0.0, 1.0, 0.0, 1.0, 0.0, 1.0, 0.0,
        0.0, 1.0, 1.0, 0.0, 0.0, 1.0, 1.0, 0.0,
        1.0, 0.0, 1.0, 1.0, 1.0, 0.0, 1.0, 1.0,
        0.0, 1.0, 1.0, 0.0, 0.0, 1.0, 1.0, 0.0,
        1.0, 0.0, 1.0, 0.0, 1.0, 0.0, 1.0, 0.0,
        0.0, 1.0, 1.0, 0.0, 0.0, 1.0, 1.0, 0.0,
        1.0, 0.0, 1.0, 1.0, 1.0, 0.0, 1.0, 1.0,
        0.0, 1.0, 1.0, 0.0, 0.0, 1.0, 1.0, 0.0
      };
      Eigen::Matrix<double,64,64> A;
      // construct A
      for(int i=0; i<64; i++) {
        for (int j = 0; j < 64; j++) {
          // transition probability from j to i
          // cooperation prob of A
          if (((j << 1) & 0b110110) != (i & 0b110110)) {
            A(i, j) = 0.0;
          } else {
            int j_inv = (((j & 0b111) << 3) | ((j >> 3) & 0b111));  // j from B's viewpoint
            double coop_prob_A;
            if (is_capri_ta == 1) { coop_prob_A = CAPRI_P[j]; }
            else if( is_capri_ta == 2) { coop_prob_A = TFTATFT_P[j]; }
            else {
              coop_prob_A = ((j & 1) == 0) ? reactive.p : reactive.q;
            }
            double coop_prob_B;
            if (other.is_capri_ta == 1) {
              coop_prob_B = CAPRI_P[j_inv];
            }
            else if( other.is_capri_ta == 2) {
              coop_prob_B = TFTATFT_P[j_inv];
            }
            else {
              coop_prob_B = ((j_inv & 1) == 0) ? other.reactive.p : other.reactive.q;
            }

            bool A_c = ((i & 0b001000) == 0); // A cooperates
            double go_target_prob_A = A_c ? coop_prob_A : (1.0 - coop_prob_A);
            bool B_c = ((i & 0b000001) == 0); // B cooperates
            double go_target_prob_B = B_c ? coop_prob_B : (1.0 - coop_prob_B);
            A(i, j) = (1.0 - error) * (1.0 - error) * go_target_prob_A * go_target_prob_B
                      + (1.0 - error) * error * go_target_prob_A * (1.0 - go_target_prob_B)
                      + (1.0 - error) * error * (1.0 - go_target_prob_A) * go_target_prob_B
                      + error * error * (1.0 - go_target_prob_A) * (1.0 - go_target_prob_B);
          }
        }
      }

      for (int i = 0; i < 64; i++) {
        A(i, i) -= 1.0;
      }
      for (int i = 0; i < 64; i++) {
        A(63, i) += 1.0;  // normalization condition
      }
      Eigen::VectorXd b(64);
      for (int i = 0; i < 63; i++) { b(i) = 0.0; }
      b(63) = 1.0;
      Eigen::VectorXd x = A.colPivHouseholderQr().solve(b);

      std::array<double, 4> ans = {0.0}; // last action are cc,cd,dc,dd
      for (int i = 0; i < 64; i++) {
        int idx = 0;
        if (i & 0b000001) { idx += 1; }
        if (i & 0b001000) { idx += 2; }
        ans[idx] += x(i);
      }
      return ans;
    }
  }

};

class Ecosystem {
  public:
  Ecosystem(uint64_t seed) : resident(0,0.0,0.0), rnd(seed) {};
  ReactiveStrategyOrCAPRI resident;
  void UpdateResident(double R, double T, double S, double P, uint64_t N, double sigma, double e, double capri_rate, double tft_atft_rate, size_t discrete_level) {
    ReactiveStrategyOrCAPRI mutant = Mutant(capri_rate, tft_atft_rate, discrete_level);
    double rho = FixationProb(R,T,S,P,N,sigma,e,mutant);
    std::uniform_real_distribution<double> uni(0.0, 1.0);
    if( uni(rnd) < rho ) {
      resident = mutant;
    }
  }
  void MeasureAvgRho(double R, double T, double S, double P, size_t n_samples) {
    double ave_s_xx = 0.0, ave_s_xy = 0.0, ave_s_yx = 0.0;
    for(size_t i = 0; i<n_samples; i++) {
      double e = 0.1;
      // auto mut = Mutant(0.0, 0.0, 10);
      auto mut = ReactiveStrategyOrCAPRI(0, 1.0, 0.5);
      auto res = ReactiveStrategyOrCAPRI(2, 0.0, 0.0);
      const auto xx = mut.StationaryStateWithSelf(e);
      const double s_xx = xx[0] * R + xx[1] * S + xx[2] * T + xx[3] * P;
      const auto xy = mut.StationaryState(res, e);
      const double s_xy = xy[0] * R + xy[1] * S + xy[2] * T + xy[3] * P;
      const double s_yx = xy[0] * R + xy[2] * S + xy[1] * T + xy[3] * P;
      const auto yy = res.StationaryStateWithSelf(e);
      const double s_yy = yy[0] * R + yy[1] * S + yy[2] * T + yy[3] * P;
      std::cerr << s_xx << ' ' << s_xy << ' ' << s_yx << ' ' << s_yy << std::endl;
      std::cerr << (s_yy - s_xx) << ' ' << (s_yx - s_xy) << ' ' << (s_yy - s_xy) << std::endl;

      size_t N = 50;
      double sigma = 10.0 / N;
      double rho_inv = 0.0;
      for(int i=0; i<N; i++) {
        double x = sigma * i * 0.5 * ( (2*N-3-i)*s_yy + (i+1)*s_yx - (2*N-1-i)*s_xy - (i-1)*s_xx );
        rho_inv += std::exp(x);
      }
      double rho = 1.0 / rho_inv;
      std::cerr << rho << std::endl;
      ave_s_xx += s_xx;
      ave_s_xy += s_xy;
      ave_s_yx += s_yx;
    }
    std::cerr << ave_s_xx/n_samples << ' ' << ave_s_xy/n_samples << ' ' << ave_s_yx/n_samples << std::endl;
  }
  private:
  ReactiveStrategyOrCAPRI Mutant(double capri_rate, double tft_atft_rate, size_t discrete_level) {
    std::uniform_real_distribution<double> uni(0.0, 1.0);
    double r = uni(rnd);
    if( r < capri_rate ) {
      return ReactiveStrategyOrCAPRI(1, 0.0, 0.0);
    }
    else if( r < capri_rate + tft_atft_rate) {
      return ReactiveStrategyOrCAPRI(2, 0.0, 0.0);
    }
    else {
      if(discrete_level > 0) {
        auto dis_uni = std::uniform_int_distribution<size_t>(0,discrete_level);
        double d = static_cast<double>(discrete_level);
        return ReactiveStrategyOrCAPRI(0, dis_uni(rnd)/d, dis_uni(rnd)/d);
      }
      else {
        return ReactiveStrategyOrCAPRI(0, uni(rnd), uni(rnd));
      }
    }
  }
  double FixationProb(double R, double T, double S, double P, int N, double sigma, double e, ReactiveStrategyOrCAPRI& mutant) {
    const auto xx = mutant.StationaryStateWithSelf(e);
    const double s_xx = xx[0] * R + xx[1] * S + xx[2] * T + xx[3] * P;
    const auto xy = mutant.StationaryState(resident, e);
    const double s_xy = xy[0] * R + xy[1] * S + xy[2] * T + xy[3] * P;
    const double s_yx = xy[0] * R + xy[2] * S + xy[1] * T + xy[3] * P;
    const auto yy = resident.StationaryStateWithSelf(e);
    const double s_yy = yy[0] * R + yy[1] * S + yy[2] * T + yy[3] * P;
    // \frac{1}{\rho} = \sum_{i=0}^{N-1} \exp\left( \sigma \sum_{j=1}^{i} \left[(N-j-1)s_{yy} + js_{yx} - (N-j)s_{xy} - (j-1)s_{xx} \right] \right) \\
    //                = \sum_{i=0}^{N-1} \exp\left( \frac{\sigma i}{2} \left[(-i+2N-3)s_{yy} + (j+1)s_{yx} - (-i+2N-1)s_{xy} - (i-1)s_{xx} \right] \right)
    double rho_inv = 0.0;
    for(int i=0; i<N; i++) {
      double x = sigma * i * 0.5 * ( (2*N-3-i)*s_yy + (i+1)*s_yx - (2*N-1-i)*s_xy - (i-1)*s_xx );
      rho_inv += std::exp(x);
    }
    return 1.0 / rho_inv;
  }
  std::mt19937_64 rnd;
};

int main(int argc, char** argv) {
  if( argc != 11 ) {
    std::cerr << "Error : invalid argument" << std::endl;
    std::cerr << "  Usage : " << argv[0] << " <benefit> <cost> <N> <N_sigma> <error rate> <tmax> <capri_rate> <tft_atft_rate> <discrete_level> <rand_seed>" << std::endl;
    return 1;
  }

  double benefit = std::strtod(argv[1], nullptr);
  double cost = std::strtod(argv[2], nullptr);

  double R = benefit - cost;
  double T = benefit;
  double S = -cost;
  double P = 0;
  uint64_t N = std::strtoull(argv[3], nullptr,0);
  double N_sigma = std::strtod(argv[4], nullptr);
  double sigma = N_sigma / N;
  double e = std::strtod(argv[5], nullptr);
  uint64_t tmax = std::strtoull(argv[6], nullptr,0);
  double capri_rate = std::strtod(argv[7], nullptr);
  double tft_atft_rate = std::strtod(argv[8], nullptr);
  size_t discrete_level = std::strtoul(argv[9], nullptr, 0);
  uint64_t seed = std::strtoull(argv[10], nullptr,0);
  double epsilon = 0.099;

  Ecosystem eco(seed);
  // eco.MeasureAvgRho(R,T,S,P, 1000);
  // return 0;
  uint64_t partner_count = 0, rival_count = 0;
  uint64_t capri_count = 0, tft_atft_count = 0;
  uint64_t t_int = 10000;
  double coop_rate = 0.0;
  for(uint64_t t = 0; t < tmax; t++) {
    eco.UpdateResident(R,T,S,P,N,sigma,e,capri_rate, tft_atft_rate, discrete_level);
    int type = eco.resident.Type(R,T,S,P,epsilon);
    if( type == 1 ) { partner_count++; }
    else if( type == 2 ) { rival_count++; }
    else if( type == 3 ) { capri_count++; }
    else if( type == 4 ) { tft_atft_count++; }

    coop_rate += eco.resident.StationaryState( eco.resident, e )[0];
    // std::cerr << eco.resident.reactive.p << ' ' << eco.resident.reactive.q << std::endl;

    if( t % t_int == t_int - 1) {
      double other = static_cast<double>(t - partner_count - rival_count - capri_count - tft_atft_count) / t;
      double partner = static_cast<double>(partner_count) / t;
      double rival = static_cast<double>(rival_count) / t;
      double capri = static_cast<double>(capri_count) / t;
      double ta = static_cast<double>(tft_atft_count) / t;
      std::cerr << t << ' ' << other << ' ' << partner << ' ' << rival << ' ' << capri << ' ' << ta << ' ' << coop_rate/t << std::endl;
    }
  }

  auto fractions = ReactiveStrategy::PartnerRivalFractions(R,T,S,P,epsilon);
  double other = static_cast<double>(tmax - partner_count - rival_count - capri_count - tft_atft_count) / tmax;
  double partner = static_cast<double>(partner_count) / tmax;
  double rival = static_cast<double>(rival_count) / tmax;
  double capri = static_cast<double>(capri_count) / tmax;
  double ta = static_cast<double>(tft_atft_count) / tmax;
  double other_f = static_cast<double>(tmax - partner_count - rival_count) / tmax / ((1.0-capri_rate-tft_atft_rate)*(1.0 - fractions.first - fractions.second));
  double partner_f = static_cast<double>(partner_count) / tmax / ((1.0-capri_rate-tft_atft_rate)*fractions.first);
  double rival_f = static_cast<double>(rival_count) / tmax / ((1.0-capri_rate-tft_atft_rate)*fractions.second);
  double capri_f = (capri_count > 0) ? static_cast<double>(capri_count) / tmax / capri_rate : 0.0;
  double ta_f = (tft_atft_count > 0) ? static_cast<double>(tft_atft_count) / tmax / tft_atft_rate : 0.0;
  std::cout << "{\"other\":" << other << ", "
            << "\"partner\":" << partner << ", "
            << "\"rival\":" << rival << ", "
            << "\"capri\":" << capri << ", "
            << "\"tft_atft\":" << ta << ", "
            << "\"other_frac\":" << other_f << ", "
            << "\"partner_frac\":" << partner_f << ", "
            << "\"rival_frac\":" << rival_f << ", "
            << "\"capri_frac\":" << capri_f << ", "
            << "\"tft_atft_frac\":" << ta_f << ", "
            << "\"cooperation_rate\":" << coop_rate/tmax << " }" << std::endl;

  return 0;
}


text:
/*=============================================================================
    Copyright (c) 2001-2006 Joel de Guzman

    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)
==============================================================================*/
#if !defined(FUSION_IS_SEQUENCE_05052005_1002)
#define FUSION_IS_SEQUENCE_05052005_1002

#include <boost/fusion/support/sequence_base.hpp>
#include <boost/fusion/support/tag_of.hpp>
#include <boost/mpl/is_sequence.hpp>
#include <boost/mpl/or.hpp>
#include <boost/mpl/bool.hpp>
#include <boost/type_traits/is_convertible.hpp>
#include <boost/type_traits/is_same.hpp>

namespace boost { namespace fusion
{
    // Special tags:
    struct non_fusion_tag;
    struct boost_tuple_tag; // boost::tuples::tuple tag
    struct boost_array_tag; // boost::array tag
    struct mpl_sequence_tag; // mpl sequence tag
    struct std_pair_tag; // std::pair tag

    namespace extension
    {
        template <typename T>
        struct is_sequence_impl
        {
            template <typename Sequence>
            struct apply
              : is_convertible<Sequence, detail::from_sequence_convertible_type>
            {};
        };

        template <>
        struct is_sequence_impl<non_fusion_tag>
        {
            template <typename T>
            struct apply : mpl::false_ {};
        };

        template <>
        struct is_sequence_impl<boost_tuple_tag>;

        template <>
        struct is_sequence_impl<boost_array_tag>;

        template <>
        struct is_sequence_impl<mpl_sequence_tag>;

        template <>
        struct is_sequence_impl<std_pair_tag>;
    }

    namespace traits
    {
        template <typename T>
        struct is_sequence
          : extension::is_sequence_impl<
                typename fusion::detail::tag_of<T>::type
            >::template apply<T>
        {};

        template <typename Sequence, typename Enable = void>
        struct is_native_fusion_sequence
          : is_convertible<Sequence, detail::from_sequence_convertible_type>
        {};
    }
}}

#endif

max_stars_repo_name: zigaosolin/Raytracer

max_issues_repo_name: ksundberg/boost-svn

max_forks_repo_name: ksundberg/boost-svn


text:
#include "turbodbc/column.h"

#include <gtest/gtest.h>
#include "mock_classes.h"

#include <turbodbc/descriptions/string_description.h>
#include <boost/variant/get.hpp>

namespace {

	/**
	* Change the address of the given target_pointer to point to the third argument of the mocked function
	*/
	ACTION_P(store_pointer_to_buffer_in, target_pointer) {
		*target_pointer = &arg2;
	}

	std::size_t const column_index = 42;

}

TEST(ColumnTest, GetInfo)
{
	std::unique_ptr<turbodbc::string_description> description(new turbodbc::string_description("custom_name", false, 128));

	turbodbc_test::mock_statement statement;
	turbodbc::column column(statement, 0, 10, std::move(description));

	auto const info = column.get_info();
	EXPECT_EQ("custom_name", info.name);
	EXPECT_FALSE(info.supports_null_values);
	EXPECT_EQ(turbodbc::type_code::string, info.type);
	EXPECT_EQ(129, info.element_size);
}

TEST(ColumnTest, GetBuffer)
{
	std::unique_ptr<turbodbc::string_description> description(new turbodbc::string_description(128));

	turbodbc_test::mock_statement statement;

	turbodbc::column column(statement, column_index, 100, std::move(description));

	cpp_odbc::multi_value_buffer * buffer = nullptr;
	EXPECT_CALL(statement, do_bind_column(column_index, testing::_, testing::_))
		.WillOnce(store_pointer_to_buffer_in(&buffer));

	column.bind();
	EXPECT_EQ(buffer, &column.get_buffer());
}

TEST(ColumnTest, MoveConstructor)
{
	std::unique_ptr<turbodbc::string_description> description(new turbodbc::string_description(128));

	turbodbc_test::mock_statement statement;

	cpp_odbc::multi_value_buffer * buffer = nullptr;
	turbodbc::column moved(statement, column_index, 100, std::move(description));
	EXPECT_CALL(statement, do_bind_column(column_index, testing::_, testing::_))
		.WillOnce(store_pointer_to_buffer_in(&buffer));
	moved.bind();
	auto const expected_data_pointer = buffer->data_pointer();

	turbodbc::column column(std::move(moved));
	EXPECT_EQ(expected_data_pointer, column.get_buffer().data_pointer());
	EXPECT_EQ(nullptr, moved.get_buffer().data_pointer());

	EXPECT_CALL(statement, do_bind_column(column_index, testing::_, testing::_))
		.WillOnce(store_pointer_to_buffer_in(&buffer));
	ASSERT_NO_THROW(column.bind());
}

max_stars_repo_name: arikfr/turbodbc

max_issues_repo_name: arikfr/turbodbc

max_forks_repo_name: arikfr/turbodbc


text:
/*****************************************************************************
 * Licensed to Qualys, Inc. (QUALYS) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * QUALYS licenses this file to You 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.
 ****************************************************************************/

/**
 * @file
 * @brief IronBee++ --- List
 *
 * This file defines (Const)List, a wrapper for ib_list_t.
 *
 * @remark Developers should be familiar with @ref ironbeepp to understand
 * aspects of this code, e.g., the public/non-virtual inheritance.
 *
 * @author Christopher Alfeld <calfeld@qualys.com>
 */

#ifndef __IBPP__LIST__
#define __IBPP__LIST__

#include <ironbeepp/abi_compatibility.hpp>
#include <ironbeepp/common_semantics.hpp>
#include <ironbeepp/exception.hpp>
#include <ironbeepp/memory_manager.hpp>
#include <ironbeepp/throw.hpp>

#include <ironbee/list.h>

#include <boost/type_traits/is_convertible.hpp>
#include <boost/type_traits/is_same.hpp>
#include <boost/type_traits/remove_const.hpp>
#ifdef __clang__
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wdelete-non-virtual-dtor"
#if __has_warning("-Wunused-local-typedef")
#pragma clang diagnostic ignored "-Wunused-local-typedef"
#endif
#endif
#include <boost/utility.hpp>
#include <boost/iterator/iterator_facade.hpp>
#include <boost/iterator/iterator_adaptor.hpp>
#ifdef __clang__
#pragma clang diagnostic pop
#endif
#include <boost/utility/enable_if.hpp>

#include <ostream>

namespace IronBee {

/// @cond Internal
namespace Internal {

/**
 * Iterate through an ib_list_t, casting values to pointers.
 *
 * This template implements non-mutable bidirectional iterators for ib_list_t,
 * where the values are cast to a pointer type, @a T, via reinterpret_cast
 * (contrast to list_const_iterator).
 *
 * It is generated by List and ConstList when their value type is a pointer.
 *
 * Note that the reference type for this iterator is @a T not @c const @a T&.
 *
 * @sa list_const_iterator
 * @sa List
 * @sa ConstList
 *
 * @tparam T Value to cast @c void* list value to.
 **/
template <typename T>
class pointer_list_const_iterator :
    public boost::iterator_facade<
        pointer_list_const_iterator<T>,
        T,
        boost::bidirectional_traversal_tag,
        T
    >
{
public:
    //! Construct from an ib_list_t and ib_list_node_t.
    pointer_list_const_iterator(const ib_list_t* l, const ib_list_node_t* n) :
        m_list(l),
        m_node(n),
        m_before_the_beginning(false),
        m_past_the_end(false)
    {
        // nop
    }

    //! Default constructor; all operations except assignment undefined.
    pointer_list_const_iterator() :
        m_list(NULL),
        m_node(NULL),
        m_before_the_beginning(false),
        m_past_the_end(false)
    {
        //
    }

    //! Provide underlying ib_list_node_t.
    ib_list_node_t* node() const
    {
        return m_node;
    }

private:
    friend class boost::iterator_core_access;

    //! Increment iterator.
    void increment()
    {
        if (! m_past_the_end) {
            if (m_before_the_beginning) {
                m_node = ib_list_first_const(m_list);
                m_before_the_beginning = false;
            }
            else if (m_node->next) {
                m_node = m_node->next;
            }
            else {
                m_node = NULL;
                m_past_the_end = true;
            }
        }
    }

    //! Decrement iterator.
    void decrement()
    {
        if (! m_before_the_beginning) {
            if (m_past_the_end) {
                m_node = ib_list_last_const(m_list);
                m_past_the_end = false;
            }
            else if (m_node->prev) {
                m_node = m_node->prev;
            }
            else {
                m_node = NULL;
                m_before_the_beginning = true;
            }
        }
    }

    //! Compare iterators.
    bool equal(
        const pointer_list_const_iterator& other
    ) const
    {
        return
            (m_node == other.m_node) &&
            (m_list == other.m_list) &&
            (m_before_the_beginning == other.m_before_the_beginning) &&
            (m_past_the_end == other.m_past_the_end)
            ;
    }

    //! Dereference iterator.  Note return of copy.
    T dereference() const
    {
        return reinterpret_cast<T>(m_node->data);
    }

    const ib_list_t* m_list;
    const ib_list_node_t* m_node;
    bool m_before_the_beginning;
    bool m_past_the_end;
};

/**
 * Iterate through an ib_list_t, casting values to IronBee++ objects.
 *
 * This template implements non-mutable bidirectional iterators for ib_list_t,
 * where the values are converted to IronBee++ objects.  Recall that IronBee++
 * objects behave much like pointers.
 *
 * It is generated by List and ConstList when their value type is not a
 * pointer.
 *
 * Note that the reference type for this iterator is @a T not @c const @a T&.
 *
 * @sa pointer_list_const_iterator
 * @sa List
 * @sa ConstList
 *
 * @remark This template is adapted from pointer_list_iterator<T::ib_type>.
 *
 * @tparam T Value to convert list value to.  Must define @c ib_type member
 *           typedef and a constructor from @c ib_type.
 **/
template <typename T>
class list_const_iterator :
    public boost::iterator_adaptor<
        list_const_iterator<T>,
        pointer_list_const_iterator<typename T::ib_type>,
        T,
        boost::bidirectional_traversal_tag,
        T // Note: Copy not reference.
    >
{
public:
    //! Default constructor; all operations except assignment undefined.
    list_const_iterator()
    {
        // nop
    }

    //! Construct from ib_list_t and ib_list_node_t.
    list_const_iterator(
        const ib_list_t *l,
        const ib_list_node_t* n
    )  :
        list_const_iterator::iterator_adaptor_(
            pointer_list_const_iterator<typename T::ib_type>(l, n)
        )
    {
        // nop
    }

    //! Copy constructor.
    list_const_iterator(
        const list_const_iterator& other
    ) :
        list_const_iterator::iterator_adaptor_(other.base())
    {
        // nop
    }

    //! Provide underlying ib_list_node_t.
    ib_list_node_t* node() const
    {
        return this->base().node();
    }

    //! Operator-> support.
    T* operator->() const
    {
        static T m_dummy;
        m_dummy = T(*this->base());
        return &m_dummy;
    }

private:
    friend class boost::iterator_core_access;

    //! Dereference.  Note returns copy not reference.
    T dereference() const
    {
        return T(*this->base());
    }
};

/**
 * Metafunction to calculate appropriate iterator type.
 *
 * If @a T is a pointer then pointer_list_const_iterator is used, otherwise
 * list_const_iterator is used.
 *
 * @tparam T Desired value type of iterator.
 **/
template <typename T>
struct make_list_const_iterator
{
    typedef list_const_iterator<T> type;
};

//! Overload of previous to make it work for pointers.
template <typename Base>
struct make_list_const_iterator<Base*>
{
    typedef pointer_list_const_iterator<Base*> type;
};

/**
 * Converts pointers to themselves and IronBee objects to their ib().
 **/
template <typename Base>
void* value_as_void(Base* v)
{
    return reinterpret_cast<void*>(
        const_cast<typename boost::remove_const<Base>::type*>(v)
    );
}
//! Overload of previous.
template <typename T>
void* value_as_void(T v)
{
    return value_as_void(v.ib());
}

} // Internal
/// @endcond

template <typename T>
class ConstList;

template <typename T>
class List;

/**
 * Metafunction to determine if @a T is a ConstList or List.
 *
 * Inherits from true_type if @a T is a ConstList or List and false_type
 * otherwise.
 *
 * @tparam T Type to test.
 **/
template <typename T>
struct is_list : public boost::false_type {};
//! Implementation detail of is_list.
template <typename U>
struct is_list<ConstList<U> > : public boost::true_type {};
//! Implementation detail of is_list.
template <typename U>
struct is_list<List<U> > : public boost::true_type {};

/**
 * Const List; equivalent to a const pointer to ib_list_t.
 *
 * Provides operators ==, !=, <, >, <=, >= and evaluation as a boolean for
 * singularity via CommonSemantics.
 *
 * See List for discussion of lists.
 *
 * @tparam T Value type for list.
 *
 * @sa List
 * @sa ironbeepp
 * @sa ib_list_t
 * @nosubgrouping
 **/
template <typename T>
class ConstList :
    public CommonSemantics<ConstList<T> >
{
public:
    //! C Type.
    typedef const ib_list_t* ib_type;

    /**
     * Construct singular ConstList.
     *
     * All behavior of a singular ConstList is undefined except for
     * assignment, copying, comparison, and evaluate-as-bool.
     **/
    ConstList() :
        m_ib(NULL)
    {
        // nop
    }

    /**
     * @name C Interoperability
     * Methods to access underlying C types.
     **/
    ///@{

    //! const ib_list_t accessor.
    // Intentionally inlined.
    ib_type ib() const
    {
        return m_ib;
    }

    //! Construct List from ib_list_t.
    explicit
    ConstList(ib_type ib_list) :
        m_ib(ib_list)
    {
        // nop
    }

    ///@}

    /**
     * @name STL types.
     *
     * These typedefs provide useful information and compatibility with STL
     * oriented code.
     *
     * Note that iterator and const_iterator are identical (similar to
     * std::set) and that reference is the same as value_type (i.e., iterators
     * dereference to copy).
     *
     * In addition to the usual iterator operations, all iterators provide a
     * node() method that returns the underlying @c ib_list_node_t* or NULL
     * for iterators that do not refer to actual list nodes, e.g., end().
     **/
    ///@{
    //! Iterator; bidirectional input iterator.
    typedef typename Internal::make_list_const_iterator<T>::type iterator;
    //! Const iterator; same as iterator.
    typedef iterator const_iterator;
    //! Reference; same as value_type.
    typedef typename iterator::reference reference;
    //! Const reference; same as reference, i.e., value_type.
    typedef reference const_reference;
    //! Size type.
    typedef size_t size_type;
    //! Different type.
    typedef typename iterator::difference_type difference_type;
    //! Value type, i.e., @a T.
    typedef T value_type;
    //! Reverse iterator; bidirectional input iterator.
    typedef std::reverse_iterator<iterator> reverse_iterator;
    //! Const reverse iterator; same as reverse_iterator.
    typedef reverse_iterator const_reverse_iterator;
    ///@}

    //! Iterator to beginning of list.
    iterator begin() const
    {
        return iterator(ib(), ib_list_first_const(ib()));
    }

    //! Iterator just past end of list.
    iterator end() const
    {
        if (ib_list_elements(ib()) == 0) {
            return begin();
        }
        else {
            return boost::next(iterator(ib(), ib_list_last_const(ib())));
        }
    }

    //! Reverse iterator at last element of list.
    reverse_iterator rbegin() const
    {
        return reverse_iterator(end());
    }

    //! Reverse iterator just past beginning of list.
    reverse_iterator rend() const
    {
        return reverse_iterator(begin());
    }

    //! True iff list is empty.
    bool empty() const
    {
        return ! ib_list_first_const(ib());
    }

    //! Number of elements in list. O(1)
    size_type size() const
    {
        return ib_list_elements(ib());
    }

    /**
     * Front element of list.
     *
     * @return Front element of list.
     * @throw enoent if list is empty.
     **/
    T front() const
    {
        if (empty()) {
            BOOST_THROW_EXCEPTION(
              enoent() << errinfo_what(
                "Trying to fetch front of empty list."
              )
            );

        }
        return *begin();
    }

    /**
     * Back element of list.
     *
     * @return  Back element of list.
     * @throw enoent if list is empty.
     **/
    T back() const
    {
        if (empty()) {
            BOOST_THROW_EXCEPTION(
              enoent() << errinfo_what(
                "Trying to fetch back of empty list."
              )
            );

        }
        return *rbegin();
    }

    //! Memory manager used by list.
    MemoryManager memory_manager() const
    {
        return ib()->mm;
    }

private:
    ib_type m_ib;
};

/**
 * List; equivalent to a pointer to ib_list_t.
 *
 * Lists can be treated as ConstLists.  See @ref ironbeepp for
 * details on IronBee++ object semantics.
 *
 * IronBee lists are lists of generic pointers (@c void*).  This template
 * provides an interface to an IronBee list that assumes all values are the
 * same actual type, @a T.
 *
 * Only a subset of the C API operations are provided.  Additional operations
 * may be added in the future as needed.  Of that subset, many operations are
 * renamed.  In general, this template and ConstList attempt to provide a
 * std::list like interface rather than the ib_list_t interface.
 *
 * @sa ironbeepp
 * @sa ib_list_t
 * @sa ConstList
 * @nosubgrouping
 **/
template <typename T>
class List :
    public ConstList<T>
{
public:
    typedef ib_list_t* ib_type;

    /**
     * Remove the constness of a ConstList
     *
     * @warning This is as dangerous as a @c const_cast, use carefully.
     *
     * @param[in] list ConstList to remove const from.
     * @returns List pointing to same underlying list as @a list.
     **/
    static List remove_const(ConstList<T> list)
    {
        return List(const_cast<ib_type>(list.ib()));
    }

    /**
     * Construct singular List.
     *
     * All behavior of a singular List is undefined except for
     * assignment, copying, comparison, and evaluate-as-bool.
     **/
    List() :
        m_ib(NULL)
    {
        // nop
    }

    /**
     * Create new list.
     *
     * Creates a new empty list using @a memory_manager for memory.
     *
     * @param[in] memory_manager Memory manager to use.
     * @return Empty List.
     **/
    static List create(MemoryManager memory_manager)
    {
        ib_list_t* ib_list;
        throw_if_error(ib_list_create(&ib_list, memory_manager.ib()));
        return List(ib_list);
    }

    /**
     * @name C Interoperability
     * Methods to access underlying C types.
     **/
    ///@{

    //! ib_list_t accessor.
    ib_type ib() const
    {
        return m_ib;
    }

    //! Construct List from ib_list_t.
    explicit
    List(ib_type ib_list) :
        ConstList<T>(ib_list),
        m_ib(ib_list)
    {
        // nop
    }

    ///@}

    /**
     * Push @a value to back of list.
     *
     * @param[in] value Value to push to back of list.
     **/
    void push_back(T value) const
    {
        throw_if_error(
            ib_list_push(m_ib, Internal::value_as_void(value))
        );
    }

    /**
     * Push @a value to front of list.
     *
     * @param[in] value Value to push to back of list.
     **/
    void push_front(T value) const
    {
        throw_if_error(
            ib_list_enqueue(m_ib, Internal::value_as_void(value))
        );
    }

    //! Pop last element off list.
    void pop_back() const
    {
        throw_if_error(ib_list_pop(m_ib, NULL));
    }

    //! Pop first element off list.
    void pop_front() const
    {
        throw_if_error(ib_list_shift(m_ib, NULL));
    }

    //! Clear list.
    void clear() const
    {
        ib_list_clear(m_ib);
    }

private:
    ib_type m_ib;
};

} // IronBee

#endif

max_issues_repo_name: ErikHendriks/ironbee

max_forks_repo_name: ErikHendriks/ironbee


text:
//==================================================================================================
/**
  Copyright 2017 NumScale SAS

  Distributed under the Boost Software License, Version 1.0.
  (See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
**/
//==================================================================================================
#ifndef BOOST_SIMD_ARCH_COMMON_SCALAR_FUNCTION_FMASUBADD_HPP_INCLUDED
#define BOOST_SIMD_ARCH_COMMON_SCALAR_FUNCTION_FMASUBADD_HPP_INCLUDED

#include <boost/config.hpp>
#include <boost/simd/function/fms.hpp>

namespace boost { namespace simd { namespace ext
{
  namespace bd = boost::dispatch;

  BOOST_DISPATCH_OVERLOAD ( fmasubadd_
                          , (typename T)
                          , bd::cpu_
                          , bd::scalar_<bd::unspecified_<T>>
                          , bd::scalar_<bd::unspecified_<T>>
                          , bd::scalar_<bd::unspecified_<T>>
                          )
  {
    BOOST_FORCEINLINE T operator()(T a, T b, T c) const BOOST_NOEXCEPT
    {
      return fms(a, b, c);
    }
  };
} } }

#endif

max_stars_repo_name: SylvainCorlay/pythran

max_issues_repo_name: SylvainCorlay/pythran

max_forks_repo_name: SylvainCorlay/pythran


text:
#include <CGAL/Surface_mesh.h>
#include <CGAL/boost/graph/Seam_mesh.h>
#include <CGAL/Simple_cartesian.h>

#include <boost/graph/graph_concepts.hpp>
#include <CGAL/boost/graph/graph_concepts.h>

typedef CGAL::Simple_cartesian<double> K;
typedef CGAL::Surface_mesh<K::Point_3> Mesh;
typedef boost::graph_traits<Mesh>::vertex_descriptor         SM_vertex_descriptor;
typedef boost::graph_traits<Mesh>::halfedge_descriptor       SM_halfedge_descriptor;
typedef boost::graph_traits<Mesh>::edge_descriptor           SM_edge_descriptor;
typedef boost::graph_traits<Mesh>::face_descriptor           SM_face_descriptor;

typedef Mesh::Property_map<SM_edge_descriptor, bool>            Seam_edge_pmap;
typedef Mesh::Property_map<SM_vertex_descriptor, bool>          Seam_vertex_pmap;
typedef CGAL::Seam_mesh<Mesh, Seam_edge_pmap, Seam_vertex_pmap> Seam_mesh;

typedef boost::graph_traits< Seam_mesh > Traits;
typedef Traits::edge_descriptor edge_descriptor;
typedef Traits::halfedge_descriptor halfedge_descriptor;
typedef Traits::vertex_descriptor vertex_descriptor;
typedef Traits::face_descriptor face_descriptor;

void concept_check_seam_surface_mesh()
{
  boost::function_requires< boost::GraphConcept<Seam_mesh> >();
  boost::function_requires< boost::VertexListGraphConcept<Seam_mesh> >();
  boost::function_requires< boost::EdgeListGraphConcept<Seam_mesh> >();
  boost::function_requires< boost::IncidenceGraphConcept<Seam_mesh> >();
  boost::function_requires< boost::AdjacencyMatrixConcept<Seam_mesh> >();
  boost::function_requires< boost::BidirectionalGraphConcept<Seam_mesh> >();

  boost::function_requires< CGAL::HalfedgeGraphConcept<Seam_mesh> >();
  boost::function_requires< CGAL::HalfedgeListGraphConcept<Seam_mesh> >();
  boost::function_requires< CGAL::FaceGraphConcept<Seam_mesh> >();
  boost::function_requires< CGAL::FaceListGraphConcept<Seam_mesh> >();

  // null
  boost::graph_traits<Seam_mesh>::null_vertex();
  boost::graph_traits<Seam_mesh>::null_halfedge();
  boost::graph_traits<Seam_mesh>::null_face();
}

int main()
{
  concept_check_seam_surface_mesh();
  return 0;
}

max_stars_repo_name: ffteja/cgal

max_issues_repo_name: ffteja/cgal

max_forks_repo_name: ffteja/cgal