Data commit
This commit is contained in:
parent
7387c8f97b
commit
cb5bb5e222
199093 changed files with 3378972 additions and 0 deletions
|
|
@ -0,0 +1,483 @@
|
|||
Imports System.Text
|
||||
|
||||
Module Module1
|
||||
Private ReadOnly MAX_ALL_FACTORS As Integer = 100_000
|
||||
#Const ALGORITHM = 2
|
||||
|
||||
Class Term
|
||||
Implements IComparable(Of Term)
|
||||
|
||||
Public ReadOnly Property Coefficient As Long
|
||||
Public ReadOnly Property Exponent As Long
|
||||
|
||||
Public Sub New(c As Long, Optional e As Long = 0)
|
||||
Coefficient = c
|
||||
Exponent = e
|
||||
End Sub
|
||||
|
||||
Public Shared Operator -(t As Term) As Term
|
||||
Return New Term(-t.Coefficient, t.Exponent)
|
||||
End Operator
|
||||
|
||||
Public Shared Operator +(lhs As Term, rhs As Term) As Term
|
||||
If lhs.Exponent <> rhs.Exponent Then
|
||||
Throw New ArgumentException("Exponents not equal")
|
||||
End If
|
||||
Return New Term(lhs.Coefficient + rhs.Coefficient, lhs.Exponent)
|
||||
End Operator
|
||||
|
||||
Public Shared Operator *(lhs As Term, rhs As Term) As Term
|
||||
Return New Term(lhs.Coefficient * rhs.Coefficient, lhs.Exponent + rhs.Exponent)
|
||||
End Operator
|
||||
|
||||
Public Function CompareTo(other As Term) As Integer Implements IComparable(Of Term).CompareTo
|
||||
Return -Exponent.CompareTo(other.Exponent)
|
||||
End Function
|
||||
|
||||
Public Overrides Function ToString() As String
|
||||
If Coefficient = 0 Then
|
||||
Return "0"
|
||||
End If
|
||||
If Exponent = 0 Then
|
||||
Return Coefficient.ToString
|
||||
End If
|
||||
If Coefficient = 1 Then
|
||||
If Exponent = 1 Then
|
||||
Return "x"
|
||||
End If
|
||||
Return String.Format("x^{0}", Exponent)
|
||||
End If
|
||||
If Coefficient = -1 Then
|
||||
If Exponent = 1 Then
|
||||
Return "-x"
|
||||
End If
|
||||
Return String.Format("-x^{0}", Exponent)
|
||||
End If
|
||||
If Exponent = 1 Then
|
||||
Return String.Format("{0}x", Coefficient)
|
||||
End If
|
||||
Return String.Format("{0}x^{1}", Coefficient, Exponent)
|
||||
End Function
|
||||
End Class
|
||||
|
||||
Class Polynomial
|
||||
Implements IEnumerable(Of Term)
|
||||
|
||||
Private ReadOnly polyTerms As New List(Of Term)
|
||||
|
||||
Public Sub New()
|
||||
polyTerms.Add(New Term(0))
|
||||
End Sub
|
||||
|
||||
Public Sub New(ParamArray values() As Term)
|
||||
If values.Length = 0 Then
|
||||
polyTerms.Add(New Term(0))
|
||||
Else
|
||||
polyTerms.AddRange(values)
|
||||
End If
|
||||
Normalize()
|
||||
End Sub
|
||||
|
||||
Public Sub New(values As IEnumerable(Of Term))
|
||||
polyTerms.AddRange(values)
|
||||
If polyTerms.Count = 0 Then
|
||||
polyTerms.Add(New Term(0))
|
||||
End If
|
||||
Normalize()
|
||||
End Sub
|
||||
|
||||
Public Function LeadingCoeficient() As Long
|
||||
Return polyTerms(0).Coefficient
|
||||
End Function
|
||||
|
||||
Public Function Degree() As Long
|
||||
Return polyTerms(0).Exponent
|
||||
End Function
|
||||
|
||||
Public Function HasCoefficentAbs(coeff As Long) As Boolean
|
||||
For Each t In polyTerms
|
||||
If Math.Abs(t.Coefficient) = coeff Then
|
||||
Return True
|
||||
End If
|
||||
Next
|
||||
Return False
|
||||
End Function
|
||||
|
||||
Public Function GetEnumerator() As IEnumerator(Of Term) Implements IEnumerable(Of Term).GetEnumerator
|
||||
Return polyTerms.GetEnumerator
|
||||
End Function
|
||||
|
||||
Private Function IEnumerable_GetEnumerator() As IEnumerator Implements IEnumerable.GetEnumerator
|
||||
Return polyTerms.GetEnumerator
|
||||
End Function
|
||||
|
||||
Private Sub Normalize()
|
||||
polyTerms.Sort(Function(a As Term, b As Term) a.CompareTo(b))
|
||||
End Sub
|
||||
|
||||
Public Shared Operator +(lhs As Polynomial, rhs As Term) As Polynomial
|
||||
Dim terms As New List(Of Term)
|
||||
Dim added = False
|
||||
For Each ct In lhs
|
||||
If ct.Exponent = rhs.Exponent Then
|
||||
added = True
|
||||
If ct.Coefficient + rhs.Coefficient <> 0 Then
|
||||
terms.Add(ct + rhs)
|
||||
End If
|
||||
Else
|
||||
terms.Add(ct)
|
||||
End If
|
||||
Next
|
||||
If Not added Then
|
||||
terms.Add(rhs)
|
||||
End If
|
||||
Return New Polynomial(terms)
|
||||
End Operator
|
||||
|
||||
Public Shared Operator *(lhs As Polynomial, rhs As Term) As Polynomial
|
||||
Dim terms As New List(Of Term)
|
||||
For Each ct In lhs
|
||||
terms.Add(ct * rhs)
|
||||
Next
|
||||
Return New Polynomial(terms)
|
||||
End Operator
|
||||
|
||||
Public Shared Operator +(lhs As Polynomial, rhs As Polynomial) As Polynomial
|
||||
Dim terms As New List(Of Term)
|
||||
Dim thisCount = lhs.polyTerms.Count
|
||||
Dim polyCount = rhs.polyTerms.Count
|
||||
While thisCount > 0 OrElse polyCount > 0
|
||||
If thisCount = 0 Then
|
||||
Dim polyTerm = rhs.polyTerms(polyCount - 1)
|
||||
terms.Add(polyTerm)
|
||||
polyCount -= 1
|
||||
ElseIf polyCount = 0 Then
|
||||
Dim thisTerm = lhs.polyTerms(thisCount - 1)
|
||||
terms.Add(thisTerm)
|
||||
thisCount -= 1
|
||||
Else
|
||||
Dim polyTerm = rhs.polyTerms(polyCount - 1)
|
||||
Dim thisTerm = lhs.polyTerms(thisCount - 1)
|
||||
If thisTerm.Exponent = polyTerm.Exponent Then
|
||||
Dim t = thisTerm + polyTerm
|
||||
If t.Coefficient <> 0 Then
|
||||
terms.Add(t)
|
||||
End If
|
||||
thisCount -= 1
|
||||
polyCount -= 1
|
||||
ElseIf thisTerm.Exponent < polyTerm.Exponent Then
|
||||
terms.Add(thisTerm)
|
||||
thisCount -= 1
|
||||
Else
|
||||
terms.Add(polyTerm)
|
||||
polyCount -= 1
|
||||
End If
|
||||
End If
|
||||
End While
|
||||
Return New Polynomial(terms)
|
||||
End Operator
|
||||
|
||||
Public Shared Operator *(lhs As Polynomial, rhs As Polynomial) As Polynomial
|
||||
Throw New Exception("Not implemented")
|
||||
End Operator
|
||||
|
||||
Public Shared Operator /(lhs As Polynomial, rhs As Polynomial) As Polynomial
|
||||
Dim q As New Polynomial
|
||||
Dim r = lhs
|
||||
Dim lcv = rhs.LeadingCoeficient
|
||||
Dim dv = rhs.Degree
|
||||
While r.Degree >= rhs.Degree
|
||||
Dim lcr = r.LeadingCoeficient
|
||||
Dim s = lcr \ lcv
|
||||
Dim t As New Term(s, r.Degree() - dv)
|
||||
q += t
|
||||
r += rhs * -t
|
||||
End While
|
||||
Return q
|
||||
End Operator
|
||||
|
||||
Public Overrides Function ToString() As String
|
||||
Dim builder As New StringBuilder
|
||||
Dim it = polyTerms.GetEnumerator()
|
||||
If it.MoveNext Then
|
||||
builder.Append(it.Current)
|
||||
End If
|
||||
While it.MoveNext
|
||||
If it.Current.Coefficient < 0 Then
|
||||
builder.Append(" - ")
|
||||
builder.Append(-it.Current)
|
||||
Else
|
||||
builder.Append(" + ")
|
||||
builder.Append(it.Current)
|
||||
End If
|
||||
End While
|
||||
Return builder.ToString
|
||||
End Function
|
||||
End Class
|
||||
|
||||
Function GetDivisors(number As Integer) As List(Of Integer)
|
||||
Dim divisors As New List(Of Integer)
|
||||
Dim root = CType(Math.Sqrt(number), Long)
|
||||
For i = 1 To root
|
||||
If number Mod i = 0 Then
|
||||
divisors.Add(i)
|
||||
Dim div = number \ i
|
||||
If div <> i AndAlso div <> number Then
|
||||
divisors.Add(div)
|
||||
End If
|
||||
End If
|
||||
Next
|
||||
Return divisors
|
||||
End Function
|
||||
|
||||
Private ReadOnly allFactors As New Dictionary(Of Integer, Dictionary(Of Integer, Integer)) From {{2, New Dictionary(Of Integer, Integer) From {{2, 1}}}}
|
||||
Function GetFactors(number As Integer) As Dictionary(Of Integer, Integer)
|
||||
If allFactors.ContainsKey(number) Then
|
||||
Return allFactors(number)
|
||||
End If
|
||||
|
||||
Dim factors As New Dictionary(Of Integer, Integer)
|
||||
If number Mod 2 = 0 Then
|
||||
Dim factorsDivTwo = GetFactors(number \ 2)
|
||||
For Each pair In factorsDivTwo
|
||||
If Not factors.ContainsKey(pair.Key) Then
|
||||
factors.Add(pair.Key, pair.Value)
|
||||
End If
|
||||
Next
|
||||
If factors.ContainsKey(2) Then
|
||||
factors(2) += 1
|
||||
Else
|
||||
factors.Add(2, 1)
|
||||
End If
|
||||
If number < MAX_ALL_FACTORS Then
|
||||
allFactors.Add(number, factors)
|
||||
End If
|
||||
Return factors
|
||||
End If
|
||||
Dim root = CType(Math.Sqrt(number), Long)
|
||||
Dim i = 3L
|
||||
While i <= root
|
||||
If number Mod i = 0 Then
|
||||
Dim factorsDivI = GetFactors(number \ i)
|
||||
For Each pair In factorsDivI
|
||||
If Not factors.ContainsKey(pair.Key) Then
|
||||
factors.Add(pair.Key, pair.Value)
|
||||
End If
|
||||
Next
|
||||
If factors.ContainsKey(i) Then
|
||||
factors(i) += 1
|
||||
Else
|
||||
factors.Add(i, 1)
|
||||
End If
|
||||
If number < MAX_ALL_FACTORS Then
|
||||
allFactors.Add(number, factors)
|
||||
End If
|
||||
Return factors
|
||||
End If
|
||||
i += 2
|
||||
End While
|
||||
factors.Add(number, 1)
|
||||
If number < MAX_ALL_FACTORS Then
|
||||
allFactors.Add(number, factors)
|
||||
End If
|
||||
Return factors
|
||||
End Function
|
||||
|
||||
Private ReadOnly computedPolynomials As New Dictionary(Of Integer, Polynomial)
|
||||
Function CyclotomicPolynomial(n As Integer) As Polynomial
|
||||
If computedPolynomials.ContainsKey(n) Then
|
||||
Return computedPolynomials(n)
|
||||
End If
|
||||
|
||||
If n = 1 Then
|
||||
REM polynomial: x - 1
|
||||
Dim p As New Polynomial(New Term(1, 1), New Term(-1))
|
||||
computedPolynomials.Add(n, p)
|
||||
Return p
|
||||
End If
|
||||
|
||||
Dim factors = GetFactors(n)
|
||||
Dim terms As New List(Of Term)
|
||||
Dim cyclo As Polynomial
|
||||
|
||||
If factors.ContainsKey(n) Then
|
||||
REM n prime
|
||||
For index = 1 To n
|
||||
terms.Add(New Term(1, index - 1))
|
||||
Next
|
||||
|
||||
cyclo = New Polynomial(terms)
|
||||
computedPolynomials.Add(n, cyclo)
|
||||
Return cyclo
|
||||
ElseIf factors.Count = 2 AndAlso factors.ContainsKey(2) AndAlso factors(2) = 1 AndAlso factors.ContainsKey(n / 2) AndAlso factors(n / 2) = 1 Then
|
||||
REM n = 2p
|
||||
Dim prime = n \ 2
|
||||
Dim coeff = -1
|
||||
|
||||
For index = 1 To prime
|
||||
coeff *= -1
|
||||
terms.Add(New Term(coeff, index - 1))
|
||||
Next
|
||||
|
||||
cyclo = New Polynomial(terms)
|
||||
computedPolynomials.Add(n, cyclo)
|
||||
Return cyclo
|
||||
ElseIf factors.Count = 1 AndAlso factors.ContainsKey(2) Then
|
||||
REM n = 2^h
|
||||
Dim h = factors(2)
|
||||
terms = New List(Of Term) From {
|
||||
New Term(1, Math.Pow(2, h - 1)),
|
||||
New Term(1)
|
||||
}
|
||||
|
||||
cyclo = New Polynomial(terms)
|
||||
computedPolynomials.Add(n, cyclo)
|
||||
Return cyclo
|
||||
ElseIf factors.Count = 1 AndAlso factors.ContainsKey(n) Then
|
||||
REM n = p^k
|
||||
Dim p = 0
|
||||
Dim k = 0
|
||||
For Each it In factors
|
||||
p = it.Key
|
||||
k = it.Value
|
||||
Next
|
||||
For index = 1 To p
|
||||
terms.Add(New Term(1, (index - 1) * Math.Pow(p, k - 1)))
|
||||
Next
|
||||
|
||||
cyclo = New Polynomial(terms)
|
||||
computedPolynomials.Add(n, cyclo)
|
||||
Return cyclo
|
||||
ElseIf factors.Count = 2 AndAlso factors.ContainsKey(2) Then
|
||||
REM n = 2^h * p^k
|
||||
Dim p = 0
|
||||
For Each it In factors
|
||||
If it.Key <> 2 Then
|
||||
p = it.Key
|
||||
End If
|
||||
Next
|
||||
|
||||
Dim coeff = -1
|
||||
Dim twoExp = CType(Math.Pow(2, factors(2) - 1), Long)
|
||||
Dim k = factors(p)
|
||||
For index = 1 To p
|
||||
coeff *= -1
|
||||
terms.Add(New Term(coeff, (index - 1) * twoExp * Math.Pow(p, k - 1)))
|
||||
Next
|
||||
|
||||
cyclo = New Polynomial(terms)
|
||||
computedPolynomials.Add(n, cyclo)
|
||||
Return cyclo
|
||||
ElseIf factors.ContainsKey(2) AndAlso (n / 2) Mod 2 = 1 AndAlso n / 2 > 1 Then
|
||||
REM CP(2m)[x] = CP(-m)[x], n odd integer > 1
|
||||
Dim cycloDiv2 = CyclotomicPolynomial(n \ 2)
|
||||
For Each t In cycloDiv2
|
||||
If t.Exponent Mod 2 = 0 Then
|
||||
terms.Add(t)
|
||||
Else
|
||||
terms.Add(-t)
|
||||
End If
|
||||
Next
|
||||
|
||||
cyclo = New Polynomial(terms)
|
||||
computedPolynomials.Add(n, cyclo)
|
||||
Return cyclo
|
||||
End If
|
||||
|
||||
#If ALGORITHM = 0 Then
|
||||
REM slow - uses basic definition
|
||||
Dim divisors = GetDivisors(n)
|
||||
REM Polynomial: (x^n - 1)
|
||||
cyclo = New Polynomial(New Term(1, n), New Term(-1))
|
||||
For Each i In divisors
|
||||
Dim p = CyclotomicPolynomial(i)
|
||||
cyclo /= p
|
||||
Next
|
||||
|
||||
computedPolynomials.Add(n, cyclo)
|
||||
Return cyclo
|
||||
#ElseIf ALGORITHM = 1 Then
|
||||
REM Faster. Remove Max divisor (and all divisors of max divisor) - only one divide for all divisors of Max Divisor
|
||||
Dim divisors = GetDivisors(n)
|
||||
Dim maxDivisor = Integer.MinValue
|
||||
For Each div In divisors
|
||||
maxDivisor = Math.Max(maxDivisor, div)
|
||||
Next
|
||||
Dim divisorExceptMax As New List(Of Integer)
|
||||
For Each div In divisors
|
||||
If maxDivisor Mod div <> 0 Then
|
||||
divisorExceptMax.Add(div)
|
||||
End If
|
||||
Next
|
||||
|
||||
REM Polynomial: ( x^n - 1 ) / ( x^m - 1 ), where m is the max divisor
|
||||
cyclo = New Polynomial(New Term(1, n), New Term(-1)) / New Polynomial(New Term(1, maxDivisor), New Term(-1))
|
||||
For Each i In divisorExceptMax
|
||||
Dim p = CyclotomicPolynomial(i)
|
||||
cyclo /= p
|
||||
Next
|
||||
|
||||
computedPolynomials.Add(n, cyclo)
|
||||
Return cyclo
|
||||
#ElseIf ALGORITHM = 2 Then
|
||||
REM Fastest
|
||||
REM Let p ; q be primes such that p does not divide n, and q divides n
|
||||
REM Then Cp(np)[x] = CP(n)[x^p] / CP(n)[x]
|
||||
Dim m = 1
|
||||
cyclo = CyclotomicPolynomial(m)
|
||||
Dim primes As New List(Of Integer)
|
||||
For Each it In factors
|
||||
primes.Add(it.Key)
|
||||
Next
|
||||
primes.Sort()
|
||||
For Each prime In primes
|
||||
REM CP(m)[x]
|
||||
Dim cycloM = cyclo
|
||||
REM Compute CP(m)[x^p]
|
||||
terms = New List(Of Term)
|
||||
For Each t In cyclo
|
||||
terms.Add(New Term(t.Coefficient, t.Exponent * prime))
|
||||
Next
|
||||
cyclo = New Polynomial(terms) / cycloM
|
||||
m *= prime
|
||||
Next
|
||||
REM Now, m is the largest square free divisor of n
|
||||
Dim s = n \ m
|
||||
REM Compute CP(n)[x] = CP(m)[x^s]
|
||||
terms = New List(Of Term)
|
||||
For Each t In cyclo
|
||||
terms.Add(New Term(t.Coefficient, t.Exponent * s))
|
||||
Next
|
||||
|
||||
cyclo = New Polynomial(terms)
|
||||
computedPolynomials.Add(n, cyclo)
|
||||
Return cyclo
|
||||
#Else
|
||||
Throw New Exception("Invalid algorithm")
|
||||
#End If
|
||||
End Function
|
||||
|
||||
Sub Main()
|
||||
Console.WriteLine("Task 1: cyclotomic polynomials for n <= 30:")
|
||||
For i = 1 To 30
|
||||
Dim p = CyclotomicPolynomial(i)
|
||||
Console.WriteLine("CP[{0}] = {1}", i, p)
|
||||
Next
|
||||
Console.WriteLine()
|
||||
|
||||
Console.WriteLine("Task 2: Smallest cyclotomic polynomial with n or -n as a coefficient:")
|
||||
Dim n = 0
|
||||
For i = 1 To 10
|
||||
While True
|
||||
n += 1
|
||||
Dim cyclo = CyclotomicPolynomial(n)
|
||||
If cyclo.HasCoefficentAbs(i) Then
|
||||
Console.WriteLine("CP[{0}] has coefficient with magnitude = {1}", n, i)
|
||||
n -= 1
|
||||
Exit While
|
||||
End If
|
||||
End While
|
||||
Next
|
||||
End Sub
|
||||
|
||||
End Module
|
||||
Loading…
Add table
Add a link
Reference in a new issue