From 7fcb8ecc9b8bdeaf127b54ed12ae133cd83db1cc Mon Sep 17 00:00:00 2001 From: feltroidprime Date: Tue, 6 Aug 2024 02:20:19 +0200 Subject: [PATCH] feat: (try) Support u384 numeric literals --- corelib/src/circuit.cairo | 1 + corelib/src/test/circuit_test.cairo | 15 ++++++++++++++ crates/cairo-lang-semantic/src/corelib.rs | 8 +++++++- .../cairo-lang-semantic/src/items/constant.rs | 20 ++++++++++++++++--- 4 files changed, 40 insertions(+), 4 deletions(-) diff --git a/corelib/src/circuit.cairo b/corelib/src/circuit.cairo index bccbe641129..bd57f889e50 100644 --- a/corelib/src/circuit.cairo +++ b/corelib/src/circuit.cairo @@ -39,6 +39,7 @@ pub struct u384 { pub limb2: u96, pub limb3: u96, } +impl NumericLiteralU384 of NumericLiteral; pub type u96 = core::internal::BoundedInt<0, 79228162514264337593543950335>; pub extern type RangeCheck96; diff --git a/corelib/src/test/circuit_test.cairo b/corelib/src/test/circuit_test.cairo index 8bfdf48f28f..0d875ecaeb8 100644 --- a/corelib/src/test/circuit_test.cairo +++ b/corelib/src/test/circuit_test.cairo @@ -13,6 +13,21 @@ fn test_u96() { assert_eq!(a, 0x123); } +#[test] +fn test_u384() { + let a: u384 = + 0x1A0111EA397FE69A4B1BA7B6434BACD764774B84F38512BF6730D2A0F6B0F6241EABFFFEB153FFFFB9FEFFFFFFFFAAAB; + assert_eq!( + a, + u384 { + limb0: 0xb153ffffb9feffffffffaaab, + limb1: 0x6730d2a0f6b0f6241eabfffe, + limb2: 0x434bacd764774b84f38512bf, + limb3: 0x1a0111ea397fe69a4b1ba7b6 + } + ); +} + #[test] fn test_try_into_u96() { assert_eq!(0x123_felt252.try_into(), Option::::Some(0x123)); diff --git a/crates/cairo-lang-semantic/src/corelib.rs b/crates/cairo-lang-semantic/src/corelib.rs index 15be1c7cbfe..1f5f148374e 100644 --- a/crates/cairo-lang-semantic/src/corelib.rs +++ b/crates/cairo-lang-semantic/src/corelib.rs @@ -860,10 +860,16 @@ pub fn validate_literal( value.to_i64().is_none() } else if ty == get_core_ty_by_name(db, "i128".into(), vec![]) { value.to_i128().is_none() + } else if ty == get_core_ty_by_name(db, "u384".into(), vec![]) { + value.is_negative() || value.bits() > 384 } else { return Err(LiteralError::InvalidTypeForLiteral(ty)); }; - if is_out_of_range { Err(LiteralError::OutOfRange(ty)) } else { Ok(()) } + if is_out_of_range { + Err(LiteralError::OutOfRange(ty)) + } else { + Ok(()) + } } /// Returns the type if the inner value of a `NonZero` type, if it is wrapped in one. diff --git a/crates/cairo-lang-semantic/src/items/constant.rs b/crates/cairo-lang-semantic/src/items/constant.rs index 58b8da11c5e..40d6ac74d8e 100644 --- a/crates/cairo-lang-semantic/src/items/constant.rs +++ b/crates/cairo-lang-semantic/src/items/constant.rs @@ -389,10 +389,9 @@ pub fn value_as_const_value( validate_literal(db.upcast(), ty, value.clone())?; let get_basic_const_value = |ty| { let u256_ty = get_core_ty_by_name(db.upcast(), "u256".into(), vec![]); + let u384_ty = get_core_ty_by_name(db.upcast(), "u384".into(), vec![]); - if ty != u256_ty { - ConstValue::Int(value.clone(), ty) - } else { + if ty == u256_ty { let u128_ty = get_core_ty_by_name(db.upcast(), "u128".into(), vec![]); let mask128 = BigInt::from(u128::MAX); let low = value & mask128; @@ -401,6 +400,21 @@ pub fn value_as_const_value( vec![(ConstValue::Int(low, u128_ty)), (ConstValue::Int(high, u128_ty))], ty, ) + } else if ty == u384_ty { + let u96_ty = get_core_ty_by_name(db.upcast(), "u96".into(), vec![]); + let mask96 = BigInt::from(2).pow(96) - 1; + + ConstValue::Struct( + vec![ + (ConstValue::Int(value & &mask96, u96_ty)), + (ConstValue::Int((value >> 96) & &mask96, u96_ty)), + (ConstValue::Int((value >> 192) & &mask96, u96_ty)), + (ConstValue::Int((value >> 288) & &mask96, u96_ty)), + ], + ty, + ) + } else { + ConstValue::Int(value.clone(), ty) } };