/usr/include/boost/numeric/ublas/tensor
Edit: /usr/include/boost/numeric/ublas/tensor/multi_index_utility.hpp (11140B)
//
// Copyright (c) 2018-2019, Cem Bassoy, cem.bassoy@gmail.com
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
// The authors gratefully acknowledge the support of
// Fraunhofer IOSB, Ettlingen, Germany
//
#ifndef BOOST_UBLAS_TENSOR_MULTI_INDEX_UTILITY_HPP
#define BOOST_UBLAS_TENSOR_MULTI_INDEX_UTILITY_HPP
#include
#include
namespace boost {
namespace numeric {
namespace ublas {
namespace detail {
template
struct has_index_impl;
template
struct has_index_impl
{
static constexpr bool value = itype_left::value == itype_right::value;
};
template
struct has_index_impl >
{
static constexpr bool value = false;
};
template
struct has_index_impl >
{
static constexpr bool value = has_index_impl::value;
};
template
struct has_index_impl >
{
using next_type = has_index_impl>;
static constexpr bool value = has_index_impl::value || next_type::value;
};
} // namespace detail
/** @brief has_index is true if index occurs once or more in a multi-index
*
* @note a multi-index represents as tuple of single indexes of type boost::numeric::ublas::index::index_type
*
* @code auto has_index_value = has_index, std::tuple,index_type<1>> >::value; @endcode
*
* @tparam index_type type of index
* @tparam tuple_type type of std::tuple representing a multi-index
*/
template
struct has_index
{
static constexpr bool value = detail::has_index_impl,std::decay_t>::value;
};
} // namespace ublas
} // namespace numeric
} // namespace boost
////////////////////////////////////////////////
////////////////////////////////////////////////
namespace boost {
namespace numeric {
namespace ublas {
namespace detail {
template
struct valid_multi_index_impl;
template<>
struct valid_multi_index_impl>
{
static constexpr bool value = true;
};
template
struct valid_multi_index_impl>
{
static constexpr bool value = true;
};
template
struct valid_multi_index_impl>
{
using ttype = std::tuple;
using has_index_type = has_index;
static constexpr bool is_index_zero = itype::value==0ul;
static constexpr bool has_index_value = has_index_type::value && !is_index_zero;
static constexpr bool value = !has_index_value && valid_multi_index_impl::value;
};
} // namespace detail
/** @brief valid_multi_index is true if indexes occur only once in a multi-index
*
* @note a multi-index represents as tuple of single indexes of type boost::numeric::ublas::index::index_type
*
* @code auto valid = valid_multi_index< std::tuple,index_type<1>> >::value;
* @endcode
*
* @tparam tuple_type type of std::tuple representing a multi-index
*/
template
struct valid_multi_index
{
static constexpr bool value = detail::valid_multi_index_impl>::value;
};
} // namespace ublas
} // namespace numeric
} // namespace boost
////////////////////////////////////////////////
////////////////////////////////////////////////
namespace boost {
namespace numeric {
namespace ublas {
namespace detail {
template
struct number_equal_indexes_impl;
template
struct number_equal_indexes_impl < std::tuple<>, std::tuple>
{
static constexpr unsigned value = 0;
};
template
struct number_equal_indexes_impl < std::tuple, std::tuple>
{
using tuple_right = std::tuple;
using has_index_type = has_index;
static constexpr bool is_index_zero = itype::value==0ul;
static constexpr bool has_index_value = has_index_type::value && !is_index_zero;
using next_type = number_equal_indexes_impl< std::tuple, tuple_right >;
static constexpr unsigned v = has_index_value ? 1 : 0;
static constexpr unsigned value = v + next_type::value;
};
} // namespace detail
/** @brief number_equal_indexes contains the number of equal indexes of two multi-indexes
*
* @note a multi-index represents as tuple of single indexes of type boost::numeric::ublas::index::index_type
*
*
* @code auto num = number_equal_indexes<
* std::tuple,index_type<1>>,
* std::tuple,index_type<3>> >::value;
* @endcode
*
* @tparam tuple_type_left type of left std::tuple representing a multi-index
* @tparam tuple_type_right type of right std::tuple representing a multi-index
*/
template
struct number_equal_indexes
{
static constexpr unsigned value =
detail::number_equal_indexes_impl< std::decay_t, std::decay_t>::value;
};
} // namespace ublas
} // namespace numeric
} // namespace boost
////////////////////////////////////////////////
////////////////////////////////////////////////
namespace boost {
namespace numeric {
namespace ublas {
namespace detail {
template
struct index_position_impl
{
static constexpr auto is_same = std::is_same< std::decay_t, std::decay_t> >::value;
static constexpr auto value = is_same ? r : index_position_impl::value;
};
template
struct index_position_impl < m, m, itype, ttype>
{
static constexpr auto value = std::tuple_size::value;
};
} // namespace detail
/** @brief index_position contains the zero-based index position of an index type within a multi-index
*
* @note a multi-index represents as tuple of single indexes of type boost::numeric::ublas::index::index_type
*
* @code auto num = index_position<
* index_type<1>,
* std::tuple,index_type<1>> >::value;
* @endcode
*
* @returns value returns 0 and N-1 if index_type is found, N otherwise where N is tuple_size_v.
*
* @tparam index_type type of index
* @tparam tuple_type type of std::tuple that is searched for index
*/
template
struct index_position
{
static constexpr auto value = detail::index_position_impl<0ul,std::tuple_size::value,std::decay_t,std::decay_t>::value;
};
} // namespace ublas
} // namespace numeric
} // namespace boost
////////////////////////////////////////////////
////////////////////////////////////////////////
namespace boost {
namespace numeric {
namespace ublas {
namespace detail {
template
struct index_position_pairs_impl
{
template
static constexpr void run(array_type& out, tuple_left const& lhs, tuple_right const& rhs, std::size_t p)
{
using index_type = std::tuple_element_t;
using has_index_type = has_index;
using get_index_type = index_position;
using next_type = index_position_pairs_impl;
if constexpr ( has_index_type::value && index_type::value != 0)
out[p++] = std::make_pair(r-1,get_index_type::value);
next_type::run( out, lhs, rhs, p );
}
};
template
struct index_position_pairs_impl
{
template
static constexpr void run(array_type& out, tuple_left const& , tuple_right const& , std::size_t p)
{
using index_type = std::tuple_element_t;
using has_index_type = has_index;
using get_index_type = index_position;
if constexpr ( has_index_type::value && index_type::value != 0 )
out[p] = std::make_pair(m-1,get_index_type::value);
}
};
template
struct index_position_pairs_impl
{
template
static constexpr void run(array_type&, tuple_left const& , tuple_right const& , std::size_t)
{}
};
} // namespace detail
/** @brief index_position_pairs returns zero-based index positions of matching indexes of two multi-indexes
*
* @note a multi-index represents as tuple of single indexes of type boost::numeric::ublas::index::index_type
*
* @code auto pairs = index_position_pairs(std::make_tuple(_a,_b), std::make_tuple(_b,_c));
* @endcode
*
* @returns a std::array instance containing index position pairs of type std::pair.
*
* @param lhs left std::tuple instance representing a multi-index
* @param rhs right std::tuple instance representing a multi-index
*/
template
auto index_position_pairs(tuple_left const& lhs, tuple_right const& rhs)
{
using pair_type = std::pair;
constexpr auto m = std::tuple_size::value;
constexpr auto p = number_equal_indexes::value;
auto array = std::array{};
detail::index_position_pairs_impl<1,m>::run(array, lhs, rhs,0);
return array;
}
} // namespace ublas
} // namespace numeric
} // namespace boost
////////////////////////////
////////////////////////////
////////////////////////////
////////////////////////////
namespace boost {
namespace numeric {
namespace ublas {
namespace detail {
template
constexpr auto array_to_vector_impl( array_type const& array, std::index_sequence )
{
return std::make_pair(
std::vector{std::get<0>( std::get(array) )+1 ...} ,
std::vector{std::get<1>( std::get(array) )+1 ...} );
}
} // namespace detail
/** @brief array_to_vector converts a std::array of zero-based index position pairs into two std::vector of one-based index positions
*
* @code auto two_vectors = array_to_vector(std::make_array ( std::make_pair(1,2), std::make_pair(3,4) ) ) ;
* @endcode
*
* @returns two std::vector of one-based index positions
*
* @param array std::array of zero-based index position pairs
*/
template
constexpr auto array_to_vector( std::array const& array)
{
constexpr auto sequence = std::make_index_sequence{};
return detail::array_to_vector_impl( array, sequence );
}
} // namespace ublas
} // namespace numeric
} // namespace boost
#endif // _BOOST_UBLAS_TENSOR_MULTI_INDEX_UTILITY_HPP_