Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 18 additions & 0 deletions src/arith_uint256.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@

#include <arith_uint256.h>

#include <limits>
#include <uint256.h>
#include <crypto/common.h>

Expand Down Expand Up @@ -72,6 +73,23 @@ base_uint<BITS>& base_uint<BITS>::operator*=(const base_uint& b)
return *this;
}

template <unsigned int BITS>
base_uint<BITS>& base_uint<BITS>::operator/=(uint64_t b32)

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: is it a typo?

Suggested change
base_uint<BITS>& base_uint<BITS>::operator/=(uint64_t b32)
base_uint<BITS>& base_uint<BITS>::operator/=(uint64_t b64)

same in other places

@knst knst Jun 11, 2026

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

not really a typo, because it's supposed optimized for b32 only. If you think that's confusing I'd rename it.

It is supposed to be uint32_t b32 but compiler won't say a word if that's called with uint64_t, so, I keep it mixed.

{
if (b32 == 0)
throw uint_error("Division by zero");
if (b32 > std::numeric_limits<uint32_t>::max()) {
return *this /= base_uint(b32);
}
uint64_t rem = 0;
for (int i = WIDTH - 1; i >= 0; --i) {
uint64_t cur = (rem << 32) | pn[i];
pn[i] = static_cast<uint32_t>(cur / b32);
rem = cur % b32;
}
return *this;
}

template <unsigned int BITS>
base_uint<BITS>& base_uint<BITS>::operator/=(const base_uint& b)
{
Expand Down
2 changes: 2 additions & 0 deletions src/arith_uint256.h
Original file line number Diff line number Diff line change
Expand Up @@ -158,6 +158,7 @@ class base_uint

base_uint& operator*=(uint32_t b32);
base_uint& operator*=(const base_uint& b);
base_uint& operator/=(uint64_t b32);
base_uint& operator/=(const base_uint& b);

base_uint& operator++()
Expand Down Expand Up @@ -207,6 +208,7 @@ class base_uint
friend inline base_uint operator>>(const base_uint& a, int shift) { return base_uint(a) >>= shift; }
friend inline base_uint operator<<(const base_uint& a, int shift) { return base_uint(a) <<= shift; }
friend inline base_uint operator*(const base_uint& a, uint32_t b) { return base_uint(a) *= b; }
friend inline base_uint operator/(const base_uint& a, uint64_t b) { return base_uint(a) /= b; }
friend inline bool operator==(const base_uint& a, const base_uint& b) { return memcmp(a.pn, b.pn, sizeof(a.pn)) == 0; }
friend inline bool operator!=(const base_uint& a, const base_uint& b) { return memcmp(a.pn, b.pn, sizeof(a.pn)) != 0; }
friend inline bool operator>(const base_uint& a, const base_uint& b) { return a.CompareTo(b) > 0; }
Expand Down
13 changes: 13 additions & 0 deletions src/test/arith_uint256_tests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -361,6 +361,19 @@ BOOST_AUTO_TEST_CASE( divide )
BOOST_CHECK(R2L / MaxL == ZeroL);
BOOST_CHECK(MaxL / R2L == 1);
BOOST_CHECK_THROW(R2L / ZeroL, uint_error);

// The integer-divisor overload must be bit-identical to dividing by the same
// value widened to arith_uint256, for both the fast word-wise path
// (<= uint32 max) and the arith_uint256 fallback above it.
for (uint64_t d : {uint64_t{1}, uint64_t{2}, uint64_t{24}, uint64_t{3600},
uint64_t{std::numeric_limits<uint32_t>::max()},
uint64_t{std::numeric_limits<uint32_t>::max()} + 1,
uint64_t{0xFEDCBA9876543210}}) {
BOOST_CHECK(R1L / d == R1L / arith_uint256(d));
BOOST_CHECK(R2L / d == R2L / arith_uint256(d));
BOOST_CHECK(MaxL / d == MaxL / arith_uint256(d));
}
BOOST_CHECK_THROW(R1L / uint64_t{0}, uint_error);
}


Expand Down
Loading