bn_mp_reduce.c 2.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100
  1. #include <tommath.h>
  2. #ifdef BN_MP_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. /* reduces x mod m, assumes 0 < x < m**2, mu is
  18. * precomputed via mp_reduce_setup.
  19. * From HAC pp.604 Algorithm 14.42
  20. */
  21. int mp_reduce (mp_int * x, mp_int * m, mp_int * mu)
  22. {
  23. mp_int q;
  24. int res, um = m->used;
  25. /* q = x */
  26. if ((res = mp_init_copy (&q, x)) != MP_OKAY) {
  27. return res;
  28. }
  29. /* q1 = x / b**(k-1) */
  30. mp_rshd (&q, um - 1);
  31. /* according to HAC this optimization is ok */
  32. if (((unsigned long) um) > (((mp_digit)1) << (DIGIT_BIT - 1))) {
  33. if ((res = mp_mul (&q, mu, &q)) != MP_OKAY) {
  34. goto CLEANUP;
  35. }
  36. } else {
  37. #ifdef BN_S_MP_MUL_HIGH_DIGS_C
  38. if ((res = s_mp_mul_high_digs (&q, mu, &q, um)) != MP_OKAY) {
  39. goto CLEANUP;
  40. }
  41. #elif defined(BN_FAST_S_MP_MUL_HIGH_DIGS_C)
  42. if ((res = fast_s_mp_mul_high_digs (&q, mu, &q, um)) != MP_OKAY) {
  43. goto CLEANUP;
  44. }
  45. #else
  46. {
  47. res = MP_VAL;
  48. goto CLEANUP;
  49. }
  50. #endif
  51. }
  52. /* q3 = q2 / b**(k+1) */
  53. mp_rshd (&q, um + 1);
  54. /* x = x mod b**(k+1), quick (no division) */
  55. if ((res = mp_mod_2d (x, DIGIT_BIT * (um + 1), x)) != MP_OKAY) {
  56. goto CLEANUP;
  57. }
  58. /* q = q * m mod b**(k+1), quick (no division) */
  59. if ((res = s_mp_mul_digs (&q, m, &q, um + 1)) != MP_OKAY) {
  60. goto CLEANUP;
  61. }
  62. /* x = x - q */
  63. if ((res = mp_sub (x, &q, x)) != MP_OKAY) {
  64. goto CLEANUP;
  65. }
  66. /* If x < 0, add b**(k+1) to it */
  67. if (mp_cmp_d (x, 0) == MP_LT) {
  68. mp_set (&q, 1);
  69. if ((res = mp_lshd (&q, um + 1)) != MP_OKAY)
  70. goto CLEANUP;
  71. if ((res = mp_add (x, &q, x)) != MP_OKAY)
  72. goto CLEANUP;
  73. }
  74. /* Back off if it's too big */
  75. while (mp_cmp (x, m) != MP_LT) {
  76. if ((res = s_mp_sub (x, m, x)) != MP_OKAY) {
  77. goto CLEANUP;
  78. }
  79. }
  80. CLEANUP:
  81. mp_clear (&q);
  82. return res;
  83. }
  84. #endif
  85. /* $Source: /cvs/libtom/libtommath/bn_mp_reduce.c,v $ */
  86. /* $Revision: 1.3 $ */
  87. /* $Date: 2006/03/31 14:18:44 $ */