]> git.proxmox.com Git - ceph.git/blame - 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
CommitLineData
92f5a8d4
TL
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>
20effc67 24#include <stdexcept>
92f5a8d4
TL
25
26namespace boost { namespace gil {
27
28// Definitions of 1D fixed-size and variable-size kernels and related operations
29
30namespace 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
35template <typename Core>
36class kernel_1d_adaptor : public Core
37{
38public:
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
92private:
93 std::size_t center_{0};
94};
95
96} // namespace detail
97
98/// \brief variable-size kernel
99template <typename T, typename Allocator = std::allocator<T> >
100class kernel_1d : public detail::kernel_1d_adaptor<std::vector<T, Allocator>>
101{
102 using parent_t = detail::kernel_1d_adaptor<std::vector<T, Allocator>>;
103public:
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
120template <typename T,std::size_t Size>
121class 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>>;
124public:
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.
145template <typename T,std::size_t Size>
146constexpr std::size_t kernel_1d_fixed<T, Size>::static_size;
147
148/// \brief reverse a kernel
149template <typename Kernel>
150inline 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
159namespace detail {
160
161template <typename Core>
162class kernel_2d_adaptor : public Core
163{
164public:
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
258protected:
259 std::size_t square_size{0};
260
261private:
262 point<std::size_t> center_{0, 0};
263};
264
265/// \brief variable-size kernel
266template
267<
268 typename T,
269 typename Allocator = std::allocator<T>
270>
271class 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
275public:
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
294template <typename T, std::size_t Size>
295class 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>>;
299public:
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.
329template <typename T, std::size_t Size>
330constexpr std::size_t kernel_2d_fixed<T, Size>::static_size;
331
20effc67
TL
332template <typename Kernel>
333inline 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}
92f5a8d4 341
20effc67
TL
342
343/// \brief reverse a kernel_2d
344template<typename T, typename Allocator>
345inline 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
351template<typename T, std::size_t Size>
352inline 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
92f5a8d4
TL
358
359}} // namespace boost::gil
360
361#endif