cairo_lang_sierra/extensions/modules/
utils.rs1use std::ops::Shl;
2
3use cairo_lang_utils::casts::IntoOrPanic;
4use itertools::{chain, repeat_n};
5use num_bigint::BigInt;
6use num_traits::One;
7use starknet_types_core::felt::CAIRO_PRIME_BIGINT;
8
9use super::bounded_int::BoundedIntType;
10use super::bytes31::Bytes31Type;
11use super::int::signed::{Sint8Type, Sint16Type, Sint32Type, Sint64Type};
12use super::int::signed128::Sint128Type;
13use super::int::unsigned::{Uint8Type, Uint16Type, Uint32Type, Uint64Type};
14use super::int::unsigned128::Uint128Type;
15use super::structure::StructType;
16use crate::extensions::felt252::Felt252Type;
17use crate::extensions::lib_func::{
18 LibfuncSignature, OutputVarInfo, ParamSignature, SierraApChange, SignatureSpecializationContext,
19};
20use crate::extensions::types::TypeInfo;
21use crate::extensions::{NamedType, OutputVarReferenceInfo, SpecializationError};
22use crate::ids::{ConcreteTypeId, UserTypeId};
23use crate::program::GenericArg;
24
25pub fn reinterpret_cast_signature(
29 from_ty: ConcreteTypeId,
30 to_ty: ConcreteTypeId,
31) -> LibfuncSignature {
32 LibfuncSignature::new_non_branch_ex(
33 vec![ParamSignature::new(from_ty).with_allow_all()],
34 vec![OutputVarInfo {
35 ty: to_ty,
36 ref_info: OutputVarReferenceInfo::SameAsParam { param_idx: 0 },
37 }],
38 SierraApChange::Known { new_vars_only: true },
39 )
40}
41
42#[derive(Clone, Debug, PartialEq, Eq)]
44pub struct Range {
45 pub lower: BigInt,
47 pub upper: BigInt,
49}
50impl Range {
51 pub fn closed(lower: impl Into<BigInt>, upper: impl Into<BigInt>) -> Self {
53 Self::half_open(lower, upper.into() as BigInt + 1)
54 }
55 pub fn half_open(lower: impl Into<BigInt>, upper: impl Into<BigInt>) -> Self {
57 let result = Self { lower: lower.into(), upper: upper.into() };
58 assert!(result.lower < result.upper, "Invalid range: {:?}", result);
59 result
60 }
61 pub fn from_type_info(ty_info: &TypeInfo) -> Result<Self, SpecializationError> {
63 Ok(match (&ty_info.long_id.generic_id, &ty_info.long_id.generic_args[..]) {
64 (id, []) if *id == Felt252Type::id() => {
65 let prime: BigInt = CAIRO_PRIME_BIGINT.clone();
66 Self::half_open(1 - &prime, prime)
67 }
68 (id, []) if *id == Uint8Type::id() => Self::closed(u8::MIN, u8::MAX),
69 (id, []) if *id == Uint16Type::id() => Self::closed(u16::MIN, u16::MAX),
70 (id, []) if *id == Uint32Type::id() => Self::closed(u32::MIN, u32::MAX),
71 (id, []) if *id == Uint64Type::id() => Self::closed(u64::MIN, u64::MAX),
72 (id, []) if *id == Uint128Type::id() => Self::closed(u128::MIN, u128::MAX),
73 (id, []) if *id == Sint8Type::id() => Self::closed(i8::MIN, i8::MAX),
74 (id, []) if *id == Sint16Type::id() => Self::closed(i16::MIN, i16::MAX),
75 (id, []) if *id == Sint32Type::id() => Self::closed(i32::MIN, i32::MAX),
76 (id, []) if *id == Sint64Type::id() => Self::closed(i64::MIN, i64::MAX),
77 (id, []) if *id == Sint128Type::id() => Self::closed(i128::MIN, i128::MAX),
78 (id, []) if *id == Bytes31Type::id() => Self::half_open(0, BigInt::one().shl(248)),
79 (id, [GenericArg::Value(min), GenericArg::Value(max)])
80 if *id == BoundedIntType::id() =>
81 {
82 Self::closed(min.clone(), max.clone())
83 }
84 _ => return Err(SpecializationError::UnsupportedGenericArg),
85 })
86 }
87 pub fn from_type(
89 context: &dyn SignatureSpecializationContext,
90 ty: ConcreteTypeId,
91 ) -> Result<Self, SpecializationError> {
92 Self::from_type_info(&context.get_type_info(ty)?)
93 }
94 pub fn is_small_range(&self) -> bool {
96 self.size() <= BigInt::one().shl(128)
97 }
98 pub fn is_full_felt252_range(&self) -> bool {
100 self.size() >= *CAIRO_PRIME_BIGINT
101 }
102 pub fn size(&self) -> BigInt {
104 &self.upper - &self.lower
105 }
106 pub fn intersection(&self, other: &Self) -> Option<Self> {
110 let lower = std::cmp::max(&self.lower, &other.lower).clone();
111 let upper = std::cmp::min(&self.upper, &other.upper).clone();
112 if lower < upper { Some(Self::half_open(lower, upper)) } else { None }
113 }
114}
115
116pub fn fixed_size_array_ty(
118 context: &dyn SignatureSpecializationContext,
119 ty: ConcreteTypeId,
120 size: i16,
121) -> Result<ConcreteTypeId, SpecializationError> {
122 let args: Vec<GenericArg> = chain!(
123 [GenericArg::UserType(UserTypeId::from_string("Tuple"))],
124 repeat_n(GenericArg::Type(ty), size.into_or_panic())
125 )
126 .collect();
127 context.get_concrete_type(StructType::id(), &args)
128}