Nano
A C++ template metaprogramming library
list_functions.hpp
Go to the documentation of this file.
1 // ----------------------------------------------------------------------------------------------------------
2 /// @file list_funcitons.hpp
3 /// @brief Header file for the list functions. Some list functions need higher order functions, but some
4 /// hof's use lists so we can't put those in the same file, so all list functions that need hof's are
5 /// here.
6 // ----------------------------------------------------------------------------------------------------------
7 
8 /*
9  * ----------------------------------------------------------------------------------------------------------
10  * list header file for nano library.
11  * Copyright (C) 2015 Rob Clucas
12  *
13  * This program is free software; you can redistribute it and/or modify
14  * it under the terms of the GNU General Public License as published by
15  * the Free Software Foundation; either version 2 of the License, or
16  * (at your option) any later version.
17  *
18  * This program is distributed in the hope that it will be useful,
19  * but WITHOUT ANY WARRANTY; without even the implied warranty of
20  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21  * GNU General Public License for more details.
22  *
23  * You should have received a copy of the GNU General Public License along
24  * with this program; if not, write to the Free Software Foundation, Inc.,
25  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
26  * ----------------------------------------------------------------------------------------------------------
27  */
28 
29 #ifndef NANO_LIST_FUNCTIONS_HPP
30 #define NANO_LIST_FUNCTIONS_HPP
31 
33 
34 #include <limits>
35 #include <type_traits>
36 
37 namespace nano {
38 
39 namespace detail {
40 
41  // ------------------------------------------------------------------------------------------------------
42  /// @struct search_lists
43  /// @brief For each element in the first list, the index of the element in the second list is
44  /// searched for, if found it's added to a new list, otherwise -1 is added
45  /// @tparam List1 The list to iterate over
46  /// @tparam List2 The list to look through for each element in List1
47  // ------------------------------------------------------------------------------------------------------
48  template <typename List1, typename List2>
49  struct search_lists;
50 
51  // ------------------------------------------------------------------------------------------------------
52  /// @tparam Head1 The front element in the first list
53  /// @tparam Tail1 The rest of the elements in the first list
54  /// @tparam Head2 THe front element in the second list
55  /// @tparam Tail2 The rest of the elements in the second list
56  // ------------------------------------------------------------------------------------------------------
57  template <typename Head1, typename... Tail1, typename Head2, typename... Tail2>
58  struct search_lists<list<Head1, Tail1...>, list<Head2, Tail2...>>
59  {
60  // For all elements in list one, search for the element's index in list2
61  using result = list<
62  nano::int_t<find_type<Head1, list<Head2, Tail2...>>::result>, // Head of List1
63  nano::int_t<find_type<Tail1, list<Head2, Tail2...>>::result>... // Rest of List1
64  >;
65  };
66 } // End namespace detail
67 
68 // ----------------------------------------------------------------------------------------------------------
69 /// @struct find_common
70 /// @brief Finds all common elements in 2 lists and returns a zipped list of the result, where each
71 /// zipped element is a index of the common element in the lists. The zips are sorted by the
72 /// index of the element in the first list. For example, if there are 2 lists: \n\n
73 /// [ 0, 4, 2, 1 ] and [ 12, 1, 4, 2 ] \n\n
74 /// the returned list will be: \n\n
75 /// [ [1, 2], [2 ,3], [1, 2] ]
76 /// @tparam List1 The first list to search through
77 /// @tparam List2 The second list to search through
78 // ----------------------------------------------------------------------------------------------------------
79 template <typename List1, typename List2>
80 struct find_common;
81 
82 // Specialization
83 template <typename Head1, typename... Tail1, typename Head2, typename... Tail2>
84 struct find_common<list<Head1, Tail1...>, list<Head2, Tail2...>>
85 {
86  // Create indices to zip
87  using indices = typename range<0, sizeof...(Tail1), 1>::result;
88 
89  // Create a list of the indices of elements from list 2 in list1
90  using searched_lists = typename
91  detail::search_lists<list<Head1, Tail1...>, list<Head2, Tail2...>>::result;
92 
93  // Essentially filter by zipping only elements in searched_lists which were found
95 };
96 
97 // ----------------------------------------------------------------------------------------------------------
98 /// @struct find_uncommon
99 /// @brief Finds all elements of the first list which are not present in the second list, and returns a
100 /// new list without the common elements. For example, if there are 2 lists: \n\n
101 /// [ 2, 3, 1, 4 ] and [ 4, 5, 2 ] \n\n
102 /// the returned list will be: \n\n
103 /// [ 3, 1 ]
104 /// @tparam List1 The first list to search through
105 /// @tparam List2 The second list to search through
106 // ----------------------------------------------------------------------------------------------------------
107 template <typename List1, typename List2>
109 
110 // Specialization
111 template <typename Head1, typename... Tail1, typename Head2, typename... Tail2>
112 struct find_uncommon<list<Head1, Tail1...>, list<Head2, Tail2...>>
113 {
114  // Filter out all the elements which were found
115  using result = typename
116  filter<type_not_present, list<Head1, Tail1...>, list<Head2, Tail2...>, empty_list>::result;
117 };
118 
119 // ----------------------------------------------------------------------------------------------------------
120 /// @struct find_uncommon_indices
121 /// @brief Finds the indices of the elements in the first list which are not present in the second list
122 /// and returns a list of the index values. For example, if there are 2 lists: \n\n
123 /// [ 2, 3, 1, 4 ] and [ 4, 5, 2 ] \n\n
124 /// the returned list will be: \n\n
125 /// [ 1, 3 ]
126 /// @tparam List1 The list to get the indices of
127 /// @tparam List2 The list to check for elements against
128 // ----------------------------------------------------------------------------------------------------------
129 template <typename List1, typename List2>
131 
132 // Specialization
133 template <typename Head1, typename... Tail1, typename Head2, typename... Tail2>
134 struct find_uncommon_indices<list<Head1, Tail1...>, list<Head2, Tail2...>>
135 {
136  // Create a list of indices
137  using indices = typename range<0, sizeof...(Tail1), 1>::result;
138 
139  // Create a list of results for if an element in list 1
140  // is found in list 2
141  using search_results = typename
142  detail::search_lists<list<Head1, Tail1...>, list<Head2, Tail2...>>::result;
143 
144  // Now create the list of indices of the elements in list one
145  // which were found in list 2 by filtering the indices list
146  // using the search results
147  using result = typename
149 };
150 
151 // ----------------------------------------------------------------------------------------------------------
152 /// @struct multiplies
153 /// @brief Same as std::multiplies, but for a nano:list which can be computed at compile time - computes
154 /// the product of the list elelents from the starting value.
155 /// @tparam List The list to compute the product of
156 /// @tparam Current The current value of the multiplication (for the first case, this is the start
157 /// value and is default to 1)
158 // ----------------------------------------------------------------------------------------------------------
159 template <typename List, typename Current = nano::int_t<1>>
160 struct multiplies;
161 
162 // Specialization for list
163 template <typename Head, typename... Tail, typename Current>
164 struct multiplies<list<Head, Tail...>, Current>
165 {
166  // Multiply head of list and the current value to update the total product sum
167  using updated_value = typename std::conditional<
168  std::is_same<typename Current::type, int>::value,
171  >::type;
172 
173  // Now use the updaed value and multiply with the next list element on the next level of recursion
174  static constexpr typename Current::type result = multiplies<list<Tail...>, updated_value>::result;
175 };
176 
177 // Terminating case
178 template <typename Current>
179 struct multiplies<empty_list, Current>
180 {
181  static constexpr typename Current::type result = Current::value;
182 };
183 
184 namespace detail {
185 
186 // ----------------------------------------------------------------------------------------------------------
187 /// @struct accumulate
188 /// @brief Like std::accumulate, where the start and end indices, and the accumulation functor can be
189 /// specified
190 /// @tparam List The list to accumulate
191 /// @tparam Iteration The iteration of the function
192 /// @tparam StartIndex The index of the element in the list to start accumulating from
193 /// @tparam EndIndex The index of the element in the list to end accumulating at
194 /// @tparam Value The value of the accumulation
195 /// @param Operation The operation to apply (multiply, add ...)
196 //-----------------------------------------------------------------------------------------------------------
197 template <typename List ,
198  std::size_t Iteration ,
199  typename StartIndex ,
200  typename EndIndex ,
201  typename Value ,
202  template <typename...> class Operation >
203 struct accumulate;
204 
205 // Recursive case
206 template <typename Head ,
207  typename... Tail ,
208  std::size_t Iteration ,
209  typename StartIndex ,
210  typename EndIndex ,
211  typename Value ,
212  template <typename...> class Operation >
213 struct accumulate<list<Head, Tail...>, Iteration, StartIndex, EndIndex, Value, Operation>
214 {
215  using temp_type = typename std::conditional<Iteration >= StartIndex::value &&
216  Iteration <= EndIndex::value ,
217  Head ,
218  typename Operation<Head, Value>::default_type
219  >::type;
220 
221  using current_accumulation = typename Operation<temp_type, Value>::type;
222 
223  static constexpr typename Value::type result =
224  accumulate<list<Tail...>, Iteration + 1, StartIndex, EndIndex, current_accumulation, Operation>::result;
225 };
226 
227 // Terminating case
228 template <typename... Tail ,
229  std::size_t Iteration ,
230  typename StartIndex ,
231  typename EndIndex ,
232  typename Value ,
233  template <typename...> class Operation >
234 struct accumulate<list<Tail...>, Iteration, StartIndex, EndIndex, Value, Operation>
235 {
236  static constexpr typename Value::type result = Value::value;
237 };
238 
239 } // End namespace detail
240 
241 
242 template <typename List ,
243  std::size_t StartIndex = 0 ,
244  std::size_t EndIndex = std::numeric_limits<std::size_t>::max() ,
245  std::size_t StartValue = 1 ,
246  template <typename...> class Operation = nano::multiply >
247 using accumulate = detail::accumulate<List ,
248  0 ,
252  Operation >;
253 
254 } // End namespace nano
255 
256 #endif // LIST_FUNCTIONS_HPP
Like std::accumulate, where the start and end indices, and the accumulation functor can be specified...
Definition: list_functions.hpp:203
Constructs a range of nano::int_t t types, which is essentially just a list of nano::int_t types...
Definition: containers.hpp:100
typename zip< is_found, indices, searched_lists, empty_list >::result result
Definition: list_functions.hpp:94
Multiplies two nano numeric types.
Definition: functions.hpp:110
For each element in the first list, the index of the element in the second list is searched for...
Definition: list_functions.hpp:49
Wrapper around int for static int types used by metaclass and metafunctions in nano.
Definition: numeric_types.hpp:63
Takes two lists, and zips the corresponding elements into a list of 2 elements if the function to det...
Definition: higher_order_functions.hpp:105
typename filter< type_not_present, list< Head1, Tail1...>, list< Head2, Tail2...>, empty_list >::result result
Definition: list_functions.hpp:116
typename std::conditional< Iteration >=StartIndex::value &&Iteration<=EndIndex::value, Head, typename Operation< Head, Value >::default_type >::type temp_type
Definition: list_functions.hpp:219
Definition: containers.hpp:34
typename range< 0, sizeof...(Tail1), 1 >::result indices
Definition: list_functions.hpp:137
Finds all elements of the first list which are not present in the second list, and returns a new list...
Definition: list_functions.hpp:108
Same as std::multiplies, but for a nano:list which can be computed at compile time - computes the pro...
Definition: list_functions.hpp:160
Header file for nano higher order functions. Higher order functions are functions which satisfy at...
Find the index of a specific type in the list (the index of the first occurrence). If the type is not found then the value 'parameter' will be -1.
Definition: list.hpp:96
Meta class that holds types, and allows functions to be applied to the elements of the list using the...
Definition: list.hpp:51
To check if a type in a list is not found. Where the find_type tries to find a type and get its index...
Definition: list.hpp:131
Takes a list and an evaluation function, which itself takes the list and a parameter to evaluate if e...
Definition: higher_order_functions.hpp:53
typename detail::search_lists< list< Head1, Tail1...>, list< Head2, Tail2...>>::result searched_lists
Definition: list_functions.hpp:91
typename range< 0, sizeof...(Tail1), 1 >::result indices
Definition: list_functions.hpp:87
typename detail::search_lists< list< Head1, Tail1...>, list< Head2, Tail2...>>::result search_results
Definition: list_functions.hpp:142
typename filter< first_not_present, indices, search_results, empty_list >::result result
Definition: list_functions.hpp:148
typename Operation< temp_type, Value >::type current_accumulation
Definition: list_functions.hpp:221
Finds the indices of the elements in the first list which are not present in the second list and retu...
Definition: list_functions.hpp:130
Wrapper around size_t for static size_t types used by metaclass and metafunctions in nano...
Definition: numeric_types.hpp:40
Finds all common elements in 2 lists and returns a zipped list of the result, where each zipped eleme...
Definition: list_functions.hpp:80
typename std::conditional< std::is_same< typename Current::type, int >::value, nano::int_t< Head::value *Current::value >, nano::size_t< Head::value *Current::value > >::type updated_value
Definition: list_functions.hpp:171