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