int aks_is_prime(mpz_t n) { // Peform simple checks before running the AKS algorithm if (mpz_cmp_ui(n, 2) == 0) { return PRIME; } if (mpz_cmp_ui(n, 1) <= 0 || mpz_divisible_ui_p(n, 2)) { return COMPOSITE; } // Step 1: Check if n is a perfect power, meaning n = a ^ b where a is a natural number and b > 1 if (mpz_perfect_power_p(n)) { return COMPOSITE; } // Step 2: Find the smallest r such that or(n) > log(n) ^ 2 mpz_t r; mpz_init(r); find_smallest_r(r, n); if (aks_debug) gmp_printf("r=%Zd\n", r); // Step 3: Check if there exists an a <= r such that 1 < (a,n) < n if (check_a_exists(n, r)) { mpz_clear(r); return COMPOSITE; } if (aks_debug) gmp_printf("a does not exist\n"); // Step 4: Check if n <= r if (mpz_cmp(n, r) <= 0) { mpz_clear(r); return PRIME; } if (aks_debug) gmp_printf("checking polynomial equation\n"); // Step 5 if (check_polys(r, n)) { mpz_clear(r); return COMPOSITE; } mpz_clear(r); // Step 6 return PRIME; }
int aks (mpz_t n) { mpz_t r; mpz_t a; mpz_t max_a; mpz_t gcd_rslt; mpz_t totient_r; mpf_t ftotient_r; mpf_t sqrt_rslt; mpf_t sqrt_rslt2; mpf_t temp; mpf_t temp2; sli_t logn; /* For the sake of maple kernel */ int argc = 0; char **argv; char err[2048]; mpz_init (r); mpz_init (a); mpz_init (max_a); mpz_init (gcd_rslt); mpz_init (totient_r); mpf_init (ftotient_r); mpf_init (sqrt_rslt); mpf_init (sqrt_rslt2); mpf_init (temp); mpf_init (temp2); /* 1. If (n = a^k for a in N and b > 1) output COMPOSITE */ if (mpz_perfect_power_p (n) != 0) { printf ("Step 1 detected composite\n"); return FALSE; } /* 2. Find the smallest r such that or(n) > 4(log n)^2 */ find_smallest_r (r, n); gmp_printf ("good r seems to be %Zd\n", r); /* 3. If 1 < gcd(a, n) < n for some a <= r, output COMPOSITE */ /* for (a = 1; a <= r; a++) { * gcd_rslt = gcd(a, n); * if (gcd_rslt > 1 && gcd_rslt < n) { * return FALSE; * } * } */ for (mpz_set_ui (a, 1); mpz_cmp (a, r) < 0 || mpz_cmp (a, r) == 0; mpz_add_ui (a, a, 1)) { mpz_gcd (gcd_rslt, a, n); if (mpz_cmp_ui (gcd_rslt, 1) > 0 && mpz_cmp (gcd_rslt, n) < 0) { printf ("Step 3 detected composite\n"); return FALSE; } } /* 4. If n <= r, output PRIME */ if (mpz_cmp (n, r) < 0 || mpz_cmp (n, r) == 0) { printf ("Step 4 detected prime\n"); return TRUE; } /* 5. For a = 1 to floor(2*sqrt(totient(r))*(log n) * if ( (X+a)^n != X^n + a (mod X^r-1, n) ), output COMPOSITE * * Choices of implementation to evaluate the polynomial equality: * (1) Implement powermodreduce on polynomial ourselves (tough manly way) * (2) Use MAPLE (not so manly, but less painful) */ /* Compute totient(r), since r is prime, this is simply r-1 */ mpz_sub_ui (totient_r, r, 1); /* Compute log n (ceilinged) */ mpz_logbase2cl (&logn, n); /* Compute sqrt(totient(r)) */ mpf_set_z (ftotient_r, totient_r); mpf_sqrt (sqrt_rslt, ftotient_r); /* Compute 2*sqrt(totient(r)) */ mpf_mul_ui (sqrt_rslt2, sqrt_rslt, 2); /* Compute 2*sqrt(totient(r))*(log n) */ mpf_set (temp, sqrt_rslt2); mpf_set_si (temp2, logn); mpf_mul (temp, temp, temp2); /* Finally, compute max_a, after lots of singing and dancing */ mpf_floor (temp, temp); mpz_set_f (max_a, temp); gmp_printf ("max_a = %Zd\n", max_a); /* Now evaluate the polynomial equality with the help of maple kernel */ /* Set up maple kernel incantations */ MKernelVector kv; MCallBackVectorDesc cb = { textCallBack, 0, /* errorCallBack not used */ 0, /* statusCallBack not used */ 0, /* readLineCallBack not used */ 0, /* redirectCallBack not used */ 0, /* streamCallBack not used */ 0, /* queryInterrupt not used */ 0 /* callBackCallBack not used */ }; /* Initialize Maple */ if ((kv = StartMaple (argc, argv, &cb, NULL, NULL, err)) == NULL) { printf ("Could not start Maple, %s\n", err); exit (666); } /* Here comes the complexity and bottleneck */ /* for (a = 1; a <= max_a; a++) { * if (!poly_eq_holds(kv, a, n, r)) { * return FALSE; * } * } */ /* Make max_a only up to 5 */ mpz_set_ui (max_a, 5); for (mpz_set_ui (a, 1); mpz_cmp (a, max_a) < 0 || mpz_cmp (a, max_a) == 0; mpz_add_ui (a, a, 1)) { if (!poly_eq_holds (kv, a, n, r)) { printf ("Step 5 detected composite\n"); return FALSE; } } /* 6. Output PRIME */ printf ("Step 6 detected prime\n"); return TRUE; }