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
92 changes: 92 additions & 0 deletions acvm-repo/acir_field/src/field_element.rs
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,58 @@ impl<F: PrimeField> From<i128> for FieldElement<F> {
}
}

impl<F: PrimeField> From<i64> for FieldElement<F> {
fn from(a: i64) -> Self {
// Optimized: Convert directly without string conversion
if a >= 0 {
FieldElement(F::from(a as u64))
} else {
// Negative case: handle i64::MIN specially to avoid overflow
let abs_value = a.wrapping_neg() as u64;
FieldElement(-F::from(abs_value))
}
}
}

impl<F: PrimeField> From<i32> for FieldElement<F> {
fn from(a: i32) -> Self {
// Optimized: Convert directly without string conversion
if a >= 0 {
FieldElement(F::from(a as u32))
} else {
// Negative case: handle i32::MIN specially to avoid overflow
let abs_value = a.wrapping_neg() as u32;
FieldElement(-F::from(abs_value))
}
}
}

impl<F: PrimeField> From<i16> for FieldElement<F> {
fn from(a: i16) -> Self {
// Optimized: Convert directly without string conversion
if a >= 0 {
FieldElement(F::from(a as u16))
} else {
// Negative case: handle i16::MIN specially to avoid overflow
let abs_value = a.wrapping_neg() as u16;
FieldElement(-F::from(abs_value))
}
}
}

impl<F: PrimeField> From<i8> for FieldElement<F> {
fn from(a: i8) -> Self {
// Optimized: Convert directly without string conversion
if a >= 0 {
FieldElement(F::from(a as u8))
} else {
// Negative case: handle i8::MIN specially to avoid overflow
let abs_value = a.wrapping_neg() as u8;
FieldElement(-F::from(abs_value))
}
}
}

impl<T: PrimeField> Serialize for FieldElement<T> {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
Expand Down Expand Up @@ -105,12 +157,52 @@ impl<F: PrimeField> From<u32> for FieldElement<F> {
}
}

impl<F: PrimeField> From<u16> for FieldElement<F> {
fn from(a: u16) -> FieldElement<F> {
FieldElement(F::from(a))
}
}

impl<F: PrimeField> From<u8> for FieldElement<F> {
fn from(a: u8) -> FieldElement<F> {
FieldElement(F::from(a))
}
}

impl<F: PrimeField> From<bool> for FieldElement<F> {
fn from(boolean: bool) -> FieldElement<F> {
if boolean { FieldElement::one() } else { FieldElement::zero() }
}
}

impl<F: PrimeField> TryFrom<FieldElement<F>> for u128 {
type Error = ();

fn try_from(value: FieldElement<F>) -> Result<Self, Self::Error> {
match value.try_into_u128() {
Some(value) => Ok(value),
None => Err(()),
}
}
}

impl<F: PrimeField> TryFrom<FieldElement<F>> for i128 {
type Error = ();

fn try_from(value: FieldElement<F>) -> Result<Self, Self::Error> {
match value.try_into_i128() {
Some(value) => Ok(value),
None => Err(()),
}
}
}

impl<F: PrimeField> From<FieldElement<F>> for bool {
fn from(field: FieldElement<F>) -> bool {
!field.is_zero()
}
}

impl<F: PrimeField> FieldElement<F> {
/// Constructs a `FieldElement` from the underlying prime field representation.
///
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
# Seeds for failure cases proptest has generated in the past. It is
# automatically read and these particular cases re-run before any
# novel cases are generated.
#
# It is recommended to check this file in to source control so that
# everyone who runs the test benefits from these saved cases.
cc f5d63c630ba2411a6e6740f226f355929fffa298ee81b94463988ded2e96209d # shrinks to n = -128
16 changes: 3 additions & 13 deletions compiler/noirc_frontend/src/elaborator/enums.rs
Original file line number Diff line number Diff line change
Expand Up @@ -867,19 +867,9 @@ impl Elaborator<'_> {
});

let value = match constant {
Value::Bool(value) => SignedField::positive(value),
Value::Field(value) => value,
Value::I8(value) => SignedField::from_signed(value),
Value::I16(value) => SignedField::from_signed(value),
Value::I32(value) => SignedField::from_signed(value),
Value::I64(value) => SignedField::from_signed(value),
Value::U1(value) => SignedField::positive(value),
Value::U8(value) => SignedField::positive(u128::from(value)),
Value::U16(value) => SignedField::positive(u128::from(value)),
Value::U32(value) => SignedField::positive(value),
Value::U64(value) => SignedField::positive(value),
Value::U128(value) => SignedField::positive(value),
Value::Zeroed(_) => SignedField::positive(0u32),
Value::Bool(value) => value.into(),
Value::Integer(int) => int.as_signed_field(),
Value::Zeroed(_) => SignedField::zero(),
_ => {
self.push_err(ResolverError::NonIntegerGlobalUsedInPattern { location });
return Pattern::Error;
Expand Down
2 changes: 1 addition & 1 deletion compiler/noirc_frontend/src/elaborator/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -755,7 +755,7 @@ impl Elaborator<'_> {
return None;
};

let Some(global_value) = global_value.to_non_negative_signed_field() else {
let Some(global_value) = global_value.as_non_negative_signed_field() else {
let global_value = global_value.clone();
if global_value.is_integral() {
self.push_err(ResolverError::NegativeGlobalType { location, global_value });
Expand Down
17 changes: 1 addition & 16 deletions compiler/noirc_frontend/src/hir/comptime/display.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
use std::fmt::Display;

use acvm::AcirField;
use iter_extended::vecmap;
use noirc_errors::Location;

Expand Down Expand Up @@ -386,21 +385,7 @@ impl Display for ValuePrinter<'_, '_> {
let msg = if *value { "true" } else { "false" };
write!(f, "{msg}")
}
Value::Field(value) => {
// write!(f, "{value}") // This would display the Field as a number, but it doesn't match the runtime.
write!(f, "{}", value.to_field_element().to_short_hex())
}
Value::I8(value) => write!(f, "{value}"),
Value::I16(value) => write!(f, "{value}"),
Value::I32(value) => write!(f, "{value}"),
Value::I64(value) => write!(f, "{value}"),
Value::U1(false) => write!(f, "0"),
Value::U1(true) => write!(f, "1"),
Value::U8(value) => write!(f, "{value}"),
Value::U16(value) => write!(f, "{value}"),
Value::U32(value) => write!(f, "{value}"),
Value::U64(value) => write!(f, "{value}"),
Value::U128(value) => write!(f, "{value}"),
Value::Integer(int) => write!(f, "{int}"),
Value::String(value) => write!(f, "{value}"),
Value::CtString(value) => write!(f, "{value}"),
Value::FormatString(fragments, _, _) => {
Expand Down
Loading
Loading