@@ -25,9 +25,9 @@ use cairo_lang_casm::{
25
25
use core:: any:: Any ;
26
26
use core:: ops:: Shl ;
27
27
28
- use num_bigint:: BigUint ;
29
- use num_integer:: Integer ;
30
- use num_traits:: ToPrimitive ;
28
+ use num_bigint:: { BigInt , BigUint } ;
29
+ use num_integer:: { ExtendedGcd , Integer } ;
30
+ use num_traits:: { Signed , ToPrimitive } ;
31
31
32
32
/// Execution scope for constant memory allocation.
33
33
struct MemoryExecScope {
@@ -242,6 +242,30 @@ impl Cairo1HintProcessor {
242
242
vm, dividend0, dividend1, dividend2, dividend3, divisor0, divisor1, quotient0,
243
243
quotient1, quotient2, quotient3, remainder0, remainder1,
244
244
) ,
245
+ Hint :: Core ( CoreHintBase :: Core ( CoreHint :: U256InvModN {
246
+ b0,
247
+ b1,
248
+ n0,
249
+ n1,
250
+ g0_or_no_inv,
251
+ g1_option,
252
+ s_or_r0,
253
+ s_or_r1,
254
+ t_or_k0,
255
+ t_or_k1,
256
+ } ) ) => self . u256_inv_mod_n (
257
+ vm,
258
+ b0,
259
+ b1,
260
+ n0,
261
+ n1,
262
+ g0_or_no_inv,
263
+ g1_option,
264
+ s_or_r0,
265
+ s_or_r1,
266
+ t_or_k0,
267
+ t_or_k1,
268
+ ) ,
245
269
246
270
hint => Err ( HintError :: UnknownHint (
247
271
format ! ( "{:?}" , hint) . into_boxed_str ( ) ,
@@ -397,7 +421,6 @@ impl Cairo1HintProcessor {
397
421
dict_manager_exec_scope. finalize_segment ( vm, dict_address)
398
422
}
399
423
400
- #[ allow( clippy:: too_many_arguments) ]
401
424
#[ allow( clippy:: too_many_arguments) ]
402
425
fn uint256_div_mod (
403
426
& self ,
@@ -1076,6 +1099,77 @@ impl Cairo1HintProcessor {
1076
1099
)
1077
1100
. map_err ( HintError :: from)
1078
1101
}
1102
+
1103
+ #[ allow( clippy:: too_many_arguments) ]
1104
+ fn u256_inv_mod_n (
1105
+ & self ,
1106
+ vm : & mut VirtualMachine ,
1107
+ b0 : & ResOperand ,
1108
+ b1 : & ResOperand ,
1109
+ n0 : & ResOperand ,
1110
+ n1 : & ResOperand ,
1111
+ g0_or_no_inv : & CellRef ,
1112
+ g1_option : & CellRef ,
1113
+ s_or_r0 : & CellRef ,
1114
+ s_or_r1 : & CellRef ,
1115
+ t_or_k0 : & CellRef ,
1116
+ t_or_k1 : & CellRef ,
1117
+ ) -> Result < ( ) , HintError > {
1118
+ let pow_2_128 = BigInt :: from ( u128:: MAX ) + 1u32 ;
1119
+ let b0 = get_val ( vm, b0) ?. to_bigint ( ) ;
1120
+ let b1 = get_val ( vm, b1) ?. to_bigint ( ) ;
1121
+ let n0 = get_val ( vm, n0) ?. to_bigint ( ) ;
1122
+ let n1 = get_val ( vm, n1) ?. to_bigint ( ) ;
1123
+ let b: BigInt = b0. clone ( ) + b1. clone ( ) . shl ( 128 ) ;
1124
+ let n: BigInt = n0 + n1. shl ( 128 ) ;
1125
+ let ExtendedGcd {
1126
+ gcd : mut g,
1127
+ x : _,
1128
+ y : mut r,
1129
+ } = n. extended_gcd ( & b) ;
1130
+ if n == 1 . into ( ) {
1131
+ vm. insert_value ( cell_ref_to_relocatable ( s_or_r0, vm) ?, Felt252 :: from ( b0) ) ?;
1132
+ vm. insert_value ( cell_ref_to_relocatable ( s_or_r1, vm) ?, Felt252 :: from ( b1) ) ?;
1133
+ vm. insert_value ( cell_ref_to_relocatable ( t_or_k0, vm) ?, Felt252 :: from ( 1 ) ) ?;
1134
+ vm. insert_value ( cell_ref_to_relocatable ( t_or_k1, vm) ?, Felt252 :: from ( 0 ) ) ?;
1135
+ vm. insert_value ( cell_ref_to_relocatable ( g0_or_no_inv, vm) ?, Felt252 :: from ( 1 ) ) ?;
1136
+ vm. insert_value ( cell_ref_to_relocatable ( g1_option, vm) ?, Felt252 :: from ( 0 ) ) ?;
1137
+ } else if g != 1 . into ( ) {
1138
+ // This makes sure `g0_or_no_inv` is always non-zero in the no inverse case.
1139
+ if g. is_even ( ) {
1140
+ g = 2u32 . into ( ) ;
1141
+ }
1142
+ let ( limb1, limb0) = ( & b / & g) . div_rem ( & pow_2_128) ;
1143
+ vm. insert_value ( cell_ref_to_relocatable ( s_or_r0, vm) ?, Felt252 :: from ( limb0) ) ?;
1144
+ vm. insert_value ( cell_ref_to_relocatable ( s_or_r1, vm) ?, Felt252 :: from ( limb1) ) ?;
1145
+ let ( limb1, limb0) = ( & n / & g) . div_rem ( & pow_2_128) ;
1146
+ vm. insert_value ( cell_ref_to_relocatable ( t_or_k0, vm) ?, Felt252 :: from ( limb0) ) ?;
1147
+ vm. insert_value ( cell_ref_to_relocatable ( t_or_k1, vm) ?, Felt252 :: from ( limb1) ) ?;
1148
+ let ( limb1, limb0) = g. div_rem ( & pow_2_128) ;
1149
+ vm. insert_value (
1150
+ cell_ref_to_relocatable ( g0_or_no_inv, vm) ?,
1151
+ Felt252 :: from ( limb0) ,
1152
+ ) ?;
1153
+ vm. insert_value (
1154
+ cell_ref_to_relocatable ( g1_option, vm) ?,
1155
+ Felt252 :: from ( limb1) ,
1156
+ ) ?;
1157
+ } else {
1158
+ r %= & n;
1159
+ if r. is_negative ( ) {
1160
+ r += & n;
1161
+ }
1162
+ let k: BigInt = ( & r * b - 1 ) / n;
1163
+ let ( limb1, limb0) = r. div_rem ( & pow_2_128) ;
1164
+ vm. insert_value ( cell_ref_to_relocatable ( s_or_r0, vm) ?, Felt252 :: from ( limb0) ) ?;
1165
+ vm. insert_value ( cell_ref_to_relocatable ( s_or_r1, vm) ?, Felt252 :: from ( limb1) ) ?;
1166
+ let ( limb1, limb0) = k. div_rem ( & pow_2_128) ;
1167
+ vm. insert_value ( cell_ref_to_relocatable ( t_or_k0, vm) ?, Felt252 :: from ( limb0) ) ?;
1168
+ vm. insert_value ( cell_ref_to_relocatable ( t_or_k1, vm) ?, Felt252 :: from ( limb1) ) ?;
1169
+ vm. insert_value ( cell_ref_to_relocatable ( g0_or_no_inv, vm) ?, Felt252 :: from ( 0 ) ) ?;
1170
+ }
1171
+ Ok ( ( ) )
1172
+ }
1079
1173
}
1080
1174
1081
1175
impl HintProcessorLogic for Cairo1HintProcessor {
0 commit comments