Skip to content

Commit

Permalink
fix array and resolve merge conflicts (#305)
Browse files Browse the repository at this point in the history
* fix array and resolve merge conflicts

* Remove suyash's function (its less efficient).

---------

Co-authored-by: Suyash Bagad <[email protected]>
  • Loading branch information
iAmMichaelConnor and suyash67 committed Apr 6, 2023
1 parent d874501 commit 3649d51
Show file tree
Hide file tree
Showing 4 changed files with 674 additions and 480 deletions.
2 changes: 2 additions & 0 deletions cpp/src/barretenberg/stdlib/primitives/bool/bool.test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -391,6 +391,8 @@ TEST(stdlib_bool, must_imply)
EXPECT_EQ(result, true);
}

// TODO: must_imply failure case

TEST(stdlib_bool, must_imply_multiple)
{
honk::StandardHonkComposer composer = honk::StandardHonkComposer();
Expand Down
72 changes: 37 additions & 35 deletions cpp/src/barretenberg/stdlib/primitives/field/array.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,9 @@ template <typename Composer, size_t SIZE> field_t<Composer> array_length(std::ar
field_t<Composer> length = 0;
bool_t<Composer> hit_zero = false;
for (const auto& e : arr) {
hit_zero |= e == 0;
bool_t<Composer> is_zero = e.is_zero();
hit_zero.must_imply(is_zero, "Once we've hit the first zero, there must only be zeros thereafter!");
hit_zero |= is_zero;
const field_t<Composer> increment = !hit_zero;
length += increment;
}
Expand Down Expand Up @@ -132,44 +134,44 @@ template <typename Composer, size_t size_1, size_t size_2>
void push_array_to_array(std::array<field_t<Composer>, size_1> const& source,
std::array<field_t<Composer>, size_2>& target)
{
ASSERT(target.size() >= source.size());
field_t<Composer> source_length = array_length<Composer>(source);
field_t<Composer> target_length = array_length<Composer>(target);
const field_t<Composer> overflow_capacity = target.max_size() + 1;

field_t<Composer> j_ct = 0; // circuit-type index for the inner loop
// Find the first empty slot in the target:
field_t<Composer> next_target_index = target_length;

bool_t<Composer> hit_s_zero = false;
bool_t<Composer> not_hit_s_zero = true;

for (size_t i = 0; i < source.max_size(); ++i) {
// Loop over each source value we want to push:
auto& s = source[i];
{
auto is_s_zero = s.is_zero();
hit_s_zero.must_imply(is_s_zero,
"Once we've hit the first source zero, there must only be zeros thereafter!");
hit_s_zero |= is_s_zero;
not_hit_s_zero = !hit_s_zero;
}

// Check if the `source` array is too large vs the remaining capacity of the `target` array
auto source_length_safe = safe_uint_t<Composer>(source_length, sizeof(size_t) * 8, "source_array_len");
auto target_length_safe = safe_uint_t<Composer>(target_length, sizeof(size_t) * 8, "target_array_len");
auto target_capacity_safe =
safe_uint_t<Composer>(field_t<Composer>(target.size()), sizeof(size_t) * 8, "target_array_capacity");
target_capacity_safe.subtract((source_length_safe + target_length_safe),
sizeof(size_t) * 8,
"push_array_to_array target array capacity exceeded");

// Ensure that all the elements after the first zero-element in target are zero
field_t<Composer> num_non_zero_in_target = 0;
for (size_t i = 0; i < size_2; i++) {
num_non_zero_in_target += !target[i].is_zero();
}
num_non_zero_in_target.assert_equal(target_length_safe, "non-zero element in target array after a zero element");
// Triangular loop:
for (size_t j = i; j < target.max_size(); ++j) {
auto& t = target[j];

// Ensure that all the elements after the first zero-element in source are zero
field_t<Composer> num_non_zero_in_source = 0;
for (size_t i = 0; i < size_1; i++) {
num_non_zero_in_source += !source[i].is_zero();
}
num_non_zero_in_source.assert_equal(source_length_safe, "non-zero element in source array after a zero element");

// Finally, insert only non-zero elements from source into target
bool_t<Composer> composer_error_found = !source_length.get_context()->err().empty();
for (size_t i = 0; i < source.size(); i++) {
bool_t<Composer> found = false;

for (size_t j = i; j < target.size(); j++) {
bool_t<Composer> is_target_non_zero = !target[j].is_zero();
target[j] = field_t<Composer>::conditional_assign(
is_target_non_zero, target[j], source[i] * !found * !composer_error_found);
found |= !is_target_non_zero;
// Check whether we've reached the next target index at which we can push `s`:
bool_t<Composer> at_next_target_index = j_ct == next_target_index;

t = field_t<Composer>::conditional_assign(at_next_target_index && not_hit_s_zero, s, t);

j_ct++;
}

next_target_index += not_hit_s_zero;

next_target_index.assert_not_equal(overflow_capacity, "push_array_to_array target array capacity exceeded");

j_ct = i + 1;
}
}

Expand Down
Loading

0 comments on commit 3649d51

Please sign in to comment.