It might be a bit slow, but I think it's linear time.
j
# my attempt at modular exponentiation with # arbitrary precision binary numbers # in perl :-) # consider this (C) 2000 John M Hanna under the GPL sub badd { # binary add local($a,$b,$r,$c)=@_; while($a || $b) { $c=chop($a) + chop($b) + $c; if($c & 1) { $r="1$r"; } else { $r="0$r"; } $c>>=1; } $r="1$r" if $c; $r; } sub bsub { # binary subtract local($a,$b,$r,$c)=@_; while($a || $b) { $c=chop($a) - chop($b) - $c; if($c==0) { $r="0$r"; } elsif($c == 1) { $r="1$r"; $c=0; } elsif($c == -1) { $r="1$r"; $c=1; } else { $r="0$r"; $c=1; } return '' if !$a && ($b || $c); } $r=~s/^0+//; $r='0' unless $r; $r; } sub bmul { # binary multiply local($a,$b,$r,$p)=@_; while($a) { if(chop($a) eq '1') { $r=&badd($r,"$b$p"); } $p.='0'; } $r; } sub bmod { # binary modulo local($a,$m,$p,$lm,$d)=@_; $lm=length($m); while($a) { return $a if length($a)<$lm; $p=substr($a,0,$lm); $a=substr($a,$lm); $d=&bsub($p,$m); return $p if $d eq '' && $a eq ''; unless(length($d)) { $p.=substr($a,0,1); $a=substr($a,1); $d=&bsub($p,$m); } $a="$d$a"; $a=~s/^0+//; } '0'; } sub bmodexp { # binary modular exponentiation # based on http://www.frontiernet.net/~jmb184/interests/sci.crypt/sma +ll_num_expont.html local($x,$y,$m,$r)=@_; $r=1; while($y) { if(chop($y) eq '1') { $r=&bmod(&bmul($r,$x),$m); } $x=&bmod(&bmul($x,$x),$m); } return $r; } sub i2b { # convert integer to binary local($i,$r)=@_; while($i) { if($i & 1) { $r="1$r";} else {$r="0$r";} $i>>=1; } $r || '0'; } # an example where I know the results print &bmodexp(&i2b(123),&i2b(17),&i2b(3233)),"=?",&i2b(855),"\n"; print &bmodexp(&i2b(855),&i2b(2753),&i2b(3233)),"=?",&i2b(123),"\n";
|
---|