Math::NumSeq::Totient -- Euler's totient function, count of coprimes
use Math::NumSeq::Totient; my $seq = Math::NumSeq::Totient->new; my ($i, $value) = $seq->next;
Euler's totient function, being the count of integers coprime to i,
1, 1, 2, 2, 4, 2, 6, 4, etc starting i=1
For example i=6 has no common factor with 1 or 5, so the totient is 2.
The totient can be calculated from the prime factorization by changing one copy of each distinct prime p to p-1.
totient(n) = product (p-1) * p^(e-1) prime factors p^e in n
See "FUNCTIONS" in Math::NumSeq for behaviour common to all sequence classes.
$value = $seq->ith($i)
This calculation requires factorizing
$iand in the current code after small factors a hard limit of 2**32 is enforced in the interests of not going into a near-infinite loop. Above that the return is
$bool = $seq->pred($value)
Return true if
$valueoccurs in the sequence, ie.
$valueis the totient of something.
Totient(n) > 1 is always even because the factors factor p-1 for odd prime p is even, or if no odd primes in n then totient(2^k)=2^(k-1) is even. So odd numbers > 1 don't occur as totients.
The strategy is to look at the divisors of the given value to find the p-1, q-1 etc parts arising as totient(n=p*q) etc.
initial maxdivisor unlimited try divisors of value, with divisor < maxdivisor if p=divisor+1 is prime then remainder = value/divisor loop if recurse pred(remainder, maxdivisor=divisor) then yes if remainder divisible by p then remainder/=p else next divisor of value
The divisors tried include 1 and the value itself. 1 becomes p=2 casting out possible factors of 2. For value itself if p=value+1 prime then simply totient(value+1)=value means it is a totient.
Care must be taken not to repeat a prime p, since value=(p-1)*(p-1) is not a totient form. One way to do this is to demand only smaller divisors when recursing, hence the "maxdivisor".
Any divisors > 1 will have to be even to give p=divisor+1 odd to be a prime. Effectively each p-1, q-1, etc part of the target takes at least one factor of 2 out of the value. It might be possible to handle the 2^k part of the target value specially, for instance noting that on reaching the last factor of 2 there can be no further recursion, only value=p^a*(p-1) can be a totient.
This search implicitly produces an n=p^a*q^b*etc with totient(n)=value but for the
pred() method that n is not required, only the fact it exists.
Copyright 2011, 2012, 2013, 2014, 2016, 2019 Kevin Ryde
Math-NumSeq is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version.
Math-NumSeq is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with Math-NumSeq. If not, see <http://www.gnu.org/licenses/>.