From 5d875631a6905f22a35e38e2e8129406c486be4d Mon Sep 17 00:00:00 2001 From: fallenoak Date: Wed, 1 Feb 2023 21:29:16 -0600 Subject: [PATCH] feat(big): add SBigSub --- storm/Big.cpp | 4 ++ storm/Big.hpp | 2 + storm/big/Ops.cpp | 13 +++++ storm/big/Ops.hpp | 2 + test/Big.cpp | 125 ++++++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 146 insertions(+) diff --git a/storm/Big.cpp b/storm/Big.cpp index 142c861..c3ebc99 100644 --- a/storm/Big.cpp +++ b/storm/Big.cpp @@ -28,6 +28,10 @@ void SBigMul(BigData* a, BigData* b, BigData* c) { Mul(a->Primary(), b->Primary(), c->Primary(), a->Stack()); } +void SBigSub(BigData* a, BigData* b, BigData* c) { + Sub(a->Primary(), b->Primary(), c->Primary()); +} + void SBigToBinaryBuffer(BigData* num, uint8_t* data, uint32_t maxBytes, uint32_t* bytes) { auto& output = num->Output(); ToBinary(output, num->Primary()); diff --git a/storm/Big.hpp b/storm/Big.hpp index e73070d..9ab6e1d 100644 --- a/storm/Big.hpp +++ b/storm/Big.hpp @@ -16,6 +16,8 @@ void SBigMul(BigData* a, BigData* b, BigData* c); void SBigNew(BigData** num); +void SBigSub(BigData* a, BigData* b, BigData* c); + void SBigToBinaryBuffer(BigData* num, uint8_t* data, uint32_t maxBytes, uint32_t* bytes); #endif diff --git a/storm/big/Ops.cpp b/storm/big/Ops.cpp index 4a4fe20..01418a4 100644 --- a/storm/big/Ops.cpp +++ b/storm/big/Ops.cpp @@ -141,6 +141,19 @@ void SetZero(BigBuffer& buffer) { buffer.Clear(); } +void Sub(BigBuffer& a, const BigBuffer& b, const BigBuffer& c) { + uint64_t borrow = 0; + uint32_t i = 0; + for (i = 0; b.IsUsed(i) || c.IsUsed(i); i++) { + borrow += b[i] - static_cast(c[i]); + a[i] = ExtractLowPartSx(borrow); + } + + a.SetCount(i); + + STORM_ASSERT(!borrow); +} + 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 bedf209..ca8d683 100644 --- a/storm/big/Ops.hpp +++ b/storm/big/Ops.hpp @@ -31,6 +31,8 @@ void SetOne(BigBuffer& buffer); void SetZero(BigBuffer& buffer); +void Sub(BigBuffer& a, const BigBuffer& b, const BigBuffer& c); + void ToBinary(TSGrowableArray& output, const BigBuffer& buffer); #endif diff --git a/test/Big.cpp b/test/Big.cpp index 20112d7..0b5e6ba 100644 --- a/test/Big.cpp +++ b/test/Big.cpp @@ -583,6 +583,31 @@ TEST_CASE("SBigMul", "[big]") { } } +TEST_CASE("SBigSub", "[big]") { + SECTION("subtracts 1 from 2") { + BigData* a; + SBigNew(&a); + + BigData* b; + SBigNew(&b); + SBigFromUnsigned(b, 2); + + BigData* c; + SBigNew(&c); + SBigFromUnsigned(c, 1); + + SBigSub(a, b, c); + + a->Primary().Trim(); + + CHECK(a->Primary().Count() == 1); + CHECK(a->Primary()[0] == 1); + + SBigDel(a); + SBigDel(b); + } +} + TEST_CASE("SBigToBinaryBuffer", "[big]") { SECTION("returns expected buffer for bigdata representing 0") { BigData* num; @@ -663,3 +688,103 @@ TEST_CASE("SetZero", "[big]") { SBigDel(num); } } + +TEST_CASE("Sub", "[big]") { + SECTION("subtracts 0 from 1") { + BigData* a; + SBigNew(&a); + + BigData* b; + SBigNew(&b); + SBigFromUnsigned(b, 1); + + BigData* c; + SBigNew(&c); + SBigFromUnsigned(c, 0); + + Sub(a->Primary(), b->Primary(), c->Primary()); + + a->Primary().Trim(); + + CHECK(a->Primary().Count() == 1); + CHECK(a->Primary()[0] == 1); + + SBigDel(a); + SBigDel(b); + } + + SECTION("subtracts 1 from 2") { + BigData* a; + SBigNew(&a); + + BigData* b; + SBigNew(&b); + SBigFromUnsigned(b, 2); + + BigData* c; + SBigNew(&c); + SBigFromUnsigned(c, 1); + + Sub(a->Primary(), b->Primary(), c->Primary()); + + a->Primary().Trim(); + + CHECK(a->Primary().Count() == 1); + CHECK(a->Primary()[0] == 1); + + SBigDel(a); + SBigDel(b); + } + + SECTION("subtracts 0x1111111111111111 from 0x9999999999999999") { + BigData* a; + SBigNew(&a); + + BigData* b; + SBigNew(&b); + uint64_t b_ = 0x9999999999999999; + SBigFromBinary(b, reinterpret_cast(&b_), sizeof(b_)); + + BigData* c; + SBigNew(&c); + uint64_t c_ = 0x1111111111111111; + SBigFromBinary(c, reinterpret_cast(&c_), sizeof(c_)); + + Sub(a->Primary(), b->Primary(), c->Primary()); + + a->Primary().Trim(); + + CHECK(a->Primary().Count() == 2); + CHECK(a->Primary()[0] == 0x88888888); + CHECK(a->Primary()[1] == 0x88888888); + + SBigDel(a); + SBigDel(b); + } + + SECTION("subtracts 0x123456789ABCDEF0 from 0xFEDCBA9876543210") { + BigData* a; + SBigNew(&a); + + BigData* b; + SBigNew(&b); + uint64_t b_ = 0xFEDCBA9876543210; + SBigFromBinary(b, reinterpret_cast(&b_), sizeof(b_)); + + BigData* c; + SBigNew(&c); + uint64_t c_ = 0x123456789ABCDEF0; + SBigFromBinary(c, reinterpret_cast(&c_), sizeof(c_)); + + Sub(a->Primary(), b->Primary(), c->Primary()); + + a->Primary().Trim(); + + CHECK(a->Primary().Count() == 2); + CHECK(a->Primary()[0] == 0xDB975320); + CHECK(a->Primary()[1] == 0xECA8641F); + + SBigDel(a); + SBigDel(b); + } +}