Skip to content

Commit

Permalink
Merge branch 'master' into hk/underscores_in_literals
Browse files Browse the repository at this point in the history
  • Loading branch information
kevaundray authored Dec 9, 2023
2 parents 045adfc + 4000fb2 commit c08d47a
Show file tree
Hide file tree
Showing 8 changed files with 58 additions and 49 deletions.
24 changes: 23 additions & 1 deletion acvm-repo/acir_field/src/generic_ark.rs
Original file line number Diff line number Diff line change
Expand Up @@ -272,7 +272,10 @@ impl<F: PrimeField> FieldElement<F> {
}
pub fn from_hex(hex_str: &str) -> Option<FieldElement<F>> {
let value = hex_str.strip_prefix("0x").unwrap_or(hex_str);
let hex_as_bytes = hex::decode(value).ok()?;
// Values of odd length require an additional "0" prefix
let sanitized_value =
if value.len() % 2 == 0 { value.to_string() } else { format!("0{}", value) };
let hex_as_bytes = hex::decode(sanitized_value).ok()?;
Some(FieldElement::from_be_bytes_reduce(&hex_as_bytes))
}

Expand Down Expand Up @@ -446,6 +449,25 @@ mod tests {
assert_eq!(minus_i_field_element.to_hex(), string);
}
}

#[test]
fn deserialize_even_and_odd_length_hex() {
// Test cases of (odd, even) length hex strings
let hex_strings =
vec![("0x0", "0x00"), ("0x1", "0x01"), ("0x002", "0x0002"), ("0x00003", "0x000003")];
for (i, case) in hex_strings.into_iter().enumerate() {
let i_field_element =
crate::generic_ark::FieldElement::<ark_bn254::Fr>::from(i as i128);
let odd_field_element =
crate::generic_ark::FieldElement::<ark_bn254::Fr>::from_hex(case.0).unwrap();
let even_field_element =
crate::generic_ark::FieldElement::<ark_bn254::Fr>::from_hex(case.1).unwrap();

assert_eq!(i_field_element, odd_field_element);
assert_eq!(odd_field_element, even_field_element);
}
}

#[test]
fn max_num_bits_smoke() {
let max_num_bits_bn254 = crate::generic_ark::FieldElement::<ark_bn254::Fr>::max_num_bits();
Expand Down
11 changes: 3 additions & 8 deletions compiler/noirc_evaluator/src/ssa/function_builder/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -314,16 +314,11 @@ impl FunctionBuilder {
(FieldElement::max_num_bits(), self.insert_binary(predicate, BinaryOp::Mul, pow))
};

let instruction = Instruction::Binary(Binary { lhs, rhs: pow, operator: BinaryOp::Mul });
if max_bit <= bit_size {
self.insert_instruction(instruction, None).first()
self.insert_binary(lhs, BinaryOp::Mul, pow)
} else {
let result = self.insert_instruction(instruction, None).first();
self.insert_instruction(
Instruction::Truncate { value: result, bit_size, max_bit_size: max_bit },
None,
)
.first()
let result = self.insert_binary(lhs, BinaryOp::Mul, pow);
self.insert_truncate(result, bit_size, max_bit)
}
}

Expand Down
14 changes: 13 additions & 1 deletion compiler/noirc_evaluator/src/ssa/ir/instruction.rs
Original file line number Diff line number Diff line change
Expand Up @@ -467,11 +467,23 @@ impl Instruction {
}
None
}
Instruction::Truncate { value, bit_size, .. } => {
Instruction::Truncate { value, bit_size, max_bit_size } => {
if let Some((numeric_constant, typ)) = dfg.get_numeric_constant_with_type(*value) {
let integer_modulus = 2_u128.pow(*bit_size);
let truncated = numeric_constant.to_u128() % integer_modulus;
SimplifiedTo(dfg.make_constant(truncated.into(), typ))
} else if let Value::Instruction { instruction, .. } = &dfg[dfg.resolve(*value)] {
if let Instruction::Truncate { bit_size: src_bit_size, .. } = &dfg[*instruction]
{
// If we're truncating the value to fit into the same or larger bit size then this is a noop.
if src_bit_size <= bit_size && src_bit_size <= max_bit_size {
SimplifiedTo(*value)
} else {
None
}
} else {
None
}
} else {
None
}
Expand Down
49 changes: 12 additions & 37 deletions compiler/noirc_evaluator/src/ssa/ssa_gen/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -275,16 +275,11 @@ impl<'a> FunctionContext<'a> {
let bit_width =
self.builder.numeric_constant(FieldElement::from(2_i128.pow(bit_size)), Type::field());
let sign_not = self.builder.insert_binary(one, BinaryOp::Sub, sign);
let as_field =
self.builder.insert_instruction(Instruction::Cast(input, Type::field()), None).first();
let sign_field =
self.builder.insert_instruction(Instruction::Cast(sign, Type::field()), None).first();
let as_field = self.builder.insert_cast(input, Type::field());
let sign_field = self.builder.insert_cast(sign, Type::field());
let positive_predicate = self.builder.insert_binary(sign_field, BinaryOp::Mul, as_field);
let two_complement = self.builder.insert_binary(bit_width, BinaryOp::Sub, as_field);
let sign_not_field = self
.builder
.insert_instruction(Instruction::Cast(sign_not, Type::field()), None)
.first();
let sign_not_field = self.builder.insert_cast(sign_not, Type::field());
let negative_predicate =
self.builder.insert_binary(sign_not_field, BinaryOp::Mul, two_complement);
self.builder.insert_binary(positive_predicate, BinaryOp::Add, negative_predicate)
Expand Down Expand Up @@ -315,17 +310,8 @@ impl<'a> FunctionContext<'a> {
match operator {
BinaryOpKind::Add | BinaryOpKind::Subtract => {
// Result is computed modulo the bit size
let mut result = self
.builder
.insert_instruction(
Instruction::Truncate {
value: result,
bit_size,
max_bit_size: bit_size + 1,
},
None,
)
.first();
let mut result =
self.builder.insert_truncate(result, bit_size, bit_size + 1);
result = self.builder.insert_cast(result, Type::unsigned(bit_size));

self.check_signed_overflow(result, lhs, rhs, operator, bit_size, location);
Expand All @@ -335,17 +321,7 @@ impl<'a> FunctionContext<'a> {
// Result is computed modulo the bit size
let mut result =
self.builder.insert_cast(result, Type::unsigned(2 * bit_size));
result = self
.builder
.insert_instruction(
Instruction::Truncate {
value: result,
bit_size,
max_bit_size: 2 * bit_size,
},
None,
)
.first();
result = self.builder.insert_truncate(result, bit_size, 2 * bit_size);

self.check_signed_overflow(result, lhs, rhs, operator, bit_size, location);
self.builder.insert_cast(result, result_type)
Expand Down Expand Up @@ -476,17 +452,16 @@ impl<'a> FunctionContext<'a> {

// Then we check the signed product fits in a signed integer of bit_size-bits
let not_same = self.builder.insert_binary(one, BinaryOp::Sub, same_sign);
let not_same_sign_field = self
.builder
.insert_instruction(Instruction::Cast(not_same, Type::unsigned(bit_size)), None)
.first();
let not_same_sign_field =
self.builder.insert_cast(not_same, Type::unsigned(bit_size));
let positive_maximum_with_offset =
self.builder.insert_binary(half_width, BinaryOp::Add, not_same_sign_field);
let product_overflow_check =
self.builder.insert_binary(product, BinaryOp::Lt, positive_maximum_with_offset);
self.builder.set_location(location).insert_instruction(
Instruction::Constrain(product_overflow_check, one, Some(message)),
None,
self.builder.set_location(location).insert_constrain(
product_overflow_check,
one,
Some(message),
);
}
BinaryOpKind::ShiftLeft => unreachable!("shift is not supported for signed integer"),
Expand Down
4 changes: 4 additions & 0 deletions test_programs/execution_success/strings/src/main.nr
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,10 @@ fn main(message: pub str<11>, y: Field, hex_as_string: str<4>, hex_as_field: Fie
assert(hex_as_string == "0x41");
// assert(hex_as_string != 0x41); This will fail with a type mismatch between str[4] and Field
assert(hex_as_field == 0x41);

// Single digit & odd length hex literals are valid
assert(hex_as_field == 0x041);
assert(hex_as_field != 0x1);
}

#[test]
Expand Down
3 changes: 1 addition & 2 deletions tooling/noir_js/.mocharc.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
{
"require": "ts-node/register",
"loader": "ts-node/esm",
"require": "tsx",
"extensions": ["ts", "cjs"],
"spec": [
"test/node/**/*.test.ts*"
Expand Down
1 change: 1 addition & 0 deletions tooling/noir_js/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@
"prettier": "3.0.3",
"ts-node": "^10.9.1",
"tsc-multi": "^1.1.0",
"tsx": "^4.6.2",
"typescript": "^5.2.2"
}
}
1 change: 1 addition & 0 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -3715,6 +3715,7 @@ __metadata:
prettier: 3.0.3
ts-node: ^10.9.1
tsc-multi: ^1.1.0
tsx: ^4.6.2
typescript: ^5.2.2
languageName: unknown
linkType: soft
Expand Down

0 comments on commit c08d47a

Please sign in to comment.