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