bn_mp_dr_reduce.c 2.4 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394
  1. #include <tommath.h>
  2. #ifdef BN_MP_DR_REDUCE_C
  3. /* LibTomMath, multiple-precision integer library -- Tom St Denis
  4. *
  5. * LibTomMath is a library that provides multiple-precision
  6. * integer arithmetic as well as number theoretic functionality.
  7. *
  8. * The library was designed directly after the MPI library by
  9. * Michael Fromberger but has been written from scratch with
  10. * additional optimizations in place.
  11. *
  12. * The library is free for all purposes without any express
  13. * guarantee it works.
  14. *
  15. * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com
  16. */
  17. /* reduce "x" in place modulo "n" using the Diminished Radix algorithm.
  18. *
  19. * Based on algorithm from the paper
  20. *
  21. * "Generating Efficient Primes for Discrete Log Cryptosystems"
  22. * Chae Hoon Lim, Pil Joong Lee,
  23. * POSTECH Information Research Laboratories
  24. *
  25. * The modulus must be of a special format [see manual]
  26. *
  27. * Has been modified to use algorithm 7.10 from the LTM book instead
  28. *
  29. * Input x must be in the range 0 <= x <= (n-1)**2
  30. */
  31. int
  32. mp_dr_reduce (mp_int * x, mp_int * n, mp_digit k)
  33. {
  34. int err, i, m;
  35. mp_word r;
  36. mp_digit mu, *tmpx1, *tmpx2;
  37. /* m = digits in modulus */
  38. m = n->used;
  39. /* ensure that "x" has at least 2m digits */
  40. if (x->alloc < m + m) {
  41. if ((err = mp_grow (x, m + m)) != MP_OKAY) {
  42. return err;
  43. }
  44. }
  45. /* top of loop, this is where the code resumes if
  46. * another reduction pass is required.
  47. */
  48. top:
  49. /* aliases for digits */
  50. /* alias for lower half of x */
  51. tmpx1 = x->dp;
  52. /* alias for upper half of x, or x/B**m */
  53. tmpx2 = x->dp + m;
  54. /* set carry to zero */
  55. mu = 0;
  56. /* compute (x mod B**m) + k * [x/B**m] inline and inplace */
  57. for (i = 0; i < m; i++) {
  58. r = ((mp_word)*tmpx2++) * ((mp_word)k) + *tmpx1 + mu;
  59. *tmpx1++ = (mp_digit)(r & MP_MASK);
  60. mu = (mp_digit)(r >> ((mp_word)DIGIT_BIT));
  61. }
  62. /* set final carry */
  63. *tmpx1++ = mu;
  64. /* zero words above m */
  65. for (i = m + 1; i < x->used; i++) {
  66. *tmpx1++ = 0;
  67. }
  68. /* clamp, sub and return */
  69. mp_clamp (x);
  70. /* if x >= n then subtract and reduce again
  71. * Each successive "recursion" makes the input smaller and smaller.
  72. */
  73. if (mp_cmp_mag (x, n) != MP_LT) {
  74. s_mp_sub(x, n, x);
  75. goto top;
  76. }
  77. return MP_OKAY;
  78. }
  79. #endif
  80. /* $Source: /cvs/libtom/libtommath/bn_mp_dr_reduce.c,v $ */
  81. /* $Revision: 1.3 $ */
  82. /* $Date: 2006/03/31 14:18:44 $ */