diff --git a/Cargo.lock b/Cargo.lock
index a24908fd2e6..78dd08047ff 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -651,12 +651,6 @@ version = "3.13.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a3e2c3daef883ecc1b5d58c15adae93470a91d425f3532ba1695849656af3fc1"
-[[package]]
-name = "bytecount"
-version = "0.6.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2c676a478f63e9fa2dd5368a42f28bba0d6c560b775f38583c8bbaa7fcd67c9c"
-
[[package]]
name = "bytemuck"
version = "1.13.1"
@@ -2606,8 +2600,6 @@ dependencies = [
name = "nargo_fmt"
version = "0.35.0"
dependencies = [
- "bytecount",
- "noirc_errors",
"noirc_frontend",
"serde",
"similar-asserts",
diff --git a/compiler/noirc_frontend/src/ast/mod.rs b/compiler/noirc_frontend/src/ast/mod.rs
index 07f15f37c6e..e85563691ba 100644
--- a/compiler/noirc_frontend/src/ast/mod.rs
+++ b/compiler/noirc_frontend/src/ast/mod.rs
@@ -173,6 +173,12 @@ pub enum GenericTypeArg {
Named(Ident, UnresolvedType),
}
+#[derive(Debug, PartialEq, Eq, Clone, Hash)]
+pub enum GenericTypeArgKind {
+ Ordered,
+ Named,
+}
+
#[derive(Debug, Default, PartialEq, Eq, Clone, Hash)]
pub struct GenericTypeArgs {
/// Each ordered argument, e.g. ``
@@ -181,6 +187,9 @@ pub struct GenericTypeArgs {
/// All named arguments, e.g. ``.
/// Used for associated types.
pub named_args: Vec<(Ident, UnresolvedType)>,
+
+ /// The kind of each argument, in order (in case traversing the generics in order is needed)
+ pub kinds: Vec,
}
impl GenericTypeArgs {
@@ -351,7 +360,11 @@ impl UnresolvedType {
let last_segment = path.segments.last_mut().unwrap();
let generics = last_segment.generics.take();
let generic_type_args = if let Some(generics) = generics {
- GenericTypeArgs { ordered_args: generics, named_args: Vec::new() }
+ let mut kinds = Vec::with_capacity(generics.len());
+ for _ in 0..generics.len() {
+ kinds.push(GenericTypeArgKind::Ordered);
+ }
+ GenericTypeArgs { ordered_args: generics, named_args: Vec::new(), kinds }
} else {
GenericTypeArgs::default()
};
diff --git a/compiler/noirc_frontend/src/hir/comptime/display.rs b/compiler/noirc_frontend/src/hir/comptime/display.rs
index 60661211a09..9f753f11e4b 100644
--- a/compiler/noirc_frontend/src/hir/comptime/display.rs
+++ b/compiler/noirc_frontend/src/hir/comptime/display.rs
@@ -860,6 +860,7 @@ fn remove_interned_in_generic_type_args(
named_args: vecmap(args.named_args, |(name, typ)| {
(name, remove_interned_in_unresolved_type(interner, typ))
}),
+ kinds: args.kinds,
}
}
diff --git a/compiler/noirc_frontend/src/hir/comptime/hir_to_display_ast.rs b/compiler/noirc_frontend/src/hir/comptime/hir_to_display_ast.rs
index 97d90b905d4..260c4e3848a 100644
--- a/compiler/noirc_frontend/src/hir/comptime/hir_to_display_ast.rs
+++ b/compiler/noirc_frontend/src/hir/comptime/hir_to_display_ast.rs
@@ -303,7 +303,8 @@ impl Type {
Type::Struct(def, generics) => {
let struct_def = def.borrow();
let ordered_args = vecmap(generics, |generic| generic.to_display_ast());
- let generics = GenericTypeArgs { ordered_args, named_args: Vec::new() };
+ let generics =
+ GenericTypeArgs { ordered_args, named_args: Vec::new(), kinds: Vec::new() };
let name = Path::from_ident(struct_def.name.clone());
UnresolvedTypeData::Named(name, generics, false)
}
@@ -312,7 +313,8 @@ impl Type {
// alias' definition was changed
let type_def = type_def.borrow();
let ordered_args = vecmap(generics, |generic| generic.to_display_ast());
- let generics = GenericTypeArgs { ordered_args, named_args: Vec::new() };
+ let generics =
+ GenericTypeArgs { ordered_args, named_args: Vec::new(), kinds: Vec::new() };
let name = Path::from_ident(type_def.name.clone());
UnresolvedTypeData::Named(name, generics, false)
}
@@ -330,7 +332,7 @@ impl Type {
let named_args = vecmap(&generics.named, |named_type| {
(named_type.name.clone(), named_type.typ.to_display_ast())
});
- let generics = GenericTypeArgs { ordered_args, named_args };
+ let generics = GenericTypeArgs { ordered_args, named_args, kinds: Vec::new() };
let name = Path::from_single(name.as_ref().clone(), Span::default());
UnresolvedTypeData::TraitAsType(name, generics)
}
diff --git a/compiler/noirc_frontend/src/lexer/lexer.rs b/compiler/noirc_frontend/src/lexer/lexer.rs
index adc68351e3c..904ce41fbf0 100644
--- a/compiler/noirc_frontend/src/lexer/lexer.rs
+++ b/compiler/noirc_frontend/src/lexer/lexer.rs
@@ -575,7 +575,11 @@ impl<'a> Lexer<'a> {
return self.lookup_word_token(word, start, end);
}
- let delimiter = self.next_token()?;
+ let mut delimiter = self.next_token()?;
+ while let Token::Whitespace(_) = delimiter.token() {
+ delimiter = self.next_token()?;
+ }
+
let (start_delim, end_delim) = match delimiter.token() {
Token::LeftBrace => (Token::LeftBrace, Token::RightBrace),
Token::LeftBracket => (Token::LeftBracket, Token::RightBracket),
diff --git a/compiler/noirc_frontend/src/lexer/token.rs b/compiler/noirc_frontend/src/lexer/token.rs
index a8e463fb93b..8f05832d26d 100644
--- a/compiler/noirc_frontend/src/lexer/token.rs
+++ b/compiler/noirc_frontend/src/lexer/token.rs
@@ -377,7 +377,7 @@ impl fmt::Display for Token {
}
Token::Keyword(k) => write!(f, "{k}"),
Token::Attribute(ref a) => write!(f, "{a}"),
- Token::InnerAttribute(ref a) => write!(f, "#![{a}]"),
+ Token::InnerAttribute(ref a) => write!(f, "#![{}]", a.contents()),
Token::LineComment(ref s, style) => match style {
Some(DocStyle::Inner) => write!(f, "//!{s}"),
Some(DocStyle::Outer) => write!(f, "///{s}"),
@@ -1010,28 +1010,32 @@ impl SecondaryAttribute {
pub(crate) fn is_abi(&self) -> bool {
matches!(self, SecondaryAttribute::Abi(_))
}
-}
-impl fmt::Display for SecondaryAttribute {
- fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ pub(crate) fn contents(&self) -> String {
match self {
- SecondaryAttribute::Deprecated(None) => write!(f, "#[deprecated]"),
+ SecondaryAttribute::Deprecated(None) => "deprecated".to_string(),
SecondaryAttribute::Deprecated(Some(ref note)) => {
- write!(f, r#"#[deprecated({note:?})]"#)
+ format!("deprecated({note:?})")
}
- SecondaryAttribute::Tag(ref attribute) => write!(f, "#['{}]", attribute.contents),
- SecondaryAttribute::Meta(ref attribute) => write!(f, "#[{}]", attribute.contents),
- SecondaryAttribute::ContractLibraryMethod => write!(f, "#[contract_library_method]"),
- SecondaryAttribute::Export => write!(f, "#[export]"),
- SecondaryAttribute::Field(ref k) => write!(f, "#[field({k})]"),
- SecondaryAttribute::Abi(ref k) => write!(f, "#[abi({k})]"),
- SecondaryAttribute::Varargs => write!(f, "#[varargs]"),
- SecondaryAttribute::UseCallersScope => write!(f, "#[use_callers_scope]"),
- SecondaryAttribute::Allow(ref k) => write!(f, "#[allow(#{k})]"),
+ SecondaryAttribute::Tag(ref attribute) => format!("'{}", attribute.contents),
+ SecondaryAttribute::Meta(ref attribute) => attribute.contents.to_string(),
+ SecondaryAttribute::ContractLibraryMethod => "contract_library_method".to_string(),
+ SecondaryAttribute::Export => "export".to_string(),
+ SecondaryAttribute::Field(ref k) => format!("field({k})"),
+ SecondaryAttribute::Abi(ref k) => format!("abi({k})"),
+ SecondaryAttribute::Varargs => "varargs".to_string(),
+ SecondaryAttribute::UseCallersScope => "use_callers_scope".to_string(),
+ SecondaryAttribute::Allow(ref k) => format!("allow({k})"),
}
}
}
+impl fmt::Display for SecondaryAttribute {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ write!(f, "#[{}]", self.contents())
+ }
+}
+
#[derive(PartialEq, Eq, Hash, Debug, Clone, PartialOrd, Ord)]
pub struct CustomAttribute {
pub contents: String,
diff --git a/compiler/noirc_frontend/src/parser/parser/generics.rs b/compiler/noirc_frontend/src/parser/parser/generics.rs
index 2c8ba5a2a65..f577a237615 100644
--- a/compiler/noirc_frontend/src/parser/parser/generics.rs
+++ b/compiler/noirc_frontend/src/parser/parser/generics.rs
@@ -130,9 +130,11 @@ impl<'a> Parser<'a> {
match generic {
GenericTypeArg::Ordered(typ) => {
generic_type_args.ordered_args.push(typ);
+ generic_type_args.kinds.push(crate::ast::GenericTypeArgKind::Ordered);
}
GenericTypeArg::Named(name, typ) => {
generic_type_args.named_args.push((name, typ));
+ generic_type_args.kinds.push(crate::ast::GenericTypeArgKind::Named);
}
}
}
diff --git a/cspell.json b/cspell.json
index 6fd25a77182..8945ad21bdc 100644
--- a/cspell.json
+++ b/cspell.json
@@ -164,6 +164,7 @@
"plonkc",
"PLONKish",
"pprof",
+ "precomputes",
"preimage",
"preprocess",
"prettytable",
@@ -178,6 +179,7 @@
"reqwest",
"rfind",
"rustc",
+ "rustfmt",
"rustup",
"sboxed",
"schnorr",
@@ -229,6 +231,8 @@
"wasi",
"wasmer",
"Weierstraß",
+ "whitespace",
+ "whitespaces",
"zkhash",
"zshell"
],
diff --git a/noir_stdlib/src/array/check_shuffle.nr b/noir_stdlib/src/array/check_shuffle.nr
index 26f5ced3467..82028d487c7 100644
--- a/noir_stdlib/src/array/check_shuffle.nr
+++ b/noir_stdlib/src/array/check_shuffle.nr
@@ -1,7 +1,10 @@
use crate::cmp::Eq;
-unconstrained fn __get_shuffle_indices(lhs: [T; N], rhs: [T; N]) -> [Field; N] where T: Eq {
- let mut shuffle_indices: [Field;N ] = [0; N];
+unconstrained fn __get_shuffle_indices(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 {
@@ -35,7 +38,10 @@ unconstrained fn __get_index(indices: [Field; N], idx: Field) -> Fie
result
}
-pub(crate) fn check_shuffle(lhs: [T; N], rhs: [T; N]) where T: Eq {
+pub(crate) fn check_shuffle(lhs: [T; N], rhs: [T; N])
+where
+ T: Eq,
+{
unsafe {
let shuffle_indices = __get_shuffle_indices(lhs, rhs);
@@ -59,7 +65,7 @@ mod test {
struct CompoundStruct {
a: bool,
b: Field,
- c: u64
+ c: u64,
}
impl Eq for CompoundStruct {
fn eq(self, other: Self) -> bool {
@@ -102,14 +108,14 @@ mod test {
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 }
+ 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 }
+ CompoundStruct { a: true, b: 5, c: 0xffffffffffffffff },
];
check_shuffle(lhs, rhs);
}
diff --git a/noir_stdlib/src/array/mod.nr b/noir_stdlib/src/array/mod.nr
index f5089de1877..8bb425854f2 100644
--- a/noir_stdlib/src/array/mod.nr
+++ b/noir_stdlib/src/array/mod.nr
@@ -7,13 +7,13 @@ mod quicksort;
impl [T; N] {
/// Returns the length of this array.
- ///
+ ///
/// ```noir
/// fn len(self) -> Field
/// ```
- ///
+ ///
/// example
- ///
+ ///
/// ```noir
/// fn main() {
/// let array = [42, 42];
@@ -24,7 +24,7 @@ impl [T; N] {
pub fn len(self) -> u32 {}
/// Returns this array as a slice.
- ///
+ ///
/// ```noir
/// let array = [1, 2];
/// let slice = array.as_slice();
@@ -34,9 +34,9 @@ impl [T; N] {
pub fn as_slice(self) -> [T] {}
/// Applies a function to each element of this array, returning a new array containing the mapped elements.
- ///
+ ///
/// Example:
- ///
+ ///
/// ```rust
/// let a = [1, 2, 3];
/// let b = a.map(|a| a * 2);
@@ -55,20 +55,20 @@ impl [T; N] {
/// Applies a function to each element of the array, returning the final accumulated value. The first
/// parameter is the initial value.
- ///
+ ///
/// This is a left fold, so the given function will be applied to the accumulator and first element of
/// the array, then the second, and so on. For a given call the expected result would be equivalent to:
- ///
+ ///
/// ```rust
/// let a1 = [1];
/// let a2 = [1, 2];
/// let a3 = [1, 2, 3];
- ///
+ ///
/// let f = |a, b| a - b;
/// a1.fold(10, f); //=> f(10, 1)
/// a2.fold(10, f); //=> f(f(10, 1), 2)
/// a3.fold(10, f); //=> f(f(f(10, 1), 2), 3)
- ///
+ ///
/// assert_eq(a3.fold(10, f), 10 - 1 - 2 - 3);
/// ```
pub fn fold(self, mut accumulator: U, f: fn[Env](U, T) -> U) -> U {
@@ -81,9 +81,9 @@ impl [T; N] {
/// Same as fold, but uses the first element as the starting element.
///
/// Requires the input array to be non-empty.
- ///
+ ///
/// Example:
- ///
+ ///
/// ```noir
/// fn main() {
/// let arr = [1, 2, 3, 4];
@@ -100,9 +100,9 @@ impl [T; N] {
}
/// Returns true if all the elements in this array satisfy the given predicate.
- ///
+ ///
/// Example:
- ///
+ ///
/// ```noir
/// fn main() {
/// let arr = [2, 2, 2, 2, 2];
@@ -119,9 +119,9 @@ impl [T; N] {
}
/// Returns true if any of the elements in this array satisfy the given predicate.
- ///
+ ///
/// Example:
- ///
+ ///
/// ```noir
/// fn main() {
/// let arr = [2, 2, 2, 2, 5];
@@ -138,14 +138,17 @@ impl [T; N] {
}
}
-impl [T; N] where T: Ord + Eq {
+impl [T; N]
+where
+ T: Ord + Eq,
+{
/// Returns a new sorted array. The original array remains untouched. Notice that this function will
/// only work for arrays of fields or integers, not for any arbitrary type. This is because the sorting
/// logic it uses internally is optimized specifically for these values. If you need a sort function to
/// sort any type, you should use the `sort_via` function.
- ///
+ ///
/// Example:
- ///
+ ///
/// ```rust
/// fn main() {
/// let arr = [42, 32];
@@ -158,21 +161,24 @@ impl [T; N] where T: Ord + Eq {
}
}
-impl [T; N] where T: Eq {
- /// Returns a new sorted array by sorting it with a custom comparison function.
- /// The original array remains untouched.
+impl [T; N]
+where
+ T: Eq,
+{
+ /// Returns a new sorted array by sorting it with a custom comparison function.
+ /// The original array remains untouched.
/// 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.
- ///
+ ///
/// Example:
- ///
+ ///
/// ```rust
/// fn main() {
/// let arr = [42, 32]
/// 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);
/// assert(sorted_descending == [32, 42]); // does not verify
/// }
@@ -187,7 +193,8 @@ impl [T; N] where T: Eq {
if !is_unconstrained() {
for i in 0..N - 1 {
assert(
- ordering(sorted[i], sorted[i + 1]), "Array has not been sorted correctly according to `ordering`."
+ ordering(sorted[i], sorted[i + 1]),
+ "Array has not been sorted correctly according to `ordering`.",
);
}
check_shuffle::check_shuffle(self, sorted);
@@ -200,9 +207,9 @@ impl [T; N] where T: Eq {
impl [u8; N] {
/// Converts a byte array of type `[u8; N]` to a string. Note that this performs no UTF-8 validation -
/// the given array is interpreted as-is as a string.
- ///
+ ///
/// Example:
- ///
+ ///
/// ```rust
/// fn main() {
/// let hi = [104, 105].as_str_unchecked();
diff --git a/noir_stdlib/src/array/quicksort.nr b/noir_stdlib/src/array/quicksort.nr
index 8563a5d75bd..5e9c575c5ce 100644
--- a/noir_stdlib/src/array/quicksort.nr
+++ b/noir_stdlib/src/array/quicksort.nr
@@ -2,7 +2,7 @@ unconstrained fn partition(
arr: &mut [T; N],
low: u32,
high: u32,
- sortfn: fn[Env](T, T) -> bool
+ sortfn: fn[Env](T, T) -> bool,
) -> u32 {
let pivot = high;
let mut i = low;
@@ -20,7 +20,12 @@ unconstrained fn partition(
i
}
-unconstrained fn quicksort_recursive(arr: &mut [T; N], low: u32, high: u32, sortfn: fn[Env](T, T) -> bool) {
+unconstrained fn quicksort_recursive(
+ arr: &mut [T; N],
+ low: u32,
+ high: u32,
+ sortfn: fn[Env](T, T) -> bool,
+) {
if low < high {
let pivot_index = partition(arr, low, high, sortfn);
if pivot_index > 0 {
@@ -30,7 +35,10 @@ unconstrained fn quicksort_recursive(arr: &mut [T; N], low:
}
}
-pub(crate) unconstrained fn quicksort(_arr: [T; N], sortfn: fn[Env](T, T) -> bool) -> [T; N] {
+pub(crate) unconstrained fn quicksort(
+ _arr: [T; N],
+ sortfn: fn[Env](T, T) -> bool,
+) -> [T; N] {
let mut arr: [T; N] = _arr;
if arr.len() <= 1 {} else {
quicksort_recursive(&mut arr, 0, arr.len() - 1, sortfn);
diff --git a/noir_stdlib/src/bigint.nr b/noir_stdlib/src/bigint.nr
index 0015f480794..203ff90d444 100644
--- a/noir_stdlib/src/bigint.nr
+++ b/noir_stdlib/src/bigint.nr
@@ -1,16 +1,30 @@
use crate::ops::{Add, Sub, Mul, Div};
use crate::cmp::Eq;
-global bn254_fq = &[0x47, 0xFD, 0x7C, 0xD8, 0x16, 0x8C, 0x20, 0x3C, 0x8d, 0xca, 0x71, 0x68, 0x91, 0x6a, 0x81, 0x97,
- 0x5d, 0x58, 0x81, 0x81, 0xb6, 0x45, 0x50, 0xb8, 0x29, 0xa0, 0x31, 0xe1, 0x72, 0x4e, 0x64, 0x30];
-global bn254_fr = &[1, 0, 0, 240, 147, 245, 225, 67, 145, 112, 185, 121, 72, 232, 51, 40, 93, 88, 129, 129, 182, 69, 80, 184, 41, 160, 49, 225, 114, 78, 100, 48];
-global secpk1_fr = &[0x41, 0x41, 0x36, 0xD0, 0x8C, 0x5E, 0xD2, 0xBF, 0x3B, 0xA0, 0x48, 0xAF, 0xE6, 0xDC, 0xAE, 0xBA,
- 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF];
-global secpk1_fq = &[0x2F, 0xFC, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
- 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF];
-global secpr1_fq = &[0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF];
-global secpr1_fr = &[81, 37, 99, 252, 194, 202, 185, 243, 132, 158, 23, 167, 173, 250, 230, 188, 255, 255, 255, 255, 255, 255, 255, 255, 0, 0, 0, 0, 255, 255, 255, 255];
+global bn254_fq = &[
+ 0x47, 0xFD, 0x7C, 0xD8, 0x16, 0x8C, 0x20, 0x3C, 0x8d, 0xca, 0x71, 0x68, 0x91, 0x6a, 0x81, 0x97,
+ 0x5d, 0x58, 0x81, 0x81, 0xb6, 0x45, 0x50, 0xb8, 0x29, 0xa0, 0x31, 0xe1, 0x72, 0x4e, 0x64, 0x30,
+];
+global bn254_fr = &[
+ 1, 0, 0, 240, 147, 245, 225, 67, 145, 112, 185, 121, 72, 232, 51, 40, 93, 88, 129, 129, 182, 69,
+ 80, 184, 41, 160, 49, 225, 114, 78, 100, 48,
+];
+global secpk1_fr = &[
+ 0x41, 0x41, 0x36, 0xD0, 0x8C, 0x5E, 0xD2, 0xBF, 0x3B, 0xA0, 0x48, 0xAF, 0xE6, 0xDC, 0xAE, 0xBA,
+ 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+];
+global secpk1_fq = &[
+ 0x2F, 0xFC, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+];
+global secpr1_fq = &[
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF,
+];
+global secpr1_fr = &[
+ 81, 37, 99, 252, 194, 202, 185, 243, 132, 158, 23, 167, 173, 250, 230, 188, 255, 255, 255, 255,
+ 255, 255, 255, 255, 0, 0, 0, 0, 255, 255, 255, 255,
+];
// docs:start:big_int_definition
pub struct BigInt {
pointer: u32,
@@ -50,7 +64,7 @@ pub trait BigField {
}
pub struct Secpk1Fq {
- array: [u8;32],
+ array: [u8; 32],
}
impl BigField for Secpk1Fq {
@@ -107,7 +121,7 @@ impl Eq for Secpk1Fq {
}
pub struct Secpk1Fr {
- array: [u8;32],
+ array: [u8; 32],
}
impl BigField for Secpk1Fr {
@@ -164,7 +178,7 @@ impl Eq for Secpk1Fr {
}
pub struct Bn254Fr {
- array: [u8;32],
+ array: [u8; 32],
}
impl BigField for Bn254Fr {
@@ -221,7 +235,7 @@ impl Eq for Bn254Fr {
}
pub struct Bn254Fq {
- array: [u8;32],
+ array: [u8; 32],
}
impl BigField for Bn254Fq {
@@ -278,7 +292,7 @@ impl Eq for Bn254Fq {
}
pub struct Secpr1Fq {
- array: [u8;32],
+ array: [u8; 32],
}
impl BigField for Secpr1Fq {
@@ -335,7 +349,7 @@ impl Eq for Secpr1Fq {
}
pub struct Secpr1Fr {
- array: [u8;32],
+ array: [u8; 32],
}
impl BigField for Secpr1Fr {
diff --git a/noir_stdlib/src/cmp.nr b/noir_stdlib/src/cmp.nr
index ac7e3df66ad..10be6e7b867 100644
--- a/noir_stdlib/src/cmp.nr
+++ b/noir_stdlib/src/cmp.nr
@@ -18,7 +18,14 @@ comptime fn derive_eq(s: StructDefinition) -> Quoted {
fields
}
};
- crate::meta::make_trait_impl(s, quote { Eq }, signature, for_each_field, quote { & }, body)
+ crate::meta::make_trait_impl(
+ s,
+ quote { Eq },
+ signature,
+ for_each_field,
+ quote { & },
+ body,
+ )
}
// docs:end:derive_eq
@@ -86,7 +93,10 @@ impl Eq for bool {
}
}
-impl Eq for [T; N] where T: Eq {
+impl Eq for [T; N]
+where
+ T: Eq,
+{
fn eq(self, other: [T; N]) -> bool {
let mut result = true;
for i in 0..self.len() {
@@ -96,7 +106,10 @@ impl Eq for [T; N] where T: Eq {
}
}
-impl Eq for [T] where T: Eq {
+impl Eq for [T]
+where
+ T: Eq,
+{
fn eq(self, other: [T]) -> bool {
let mut result = self.len() == other.len();
for i in 0..self.len() {
@@ -114,25 +127,47 @@ impl Eq for str {
}
}
-impl Eq for (A, B) where A: Eq, B: Eq {
+impl Eq for (A, B)
+where
+ A: Eq,
+ B: Eq,
+{
fn eq(self, other: (A, B)) -> bool {
self.0.eq(other.0) & self.1.eq(other.1)
}
}
-impl Eq for (A, B, C) where A: Eq, B: Eq, C: Eq {
+impl Eq for (A, B, C)
+where
+ A: Eq,
+ B: Eq,
+ C: Eq,
+{
fn eq(self, other: (A, B, C)) -> bool {
self.0.eq(other.0) & self.1.eq(other.1) & self.2.eq(other.2)
}
}
-impl Eq for (A, B, C, D) where A: Eq, B: Eq, C: Eq, D: Eq {
+impl Eq for (A, B, C, D)
+where
+ A: Eq,
+ B: Eq,
+ C: Eq,
+ D: Eq,
+{
fn eq(self, other: (A, B, C, D)) -> bool {
self.0.eq(other.0) & self.1.eq(other.1) & self.2.eq(other.2) & self.3.eq(other.3)
}
}
-impl Eq for (A, B, C, D, E) where A: Eq, B: Eq, C: Eq, D: Eq, E: Eq {
+impl Eq for (A, B, C, D, E)
+where
+ A: Eq,
+ B: Eq,
+ C: Eq,
+ D: Eq,
+ E: Eq,
+{
fn eq(self, other: (A, B, C, D, E)) -> bool {
self.0.eq(other.0)
& self.1.eq(other.1)
@@ -315,7 +350,10 @@ impl Ord for bool {
}
}
-impl Ord for [T; N] where T: Ord {
+impl Ord for [T; N]
+where
+ T: Ord,
+{
// The first non-equal element of both arrays determines
// the ordering for the whole array.
fn cmp(self, other: [T; N]) -> Ordering {
@@ -335,7 +373,10 @@ impl Ord for [T; N] where T: Ord {
}
}
-impl Ord for [T] where T: Ord {
+impl Ord for [T]
+where
+ T: Ord,
+{
// The first non-equal element of both arrays determines
// the ordering for the whole array.
fn cmp(self, other: [T]) -> Ordering {
@@ -355,7 +396,11 @@ impl Ord for [T] where T: Ord {
}
}
-impl Ord for (A, B) where A: Ord, B: Ord {
+impl Ord for (A, B)
+where
+ A: Ord,
+ B: Ord,
+{
fn cmp(self, other: (A, B)) -> Ordering {
let result = self.0.cmp(other.0);
@@ -367,7 +412,12 @@ impl Ord for (A, B) where A: Ord, B: Ord {
}
}
-impl Ord for (A, B, C) where A: Ord, B: Ord, C: Ord {
+impl Ord for (A, B, C)
+where
+ A: Ord,
+ B: Ord,
+ C: Ord,
+{
fn cmp(self, other: (A, B, C)) -> Ordering {
let mut result = self.0.cmp(other.0);
@@ -383,7 +433,13 @@ impl Ord for (A, B, C) where A: Ord, B: Ord, C: Ord {
}
}
-impl Ord for (A, B, C, D) where A: Ord, B: Ord, C: Ord, D: Ord {
+impl Ord for (A, B, C, D)
+where
+ A: Ord,
+ B: Ord,
+ C: Ord,
+ D: Ord,
+{
fn cmp(self, other: (A, B, C, D)) -> Ordering {
let mut result = self.0.cmp(other.0);
@@ -403,7 +459,14 @@ impl Ord for (A, B, C, D) where A: Ord, B: Ord, C: Ord, D: Ord {
}
}
-impl Ord for (A, B, C, D, E) where A: Ord, B: Ord, C: Ord, D: Ord, E: Ord {
+impl Ord for (A, B, C, D, E)
+where
+ A: Ord,
+ B: Ord,
+ C: Ord,
+ D: Ord,
+ E: Ord,
+{
fn cmp(self, other: (A, B, C, D, E)) -> Ordering {
let mut result = self.0.cmp(other.0);
@@ -439,8 +502,15 @@ impl Ord for (A, B, C, D, E) where A: Ord, B: Ord, C: Ord, D: Ord
// assert_eq(cmp::max(1, 2), 2);
// assert_eq(cmp::max(2, 2), 2);
// ```
-pub fn max(v1: T, v2: T) -> T where T: Ord {
- if v1 > v2 { v1 } else { v2 }
+pub fn max(v1: T, v2: T) -> T
+where
+ T: Ord,
+{
+ if v1 > v2 {
+ v1
+ } else {
+ v2
+ }
}
// Compares and returns the minimum of two values.
@@ -455,8 +525,15 @@ pub fn max(v1: T, v2: T) -> T where T: Ord {
// assert_eq(cmp::min(1, 2), 1);
// assert_eq(cmp::min(2, 2), 2);
// ```
-pub fn min(v1: T, v2: T) -> T where T: Ord {
- if v1 > v2 { v2 } else { v1 }
+pub fn min(v1: T, v2: T) -> T
+where
+ T: Ord,
+{
+ if v1 > v2 {
+ v2
+ } else {
+ v1
+ }
}
mod cmp_tests {
diff --git a/noir_stdlib/src/collections/bounded_vec.nr b/noir_stdlib/src/collections/bounded_vec.nr
index c2a3ff9b7ca..9e70c403f77 100644
--- a/noir_stdlib/src/collections/bounded_vec.nr
+++ b/noir_stdlib/src/collections/bounded_vec.nr
@@ -4,16 +4,16 @@ use crate::{cmp::Eq, convert::From};
/// is bounded with a maximum possible length. Unlike `Vec`, `BoundedVec` is not implemented
/// via slices and thus is not subject to the same restrictions slices are (notably, nested
/// slices - and thus nested vectors as well - are disallowed).
-///
+///
/// Since a BoundedVec is backed by a normal array under the hood, growing the BoundedVec by
/// pushing an additional element is also more efficient - the length only needs to be increased
/// by one.
-///
+///
/// For these reasons `BoundedVec` should generally be preferred over `Vec` when there
/// is a reasonable maximum bound that can be placed on the vector.
-///
+///
/// Example:
-///
+///
/// ```noir
/// let mut vector: BoundedVec = BoundedVec::new();
/// for i in 0..5 {
@@ -63,7 +63,7 @@ impl BoundedVec {
/// ```
///
/// This defaulting of `MaxLen` (and numeric generics in general) to zero may change in future noir versions
- /// but for now make sure to use type annotations when using bounded vectors. Otherwise, you will receive a
+ /// but for now make sure to use type annotations when using bounded vectors. Otherwise, you will receive a
/// constraint failure at runtime when the vec is pushed to.
pub fn new() -> Self {
let zeroed = crate::mem::zeroed();
@@ -71,12 +71,12 @@ impl BoundedVec {
}
/// Retrieves an element from the vector at the given index, starting from zero.
- ///
+ ///
/// If the given index is equal to or greater than the length of the vector, this
/// will issue a constraint failure.
- ///
+ ///
/// Example:
- ///
+ ///
/// ```noir
/// fn foo(v: BoundedVec) {
/// let first = v.get(0);
@@ -91,12 +91,12 @@ impl BoundedVec {
/// Retrieves an element from the vector at the given index, starting from zero, without
/// performing a bounds check.
- ///
+ ///
/// Since this function does not perform a bounds check on length before accessing the element,
/// it is unsafe! Use at your own risk!
- ///
+ ///
/// Example:
- ///
+ ///
/// ```noir
/// fn sum_of_first_three(v: BoundedVec) -> u32 {
/// // Always ensure the length is larger than the largest
@@ -113,11 +113,11 @@ impl BoundedVec {
}
/// Writes an element to the vector at the given index, starting from zero.
- ///
+ ///
/// If the given index is equal to or greater than the length of the vector, this will issue a constraint failure.
- ///
+ ///
/// Example:
- ///
+ ///
/// ```noir
/// fn foo(v: BoundedVec) {
/// let first = v.get(0);
@@ -133,30 +133,30 @@ impl BoundedVec {
}
/// Writes an element to the vector at the given index, starting from zero, without performing a bounds check.
- ///
+ ///
/// Since this function does not perform a bounds check on length before accessing the element, it is unsafe! Use at your own risk!
- ///
+ ///
/// Example:
- ///
+ ///
/// ```noir
/// fn set_unchecked_example() {
/// let mut vec: BoundedVec = BoundedVec::new();
/// vec.extend_from_array([1, 2]);
- ///
+ ///
/// // Here we're safely writing within the valid range of `vec`
/// // `vec` now has the value [42, 2]
/// vec.set_unchecked(0, 42);
- ///
+ ///
/// // We can then safely read this value back out of `vec`.
/// // Notice that we use the checked version of `get` which would prevent reading unsafe values.
/// assert_eq(vec.get(0), 42);
- ///
+ ///
/// // We've now written past the end of `vec`.
/// // As this index is still within the maximum potential length of `v`,
- /// // it won't cause a constraint failure.
+ /// // it won't cause a constraint failure.
/// vec.set_unchecked(2, 42);
/// println(vec);
- ///
+ ///
/// // This will write past the end of the maximum potential length of `vec`,
/// // it will then trigger a constraint failure.
/// vec.set_unchecked(5, 42);
@@ -169,17 +169,17 @@ impl BoundedVec {
/// Pushes an element to the end of the vector. This increases the length
/// of the vector by one.
- ///
+ ///
/// Panics if the new length of the vector will be greater than the max length.
- ///
+ ///
/// Example:
- ///
+ ///
/// ```noir
/// let mut v: BoundedVec = BoundedVec::new();
- ///
+ ///
/// v.push(1);
/// v.push(2);
- ///
+ ///
/// // Panics with failed assertion "push out of bounds"
/// v.push(3);
/// ```
@@ -191,21 +191,21 @@ impl BoundedVec {
}
/// Returns the current length of this vector
- ///
+ ///
/// Example:
- ///
+ ///
/// ```noir
/// let mut v: BoundedVec = BoundedVec::new();
/// assert(v.len() == 0);
- ///
+ ///
/// v.push(100);
/// assert(v.len() == 1);
- ///
+ ///
/// v.push(200);
/// v.push(300);
/// v.push(400);
/// assert(v.len() == 4);
- ///
+ ///
/// let _ = v.pop();
/// let _ = v.pop();
/// assert(v.len() == 2);
@@ -216,12 +216,12 @@ impl BoundedVec {
/// Returns the maximum length of this vector. This is always
/// equal to the `MaxLen` parameter this vector was initialized with.
- ///
+ ///
/// Example:
- ///
+ ///
/// ```noir
/// let mut v: BoundedVec = BoundedVec::new();
- ///
+ ///
/// assert(v.max_len() == 5);
/// v.push(10);
/// assert(v.max_len() == 5);
@@ -231,19 +231,19 @@ impl BoundedVec {
}
/// Returns the internal array within this vector.
- ///
+ ///
/// Since arrays in Noir are immutable, mutating the returned storage array will not mutate
/// the storage held internally by this vector.
- ///
+ ///
/// Note that uninitialized elements may be zeroed out!
- ///
+ ///
/// Example:
- ///
+ ///
/// ```noir
/// let mut v: BoundedVec = BoundedVec::new();
- ///
+ ///
/// assert(v.storage() == [0, 0, 0, 0, 0]);
- ///
+ ///
/// v.push(57);
/// assert(v.storage() == [57, 0, 0, 0, 0]);
/// ```
@@ -252,16 +252,16 @@ impl BoundedVec {
}
/// Pushes each element from the given array to this vector.
- ///
+ ///
/// Panics if pushing each element would cause the length of this vector
/// to exceed the maximum length.
- ///
+ ///
/// Example:
- ///
+ ///
/// ```noir
/// let mut vec: BoundedVec = BoundedVec::new();
/// vec.extend_from_array([2, 4]);
- ///
+ ///
/// assert(vec.len == 2);
/// assert(vec.get(0) == 2);
/// assert(vec.get(1) == 4);
@@ -276,16 +276,16 @@ impl BoundedVec {
}
/// Pushes each element from the given slice to this vector.
- ///
+ ///
/// Panics if pushing each element would cause the length of this vector
/// to exceed the maximum length.
- ///
+ ///
/// Example:
- ///
+ ///
/// ```noir
/// let mut vec: BoundedVec = BoundedVec::new();
/// vec.extend_from_slice(&[2, 4]);
- ///
+ ///
/// assert(vec.len == 2);
/// assert(vec.get(0) == 2);
/// assert(vec.get(1) == 4);
@@ -301,17 +301,17 @@ impl BoundedVec {
/// Pushes each element from the other vector to this vector. The length of
/// the other vector is left unchanged.
- ///
+ ///
/// Panics if pushing each element would cause the length of this vector
/// to exceed the maximum length.
- ///
+ ///
/// ```noir
/// let mut v1: BoundedVec = BoundedVec::new();
/// let mut v2: BoundedVec = BoundedVec::new();
- ///
+ ///
/// v2.extend_from_array([1, 2, 3]);
/// v1.extend_from_bounded_vec(v2);
- ///
+ ///
/// assert(v1.storage() == [1, 2, 3, 0, 0]);
/// assert(v2.storage() == [1, 2, 3, 0, 0, 0, 0]);
/// ```
@@ -330,11 +330,11 @@ impl BoundedVec {
self.len = new_len;
}
- /// Creates a new vector, populating it with values derived from an array input.
+ /// Creates a new vector, populating it with values derived from an array input.
/// The maximum length of the vector is determined based on the type signature.
- ///
+ ///
/// Example:
- ///
+ ///
/// ```noir
/// let bounded_vec: BoundedVec = BoundedVec::from_array([1, 2, 3])
/// ```
@@ -347,19 +347,19 @@ impl BoundedVec {
/// Pops the element at the end of the vector. This will decrease the length
/// of the vector by one.
- ///
+ ///
/// Panics if the vector is empty.
- ///
+ ///
/// Example:
- ///
+ ///
/// ```noir
/// let mut v: BoundedVec = BoundedVec::new();
/// v.push(1);
/// v.push(2);
- ///
+ ///
/// let two = v.pop();
/// let one = v.pop();
- ///
+ ///
/// assert(two == 2);
/// assert(one == 1);
///
@@ -377,13 +377,13 @@ impl BoundedVec {
/// Returns true if the given predicate returns true for any element
/// in this vector.
- ///
+ ///
/// Example:
- ///
+ ///
/// ```noir
/// let mut v: BoundedVec = BoundedVec::new();
/// v.extend_from_array([2, 4, 6]);
- ///
+ ///
/// let all_even = !v.any(|elem: u32| elem % 2 != 0);
/// assert(all_even);
/// ```
@@ -399,14 +399,14 @@ impl BoundedVec {
ret
}
- /// Creates a new vector of equal size by calling a closure on each element in this vector.
- ///
+ /// Creates a new vector of equal size by calling a closure on each element in this vector.
+ ///
/// Example:
- ///
+ ///
/// ```noir
/// let vec: BoundedVec = BoundedVec::from_array([1, 2, 3, 4]);
/// let result = vec.map(|value| value * 2);
- ///
+ ///
/// let expected = BoundedVec::from_array([2, 4, 6, 8]);
/// assert_eq(result, expected);
/// ```
@@ -422,13 +422,15 @@ impl BoundedVec {
}
}
-impl Eq for BoundedVec where T: Eq {
+impl Eq for BoundedVec
+where
+ T: Eq,
+{
fn eq(self, other: BoundedVec) -> bool {
// TODO: https://github.com/noir-lang/noir/issues/4837
//
// We make the assumption that the user has used the proper interface for working with `BoundedVec`s
// rather than directly manipulating the internal fields as this can result in an inconsistent internal state.
-
(self.len == other.len) & (self.storage == other.storage)
}
}
@@ -502,7 +504,7 @@ mod bounded_vec_tests {
#[test]
fn applies_function_that_changes_return_type() {
let vec: BoundedVec = BoundedVec::from_array([1, 2, 3, 4]);
- let result = vec.map(|value| (value * 2) as Field);
+ let result = vec.map(|value| (value * 2) as Field);
let expected: BoundedVec = BoundedVec::from_array([2, 4, 6, 8]);
assert_eq(result, expected);
diff --git a/noir_stdlib/src/collections/map.nr b/noir_stdlib/src/collections/map.nr
index a336a01d101..cd203c43ad3 100644
--- a/noir_stdlib/src/collections/map.nr
+++ b/noir_stdlib/src/collections/map.nr
@@ -4,30 +4,30 @@ use crate::default::Default;
use crate::hash::{Hash, Hasher, BuildHasher};
use crate::collections::bounded_vec::BoundedVec;
-// We use load factor alpha_max = 0.75.
-// Upon exceeding it, assert will fail in order to inform the user
+// We use load factor alpha_max = 0.75.
+// Upon exceeding it, assert will fail in order to inform the user
// about performance degradation, so that he can adjust the capacity.
global MAX_LOAD_FACTOR_NUMERATOR = 3;
global MAX_LOAD_FACTOR_DEN0MINATOR = 4;
/// `HashMap` is used to efficiently store and look up key-value pairs.
-///
+///
/// `HashMap` is a bounded type which can store anywhere from zero to `MaxLen` total elements.
/// Note that due to hash collisions, the actual maximum number of elements stored by any particular
/// hashmap is likely lower than `MaxLen`. This is true even with cryptographic hash functions since
/// every hash value will be performed modulo `MaxLen`.
-///
+///
/// Example:
-///
+///
/// ```noir
/// // Create a mapping from Fields to u32s with a maximum length of 12
/// // using a poseidon2 hasher
/// use std::hash::poseidon2::Poseidon2Hasher;
/// let mut map: HashMap> = HashMap::default();
-///
+///
/// map.insert(1, 2);
/// map.insert(3, 4);
-///
+///
/// let two = map.get(1).unwrap();
/// ```
pub struct HashMap {
@@ -36,11 +36,11 @@ pub struct HashMap {
/// Amount of valid elements in the map.
_len: u32,
- _build_hasher: B
+ _build_hasher: B,
}
// Data unit in the HashMap table.
-// In case Noir adds support for enums in the future, this
+// In case Noir adds support for enums in the future, this
// should be refactored to have three states:
// 1. (key, value)
// 2. (empty)
@@ -79,7 +79,7 @@ impl Slot {
}
// Shall not override `_key_value` with Option::none(),
- // because we must be able to differentiate empty
+ // because we must be able to differentiate empty
// and deleted slots for lookup.
fn mark_deleted(&mut self) {
self._is_deleted = true;
@@ -87,12 +87,12 @@ impl Slot {
}
// While conducting lookup, we iterate attempt from 0 to N - 1 due to heuristic,
-// that if we have went that far without finding desired,
+// that if we have went that far without finding desired,
// it is very unlikely to be after - performance will be heavily degraded.
impl HashMap {
/// Creates a hashmap with an existing `BuildHasher`. This can be used to ensure multiple
/// hashmaps are created with the same hasher instance.
- ///
+ ///
/// Example:
///
/// ```noir
@@ -103,7 +103,8 @@ impl HashMap {
// docs:start:with_hasher
pub fn with_hasher(_build_hasher: B) -> Self
where
- B: BuildHasher {
+ B: BuildHasher,
+ {
// docs:end:with_hasher
let _table = [Slot::default(); N];
let _len = 0;
@@ -111,9 +112,9 @@ impl HashMap {
}
/// Clears the hashmap, removing all key-value pairs from it.
- ///
+ ///
/// Example:
- ///
+ ///
/// ```noir
/// assert(!map.is_empty());
/// map.clear();
@@ -128,9 +129,9 @@ impl HashMap {
/// Returns `true` if the hashmap contains the given key. Unlike `get`, this will not also return
/// the value associated with the key.
- ///
+ ///
/// Example:
- ///
+ ///
/// ```noir
/// if map.contains_key(7) {
/// let value = map.get(7);
@@ -140,28 +141,26 @@ impl HashMap {
/// }
/// ```
// docs:start:contains_key
- pub fn contains_key(
- self,
- key: K
- ) -> bool
+ pub fn contains_key(self, key: K) -> bool
where
K: Hash + Eq,
B: BuildHasher,
- H: Hasher {
+ H: Hasher,
+ {
// docs:end:contains_key
self.get(key).is_some()
}
/// Returns `true` if the length of the hash map is empty.
- ///
+ ///
/// Example:
- ///
+ ///
/// ```noir
/// assert(map.is_empty());
- ///
+ ///
/// map.insert(1, 2);
/// assert(!map.is_empty());
- ///
+ ///
/// map.remove(1);
/// assert(map.is_empty());
/// ```
@@ -172,14 +171,14 @@ impl HashMap {
}
/// Returns a vector of each key-value pair present in the hashmap.
- ///
+ ///
/// The length of the returned vector is always equal to the length of the hashmap.
- ///
+ ///
/// Example:
- ///
+ ///
/// ```noir
/// let entries = map.entries();
- ///
+ ///
/// // The length of a hashmap may not be compile-time known, so we
/// // need to loop over its capacity instead
/// for i in 0..map.capacity() {
@@ -209,14 +208,14 @@ impl HashMap {
}
/// Returns a vector of each key present in the hashmap.
- ///
+ ///
/// The length of the returned vector is always equal to the length of the hashmap.
- ///
+ ///
/// Example:
- ///
+ ///
/// ```noir
/// let keys = map.keys();
- ///
+ ///
/// for i in 0..keys.max_len() {
/// if i < keys.len() {
/// let key = keys.get_unchecked(i);
@@ -237,21 +236,22 @@ impl HashMap {
}
}
- let msg = f"Amount of valid elements should have been {self._len} times, but got {keys.len()}.";
+ let msg =
+ f"Amount of valid elements should have been {self._len} times, but got {keys.len()}.";
assert(keys.len() == self._len, msg);
keys
}
/// Returns a vector of each value present in the hashmap.
- ///
+ ///
/// The length of the returned vector is always equal to the length of the hashmap.
- ///
+ ///
/// Example:
- ///
+ ///
/// ```noir
/// let values = map.values();
- ///
+ ///
/// for i in 0..values.max_len() {
/// if i < values.len() {
/// let value = values.get_unchecked(i);
@@ -266,14 +266,13 @@ impl HashMap {
for slot in self._table {
if slot.is_valid() {
- let (_, value) = unsafe {
- slot.key_value_unchecked()
- };
+ let (_, value) = unsafe { slot.key_value_unchecked() };
values.push(value);
}
}
- let msg = f"Amount of valid elements should have been {self._len} times, but got {values.len()}.";
+ let msg =
+ f"Amount of valid elements should have been {self._len} times, but got {values.len()}.";
assert(values.len() == self._len, msg);
values
@@ -281,29 +280,27 @@ impl HashMap {
/// Iterates through each key-value pair of the HashMap, setting each key-value pair to the
/// result returned from the given function.
- ///
+ ///
/// Note that since keys can be mutated, the HashMap needs to be rebuilt as it is iterated
/// through. If this is not desired, use `iter_values_mut` if only values need to be mutated,
/// or `entries` if neither keys nor values need to be mutated.
- ///
+ ///
/// The iteration order is left unspecified. As a result, if two keys are mutated to become
/// equal, which of the two values that will be present for the key in the resulting map is also unspecified.
- ///
+ ///
/// Example:
- ///
+ ///
/// ```noir
/// // Add 1 to each key in the map, and double the value associated with that key.
/// map.iter_mut(|k, v| (k + 1, v * 2));
/// ```
// docs:start:iter_mut
- pub fn iter_mut(
- &mut self,
- f: fn(K, V) -> (K, V)
- )
+ pub fn iter_mut(&mut self, f: fn(K, V) -> (K, V))
where
K: Eq + Hash,
B: BuildHasher,
- H: Hasher {
+ H: Hasher,
+ {
// docs:end:iter_mut
let mut entries = self.entries();
let mut new_map = HashMap::with_hasher(self._build_hasher);
@@ -321,29 +318,27 @@ impl HashMap {
/// Iterates through the HashMap, mutating each key to the result returned from
/// the given function.
- ///
+ ///
/// Note that since keys can be mutated, the HashMap needs to be rebuilt as it is iterated
/// through. If only iteration is desired and the keys are not intended to be mutated,
/// prefer using `entries` instead.
- ///
+ ///
/// The iteration order is left unspecified. As a result, if two keys are mutated to become
/// equal, which of the two values that will be present for the key in the resulting map is also unspecified.
- ///
+ ///
/// Example:
- ///
+ ///
/// ```noir
/// // Double each key, leaving the value associated with that key untouched
/// map.iter_keys_mut(|k| k * 2);
/// ```
// docs:start:iter_keys_mut
- pub fn iter_keys_mut(
- &mut self,
- f: fn(K) -> K
- )
+ pub fn iter_keys_mut(&mut self, f: fn(K) -> K)
where
K: Eq + Hash,
B: BuildHasher,
- H: Hasher {
+ H: Hasher,
+ {
// docs:end:iter_keys_mut
let mut entries = self.entries();
let mut new_map = HashMap::with_hasher(self._build_hasher);
@@ -362,9 +357,9 @@ impl HashMap {
/// Iterates through the HashMap, applying the given function to each value and mutating the
/// value to equal the result. This function is more efficient than `iter_mut` and `iter_keys_mut`
/// because the keys are untouched and the underlying hashmap thus does not need to be reordered.
- ///
+ ///
/// Example:
- ///
+ ///
/// ```noir
/// // Halve each value
/// map.iter_values_mut(|v| v / 2);
@@ -384,9 +379,9 @@ impl HashMap {
/// Retains only the key-value pairs for which the given function returns true.
/// Any key-value pairs for which the function returns false will be removed from the map.
- ///
+ ///
/// Example:
- ///
+ ///
/// ```noir
/// map.retain(|k, v| (k != 0) & (v != 0));
/// ```
@@ -407,22 +402,22 @@ impl HashMap {
}
/// Returns the current length of this hash map.
- ///
+ ///
/// Example:
- ///
+ ///
/// ```noir
/// // This is equivalent to checking map.is_empty()
/// assert(map.len() == 0);
- ///
+ ///
/// map.insert(1, 2);
/// map.insert(3, 4);
/// map.insert(5, 6);
/// assert(map.len() == 3);
- ///
+ ///
/// // 3 was already present as a key in the hash map, so the length is unchanged
/// map.insert(3, 7);
/// assert(map.len() == 3);
- ///
+ ///
/// map.remove(1);
/// assert(map.len() == 2);
/// ```
@@ -434,15 +429,15 @@ impl HashMap {
/// Returns the maximum capacity of this hashmap. This is always equal to the capacity
/// specified in the hashmap's type.
- ///
+ ///
/// Unlike hashmaps in general purpose programming languages, hashmaps in Noir have a
/// static capacity that does not increase as the map grows larger. Thus, this capacity
/// is also the maximum possible element count that can be inserted into the hashmap.
/// Due to hash collisions (modulo the hashmap length), it is likely the actual maximum
/// element count will be lower than the full capacity.
- ///
+ ///
/// Example:
- ///
+ ///
/// ```noir
/// let empty_map: HashMap> = HashMap::default();
/// assert(empty_map.len() == 0);
@@ -455,27 +450,25 @@ impl HashMap {
}
/// Retrieves a value from the hashmap, returning `Option::none()` if it was not found.
- ///
+ ///
/// Example:
- ///
+ ///
/// ```noir
/// fn get_example(map: HashMap>) {
/// let x = map.get(12);
- ///
+ ///
/// if x.is_some() {
/// assert(x.unwrap() == 42);
/// }
/// }
/// ```
// docs:start:get
- pub fn get(
- self,
- key: K
- ) -> Option
+ pub fn get(self, key: K) -> Option
where
K: Eq + Hash,
B: BuildHasher,
- H: Hasher {
+ H: Hasher,
+ {
// docs:end:get
let mut result = Option::none();
@@ -503,24 +496,21 @@ impl HashMap {
/// Inserts a new key-value pair into the map. If the key was already in the map, its
/// previous value will be overridden with the newly provided one.
- ///
+ ///
/// Example:
- ///
+ ///
/// ```noir
/// let mut map: HashMap> = HashMap::default();
/// map.insert(12, 42);
/// assert(map.len() == 1);
/// ```
// docs:start:insert
- pub fn insert(
- &mut self,
- key: K,
- value: V
- )
+ pub fn insert(&mut self, key: K, value: V)
where
K: Eq + Hash,
B: BuildHasher,
- H: Hasher {
+ H: Hasher,
+ {
// docs:end:insert
self.assert_load_factor();
@@ -555,30 +545,28 @@ impl HashMap {
/// Removes the given key-value pair from the map. If the key was not already present
/// in the map, this does nothing.
- ///
+ ///
/// Example:
- ///
+ ///
/// ```noir
/// let mut map: HashMap> = HashMap::default();
/// map.insert(12, 42);
/// assert(!map.is_empty());
- ///
+ ///
/// map.remove(12);
/// assert(map.is_empty());
- ///
+ ///
/// // If a key was not present in the map, remove does nothing
/// map.remove(12);
/// assert(map.is_empty());
/// ```
// docs:start:remove
- pub fn remove(
- &mut self,
- key: K
- )
+ pub fn remove(&mut self, key: K)
where
K: Eq + Hash,
B: BuildHasher,
- H: Hasher {
+ H: Hasher,
+ {
// docs:end:remove
let hash = self.hash(key);
let mut should_break = false;
@@ -603,14 +591,12 @@ impl HashMap {
}
// Apply HashMap's hasher onto key to obtain pre-hash for probing.
- fn hash(
- self,
- key: K
- ) -> u32
+ fn hash(self, key: K) -> u32
where
K: Hash,
B: BuildHasher,
- H: Hasher {
+ H: Hasher,
+ {
let mut hasher = self._build_hasher.build_hasher();
key.hash(&mut hasher);
hasher.finish() as u32
@@ -619,15 +605,15 @@ impl HashMap {
// Probing scheme: quadratic function.
// We use 0.5 constant near variadic attempt and attempt^2 monomials.
// This ensures good uniformity of distribution for table sizes
- // equal to prime numbers or powers of two.
+ // equal to prime numbers or powers of two.
fn quadratic_probe(_self: Self, hash: u32, attempt: u32) -> u32 {
(hash + (attempt + attempt * attempt) / 2) % N
}
- // Amount of elements in the table in relation to available slots exceeds alpha_max.
- // To avoid a comparatively more expensive division operation
+ // Amount of elements in the table in relation to available slots exceeds alpha_max.
+ // To avoid a comparatively more expensive division operation
// we conduct cross-multiplication instead.
- // n / m >= MAX_LOAD_FACTOR_NUMERATOR / MAX_LOAD_FACTOR_DEN0MINATOR
+ // n / m >= MAX_LOAD_FACTOR_NUMERATOR / MAX_LOAD_FACTOR_DEN0MINATOR
// n * MAX_LOAD_FACTOR_DEN0MINATOR >= m * MAX_LOAD_FACTOR_NUMERATOR
fn assert_load_factor(self) {
let lhs = self._len * MAX_LOAD_FACTOR_DEN0MINATOR;
@@ -637,8 +623,8 @@ impl HashMap {
}
}
-// Equality class on HashMap has to test that they have
-// equal sets of key-value entries,
+// Equality class on HashMap has to test that they have
+// equal sets of key-value entries,
// thus one is a subset of the other and vice versa.
// docs:start:eq
impl Eq for HashMap
@@ -646,21 +632,22 @@ where
K: Eq + Hash,
V: Eq,
B: BuildHasher,
- H: Hasher {
+ H: Hasher,
+{
/// Checks if two HashMaps are equal.
- ///
+ ///
/// Example:
- ///
+ ///
/// ```noir
/// let mut map1: HashMap> = HashMap::default();
/// let mut map2: HashMap> = HashMap::default();
- ///
+ ///
/// map1.insert(1, 2);
/// map1.insert(3, 4);
- ///
+ ///
/// map2.insert(3, 4);
/// map2.insert(1, 2);
- ///
+ ///
/// assert(map1 == map2);
/// ```
fn eq(self, other: HashMap) -> bool {
@@ -695,15 +682,16 @@ where
impl Default for HashMap
where
B: BuildHasher + Default,
- H: Hasher + Default {
+ H: Hasher + Default,
+{
/// Constructs an empty HashMap.
- ///
+ ///
/// Example:
- ///
+ ///
/// ```noir
/// let hashmap: HashMap> = HashMap::default();
/// assert(hashmap.is_empty());
- /// ```
+ /// ```
fn default() -> Self {
// docs:end:default
let _build_hasher = B::default();
diff --git a/noir_stdlib/src/collections/umap.nr b/noir_stdlib/src/collections/umap.nr
index 33010e75560..9b72b6173ca 100644
--- a/noir_stdlib/src/collections/umap.nr
+++ b/noir_stdlib/src/collections/umap.nr
@@ -17,7 +17,7 @@ pub struct UHashMap {
// Amount of valid elements in the map.
_len: u32,
- _build_hasher: B
+ _build_hasher: B,
}
// Data unit in the UHashMap table.
@@ -75,7 +75,8 @@ impl UHashMap {
// docs:start:with_hasher
pub fn with_hasher(_build_hasher: B) -> Self
where
- B: BuildHasher {
+ B: BuildHasher,
+ {
// docs:end:with_hasher
let _table = &[Slot::default()];
let _len = 0;
@@ -84,7 +85,8 @@ impl UHashMap {
pub fn with_hasher_and_capacity(_build_hasher: B, capacity: u32) -> Self
where
- B: BuildHasher {
+ B: BuildHasher,
+ {
// docs:end:with_hasher
let mut _table = &[];
for _ in 0..capacity {
@@ -104,18 +106,14 @@ impl UHashMap {
// Returns true if the map contains a value for the specified key.
// docs:start:contains_key
- pub fn contains_key(
- self,
- key: K
- ) -> bool
+ pub fn contains_key(self, key: K) -> bool
where
K: Hash + Eq,
B: BuildHasher,
- H: Hasher {
+ H: Hasher,
+ {
// docs:end:contains_key
- unsafe {
- self.get(key)
- }.is_some()
+ unsafe { self.get(key) }.is_some()
}
// Returns true if the map contains no elements.
@@ -160,7 +158,8 @@ impl UHashMap {
}
}
- let msg = f"Amount of valid elements should have been {self._len} times, but got {keys.len()}.";
+ let msg =
+ f"Amount of valid elements should have been {self._len} times, but got {keys.len()}.";
assert(keys.len() == self._len, msg);
keys
@@ -180,7 +179,8 @@ impl UHashMap {
}
}
- let msg = f"Amount of valid elements should have been {self._len} times, but got {values.len()}.";
+ let msg =
+ f"Amount of valid elements should have been {self._len} times, but got {values.len()}.";
assert(values.len() == self._len, msg);
values
@@ -188,14 +188,12 @@ impl UHashMap {
// For each key-value entry applies mutator function.
// docs:start:iter_mut
- pub unconstrained fn iter_mut(
- &mut self,
- f: fn(K, V) -> (K, V)
- )
+ pub unconstrained fn iter_mut(&mut self, f: fn(K, V) -> (K, V))
where
K: Eq + Hash,
B: BuildHasher,
- H: Hasher {
+ H: Hasher,
+ {
// docs:end:iter_mut
let mut entries = self.entries();
let mut new_map = UHashMap::with_hasher(self._build_hasher);
@@ -210,14 +208,12 @@ impl UHashMap {
// For each key applies mutator function.
// docs:start:iter_keys_mut
- pub unconstrained fn iter_keys_mut(
- &mut self,
- f: fn(K) -> K
- )
+ pub unconstrained fn iter_keys_mut(&mut self, f: fn(K) -> K)
where
K: Eq + Hash,
B: BuildHasher,
- H: Hasher {
+ H: Hasher,
+ {
// docs:end:iter_keys_mut
let mut entries = self.entries();
let mut new_map = UHashMap::with_hasher(self._build_hasher);
@@ -277,14 +273,12 @@ impl UHashMap {
// Get the value by key. If it does not exist, returns none().
// docs:start:get
- pub unconstrained fn get(
- self,
- key: K
- ) -> Option
+ pub unconstrained fn get(self, key: K) -> Option
where
K: Eq + Hash,
B: BuildHasher,
- H: Hasher {
+ H: Hasher,
+ {
// docs:end:get
let mut result = Option::none();
@@ -309,15 +303,12 @@ impl UHashMap {
// Insert key-value entry. In case key was already present, value is overridden.
// docs:start:insert
- pub unconstrained fn insert(
- &mut self,
- key: K,
- value: V
- )
+ pub unconstrained fn insert(&mut self, key: K, value: V)
where
K: Eq + Hash,
B: BuildHasher,
- H: Hasher {
+ H: Hasher,
+ {
// docs:end:insert
self.try_resize();
@@ -348,7 +339,11 @@ impl UHashMap {
}
unconstrained fn try_resize(&mut self)
- where B: BuildHasher, K: Eq + Hash, H: Hasher {
+ where
+ B: BuildHasher,
+ K: Eq + Hash,
+ H: Hasher,
+ {
if self.len() + 1 >= self.capacity() / 2 {
let capacity = self.capacity() * 2;
let mut new_map = UHashMap::with_hasher_and_capacity(self._build_hasher, capacity);
@@ -362,14 +357,12 @@ impl UHashMap {
// Removes a key-value entry. If key is not present, UHashMap remains unchanged.
// docs:start:remove
- pub unconstrained fn remove(
- &mut self,
- key: K
- )
+ pub unconstrained fn remove