Multiplicative order: Difference between revisions

Content added Content deleted
Line 2,339: Line 2,339:
}
}
puts "OK, $n is the smallest n such that {$a $n $m} satisfies $lambda"</lang>
puts "OK, $n is the smallest n such that {$a $n $m} satisfies $lambda"</lang>

=={{header|Visual Basic .NET}}==
{{trans|C#}}
<lang vbnet>Imports System.Numerics
Imports System.Runtime.CompilerServices
Imports System.Threading

Module Module1
Private s_gen As New ThreadLocal(Of Random)(Function() New Random())

Private Function Gen()
Return s_gen.Value
End Function

<Extension()>
Public Function IsProbablyPrime(value As BigInteger, Optional witnesses As Integer = 10) As Boolean
If value <= 1 Then
Return False
End If

If witnesses <= 0 Then
witnesses = 10
End If

Dim d = value - 1
Dim s = 0

While d Mod 2 = 0
d /= 2
s += 1
End While

Dim bytes(value.ToByteArray.LongLength - 1) As Byte
Dim a As BigInteger

For i = 1 To witnesses
Do
Gen.NextBytes(bytes)

a = New BigInteger(bytes)
Loop While a < 2 OrElse a >= value - 2

Dim x = BigInteger.ModPow(a, d, value)
If x = 1 OrElse x = value - 1 Then
Continue For
End If

For r = 1 To s - 1
x = BigInteger.ModPow(x, 2, value)

If x = 1 Then
Return False
End If
If x = value - 1 Then
Exit For
End If
Next

If x <> value - 1 Then
Return False
End If
Next

Return True
End Function

<Extension()>
Function Sqrt(self As BigInteger) As BigInteger
Dim b = self
While True
Dim a = b
b = self / a + a >> 1
If b >= a Then
Return a
End If
End While
Throw New Exception("Should not have happened")
End Function

<Extension()>
Function BitLength(self As BigInteger) As Long
Dim bi = self
Dim len = 0L
While bi <> 0
len += 1
bi >>= 1
End While
Return len
End Function

<Extension()>
Function BitTest(self As BigInteger, pos As Integer) As Boolean
Dim arr = self.ToByteArray
Dim i = pos \ 8
Dim m = pos Mod 8
If i >= arr.Length Then
Return False
End If
Return (arr(i) And (1 << m)) > 0
End Function

Class PExp
Sub New(p As BigInteger, e As Integer)
Prime = p
Exp = e
End Sub

Public ReadOnly Property Prime As BigInteger
Public ReadOnly Property Exp As Integer
End Class

Function MoBachShallit58(a As BigInteger, n As BigInteger, pf As List(Of PExp)) As BigInteger
Dim n1 = n - 1
Dim mo As BigInteger = 1
For Each pe In pf
Dim y = n1 / BigInteger.Pow(pe.Prime, pe.Exp)
Dim o = 0
Dim x = BigInteger.ModPow(a, y, BigInteger.Abs(n))
While x > 1
x = BigInteger.ModPow(x, pe.Prime, BigInteger.Abs(n))
o += 1
End While
Dim o1 = BigInteger.Pow(pe.Prime, o)
o1 /= BigInteger.GreatestCommonDivisor(mo, o1)
mo *= o1
Next
Return mo
End Function

Function Factor(n As BigInteger) As List(Of PExp)
Dim pf As New List(Of PExp)
Dim nn = n
Dim e = 0
While Not nn.BitTest(e)
e += 1
End While
If e > 0 Then
nn >>= e
pf.Add(New PExp(2, e))
End If
Dim s = nn.Sqrt
Dim d As BigInteger = 3
While nn > 1
If d > s Then
d = nn
End If
e = 0
While True
Dim remainder As New BigInteger
Dim div = BigInteger.DivRem(nn, d, remainder)
If remainder.BitLength > 0 Then
Exit While
End If
nn = div
e += 1
End While
If e > 0 Then
pf.Add(New PExp(d, e))
s = nn.Sqrt
End If
d += 2
End While
Return pf
End Function

Sub MoTest(a As BigInteger, n As BigInteger)
If Not n.IsProbablyPrime(20) Then
Console.WriteLine("Not computed. Modulus must be prime for this algorithm.")
Return
End If
If a.BitLength < 100 Then
Console.Write("ord({0})", a)
Else
Console.Write("ord([big])")
End If
If n.BitLength < 100 Then
Console.Write(" mod {0}", n)
Else
Console.Write(" mod [big]")
End If
Dim mob = MoBachShallit58(a, n, Factor(n - 1))
Console.WriteLine(" = {0}", mob)
End Sub

Sub Main()
MoTest(37, 3343)
MoTest(BigInteger.Pow(10, 100) + 1, 7919)
MoTest(BigInteger.Pow(10, 1000) + 1, 15485863)
MoTest(BigInteger.Pow(10, 10000) - 1, 22801763489)
MoTest(1511678068, 7379191741)
MoTest(3047753288, 2257683301)
End Sub

End Module</lang>
{{out}}
<pre>ord(37) mod 3343 = 1114
ord([big]) mod 7919 = 3959
ord([big]) mod 15485863 = 15485862
ord([big]) mod 22801763489 = 22801763488
ord(1511678068) mod 7379191741 = 614932645
ord(3047753288) mod 2257683301 = 62713425</pre>


=={{header|Wren}}==
=={{header|Wren}}==