Line data Source code
1 : /* ✔ */
2 :
3 : #pragma once
4 :
5 : #include "Array.hpp"
6 :
7 : #if __cplusplus >= 201400L
8 : #define USE_CONSTEXPR_ARRAY_HELPERS constexpr
9 : #else
10 : #define USE_CONSTEXPR_ARRAY_HELPERS
11 : #endif
12 :
13 : /// https://en.cppreference.com/w/cpp/algorithm/generate
14 : template <class ForwardIt, class Generator>
15 4 : USE_CONSTEXPR_ARRAY_HELPERS void generate(ForwardIt first, ForwardIt last,
16 : Generator g) {
17 20 : while (first != last)
18 16 : *first++ = g();
19 4 : }
20 :
21 : /**
22 : * @brief Utility class that acts as a functor to return incremental values.
23 : *
24 : * @tparam T
25 : * The type that will be returned by the functor, as well as the type
26 : * of the initial value.
27 : * @tparam V
28 : * The type of the object that is added to the value on each call.
29 : */
30 : template <class T, class V>
31 : class Incrementor {
32 : public:
33 1 : USE_CONSTEXPR_ARRAY_HELPERS Incrementor(T start = 0, V increment = 1)
34 1 : : value(start), increment(increment) {}
35 4 : USE_CONSTEXPR_ARRAY_HELPERS T operator()() {
36 4 : T temp = value;
37 4 : value += increment;
38 4 : return temp;
39 : }
40 :
41 : private:
42 : T value;
43 : const V increment;
44 : };
45 :
46 : /// @addtogroup Containers
47 : /// @{
48 :
49 : /**
50 : * @brief Generate an array using the given generator.
51 : *
52 : * @tparam T
53 : * The type of the elements in the array.
54 : * @tparam N
55 : * The number of elements in the array.
56 : * @tparam G
57 : * The generator functor type.
58 : *
59 : * @param generator
60 : * A functor that will be called to create each element.
61 : *
62 : * @return The generated array.
63 : */
64 : template <class T, size_t N, class G>
65 2 : USE_CONSTEXPR_ARRAY_HELPERS Array<T, N> generateArray(G generator) {
66 2 : Array<T, N> array{};
67 2 : generate(array.begin(), array.end(), generator);
68 2 : return array;
69 : }
70 :
71 : /**
72 : * @brief Generate an array using the given generator.
73 : *
74 : * @tparam N
75 : * The number of elements in the array.
76 : * @tparam G
77 : * The generator functor type.
78 : *
79 : * @param generator
80 : * A functor that will be called to create each element.
81 : *
82 : * @return The generated array.
83 : */
84 : template <size_t N, class G>
85 2 : USE_CONSTEXPR_ARRAY_HELPERS auto generateArray(G generator)
86 : -> Array<decltype(generator()), N> {
87 2 : Array<decltype(generator()), N> array{};
88 2 : generate(array.begin(), array.end(), generator);
89 2 : return array;
90 : }
91 :
92 : /**
93 : * @brief Copy an Array to an Array of a different type.
94 : *
95 : * @tparam T
96 : * The type of the new array.
97 : * @tparam N
98 : * The number of elements in the arrays.
99 : * @tparam U
100 : * The type of the source array.
101 : *
102 : * @param src
103 : * The source array to be copied.
104 : */
105 : template <class T, size_t N, class U>
106 1 : USE_CONSTEXPR_ARRAY_HELPERS Array<T, N> copyAs(const Array<U, N> &src) {
107 4 : Array<T, N> dest{};
108 5 : for (size_t i = 0; i < N; ++i)
109 4 : dest[i] = src[i];
110 1 : return dest;
111 : }
112 :
113 : template <class T, size_t N, class... Args>
114 1 : USE_CONSTEXPR_ARRAY_HELPERS Array<T, N> fillArray(Args... args) {
115 5 : return generateArray<N>([&]() { return T{args...}; });
116 : }
117 :
118 : /**
119 : * @brief Generate an array where the first value is given, and the subsequent
120 : * values are calculated as the previous value incremented with a given
121 : * value:
122 : * @f$ x[0] = \mathrm{start} @f$
123 : * @f$ x[k+1] = x[k] + \mathrm{increment} @f$ .
124 : *
125 : * For example:
126 : * ```
127 : * auto x = generateIncrementalArray<unsigned int, 4>(2, 3);
128 : * ```
129 : * is equivalent to
130 : * ```
131 : * Array<unsigned int, 4> x = {2, 5, 8, 11};
132 : * ```
133 : *
134 : * @tparam T
135 : * The type of the elements in the array.
136 : * @tparam N
137 : * The number of elements in the array.
138 : * @tparam U
139 : * The type of the initial value.
140 : * @tparam V
141 : * The type of the value that will be added to each subsequent element.
142 : *
143 : * @param start
144 : * The first value in the array.
145 : * @param increment
146 : * The value to add to each subsequent element of the array.
147 : *
148 : * @return The generated array.
149 : */
150 : template <class T, size_t N, class U, class V = U>
151 : USE_CONSTEXPR_ARRAY_HELPERS Array<T, N>
152 1 : generateIncrementalArray(U start = 0, V increment = 1) {
153 1 : Incrementor<U, V> g(start, increment);
154 1 : return generateArray<T, N>(g);
155 : }
156 :
157 : /**
158 : * @brief Concatenate two arrays.
159 : *
160 : * @tparam T
161 : * The type of the elements in the array.
162 : * @tparam M
163 : * The number of elements in the first array.
164 : * @tparam N
165 : * The number of elements in the second array.
166 : * @param a
167 : * The first array.
168 : * @param b
169 : * The second array.
170 : * @return A new array containing the elements of both input arrays (in order).
171 : */
172 : template <class T, size_t M, size_t N>
173 : USE_CONSTEXPR_ARRAY_HELPERS Array<T, M + N> cat(const Array<T, M> &a,
174 : const Array<T, N> &b) {
175 : Array<T, M + N> result = {};
176 : size_t r = 0;
177 : for (size_t i = 0; i < M; ++i, ++r)
178 : result[r] = a[i];
179 : for (size_t i = 0; i < N; ++i, ++r)
180 : result[r] = b[i];
181 : return result;
182 : }
183 :
184 : /// @}
|