From 8c4766ab71eb89976056b0990715cbffbeadd130 Mon Sep 17 00:00:00 2001 From: Clint Banzhaf Date: Wed, 13 May 2026 22:52:57 +0200 Subject: [PATCH] addcarry: add support for larger result --- include/CppCore.Test/Math/Util.h | 24 ++++++++++++++++++++++++ include/CppCore/Math/Util.h | 18 +++++++++++++++++- src/CppCore.Test/Test.cpp | 1 + 3 files changed, 42 insertions(+), 1 deletion(-) diff --git a/include/CppCore.Test/Math/Util.h b/include/CppCore.Test/Math/Util.h index 5374c681..cc54929e 100644 --- a/include/CppCore.Test/Math/Util.h +++ b/include/CppCore.Test/Math/Util.h @@ -376,6 +376,29 @@ namespace CppCore { namespace Test { namespace Math return true; } + INLINE static bool addcarry() + { + uint8_t c; + uint64_t a1[1]; uint64_t b1[1]; uint64_t r1[1]; + uint64_t a2[2]; uint64_t b2[2]; uint64_t r2[2]; + uint64_t a3[3]; uint64_t b3[3]; uint64_t r3[3]; + uint64_t a4[4]; uint64_t b4[4]; uint64_t r4[4]; + + a2[0] = 0xFFFFFFFFFFFFFFFFULL; a2[1] = 0xFFFFFFFFFFFFFFFFULL; + b2[0] = 0x0000000000000001ULL; b2[1] = 0x0000000000000000ULL; + c = 0; CppCore::addcarry(a2, b2, r2, c); if (c != 0x01 || r2[0] != 0x0000000000000000ULL || r2[1] != 0x0000000000000000ULL) return false; + + a1[0] = 0xFFFFFFFFFFFFFFFFULL; + b2[0] = 0x0000000000000001ULL; b2[1] = 0xFF00000000000000ULL; + c = 0; CppCore::addcarry(a1, b2, r2, c); if (c != 0x00 || r2[0] != 0x0000000000000000ULL || r2[1] != 0xFF00000000000001ULL) return false; + + a2[0] = 0xFFFFFFFFFFFFFFFFULL; a2[1] = 0xFFFFFFFFFFFFFFFFULL; + b2[0] = 0x0000000000000001ULL; b2[1] = 0x0000000000000000ULL; + c = 0; CppCore::addcarry(a2, b2, r4, c); if (c != 0x00 || r4[0] != 0x0000000000000000ULL || r4[1] != 0x0000000000000000ULL || r4[2] != 0x0000000000000001ULL || r4[3] != 0x0000000000000000ULL) return false; + + return true; + } + INLINE static bool subborrow8() { uint8_t r; uint8_t c; @@ -1552,6 +1575,7 @@ namespace CppCore { namespace Test { namespace VS { namespace Math { TEST_METHOD(ADDCARRY16) { Assert::AreEqual(true, CppCore::Test::Math::Util::addcarry16()); } TEST_METHOD(ADDCARRY32) { Assert::AreEqual(true, CppCore::Test::Math::Util::addcarry32()); } TEST_METHOD(ADDCARRY64) { Assert::AreEqual(true, CppCore::Test::Math::Util::addcarry64()); } + TEST_METHOD(ADDCARRY) { Assert::AreEqual(true, CppCore::Test::Math::Util::addcarry()); } TEST_METHOD(SUBBORROW8) { Assert::AreEqual(true, CppCore::Test::Math::Util::subborrow8()); } TEST_METHOD(SUBBORROW16) { Assert::AreEqual(true, CppCore::Test::Math::Util::subborrow16()); } TEST_METHOD(SUBBORROW32) { Assert::AreEqual(true, CppCore::Test::Math::Util::subborrow32()); } diff --git a/include/CppCore/Math/Util.h b/include/CppCore/Math/Util.h index d6ee6b06..e87123ad 100644 --- a/include/CppCore/Math/Util.h +++ b/include/CppCore/Math/Util.h @@ -740,13 +740,15 @@ namespace CppCore static_assert(sizeof(UINT3) % 4 == 0); constexpr size_t MAXSIZE = MAX(sizeof(UINT1), sizeof(UINT2)); constexpr size_t MINSIZE = MIN(sizeof(UINT1), sizeof(UINT2)); - static_assert(sizeof(UINT3) == MAXSIZE); + static_assert(sizeof(UINT3) >= MAXSIZE); #if defined(CPPCORE_CPU_64BIT) if constexpr (sizeof(UINT1) % 8 == 0 && sizeof(UINT2) % 8 == 0 && sizeof(UINT3) % 8 == 0) { constexpr size_t NUINT1 = sizeof(UINT1) / 8; constexpr size_t NUINT2 = sizeof(UINT2) / 8; + constexpr size_t NUINT3 = sizeof(UINT3) / 8; constexpr size_t NMIN = MINSIZE / 8; + constexpr size_t NMAX = MAXSIZE / 8; uint64_t* px = (uint64_t*)&x; uint64_t* py = (uint64_t*)&y; uint64_t* pz = (uint64_t*)&z; @@ -758,6 +760,12 @@ namespace CppCore if constexpr (sizeof(UINT1) < sizeof(UINT2)) for (size_t i = NMIN; i < NUINT2; i++) CppCore::addcarry64(0ULL, py[i], pz[i], c); + if constexpr (sizeof(UINT3) > MAXSIZE) + { + pz[NMAX] = c; c = 0; + for (size_t i = NMAX+1; i < NUINT3; i++) + pz[i] = 0ULL; + } } else if #else @@ -767,7 +775,9 @@ namespace CppCore { constexpr size_t NUINT1 = sizeof(UINT1) / 4; constexpr size_t NUINT2 = sizeof(UINT2) / 4; + constexpr size_t NUINT3 = sizeof(UINT3) / 4; constexpr size_t NMIN = MINSIZE / 4; + constexpr size_t NMAX = MAXSIZE / 4; uint32_t* px = (uint32_t*)&x; uint32_t* py = (uint32_t*)&y; uint32_t* pz = (uint32_t*)&z; @@ -779,6 +789,12 @@ namespace CppCore if constexpr (sizeof(UINT1) < sizeof(UINT2)) for (size_t i = NMIN; i < NUINT2; i++) CppCore::addcarry32(0U, py[i], pz[i], c); + if constexpr (sizeof(UINT3) > MAXSIZE) + { + pz[NMAX] = c; c = 0; + for (size_t i = NMAX+1; i < NUINT3; i++) + pz[i] = 0U; + } } else if constexpr (sizeof(UINT1) < sizeof(size_t)) { CppCore::addcarry((size_t)x, y, z, c); } else if constexpr (sizeof(UINT2) < sizeof(size_t)) { CppCore::addcarry(x, (size_t)y, z, c); } diff --git a/src/CppCore.Test/Test.cpp b/src/CppCore.Test/Test.cpp index 2d3c88e7..b2f23f39 100644 --- a/src/CppCore.Test/Test.cpp +++ b/src/CppCore.Test/Test.cpp @@ -359,6 +359,7 @@ int main() TEST(CppCore::Test::Math::Util::addcarry16, "addcarry16: ", std::endl); TEST(CppCore::Test::Math::Util::addcarry32, "addcarry32: ", std::endl); TEST(CppCore::Test::Math::Util::addcarry64, "addcarry64: ", std::endl); + TEST(CppCore::Test::Math::Util::addcarry, "addcarry: ", std::endl); TEST(CppCore::Test::Math::Util::subborrow8, "subborrow8: ", std::endl); TEST(CppCore::Test::Math::Util::subborrow16, "subborrow16: ", std::endl); TEST(CppCore::Test::Math::Util::subborrow32, "subborrow32: ", std::endl);