cairo_lang_sierra/extensions/modules/int/
signed.rs1use std::marker::PhantomData;
2
3use super::signed128::Sint128Type;
4use super::unsigned::{Uint8Type, Uint16Type, Uint32Type, Uint64Type};
5use super::{
6 IntConstLibfunc, IntEqualLibfunc, IntFromFelt252Libfunc, IntMulTraits,
7 IntOperationConcreteLibfunc, IntOperator, IntToFelt252Libfunc, IntTraits, IntType,
8 IntWideMulLibfunc,
9};
10use crate::define_libfunc_hierarchy;
11use crate::extensions::lib_func::{
12 BranchSignature, DeferredOutputKind, LibfuncSignature, OutputVarInfo, ParamSignature,
13 SierraApChange, SignatureSpecializationContext, SpecializationContext,
14};
15use crate::extensions::range_check::RangeCheckType;
16use crate::extensions::{
17 GenericLibfunc, NamedType, NoGenericArgsGenericLibfunc, OutputVarReferenceInfo,
18 SpecializationError,
19};
20use crate::ids::{GenericLibfuncId, GenericTypeId};
21use crate::program::GenericArg;
22
23pub trait SintTraits: IntTraits {
25 const OVERFLOWING_ADD: &'static str;
27 const OVERFLOWING_SUB: &'static str;
29 const DIFF: &'static str;
32 const UNSIGNED_INT_TYPE: GenericTypeId;
34}
35
36define_libfunc_hierarchy! {
37 pub enum SintLibfunc<TSintTraits: SintTraits + IntMulTraits> {
38 Const(IntConstLibfunc<TSintTraits>),
39 Equal(IntEqualLibfunc<TSintTraits>),
40 ToFelt252(IntToFelt252Libfunc<TSintTraits>),
41 FromFelt252(IntFromFelt252Libfunc<TSintTraits>),
42 Operation(SintOperationLibfunc<TSintTraits>),
43 Diff(SintDiffLibfunc<TSintTraits>),
44 WideMul(IntWideMulLibfunc<TSintTraits>),
45 }, SintConcrete
46}
47
48pub struct SintOperationLibfunc<TSintTraits: SintTraits> {
50 pub operator: IntOperator,
51 _phantom: PhantomData<TSintTraits>,
52}
53impl<TSintTraits: SintTraits> SintOperationLibfunc<TSintTraits> {
54 const OVERFLOWING_ADD: &'static str = TSintTraits::OVERFLOWING_ADD;
55 const OVERFLOWING_SUB: &'static str = TSintTraits::OVERFLOWING_SUB;
56 fn new(operator: IntOperator) -> Option<Self> {
57 Some(Self { operator, _phantom: PhantomData })
58 }
59}
60impl<TSintTraits: SintTraits> GenericLibfunc for SintOperationLibfunc<TSintTraits> {
61 type Concrete = IntOperationConcreteLibfunc;
62
63 fn supported_ids() -> Vec<GenericLibfuncId> {
64 vec![
65 GenericLibfuncId::from(Self::OVERFLOWING_ADD),
66 GenericLibfuncId::from(Self::OVERFLOWING_SUB),
67 ]
68 }
69
70 fn by_id(id: &GenericLibfuncId) -> Option<Self> {
71 match id.0.as_str() {
72 id if id == Self::OVERFLOWING_ADD => Self::new(IntOperator::OverflowingAdd),
73 id if id == Self::OVERFLOWING_SUB => Self::new(IntOperator::OverflowingSub),
74 _ => None,
75 }
76 }
77
78 fn specialize_signature(
79 &self,
80 context: &dyn SignatureSpecializationContext,
81 args: &[GenericArg],
82 ) -> Result<LibfuncSignature, SpecializationError> {
83 if !args.is_empty() {
84 return Err(SpecializationError::WrongNumberOfGenericArgs);
85 }
86 let ty = context.get_concrete_type(TSintTraits::GENERIC_TYPE_ID, &[])?;
87 let range_check_type = context.get_concrete_type(RangeCheckType::id(), &[])?;
88
89 let ty_param = ParamSignature::new(ty.clone());
90 let rc_output_info = OutputVarInfo::new_builtin(range_check_type.clone(), 0);
91 let wrapping_result_info = OutputVarInfo {
92 ty: ty.clone(),
93 ref_info: OutputVarReferenceInfo::Deferred(DeferredOutputKind::Generic),
94 };
95 Ok(LibfuncSignature {
96 param_signatures: vec![
97 ParamSignature::new(range_check_type).with_allow_add_const(),
98 ty_param.clone(),
99 ty_param,
100 ],
101 branch_signatures: vec![
102 BranchSignature {
104 vars: vec![
105 rc_output_info.clone(),
106 OutputVarInfo { ty, ref_info: OutputVarReferenceInfo::SimpleDerefs },
107 ],
108 ap_change: SierraApChange::Known { new_vars_only: false },
109 },
110 BranchSignature {
112 vars: vec![rc_output_info.clone(), wrapping_result_info.clone()],
113 ap_change: SierraApChange::Known { new_vars_only: false },
114 },
115 BranchSignature {
117 vars: vec![rc_output_info, wrapping_result_info],
118 ap_change: SierraApChange::Known { new_vars_only: false },
119 },
120 ],
121 fallthrough: Some(0),
122 })
123 }
124
125 fn specialize(
126 &self,
127 context: &dyn SpecializationContext,
128 args: &[GenericArg],
129 ) -> Result<Self::Concrete, SpecializationError> {
130 Ok(IntOperationConcreteLibfunc {
131 operator: self.operator,
132 signature: self.specialize_signature(context.upcast(), args)?,
133 })
134 }
135}
136
137#[derive(Default)]
139pub struct SintDiffLibfunc<TSintTraits: SintTraits> {
140 _phantom: PhantomData<TSintTraits>,
141}
142impl<TSintTraits: SintTraits> NoGenericArgsGenericLibfunc for SintDiffLibfunc<TSintTraits> {
143 const STR_ID: &'static str = TSintTraits::DIFF;
144
145 fn specialize_signature(
146 &self,
147 context: &dyn SignatureSpecializationContext,
148 ) -> Result<LibfuncSignature, SpecializationError> {
149 let signed_ty = context.get_concrete_type(TSintTraits::GENERIC_TYPE_ID, &[])?;
150 let unsigned_ty = context.get_concrete_type(TSintTraits::UNSIGNED_INT_TYPE, &[])?;
151 let range_check_type = context.get_concrete_type(RangeCheckType::id(), &[])?;
152
153 let signed_ty_param = ParamSignature::new(signed_ty);
154 let rc_output_info = OutputVarInfo::new_builtin(range_check_type.clone(), 0);
155 let wrapping_result_ref_info = if TSintTraits::IS_SMALL {
156 OutputVarReferenceInfo::Deferred(DeferredOutputKind::Generic)
157 } else {
158 OutputVarReferenceInfo::NewTempVar { idx: 0 }
159 };
160 Ok(LibfuncSignature {
161 param_signatures: vec![
162 ParamSignature::new(range_check_type).with_allow_add_const(),
163 signed_ty_param.clone(),
164 signed_ty_param,
165 ],
166 branch_signatures: vec![
167 BranchSignature {
169 vars: vec![
170 rc_output_info.clone(),
171 OutputVarInfo {
172 ty: unsigned_ty.clone(),
173 ref_info: OutputVarReferenceInfo::NewTempVar { idx: 0 },
174 },
175 ],
176 ap_change: SierraApChange::Known { new_vars_only: false },
177 },
178 BranchSignature {
180 vars: vec![
181 rc_output_info,
182 OutputVarInfo { ty: unsigned_ty, ref_info: wrapping_result_ref_info },
183 ],
184 ap_change: SierraApChange::Known { new_vars_only: false },
185 },
186 ],
187 fallthrough: Some(0),
188 })
189 }
190}
191
192#[derive(Default)]
193pub struct Sint8Traits;
194
195impl SintTraits for Sint8Traits {
196 const OVERFLOWING_ADD: &'static str = "i8_overflowing_add_impl";
197 const OVERFLOWING_SUB: &'static str = "i8_overflowing_sub_impl";
198 const DIFF: &'static str = "i8_diff";
199 const UNSIGNED_INT_TYPE: GenericTypeId = <Uint8Type as NamedType>::ID;
200}
201
202impl IntTraits for Sint8Traits {
203 type IntType = i8;
204 const GENERIC_TYPE_ID: GenericTypeId = GenericTypeId::new_inline("i8");
205 const IS_SMALL: bool = true;
206 const CONST: &'static str = "i8_const";
207 const EQUAL: &'static str = "i8_eq";
208 const TO_FELT252: &'static str = "i8_to_felt252";
209 const TRY_FROM_FELT252: &'static str = "i8_try_from_felt252";
210}
211
212impl IntMulTraits for Sint8Traits {
213 const WIDE_MUL: &'static str = "i8_wide_mul";
214 const WIDE_MUL_RES_TYPE_ID: GenericTypeId = <Sint16Type as NamedType>::ID;
215}
216
217pub type Sint8Type = IntType<Sint8Traits>;
219pub type Sint8Libfunc = SintLibfunc<Sint8Traits>;
220pub type Sint8Concrete = <Sint8Libfunc as GenericLibfunc>::Concrete;
221
222#[derive(Default)]
223pub struct Sint16Traits;
224
225impl SintTraits for Sint16Traits {
226 const OVERFLOWING_ADD: &'static str = "i16_overflowing_add_impl";
227 const OVERFLOWING_SUB: &'static str = "i16_overflowing_sub_impl";
228 const DIFF: &'static str = "i16_diff";
229 const UNSIGNED_INT_TYPE: GenericTypeId = <Uint16Type as NamedType>::ID;
230}
231
232impl IntTraits for Sint16Traits {
233 type IntType = i16;
234 const GENERIC_TYPE_ID: GenericTypeId = GenericTypeId::new_inline("i16");
235 const IS_SMALL: bool = true;
236 const CONST: &'static str = "i16_const";
237 const EQUAL: &'static str = "i16_eq";
238 const TO_FELT252: &'static str = "i16_to_felt252";
239 const TRY_FROM_FELT252: &'static str = "i16_try_from_felt252";
240}
241
242impl IntMulTraits for Sint16Traits {
243 const WIDE_MUL: &'static str = "i16_wide_mul";
244 const WIDE_MUL_RES_TYPE_ID: GenericTypeId = <Sint32Type as NamedType>::ID;
245}
246
247pub type Sint16Type = IntType<Sint16Traits>;
249pub type Sint16Libfunc = SintLibfunc<Sint16Traits>;
250pub type Sint16Concrete = <Sint16Libfunc as GenericLibfunc>::Concrete;
251
252#[derive(Default)]
253pub struct Sint32Traits;
254
255impl SintTraits for Sint32Traits {
256 const OVERFLOWING_ADD: &'static str = "i32_overflowing_add_impl";
257 const OVERFLOWING_SUB: &'static str = "i32_overflowing_sub_impl";
258 const DIFF: &'static str = "i32_diff";
259 const UNSIGNED_INT_TYPE: GenericTypeId = <Uint32Type as NamedType>::ID;
260}
261
262impl IntTraits for Sint32Traits {
263 type IntType = i32;
264 const GENERIC_TYPE_ID: GenericTypeId = GenericTypeId::new_inline("i32");
265 const IS_SMALL: bool = true;
266 const CONST: &'static str = "i32_const";
267 const EQUAL: &'static str = "i32_eq";
268 const TO_FELT252: &'static str = "i32_to_felt252";
269 const TRY_FROM_FELT252: &'static str = "i32_try_from_felt252";
270}
271
272impl IntMulTraits for Sint32Traits {
273 const WIDE_MUL: &'static str = "i32_wide_mul";
274 const WIDE_MUL_RES_TYPE_ID: GenericTypeId = <Sint64Type as NamedType>::ID;
275}
276
277pub type Sint32Type = IntType<Sint32Traits>;
279pub type Sint32Libfunc = SintLibfunc<Sint32Traits>;
280pub type Sint32Concrete = <Sint32Libfunc as GenericLibfunc>::Concrete;
281
282#[derive(Default)]
283pub struct Sint64Traits;
284
285impl SintTraits for Sint64Traits {
286 const OVERFLOWING_ADD: &'static str = "i64_overflowing_add_impl";
287 const OVERFLOWING_SUB: &'static str = "i64_overflowing_sub_impl";
288 const DIFF: &'static str = "i64_diff";
289 const UNSIGNED_INT_TYPE: GenericTypeId = <Uint64Type as NamedType>::ID;
290}
291
292impl IntTraits for Sint64Traits {
293 type IntType = i64;
294 const GENERIC_TYPE_ID: GenericTypeId = GenericTypeId::new_inline("i64");
295 const IS_SMALL: bool = true;
296 const CONST: &'static str = "i64_const";
297 const EQUAL: &'static str = "i64_eq";
298 const TO_FELT252: &'static str = "i64_to_felt252";
299 const TRY_FROM_FELT252: &'static str = "i64_try_from_felt252";
300}
301
302impl IntMulTraits for Sint64Traits {
303 const WIDE_MUL: &'static str = "i64_wide_mul";
304 const WIDE_MUL_RES_TYPE_ID: GenericTypeId = <Sint128Type as NamedType>::ID;
305}
306
307pub type Sint64Type = IntType<Sint64Traits>;
309pub type Sint64Libfunc = SintLibfunc<Sint64Traits>;
310pub type Sint64Concrete = <Sint64Libfunc as GenericLibfunc>::Concrete;