cairo_lang_sierra/extensions/modules/int/
unsigned512.rs

1use super::unsigned128::{U128MulGuaranteeType, Uint128Type};
2use crate::define_libfunc_hierarchy;
3use crate::extensions::lib_func::{
4    LibfuncSignature, OutputVarInfo, ParamSignature, SierraApChange, SignatureSpecializationContext,
5};
6use crate::extensions::modules::get_u256_type;
7use crate::extensions::non_zero::nonzero_ty;
8use crate::extensions::range_check::RangeCheckType;
9use crate::extensions::structure::StructType;
10use crate::extensions::{
11    NamedType, NoGenericArgsGenericLibfunc, OutputVarReferenceInfo, SpecializationError,
12};
13use crate::ids::{ConcreteTypeId, UserTypeId};
14use crate::program::GenericArg;
15
16define_libfunc_hierarchy! {
17    pub enum Uint512Libfunc {
18        DivModU256(Uint512DivmodU256Libfunc),
19    }, Uint512Concrete
20}
21
22// Divmod.
23#[derive(Default)]
24pub struct Uint512DivmodU256Libfunc;
25impl NoGenericArgsGenericLibfunc for Uint512DivmodU256Libfunc {
26    const STR_ID: &'static str = "u512_safe_divmod_by_u256";
27
28    fn specialize_signature(
29        &self,
30        context: &dyn SignatureSpecializationContext,
31    ) -> Result<LibfuncSignature, SpecializationError> {
32        let u256_ty = get_u256_type(context)?;
33        let u512_ty = get_u512_type(context)?;
34        let range_check_type = context.get_concrete_type(RangeCheckType::id(), &[])?;
35        let guarantee_ty = context.get_concrete_type(U128MulGuaranteeType::id(), &[])?;
36        let guarantee_output_info =
37            OutputVarInfo { ty: guarantee_ty, ref_info: OutputVarReferenceInfo::SimpleDerefs };
38        Ok(LibfuncSignature::new_non_branch_ex(
39            vec![
40                ParamSignature::new(range_check_type.clone()).with_allow_add_const(),
41                ParamSignature::new(u512_ty.clone()),
42                ParamSignature::new(nonzero_ty(context, &u256_ty)?),
43            ],
44            vec![
45                OutputVarInfo::new_builtin(range_check_type, 0),
46                OutputVarInfo { ty: u512_ty, ref_info: OutputVarReferenceInfo::SimpleDerefs },
47                OutputVarInfo { ty: u256_ty, ref_info: OutputVarReferenceInfo::SimpleDerefs },
48                guarantee_output_info.clone(),
49                guarantee_output_info.clone(),
50                guarantee_output_info.clone(),
51                guarantee_output_info.clone(),
52                guarantee_output_info,
53            ],
54            SierraApChange::Known { new_vars_only: false },
55        ))
56    }
57}
58
59/// Helper for u512 type def.
60fn get_u512_type(
61    context: &dyn SignatureSpecializationContext,
62) -> Result<ConcreteTypeId, SpecializationError> {
63    let u128_ty = context.get_concrete_type(Uint128Type::id(), &[])?;
64    context.get_concrete_type(StructType::id(), &[
65        GenericArg::UserType(UserTypeId::from_string("core::integer::u512")),
66        GenericArg::Type(u128_ty.clone()),
67        GenericArg::Type(u128_ty.clone()),
68        GenericArg::Type(u128_ty.clone()),
69        GenericArg::Type(u128_ty),
70    ])
71}