2
0
mirror of https://github.com/boostorg/gil.git synced 2026-01-24 18:02:17 +00:00
Files
gil/test/extension/numeric/channel_numeric_operations.cpp
Mateusz Łoskot f641190948 Replace BOOST_TEST with BOOST_TEST_EQ for streamable operands (#472)
Improve utilities sending channels, pixels and other GIL objects to
output stream for logging of test errors.

Fix missing namespace qualification in IO tests.

Comment TARGA test case with FIXME that was accidentally
uncommented in cc64bdd1a4
2020-04-01 01:54:12 +02:00

485 lines
15 KiB
C++

//
// Copyright 2019-2020 Mateusz Loskot <mateusz at loskot dot net>
//
// Distributed under the Boost Software License, Version 1.0
// See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt
//
#include <boost/gil.hpp>
#include <boost/gil/extension/numeric/channel_numeric_operations.hpp>
#include <boost/core/lightweight_test.hpp>
#include <tuple>
#include <type_traits>
#include "test_utility_output_stream.hpp"
#include "core/channel/test_fixture.hpp"
namespace gil = boost::gil;
namespace fixture = boost::gil::test::fixture;
struct test_plus_integer_same_types
{
template <typename Channel>
void operator()(Channel const&)
{
using channel_t = Channel;
gil::channel_plus_t<channel_t, channel_t, channel_t> f;
BOOST_TEST_EQ(f(0, 0), channel_t(0));
BOOST_TEST_EQ(f(100, 27), channel_t(127));
}
static void run()
{
boost::mp11::mp_for_each<fixture::channel_integer_types>(test_plus_integer_same_types{});
}
};
struct test_plus_integer_mixed_types
{
template <typename Channel>
void operator()(Channel const&)
{
using channel_t = Channel;
{
using channel1_t = channel_t;
using channel2_t = std::uint8_t; // duplicates only one of fixture::channel_integer_types
gil::channel_plus_t<channel1_t, channel2_t, channel1_t> f;
BOOST_TEST_EQ(f(0, 0), channel1_t(0));
BOOST_TEST_EQ(f(100, 27), channel_t(127));
}
{
using channel1_t = std::uint8_t; // duplicates only one of fixture::channel_integer_types
using channel2_t = channel_t;
gil::channel_plus_t<channel1_t, channel2_t, channel2_t> f;
BOOST_TEST_EQ(f(0, 0), channel2_t(0));
BOOST_TEST_EQ(f(100, 27), channel_t(127));
}
}
static void run()
{
boost::mp11::mp_for_each<fixture::channel_integer_types>(test_plus_integer_mixed_types{});
}
};
struct test_plus_integer_signed_types_with_overflow
{
template <typename Channel>
void operator()(Channel const&)
{
using channel_t = Channel;
// Signed integer overflow is UB, so just check addition does not yield mathematically
// expected value but is constrained by the range of representable values for given type.
auto const max_value = gil::channel_traits<channel_t>::max_value();
gil::channel_plus_t<channel_t, channel_t, channel_t> f;
BOOST_TEST_NE(f(max_value, 1), std::int64_t(max_value) + 1);
BOOST_TEST_NE(f(max_value, max_value), std::int64_t(max_value) + max_value);
}
static void run()
{
boost::mp11::mp_for_each<fixture::channel_integer_signed_types>(test_plus_integer_signed_types_with_overflow{});
}
};
struct test_plus_integer_unsigned_types_with_wraparound
{
template <typename Channel>
void operator()(Channel const&)
{
using channel_t = Channel;
// The C Standard, 6.2.5, paragraph 9 [ISO/IEC 9899:2011], states:
// A computation involving unsigned operands can never overflow, because a result that
// cannot be represented by the resulting unsigned integer type is reduced modulo the number
// that is one greater than the largest value that can be represented by the resulting type.
auto const max_value = gil::channel_traits<channel_t>::max_value();
auto const min_value = gil::channel_traits<channel_t>::min_value();
gil::channel_plus_t<channel_t, channel_t, channel_t> f;
BOOST_TEST_EQ(f(max_value, 1), min_value);
BOOST_TEST_EQ(f(max_value, max_value), max_value - 1);
}
static void run()
{
boost::mp11::mp_for_each<fixture::channel_integer_unsigned_types>(test_plus_integer_unsigned_types_with_wraparound{});
}
};
struct test_minus_integer_same_types
{
template <typename Channel>
void operator()(Channel const&)
{
using channel_t = Channel;
gil::channel_minus_t<channel_t, channel_t, channel_t> f;
BOOST_TEST_EQ(f(0, 0), channel_t(0));
BOOST_TEST_EQ(f(100, 27), channel_t(73));
}
static void run()
{
boost::mp11::mp_for_each<fixture::channel_integer_types>(test_minus_integer_same_types{});
}
};
struct test_minus_integer_mixed_types
{
template <typename Channel>
void operator()(Channel const&)
{
using channel_t = Channel;
{
using channel1_t = channel_t;
using channel2_t = std::uint8_t; // duplicates only one of fixture::channel_integer_types
gil::channel_minus_t<channel1_t, channel2_t, channel1_t> f;
BOOST_TEST_EQ(f(0, 0), channel1_t(0));
BOOST_TEST_EQ(f(100, 27), channel_t(73));
}
{
using channel1_t = std::uint8_t; // duplicates only one of fixture::channel_integer_types
using channel2_t = channel_t;
gil::channel_minus_t<channel1_t, channel2_t, channel2_t> f;
BOOST_TEST_EQ(f(0, 0), channel2_t(0));
BOOST_TEST_EQ(f(100, 27), channel_t(73));
}
}
static void run()
{
boost::mp11::mp_for_each<fixture::channel_integer_types>(test_minus_integer_mixed_types{});
}
};
struct test_multiplies_integer_same_types
{
template <typename Channel>
void operator()(Channel const&)
{
using channel_t = Channel;
gil::channel_multiplies_t<channel_t, channel_t, channel_t> f;
BOOST_TEST_EQ(f(0, 0), channel_t(0));
BOOST_TEST_EQ(f(1, 1), channel_t(1));
BOOST_TEST_EQ(f(4, 2), channel_t(8));
}
static void run()
{
boost::mp11::mp_for_each<fixture::channel_integer_types>(test_multiplies_integer_same_types{});
}
};
struct test_multiplies_integer_mixed_types
{
template <typename Channel>
void operator()(Channel const&)
{
using channel_t = Channel;
{
using channel1_t = channel_t;
using channel2_t = std::uint8_t; // duplicates only one of fixture::channel_integer_types
gil::channel_multiplies_t<channel1_t, channel2_t, channel1_t> f;
BOOST_TEST_EQ(f(0, 0), channel1_t(0));
BOOST_TEST_EQ(f(4, 2), channel_t(8));
}
{
using channel1_t = std::uint8_t; // duplicates only one of fixture::channel_integer_types
using channel2_t = channel_t;
gil::channel_multiplies_t<channel1_t, channel2_t, channel2_t> f;
BOOST_TEST_EQ(f(0, 0), channel2_t(0));
BOOST_TEST_EQ(f(4, 2), channel_t(8));
}
}
static void run()
{
boost::mp11::mp_for_each<fixture::channel_integer_types>(test_multiplies_integer_mixed_types{});
}
};
struct test_divides_integer_same_types
{
template <typename Channel>
void operator()(Channel const&)
{
using channel_t = Channel;
gil::channel_divides_t<channel_t, channel_t, channel_t> f;
BOOST_TEST_EQ(f(0, 1), channel_t(0));
BOOST_TEST_EQ(f(1, 1), channel_t(1));
BOOST_TEST_EQ(f(4, 2), channel_t(2));
}
static void run()
{
boost::mp11::mp_for_each<fixture::channel_integer_types>(test_divides_integer_same_types{});
}
};
struct test_divides_integer_mixed_types
{
template <typename Channel>
void operator()(Channel const&)
{
using channel_t = Channel;
{
using channel1_t = channel_t;
using channel2_t = std::uint8_t; // duplicates only one of fixture::channel_integer_types
gil::channel_divides_t<channel1_t, channel2_t, channel1_t> f;
BOOST_TEST_EQ(f(0, 1), channel1_t(0));
BOOST_TEST_EQ(f(4, 2), channel_t(2));
}
{
using channel1_t = std::uint8_t; // duplicates only one of fixture::channel_integer_types
using channel2_t = channel_t;
gil::channel_divides_t<channel1_t, channel2_t, channel2_t> f;
BOOST_TEST_EQ(f(0, 1), channel2_t(0));
BOOST_TEST_EQ(f(4, 2), channel_t(2));
}
}
static void run()
{
boost::mp11::mp_for_each<fixture::channel_integer_types>(test_divides_integer_mixed_types{});
}
};
struct test_plus_scalar_integer_same_types
{
template <typename Channel>
void operator()(Channel const&)
{
using channel_t = Channel;
gil::channel_plus_scalar_t<channel_t, int, channel_t> f;
BOOST_TEST_EQ(f(0, 0), channel_t(0));
BOOST_TEST_EQ(f(100, 27), channel_t(127));
}
static void run()
{
boost::mp11::mp_for_each<fixture::channel_integer_types>(test_plus_scalar_integer_same_types{});
}
};
struct test_plus_scalar_integer_mixed_types
{
template <typename Channel>
void operator()(Channel const&)
{
using channel_t = Channel;
using channel_result_t = std::uint8_t;
gil::channel_plus_scalar_t<channel_t, int, channel_result_t> f;
BOOST_TEST_EQ(f(0, 0), channel_result_t(0));
BOOST_TEST_EQ(f(100, 27), channel_result_t(127));
}
static void run()
{
boost::mp11::mp_for_each<fixture::channel_integer_types>(test_plus_scalar_integer_mixed_types{});
}
};
struct test_minus_scalar_integer_same_types
{
template <typename Channel>
void operator()(Channel const&)
{
using channel_t = Channel;
gil::channel_minus_scalar_t<channel_t, int, channel_t> f;
BOOST_TEST_EQ(f(0, 0), channel_t(0));
BOOST_TEST_EQ(f(100, 27), channel_t(73));
}
static void run()
{
boost::mp11::mp_for_each<fixture::channel_integer_types>(test_minus_scalar_integer_same_types{});
}
};
struct test_minus_scalar_integer_mixed_types
{
template <typename Channel>
void operator()(Channel const&)
{
using channel_t = Channel;
using channel_result_t = std::uint8_t;
gil::channel_minus_scalar_t<channel_t, int, std::uint8_t> f;
BOOST_TEST_EQ(f(0, 0), channel_result_t(0));
BOOST_TEST_EQ(f(100, 27), channel_result_t(73));
}
static void run()
{
boost::mp11::mp_for_each<fixture::channel_integer_types>(test_minus_scalar_integer_mixed_types{});
}
};
struct test_multiplies_scalar_integer_same_types
{
template <typename Channel>
void operator()(Channel const&)
{
using channel_t = Channel;
gil::channel_multiplies_scalar_t<channel_t, channel_t, channel_t> f;
BOOST_TEST_EQ(f(0, 0), channel_t(0));
BOOST_TEST_EQ(f(1, 1), channel_t(1));
BOOST_TEST_EQ(f(4, 2), channel_t(8));
}
static void run()
{
boost::mp11::mp_for_each<fixture::channel_integer_types>(test_multiplies_scalar_integer_same_types{});
}
};
struct test_multiplies_scalar_integer_mixed_types
{
template <typename Channel>
void operator()(Channel const&)
{
using channel_t = Channel;
using channel_result_t = std::uint8_t;
gil::channel_multiplies_scalar_t<channel_t, int, channel_result_t> f;
BOOST_TEST_EQ(f(0, 0), channel_result_t(0));
BOOST_TEST_EQ(f(4, 2), channel_result_t(8));
}
static void run()
{
boost::mp11::mp_for_each<fixture::channel_integer_types>(test_multiplies_scalar_integer_mixed_types{});
}
};
struct test_divides_scalar_integer_same_types
{
template <typename Channel>
void operator()(Channel const&)
{
using channel_t = Channel;
gil::channel_divides_scalar_t<channel_t, channel_t, channel_t> f;
BOOST_TEST_EQ(f(0, 1), channel_t(0));
BOOST_TEST_EQ(f(1, 1), channel_t(1));
BOOST_TEST_EQ(f(4, 2), channel_t(2));
}
static void run()
{
boost::mp11::mp_for_each<fixture::channel_integer_types>(test_divides_scalar_integer_same_types{});
}
};
struct test_divides_scalar_integer_mixed_types
{
template <typename Channel>
void operator()(Channel const&)
{
using channel_t = Channel;
using channel_result_t = std::uint8_t; // duplicates only one of fixture::channel_integer_types
gil::channel_divides_scalar_t<channel_t, int, channel_result_t> f;
BOOST_TEST_EQ(f(0, 1), channel_t(0));
BOOST_TEST_EQ(f(4, 2), channel_t(2));
}
static void run()
{
boost::mp11::mp_for_each<fixture::channel_integer_types>(test_divides_scalar_integer_mixed_types{});
}
};
struct test_halves_integer_same_types
{
template <typename Channel>
void operator()(Channel const&)
{
using channel_t = Channel;
gil::channel_halves_t<channel_t> f;
{
channel_t c(0);
f(c);
BOOST_TEST_EQ(c, channel_t(0));
}
{
channel_t c(2);
f(c);
BOOST_TEST_EQ(c, channel_t(1));
}
{
channel_t c(4);
f(c);
BOOST_TEST_EQ(c, channel_t(2));
}
}
static void run()
{
boost::mp11::mp_for_each<fixture::channel_integer_types>(test_halves_integer_same_types{});
}
};
struct test_zeros_integer_same_types
{
template <typename Channel>
void operator()(Channel const&)
{
using channel_t = Channel;
gil::channel_zeros_t<channel_t> f;
{
channel_t c(0);
f(c);
BOOST_TEST_EQ(c, channel_t(0));
}
{
channel_t c(2);
f(c);
BOOST_TEST_EQ(c, channel_t(0));
}
{
channel_t c(4);
f(c);
BOOST_TEST_EQ(c, channel_t(0));
}
}
static void run()
{
boost::mp11::mp_for_each<fixture::channel_integer_types>(test_zeros_integer_same_types{});
}
};
struct test_assigns_integer_same_types
{
template <typename Channel>
void operator()(Channel const&)
{
using channel_t = Channel;
gil::channel_assigns_t<channel_t, channel_t> f;
{
channel_t c1(10);
channel_t c2(20);
f(c1, c2);
BOOST_TEST_EQ(c2, c1);
}
}
static void run()
{
boost::mp11::mp_for_each<fixture::channel_integer_types>(test_assigns_integer_same_types{});
}
};
int main()
{
test_plus_integer_same_types::run();
test_plus_integer_mixed_types::run();
test_plus_integer_signed_types_with_overflow::run();
test_plus_integer_unsigned_types_with_wraparound::run();
test_minus_integer_same_types::run();
test_minus_integer_mixed_types::run();
test_multiplies_integer_same_types::run();
test_multiplies_integer_mixed_types::run();
test_divides_integer_same_types::run();
test_divides_integer_mixed_types::run();
test_plus_scalar_integer_same_types::run();
test_plus_scalar_integer_mixed_types::run();
test_minus_scalar_integer_same_types::run();
test_minus_scalar_integer_mixed_types::run();
test_multiplies_scalar_integer_same_types::run();
test_multiplies_scalar_integer_mixed_types::run();
test_divides_scalar_integer_same_types::run();
test_divides_scalar_integer_mixed_types::run();
test_halves_integer_same_types::run();
test_zeros_integer_same_types::run();
test_assigns_integer_same_types::run();
return ::boost::report_errors();
}