clear

a   hex10 )
m   hex17 )
x   call modinv$a$m )

tmp big_mul$a$x )
tmp big_mod$tmp$m )
if $tmp != 01
    
? "求逆失败"
    
pause
endif

a   int2hex0987654321012345678909876543210123456789 )
m   int2hex1000000000000000000000000000000000000037 )
x   call modinv$a$m )

tmp big_mul$a$x )
tmp big_mod$tmp$m )
if $tmp != 01
    
? "求逆失败"
    
pause
endif

a   random40 )
a   or$a00000000000000000000000000000000000000000000000000000000000000000000000000000001 )
m   shl01320 )
x   call modinv$a$m )

tmp big_mul$a$x )
tmp big_mod$tmp$m )
if $tmp != 01
    
? "求逆失败"
    
pause
endif

end

ExtEuclid:
    
prompt off
    
local a     getpara
    
local m     getpara
    
local inv   getpara

    
//     uint64_t r0 = a, r1 = m;
    
//     uint64_t s0 = 1, s1 = 0;
    
local r0    $a
    
local r1    $m
    
local s0    01
    
local s1    00
    
local tmp
    
local r2
    
local q
    
local t
    
local tmp1

    
while $r1 > 00
        
//      q = r0 / r1
        
q   big_div$r0$r1 )

        
//    /* r0, r1 = r1, r0 - q*r1 */
        
//    uint64_t r2 = r0 - q * r1;
        
//    r0 = r1;
        
//    r1 = r2;
        
tmp big_mul$q$r1 )        // tmp = q * s1
        
r2  big_sub$r0$tmp )      // r2 = r0 - (q*s1)

        
r0  $r1
        
r1  $r2

        
//  /* s0, s1 = s1, s0 - q*s1 (mod m) */
        
//  uint64_t t;
        
//  if (s0 >= q * s1)
        
//      t = s0 - q * s1;
        
//  else
        
//      t = (s0 + m - (q * s1) % m) % m;
        
tmp big_mul$q$s1 )
        
if $s0 >= $tmp
            
t       big_sub$s0$tmp )  // t = s0 - (q*s1)
        
else
            
tmp     big_mod$tmp$m )   // tmp = (q*s1) % m
            
tmp1    big_add$s0$m )    // tmp1 = s0 + m
            
tmp1    big_sub$tmp1$tmp )    // tmp1 = s0 + m - (q*s1) %m
            
t       big_mod$tmp1$m )  // tmp1 = (s0 + m - (q * s1) % m) % m
        
endif

        
//    s0 = s1;
        
//    s1 = t;
        
s0  $s1
        
s1  $t
    
loop

    
r0          big_add$r000 )

    
if $r0 == 01
        
tmp     big_mod$s0$m )
        
tmp1    setvalue$inv$tmp )
    
else
        
tmp1    setvalue$inv00 )
    
endif

    
prompt on
return $r0

ModInv:
    
local a getpara
    
local m getpara
    
local inv
    
local g call exteuclid$a$m&inv )
    
g       big_add$g00 )

    
if $g != 01
        
inv 00
    
endif

return $inv