Fun for Math Geeks
There are probably better ways of doing this. Any suggestions?
gmptrialdiv.c
/* a basic program for testing the primality of a number using trial
* division
*
* Author: Ron Henry - rlh@ciphermonk.net
* Ciphermonk Research
*
* Notes: Assumes an _odd number_ as input. Program has
* a maximum runtime of sqrt(n)/2.
*
* Variables: n == the input number to be tested for primality
* i == the iterator/counter variable
* root == sqrt of n. used to reduce the length of the test
* rem == the remainder captured from modulo operations
*/
#include <stdio.h>
#include <gmp.h>
int main(int argc, char *argv[])
{
if(argc < 2) {
fprintf(stderr, "Usage: %s <primality test candidate>\n", *argv);
return 1;
}
/* Create and Initialize variables */
mpz_t i, n, root, rem;
mpz_init(n);
mpz_init_set_str(i, "3", 10);
mpz_init(root);
mpz_init(rem);
mpz_set_str(n, argv[1], 10); /* Copy user input to 'n' */
/* Test for even number as input. */
mpz_cdiv_r_ui(rem, n, (unsigned long) 2);
if((mpz_cmp_ui(rem, (unsigned long) 0)) == 0) {
printf("%s expects odd numbers as input!\n", argv[0]);
return 0;
}
/* End even number input check */
/* ============== Tests for Primality Start ============== */
mpz_init(rem); /* Zero out the remainder again */
mpz_sqrt(root, n); /* we shouldn't have to test
more than sqrt(n)/2 factors
to determine primality
*/
mpz_cdiv_q_ui(rem, root, (unsigned long) 2); /* borrowing rem for a quick calculation */
mpz_add_ui(root,root, (unsigned long) 1); /* increment root by 1 to compensate for
rounding */
gmp_printf("\n- Attempting Trial Division for up to %Zd iterations\n", root);
while(mpz_cmp(i, root) < 0) {
mpz_cdiv_r(rem, n, i);
if((mpz_cmp_ui(rem, (unsigned long) 0)) == 0) {
mpz_cdiv_q(rem, n, i);
gmp_printf("Factors of %Zd are %Zd and %Zd\n", n, i, rem);
return 0;
}
else
mpz_add_ui(i, i, (unsigned long) 2); /*divide by the next odd integer*/
}
gmp_printf("%Zd is prime!\n", n);
mpz_clear(i);
mpz_clear(n);
mpz_clear(root);
mpz_clear(rem);
return 0;
}