1 //
2 //  Copyright (c) 2018-2019, Cem Bassoy, [email protected]
3 //
4 //  Distributed under the Boost Software License, Version 1.0. (See
5 //  accompanying file LICENSE_1_0.txt or copy at
6 //  http://www.boost.org/LICENSE_1_0.txt)
7 //
8 //  The authors gratefully acknowledge the support of
9 //  Fraunhofer IOSB, Ettlingen, Germany
10 //
11 
12 #ifndef BOOST_UBLAS_TENSOR_MULTI_INDEX_HPP
13 #define BOOST_UBLAS_TENSOR_MULTI_INDEX_HPP
14 
15 
16 #include <cstddef>
17 #include <array>
18 #include <vector>
19 
20 #include "multi_index_utility.hpp"
21 
22 namespace boost {
23 namespace numeric {
24 namespace ublas {
25 namespace index {
26 
27 template<std::size_t I>
28 struct index_type;
29 
30 } // namespace indices
31 }
32 }
33 }
34 
35 
36 namespace boost {
37 namespace numeric {
38 namespace ublas {
39 
40 /** @brief Proxy class for the einstein summation notation
41  *
42  * Denotes an array of index_type types ::_a for 0<=K<=16 is used in tensor::operator()
43 */
44 template<std::size_t N>
45 class multi_index
46 {
47 public:
48 	multi_index() = delete;
49 
50 	template<std::size_t I, class ... indexes>
multi_index(index::index_type<I> const & i,indexes...is)51 	constexpr multi_index(index::index_type<I> const& i, indexes ... is )
52 	  : _base{i(), is()... }
53 	{
54 		static_assert( sizeof...(is)+1 == N,
55 		               "Static assert in boost::numeric::ublas::multi_index: number of constructor arguments is not equal to the template parameter." );
56 
57 		static_assert( valid_multi_index<std::tuple<index::index_type<I>, indexes ...> >::value,
58 		               "Static assert in boost::numeric::ublas::multi_index: indexes occur twice in multi-index." );
59 	}
60 
multi_index(multi_index const & other)61 	multi_index(multi_index const& other)
62 	  : _base(other._base)
63 	{
64 	}
65 
operator =(multi_index const & other)66 	multi_index& operator=(multi_index const& other)
67 	{
68 		this->_base = other._base;
69 		return *this;
70 	}
71 
72 	~multi_index() = default;
73 
base() const74 	auto const& base() const { return _base; }
size() const75 	constexpr auto size() const { return _base.size(); }
at(std::size_t i) const76 	constexpr auto at(std::size_t i) const { return _base.at(i); }
operator [](std::size_t i) const77 	constexpr auto operator[](std::size_t i) const { return _base.at(i); }
78 
79 private:
80 	std::array<std::size_t, N> _base;
81 };
82 
83 template<std::size_t K, std::size_t N>
get(multi_index<N> const & m)84 constexpr auto get(multi_index<N> const& m) { return std::get<K>(m.base()); }
85 
86 template<std::size_t M, std::size_t N>
array_to_vector(multi_index<M> const & lhs,multi_index<N> const & rhs)87 auto array_to_vector(multi_index<M> const& lhs, multi_index<N> const& rhs)
88 {
89 	using vtype = std::vector<std::size_t>;
90 
91 	auto pair_of_vector = std::make_pair( vtype {}, vtype{}  );
92 
93 	for(auto i = 0u; i < N; ++i)
94 		for(auto j = 0u; j < M; ++j)
95 			if ( lhs.at(i) == rhs.at(j) && lhs.at(i) != boost::numeric::ublas::index::_())
96 				pair_of_vector.first .push_back( i+1 ),
97 				    pair_of_vector.second.push_back( j+1 );
98 
99 	return pair_of_vector;
100 }
101 
102 
103 
104 
105 
106 } // namespace ublas
107 } // namespace numeric
108 } // namespace boost
109 
110 #endif // MULTI_INDEX_HPP
111