text:
// Copyright (c) 2016 Bitcoin Unlimited Developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

// All global variables that have construction/destruction dependencies
// must be placed in this file so that the ctor/dtor order is correct.

// Independent global variables may be placed here for organizational
// purposes.

#include "chain.h"
#include "clientversion.h"
#include "chainparams.h"
#include "miner.h"
#include "consensus/consensus.h"
#include "consensus/params.h"
#include "consensus/validation.h"
#include "leakybucket.h"
#include "main.h"
#include "net.h"
#include "policy/policy.h"
#include "primitives/block.h"
#include "parallel.h"
#include "rpc/server.h"
#include "thinblock.h"
#include "timedata.h"
#include "tinyformat.h"
#include "txmempool.h"
#include "unlimited.h"
#include "utilstrencodings.h"
#include "ui_interface.h"
#include "util.h"
#include "validationinterface.h"
#include "version.h"
#include "stat.h"
#include "tweak.h"
#include "addrman.h"

#include <boost/foreach.hpp>
#include <boost/lexical_cast.hpp>
#include <iomanip>
#include <boost/thread.hpp>
#include <inttypes.h>
#include <queue>

using namespace std;

#ifdef DEBUG_LOCKORDER
boost::mutex dd_mutex;
std::map<std::pair<void*, void*>, LockStack> lockorders;
boost::thread_specific_ptr<LockStack> lockstack;
#endif

// main.cpp CriticalSections:
CCriticalSection cs_LastBlockFile;
CCriticalSection cs_nBlockSequenceId;

CCriticalSection cs_nTimeOffset;
int64_t nTimeOffset = 0;

CCriticalSection cs_rpcWarmup;

CCriticalSection cs_main;
BlockMap mapBlockIndex;
CChain chainActive;
CWaitableCriticalSection csBestBlock;
CConditionVariable cvBlockChange;

proxyType proxyInfo[NET_MAX];
proxyType nameProxy;
CCriticalSection cs_proxyInfos;

set<uint256> setPreVerifiedTxHash;
set<uint256> setUnVerifiedOrphanTxHash;
CCriticalSection cs_xval;
CCriticalSection cs_vNodes;
CCriticalSection cs_mapLocalHost;
map<CNetAddr, LocalServiceInfo> mapLocalHost;
std::vector<CSubNet> CNode::vWhitelistedRange;
CCriticalSection CNode::cs_vWhitelistedRange;
CCriticalSection CNode::cs_setBanned;
uint64_t CNode::nTotalBytesRecv = 0;
uint64_t CNode::nTotalBytesSent = 0;
CCriticalSection CNode::cs_totalBytesRecv;
CCriticalSection CNode::cs_totalBytesSent;

// critical sections from net.cpp
CCriticalSection cs_setservAddNodeAddresses;
CCriticalSection cs_vAddedNodes;
CCriticalSection cs_vUseDNSSeeds;
CCriticalSection cs_nLastNodeId;
CCriticalSection cs_mapInboundConnectionTracker;
CCriticalSection cs_vOneShots;

CCriticalSection cs_statMap;

//semaphore for parallel validation threads
CCriticalSection cs_semPV;
CSemaphore *semPV;

deque<string> vOneShots;
std::map<CNetAddr, ConnectionHistory> mapInboundConnectionTracker;
vector<std::string> vUseDNSSeeds;
vector<std::string> vAddedNodes;
set<CNetAddr> setservAddNodeAddresses;

uint64_t maxGeneratedBlock = DEFAULT_MAX_GENERATED_BLOCK_SIZE;
unsigned int excessiveBlockSize = DEFAULT_EXCESSIVE_BLOCK_SIZE;
unsigned int excessiveAcceptDepth = DEFAULT_EXCESSIVE_ACCEPT_DEPTH;
unsigned int maxMessageSizeMultiplier = DEFAULT_MAX_MESSAGE_SIZE_MULTIPLIER;
int nMaxOutConnections = DEFAULT_MAX_OUTBOUND_CONNECTIONS;

uint32_t blockVersion = 0;  // Overrides the mined block version if non-zero

std::vector<std::string> BUComments = std::vector<std::string>();
std::string minerComment;

// Variables for traffic shaping
/** Default value for the maximum amount of data that can be received in a burst */
const int64_t DEFAULT_MAX_RECV_BURST = std::numeric_limits<long long>::max();
/** Default value for the maximum amount of data that can be sent in a burst */
const int64_t DEFAULT_MAX_SEND_BURST = std::numeric_limits<long long>::max();
/** Default value for the average amount of data received per second */
const int64_t DEFAULT_AVE_RECV = std::numeric_limits<long long>::max();
/** Default value for the average amount of data sent per second */
const int64_t DEFAULT_AVE_SEND = std::numeric_limits<long long>::max();
CLeakyBucket receiveShaper(DEFAULT_MAX_RECV_BURST, DEFAULT_AVE_RECV);
CLeakyBucket sendShaper(DEFAULT_MAX_SEND_BURST, DEFAULT_AVE_SEND);
boost::chrono::steady_clock CLeakyBucket::clock;

// Variables for statistics tracking, must be before the "requester" singleton instantiation
const char* sampleNames[] = { "sec10", "min5", "hourly", "daily","monthly"};
int operateSampleCount[] = { 30,       12,   24,  30 };
int interruptIntervals[] = { 30,       30*12,   30*12*24,   30*12*24*30 };

CTxMemPool mempool(::minRelayTxFee);

boost::posix_time::milliseconds statMinInterval(10000);
boost::asio::io_service stat_io_service;

CStatMap statistics;
CTweakMap tweaks;

map<CInv, CDataStream> mapRelay;
deque<pair<int64_t, CInv> > vRelayExpiration;
CCriticalSection cs_mapRelay;
limitedmap<uint256, int64_t> mapAlreadyAskedFor(MAX_INV_SZ);

vector<CNode*> vNodes;
list<CNode*> vNodesDisconnected;
CSemaphore*  semOutbound = NULL;
CSemaphore*  semOutboundAddNode = NULL; // BU: separate semaphore for -addnodes
CNodeSignals g_signals;
CAddrMan addrman;

// BU: change locking of orphan map from using cs_main to cs_orphancache.  There is too much dependance on cs_main locks which
//     are generally too broad in scope.
CCriticalSection cs_orphancache;
map<uint256, COrphanTx> mapOrphanTransactions GUARDED_BY(cs_orphancache);
map<uint256, set<uint256> > mapOrphanTransactionsByPrev GUARDED_BY(cs_orphancache);

CTweakRef<unsigned int> ebTweak("net.excessiveBlock","Excessive block size in bytes", &excessiveBlockSize,&ExcessiveBlockValidator);
CTweak<uint64_t> blockSigopsPerMb("net.excessiveSigopsPerMb","Excessive effort per block, denoted in cost (# inputs * txsize) per MB",BLOCKSTREAM_CORE_MAX_BLOCK_SIGOPS);
CTweak<uint64_t> blockMiningSigopsPerMb("mining.excessiveSigopsPerMb","Excessive effort per block, denoted in cost (# inputs * txsize) per MB",BLOCKSTREAM_CORE_MAX_BLOCK_SIGOPS);
CTweak<uint64_t> coinbaseReserve("mining.coinbaseReserve","How much space to reserve for the coinbase transaction, in bytes",DEFAULT_COINBASE_RESERVE_SIZE);
CTweakRef<std::string> miningCommentTweak("mining.comment","Include text in a block's coinbase.",&minerComment);
CTweakRef<uint64_t> miningBlockSize("mining.blockSize","Maximum block size in bytes.  The maximum block size returned from 'getblocktemplate' will be this value minus mining.coinbaseReserve.",&maxGeneratedBlock,&MiningBlockSizeValidator);

CTweak<unsigned int> maxTxSize("net.excessiveTx","Largest transaction size in bytes", DEFAULT_LARGEST_TRANSACTION);
CTweakRef<unsigned int> eadTweak("net.excessiveAcceptDepth","Excessive block chain acceptance depth in blocks", &excessiveAcceptDepth);
CTweakRef<int> maxOutConnectionsTweak("net.maxOutboundConnections","Maximum number of outbound connections", &nMaxOutConnections,&OutboundConnectionValidator);
CTweakRef<int> maxConnectionsTweak("net.maxConnections","Maximum number of connections connections",&nMaxConnections);
CTweakRef<unsigned int> triTweak("net.txRetryInterval","How long to wait in microseconds before requesting a transaction from another source", &MIN_TX_REQUEST_RETRY_INTERVAL);  // When should I request a tx from someone else (in microseconds). cmdline/bitcoin.conf: -txretryinterval
CTweakRef<unsigned int> briTweak("net.blockRetryInterval","How long to wait in microseconds before requesting a block from another source", &MIN_BLK_REQUEST_RETRY_INTERVAL); // When should I request a block from someone else (in microseconds). cmdline/bitcoin.conf: -blkretryinterval

CTweakRef<std::string> subverOverrideTweak("net.subversionOverride","If set, this field will override the normal subversion field.  This is useful if you need to hide your node.",&subverOverride,&SubverValidator);

CTweak<CAmount> maxTxFee("wallet.maxTxFee","Maximum total fees to use in a single wallet transaction or raw transaction; setting this too low may abort large transactions.",DEFAULT_TRANSACTION_MAXFEE);

/** Number of blocks that can be requested at any given time from a single peer. */
CTweak<unsigned int> maxBlocksInTransitPerPeer("net.maxBlocksInTransitPerPeer","Number of blocks that can be requested at any given time from a single peer. 0 means use algorithm.",0);
/** Size of the "block download window": how far ahead of our current height do we fetch?
 *  Larger windows tolerate larger download speed differences between peer, but increase the potential
 *  degree of disordering of blocks on disk (which make reindexing and in the future perhaps pruning
 *  harder). We'll probably want to make this a per-peer adaptive value at some point. */
CTweak<unsigned int> blockDownloadWindow("net.blockDownloadWindow","How far ahead of our current height do we fetch? 0 means use algorithm.",0);

/** This is the initial size of CFileBuffer's RAM buffer during reindex.  A
larger size will result in a tiny bit better performance if blocks are that
size.
The real purpose of this parameter is to exhaustively test dynamic buffer resizes
during reindexing by allowing the size to be set to low and random values.
*/
CTweak<uint64_t> reindexTypicalBlockSize("reindex.typicalBlockSize","Set larger than the typical block size.  The block data file's RAM buffer will initally be 2x this size.",TYPICAL_BLOCK_SIZE);

/** This is the initial size of CFileBuffer's RAM buffer during reindex.  A
larger size will result in a tiny bit better performance if blocks are that
size.
The real purpose of this parameter is to exhaustively test dynamic buffer resizes
during reindexing by allowing the size to be set to low and random values.
*/
CTweak<uint64_t> checkScriptDays("blockchain.checkScriptDays","The number of days in the past we check scripts during initial block download.",DEFAULT_CHECKPOINT_DAYS);

CRequestManager requester;  // after the maps nodes and tweaks

// Parallel Validation Variables
CParallelValidation PV;  // Singleton class
CAllScriptCheckQueues allScriptCheckQueues; // Singleton class

CStatHistory<unsigned int> txAdded; //"memPool/txAdded");
CStatHistory<uint64_t, MinValMax<uint64_t> > poolSize; // "memPool/size",STAT_OP_AVE);
CStatHistory<uint64_t > recvAmt;
CStatHistory<uint64_t > sendAmt;
CStatHistory<uint64_t> nTxValidationTime("txValidationTime", STAT_OP_MAX | STAT_INDIVIDUAL);
CStatHistory<uint64_t> nBlockValidationTime("blockValidationTime", STAT_OP_MAX | STAT_INDIVIDUAL);
CCriticalSection cs_blockvalidationtime;

CThinBlockData thindata; // Singleton class

// Expedited blocks
std::vector<CNode*> xpeditedBlk; // (256,(CNode*)NULL);    // Who requested expedited blocks from us
std::vector<CNode*> xpeditedBlkUp; //(256,(CNode*)NULL);  // Who we requested expedited blocks from
std::vector<CNode*> xpeditedTxn; // (256,(CNode*)NULL);

max_stars_repo_name: cddjr/BitcoinUnlimited

max_issues_repo_name: cddjr/BitcoinUnlimited

max_forks_repo_name: cddjr/BitcoinUnlimited


text:
// Boost.Geometry (aka GGL, Generic Geometry Library)

// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.

// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.

// Use, modification and distribution is subject to 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)

#ifndef GEOMETRY_TEST_GEOMETRY_TEST_COMMON_HPP
#define GEOMETRY_TEST_GEOMETRY_TEST_COMMON_HPP

#if defined(_MSC_VER)
// We deliberately mix float/double's  so turn off warnings
#pragma warning( disable : 4244 )
// For (new since Boost 1.40) warning in Boost.Test on putenv/posix
#pragma warning( disable : 4996 )

//#pragma warning( disable : 4305 )
#endif // defined(_MSC_VER)

#include <boost/config.hpp>

#if defined(BOOST_INTEL_CXX_VERSION)
#define BOOST_GEOMETRY_TEST_ONLY_ONE_TYPE
#endif

#include <boost/foreach.hpp>

// Include some always-included-for-testing files
#if ! defined(BOOST_GEOMETRY_NO_BOOST_TEST)

// Until Boost fixes it, silence warning issued by clang:
// warning: unused variable 'check_is_close' [-Wunused-variable]
#ifdef __clang__
# pragma clang diagnostic push
# pragma clang diagnostic ignored "-Wunused-variable"
#endif

# include <boost/test/floating_point_comparison.hpp>
# include <boost/test/included/test_exec_monitor.hpp>
//#  include <boost/test/included/prg_exec_monitor.hpp>
# include <boost/test/impl/execution_monitor.ipp>

#ifdef __clang__
# pragma clang diagnostic pop
#endif

#endif

#if defined(HAVE_TTMATH)
#  include <boost/geometry/extensions/contrib/ttmath_stub.hpp>
#endif

#if defined(HAVE_CLN) || defined(HAVE_GMP)
#  include <boost/numeric_adaptor/numeric_adaptor.hpp>
#endif

#if defined(HAVE_GMP)
#  include <boost/numeric_adaptor/gmp_value_type.hpp>
#endif
#if defined(HAVE_CLN)
#  include <boost/numeric_adaptor/cln_value_type.hpp>
#endif

template <typename T>
struct string_from_type {};

template <> struct string_from_type<void>
{ static std::string name() { return "v"; }  };

template <> struct string_from_type<float>
{ static std::string name() { return "f"; }  };

template <> struct string_from_type<double>
{ static std::string name() { return "d"; }  };

template <> struct string_from_type<long double>
{ static std::string name() { return "e"; }  };

#if defined(HAVE_TTMATH)
    template <> struct string_from_type<ttmath_big>
    { static std::string name() { return "t"; }  };
#endif

#if defined(BOOST_RATIONAL_HPP)
template <typename T> struct string_from_type<boost::rational<T> >
{ static std::string name() { return "r"; }  };
#endif

#if defined(HAVE_GMP)
    template <> struct string_from_type<boost::numeric_adaptor::gmp_value_type>
    { static std::string name() { return "g"; }  };
#endif

#if defined(HAVE_CLN)
    template <> struct string_from_type<boost::numeric_adaptor::cln_value_type>
    { static std::string name() { return "c"; }  };
#endif

template <typename CoordinateType, typename T1, typename T2>
inline T1 if_typed_tt(T1 value_tt, T2 value)
{
#if defined(HAVE_TTMATH)
    return boost::is_same<CoordinateType, ttmath_big>::type::value ? value_tt : value;
#else
    return value;
#endif
}

template <typename CoordinateType, typename Specified, typename T>
inline T if_typed(T value_typed, T value)
{
    return boost::is_same<CoordinateType, Specified>::value ? value_typed : value;
}

struct geographic_policy
{
    template <typename CoordinateType>
    static inline CoordinateType apply(CoordinateType const& value)
    {
        return value;
    }
};

struct mathematical_policy
{
    template <typename CoordinateType>
    static inline CoordinateType apply(CoordinateType const& value)
    {
        return 90 - value;
    }

};

// For all tests:
// - do NOT use "using namespace boost::geometry" to make clear what is Boost.Geometry
// - use bg:: as short alias
#include <boost/geometry/core/tag.hpp>
namespace bg = boost::geometry;

#endif // GEOMETRY_TEST_GEOMETRY_TEST_COMMON_HPP

ext: hpp


text:
/*
 * Copyright (C) 2012-2016 Open Source Robotics Foundation
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
*/

#include <boost/filesystem.hpp>
#include "gazebo/common/Assert.hh"
#include "gazebo/common/SystemPaths.hh"
#include "gazebo/msgs/msgs.hh"
#include "gazebo/transport/transport.hh"
#include "gazebo/test/ServerFixture.hh"

using namespace gazebo;
class StateLogTest : public ServerFixture
{
};

double g_pr2LGripperXStart = -1;
double g_pr2LGripperXEnd = -1;
int g_msgCount = 0;

/////////////////////////////////////////////////
// Pose callback. We are just getting one link from the pr2 for simplicity.
void onPoseInfo(ConstPose_VPtr &_msg)
{
  for (int i = 0; i < _msg->pose_size(); ++i)
  {
    if (_msg->pose(i).name() == "pr2::l_gripper_r_parallel_link")
    {
      if (g_pr2LGripperXStart < 0)
        g_pr2LGripperXStart = _msg->pose(i).position().x();

      g_pr2LGripperXEnd = _msg->pose(i).position().x();
    }
  }

  ++g_msgCount;
}

/////////////////////////////////////////////////
/// Record a log file
TEST(StateLogTest, PR2Record)
{
  common::SystemPaths *paths = common::SystemPaths::Instance();
  custom_exec(("gzserver -r --record_path " + paths->GetDefaultTestPath()
    + " --iters 1000 --seed 12345 worlds/pr2.world").c_str());

  boost::filesystem::path path = paths->GetDefaultTestPath() + "/state.log";
  EXPECT_TRUE(boost::filesystem::exists(path) != false);
}

/////////////////////////////////////////////////
// Playback a log file
TEST(StateLogTest, PR2PlaybackZipped)
{
  // Cleanup...not the best
  custom_exec("killall -9 gzserver");

  // Run playback
  common::SystemPaths *paths = common::SystemPaths::Instance();
  boost::thread *play = new boost::thread(boost::bind(&custom_exec,
    ("gzserver -u -p " + paths->GetDefaultTestPath() "/state.log").c_str()));

  // Setup transportation
  gazebo::transport::init();
  gazebo::transport::run();

  gazebo::transport::NodePtr node(new gazebo::transport::Node());
  node->Init();

  // Create a publisher to unpause gzserver
  gazebo::transport::PublisherPtr pub =
    node->Advertise<gazebo::msgs::WorldControl>(
        "/gazebo/default/world_control");
  pub->WaitForConnection();

  // Subscribe to pose info
  gazebo::transport::SubscriberPtr sub = node->Subscribe(
      "/gazebo/default/pose/info", &onPoseInfo);

  // Unpause gzserver
  gazebo::msgs::WorldControl msg;
  msg.set_pause(false);
  pub->Publish(msg);

  int i = 0;
  // Wait for messages to arrive
  while (g_msgCount < 120 && i < 100)
  {
    gzdbg << "Pose Msg Count = " << g_msgCount  << std::endl;
    gazebo::common::Time::MSleep(100);
    ++i;
  }

  // Kill gserver
  play->interrupt();
  delete play;

  // Cleanup...not the best
  custom_exec("killall -9 gzserver");

  gazebo::transport::fini();

  if (g_msgCount >= 120)
  {
    // Make sure the values are correct.
    EXPECT_NEAR(g_pr2LGripperXStart, 0.83, 0.05);
    EXPECT_NEAR(g_pr2LGripperXEnd, 0.76, 0.05);
  }
}

/////////////////////////////////////////////////
// Playback a log file
TEST(StateLogTest, PR2PlaybackTxt)
{
  // Cleanup...not the best
  custom_exec("killall -9 gzserver");

  g_pr2LGripperXStart = -1;
  g_pr2LGripperXEnd = -1;
  g_msgCount = 0;

  // Convert the zipped state to txt and set a Hz filter.
  common::SystemPaths *paths = common::SystemPaths::Instance();
  custom_exec(("gzlog echo " + paths->GetDefaultTestPath() + "/state.log" +
    " -z 30 > " + paths->GetDefaultTestPath() + "/state_txt.log").c_str());

  // Run playback
  boost::thread *play = new boost::thread(boost::bind(&custom_exec,
    ("gzserver -u -p " + paths->GetDefaultTestPath() "/state.log").c_str()));

  // Setup transportation
  gazebo::transport::init();
  gazebo::transport::run();

  gazebo::transport::NodePtr node(new gazebo::transport::Node());
  node->Init();

  // Create a publisher to unpause gzserver
  gazebo::transport::PublisherPtr pub =
    node->Advertise<gazebo::msgs::WorldControl>(
        "/gazebo/default/world_control");
  pub->WaitForConnection();

  // Subscribe to pose info
  gazebo::transport::SubscriberPtr sub = node->Subscribe(
      "/gazebo/default/pose/info", &onPoseInfo);

  // Unpause gzserver
  gazebo::msgs::WorldControl msg;
  msg.set_pause(false);
  pub->Publish(msg);

  int i = 0;
  // Wait for messages to arrive
  while (g_msgCount < 120 && i < 100)
  {
    gzdbg << "Pose Msg Count = " << g_msgCount  << std::endl;
    gazebo::common::Time::MSleep(100);
    ++i;
  }

  // Kill gserver
  play->interrupt();
  delete play;

  // Cleanup...not the best
  custom_exec("killall -9 gzserver");

  gazebo::transport::fini();

  if (g_msgCount > 100)
  {
  // Make sure the values are correct.
  EXPECT_NEAR(g_pr2LGripperXStart, 0.83, 0.05);
  EXPECT_NEAR(g_pr2LGripperXEnd, 0.76, 0.05);
  }
}

/////////////////////////////////////////////////
int main(int argc, char **argv)
{
  // Cleanup test directory and create a new one.
  common::SystemPaths *paths = common::SystemPaths::Instance();
  boost::filesystem::remove_all(paths->GetDefaultTestPath());
  boost::filesystem::create_directories(paths->GetDefaultTestPath());

  ::testing::InitGoogleTest(&argc, argv);
  int result = RUN_ALL_TESTS();

  // Cleanup test directory.
  boost::filesystem::remove_all(paths->GetDefaultTestPath());

  return result;
}

ext: cc


text:
/***************************************************************************************************************************
*
* Author: bingo
* Email: 1554459957@qq.com
* Time: 2019.10.14
* Description: lidar collision v1.0
*
***************************************************************************************************************************/

//ROS 头文件
#include <ros/ros.h>
#include <Eigen/Eigen>

//topic 头文件
#include <iostream>
#include <std_msgs/Bool.h>
#include <geometry_msgs/Pose.h>
#include <sensor_msgs/LaserScan.h>
#include <geometry_msgs/PoseStamped.h>
#include <mavros_msgs/PositionTarget.h>

using namespace std;

#define RAD2DEG(x) ((x)*180./M_PI)
//--------------------------------------------输入--------------------------------------------------
sensor_msgs::LaserScan Laser;                                   //激光雷达点云数据
Eigen::Vector3d pos_drone;                                      //无人机当前位置 (来自fcu)
float target_x;                                                 //期望位置_x
float target_y;                                                 //期望位置_y
float target_z;                                                 //期望位置_z
float target_temp_x;
float target_temp_y;
//--------------------------------------------算法相关--------------------------------------------------
float p_xy;                                                     //追踪部分位置环P
float vel_track[2];                                             //追踪部分速度
//--------------------------------------------输出--------------------------------------------------
Eigen::Vector3d vel_sp_body;                                           //总速度
float vel_sp_max;                                               //总速度限幅
//>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>声 明 函 数<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
float satfunc(float data, float Max);
void printf();                                                                       //打印函数
void printf_param();                                                                 //打印各项参数以供检查
//>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>回 调 函 数<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
float barriar_threshols = 3; //设置判断是否为障碍物距离
float pi = 3.1415926;
typedef struct
{
	int amount; 				//障碍物数量
	float distan_min;			//据某个障碍物最短距离
	float direc_start;			//障碍物起始方向
	float distan_start;			//障碍物起始距离
	float direc_stop;			//障碍物结束方向
	float distan_stop;			//障碍物结束距离
	float size; 				//障碍物大小
	float frame_x;				//障碍物相当飞机的坐标
	float frame_y;
	float world_x;				//世界坐标系ENU
	float world_y;
	float distan_min_vert_range; //某个障碍物最短距离点据最短路经的垂直距离
	float distan_min_away_target;//某个障碍物据目标点的距离
}S_BARRIER;
int barrier_num = 0;
int barrier_obj = 0;
float uav2targetDistan;
S_BARRIER s_barrier[10];
void lidar_cb(const sensor_msgs::LaserScan::ConstPtr& scan)
{
    	Laser = *scan;
    	int count = 359;
	float distan_min_direc = 0;
	for(int i=0; i<= barrier_num; i++)
	{
		s_barrier[i].distan_min = 0;
 		s_barrier[i].direc_start = 0;
		s_barrier[i].direc_stop = 0;
 		s_barrier[i].distan_start = 0;
		s_barrier[i].distan_stop = 0;
		s_barrier[i].frame_x = 0;
		s_barrier[i].frame_y = 0;
		s_barrier[i].world_x = 0;
		s_barrier[i].world_y = 0;
		s_barrier[i].distan_min_vert_range = 0;
		s_barrier[i].size = 0;

	}
	barrier_num = 0;
	/*检测障碍物*/
    for(int temp = 0; temp <= count; temp++)
    {
		if(isinf(Laser.ranges[temp]))
		{

		}
		else if(Laser.ranges[temp] <= barriar_threshols)
		{
				barrier_num++;
				s_barrier[barrier_num].direc_start = temp;
				s_barrier[barrier_num].distan_min = Laser.ranges[temp];
				s_barrier[barrier_num].distan_start = Laser.ranges[temp];
				distan_min_direc = temp;
			while(1)
			{
				//cout << "Laser.ranges[temp] : " << Laser.ranges[temp] << endl;
				temp++;
				if(s_barrier[barrier_num].distan_min > Laser.ranges[temp])
				{
					s_barrier[barrier_num].distan_min = Laser.ranges[temp];
					distan_min_direc = temp;
					//cout << "s_barrier[barrier_num].distan_min : " << s_barrier[barrier_num].distan_min << endl;
				}
				if(Laser.ranges[temp] > barriar_threshols || temp >= 359)
				{
					s_barrier[barrier_num].direc_stop = temp;
					s_barrier[barrier_num].distan_stop = Laser.ranges[temp-1];
					//余弦定理
					s_barrier[barrier_num].size =  sqrt(s_barrier[barrier_num].distan_start*s_barrier[barrier_num].distan_start+s_barrier[barrier_num].distan_stop*s_barrier[barrier_num].distan_stop-2*s_barrier[barrier_num].distan_stop*s_barrier[barrier_num].distan_start*cos((s_barrier[barrier_num].direc_stop- s_barrier[barrier_num].direc_start)*pi/180));
					s_barrier[barrier_num].frame_x = -s_barrier[barrier_num].distan_min * cos(distan_min_direc/180*3.1415926);
					s_barrier[barrier_num].frame_y = -s_barrier[barrier_num].distan_min * sin(distan_min_direc/180*3.1415926);
					s_barrier[barrier_num].world_x = s_barrier[barrier_num].frame_x + pos_drone[0];
					s_barrier[barrier_num].world_y = s_barrier[barrier_num].frame_y + pos_drone[1];
					//点到直线距离公式
					float k = (pos_drone[1] - target_y)/(pos_drone[0] - target_x);
					s_barrier[barrier_num].distan_min_vert_range = (s_barrier[barrier_num].world_y-k*s_barrier[barrier_num].world_x+k*target_x-target_y)/sqrt(1+k*k);
					//勾股定理
					s_barrier[barrier_num].distan_min_away_target = sqrt((s_barrier[barrier_num].world_x-target_x)*(s_barrier[barrier_num].world_x-target_x)+(s_barrier[barrier_num].world_y-target_y)*(s_barrier[barrier_num].world_y-target_y));
					break;
				}
			}
		}
		else
		{

		}

    }
	/*避障策略*/
	if(barrier_num >0)
	{
		//cout << "barrier_num : " << barrier_num  <<endl;
		float barrier_distan_min = 1;
		int barrier_temp = 0;
		for(int temp=1;temp<=barrier_num;temp++)
		{
			//cout << "barrier_num : " << barrier_num  <<endl;
			uav2targetDistan = sqrt((target_x - pos_drone[0])*(target_x - pos_drone[0]) + (target_y - pos_drone[1])*(target_y - pos_drone[1]));//飞机与目标点之间的距离
			if(s_barrier[temp].distan_min_vert_range < 0.5 && s_barrier[temp].distan_min_vert_range > -0.5 && s_barrier[temp].distan_min_away_target < uav2targetDistan)//找到满足条件的障碍物点
			{
				// cout << "temp : " << temp <<endl;
				if(barrier_distan_min > s_barrier[temp].distan_min)//寻找离飞机最近的障碍物，前提要障碍物据飞机与目标点直线距离不小于1m,而且障碍物在飞机的前方。
				{
					barrier_distan_min = s_barrier[temp].distan_min;
					barrier_temp = temp;
   					cout << "barrier_temp : " << barrier_temp <<endl;
				}

			}

		}
		if(barrier_temp > 0)
		{
 			if (s_barrier[barrier_temp].distan_min_vert_range > 0)			//正负代表障碍物在uav到目标点的直线的哪一侧
			{
				target_temp_x =  s_barrier[barrier_temp].world_x+1/s_barrier[barrier_temp].distan_min;
				target_temp_y =  s_barrier[barrier_temp].world_y-1/s_barrier[barrier_temp].distan_min;
			}
			else
			{
				target_temp_x = s_barrier[barrier_temp].world_x-1/s_barrier[barrier_temp].distan_min;
				target_temp_y = s_barrier[barrier_temp].world_y+1/s_barrier[barrier_temp].distan_min;
			}
			vel_sp_body[0] = 1 * (target_temp_x - pos_drone[0]);
			vel_sp_body[1] = 1 * (target_temp_y - pos_drone[1]);
			cout << "target_temp_x : " << target_temp_x << " m "<<endl;
    			cout << "target_temp_y : " << target_temp_y << " m "<<endl;
		}
		else
		{
			vel_sp_body[0] = p_xy * (target_x - pos_drone[0]);
			vel_sp_body[1] = p_xy * (target_x - pos_drone[1]);
		}
	}
	else
	{
		vel_sp_body[0] = p_xy * (target_x - pos_drone[0]);
		vel_sp_body[1] = p_xy * (target_y - pos_drone[1]);
	}

	cout <<">>>>>>>>>>>>>>>>>>>>>>>>>>>>>s_barrier<<<<<<<<<<<<<<<<<<<<<<<<<<<<<" <<endl;
	if(barrier_num > 0)
	{
		for(int i=1;i<=barrier_num;i++)
		{
			cout << "s_barrier_number : " << i << endl;
			cout <<	"s_barrier_distan_min : " << s_barrier[i].distan_min << endl;
			cout <<	"s_barrier_direc_start : " << s_barrier[i].direc_start << endl;
			cout <<	"s_barrier_direc_stop: " << s_barrier[i].direc_stop << endl;
			cout <<	"s_barrier_distan_stop: " << s_barrier[i].distan_stop << endl;
			cout <<	"s_barrier_distan_start: " << s_barrier[i].distan_start << endl;
			cout <<	"s_barrier_size: " << s_barrier[i].size << endl;
			cout <<	"s_barrier_frame_x: " << s_barrier[i].frame_x << endl;
			cout <<	"s_barrier_frame_y: " << s_barrier[i].frame_y << endl;
			cout <<	"s_barrier_world_x: " << s_barrier[i].world_x << endl;
			cout <<	"s_barrier_world_y: " << s_barrier[i].world_y << endl;
			cout <<	"s_barrier_distan_min_vert_range: " << s_barrier[i].distan_min_vert_range << endl;
			cout <<	"s_barrier_distan_min_away_target: " << s_barrier[i].distan_min_away_target << endl;
		}
	}

}

void pos_cb(const geometry_msgs::PoseStamped::ConstPtr &msg)
{
    // Read the Drone Position from the Mavros Package [Frame: ENU]
    Eigen::Vector3d pos_drone_fcu_enu(msg->pose.position.x,msg->pose.position.y,msg->pose.position.z);

    pos_drone = pos_drone_fcu_enu;
}

//>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>主 函 数<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
int main(int argc, char **argv)
{
    ros::init(argc, argv, "collision_avoidance");
    ros::NodeHandle nh("~");
    float p_temp_xy;
    // 频率 [20Hz]
    ros::Rate rate(20.0);

    //【订阅】Lidar数据
    ros::Subscriber lidar_sub = nh.subscribe<sensor_msgs::LaserScan>("/laser/scan", 1000, lidar_cb);

    ros::Subscriber position_sub = nh.subscribe<geometry_msgs::PoseStamped>("/mavros/local_position/pose", 100, pos_cb);
    ros::Publisher setpoint_raw_local_pub = nh.advertise<mavros_msgs::PositionTarget>("/mavros/setpoint_raw/local", 10);

    //读取参数表中的参数
    nh.param<float>("target_x", target_x, 1.0);
    nh.param<float>("target_y", target_y, 1.0);

    nh.param<float>("p_xy", p_xy, 0.5);

    nh.param<float>("vel_sp_max", vel_sp_max, 0.0);

    //打印现实检查参数
    printf_param();
    int check_flag;

    vel_sp_body[0]= 0;
    vel_sp_body[1]= 0;
    //输出指令初始化
    int comid = 1;
//>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>Main Loop<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
    while(ros::ok())
    {

        ros::spinOnce();
       for (int i = 0; i < 2; i++)
	{
	    vel_sp_body[i] = satfunc(vel_sp_body[i],vel_sp_max);
	}
    mavros_msgs::PositionTarget pos_setpoint;

    pos_setpoint.type_mask = 0b100111000111;

    pos_setpoint.coordinate_frame = 1;

    pos_setpoint.velocity.x = vel_sp_body[0];
    pos_setpoint.velocity.y = vel_sp_body[1];
    pos_setpoint.velocity.z = 0;

//    pos_setpoint.yaw = 1.5;

    setpoint_raw_local_pub.publish(pos_setpoint);
     //   printf();
        rate.sleep();

    }

    return 0;

}

//饱和函数
float satfunc(float data, float Max)
{
    if(abs(data)>Max)
    {
        return ( data > 0 ) ? Max : -Max;
    }
    else
    {
        return data;
    }
}

void printf()
{

    cout <<  "uav2targetDistan :" << uav2targetDistan << "m" <<endl;
    cout << "vel_sp_x : " << vel_sp_body[0] << " [m/s] "<<endl;
    cout << "vel_sp_y : " << vel_sp_body[1] << " [m/s] "<<endl;

}

void printf_param()
{
    cout <<">>>>>>>>>>>>>>>>>>>>>>>>>>>>>> Parameter <<<<<<<<<<<<<<<<<<<<<<<<<<<" <<endl;
    cout << "target_x : "<< target_x << endl;
    cout << "target_y : "<< target_y << endl;

    cout << "p_xy : "<< p_xy << endl;

    cout << "vel_sp_max : "<< vel_sp_max << endl;

}

ext: cpp


text:
// Copyright (c) 2019 Graphcore Ltd. All rights reserved.
#define BOOST_TEST_MODULE sgd_mixed_mode_test_0

#include <algorithm>
#include <boost/test/unit_test.hpp>
#include <map>
#include <random>
#include <tuple>
#include <vector>

#define protected public
#include <filereader.hpp>
#include <popart/builder.hpp>
#include <popart/dataflow.hpp>
#include <popart/devicemanager.hpp>
#include <popart/inputshapeinfo.hpp>
#include <popart/ndarraywrapper.hpp>
#include <popart/op/identity.hpp>
#include <popart/op/ipucopy.hpp>
#include <popart/op/l1.hpp>
#include <popart/op/restore.hpp>
#include <popart/op/sgd0varupdate.hpp>
#include <popart/op/stash.hpp>
#include <popart/optimizer.hpp>
#include <popart/sgd.hpp>
#include <popart/tensorinfo.hpp>
#include <popart/tensornames.hpp>
#include <popart/testdevice.hpp>
#undef protected

#include <popart/session.hpp>

BOOST_AUTO_TEST_CASE(SgdMixedModeTest0) {

  using namespace popart;

  // names of 3 weights used in model
  std::string w0name = "__w0__";
  std::string w1name = "__w1__";
  std::string w2name = "__w2__";

  class Expectation {
  public:
    // after one run with SGD opt0, and one run with SGD opt1, what do we expect
    // the final value of the weight to be?
    float finalValue;

    // Given opt0 (and opt1) do we expect the computation to be done with
    // constant optimizer values?
    bool scaledLearningRateIsConst;
    bool weightDecayScaleFactorIsConst;
  };

  auto test = [w0name, w1name, w2name](
                  const SGD &opt0,       // initial Optimizer
                  const SGD &opt1,       // Optimizer to switch to
                  const Expectation &e0, // expectation for weight 0
                  const Expectation &e1, // expectation for weight 1
                  const Expectation &e2  // expectation for weight 2
              ) {
    // Model
    // ----
    //
    // loss = l1_loss((((input + w0) + w1) + w2))
    //
    // where input is small positive and w0, w1, w2 are large positive
    //

    auto builder = Builder::create();
    auto aiOnnx  = builder->aiOnnxOpset9();

    int64_t sampleDim = 1;
    int64_t batchSize = 1;
    int64_t stepSize  = 1;

    std::vector<int64_t> batchShape{batchSize, sampleDim};
    TensorInfo batchInfo{"FLOAT", batchShape};

    std::vector<int64_t> sampleShape{sampleDim};
    TensorInfo sampleInfo{"FLOAT", sampleShape};

    std::vector<int64_t> stepDataShape{stepSize, batchSize, sampleDim};
    TensorInfo stepDataInfo{"FLOAT", stepDataShape};

    auto input0 = builder->addInputTensor(batchInfo, "0tupni");

    WeightsIO weightsRead;

    std::vector<float> weight0(sampleDim, 100.0f);
    // read-back buffer for weight0
    std::vector<float> rb0(sampleDim, -777.0f);
    ConstVoidData cvd0({weight0.data(), sampleInfo});

    auto w0Id = builder->addInitializedInputTensor(cvd0, w0name);
    weightsRead.insert(w0Id, {rb0.data(), sampleInfo});

    std::vector<float> weight1(sampleDim, 200.0f);
    std::vector<float> rb1(sampleDim, -777.0f);
    ConstVoidData cvd1({weight1.data(), sampleInfo});
    auto w1Id = builder->addInitializedInputTensor(cvd1, w1name);
    weightsRead.insert(w1Id, {rb1.data(), sampleInfo});

    std::vector<float> weight2(sampleDim, 300.0f);
    std::vector<float> rb2(sampleDim, -777.0f);
    ConstVoidData cvd2({weight2.data(), sampleInfo});
    auto w2Id = builder->addInitializedInputTensor(cvd2, w2name);
    weightsRead.insert(w2Id, {rb2.data(), sampleInfo});

    auto add0 = aiOnnx.add({w0Id, input0});
    auto add1 = aiOnnx.add({w1Id, add0});
    auto add2 = aiOnnx.add({w2Id, add1});
    auto l1   = builder->aiGraphcoreOpset1().l1loss({add2}, 1.0);

    builder->addOutputTensor(add2);
    auto proto    = builder->getModelProto();
    auto dataFlow = DataFlow(stepSize);

    SessionOptions userOptions;

    auto device = createTestDevice(TEST_TARGET, 1);

    auto session = popart::TrainingSession::createFromOnnxModel(
        proto,
        dataFlow,
        l1,
        opt0, // construct with opt0, will switch to opt1 later
        device,
        InputShapeInfo(),
        SessionOptions(),
        popart::Patterns(PatternsLevel::Default));

    session->prepareDevice();
    std::vector<float> v_input_x(stepDataInfo.nelms(), 3.1415);

    popart::NDArrayWrapper<float> input_x_wrapper(v_input_x.data(),
                                                  stepDataInfo);

    std::map<popart::TensorId, popart::IArray &> inputs = {
        {input0, input_x_wrapper}};

    popart::StepIO stepio(inputs, {});

    session->weightsFromHost();

    // run 1 with opt0
    session->run(stepio);

    // run 2 with opt1
    session->updateOptimizerFromHost(&opt1);

    session->run(stepio);

    // read final weights back
    session->weightsToHost();
    session->readWeights(weightsRead);

    std::cout << "Values read-back from device for weights 0,1,2:" << std::endl;
    std::cout << rb0[0] << "  " << rb1[0] << "  " << rb2[0] << "." << std::endl;

    // All the SGD0VarUpdateOps, in no particular order
    std::vector<SGD0VarUpdateOp *> sgdOpsOOO;
    for (auto op :
         session->getIr().getOpSchedule({}, RequireOptimalSchedule::No)) {
      auto asSgd = dynamic_cast<SGD0VarUpdateOp *>(op);
      if (asSgd) {
        sgdOpsOOO.push_back(asSgd);
      }
    }
    BOOST_CHECK(sgdOpsOOO.size() == 3);

    std::vector<SGD0VarUpdateOp *> sgdOps = sgdOpsOOO;
    for (auto op : sgdOpsOOO) {
      auto id = op->inId(op->getVarToUpdateInIndex());
      if (id == w0name) {
        sgdOps[0] = op;
      } else if (id == w1name) {
        sgdOps[1] = op;
      } else if (id == w2name) {
        sgdOps[2] = op;
      } else {
        throw error("failed to determine input id in sgd test");
      }
    }

    // check that expected values are the same as read-back values
    BOOST_CHECK(e0.finalValue == rb0[0]);
    BOOST_CHECK(e1.finalValue == rb1[0]);
    BOOST_CHECK(e2.finalValue == rb2[0]);

    BOOST_CHECK(e0.scaledLearningRateIsConst == sgdOps[0]->initSlr0.isConst());
    BOOST_CHECK(e1.scaledLearningRateIsConst == sgdOps[1]->initSlr0.isConst());
    BOOST_CHECK(e2.scaledLearningRateIsConst == sgdOps[2]->initSlr0.isConst());

    BOOST_CHECK(e0.weightDecayScaleFactorIsConst ==
                sgdOps[0]->initWdsf0.isConst());
    BOOST_CHECK(e1.weightDecayScaleFactorIsConst ==
                sgdOps[1]->initWdsf0.isConst());
    BOOST_CHECK(e2.weightDecayScaleFactorIsConst ==
                sgdOps[2]->initWdsf0.isConst());
  };

  // Test case 1
  // ------------
  std::cout << "TEST CASE 1" << std::endl;
  OptimizerValue defaultWeightDecay{0, false};
  OptimizerValue defaultLearningRate{0.1, true};
  OptimizerValue lossScaling{10, true};

  std::map<std::string, std::pair<float, bool>> optParams;
  optParams.insert({"defaultWeightDecay", {0.0f, false}});
  optParams.insert({"defaultLearningRate", {0.1f, true}});
  optParams.insert({"lossScaling", {10.0f, true}});

  auto opt0 = SGD(optParams);
  opt0.insertSpecific(
      w1name, {{"learningRate", {0.2, false}}, {"weightDecay", {0.0f, true}}});

  // same as opt1, but increased learning rate for weight 1
  auto opt1 = SGD(optParams);

  opt1.insertSpecific(
      w1name, {{"learningRate", {0.5, false}}, {"weightDecay", {0, true}}});

  // weight 0 uses the global optimizer values
  Expectation e0({
      100 - 0.1 - 0.1, // initial value - (lr run 1) - (lr run 2)
      true,            // constant scaled learning rate
      false            // non-constant weight decay scale factor
  });

  // weight 1 uses local optimizer values
  Expectation e1({
      200 - 0.2 - 0.5, // initial - (lr 1) - (lr 2)
      false,           // non-constant scaled learning rate
      false // non-constant scaled weight decay - this is because of the
            // dependance on the learning rate, which is non-constant
  });

  Expectation e2({300 - 0.1 - 0.1, true, false});

  test(opt0, opt1, e0, e1, e2);

  // Test case 2
  // -----------
  // We confirm that a non-const lossScaling results in all learning rates being
  // non-const
  std::cout << "TEST CASE 2" << std::endl;

  opt0 = SGD({{"defaultLearningRate", {2, true}},
              {"defaultWeightDecay", {0, true}},
              {"lossScaling", {20, false}}});

  opt0.insertSpecific(
      w1name, {{"learningRate", {4.0, true}}, {"weightDecay", {0.125, true}}});

  opt1 = opt0;

  // weight 0 uses the global optimizer values
  e0 = {
      100 - 2.0 - 2.0,
      false, // scaled learning rate is not constant, becase loss scaling isn't
      true   // weight decay scaling factor is constant
  };

  // 0.125 * 4.0 = 0.5 (half-life of 1)
  // 200 * (1 - 0.5) - 4 = 96
  // 96  * (1 - 0.5) - 4 = 44
  //
  // weight 1 uses local optimizer values
  e1 = {44, false, true};

  e2 = {300 - 2.0 - 2.0, false, true};

  test(opt0, opt1, e0, e1, e2);
}


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

#include <cast_core/actors/RandomSampler.hpp>

#include <memory>

#include <yaml-cpp/yaml.h>

#include <bsoncxx/json.hpp>

#include <mongocxx/client.hpp>
#include <mongocxx/collection.hpp>
#include <mongocxx/database.hpp>

#include <boost/log/trivial.hpp>
#include <boost/throw_exception.hpp>

#include <gennylib/Cast.hpp>
#include <gennylib/MongoException.hpp>
#include <gennylib/context.hpp>

#include <value_generators/DocumentGenerator.hpp>

namespace genny::actor {

struct RandomSampler::PhaseConfig {
    std::vector<mongocxx::collection> collections;
    boost::random::uniform_int_distribution<> integerDistribution;
    /*
     * Two separate trackers as we want to be able to observe the impact
     * of the collection scanner on the read throughput.
     */
    metrics::Operation readOperation;
    metrics::Operation readWithScanOperation;
    mongocxx::pipeline pipeline{};

    PhaseConfig(PhaseContext& context,
                const RandomSampler* actor,
                const mongocxx::database& db,
                int collectionCount,
                int threads)
        : readOperation{context.operation("Read", actor->id())},
          readWithScanOperation{context.operation("ReadWithScan", actor->id())} {
        // Construct basic pipeline for retrieving 10 random records.
        pipeline.sample(10);

        // Distribute the collections among the actors.
        for (const auto& collectionName :
             distributeCollectionNames(collectionCount, threads, actor->_index)) {
            collections.push_back(db[collectionName]);
        }
        // Setup the int distribution.
        integerDistribution =
            boost::random::uniform_int_distribution(0, (int)collections.size() - 1);
    }
};

void RandomSampler::run() {
    for (auto&& config : _loop) {
        for (const auto&& _ : config) {
            auto statTracker = _activeCollectionScannerInstances > 0
                ? config->readWithScanOperation.start()
                : config->readOperation.start();
            int index = config->collections.size() > 1 ? config->integerDistribution(_random) : 0;
            auto cursor = config->collections[index].aggregate(config->pipeline,
                                                               mongocxx::options::aggregate{});
            for (auto doc : cursor) {
                statTracker.addDocuments(1);
                statTracker.addBytes(doc.length());
            }
            statTracker.success();
        }
    }
}

RandomSampler::RandomSampler(genny::ActorContext& context)
    : Actor{context},
      _client{context.client()},
      _index{WorkloadContext::getActorSharedState<RandomSampler, ActorCounter>().fetch_add(1)},
      _activeCollectionScannerInstances{
          WorkloadContext::getActorSharedState<CollectionScanner,
                                               CollectionScanner::RunningActorCounter>()},
      _random{context.workload().getRNGForThread(RandomSampler::id())},
      _loop{context,
            this,
            (*_client)[context["Database"].to<std::string>()],
            context["CollectionCount"].to<IntegerSpec>(),
            context["Threads"].to<IntegerSpec>()} {}

namespace {
auto registerRandomSampler = Cast::registerDefault<RandomSampler>();
}
}  // namespace genny::actor

max_stars_repo_name: samanca/genny

max_issues_repo_name: samanca/genny

max_forks_repo_name: samanca/genny


text:
// Copyright (c) 2008-2017 Emil Dotchevski and Reverge Studios, Inc.

// 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)

#ifndef BOOST_QVM_2923BE84E16CD6AE529049F1F1BBE9EB
#define BOOST_QVM_2923BE84E16CD6AE529049F1F1BBE9EB

// This file was generated by a program. Do not edit manually.

#include <boost/qvm/assert.hpp>
#include <boost/qvm/deduce_mat.hpp>
#include <boost/qvm/deduce_vec.hpp>
#include <boost/qvm/error.hpp>
#include <boost/qvm/gen/mat_assign2.hpp>
#include <boost/qvm/throw_exception.hpp>

namespace boost {
namespace qvm {
template <class A, class B>
BOOST_QVM_INLINE_OPERATIONS typename lazy_enable_if_c<
    mat_traits<A>::rows == 2 && mat_traits<B>::rows == 2 &&
        mat_traits<A>::cols == 2 && mat_traits<B>::cols == 2,
    deduce_mat2<A, B, 2, 2>>::type
operator+(A const &a, B const &b) {
  typedef typename deduce_mat2<A, B, 2, 2>::type R;
  BOOST_QVM_STATIC_ASSERT(mat_traits<R>::rows == 2);
  BOOST_QVM_STATIC_ASSERT(mat_traits<R>::cols == 2);
  R r;
  mat_traits<R>::template write_element<0, 0>(r) =
      mat_traits<A>::template read_element<0, 0>(a) +
      mat_traits<B>::template read_element<0, 0>(b);
  mat_traits<R>::template write_element<0, 1>(r) =
      mat_traits<A>::template read_element<0, 1>(a) +
      mat_traits<B>::template read_element<0, 1>(b);
  mat_traits<R>::template write_element<1, 0>(r) =
      mat_traits<A>::template read_element<1, 0>(a) +
      mat_traits<B>::template read_element<1, 0>(b);
  mat_traits<R>::template write_element<1, 1>(r) =
      mat_traits<A>::template read_element<1, 1>(a) +
      mat_traits<B>::template read_element<1, 1>(b);
  return r;
}

namespace sfinae {
using ::boost::qvm::operator+;
}

namespace qvm_detail {
template <int R, int C> struct plus_mm_defined;

template <> struct plus_mm_defined<2, 2> { static bool const value = true; };
} // namespace qvm_detail

template <class A, class B>
BOOST_QVM_INLINE_OPERATIONS typename lazy_enable_if_c<
    mat_traits<A>::rows == 2 && mat_traits<B>::rows == 2 &&
        mat_traits<A>::cols == 1 && mat_traits<B>::cols == 1,
    deduce_mat2<A, B, 2, 1>>::type
operator+(A const &a, B const &b) {
  typedef typename deduce_mat2<A, B, 2, 1>::type R;
  BOOST_QVM_STATIC_ASSERT(mat_traits<R>::rows == 2);
  BOOST_QVM_STATIC_ASSERT(mat_traits<R>::cols == 1);
  R r;
  mat_traits<R>::template write_element<0, 0>(r) =
      mat_traits<A>::template read_element<0, 0>(a) +
      mat_traits<B>::template read_element<0, 0>(b);
  mat_traits<R>::template write_element<1, 0>(r) =
      mat_traits<A>::template read_element<1, 0>(a) +
      mat_traits<B>::template read_element<1, 0>(b);
  return r;
}

namespace sfinae {
using ::boost::qvm::operator+;
}

namespace qvm_detail {
template <int R, int C> struct plus_mm_defined;

template <> struct plus_mm_defined<2, 1> { static bool const value = true; };
} // namespace qvm_detail

template <class A, class B>
BOOST_QVM_INLINE_OPERATIONS typename lazy_enable_if_c<
    mat_traits<A>::rows == 1 && mat_traits<B>::rows == 1 &&
        mat_traits<A>::cols == 2 && mat_traits<B>::cols == 2,
    deduce_mat2<A, B, 1, 2>>::type
operator+(A const &a, B const &b) {
  typedef typename deduce_mat2<A, B, 1, 2>::type R;
  BOOST_QVM_STATIC_ASSERT(mat_traits<R>::rows == 1);
  BOOST_QVM_STATIC_ASSERT(mat_traits<R>::cols == 2);
  R r;
  mat_traits<R>::template write_element<0, 0>(r) =
      mat_traits<A>::template read_element<0, 0>(a) +
      mat_traits<B>::template read_element<0, 0>(b);
  mat_traits<R>::template write_element<0, 1>(r) =
      mat_traits<A>::template read_element<0, 1>(a) +
      mat_traits<B>::template read_element<0, 1>(b);
  return r;
}

namespace sfinae {
using ::boost::qvm::operator+;
}

namespace qvm_detail {
template <int R, int C> struct plus_mm_defined;

template <> struct plus_mm_defined<1, 2> { static bool const value = true; };
} // namespace qvm_detail

template <class A, class B>
BOOST_QVM_INLINE_OPERATIONS typename lazy_enable_if_c<
    mat_traits<A>::rows == 2 && mat_traits<B>::rows == 2 &&
        mat_traits<A>::cols == 2 && mat_traits<B>::cols == 2,
    deduce_mat2<A, B, 2, 2>>::type
operator-(A const &a, B const &b) {
  typedef typename deduce_mat2<A, B, 2, 2>::type R;
  BOOST_QVM_STATIC_ASSERT(mat_traits<R>::rows == 2);
  BOOST_QVM_STATIC_ASSERT(mat_traits<R>::cols == 2);
  R r;
  mat_traits<R>::template write_element<0, 0>(r) =
      mat_traits<A>::template read_element<0, 0>(a) -
      mat_traits<B>::template read_element<0, 0>(b);
  mat_traits<R>::template write_element<0, 1>(r) =
      mat_traits<A>::template read_element<0, 1>(a) -
      mat_traits<B>::template read_element<0, 1>(b);
  mat_traits<R>::template write_element<1, 0>(r) =
      mat_traits<A>::template read_element<1, 0>(a) -
      mat_traits<B>::template read_element<1, 0>(b);
  mat_traits<R>::template write_element<1, 1>(r) =
      mat_traits<A>::template read_element<1, 1>(a) -
      mat_traits<B>::template read_element<1, 1>(b);
  return r;
}

namespace sfinae {
using ::boost::qvm::operator-;
}

namespace qvm_detail {
template <int R, int C> struct minus_mm_defined;

template <> struct minus_mm_defined<2, 2> { static bool const value = true; };
} // namespace qvm_detail

template <class A, class B>
BOOST_QVM_INLINE_OPERATIONS typename lazy_enable_if_c<
    mat_traits<A>::rows == 2 && mat_traits<B>::rows == 2 &&
        mat_traits<A>::cols == 1 && mat_traits<B>::cols == 1,
    deduce_mat2<A, B, 2, 1>>::type
operator-(A const &a, B const &b) {
  typedef typename deduce_mat2<A, B, 2, 1>::type R;
  BOOST_QVM_STATIC_ASSERT(mat_traits<R>::rows == 2);
  BOOST_QVM_STATIC_ASSERT(mat_traits<R>::cols == 1);
  R r;
  mat_traits<R>::template write_element<0, 0>(r) =
      mat_traits<A>::template read_element<0, 0>(a) -
      mat_traits<B>::template read_element<0, 0>(b);
  mat_traits<R>::template write_element<1, 0>(r) =
      mat_traits<A>::template read_element<1, 0>(a) -
      mat_traits<B>::template read_element<1, 0>(b);
  return r;
}

namespace sfinae {
using ::boost::qvm::operator-;
}

namespace qvm_detail {
template <int R, int C> struct minus_mm_defined;

template <> struct minus_mm_defined<2, 1> { static bool const value = true; };
} // namespace qvm_detail

template <class A, class B>
BOOST_QVM_INLINE_OPERATIONS typename lazy_enable_if_c<
    mat_traits<A>::rows == 1 && mat_traits<B>::rows == 1 &&
        mat_traits<A>::cols == 2 && mat_traits<B>::cols == 2,
    deduce_mat2<A, B, 1, 2>>::type
operator-(A const &a, B const &b) {
  typedef typename deduce_mat2<A, B, 1, 2>::type R;
  BOOST_QVM_STATIC_ASSERT(mat_traits<R>::rows == 1);
  BOOST_QVM_STATIC_ASSERT(mat_traits<R>::cols == 2);
  R r;
  mat_traits<R>::template write_element<0, 0>(r) =
      mat_traits<A>::template read_element<0, 0>(a) -
      mat_traits<B>::template read_element<0, 0>(b);
  mat_traits<R>::template write_element<0, 1>(r) =
      mat_traits<A>::template read_element<0, 1>(a) -
      mat_traits<B>::template read_element<0, 1>(b);
  return r;
}

namespace sfinae {
using ::boost::qvm::operator-;
}

namespace qvm_detail {
template <int R, int C> struct minus_mm_defined;

template <> struct minus_mm_defined<1, 2> { static bool const value = true; };
} // namespace qvm_detail

template <class A, class B>
BOOST_QVM_INLINE_OPERATIONS
    typename enable_if_c<mat_traits<A>::rows == 2 && mat_traits<B>::rows == 2 &&
                             mat_traits<A>::cols == 2 &&
                             mat_traits<B>::cols == 2,
                         A &>::type
    operator+=(A &a, B const &b) {
  mat_traits<A>::template write_element<0, 0>(a) +=
      mat_traits<B>::template read_element<0, 0>(b);
  mat_traits<A>::template write_element<0, 1>(a) +=
      mat_traits<B>::template read_element<0, 1>(b);
  mat_traits<A>::template write_element<1, 0>(a) +=
      mat_traits<B>::template read_element<1, 0>(b);
  mat_traits<A>::template write_element<1, 1>(a) +=
      mat_traits<B>::template read_element<1, 1>(b);
  return a;
}

namespace sfinae {
using ::boost::qvm::operator+=;
}

namespace qvm_detail {
template <int R, int C> struct plus_eq_mm_defined;

template <> struct plus_eq_mm_defined<2, 2> { static bool const value = true; };
} // namespace qvm_detail

template <class A, class B>
BOOST_QVM_INLINE_OPERATIONS
    typename enable_if_c<mat_traits<A>::rows == 2 && mat_traits<B>::rows == 2 &&
                             mat_traits<A>::cols == 1 &&
                             mat_traits<B>::cols == 1,
                         A &>::type
    operator+=(A &a, B const &b) {
  mat_traits<A>::template write_element<0, 0>(a) +=
      mat_traits<B>::template read_element<0, 0>(b);
  mat_traits<A>::template write_element<1, 0>(a) +=
      mat_traits<B>::template read_element<1, 0>(b);
  return a;
}

namespace sfinae {
using ::boost::qvm::operator+=;
}

namespace qvm_detail {
template <int R, int C> struct plus_eq_mm_defined;

template <> struct plus_eq_mm_defined<2, 1> { static bool const value = true; };
} // namespace qvm_detail

template <class A, class B>
BOOST_QVM_INLINE_OPERATIONS
    typename enable_if_c<mat_traits<A>::rows == 1 && mat_traits<B>::rows == 1 &&
                             mat_traits<A>::cols == 2 &&
                             mat_traits<B>::cols == 2,
                         A &>::type
    operator+=(A &a, B const &b) {
  mat_traits<A>::template write_element<0, 0>(a) +=
      mat_traits<B>::template read_element<0, 0>(b);
  mat_traits<A>::template write_element<0, 1>(a) +=
      mat_traits<B>::template read_element<0, 1>(b);
  return a;
}

namespace sfinae {
using ::boost::qvm::operator+=;
}

namespace qvm_detail {
template <int R, int C> struct plus_eq_mm_defined;

template <> struct plus_eq_mm_defined<1, 2> { static bool const value = true; };
} // namespace qvm_detail

template <class A, class B>
BOOST_QVM_INLINE_OPERATIONS
    typename enable_if_c<mat_traits<A>::rows == 2 && mat_traits<B>::rows == 2 &&
                             mat_traits<A>::cols == 2 &&
                             mat_traits<B>::cols == 2,
                         A &>::type
    operator-=(A &a, B const &b) {
  mat_traits<A>::template write_element<0, 0>(a) -=
      mat_traits<B>::template read_element<0, 0>(b);
  mat_traits<A>::template write_element<0, 1>(a) -=
      mat_traits<B>::template read_element<0, 1>(b);
  mat_traits<A>::template write_element<1, 0>(a) -=
      mat_traits<B>::template read_element<1, 0>(b);
  mat_traits<A>::template write_element<1, 1>(a) -=
      mat_traits<B>::template read_element<1, 1>(b);
  return a;
}

namespace sfinae {
using ::boost::qvm::operator-=;
}

namespace qvm_detail {
template <int R, int C> struct minus_eq_mm_defined;

template <> struct minus_eq_mm_defined<2, 2> {
  static bool const value = true;
};
} // namespace qvm_detail

template <class A, class B>
BOOST_QVM_INLINE_OPERATIONS
    typename enable_if_c<mat_traits<A>::rows == 2 && mat_traits<B>::rows == 2 &&
                             mat_traits<A>::cols == 1 &&
                             mat_traits<B>::cols == 1,
                         A &>::type
    operator-=(A &a, B const &b) {
  mat_traits<A>::template write_element<0, 0>(a) -=
      mat_traits<B>::template read_element<0, 0>(b);
  mat_traits<A>::template write_element<1, 0>(a) -=
      mat_traits<B>::template read_element<1, 0>(b);
  return a;
}

namespace sfinae {
using ::boost::qvm::operator-=;
}

namespace qvm_detail {
template <int R, int C> struct minus_eq_mm_defined;

template <> struct minus_eq_mm_defined<2, 1> {
  static bool const value = true;
};
} // namespace qvm_detail

template <class A, class B>
BOOST_QVM_INLINE_OPERATIONS
    typename enable_if_c<mat_traits<A>::rows == 1 && mat_traits<B>::rows == 1 &&
                             mat_traits<A>::cols == 2 &&
                             mat_traits<B>::cols == 2,
                         A &>::type
    operator-=(A &a, B const &b) {
  mat_traits<A>::template write_element<0, 0>(a) -=
      mat_traits<B>::template read_element<0, 0>(b);
  mat_traits<A>::template write_element<0, 1>(a) -=
      mat_traits<B>::template read_element<0, 1>(b);
  return a;
}

namespace sfinae {
using ::boost::qvm::operator-=;
}

namespace qvm_detail {
template <int R, int C> struct minus_eq_mm_defined;

template <> struct minus_eq_mm_defined<1, 2> {
  static bool const value = true;
};
} // namespace qvm_detail

template <class A, class B>
BOOST_QVM_INLINE_OPERATIONS typename lazy_enable_if_c<
    mat_traits<A>::rows == 2 && mat_traits<A>::cols == 2 && is_scalar<B>::value,
    deduce_mat<A>>::type
operator*(A const &a, B b) {
  typedef typename deduce_mat<A>::type R;
  R r;
  mat_traits<R>::template write_element<0, 0>(r) =
      mat_traits<A>::template read_element<0, 0>(a) * b;
  mat_traits<R>::template write_element<0, 1>(r) =
      mat_traits<A>::template read_element<0, 1>(a) * b;
  mat_traits<R>::template write_element<1, 0>(r) =
      mat_traits<A>::template read_element<1, 0>(a) * b;
  mat_traits<R>::template write_element<1, 1>(r) =
      mat_traits<A>::template read_element<1, 1>(a) * b;
  return r;
}

namespace sfinae {
using ::boost::qvm::operator*;
}

namespace qvm_detail {
template <int R, int C> struct mul_ms_defined;

template <> struct mul_ms_defined<2, 2> { static bool const value = true; };
} // namespace qvm_detail

template <class A, class B>
BOOST_QVM_INLINE_OPERATIONS
    typename lazy_enable_if_c<is_scalar<A>::value && mat_traits<B>::rows == 2 &&
                                  mat_traits<B>::cols == 2,
                              deduce_mat<B>>::type
    operator*(A a, B const &b) {
  typedef typename deduce_mat<B>::type R;
  R r;
  mat_traits<R>::template write_element<0, 0>(r) =
      a * mat_traits<B>::template read_element<0, 0>(b);
  mat_traits<R>::template write_element<0, 1>(r) =
      a * mat_traits<B>::template read_element<0, 1>(b);
  mat_traits<R>::template write_element<1, 0>(r) =
      a * mat_traits<B>::template read_element<1, 0>(b);
  mat_traits<R>::template write_element<1, 1>(r) =
      a * mat_traits<B>::template read_element<1, 1>(b);
  return r;
}

namespace sfinae {
using ::boost::qvm::operator*;
}

namespace qvm_detail {
template <int R, int C> struct mul_sm_defined;

template <> struct mul_sm_defined<2, 2> { static bool const value = true; };
} // namespace qvm_detail

template <class A, class B>
BOOST_QVM_INLINE_OPERATIONS typename lazy_enable_if_c<
    mat_traits<A>::rows == 2 && mat_traits<A>::cols == 1 && is_scalar<B>::value,
    deduce_mat<A>>::type
operator*(A const &a, B b) {
  typedef typename deduce_mat<A>::type R;
  R r;
  mat_traits<R>::template write_element<0, 0>(r) =
      mat_traits<A>::template read_element<0, 0>(a) * b;
  mat_traits<R>::template write_element<1, 0>(r) =
      mat_traits<A>::template read_element<1, 0>(a) * b;
  return r;
}

namespace sfinae {
using ::boost::qvm::operator*;
}

namespace qvm_detail {
template <int R, int C> struct mul_ms_defined;

template <> struct mul_ms_defined<2, 1> { static bool const value = true; };
} // namespace qvm_detail

template <class A, class B>
BOOST_QVM_INLINE_OPERATIONS
    typename lazy_enable_if_c<is_scalar<A>::value && mat_traits<B>::rows == 2 &&
                                  mat_traits<B>::cols == 1,
                              deduce_mat<B>>::type
    operator*(A a, B const &b) {
  typedef typename deduce_mat<B>::type R;
  R r;
  mat_traits<R>::template write_element<0, 0>(r) =
      a * mat_traits<B>::template read_element<0, 0>(b);
  mat_traits<R>::template write_element<1, 0>(r) =
      a * mat_traits<B>::template read_element<1, 0>(b);
  return r;
}

namespace sfinae {
using ::boost::qvm::operator*;
}

namespace qvm_detail {
template <int R, int C> struct mul_sm_defined;

template <> struct mul_sm_defined<2, 1> { static bool const value = true; };
} // namespace qvm_detail

template <class A, class B>
BOOST_QVM_INLINE_OPERATIONS typename lazy_enable_if_c<
    mat_traits<A>::rows == 1 && mat_traits<A>::cols == 2 && is_scalar<B>::value,
    deduce_mat<A>>::type
operator*(A const &a, B b) {
  typedef typename deduce_mat<A>::type R;
  R r;
  mat_traits<R>::template write_element<0, 0>(r) =
      mat_traits<A>::template read_element<0, 0>(a) * b;
  mat_traits<R>::template write_element<0, 1>(r) =
      mat_traits<A>::template read_element<0, 1>(a) * b;
  return r;
}

namespace sfinae {
using ::boost::qvm::operator*;
}

namespace qvm_detail {
template <int R, int C> struct mul_ms_defined;

template <> struct mul_ms_defined<1, 2> { static bool const value = true; };
} // namespace qvm_detail

template <class A, class B>
BOOST_QVM_INLINE_OPERATIONS
    typename lazy_enable_if_c<is_scalar<A>::value && mat_traits<B>::rows == 1 &&
                                  mat_traits<B>::cols == 2,
                              deduce_mat<B>>::type
    operator*(A a, B const &b) {
  typedef typename deduce_mat<B>::type R;
  R r;
  mat_traits<R>::template write_element<0, 0>(r) =
      a * mat_traits<B>::template read_element<0, 0>(b);
  mat_traits<R>::template write_element<0, 1>(r) =
      a * mat_traits<B>::template read_element<0, 1>(b);
  return r;
}

namespace sfinae {
using ::boost::qvm::operator*;
}

namespace qvm_detail {
template <int R, int C> struct mul_sm_defined;

template <> struct mul_sm_defined<1, 2> { static bool const value = true; };
} // namespace qvm_detail

template <class A, class B>
BOOST_QVM_INLINE_OPERATIONS
    typename enable_if_c<mat_traits<A>::rows == 2 && mat_traits<A>::cols == 2 &&
                             is_scalar<B>::value,
                         A &>::type
    operator*=(A &a, B b) {
  mat_traits<A>::template write_element<0, 0>(a) *= b;
  mat_traits<A>::template write_element<0, 1>(a) *= b;
  mat_traits<A>::template write_element<1, 0>(a) *= b;
  mat_traits<A>::template write_element<1, 1>(a) *= b;
  return a;
}

namespace sfinae {
using ::boost::qvm::operator*=;
}

namespace qvm_detail {
template <int R, int C> struct mul_eq_ms_defined;

template <> struct mul_eq_ms_defined<2, 2> { static bool const value = true; };
} // namespace qvm_detail

template <class A, class B>
BOOST_QVM_INLINE_OPERATIONS
    typename enable_if_c<mat_traits<A>::rows == 2 && mat_traits<A>::cols == 1 &&
                             is_scalar<B>::value,
                         A &>::type
    operator*=(A &a, B b) {
  mat_traits<A>::template write_element<0, 0>(a) *= b;
  mat_traits<A>::template write_element<1, 0>(a) *= b;
  return a;
}

namespace sfinae {
using ::boost::qvm::operator*=;
}

namespace qvm_detail {
template <int R, int C> struct mul_eq_ms_defined;

template <> struct mul_eq_ms_defined<2, 1> { static bool const value = true; };
} // namespace qvm_detail

template <class A, class B>
BOOST_QVM_INLINE_OPERATIONS
    typename enable_if_c<mat_traits<A>::rows == 1 && mat_traits<A>::cols == 2 &&
                             is_scalar<B>::value,
                         A &>::type
    operator*=(A &a, B b) {
  mat_traits<A>::template write_element<0, 0>(a) *= b;
  mat_traits<A>::template write_element<0, 1>(a) *= b;
  return a;
}

namespace sfinae {
using ::boost::qvm::operator*=;
}

namespace qvm_detail {
template <int R, int C> struct mul_eq_ms_defined;

template <> struct mul_eq_ms_defined<1, 2> { static bool const value = true; };
} // namespace qvm_detail

template <class A, class B>
BOOST_QVM_INLINE_OPERATIONS typename lazy_enable_if_c<
    mat_traits<A>::rows == 2 && mat_traits<A>::cols == 2 && is_scalar<B>::value,
    deduce_mat<A>>::type
operator/(A const &a, B b) {
  typedef typename deduce_mat<A>::type R;
  R r;
  mat_traits<R>::template write_element<0, 0>(r) =
      mat_traits<A>::template read_element<0, 0>(a) / b;
  mat_traits<R>::template write_element<0, 1>(r) =
      mat_traits<A>::template read_element<0, 1>(a) / b;
  mat_traits<R>::template write_element<1, 0>(r) =
      mat_traits<A>::template read_element<1, 0>(a) / b;
  mat_traits<R>::template write_element<1, 1>(r) =
      mat_traits<A>::template read_element<1, 1>(a) / b;
  return r;
}

namespace sfinae {
using ::boost::qvm::operator/;
}

namespace qvm_detail {
template <int R, int C> struct div_ms_defined;

template <> struct div_ms_defined<2, 2> { static bool const value = true; };
} // namespace qvm_detail

template <class A, class B>
BOOST_QVM_INLINE_OPERATIONS
    typename lazy_enable_if_c<is_scalar<A>::value && mat_traits<B>::rows == 2 &&
                                  mat_traits<B>::cols == 2,
                              deduce_mat<B>>::type
    operator/(A a, B const &b) {
  typedef typename deduce_mat<B>::type R;
  R r;
  mat_traits<R>::template write_element<0, 0>(r) =
      a / mat_traits<B>::template read_element<0, 0>(b);
  mat_traits<R>::template write_element<0, 1>(r) =
      a / mat_traits<B>::template read_element<0, 1>(b);
  mat_traits<R>::template write_element<1, 0>(r) =
      a / mat_traits<B>::template read_element<1, 0>(b);
  mat_traits<R>::template write_element<1, 1>(r) =
      a / mat_traits<B>::template read_element<1, 1>(b);
  return r;
}

namespace sfinae {
using ::boost::qvm::operator/;
}

namespace qvm_detail {
template <int R, int C> struct div_sm_defined;

template <> struct div_sm_defined<2, 2> { static bool const value = true; };
} // namespace qvm_detail

template <class A, class B>
BOOST_QVM_INLINE_OPERATIONS typename lazy_enable_if_c<
    mat_traits<A>::rows == 2 && mat_traits<A>::cols == 1 && is_scalar<B>::value,
    deduce_mat<A>>::type
operator/(A const &a, B b) {
  typedef typename deduce_mat<A>::type R;
  R r;
  mat_traits<R>::template write_element<0, 0>(r) =
      mat_traits<A>::template read_element<0, 0>(a) / b;
  mat_traits<R>::template write_element<1, 0>(r) =
      mat_traits<A>::template read_element<1, 0>(a) / b;
  return r;
}

namespace sfinae {
using ::boost::qvm::operator/;
}

namespace qvm_detail {
template <int R, int C> struct div_ms_defined;

template <> struct div_ms_defined<2, 1> { static bool const value = true; };
} // namespace qvm_detail

template <class A, class B>
BOOST_QVM_INLINE_OPERATIONS
    typename lazy_enable_if_c<is_scalar<A>::value && mat_traits<B>::rows == 2 &&
                                  mat_traits<B>::cols == 1,
                              deduce_mat<B>>::type
    operator/(A a, B const &b) {
  typedef typename deduce_mat<B>::type R;
  R r;
  mat_traits<R>::template write_element<0, 0>(r) =
      a / mat_traits<B>::template read_element<0, 0>(b);
  mat_traits<R>::template write_element<1, 0>(r) =
      a / mat_traits<B>::template read_element<1, 0>(b);
  return r;
}

namespace sfinae {
using ::boost::qvm::operator/;
}

namespace qvm_detail {
template <int R, int C> struct div_sm_defined;

template <> struct div_sm_defined<2, 1> { static bool const value = true; };
} // namespace qvm_detail

template <class A, class B>
BOOST_QVM_INLINE_OPERATIONS typename lazy_enable_if_c<
    mat_traits<A>::rows == 1 && mat_traits<A>::cols == 2 && is_scalar<B>::value,
    deduce_mat<A>>::type
operator/(A const &a, B b) {
  typedef typename deduce_mat<A>::type R;
  R r;
  mat_traits<R>::template write_element<0, 0>(r) =
      mat_traits<A>::template read_element<0, 0>(a) / b;
  mat_traits<R>::template write_element<0, 1>(r) =
      mat_traits<A>::template read_element<0, 1>(a) / b;
  return r;
}

namespace sfinae {
using ::boost::qvm::operator/;
}

namespace qvm_detail {
template <int R, int C> struct div_ms_defined;

template <> struct div_ms_defined<1, 2> { static bool const value = true; };
} // namespace qvm_detail

template <class A, class B>
BOOST_QVM_INLINE_OPERATIONS
    typename enable_if_c<mat_traits<A>::rows == 2 && mat_traits<A>::cols == 2 &&
                             is_scalar<B>::value,
                         A &>::type
    operator/=(A &a, B b) {
  mat_traits<A>::template write_element<0, 0>(a) /= b;
  mat_traits<A>::template write_element<0, 1>(a) /= b;
  mat_traits<A>::template write_element<1, 0>(a) /= b;
  mat_traits<A>::template write_element<1, 1>(a) /= b;
  return a;
}

namespace sfinae {
using ::boost::qvm::operator/=;
}

namespace qvm_detail {
template <int R, int C> struct div_eq_ms_defined;

template <> struct div_eq_ms_defined<2, 2> { static bool const value = true; };
} // namespace qvm_detail

template <class A, class B>
BOOST_QVM_INLINE_OPERATIONS
    typename enable_if_c<mat_traits<A>::rows == 2 && mat_traits<A>::cols == 1 &&
                             is_scalar<B>::value,
                         A &>::type
    operator/=(A &a, B b) {
  mat_traits<A>::template write_element<0, 0>(a) /= b;
  mat_traits<A>::template write_element<1, 0>(a) /= b;
  return a;
}

namespace sfinae {
using ::boost::qvm::operator/=;
}

namespace qvm_detail {
template <int R, int C> struct div_eq_ms_defined;

template <> struct div_eq_ms_defined<2, 1> { static bool const value = true; };
} // namespace qvm_detail

template <class A, class B>
BOOST_QVM_INLINE_OPERATIONS
    typename enable_if_c<mat_traits<A>::rows == 1 && mat_traits<A>::cols == 2 &&
                             is_scalar<B>::value,
                         A &>::type
    operator/=(A &a, B b) {
  mat_traits<A>::template write_element<0, 0>(a) /= b;
  mat_traits<A>::template write_element<0, 1>(a) /= b;
  return a;
}

namespace sfinae {
using ::boost::qvm::operator/=;
}

namespace qvm_detail {
template <int R, int C> struct div_eq_ms_defined;

template <> struct div_eq_ms_defined<1, 2> { static bool const value = true; };
} // namespace qvm_detail

template <class R, class A>
BOOST_QVM_INLINE_OPERATIONS
    typename enable_if_c<mat_traits<R>::rows == 2 && mat_traits<A>::rows == 2 &&
                             mat_traits<R>::cols == 2 &&
                             mat_traits<A>::cols == 2,
                         R>::type
    convert_to(A const &a) {
  R r;
  mat_traits<R>::template write_element<0, 0>(r) =
      mat_traits<A>::template read_element<0, 0>(a);
  mat_traits<R>::template write_element<0, 1>(r) =
      mat_traits<A>::template read_element<0, 1>(a);
  mat_traits<R>::template write_element<1, 0>(r) =
      mat_traits<A>::template read_element<1, 0>(a);
  mat_traits<R>::template write_element<1, 1>(r) =
      mat_traits<A>::template read_element<1, 1>(a);
  return r;
}

namespace sfinae {
using ::boost::qvm::convert_to;
}

namespace qvm_detail {
template <int R, int C> struct convert_to_m_defined;

template <> struct convert_to_m_defined<2, 2> {
  static bool const value = true;
};
} // namespace qvm_detail

template <class R, class A>
BOOST_QVM_INLINE_OPERATIONS
    typename enable_if_c<mat_traits<R>::rows == 2 && mat_traits<A>::rows == 2 &&
                             mat_traits<R>::cols == 1 &&
                             mat_traits<A>::cols == 1,
                         R>::type
    convert_to(A const &a) {
  R r;
  mat_traits<R>::template write_element<0, 0>(r) =
      mat_traits<A>::template read_element<0, 0>(a);
  mat_traits<R>::template write_element<1, 0>(r) =
      mat_traits<A>::template read_element<1, 0>(a);
  return r;
}

namespace sfinae {
using ::boost::qvm::convert_to;
}

namespace qvm_detail {
template <int R, int C> struct convert_to_m_defined;

template <> struct convert_to_m_defined<2, 1> {
  static bool const value = true;
};
} // namespace qvm_detail

template <class R, class A>
BOOST_QVM_INLINE_OPERATIONS
    typename enable_if_c<mat_traits<R>::rows == 1 && mat_traits<A>::rows == 1 &&
                             mat_traits<R>::cols == 2 &&
                             mat_traits<A>::cols == 2,
                         R>::type
    convert_to(A const &a) {
  R r;
  mat_traits<R>::template write_element<0, 0>(r) =
      mat_traits<A>::template read_element<0, 0>(a);
  mat_traits<R>::template write_element<0, 1>(r) =
      mat_traits<A>::template read_element<0, 1>(a);
  return r;
}

namespace sfinae {
using ::boost::qvm::convert_to;
}

namespace qvm_detail {
template <int R, int C> struct convert_to_m_defined;

template <> struct convert_to_m_defined<1, 2> {
  static bool const value = true;
};
} // namespace qvm_detail

template <class A, class B>
BOOST_QVM_INLINE_OPERATIONS
    typename enable_if_c<mat_traits<A>::rows == 2 && mat_traits<B>::rows == 2 &&
                             mat_traits<A>::cols == 2 &&
                             mat_traits<B>::cols == 2,
                         bool>::type
    operator==(A const &a, B const &b) {
  return mat_traits<A>::template read_element<0, 0>(a) ==
             mat_traits<B>::template read_element<0, 0>(b) &&
         mat_traits<A>::template read_element<0, 1>(a) ==
             mat_traits<B>::template read_element<0, 1>(b) &&
         mat_traits<A>::template read_element<1, 0>(a) ==
             mat_traits<B>::template read_element<1, 0>(b) &&
         mat_traits<A>::template read_element<1, 1>(a) ==
             mat_traits<B>::template read_element<1, 1>(b);
}

namespace sfinae {
using ::boost::qvm::operator==;
}

namespace qvm_detail {
template <int R, int C> struct eq_mm_defined;

template <> struct eq_mm_defined<2, 2> { static bool const value = true; };
} // namespace qvm_detail

template <class A, class B>
BOOST_QVM_INLINE_OPERATIONS
    typename enable_if_c<mat_traits<A>::rows == 2 && mat_traits<B>::rows == 2 &&
                             mat_traits<A>::cols == 1 &&
                             mat_traits<B>::cols == 1,
                         bool>::type
    operator==(A const &a, B const &b) {
  return mat_traits<A>::template read_element<0, 0>(a) ==
             mat_traits<B>::template read_element<0, 0>(b) &&
         mat_traits<A>::template read_element<1, 0>(a) ==
             mat_traits<B>::template read_element<1, 0>(b);
}

namespace sfinae {
using ::boost::qvm::operator==;
}

namespace qvm_detail {
template <int R, int C> struct eq_mm_defined;

template <> struct eq_mm_defined<2, 1> { static bool const value = true; };
} // namespace qvm_detail

template <class A, class B>
BOOST_QVM_INLINE_OPERATIONS
    typename enable_if_c<mat_traits<A>::rows == 1 && mat_traits<B>::rows == 1 &&
                             mat_traits<A>::cols == 2 &&
                             mat_traits<B>::cols == 2,
                         bool>::type
    operator==(A const &a, B const &b) {
  return mat_traits<A>::template read_element<0, 0>(a) ==
             mat_traits<B>::template read_element<0, 0>(b) &&
         mat_traits<A>::template read_element<0, 1>(a) ==
             mat_traits<B>::template read_element<0, 1>(b);
}

namespace sfinae {
using ::boost::qvm::operator==;
}

namespace qvm_detail {
template <int R, int C> struct eq_mm_defined;

template <> struct eq_mm_defined<1, 2> { static bool const value = true; };
} // namespace qvm_detail

template <class A, class B>
BOOST_QVM_INLINE_OPERATIONS
    typename enable_if_c<mat_traits<A>::rows == 2 && mat_traits<B>::rows == 2 &&
                             mat_traits<A>::cols == 2 &&
                             mat_traits<B>::cols == 2,
                         bool>::type
    operator!=(A const &a, B const &b) {
  return !(mat_traits<A>::template read_element<0, 0>(a) ==
           mat_traits<B>::template read_element<0, 0>(b)) ||
         !(mat_traits<A>::template read_element<0, 1>(a) ==
           mat_traits<B>::template read_element<0, 1>(b)) ||
         !(mat_traits<A>::template read_element<1, 0>(a) ==
           mat_traits<B>::template read_element<1, 0>(b)) ||
         !(mat_traits<A>::template read_element<1, 1>(a) ==
           mat_traits<B>::template read_element<1, 1>(b));
}

namespace sfinae {
using ::boost::qvm::operator!=;
}

namespace qvm_detail {
template <int R, int C> struct neq_mm_defined;

template <> struct neq_mm_defined<2, 2> { static bool const value = true; };
} // namespace qvm_detail

template <class A, class B>
BOOST_QVM_INLINE_OPERATIONS
    typename enable_if_c<mat_traits<A>::rows == 2 && mat_traits<B>::rows == 2 &&
                             mat_traits<A>::cols == 1 &&
                             mat_traits<B>::cols == 1,
                         bool>::type
    operator!=(A const &a, B const &b) {
  return !(mat_traits<A>::template read_element<0, 0>(a) ==
           mat_traits<B>::template read_element<0, 0>(b)) ||
         !(mat_traits<A>::template read_element<1, 0>(a) ==
           mat_traits<B>::template read_element<1, 0>(b));
}

namespace sfinae {
using ::boost::qvm::operator!=;
}

namespace qvm_detail {
template <int R, int C> struct neq_mm_defined;

template <> struct neq_mm_defined<2, 1> { static bool const value = true; };
} // namespace qvm_detail

template <class A, class B>
BOOST_QVM_INLINE_OPERATIONS
    typename enable_if_c<mat_traits<A>::rows == 1 && mat_traits<B>::rows == 1 &&
                             mat_traits<A>::cols == 2 &&
                             mat_traits<B>::cols == 2,
                         bool>::type
    operator!=(A const &a, B const &b) {
  return !(mat_traits<A>::template read_element<0, 0>(a) ==
           mat_traits<B>::template read_element<0, 0>(b)) ||
         !(mat_traits<A>::template read_element<0, 1>(a) ==
           mat_traits<B>::template read_element<0, 1>(b));
}

namespace sfinae {
using ::boost::qvm::operator!=;
}

namespace qvm_detail {
template <int R, int C> struct neq_mm_defined;

template <> struct neq_mm_defined<1, 2> { static bool const value = true; };
} // namespace qvm_detail

template <class A>
BOOST_QVM_INLINE_OPERATIONS typename lazy_enable_if_c<
    mat_traits<A>::rows == 2 && mat_traits<A>::cols == 2, deduce_mat<A>>::type
operator-(A const &a) {
  typedef typename deduce_mat<A>::type R;
  R r;
  mat_traits<R>::template write_element<0, 0>(r) =
      -mat_traits<A>::template read_element<0, 0>(a);
  mat_traits<R>::template write_element<0, 1>(r) =
      -mat_traits<A>::template read_element<0, 1>(a);
  mat_traits<R>::template write_element<1, 0>(r) =
      -mat_traits<A>::template read_element<1, 0>(a);
  mat_traits<R>::template write_element<1, 1>(r) =
      -mat_traits<A>::template read_element<1, 1>(a);
  return r;
}

namespace sfinae {
using ::boost::qvm::operator-;
}

namespace qvm_detail {
template <int R, int C> struct minus_m_defined;

template <> struct minus_m_defined<2, 2> { static bool const value = true; };
} // namespace qvm_detail

template <class A>
BOOST_QVM_INLINE_OPERATIONS typename lazy_enable_if_c<
    mat_traits<A>::rows == 2 && mat_traits<A>::cols == 1, deduce_mat<A>>::type
operator-(A const &a) {
  typedef typename deduce_mat<A>::type R;
  R r;
  mat_traits<R>::template write_element<0, 0>(r) =
      -mat_traits<A>::template read_element<0, 0>(a);
  mat_traits<R>::template write_element<1, 0>(r) =
      -mat_traits<A>::template read_element<1, 0>(a);
  return r;
}

namespace sfinae {
using ::boost::qvm::operator-;
}

namespace qvm_detail {
template <int R, int C> struct minus_m_defined;

template <> struct minus_m_defined<2, 1> { static bool const value = true; };
} // namespace qvm_detail

template <class A>
BOOST_QVM_INLINE_OPERATIONS typename lazy_enable_if_c<
    mat_traits<A>::rows == 1 && mat_traits<A>::cols == 2, deduce_mat<A>>::type
operator-(A const &a) {
  typedef typename deduce_mat<A>::type R;
  R r;
  mat_traits<R>::template write_element<0, 0>(r) =
      -mat_traits<A>::template read_element<0, 0>(a);
  mat_traits<R>::template write_element<0, 1>(r) =
      -mat_traits<A>::template read_element<0, 1>(a);
  return r;
}

namespace sfinae {
using ::boost::qvm::operator-;
}

namespace qvm_detail {
template <int R, int C> struct minus_m_defined;

template <> struct minus_m_defined<1, 2> { static bool const value = true; };
} // namespace qvm_detail

template <class A>
BOOST_QVM_INLINE_OPERATIONS
    typename enable_if_c<mat_traits<A>::rows == 2 && mat_traits<A>::cols == 2,
                         typename mat_traits<A>::scalar_type>::type
    determinant(A const &a) {
  typedef typename mat_traits<A>::scalar_type T;
  T const a00 = mat_traits<A>::template read_element<0, 0>(a);
  T const a01 = mat_traits<A>::template read_element<0, 1>(a);
  T const a10 = mat_traits<A>::template read_element<1, 0>(a);
  T const a11 = mat_traits<A>::template read_element<1, 1>(a);
  T det = (a00 * a11 - a01 * a10);
  return det;
}

namespace sfinae {
using ::boost::qvm::determinant;
}

namespace qvm_detail {
template <int D> struct determinant_defined;

template <> struct determinant_defined<2> { static bool const value = true; };
} // namespace qvm_detail

template <class A, class B>
BOOST_QVM_INLINE_OPERATIONS typename lazy_enable_if_c<
    mat_traits<A>::rows == 2 && mat_traits<A>::cols == 2 && is_scalar<B>::value,
    deduce_mat<A>>::type
inverse(A const &a, B det) {
  typedef typename mat_traits<A>::scalar_type T;
  BOOST_QVM_ASSERT(det != scalar_traits<B>::value(0));
  T const a00 = mat_traits<A>::template read_element<0, 0>(a);
  T const a01 = mat_traits<A>::template read_element<0, 1>(a);
  T const a10 = mat_traits<A>::template read_element<1, 0>(a);
  T const a11 = mat_traits<A>::template read_element<1, 1>(a);
  T const f = scalar_traits<T>::value(1) / det;
  typedef typename deduce_mat<A>::type R;
  R r;
  mat_traits<R>::template write_element<0, 0>(r) = f * a11;
  mat_traits<R>::template write_element<0, 1>(r) = -f * a01;
  mat_traits<R>::template write_element<1, 0>(r) = -f * a10;
  mat_traits<R>::template write_element<1, 1>(r) = f * a00;
  return r;
}

template <class A>
BOOST_QVM_INLINE_OPERATIONS typename lazy_enable_if_c<
    mat_traits<A>::rows == 2 && mat_traits<A>::cols == 2, deduce_mat<A>>::type
inverse(A const &a) {
  typedef typename mat_traits<A>::scalar_type T;
  T det = determinant(a);
  if (det == scalar_traits<T>::value(0))
    BOOST_QVM_THROW_EXCEPTION(zero_determinant_error());
  return inverse(a, det);
}

namespace sfinae {
using ::boost::qvm::inverse;
}

namespace qvm_detail {
template <int D> struct inverse_m_defined;

template <> struct inverse_m_defined<2> { static bool const value = true; };
} // namespace qvm_detail

template <class A, class B>
BOOST_QVM_INLINE_OPERATIONS typename lazy_enable_if_c<
    mat_traits<A>::rows == 2 && mat_traits<B>::rows == 2 &&
        mat_traits<A>::cols == 2 && mat_traits<B>::cols == 2,
    deduce_mat2<A, B, 2, 2>>::type
operator*(A const &a, B const &b) {
  typedef typename mat_traits<A>::scalar_type Ta;
  typedef typename mat_traits<B>::scalar_type Tb;
  Ta const a00 = mat_traits<A>::template read_element<0, 0>(a);
  Ta const a01 = mat_traits<A>::template read_element<0, 1>(a);
  Ta const a10 = mat_traits<A>::template read_element<1, 0>(a);
  Ta const a11 = mat_traits<A>::template read_element<1, 1>(a);
  Tb const b00 = mat_traits<B>::template read_element<0, 0>(b);
  Tb const b01 = mat_traits<B>::template read_element<0, 1>(b);
  Tb const b10 = mat_traits<B>::template read_element<1, 0>(b);
  Tb const b11 = mat_traits<B>::template read_element<1, 1>(b);
  typedef typename deduce_mat2<A, B, 2, 2>::type R;
  BOOST_QVM_STATIC_ASSERT(mat_traits<R>::rows == 2);
  BOOST_QVM_STATIC_ASSERT(mat_traits<R>::cols == 2);
  R r;
  mat_traits<R>::template write_element<0, 0>(r) = a00 * b00 + a01 * b10;
  mat_traits<R>::template write_element<0, 1>(r) = a00 * b01 + a01 * b11;
  mat_traits<R>::template write_element<1, 0>(r) = a10 * b00 + a11 * b10;
  mat_traits<R>::template write_element<1, 1>(r) = a10 * b01 + a11 * b11;
  return r;
}

namespace sfinae {
using ::boost::qvm::operator*;
}

namespace qvm_detail {
template <int R, int CR, int C> struct mul_mm_defined;

template <> struct mul_mm_defined<2, 2, 2> { static bool const value = true; };
} // namespace qvm_detail

template <class A, class B>
BOOST_QVM_INLINE_OPERATIONS
    typename enable_if_c<mat_traits<A>::rows == 2 && mat_traits<B>::rows == 2 &&
                             mat_traits<A>::cols == 2 &&
                             mat_traits<B>::cols == 2,
                         A &>::type
    operator*=(A &a, B const &b) {
  typedef typename mat_traits<A>::scalar_type Ta;
  typedef typename mat_traits<B>::scalar_type Tb;
  Ta const a00 = mat_traits<A>::template read_element<0, 0>(a);
  Ta const a01 = mat_traits<A>::template read_element<0, 1>(a);
  Ta const a10 = mat_traits<A>::template read_element<1, 0>(a);
  Ta const a11 = mat_traits<A>::template read_element<1, 1>(a);
  Tb const b00 = mat_traits<B>::template read_element<0, 0>(b);
  Tb const b01 = mat_traits<B>::template read_element<0, 1>(b);
  Tb const b10 = mat_traits<B>::template read_element<1, 0>(b);
  Tb const b11 = mat_traits<B>::template read_element<1, 1>(b);
  mat_traits<A>::template write_element<0, 0>(a) = a00 * b00 + a01 * b10;
  mat_traits<A>::template write_element<0, 1>(a) = a00 * b01 + a01 * b11;
  mat_traits<A>::template write_element<1, 0>(a) = a10 * b00 + a11 * b10;
  mat_traits<A>::template write_element<1, 1>(a) = a10 * b01 + a11 * b11;
  return a;
}

namespace sfinae {
using ::boost::qvm::operator*=;
}

namespace qvm_detail {
template <int D> struct mul_eq_mm_defined;

template <> struct mul_eq_mm_defined<2> { static bool const value = true; };
} // namespace qvm_detail

template <class A, class B>
BOOST_QVM_INLINE_OPERATIONS typename lazy_enable_if_c<
    mat_traits<A>::rows == 2 && mat_traits<B>::rows == 2 &&
        mat_traits<A>::cols == 2 && mat_traits<B>::cols == 1,
    deduce_mat2<A, B, 2, 1>>::type
operator*(A const &a, B const &b) {
  typedef typename mat_traits<A>::scalar_type Ta;
  typedef typename mat_traits<B>::scalar_type Tb;
  Ta const a00 = mat_traits<A>::template read_element<0, 0>(a);
  Ta const a01 = mat_traits<A>::template read_element<0, 1>(a);
  Ta const a10 = mat_traits<A>::template read_element<1, 0>(a);
  Ta const a11 = mat_traits<A>::template read_element<1, 1>(a);
  Tb const b00 = mat_traits<B>::template read_element<0, 0>(b);
  Tb const b10 = mat_traits<B>::template read_element<1, 0>(b);
  typedef typename deduce_mat2<A, B, 2, 1>::type R;
  BOOST_QVM_STATIC_ASSERT(mat_traits<R>::rows == 2);
  BOOST_QVM_STATIC_ASSERT(mat_traits<R>::cols == 1);
  R r;
  mat_traits<R>::template write_element<0, 0>(r) = a00 * b00 + a01 * b10;
  mat_traits<R>::template write_element<1, 0>(r) = a10 * b00 + a11 * b10;
  return r;
}

namespace sfinae {
using ::boost::qvm::operator*;
}

namespace qvm_detail {
template <int R, int CR, int C> struct mul_mm_defined;

template <> struct mul_mm_defined<2, 2, 1> { static bool const value = true; };
} // namespace qvm_detail

template <class A, class B>
BOOST_QVM_INLINE_OPERATIONS typename lazy_enable_if_c<
    mat_traits<A>::rows == 1 && mat_traits<B>::rows == 2 &&
        mat_traits<A>::cols == 2 && mat_traits<B>::cols == 2,
    deduce_mat2<A, B, 1, 2>>::type
operator*(A const &a, B const &b) {
  typedef typename mat_traits<A>::scalar_type Ta;
  typedef typename mat_traits<B>::scalar_type Tb;
  Ta const a00 = mat_traits<A>::template read_element<0, 0>(a);
  Ta const a01 = mat_traits<A>::template read_element<0, 1>(a);
  Tb const b00 = mat_traits<B>::template read_element<0, 0>(b);
  Tb const b01 = mat_traits<B>::template read_element<0, 1>(b);
  Tb const b10 = mat_traits<B>::template read_element<1, 0>(b);
  Tb const b11 = mat_traits<B>::template read_element<1, 1>(b);
  typedef typename deduce_mat2<A, B, 1, 2>::type R;
  BOOST_QVM_STATIC_ASSERT(mat_traits<R>::rows == 1);
  BOOST_QVM_STATIC_ASSERT(mat_traits<R>::cols == 2);
  R r;
  mat_traits<R>::template write_element<0, 0>(r) = a00 * b00 + a01 * b10;
  mat_traits<R>::template write_element<0, 1>(r) = a00 * b01 + a01 * b11;
  return r;
}

namespace sfinae {
using ::boost::qvm::operator*;
}

namespace qvm_detail {
template <int R, int CR, int C> struct mul_mm_defined;

template <> struct mul_mm_defined<1, 2, 2> { static bool const value = true; };
} // namespace qvm_detail

} // namespace qvm
} // namespace boost

#endif

max_stars_repo_name: henrywarhurst/matrix

max_issues_repo_name: henrywarhurst/matrix

max_forks_repo_name: henrywarhurst/matrix


text:
#include "trtretinafacenet.h"
#include "trtutility.h"
#include <map>
#include <boost/bind/bind.hpp>
#include <assert.h>

using namespace std;

TrtRetinaFaceNet::TrtRetinaFaceNet(string netWorkName) : TrtNetBase(netWorkName)
{
    numBinding = 10;
    buffers = new void *[numBinding];
    for (int i = 0; i < numBinding; i++)
    {
        buffers[i] = NULL;
    }

    inputBuffer = NULL;

    workSpaceSize = 1 << 24;
    maxBatchSize = 8;

    outputs = {"face_rpn_cls_prob_reshape_stride32",
               "face_rpn_bbox_pred_stride32",
               "face_rpn_landmark_pred_stride32",
               "face_rpn_cls_prob_reshape_stride16",
               "face_rpn_bbox_pred_stride16",
               "face_rpn_landmark_pred_stride16",
               "face_rpn_cls_prob_reshape_stride8",
               "face_rpn_bbox_pred_stride8",
               "face_rpn_landmark_pred_stride8"};

    for(size_t i = 0; i < outputs.size(); i++) {
        outputBuffers.push_back(NULL);
    }

    results.resize(outputs.size());
    for(size_t i = 0; i < outputs.size(); i++) {
        results[i].layer_name = outputs[i];
    }
}

TrtRetinaFaceNet::~TrtRetinaFaceNet()
{
    delete []buffers;
}

void TrtRetinaFaceNet::doInference(int batchSize, float *input)
{
    if (!enableTrtProfiler) {
        cudaStream_t stream;
        CHECK(cudaStreamCreate(&stream));
        // DMA the input to the GPU,  execute the batch asynchronously
        // and DMA it back
        if (input != NULL) {  //NULL means we have use GPU to map memory
            inputSize = batchSize * inputDims.c() * inputDims.h() * inputDims.w() * sizeof(float);
            CHECK(cudaMemcpyAsync(buffers[inputIndex], input, inputSize, cudaMemcpyDeviceToDevice, stream));
        }

        context->enqueue(batchSize, buffers, stream, nullptr);

        //异步拷贝是否需要pinned memory?
        for(size_t i = 0; i < outputDims.size(); i++){
            //只拷贝batch大小，因为开辟空间是maxBatchSize，如果batch < maxbatch,则拷贝浪费时间
            CHECK(cudaMemcpyAsync(outputBuffers[i], buffers[outputIndexs[i]],
                  batchSize * outputsizes[i] / maxBatchSize,
                  cudaMemcpyDeviceToHost, stream));
        }

        cudaStreamSynchronize(stream);
        // release the stream and the buffers
        cudaStreamDestroy(stream);
    }
    else {
        // DMA the input to the GPU, execute the batch synchronously
        // and DMA it back
        if (input != NULL) {   //NULL means we have use GPU to map memory
            inputSize = batchSize * inputDims.c() * inputDims.h() * inputDims.w() * sizeof(float);
            CHECK(cudaMemcpy(buffers[inputIndex], input, inputSize, cudaMemcpyDeviceToDevice));
        }

        context->execute(batchSize, buffers);

        for(size_t i = 0; i < outputDims.size(); i++){
            CHECK(cudaMemcpyAsync(outputBuffers[i], buffers[outputIndexs[i]], outputsizes[i], cudaMemcpyDeviceToHost));
        }
    }

    //output to vector
    for(size_t i = 0; i < outputBuffers.size(); i++){
        int count = outputsizes[i] / (sizeof(float) * maxBatchSize);
        results[i].result.clear();
        for(int j = 0; j < batchSize; j++) {
            const float* confidenceBegin = outputBuffers[i] + j * count;
            const float* confidenceEnd = confidenceBegin + count;
            std::vector<float> ret = std::vector<float>(confidenceBegin, confidenceEnd);
            results[i].result.push_back(ret);
        }

        results[i].batchsize = batchSize;
    }
}

TrtBlob* TrtRetinaFaceNet::blob_by_name(string layer_name)
{
    vector<TrtBlob>::iterator it =
            std::find_if(results.begin(), results.end(), boost::bind(&TrtBlob::layer_name, _1) == layer_name);

    if(it == results.end()) {
        return NULL;
    }

    return &(*it);
}

vector<int> TrtRetinaFaceNet::getOutputWidth()
{
    //返回每个fpn输出宽
    if(outputDims.size() == 0) {
        return vector<int>();
    }

    vector<int> out;
    out.push_back(outputDims[0].w());
    out.push_back(outputDims[3].w());
    out.push_back(outputDims[6].w());

    return out;
}

vector<int> TrtRetinaFaceNet::getOutputHeight()
{
    //返回每个fpn输出高
    if(outputDims.size() == 0) {
        return vector<int>();
    }

    vector<int> out;
    out.push_back(outputDims[0].h());
    out.push_back(outputDims[3].h());
    out.push_back(outputDims[6].h());

    return out;
}

void TrtRetinaFaceNet::allocateMemory(bool bUseCPUBuf)
{
    const ICudaEngine& cudaEngine = context->getEngine();
    // input and output buffer pointers that we pass to the engine
    // the engine requires exactly IEngine::getNbBindings() of these
    // but in this case we know that there is exactly one input and one output
    assert(cudaEngine.getNbBindings() == numBinding);

    // In order to bind the buffers, we need to know the names of the input
    // and output tensors. note that indices are guaranteed to be less than
    // IEngine::getNbBindings()
    inputIndex = cudaEngine.getBindingIndex(inputBlobName.c_str());
    outputIndexs.resize(outputs.size());
    for(size_t i = 0; i < outputs.size(); i++){
        int idx = cudaEngine.getBindingIndex(outputs[i].c_str());
        outputIndexs[i] = idx;
        results[i].layer_index = idx;
    }

    // allocate GPU buffers
    inputDims = static_cast<DimsCHW&&>(cudaEngine.getBindingDimensions(inputIndex));

    outputDims.resize(outputIndexs.size());
    for(size_t i = 0; i < outputIndexs.size(); i++){
        DimsCHW dim = static_cast<DimsCHW&&>(cudaEngine.getBindingDimensions(outputIndexs[i]));
        outputDims[i] = dim;
        results[i].outputDims = dim;
    }

    inputSize = maxBatchSize * inputDims.c() * inputDims.h() * inputDims.w() * sizeof(float);

    outputsizes.resize(outputDims.size());
    for(size_t i = 0; i < outputDims.size(); i++){
        size_t sz = maxBatchSize * outputDims[i].c() * outputDims[i].h() * outputDims[i].w() * sizeof(float);
        outputsizes[i] = sz;
        results[i].outputSize = sz;
    }

    if (bUseCPUBuf && inputBuffer == NULL) {
        inputBuffer = (float *)malloc(inputSize);
        assert(inputBuffer != NULL);
    }

    for(size_t i = 0; i < outputBuffers.size(); i++){
        if (outputBuffers[i] == NULL) {
            outputBuffers[i] = (float *)malloc(outputsizes[i]);
            assert(outputBuffers[i] != NULL);
        }
    }

    // create GPU buffers and a stream
    if (buffers[inputIndex] == NULL) {
        CHECK(cudaMalloc(&buffers[inputIndex], inputSize));
    }

    for(size_t i = 0; i < outputIndexs.size(); i++){
        if (buffers[outputIndexs[i]] == NULL) {
            CHECK(cudaMalloc(&buffers[outputIndexs[i]], outputsizes[i]));
        }
    }

    if (dumpResult) {
        fstream.open(resultFile.c_str(), ios::out);
    }
}

void TrtRetinaFaceNet::releaseMemory(bool bUseCPUBuf)
{
    for (int i = 0; i < numBinding; i++) {
        if (buffers[i] != NULL) {
            CHECK(cudaFree(buffers[i]));
            buffers[i] = NULL;
        }
    }

    if (bUseCPUBuf && inputBuffer != NULL) {
        free(inputBuffer);
        inputBuffer = NULL;
    }

    for(size_t i = 0; i < outputBuffers.size(); i++){
        if (outputBuffers[i] != NULL) {
            free(outputBuffers[i]);
            outputBuffers[i] = NULL;
        }
    }

    if (dumpResult) {
        fstream.close();
    }
}

max_stars_repo_name: cbwces/retinaface

max_issues_repo_name: cbwces/retinaface

max_forks_repo_name: cbwces/retinaface