text:
//==============================================================================
//         Copyright 2003 - 2011   LASMEA UMR 6602 CNRS/Univ. Clermont II
//         Copyright 2009 - 2011   LRI    UMR 8623 CNRS/Univ Paris Sud XI
//
//          Distributed under the Boost Software License, Version 1.0.
//                 See accompanying file LICENSE.txt or copy at
//                     http://www.boost.org/LICENSE_1_0.txt
//==============================================================================
#ifndef NT2_DSL_FUNCTIONS_RUN_HPP_INCLUDED
#define NT2_DSL_FUNCTIONS_RUN_HPP_INCLUDED

#include <boost/simd/dsl/functions/run.hpp>
#include <nt2/include/functor.hpp>

namespace nt2
{
  namespace tag
  {
    /*! \brief Same as \classref{boost::simd::tag::run_} **/
    struct run_ : boost::simd::tag::run_
    {
      typedef boost::simd::tag::run_ parent;
      template<class... Args>
      static BOOST_FORCEINLINE BOOST_AUTO_DECLTYPE dispatch(Args&&... args)
      BOOST_AUTO_DECLTYPE_BODY( dispatching_run_( ext::adl_helper(), static_cast<Args&&>(args)... ) )
    };

    /*! \brief Same as \classref{boost::simd::tag::run_assign_} **/
    struct run_assign_ : boost::simd::tag::run_assign_
    {
      typedef boost::simd::tag::run_ parent;
      template<class... Args>
      static BOOST_FORCEINLINE BOOST_AUTO_DECLTYPE dispatch(Args&&... args)
      BOOST_AUTO_DECLTYPE_BODY( dispatching_run_assign_( ext::adl_helper(), static_cast<Args&&>(args)... ) )
    };
  }

  namespace ext
  {
    template<class Site, class... Ts>
    BOOST_FORCEINLINE generic_dispatcher<tag::run_, Site> dispatching_run_(adl_helper, boost::dispatch::meta::unknown_<Site>, boost::dispatch::meta::unknown_<Ts>...)
    {
      return generic_dispatcher<tag::run_, Site>();
    }
    template<class... Args>
    struct impl_run_;

    template<class Site, class... Ts>
    BOOST_FORCEINLINE generic_dispatcher<tag::run_assign_, Site> dispatching_run_assign_(adl_helper, boost::dispatch::meta::unknown_<Site>, boost::dispatch::meta::unknown_<Ts>...)
    {
      return generic_dispatcher<tag::run_assign_, Site>();
    }
    template<class... Args>
    struct impl_run_assign_;
  }

  /*! \brief Same as \funcref{boost::simd::run} **/
  template<class A0, class... Args>
  BOOST_FORCEINLINE BOOST_AUTO_DECLTYPE run(A0&& a0, Args&&... args)
  BOOST_AUTO_DECLTYPE_BODY( dispatching_run_( ext::adl_helper(), boost::dispatch::default_site_t<A0>(), boost::dispatch::meta::hierarchy_of_t<A0&&>(), boost::dispatch::meta::hierarchy_of_t<Args&&>()... )(static_cast<A0&&>(a0), static_cast<Args&&>(args)...) )

  /*! \brief Same as \funcref{boost::simd::run} **/
  template<class A0, class... Args>
  BOOST_FORCEINLINE BOOST_AUTO_DECLTYPE run_assign(A0&& a0, Args&&... args)
  BOOST_AUTO_DECLTYPE_BODY( dispatching_run_assign_( ext::adl_helper(), boost::dispatch::default_site_t<A0>(), boost::dispatch::meta::hierarchy_of_t<A0&&>(), boost::dispatch::meta::hierarchy_of_t<Args&&>()... )(static_cast<A0&&>(a0), static_cast<Args&&>(args)...) )
}

#endif


text:
//-----------------------------------------------------------------------------
// Copyright (c) 2015-2018 Benjamin Buch
//
// https://github.com/bebuch/mitrax
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at https://www.boost.org/LICENSE_1_0.txt)
//-----------------------------------------------------------------------------
#define BOOST_TEST_MODULE mitrax dim
#define BOOST_TEST_NO_MAIN
#include <boost/test/unit_test.hpp>

#include <functional>

#include <mitrax/dim.hpp>

namespace utf = boost::unit_test;
using boost::typeindex::type_id;
using boost::typeindex::type_id_runtime;
using namespace mitrax;

#define CP(expr) [&]{ constexpr auto tmp = expr; return tmp; }()

template < typename T >
auto rt_id(T&& v){
	return type_id_runtime(static_cast< T&& >(v));
}

template < typename T >
auto const id = type_id< T >();

template < bool Nct, typename CT, size_t N >
using DimT = dim_type< Nct, CT, CT(N) >;

template < typename CT >
void construct(){
	constexpr auto cct = DimT< true,  CT, 3 >();
	constexpr auto crt = DimT< false, CT, 3 >();
	constexpr auto rrt = DimT< false, CT, 0 >(CT(3));

	BOOST_TEST((rt_id(cct) == id< DimT< true,  CT, 3 > >));
	BOOST_TEST((rt_id(crt) == id< DimT< false, CT, 3 > >));
	BOOST_TEST((rt_id(rrt) == id< DimT< false, CT, 0 > >));

	BOOST_TEST((size_t(cct) == 3));
	BOOST_TEST((size_t(crt) == 3));
	BOOST_TEST((size_t(rrt) == 3));
}

template < typename CT >
void default_construct(){
	constexpr auto cct = DimT< true,  CT, 3 >();
	constexpr auto crt = DimT< false, CT, 3 >();
	constexpr auto rrt = DimT< false, CT, 0 >();

	BOOST_TEST((rt_id(cct) == id< DimT< true,  CT, 3 > >));
	BOOST_TEST((rt_id(crt) == id< DimT< false, CT, 3 > >));
	BOOST_TEST((rt_id(rrt) == id< DimT< false, CT, 0 > >));

	BOOST_TEST((size_t(cct) == 3));
	BOOST_TEST((size_t(crt) == 3));
	BOOST_TEST((size_t(rrt) == 0));
}

void index_literal(){
	BOOST_TEST((rt_id(3_c) == id< c_t >));
	BOOST_TEST((rt_id(3_r) == id< r_t >));
	BOOST_TEST((rt_id(3_d) == id< d_t >));
}

void dim_t_literal(){
	BOOST_TEST((rt_id(3_C) == id< col_t >));
	BOOST_TEST((rt_id(3_R) == id< row_t >));
	BOOST_TEST((rt_id(3_D) == id< dim_t >));
}

void dim_literal(){
	BOOST_TEST((rt_id(3_CS) == id< col< true,  3_C > >));
	BOOST_TEST((rt_id(3_CD) == id< col< false, 3_C > >));

	BOOST_TEST((rt_id(3_RS) == id< row< true,  3_R > >));
	BOOST_TEST((rt_id(3_RD) == id< row< false, 3_R > >));

	BOOST_TEST((rt_id(3_DS) == id< dim< true,  3_D > >));
	BOOST_TEST((rt_id(3_DD) == id< dim< false, 3_D > >));
}

template < typename CT >
void convert2size_t(){
	constexpr auto cct = DimT< true,  CT, 3 >();
	constexpr auto crt = DimT< false, CT, 3 >();
	constexpr auto rrt = DimT< false, CT, 0 >(CT(3));

	BOOST_TEST((rt_id(size_t(cct)) == id< size_t >));
	BOOST_TEST((rt_id(size_t(crt)) == id< size_t >));
	BOOST_TEST((rt_id(size_t(rrt)) == id< size_t >));

	BOOST_TEST((CP(size_t(cct)) == 3));
	BOOST_TEST((CP(size_t(crt)) == 3));
	BOOST_TEST((CP(size_t(rrt)) == 3));
}

template < typename CT >
void convert2dim(){
	constexpr auto cct = DimT< true,  CT, 3 >();
	constexpr auto crt = DimT< false, CT, 3 >();
	constexpr auto rrt = DimT< false, CT, 0 >(CT(3));

	BOOST_TEST((rt_id(cct.as_col()) == id< col< true,  3_C > >));
	BOOST_TEST((rt_id(crt.as_col()) == id< col< false, 3_C > >));
	BOOST_TEST((rt_id(rrt.as_col()) == id< col< false, 0_C > >));

	BOOST_TEST((CP(cct.as_col()) == 3_CS));
	BOOST_TEST((CP(crt.as_col()) == 3_CS));
	BOOST_TEST((CP(rrt.as_col()) == 3_CS));

	BOOST_TEST((rt_id(cct.as_row()) == id< row< true,  3_R > >));
	BOOST_TEST((rt_id(crt.as_row()) == id< row< false, 3_R > >));
	BOOST_TEST((rt_id(rrt.as_row()) == id< row< false, 0_R > >));

	BOOST_TEST((CP(cct.as_row()) == 3_RS));
	BOOST_TEST((CP(crt.as_row()) == 3_RS));
	BOOST_TEST((CP(rrt.as_row()) == 3_RS));

	BOOST_TEST((rt_id(cct.as_dim()) == id< dim< true,  3_D > >));
	BOOST_TEST((rt_id(crt.as_dim()) == id< dim< false, 3_D > >));
	BOOST_TEST((rt_id(rrt.as_dim()) == id< dim< false, 0_D > >));

	BOOST_TEST((CP(cct.as_dim()) == 3_DS));
	BOOST_TEST((CP(crt.as_dim()) == 3_DS));
	BOOST_TEST((CP(rrt.as_dim()) == 3_DS));
}

template < typename CT, typename Op >
void arithmetic(){
	constexpr auto op = Op();
	constexpr auto l = 4;
	constexpr auto r = 3;

	constexpr auto cct1 = DimT< true,  CT, l >();
	constexpr auto crt1 = DimT< false, CT, l >();
	constexpr auto rrt1 = DimT< false, CT, 0 >(CT(l));

	constexpr auto cct2 = DimT< true,  CT, r >();
	constexpr auto crt2 = DimT< false, CT, r >();
	constexpr auto rrt2 = DimT< false, CT, 0 >(CT(r));

	BOOST_TEST((rt_id(CP(op(cct1, cct2))) == id< DimT< true,  CT, op(l, r) > >));
	BOOST_TEST((rt_id(CP(op(cct1, crt2))) == id< DimT< true,  CT, op(l, r) > >));
	BOOST_TEST((rt_id(CP(op(cct1, rrt2))) == id< DimT< false, CT, 0 > >));

	BOOST_TEST((rt_id(CP(op(crt1, cct2))) == id< DimT< true,  CT, op(l, r) > >));
	BOOST_TEST((rt_id(CP(op(crt1, crt2))) == id< DimT< false, CT, op(l, r) > >));
	BOOST_TEST((rt_id(CP(op(crt1, rrt2))) == id< DimT< false, CT, 0 > >));

	BOOST_TEST((rt_id(CP(op(rrt1, cct2))) == id< DimT< false, CT, 0 > >));
	BOOST_TEST((rt_id(CP(op(rrt1, crt2))) == id< DimT< false, CT, 0 > >));
	BOOST_TEST((rt_id(CP(op(rrt1, rrt2))) == id< DimT< false, CT, 0 > >));

	BOOST_TEST((size_t(CP(op(cct1, cct2))) == op(l, r)));
	BOOST_TEST((size_t(CP(op(cct1, crt2))) == op(l, r)));
	BOOST_TEST((size_t(CP(op(cct1, rrt2))) == op(l, r)));

	BOOST_TEST((size_t(CP(op(crt1, cct2))) == op(l, r)));
	BOOST_TEST((size_t(CP(op(crt1, crt2))) == op(l, r)));
	BOOST_TEST((size_t(CP(op(crt1, rrt2))) == op(l, r)));

	BOOST_TEST((size_t(CP(op(rrt1, cct2))) == op(l, r)));
	BOOST_TEST((size_t(CP(op(rrt1, crt2))) == op(l, r)));
	BOOST_TEST((size_t(CP(op(rrt1, rrt2))) == op(l, r)));
}

template < typename CT, typename Op >
void compare(){
	constexpr auto op = Op();
	constexpr auto l = 4;
	constexpr auto r = 3;

	constexpr auto cct1 = DimT< true,  CT, l >();
	constexpr auto crt1 = DimT< false, CT, l >();
	constexpr auto rrt1 = DimT< false, CT, 0 >(CT(l));

	constexpr auto cct2 = DimT< true,  CT, r >();
	constexpr auto crt2 = DimT< false, CT, r >();
	constexpr auto rrt2 = DimT< false, CT, 0 >(CT(r));

	BOOST_TEST((rt_id(CP(op(cct1, cct2))) == id< bool >));
	BOOST_TEST((rt_id(CP(op(cct1, crt2))) == id< bool >));
	BOOST_TEST((rt_id(CP(op(cct1, rrt2))) == id< bool >));

	BOOST_TEST((rt_id(CP(op(crt1, cct2))) == id< bool >));
	BOOST_TEST((rt_id(CP(op(crt1, crt2))) == id< bool >));
	BOOST_TEST((rt_id(CP(op(crt1, rrt2))) == id< bool >));

	BOOST_TEST((rt_id(CP(op(rrt1, cct2))) == id< bool >));
	BOOST_TEST((rt_id(CP(op(rrt1, crt2))) == id< bool >));
	BOOST_TEST((rt_id(CP(op(rrt1, rrt2))) == id< bool >));

	BOOST_TEST((CP(op(cct1, cct2)) == op(l, r)));
	BOOST_TEST((CP(op(cct1, crt2)) == op(l, r)));
	BOOST_TEST((CP(op(cct1, rrt2)) == op(l, r)));

	BOOST_TEST((CP(op(crt1, cct2)) == op(l, r)));
	BOOST_TEST((CP(op(crt1, crt2)) == op(l, r)));
	BOOST_TEST((CP(op(crt1, rrt2)) == op(l, r)));

	BOOST_TEST((CP(op(rrt1, cct2)) == op(l, r)));
	BOOST_TEST((CP(op(rrt1, crt2)) == op(l, r)));
	BOOST_TEST((CP(op(rrt1, rrt2)) == op(l, r)));
}

template < typename CT >
void get_dim(){
	constexpr auto v = 7;

	constexpr auto d1 = DimT< true,  CT, v >();
	constexpr auto d2 = DimT< false, CT, v >();
	constexpr auto d3 = DimT< false, CT, 0 >(CT(v));

	constexpr auto res01 = get(d1);
	constexpr auto res02 = get(d2);
	constexpr auto res03 = get(d3);
	constexpr auto res04 = get(d1, d1);
	constexpr auto res05 = get(d2, d2);
	constexpr auto res06 = get(d3, d3);
	constexpr auto res07 = get(d1, d2);
	constexpr auto res08 = get(d1, d3);
	constexpr auto res09 = get(d2, d1);
	constexpr auto res10 = get(d2, d3);
	constexpr auto res11 = get(d3, d1);
	constexpr auto res12 = get(d3, d2);
	constexpr auto res13 = get(d1, d1, d1);
	constexpr auto res14 = get(d2, d2, d2);
	constexpr auto res15 = get(d3, d3, d3);
	constexpr auto res16 = get(d1, d2, d1);
	constexpr auto res17 = get(d1, d2, d2);
	constexpr auto res18 = get(d1, d2, d3);
	constexpr auto res19 = get(d1, d3, d1);
	constexpr auto res20 = get(d1, d3, d2);
	constexpr auto res21 = get(d1, d3, d3);
	constexpr auto res22 = get(d2, d1, d1);
	constexpr auto res23 = get(d2, d1, d2);
	constexpr auto res24 = get(d2, d1, d3);
	constexpr auto res25 = get(d2, d3, d1);
	constexpr auto res26 = get(d2, d3, d2);
	constexpr auto res27 = get(d2, d3, d3);
	constexpr auto res28 = get(d3, d1, d1);
	constexpr auto res29 = get(d3, d1, d2);
	constexpr auto res30 = get(d3, d1, d3);
	constexpr auto res31 = get(d3, d2, d1);
	constexpr auto res32 = get(d3, d2, d2);
	constexpr auto res33 = get(d3, d2, d3);

	BOOST_TEST((size_t(res01) == 7));
	BOOST_TEST((size_t(res02) == 7));
	BOOST_TEST((size_t(res03) == 7));
	BOOST_TEST((size_t(res04) == 7));
	BOOST_TEST((size_t(res05) == 7));
	BOOST_TEST((size_t(res06) == 7));
	BOOST_TEST((size_t(res07) == 7));
	BOOST_TEST((size_t(res08) == 7));
	BOOST_TEST((size_t(res09) == 7));
	BOOST_TEST((size_t(res10) == 7));
	BOOST_TEST((size_t(res11) == 7));
	BOOST_TEST((size_t(res12) == 7));
	BOOST_TEST((size_t(res13) == 7));
	BOOST_TEST((size_t(res14) == 7));
	BOOST_TEST((size_t(res15) == 7));
	BOOST_TEST((size_t(res16) == 7));
	BOOST_TEST((size_t(res17) == 7));
	BOOST_TEST((size_t(res18) == 7));
	BOOST_TEST((size_t(res19) == 7));
	BOOST_TEST((size_t(res20) == 7));
	BOOST_TEST((size_t(res21) == 7));
	BOOST_TEST((size_t(res22) == 7));
	BOOST_TEST((size_t(res23) == 7));
	BOOST_TEST((size_t(res24) == 7));
	BOOST_TEST((size_t(res25) == 7));
	BOOST_TEST((size_t(res26) == 7));
	BOOST_TEST((size_t(res27) == 7));
	BOOST_TEST((size_t(res28) == 7));
	BOOST_TEST((size_t(res29) == 7));
	BOOST_TEST((size_t(res30) == 7));
	BOOST_TEST((size_t(res31) == 7));
	BOOST_TEST((size_t(res32) == 7));
	BOOST_TEST((size_t(res33) == 7));

	BOOST_TEST((rt_id(res01) == (id< DimT< true,  CT, 7 > >)));
	BOOST_TEST((rt_id(res02) == (id< DimT< false, CT, 7 > >)));
	BOOST_TEST((rt_id(res03) == (id< DimT< false, CT, 0 > >)));
	BOOST_TEST((rt_id(res04) == (id< DimT< true,  CT, 7 > >)));
	BOOST_TEST((rt_id(res05) == (id< DimT< false, CT, 7 > >)));
	BOOST_TEST((rt_id(res06) == (id< DimT< false, CT, 0 > >)));
	BOOST_TEST((rt_id(res07) == (id< DimT< true,  CT, 7 > >)));
	BOOST_TEST((rt_id(res08) == (id< DimT< true,  CT, 7 > >)));
	BOOST_TEST((rt_id(res09) == (id< DimT< true,  CT, 7 > >)));
	BOOST_TEST((rt_id(res10) == (id< DimT< false, CT, 7 > >)));
	BOOST_TEST((rt_id(res11) == (id< DimT< true,  CT, 7 > >)));
	BOOST_TEST((rt_id(res12) == (id< DimT< false, CT, 7 > >)));
	BOOST_TEST((rt_id(res13) == (id< DimT< true,  CT, 7 > >)));
	BOOST_TEST((rt_id(res14) == (id< DimT< false, CT, 7 > >)));
	BOOST_TEST((rt_id(res15) == (id< DimT< false, CT, 0 > >)));
	BOOST_TEST((rt_id(res16) == (id< DimT< true,  CT, 7 > >)));
	BOOST_TEST((rt_id(res17) == (id< DimT< true,  CT, 7 > >)));
	BOOST_TEST((rt_id(res18) == (id< DimT< true,  CT, 7 > >)));
	BOOST_TEST((rt_id(res19) == (id< DimT< true,  CT, 7 > >)));
	BOOST_TEST((rt_id(res20) == (id< DimT< true,  CT, 7 > >)));
	BOOST_TEST((rt_id(res21) == (id< DimT< true,  CT, 7 > >)));
	BOOST_TEST((rt_id(res22) == (id< DimT< true,  CT, 7 > >)));
	BOOST_TEST((rt_id(res23) == (id< DimT< true,  CT, 7 > >)));
	BOOST_TEST((rt_id(res24) == (id< DimT< true,  CT, 7 > >)));
	BOOST_TEST((rt_id(res25) == (id< DimT< true,  CT, 7 > >)));
	BOOST_TEST((rt_id(res26) == (id< DimT< false, CT, 7 > >)));
	BOOST_TEST((rt_id(res27) == (id< DimT< false, CT, 7 > >)));
	BOOST_TEST((rt_id(res28) == (id< DimT< true,  CT, 7 > >)));
	BOOST_TEST((rt_id(res29) == (id< DimT< true,  CT, 7 > >)));
	BOOST_TEST((rt_id(res30) == (id< DimT< true,  CT, 7 > >)));
	BOOST_TEST((rt_id(res31) == (id< DimT< true,  CT, 7 > >)));
	BOOST_TEST((rt_id(res32) == (id< DimT< false, CT, 7 > >)));
	BOOST_TEST((rt_id(res33) == (id< DimT< false, CT, 7 > >)));
}

template < typename CT >
void add_test(utf::test_suite* ts){
	ts->add(BOOST_TEST_CASE(&construct< CT >));
	ts->add(BOOST_TEST_CASE(&default_construct< CT >));
	ts->add(BOOST_TEST_CASE(&convert2size_t< CT >));
	ts->add(BOOST_TEST_CASE(&convert2dim< CT >));
	ts->add(BOOST_TEST_CASE(&get_dim< CT >));
	ts->add(BOOST_TEST_CASE((&arithmetic< CT, std::plus<> >)));
	ts->add(BOOST_TEST_CASE((&arithmetic< CT, std::minus<> >)));
	ts->add(BOOST_TEST_CASE((&arithmetic< CT, std::multiplies<> >)));
	ts->add(BOOST_TEST_CASE((&arithmetic< CT, std::divides<> >)));
	ts->add(BOOST_TEST_CASE((&arithmetic< CT, std::modulus<> >)));
	ts->add(BOOST_TEST_CASE((&compare< CT, std::equal_to<> >)));
	ts->add(BOOST_TEST_CASE((&compare< CT, std::not_equal_to<> >)));
	ts->add(BOOST_TEST_CASE((&compare< CT, std::less<> >)));
	ts->add(BOOST_TEST_CASE((&compare< CT, std::less_equal<> >)));
	ts->add(BOOST_TEST_CASE((&compare< CT, std::greater<> >)));
	ts->add(BOOST_TEST_CASE((&compare< CT, std::greater_equal<> >)));
}

void make_col(){
	constexpr auto cct = cols< 3_C >();
	constexpr auto crt = cols_rt< 3_C >();
	constexpr auto rrt = cols(3_C);

	BOOST_TEST((rt_id(cct) == id< col< true,  3_C > >));
	BOOST_TEST((rt_id(crt) == id< col< false, 3_C > >));
	BOOST_TEST((rt_id(rrt) == id< col< false, 0_C > >));

	BOOST_TEST((cct == 3_CS));
	BOOST_TEST((crt == 3_CS));
	BOOST_TEST((rrt == 3_CS));
}

void make_row(){
	constexpr auto cct = rows< 3_R >();
	constexpr auto crt = rows_rt< 3_R >();
	constexpr auto rrt = rows(3_R);

	BOOST_TEST((rt_id(cct) == id< row< true,  3_R > >));
	BOOST_TEST((rt_id(crt) == id< row< false, 3_R > >));
	BOOST_TEST((rt_id(rrt) == id< row< false, 0_R > >));

	BOOST_TEST((cct == 3_RS));
	BOOST_TEST((crt == 3_RS));
	BOOST_TEST((rrt == 3_RS));
}

void make_dim(){
	constexpr auto cct = dims< 3_D >();
	constexpr auto crt = dims_rt< 3_D >();
	constexpr auto rrt = dims(3_D);

	BOOST_TEST((rt_id(cct) == id< dim< true,  3_D > >));
	BOOST_TEST((rt_id(crt) == id< dim< false, 3_D > >));
	BOOST_TEST((rt_id(rrt) == id< dim< false, 0_D > >));

	BOOST_TEST((cct == 3_DS));
	BOOST_TEST((crt == 3_DS));
	BOOST_TEST((rrt == 3_DS));
}

void dim_pair_t_default_construct(){
	constexpr auto c = 3_C;
	constexpr auto r = 4_R;

	constexpr auto cc = auto_dim_pair_t< c, r >();
	constexpr auto cr = auto_dim_pair_t< c, 0_R >();
	constexpr auto rc = auto_dim_pair_t< 0_C, r >();
	constexpr auto rr = auto_dim_pair_t< 0_C, 0_R >();

	BOOST_TEST((CP(cc.cols()) == cols(c)));
	BOOST_TEST((CP(cr.cols()) == cols(c)));
	BOOST_TEST((CP(rc.cols()) == 0_CD));
	BOOST_TEST((CP(rr.cols()) == 0_CD));

	BOOST_TEST((CP(cc.rows()) == rows(r)));
	BOOST_TEST((CP(cr.rows()) == 0_RD));
	BOOST_TEST((CP(rc.rows()) == rows(r)));
	BOOST_TEST((CP(rr.rows()) == 0_RD));
}

void dim_pair_t_construct(){
	constexpr auto c = 3_C;
	constexpr auto r = 4_R;

	constexpr auto cc = auto_dim_pair_t< c, r >(cols< c >(), rows< r >());
	constexpr auto cr = auto_dim_pair_t< c, 0_R >(cols< c >(), rows(r));
	constexpr auto rc = auto_dim_pair_t< 0_C, r >(cols(c), rows< r >());
	constexpr auto rr = auto_dim_pair_t< 0_C, 0_R >(cols(c), rows(r));

	BOOST_TEST((CP(cc.cols()) == cols(c)));
	BOOST_TEST((CP(cr.cols()) == cols(c)));
	BOOST_TEST((CP(rc.cols()) == cols(c)));
	BOOST_TEST((CP(rr.cols()) == cols(c)));

	BOOST_TEST((CP(cc.rows()) == rows(r)));
	BOOST_TEST((CP(cr.rows()) == rows(r)));
	BOOST_TEST((CP(rc.rows()) == rows(r)));
	BOOST_TEST((CP(rr.rows()) == rows(r)));
}

void dim_pair_t_make(){
	constexpr auto c = 3_C;
	constexpr auto r = 4_R;

	constexpr auto ll = dim_pair(c, r);
	constexpr auto lr = dim_pair(c, rows(r));
	constexpr auto lc = dim_pair(c, rows< r >());
	constexpr auto ld = dim_pair(c, rows_rt< r >());

	constexpr auto rl = dim_pair(cols(c), r);
	constexpr auto rr = dim_pair(cols(c), rows(r));
	constexpr auto rc = dim_pair(cols(c), rows< r >());
	constexpr auto rd = dim_pair(cols(c), rows_rt< r >());

	constexpr auto cl = dim_pair(cols< c >(), r);
	constexpr auto cr = dim_pair(cols< c >(), rows(r));
	constexpr auto cc = dim_pair(cols< c >(), rows< r >());
	constexpr auto cd = dim_pair(cols< c >(), rows_rt< r >());

	constexpr auto dl = dim_pair(cols_rt< c >(), r);
	constexpr auto dr = dim_pair(cols_rt< c >(), rows(r));
	constexpr auto dc = dim_pair(cols_rt< c >(), rows< r >());
	constexpr auto dd = dim_pair(cols_rt< c >(), rows_rt< r >());

	BOOST_TEST((rt_id(ll) == id< dim_pair_t< false, 0_C, false, 0_R > >));
	BOOST_TEST((rt_id(lr) == id< dim_pair_t< false, 0_C, false, 0_R > >));
	BOOST_TEST((rt_id(lc) == id< dim_pair_t< false, 0_C, true,  4_R > >));
	BOOST_TEST((rt_id(ld) == id< dim_pair_t< false, 0_C, false, 4_R > >));

	BOOST_TEST((rt_id(rl) == id< dim_pair_t< false, 0_C, false, 0_R > >));
	BOOST_TEST((rt_id(rr) == id< dim_pair_t< false, 0_C, false, 0_R > >));
	BOOST_TEST((rt_id(rc) == id< dim_pair_t< false, 0_C, true,  4_R > >));
	BOOST_TEST((rt_id(rd) == id< dim_pair_t< false, 0_C, false, 4_R > >));

	BOOST_TEST((rt_id(cl) == id< dim_pair_t< true,  3_C, false, 0_R > >));
	BOOST_TEST((rt_id(cr) == id< dim_pair_t< true,  3_C, false, 0_R > >));
	BOOST_TEST((rt_id(cc) == id< dim_pair_t< true,  3_C, true,  4_R > >));
	BOOST_TEST((rt_id(cd) == id< dim_pair_t< true,  3_C, false, 4_R > >));

	BOOST_TEST((rt_id(dl) == id< dim_pair_t< false, 3_C, false, 0_R > >));
	BOOST_TEST((rt_id(dr) == id< dim_pair_t< false, 3_C, false, 0_R > >));
	BOOST_TEST((rt_id(dc) == id< dim_pair_t< false, 3_C, true,  4_R > >));
	BOOST_TEST((rt_id(dd) == id< dim_pair_t< false, 3_C, false, 4_R > >));

	BOOST_TEST((rt_id(ll.cols()) == id< col< false, 0_C > >));
	BOOST_TEST((rt_id(lr.cols()) == id< col< false, 0_C > >));
	BOOST_TEST((rt_id(lc.cols()) == id< col< false, 0_C > >));
	BOOST_TEST((rt_id(ld.cols()) == id< col< false, 0_C > >));

	BOOST_TEST((rt_id(rl.cols()) == id< col< false, 0_C > >));
	BOOST_TEST((rt_id(rr.cols()) == id< col< false, 0_C > >));
	BOOST_TEST((rt_id(rc.cols()) == id< col< false, 0_C > >));
	BOOST_TEST((rt_id(rd.cols()) == id< col< false, 0_C > >));

	BOOST_TEST((rt_id(cl.cols()) == id< col< true,  3_C > >));
	BOOST_TEST((rt_id(cr.cols()) == id< col< true,  3_C > >));
	BOOST_TEST((rt_id(cc.cols()) == id< col< true,  3_C > >));
	BOOST_TEST((rt_id(cd.cols()) == id< col< true,  3_C > >));

	BOOST_TEST((rt_id(dl.cols()) == id< col< false, 3_C > >));
	BOOST_TEST((rt_id(dr.cols()) == id< col< false, 3_C > >));
	BOOST_TEST((rt_id(dc.cols()) == id< col< false, 3_C > >));
	BOOST_TEST((rt_id(dd.cols()) == id< col< false, 3_C > >));

	BOOST_TEST((rt_id(ll.rows()) == id< row< false, 0_R > >));
	BOOST_TEST((rt_id(lr.rows()) == id< row< false, 0_R > >));
	BOOST_TEST((rt_id(lc.rows()) == id< row< true,  4_R > >));
	BOOST_TEST((rt_id(ld.rows()) == id< row< false, 4_R > >));

	BOOST_TEST((rt_id(rl.rows()) == id< row< false, 0_R > >));
	BOOST_TEST((rt_id(rr.rows()) == id< row< false, 0_R > >));
	BOOST_TEST((rt_id(rc.rows()) == id< row< true,  4_R > >));
	BOOST_TEST((rt_id(rd.rows()) == id< row< false, 4_R > >));

	BOOST_TEST((rt_id(cl.rows()) == id< row< false, 0_R > >));
	BOOST_TEST((rt_id(cr.rows()) == id< row< false, 0_R > >));
	BOOST_TEST((rt_id(cc.rows()) == id< row< true,  4_R > >));
	BOOST_TEST((rt_id(cd.rows()) == id< row< false, 4_R > >));

	BOOST_TEST((rt_id(dl.rows()) == id< row< false, 0_R > >));
	BOOST_TEST((rt_id(dr.rows()) == id< row< false, 0_R > >));
	BOOST_TEST((rt_id(dc.rows()) == id< row< true,  4_R > >));
	BOOST_TEST((rt_id(dd.rows()) == id< row< false, 4_R > >));

	BOOST_TEST((CP(ll.cols()) == 3_CS));
	BOOST_TEST((CP(lr.cols()) == 3_CS));
	BOOST_TEST((CP(lc.cols()) == 3_CS));
	BOOST_TEST((CP(ld.cols()) == 3_CS));

	BOOST_TEST((CP(rl.cols()) == 3_CS));
	BOOST_TEST((CP(rr.cols()) == 3_CS));
	BOOST_TEST((CP(rc.cols()) == 3_CS));
	BOOST_TEST((CP(rd.cols()) == 3_CS));

	BOOST_TEST((CP(cl.cols()) == 3_CS));
	BOOST_TEST((CP(cr.cols()) == 3_CS));
	BOOST_TEST((CP(cc.cols()) == 3_CS));
	BOOST_TEST((CP(cd.cols()) == 3_CS));

	BOOST_TEST((CP(dl.cols()) == 3_CS));
	BOOST_TEST((CP(dr.cols()) == 3_CS));
	BOOST_TEST((CP(dc.cols()) == 3_CS));
	BOOST_TEST((CP(dd.cols()) == 3_CS));

	BOOST_TEST((CP(ll.rows()) == 4_RS));
	BOOST_TEST((CP(lr.rows()) == 4_RS));
	BOOST_TEST((CP(lc.rows()) == 4_RS));
	BOOST_TEST((CP(ld.rows()) == 4_RS));

	BOOST_TEST((CP(rl.rows()) == 4_RS));
	BOOST_TEST((CP(rr.rows()) == 4_RS));
	BOOST_TEST((CP(rc.rows()) == 4_RS));
	BOOST_TEST((CP(rd.rows()) == 4_RS));

	BOOST_TEST((CP(cl.rows()) == 4_RS));
	BOOST_TEST((CP(cr.rows()) == 4_RS));
	BOOST_TEST((CP(cc.rows()) == 4_RS));
	BOOST_TEST((CP(cd.rows()) == 4_RS));

	BOOST_TEST((CP(dl.rows()) == 4_RS));
	BOOST_TEST((CP(dr.rows()) == 4_RS));
	BOOST_TEST((CP(dc.rows()) == 4_RS));
	BOOST_TEST((CP(dd.rows()) == 4_RS));
}

template <
	bool Cct1, col_t C1, bool Rct1, row_t R1,
	bool Cct2, col_t C2, bool Rct2, row_t R2 >
constexpr void dim_compare_test(
	dim_pair_t< Cct1, C1, Rct1, R1 > const& d1,
	dim_pair_t< Cct2, C2, Rct2, R2 > const& d2,
	bool equal_expection
)noexcept{
	BOOST_TEST((rt_id(d1 == d2) == id< bool >));
	BOOST_TEST((d1 == d2) == equal_expection);
	BOOST_TEST(!(d1 == d2) != equal_expection);
}

void dim_pair_t_compare(){
	using namespace ::mitrax::literals;

	constexpr auto cc1 = dim_pair(3_CS,  4_RS );
	constexpr auto cr1 = dim_pair(3_CS,  4_RD);
	constexpr auto rc1 = dim_pair(3_CD, 4_RS );
	constexpr auto rr1 = dim_pair(3_CD, 4_RD);

	constexpr auto cc2 = dim_pair(6_CS,  5_RS );
	constexpr auto cr2 = dim_pair(6_CS,  5_RD);
	constexpr auto rc2 = dim_pair(6_CD, 5_RS );
	constexpr auto rr2 = dim_pair(6_CD, 5_RD);

	constexpr auto cc3 = dim_pair(3_CS,  5_RS );
	constexpr auto cr3 = dim_pair(3_CS,  5_RD);
	constexpr auto rc3 = dim_pair(3_CD, 5_RS );
	constexpr auto rr3 = dim_pair(3_CD, 5_RD);

	constexpr auto cc4 = dim_pair(6_CS,  4_RS );
	constexpr auto cr4 = dim_pair(6_CS,  4_RD);
	constexpr auto rc4 = dim_pair(6_CD, 4_RS );
	constexpr auto rr4 = dim_pair(6_CD, 4_RD);

	dim_compare_test(cc1, cc1, true);
	dim_compare_test(cr1, cc1, true);
	dim_compare_test(rc1, cc1, true);
	dim_compare_test(rr1, cc1, true);

	dim_compare_test(cc1, cr1, true);
	dim_compare_test(cr1, cr1, true);
	dim_compare_test(rc1, cr1, true);
	dim_compare_test(rr1, cr1, true);

	dim_compare_test(cc1, rc1, true);
	dim_compare_test(cr1, rc1, true);
	dim_compare_test(rc1, rc1, true);
	dim_compare_test(rr1, rc1, true);

	dim_compare_test(cc1, rr1, true);
	dim_compare_test(cr1, rr1, true);
	dim_compare_test(rc1, rr1, true);
	dim_compare_test(rr1, rr1, true);

	dim_compare_test(cc1, cc2, false);
	dim_compare_test(cr1, cc2, false);
	dim_compare_test(rc1, cc2, false);
	dim_compare_test(rr1, cc2, false);

	dim_compare_test(cc1, cr2, false);
	dim_compare_test(cr1, cr2, false);
	dim_compare_test(rc1, cr2, false);
	dim_compare_test(rr1, cr2, false);

	dim_compare_test(cc1, rc2, false);
	dim_compare_test(cr1, rc2, false);
	dim_compare_test(rc1, rc2, false);
	dim_compare_test(rr1, rc2, false);

	dim_compare_test(cc1, rr2, false);
	dim_compare_test(cr1, rr2, false);
	dim_compare_test(rc1, rr2, false);
	dim_compare_test(rr1, rr2, false);

	dim_compare_test(cc1, cc3, false);
	dim_compare_test(cr1, cc3, false);
	dim_compare_test(rc1, cc3, false);
	dim_compare_test(rr1, cc3, false);

	dim_compare_test(cc1, cr3, false);
	dim_compare_test(cr1, cr3, false);
	dim_compare_test(rc1, cr3, false);
	dim_compare_test(rr1, cr3, false);

	dim_compare_test(cc1, rc3, false);
	dim_compare_test(cr1, rc3, false);
	dim_compare_test(rc1, rc3, false);
	dim_compare_test(rr1, rc3, false);

	dim_compare_test(cc1, rr3, false);
	dim_compare_test(cr1, rr3, false);
	dim_compare_test(rc1, rr3, false);
	dim_compare_test(rr1, rr3, false);

	dim_compare_test(cc1, cc4, false);
	dim_compare_test(cr1, cc4, false);
	dim_compare_test(rc1, cc4, false);
	dim_compare_test(rr1, cc4, false);

	dim_compare_test(cc1, cr4, false);
	dim_compare_test(cr1, cr4, false);
	dim_compare_test(rc1, cr4, false);
	dim_compare_test(rr1, cr4, false);

	dim_compare_test(cc1, rc4, false);
	dim_compare_test(cr1, rc4, false);
	dim_compare_test(rc1, rc4, false);
	dim_compare_test(rr1, rc4, false);

	dim_compare_test(cc1, rr4, false);
	dim_compare_test(cr1, rr4, false);
	dim_compare_test(rc1, rr4, false);
	dim_compare_test(rr1, rr4, false);
}

template < typename Op >
void dim_pair_t_arithmetic_size_t(){
	constexpr auto op = Op();
	constexpr auto c = 9_C;
	constexpr auto r = 7_R;
	constexpr auto v = 5_D;

	constexpr auto cc = auto_dim_pair_t< c, r >(cols< c >(), rows< r >());
	constexpr auto cr = auto_dim_pair_t< c, 0_R >(cols< c >(), rows(r));
	constexpr auto rc = auto_dim_pair_t< 0_C, r >(cols(c), rows< r >());
	constexpr auto rr = auto_dim_pair_t< 0_C, 0_R >(cols(c), rows(r));

	constexpr auto vcc = dims< v >();
	constexpr auto vcr = dims_rt< v >();
	constexpr auto vrr = dims(v);

	BOOST_TEST((rt_id(CP(op(cc, vcc))) == id< auto_dim_pair_t< op(c, col_t(v)), op(r, row_t(v)) > >));
	BOOST_TEST((rt_id(CP(op(cr, vcc))) == id< auto_dim_pair_t< op(c, col_t(v)), 0_R > >));
	BOOST_TEST((rt_id(CP(op(rc, vcc))) == id< auto_dim_pair_t< 0_C, op(r, row_t(v)) > >));
	BOOST_TEST((rt_id(CP(op(rr, vcc))) == id< auto_dim_pair_t< 0_C, 0_R > >));

	BOOST_TEST((rt_id(CP(op(cc, vcr))) == id< auto_dim_pair_t< op(c, col_t(v)), op(r, row_t(v)) > >));
	BOOST_TEST((rt_id(CP(op(cr, vcr))) == id< auto_dim_pair_t< op(c, col_t(v)), 0_R > >));
	BOOST_TEST((rt_id(CP(op(rc, vcr))) == id< auto_dim_pair_t< 0_C, op(r, row_t(v)) > >));
	BOOST_TEST((rt_id(CP(op(rr, vcr))) == id< auto_dim_pair_t< 0_C, 0_R > >));

	BOOST_TEST((rt_id(CP(op(cc, vrr))) == id< auto_dim_pair_t< 0_C, 0_R > >));
	BOOST_TEST((rt_id(CP(op(cr, vrr))) == id< auto_dim_pair_t< 0_C, 0_R > >));
	BOOST_TEST((rt_id(CP(op(rc, vrr))) == id< auto_dim_pair_t< 0_C, 0_R > >));
	BOOST_TEST((rt_id(CP(op(rr, vrr))) == id< auto_dim_pair_t< 0_C, 0_R > >));

	BOOST_TEST((CP(op(cc, vcc).cols()) == cols(op(c, col_t(v)))));
	BOOST_TEST((CP(op(cr, vcc).cols()) == cols(op(c, col_t(v)))));
	BOOST_TEST((CP(op(rc, vcc).cols()) == cols(op(c, col_t(v)))));
	BOOST_TEST((CP(op(rr, vcc).cols()) == cols(op(c, col_t(v)))));

	BOOST_TEST((CP(op(cc, vcr).cols()) == cols(op(c, col_t(v)))));
	BOOST_TEST((CP(op(cr, vcr).cols()) == cols(op(c, col_t(v)))));
	BOOST_TEST((CP(op(rc, vcr).cols()) == cols(op(c, col_t(v)))));
	BOOST_TEST((CP(op(rr, vcr).cols()) == cols(op(c, col_t(v)))));

	BOOST_TEST((CP(op(cc, vrr).cols()) == cols(op(c, col_t(v)))));
	BOOST_TEST((CP(op(cr, vrr).cols()) == cols(op(c, col_t(v)))));
	BOOST_TEST((CP(op(rc, vrr).cols()) == cols(op(c, col_t(v)))));
	BOOST_TEST((CP(op(rr, vrr).cols()) == cols(op(c, col_t(v)))));

	BOOST_TEST((CP(op(cc, vcc).rows()) == rows(op(r, row_t(v)))));
	BOOST_TEST((CP(op(cr, vcc).rows()) == rows(op(r, row_t(v)))));
	BOOST_TEST((CP(op(rc, vcc).rows()) == rows(op(r, row_t(v)))));
	BOOST_TEST((CP(op(rr, vcc).rows()) == rows(op(r, row_t(v)))));

	BOOST_TEST((CP(op(cc, vcr).rows()) == rows(op(r, row_t(v)))));
	BOOST_TEST((CP(op(cr, vcr).rows()) == rows(op(r, row_t(v)))));
	BOOST_TEST((CP(op(rc, vcr).rows()) == rows(op(r, row_t(v)))));
	BOOST_TEST((CP(op(rr, vcr).rows()) == rows(op(r, row_t(v)))));

	BOOST_TEST((CP(op(cc, vrr).rows()) == rows(op(r, row_t(v)))));
	BOOST_TEST((CP(op(cr, vrr).rows()) == rows(op(r, row_t(v)))));
	BOOST_TEST((CP(op(rc, vrr).rows()) == rows(op(r, row_t(v)))));
	BOOST_TEST((CP(op(rr, vrr).rows()) == rows(op(r, row_t(v)))));
}

template < typename Op >
void dim_pair_t_arithmetic(){
	constexpr auto op = Op();
	constexpr auto c1 = 9_C;
	constexpr auto r1 = 15_R;
	constexpr auto c2 = 5_C;
	constexpr auto r2 = 7_R;

	constexpr auto cc1 = auto_dim_pair_t< c1, r1 >(cols< c1 >(), rows< r1 >());
	constexpr auto cr1 = auto_dim_pair_t< c1, 0_R >(cols< c1 >(), rows(r1));
	constexpr auto rc1 = auto_dim_pair_t< 0_C, r1 >(cols(c1), rows< r1 >());
	constexpr auto rr1 = auto_dim_pair_t< 0_C, 0_R >(cols(c1), rows(r1));

	constexpr auto cc2 = auto_dim_pair_t< c2, r2 >(cols< c2 >(), rows< r2 >());
	constexpr auto cr2 = auto_dim_pair_t< c2, 0_R >(cols< c2 >(), rows(r2));
	constexpr auto rc2 = auto_dim_pair_t< 0_C, r2 >(cols(c2), rows< r2 >());
	constexpr auto rr2 = auto_dim_pair_t< 0_C, 0_R >(cols(c2), rows(r2));

	BOOST_TEST((rt_id(CP(op(cc1, cc2))) == id< auto_dim_pair_t< op(c1, c2), op(r1, r2) > >));
	BOOST_TEST((rt_id(CP(op(cc1, cr2))) == id< auto_dim_pair_t< op(c1, c2), 0_R > >));
	BOOST_TEST((rt_id(CP(op(cc1, rc2))) == id< auto_dim_pair_t< 0_C, op(r1, r2) > >));
	BOOST_TEST((rt_id(CP(op(cc1, rr2))) == id< auto_dim_pair_t< 0_C, 0_R > >));

	BOOST_TEST((rt_id(CP(op(cr1, cc2))) == id< auto_dim_pair_t< op(c1, c2), 0_R > >));
	BOOST_TEST((rt_id(CP(op(cr1, cr2))) == id< auto_dim_pair_t< op(c1, c2), 0_R > >));
	BOOST_TEST((rt_id(CP(op(cr1, rc2))) == id< auto_dim_pair_t< 0_C, 0_R > >));
	BOOST_TEST((rt_id(CP(op(cr1, rr2))) == id< auto_dim_pair_t< 0_C, 0_R > >));

	BOOST_TEST((rt_id(CP(op(rc1, cc2))) == id< auto_dim_pair_t< 0_C, op(r1, r2) > >));
	BOOST_TEST((rt_id(CP(op(rc1, cr2))) == id< auto_dim_pair_t< 0_C, 0_R > >));
	BOOST_TEST((rt_id(CP(op(rc1, rc2))) == id< auto_dim_pair_t< 0_C, op(r1, r2) > >));
	BOOST_TEST((rt_id(CP(op(rc1, rr2))) == id< auto_dim_pair_t< 0_C, 0_R > >));

	BOOST_TEST((rt_id(CP(op(rr1, cc2))) == id< auto_dim_pair_t< 0_C, 0_R > >));
	BOOST_TEST((rt_id(CP(op(rr1, cr2))) == id< auto_dim_pair_t< 0_C, 0_R > >));
	BOOST_TEST((rt_id(CP(op(rr1, rc2))) == id< auto_dim_pair_t< 0_C, 0_R > >));
	BOOST_TEST((rt_id(CP(op(rr1, rr2))) == id< auto_dim_pair_t< 0_C, 0_R > >));

	BOOST_TEST((CP(op(cc1, cc2).cols()) == cols(op(c1, c2))));
	BOOST_TEST((CP(op(cc1, cr2).cols()) == cols(op(c1, c2))));
	BOOST_TEST((CP(op(cc1, rc2).cols()) == cols(op(c1, c2))));
	BOOST_TEST((CP(op(cc1, rr2).cols()) == cols(op(c1, c2))));

	BOOST_TEST((CP(op(cr1, cc2).cols()) == cols(op(c1, c2))));
	BOOST_TEST((CP(op(cr1, cr2).cols()) == cols(op(c1, c2))));
	BOOST_TEST((CP(op(cr1, rc2).cols()) == cols(op(c1, c2))));
	BOOST_TEST((CP(op(cr1, rr2).cols()) == cols(op(c1, c2))));

	BOOST_TEST((CP(op(rc1, cc2).cols()) == cols(op(c1, c2))));
	BOOST_TEST((CP(op(rc1, cr2).cols()) == cols(op(c1, c2))));
	BOOST_TEST((CP(op(rc1, rc2).cols()) == cols(op(c1, c2))));
	BOOST_TEST((CP(op(rc1, rr2).cols()) == cols(op(c1, c2))));

	BOOST_TEST((CP(op(rr1, cc2).cols()) == cols(op(c1, c2))));
	BOOST_TEST((CP(op(rr1, cr2).cols()) == cols(op(c1, c2))));
	BOOST_TEST((CP(op(rr1, rc2).cols()) == cols(op(c1, c2))));
	BOOST_TEST((CP(op(rr1, rr2).cols()) == cols(op(c1, c2))));

	BOOST_TEST((CP(op(cc1, cc2).rows()) == rows(op(r1, r2))));
	BOOST_TEST((CP(op(cc1, cr2).rows()) == rows(op(r1, r2))));
	BOOST_TEST((CP(op(cc1, rc2).rows()) == rows(op(r1, r2))));
	BOOST_TEST((CP(op(cc1, rr2).rows()) == rows(op(r1, r2))));

	BOOST_TEST((CP(op(cr1, cc2).rows()) == rows(op(r1, r2))));
	BOOST_TEST((CP(op(cr1, cr2).rows()) == rows(op(r1, r2))));
	BOOST_TEST((CP(op(cr1, rc2).rows()) == rows(op(r1, r2))));
	BOOST_TEST((CP(op(cr1, rr2).rows()) == rows(op(r1, r2))));

	BOOST_TEST((CP(op(rc1, cc2).rows()) == rows(op(r1, r2))));
	BOOST_TEST((CP(op(rc1, cr2).rows()) == rows(op(r1, r2))));
	BOOST_TEST((CP(op(rc1, rc2).rows()) == rows(op(r1, r2))));
	BOOST_TEST((CP(op(rc1, rr2).rows()) == rows(op(r1, r2))));

	BOOST_TEST((CP(op(rr1, cc2).rows()) == rows(op(r1, r2))));
	BOOST_TEST((CP(op(rr1, cr2).rows()) == rows(op(r1, r2))));
	BOOST_TEST((CP(op(rr1, rc2).rows()) == rows(op(r1, r2))));
	BOOST_TEST((CP(op(rr1, rr2).rows()) == rows(op(r1, r2))));
}

void get_dim_pair(){
	constexpr auto c = 3_C;
	constexpr auto r = 4_R;

	constexpr auto d1 = dim_pair(cols< c >(), rows< r >());
	constexpr auto d2 = dim_pair(cols< c >(), rows(r));
	constexpr auto d3 = dim_pair(cols(c), rows< r >());
	constexpr auto d4 = dim_pair(cols(c), rows(r));

	constexpr auto res01 = get(d1);
	constexpr auto res02 = get(d2);
	constexpr auto res03 = get(d3);
	constexpr auto res04 = get(d4);
	constexpr auto res05 = get(d1, d1);
	constexpr auto res06 = get(d1, d2);
	constexpr auto res07 = get(d1, d3);
	constexpr auto res08 = get(d1, d4);
	constexpr auto res09 = get(d2, d1);
	constexpr auto res10 = get(d2, d2);
	constexpr auto res11 = get(d2, d3);
	constexpr auto res12 = get(d2, d4);
	constexpr auto res13 = get(d3, d1);
	constexpr auto res14 = get(d3, d2);
	constexpr auto res15 = get(d3, d3);
	constexpr auto res16 = get(d3, d4);
	constexpr auto res17 = get(d4, d1);
	constexpr auto res18 = get(d4, d2);
	constexpr auto res19 = get(d4, d3);
	constexpr auto res20 = get(d4, d4);
	constexpr auto res21 = get(d1, d1, d1);
	constexpr auto res22 = get(d1, d1, d2);
	constexpr auto res23 = get(d1, d1, d3);
	constexpr auto res24 = get(d1, d1, d4);
	constexpr auto res25 = get(d1, d2, d1);
	constexpr auto res26 = get(d1, d2, d2);
	constexpr auto res27 = get(d1, d2, d3);
	constexpr auto res28 = get(d1, d2, d4);
	constexpr auto res29 = get(d1, d3, d1);
	constexpr auto res30 = get(d1, d3, d2);
	constexpr auto res31 = get(d1, d3, d3);
	constexpr auto res32 = get(d1, d3, d4);
	constexpr auto res33 = get(d1, d4, d1);
	constexpr auto res34 = get(d1, d4, d2);
	constexpr auto res35 = get(d1, d4, d3);
	constexpr auto res36 = get(d1, d4, d4);
	constexpr auto res37 = get(d2, d1, d1);
	constexpr auto res38 = get(d2, d1, d2);
	constexpr auto res39 = get(d2, d1, d3);
	constexpr auto res40 = get(d2, d1, d4);
	constexpr auto res41 = get(d2, d2, d1);
	constexpr auto res42 = get(d2, d2, d2);
	constexpr auto res43 = get(d2, d2, d3);
	constexpr auto res44 = get(d2, d2, d4);
	constexpr auto res45 = get(d2, d3, d1);
	constexpr auto res46 = get(d2, d3, d2);
	constexpr auto res47 = get(d2, d3, d3);
	constexpr auto res48 = get(d2, d3, d4);
	constexpr auto res49 = get(d2, d4, d1);
	constexpr auto res50 = get(d2, d4, d2);
	constexpr auto res51 = get(d2, d4, d3);
	constexpr auto res52 = get(d2, d4, d4);
	constexpr auto res53 = get(d3, d1, d1);
	constexpr auto res54 = get(d3, d1, d2);
	constexpr auto res55 = get(d3, d1, d3);
	constexpr auto res56 = get(d3, d1, d4);
	constexpr auto res57 = get(d3, d2, d1);
	constexpr auto res58 = get(d3, d2, d2);
	constexpr auto res59 = get(d3, d2, d3);
	constexpr auto res60 = get(d3, d2, d4);
	constexpr auto res61 = get(d3, d3, d1);
	constexpr auto res62 = get(d3, d3, d2);
	constexpr auto res63 = get(d3, d3, d3);
	constexpr auto res64 = get(d3, d3, d4);
	constexpr auto res65 = get(d3, d4, d1);
	constexpr auto res66 = get(d3, d4, d2);
	constexpr auto res67 = get(d3, d4, d3);
	constexpr auto res68 = get(d3, d4, d4);
	constexpr auto res69 = get(d4, d1, d1);
	constexpr auto res70 = get(d4, d1, d2);
	constexpr auto res71 = get(d4, d1, d3);
	constexpr auto res72 = get(d4, d1, d4);
	constexpr auto res73 = get(d4, d2, d1);
	constexpr auto res74 = get(d4, d2, d2);
	constexpr auto res75 = get(d4, d2, d3);
	constexpr auto res76 = get(d4, d2, d4);
	constexpr auto res77 = get(d4, d3, d1);
	constexpr auto res78 = get(d4, d3, d2);
	constexpr auto res79 = get(d4, d3, d3);
	constexpr auto res80 = get(d4, d3, d4);
	constexpr auto res81 = get(d4, d4, d1);
	constexpr auto res82 = get(d4, d4, d2);
	constexpr auto res83 = get(d4, d4, d3);
	constexpr auto res84 = get(d4, d4, d4);

	BOOST_TEST((rt_id(res01) == id< auto_dim_pair_t< c, r > >));
	BOOST_TEST((rt_id(res02) == id< auto_dim_pair_t< c, 0_R > >));
	BOOST_TEST((rt_id(res03) == id< auto_dim_pair_t< 0_C, r > >));
	BOOST_TEST((rt_id(res04) == id< auto_dim_pair_t< 0_C, 0_R > >));
	BOOST_TEST((rt_id(res05) == id< auto_dim_pair_t< c, r > >));
	BOOST_TEST((rt_id(res06) == id< auto_dim_pair_t< c, r > >));
	BOOST_TEST((rt_id(res07) == id< auto_dim_pair_t< c, r > >));
	BOOST_TEST((rt_id(res08) == id< auto_dim_pair_t< c, r > >));
	BOOST_TEST((rt_id(res09) == id< auto_dim_pair_t< c, r > >));
	BOOST_TEST((rt_id(res10) == id< auto_dim_pair_t< c, 0_R > >));
	BOOST_TEST((rt_id(res11) == id< auto_dim_pair_t< c, r > >));
	BOOST_TEST((rt_id(res12) == id< auto_dim_pair_t< c, 0_R > >));
	BOOST_TEST((rt_id(res13) == id< auto_dim_pair_t< c, r > >));
	BOOST_TEST((rt_id(res14) == id< auto_dim_pair_t< c, r > >));
	BOOST_TEST((rt_id(res15) == id< auto_dim_pair_t< 0_C, r > >));
	BOOST_TEST((rt_id(res16) == id< auto_dim_pair_t< 0_C, r > >));
	BOOST_TEST((rt_id(res17) == id< auto_dim_pair_t< c, r > >));
	BOOST_TEST((rt_id(res18) == id< auto_dim_pair_t< c, 0_R > >));
	BOOST_TEST((rt_id(res19) == id< auto_dim_pair_t< 0_C, r > >));
	BOOST_TEST((rt_id(res20) == id< auto_dim_pair_t< 0_C, 0_R > >));
	BOOST_TEST((rt_id(res21) == id< auto_dim_pair_t< c, r > >));
	BOOST_TEST((rt_id(res22) == id< auto_dim_pair_t< c, r > >));
	BOOST_TEST((rt_id(res23) == id< auto_dim_pair_t< c, r > >));
	BOOST_TEST((rt_id(res24) == id< auto_dim_pair_t< c, r > >));
	BOOST_TEST((rt_id(res25) == id< auto_dim_pair_t< c, r > >));
	BOOST_TEST((rt_id(res26) == id< auto_dim_pair_t< c, r > >));
	BOOST_TEST((rt_id(res27) == id< auto_dim_pair_t< c, r > >));
	BOOST_TEST((rt_id(res28) == id< auto_dim_pair_t< c, r > >));
	BOOST_TEST((rt_id(res29) == id< auto_dim_pair_t< c, r > >));
	BOOST_TEST((rt_id(res30) == id< auto_dim_pair_t< c, r > >));
	BOOST_TEST((rt_id(res31) == id< auto_dim_pair_t< c, r > >));
	BOOST_TEST((rt_id(res32) == id< auto_dim_pair_t< c, r > >));
	BOOST_TEST((rt_id(res33) == id< auto_dim_pair_t< c, r > >));
	BOOST_TEST((rt_id(res34) == id< auto_dim_pair_t< c, r > >));
	BOOST_TEST((rt_id(res35) == id< auto_dim_pair_t< c, r > >));
	BOOST_TEST((rt_id(res36) == id< auto_dim_pair_t< c, r > >));
	BOOST_TEST((rt_id(res37) == id< auto_dim_pair_t< c, r > >));
	BOOST_TEST((rt_id(res38) == id< auto_dim_pair_t< c, r > >));
	BOOST_TEST((rt_id(res39) == id< auto_dim_pair_t< c, r > >));
	BOOST_TEST((rt_id(res40) == id< auto_dim_pair_t< c, r > >));
	BOOST_TEST((rt_id(res41) == id< auto_dim_pair_t< c, r > >));
	BOOST_TEST((rt_id(res42) == id< auto_dim_pair_t< c, 0_R > >));
	BOOST_TEST((rt_id(res43) == id< auto_dim_pair_t< c, r > >));
	BOOST_TEST((rt_id(res44) == id< auto_dim_pair_t< c, 0_R > >));
	BOOST_TEST((rt_id(res45) == id< auto_dim_pair_t< c, r > >));
	BOOST_TEST((rt_id(res46) == id< auto_dim_pair_t< c, r > >));
	BOOST_TEST((rt_id(res47) == id< auto_dim_pair_t< c, r > >));
	BOOST_TEST((rt_id(res48) == id< auto_dim_pair_t< c, r > >));
	BOOST_TEST((rt_id(res49) == id< auto_dim_pair_t< c, r > >));
	BOOST_TEST((rt_id(res50) == id< auto_dim_pair_t< c, 0_R > >));
	BOOST_TEST((rt_id(res51) == id< auto_dim_pair_t< c, r > >));
	BOOST_TEST((rt_id(res52) == id< auto_dim_pair_t< c, 0_R > >));
	BOOST_TEST((rt_id(res53) == id< auto_dim_pair_t< c, r > >));
	BOOST_TEST((rt_id(res54) == id< auto_dim_pair_t< c, r > >));
	BOOST_TEST((rt_id(res55) == id< auto_dim_pair_t< c, r > >));
	BOOST_TEST((rt_id(res56) == id< auto_dim_pair_t< c, r > >));
	BOOST_TEST((rt_id(res57) == id< auto_dim_pair_t< c, r > >));
	BOOST_TEST((rt_id(res58) == id< auto_dim_pair_t< c, r > >));
	BOOST_TEST((rt_id(res59) == id< auto_dim_pair_t< c, r > >));
	BOOST_TEST((rt_id(res60) == id< auto_dim_pair_t< c, r > >));
	BOOST_TEST((rt_id(res61) == id< auto_dim_pair_t< c, r > >));
	BOOST_TEST((rt_id(res62) == id< auto_dim_pair_t< c, r > >));
	BOOST_TEST((rt_id(res63) == id< auto_dim_pair_t< 0_C, r > >));
	BOOST_TEST((rt_id(res64) == id< auto_dim_pair_t< 0_C, r > >));
	BOOST_TEST((rt_id(res65) == id< auto_dim_pair_t< c, r > >));
	BOOST_TEST((rt_id(res66) == id< auto_dim_pair_t< c, r > >));
	BOOST_TEST((rt_id(res67) == id< auto_dim_pair_t< 0_C, r > >));
	BOOST_TEST((rt_id(res68) == id< auto_dim_pair_t< 0_C, r > >));
	BOOST_TEST((rt_id(res69) == id< auto_dim_pair_t< c, r > >));
	BOOST_TEST((rt_id(res70) == id< auto_dim_pair_t< c, r > >));
	BOOST_TEST((rt_id(res71) == id< auto_dim_pair_t< c, r > >));
	BOOST_TEST((rt_id(res72) == id< auto_dim_pair_t< c, r > >));
	BOOST_TEST((rt_id(res73) == id< auto_dim_pair_t< c, r > >));
	BOOST_TEST((rt_id(res74) == id< auto_dim_pair_t< c, 0_R > >));
	BOOST_TEST((rt_id(res75) == id< auto_dim_pair_t< c, r > >));
	BOOST_TEST((rt_id(res76) == id< auto_dim_pair_t< c, 0_R > >));
	BOOST_TEST((rt_id(res77) == id< auto_dim_pair_t< c, r > >));
	BOOST_TEST((rt_id(res78) == id< auto_dim_pair_t< c, r > >));
	BOOST_TEST((rt_id(res79) == id< auto_dim_pair_t< 0_C, r > >));
	BOOST_TEST((rt_id(res80) == id< auto_dim_pair_t< 0_C, r > >));
	BOOST_TEST((rt_id(res81) == id< auto_dim_pair_t< c, r > >));
	BOOST_TEST((rt_id(res82) == id< auto_dim_pair_t< c, 0_R > >));
	BOOST_TEST((rt_id(res83) == id< auto_dim_pair_t< 0_C, r > >));
	BOOST_TEST((rt_id(res84) == id< auto_dim_pair_t< 0_C, 0_R > >));

	BOOST_TEST((res01 == dim_pair(c, r)));
	BOOST_TEST((res02 == dim_pair(c, r)));
	BOOST_TEST((res03 == dim_pair(c, r)));
	BOOST_TEST((res04 == dim_pair(c, r)));
	BOOST_TEST((res05 == dim_pair(c, r)));
	BOOST_TEST((res06 == dim_pair(c, r)));
	BOOST_TEST((res07 == dim_pair(c, r)));
	BOOST_TEST((res08 == dim_pair(c, r)));
	BOOST_TEST((res09 == dim_pair(c, r)));
	BOOST_TEST((res10 == dim_pair(c, r)));
	BOOST_TEST((res11 == dim_pair(c, r)));
	BOOST_TEST((res12 == dim_pair(c, r)));
	BOOST_TEST((res13 == dim_pair(c, r)));
	BOOST_TEST((res14 == dim_pair(c, r)));
	BOOST_TEST((res15 == dim_pair(c, r)));
	BOOST_TEST((res16 == dim_pair(c, r)));
	BOOST_TEST((res17 == dim_pair(c, r)));
	BOOST_TEST((res18 == dim_pair(c, r)));
	BOOST_TEST((res19 == dim_pair(c, r)));
	BOOST_TEST((res20 == dim_pair(c, r)));
	BOOST_TEST((res21 == dim_pair(c, r)));
	BOOST_TEST((res22 == dim_pair(c, r)));
	BOOST_TEST((res23 == dim_pair(c, r)));
	BOOST_TEST((res24 == dim_pair(c, r)));
	BOOST_TEST((res25 == dim_pair(c, r)));
	BOOST_TEST((res26 == dim_pair(c, r)));
	BOOST_TEST((res27 == dim_pair(c, r)));
	BOOST_TEST((res28 == dim_pair(c, r)));
	BOOST_TEST((res29 == dim_pair(c, r)));
	BOOST_TEST((res30 == dim_pair(c, r)));
	BOOST_TEST((res31 == dim_pair(c, r)));
	BOOST_TEST((res32 == dim_pair(c, r)));
	BOOST_TEST((res33 == dim_pair(c, r)));
	BOOST_TEST((res34 == dim_pair(c, r)));
	BOOST_TEST((res35 == dim_pair(c, r)));
	BOOST_TEST((res36 == dim_pair(c, r)));
	BOOST_TEST((res37 == dim_pair(c, r)));
	BOOST_TEST((res38 == dim_pair(c, r)));
	BOOST_TEST((res39 == dim_pair(c, r)));
	BOOST_TEST((res40 == dim_pair(c, r)));
	BOOST_TEST((res41 == dim_pair(c, r)));
	BOOST_TEST((res42 == dim_pair(c, r)));
	BOOST_TEST((res43 == dim_pair(c, r)));
	BOOST_TEST((res44 == dim_pair(c, r)));
	BOOST_TEST((res45 == dim_pair(c, r)));
	BOOST_TEST((res46 == dim_pair(c, r)));
	BOOST_TEST((res47 == dim_pair(c, r)));
	BOOST_TEST((res48 == dim_pair(c, r)));
	BOOST_TEST((res49 == dim_pair(c, r)));
	BOOST_TEST((res50 == dim_pair(c, r)));
	BOOST_TEST((res51 == dim_pair(c, r)));
	BOOST_TEST((res52 == dim_pair(c, r)));
	BOOST_TEST((res53 == dim_pair(c, r)));
	BOOST_TEST((res54 == dim_pair(c, r)));
	BOOST_TEST((res55 == dim_pair(c, r)));
	BOOST_TEST((res56 == dim_pair(c, r)));
	BOOST_TEST((res57 == dim_pair(c, r)));
	BOOST_TEST((res58 == dim_pair(c, r)));
	BOOST_TEST((res59 == dim_pair(c, r)));
	BOOST_TEST((res60 == dim_pair(c, r)));
	BOOST_TEST((res61 == dim_pair(c, r)));
	BOOST_TEST((res62 == dim_pair(c, r)));
	BOOST_TEST((res63 == dim_pair(c, r)));
	BOOST_TEST((res64 == dim_pair(c, r)));
	BOOST_TEST((res65 == dim_pair(c, r)));
	BOOST_TEST((res66 == dim_pair(c, r)));
	BOOST_TEST((res67 == dim_pair(c, r)));
	BOOST_TEST((res68 == dim_pair(c, r)));
	BOOST_TEST((res69 == dim_pair(c, r)));
	BOOST_TEST((res70 == dim_pair(c, r)));
	BOOST_TEST((res71 == dim_pair(c, r)));
	BOOST_TEST((res72 == dim_pair(c, r)));
	BOOST_TEST((res73 == dim_pair(c, r)));
	BOOST_TEST((res74 == dim_pair(c, r)));
	BOOST_TEST((res75 == dim_pair(c, r)));
	BOOST_TEST((res76 == dim_pair(c, r)));
	BOOST_TEST((res77 == dim_pair(c, r)));
	BOOST_TEST((res78 == dim_pair(c, r)));
	BOOST_TEST((res79 == dim_pair(c, r)));
	BOOST_TEST((res80 == dim_pair(c, r)));
	BOOST_TEST((res81 == dim_pair(c, r)));
	BOOST_TEST((res82 == dim_pair(c, r)));
	BOOST_TEST((res83 == dim_pair(c, r)));
	BOOST_TEST((res84 == dim_pair(c, r)));
}

int main(int argc, char** argv, char** /*envp*/){
	auto ts = BOOST_TEST_SUITE("suite_dim");

	add_test< col_t >(ts);
	add_test< row_t >(ts);
	add_test< dim_t >(ts);
	ts->add(BOOST_TEST_CASE(&index_literal));
	ts->add(BOOST_TEST_CASE(&dim_t_literal));
	ts->add(BOOST_TEST_CASE(&dim_literal));
	ts->add(BOOST_TEST_CASE(&make_col));
	ts->add(BOOST_TEST_CASE(&make_row));
	ts->add(BOOST_TEST_CASE(&make_dim));
	ts->add(BOOST_TEST_CASE(&dim_pair_t_default_construct));
	ts->add(BOOST_TEST_CASE(&dim_pair_t_construct));
	ts->add(BOOST_TEST_CASE(&dim_pair_t_make));
	ts->add(BOOST_TEST_CASE(&dim_pair_t_compare));
	ts->add(BOOST_TEST_CASE(&dim_pair_t_arithmetic_size_t< std::multiplies<> >));
	ts->add(BOOST_TEST_CASE(&dim_pair_t_arithmetic_size_t< std::divides<> >));
	ts->add(BOOST_TEST_CASE(&dim_pair_t_arithmetic_size_t< std::modulus<> >));
	ts->add(BOOST_TEST_CASE(&dim_pair_t_arithmetic< std::plus<> >));
	ts->add(BOOST_TEST_CASE(&dim_pair_t_arithmetic< std::minus<> >));
	ts->add(BOOST_TEST_CASE(&dim_pair_t_arithmetic< std::multiplies<> >));
	ts->add(BOOST_TEST_CASE(&dim_pair_t_arithmetic< std::divides<> >));
	ts->add(BOOST_TEST_CASE(&dim_pair_t_arithmetic< std::modulus<> >));
	ts->add(BOOST_TEST_CASE(&get_dim_pair));

	utf::framework::master_test_suite().add(ts);

	return utf::unit_test_main(&init_unit_test, argc, argv);
}

ext: cpp

max_stars_repo_name: bebuch/Mitrax

max_issues_repo_name: bebuch/Mitrax

max_forks_repo_name: bebuch/Mitrax


text:
// Copyright @2012 JDSU Xtreme

#define CSPARAMTRANSLATOR_INSTANTIATE_DEFINE_TEMPLATES 1
#include "xtreme/config/internal/csparamtranslator.h"
#undef CSPARAMTRANSLATOR_INSTANTIATE_DEFINE_TEMPLATES

#include <sstream>
#include <boost/foreach.hpp>
#include <boost/lexical_cast.hpp>

#include "xtreme/config/internal/csparamstoremgr.h"

namespace xtreme {
  namespace config {
    inline const char * const BoolToString(bool b) {
      // It should be OK to return a pointer to string literal [as they live throughout the prog lifetime]
      return (b ? "true" : "false");
    }
    inline bool StringToBool(const std::string& str) {
      return (("true" == str) ? true : false);
    }

    template <typename NUMTYPE>
    inline std::string NumToString(NUMTYPE num) {
      std::ostringstream ssConvert;
      ssConvert << num;
      return ssConvert.str();
    }
    template <typename NUMTYPE>
    inline NUMTYPE StringToNum(const std::string& str) {
      std::istringstream ssConvert(str);
      NUMTYPE num;
      return ((ssConvert >> num) ? num : 0);
    }
    // Explicit template instantiation
    template std::string NumToString<uint32_t>(uint32_t num);
    template std::string NumToString<uint64_t>(uint64_t num);
    template uint32_t StringToNum<uint32_t>(const std::string& str);
    template uint64_t StringToNum<uint64_t>(const std::string& str);

    // START: CSParamTranslatorBOOL methods
    iptr_CSParam_t CSParamTranslatorBOOL::makeCSParam(
        const std::string& cfgName, CSParamStoreMgr * pStoreMgr)
            throw(XtremeException) {
      if (BOOL_T != pStoreMgr->mdataGetType(cfgName))
        throw xtreme::XtremeException(
            cfgName + ": 'type' in MetaData is NOT 'bool'");
      iptr_CSParam_bool_t ipNewVal = new CSParam_bool_t(cfgName);
      ipNewVal->setValue(StringToBool(pStoreMgr->mdataGetDefault(cfgName)));
      return ipNewVal;
    }

    iptr_CSParam_t CSParamTranslatorBOOL::tr_read(const std::string& cfgName,
        CSParamStoreMgr * pStoreMgr) throw(XtremeException) {
      // Make CSParam
      iptr_CSParam_t pRdVal = makeCSParam(cfgName, pStoreMgr);

      // Read from store & Set value
      // If parameter store does NOT define a value ... simply return the default value
      try {
        (param_downcast<CSParam_bool_t >(pRdVal.get()))->setValue(
            StringToBool(pStoreMgr->paramRead(cfgName)));
      } catch(const xtreme::XtremeException& ex) {
      }

      return pRdVal;
    }

    void CSParamTranslatorBOOL::tr_write(const CSParam_t& newVal,
        CSParamStoreMgr * pStoreMgr) throw(XtremeException) {
      std::string valStr = BoolToString(
          (*param_downcast<CSParam_bool_t>(const_cast<p_CSParam_t>(&newVal))).getValue());
      pStoreMgr->paramWrite(newVal.getName(), valStr);
    }

    iptr_CSParam_t CSParamTranslatorBOOL::tr_read_OnList(const std::string& cfgName,
        const std::string& itemXPath, CSParamStoreMgr * pStoreMgr) throw(xtreme::XtremeException) {
      // Make CSParam
      iptr_CSParam_t pRdVal = makeCSParam(cfgName, pStoreMgr);

      // Read from store & Set value
      // If parameter store does NOT define a value ... simply return the default value
      try {
        (param_downcast<CSParam_bool_t >(pRdVal.get()))->setValue(
            StringToBool(pStoreMgr->paramRead(itemXPath)));
      } catch(const xtreme::XtremeException& ex) {
      }
      return pRdVal;
    }

    void CSParamTranslatorBOOL::tr_write_OnList(const CSParam_t& newVal, const std::string& itemXPath,
        CSParamStoreMgr * pStoreMgr) throw(xtreme::XtremeException) {
      std::string valStr = BoolToString(
          (*param_downcast<CSParam_bool_t>(const_cast<p_CSParam_t>(&newVal))).getValue());
      pStoreMgr->paramWrite(itemXPath, valStr);
    }
    // END:   CSParamTranslatorBOOL methods

    // START: CSParamTranslatorSTRING methods
    iptr_CSParam_t CSParamTranslatorSTRING::makeCSParam(
        const std::string& cfgName, CSParamStoreMgr * pStoreMgr)
            throw(XtremeException) {
      if (STRING_T != pStoreMgr->mdataGetType(cfgName))
        throw xtreme::XtremeException(
            cfgName + ": 'type' in MetaData is NOT 'string'");
      iptr_CSParam_string_t ipNewVal = new CSParam_string_t(cfgName);
      ipNewVal->setValue(pStoreMgr->mdataGetDefault(cfgName));
      return ipNewVal;
    }

    iptr_CSParam_t CSParamTranslatorSTRING::tr_read(const std::string& cfgName,
        CSParamStoreMgr * pStoreMgr) throw(XtremeException) {
      // Make CSParam
      iptr_CSParam_t pRdVal = makeCSParam(cfgName, pStoreMgr);

      // Read from store & Set value
      // If parameter store does NOT define a value ... simply return the default value
      try {
        (param_downcast<CSParam_string_t >(pRdVal.get()))->setValue(
            pStoreMgr->paramRead(cfgName));
      } catch(const xtreme::XtremeException& ex) {
      }

      return pRdVal;
    }

    void CSParamTranslatorSTRING::tr_write(const CSParam_t& newVal,
        CSParamStoreMgr * pStoreMgr) throw(XtremeException) {
      const std::string valStr =
          (*param_downcast<CSParam_string_t>(const_cast<p_CSParam_t>(&newVal))).getValue();
      pStoreMgr->paramWrite(newVal.getName(), valStr);
    }

    iptr_CSParam_t CSParamTranslatorSTRING::tr_read_OnList(const std::string& cfgName,
        const std::string& itemXPath, CSParamStoreMgr * pStoreMgr) throw(xtreme::XtremeException) {
      // Make CSParam
      iptr_CSParam_t pRdVal = makeCSParam(cfgName, pStoreMgr);

      // Read from store & Set value
      // If parameter store does NOT define a value ... simply return the default value
      try {
        (param_downcast<CSParam_string_t >(pRdVal.get()))->setValue(
            pStoreMgr->paramRead(itemXPath));
      } catch(const xtreme::XtremeException& ex) {
      }
      return pRdVal;
    }

    void CSParamTranslatorSTRING::tr_write_OnList(const CSParam_t& newVal, const std::string& itemXPath,
        CSParamStoreMgr * pStoreMgr) throw(xtreme::XtremeException) {
      const std::string valStr =
          (*param_downcast<CSParam_string_t>(const_cast<p_CSParam_t>(&newVal))).getValue();
      pStoreMgr->paramWrite(itemXPath, valStr);
    }
    // END:   CSParamTranslatorSTRING methods

    // START: CSParamTranslatorNUM<NUMTYPE> methods
    // makeCSParam() member function needs 'specialization's for different NUMTYPE(s)
    template<>
    iptr_CSParam_t CSParamTranslatorNUM<uint32_t>::makeCSParam(
        const std::string& cfgName, CSParamStoreMgr * pStoreMgr)
            throw(XtremeException) {
      if (UINT_T != pStoreMgr->mdataGetType(cfgName))
        throw xtreme::XtremeException(
            cfgName + ": 'type' in MetaData is NOT 'unsigned int or uint'");
      iptr_CSParam_uint_t ipNewVal = new CSParam_uint_t(cfgName);
      ipNewVal->setValue(StringToNum<uint32_t>(pStoreMgr->mdataGetDefault(cfgName)));
      return ipNewVal;
    }

    template<>
    iptr_CSParam_t CSParamTranslatorNUM<uint64_t>::makeCSParam(
        const std::string& cfgName, CSParamStoreMgr * pStoreMgr)
            throw(XtremeException) {
      if (UINT64_T != pStoreMgr->mdataGetType(cfgName))
        throw xtreme::XtremeException(
            cfgName + ": 'type' in MetaData is NOT 'unsigned int64 or uint64'");
      iptr_CSParam_uint64_t ipNewVal = new CSParam_uint64_t(cfgName);
      ipNewVal->setValue(StringToNum<uint64_t>(pStoreMgr->mdataGetDefault(cfgName)));
      return ipNewVal;
    }

    template<typename NUMTYPE>
    iptr_CSParam_t CSParamTranslatorNUM<NUMTYPE>::tr_read(const std::string& cfgName,
        CSParamStoreMgr * pStoreMgr) throw(XtremeException) {
      // Make CSParam
      iptr_CSParam_t pRdVal = makeCSParam(cfgName, pStoreMgr);

      // Read from store & Set value
      // If parameter store does NOT define a value ... simply return the default value
      try {
        (param_downcast<CSParamVal<NUMTYPE> >(pRdVal.get()))->setValue(
            StringToNum<NUMTYPE>(pStoreMgr->paramRead(cfgName)));
      } catch(const xtreme::XtremeException& ex) {
      }

      return pRdVal;
    }

    template<typename NUMTYPE>
    void CSParamTranslatorNUM<NUMTYPE>::tr_write(const CSParam_t& newVal,
        CSParamStoreMgr * pStoreMgr) throw(XtremeException) {
      std::string valStr = NumToString<NUMTYPE>(
          (*param_downcast<CSParamVal<NUMTYPE> >(const_cast<p_CSParam_t>(&newVal))).getValue());
      pStoreMgr->paramWrite(newVal.getName(), valStr);
    }

    template<typename NUMTYPE>
    iptr_CSParam_t CSParamTranslatorNUM<NUMTYPE>::tr_read_OnList(const std::string& cfgName,
        const std::string& itemXPath, CSParamStoreMgr * pStoreMgr) throw(xtreme::XtremeException) {
      // Make CSParam
      iptr_CSParam_t pRdVal = makeCSParam(cfgName, pStoreMgr);

      // Read from store & Set value
      // If parameter store does NOT define a value ... simply return the default value
      try {
        (param_downcast<CSParamVal<NUMTYPE> >(pRdVal.get()))->setValue(
            StringToNum<NUMTYPE>(pStoreMgr->paramRead(itemXPath)));
      } catch(const xtreme::XtremeException& ex) {
      }
      return pRdVal;
    }

    template<typename NUMTYPE>
    void CSParamTranslatorNUM<NUMTYPE>::tr_write_OnList(const CSParam_t& newVal, const std::string& itemXPath,
        CSParamStoreMgr * pStoreMgr) throw(xtreme::XtremeException) {
      std::string valStr = NumToString<NUMTYPE>(
          (*param_downcast<CSParamVal<NUMTYPE> >(const_cast<p_CSParam_t>(&newVal))).getValue());
      pStoreMgr->paramWrite(itemXPath, valStr);
    }

    // Explicit template instantiation(s)
    template class CSParamTranslatorNUM<uint32_t>;
    template class CSParamTranslatorNUM<uint64_t>;

    // END:   CSParamTranslatorNUM<NUMTYPE> methods

    // START: CSParamTranslatorCOMPLEX methods
    iptr_CSParam_t CSParamTranslatorCOMPLEX::makeCSParam(const std::string& cfgName,
        CSParamStoreMgr * pStoreMgr) throw(xtreme::XtremeException) {
      if (COMPLEX_T != pStoreMgr->mdataGetType(cfgName))
        throw xtreme::XtremeException(
            cfgName + ": 'type' in MetaData is NOT 'complex'");
      iptr_CSParam_complex_t ipNewVal = new CSParam_complex_t(cfgName);
      discoverFields(cfgName, pStoreMgr, ipNewVal);
      // There is NO 'default' for complex parameters
      return ipNewVal;
    }

    iptr_CSParam_t CSParamTranslatorCOMPLEX::tr_read(const std::string& cfgName,
        CSParamStoreMgr * pStoreMgr) throw(xtreme::XtremeException) {
      // Make CSParam
      iptr_CSParam_t pRdVal = makeCSParam(cfgName, pStoreMgr);
      CSParam_complex_t * ptrRdComplexParam = param_downcast<CSParam_complex_t >(pRdVal.get());

      // For each field: Read from store & Set value
      // If parameter store does NOT define a value ... simply return the default value
      try {
        ParamRoster_t retFields = ptrRdComplexParam->getValue().getFieldsRoster();
        // TODO(Shilpa): is any deep copy assignment needed below?
        // OR the intrusive_ptrs will duplicate themselves in default operator generated by compiler
        ComplexVal readVal = ptrRdComplexParam->getValue();
        BOOST_FOREACH(const std::string& aFld, retFields) {
          std::string cfgNameOfFld = cfgName + "/" + aFld;
          CSPARAM_TYPE typeOfFld = pStoreMgr->mdataGetType(cfgNameOfFld);
          CSPARAM_OCCUR occurOfFld = pStoreMgr->mdataGetOccurence(cfgNameOfFld);
          iptr_CSParam_t pVal = pStoreMgr->read(cfgNameOfFld,
              typeOfFld, (SINGLE_T == occurOfFld));
          readVal.setFieldValue(aFld, pVal);
        }
        ptrRdComplexParam->setValue(readVal);
      } catch(const xtreme::XtremeException& ex) {
      }

      return pRdVal;
    }

    void CSParamTranslatorCOMPLEX::tr_write(const CSParam_t& newVal, CSParamStoreMgr * pStoreMgr)
        throw(xtreme::XtremeException) {
      // For intrusive smart pointer it's OK to get raw pointer (as counter is IN object itself)
      const CSParam_complex_t* ptrWrComplexParam =
          param_downcast<CSParam_complex_t>(const_cast<p_CSParam_t>(&newVal));

      // For each field: Write to store
      ComplexVal writeVal = ptrWrComplexParam->getValue();
      ParamRoster_t retFields = writeVal.getFieldsRoster();
      BOOST_FOREACH(const std::string& aFld, retFields) {
        std::string cfgNameOfFld = newVal.getName() + "/" + aFld;
        CSPARAM_TYPE typeOfFld = pStoreMgr->mdataGetType(cfgNameOfFld);
        CSPARAM_OCCUR occurOfFld = pStoreMgr->mdataGetOccurence(cfgNameOfFld);
        iptr_CSParam_t ipNewFldParam = writeVal.getFieldValue(aFld);
        pStoreMgr->write(typeOfFld,
            *(ipNewFldParam.get()),   // Casting/dereferencing ... does not cause object slice.
            (SINGLE_T == occurOfFld));
      }
    }

    void CSParamTranslatorCOMPLEX::discoverFields(const std::string& cfgName, CSParamStoreMgr * pStoreMgr,
        iptr_CSParam_complex_t ipComplexParam) {
      ParamRoster_t retFields;
      ComplexVal newVal;
      pStoreMgr->mdataGetFieldsInComplex(cfgName, retFields);
      BOOST_FOREACH(const std::string& aFld, retFields) {
        newVal.addField(aFld);
      }
      ipComplexParam.get()->setValue(newVal);
      return;
    }

    iptr_CSParam_t CSParamTranslatorCOMPLEX::tr_read_OnList(const std::string& cfgName,
        const std::string& itemXPath, CSParamStoreMgr * pStoreMgr) throw(xtreme::XtremeException) {
      // Make CSParam
      iptr_CSParam_t pRdVal = makeCSParam(cfgName, pStoreMgr);
      CSParam_complex_t * ptrRdComplexParam = param_downcast<CSParam_complex_t >(pRdVal.get());

      // For each field: Read from store & Set value
      // If parameter store does NOT define a value ... simply return the default value
      try {
        ParamRoster_t retFields = ptrRdComplexParam->getValue().getFieldsRoster();
        // TODO(Shilpa): is any deep copy assignment needed below?
        // OR the intrusive_ptrs will duplicate themselves in default operator generated by compiler
        ComplexVal readVal = ptrRdComplexParam->getValue();
        BOOST_FOREACH(const std::string& aFld, retFields) {
          std::string cfgNameOfFld = cfgName + "/" + aFld;
          std::string cfgXPathOfFld= itemXPath + "/" + aFld;
          CSPARAM_TYPE typeOfFld   = pStoreMgr->mdataGetType(cfgNameOfFld);
          CSPARAM_OCCUR occurOfFld = pStoreMgr->mdataGetOccurence(cfgNameOfFld);
          iptr_CSParam_t pVal = pStoreMgr->read_OnList(cfgNameOfFld, cfgXPathOfFld,
              typeOfFld, (SINGLE_T == occurOfFld));
          readVal.setFieldValue(aFld, pVal);
        }
        ptrRdComplexParam->setValue(readVal);
      } catch(const xtreme::XtremeException& ex) {
      }
      return pRdVal;
    }

    void CSParamTranslatorCOMPLEX::tr_write_OnList(const CSParam_t& newVal, const std::string& itemXPath,
        CSParamStoreMgr * pStoreMgr) throw(xtreme::XtremeException) {
      // For intrusive smart pointer it's OK to get raw pointer (as counter is IN object itself)
      const CSParam_complex_t* ptrWrComplexParam =
            param_downcast<CSParam_complex_t>(const_cast<p_CSParam_t>(&newVal));

      // For each field: Write to store [Use given itemPath to write
      ComplexVal writeVal = ptrWrComplexParam->getValue();
      ParamRoster_t retFields = writeVal.getFieldsRoster();
      BOOST_FOREACH(const std::string& aFld, retFields) {
        std::string cfgNameOfFld = newVal.getName() + "/" + aFld;
        std::string cfgXPathOfFld= itemXPath + "/" + aFld;
        CSPARAM_TYPE typeOfFld = pStoreMgr->mdataGetType(cfgNameOfFld);
        CSPARAM_OCCUR occurOfFld = pStoreMgr->mdataGetOccurence(cfgNameOfFld);
        iptr_CSParam_t ipNewFldParam = writeVal.getFieldValue(aFld);
        pStoreMgr->write_OnList(cfgXPathOfFld,
            typeOfFld,
            *(ipNewFldParam.get()),   // Casting/dereferencing ... does not cause object slice.
            (SINGLE_T == occurOfFld));
      }
    }
    // END:   CSParamTranslatorCOMPLEX methods

    // START: CSParamTranslatorList methods
    template<typename VALTYPE>
    CSParamTranslatorList<VALTYPE>::CSParamTranslatorList(CSPARAM_TYPE _type):
        CSParamTranslator(), m_ItemType(_type) {
    }

    template<typename VALTYPE>
    iptr_CSParam_t CSParamTranslatorList<VALTYPE>::makeCSParam(
        const std::string& cfgName, CSParamStoreMgr * pStoreMgr)
            throw(XtremeException) {
      if ((m_ItemType != pStoreMgr->mdataGetType(cfgName)) ||
          (MULTIPLE_T != pStoreMgr->mdataGetOccurence(cfgName)))
        throw xtreme::XtremeException(
            cfgName + ": 'type' &/or 'occur' in MetaData does NOT match");
      std::string keyName = pStoreMgr->mdataGetKeyName(cfgName);
      iptr_CSParam_t ipNewVal = new CSParamValList<VALTYPE>(cfgName, keyName);
      // There is NO 'default' for list of parameters
      return ipNewVal;
    }

    template<typename VALTYPE>
    iptr_CSParam_t CSParamTranslatorList<VALTYPE>::tr_read(const std::string& cfgName,
        CSParamStoreMgr * pStoreMgr) throw(XtremeException) {
      // Make CSParam
      iptr_CSParam_t ipRdParam = makeCSParam(cfgName, pStoreMgr);

      // Discover/Read Items
      discoverItems(ipRdParam, cfgName, pStoreMgr);

      return ipRdParam;
    }

    template<typename VALTYPE>
    void CSParamTranslatorList<VALTYPE>::tr_write(const CSParam_t& newVal,
        CSParamStoreMgr * pStoreMgr) throw(XtremeException) {
      // Write all items
      writeItems(newVal, newVal.getName(), pStoreMgr);
      return;
    }

    template<typename VALTYPE>
    void CSParamTranslatorList<VALTYPE>::writeItems(const CSParam_t& newVal, const std::string& writeXPath,
        CSParamStoreMgr * pStoreMgr) throw(XtremeException) {
      if (newVal.isSolitary() || (newVal.getType() != m_ItemType))
        throw xtreme::XtremeException(
            newVal.getName() + ": 'type' &/or 'occur' of CSParam is NOT recognized by translator");
      // For intrusive smart pointer it's OK to get raw pointer (as counter is IN object itself)
      const CSParamValList<VALTYPE>* ptrWrListParam =
          param_downcast<CSParamValList<VALTYPE> >(const_cast<p_CSParam_t>(&newVal));

      const std::string cfgNameOfItem = ptrWrListParam->getName();
      const std::string keyFld = ptrWrListParam->getKeyFld();
      bool isKeyProvided = (keyFld.find_first_not_of(" \t\n\v\f\r") != std::string::npos);
      std::string writeXPathOfItem;

      if (pStoreMgr->mdataGetKeyName(cfgNameOfItem) !=  keyFld)
        throw xtreme::XtremeException(
            newVal.getName() + ": 'key' of CSParam in MetaData is NOT - " + keyFld);

      // For each item on list: Write to store
      Key_Values_t allKeys;
      ptrWrListParam->getKeyValues(allKeys);

      BOOST_FOREACH(const std::string& aKeyVal, allKeys) {
        VALTYPE itemVal = ptrWrListParam->getItemValue(aKeyVal);
        iptr_CSParam_t itemParam = pStoreMgr->makeEmptyCSParam(cfgNameOfItem, m_ItemType, true);
        (param_downcast<CSParamVal<VALTYPE> > (itemParam))->setValue(itemVal);

        if (isKeyProvided)
          writeXPathOfItem = writeXPath + "[./" + keyFld + "=\"" + aKeyVal + "\"]";
        else
          writeXPathOfItem = writeXPath + "[" + aKeyVal + "]";   // no KEY field, use index

        pStoreMgr->write_OnList(writeXPathOfItem,
            m_ItemType,
            *(itemParam.get()),   // Casting/dereferencing ... does not cause object slice.
            true);
      }
      return;
    }

    template<typename VALTYPE>
    void CSParamTranslatorList<VALTYPE>::discoverItems(iptr_CSParam_t _ipRdParam, const std::string& readXPath,
        CSParamStoreMgr * pStoreMgr) {
      if (_ipRdParam->isSolitary() || (_ipRdParam->getType() != m_ItemType))
        throw xtreme::XtremeException(
            _ipRdParam->getName() + ": 'type' &/or 'occur' of CSParam is NOT recognized by translator");

      // For intrusive smart pointer it's OK to get raw pointer (as counter is IN object itself)
      CSParamValList<VALTYPE> * ptrRdListParam =
          param_downcast<CSParamValList<VALTYPE> > (_ipRdParam.get());
      std::string cfgName= ptrRdListParam->getName();
      std::string keyFld = ptrRdListParam->getKeyFld();
      bool isKeyProvided = (keyFld.find_first_not_of(" \t\n\v\f\r") != std::string::npos);
      std::string predicateStr;

      if (isKeyProvided) {
        // If 'key' is NOT empty/blank ... then use the 'key-values' in 'predicate'

        std::vector<std::string> keyValues;
        pStoreMgr->paramGetValues(readXPath+"/"+keyFld, keyValues);
        BOOST_FOREACH(const std::string& aKeyVal, keyValues) {
          predicateStr = "[./" + keyFld + "=\"" + aKeyVal + "\"]";
          iptr_CSParam_t ipRdItemParam = pStoreMgr->read_OnList(cfgName, readXPath + predicateStr, m_ItemType, true);
          CSParamVal<VALTYPE>* pParam = param_downcast<CSParamVal<VALTYPE> >(ipRdItemParam.get());
          ptrRdListParam->setItemValue(aKeyVal, pParam->getValue());
        }
      } else {
        // Else when 'key' IS empty/blank ... then use the count as index in 'predicate'

        uint32_t itemCount = pStoreMgr->paramGetCount(cfgName);
        for (uint32_t i = 1; i <= itemCount; i++) {
          predicateStr = "[" + NumToString<uint32_t>(i) + "]";
          iptr_CSParam_t ipRdItemParam = pStoreMgr->read_OnList(cfgName, readXPath + predicateStr, m_ItemType, true);
          CSParamVal<VALTYPE>* pParam = param_downcast<CSParamVal<VALTYPE> >(ipRdItemParam.get());
          ptrRdListParam->setItemValue(""+i, pParam->getValue());
        }
      }
      return;
    }

    template<typename VALTYPE>
    iptr_CSParam_t CSParamTranslatorList<VALTYPE>::tr_read_OnList(const std::string& cfgName,
        const std::string& itemXPath, CSParamStoreMgr * pStoreMgr) throw(xtreme::XtremeException) {
      // Make CSParam
      iptr_CSParam_t ipRdParam = makeCSParam(cfgName, pStoreMgr);

      // Discover/Read Items
      discoverItems(ipRdParam, itemXPath, pStoreMgr);

      return ipRdParam;
    }

    template<typename VALTYPE>
    void CSParamTranslatorList<VALTYPE>::tr_write_OnList(const CSParam_t& newVal, const std::string& itemXPath,
        CSParamStoreMgr * pStoreMgr) throw(xtreme::XtremeException) {
      // Write all items [at given base-XPath
      writeItems(newVal, itemXPath, pStoreMgr);
      return;
    }
    // END:   CSParamTranslatorList methods

    CSParamTranslatorFactoryMethod::CSParamTranslatorFactoryMethod() {
      m_ipTRSLTR_bool   = new CSParamTranslatorBOOL();
      m_ipTRSLTR_string = new CSParamTranslatorSTRING();
      m_ipTRSLTR_uint   = new CSParamTranslatorNUM<uint32_t>();
      m_ipTRSLTR_uint64 = new CSParamTranslatorNUM<uint64_t>();
      m_ipTRSLTR_complex= new CSParamTranslatorCOMPLEX();

      m_ipTRSLTR_list_bool   = new CSParamTranslatorList<bool>(BOOL_T);
      m_ipTRSLTR_list_string = new CSParamTranslatorList<std::string>(STRING_T);
      m_ipTRSLTR_list_uint   = new CSParamTranslatorList<uint32_t>(UINT_T);
      m_ipTRSLTR_list_uint64 = new CSParamTranslatorList<uint64_t>(UINT64_T);
      m_ipTRSLTR_list_complex= new CSParamTranslatorList<ComplexVal>(COMPLEX_T);

      return;
    }

    iptr_CSParamTranslator_t CSParamTranslatorFactoryMethod::getTranslator(
        const CSPARAM_TYPE& type, bool isSingle) {
      iptr_CSParamTranslator_t ipTRSLTR;
      if (isSingle) {
        switch (type) {
        case BOOL_T:
          ipTRSLTR = m_ipTRSLTR_bool;
          break;
        case STRING_T:
          ipTRSLTR = m_ipTRSLTR_string;
          break;
        case UINT_T:
          ipTRSLTR = m_ipTRSLTR_uint;
          break;
        case UINT64_T:
          ipTRSLTR = m_ipTRSLTR_uint64;
          break;
        case COMPLEX_T:
          ipTRSLTR = m_ipTRSLTR_complex;
          break;
        default:
          throw xtreme::XtremeException(
              "No Translator available for CSParam type: " + boost::lexical_cast<std::string>(type));
          break;
        }
      } else {
        // Return List translators
        switch (type) {
        case BOOL_T:
          ipTRSLTR = m_ipTRSLTR_list_bool;
          break;
        case STRING_T:
          ipTRSLTR = m_ipTRSLTR_list_string;
          break;
        case UINT_T:
          ipTRSLTR = m_ipTRSLTR_list_uint;
          break;
        case UINT64_T:
          ipTRSLTR = m_ipTRSLTR_list_uint64;
          break;
        case COMPLEX_T:
          ipTRSLTR = m_ipTRSLTR_list_complex;
          break;
        default:
          throw xtreme::XtremeException(
              "No LIST-Translator available for CSParam type: " + boost::lexical_cast<std::string>(type));
          break;
        }
      }

      return ipTRSLTR;
    }

    // Explicit template instantiation
    template class CSParamTranslatorList<bool>;
    template class CSParamTranslatorList<std::string>;
    template class CSParamTranslatorList<uint32_t>;
    template class CSParamTranslatorList<uint64_t>;
    template class CSParamTranslatorList<ComplexVal>;
  }
}  // end namespace xtreme

ext: cc


text:
// Software License Agreement (BSD-3-Clause)
//
// Copyright 2018 The University of North Carolina at Chapel Hill
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions
// are met:
//
// 1. Redistributions of source code must retain the above copyright
//    notice, this list of conditions and the following disclaimer.
//
// 2. Redistributions in binary form must reproduce the above
//    copyright notice, this list of conditions and the following
//    disclaimer in the documentation and/or other materials provided
//    with the distribution.
//
// 3. Neither the name of the copyright holder nor the names of its
//    contributors may be used to endorse or promote products derived
//    from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
// COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
// INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
// OF THE POSSIBILITY OF SUCH DAMAGE.

//! @author Jeff Ichnowski

#pragma once

#ifndef MPT_LOG_HPP_
#define MPT_LOG_HPP_

//#include "impl/nocopy_stringstream.hpp"
#include <atomic>
#include <cassert>
#include <chrono>
#include <cstdarg>
#include <cstdio>
#include <iomanip>
#include <iostream>
#include <sstream>
#include <thread>
#include <vector>
#include <unistd.h>
#include <Eigen/Dense>

namespace unc::robotics::mpt::log::detail {
    template <typename Ratio> struct si_prefix;
    template <> struct si_prefix<std::ratio<1>> {
        static constexpr const char *value() { return ""; }
    };
    template <> struct si_prefix<std::milli> {
        static constexpr const char *value() { return "m"; }
    };
    template <> struct si_prefix<std::micro> {
        static constexpr const char *value() { return "u"; }
    };
    template <> struct si_prefix<std::nano> {
        static constexpr const char *value() { return "n"; }
    };

    template <typename T> struct is_tuple : std::false_type {};
    template <typename ... U> struct is_tuple<std::tuple<U...>> : std::true_type {};
    template <typename T> struct is_tuple<const T> : is_tuple<T> {};
    template <typename T> struct is_tuple<volatile T> : is_tuple<T> {};
    template <typename T> struct is_tuple<T&> : is_tuple<T> {};
    template <typename T> struct is_tuple<T&&> : is_tuple<T> {};

    template <typename T> struct is_duration : std::false_type {};
    template <class R, class P> struct is_duration<std::chrono::duration<R, P>> : std::true_type {};

    template <typename T>
    constexpr T log10(T value) {
        return (value > 1 ? log10(value/10) + 1 : 0);
    }
    // template <std::intmax_t value>
    // constexpr std::intmax_t log10 = (value > 1 ? log10<value/10> + 1 : 0);

    class ThreadName {
        std::string name_;

        static std::string autoName() {
            static std::atomic<std::size_t> count{};
            std::ostringstream tmp;
            tmp << std::hex << std::setfill('0') << std::setw(4) << count++;
            // return "thread-" + std::to_string(++count);
            return tmp.str();
            // std::ostringstream tmp;
            // tmp << std::hex << std::this_thread::get_id();
            // return tmp.str();
        }

    public:
        ThreadName()
            : name_(autoName())
        {
        }

        static ThreadName& instance() {
            thread_local ThreadName x;
            return x;
        }

        const std::string& get() const {
            return name_;
        }

        void set(const std::string& name) {
            name_ = name;
        }
    };

    // Interesting idea to help out logf by forcing the format to
    // be a literal and allowing for compile-time information such
    // as the string length.
    //
    // class ConstString {
    //     const char *ptr_;
    //     std::size_t size_;
    // public:
    //     template <std::size_t _N>
    //     ConstString(const char(&ptr)[_N]) : ptr_(ptr), size_(_N - 1) {}

    //     constexpr char operator[] (std::size_t n) const {
    //         return n < size_ ? ptr_[n] : throw std::out_of_range("");
    //     }

    //     constexpr std::size_t size() const {
    //         return size_;
    //     }

    //     operator const char * () const {
    //         return ptr_;
    //     }
    // };

    class LogQueue {
        struct Item {
            std::string msg_;
            Item *next_;
            inline Item(std::string&& msg, Item *next) : msg_(std::move(msg)), next_(next) {}
        };

        struct Lock {
            std::atomic_bool& lock_;
            bool ticket_;
            inline Lock(std::atomic_bool& lock) : lock_(lock), ticket_{lock.exchange(true)} {}
            inline ~Lock() { if (!ticket_) lock_.store(false, std::memory_order_release); }
            inline operator bool() { return !ticket_; }
        };

        // Here we check if stderr is a terminal or not.  If it is a
        // terminal, we write ANSI color codes, otherwise we don't.
        // Note that std::clog is documented to write to stderr.
        bool isTTY_{::isatty(STDERR_FILENO) == 1};

        std::atomic_bool locked_{false};
        std::atomic<Item*> list_{nullptr};

        inline Item *dequeue() {
            // log messages are placed in LIFO order, here we reverse
            // it to make sure we output in FIFO order.
            Item *prev = nullptr;
            for (Item *head = list_.exchange(nullptr), *next ; head != nullptr ; head = next) {
                next = head->next_;
                head->next_ = prev;
                prev = head;
            }
            return prev;
        }

        inline void drain() {
            for (Item *item = dequeue(), *next ; item ; item = next) {
                next = item->next_;
                std::clog << item->msg_;
                delete item;
            }
        }

    public:
        // LogQueue() {
        //     std::clog.sync_with_stdio(false);
        // }

        inline bool isTTY() const {
            return isTTY_;
        }

        inline ~LogQueue() {
            // destructor assumes no concurrent access.  Thus we do
            // not need to lock, and indeed the lock should not be
            // held.
            assert(locked_ == false);
            drain();
            if (isTTY_)
                std::clog << "\33[90m[log queue drained] (" << __FILE__ << ")\33[0m\n" << std::flush;
        }

        inline void operator() (std::ostringstream& msg) {
            if (isTTY_) {
                msg << "\33[0m\n";
            } else {
                msg << '\n';
            }

            (*this)(msg.str());
        }

        inline void operator() (std::string&& str) {
            // The queue operator attempts to output the string as
            // soon as possible.  However, to avoid processing delays,
            // if the stream is currently locked, we append the
            // message to a lock-free queue and return.
            if (Lock lock{locked_}) {
                drain();
                std::clog << str << std::flush;
            } else {
                Item *item = new Item(std::move(str), list_.load(std::memory_order_acquire));
                while (!list_.compare_exchange_weak(item->next_, item, std::memory_order_acq_rel))
                    ;

                if (Lock lock{locked_})
                    drain();
            }
        }
    };
}

namespace unc::robotics::mpt::log::level {
    struct ALL {};

#define MPT_LOG_DEFINE_LEVEL(NAME, NEXT, COLOR)                         \
    struct NAME {                                                       \
        typedef NEXT next;                                              \
        static constexpr const char *name() { return #NAME; }           \
        static constexpr const char *color() {                          \
            return "\33[" COLOR "m";                                    \
        }                                                               \
    }

    MPT_LOG_DEFINE_LEVEL(TRACE, ALL, "34"); // blue
    MPT_LOG_DEFINE_LEVEL(DEBUG, TRACE, "36"); // cyan
    MPT_LOG_DEFINE_LEVEL(INFO , DEBUG,  "32");  // green
    MPT_LOG_DEFINE_LEVEL(WARN , INFO, "33");  // yellow
    MPT_LOG_DEFINE_LEVEL(ERROR, WARN, "31;1"); // red, bold
    MPT_LOG_DEFINE_LEVEL(FATAL, ERROR,  "101;30");  // background red, black text
#undef MPT_LOG_DEFINE_LEVEL

    struct NONE {
        typedef FATAL next;
    };
}

// At compile time, define MPT_LOG_LEVEL to the level logging level to
// one of: ALL, TRACE, DEBUG, INFO, WARN, ERROR, FATAL or NONE.  NONE
// should be avoided as it hides FATAL messages too.  ALL is an alias
// for the lowest level (TRACE).  If MPT_LOG_LEVEL is not defined, the
// log level is determined by whether or not NDEBUG is defined.
#ifndef MPT_LOG_LEVEL
  #ifdef NDEBUG
    #define MPT_LOG_LEVEL INFO
  #else
    #define MPT_LOG_LEVEL ALL
  #endif
#endif

namespace unc::robotics::mpt::log {

    template <typename Ratio = std::milli>
    class Timer {
        using Clock = std::chrono::high_resolution_clock;
        Clock::time_point start_{Clock::now()};
    public:
        double elapsed() const {
            return std::chrono::duration<double, Ratio>(Clock::now() - start_).count();
        }
    };

    template <typename Level, class = std::void_t<>>
    struct is_enabled : std::false_type {};
    template <typename Level>
    struct is_enabled<Level, std::void_t<typename Level::next>>  : is_enabled<typename Level::next> {};
    template <>
    struct is_enabled<level:: MPT_LOG_LEVEL> : std::true_type {};

    inline void setThreadName(const std::string& name) {
        detail::ThreadName::instance().set(name);
    }

    inline const std::string& getThreadName() {
        return detail::ThreadName::instance().get();
    }

    class Event {
        std::ostringstream msg_;
        // impl::NoCopyStringOutputStream<char> msg_;

        inline static detail::LogQueue& logQueue() {
            static detail::LogQueue instance;
            return instance;
        }

    public:
        template <typename Level>
        Event(const Level&, const char *file, int line) {
            using namespace std::chrono;
            auto now = system_clock::now();
            std::time_t t = system_clock::to_time_t(now);
            auto millis = duration_cast<milliseconds>(
                now.time_since_epoch()).count() % 1000;

            // 12:34:56.789 INFO  [main] (file.hpp:123) message goes here
            if (logQueue().isTTY()) {
                // use the hash value of the thread id to color code
                // (using the 256 color palette) the thread.  Colors in
                // the range [0..15] come from the 4-bit color palette.
                // Colors in the range [232..255] are grayscale.  We
                // choose a color in the range [16..231].
                std::hash<std::string> hasher;
                std::size_t th = hasher(getThreadName()) % 216 + 16;

                msg_ << std::put_time(std::localtime(&t), "%T") << '.'
                     << std::setfill('0') << std::setw(3) << millis << ' '
                     << Level::color()
                     << std::setfill(' ') << std::left << std::setw(5) << Level::name()
                     << "\33[0m [\33[38;5;" << th << "m" << getThreadName() << "\33[0m] \33[37m("
                     << file << ':' << line << ")\33[0m "
                     << Level::color();
            } else {
                msg_ << std::put_time(std::localtime(&t), "%T") << '.'
                     << std::setfill('0') << std::setw(3) << millis << ' '
                     << std::setfill(' ') << std::left << std::setw(5) << Level::name()
                     << " [" << getThreadName() << "] ("
                     << file << ':' << line << ") ";
            }
        }

        inline ~Event() {
            logQueue()(msg_);
        }

        template <typename U>
        std::enable_if_t<
            !std::is_base_of_v<Eigen::DenseBase<std::decay_t<U>>, std::decay_t<U>> &&
            !std::is_base_of_v<Eigen::QuaternionBase<std::decay_t<U>>, std::decay_t<U>> &&
            !detail::is_duration<std::decay_t<U>>::value &&
            !detail::is_tuple<U>::value, Event&>
        operator << (const U& arg) {
            msg_ << arg;
            return *this;
        }

        template <typename Ratio>
        Event& operator << (const Timer<Ratio>& t) {
            msg_ << t.elapsed() << " " << detail::si_prefix<Ratio>::value() << "s";
            return *this;
        }

        template <typename ... U>
        Event& operator << (const std::tuple<U...>& arg) {
            write(arg, std::index_sequence_for<U...>{});
            return *this;
        }

        template <typename Derived>
        Event& operator << (const Eigen::QuaternionBase<Derived>& q) {
            Eigen::IOFormat fmt(Eigen::FullPrecision, Eigen::DontAlignCols, " ", " ", "", "", "[", "]");
            msg_ << q.coeffs().format(fmt);
            return *this;
        }

        template <typename Derived>
        Event& operator << (const Eigen::DenseBase<Derived>& m) {
            Eigen::IOFormat fmt(Eigen::FullPrecision, Eigen::DontAlignCols, " ", " ", "", "", "[", "]");
            if (m.cols() == 1 && m.rows() > 1) {
                msg_ << m.transpose().format(fmt) << "^T";
            } else {
                msg_ << m.format(fmt);
            }
            return *this;
        }

        template <typename Rep, typename Period>
        Event& operator << (const std::chrono::duration<Rep, Period>& d) {
            if constexpr (std::is_integral_v<Rep> && Period::num == 1 && Period::den % 10 == 0 && Period::den > 1) {
                // output directly as an integer if easy to do.  This
                // route keeps precision, and may be faster.
                msg_ << d.count() / static_cast<Rep>(Period::den) << '.';
                auto oldFill = msg_.fill('0');
                auto oldWidth = msg_.width(detail::log10(Period::den));
                auto oldPos = msg_.setf(std::ios_base::right, std::ios_base::adjustfield);
                msg_ << d.count() % Period::den;
                msg_.fill(oldFill);
                msg_.width(oldWidth);
                msg_.setf(oldPos, std::ios_base::adjustfield);
                msg_ << " s";
            } else {
                // otherwise convert to double and output.  This
                // typically loses some precision (mostly due to
                // formatting, but also after 104 days with
                // 64-bit nanoseconds)
                msg_ << std::chrono::duration<double>(d).count() << " s";
            }
            return *this;
        }

        // This is here to allow the expansion of a conditional log
        // without using an if/else.  See MPT_IMPL_LOG_S.  Essentially
        // it expands to:
        //    enabledBool && Event(...) << "message" << ...;
        // Which is parsed as:
        //    enabledBool && (Event(...) << "message" << ... );
        inline constexpr operator bool () const { return false; }

        // TODO:
        // template <typename Scalar, int rows>
        // Event& operator << (const Eigen::Matrix<Scalar, rows, 1>& m) {
        //     msg_ << m.transpose() << "^T";
        //     return *this;
        // }

    private:
        template <std::size_t I, typename T>
        void ith(const T& t) {
            if (I) msg_ << ", ";
            // msg_ << '(';
            *this << std::get<I>(t);
            // msg_ << ')';
        }

        template <typename T, std::size_t ... I>
        void write(const T& t, std::index_sequence<I...>) {
            msg_ << '{';
            (ith<I>(t), ...);
            msg_ << '}';
        }
    };

    template <typename Level>
    __attribute__((format(printf, 3, 4)))
    int logf(const char *file, int line, const char *fmt, ...) {
        Event evt(Level{}, file, line);
        va_list args1;
        va_list args2;
        va_start(args1, fmt);
        va_copy(args2, args1);
        int n = std::vsnprintf(nullptr, 0, fmt, args1);
        va_end(args1);
        if (n >= 0) {
            std::vector<char> v(n+1);
            n = std::vsnprintf(v.data(), v.size(), fmt, args2);
            evt << static_cast<const char*>(v.data());
        }
        va_end(args2);
        return n;
    }

    template <class T>
    constexpr std::string_view type_name() {
        // https://stackoverflow.com/questions/81870/is-it-possible-to-print-a-variables-type-in-standard-c
#ifdef __clang__
        // "std::string_view unc::robotics::mpt::log::type_name() [T = XYZ]"
        std::string_view p = __PRETTY_FUNCTION__;
        return std::string_view(p.data() + 59, p.size() - 59 - 1);
#elif defined(__GNUC__)
        // "constexpr std::string_view unc::robotics::mpt::log::type_name() [with T = XYZ; std::string_view = std::basic_string_view<char>]"
        //
        // the stackoverflow answer uses p.find(';', 74) to trim out
        // the definition of std::string_view.  here we just assume
        // that std::string_view will not change, and if it does, that
        // 74 may also become invalid.
        std::string_view p = __PRETTY_FUNCTION__;
        return std::string_view(p.data() + 74, p.size() - 74 - 50);
#elif defined(_MSC_VER)
        // this is untested (as is everything MSC code) :(
        std::string_view p = __FUNCSIG__;
        return std::string_view(p.data() + 109, p.size() - 109 - 7);
#endif
    }
}

// _S for 'stream'
// MPT_LOG(TRACE) << "messages" << data << etc;
#define MPT_IMPL_LOG_S(LVL)                                             \
    ::unc::robotics::mpt::log::is_enabled< ::unc::robotics::mpt::log::level::LVL >::value && \
    ::unc::robotics::mpt::log::Event( ::unc::robotics::mpt::log::level::LVL {}, __FILE__, __LINE__)

// _M for 'message' (single)
// MPT_LOG(TRACE, "text")
#define MPT_IMPL_LOG_M(LVL, msg) do {                                   \
        if (::unc::robotics::mpt::log::is_enabled< ::unc::robotics::mpt::log::level::LVL >::value) \
            ::unc::robotics::mpt::log::logf< ::unc::robotics::mpt::log::level::LVL >(__FILE__, __LINE__, "%s", msg); \
    } while (false)

// _F for formatted
// MPT_LOG(TRACE, "printf %s formatting, with up to %d args", "style", 58)
#define MPT_IMPL_LOG_F(LVL, ...) do {                                   \
        if (::unc::robotics::mpt::log::is_enabled< ::unc::robotics::mpt::log::level::LVL >::value) \
            ::unc::robotics::mpt::log::logf< ::unc::robotics::mpt::log::level::LVL >(__FILE__, __LINE__, __VA_ARGS__); \
    } while (false)

// _MPT_SELECT
#define MPT_IMPL_SELECT(                                                \
    PREFIX,                                                             \
    a60, a59, a58, a57, a56, a55, a54, a53, a52, a51,                   \
    a50, a49, a48, a47, a46, a45, a44, a43, a42, a41,                   \
    a40, a39, a38, a37, a36, a35, a34, a33, a32, a31,                   \
    a30, a29, a28, a27, a26, a25, a24, a23, a22, a21,                   \
    a20, a19, a18, a17, a16, a15, a14, a13, a12, a11,                   \
    a10, a09, a08, a07, a06, a05, a04, a03, a02, a01,                   \
    SUFFIX,...) MPT_IMPL_ ## PREFIX ## _ ## SUFFIX

// Usage:
//
// MPT_LOG(LEVEL, "message")
// MPT_LOG(LEVEL, "printf-format", args...)
// MPT_LOG(LEVEL) << "stream message" << ...;
//
// Where LEVEL is one of:
//   TRACE, DEBUG, INFO, WARN, ERROR, FATAL
#define MPT_LOG(...) MPT_IMPL_SELECT(                                   \
        LOG, __VA_ARGS__,                                               \
        F,F,F,F,F, F,F,F,F,F, F,F,F,F,F, F,F,F,F,F,                     \
        F,F,F,F,F, F,F,F,F,F, F,F,F,F,F, F,F,F,F,F,                     \
        F,F,F,F,F, F,F,F,F,F, F,F,F,F,F, F,F,F,M,S,)(__VA_ARGS__)

#endif // MPT_LOG_HPP_

ext: hpp

max_stars_repo_name: elishafer/mpt

max_issues_repo_name: elishafer/mpt

max_forks_repo_name: elishafer/mpt