From d2d26c6771d82011fded7f739c5aa2f0f4ce50ba Mon Sep 17 00:00:00 2001 From: Miodrag Milanovic Date: Thu, 9 Feb 2017 11:19:36 +0100 Subject: [PATCH] added RGB unit testing (nw) --- scripts/src/tests.lua | 8 + tests/emu/video/rgbutil.cpp | 1036 +++++++++++++++++++++++++++++++++++ 2 files changed, 1044 insertions(+) create mode 100644 tests/emu/video/rgbutil.cpp diff --git a/scripts/src/tests.lua b/scripts/src/tests.lua index cb0bd3ee3ad..f01a5fa4de8 100644 --- a/scripts/src/tests.lua +++ b/scripts/src/tests.lua @@ -82,10 +82,18 @@ project("mametests") ext_includedir("zlib"), } + files { + MAME_DIR .. "src/emu/video/rgbsse.cpp", + MAME_DIR .. "src/emu/video/rgbsse.h", + MAME_DIR .. "src/emu/video/rgbvmx.cpp", + MAME_DIR .. "src/emu/video/rgbvmx.h", + } + files { MAME_DIR .. "tests/main.cpp", MAME_DIR .. "tests/lib/util/corestr.cpp", MAME_DIR .. "tests/lib/util/options.cpp", MAME_DIR .. "tests/emu/attotime.cpp", + MAME_DIR .. "tests/emu/video/rgbutil.cpp", } diff --git a/tests/emu/video/rgbutil.cpp b/tests/emu/video/rgbutil.cpp new file mode 100644 index 00000000000..c3fcc6a9fd2 --- /dev/null +++ b/tests/emu/video/rgbutil.cpp @@ -0,0 +1,1036 @@ +#include "catch.hpp" +#include "emucore.h" +#include "video/rgbutil.h" + + +//------------------------------------------------- +// random_u64 +// random_s64 +// random_u32 +// random_s32 +//------------------------------------------------- +#undef rand +inline u32 random_u32() { return rand() ^ (rand() << 15); } +inline s32 random_i32() { return s32(random_u32()); } +inline u64 random_u64() { return u64(random_u32()) ^ (u64(random_u32()) << 30); } +inline s64 random_i64() { return s64(random_u64()); } + + +TEST_CASE("check rgb", "[emu][video]") +{ + /* + This performs cursory tests of most of the vector-optimised RGB + utilities, concentrating on the low-level maths. It uses random + values most of the time for a quick go/no-go indication rather + than trying to exercise edge cases. It doesn't matter too much + if the compiler optimises out some of the operations since it's + really intended to check for logic bugs in the vector code. If + the compiler can work out that the code produces the expected + result, that's good enough. + + The tests for bitwise logical operations are ordered to minimise + the chance of all-zero or all-one patterns producing a + misleading good result. + + The following functions are not tested yet: + rgbaint_t() + clamp_and_clear(const u32) + sign_extend(const u32, const u32) + min(const s32) + max(const s32) + blend(const rgbaint_t&, u8) + scale_and_clamp(const rgbaint_t&) + scale_imm_and_clamp(const s32) + scale2_add_and_clamp(const rgbaint_t&, const rgbaint_t&, const rgbaint_t&) + scale_add_and_clamp(const rgbaint_t&, const rgbaint_t&); + scale_imm_add_and_clamp(const s32, const rgbaint_t&); + static bilinear_filter(u32, u32, u32, u32, u8, u8) + bilinear_filter_rgbaint(u32, u32, u32, u32, u8, u8) + */ + + auto random_i32_nolimit = [] + { + s32 result; + do { result = random_i32(); } while ((result == std::numeric_limits::min()) || (result == std::numeric_limits::max())); + return result; + }; + + volatile s32 expected_a, expected_r, expected_g, expected_b; + volatile s32 actual_a, actual_r, actual_g, actual_b; + volatile s32 imm; + rgbaint_t rgb, other; + rgb_t packed; + auto check_expected = [&] () + { + const volatile s32 a = rgb.get_a32(); + const volatile s32 r = rgb.get_r32(); + const volatile s32 g = rgb.get_g32(); + const volatile s32 b = rgb.get_b32(); + REQUIRE(a == expected_a); + (r == expected_r); + REQUIRE(g == expected_g); + REQUIRE(b == expected_b); + }; + + // check set/get + SECTION("rgbaint_t::set(a, r, g, b)") + { + expected_a = random_i32(); + expected_r = random_i32(); + expected_g = random_i32(); + expected_b = random_i32(); + rgb.set(expected_a, expected_r, expected_g, expected_b); + + check_expected(); + } + + // check construct/set + SECTION("rgbaint_t::set(rgbaint_t)") + { + expected_a = random_i32(); + expected_r = random_i32(); + expected_g = random_i32(); + expected_b = random_i32(); + rgb.set(rgbaint_t(expected_a, expected_r, expected_g, expected_b)); + check_expected(); + } + + // check construct/assign + SECTION("rgbaint_t assignment") + { + expected_a = random_i32(); + expected_r = random_i32(); + expected_g = random_i32(); + expected_b = random_i32(); + rgb = rgbaint_t(expected_a, expected_r, expected_g, expected_b); + check_expected(); + } + + // check piecewise set + SECTION("rgbaint_t::set_a") + { + rgb.set_a(expected_a = random_i32()); + check_expected(); + } + + SECTION("rgbaint_t::set_r") + { + rgb.set_r(expected_r = random_i32()); + check_expected(); + } + + SECTION("rgbaint_t::set_g") + { + rgb.set_g(expected_g = random_i32()); + check_expected(); + } + + SECTION("rgbaint_t::set_b") + { + rgb.set_b(expected_b = random_i32()); + check_expected(); + } + + // test merge_alpha + SECTION("rgbaint_t::merge_alpha") + { + expected_a = rand(); + rgb.merge_alpha(rgbaint_t(expected_a, rand(), rand(), rand())); + check_expected(); + } + + // test RGB addition (method) + SECTION("rgbaint_t::add") + { + expected_a += actual_a = random_i32(); + expected_r += actual_r = random_i32(); + expected_g += actual_g = random_i32(); + expected_b += actual_b = random_i32(); + rgb.add(rgbaint_t(actual_a, actual_r, actual_g, actual_b)); + check_expected(); + } + + // test RGB addition (operator) + SECTION("rgbaint_t::operator+=") + { + expected_a += actual_a = random_i32(); + expected_r += actual_r = random_i32(); + expected_g += actual_g = random_i32(); + expected_b += actual_b = random_i32(); + rgb += rgbaint_t(actual_a, actual_r, actual_g, actual_b); + check_expected(); + } + + // test offset addition (method) + SECTION("rgbaint_t::add_imm") + { + imm = random_i32(); + expected_a += imm; + expected_r += imm; + expected_g += imm; + expected_b += imm; + rgb.add_imm(imm); + check_expected(); + } + + // test offset addition (operator) + SECTION("rgbaint_t::operator+=") + { + imm = random_i32(); + expected_a += imm; + expected_r += imm; + expected_g += imm; + expected_b += imm; + rgb += imm; + check_expected(); + } + + // test immediate RGB addition + SECTION("rgbaint_t::add_imm_rgba") + { + expected_a += actual_a = random_i32(); + expected_r += actual_r = random_i32(); + expected_g += actual_g = random_i32(); + expected_b += actual_b = random_i32(); + rgb.add_imm_rgba(actual_a, actual_r, actual_g, actual_b); + check_expected(); + } + + // test RGB subtraction (method) + SECTION("rgbaint_t::sub") + { + expected_a -= actual_a = random_i32(); + expected_r -= actual_r = random_i32(); + expected_g -= actual_g = random_i32(); + expected_b -= actual_b = random_i32(); + rgb.sub(rgbaint_t(actual_a, actual_r, actual_g, actual_b)); + check_expected(); + } + + // test RGB subtraction (operator) + SECTION("rgbaint_t::operator-=") + { + expected_a -= actual_a = random_i32(); + expected_r -= actual_r = random_i32(); + expected_g -= actual_g = random_i32(); + expected_b -= actual_b = random_i32(); + rgb -= rgbaint_t(actual_a, actual_r, actual_g, actual_b); + check_expected(); + } + + // test offset subtraction + SECTION("rgbaint_t::sub_imm") + { + imm = random_i32(); + expected_a -= imm; + expected_r -= imm; + expected_g -= imm; + expected_b -= imm; + rgb.sub_imm(imm); + check_expected(); + } + + // test immediate RGB subtraction + SECTION("rgbaint_t::sub_imm_rgba") + { + expected_a -= actual_a = random_i32(); + expected_r -= actual_r = random_i32(); + expected_g -= actual_g = random_i32(); + expected_b -= actual_b = random_i32(); + rgb.sub_imm_rgba(actual_a, actual_r, actual_g, actual_b); + check_expected(); + } + + // test reversed RGB subtraction + SECTION("rgbaint_t::subr") + { + expected_a = (actual_a = random_i32()) - expected_a; + expected_r = (actual_r = random_i32()) - expected_r; + expected_g = (actual_g = random_i32()) - expected_g; + expected_b = (actual_b = random_i32()) - expected_b; + rgb.subr(rgbaint_t(actual_a, actual_r, actual_g, actual_b)); + check_expected(); + } + + // test reversed offset subtraction + SECTION("rgbaint_t::subr_imm") + { + imm = random_i32(); + expected_a = imm - expected_a; + expected_r = imm - expected_r; + expected_g = imm - expected_g; + expected_b = imm - expected_b; + rgb.subr_imm(imm); + check_expected(); + } + + // test reversed immediate RGB subtraction + SECTION("rgbaint_t::subr_imm_rgba") + { + expected_a = (actual_a = random_i32()) - expected_a; + expected_r = (actual_r = random_i32()) - expected_r; + expected_g = (actual_g = random_i32()) - expected_g; + expected_b = (actual_b = random_i32()) - expected_b; + rgb.subr_imm_rgba(actual_a, actual_r, actual_g, actual_b); + check_expected(); + } + + // test RGB multiplication (method) + SECTION("rgbaint_t::mul") + { + expected_a *= actual_a = random_i32(); + expected_r *= actual_r = random_i32(); + expected_g *= actual_g = random_i32(); + expected_b *= actual_b = random_i32(); + rgb.mul(rgbaint_t(actual_a, actual_r, actual_g, actual_b)); + check_expected(); + } + + // test RGB multiplication (operator) + SECTION("rgbaint_t::operator*=") + { + expected_a *= actual_a = random_i32(); + expected_r *= actual_r = random_i32(); + expected_g *= actual_g = random_i32(); + expected_b *= actual_b = random_i32(); + rgb *= rgbaint_t(actual_a, actual_r, actual_g, actual_b); + check_expected(); + } + + // test factor multiplication (method) + SECTION("rgbaint_t::mul_imm") + { + imm = random_i32(); + expected_a *= imm; + expected_r *= imm; + expected_g *= imm; + expected_b *= imm; + rgb.mul_imm(imm); + check_expected(); + } + + // test factor multiplication (operator) + SECTION("rgbaint_t::operator*=") + { + imm = random_i32(); + expected_a *= imm; + expected_r *= imm; + expected_g *= imm; + expected_b *= imm; + rgb *= imm; + check_expected(); + } + + // test immediate RGB multiplication + SECTION("rgbaint_t::mul_imm_rgba") + { + expected_a *= actual_a = random_i32(); + expected_r *= actual_r = random_i32(); + expected_g *= actual_g = random_i32(); + expected_b *= actual_b = random_i32(); + rgb.mul_imm_rgba(actual_a, actual_r, actual_g, actual_b); + check_expected(); + } + + // test RGB and not + SECTION("rgbaint_t::andnot_reg") + { + expected_a &= ~(actual_a = random_i32()); + expected_r &= ~(actual_r = random_i32()); + expected_g &= ~(actual_g = random_i32()); + expected_b &= ~(actual_b = random_i32()); + rgb.andnot_reg(rgbaint_t(actual_a, actual_r, actual_g, actual_b)); + check_expected(); + } + + // test RGB or + SECTION("rgbaint_t::or_reg") + { + expected_a |= actual_a = random_i32(); + expected_r |= actual_r = random_i32(); + expected_g |= actual_g = random_i32(); + expected_b |= actual_b = random_i32(); + rgb.or_reg(rgbaint_t(actual_a, actual_r, actual_g, actual_b)); + check_expected(); + } + + // test RGB and + SECTION("rgbaint_t::and_reg") + { + expected_a &= actual_a = random_i32(); + expected_r &= actual_r = random_i32(); + expected_g &= actual_g = random_i32(); + expected_b &= actual_b = random_i32(); + rgb.and_reg(rgbaint_t(actual_a, actual_r, actual_g, actual_b)); + check_expected(); + } + + // test RGB xor + SECTION("rgbaint_t::xor_reg") + { + expected_a ^= actual_a = random_i32(); + expected_r ^= actual_r = random_i32(); + expected_g ^= actual_g = random_i32(); + expected_b ^= actual_b = random_i32(); + rgb.xor_reg(rgbaint_t(actual_a, actual_r, actual_g, actual_b)); + check_expected(); + } + // test uniform or + SECTION("rgbaint_t::or_imm") + { + imm = random_i32(); + expected_a |= imm; + expected_r |= imm; + expected_g |= imm; + expected_b |= imm; + rgb.or_imm(imm); + check_expected(); + } + + // test uniform and + SECTION("rgbaint_t::and_imm") + { + imm = random_i32(); + expected_a &= imm; + expected_r &= imm; + expected_g &= imm; + expected_b &= imm; + rgb.and_imm(imm); + check_expected(); + } + + // test uniform xor + SECTION("rgbaint_t::xor_imm") + { + imm = random_i32(); + expected_a ^= imm; + expected_r ^= imm; + expected_g ^= imm; + expected_b ^= imm; + rgb.xor_imm(imm); + check_expected(); + } + + // test immediate RGB or + SECTION("rgbaint_t::or_imm_rgba") + { + expected_a |= actual_a = random_i32(); + expected_r |= actual_r = random_i32(); + expected_g |= actual_g = random_i32(); + expected_b |= actual_b = random_i32(); + rgb.or_imm_rgba(actual_a, actual_r, actual_g, actual_b); + check_expected(); + } + + // test immediate RGB and + SECTION("rgbaint_t::and_imm_rgba") + { + expected_a &= actual_a = random_i32(); + expected_r &= actual_r = random_i32(); + expected_g &= actual_g = random_i32(); + expected_b &= actual_b = random_i32(); + rgb.and_imm_rgba(actual_a, actual_r, actual_g, actual_b); + check_expected(); + } + + // test immediate RGB xor + SECTION("rgbaint_t::xor_imm_rgba") + { + expected_a ^= actual_a = random_i32(); + expected_r ^= actual_r = random_i32(); + expected_g ^= actual_g = random_i32(); + expected_b ^= actual_b = random_i32(); + rgb.xor_imm_rgba(actual_a, actual_r, actual_g, actual_b); + check_expected(); + } + + // test 8-bit get + SECTION("8-bit get") + { + expected_a = s32(u32(expected_a) & 0x00ff); + expected_r = s32(u32(expected_r) & 0x00ff); + expected_g = s32(u32(expected_g) & 0x00ff); + expected_b = s32(u32(expected_b) & 0x00ff); + actual_a = s32(u32(rgb.get_a())); + actual_r = s32(u32(rgb.get_r())); + actual_g = s32(u32(rgb.get_g())); + actual_b = s32(u32(rgb.get_b())); + REQUIRE(actual_a == expected_a); + REQUIRE(actual_r == expected_r); + REQUIRE(actual_g == expected_g); + REQUIRE(actual_b == expected_b); + } + + // test set from packed RGBA + SECTION("rgbaint_t::set(u32)") + { + imm = random_i32(); + expected_a = s32((u32(imm) >> 24) & 0x00ff); + expected_r = s32((u32(imm) >> 16) & 0x00ff); + expected_g = s32((u32(imm) >> 8) & 0x00ff); + expected_b = s32((u32(imm) >> 0) & 0x00ff); + rgb.set(u32(imm)); + check_expected(); + } + + // while we have a value loaded that we know doesn't exceed 8-bit range, check the non-clamping convert-to-rgba + SECTION("non-clamping convert-to-rgba") + { + packed = rgb.to_rgba(); + REQUIRE(u32(imm) == u32(packed)); + } + + // test construct from packed RGBA and assign + SECTION("rgbaint_t(u32)") + { + imm = random_i32(); + expected_a = s32((u32(imm) >> 24) & 0x00ff); + expected_r = s32((u32(imm) >> 16) & 0x00ff); + expected_g = s32((u32(imm) >> 8) & 0x00ff); + expected_b = s32((u32(imm) >> 0) & 0x00ff); + rgb = rgbaint_t(u32(imm)); + check_expected(); + } + + // while we have a value loaded that we know doesn't exceed 8-bit range, check the non-clamping convert-to-rgba + SECTION("non-clamping convert-to-rgba") + { + packed = rgb.to_rgba(); + REQUIRE(u32(imm) == u32(packed)); + } + + // test set with rgb_t + SECTION("rgbaint_t::set(rgba_t)") + { + packed = random_u32(); + expected_a = s32(u32(packed.a())); + expected_r = s32(u32(packed.r())); + expected_g = s32(u32(packed.g())); + expected_b = s32(u32(packed.b())); + rgb.set(packed); + check_expected(); + } + + // test construct with rgb_t + SECTION("construct rgb_t") + { + packed = random_u32(); + expected_a = s32(u32(packed.a())); + expected_r = s32(u32(packed.r())); + expected_g = s32(u32(packed.g())); + expected_b = s32(u32(packed.b())); + rgb = rgbaint_t(packed); + check_expected(); + } + + // test clamping convert-to-rgba with hand-crafted values to catch edge cases + SECTION("clamping convert-to-rgba with hand-crafted values to catch edge cases") + { + rgb.set(std::numeric_limits::min(), -1, 0, 1); + packed = rgb.to_rgba_clamp(); + REQUIRE(u32(0x00000001) == u32(packed)); + + rgb.set(254, 255, 256, std::numeric_limits::max()); + packed = rgb.to_rgba_clamp(); + REQUIRE(u32(0xfeffffff) == u32(packed)); + + rgb.set(std::numeric_limits::max(), std::numeric_limits::min(), 256, -1); + packed = rgb.to_rgba_clamp(); + REQUIRE(u32(0xff00ff00) == u32(packed)); + + rgb.set(0, 255, 1, 254); + packed = rgb.to_rgba_clamp(); + REQUIRE(u32(0x00ff01fe) == u32(packed)); + } + + // test in-place clamping with hand-crafted values to catch edge cases + SECTION("rgbaint_t::clamp_to_uint8") + { + expected_a = 0; + expected_r = 0; + expected_g = 0; + expected_b = 1; + rgb.set(std::numeric_limits::min(), -1, 0, 1); + rgb.clamp_to_uint8(); + check_expected(); + + expected_a = 254; + expected_r = 255; + expected_g = 255; + expected_b = 255; + rgb.set(254, 255, 256, std::numeric_limits::max()); + rgb.clamp_to_uint8(); + check_expected(); + + expected_a = 255; + expected_r = 0; + expected_g = 255; + expected_b = 0; + rgb.set(std::numeric_limits::max(), std::numeric_limits::min(), 256, -1); + rgb.clamp_to_uint8(); + check_expected(); + + expected_a = 0; + expected_r = 255; + expected_g = 1; + expected_b = 254; + rgb.set(0, 255, 1, 254); + rgb.clamp_to_uint8(); + check_expected(); + } + + // test shift left + SECTION("rgbaint_t::shl") + { + expected_a = (actual_a = random_i32()) << 19; + expected_r = (actual_r = random_i32()) << 3; + expected_g = (actual_g = random_i32()) << 21; + expected_b = (actual_b = random_i32()) << 6; + rgb.set(actual_a, actual_r, actual_g, actual_b); + rgb.shl(rgbaint_t(19, 3, 21, 6)); + check_expected(); + } + + // test shift left immediate + SECTION("rgbaint_t::shl_imm") + { + expected_a = (actual_a = random_i32()) << 7; + expected_r = (actual_r = random_i32()) << 7; + expected_g = (actual_g = random_i32()) << 7; + expected_b = (actual_b = random_i32()) << 7; + rgb.set(actual_a, actual_r, actual_g, actual_b); + rgb.shl_imm(7); + check_expected(); + } + + // test logical shift right + SECTION("rgbaint_t::shr") + { + expected_a = s32(u32(actual_a = random_i32()) >> 8); + expected_r = s32(u32(actual_r = random_i32()) >> 18); + expected_g = s32(u32(actual_g = random_i32()) >> 26); + expected_b = s32(u32(actual_b = random_i32()) >> 4); + rgb.set(actual_a, actual_r, actual_g, actual_b); + rgb.shr(rgbaint_t(8, 18, 26, 4)); + check_expected(); + } + + // test logical shift right with opposite signs + SECTION("rgbaint_t::shrwith opposite signs") + { + expected_a = s32(u32(actual_a = -actual_a) >> 21); + expected_r = s32(u32(actual_r = -actual_r) >> 13); + expected_g = s32(u32(actual_g = -actual_g) >> 11); + expected_b = s32(u32(actual_b = -actual_b) >> 17); + rgb.set(actual_a, actual_r, actual_g, actual_b); + rgb.shr(rgbaint_t(21, 13, 11, 17)); + check_expected(); + } + + // test logical shift right immediate + SECTION("rgbaint_t::shr_imm") + { + expected_a = s32(u32(actual_a = random_i32()) >> 5); + expected_r = s32(u32(actual_r = random_i32()) >> 5); + expected_g = s32(u32(actual_g = random_i32()) >> 5); + expected_b = s32(u32(actual_b = random_i32()) >> 5); + rgb.set(actual_a, actual_r, actual_g, actual_b); + rgb.shr_imm(5); + check_expected(); + } + + // test logical shift right immediate with opposite signs + SECTION("rgbaint_t::shr_imm with opposite signs") + { + expected_a = s32(u32(actual_a = -actual_a) >> 15); + expected_r = s32(u32(actual_r = -actual_r) >> 15); + expected_g = s32(u32(actual_g = -actual_g) >> 15); + expected_b = s32(u32(actual_b = -actual_b) >> 15); + rgb.set(actual_a, actual_r, actual_g, actual_b); + rgb.shr_imm(15); + check_expected(); + } + + // test arithmetic shift right + SECTION("rgbaint_t::sra") + { + expected_a = (actual_a = random_i32()) >> 16; + expected_r = (actual_r = random_i32()) >> 20; + expected_g = (actual_g = random_i32()) >> 14; + expected_b = (actual_b = random_i32()) >> 2; + rgb.set(actual_a, actual_r, actual_g, actual_b); + rgb.sra(rgbaint_t(16, 20, 14, 2)); + check_expected(); + } + + // test arithmetic shift right with opposite signs + SECTION("rgbaint_t::sra with opposite signs") + { + expected_a = (actual_a = -actual_a) >> 1; + expected_r = (actual_r = -actual_r) >> 29; + expected_g = (actual_g = -actual_g) >> 10; + expected_b = (actual_b = -actual_b) >> 22; + rgb.set(actual_a, actual_r, actual_g, actual_b); + rgb.sra(rgbaint_t(1, 29, 10, 22)); + check_expected(); + } + + // test arithmetic shift right immediate (method) + SECTION("rgbaint_t::sra_imm") + { + expected_a = (actual_a = random_i32()) >> 12; + expected_r = (actual_r = random_i32()) >> 12; + expected_g = (actual_g = random_i32()) >> 12; + expected_b = (actual_b = random_i32()) >> 12; + rgb.set(actual_a, actual_r, actual_g, actual_b); + rgb.sra_imm(12); + check_expected(); + } + + // test arithmetic shift right immediate with opposite signs (method) + SECTION("rgbaint_t::sra_imm with opposite signs") + { + expected_a = (actual_a = -actual_a) >> 9; + expected_r = (actual_r = -actual_r) >> 9; + expected_g = (actual_g = -actual_g) >> 9; + expected_b = (actual_b = -actual_b) >> 9; + rgb.set(actual_a, actual_r, actual_g, actual_b); + rgb.sra_imm(9); + check_expected(); + } + + // test arithmetic shift right immediate (operator) + SECTION("rgbaint_t::operator>>=") + { + expected_a = (actual_a = random_i32()) >> 7; + expected_r = (actual_r = random_i32()) >> 7; + expected_g = (actual_g = random_i32()) >> 7; + expected_b = (actual_b = random_i32()) >> 7; + rgb.set(actual_a, actual_r, actual_g, actual_b); + rgb >>= 7; + check_expected(); + } + + // test arithmetic shift right immediate with opposite signs (operator) + SECTION("rgbaint_t::operator>>= with opposite signs") + { + expected_a = (actual_a = -actual_a) >> 11; + expected_r = (actual_r = -actual_r) >> 11; + expected_g = (actual_g = -actual_g) >> 11; + expected_b = (actual_b = -actual_b) >> 11; + rgb.set(actual_a, actual_r, actual_g, actual_b); + rgb >>= 11; + check_expected(); + } + + // test RGB equality comparison + SECTION("rgbaint_t::cmpeq RGB equality comparison") + { + actual_a = random_i32_nolimit(); + actual_r = random_i32_nolimit(); + actual_g = random_i32_nolimit(); + actual_b = random_i32_nolimit(); + expected_a = ~s32(0); + expected_r = 0; + expected_g = 0; + expected_b = 0; + rgb.set(actual_a, actual_r, actual_g, actual_b); + rgb.cmpeq(rgbaint_t(actual_a, actual_r - 1, actual_g + 1, std::numeric_limits::min())); + check_expected(); + expected_a = 0; + expected_r = ~s32(0); + expected_g = 0; + expected_b = 0; + rgb.set(actual_a, actual_r, actual_g, actual_b); + rgb.cmpeq(rgbaint_t(std::numeric_limits::max(), actual_r, actual_g - 1, actual_b + 1)); + check_expected(); + } + + // test immediate equality comparison + SECTION("rgbaint_t::cmpeq_imm immediate equality comparison") + { + actual_a = random_i32_nolimit(); + actual_r = random_i32_nolimit(); + actual_g = random_i32_nolimit(); + actual_b = random_i32_nolimit(); + expected_a = ~s32(0); + expected_r = (actual_r == actual_a) ? ~s32(0) : 0; + expected_g = (actual_g == actual_a) ? ~s32(0) : 0; + expected_b = (actual_b == actual_a) ? ~s32(0) : 0; + rgb.set(actual_a, actual_r, actual_g, actual_b); + rgb.cmpeq_imm(actual_a); + check_expected(); + expected_a = (actual_a == actual_r) ? ~s32(0) : 0; + expected_r = ~s32(0); + expected_g = (actual_g == actual_r) ? ~s32(0) : 0; + expected_b = (actual_b == actual_r) ? ~s32(0) : 0; + rgb.set(actual_a, actual_r, actual_g, actual_b); + rgb.cmpeq_imm(actual_r); + check_expected(); + expected_a = (actual_a == actual_g) ? ~s32(0) : 0; + expected_r = (actual_r == actual_g) ? ~s32(0) : 0; + expected_g = ~s32(0); + expected_b = (actual_b == actual_g) ? ~s32(0) : 0; + rgb.set(actual_a, actual_r, actual_g, actual_b); + rgb.cmpeq_imm(actual_g); + check_expected(); + expected_a = (actual_a == actual_b) ? ~s32(0) : 0; + expected_r = (actual_r == actual_b) ? ~s32(0) : 0; + expected_g = (actual_g == actual_b) ? ~s32(0) : 0; + expected_b = ~s32(0); + rgb.set(actual_a, actual_r, actual_g, actual_b); + rgb.cmpeq_imm(actual_b); + check_expected(); + expected_a = 0; + expected_r = 0; + expected_g = 0; + expected_b = 0; + rgb.set(actual_a, actual_r, actual_g, actual_b); + rgb.cmpeq_imm(std::numeric_limits::min()); + check_expected(); + expected_a = !actual_a ? ~s32(0) : 0; + expected_r = !actual_r ? ~s32(0) : 0; + expected_g = !actual_g ? ~s32(0) : 0; + expected_b = !actual_b ? ~s32(0) : 0; + rgb.set(actual_a, actual_r, actual_g, actual_b); + rgb.cmpeq_imm(0); + check_expected(); + expected_a = 0; + expected_r = 0; + expected_g = 0; + expected_b = 0; + rgb.set(actual_a, actual_r, actual_g, actual_b); + rgb.cmpeq_imm(std::numeric_limits::max()); + check_expected(); + } + + // test immediate RGB equality comparison + SECTION("rgbaint_t::cmpeq_imm_rgba immediate RGB equality comparison") + { + actual_a = random_i32_nolimit(); + actual_r = random_i32_nolimit(); + actual_g = random_i32_nolimit(); + actual_b = random_i32_nolimit(); + expected_a = 0; + expected_r = 0; + expected_g = ~s32(0); + expected_b = 0; + rgb.set(actual_a, actual_r, actual_g, actual_b); + rgb.cmpeq_imm_rgba(std::numeric_limits::min(), std::numeric_limits::max(), actual_g, actual_b - 1); + check_expected(); + expected_a = 0; + expected_r = 0; + expected_g = 0; + expected_b = ~s32(0); + rgb.set(actual_a, actual_r, actual_g, actual_b); + rgb.cmpeq_imm_rgba(actual_a + 1, std::numeric_limits::min(), std::numeric_limits::max(), actual_b); + check_expected(); + } + + // test RGB greater than comparison + SECTION("rgbaint_t::cmpgt RGB greater than comparison") + { + actual_a = random_i32_nolimit(); + actual_r = random_i32_nolimit(); + actual_g = random_i32_nolimit(); + actual_b = random_i32_nolimit(); + expected_a = 0; + expected_r = ~s32(0); + expected_g = 0; + expected_b = ~s32(0); + rgb.set(actual_a, actual_r, actual_g, actual_b); + rgb.cmpgt(rgbaint_t(actual_a, actual_r - 1, actual_g + 1, std::numeric_limits::min())); + check_expected(); + expected_a = 0; + expected_r = 0; + expected_g = ~s32(0); + expected_b = 0; + rgb.set(actual_a, actual_r, actual_g, actual_b); + rgb.cmpgt(rgbaint_t(std::numeric_limits::max(), actual_r, actual_g - 1, actual_b + 1)); + check_expected(); + } + + // test immediate greater than comparison + SECTION("rgbaint_t::cmpgt_imm immediate greater than comparison") + { + actual_a = random_i32_nolimit(); + actual_r = random_i32_nolimit(); + actual_g = random_i32_nolimit(); + actual_b = random_i32_nolimit(); + expected_a = 0; + expected_r = (actual_r > actual_a) ? ~s32(0) : 0; + expected_g = (actual_g > actual_a) ? ~s32(0) : 0; + expected_b = (actual_b > actual_a) ? ~s32(0) : 0; + rgb.set(actual_a, actual_r, actual_g, actual_b); + rgb.cmpgt_imm(actual_a); + check_expected(); + expected_a = (actual_a > actual_r) ? ~s32(0) : 0; + expected_r = 0; + expected_g = (actual_g > actual_r) ? ~s32(0) : 0; + expected_b = (actual_b > actual_r) ? ~s32(0) : 0; + rgb.set(actual_a, actual_r, actual_g, actual_b); + rgb.cmpgt_imm(actual_r); + check_expected(); + expected_a = (actual_a > actual_g) ? ~s32(0) : 0; + expected_r = (actual_r > actual_g) ? ~s32(0) : 0; + expected_g =0; + expected_b = (actual_b > actual_g) ? ~s32(0) : 0; + rgb.set(actual_a, actual_r, actual_g, actual_b); + rgb.cmpgt_imm(actual_g); + check_expected(); + expected_a = (actual_a > actual_b) ? ~s32(0) : 0; + expected_r = (actual_r > actual_b) ? ~s32(0) : 0; + expected_g = (actual_g > actual_b) ? ~s32(0) : 0; + expected_b = 0; + rgb.set(actual_a, actual_r, actual_g, actual_b); + rgb.cmpgt_imm(actual_b); + check_expected(); + expected_a = ~s32(0); + expected_r = ~s32(0); + expected_g = ~s32(0); + expected_b = ~s32(0); + rgb.set(actual_a, actual_r, actual_g, actual_b); + rgb.cmpgt_imm(std::numeric_limits::min()); + check_expected(); + expected_a = (actual_a > 0) ? ~s32(0) : 0; + expected_r = (actual_r > 0) ? ~s32(0) : 0; + expected_g = (actual_g > 0) ? ~s32(0) : 0; + expected_b = (actual_b > 0) ? ~s32(0) : 0; + rgb.set(actual_a, actual_r, actual_g, actual_b); + rgb.cmpgt_imm(0); + check_expected(); + expected_a = 0; + expected_r = 0; + expected_g = 0; + expected_b = 0; + rgb.set(actual_a, actual_r, actual_g, actual_b); + rgb.cmpgt_imm(std::numeric_limits::max()); + check_expected(); + } + + // test immediate RGB greater than comparison + SECTION("rgbaint_t::cmpgt_imm_rgba immediate RGB greater than comparison") + { + actual_a = random_i32_nolimit(); + actual_r = random_i32_nolimit(); + actual_g = random_i32_nolimit(); + actual_b = random_i32_nolimit(); + expected_a = ~s32(0); + expected_r = 0; + expected_g = 0; + expected_b = ~s32(0); + rgb.set(actual_a, actual_r, actual_g, actual_b); + rgb.cmpgt_imm_rgba(std::numeric_limits::min(), std::numeric_limits::max(), actual_g, actual_b - 1); + check_expected(); + expected_a = 0; + expected_r = ~s32(0); + expected_g = 0; + expected_b = 0; + rgb.set(actual_a, actual_r, actual_g, actual_b); + rgb.cmpgt_imm_rgba(actual_a + 1, std::numeric_limits::min(), std::numeric_limits::max(), actual_b); + check_expected(); + } + // test RGB less than comparison + SECTION("rgbaint_t::cmplt RGB less than comparison") + { + actual_a = random_i32_nolimit(); + actual_r = random_i32_nolimit(); + actual_g = random_i32_nolimit(); + actual_b = random_i32_nolimit(); + expected_a = 0; + expected_r = 0; + expected_g = ~s32(0); + expected_b = 0; + rgb.set(actual_a, actual_r, actual_g, actual_b); + rgb.cmplt(rgbaint_t(actual_a, actual_r - 1, actual_g + 1, std::numeric_limits::min())); + check_expected(); + expected_a = ~s32(0); + expected_r = 0; + expected_g = 0; + expected_b = ~s32(0); + rgb.set(actual_a, actual_r, actual_g, actual_b); + rgb.cmplt(rgbaint_t(std::numeric_limits::max(), actual_r, actual_g - 1, actual_b + 1)); + check_expected(); + } + + // test immediate less than comparison + SECTION("rgbaint_t::cmplt_imm immediate less than comparison") + { + actual_a = random_i32_nolimit(); + actual_r = random_i32_nolimit(); + actual_g = random_i32_nolimit(); + actual_b = random_i32_nolimit(); + expected_a = 0; + expected_r = (actual_r < actual_a) ? ~s32(0) : 0; + expected_g = (actual_g < actual_a) ? ~s32(0) : 0; + expected_b = (actual_b < actual_a) ? ~s32(0) : 0; + rgb.set(actual_a, actual_r, actual_g, actual_b); + rgb.cmplt_imm(actual_a); + check_expected(); + expected_a = (actual_a < actual_r) ? ~s32(0) : 0; + expected_r = 0; + expected_g = (actual_g < actual_r) ? ~s32(0) : 0; + expected_b = (actual_b < actual_r) ? ~s32(0) : 0; + rgb.set(actual_a, actual_r, actual_g, actual_b); + rgb.cmplt_imm(actual_r); + check_expected(); + expected_a = (actual_a < actual_g) ? ~s32(0) : 0; + expected_r = (actual_r < actual_g) ? ~s32(0) : 0; + expected_g =0; + expected_b = (actual_b < actual_g) ? ~s32(0) : 0; + rgb.set(actual_a, actual_r, actual_g, actual_b); + rgb.cmplt_imm(actual_g); + check_expected(); + expected_a = (actual_a < actual_b) ? ~s32(0) : 0; + expected_r = (actual_r < actual_b) ? ~s32(0) : 0; + expected_g = (actual_g < actual_b) ? ~s32(0) : 0; + expected_b = 0; + rgb.set(actual_a, actual_r, actual_g, actual_b); + rgb.cmplt_imm(actual_b); + check_expected(); + expected_a = 0; + expected_r = 0; + expected_g = 0; + expected_b = 0; + rgb.set(actual_a, actual_r, actual_g, actual_b); + rgb.cmplt_imm(std::numeric_limits::min()); + check_expected(); + expected_a = (actual_a < 0) ? ~s32(0) : 0; + expected_r = (actual_r < 0) ? ~s32(0) : 0; + expected_g = (actual_g < 0) ? ~s32(0) : 0; + expected_b = (actual_b < 0) ? ~s32(0) : 0; + rgb.set(actual_a, actual_r, actual_g, actual_b); + rgb.cmplt_imm(0); + check_expected(); + expected_a = ~s32(0); + expected_r = ~s32(0); + expected_g = ~s32(0); + expected_b = ~s32(0); + rgb.set(actual_a, actual_r, actual_g, actual_b); + rgb.cmplt_imm(std::numeric_limits::max()); + check_expected(); + } + + // test immediate RGB less than comparison + SECTION("rgbaint_t::cmplt_imm_rgba immediate RGB less than comparison") + { + actual_a = random_i32_nolimit(); + actual_r = random_i32_nolimit(); + actual_g = random_i32_nolimit(); + actual_b = random_i32_nolimit(); + expected_a = 0; + expected_r = ~s32(0); + expected_g = 0; + expected_b = 0; + rgb.set(actual_a, actual_r, actual_g, actual_b); + rgb.cmplt_imm_rgba(std::numeric_limits::min(), std::numeric_limits::max(), actual_g, actual_b - 1); + check_expected(); + expected_a = ~s32(0); + expected_r = 0; + expected_g = ~s32(0); + expected_b = 0; + rgb.set(actual_a, actual_r, actual_g, actual_b); + rgb.cmplt_imm_rgba(actual_a + 1, std::numeric_limits::min(), std::numeric_limits::max(), actual_b); + check_expected(); + } +}