2

I am not sure of the correct mathematical name of the feature I am looking at. Its been a long time since I did math at school. https://en.wikipedia.org/wiki/Multiplicative_group_of_integers_modulo_n seems to concerned with this sort of thing, but leaves me unsure that I have understood what is written.

Below I use '%' as MOD and '^' as 'raised to the power of'. And am quite wordy.

For all primes > 2, there is a sequence {2^n%prime, for all integer n, 0 to infinity}. That is { 2^0 % prime = 1, 2^1 % prime = 2, .. 2^(prime-1) % prime = 1, 2^prime % prime = 2, ..} 2^((prime-1) * m)%prime = 1 and 2^(prime * m)%prime = 2 for all integer m.

if the prime is 7 however, the sequence is made up of two instance of a shorter sequence thus: 2^0%7 = 1, 2^1%7 = 2, 2^2%7 = 4, 2^3%7 = 1, 2^4%7 = 2, 2^5%7 = 4, 2^6%7 = 1 and then 2^(6 * n)%7 is still 1; but the are extra values that are also another set of at (2^(3+6*n)%7)

So the cycle-length(prime) is what I have been calling the first n > 0 where 2^n mod prime is 1.

I have inserted some code that calculates this by trial until repetition.. with some trivial uses of it.

long cycleLength(long prime)
{
    long remainder = 1 ;
    long length = 0 ;
do {
    length++ ;

//#define FAST_MODULO #ifdef FAST_MODULO remainder = (remainder+remainder)%prime ; #else remainder += remainder ; if (remainder > prime) remainder -= prime ; #endif if (remainder == 1) return length ; } while (length < prime/2) ;

return prime-1 ;}

size_t pow_of_2(unsigned n) { size_t result = 1 ; size_t pow = 2 ;

while(n)
{
    if (n &amp; 1) result *= pow ;
    pow *= pow ;
    n /= 2;
}
return result ;

}

#include <iostream> using std::cout ;

int main(int ac, char **av) { long prime = 17 ;

cout &lt;&lt; &quot;cycleLength(17) = &quot; &lt;&lt; cycleLength(17) &lt;&lt; '\n';

cout &lt;&lt; &quot;2^16 = &quot; &lt;&lt; pow_of_2(16) &lt;&lt; '\n' ;
cout &lt;&lt; &quot;2^33 = &quot; &lt;&lt; pow_of_2(33) &lt;&lt; '\n' ;

cout &lt;&lt; &quot;33 % CL(17) = &quot; &lt;&lt; 33 % cycleLength(17) 
     &lt;&lt; &quot;, 2^(33 % CL(17)) % 17 = &quot; &lt;&lt; pow_of_2(33%cycleLength(17)) % 17 &lt;&lt; '\n' ;
cout &lt;&lt; &quot;2^33 % 17 = &quot; &lt;&lt; pow_of_2(33)%17 &lt;&lt; '\n' ;
cout &lt;&lt; std::endl ;

}

I have observed that cycles are either length (prime-1) or divisor of (prime-1).

So the run-time is reduced by stopping at (n == prime/2) and returning (prime-1) as that is the only case remaining; and the code is about 25% quicker as a result.

The algorithm is currently O(N) time complexity. I am hoping for clues or insight that might reduce this.

Thanks for reading this.

0 Answers0