Lagrange
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
27
34template <typename T, size_t N>
36{
37private:
38 std::array<T, N> m_array;
39 size_t m_size = 0;
40
41public:
42 StackSet() = default;
43
44 StackSet(std::initializer_list<T> init)
45 : m_size(init.size())
46 {
47 la_runtime_assert(m_size <= N);
48 auto it = init.begin();
49 for (size_t i = 0; i < m_size; ++i) {
50 m_array[i] = std::move(*it);
51 ++it;
52 }
53 ensure_unique();
54 }
55
56public:
57 using iterator = typename std::array<T, N>::iterator;
58 using const_iterator = typename std::array<T, N>::const_iterator;
59 iterator begin() { return m_array.begin(); }
60 iterator end() { return m_array.begin() + m_size; }
61 const_iterator begin() const { return m_array.begin(); }
62 const_iterator end() const { return m_array.begin() + m_size; }
63
64public:
65 size_t size() const { return m_size; }
66
67 void clear() { m_size = 0; }
68
69 void resize(const size_t i)
70 {
71 la_runtime_assert(i <= m_array.size());
72 m_size = i;
73 }
74
75 std::pair<iterator, bool> insert(const T& v)
76 {
77 la_runtime_assert(m_size < m_array.size());
78 for (size_t i = 0; i < m_size; ++i) {
79 if (m_array[i] == v) {
80 return {begin() + i, false};
81 }
82 }
83 m_array[m_size++] = v;
84 return {begin() + m_size - 1, true};
85 }
86
87 size_t erase(const T& v)
88 {
89 la_runtime_assert(m_size < m_array.size());
90 auto it = find(v);
91 if (it != end()) {
92 std::swap(*it, *(end() - 1));
93 --m_size;
94 return 1;
95 }
96 return 0;
97 }
98
99 bool contains(const T& v) const { return find(v) != end(); }
100
101 const_iterator find(const T& v) const { return std::find(begin(), end(), v); }
102
103 const T* data() const { return m_array.data(); }
104
105 const T& front() const
106 {
107 la_runtime_assert(m_size > 0);
108 return m_array.front();
109 }
110
111 const T& back() const
112 {
113 la_runtime_assert(m_size > 0);
114 return m_array.at(m_size - 1);
115 }
116
117 const T& at(const size_t i) const
118 {
119 la_runtime_assert(i < m_size);
120 return m_array.at(i);
121 }
122
123 const T& operator[](const size_t i) const
124 {
125 la_runtime_assert(i < m_size);
126 return m_array[i];
127 }
128
129 template <typename U, class UnaryOperation>
130 auto transformed(UnaryOperation op)
131 {
132 StackSet<U, N> result;
133 result.resize(size());
134 for (size_t i = 0; i < size(); ++i) {
135 result[i] = op(at(i));
136 }
137 result.ensure_unique();
138 return result;
139 }
140
141 template <size_t D>
142 auto to_tuple()
143 {
144 assert(D == m_size);
145 static_assert(D <= N, "Invalid size");
146 return to_tuple_helper(std::make_index_sequence<D>());
147 }
148
149protected:
150 template <size_t... Indices>
151 auto to_tuple_helper(std::index_sequence<Indices...>)
152 {
153 return std::make_tuple(m_array[Indices]...);
154 }
155
156 void ensure_unique()
157 {
158 std::sort(m_array.begin(), m_array.end());
159 auto it = std::unique(m_array.begin(), m_array.end());
160 m_size = static_cast<size_t>(std::distance(m_array.begin(), it));
161 }
162
163 iterator find(const T& v) { return std::find(begin(), end(), v); }
164
165 T* data() { return m_array.data(); }
166
167 T& front()
168 {
169 la_runtime_assert(m_size > 0);
170 return m_array.front();
171 }
172
173 T& back()
174 {
175 la_runtime_assert(m_size > 0);
176 return m_array.at(m_size - 1);
177 }
178};
179
180template <class T, size_t N>
181bool operator==(const StackSet<T, N>& lhs, const StackSet<T, N>& rhs)
182{
183 return (lhs.size() == rhs.size() && std::equal(lhs.begin(), lhs.end(), rhs.begin()));
184}
185
187
188} // namespace lagrange
#define la_runtime_assert(...)
Runtime assertion check.
Definition: assert.h:169
constexpr void swap(function_ref< R(Args...)> &lhs, function_ref< R(Args...)> &rhs) noexcept
Swaps the referred callables of lhs and rhs.
Definition: function_ref.h:114
Main namespace for Lagrange.
Definition: AABBIGL.h:30
Stack-allocated set with a maximum size.
Definition: StackSet.h:36