Task: Montgomery reduction







Python: class Montgomery:
    BASE = 2

    def __init__(self, m):
        self.m = m
        self.n = m.bit_length()
        self.rrm = (1 << (self.n * 2)) % m

    def reduce(self, t):
        a = t
        for i in xrange(self.n):
            if (a & 1) == 1:
                a = a + self.m
            a = a >> 1
        if a >= self.m:
            a = a - self.m
        return a


m = 750791094644726559640638407699
x1 = 540019781128412936473322405310
x2 = 515692107665463680305819378593

mont = Montgomery(m)
t1 = x1 * mont.rrm
t2 = x2 * mont.rrm

r1 = mont.reduce(t1)
r2 = mont.reduce(t2)
r = 1 << mont.n

print "b : ", Montgomery.BASE
print "n : ", mont.n
print "r : ", r
print "m : ", mont.m
print "t1: ", t1
print "t2: ", t2
print "r1: ", r1
print "r2: ", r2
print
print "Original x1       :", x1
print "Recovered from r1 :", mont.reduce(r1)
print "Original x2       :", x2
print "Recovered from r2 :", mont.reduce(r2)

print "\nMontgomery computation of x1 ^ x2 mod m:"
prod = mont.reduce(mont.rrm)
base = mont.reduce(x1 * mont.rrm)
exp = x2
while exp.bit_length() > 0:
    if (exp & 1) == 1:
        prod = mont.reduce(prod * base)
    exp = exp >> 1
    base = mont.reduce(base * base)
print mont.reduce(prod)
print "\nAlternate computation of x1 ^ x2 mod m :"
print pow(x1, x2, m)


VB: Imports System.Numerics
Imports System.Runtime.CompilerServices

Module Module1

    <Extension()>
    Function BitLength(v As BigInteger) As Integer
        If v < 0 Then
            v *= -1
        End If

        Dim result = 0
        While v > 0
            v >>= 1
            result += 1
        End While
        Return result
    End Function

    Structure Montgomery
        Shared ReadOnly BASE = 2
        Dim m As BigInteger
        Dim rrm As BigInteger
        Dim n As Integer

        Sub New(m As BigInteger)
            If m < 0 OrElse m.IsEven Then
                Throw New ArgumentException()
            End If

            Me.m = m
            n = m.BitLength
            rrm = (BigInteger.One << (n * 2)) Mod m
        End Sub

        Function Reduce(t As BigInteger) As BigInteger
            Dim a = t
            For i = 1 To n
                If Not a.IsEven Then
                    a += m
                End If
                a >>= 1
            Next
            If a >= m Then
                a -= m
            End If
            Return a
        End Function
    End Structure

    Sub Main()
        Dim m = BigInteger.Parse("750791094644726559640638407699")
        Dim x1 = BigInteger.Parse("540019781128412936473322405310")
        Dim x2 = BigInteger.Parse("515692107665463680305819378593")

        Dim mont As New Montgomery(m)
        Dim t1 = x1 * mont.rrm
        Dim t2 = x2 * mont.rrm

        Dim r1 = mont.Reduce(t1)
        Dim r2 = mont.Reduce(t2)
        Dim r = BigInteger.One << mont.n

        Console.WriteLine("b :  {0}", Montgomery.BASE)
        Console.WriteLine("n :  {0}", mont.n)
        Console.WriteLine("r :  {0}", r)
        Console.WriteLine("m :  {0}", mont.m)
        Console.WriteLine("t1:  {0}", t1)
        Console.WriteLine("t2:  {0}", t2)
        Console.WriteLine("r1:  {0}", r1)
        Console.WriteLine("r2:  {0}", r2)
        Console.WriteLine()
        Console.WriteLine("Original x1       : {0}", x1)
        Console.WriteLine("Recovered from r1 : {0}", mont.Reduce(r1))
        Console.WriteLine("Original x2       : {0}", x2)
        Console.WriteLine("Recovered from r2 : {0}", mont.Reduce(r2))

        Console.WriteLine()
        Console.WriteLine("Montgomery computation of x1 ^ x2 mod m :")
        Dim prod = mont.Reduce(mont.rrm)
        Dim base = mont.Reduce(x1 * mont.rrm)
        Dim exp = x2
        While exp.BitLength > 0
            If Not exp.IsEven Then
                prod = mont.Reduce(prod * base)
            End If
            exp >>= 1
            base = mont.Reduce(base * base)
        End While
        Console.WriteLine(mont.Reduce(prod))
        Console.WriteLine()
        Console.WriteLine("Alternate computation of x1 ^ x2 mod m :")
        Console.WriteLine(BigInteger.ModPow(x1, x2, m))
    End Sub

End Module