From 09d2481be9803882c114d34cf45d5e65e6b6e4fb Mon Sep 17 00:00:00 2001 From: fallenoak Date: Sun, 5 Feb 2023 16:36:38 -0600 Subject: [PATCH] feat(big): add SBigPowMod --- storm/Big.cpp | 4 ++ storm/Big.hpp | 2 + storm/big/Ops.cpp | 57 +++++++++++++++ storm/big/Ops.hpp | 2 + test/Big.cpp | 179 ++++++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 244 insertions(+) diff --git a/storm/Big.cpp b/storm/Big.cpp index 2930de2..11f25e4 100644 --- a/storm/Big.cpp +++ b/storm/Big.cpp @@ -58,6 +58,10 @@ void SBigMul(BigData* a, BigData* b, BigData* c) { Mul(a->Primary(), b->Primary(), c->Primary(), a->Stack()); } +void SBigPowMod(BigData* a, BigData* b, BigData* c, BigData* d) { + PowMod(a->Primary(), b->Primary(), c->Primary(), d->Primary(), a->Stack()); +} + void SBigShl(BigData* a, BigData* b, uint32_t shift) { Shl(a->Primary(), b->Primary(), shift); } diff --git a/storm/Big.hpp b/storm/Big.hpp index 2346dfd..aa2f9fb 100644 --- a/storm/Big.hpp +++ b/storm/Big.hpp @@ -22,6 +22,8 @@ void SBigMul(BigData* a, BigData* b, BigData* c); void SBigNew(BigData** num); +void SBigPowMod(BigData* a, BigData* b, BigData* c, BigData* d); + void SBigShl(BigData* a, BigData* b, uint32_t shift); void SBigShr(BigData* a, BigData* b, uint32_t shift); diff --git a/storm/big/Ops.cpp b/storm/big/Ops.cpp index 3bf46cc..d1407ec 100644 --- a/storm/big/Ops.cpp +++ b/storm/big/Ops.cpp @@ -241,6 +241,63 @@ void MulMod(BigBuffer& a, const BigBuffer& b, const BigBuffer& c, const BigBuffe stack.Free(allocCount); } +void PowMod(BigBuffer& a, const BigBuffer& b, const BigBuffer& c, const BigBuffer& d, BigStack& stack) { + c.Trim(); + + if (c.Count() == 0) { + SetOne(a); + return; + } + + uint32_t allocCount = 0; + auto& temp = stack.Alloc(&allocCount); + auto& b2 = stack.Alloc(&allocCount); + auto& b3 = stack.Alloc(&allocCount); + + auto& aa = stack.MakeDistinct(a, &a == &b || &a == &c || &a == &d); + + MulMod(b2, b, b, d, stack); + MulMod(b3, b2, b, d, stack); + + const BigBuffer* bPower[3]; + bPower[0] = &b; + bPower[1] = &b2; + bPower[2] = &b3; + + SetOne(aa); + + for (uint32_t i = c.Count() - 1; i + 1 > 0; i--) { + auto v12 = c[i]; + uint32_t v23 = 32; + + if (i == c.Count() - 1 && !(v12 & 0xC0000000)) { + do { + v12 *= 4; + v23 -= 2; + } while (!(v12 & 0xC0000000)); + } + + if (v23) { + for (uint32_t j = ((v23 - 1) >> 1) + 1; j > 0; j--) { + Square(aa, aa, stack); + Div(temp, aa, aa, d, stack); + Square(aa, aa, stack); + Div(temp, aa, aa, d, stack); + + if (v12 >> 30) { + auto& power = *bPower[(v12 >> 30) - 1]; + MulMod(aa, aa, power, d, stack); + } + + v12 *= 4; + } + } + } + + stack.UnmakeDistinct(a, aa); + stack.Free(allocCount); +} + void SetOne(BigBuffer& buffer) { buffer.SetCount(1); buffer[0] = 1; diff --git a/storm/big/Ops.hpp b/storm/big/Ops.hpp index 3b01e87..d2b1b11 100644 --- a/storm/big/Ops.hpp +++ b/storm/big/Ops.hpp @@ -37,6 +37,8 @@ void Mul(BigBuffer& a, const BigBuffer& b, const BigBuffer& c, BigStack& stack); void MulMod(BigBuffer& a, const BigBuffer& b, const BigBuffer& c, const BigBuffer& d, BigStack& stack); +void PowMod(BigBuffer& a, const BigBuffer& b, const BigBuffer& c, const BigBuffer& d, BigStack& stack); + void SetOne(BigBuffer& buffer); void SetZero(BigBuffer& buffer); diff --git a/test/Big.cpp b/test/Big.cpp index 66d509f..31fc69e 100644 --- a/test/Big.cpp +++ b/test/Big.cpp @@ -717,6 +717,154 @@ TEST_CASE("MakeLarge", "[big]") { } } +TEST_CASE("PowMod", "[big]") { + SECTION("takes 0 to the 0th power and mods the result by 1") { + BigData* a; + SBigNew(&a); + + BigData* b; + SBigNew(&b); + SBigFromUnsigned(b, 0); + + BigData* c; + SBigNew(&c); + SBigFromUnsigned(c, 0); + + BigData* d; + SBigNew(&d); + SBigFromUnsigned(d, 1); + + PowMod(a->Primary(), b->Primary(), c->Primary(), d->Primary(), a->Stack()); + + a->Primary().Trim(); + + CHECK(a->Primary().Count() == 1); + CHECK(a->Primary()[0] == 1); + + SBigDel(a); + SBigDel(b); + SBigDel(c); + SBigDel(d); + } + + SECTION("takes 2 to the 0th power and mods the result by 7") { + BigData* a; + SBigNew(&a); + + BigData* b; + SBigNew(&b); + SBigFromUnsigned(b, 2); + + BigData* c; + SBigNew(&c); + SBigFromUnsigned(c, 0); + + BigData* d; + SBigNew(&d); + SBigFromUnsigned(d, 7); + + PowMod(a->Primary(), b->Primary(), c->Primary(), d->Primary(), a->Stack()); + + a->Primary().Trim(); + + CHECK(a->Primary().Count() == 1); + CHECK(a->Primary()[0] == 1); + + SBigDel(a); + SBigDel(b); + SBigDel(c); + SBigDel(d); + } + + SECTION("takes 2 to the 4th power and mods the result by 7") { + BigData* a; + SBigNew(&a); + + BigData* b; + SBigNew(&b); + SBigFromUnsigned(b, 2); + + BigData* c; + SBigNew(&c); + SBigFromUnsigned(c, 4); + + BigData* d; + SBigNew(&d); + SBigFromUnsigned(d, 7); + + PowMod(a->Primary(), b->Primary(), c->Primary(), d->Primary(), a->Stack()); + + a->Primary().Trim(); + + CHECK(a->Primary().Count() == 1); + CHECK(a->Primary()[0] == 2); + + SBigDel(a); + SBigDel(b); + SBigDel(c); + SBigDel(d); + } + + SECTION("takes 256 to the 8th power and mods the result by 999") { + BigData* a; + SBigNew(&a); + + BigData* b; + SBigNew(&b); + SBigFromUnsigned(b, 256); + + BigData* c; + SBigNew(&c); + SBigFromUnsigned(c, 8); + + BigData* d; + SBigNew(&d); + SBigFromUnsigned(d, 999); + + PowMod(a->Primary(), b->Primary(), c->Primary(), d->Primary(), a->Stack()); + + a->Primary().Trim(); + + CHECK(a->Primary().Count() == 1); + CHECK(a->Primary()[0] == 160); + + SBigDel(a); + SBigDel(b); + SBigDel(c); + SBigDel(d); + } + + SECTION("takes 0x100000000 to the 2nd power and mods the result by 0xAAAAFFFF") { + BigData* a; + SBigNew(&a); + + BigData* b; + SBigNew(&b); + uint64_t b_ = 0x100000000; + SBigFromBinary(b, reinterpret_cast(&b_), sizeof(b_)); + + BigData* c; + SBigNew(&c); + SBigFromUnsigned(c, 2); + + BigData* d; + SBigNew(&d); + SBigFromUnsigned(d, 0xAAAAFFFF); + + PowMod(a->Primary(), b->Primary(), c->Primary(), d->Primary(), a->Stack()); + + a->Primary().Trim(); + + CHECK(a->Primary().Count() == 1); + CHECK(a->Primary()[0] == 0x6AA94002); + + SBigDel(a); + SBigDel(b); + SBigDel(c); + SBigDel(d); + } +} + TEST_CASE("SBigAdd", "[big]") { SECTION("adds 0 and 1") { BigData* a; @@ -1135,6 +1283,37 @@ TEST_CASE("SBigMul", "[big]") { } } +TEST_CASE("SBigPowMod", "[big]") { + SECTION("takes 256 to the 8th power and mods the result by 999") { + BigData* a; + SBigNew(&a); + + BigData* b; + SBigNew(&b); + SBigFromUnsigned(b, 256); + + BigData* c; + SBigNew(&c); + SBigFromUnsigned(c, 8); + + BigData* d; + SBigNew(&d); + SBigFromUnsigned(d, 999); + + SBigPowMod(a, b, c, d); + + a->Primary().Trim(); + + CHECK(a->Primary().Count() == 1); + CHECK(a->Primary()[0] == 160); + + SBigDel(a); + SBigDel(b); + SBigDel(c); + SBigDel(d); + } +} + TEST_CASE("SBigShl", "[big]") { SECTION("shifts 256 left 7 bits") { BigData* a;