]> git.proxmox.com Git - ceph.git/blob - ceph/src/boost/boost/gil/extension/numeric/kernel.hpp
import quincy beta 17.1.0
[ceph.git] / ceph / src / boost / boost / gil / extension / numeric / kernel.hpp
1 //
2 // Copyright 2005-2007 Adobe Systems Incorporated
3 // Copyright 2019 Miral Shah <miralshah2211@gmail.com>
4 //
5 // Distributed under the Boost Software License, Version 1.0
6 // See accompanying file LICENSE_1_0.txt or copy at
7 // http://www.boost.org/LICENSE_1_0.txt
8 //
9
10 #ifndef BOOST_GIL_EXTENSION_NUMERIC_KERNEL_HPP
11 #define BOOST_GIL_EXTENSION_NUMERIC_KERNEL_HPP
12
13 #include <boost/gil/utilities.hpp>
14 #include <boost/gil/point.hpp>
15
16 #include <boost/assert.hpp>
17
18 #include <algorithm>
19 #include <array>
20 #include <cstddef>
21 #include <memory>
22 #include <vector>
23 #include <cmath>
24 #include <stdexcept>
25
26 namespace boost { namespace gil {
27
28 // Definitions of 1D fixed-size and variable-size kernels and related operations
29
30 namespace detail {
31
32 /// \brief kernel adaptor for one-dimensional cores
33 /// Core needs to provide size(),begin(),end(),operator[],
34 /// value_type,iterator,const_iterator,reference,const_reference
35 template <typename Core>
36 class kernel_1d_adaptor : public Core
37 {
38 public:
39 kernel_1d_adaptor() = default;
40
41 explicit kernel_1d_adaptor(std::size_t center)
42 : center_(center)
43 {
44 BOOST_ASSERT(center_ < this->size());
45 }
46
47 kernel_1d_adaptor(std::size_t size, std::size_t center)
48 : Core(size) , center_(center)
49 {
50 BOOST_ASSERT(this->size() > 0);
51 BOOST_ASSERT(center_ < this->size()); // also implies `size() > 0`
52 }
53
54 kernel_1d_adaptor(kernel_1d_adaptor const& other)
55 : Core(other), center_(other.center_)
56 {
57 BOOST_ASSERT(this->size() > 0);
58 BOOST_ASSERT(center_ < this->size()); // also implies `size() > 0`
59 }
60
61 kernel_1d_adaptor& operator=(kernel_1d_adaptor const& other)
62 {
63 Core::operator=(other);
64 center_ = other.center_;
65 return *this;
66 }
67
68 std::size_t left_size() const
69 {
70 BOOST_ASSERT(center_ < this->size());
71 return center_;
72 }
73
74 std::size_t right_size() const
75 {
76 BOOST_ASSERT(center_ < this->size());
77 return this->size() - center_ - 1;
78 }
79
80 auto center() -> std::size_t&
81 {
82 BOOST_ASSERT(center_ < this->size());
83 return center_;
84 }
85
86 auto center() const -> std::size_t const&
87 {
88 BOOST_ASSERT(center_ < this->size());
89 return center_;
90 }
91
92 private:
93 std::size_t center_{0};
94 };
95
96 } // namespace detail
97
98 /// \brief variable-size kernel
99 template <typename T, typename Allocator = std::allocator<T> >
100 class kernel_1d : public detail::kernel_1d_adaptor<std::vector<T, Allocator>>
101 {
102 using parent_t = detail::kernel_1d_adaptor<std::vector<T, Allocator>>;
103 public:
104
105 kernel_1d() = default;
106 kernel_1d(std::size_t size, std::size_t center) : parent_t(size, center) {}
107
108 template <typename FwdIterator>
109 kernel_1d(FwdIterator elements, std::size_t size, std::size_t center)
110 : parent_t(size, center)
111 {
112 detail::copy_n(elements, size, this->begin());
113 }
114
115 kernel_1d(kernel_1d const& other) : parent_t(other) {}
116 kernel_1d& operator=(kernel_1d const& other) = default;
117 };
118
119 /// \brief static-size kernel
120 template <typename T,std::size_t Size>
121 class kernel_1d_fixed : public detail::kernel_1d_adaptor<std::array<T, Size>>
122 {
123 using parent_t = detail::kernel_1d_adaptor<std::array<T, Size>>;
124 public:
125 static constexpr std::size_t static_size = Size;
126 static_assert(static_size > 0, "kernel must have size greater than 0");
127 static_assert(static_size % 2 == 1, "kernel size must be odd to ensure validity at the center");
128
129 kernel_1d_fixed() = default;
130 explicit kernel_1d_fixed(std::size_t center) : parent_t(center) {}
131
132 template <typename FwdIterator>
133 explicit kernel_1d_fixed(FwdIterator elements, std::size_t center)
134 : parent_t(center)
135 {
136 detail::copy_n(elements, Size, this->begin());
137 }
138
139 kernel_1d_fixed(kernel_1d_fixed const& other) : parent_t(other) {}
140 kernel_1d_fixed& operator=(kernel_1d_fixed const& other) = default;
141 };
142
143 // TODO: This data member is odr-used and definition at namespace scope
144 // is required by C++11. Redundant and deprecated in C++17.
145 template <typename T,std::size_t Size>
146 constexpr std::size_t kernel_1d_fixed<T, Size>::static_size;
147
148 /// \brief reverse a kernel
149 template <typename Kernel>
150 inline Kernel reverse_kernel(Kernel const& kernel)
151 {
152 Kernel result(kernel);
153 result.center() = kernel.right_size();
154 std::reverse(result.begin(), result.end());
155 return result;
156 }
157
158
159 namespace detail {
160
161 template <typename Core>
162 class kernel_2d_adaptor : public Core
163 {
164 public:
165 kernel_2d_adaptor() = default;
166
167 explicit kernel_2d_adaptor(std::size_t center_y, std::size_t center_x)
168 : center_(center_x, center_y)
169 {
170 BOOST_ASSERT(center_.y < this->size() && center_.x < this->size());
171 }
172
173 kernel_2d_adaptor(std::size_t size, std::size_t center_y, std::size_t center_x)
174 : Core(size * size), square_size(size), center_(center_x, center_y)
175 {
176 BOOST_ASSERT(this->size() > 0);
177 BOOST_ASSERT(center_.y < this->size() && center_.x < this->size()); // implies `size() > 0`
178 }
179
180 kernel_2d_adaptor(kernel_2d_adaptor const& other)
181 : Core(other), square_size(other.square_size), center_(other.center_.x, other.center_.y)
182 {
183 BOOST_ASSERT(this->size() > 0);
184 BOOST_ASSERT(center_.y < this->size() && center_.x < this->size()); // implies `size() > 0`
185 }
186
187 kernel_2d_adaptor& operator=(kernel_2d_adaptor const& other)
188 {
189 Core::operator=(other);
190 center_.y = other.center_.y;
191 center_.x = other.center_.x;
192 square_size = other.square_size;
193 return *this;
194 }
195
196 std::size_t upper_size() const
197 {
198 BOOST_ASSERT(center_.y < this->size());
199 return center_.y;
200 }
201
202 std::size_t lower_size() const
203 {
204 BOOST_ASSERT(center_.y < this->size());
205 return this->size() - center_.y - 1;
206 }
207
208 std::size_t left_size() const
209 {
210 BOOST_ASSERT(center_.x < this->size());
211 return center_.x;
212 }
213
214 std::size_t right_size() const
215 {
216 BOOST_ASSERT(center_.x < this->size());
217 return this->size() - center_.x - 1;
218 }
219
220 auto center_y() -> std::size_t&
221 {
222 BOOST_ASSERT(center_.y < this->size());
223 return center_.y;
224 }
225
226 auto center_y() const -> std::size_t const&
227 {
228 BOOST_ASSERT(center_.y < this->size());
229 return center_.y;
230 }
231
232 auto center_x() -> std::size_t&
233 {
234 BOOST_ASSERT(center_.x < this->size());
235 return center_.x;
236 }
237
238 auto center_x() const -> std::size_t const&
239 {
240 BOOST_ASSERT(center_.x < this->size());
241 return center_.x;
242 }
243
244 std::size_t size() const
245 {
246 return square_size;
247 }
248
249 typename Core::value_type at(std::size_t x, std::size_t y) const
250 {
251 if (x >= this->size() || y >= this->size())
252 {
253 throw std::out_of_range("Index out of range");
254 }
255 return this->begin()[y * this->size() + x];
256 }
257
258 protected:
259 std::size_t square_size{0};
260
261 private:
262 point<std::size_t> center_{0, 0};
263 };
264
265 /// \brief variable-size kernel
266 template
267 <
268 typename T,
269 typename Allocator = std::allocator<T>
270 >
271 class kernel_2d : public detail::kernel_2d_adaptor<std::vector<T, Allocator>>
272 {
273 using parent_t = detail::kernel_2d_adaptor<std::vector<T, Allocator>>;
274
275 public:
276
277 kernel_2d() = default;
278 kernel_2d(std::size_t size,std::size_t center_y, std::size_t center_x)
279 : parent_t(size, center_y, center_x)
280 {}
281
282 template <typename FwdIterator>
283 kernel_2d(FwdIterator elements, std::size_t size, std::size_t center_y, std::size_t center_x)
284 : parent_t(static_cast<int>(std::sqrt(size)), center_y, center_x)
285 {
286 detail::copy_n(elements, size, this->begin());
287 }
288
289 kernel_2d(kernel_2d const& other) : parent_t(other) {}
290 kernel_2d& operator=(kernel_2d const& other) = default;
291 };
292
293 /// \brief static-size kernel
294 template <typename T, std::size_t Size>
295 class kernel_2d_fixed :
296 public detail::kernel_2d_adaptor<std::array<T, Size * Size>>
297 {
298 using parent_t = detail::kernel_2d_adaptor<std::array<T, Size * Size>>;
299 public:
300 static constexpr std::size_t static_size = Size;
301 static_assert(static_size > 0, "kernel must have size greater than 0");
302 static_assert(static_size % 2 == 1, "kernel size must be odd to ensure validity at the center");
303
304 kernel_2d_fixed()
305 {
306 this->square_size = Size;
307 }
308
309 explicit kernel_2d_fixed(std::size_t center_y, std::size_t center_x) :
310 parent_t(center_y, center_x)
311 {
312 this->square_size = Size;
313 }
314
315 template <typename FwdIterator>
316 explicit kernel_2d_fixed(FwdIterator elements, std::size_t center_y, std::size_t center_x)
317 : parent_t(center_y, center_x)
318 {
319 this->square_size = Size;
320 detail::copy_n(elements, Size * Size, this->begin());
321 }
322
323 kernel_2d_fixed(kernel_2d_fixed const& other) : parent_t(other) {}
324 kernel_2d_fixed& operator=(kernel_2d_fixed const& other) = default;
325 };
326
327 // TODO: This data member is odr-used and definition at namespace scope
328 // is required by C++11. Redundant and deprecated in C++17.
329 template <typename T, std::size_t Size>
330 constexpr std::size_t kernel_2d_fixed<T, Size>::static_size;
331
332 template <typename Kernel>
333 inline Kernel reverse_kernel_2d(Kernel const& kernel)
334 {
335 Kernel result(kernel);
336 result.center_x() = kernel.lower_size();
337 result.center_y() = kernel.right_size();
338 std::reverse(result.begin(), result.end());
339 return result;
340 }
341
342
343 /// \brief reverse a kernel_2d
344 template<typename T, typename Allocator>
345 inline kernel_2d<T, Allocator> reverse_kernel(kernel_2d<T, Allocator> const& kernel)
346 {
347 return reverse_kernel_2d(kernel);
348 }
349
350 /// \brief reverse a kernel_2d
351 template<typename T, std::size_t Size>
352 inline kernel_2d_fixed<T, Size> reverse_kernel(kernel_2d_fixed<T, Size> const& kernel)
353 {
354 return reverse_kernel_2d(kernel);
355 }
356
357 } //namespace detail
358
359 }} // namespace boost::gil
360
361 #endif