Cyclotomic polynomial: Difference between revisions
Content added Content deleted
Thundergnat (talk | contribs) m (syntax highlighting fixup automation) |
|||
Line 14: | Line 14: | ||
=={{header|C++}}== |
=={{header|C++}}== |
||
{{trans|Java}} |
{{trans|Java}} |
||
< |
<syntaxhighlight lang="cpp">#include <algorithm> |
||
#include <iostream> |
#include <iostream> |
||
#include <initializer_list> |
#include <initializer_list> |
||
Line 532: | Line 532: | ||
return 0; |
return 0; |
||
}</ |
}</syntaxhighlight> |
||
{{out}} |
{{out}} |
||
<pre>Task 1: cyclotomic polynomials for n <= 30: |
<pre>Task 1: cyclotomic polynomials for n <= 30: |
||
Line 581: | Line 581: | ||
{{trans|Java}} |
{{trans|Java}} |
||
{{works with|C sharp|8}} |
{{works with|C sharp|8}} |
||
< |
<syntaxhighlight lang="csharp">using System; |
||
using System.Collections; |
using System.Collections; |
||
using System.Collections.Generic; |
using System.Collections.Generic; |
||
Line 816: | Line 816: | ||
}; |
}; |
||
} |
} |
||
}</ |
}</syntaxhighlight> |
||
{{out}} |
{{out}} |
||
<pre> |
<pre> |
||
Line 865: | Line 865: | ||
=={{header|D}}== |
=={{header|D}}== |
||
{{trans|Kotlin}} |
{{trans|Kotlin}} |
||
< |
<syntaxhighlight lang="d">import std.algorithm; |
||
import std.exception; |
import std.exception; |
||
import std.format; |
import std.format; |
||
Line 1,303: | Line 1,303: | ||
} |
} |
||
} |
} |
||
}</ |
}</syntaxhighlight> |
||
{{out}} |
{{out}} |
||
<pre>Task 1: cyclotomic polynomials for n <= 30: |
<pre>Task 1: cyclotomic polynomials for n <= 30: |
||
Line 1,351: | Line 1,351: | ||
=={{header|Fermat}}== |
=={{header|Fermat}}== |
||
This isn't terribly efficient if you have to calculate many cyclotomics- store them in an array rather than using recursion instead if you need to do that- but it showcases Fermat's strength at polynomial expressions. |
This isn't terribly efficient if you have to calculate many cyclotomics- store them in an array rather than using recursion instead if you need to do that- but it showcases Fermat's strength at polynomial expressions. |
||
< |
<syntaxhighlight lang="fermat"> |
||
&(J=x); {adjoin x as the variable in the polynomials} |
&(J=x); {adjoin x as the variable in the polynomials} |
||
Line 1,381: | Line 1,381: | ||
od; |
od; |
||
!!(m,' : ',i); |
!!(m,' : ',i); |
||
od;</ |
od;</syntaxhighlight> |
||
=={{header|Go}}== |
=={{header|Go}}== |
||
{{trans|Java}} |
{{trans|Java}} |
||
< |
<syntaxhighlight lang="go">package main |
||
import ( |
import ( |
||
Line 1,824: | Line 1,824: | ||
} |
} |
||
} |
} |
||
}</ |
}</syntaxhighlight> |
||
{{out}} |
{{out}} |
||
Line 1,877: | Line 1,877: | ||
Uses synthetic polynomial division and simple memoization. |
Uses synthetic polynomial division and simple memoization. |
||
< |
<syntaxhighlight lang="haskell">import Data.List |
||
import Data.Numbers.Primes (primeFactors) |
import Data.Numbers.Primes (primeFactors) |
||
Line 1,915: | Line 1,915: | ||
-- general case |
-- general case |
||
(p, m):ps -> let cm = cyclotomics !! (n `div` (p ^ m)) |
(p, m):ps -> let cm = cyclotomics !! (n `div` (p ^ m)) |
||
in lift (lift cm p `shortDiv` cm) (p^(m-1))</ |
in lift (lift cm p `shortDiv` cm) (p^(m-1))</syntaxhighlight> |
||
Simple examples |
Simple examples |
||
Line 1,930: | Line 1,930: | ||
The task solution |
The task solution |
||
< |
<syntaxhighlight lang="haskell">showPoly [] = "0" |
||
showPoly p = foldl1 (\r -> (r ++) . term) $ |
showPoly p = foldl1 (\r -> (r ++) . term) $ |
||
dropWhile null $ |
dropWhile null $ |
||
Line 1,965: | Line 1,965: | ||
skipBy n [] = [] |
skipBy n [] = [] |
||
skipBy n lst = let (x:_, b) = splitAt n lst in x:skipBy n b</ |
skipBy n lst = let (x:_, b) = splitAt n lst in x:skipBy n b</syntaxhighlight> |
||
Result |
Result |
||
Line 2,017: | Line 2,017: | ||
For values up to 70, we can find cyclotomic polynomials by finding a polynomial with roots of unity relatively prime to the order of the polynomial: |
For values up to 70, we can find cyclotomic polynomials by finding a polynomial with roots of unity relatively prime to the order of the polynomial: |
||
< |
<syntaxhighlight lang="j">cyclo=: {{<.-:1+(++) p. 1;^0j2p1* y%~1+I.1=y+.1+i.y}}</syntaxhighlight> |
||
This approach suggests that cyclotomic polynomial zero should be <tt>f<sub>0</sub>(x)= 1</tt> |
This approach suggests that cyclotomic polynomial zero should be <tt>f<sub>0</sub>(x)= 1</tt> |
||
Line 2,023: | Line 2,023: | ||
Routine to find the nth cyclotomic polynomial: |
Routine to find the nth cyclotomic polynomial: |
||
< |
<syntaxhighlight lang="j">{{ if.0>nc<'cache' do.cache=:y end.}} (,1);_1 1 |
||
cyclotomic=: {{ |
cyclotomic=: {{ |
||
Line 2,067: | Line 2,067: | ||
end. |
end. |
||
end.q |
end.q |
||
}}</ |
}}</syntaxhighlight> |
||
If you take all the divisors of a number. (For example, for 12, the divisors are: 1, 2, 3, 4, 6 and 12) and find the product of their cyclotomic polynomials (for example, for 12, x-1, x+1, x<sup>2</sup>+x+1, x<sup>2</sup>+1, x<sup>2</sup>-x+1, and x<sup>4</sup>-x<sup>2</sup>+1) you get x<sup>n</sup>-1 (for 12, that would of course be x<sup>12</sup>-1). |
If you take all the divisors of a number. (For example, for 12, the divisors are: 1, 2, 3, 4, 6 and 12) and find the product of their cyclotomic polynomials (for example, for 12, x-1, x+1, x<sup>2</sup>+x+1, x<sup>2</sup>+1, x<sup>2</sup>-x+1, and x<sup>4</sup>-x<sup>2</sup>+1) you get x<sup>n</sup>-1 (for 12, that would of course be x<sup>12</sup>-1). |
||
Line 2,082: | Line 2,082: | ||
Task examples: |
Task examples: |
||
< |
<syntaxhighlight lang="j">taskfmt=: {{ |
||
c=. ":each j=.cyclotomic y |
c=. ":each j=.cyclotomic y |
||
raw=. rplc&'_-' ;:inv}.,'+';"0|.(*|j)#c('(',[,],')'"_)each '*x^',&":L:0 <"0 i.#c |
raw=. rplc&'_-' ;:inv}.,'+';"0|.(*|j)#c('(',[,],')'"_)each '*x^',&":L:0 <"0 i.#c |
||
Line 2,141: | Line 2,141: | ||
8 6545 |
8 6545 |
||
9 6545 |
9 6545 |
||
10 10465</ |
10 10465</syntaxhighlight> |
||
=== Another approach === |
=== Another approach === |
||
Line 2,147: | Line 2,147: | ||
As noted in the [http://jsoftware.com/pipermail/programming/2022-March/060209.html J programming forum], we can improve the big-O character of this algorithm by using the [[Fast Fourier transform#J|fast fourier transform]] for polynomial multiplication and division. |
As noted in the [http://jsoftware.com/pipermail/programming/2022-March/060209.html J programming forum], we can improve the big-O character of this algorithm by using the [[Fast Fourier transform#J|fast fourier transform]] for polynomial multiplication and division. |
||
< |
<syntaxhighlight lang="j">NB. install'math/fftw' |
||
require'math/fftw' |
require'math/fftw' |
||
Line 2,169: | Line 2,169: | ||
}} |
}} |
||
roundreal =: [: <. 0.5 + 9&o.</ |
roundreal =: [: <. 0.5 + 9&o.</syntaxhighlight> |
||
This variation for polynomial division is only valid when there's no remainder to be concerned with (which is the case, here). The article mentioned in the comments is an essay on using [[j:Essays/FFT|fft for polynomial multiplication]] |
This variation for polynomial division is only valid when there's no remainder to be concerned with (which is the case, here). The article mentioned in the comments is an essay on using [[j:Essays/FFT|fft for polynomial multiplication]] |
||
Line 2,176: | Line 2,176: | ||
=={{header|Java}}== |
=={{header|Java}}== |
||
< |
<syntaxhighlight lang="java"> |
||
import java.util.ArrayList; |
import java.util.ArrayList; |
||
import java.util.Collections; |
import java.util.Collections; |
||
Line 2,703: | Line 2,703: | ||
} |
} |
||
</syntaxhighlight> |
|||
</lang> |
|||
{{out}} |
{{out}} |
||
<pre> |
<pre> |
||
Line 2,752: | Line 2,752: | ||
=={{header|Julia}}== |
=={{header|Julia}}== |
||
< |
<syntaxhighlight lang="julia">using Primes, Polynomials |
||
# memoize cache for recursive calls |
# memoize cache for recursive calls |
||
Line 2,809: | Line 2,809: | ||
println("The cyclotomic polynomial Φ(", abs(n), ") has a coefficient that is ", n < 0 ? -i : i) |
println("The cyclotomic polynomial Φ(", abs(n), ") has a coefficient that is ", n < 0 ? -i : i) |
||
end |
end |
||
</ |
</syntaxhighlight>{{out}} |
||
<pre> |
<pre> |
||
First 30 cyclotomic polynomials: |
First 30 cyclotomic polynomials: |
||
Line 2,856: | Line 2,856: | ||
=={{header|Kotlin}}== |
=={{header|Kotlin}}== |
||
{{trans|Java}} |
{{trans|Java}} |
||
< |
<syntaxhighlight lang="scala">import java.util.TreeMap |
||
import kotlin.math.abs |
import kotlin.math.abs |
||
import kotlin.math.pow |
import kotlin.math.pow |
||
Line 3,312: | Line 3,312: | ||
} else coefficient.toString() + "x^" + exponent |
} else coefficient.toString() + "x^" + exponent |
||
} |
} |
||
}</ |
}</syntaxhighlight> |
||
{{out}} |
{{out}} |
||
<pre>Task 1: cyclotomic polynomials for n <= 30: |
<pre>Task 1: cyclotomic polynomials for n <= 30: |
||
Line 3,359: | Line 3,359: | ||
=={{header|Maple}}== |
=={{header|Maple}}== |
||
< |
<syntaxhighlight lang="maple">with(NumberTheory): |
||
for n to 30 do lprint(Phi(n,x)) od: |
for n to 30 do lprint(Phi(n,x)) od: |
||
Line 3,396: | Line 3,396: | ||
[seq(ListTools:-SelectFirst(s->member(n,s),PhiSet,output=indices),n=1..20)]; |
[seq(ListTools:-SelectFirst(s->member(n,s),PhiSet,output=indices),n=1..20)]; |
||
#[1, 105, 385, 1365, 1785, 2805, 3135, 6545, 6545, 10465, 10465, |
#[1, 105, 385, 1365, 1785, 2805, 3135, 6545, 6545, 10465, 10465, |
||
# 10465, 10465, 10465, 11305, 11305, 11305, 11305, 11305, 11305]</ |
# 10465, 10465, 10465, 11305, 11305, 11305, 11305, 11305, 11305]</syntaxhighlight> |
||
=={{header|Mathematica}} / {{header|Wolfram Language}}== |
=={{header|Mathematica}} / {{header|Wolfram Language}}== |
||
< |
<syntaxhighlight lang="mathematica">Cyclotomic[#, x] & /@ Range[30] // Column |
||
i = 1; |
i = 1; |
||
n = 10; |
n = 10; |
||
Line 3,420: | Line 3,420: | ||
]; |
]; |
||
i++; |
i++; |
||
]</ |
]</syntaxhighlight> |
||
{{out}} |
{{out}} |
||
<pre>-1+x |
<pre>-1+x |
||
Line 3,469: | Line 3,469: | ||
We use Java algorithm with ideas from C#, D, Go and Kotlin. We have kept only algorithm number 2 as other algorithms are much less efficient. We have also done some Nim specific improvements in order to get better performances. |
We use Java algorithm with ideas from C#, D, Go and Kotlin. We have kept only algorithm number 2 as other algorithms are much less efficient. We have also done some Nim specific improvements in order to get better performances. |
||
< |
<syntaxhighlight lang="nim">import algorithm, math, sequtils, strformat, tables |
||
type |
type |
||
Line 3,803: | Line 3,803: | ||
echo &"Φ{'(' & $n & ')':7} has coefficient with magnitude = {i}" |
echo &"Φ{'(' & $n & ')':7} has coefficient with magnitude = {i}" |
||
dec n |
dec n |
||
break</ |
break</syntaxhighlight> |
||
{{out}} |
{{out}} |
||
Line 3,854: | Line 3,854: | ||
=={{header|PARI/GP}}== |
=={{header|PARI/GP}}== |
||
Cyclotomic polynomials are a built-in function. |
Cyclotomic polynomials are a built-in function. |
||
< |
<syntaxhighlight lang="parigp"> |
||
for(n=1,30,print(n," : ",polcyclo(n))) |
for(n=1,30,print(n," : ",polcyclo(n))) |
||
Line 3,860: | Line 3,860: | ||
for(d=1,10,i=1; while(contains_coeff(i,d)==0,i=i+1);print(d," : ",i)) |
for(d=1,10,i=1; while(contains_coeff(i,d)==0,i=i+1);print(d," : ",i)) |
||
</syntaxhighlight> |
|||
</lang> |
|||
{{out}}<pre> |
{{out}}<pre> |
||
Line 3,907: | Line 3,907: | ||
=={{header|Perl}}== |
=={{header|Perl}}== |
||
Conveniently, the module <code>Math::Polynomial::Cyclotomic</code> exists to do all the work. An <code>exponent too large</code> error prevents reaching the 10th step of the 2nd part of the task. |
Conveniently, the module <code>Math::Polynomial::Cyclotomic</code> exists to do all the work. An <code>exponent too large</code> error prevents reaching the 10th step of the 2nd part of the task. |
||
< |
<syntaxhighlight lang="perl">use feature 'say'; |
||
use List::Util qw(first); |
use List::Util qw(first); |
||
use Math::Polynomial::Cyclotomic qw(cyclo_poly_iterate); |
use Math::Polynomial::Cyclotomic qw(cyclo_poly_iterate); |
||
Line 3,924: | Line 3,924: | ||
$n++; |
$n++; |
||
} |
} |
||
}</ |
}</syntaxhighlight> |
||
{{out}} |
{{out}} |
||
<pre>First 30 cyclotomic polynomials: |
<pre>First 30 cyclotomic polynomials: |
||
Line 3,972: | Line 3,972: | ||
{{trans|Julia}} |
{{trans|Julia}} |
||
Uses several routines from [[Polynomial_long_division#Phix]], tweaked slightly to check remainder is zero and trim the quotient. |
Uses several routines from [[Polynomial_long_division#Phix]], tweaked slightly to check remainder is zero and trim the quotient. |
||
<!--< |
<!--<syntaxhighlight lang="phix">(phixonline)--> |
||
<span style="color: #000080;font-style:italic;">-- demo\rosetta\Cyclotomic_Polynomial.exw</span> |
<span style="color: #000080;font-style:italic;">-- demo\rosetta\Cyclotomic_Polynomial.exw</span> |
||
<span style="color: #008080;">with</span> <span style="color: #008080;">javascript_semantics</span> |
<span style="color: #008080;">with</span> <span style="color: #008080;">javascript_semantics</span> |
||
Line 4,087: | Line 4,087: | ||
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span> |
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span> |
||
<span style="color: #008080;">end</span> <span style="color: #008080;">while</span> |
<span style="color: #008080;">end</span> <span style="color: #008080;">while</span> |
||
<!--</ |
<!--</syntaxhighlight>--> |
||
{{out}} |
{{out}} |
||
If you disable the cheating, and if in a particularly self harming mood replace it with n+=1, you will get exactly the same output, eventually.<br> |
If you disable the cheating, and if in a particularly self harming mood replace it with n+=1, you will get exactly the same output, eventually.<br> |
||
Line 4,136: | Line 4,136: | ||
=={{header|Python}}== |
=={{header|Python}}== |
||
< |
<syntaxhighlight lang="python">from itertools import count, chain |
||
from collections import deque |
from collections import deque |
||
Line 4,257: | Line 4,257: | ||
while want in c or -want in c: |
while want in c or -want in c: |
||
print(f'C[{want}]: {n}') |
print(f'C[{want}]: {n}') |
||
want += 1</ |
want += 1</syntaxhighlight> |
||
{{out}} |
{{out}} |
||
Only showing first 10 polynomials to avoid clutter. |
Only showing first 10 polynomials to avoid clutter. |
||
Line 4,303: | Line 4,303: | ||
Uses the same library as Perl, so comes with the same caveats. |
Uses the same library as Perl, so comes with the same caveats. |
||
<lang |
<syntaxhighlight lang="raku" line>use Math::Polynomial::Cyclotomic:from<Perl5> <cyclo_poly_iterate cyclo_poly>; |
||
say 'First 30 cyclotomic polynomials:'; |
say 'First 30 cyclotomic polynomials:'; |
||
Line 4,326: | Line 4,326: | ||
sub super ($str) { |
sub super ($str) { |
||
$str.subst( / '^' (\d+) /, { $0.trans([<0123456789>.comb] => [<⁰¹²³⁴⁵⁶⁷⁸⁹>.comb]) }, :g) |
$str.subst( / '^' (\d+) /, { $0.trans([<0123456789>.comb] => [<⁰¹²³⁴⁵⁶⁷⁸⁹>.comb]) }, :g) |
||
}</ |
}</syntaxhighlight> |
||
<pre>First 30 cyclotomic polynomials: |
<pre>First 30 cyclotomic polynomials: |
||
Φ(1) = (x - 1) |
Φ(1) = (x - 1) |
||
Line 4,372: | Line 4,372: | ||
=={{header|Sidef}}== |
=={{header|Sidef}}== |
||
Solution based on polynomial interpolation (slow). |
Solution based on polynomial interpolation (slow). |
||
< |
<syntaxhighlight lang="ruby">var Poly = require('Math::Polynomial') |
||
Poly.string_config(Hash(fold_sign => true, prefix => "", suffix => "")) |
Poly.string_config(Hash(fold_sign => true, prefix => "", suffix => "")) |
||
Line 4,392: | Line 4,392: | ||
}) |
}) |
||
say "Φ(#{k}) has coefficient with magnitude #{n}" |
say "Φ(#{k}) has coefficient with magnitude #{n}" |
||
}</ |
}</syntaxhighlight> |
||
Slightly faster solution, using the '''Math::Polynomial::Cyclotomic''' Perl module. |
Slightly faster solution, using the '''Math::Polynomial::Cyclotomic''' Perl module. |
||
< |
<syntaxhighlight lang="ruby">var Poly = require('Math::Polynomial') |
||
require('Math::Polynomial::Cyclotomic') |
require('Math::Polynomial::Cyclotomic') |
||
Line 4,412: | Line 4,412: | ||
}) |
}) |
||
say "Φ(#{k}) has coefficient with magnitude = #{n}" |
say "Φ(#{k}) has coefficient with magnitude = #{n}" |
||
}</ |
}</syntaxhighlight> |
||
{{out}} |
{{out}} |
||
Line 4,460: | Line 4,460: | ||
=={{header|Visual Basic .NET}}== |
=={{header|Visual Basic .NET}}== |
||
{{trans|C++}} |
{{trans|C++}} |
||
< |
<syntaxhighlight lang="vbnet">Imports System.Text |
||
Module Module1 |
Module Module1 |
||
Line 4,942: | Line 4,942: | ||
End Sub |
End Sub |
||
End Module</ |
End Module</syntaxhighlight> |
||
{{out}} |
{{out}} |
||
<pre>Task 1: cyclotomic polynomials for n <= 30: |
<pre>Task 1: cyclotomic polynomials for n <= 30: |
||
Line 4,995: | Line 4,995: | ||
{{libheader|Wren-fmt}} |
{{libheader|Wren-fmt}} |
||
Second part is very slow. Limited to first 7 to finish in a reasonable time - 5 minutes on my machine. |
Second part is very slow. Limited to first 7 to finish in a reasonable time - 5 minutes on my machine. |
||
< |
<syntaxhighlight lang="ecmascript">import "/trait" for Stepped |
||
import "/sort" for Sort |
import "/sort" for Sort |
||
import "/math" for Int, Nums |
import "/math" for Int, Nums |
||
Line 5,334: | Line 5,334: | ||
} |
} |
||
} |
} |
||
}</ |
}</syntaxhighlight> |
||
{{out}} |
{{out}} |