178 lines
4.1 KiB
Plaintext
178 lines
4.1 KiB
Plaintext
#include "windows.bi"
|
|
|
|
Type prime_factor
|
|
p As Ulong
|
|
e As Ulong
|
|
End Type
|
|
|
|
' Arrays and their counters
|
|
Dim Shared primes(1 Shl 15) As Ulong
|
|
Dim Shared primeCount As Integer = 0
|
|
|
|
Function get_prime_factors(n As Ulong, factors() As prime_factor) As Integer
|
|
Static As Ulong e, p, i
|
|
Dim factorCount As Integer = 0
|
|
|
|
' Handle even numbers specially
|
|
If (n And 1) = 0 Then
|
|
e = 0
|
|
While (n And 1) = 0
|
|
e += 1
|
|
n Shr= 1
|
|
Wend
|
|
factors(factorCount).p = 2
|
|
factors(factorCount).e = e
|
|
factorCount += 1
|
|
End If
|
|
|
|
' Now we only need to check odd numbers
|
|
For i = 1 To primeCount - 1
|
|
p = primes(i)
|
|
If p * p > n Then Exit For
|
|
|
|
If (n Mod p) = 0 Then
|
|
e = 0
|
|
Do
|
|
e += 1
|
|
n \= p
|
|
Loop While (n Mod p) = 0
|
|
|
|
factors(factorCount).p = p
|
|
factors(factorCount).e = e
|
|
factorCount += 1
|
|
End If
|
|
Next
|
|
|
|
If n > 1 Then
|
|
factors(factorCount).p = n
|
|
factors(factorCount).e = 1
|
|
factorCount += 1
|
|
End If
|
|
|
|
Return factorCount
|
|
End Function
|
|
|
|
Function get_factors(n As Ulong, factors() As Ulong) As Integer
|
|
Dim As Ulong i, k
|
|
Dim As Integer p, j, prevLen
|
|
Dim As prime_factor prime_factors(100)
|
|
Dim As Integer factorCount = get_prime_factors(n, prime_factors())
|
|
|
|
factors(0) = 1
|
|
Dim As Integer len2 = 1
|
|
Dim As Integer totalFactors = 1
|
|
|
|
For i = 0 To factorCount - 1
|
|
p = prime_factors(i).p
|
|
prevLen = totalFactors
|
|
|
|
For j = 0 To prime_factors(i).e - 1
|
|
For k = 0 To prevLen - 1
|
|
factors(totalFactors) = factors(k) * p
|
|
totalFactors += 1
|
|
Next
|
|
p *= prime_factors(i).p
|
|
Next
|
|
Next
|
|
|
|
' Sort the factors
|
|
For i = 0 To totalFactors - 2
|
|
For p = i + 1 To totalFactors - 1
|
|
If factors(i) > factors(p) Then Swap factors(i), factors(p)
|
|
Next
|
|
Next
|
|
|
|
Return totalFactors
|
|
End Function
|
|
|
|
Function mpow(a As Ulongint, p As Ulongint, m As Ulongint) As Ulongint
|
|
Dim r As Ulongint = 1
|
|
While p > 0
|
|
If (p And 1) Then r = (r * a) Mod m
|
|
a = (a * a) Mod m
|
|
p Shr= 1
|
|
Wend
|
|
Return r
|
|
End Function
|
|
|
|
Function ipow(a As Ulongint, p As Ulongint) As Ulongint
|
|
Dim r As Ulongint = 1
|
|
While p > 0
|
|
If (p And 1) Then r *= a
|
|
a *= a
|
|
p Shr= 1
|
|
Wend
|
|
Return r
|
|
End Function
|
|
|
|
Function GCD(n As Ulongint, d As Ulongint) As Ulongint
|
|
Return Iif(d = 0, n, GCD(d, n Mod d))
|
|
End Function
|
|
|
|
Function lcm(r As Ulongint, s As Ulongint) As Ulongint
|
|
Return (r * s) / GCD(r, s)
|
|
End Function
|
|
|
|
Function multi_order_p(a As Ulong, p As Ulong, e As Ulong) As Ulong
|
|
Dim As Ulong m = ipow(p, e)
|
|
Dim As Ulong t = (m \ p) * (p - 1)
|
|
Dim As Ulong fac(1000)
|
|
Dim As Integer facCount = get_factors(t, fac())
|
|
|
|
For i As Integer = 0 To facCount - 1
|
|
If mpow(a, fac(i), m) = 1 Then Return fac(i)
|
|
Next
|
|
|
|
Return 0
|
|
End Function
|
|
|
|
Function multi_order(a As Ulong, m As Ulong) As Ulong
|
|
Dim pf(100) As prime_factor
|
|
Dim pfCount As Integer = get_prime_factors(m, pf())
|
|
Dim res As Ulong = 1
|
|
|
|
For i As Integer = 0 To pfCount - 1
|
|
res = lcm(res, multi_order_p(a, pf(i).p, pf(i).e))
|
|
Next
|
|
|
|
Return res
|
|
End Function
|
|
|
|
Sub sieve()
|
|
Dim As Integer i, j
|
|
Const SIZE = 1 Shl 15
|
|
Static bits(0 To SIZE-1) As Boolean
|
|
|
|
' Fill with True's (faster than loop)
|
|
FillMemory(@bits(0), SIZE, True)
|
|
|
|
bits(0) = False
|
|
bits(1) = False
|
|
|
|
' Only need to check up to sqrt(SIZE)
|
|
For i = 2 To Int(Sqr(SIZE))
|
|
If bits(i) Then
|
|
For j = i * i To SIZE-1 Step i
|
|
bits(j) = False
|
|
Next
|
|
End If
|
|
Next
|
|
|
|
' Store primes in array
|
|
For i = 2 To SIZE-1
|
|
If bits(i) Then
|
|
primes(primeCount) = i
|
|
primeCount += 1
|
|
End If
|
|
Next
|
|
End Sub
|
|
|
|
' Main program
|
|
sieve()
|
|
Print multi_order(37, 1000) ' Prints 100
|
|
Print multi_order(37, 3343) ' Prints 1114
|
|
Print multi_order(54, 100001) ' Prints 9090
|
|
Print multi_order(3047753288, 2257683301) ' Prints 62713425
|
|
|
|
Sleep
|