Lagrange
Loading...
Searching...
No Matches
StackSet.h
1/*
2 * Copyright 2022 Adobe. All rights reserved.
3 * This file is licensed to you under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License. You may obtain a copy
5 * of the License at http://www.apache.org/licenses/LICENSE-2.0
6 *
7 * Unless required by applicable law or agreed to in writing, software distributed under
8 * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
9 * OF ANY KIND, either express or implied. See the License for the specific language
10 * governing permissions and limitations under the License.
11 */
12#pragma once
13
14#include <lagrange/utils/assert.h>
15
16#include <algorithm>
17#include <array>
18#include <initializer_list>
19
20namespace lagrange {
21
25
32template <typename T, size_t N>
33struct StackSet
34{
35private:
36 std::array<T, N> m_array;
37 size_t m_size = 0;
38
39public:
40 StackSet() = default;
41
42 StackSet(std::initializer_list<T> init)
43 : m_size(init.size())
44 {
45 la_runtime_assert(m_size <= N);
46 auto it = init.begin();
47 for (size_t i = 0; i < m_size; ++i) {
48 m_array[i] = std::move(*it);
49 ++it;
50 }
51 ensure_unique();
52 }
53
54public:
55 using iterator = typename std::array<T, N>::iterator;
56 using const_iterator = typename std::array<T, N>::const_iterator;
57 iterator begin() { return m_array.begin(); }
58 iterator end() { return m_array.begin() + m_size; }
59 const_iterator begin() const { return m_array.begin(); }
60 const_iterator end() const { return m_array.begin() + m_size; }
61
62public:
63 size_t size() const { return m_size; }
64
65 void clear() { m_size = 0; }
66
67 void resize(const size_t i)
68 {
69 la_runtime_assert(i <= m_array.size());
70 m_size = i;
71 }
72
73 std::pair<iterator, bool> insert(const T& v)
74 {
75 la_runtime_assert(m_size < m_array.size());
76 for (size_t i = 0; i < m_size; ++i) {
77 if (m_array[i] == v) {
78 return {begin() + i, false};
79 }
80 }
81 m_array[m_size++] = v;
82 return {begin() + m_size - 1, true};
83 }
84
85 size_t erase(const T& v)
86 {
87 la_runtime_assert(m_size < m_array.size());
88 auto it = find(v);
89 if (it != end()) {
90 std::swap(*it, *(end() - 1));
91 --m_size;
92 return 1;
93 }
94 return 0;
95 }
96
97 bool contains(const T& v) const { return find(v) != end(); }
98
99 const_iterator find(const T& v) const { return std::find(begin(), end(), v); }
100
101 const T* data() const { return m_array.data(); }
102
103 const T& front() const
104 {
105 la_runtime_assert(m_size > 0);
106 return m_array.front();
107 }
108
109 const T& back() const
110 {
111 la_runtime_assert(m_size > 0);
112 return m_array.at(m_size - 1);
113 }
114
115 const T& at(const size_t i) const
116 {
117 la_runtime_assert(i < m_size);
118 return m_array.at(i);
119 }
120
121 const T& operator[](const size_t i) const
122 {
123 la_runtime_assert(i < m_size);
124 return m_array[i];
125 }
126
127 template <typename U, class UnaryOperation>
128 auto transformed(UnaryOperation op)
129 {
130 StackSet<U, N> result;
131 result.resize(size());
132 for (size_t i = 0; i < size(); ++i) {
133 result[i] = op(at(i));
134 }
135 result.ensure_unique();
136 return result;
137 }
138
139 template <size_t D>
140 auto to_tuple()
141 {
142 assert(D == m_size);
143 static_assert(D <= N, "Invalid size");
144 return to_tuple_helper(std::make_index_sequence<D>());
145 }
146
147protected:
148 template <size_t... Indices>
149 auto to_tuple_helper(std::index_sequence<Indices...>)
150 {
151 return std::make_tuple(m_array[Indices]...);
152 }
153
154 void ensure_unique()
155 {
156 std::sort(m_array.begin(), m_array.end());
157 auto it = std::unique(m_array.begin(), m_array.end());
158 m_size = static_cast<size_t>(std::distance(m_array.begin(), it));
159 }
160
161 iterator find(const T& v) { return std::find(begin(), end(), v); }
162
163 T* data() { return m_array.data(); }
164
165 T& front()
166 {
167 la_runtime_assert(m_size > 0);
168 return m_array.front();
169 }
170
171 T& back()
172 {
173 la_runtime_assert(m_size > 0);
174 return m_array.at(m_size - 1);
175 }
176};
177
178template <class T, size_t N>
179bool operator==(const StackSet<T, N>& lhs, const StackSet<T, N>& rhs)
180{
181 return (lhs.size() == rhs.size() && std::equal(lhs.begin(), lhs.end(), rhs.begin()));
182}
183
185
186} // namespace lagrange
#define la_runtime_assert(...)
Runtime assertion check.
Definition assert.h:177
Main namespace for Lagrange.
Stack-allocated set with a maximum size.
Definition StackSet.h:34