mprime.cpp 1.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143
  1. // Bignum prime test (returns 1 if prime, 0 if not)
  2. // Uses Algorithm P (probabilistic primality test) from p. 395 of
  3. // "The Art of Computer Programming, Volume 2" by Donald E. Knuth.
  4. #include "stdafx.h"
  5. #include "defs.h"
  6. static int mprimef(unsigned int *, unsigned int *, int);
  7. int
  8. mprime(unsigned int *n)
  9. {
  10. int i, k;
  11. unsigned int *q;
  12. // 1?
  13. if (MLENGTH(n) == 1 && n[0] == 1)
  14. return 0;
  15. // 2?
  16. if (MLENGTH(n) == 1 && n[0] == 2)
  17. return 1;
  18. // even?
  19. if ((n[0] & 1) == 0)
  20. return 0;
  21. // n = 1 + (2 ^ k) q
  22. q = mcopy(n);
  23. k = 0;
  24. do {
  25. mshiftright(q);
  26. k++;
  27. } while ((q[0] & 1) == 0);
  28. // try 25 times
  29. for (i = 0; i < 25; i++)
  30. if (mprimef(n, q, k) == 0)
  31. break;
  32. mfree(q);
  33. if (i < 25)
  34. return 0;
  35. else
  36. return 1;
  37. }
  38. //-----------------------------------------------------------------------------
  39. //
  40. // This is the actual implementation of Algorithm P.
  41. //
  42. // Input: n The number in question.
  43. //
  44. // q n = 1 + (2 ^ k) q
  45. //
  46. // k
  47. //
  48. // Output: 1 when n is probably prime
  49. //
  50. // 0 when n is definitely not prime
  51. //
  52. //-----------------------------------------------------------------------------
  53. static int
  54. mprimef(unsigned int *n, unsigned int *q, int k)
  55. {
  56. int i, j;
  57. unsigned int *t, *x, *y;
  58. // generate x
  59. t = mcopy(n);
  60. while (1) {
  61. for (i = 0; i < MLENGTH(t); i++)
  62. t[i] = rand();
  63. x = mmod(t, n);
  64. if (!MZERO(x) && !MEQUAL(x, 1))
  65. break;
  66. mfree(x);
  67. }
  68. mfree(t);
  69. // exponentiate
  70. y = mmodpow(x, q, n);
  71. // done?
  72. if (MEQUAL(y, 1)) {
  73. mfree(x);
  74. mfree(y);
  75. return 1;
  76. }
  77. j = 0;
  78. while (1) {
  79. // y = n - 1?
  80. t = msub(n, y);
  81. if (MEQUAL(t, 1)) {
  82. mfree(t);
  83. mfree(x);
  84. mfree(y);
  85. return 1;
  86. }
  87. mfree(t);
  88. if (++j == k) {
  89. mfree(x);
  90. mfree(y);
  91. return 0;
  92. }
  93. // y = (y ^ 2) mod n
  94. t = mmul(y, y);
  95. mfree(y);
  96. y = mmod(t, n);
  97. mfree(t);
  98. // y = 1?
  99. if (MEQUAL(y, 1)) {
  100. mfree(x);
  101. mfree(y);
  102. return 0;
  103. }
  104. }
  105. }