Empirical
IntPack.h
Go to the documentation of this file.
1 
16 #ifndef EMP_INT_PACK_H
17 #define EMP_INT_PACK_H
18 
19 #include "meta.h"
20 
21 #include <iostream>
22 
23 namespace emp {
24 
25  // Pre-declaration of IntPack
26  template <int... Ts> struct IntPack;
27 
28  // Anonymous implementations of IntPack interface.
29  namespace internal {
30  template <bool DONE, int START, int END, int STEP, int... VALS>
31  struct ip_range {
32  static constexpr int NEXT = START + STEP;
33  using type = typename ip_range<(NEXT >= END), NEXT, END, STEP, VALS..., START>::type;
34  };
35  template <int START, int END, int STEP, int... VALS>
36  struct ip_range <true, START, END, STEP, VALS...> {
37  using type = IntPack<VALS...>;
38  };
39 
40  template <typename T1, typename T2> struct ip_concat;
41  template <int... T1s, int... T2s>
42  struct ip_concat<IntPack<T1s...>, IntPack<T2s...>> {
43  using result = IntPack<T1s..., T2s...>;
44  };
45 
46  template <typename T_IN, typename T_OUT=IntPack<>, bool DONE=false, int VERSION=0>
47  struct ip_loop {
48  // Helpers...
49  using in_pop = typename T_IN::pop;
50  template <int V> using out_pbin = typename T_OUT::template push_back_if_not<T_IN::first, V>;
51  template <int V, bool D=false> using pnext = ip_loop< in_pop, out_pbin<V>, D, VERSION >; // Prune
52 
53  // Main operations...
54  template <int V> using pop_val = typename pnext<V, T_IN::first==V>::template pop_val<V>;
55  template <int V> using remove = typename pnext<V>::template remove<V>;
56  template <int V> using uniq = typename pnext<V>::template uniq<T_IN::first>;
57  };
58  template <typename T_IN, typename T_OUT, int VERSION>
59  struct ip_loop<T_IN, T_OUT, true, VERSION> {
60  template <int V> using pop_val = typename T_OUT::template append<T_IN>; // Pop done!
61  };
62  template <typename T_OUT, int VERSION>
63  struct ip_loop<IntPack<>, T_OUT, false, VERSION> {
64  template <int V> using pop_val = T_OUT; // Nothing to pop! (error?)
65  template <int V> using remove = T_OUT; // Nothing left to remove!
66  template <int V> using uniq = T_OUT; // Nothing left to check!
67  };
68 
69  // Implement == ip_push_if_not ==
70  template <int V, int X, typename T>
71  struct ip_push_if_not {
72  using result = typename T::template push<V>;
73  using back = typename T::template push_back<V>;
74  };
75  template <int V, typename T>
76  struct ip_push_if_not<V,V,T> {
77  using result = T;
78  using back = T;
79  };
80 
81  // Setup ==reverse== operation.
82  template <typename T> struct ip_reverse;
83  template <int V1, int... Vs> struct ip_reverse<IntPack<V1, Vs...>> {
84  using result = typename ip_reverse< IntPack<Vs...> >::result::template push_back<V1>;
85  };
86  template <> struct ip_reverse<IntPack<>> { using result = IntPack<>; };
87 
88  // Setup ==uniq== operation.
89  template <typename T> struct ip_uniq;
90  template <int V1, int... Vs> struct ip_uniq<IntPack<V1, Vs...>> {
91  using result = typename ip_loop<IntPack<V1, Vs...>, IntPack<>, false, 1>::template uniq<V1+1>;
92  };
93  template <> struct ip_uniq<IntPack<>> { using result = IntPack<>; };
94 
95  // Setup ==sort== operation.
96  template <typename T_IN, typename T_OUT>
97  struct ip_sort_impl {
98  template <int V> using spop = typename T_IN::template pop_val<V>;
99  template <int V> using snext = ip_sort_impl< spop<V>, typename T_OUT::template push_back<V> >;
100  template <int V> using sort = typename snext<V>::template sort< spop<V>::Min(T_IN::first) >;
101  };
102  template <typename T_OUT>
103  struct ip_sort_impl<IntPack<>, T_OUT> {
104  template <int V> using sort = T_OUT; // Nothing left to sort!
105  };
106 
107  template <typename T> struct ip_sort;
108  template <int V1, int... Vs> struct ip_sort<IntPack<V1, Vs...>> {
109  using ip = IntPack<V1, Vs...>;
110  using result = typename ip_sort_impl<ip, IntPack<>>::template sort<ip::Min()>;
111  };
112  template <> struct ip_sort<IntPack<>> { using result = IntPack<>; };
113  }
114 
115  // Generate an IntPack with a specified range of values.
116  template <int START, int END, int STEP=1>
117  using IntPackRange = typename internal::ip_range<(START >= END), START, END, STEP>::type;
118 
119  // IntPack with at least one value.
120  template <int V1, int... Vs>
121  struct IntPack<V1,Vs...> {
122  static constexpr int first = V1;
123 
124  using this_t = IntPack<V1,Vs...>;
125  using pop = IntPack<Vs...>;
126 
127  template <int V> using push = IntPack<V, V1, Vs...>;
128  template <int V> using push_back = IntPack<V1, Vs..., V>;
129  template <int V, int X> using push_if_not = typename internal::ip_push_if_not<V,X,this_t>::result;
130  template <int V, int X> using push_back_if_not = typename internal::ip_push_if_not<V,X,this_t>::back;
131  template <int V> using pop_val = typename internal::ip_loop<this_t, IntPack<>, false, 2>::template pop_val<V>;
132  template <int V> using remove = typename internal::ip_loop<this_t, IntPack<>, false, 3>::template remove<V>;
133  template <typename T> using append = typename internal::ip_concat<this_t,T>::result;
134 
135  constexpr static bool Has(int V) { return (V==V1) | pop::Has(V); }
136  constexpr static int Count(int V) { return pop::Count(V) + (V==V1); }
137  constexpr static int GetID(int V) { return (V==V1) ? 0 : (1+pop::GetID(V)); }
138 
139  constexpr static int SIZE = 1+sizeof...(Vs);
140  constexpr static int GetSize() { return SIZE; }
141 
142  constexpr static bool IsEmpty() { return false; }
143  constexpr static bool IsUnique() { return pop::IsUnique() && !pop::Has(V1); }
144 
145  constexpr static int Sum() { return V1 + pop::Sum(); }
146  constexpr static int Product() { return V1 * pop::Product(); }
147  constexpr static int Min(int cap) { return cap < pop::Min(V1) ? cap : pop::Min(V1); }
148  constexpr static int Min() { return pop::Min(V1); }
149  constexpr static int Max(int floor) { return floor > pop::Max(V1) ? floor : pop::Max(V1); }
150  constexpr static int Max() { return pop::Max(V1); }
151 
152  static void PrintInts(std::ostream & os=std::cout) {
153  os << V1;
154  if (GetSize() > 1) os << ',';
155  pop::PrintInts(os);
156  }
157  };
158 
159  // IntPack with no values.
160  template <> struct IntPack<> {
161  using this_t = IntPack<>;
162 
163  template <int V> using push = IntPack<V>;
164  template <int V> using push_back = IntPack<V>;
165  template <int V, int X> using push_if_not = typename internal::ip_push_if_not<V,X,IntPack<>>::result;
166  template <int V, int X> using push_back_if_not = typename internal::ip_push_if_not<V,X,IntPack<>>::back;
167  template <int V> using pop_val = IntPack<>; // No value to pop! Faulure?
168  template <int V> using remove = IntPack<>;
169  template <typename T> using append = T;
170 
171  constexpr static bool Has(int) { return false; }
172  constexpr static int Count(int) { return 0; }
173  constexpr static int GetID(int V) { return -100000; }
174 
175  constexpr static int SIZE = 0;
176  constexpr static int GetSize() { return 0; }
177 
178  constexpr static bool IsEmpty() { return true; }
179  constexpr static bool IsUnique() { return true; }
180 
181  constexpr static int Sum() { return 0; }
182  constexpr static int Product() { return 1; }
183  constexpr static int Min(int cap) { return cap; }
184  constexpr static int Max(int floor) { return floor; }
185 
186  static void PrintInts(std::ostream & os=std::cout) { ; }
187  };
188 
189  namespace pack {
190  template <typename T> using reverse = typename internal::ip_reverse<T>::result;
191  template <typename T> using uniq = typename internal::ip_uniq<T>::result;
192 
193  template <typename T> using sort = typename internal::ip_sort<T>::result;
194  template <typename T> using Rsort = reverse< sort<T> >;
195  template <typename T> using Usort = uniq< sort<T> >;
196  template <typename T> using RUsort = reverse< Usort<T> >;
197  }
198 }
199 
200 #endif
Definition: IntPack.h:31
static constexpr int Sum()
Definition: IntPack.h:181
static constexpr int NEXT
Definition: IntPack.h:32
constexpr T Min(T in1)
Min of only one element is that element itself!
Definition: math.h:50
typename T_IN::pop in_pop
Definition: IntPack.h:49
typename T_OUT::template push_back_if_not< T_IN::first, V > out_pbin
Definition: IntPack.h:50
static constexpr int GetSize()
Definition: IntPack.h:140
typename T_OUT::template append< T_IN > pop_val
Definition: IntPack.h:60
static constexpr bool IsUnique()
Definition: IntPack.h:179
static void PrintInts(std::ostream &os=std::cout)
Definition: IntPack.h:152
typename internal::ip_push_if_not< V, X, IntPack<>>::back push_back_if_not
Definition: IntPack.h:166
Definition: IntPack.h:26
static constexpr int GetID(int V)
Definition: IntPack.h:173
typename pnext< V, T_IN::first==V >::template pop_val< V > pop_val
Definition: IntPack.h:54
Definition: IntPack.h:89
static constexpr bool IsEmpty()
Definition: IntPack.h:142
static constexpr bool IsUnique()
Definition: IntPack.h:143
typename snext< V >::template sort< spop< V >::Min(T_IN::first) > sort
Definition: IntPack.h:100
Definition: IntPack.h:40
static constexpr int Max(int floor)
Definition: IntPack.h:149
Definition: IntPack.h:82
reverse< Usort< T > > RUsort
Definition: IntPack.h:196
typename internal::ip_push_if_not< V, X, this_t >::back push_back_if_not
Definition: IntPack.h:130
static constexpr int GetID(int V)
Definition: IntPack.h:137
Definition: IntPack.h:160
static constexpr int Min(int cap)
Definition: IntPack.h:147
static constexpr int Min()
Definition: IntPack.h:148
typename ip_sort_impl< ip, IntPack<>>::template sort< ip::Min()> result
Definition: IntPack.h:110
static constexpr bool Has(int V)
Definition: IntPack.h:135
T result
Definition: IntPack.h:77
T Product(const emp::vector< T > &v)
Multiply all of the contents of a vector.
Definition: vector_utils.h:86
static constexpr int Min(int cap)
Definition: IntPack.h:183
typename internal::ip_loop< this_t, IntPack<>, false, 3 >::template remove< V > remove
Definition: IntPack.h:132
typename internal::ip_loop< this_t, IntPack<>, false, 2 >::template pop_val< V > pop_val
Definition: IntPack.h:131
typename internal::ip_push_if_not< V, X, IntPack<>>::result push_if_not
Definition: IntPack.h:165
typename ip_loop< IntPack< V1, Vs... >, IntPack<>, false, 1 >::template uniq< V1+1 > result
Definition: IntPack.h:91
typename T::template push_back< V > back
Definition: IntPack.h:73
typename T_IN::template pop_val< V > spop
Definition: IntPack.h:98
T append
Definition: IntPack.h:169
typename internal::ip_reverse< T >::result reverse
Definition: IntPack.h:190
typename pnext< V >::template remove< V > remove
Definition: IntPack.h:55
typename internal::ip_concat< this_t, T >::result append
Definition: IntPack.h:133
typename internal::ip_range<(START >=END), START, END, STEP >::type IntPackRange
Definition: IntPack.h:117
Definition: IntPack.h:47
static constexpr int Product()
Definition: IntPack.h:182
static constexpr bool Has(int)
Definition: IntPack.h:171
constexpr T Max(T in1)
Max of only one element is that element itself!
Definition: math.h:61
uniq< sort< T > > Usort
Definition: IntPack.h:195
bool Has(const MAP_T &in_map, const KEY_T &key)
Take any map type, and run find to determine if a key is present.
Definition: map_utils.h:21
static constexpr int GetSize()
Definition: IntPack.h:176
Definition: IntPack.h:71
Definition: IntPack.h:121
static constexpr int Max(int floor)
Definition: IntPack.h:184
typename internal::ip_uniq< T >::result uniq
Definition: IntPack.h:191
typename T::template push< V > result
Definition: IntPack.h:72
If we are in emscripten, make sure to include the header.
Definition: array.h:37
static constexpr int Count(int V)
Definition: IntPack.h:136
reverse< sort< T > > Rsort
Definition: IntPack.h:194
static constexpr int Sum()
Definition: IntPack.h:145
typename pnext< V >::template uniq< T_IN::first > uniq
Definition: IntPack.h:56
static constexpr int Max()
Definition: IntPack.h:150
typename internal::ip_sort< T >::result sort
Definition: IntPack.h:193
static constexpr int Count(int)
Definition: IntPack.h:172
Definition: IntPack.h:107
static void PrintInts(std::ostream &os=std::cout)
Definition: IntPack.h:186
typename internal::ip_push_if_not< V, X, this_t >::result push_if_not
Definition: IntPack.h:129
typename ip_reverse< IntPack< Vs... > >::result::template push_back< V1 > result
Definition: IntPack.h:84
typename ip_range<(NEXT >=END), NEXT, END, STEP, VALS..., START >::type type
Definition: IntPack.h:33
Definition: IntPack.h:97
static constexpr bool IsEmpty()
Definition: IntPack.h:178
constexpr size_t GetSize(T(&)[N])
Determine the size of a built-in array.
Definition: functions.h:81
static constexpr int Product()
Definition: IntPack.h:146
std::enable_if<!emp::is_ptr_type< typename C::value_type >::value &&std::is_scalar< typename C::value_type >::value, typename C::value_type >::type Sum(C &elements)
Definition: stats.h:33