prime.odin 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256
  1. package math_big
  2. /*
  3. Copyright 2021 Jeroen van Rijn <[email protected]>.
  4. Made available under Odin's BSD-3 license.
  5. An arbitrary precision mathematics implementation in Odin.
  6. For the theoretical underpinnings, see Knuth's The Art of Computer Programming, Volume 2, section 4.3.
  7. The code started out as an idiomatic source port of libTomMath, which is in the public domain, with thanks.
  8. This file contains prime finding operations.
  9. */
  10. /*
  11. Determines if an Integer is divisible by one of the _PRIME_TABLE primes.
  12. Returns true if it is, false if not.
  13. */
  14. int_prime_is_divisible :: proc(a: ^Int, allocator := context.allocator) -> (res: bool, err: Error) {
  15. assert_if_nil(a);
  16. context.allocator = allocator;
  17. internal_clear_if_uninitialized(a) or_return;
  18. for prime in _private_prime_table {
  19. rem := #force_inline int_mod_digit(a, prime) or_return;
  20. if rem == 0 {
  21. return true, nil;
  22. }
  23. }
  24. /*
  25. Default to not divisible.
  26. */
  27. return false, nil;
  28. }
  29. /*
  30. Computes xR**-1 == x (mod N) via Montgomery Reduction.
  31. */
  32. internal_int_montgomery_reduce :: proc(x, n: ^Int, rho: DIGIT, allocator := context.allocator) -> (err: Error) {
  33. context.allocator = allocator;
  34. /*
  35. Can the fast reduction [comba] method be used?
  36. Note that unlike in mul, you're safely allowed *less* than the available columns [255 per default],
  37. since carries are fixed up in the inner loop.
  38. */
  39. digs := (n.used * 2) + 1;
  40. if digs < _WARRAY && x.used <= _WARRAY && n.used < _MAX_COMBA {
  41. return _private_montgomery_reduce_comba(x, n, rho);
  42. }
  43. /*
  44. Grow the input as required
  45. */
  46. internal_grow(x, digs) or_return;
  47. x.used = digs;
  48. for ix := 0; ix < n.used; ix += 1 {
  49. /*
  50. `mu = ai * rho mod b`
  51. The value of rho must be precalculated via `int_montgomery_setup()`,
  52. such that it equals -1/n0 mod b this allows the following inner loop
  53. to reduce the input one digit at a time.
  54. */
  55. mu := DIGIT((_WORD(x.digit[ix]) * _WORD(rho)) & _WORD(_MASK));
  56. /*
  57. a = a + mu * m * b**i
  58. Multiply and add in place.
  59. */
  60. u := DIGIT(0);
  61. iy := int(0);
  62. for ; iy < n.used; iy += 1 {
  63. /*
  64. Compute product and sum.
  65. */
  66. r := (_WORD(mu) * _WORD(n.digit[iy]) + _WORD(u) + _WORD(x.digit[ix + iy]));
  67. /*
  68. Get carry.
  69. */
  70. u = DIGIT(r >> _DIGIT_BITS);
  71. /*
  72. Fix digit.
  73. */
  74. x.digit[ix + iy] = DIGIT(r & _WORD(_MASK));
  75. }
  76. /*
  77. At this point the ix'th digit of x should be zero.
  78. Propagate carries upwards as required.
  79. */
  80. for u != 0 {
  81. x.digit[ix + iy] += u;
  82. u = x.digit[ix + iy] >> _DIGIT_BITS;
  83. x.digit[ix + iy] &= _MASK;
  84. iy += 1;
  85. }
  86. }
  87. /*
  88. At this point the n.used'th least significant digits of x are all zero,
  89. which means we can shift x to the right by n.used digits and the
  90. residue is unchanged.
  91. x = x/b**n.used.
  92. */
  93. internal_clamp(x);
  94. internal_shr_digit(x, n.used);
  95. /*
  96. if x >= n then x = x - n
  97. */
  98. if internal_cmp_mag(x, n) != -1 {
  99. return internal_sub(x, x, n);
  100. }
  101. return nil;
  102. }
  103. int_montgomery_reduce :: proc(x, n: ^Int, rho: DIGIT, allocator := context.allocator) -> (err: Error) {
  104. assert_if_nil(x, n);
  105. context.allocator = allocator;
  106. internal_clear_if_uninitialized(x, n) or_return;
  107. return #force_inline internal_int_montgomery_reduce(x, n, rho);
  108. }
  109. /*
  110. Shifts with subtractions when the result is greater than b.
  111. The method is slightly modified to shift B unconditionally upto just under
  112. the leading bit of b. This saves alot of multiple precision shifting.
  113. */
  114. internal_int_montgomery_calc_normalization :: proc(a, b: ^Int, allocator := context.allocator) -> (err: Error) {
  115. context.allocator = allocator;
  116. /*
  117. How many bits of last digit does b use.
  118. */
  119. bits := internal_count_bits(b) % _DIGIT_BITS;
  120. if b.used > 1 {
  121. power := ((b.used - 1) * _DIGIT_BITS) + bits - 1;
  122. internal_int_power_of_two(a, power) or_return;
  123. } else {
  124. internal_one(a);
  125. bits = 1;
  126. }
  127. /*
  128. Now compute C = A * B mod b.
  129. */
  130. for x := bits - 1; x < _DIGIT_BITS; x += 1 {
  131. internal_int_shl1(a, a) or_return;
  132. if internal_cmp_mag(a, b) != -1 {
  133. internal_sub(a, a, b) or_return;
  134. }
  135. }
  136. return nil;
  137. }
  138. int_montgomery_calc_normalization :: proc(a, b: ^Int, allocator := context.allocator) -> (err: Error) {
  139. assert_if_nil(a, b);
  140. context.allocator = allocator;
  141. internal_clear_if_uninitialized(a, b) or_return;
  142. return #force_inline internal_int_montgomery_calc_normalization(a, b);
  143. }
  144. /*
  145. Sets up the Montgomery reduction stuff.
  146. */
  147. internal_int_montgomery_setup :: proc(n: ^Int) -> (rho: DIGIT, err: Error) {
  148. /*
  149. Fast inversion mod 2**k
  150. Based on the fact that:
  151. XA = 1 (mod 2**n) => (X(2-XA)) A = 1 (mod 2**2n)
  152. => 2*X*A - X*X*A*A = 1
  153. => 2*(1) - (1) = 1
  154. */
  155. b := n.digit[0];
  156. if b & 1 == 0 { return 0, .Invalid_Argument; }
  157. x := (((b + 2) & 4) << 1) + b; /* here x*a==1 mod 2**4 */
  158. x *= 2 - (b * x); /* here x*a==1 mod 2**8 */
  159. x *= 2 - (b * x); /* here x*a==1 mod 2**16 */
  160. when _WORD_TYPE_BITS == 64 {
  161. x *= 2 - (b * x); /* here x*a==1 mod 2**32 */
  162. x *= 2 - (b * x); /* here x*a==1 mod 2**64 */
  163. }
  164. /*
  165. rho = -1/m mod b
  166. */
  167. rho = DIGIT(((_WORD(1) << _WORD(_DIGIT_BITS)) - _WORD(x)) & _WORD(_MASK));
  168. return rho, nil;
  169. }
  170. int_montgomery_setup :: proc(n: ^Int, allocator := context.allocator) -> (rho: DIGIT, err: Error) {
  171. assert_if_nil(n);
  172. internal_clear_if_uninitialized(n, allocator) or_return;
  173. return #force_inline internal_int_montgomery_setup(n);
  174. }
  175. /*
  176. Returns the number of Rabin-Miller trials needed for a given bit size.
  177. */
  178. number_of_rabin_miller_trials :: proc(bit_size: int) -> (number_of_trials: int) {
  179. switch {
  180. case bit_size <= 80:
  181. return - 1; /* Use deterministic algorithm for size <= 80 bits */
  182. case bit_size >= 81 && bit_size < 96:
  183. return 37; /* max. error = 2^(-96) */
  184. case bit_size >= 96 && bit_size < 128:
  185. return 32; /* max. error = 2^(-96) */
  186. case bit_size >= 128 && bit_size < 160:
  187. return 40; /* max. error = 2^(-112) */
  188. case bit_size >= 160 && bit_size < 256:
  189. return 35; /* max. error = 2^(-112) */
  190. case bit_size >= 256 && bit_size < 384:
  191. return 27; /* max. error = 2^(-128) */
  192. case bit_size >= 384 && bit_size < 512:
  193. return 16; /* max. error = 2^(-128) */
  194. case bit_size >= 512 && bit_size < 768:
  195. return 18; /* max. error = 2^(-160) */
  196. case bit_size >= 768 && bit_size < 896:
  197. return 11; /* max. error = 2^(-160) */
  198. case bit_size >= 896 && bit_size < 1_024:
  199. return 10; /* max. error = 2^(-160) */
  200. case bit_size >= 1_024 && bit_size < 1_536:
  201. return 12; /* max. error = 2^(-192) */
  202. case bit_size >= 1_536 && bit_size < 2_048:
  203. return 8; /* max. error = 2^(-192) */
  204. case bit_size >= 2_048 && bit_size < 3_072:
  205. return 6; /* max. error = 2^(-192) */
  206. case bit_size >= 3_072 && bit_size < 4_096:
  207. return 4; /* max. error = 2^(-192) */
  208. case bit_size >= 4_096 && bit_size < 5_120:
  209. return 5; /* max. error = 2^(-256) */
  210. case bit_size >= 5_120 && bit_size < 6_144:
  211. return 4; /* max. error = 2^(-256) */
  212. case bit_size >= 6_144 && bit_size < 8_192:
  213. return 4; /* max. error = 2^(-256) */
  214. case bit_size >= 8_192 && bit_size < 9_216:
  215. return 3; /* max. error = 2^(-256) */
  216. case bit_size >= 9_216 && bit_size < 10_240:
  217. return 3; /* max. error = 2^(-256) */
  218. case:
  219. return 2; /* For keysizes bigger than 10_240 use always at least 2 Rounds */
  220. }
  221. }