Skip to content
Merged
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
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ template <class Params_> struct alignas(32) field {
}

constexpr field(const uint128_t& input) noexcept
: field(uint256_t::from_uint128(input))
: field(static_cast<uint256_t>(input))
{}

// NOLINTNEXTLINE (unsigned long is platform dependent, which we want in this case)
Expand Down
25 changes: 17 additions & 8 deletions barretenberg/cpp/src/barretenberg/numeric/uint256/uint256.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -36,20 +36,34 @@ class alignas(32) uint256_t {
#define WASM_NUM_LIMBS 9
#define WASM_LIMB_BITS 29
#endif
constexpr uint256_t(const uint64_t a = 0) noexcept
: data{ a, 0, 0, 0 }
constexpr uint256_t() noexcept
: data{ 0, 0, 0, 0 }
{}

// Template constructor for integral types to avoid ambiguity
// This provides an exact match for int, unsigned int, etc., avoiding conversion ambiguity
// Only accepts integral types that fit in uint64_t to prevent silent truncation
// Note: Accepts both signed and unsigned to handle integer literals (which are signed in C++)
template <std::integral T>
requires(!std::same_as<std::remove_cv_t<T>, bool> && sizeof(T) <= sizeof(uint64_t))
constexpr uint256_t(T value) noexcept
: data{ static_cast<uint64_t>(value), 0, 0, 0 }
{}

constexpr uint256_t(const uint64_t a, const uint64_t b, const uint64_t c, const uint64_t d) noexcept
: data{ a, b, c, d }
{}

constexpr uint256_t(const uint128_t& a) noexcept
: data{ static_cast<uint64_t>(a), static_cast<uint64_t>(a >> 64), 0, 0 }
{}

constexpr uint256_t(const uint256_t& other) noexcept
: data{ other.data[0], other.data[1], other.data[2], other.data[3] }
{}
constexpr uint256_t(uint256_t&& other) noexcept = default;

explicit constexpr uint256_t(std::string input) noexcept
explicit constexpr uint256_t(const std::string& input) noexcept
{
/* Quick and dirty conversion from a single character to its hex equivelent */
constexpr auto HexCharToInt = [](uint8_t Input) {
Expand Down Expand Up @@ -91,11 +105,6 @@ class alignas(32) uint256_t {
data[3] = limbs[0];
}

static constexpr uint256_t from_uint128(const uint128_t a) noexcept
{
return { static_cast<uint64_t>(a), static_cast<uint64_t>(a >> 64), 0, 0 };
}

constexpr uint256_t& operator=(const uint256_t& other) noexcept = default;
constexpr uint256_t& operator=(uint256_t&& other) noexcept = default;
constexpr ~uint256_t() noexcept = default;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -235,8 +235,8 @@ TEST(FieldGreaterThanConstrainingTest, NegativeManipulatedComparisonsWithP)
check_relation<ff_gt>(trace);

auto p_limbs = simulation::decompose_256(FF::modulus);
uint256_t p_lo = uint256_t::from_uint128(p_limbs.lo);
uint256_t p_hi = uint256_t::from_uint128(p_limbs.hi);
uint256_t p_lo = p_limbs.lo;
uint256_t p_hi = p_limbs.hi;

// Manipulate the decomposition in a way that passes the decomposition check due to overflow
trace.set(Column::ff_gt_a_lo, 1, p_lo);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ TEST(RangeCheckConstrainingTest, NegativeIsLteMutuallyExclusive)
TEST(RangeCheckConstrainingTest, CheckRecomposition)
{
uint128_t value = 0x3FFFFFFFD;
uint256_t value_u256 = uint256_t::from_uint128(value);
uint256_t value_u256 = value;

uint16_t u16_r0 = 0xFFFD; // value & 0xFFFF;
uint16_t u16_r1 = 0xFFFF; // (value >> 16) & 0xFFFF;
Expand All @@ -71,7 +71,7 @@ TEST(RangeCheckConstrainingTest, NegativeCheckRecomposition)
{
uint128_t value = 0x3FFFFFFFD;
// Add 1 to the value to create a "bad" value that doesn't match recomposition
uint256_t bad_value = uint256_t::from_uint128(value + 1);
uint256_t bad_value = value + 1;

uint16_t u16_r0 = value & 0xFFFF;
uint16_t u16_r1 = (value >> 16) & 0xFFFF;
Expand All @@ -98,7 +98,7 @@ TEST(RangeCheckConstrainingTest, Full)

// Choose a value that has num_bits
uint128_t value = (static_cast<uint128_t>(1) << num_bits) - 3;
uint256_t value_u256 = uint256_t::from_uint128(value);
uint256_t value_u256 = value;

uint16_t u16_r0 = value & 0xFFFF;
uint16_t u16_r1 = (value >> 16) & 0xFFFF;
Expand Down Expand Up @@ -134,7 +134,7 @@ TEST(RangeCheckConstrainingTest, NegativeMissingLookup)

// Choose a value that has num_bits
uint128_t value = (static_cast<uint128_t>(1) << num_bits) - 3;
uint256_t value_u256 = uint256_t::from_uint128(value);
uint256_t value_u256 = value;

uint16_t u16_r0 = value & 0xFFFF;
uint16_t u16_r1 = (value >> 16) & 0xFFFF;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -288,7 +288,7 @@ MemoryValue Alu::shl(const MemoryValue& a, const MemoryValue& b)
// We cast to uint256_t to be sure that the shift 1 << a_lo_bits has a defined behaviour.
// 1 << 128 is undefined behavior on uint128_t.
const uint128_t mask =
static_cast<uint128_t>((static_cast<uint256_t>(1) << uint256_t::from_uint128(a_lo_bits)) - 1);
static_cast<uint128_t>((static_cast<uint256_t>(1) << static_cast<uint256_t>(a_lo_bits)) - 1);
// Make use of x % pow_of_two = x & (pow_of_two - 1)
uint128_t a_lo = overflow ? b_num - max_bits : a_num & mask;
uint128_t a_hi = a_lo_bits >= 128 ? 0 : a_num >> a_lo_bits; // 128-bit shift undefined behaviour guard.
Expand Down Expand Up @@ -330,7 +330,7 @@ MemoryValue Alu::shr(const MemoryValue& a, const MemoryValue& b)
// We cast to uint256_t to be sure that the shift 1 << a_lo_bits has a defined behaviour.
// 1 << 128 is undefined behavior on uint128_t.
const uint128_t mask =
static_cast<uint128_t>((static_cast<uint256_t>(1) << uint256_t::from_uint128(a_lo_bits)) - 1);
static_cast<uint128_t>((static_cast<uint256_t>(1) << static_cast<uint256_t>(a_lo_bits)) - 1);
// Make use of x % pow_of_two = x & (pow_of_two - 1)
uint128_t a_lo = overflow ? b_num - max_bits : a_num & mask;
uint128_t a_hi = a_lo_bits >= 128 ? 0 : a_num >> a_lo_bits; // 128-bit shift undefined behaviour guard.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ bool GreaterThan::gt(const uint128_t& a, const uint128_t& b)
{
bool res = a > b;
const uint128_t abs_diff = res ? a - b - 1 : b - a;
const uint8_t num_bits_bound = static_cast<uint8_t>(uint256_t::from_uint128(abs_diff).get_msb() + 1);
const uint8_t num_bits_bound = static_cast<uint8_t>(static_cast<uint256_t>(abs_diff).get_msb() + 1);
const uint8_t num_bits_bound_16 = ((num_bits_bound - 1) / 16 + 1) * 16; // round up to multiple of 16
range_check.assert_range(abs_diff, num_bits_bound_16);
events.emit({
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -247,7 +247,7 @@ std::vector<std::pair<C, FF>> get_operation_specific_columns(const simulation::A
uint128_t a_lo_bits = overflow ? max_bits : max_bits - b_num;
// Cast to uint256_t to be sure that the shift 1 << a_lo_bits is cpp defined behaviour.
const uint128_t mask =
static_cast<uint128_t>((static_cast<uint256_t>(1) << uint256_t::from_uint128(a_lo_bits)) - 1);
static_cast<uint128_t>((static_cast<uint256_t>(1) << static_cast<uint256_t>(a_lo_bits)) - 1);
// The low limb of decomposed input a (if overflow, assigned as b - max_bits to range check and
// prove b > max_bits).
uint128_t a_lo =
Expand All @@ -265,8 +265,8 @@ std::vector<std::pair<C, FF>> get_operation_specific_columns(const simulation::A
{ C::alu_a_hi_bits, a_hi_bits },
{ C::alu_shift_lo_bits, a_lo_bits },
{ C::alu_two_pow_shift_lo_bits,
overflow ? 0 : static_cast<uint256_t>(1) << uint256_t::from_uint128(a_lo_bits) },
{ C::alu_helper1, overflow ? 0 : static_cast<uint256_t>(1) << uint256_t::from_uint128(b_num) },
overflow ? 0 : static_cast<uint256_t>(1) << static_cast<uint256_t>(a_lo_bits) },
{ C::alu_helper1, overflow ? 0 : static_cast<uint256_t>(1) << static_cast<uint256_t>(b_num) },
});
}
return res;
Expand Down Expand Up @@ -306,7 +306,7 @@ std::vector<std::pair<C, FF>> get_operation_specific_columns(const simulation::A
{ C::alu_a_hi_bits, a_hi_bits },
{ C::alu_shift_lo_bits, a_lo_bits },
{ C::alu_two_pow_shift_lo_bits,
overflow ? 0 : static_cast<uint256_t>(1) << uint256_t::from_uint128(a_lo_bits) },
overflow ? 0 : static_cast<uint256_t>(1) << static_cast<uint256_t>(a_lo_bits) },
});
}
return res;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,11 +22,11 @@ void RangeCheckTraceBuilder::process(
for (const auto& event : events) {
// store off event entries to be used directly in row
const uint256_t original_num_bits = event.num_bits;
const uint256_t original_value = uint256_t::from_uint128(event.value);
const uint256_t original_value = static_cast<uint256_t>(event.value);

// these will be mutated below
uint8_t num_bits = event.num_bits;
uint256_t value = uint256_t::from_uint128(event.value);
uint256_t value = static_cast<uint256_t>(event.value);

std::array<uint16_t, 7> fixed_slice_registers; // u16_r0...6
size_t index_of_most_sig_16b_chunk = 0;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ TEST(RangeCheckTraceGenTest, RangeCheckLte16Bit)

// Choose a value that has num_bits
uint128_t value = (static_cast<uint128_t>(1) << num_bits) - 3;
uint256_t value_u256 = uint256_t::from_uint128(value);
uint256_t value_u256 = value;

// <= 16 bits means that the only register used is the dynamic slice
uint16_t dynamic_slice_register = value & 0xFFFF;
Expand Down Expand Up @@ -58,7 +58,7 @@ TEST(RangeCheckTraceGenTest, RangeCheckLte48Bit)

// Choose a value that has num_bits
uint128_t value = (static_cast<uint128_t>(1) << num_bits) - 3;
uint256_t value_u256 = uint256_t::from_uint128(value);
uint256_t value_u256 = value;

uint16_t u16_r0 = value & 0xFFFF;
uint16_t u16_r1 = (value >> 16) & 0xFFFF;
Expand Down Expand Up @@ -98,7 +98,7 @@ TEST(RangeCheckTraceGenTest, RangeCheckLte128Bit)

// Choose a value that has num_bits
uint128_t value = static_cast<uint128_t>((static_cast<uint256_t>(1) << (num_bits)) - 3);
uint256_t value_u256 = uint256_t::from_uint128(value);
uint256_t value_u256 = value;

uint16_t u16_r0 = value & 0xFFFF;
uint16_t u16_r1 = (value >> 16) & 0xFFFF;
Expand Down
Loading