Modular exponentiation: Difference between revisions

Content deleted Content added
Chemoelectric (talk | contribs)
Aerobar (talk | contribs)
added RPL
 
(8 intermediate revisions by 3 users not shown)
Line 119:
 
=={{header|ATS}}==
{{libheader|ats2-xprelude}}
{{libheader|GMP}}
 
For its multiple precision support, you will need [https://sourceforge.net/p/chemoelectric/ats2-xprelude/ ats2-xprelude] with GNU MP support enabled.
Line 2,037 ⟶ 2,039:
a := 2988348162058574136915891421498819466320163312926952423791023078876139
b := 2351399303373464486466122544523690094744975233415544072992656881240319
write("last 40 digits = ",mod_power(a,b,(10^40)))
end
 
Line 2,231 ⟶ 2,233:
{{out}}
<pre>1527229998585248450016808958343740453059</pre>
 
=={{header|ObjectIcon}}==
{{trans|Icon and Unicon}}
 
<syntaxhighlight lang="objecticon">
# -*- ObjectIcon -*-
#
# This program is close to being an exact copy of the Icon.
#
 
import io # <-- Object Icon requires this for I/O.
 
procedure main()
local a, b # <-- Object Icon forces you to declare your variables.
 
a := 2988348162058574136915891421498819466320163312926952423791023078876139
b := 2351399303373464486466122544523690094744975233415544072992656881240319
 
# You could leave out the "io." in the call to "write" below,
# because there is some "compatibility with regular Icon" support in
# the io package.
io.write("last 40 digits = ", mod_power(a,b,(10^40)))
end
 
procedure mod_power(base, exponent, modulus)
local result
 
result := 1
while exponent > 0 do
{
if exponent % 2 = 1 then
result := (result * base) % modulus
exponent /:= 2
base := base ^ 2 % modulus
}
return result
end
</syntaxhighlight>
 
<pre>$ oiscript modular-exponentiation-OI.icn
last 40 digits = 1527229998585248450016808958343740453059
</pre>
 
=={{header|OCaml}}==
Line 2,268 ⟶ 2,312:
1527229998585248450016808958343740453059
ok
</pre>
 
=={{header|ooRexx}}==
<syntaxhighlight lang="rexx">/* Modular exponentiation */
 
numeric digits 100
say powerMod(,
2988348162058574136915891421498819466320163312926952423791023078876139,,
2351399303373464486466122544523690094744975233415544072992656881240319,,
1e40)
exit
 
powerMod: procedure
 
use strict arg base, exponent, modulus
 
exponent=exponent~d2x~x2b~strip('L','0')
result=1
base = base // modulus
do exponentPos=exponent~length to 1 by -1
if (exponent~subChar(exponentPos) == '1')
then result = (result * base) // modulus
base = (base * base) // modulus
end
return result</syntaxhighlight>
{{out}}
<pre>
1527229998585248450016808958343740453059
</pre>
 
Line 2,559 ⟶ 2,575:
 
=={{header|REXX}}==
===version 1===
This REXX program attempts to handle &nbsp; ''any'' <big> &nbsp; '''a''', &nbsp; '''b''', &nbsp; or &nbsp; '''m''', </big> &nbsp; but there are limits for any computer language.
 
For some REXXes, it's around eight million digits for any arithmetic expression or value, which puts limitations on
<br>the values of &nbsp; <big>a<sup>2</sup></big> &nbsp; or &nbsp; <big>10<sup>m</sup></big>.
 
This REXX program code has code to &nbsp; automatically &nbsp; adjust the number of decimal digits to accommodate huge
<br>numbers which are computed when raising large numbers to some arbitrary power.
<syntaxhighlight lang="rexx">/*REXX program displays the modular exponentiation of: a**b mod m */
parse arg a b m /*obtain optional args from the CL*/
if a=='' | a=="," then a= 2988348162058574136915891421498819466320163312926952423791023078876139
if b=='' | b=="," then b= 2351399303373464486466122544523690094744975233415544072992656881240319
if m ='' | m ="," then m= 40 /*Not specified? Then use default.*/
say 'a=' a " ("length(a) 'digits)' /*display the value of A (&length)*/
say 'b=' b " ("length(b) 'digits)' /* " " " " B " */
do j=1 for words(m); y= word(m, j) /*use one of the MM powers (list).*/
say copies('═', linesize() - 1) /*show a nice separator fence line*/
say 'a**b (mod 10**'y")=" powerMod(a,b,10**y) /*display the answer ───► console.*/
end /*j*/
exit 0 /*stick a fork in it, we're done. */
/*──────────────────────────────────────────────────────────────────────────────────────*/
powerMod: procedure; parse arg x,p,mm /*fast modular exponentiation code*/
parse value max(x*x, p, mm)'E0' with "E" e /*obtain the biggest of the three.*/
numeric digits max(40, e+e) /*ensure big enough to handle A².*/
$= 1 /*use this for the first value. */
do until p==0 /*perform until P is equal to zero*/
if p // 2 then $= $ * x // mm /*is P odd? (is ÷ remainder ≡ 1?)*/
p= p % 2; x= x * x // mm /*halve P; calculate x² mod n */
end /*until*/; return $ /* [↑] keep mod'ing until P=zero.*/</syntaxhighlight>
This REXX program makes use of &nbsp; '''LINESIZE''' &nbsp; REXX program (or BIF) which is used to determine the screen width (or linesize) of the terminal (console).
<br>The BIF is used to determine the width of a line separator &nbsp; (which are used to separate different outputs).
<br>The &nbsp; '''LINESIZE.REX''' &nbsp; REXX program is included here &nbsp; ──► &nbsp; [[LINESIZE.REX]].<br>
 
{{out|output|text=&nbsp; when using the inputs of: &nbsp; <tt> &nbsp; , &nbsp; , &nbsp; 40 &nbsp; 80 &nbsp; 180 &nbsp; 888 </tt>}}
<pre>
a= 2988348162058574136915891421498819466320163312926952423791023078876139 (70 digits)
b= 2351399303373464486466122544523690094744975233415544072992656881240319 (70 digits)
═══════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════
a**b (mod 10**40)= 1527229998585248450016808958343740453059
═══════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════
a**b (mod 10**80)= 53259517041910225328867076245698908287781527229998585248450016808958343740453059
═══════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════
a**b (mod 10**180)= 31857295076204937005344367438778481743660325586328069392203762862423884839076695547212682454523811053259517041910225328867076245698908287781527229998585248450016808958343740453059
═══════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════
a**b (mod 10**888)= 261284964380836515397030706363442226571397237057488951313684545241085642329943676248755716124260447188788530017182951051652748425560733974835944416069466176713156182727448301838517000343485327001656948285381173038339073779331230132340669899896448938858785362771190460312412579875349871655999446205426049662261450633448468931573506876255644749155348923523680730999869785472779116009356696816952771965930728940530517799329942590114178284009260298426735086579254282591289756840358811
822151307479352856856983393715348870715239020037962938019847992960978849852850613063177471175191444262586321233906926671000476591123695550566585083205841790404069511972417770392822283604206143472509425391114072344402850867571806031857295076204937005344367438778481743660325586328069392203762862423884839076695547212682454523811053259517041910225328867076245698908287781527229998585248450016808958343740453059
</pre>
 
===version 2===
This REXX version handles only up to 100 decimal digits.
<syntaxhighlight lang="rexx">
/* REXX Modular exponentiation */
 
say powerMod(,
numeric digits 100
2988348162058574136915891421498819466320163312926952423791023078876139,,
say powerMod(,
2351399303373464486466122544523690094744975233415544072992656881240319,,
2988348162058574136915891421498819466320163312926952423791023078876139,,
2351399303373464486466122544523690094744975233415544072992656881240319,,
1e40)
return
exit
 
powerMod: procedure
parse arg base, exponent, modulus
 
/* we need a numeric precision of twice the modulus size, */
parse arg base, exponent, modulus
/* the exponent size, or the base size, whichever is largest */
numeric digits max(2 * length(format(modulus, , , 0)),,
length(format(exponent, , , 0)), length(format(base, , , 0)))
 
result = 1
exponent = strip(x2b(d2x(exponent)), 'L', '0')
base = base // modulus
result = 1
do while exponent > 0
base = base // modulus
do exponentPos=length( if exponent) to// 12 by= -1 then
result = result * base // modulus
if substr(exponent, exponentPos, 1) = '1'
then resultbase = (resultbase * base) // modulus
base = (baseexponent *= base)exponent //% modulus2
end
return result</syntaxhighlight>
</syntaxhighlight>
{{out}}
<pre>
1527229998585248450016808958343740453059
</pre>
 
=={{header|RPL}}==
{{works with|RPL|HP-49C}}
10 40 ^ MODSTO
2988348162058574136915891421498819466320163312926952423791023078876139
2351399303373464486466122544523690094744975233415544072992656881240319
POWMOD
{{out}}
<pre>
1: 1527229998585248450016808958343740453059
</pre>
 
Line 2,976 ⟶ 2,957:
=={{header|Wren}}==
{{libheader|Wren-big}}
<syntaxhighlight lang="ecmascriptwren">import "./big" for BigInt
 
var a = BigInt.new("2988348162058574136915891421498819466320163312926952423791023078876139")
Line 3,001 ⟶ 2,982:
1,527,229,998,585,248,450,016,808,958,343,740,453,059
</pre>
 
=={{header|zsh}}==
<syntaxhighlight lang="zsh">
#!/bin/zsh
 
#
# I use expr from GNU coreutils.
EXPR=`which expr`
#
# One could use GNU bc or any other such program that is capable of
# handling the large integers.
#
 
unset PATH # Besides shell commands, the script uses ONLY
# the expression calculator.
 
mod_power()
{
local base="${1}"
local exponent="${2}"
local modulus="${3}"
local result=1
 
while [[ `${EXPR} ${exponent} '>' 0` != 0 ]] ; do
if [[ `${EXPR} '(' ${exponent} '%' 2 ')' '=' 1` != 0 ]] ; then
result=`${EXPR} '(' ${result} '*' ${base} ')' '%' ${modulus}`
fi
exponent=`${EXPR} ${exponent} / 2`
base=`${EXPR} '(' ${base} '*' ${base} ')' '%' ${modulus}`
done
echo ${result}
}
 
a=2988348162058574136915891421498819466320163312926952423791023078876139
b=2351399303373464486466122544523690094744975233415544072992656881240319
 
# One followed by 40 zeros.
modulus=10000000000000000000000000000000000000000
 
# Or the following will work, as long as the modulus is at least
# 10**40. :)))))
#modulus=$(mod_power 10 40 1000000000000000000000000000000000000000000000000000000000000)
 
echo $(mod_power ${a} ${b} ${modulus})
 
exit 0
</syntaxhighlight>
 
{{out}}
<pre>$ zsh ./modular-exponentiation.zsh
1527229998585248450016808958343740453059</pre>