text:
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wsign-compare"
#include <boost/test/unit_test.hpp>
#pragma GCC diagnostic pop
#include <boost/algorithm/string/predicate.hpp>
#include <bcio/testing/tester.hpp>
#include <bcio/chain/abi_serializer.hpp>
#include <bcio/chain/generated_transaction_object.hpp>

#include <bcio.token/bcio.token.wast.hpp>
#include <bcio.token/bcio.token.abi.hpp>

#include <proxy/proxy.wast.hpp>
#include <proxy/proxy.abi.hpp>

#include <Runtime/Runtime.h>

#include <fc/variant_object.hpp>
#include <fc/io/json.hpp>

#ifdef NON_VALIDATING_TEST
#define TESTER tester
#else
#define TESTER validating_tester
#endif

using namespace bcio;
using namespace bcio::chain;
using namespace bcio::testing;
using namespace fc;

class currency_tester : public TESTER {
   public:

      auto push_action(const account_name& signer, const action_name &name, const variant_object &data ) {
         string action_type_name = abi_ser.get_action_type(name);

         action act;
         act.account = N(bcio.token);
         act.name = name;
         act.authorization = vector<permission_level>{{signer, config::active_name}};
         act.data = abi_ser.variant_to_binary(action_type_name, data, abi_serializer_max_time);

         signed_transaction trx;
         trx.actions.emplace_back(std::move(act));

         set_transaction_headers(trx);
         trx.sign(get_private_key(signer, "active"), control->get_chain_id());
         return push_transaction(trx);
      }

      asset get_balance(const account_name& account) const {
         return get_currency_balance(N(bcio.token), symbol(SY(4,CUR)), account);
      }

      auto transfer(const account_name& from, const account_name& to, const std::string& quantity, const std::string& memo = "") {
         auto trace = push_action(from, N(transfer), mutable_variant_object()
                                  ("from",     from)
                                  ("to",       to)
                                  ("quantity", quantity)
                                  ("memo",     memo)
                                  );
         produce_block();
         return trace;
      }

      auto issue(const account_name& to, const std::string& quantity, const std::string& memo = "") {
         auto trace = push_action(N(bcio.token), N(issue), mutable_variant_object()
                                  ("to",       to)
                                  ("quantity", quantity)
                                  ("memo",     memo)
                                  );
         produce_block();
         return trace;
      }

      currency_tester()
      :TESTER(),abi_ser(json::from_string(bcio_token_abi).as<abi_def>(), abi_serializer_max_time)
      {
         create_account( N(bcio.token));
         set_code( N(bcio.token), bcio_token_wast );

         auto result = push_action(N(bcio.token), N(create), mutable_variant_object()
                 ("issuer",       bcio_token)
                 ("maximum_supply", "1000000000.0000 CUR")
                 ("can_freeze", 0)
                 ("can_recall", 0)
                 ("can_whitelist", 0)
         );
         wdump((result));

         result = push_action(N(bcio.token), N(issue), mutable_variant_object()
                 ("to",       bcio_token)
                 ("quantity", "1000000.0000 CUR")
                 ("memo", "gggggggggggg")
         );
         wdump((result));
         produce_block();
      }

      abi_serializer abi_ser;
      static const std::string bcio_token;
};

const std::string currency_tester::bcio_token = name(N(bcio.token)).to_string();

BOOST_AUTO_TEST_SUITE(currency_tests)

BOOST_AUTO_TEST_CASE( bootstrap ) try {
   auto expected = asset::from_string( "1000000.0000 CUR" );
   currency_tester t;
   auto actual = t.get_currency_balance(N(bcio.token), expected.get_symbol(), N(bcio.token));
   BOOST_REQUIRE_EQUAL(expected, actual);
} FC_LOG_AND_RETHROW() /// test_api_bootstrap

BOOST_FIXTURE_TEST_CASE( test_transfer, currency_tester ) try {
   create_accounts( {N(alice)} );

   // make a transfer from the contract to a user
   {
      auto trace = push_action(N(bcio.token), N(transfer), mutable_variant_object()
         ("from", bcio_token)
         ("to",   "alice")
         ("quantity", "100.0000 CUR")
         ("memo", "fund Alice")
      );

      produce_block();

      BOOST_REQUIRE_EQUAL(true, chain_has_transaction(trace->id));
      BOOST_REQUIRE_EQUAL(get_balance(N(alice)), asset::from_string( "100.0000 CUR" ) );
   }
} FC_LOG_AND_RETHROW() /// test_transfer

BOOST_FIXTURE_TEST_CASE( test_duplicate_transfer, currency_tester ) {
   create_accounts( {N(alice)} );

   auto trace = push_action(N(bcio.token), N(transfer), mutable_variant_object()
      ("from", bcio_token)
      ("to",   "alice")
      ("quantity", "100.0000 CUR")
      ("memo", "fund Alice")
   );

   BOOST_REQUIRE_THROW(push_action(N(bcio.token), N(transfer), mutable_variant_object()
                                    ("from", bcio_token)
                                    ("to",   "alice")
                                    ("quantity", "100.0000 CUR")
                                    ("memo", "fund Alice")),
                       tx_duplicate);

   produce_block();

   BOOST_CHECK_EQUAL(true, chain_has_transaction(trace->id));
   BOOST_CHECK_EQUAL(get_balance(N(alice)), asset::from_string( "100.0000 CUR" ) );
}

BOOST_FIXTURE_TEST_CASE( test_addtransfer, currency_tester ) try {
   create_accounts( {N(alice)} );

   // make a transfer from the contract to a user
   {
      auto trace = push_action(N(bcio.token), N(transfer), mutable_variant_object()
         ("from", bcio_token)
         ("to",   "alice")
         ("quantity", "100.0000 CUR")
         ("memo", "fund Alice")
      );

      produce_block();

      BOOST_REQUIRE_EQUAL(true, chain_has_transaction(trace->id));
      BOOST_REQUIRE_EQUAL(get_balance(N(alice)), asset::from_string( "100.0000 CUR" ));
   }

   // make a transfer from the contract to a user
   {
      auto trace = push_action(N(bcio.token), N(transfer), mutable_variant_object()
         ("from", bcio_token)
         ("to",   "alice")
         ("quantity", "10.0000 CUR")
         ("memo", "add Alice")
      );

      produce_block();

      BOOST_REQUIRE_EQUAL(true, chain_has_transaction(trace->id));
      BOOST_REQUIRE_EQUAL(get_balance(N(alice)), asset::from_string( "110.0000 CUR" ));
   }
} FC_LOG_AND_RETHROW() /// test_transfer

BOOST_FIXTURE_TEST_CASE( test_overspend, currency_tester ) try {
   create_accounts( {N(alice), N(bob)} );

   // make a transfer from the contract to a user
   {
      auto trace = push_action(N(bcio.token), N(transfer), mutable_variant_object()
         ("from", bcio_token)
         ("to",   "alice")
         ("quantity", "100.0000 CUR")
         ("memo", "fund Alice")
      );

      produce_block();

      BOOST_REQUIRE_EQUAL(true, chain_has_transaction(trace->id));
      BOOST_REQUIRE_EQUAL(get_balance(N(alice)), asset::from_string( "100.0000 CUR" ));
   }

   // Overspend!
   {
      variant_object data = mutable_variant_object()
         ("from", "alice")
         ("to",   "bob")
         ("quantity", "101.0000 CUR")
         ("memo", "overspend! Alice");

      BOOST_CHECK_EXCEPTION( push_action(N(alice), N(transfer), data),
                             bcio_assert_message_exception, bcio_assert_message_is("overdrawn balance") );
      produce_block();

      BOOST_REQUIRE_EQUAL(get_balance(N(alice)), asset::from_string( "100.0000 CUR" ));
      BOOST_REQUIRE_EQUAL(get_balance(N(bob)), asset::from_string( "0.0000 CUR" ));
   }
} FC_LOG_AND_RETHROW() /// test_overspend

BOOST_FIXTURE_TEST_CASE( test_fullspend, currency_tester ) try {
   create_accounts( {N(alice), N(bob)} );

   // make a transfer from the contract to a user
   {
      auto trace = push_action(N(bcio.token), N(transfer), mutable_variant_object()
         ("from", bcio_token)
         ("to",   "alice")
         ("quantity", "100.0000 CUR")
         ("memo", "fund Alice")
      );

      produce_block();

      BOOST_REQUIRE_EQUAL(true, chain_has_transaction(trace->id));
      BOOST_REQUIRE_EQUAL(get_balance(N(alice)), asset::from_string( "100.0000 CUR" ));
   }

   // Full spend
   {
      variant_object data = mutable_variant_object()
         ("from", "alice")
         ("to",   "bob")
         ("quantity", "100.0000 CUR")
         ("memo", "all in! Alice");

      auto trace = push_action(N(alice), N(transfer), data);
      produce_block();

      BOOST_REQUIRE_EQUAL(true, chain_has_transaction(trace->id));
      BOOST_REQUIRE_EQUAL(get_balance(N(alice)), asset::from_string( "0.0000 CUR" ));
      BOOST_REQUIRE_EQUAL(get_balance(N(bob)), asset::from_string( "100.0000 CUR" ));
   }

} FC_LOG_AND_RETHROW() /// test_fullspend

BOOST_FIXTURE_TEST_CASE(test_symbol, TESTER) try {

   {
      symbol dollar(2, "DLLR");
      BOOST_REQUIRE_EQUAL(SY(2, DLLR), dollar.value());
      BOOST_REQUIRE_EQUAL(2, dollar.decimals());
      BOOST_REQUIRE_EQUAL(100, dollar.precision());
      BOOST_REQUIRE_EQUAL("DLLR", dollar.name());
      BOOST_REQUIRE_EQUAL(true, dollar.valid());
   }

   {
      symbol sys(4, "SYS");
      BOOST_REQUIRE_EQUAL(SY(4,SYS), sys.value());
      BOOST_REQUIRE_EQUAL("4,SYS", sys.to_string());
      BOOST_REQUIRE_EQUAL("SYS", sys.name());
      BOOST_REQUIRE_EQUAL(4, sys.decimals());
   }

   // default is "4,${CORE_SYMBOL_NAME}"
   {
      symbol def;
      BOOST_REQUIRE_EQUAL(4, def.decimals());
      BOOST_REQUIRE_EQUAL(CORE_SYMBOL_NAME, def.name());
   }
   // from string
   {
      symbol y = symbol::from_string("3,YEN");
      BOOST_REQUIRE_EQUAL(3, y.decimals());
      BOOST_REQUIRE_EQUAL("YEN", y.name());
   }

   // from empty string
   {
      BOOST_CHECK_EXCEPTION(symbol::from_string(""),
                            symbol_type_exception, fc_exception_message_is("creating symbol from empty string"));
   }

   // precision part missing
   {
      BOOST_CHECK_EXCEPTION(symbol::from_string("RND"),
                            symbol_type_exception, fc_exception_message_is("missing comma in symbol"));
   }

   // 0 decimals part
   {
      symbol sym = symbol::from_string("0,EURO");
      BOOST_REQUIRE_EQUAL(0, sym.decimals());
      BOOST_REQUIRE_EQUAL("EURO", sym.name());
   }

   // invalid - contains lower case characters, no validation
   {
      BOOST_CHECK_EXCEPTION(symbol malformed(SY(6,EoS)),
                            symbol_type_exception, fc_exception_message_is("invalid symbol: EoS"));
   }

   // invalid - contains lower case characters, exception thrown
   {
      BOOST_CHECK_EXCEPTION(symbol(5,"EoS"),
                            symbol_type_exception, fc_exception_message_is("invalid character in symbol name"));
   }

   // Missing decimal point, should create asset with 0 decimals
   {
      asset a = asset::from_string("10 CUR");
      BOOST_REQUIRE_EQUAL(a.get_amount(), 10);
      BOOST_REQUIRE_EQUAL(a.precision(), 1);
      BOOST_REQUIRE_EQUAL(a.decimals(), 0);
      BOOST_REQUIRE_EQUAL(a.symbol_name(), "CUR");
   }

   // Missing space
   {
      BOOST_CHECK_EXCEPTION(asset::from_string("10CUR"),
                            asset_type_exception, fc_exception_message_is("Asset's amount and symbol should be separated with space"));
   }

   // Precision is not specified when decimal separator is introduced
   {
      BOOST_CHECK_EXCEPTION(asset::from_string("10. CUR"),
                            asset_type_exception, fc_exception_message_is("Missing decimal fraction after decimal point"));
   }

   // Missing symbol
   {
      BOOST_CHECK_EXCEPTION(asset::from_string("10"),
                            asset_type_exception, fc_exception_message_is("Asset's amount and symbol should be separated with space"));
   }

   // Multiple spaces
   {
      asset a = asset::from_string("1000000000.00000  CUR");
      BOOST_REQUIRE_EQUAL(a.get_amount(), 100000000000000);
      BOOST_REQUIRE_EQUAL(a.decimals(), 5);
      BOOST_REQUIRE_EQUAL(a.symbol_name(), "CUR");
      BOOST_REQUIRE_EQUAL(a.to_string(), "1000000000.00000 CUR");
   }

   // Valid asset
   {
      asset a = asset::from_string("1000000000.00000 CUR");
      BOOST_REQUIRE_EQUAL(a.get_amount(), 100000000000000);
      BOOST_REQUIRE_EQUAL(a.decimals(), 5);
      BOOST_REQUIRE_EQUAL(a.symbol_name(), "CUR");
      BOOST_REQUIRE_EQUAL(a.to_string(), "1000000000.00000 CUR");
   }

   // Negative asset
   {
      asset a = asset::from_string("-001000000.00010 CUR");
      BOOST_REQUIRE_EQUAL(a.get_amount(), -100000000010);
      BOOST_REQUIRE_EQUAL(a.decimals(), 5);
      BOOST_REQUIRE_EQUAL(a.symbol_name(), "CUR");
      BOOST_REQUIRE_EQUAL(a.to_string(), "-1000000.00010 CUR");
   }

   // Negative asset below 1
   {
      asset a = asset::from_string("-000000000.00100 CUR");
      BOOST_REQUIRE_EQUAL(a.get_amount(), -100);
      BOOST_REQUIRE_EQUAL(a.decimals(), 5);
      BOOST_REQUIRE_EQUAL(a.symbol_name(), "CUR");
      BOOST_REQUIRE_EQUAL(a.to_string(), "-0.00100 CUR");
   }

   // Negative asset below 1
   {
      asset a = asset::from_string("-0.0001 PPP");
      BOOST_REQUIRE_EQUAL(a.get_amount(), -1);
      BOOST_REQUIRE_EQUAL(a.decimals(), 4);
      BOOST_REQUIRE_EQUAL(a.symbol_name(), "PPP");
      BOOST_REQUIRE_EQUAL(a.to_string(), "-0.0001 PPP");
   }

} FC_LOG_AND_RETHROW() /// test_symbol

BOOST_FIXTURE_TEST_CASE( test_proxy, currency_tester ) try {
   produce_blocks(2);

   create_accounts( {N(alice), N(proxy)} );
   produce_block();

   set_code(N(proxy), proxy_wast);
   produce_blocks(1);

   abi_serializer proxy_abi_ser(json::from_string(proxy_abi).as<abi_def>(), abi_serializer_max_time);

   // set up proxy owner
   {
      signed_transaction trx;
      action setowner_act;
      setowner_act.account = N(proxy);
      setowner_act.name = N(setowner);
      setowner_act.authorization = vector<permission_level>{{N(alice), config::active_name}};
      setowner_act.data = proxy_abi_ser.variant_to_binary("setowner", mutable_variant_object()
         ("owner", "alice")
         ("delay", 10),
         abi_serializer_max_time
      );
      trx.actions.emplace_back(std::move(setowner_act));

      set_transaction_headers(trx);
      trx.sign(get_private_key(N(alice), "active"), control->get_chain_id());
      push_transaction(trx);
      produce_block();
      BOOST_REQUIRE_EQUAL(true, chain_has_transaction(trx.id()));
   }

   // for now wasm "time" is in seconds, so we have to truncate off any parts of a second that may have applied
   fc::time_point expected_delivery(fc::seconds(control->head_block_time().sec_since_epoch()) + fc::seconds(10));
   {
      auto trace = push_action(N(bcio.token), N(transfer), mutable_variant_object()
         ("from", bcio_token)
         ("to",   "proxy")
         ("quantity", "5.0000 CUR")
         ("memo", "fund Proxy")
      );
   }

   while(control->head_block_time() < expected_delivery) {
      produce_block();
      BOOST_REQUIRE_EQUAL(get_balance( N(proxy)), asset::from_string("5.0000 CUR"));
      BOOST_REQUIRE_EQUAL(get_balance( N(alice)),   asset::from_string("0.0000 CUR"));
   }

   produce_block();
   BOOST_REQUIRE_EQUAL(get_balance( N(proxy)), asset::from_string("0.0000 CUR"));
   BOOST_REQUIRE_EQUAL(get_balance( N(alice)),   asset::from_string("5.0000 CUR"));

} FC_LOG_AND_RETHROW() /// test_currency

BOOST_FIXTURE_TEST_CASE( test_deferred_failure, currency_tester ) try {
   produce_blocks(2);

   create_accounts( {N(alice), N(bob), N(proxy)} );
   produce_block();

   set_code(N(proxy), proxy_wast);
   set_code(N(bob), proxy_wast);
   produce_blocks(1);

   abi_serializer proxy_abi_ser(json::from_string(proxy_abi).as<abi_def>(), abi_serializer_max_time);

   // set up proxy owner
   {
      signed_transaction trx;
      action setowner_act;
      setowner_act.account = N(proxy);
      setowner_act.name = N(setowner);
      setowner_act.authorization = vector<permission_level>{{N(bob), config::active_name}};
      setowner_act.data = proxy_abi_ser.variant_to_binary("setowner", mutable_variant_object()
         ("owner", "bob")
         ("delay", 10),
         abi_serializer_max_time
      );
      trx.actions.emplace_back(std::move(setowner_act));

      set_transaction_headers(trx);
      trx.sign(get_private_key(N(bob), "active"), control->get_chain_id());
      push_transaction(trx);
      produce_block();
      BOOST_REQUIRE_EQUAL(true, chain_has_transaction(trx.id()));
   }
   const auto& index = control->db().get_index<generated_transaction_multi_index,by_trx_id>();
   BOOST_REQUIRE_EQUAL(0, index.size());

   auto trace = push_action(N(bcio.token), N(transfer), mutable_variant_object()
      ("from", bcio_token)
      ("to",   "proxy")
      ("quantity", "5.0000 CUR")
      ("memo", "fund Proxy")
   );
   fc::time_point expected_delivery = control->pending_block_time() + fc::seconds(10);

   BOOST_REQUIRE_EQUAL(1, index.size());
   auto deferred_id = index.begin()->trx_id;
   BOOST_REQUIRE_EQUAL(false, chain_has_transaction(deferred_id));

   while( control->pending_block_time() < expected_delivery ) {
      produce_block();
      BOOST_REQUIRE_EQUAL(get_balance( N(proxy)), asset::from_string("5.0000 CUR"));
      BOOST_REQUIRE_EQUAL(get_balance( N(bob)),   asset::from_string("0.0000 CUR"));
      BOOST_REQUIRE_EQUAL(get_balance( N(bob)),   asset::from_string("0.0000 CUR"));
      BOOST_REQUIRE_EQUAL(1, index.size());
      BOOST_REQUIRE_EQUAL(false, chain_has_transaction(deferred_id));
   }

   fc::time_point expected_redelivery = control->pending_block_time() + fc::seconds(10);
   // First deferred transaction should be retired in this block.
   // It will fail, and its onerror handler will reschedule the transaction for 10 seconds later.
   produce_block();
   BOOST_REQUIRE_EQUAL(1, index.size()); // Still one because the first deferred transaction retires but the second is created at the same time.
   BOOST_REQUIRE_EQUAL(get_transaction_receipt(deferred_id).status, transaction_receipt::soft_fail);
   auto deferred2_id = index.begin()->trx_id;

   // set up alice owner
   {
      signed_transaction trx;
      action setowner_act;
      setowner_act.account = N(bob);
      setowner_act.name = N(setowner);
      setowner_act.authorization = vector<permission_level>{{N(alice), config::active_name}};
      setowner_act.data = proxy_abi_ser.variant_to_binary("setowner", mutable_variant_object()
         ("owner", "alice")
         ("delay", 0),
         abi_serializer_max_time
      );
      trx.actions.emplace_back(std::move(setowner_act));

      set_transaction_headers(trx);
      trx.sign(get_private_key(N(alice), "active"), control->get_chain_id());
      push_transaction(trx);
      produce_block();
      BOOST_REQUIRE_EQUAL(true, chain_has_transaction(trx.id()));
   }

   while( control->pending_block_time() < expected_redelivery ) {
      produce_block();
      BOOST_REQUIRE_EQUAL(get_balance( N(proxy)), asset::from_string("5.0000 CUR"));
      BOOST_REQUIRE_EQUAL(get_balance( N(alice)),   asset::from_string("0.0000 CUR"));
      BOOST_REQUIRE_EQUAL(get_balance( N(bob)),   asset::from_string("0.0000 CUR"));
      BOOST_REQUIRE_EQUAL(1, index.size());
      BOOST_REQUIRE_EQUAL(false, chain_has_transaction(deferred2_id));
   }

   BOOST_REQUIRE_EQUAL(1, index.size());

   // Second deferred transaction should be retired in this block and should succeed,
   // which should move tokens from the proxy contract to the bob contract, thereby trigger the bob contract to
   // schedule a third deferred transaction with no delay.
   // That third deferred transaction (which moves tokens from the bob contract to account alice) should be executed immediately
   // after in the same block (note that this is the current deferred transaction scheduling policy in tester and it may change).
   produce_block();
   BOOST_REQUIRE_EQUAL(0, index.size());
   BOOST_REQUIRE_EQUAL(get_transaction_receipt(deferred2_id).status, transaction_receipt::executed);

   BOOST_REQUIRE_EQUAL(get_balance( N(proxy)), asset::from_string("0.0000 CUR"));
   BOOST_REQUIRE_EQUAL(get_balance( N(alice)), asset::from_string("5.0000 CUR"));
   BOOST_REQUIRE_EQUAL(get_balance( N(bob)),   asset::from_string("0.0000 CUR"));

} FC_LOG_AND_RETHROW() /// test_currency

BOOST_FIXTURE_TEST_CASE( test_input_quantity, currency_tester ) try {

   produce_blocks(2);

   create_accounts( {N(alice), N(bob), N(carl)} );

   // transfer to alice using right precision
   {
      auto trace = transfer(bcio_token, N(alice), "100.0000 CUR");

      BOOST_CHECK_EQUAL(true, chain_has_transaction(trace->id));
      BOOST_CHECK_EQUAL(asset::from_string( "100.0000 CUR"), get_balance(N(alice)));
      BOOST_CHECK_EQUAL(1000000, get_balance(N(alice)).get_amount());
   }

   // transfer using different symbol name fails
   {
      BOOST_REQUIRE_THROW(transfer(N(alice), N(carl), "20.50 USD"), bcio_assert_message_exception);
   }

   // issue to alice using right precision
   {
      auto trace = issue(N(alice), "25.0256 CUR");

      BOOST_CHECK_EQUAL(true, chain_has_transaction(trace->id));
      BOOST_CHECK_EQUAL(asset::from_string("125.0256 CUR"), get_balance(N(alice)));
   }

} FC_LOG_AND_RETHROW() /// test_currency

BOOST_AUTO_TEST_SUITE_END()


text:
#include <Eigen/Eigen>
#include <opencv2/opencv.hpp>
#include "Halide.h"
extern "C" {
    #include "extApi.h"
}

// ------------ defs -------------//
#define SELECT_PERIOD 1          // controller period: 0 -> 0.035, 1 -> 0.065, 2 -> 0.1
#define DRAW_SLIDING_WINDOWS 1   // select whether to draw the sliding window while tracking
#define VREP_CAM 1               // select when VREP camera frames are used
//#define CARND_CAM 1            // select when CARND camera frames are used
#define RE_DRAW_IMAGE 1          // run re-draw image function

// ------------ class declarations -------------//
class vrepAPI {
private:
    // private membcvers
    // std::vector<std::vector<cv::Mat>> m_three_channels = std::vector<std::vector<cv::Mat>> (400);
    // std::vector<cv::Mat> m_out_Mat = std::vector<cv::Mat> (400, cv::Mat(256,512,CV_8UC3));
    int m_clientID, m_ping_time, m_cam, m_car, m_floor;
    int m_resolution[2];
    simxUChar* m_image;
    int m_nakedCar_steeringLeft, m_nakedCar_steeringRight;
    int m_nakedCar_motorLeft, m_nakedCar_motorRight;
    simxFloat m_position[3];
    double m_vx, m_desired_wheel_rot_speed;
    // private methods
    cv::Mat vrep_img_2_Mat();
public:
    // constructor
    vrepAPI();
    // destructor
    ~vrepAPI();
    // public methods
    void sim_delay(int time_step);
    cv::Mat sim_sense();
    void sim_actuate(std::vector<long double> the_steering_angles);
};

class laneDetection {
private:
    std::vector<long double> m_yL_container;
	std::vector<long double> m_ref_container;
    // private methods
    void bev_transform(cv::Mat& src, cv::Mat& dst);
    void bev_rev_transform(cv::Mat& src, cv::Mat& dst);
    std::vector<std::vector<cv::Point2f>> get_bev_points();
    std::vector<std::vector<cv::Point>> sliding_window_lane_tracking(cv::Mat& src);
    std::vector<long double> calculate_lateral_deviation(std::vector<cv::Point> left_lane_inds,
                                            std::vector<cv::Point> right_lane_inds);
    void lane_identification(std::vector<std::vector<cv::Point>> lanes, cv::Mat& src, cv::Mat& img_roi,
                            cv::Mat& img_warped, cv::Mat& img_lanes_temp, cv::Mat& img_detected_lanes,
                            cv::Mat& draw_lines, cv::Mat& diff_src_rebev, cv::Mat& img_rev_warped);
public:
    // constructor
    laneDetection();
    // destructor
    ~laneDetection();
    // class public methods
    long double lane_detection_pipeline(cv::Mat src);
    std::vector<long double> get_yL_container();
	std::vector<long double> get_ref_container();
};

class lateralController {
private:
	std::vector<long double> m_steering_angle_left_container;
	std::vector<long double> m_steering_angle_right_container;
    // member variables
    long double m_d, m_l, m_vx, m_LL, m_l_r;
    long double m_z1, m_z2, m_z3, m_z4, m_z5;
    std::vector<long double> m_input = std::vector<long double> (400);
    long double m_desired_steering_angle, m_steering_angle_left, m_steering_angle_right;
    std::vector< Eigen::Matrix<long double, 6, 6> > m_phi_aug
                                    = std::vector< Eigen::Matrix<long double, 6, 6> > (9);
    std::vector< Eigen::Matrix<long double, 6, 6> > m_T
                                    = std::vector< Eigen::Matrix<long double, 6, 6> > (9);
    std::vector< Eigen::Matrix<long double, 1, 5> > m_K2c
                                    = std::vector< Eigen::Matrix<long double, 1, 5> > (9);
    std::vector< Eigen::Matrix<long double, 6, 1> > m_Gamma_aug
                                    = std::vector< Eigen::Matrix<long double, 6, 1> > (9);
public:
    // constructor
    lateralController();
    // destructor
    ~lateralController();
    // class public methods
    void compute_steering_angles(long double the_yL, int the_it_counter, int the_pipe_version);
    std::vector<long double> get_steering_angles();
    void estimate_next_state(int the_it_counter, int the_pipe_version);
	std::vector<long double> get_steering_angle_left_container();
	std::vector<long double> get_steering_angle_right_container();
};

class imageSignalProcessing {
private:
    // class private methods
    cv::Mat run_pipeline(bool direction, cv::Mat the_img_in, int the_pipe_version);
    Halide::Runtime::Buffer<uint8_t> Mat2Image(cv::Mat *InMat);
	Halide::Buffer<uint8_t> Mat2ImageB(cv::Mat *InMat);
    cv::Mat Image2Mat(Halide::Runtime::Buffer<uint8_t> *InImage);
	Halide::Runtime::Buffer<float> Mat2Imagef(cv::Mat *InMat);
	cv::Mat Image2Matf( Halide::Buffer<float> *InImage );
	void OpenCV_remosaic (cv::Mat *InMat );
	Halide::Func make_scale(Halide::Buffer<uint8_t> *in_img );
public:
    // constructor
    imageSignalProcessing();
    // destructor
    ~imageSignalProcessing();
    // class public methods
    cv::Mat approximate_pipeline(cv::Mat the_img_vrep, int the_pipe_version);
};

// ------------ function declarations -------------//
template<class Container>
std::ostream& write_containers(	const Container& c1,
								const Container& c2,
								const Container& c3,
								std::ostream& out,
								char delimiter = ',')
{
	out << "lateral_deviation(m)";
	out << delimiter;
    bool write_sep = false;
    for (const auto& e: c1) {
        if (write_sep)
            out << delimiter;
        else
            write_sep = true;
        out << e;
    }

	out << "\n";
	out << "steering_angle(left)";
	out << delimiter;
    write_sep = false;
    for (const auto& e: c2) {
        if (write_sep)
            out << delimiter;
        else
            write_sep = true;
        out << e;
    }

	out << "\n";
	out << "steering_angle(right)";
	out << delimiter;
    write_sep = false;
    for (const auto& e: c3) {
        if (write_sep)
            out << delimiter;
        else
            write_sep = true;
        out << e;
    }

    return out;
}

template<class Container>
std::ostream& write_containers_wref(	const Container& c1,
								const Container& c4,
								const Container& c2,
								const Container& c3,
								std::ostream& out,
								char delimiter = ',')
{
	out << "lateral_deviation(m)";
	out << delimiter;
    bool write_sep = false;
    for (const auto& e: c1) {
        if (write_sep)
            out << delimiter;
        else
            write_sep = true;
        out << e;
    }

	out << "\n";
	out << "lane_reference(m)";
	out << delimiter;
    write_sep = false;
    for (const auto& e: c4) {
        if (write_sep)
            out << delimiter;
        else
            write_sep = true;
        out << e;
    }

	out << "\n";
	out << "steering_angle(left)";
	out << delimiter;
    write_sep = false;
    for (const auto& e: c2) {
        if (write_sep)
            out << delimiter;
        else
            write_sep = true;
        out << e;
    }

	out << "\n";
	out << "steering_angle(right)";
	out << delimiter;
    write_sep = false;
    for (const auto& e: c3) {
        if (write_sep)
            out << delimiter;
        else
            write_sep = true;
        out << e;
    }

    return out;
}

// void write_yL_2_file(std::vector<long double> yL_container, int pipeline_version);
std::string get_timestamp();

ext: hpp


text:
#include <cmdstan/command.hpp>
#include <boost/exception/diagnostic_information.hpp>
#include <boost/exception_ptr.hpp>

int main(int argc, const char* argv[]) {
  try {
    return stan::services::command<stan_model>(argc,argv);
  } catch (const std::exception& e) {
    std::cerr << std::endl << "Exception: " << e.what() << std::endl;
    std::cerr << "Diagnostic information: " << std::endl << boost::diagnostic_information(e) << std::endl;
    return -1;
  }
}

ext: cpp

max_stars_repo_name: guillefix/BayesianTumourGrowth

max_issues_repo_name: guillefix/BayesianTumourGrowth

max_forks_repo_name: guillefix/BayesianTumourGrowth


text:
#include <functional>
#include <iostream>
#include <list>
#include <memory>
#include <set>
#include <sstream>
#include <stdexcept>
#include <string>
#include <thread>
#include <unordered_set>

#include "baldr/rapidjson_utils.h"
#include <boost/property_tree/ptree.hpp>

#ifdef HAVE_HTTP
#include <prime_server/http_protocol.hpp>
#include <prime_server/prime_server.hpp>
using namespace prime_server;
#endif

#include "midgard/logging.h"

#include "loki/worker.h"
#include "odin/worker.h"
#include "thor/worker.h"
#include "tyr/actor.h"

int main(int argc, char** argv) {
#ifdef HAVE_HTTP
  if (argc < 2 || argc > 4) {
    LOG_ERROR("Usage: " + std::string(argv[0]) + " config/file.json [concurrency]");
    LOG_ERROR("Usage: " + std::string(argv[0]) + " config/file.json action json_request");
    return 1;
  }
#else
  if (argc < 4) {
    LOG_ERROR("Usage: " + std::string(argv[0]) + " config/file.json action json_request");
    return 1;
  }
#endif

  // config file
  // TODO: validate the config
  std::string config_file(argv[1]);
  boost::property_tree::ptree config;
  rapidjson::read_json(config_file, config);

  // one shot direct request mode
  if (argc == 4) {
    // because we want the program output to go only to stdout we force any logging to be stderr
    valhalla::midgard::logging::Configure({{"type", "std_err"}});

    // setup an object that can answer the request
    valhalla::tyr::actor_t actor(config);

    // figure out which action
    valhalla::Options::Action action;
    if (!valhalla::Options_Action_Enum_Parse(argv[2], &action)) {
      std::cerr << "Unknown action" << std::endl;
      return 1;
    }

    // do the right action
    valhalla::Api request;
    try {
      switch (action) {
        case valhalla::Options::route:
          std::cout << actor.route(argv[3], nullptr, &request) << std::endl;
          break;
        case valhalla::Options::locate:
          std::cout << actor.locate(argv[3], nullptr, &request) << std::endl;
          break;
        case valhalla::Options::sources_to_targets:
          std::cout << actor.matrix(argv[3], nullptr, &request) << std::endl;
          break;
        case valhalla::Options::optimized_route:
          std::cout << actor.optimized_route(argv[3], nullptr, &request) << std::endl;
          break;
        case valhalla::Options::isochrone:
          std::cout << actor.isochrone(argv[3], nullptr, &request) << std::endl;
          break;
        case valhalla::Options::trace_route:
          std::cout << actor.trace_route(argv[3], nullptr, &request) << std::endl;
          break;
        case valhalla::Options::trace_attributes:
          std::cout << actor.trace_attributes(argv[3], nullptr, &request) << std::endl;
          break;
        case valhalla::Options::height:
          std::cout << actor.height(argv[3], nullptr, &request) << std::endl;
          break;
        case valhalla::Options::transit_available:
          std::cout << actor.transit_available(argv[3], nullptr, &request) << std::endl;
          break;
        case valhalla::Options::expansion:
          std::cout << actor.expansion(argv[3], nullptr, &request) << std::endl;
          break;
        default:
          std::cerr << "Unknown action" << std::endl;
          return 1;
      }
    } // request processing error specific error condition
    catch (const valhalla::valhalla_exception_t& ve) {
      std::cout << valhalla::jsonify_error(ve, request) << std::endl;
      return 1;
    } // it was a regular exception!?
    catch (const std::exception& e) {
      std::cout << jsonify_error({599, std::string(e.what())}, request) << std::endl;
      return 1;
    } // anything else
    catch (...) {
      std::cout << jsonify_error({599, std::string("Unknown exception thrown")}, request)
                << std::endl;
      return 1;
    }

    // we are done
    return 0;
  }

#ifdef HAVE_HTTP
  // grab the endpoints
  std::string listen = config.get<std::string>("httpd.service.listen");
  std::string loopback = config.get<std::string>("httpd.service.loopback");
  std::string interrupt = config.get<std::string>("httpd.service.interrupt");
  std::string loki_proxy = config.get<std::string>("loki.service.proxy");
  std::string thor_proxy = config.get<std::string>("thor.service.proxy");
  std::string odin_proxy = config.get<std::string>("odin.service.proxy");
  // TODO: add multipoint accumulator worker

  // check the server endpoint
  if (listen.find("tcp://") != 0) {
    if (listen.find("ipc://") != 0) {
      LOG_ERROR("You must listen on either tcp://ip:port or ipc://some_socket_file");
      return EXIT_FAILURE;
    } else {
      LOG_WARN("Listening on a domain socket limits the server to local requests");
    }
  }

  // configure logging
  boost::optional<boost::property_tree::ptree&> logging_subtree =
      config.get_child_optional("tyr.logging");
  if (logging_subtree) {
    auto logging_config =
        valhalla::midgard::ToMap<const boost::property_tree::ptree&,
                                 std::unordered_map<std::string, std::string>>(logging_subtree.get());
    valhalla::midgard::logging::Configure(logging_config);
  }

  // number of workers to use at each stage
  auto worker_concurrency = std::thread::hardware_concurrency();
  if (argc > 2) {
    worker_concurrency = std::stoul(argv[2]);
  }

  // setup the cluster within this process
  zmq::context_t context;
  std::thread server_thread =
      std::thread(std::bind(&http_server_t::serve, http_server_t(context, listen, loki_proxy + "_in",
                                                                 loopback, interrupt, true)));

  // loki layer
  std::thread loki_proxy_thread(
      std::bind(&proxy_t::forward, proxy_t(context, loki_proxy + "_in", loki_proxy + "_out")));
  loki_proxy_thread.detach();
  std::list<std::thread> loki_worker_threads;
  for (size_t i = 0; i < worker_concurrency; ++i) {
    loki_worker_threads.emplace_back(valhalla::loki::run_service, config);
    loki_worker_threads.back().detach();
  }

  // thor layer
  std::thread thor_proxy_thread(
      std::bind(&proxy_t::forward, proxy_t(context, thor_proxy + "_in", thor_proxy + "_out")));
  thor_proxy_thread.detach();
  std::list<std::thread> thor_worker_threads;
  for (size_t i = 0; i < worker_concurrency; ++i) {
    thor_worker_threads.emplace_back(valhalla::thor::run_service, config);
    thor_worker_threads.back().detach();
  }

  // odin layer
  std::thread odin_proxy_thread(
      std::bind(&proxy_t::forward, proxy_t(context, odin_proxy + "_in", odin_proxy + "_out")));
  odin_proxy_thread.detach();
  std::list<std::thread> odin_worker_threads;
  for (size_t i = 0; i < worker_concurrency; ++i) {
    odin_worker_threads.emplace_back(valhalla::odin::run_service, config);
    odin_worker_threads.back().detach();
  }

  // TODO: add multipoint accumulator

  // wait forever (or for interrupt)
  server_thread.join();
#endif

  return 0;
}

ext: cc

max_stars_repo_name: genadz/valhalla

max_issues_repo_name: genadz/valhalla

max_forks_repo_name: genadz/valhalla


text:
//
// Copyright 2007-2012 Christian Henning, Lubomir Bourdev
//
// 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_GIL_EXTENSION_IO_TIFF_DETAIL_READER_HPP
#define BOOST_GIL_EXTENSION_IO_TIFF_DETAIL_READER_HPP

#include <boost/gil/extension/io/tiff/detail/device.hpp>
#include <boost/gil/extension/io/tiff/detail/is_allowed.hpp>
#include <boost/gil/extension/io/tiff/detail/reader_backend.hpp>

#include <boost/gil/io/base.hpp>
#include <boost/gil/io/bit_operations.hpp>
#include <boost/gil/io/conversion_policies.hpp>
#include <boost/gil/io/device.hpp>
#include <boost/gil/io/dynamic_io_new.hpp>
#include <boost/gil/io/reader_base.hpp>
#include <boost/gil/io/row_buffer_helper.hpp>

#include <boost/assert.hpp>

#include <algorithm>
#include <string>
#include <type_traits>
#include <vector>

// taken from jpegxx - https://bitbucket.org/edd/jpegxx/src/ea2492a1a4a6/src/ijg_headers.hpp
#ifndef BOOST_GIL_EXTENSION_IO_TIFF_C_LIB_COMPILED_AS_CPLUSPLUS
    extern "C" {
#endif

#include <tiff.h>
#include <tiffio.h>

#ifndef BOOST_GIL_EXTENSION_IO_TIFF_C_LIB_COMPILED_AS_CPLUSPLUS
    }
#endif

namespace boost { namespace gil {

#if BOOST_WORKAROUND(BOOST_MSVC, >= 1400)
#pragma warning(push)
#pragma warning(disable:4512) //assignment operator could not be generated
#endif

template < int K >
struct plane_recursion
{
   template< typename View
           , typename Device
           , typename ConversionPolicy
           >
   static
   void read_plane( const View& dst_view
                  , reader< Device
                          , tiff_tag
                          , ConversionPolicy >* p
                  )
   {
        using plane_t = typename kth_channel_view_type<K, View>::type;
        plane_t plane = kth_channel_view<K>( dst_view );

        p->template read_data< detail::row_buffer_helper_view< plane_t > >( plane, K );

        plane_recursion< K - 1 >::read_plane( dst_view, p );
   }
};

template <>
struct plane_recursion< -1 >
{
   template< typename View
           , typename Device
           , typename ConversionPolicy
           >
   static
   void read_plane( const View&               /* dst_view */
                  , reader< Device
                          , tiff_tag
                          , ConversionPolicy
                          >*                  /* p         */
                  )
    {}
};

///
/// Tiff Reader
///
template< typename Device
        , typename ConversionPolicy
        >
class reader< Device
            , tiff_tag
            , ConversionPolicy
            >
    : public reader_base< tiff_tag
                        , ConversionPolicy >

    , public reader_backend< Device
                           , tiff_tag
                           >
{
private:

    using this_t = reader<Device, tiff_tag, ConversionPolicy>;
    using cc_t = typename ConversionPolicy::color_converter_type;

public:

    using backend_t = reader_backend<Device, tiff_tag>;

    reader( const Device&                          io_dev
          , const image_read_settings< tiff_tag >& settings
          )
    : reader_base< tiff_tag
                 , ConversionPolicy
                 >()
    , backend_t( io_dev
               , settings
               )
    {}

    reader( const Device&                                          io_dev
          , const typename ConversionPolicy::color_converter_type& cc
          , const image_read_settings< tiff_tag >&                 settings
          )
    : reader_base< tiff_tag
                 , ConversionPolicy
                 >( cc )
    , backend_t( io_dev
               , settings
               )
    {}

    // only works for homogeneous image types
    template< typename View >
    void apply( View& dst_view )
    {
        if( this->_info._photometric_interpretation == PHOTOMETRIC_PALETTE )
        {
            this->_scanline_length = this->_info._width
                                   * num_channels< rgb16_view_t >::value
                                   * sizeof( channel_type<rgb16_view_t>::type );

            // Steps:
            // 1. Read indices. It's an array of grayX_pixel_t.
            // 2. Read palette. It's an array of rgb16_pixel_t.
            // 3. ??? Create virtual image or transform the two arrays
            //    into a rgb16_image_t object. The latter might
            //    be a good first solution.

            switch( this->_info._bits_per_sample )
            {
                case 1:  { read_palette_image< gray1_image_t  >( dst_view ); break; }
                case 2:  { read_palette_image< gray2_image_t  >( dst_view ); break; }
                case 4:  { read_palette_image< gray4_image_t  >( dst_view ); break; }
                case 8:  { read_palette_image< gray8_image_t  >( dst_view ); break; }
                case 16: { read_palette_image< gray16_image_t >( dst_view ); break; }

                default: { io_error( "Not supported palette " ); }
            }

            return;

        }
        else
        {
            this->_scanline_length = this->_io_dev.get_scanline_size();

            // In case we only read the image the user's type and
            // the tiff type need to compatible. Which means:
            // color_spaces_are_compatible && channels_are_pairwise_compatible

            using is_read_only = typename std::is_same
                <
                    ConversionPolicy,
                    detail::read_and_no_convert
                >::type;

            io_error_if( !detail::is_allowed< View >( this->_info
                                                    , is_read_only()
                                                    )
                       , "Image types aren't compatible."
                       );

            if( this->_info._planar_configuration == PLANARCONFIG_SEPARATE )
            {
                plane_recursion< num_channels< View >::value - 1 >::read_plane( dst_view
                                                                              , this
                                                                              );
            }
            else if( this->_info._planar_configuration == PLANARCONFIG_CONTIG )
            {
                read( dst_view
                    , typename is_read_only::type()
                    );
            }
            else
            {
                io_error( "Wrong planar configuration setting." );
            }
        }
    }

private:

    template< typename View >
    void read( View v
             , std::true_type // is_read_only
             )
    {
        read_data< detail::row_buffer_helper_view< View > >( v, 0 );
    }

    template< typename View >
    void read( View v
             , std::false_type  // is_read_only
             )
    {
        // the read_data function needs to know what gil type the source image is
        // to have the default color converter function correctly

        switch( this->_info._photometric_interpretation )
        {
            case PHOTOMETRIC_MINISWHITE:
            case PHOTOMETRIC_MINISBLACK:
            {
                switch( this->_info._bits_per_sample )
                {
                    case  1: { read_data< detail::row_buffer_helper_view< gray1_image_t::view_t > >( v, 0 );  break; }
                    case  2: { read_data< detail::row_buffer_helper_view< gray2_image_t::view_t > >( v, 0 );  break; }
                    case  4: { read_data< detail::row_buffer_helper_view< gray4_image_t::view_t > >( v, 0 );  break; }
                    case  8: { read_data< detail::row_buffer_helper_view< gray8_view_t  > >( v, 0 );  break; }
                    case 16: { read_data< detail::row_buffer_helper_view< gray16_view_t > >( v, 0 );  break; }
                    case 32: { read_data< detail::row_buffer_helper_view< gray32_view_t > >( v, 0 );  break; }
                    default: { io_error( "Image type is not supported." ); }
                }

                break;
            }

            case PHOTOMETRIC_RGB:
            {
                switch( this->_info._samples_per_pixel )
                {
                    case 3:
                    {
                        switch( this->_info._bits_per_sample )
                        {
                            case  8: { read_data< detail::row_buffer_helper_view< rgb8_view_t  > >( v, 0 );  break; }
                            case 16: { read_data< detail::row_buffer_helper_view< rgb16_view_t > >( v, 0 );  break; }
                            case 32: { read_data< detail::row_buffer_helper_view< rgb32_view_t > >( v, 0 );  break; }
                            default: { io_error( "Image type is not supported." ); }
                        }

                        break;
                    }

                    case 4:
                    {
                        switch( this->_info._bits_per_sample )
                        {
                            case  8: { read_data< detail::row_buffer_helper_view< rgba8_view_t  > >( v, 0 );  break; }
                            case 16: { read_data< detail::row_buffer_helper_view< rgba16_view_t > >( v, 0 );  break; }
                            case 32: { read_data< detail::row_buffer_helper_view< rgba32_view_t > >( v, 0 );  break; }
                            default: { io_error( "Image type is not supported." ); }
                        }

                        break;
                    }

                    default: { io_error( "Image type is not supported." ); }
                }

                break;
            }
            case PHOTOMETRIC_SEPARATED: // CYMK
            {
                switch( this->_info._bits_per_sample )
                {
                    case  8: { read_data< detail::row_buffer_helper_view< cmyk8_view_t  > >( v, 0 );  break; }
                    case 16: { read_data< detail::row_buffer_helper_view< cmyk16_view_t > >( v, 0 );  break; }
                    case 32: { read_data< detail::row_buffer_helper_view< cmyk32_view_t > >( v, 0 );  break; }
                    default: { io_error( "Image type is not supported." ); }
                }

                break;
            }

            default: { io_error( "Image type is not supported." ); }
        }
    }

   template< typename PaletteImage
           , typename View
           >
   void read_palette_image( const View& dst_view )
   {
      PaletteImage indices( this->_info._width  - this->_settings._top_left.x
                          , this->_info._height - this->_settings._top_left.y );

      // read the palette first
      read_data< detail::row_buffer_helper_view
          <
            typename PaletteImage::view_t>
        >(view(indices), 0);

      read_palette_image(dst_view, view(indices),
          typename std::is_same<View, rgb16_view_t>::type());
   }

   template< typename View
           , typename Indices_View
           >
   void read_palette_image( const View&         dst_view
                          , const Indices_View& indices_view
                          , std::true_type   // is View rgb16_view_t
                          )
   {
      tiff_color_map::red_t   red   = nullptr;
      tiff_color_map::green_t green = nullptr;
      tiff_color_map::blue_t  blue  = nullptr;

      this->_io_dev.get_field_defaulted( red, green, blue );

      using channel_t = typename channel_traits<typename element_type<typename Indices_View::value_type>::type>::value_type;

      int num_colors = channel_traits< channel_t >::max_value();

      rgb16_planar_view_t palette = planar_rgb_view( num_colors
                                                   , 1
                                                   , red
                                                   , green
                                                   , blue
                                                   , sizeof(uint16_t) * num_colors );

      for( typename rgb16_view_t::y_coord_t y = 0; y < dst_view.height(); ++y )
      {
         typename rgb16_view_t::x_iterator it  = dst_view.row_begin( y );
         typename rgb16_view_t::x_iterator end = dst_view.row_end( y );

         typename Indices_View::x_iterator indices_it = indices_view.row_begin( y );

         for( ; it != end; ++it, ++indices_it )
         {
            uint16_t i = gil::at_c<0>( *indices_it );

            *it = palette[i];
         }
      }
   }

   template< typename View
           , typename Indices_View
           >
   inline
   void read_palette_image( const View&         /* dst_view     */
                          , const Indices_View& /* indices_view */
                          , std::false_type  // is View rgb16_view_t
                          )
   {
      io_error( "User supplied image type must be rgb16_image_t." );
   }

   template< typename Buffer >
   void skip_over_rows( Buffer& buffer
                      , int     plane
                      )
   {
      if( this->_info._compression != COMPRESSION_NONE )
      {
         // Skipping over rows is not possible for compressed images(  no random access ). See man
         // page ( diagnostics section ) for more information.
         for( std::ptrdiff_t row = 0; row < this->_settings._top_left.y; ++row )
         {
            this->_io_dev.read_scanline( buffer
                                 , row
                                 , static_cast< tsample_t >( plane ));
         }
      }
   }

   template< typename Buffer
           , typename View
           >
   void read_data( const View& dst_view
                 , int         /* plane */ )
    {
        if( this->_io_dev.is_tiled() )
        {
            read_tiled_data< Buffer >( dst_view, 0 );
        }
        else
        {
            read_stripped_data< Buffer >( dst_view, 0 );
        }
    }

   template< typename Buffer
           , typename View
           >
   void read_tiled_data( const View& dst_view
                       , int         plane
                       )
   {
      if(  dst_view.width()  != this->_info._width
        || dst_view.height() != this->_info._height
        )
      {
          // read a subimage
          read_tiled_data_subimage< Buffer >( dst_view, plane );
      }
      else
      {
          // read full image
          read_tiled_data_full< Buffer >( dst_view, plane );
      }
   }

   template< typename Buffer
           , typename View
           >
   void read_tiled_data_subimage( const View& dst_view
                                , int         plane
                                )
   {
       ///@todo: why is
       /// using row_buffer_helper_t = Buffer;
       /// not working? I get compiler error with MSVC10.
       /// read_stripped_data IS working.
       using row_buffer_helper_t = detail::row_buffer_helper_view<View>;

       using it_t = typename row_buffer_helper_t::iterator_t;

       tiff_image_width::type  image_width  = this->_info._width;
       tiff_image_height::type image_height = this->_info._height;

       tiff_tile_width::type  tile_width  = this->_info._tile_width;
       tiff_tile_length::type tile_height = this->_info._tile_length;

       std::ptrdiff_t subimage_x = this->_settings._top_left.x;
       std::ptrdiff_t subimage_y = this->_settings._top_left.y;

       std::ptrdiff_t subimage_width  = this->_settings._dim.x;
       std::ptrdiff_t subimage_height = this->_settings._dim.y;

       row_buffer_helper_t row_buffer_helper(this->_io_dev.get_tile_size(), true );

       for( unsigned int y = 0; y < image_height; y += tile_height )
       {
           for( unsigned int x = 0; x < image_width; x += tile_width )
           {
               uint32_t current_tile_width  = ( x + tile_width  <  image_width ) ? tile_width  : image_width  - x;
               uint32_t current_tile_length = ( y + tile_height < image_height ) ? tile_height : image_height - y;

               this->_io_dev.read_tile( row_buffer_helper.buffer()
                                , x
                                , y
                                , 0
                                , static_cast< tsample_t >( plane )
                                );

               // these are all whole image coordinates
               point_t tile_top_left   ( x, y );
               point_t tile_lower_right( x + current_tile_width - 1, y + current_tile_length - 1 );

               point_t view_top_left   ( subimage_x, subimage_y );
               point_t view_lower_right( subimage_x + subimage_width  - 1
                                       , subimage_y + subimage_height - 1 );

               if(  tile_top_left.x    > view_lower_right.x
                 || tile_top_left.y    > view_lower_right.y
                 || tile_lower_right.x < view_top_left.x
                 || tile_lower_right.y < view_top_left.y
                 )
               {
                   // current tile and dst_view do not overlap
                   continue;
               }
               else
               {
                   // dst_view is overlapping the current tile

                   // next is to define the portion in the tile that needs to be copied

                   // get the whole image coordinates
                   std::ptrdiff_t img_x0 = ( tile_top_left.x >= view_top_left.x ) ? tile_top_left.x : view_top_left.x;
                   std::ptrdiff_t img_y0 = ( tile_top_left.y >= view_top_left.y ) ? tile_top_left.y : view_top_left.y;

                   std::ptrdiff_t img_x1 = ( tile_lower_right.x <= view_lower_right.x ) ? tile_lower_right.x : view_lower_right.x;
                   std::ptrdiff_t img_y1 = ( tile_lower_right.y <= view_lower_right.y ) ? tile_lower_right.y : view_lower_right.y;

                   // convert to tile coordinates
                   std::ptrdiff_t tile_x0 = img_x0 - x;
                   std::ptrdiff_t tile_y0 = img_y0 - y;
                   std::ptrdiff_t tile_x1 = img_x1 - x;
                   std::ptrdiff_t tile_y1 = img_y1 - y;

                   BOOST_ASSERT(tile_x0 >= 0 && tile_y0 >= 0 && tile_x1 >= 0 && tile_y1 >= 0);
                   BOOST_ASSERT(tile_x0 <= img_x1 && tile_y0 <= img_y1);
                   BOOST_ASSERT(tile_x0 < tile_width && tile_y0 < tile_height && tile_x1 < tile_width && tile_y1 < tile_height);

                   std::ptrdiff_t tile_subimage_view_width  = tile_x1 - tile_x0 + 1;
                   std::ptrdiff_t tile_subimage_view_height = tile_y1 - tile_y0 + 1;

                   // convert to dst_view coordinates
                   std::ptrdiff_t dst_x0 = img_x0 - subimage_x;
                   std::ptrdiff_t dst_y0 = img_y0 - subimage_y;
                   BOOST_ASSERT(dst_x0 >= 0 && dst_y0 >= 0);

                   View dst_subimage_view = subimage_view( dst_view
                                                         , (int) dst_x0
                                                         , (int) dst_y0
                                                         , (int) tile_subimage_view_width
                                                         , (int) tile_subimage_view_height
                                                         );

                   // the row_buffer is a 1D array which represents a 2D image. We cannot
                   // use interleaved_view here, since row_buffer could be bit_aligned.
                   // Interleaved_view's fourth parameter "rowsize_in_bytes" doesn't work
                   // for bit_aligned pixels.

                   for( std::ptrdiff_t dst_row = 0; dst_row < dst_subimage_view.height(); ++dst_row )
                   {
                       std::ptrdiff_t tile_row = dst_row + tile_y0;

                       // jump to the beginning of the current tile row
                       it_t begin = row_buffer_helper.begin() + tile_row * tile_width;

                       begin    += tile_x0;
                       it_t end  = begin + dst_subimage_view.width();

                       this->_cc_policy.read( begin
                                            , end
                                            , dst_subimage_view.row_begin( dst_row )
                                            );
                    } //for
               }
           } // for
       } // for
   }

   template< typename Buffer
           , typename View
           >
   void read_tiled_data_full( const View& dst_view
                            , int         plane
                            )
   {
       ///@todo: why is
       /// using row_buffer_helper_t = Buffer;
       /// not working? I get compiler error with MSVC10.
       /// read_stripped_data IS working.
       using row_buffer_helper_t = detail::row_buffer_helper_view<View>;

       using it_t = typename row_buffer_helper_t::iterator_t;

       tiff_image_width::type  image_width  = this->_info._width;
       tiff_image_height::type image_height = this->_info._height;

       tiff_tile_width::type  tile_width  = this->_info._tile_width;
       tiff_tile_length::type tile_height = this->_info._tile_length;

       row_buffer_helper_t row_buffer_helper(this->_io_dev.get_tile_size(), true );

       for( unsigned int y = 0; y < image_height; y += tile_height )
       {
           for( unsigned int x = 0; x < image_width; x += tile_width )
           {
               uint32_t current_tile_width  = ( x + tile_width  <  image_width ) ? tile_width  : image_width  - x;
               uint32_t current_tile_length = ( y + tile_height < image_height ) ? tile_height : image_height - y;

               this->_io_dev.read_tile( row_buffer_helper.buffer()
                                , x
                                , y
                                , 0
                                , static_cast< tsample_t >( plane )
                                );

               View dst_subimage_view = subimage_view( dst_view
                                                     , x
                                                     , y
                                                     , current_tile_width
                                                     , current_tile_length
                                                     );

               // the row_buffer is a 1D array which represents a 2D image. We cannot
               // use interleaved_view here, since row_buffer could be bit_aligned.
               // Interleaved_view's fourth parameter "rowsize_in_bytes" doesn't work
               // for bit_aligned pixels.

               for( int row = 0; row < dst_subimage_view.height(); ++row )
               {
                   it_t begin = row_buffer_helper.begin() + row * tile_width;
                   it_t end   = begin + dst_subimage_view.width();

                   this->_cc_policy.read( begin
                                        , end
                                        , dst_subimage_view.row_begin( row )
                                        );
                } //for
           } // for
       } // for
   }

   template< typename Buffer
           , typename View
           >
   void read_stripped_data( const View& dst_view
                          , int         plane     )
   {
      using is_view_bit_aligned_t = typename is_bit_aligned<typename View::value_type>::type;

      //using row_buffer_helper_t =detail::row_buffer_helper_view<View>;
      using row_buffer_helper_t = Buffer;
      using it_t = typename row_buffer_helper_t::iterator_t;

      std::size_t size_to_allocate = buffer_size< typename View::value_type >( dst_view.width()
                                                                             , is_view_bit_aligned_t() );
      row_buffer_helper_t row_buffer_helper( size_to_allocate, true );

      it_t begin = row_buffer_helper.begin();

      it_t first = begin + this->_settings._top_left.x;
      it_t last  = first + this->_settings._dim.x; // one after last element

      // I don't think tiff allows for random access of row, that's why we need
      // to read and discard rows when reading subimages.
      skip_over_rows( row_buffer_helper.buffer()
                    , plane
                    );

      std::ptrdiff_t row     = this->_settings._top_left.y;
      std::ptrdiff_t row_end = row + this->_settings._dim.y;
      std::ptrdiff_t dst_row = 0;

      for(
         ; row < row_end
         ; ++row, ++dst_row
         )
      {
         this->_io_dev.read_scanline( row_buffer_helper.buffer()
                              , row
                              , static_cast< tsample_t >( plane )
                              );

         this->_cc_policy.read( first
                              , last
                              , dst_view.row_begin( dst_row ));
      }
   }

    template< typename Pixel >
    std::size_t buffer_size( std::size_t width
                           , std::false_type // is_bit_aligned
                           )
    {
        std::size_t scanline_size_in_bytes = this->_io_dev.get_scanline_size();

        std::size_t element_size = sizeof( Pixel );

        std::size_t ret = std::max( width
                                  , (( scanline_size_in_bytes + element_size - 1 ) / element_size )
                                  );

        return ret;
    }

    template< typename Pixel >
    std::size_t buffer_size( std::size_t /* width */
                            , std::true_type  // is_bit_aligned
                            )
    {
        return this->_io_dev.get_scanline_size();
    }

private:

   template < int K > friend struct plane_recursion;
};

namespace detail {

struct tiff_type_format_checker
{
    tiff_type_format_checker( const image_read_info< tiff_tag >& info )
    : _info( info )
    {}

    template< typename Image >
    bool apply()
    {
        using view_t = typename Image::view_t;

        return is_allowed< view_t >( _info
                                   , std::true_type()
                                   );
    }

private:
    tiff_type_format_checker& operator=( const tiff_type_format_checker& ) { return *this; }

private:

    const image_read_info< tiff_tag > _info;
};

struct tiff_read_is_supported
{
    template< typename View >
    struct apply : public is_read_supported< typename get_pixel_type< View >::type
                                           , tiff_tag
                                           >
    {};
};

} // namespace detail

///
/// Tiff Dynamic Image Reader
///
template< typename Device >
class dynamic_image_reader< Device
                          , tiff_tag
                          >
    : public reader< Device
                   , tiff_tag
                   , detail::read_and_no_convert
                   >
{
    using parent_t = reader<Device, tiff_tag, detail::read_and_no_convert>;

public:

    dynamic_image_reader( const Device&                          io_dev
                        , const image_read_settings< tiff_tag >& settings
                        )
    : parent_t( io_dev
              , settings
              )
    {}

    template< typename ...Images >
    void apply( any_image< Images... >& images )
    {
        detail::tiff_type_format_checker format_checker( this->_info );

        if( !construct_matched( images
                              , format_checker
                              ))
        {
            io_error( "No matching image type between those of the given any_image and that of the file" );
        }
        else
        {
            this->init_image( images
                            , this->_settings
                            );

            detail::dynamic_io_fnobj< detail::tiff_read_is_supported
                                    , parent_t
                                    > op( this );

            apply_operation( view( images )
                           , op
                           );
        }
    }
};

#if BOOST_WORKAROUND(BOOST_MSVC, >= 1400)
#pragma warning(pop)
#endif

} // namespace gil
} // namespace boost

#endif


text:
// Copyright Louis Dionne 2013-2016
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)

#include <boost/hana/functional/iterate.hpp>
#include <boost/hana/assert.hpp>

#include <laws/base.hpp>

#include <vector>
using namespace boost::hana;

struct undefined { };

constexpr int incr(int i) { return i + 1; }

int main() {
    test::_injection<0> f{};
    using test::ct_eq;

    // "real usage" tests
    static_assert(iterate<3>(incr, 0) == 3, "");
    {
        std::vector<int> vec;
        iterate<10>([&](int i) { vec.push_back(i); return i + 1; }, 0);
        BOOST_HANA_RUNTIME_CHECK(
            vec == std::vector<int>{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}
        );
    }

    // equivalence between iterate<n>(f, x) and iterate<n>(f)(x)
    BOOST_HANA_CONSTANT_CHECK(equal(
        iterate<0>(undefined{})(ct_eq<0>{}),
        iterate<0>(undefined{}, ct_eq<0>{})
    ));

    BOOST_HANA_CONSTANT_CHECK(equal(
        iterate<4>(f)(ct_eq<0>{}),
        iterate<4>(f, ct_eq<0>{})
    ));

    BOOST_HANA_CONSTANT_CHECK(equal(
        iterate<10>(f)(ct_eq<0>{}),
        iterate<10>(f, ct_eq<0>{})
    ));

    // systematic tests
    BOOST_HANA_CONSTANT_CHECK(equal(
        iterate<0>(undefined{}, ct_eq<0>{}),
        ct_eq<0>{}
    ));

    BOOST_HANA_CONSTANT_CHECK(equal(
        iterate<1>(f, ct_eq<0>{}),
        f(ct_eq<0>{})
    ));

    BOOST_HANA_CONSTANT_CHECK(equal(
        iterate<2>(f, ct_eq<0>{}),
        f(f(ct_eq<0>{}))
    ));

    BOOST_HANA_CONSTANT_CHECK(equal(
        iterate<3>(f, ct_eq<0>{}),
        f(f(f(ct_eq<0>{})))
    ));

    BOOST_HANA_CONSTANT_CHECK(equal(
        iterate<4>(f, ct_eq<0>{}),
        f(f(f(f(ct_eq<0>{}))))
    ));

    BOOST_HANA_CONSTANT_CHECK(equal(
        iterate<5>(f, ct_eq<0>{}),
        f(f(f(f(f(ct_eq<0>{})))))
    ));

    BOOST_HANA_CONSTANT_CHECK(equal(
        iterate<6>(f, ct_eq<0>{}),
        f(f(f(f(f(f(ct_eq<0>{}))))))
    ));

    BOOST_HANA_CONSTANT_CHECK(equal(
        iterate<7>(f, ct_eq<0>{}),
        f(f(f(f(f(f(f(ct_eq<0>{})))))))
    ));

    BOOST_HANA_CONSTANT_CHECK(equal(
        iterate<11>(f, ct_eq<0>{}),
        f(f(f(f(f(f(f(f(f(f(f(ct_eq<0>{})))))))))))
    ));

    BOOST_HANA_CONSTANT_CHECK(equal(
        iterate<12>(f, ct_eq<0>{}),
        f(f(f(f(f(f(f(f(f(f(f(f(ct_eq<0>{}))))))))))))
    ));

    BOOST_HANA_CONSTANT_CHECK(equal(
        iterate<13>(f, ct_eq<0>{}),
        f(f(f(f(f(f(f(f(f(f(f(f(f(ct_eq<0>{})))))))))))))
    ));

    // We can't nest too many calls to f, because that uses a hana::tuple
    // internally and some implementation (libstdc++) have trouble with
    // deeply-nested calls to `std::is_constructible`, which is required by
    // hana::tuple. Hence, we use an homogeneous function for the remaining
    // tests.
    static_assert(iterate<23>(incr, 0) == 23, "");
    static_assert(iterate<24>(incr, 0) == 24, "");
    static_assert(iterate<25>(incr, 0) == 25, "");
    static_assert(iterate<26>(incr, 0) == 26, "");
    static_assert(iterate<27>(incr, 0) == 27, "");
    static_assert(iterate<28>(incr, 0) == 28, "");
    static_assert(iterate<29>(incr, 0) == 29, "");

    static_assert(iterate<30>(incr, 0) == 30, "");
    static_assert(iterate<31>(incr, 0) == 31, "");
    static_assert(iterate<32>(incr, 0) == 32, "");
    static_assert(iterate<33>(incr, 0) == 33, "");
    static_assert(iterate<34>(incr, 0) == 34, "");
    static_assert(iterate<35>(incr, 0) == 35, "");
    static_assert(iterate<36>(incr, 0) == 36, "");
    static_assert(iterate<37>(incr, 0) == 37, "");
    static_assert(iterate<38>(incr, 0) == 38, "");
    static_assert(iterate<39>(incr, 0) == 39, "");

    static_assert(iterate<40>(incr, 0) == 40, "");
    static_assert(iterate<41>(incr, 0) == 41, "");
    static_assert(iterate<42>(incr, 0) == 42, "");
    static_assert(iterate<43>(incr, 0) == 43, "");
    static_assert(iterate<44>(incr, 0) == 44, "");
    static_assert(iterate<45>(incr, 0) == 45, "");
    static_assert(iterate<46>(incr, 0) == 46, "");
    static_assert(iterate<47>(incr, 0) == 47, "");
    static_assert(iterate<48>(incr, 0) == 48, "");
    static_assert(iterate<49>(incr, 0) == 49, "");

    static_assert(iterate<50>(incr, 0) == 50, "");
    static_assert(iterate<51>(incr, 0) == 51, "");
    static_assert(iterate<52>(incr, 0) == 52, "");
    static_assert(iterate<53>(incr, 0) == 53, "");
    static_assert(iterate<54>(incr, 0) == 54, "");
    static_assert(iterate<55>(incr, 0) == 55, "");
    static_assert(iterate<56>(incr, 0) == 56, "");
    static_assert(iterate<57>(incr, 0) == 57, "");
    static_assert(iterate<58>(incr, 0) == 58, "");
    static_assert(iterate<59>(incr, 0) == 59, "");
}

max_stars_repo_name: nxplatform/nx-mobile

max_issues_repo_name: nxplatform/nx-mobile

max_forks_repo_name: nxplatform/nx-mobile


text:
// Boost.Range library
//
//  Copyright Neil Groves 2010. 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)
//
//
// For more information, see http://www.boost.org/libs/range/
//
#include <boost/range/join.hpp>

#include <boost/foreach.hpp>
#include <boost/test/test_tools.hpp>
#include <boost/test/unit_test.hpp>

#include <boost/assign.hpp>
#include <boost/range/algorithm_ext.hpp>
#include <boost/range/irange.hpp>

#include <boost/iterator/iterator_facade.hpp>

#include <algorithm>
#include <deque>
#include <list>
#include <vector>

namespace boost
{
    namespace
    {
        // This function is a helper function that writes integers
        // of increasing value into a range. It is used to test
        // that joined ranged may be written to.
        //
        // Requires:
        // - Range uses shallow copy semantics.
        template< typename Range >
        void fill_with_ints(Range rng)
        {
            typedef typename range_iterator<Range>::type iterator;
            iterator target = boost::begin(rng);
            const int count = boost::distance(rng);
            for (int i = 0; i < count; ++i)
            {
                *target = i;
                ++target;
            }
        }

        // The test_join_traversal function is used to provide additional
        // tests based upon the underlying join iterator traversal.
        // The join iterator takes care of the appropriate demotion, and
        // this demotion.

        // test_join_traversal - additional tests for input and forward
        // traversal iterators. This is of course a no-op.
        template< typename Range1, typename Range2, typename TraversalTag >
        void test_join_traversal(Range1& rng1, Range2& rng2, TraversalTag)
        {
        }

        // test_join_traversal - additional tests for bidirectional
        // traversal iterators.
        template< typename Range1, typename Range2 >
        void test_join_traversal(Range1& rng1, Range2& rng2, boost::bidirectional_traversal_tag)
        {
            typedef typename range_value<Range1>::type value_type;
            std::vector<value_type> reference(boost::begin(rng1), boost::end(rng1));
            boost::push_back(reference, rng2);
            std::reverse(reference.begin(), reference.end());

            std::vector<value_type> test_result;
            BOOST_REVERSE_FOREACH( value_type x, join(rng1, rng2) )
            {
                test_result.push_back(x);
            }

            BOOST_CHECK_EQUAL_COLLECTIONS( reference.begin(), reference.end(),
                                           test_result.begin(), test_result.end() );
        }

        // Test helper function to implement the additional tests for random
        // access traversal iterators. This is used by the test_join_traversal
        // function for random access iterators. The reason that the test
        // implementation is put into this function is to utilise
        // template parameter type deduction for the joined range type.
        template< typename Range1, typename Range2, typename JoinedRange >
        void test_random_access_join(Range1& rng1, Range2& rng2, JoinedRange joined)
        {
            BOOST_CHECK_EQUAL( boost::end(joined) - boost::begin(joined), boost::distance(joined) );
            BOOST_CHECK( boost::end(joined) <= boost::begin(joined) );
            BOOST_CHECK( boost::begin(joined) >= boost::end(joined) );
            if (boost::empty(joined))
            {
                BOOST_CHECK(!(boost::begin(joined) < boost::end(joined)));
                BOOST_CHECK(!(boost::end(joined) > boost::begin(joined)));
            }
            else
            {
                BOOST_CHECK(boost::begin(joined) < boost::end(joined));
                BOOST_CHECK(boost::end(joined) < boost::begin(joined));
            }

            typedef typename boost::range_difference<JoinedRange>::type difference_t;
            const difference_t count = boost::distance(joined);
            BOOST_CHECK( boost::begin(joined) + count == boost::end(joined) );
            BOOST_CHECK( boost::end(joined) - count == boost::begin(joined) );

            typedef typename boost::range_iterator<JoinedRange>::type iterator_t;
            iterator_t it = boost::begin(joined);
            it += count;
            BOOST_CHECK( it == boost::end(joined) );

            it = boost::end(joined);
            it -= count;
            BOOST_CHECK( it == boost::begin(joined) );
        }

        // test_join_traversal function for random access traversal joined
        // ranges.
        template< typename Range1, typename Range2 >
        void test_join_traversal(Range1& rng1, Range2& rng2, boost::random_access_traversal_tag)
        {
            test_join_traversal(rng1, rng2, boost::bidirectional_traversal_tag());
            test_random_access_join(rng1, rng2, join(rng1, rng2));
        }

        // Test the ability to write values into a joined range. This is
        // achieved by copying the constant collections, altering them
        // and then checking the result. Hence this relies upon both
        // rng1 and rng2 having value copy semantics.
        template< typename Collection1, typename Collection2 >
        void test_write_to_joined_range(const Collection1& rng1, const Collection2& rng2)
        {
            Collection1 c1(rng1);
            Collection2 c2(rng2);
            typedef typename boost::range_value<Collection1>::type value_t;
            fill_with_ints(boost::join(c1,c2));

            // Ensure that the size of the written range has not been
            // altered.
            BOOST_CHECK_EQUAL( boost::distance(c1), boost::distance(rng1) );
            BOOST_CHECK_EQUAL( boost::distance(c2), boost::distance(rng2) );

            // For each element x, in c1 ensure that it has been written to
            // with incrementing integers
            int x = 0;
            typedef typename range_iterator<Collection1>::type iterator1;
            iterator1 it1 = boost::begin(c1);
            for (; it1 != boost::end(c1); ++it1)
            {
                BOOST_CHECK_EQUAL( x, *it1 );
                ++x;
            }

            // For each element y, in c2 ensure that it has been written to
            // with incrementing integers
            typedef typename range_iterator<Collection2>::type iterator2;
            iterator2 it2 = boost::begin(c2);
            for (; it2 != boost::end(c2); ++it2)
            {
                BOOST_CHECK_EQUAL( x, *it2 );
                ++x;
            }
        }

        // Perform a unit test of a Boost.Range join() comparing
        // it to a reference that is populated by appending
        // elements from both source ranges into a vector.
        template< typename Collection1, typename Collection2 >
        void test_join_impl(Collection1& rng1, Collection2& rng2)
        {
            typedef typename range_value<Collection1>::type value_type;
            std::vector<value_type> reference(boost::begin(rng1), boost::end(rng1));
            boost::push_back(reference, rng2);

            std::vector<value_type> test_result;
            boost::push_back(test_result, join(rng1, rng2));

            BOOST_CHECK_EQUAL_COLLECTIONS( reference.begin(), reference.end(),
                                           test_result.begin(), test_result.end() );

            typedef boost::range_detail::join_iterator<
                typename boost::range_iterator<Collection1>::type,
                typename boost::range_iterator<Collection2>::type
                > join_iterator_t;

            typedef boost::iterator_traversal< join_iterator_t > tag_t;

           test_join_traversal(rng1, rng2, tag_t());

           test_write_to_joined_range(rng1, rng2);
        }

        // Make a collection filling it with items from the source
        // range. This is used to build collections of various
        // sizes populated with various values designed to optimize
        // the code coverage exercised by the core test function
        // test_join_impl.
        template<typename Collection, typename Range>
        boost::shared_ptr<Collection> makeCollection(const Range& source)
        {
            boost::shared_ptr<Collection> c(new Collection);
            c->insert(c->end(), boost::begin(source), boost::end(source));
            return c;
        }

        // This templatised version of the test_join_impl function
        // generates and populates collections which are later
        // used as input to the core test function.
        // The caller of this function explicitly provides the
        // template parameters. This supports the generation
        // of testing a large combination of range types to be
        // joined. It is of particular importance to remember
        // to combine a random_access range with a bidirectional
        // range to determine that the correct demotion of
        // types occurs in the join_iterator.
        template< typename Collection1, typename Collection2 >
        void test_join_impl()
        {
            typedef boost::shared_ptr<Collection1> collection1_ptr;
            typedef boost::shared_ptr<Collection2> collection2_ptr;
            typedef boost::shared_ptr<const Collection1> collection1_cptr;
            typedef boost::shared_ptr<const Collection2> collection2_cptr;
            std::vector< collection1_cptr > left_containers;
            std::vector< collection2_cptr > right_containers;

            left_containers.push_back(collection1_ptr(new Collection1));
            left_containers.push_back(makeCollection<Collection1>(irange(0,1)));
            left_containers.push_back(makeCollection<Collection1>(irange(0,100)));

            right_containers.push_back(collection2_ptr(new Collection2));
            right_containers.push_back(makeCollection<Collection2>(irange(0,1)));
            right_containers.push_back(makeCollection<Collection2>(irange(0,100)));

            BOOST_FOREACH( collection1_cptr left_container, left_containers )
            {
                BOOST_FOREACH( collection2_cptr right_container, right_containers )
                {
                    test_join_impl(*left_container, *right_container);
                }
            }
        }

        // entry-point into the unit test for the join() function
        // this tests a representative sample of combinations of
        // source range type.
        void join_test()
        {
            test_join_impl< std::vector<int>, std::vector<int> >();
            test_join_impl< std::list<int>,   std::list<int>   >();
            test_join_impl< std::deque<int>,  std::deque<int>  >();

            test_join_impl< std::vector<int>, std::list<int>   >();
            test_join_impl< std::list<int>,   std::vector<int> >();
            test_join_impl< std::vector<int>, std::deque<int>  >();
            test_join_impl< std::deque<int>,  std::vector<int> >();
        }

    }
}

boost::unit_test::test_suite*
init_unit_test_suite(int argc, char* argv[])
{
    boost::unit_test::test_suite* test
        = BOOST_TEST_SUITE( "RangeTestSuite.adaptor.joined" );

    test->add( BOOST_TEST_CASE( &boost::join_test ) );

    return test;
}

max_stars_repo_name: randolphwong/mcsema

max_issues_repo_name: randolphwong/mcsema

max_forks_repo_name: randolphwong/mcsema