When you are done with that, try to understand this primality test, based on the same algorithm. This is a truly obscure piece of code.
- Code: Select all
struct S {
typedef unsigned long long ull;
static ull n;
ull a,b,c,x,y;
S(ull a=1, ull b=0, ull c=0, ull x=1, ull y=0):a(a),b(b),c(c),x(x),y(y){}
S operator*(S const &s){
return S((a*s.a+b*s.c+c*s.b)%n,
(a*s.b+b*(s.a+s.c)+c*(s.b+s.c))%n,
(a*s.c+b*s.b+c*(s.a+s.c))%n,
(x*s.x+y*s.y)%n,
(x*s.y+y*(s.x+s.y))%n);
}
S operator^(unsigned n){
return n?(n&1?*this*(*this^(n-1)):(*this* *this)^(n>>1)):1;
}
};
S::ull S::n;
bool is_prime(unsigned n){
S::n=n;
S s=S(0,1,0,0,1)^n;
return (3*s.a+2*s.c)%n==0 && (2*s.x+s.y)%n==1;
}