From e74654800d21e4daf0ed3069f21ae33e022796dd Mon Sep 17 00:00:00 2001 From: fallenoak Date: Sun, 29 Jan 2023 22:59:28 -0600 Subject: [PATCH] feat(big): add Mul --- storm/big/Ops.cpp | 13 ++++++++++ storm/big/Ops.hpp | 2 ++ test/Big.cpp | 60 +++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 75 insertions(+) diff --git a/storm/big/Ops.cpp b/storm/big/Ops.cpp index 5a3a36f..f6411ee 100644 --- a/storm/big/Ops.cpp +++ b/storm/big/Ops.cpp @@ -49,6 +49,19 @@ uint64_t MakeLarge(uint32_t low, uint32_t high) { return low + (static_cast(high) << 32); } +void Mul(BigBuffer& a, const BigBuffer& b, uint64_t c) { + // TODO assertion c <= SMALL_BOUND + + uint64_t carry = 0; + uint32_t i = 0; + for (i = 0; carry || b.IsUsed(i); i++) { + carry += b[i] * c; + a[i] = ExtractLowPart(carry); + } + + a.SetCount(i); +} + void ToBinaryAppend(TSGrowableArray& output, const BigBuffer& buffer) { for (uint32_t i = 0; i < buffer.Count() * 4; i++) { auto byte = buffer[i / 4] >> (8 * (i & 3)); diff --git a/storm/big/Ops.hpp b/storm/big/Ops.hpp index 6db197b..30f1f4b 100644 --- a/storm/big/Ops.hpp +++ b/storm/big/Ops.hpp @@ -16,6 +16,8 @@ void FromUnsigned(BigBuffer& buffer, uint32_t value); uint64_t MakeLarge(uint32_t low, uint32_t high); +void Mul(BigBuffer& a, const BigBuffer& b, uint64_t c); + void ToBinary(TSGrowableArray& output, const BigBuffer& buffer); #endif diff --git a/test/Big.cpp b/test/Big.cpp index 637ea1c..9d354a8 100644 --- a/test/Big.cpp +++ b/test/Big.cpp @@ -54,6 +54,66 @@ TEST_CASE("ExtractLowPartSx", "[big]") { } } +TEST_CASE("Mul", "[big]") { + SECTION("multiplies 0 and 1") { + BigData* a; + SBigNew(&a); + + BigData* b; + SBigNew(&b); + SBigFromUnsigned(b, 0); + + uint64_t c = 1; + + Mul(a->Primary(), b->Primary(), c); + + CHECK(a->Primary().Count() == 1); + CHECK(a->Primary()[0] == 0); + + SBigDel(a); + SBigDel(b); + } + + SECTION("multiplies 2 and 4") { + BigData* a; + SBigNew(&a); + + BigData* b; + SBigNew(&b); + SBigFromUnsigned(b, 2); + + uint64_t c = 4; + + Mul(a->Primary(), b->Primary(), c); + + CHECK(a->Primary().Count() == 1); + CHECK(a->Primary()[0] == 8); + + SBigDel(a); + SBigDel(b); + } + + SECTION("multiplies 0xFFFFFFFF and 0x100") { + BigData* a; + SBigNew(&a); + + BigData* b; + SBigNew(&b); + SBigFromUnsigned(b, 0xFFFFFFFF); + + uint64_t c = 0x100; + + Mul(a->Primary(), b->Primary(), c); + + CHECK(a->Primary().Count() == 2); + CHECK(a->Primary()[0] == 0xFFFFFF00); + CHECK(a->Primary()[1] == 0xFF); + + SBigDel(a); + SBigDel(b); + } +} + TEST_CASE("MakeLarge", "[big]") { SECTION("creates uint64_t out of 0xAABBCCDD and 0x11223344") { uint64_t value = MakeLarge(0xAABBCCDD, 0x11223344);