Skip to content

Commit

Permalink
2D kernel support added to numeric extension
Browse files Browse the repository at this point in the history
Tests for 2D numeric kernel added
  • Loading branch information
miralshah365 committed Jul 31, 2019
1 parent 8815ab0 commit 5783bbb
Show file tree
Hide file tree
Showing 2 changed files with 343 additions and 0 deletions.
181 changes: 181 additions & 0 deletions include/boost/gil/extension/numeric/kernel.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,187 @@ inline Kernel reverse_kernel(Kernel const& kernel)
return result;
}


namespace detail {

template <typename Core>
class kernel_2d_adaptor : public Core
{
public:
kernel_2d_adaptor() = default;

explicit kernel_2d_adaptor(std::size_t center_vertical, std::size_t center_horizontal)
: center_vertical_(center_vertical), center_horizontal_(center_horizontal)
{
BOOST_ASSERT(center_vertical_ < this->size());
BOOST_ASSERT(center_horizontal_ < this->at(0).size());
}

kernel_2d_adaptor(std::size_t size, std::size_t center_vertical, std::size_t center_horizontal)
: Core(size, typename Core::value_type(size)),
center_vertical_(center_vertical),
center_horizontal_(center_horizontal)
{
BOOST_ASSERT(this->size() > 0);
BOOST_ASSERT(center_vertical_ < this->size()); // also implies `size() > 0`

BOOST_ASSERT(center_horizontal_ < this->at(0).size());
BOOST_ASSERT(this->at(0).size() > 0);
}

kernel_2d_adaptor(kernel_2d_adaptor const& other)
: Core(other),
center_vertical_(other.center_vertical_),
center_horizontal_(other.center_horizontal_)
{
BOOST_ASSERT(this->size() > 0);
BOOST_ASSERT(center_vertical_ < this->size()); // also implies `size() > 0`

BOOST_ASSERT(center_horizontal_ < this->at(0).size());
BOOST_ASSERT(this->at(0).size() > 0);
}

kernel_2d_adaptor& operator=(kernel_2d_adaptor const& other)
{
Core::operator=(other);
center_vertical_ = other.center_vertical_;
center_horizontal_ = other.center_horizontal_;
return *this;
}

std::size_t upper_size() const
{
BOOST_ASSERT(center_vertical_ < this->size());
return center_vertical_;
}

std::size_t lower_size() const
{
BOOST_ASSERT(center_vertical_ < this->size());
return this->size() - center_vertical_ - 1;
}

std::size_t left_size() const
{
BOOST_ASSERT(center_horizontal_ < this->at(0).size());
return center_horizontal_;
}

std::size_t right_size() const
{
BOOST_ASSERT(center_horizontal_ < this->at(0).size());
return this->at(0).size() - center_horizontal_ - 1;
}

auto center_vertical() -> std::size_t&
{
BOOST_ASSERT(center_ < this->size());
return center_vertical_;
}

auto center_vertical() const -> std::size_t const&
{
BOOST_ASSERT(center_vertical_ < this->size());
return center_vertical_;
}

auto center_horizontal() -> std::size_t&
{
BOOST_ASSERT(center_horizontal_ < this->at(0).size());
return center_horizontal_;
}

auto center_horizontal() const -> std::size_t const&
{
BOOST_ASSERT(center_horizontal_ < this->at(0).size());
return center_horizontal_;
}

private:
std::size_t center_vertical_{ 0 }, center_horizontal_{ 0 };
};
} //namespace detail

/// \brief variable-size kernel
template
<
typename T,
typename ColAllocator = std::allocator<T>,
typename RowAllocator = std::allocator<std::vector<T, ColAllocator>>
>
class kernel_2d :
public detail::kernel_2d_adaptor<std::vector<std::vector<T, ColAllocator>, RowAllocator>>
{
using parent_t =
detail::kernel_2d_adaptor<std::vector<std::vector<T, ColAllocator>, RowAllocator>>;
public:

kernel_2d() = default;
kernel_2d(
std::size_t size,
std::size_t vertical_center,
std::size_t center_horizontal
) : parent_t(size, vertical_center, center_horizontal){}

template <typename FwdIterator>
kernel_2d(
FwdIterator elements,
std::size_t size,
std::size_t vertical_center,
std::size_t center_horizontal
) : parent_t(size, vertical_center, center_horizontal)
{
detail::copy_n(elements, size, this->begin());
}

kernel_2d(kernel_2d const& other) : parent_t(other) {}
kernel_2d& operator=(kernel_2d const& other) = default;
};

/// \brief static-size kernel
template <typename T, std::size_t Size>
class kernel_2d_fixed :
public detail::kernel_2d_adaptor<std::array<std::array<T, Size>, Size>>
{
using parent_t = detail::kernel_2d_adaptor<std::array<std::array<T, Size>, Size>>;
public:
static constexpr std::size_t static_size = Size;
static_assert(static_size > 0, "kernel must have size greater than 0");
static_assert(static_size % 2 == 1, "kernel size must be odd to ensure validity at the center");

kernel_2d_fixed() = default;
explicit kernel_2d_fixed(std::size_t center_vertical, std::size_t center_horizontal) :
parent_t(center_vertical, center_horizontal) {}

template <typename FwdIterator>
explicit kernel_2d_fixed(
FwdIterator elements,
std::size_t center_vertical,
std::size_t center_horizontal
) : parent_t(center_vertical, center_horizontal)
{
detail::copy_n(elements, Size, this->begin());
}

kernel_2d_fixed(kernel_2d_fixed const& other) : parent_t(other) {}
kernel_2d_fixed& operator=(kernel_2d_fixed const& other) = default;
};

// TODO: This data member is odr-used and definition at namespace scope
// is required by C++11. Redundant and deprecated in C++17.
template <typename T, std::size_t Size>
constexpr std::size_t kernel_2d_fixed<T, Size>::static_size;

/// \brief reverse a kernel
//template <typename Kernel>
//inline Kernel reverse_kernel(Kernel const& kernel)
//{
// Kernel result(kernel);
// result.center() = kernel.right_size();
// std::reverse(result.begin(), result.end());
// return result;
//}

}} // namespace boost::gil

#endif
Loading

0 comments on commit 5783bbb

Please sign in to comment.