probably_prime.c 1.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293
  1. /*
  2. * This file is part of the UCB release of Plan 9. It is subject to the license
  3. * terms in the LICENSE file found in the top-level directory of this
  4. * distribution and at http://akaros.cs.berkeley.edu/files/Plan9License. No
  5. * part of the UCB release of Plan 9, including this file, may be copied,
  6. * modified, propagated, or distributed except according to the terms contained
  7. * in the LICENSE file.
  8. */
  9. #include "os.h"
  10. #include <mp.h>
  11. #include <libsec.h>
  12. // Miller-Rabin probabilistic primality testing
  13. // Knuth (1981) Seminumerical Algorithms, p.379
  14. // Menezes et al () Handbook, p.39
  15. // 0 if composite; 1 if almost surely prime, Pr(err)<1/4**nrep
  16. int
  17. probably_prime(mpint *n, int nrep)
  18. {
  19. int j, k, rep, nbits, isprime = 1;
  20. mpint *nm1, *q, *x, *y, *r;
  21. if(n->sign < 0)
  22. sysfatal("negative prime candidate");
  23. if(nrep <= 0)
  24. nrep = 18;
  25. k = mptoi(n);
  26. if(k == 2) // 2 is prime
  27. return 1;
  28. if(k < 2) // 1 is not prime
  29. return 0;
  30. if((n->p[0] & 1) == 0) // even is not prime
  31. return 0;
  32. // test against small prime numbers
  33. if(smallprimetest(n) < 0)
  34. return 0;
  35. // fermat test, 2^n mod n == 2 if p is prime
  36. x = uitomp(2, nil);
  37. y = mpnew(0);
  38. mpexp(x, n, n, y);
  39. k = mptoi(y);
  40. if(k != 2){
  41. mpfree(x);
  42. mpfree(y);
  43. return 0;
  44. }
  45. nbits = mpsignif(n);
  46. nm1 = mpnew(nbits);
  47. mpsub(n, mpone, nm1); // nm1 = n - 1 */
  48. k = mplowbits0(nm1);
  49. q = mpnew(0);
  50. mpright(nm1, k, q); // q = (n-1)/2**k
  51. for(rep = 0; rep < nrep; rep++){
  52. // x = random in [2, n-2]
  53. r = mprand(nbits, prng, nil);
  54. mpmod(r, nm1, x);
  55. mpfree(r);
  56. if(mpcmp(x, mpone) <= 0)
  57. continue;
  58. // y = x**q mod n
  59. mpexp(x, q, n, y);
  60. if(mpcmp(y, mpone) == 0 || mpcmp(y, nm1) == 0)
  61. goto done;
  62. for(j = 1; j < k; j++){
  63. mpmul(y, y, x);
  64. mpmod(x, n, y); // y = y*y mod n
  65. if(mpcmp(y, nm1) == 0)
  66. goto done;
  67. if(mpcmp(y, mpone) == 0){
  68. isprime = 0;
  69. goto done;
  70. }
  71. }
  72. isprime = 0;
  73. }
  74. done:
  75. mpfree(y);
  76. mpfree(x);
  77. mpfree(q);
  78. mpfree(nm1);
  79. return isprime;
  80. }