Skip to content

Commit

Permalink
Merge a329123 into 3c3ed1e
Browse files Browse the repository at this point in the history
  • Loading branch information
TomAFrench authored Sep 11, 2024
2 parents 3c3ed1e + a329123 commit 1e569bf
Show file tree
Hide file tree
Showing 23 changed files with 234 additions and 105 deletions.
8 changes: 5 additions & 3 deletions docs/docs/noir/concepts/data_types/arrays.md
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,9 @@ fn main() {

### sort_via

Sorts the array with a custom comparison function
Sorts the array with a custom comparison function. The ordering function must return true if the first argument should be sorted to be before the second argument or is equal to the second argument.

Using this method with an operator like `<` that does not return `true` for equal values will result in an assertion failure for arrays with equal elements.

```rust
fn sort_via(self, ordering: fn(T, T) -> bool) -> [T; N]
Expand All @@ -139,10 +141,10 @@ example
```rust
fn main() {
let arr = [42, 32]
let sorted_ascending = arr.sort_via(|a, b| a < b);
let sorted_ascending = arr.sort_via(|a, b| a <= b);
assert(sorted_ascending == [32, 42]); // verifies

let sorted_descending = arr.sort_via(|a, b| a > b);
let sorted_descending = arr.sort_via(|a, b| a >= b);
assert(sorted_descending == [32, 42]); // does not verify
}
```
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -130,10 +130,10 @@ example
```rust
fn main() {
let arr = [42, 32]
let sorted_ascending = arr.sort_via(|a, b| a < b);
let sorted_ascending = arr.sort_via(|a, b| a <= b);
assert(sorted_ascending == [32, 42]); // verifies

let sorted_descending = arr.sort_via(|a, b| a > b);
let sorted_descending = arr.sort_via(|a, b| a >= b);
assert(sorted_descending == [32, 42]); // does not verify
}
```
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -130,10 +130,10 @@ example
```rust
fn main() {
let arr = [42, 32]
let sorted_ascending = arr.sort_via(|a, b| a < b);
let sorted_ascending = arr.sort_via(|a, b| a <= b);
assert(sorted_ascending == [32, 42]); // verifies

let sorted_descending = arr.sort_via(|a, b| a > b);
let sorted_descending = arr.sort_via(|a, b| a >= b);
assert(sorted_descending == [32, 42]); // does not verify
}
```
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -130,10 +130,10 @@ example
```rust
fn main() {
let arr = [42, 32]
let sorted_ascending = arr.sort_via(|a, b| a < b);
let sorted_ascending = arr.sort_via(|a, b| a <= b);
assert(sorted_ascending == [32, 42]); // verifies

let sorted_descending = arr.sort_via(|a, b| a > b);
let sorted_descending = arr.sort_via(|a, b| a >= b);
assert(sorted_descending == [32, 42]); // does not verify
}
```
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -130,10 +130,10 @@ example
```rust
fn main() {
let arr = [42, 32]
let sorted_ascending = arr.sort_via(|a, b| a < b);
let sorted_ascending = arr.sort_via(|a, b| a <= b);
assert(sorted_ascending == [32, 42]); // verifies

let sorted_descending = arr.sort_via(|a, b| a > b);
let sorted_descending = arr.sort_via(|a, b| a >= b);
assert(sorted_descending == [32, 42]); // does not verify
}
```
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -130,10 +130,10 @@ example
```rust
fn main() {
let arr = [42, 32]
let sorted_ascending = arr.sort_via(|a, b| a < b);
let sorted_ascending = arr.sort_via(|a, b| a <= b);
assert(sorted_ascending == [32, 42]); // verifies

let sorted_descending = arr.sort_via(|a, b| a > b);
let sorted_descending = arr.sort_via(|a, b| a >= b);
assert(sorted_descending == [32, 42]); // does not verify
}
```
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -130,10 +130,10 @@ example
```rust
fn main() {
let arr = [42, 32]
let sorted_ascending = arr.sort_via(|a, b| a < b);
let sorted_ascending = arr.sort_via(|a, b| a <= b);
assert(sorted_ascending == [32, 42]); // verifies

let sorted_descending = arr.sort_via(|a, b| a > b);
let sorted_descending = arr.sort_via(|a, b| a >= b);
assert(sorted_descending == [32, 42]); // does not verify
}
```
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -131,10 +131,10 @@ example
```rust
fn main() {
let arr = [42, 32]
let sorted_ascending = arr.sort_via(|a, b| a < b);
let sorted_ascending = arr.sort_via(|a, b| a <= b);
assert(sorted_ascending == [32, 42]); // verifies

let sorted_descending = arr.sort_via(|a, b| a > b);
let sorted_descending = arr.sort_via(|a, b| a >= b);
assert(sorted_descending == [32, 42]); // does not verify
}
```
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -137,10 +137,10 @@ example
```rust
fn main() {
let arr = [42, 32]
let sorted_ascending = arr.sort_via(|a, b| a < b);
let sorted_ascending = arr.sort_via(|a, b| a <= b);
assert(sorted_ascending == [32, 42]); // verifies

let sorted_descending = arr.sort_via(|a, b| a > b);
let sorted_descending = arr.sort_via(|a, b| a >= b);
assert(sorted_descending == [32, 42]); // does not verify
}
```
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -139,10 +139,10 @@ example
```rust
fn main() {
let arr = [42, 32]
let sorted_ascending = arr.sort_via(|a, b| a < b);
let sorted_ascending = arr.sort_via(|a, b| a <= b);
assert(sorted_ascending == [32, 42]); // verifies

let sorted_descending = arr.sort_via(|a, b| a > b);
let sorted_descending = arr.sort_via(|a, b| a >= b);
assert(sorted_descending == [32, 42]); // does not verify
}
```
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -139,10 +139,10 @@ example
```rust
fn main() {
let arr = [42, 32]
let sorted_ascending = arr.sort_via(|a, b| a < b);
let sorted_ascending = arr.sort_via(|a, b| a <= b);
assert(sorted_ascending == [32, 42]); // verifies

let sorted_descending = arr.sort_via(|a, b| a > b);
let sorted_descending = arr.sort_via(|a, b| a >= b);
assert(sorted_descending == [32, 42]); // does not verify
}
```
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -139,10 +139,10 @@ example
```rust
fn main() {
let arr = [42, 32]
let sorted_ascending = arr.sort_via(|a, b| a < b);
let sorted_ascending = arr.sort_via(|a, b| a <= b);
assert(sorted_ascending == [32, 42]); // verifies

let sorted_descending = arr.sort_via(|a, b| a > b);
let sorted_descending = arr.sort_via(|a, b| a >= b);
assert(sorted_descending == [32, 42]); // does not verify
}
```
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -139,10 +139,10 @@ example
```rust
fn main() {
let arr = [42, 32]
let sorted_ascending = arr.sort_via(|a, b| a < b);
let sorted_ascending = arr.sort_via(|a, b| a <= b);
assert(sorted_ascending == [32, 42]); // verifies

let sorted_descending = arr.sort_via(|a, b| a > b);
let sorted_descending = arr.sort_via(|a, b| a >= b);
assert(sorted_descending == [32, 42]); // does not verify
}
```
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -139,10 +139,10 @@ example
```rust
fn main() {
let arr = [42, 32]
let sorted_ascending = arr.sort_via(|a, b| a < b);
let sorted_ascending = arr.sort_via(|a, b| a <= b);
assert(sorted_ascending == [32, 42]); // verifies

let sorted_descending = arr.sort_via(|a, b| a > b);
let sorted_descending = arr.sort_via(|a, b| a >= b);
assert(sorted_descending == [32, 42]); // does not verify
}
```
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -139,10 +139,10 @@ example
```rust
fn main() {
let arr = [42, 32]
let sorted_ascending = arr.sort_via(|a, b| a < b);
let sorted_ascending = arr.sort_via(|a, b| a <= b);
assert(sorted_ascending == [32, 42]); // verifies

let sorted_descending = arr.sort_via(|a, b| a > b);
let sorted_descending = arr.sort_via(|a, b| a >= b);
assert(sorted_descending == [32, 42]); // does not verify
}
```
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -139,10 +139,10 @@ example
```rust
fn main() {
let arr = [42, 32]
let sorted_ascending = arr.sort_via(|a, b| a < b);
let sorted_ascending = arr.sort_via(|a, b| a <= b);
assert(sorted_ascending == [32, 42]); // verifies

let sorted_descending = arr.sort_via(|a, b| a > b);
let sorted_descending = arr.sort_via(|a, b| a >= b);
assert(sorted_descending == [32, 42]); // does not verify
}
```
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -139,10 +139,10 @@ example
```rust
fn main() {
let arr = [42, 32]
let sorted_ascending = arr.sort_via(|a, b| a < b);
let sorted_ascending = arr.sort_via(|a, b| a <= b);
assert(sorted_ascending == [32, 42]); // verifies

let sorted_descending = arr.sort_via(|a, b| a > b);
let sorted_descending = arr.sort_via(|a, b| a >= b);
assert(sorted_descending == [32, 42]); // does not verify
}
```
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -139,10 +139,10 @@ example
```rust
fn main() {
let arr = [42, 32]
let sorted_ascending = arr.sort_via(|a, b| a < b);
let sorted_ascending = arr.sort_via(|a, b| a <= b);
assert(sorted_ascending == [32, 42]); // verifies

let sorted_descending = arr.sort_via(|a, b| a > b);
let sorted_descending = arr.sort_via(|a, b| a >= b);
assert(sorted_descending == [32, 42]); // does not verify
}
```
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -139,10 +139,10 @@ example
```rust
fn main() {
let arr = [42, 32]
let sorted_ascending = arr.sort_via(|a, b| a < b);
let sorted_ascending = arr.sort_via(|a, b| a <= b);
assert(sorted_ascending == [32, 42]); // verifies

let sorted_descending = arr.sort_via(|a, b| a > b);
let sorted_descending = arr.sort_via(|a, b| a >= b);
assert(sorted_descending == [32, 42]); // does not verify
}
```
Expand Down
116 changes: 116 additions & 0 deletions noir_stdlib/src/array/check_shuffle.nr
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
use crate::cmp::Eq;

unconstrained fn __get_shuffle_indices<T, let N: u32>(lhs: [T; N], rhs: [T; N]) -> [Field; N] where T: Eq {
let mut shuffle_indices: [Field;N ] = [0; N];

let mut shuffle_mask: [bool; N] = [false; N];
for i in 0..N {
let mut found = false;
for j in 0..N {
if ((shuffle_mask[j] == false) & (!found)) {
if (lhs[i] == rhs[j]) {
found = true;
shuffle_indices[i] = j as Field;
shuffle_mask[j] = true;
}
}
if (found) {
continue;
}
}
assert(found == true, "check_shuffle, lhs and rhs arrays do not contain equivalent values");
}

shuffle_indices
}

unconstrained fn __get_index<let N: u32>(indices: [Field; N], idx: Field) -> Field {
let mut result = 0;
for i in 0..N {
if (indices[i] == idx) {
result = i as Field;
break;
}
}
result
}

pub(crate) fn check_shuffle<T, let N: u32>(lhs: [T; N], rhs: [T; N]) where T: Eq {
unsafe {
let shuffle_indices = __get_shuffle_indices(lhs, rhs);

for i in 0..N {
let idx = __get_index(shuffle_indices, i as Field);
assert_eq(shuffle_indices[idx], i as Field);
}
for i in 0..N {
let idx = shuffle_indices[i];
let expected = rhs[idx];
let result = lhs[i];
assert_eq(expected, result);
}
}
}

mod test {
use super::check_shuffle;
use crate::cmp::Eq;

struct CompoundStruct {
a: bool,
b: Field,
c: u64
}
impl Eq for CompoundStruct {
fn eq(self, other: Self) -> bool {
(self.a == other.a) & (self.b == other.b) & (self.c == other.c)
}
}

#[test]
fn test_shuffle() {
let lhs: [Field; 5] = [0, 1, 2, 3, 4];
let rhs: [Field; 5] = [2, 0, 3, 1, 4];
check_shuffle(lhs, rhs);
}

#[test]
fn test_shuffle_identity() {
let lhs: [Field; 5] = [0, 1, 2, 3, 4];
let rhs: [Field; 5] = [0, 1, 2, 3, 4];
check_shuffle(lhs, rhs);
}

#[test(should_fail_with = "check_shuffle, lhs and rhs arrays do not contain equivalent values")]
fn test_shuffle_fail() {
let lhs: [Field; 5] = [0, 1, 2, 3, 4];
let rhs: [Field; 5] = [0, 1, 2, 3, 5];
check_shuffle(lhs, rhs);
}

#[test(should_fail_with = "check_shuffle, lhs and rhs arrays do not contain equivalent values")]
fn test_shuffle_duplicates() {
let lhs: [Field; 5] = [0, 1, 2, 3, 4];
let rhs: [Field; 5] = [0, 1, 2, 3, 3];
check_shuffle(lhs, rhs);
}

#[test]
fn test_shuffle_compound_struct() {
let lhs: [CompoundStruct; 5] = [
CompoundStruct { a: false, b: 0, c: 12345 },
CompoundStruct { a: false, b: -100, c: 54321 },
CompoundStruct { a: true, b: 5, c: 0xffffffffffffffff },
CompoundStruct { a: true, b: 9814, c: 0xeeffee0011001133 },
CompoundStruct { a: false, b: 0x155, c: 0 }
];
let rhs: [CompoundStruct; 5] = [
CompoundStruct { a: false, b: 0x155, c: 0 },
CompoundStruct { a: false, b: 0, c: 12345 },
CompoundStruct { a: false, b: -100, c: 54321 },
CompoundStruct { a: true, b: 9814, c: 0xeeffee0011001133 },
CompoundStruct { a: true, b: 5, c: 0xffffffffffffffff }
];
check_shuffle(lhs, rhs);
}
}
Loading

0 comments on commit 1e569bf

Please sign in to comment.