math: check_and_set/check_and_clear bit flags functions

This commit is contained in:
2019-02-08 06:10:52 +07:00
parent 6929bdd020
commit 1ce03f493d
2 changed files with 140 additions and 0 deletions

View File

@@ -366,6 +366,58 @@ namespace e2d { namespace math
return flag_mask == (flags & flag_mask);
}
template < typename T, typename U >
std::enable_if_t<
std::is_unsigned<T>::value &&
std::is_convertible<U,T>::value,
bool>
check_and_set_any_flags(T& flags, U flag_mask) noexcept {
if ( flag_mask == (flags & flag_mask) ) {
return false;
}
flags |= flag_mask;
return true;
}
template < typename T, typename U >
std::enable_if_t<
std::is_unsigned<T>::value &&
std::is_convertible<U,T>::value,
bool>
check_and_set_all_flags(T& flags, U flag_mask) noexcept {
if ( !!(flags & flag_mask) ) {
return false;
}
flags |= flag_mask;
return true;
}
template < typename T, typename U >
std::enable_if_t<
std::is_unsigned<T>::value &&
std::is_convertible<U,T>::value,
bool>
check_and_clear_any_flags(T& flags, U flag_mask) noexcept {
if ( !(flags & flag_mask) ) {
return false;
}
flags &= ~flag_mask;
return true;
}
template < typename T, typename U >
std::enable_if_t<
std::is_unsigned<T>::value &&
std::is_convertible<U,T>::value,
bool>
check_and_clear_all_flags(T& flags, U flag_mask) noexcept {
if ( flag_mask != (flags & flag_mask) ) {
return false;
}
flags &= ~flag_mask;
return true;
}
//
// power of two
//

View File

@@ -200,6 +200,94 @@ TEST_CASE("math") {
REQUIRE_FALSE(math::check_all_flags(0b1101u, fm_flag0 | fm_flag1));
REQUIRE_FALSE(math::check_all_flags(0b1100u, fm_flag0 | fm_flag1));
REQUIRE_FALSE(math::check_all_flags(0b0000u, fm_flag0 | fm_flag1));
//
// check_and_set_any_flags
//
{
u32 f = 0b0000u;
REQUIRE(math::check_and_set_any_flags(f, fm_flag0 | fm_flag1));
REQUIRE(f == 0b0011u);
f = 0b0001u;
REQUIRE(math::check_and_set_any_flags(f, fm_flag0 | fm_flag1));
REQUIRE(f == 0b0011u);
f = 0b0010u;
REQUIRE(math::check_and_set_any_flags(f, fm_flag0 | fm_flag1));
REQUIRE(f == 0b0011u);
f = 0b0011u;
REQUIRE_FALSE(math::check_and_set_any_flags(f, fm_flag0 | fm_flag1));
REQUIRE(f == 0b0011u);
}
//
// check_and_set_all_flags
//
{
u32 f = 0b0000u;
REQUIRE(math::check_and_set_all_flags(f, fm_flag0 | fm_flag1));
REQUIRE(f == 0b0011u);
f = 0b0001u;
REQUIRE_FALSE(math::check_and_set_all_flags(f, fm_flag0 | fm_flag1));
REQUIRE(f == 0b0001u);
f = 0b0010u;
REQUIRE_FALSE(math::check_and_set_all_flags(f, fm_flag0 | fm_flag1));
REQUIRE(f == 0b0010u);
f = 0b0011u;
REQUIRE_FALSE(math::check_and_set_all_flags(f, fm_flag0 | fm_flag1));
REQUIRE(f == 0b0011u);
}
//
// check_and_clear_any_flags
//
{
u32 f = 0b1100u;
REQUIRE_FALSE(math::check_and_clear_any_flags(f, fm_flag0 | fm_flag1));
REQUIRE(f == 0b1100u);
f = 0b1101u;
REQUIRE(math::check_and_clear_any_flags(f, fm_flag0 | fm_flag1));
REQUIRE(f == 0b1100u);
f = 0b1110u;
REQUIRE(math::check_and_clear_any_flags(f, fm_flag0 | fm_flag1));
REQUIRE(f == 0b1100u);
f = 0b1111u;
REQUIRE(math::check_and_clear_any_flags(f, fm_flag0 | fm_flag1));
REQUIRE(f == 0b1100u);
}
//
// check_and_clear_all_flags
//
{
u32 f = 0b1100u;
REQUIRE_FALSE(math::check_and_clear_all_flags(f, fm_flag0 | fm_flag1));
REQUIRE(f == 0b1100u);
f = 0b1101u;
REQUIRE_FALSE(math::check_and_clear_all_flags(f, fm_flag0 | fm_flag1));
REQUIRE(f == 0b1101u);
f = 0b1110u;
REQUIRE_FALSE(math::check_and_clear_all_flags(f, fm_flag0 | fm_flag1));
REQUIRE(f == 0b1110u);
f = 0b1111u;
REQUIRE(math::check_and_clear_all_flags(f, fm_flag0 | fm_flag1));
REQUIRE(f == 0b1100u);
}
}
{
REQUIRE(math::is_power_of_2(1u));