mantissa_util_tests.cpp
1 /* This file is part of the dynarmic project. 2 * Copyright (c) 2018 MerryMage 3 * SPDX-License-Identifier: 0BSD 4 */ 5 6 #include <tuple> 7 #include <vector> 8 9 #include <catch2/catch_test_macros.hpp> 10 #include <mcl/stdint.hpp> 11 12 #include "../rand_int.h" 13 #include "dynarmic/common/fp/mantissa_util.h" 14 #include "dynarmic/common/safe_ops.h" 15 16 using namespace Dynarmic; 17 using namespace Dynarmic::FP; 18 19 TEST_CASE("ResidualErrorOnRightShift", "[fp]") { 20 const std::vector<std::tuple<u32, int, ResidualError>> test_cases{ 21 {0x00000001, 1, ResidualError::Half}, 22 {0x00000002, 1, ResidualError::Zero}, 23 {0x00000001, 2, ResidualError::LessThanHalf}, 24 {0x00000002, 2, ResidualError::Half}, 25 {0x00000003, 2, ResidualError::GreaterThanHalf}, 26 {0x00000004, 2, ResidualError::Zero}, 27 {0x00000005, 2, ResidualError::LessThanHalf}, 28 {0x00000006, 2, ResidualError::Half}, 29 {0x00000007, 2, ResidualError::GreaterThanHalf}, 30 }; 31 32 for (auto [mantissa, shift, expected_result] : test_cases) { 33 const ResidualError result = ResidualErrorOnRightShift(mantissa, shift); 34 REQUIRE(result == expected_result); 35 } 36 } 37 38 TEST_CASE("ResidualErrorOnRightShift Randomized", "[fp]") { 39 for (size_t test = 0; test < 100000; test++) { 40 const u64 mantissa = mcl::bit::sign_extend<32, u64>(RandInt<u32>(0, 0xFFFFFFFF)); 41 const int shift = RandInt<int>(-60, 60); 42 43 const ResidualError result = ResidualErrorOnRightShift(mantissa, shift); 44 45 const u64 calculated_error = Safe::ArithmeticShiftRightDouble(mantissa, u64(0), shift); 46 const ResidualError expected_result = [&] { 47 constexpr u64 half_error = 0x8000'0000'0000'0000ull; 48 if (calculated_error == 0) { 49 return ResidualError::Zero; 50 } 51 if (calculated_error < half_error) { 52 return ResidualError::LessThanHalf; 53 } 54 if (calculated_error == half_error) { 55 return ResidualError::Half; 56 } 57 return ResidualError::GreaterThanHalf; 58 }(); 59 60 INFO(std::hex << "mantissa " << mantissa << " shift " << shift << " calculated_error " << calculated_error); 61 REQUIRE(result == expected_result); 62 } 63 }