pri_test.c 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161
  1. /*
  2. *******************************************************************************
  3. \file pri_test.c
  4. \brief Tests for prime numbers
  5. \project bee2/test
  6. \created 2014.07.07
  7. \version 2024.02.26
  8. \copyright The Bee2 authors
  9. \license Licensed under the Apache License, Version 2.0 (see LICENSE.txt).
  10. *******************************************************************************
  11. */
  12. #include <bee2/core/mem.h>
  13. #include <bee2/core/prng.h>
  14. #include <bee2/core/util.h>
  15. #include <bee2/core/word.h>
  16. #include <bee2/math/pri.h>
  17. #include <bee2/math/ww.h>
  18. /*
  19. *******************************************************************************
  20. Тестирование
  21. *******************************************************************************
  22. */
  23. bool_t priTest()
  24. {
  25. size_t i;
  26. size_t n;
  27. word a[W_OF_B(521)];
  28. word p[W_OF_B(289)];
  29. word mods[1024];
  30. octet combo_state[32];
  31. octet stack[4096];
  32. // инициализировать генератор COMBO
  33. if (sizeof(combo_state) < prngCOMBO_keep())
  34. return FALSE;
  35. prngCOMBOStart(combo_state, utilNonce32());
  36. // проверить простоту элементов факторной базы
  37. if (sizeof(stack) < priIsPrimeW_deep() ||
  38. sizeof(stack) < priIsPrime_deep(1))
  39. return FALSE;
  40. for (i = 0; i < priBaseSize(); ++i)
  41. {
  42. a[0] = priBasePrime(i);
  43. if (!priIsPrimeW(a[0], stack) ||
  44. !priIsPrime(a, 1, stack))
  45. return FALSE;
  46. }
  47. // найти произведение квадратов первых простых факторной базы
  48. a[0] = 1, n = 1;
  49. for (i = 0; i < priBaseSize() && n + 2 < COUNT_OF(a); ++i)
  50. {
  51. register word w;
  52. w = zzMulW(a, a, n, priBasePrime(i));
  53. if (w > 0)
  54. a[n++] = w;
  55. w = zzMulW(a, a, n, priBasePrime(i));
  56. if (w > 0)
  57. a[n++] = w;
  58. }
  59. // проверить гладкость и просеянность
  60. if (sizeof(stack) < priIsSieved_deep(n) ||
  61. sizeof(stack) < priIsSmooth_deep(n) ||
  62. priIsSieved(a, n, i, stack) ||
  63. !priIsSmooth(a, n, i, stack))
  64. return FALSE;
  65. VERIFY(zzAddW2(a, n, 2) == 0);
  66. if (!priIsSieved(a, n, i, stack) ||
  67. priIsSmooth(a, n, i, stack))
  68. return FALSE;
  69. // проверить простоту числа Ферма 2^{2^5} + 1
  70. wwSetZero(a, W_OF_B(32));
  71. wwSetBit(a, 32, 1);
  72. zzAddW2(a, W_OF_B(32), 1);
  73. if (sizeof(stack) < priIsPrime_deep(W_OF_B(32)) ||
  74. priIsPrime(a, W_OF_B(32), stack) != FALSE)
  75. return FALSE;
  76. // проверить простоту 13-го числа Мерсенна 2^521 - 1
  77. wwSetZero(a, W_OF_B(521));
  78. wwSetBit(a, 521, 1);
  79. zzSubW2(a, W_OF_B(521), 1);
  80. if (sizeof(stack) < priRMTest_deep(W_OF_B(521)) ||
  81. priRMTest(a, W_OF_B(521), 20, stack) != TRUE)
  82. return FALSE;
  83. // остатки по простым из факторной базы
  84. i = MIN2(COUNT_OF(mods), priBaseSize());
  85. priBaseMod(mods, a, W_OF_B(521), i);
  86. while (i--)
  87. if (mods[i] != zzModW(a, W_OF_B(521), priBasePrime(i)) ||
  88. priBasePrime(i) < WORD_BIT_HALF &&
  89. mods[i] != zzModW2(a, W_OF_B(521), priBasePrime(i)))
  90. return FALSE;
  91. // найти 2-битовое нечетное простое число
  92. a[0] = 2;
  93. if (sizeof(stack) < priNextPrime_deep(1, 0) ||
  94. !priNextPrime(a, a, 1, SIZE_MAX, 0, B_PER_IMPOSSIBLE, stack) ||
  95. a[0] != 3)
  96. return FALSE;
  97. // найти 10-битовое нечетное простое число
  98. a[0] = 512;
  99. if (sizeof(stack) < priNextPrime_deep(1, 0) ||
  100. !priNextPrime(a, a, 1, SIZE_MAX, 0, B_PER_IMPOSSIBLE, stack) ||
  101. a[0] != 521)
  102. return FALSE;
  103. // найти следующее 10-битовое нечетное простое число
  104. if (sizeof(stack) < priNextPrimeW_deep() ||
  105. !priNextPrimeW(a, ++a[0], stack) ||
  106. a[0] != 523)
  107. return FALSE;
  108. // убедиться, что 2^256 - 400 не является гладким
  109. memSet(a, 0xFF, O_OF_B(256));
  110. zzSubW2(a, W_OF_B(256), 400);
  111. if (sizeof(stack) < priIsSmooth_deep(W_OF_B(256)) ||
  112. priIsSmooth(a, W_OF_B(256), priBaseSize(), stack))
  113. return FALSE;
  114. // найти простое число 2^256 - 357
  115. if (priBaseSize() < 10 ||
  116. sizeof(stack) < priNextPrime_deep(W_OF_B(256), 10) ||
  117. !priNextPrime(a, a, W_OF_B(256), 50, 10, B_PER_IMPOSSIBLE, stack) ||
  118. a[0] != WORD_MAX - 356 ||
  119. !wwIsRepW(a + 1, W_OF_B(256) - 1, WORD_MAX))
  120. return FALSE;
  121. // найти простое число 2^256 - 189
  122. zzAddW2(a, W_OF_B(256), 1);
  123. if (!priNextPrime(a, a, W_OF_B(256), 200, 10, B_PER_IMPOSSIBLE, stack) ||
  124. a[0] != WORD_MAX - 188 ||
  125. !wwIsRepW(a + 1, W_OF_B(256) - 1, WORD_MAX))
  126. return FALSE;
  127. // построить 289-битовое простое вида 2r(2^256 - 189) + 1
  128. if (priBaseSize() < 10 ||
  129. sizeof(stack) < priExtendPrime_deep(289, W_OF_B(256), 0) ||
  130. !priExtendPrime(p, 289, a, W_OF_B(256), SIZE_MAX, 0, prngCOMBOStepR,
  131. combo_state, stack) ||
  132. sizeof(stack) < priIsPrime_deep(W_OF_B(256)) ||
  133. !priIsPrime(p, W_OF_B(289), stack))
  134. return FALSE;
  135. // удостовериться, что в интервале (2^256 - 188, 2^256 - 1) нет простых
  136. zzAddW2(a, W_OF_B(256), 1);
  137. if (sizeof(stack) < priNextPrime_deep(W_OF_B(256), 200) ||
  138. priNextPrime(a, a, W_OF_B(256), 200, 0, B_PER_IMPOSSIBLE, stack))
  139. return FALSE;
  140. // проверить, что 2^256 - 29237 является простым Жермен
  141. memSet(a, 0xFF, O_OF_B(256));
  142. a[0] = WORD_MAX - 29236;
  143. if (sizeof(stack) < priIsSieved_deep(10) ||
  144. sizeof(stack) < priIsSGPrime_deep(W_OF_B(256)) ||
  145. !priIsSieved(a, W_OF_B(256), 10, stack) ||
  146. !priIsSGPrime(a, W_OF_B(256), stack) != 0)
  147. return FALSE;
  148. // построить простое 23 = 2 * 11 + 1 (за одну попытку)
  149. a[0] = 11;
  150. if (sizeof(stack) < priExtendPrime_deep(5, 1, 10) ||
  151. !priExtendPrime(p, 5, a, 1, SIZE_MAX, 0,
  152. prngCOMBOStepR, combo_state, stack) ||
  153. p[0] != 23)
  154. return FALSE;
  155. // все нормально
  156. return TRUE;
  157. }