diff --git a/mathx/number_theory.h b/mathx/number_theory.h index 0572f3e..24cffaa 100644 --- a/mathx/number_theory.h +++ b/mathx/number_theory.h @@ -2,8 +2,11 @@ #define MATHX_NUMBER_THEORY_H_ namespace mathx { - int gcd(int a, int b); - int lcm(int a, int b); + long long gcd(long long a, long long b); + long long lcm(long long a, long long b); + long long pow(long long a, long long e, long long mod); + bool is_miller_rabin_witness(long long a, long long p); + bool is_prime_fast(long long p); } #endif diff --git a/src/number_theory.cpp b/src/number_theory.cpp index a3c66a5..5a52654 100644 --- a/src/number_theory.cpp +++ b/src/number_theory.cpp @@ -1,7 +1,7 @@ #include namespace mathx { - int gcd(int a, int b) { + long long gcd(long long a, long long b) { while( a * b ){ if(a > b) a = a % b; @@ -10,7 +10,63 @@ namespace mathx { } return a + b; } - int lcm(int a, int b) { + + long long lcm(long long a, long long b) { return (a * b / gcd(a,b)); } + + long long pow(long long a, long long e, long long mod) { + if (e == 0) { + return 1; + } + + long long x = mathx::pow(a, e / 2, mod); + if (e % 2 == 0) { + return (x * x) % mod; + } + else { + return (((x * x) % mod) * x) % mod; + } + } + + bool is_miller_rabin_witness(long long a, long long p) { + long long g = mathx::gcd(a,p); + if (g == 1) { + return true; + } + + long long k = 0; + long long q = p - 1; + while (q % 2 == 0) { + q = q / 2; + ++k; + } + long long temp = mathx::pow(a, q, p); + if (temp == 1) { + return false; + } + + for (int i = 0; i < k; ++i) { + if (temp == p - 1) { + return false; + } + else { + temp = (temp * temp) % p; + } + } + return true; + } + + + bool is_prime_fast(long long p) { + if (p == 1) { + return false; + } + for (int i = 0; i < 100; ++i) { + if (mathx::is_miller_rabin_witness(i, p) == true) { + return false; + } + } + return true; + } }