From d3fd03d67e1314cc87af04e3d5dd5a256306c2b2 Mon Sep 17 00:00:00 2001 From: fallenoak Date: Mon, 23 Jan 2023 22:10:24 -0600 Subject: [PATCH] feat(big): add 64-bit-centric ops --- storm/CMakeLists.txt | 1 + storm/big/Ops.cpp | 24 ++++++++++++++++ storm/big/Ops.hpp | 12 ++++++++ test/Big.cpp | 68 ++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 105 insertions(+) create mode 100644 storm/big/Ops.cpp create mode 100644 storm/big/Ops.hpp create mode 100644 test/Big.cpp diff --git a/storm/CMakeLists.txt b/storm/CMakeLists.txt index 92ef8c9..c204bee 100644 --- a/storm/CMakeLists.txt +++ b/storm/CMakeLists.txt @@ -3,6 +3,7 @@ check_cxx_compiler_flag(-Wno-invalid-offsetof HAS_NO_INVALID_OFFSETOF) file(GLOB STORM_SOURCES "*.cpp" + "big/*.cpp" "hash/*.cpp" "queue/*.cpp" "string/*.cpp" diff --git a/storm/big/Ops.cpp b/storm/big/Ops.cpp new file mode 100644 index 0000000..d2200d4 --- /dev/null +++ b/storm/big/Ops.cpp @@ -0,0 +1,24 @@ +#include "storm/big/Ops.hpp" + +uint32_t ExtractLowPart(uint64_t& value) { + auto low = static_cast(value); + value >>= 32; + + return low; +} + +uint32_t ExtractLowPartSx(uint64_t& value) { + auto low = static_cast(value); + value >>= 32; + + if (value >= 0x80000000) { + reinterpret_cast(&value)[0] = value; + reinterpret_cast(&value)[1] = -1; + } + + return low; +} + +uint64_t MakeLarge(uint32_t low, uint32_t high) { + return low + (static_cast(high) << 32); +} diff --git a/storm/big/Ops.hpp b/storm/big/Ops.hpp new file mode 100644 index 0000000..fb0b9e5 --- /dev/null +++ b/storm/big/Ops.hpp @@ -0,0 +1,12 @@ +#ifndef STORM_BIG_OPS_HPP +#define STORM_BIG_OPS_HPP + +#include + +uint32_t ExtractLowPart(uint64_t& value); + +uint32_t ExtractLowPartSx(uint64_t& value); + +uint64_t MakeLarge(uint32_t low, uint32_t high); + +#endif diff --git a/test/Big.cpp b/test/Big.cpp new file mode 100644 index 0000000..702a5d9 --- /dev/null +++ b/test/Big.cpp @@ -0,0 +1,68 @@ +#include "storm/big/Ops.hpp" +#include "test/Test.hpp" + +TEST_CASE("ExtractLowPart", "[big]") { + SECTION("extracts low part of 0") { + uint64_t value = 0; + auto low = ExtractLowPart(value); + + REQUIRE(low == 0); + REQUIRE(value == 0); + } + + SECTION("extracts low part of 0x12345678") { + uint64_t value = 0x12345678; + auto low = ExtractLowPart(value); + + REQUIRE(low == 0x12345678); + REQUIRE(value == 0); + } + + SECTION("extracts low part of 0xAAAABBBBCCCCDDDD") { + uint64_t value = 0xAAAABBBBCCCCDDDD; + auto low = ExtractLowPart(value); + + REQUIRE(low == 0xCCCCDDDD); + REQUIRE(value == 0xAAAABBBB); + } +} + +TEST_CASE("ExtractLowPartSx", "[big]") { + SECTION("extracts low part of 0") { + uint64_t value = 0; + auto low = ExtractLowPartSx(value); + + REQUIRE(low == 0); + REQUIRE(value == 0); + } + + SECTION("extracts low part of 0x12345678") { + uint64_t value = 0x12345678; + auto low = ExtractLowPartSx(value); + + REQUIRE(low == 0x12345678); + REQUIRE(value == 0); + } + + SECTION("extracts low part of 0xAAAABBBBCCCCDDDD") { + uint64_t value = 0xAAAABBBBCCCCDDDD; + auto low = ExtractLowPartSx(value); + + REQUIRE(low == 0xCCCCDDDD); + REQUIRE(value == 0xFFFFFFFFAAAABBBB); + } +} + +TEST_CASE("MakeLarge", "[big]") { + SECTION("creates uint64_t out of 0xAABBCCDD and 0x11223344") { + uint64_t value = MakeLarge(0xAABBCCDD, 0x11223344); + + REQUIRE(value == 0x11223344AABBCCDD); + } + + SECTION("creates uint64_t out of 0 and 0x11223344") { + uint64_t value = MakeLarge(0x00000000, 0x11223344); + + REQUIRE(value == 0x1122334400000000); + } +}