bn_mp_div.c 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250
  1. #include "tommath_private.h"
  2. #ifdef BN_MP_DIV_C
  3. /* LibTomMath, multiple-precision integer library -- Tom St Denis */
  4. /* SPDX-License-Identifier: Unlicense */
  5. #ifdef BN_MP_DIV_SMALL
  6. /* slower bit-bang division... also smaller */
  7. mp_err mp_div(const mp_int *a, const mp_int *b, mp_int *c, mp_int *d)
  8. {
  9. mp_int ta, tb, tq, q;
  10. int n, n2;
  11. mp_err err;
  12. /* is divisor zero ? */
  13. if (MP_IS_ZERO(b)) {
  14. return MP_VAL;
  15. }
  16. /* if a < b then q=0, r = a */
  17. if (mp_cmp_mag(a, b) == MP_LT) {
  18. if (d != NULL) {
  19. err = mp_copy(a, d);
  20. } else {
  21. err = MP_OKAY;
  22. }
  23. if (c != NULL) {
  24. mp_zero(c);
  25. }
  26. return err;
  27. }
  28. /* init our temps */
  29. if ((err = mp_init_multi(&ta, &tb, &tq, &q, NULL)) != MP_OKAY) {
  30. return err;
  31. }
  32. mp_set(&tq, 1uL);
  33. n = mp_count_bits(a) - mp_count_bits(b);
  34. if ((err = mp_abs(a, &ta)) != MP_OKAY) goto LBL_ERR;
  35. if ((err = mp_abs(b, &tb)) != MP_OKAY) goto LBL_ERR;
  36. if ((err = mp_mul_2d(&tb, n, &tb)) != MP_OKAY) goto LBL_ERR;
  37. if ((err = mp_mul_2d(&tq, n, &tq)) != MP_OKAY) goto LBL_ERR;
  38. while (n-- >= 0) {
  39. if (mp_cmp(&tb, &ta) != MP_GT) {
  40. if ((err = mp_sub(&ta, &tb, &ta)) != MP_OKAY) goto LBL_ERR;
  41. if ((err = mp_add(&q, &tq, &q)) != MP_OKAY) goto LBL_ERR;
  42. }
  43. if ((err = mp_div_2d(&tb, 1, &tb, NULL)) != MP_OKAY) goto LBL_ERR;
  44. if ((err = mp_div_2d(&tq, 1, &tq, NULL)) != MP_OKAY) goto LBL_ERR;
  45. }
  46. /* now q == quotient and ta == remainder */
  47. n = a->sign;
  48. n2 = (a->sign == b->sign) ? MP_ZPOS : MP_NEG;
  49. if (c != NULL) {
  50. mp_exch(c, &q);
  51. c->sign = MP_IS_ZERO(c) ? MP_ZPOS : n2;
  52. }
  53. if (d != NULL) {
  54. mp_exch(d, &ta);
  55. d->sign = MP_IS_ZERO(d) ? MP_ZPOS : n;
  56. }
  57. LBL_ERR:
  58. mp_clear_multi(&ta, &tb, &tq, &q, NULL);
  59. return err;
  60. }
  61. #else
  62. /* integer signed division.
  63. * c*b + d == a [e.g. a/b, c=quotient, d=remainder]
  64. * HAC pp.598 Algorithm 14.20
  65. *
  66. * Note that the description in HAC is horribly
  67. * incomplete. For example, it doesn't consider
  68. * the case where digits are removed from 'x' in
  69. * the inner loop. It also doesn't consider the
  70. * case that y has fewer than three digits, etc..
  71. *
  72. * The overall algorithm is as described as
  73. * 14.20 from HAC but fixed to treat these cases.
  74. */
  75. mp_err mp_div(const mp_int *a, const mp_int *b, mp_int *c, mp_int *d)
  76. {
  77. mp_int q, x, y, t1, t2;
  78. int n, t, i, norm;
  79. mp_sign neg;
  80. mp_err err;
  81. /* is divisor zero ? */
  82. if (MP_IS_ZERO(b)) {
  83. return MP_VAL;
  84. }
  85. /* if a < b then q=0, r = a */
  86. if (mp_cmp_mag(a, b) == MP_LT) {
  87. if (d != NULL) {
  88. err = mp_copy(a, d);
  89. } else {
  90. err = MP_OKAY;
  91. }
  92. if (c != NULL) {
  93. mp_zero(c);
  94. }
  95. return err;
  96. }
  97. if ((err = mp_init_size(&q, a->used + 2)) != MP_OKAY) {
  98. return err;
  99. }
  100. q.used = a->used + 2;
  101. if ((err = mp_init(&t1)) != MP_OKAY) goto LBL_Q;
  102. if ((err = mp_init(&t2)) != MP_OKAY) goto LBL_T1;
  103. if ((err = mp_init_copy(&x, a)) != MP_OKAY) goto LBL_T2;
  104. if ((err = mp_init_copy(&y, b)) != MP_OKAY) goto LBL_X;
  105. /* fix the sign */
  106. neg = (a->sign == b->sign) ? MP_ZPOS : MP_NEG;
  107. x.sign = y.sign = MP_ZPOS;
  108. /* normalize both x and y, ensure that y >= b/2, [b == 2**MP_DIGIT_BIT] */
  109. norm = mp_count_bits(&y) % MP_DIGIT_BIT;
  110. if (norm < (MP_DIGIT_BIT - 1)) {
  111. norm = (MP_DIGIT_BIT - 1) - norm;
  112. if ((err = mp_mul_2d(&x, norm, &x)) != MP_OKAY) goto LBL_Y;
  113. if ((err = mp_mul_2d(&y, norm, &y)) != MP_OKAY) goto LBL_Y;
  114. } else {
  115. norm = 0;
  116. }
  117. /* note hac does 0 based, so if used==5 then its 0,1,2,3,4, e.g. use 4 */
  118. n = x.used - 1;
  119. t = y.used - 1;
  120. /* while (x >= y*b**n-t) do { q[n-t] += 1; x -= y*b**{n-t} } */
  121. /* y = y*b**{n-t} */
  122. if ((err = mp_lshd(&y, n - t)) != MP_OKAY) goto LBL_Y;
  123. while (mp_cmp(&x, &y) != MP_LT) {
  124. ++(q.dp[n - t]);
  125. if ((err = mp_sub(&x, &y, &x)) != MP_OKAY) goto LBL_Y;
  126. }
  127. /* reset y by shifting it back down */
  128. mp_rshd(&y, n - t);
  129. /* step 3. for i from n down to (t + 1) */
  130. for (i = n; i >= (t + 1); i--) {
  131. if (i > x.used) {
  132. continue;
  133. }
  134. /* step 3.1 if xi == yt then set q{i-t-1} to b-1,
  135. * otherwise set q{i-t-1} to (xi*b + x{i-1})/yt */
  136. if (x.dp[i] == y.dp[t]) {
  137. q.dp[(i - t) - 1] = ((mp_digit)1 << (mp_digit)MP_DIGIT_BIT) - (mp_digit)1;
  138. } else {
  139. mp_word tmp;
  140. tmp = (mp_word)x.dp[i] << (mp_word)MP_DIGIT_BIT;
  141. tmp |= (mp_word)x.dp[i - 1];
  142. tmp /= (mp_word)y.dp[t];
  143. if (tmp > (mp_word)MP_MASK) {
  144. tmp = MP_MASK;
  145. }
  146. q.dp[(i - t) - 1] = (mp_digit)(tmp & (mp_word)MP_MASK);
  147. }
  148. /* while (q{i-t-1} * (yt * b + y{t-1})) >
  149. xi * b**2 + xi-1 * b + xi-2
  150. do q{i-t-1} -= 1;
  151. */
  152. q.dp[(i - t) - 1] = (q.dp[(i - t) - 1] + 1uL) & (mp_digit)MP_MASK;
  153. do {
  154. q.dp[(i - t) - 1] = (q.dp[(i - t) - 1] - 1uL) & (mp_digit)MP_MASK;
  155. /* find left hand */
  156. mp_zero(&t1);
  157. t1.dp[0] = ((t - 1) < 0) ? 0u : y.dp[t - 1];
  158. t1.dp[1] = y.dp[t];
  159. t1.used = 2;
  160. if ((err = mp_mul_d(&t1, q.dp[(i - t) - 1], &t1)) != MP_OKAY) goto LBL_Y;
  161. /* find right hand */
  162. t2.dp[0] = ((i - 2) < 0) ? 0u : x.dp[i - 2];
  163. t2.dp[1] = x.dp[i - 1]; /* i >= 1 always holds */
  164. t2.dp[2] = x.dp[i];
  165. t2.used = 3;
  166. } while (mp_cmp_mag(&t1, &t2) == MP_GT);
  167. /* step 3.3 x = x - q{i-t-1} * y * b**{i-t-1} */
  168. if ((err = mp_mul_d(&y, q.dp[(i - t) - 1], &t1)) != MP_OKAY) goto LBL_Y;
  169. if ((err = mp_lshd(&t1, (i - t) - 1)) != MP_OKAY) goto LBL_Y;
  170. if ((err = mp_sub(&x, &t1, &x)) != MP_OKAY) goto LBL_Y;
  171. /* if x < 0 then { x = x + y*b**{i-t-1}; q{i-t-1} -= 1; } */
  172. if (x.sign == MP_NEG) {
  173. if ((err = mp_copy(&y, &t1)) != MP_OKAY) goto LBL_Y;
  174. if ((err = mp_lshd(&t1, (i - t) - 1)) != MP_OKAY) goto LBL_Y;
  175. if ((err = mp_add(&x, &t1, &x)) != MP_OKAY) goto LBL_Y;
  176. q.dp[(i - t) - 1] = (q.dp[(i - t) - 1] - 1uL) & MP_MASK;
  177. }
  178. }
  179. /* now q is the quotient and x is the remainder
  180. * [which we have to normalize]
  181. */
  182. /* get sign before writing to c */
  183. x.sign = (x.used == 0) ? MP_ZPOS : a->sign;
  184. if (c != NULL) {
  185. mp_clamp(&q);
  186. mp_exch(&q, c);
  187. c->sign = neg;
  188. }
  189. if (d != NULL) {
  190. if ((err = mp_div_2d(&x, norm, &x, NULL)) != MP_OKAY) goto LBL_Y;
  191. mp_exch(&x, d);
  192. }
  193. err = MP_OKAY;
  194. LBL_Y:
  195. mp_clear(&y);
  196. LBL_X:
  197. mp_clear(&x);
  198. LBL_T2:
  199. mp_clear(&t2);
  200. LBL_T1:
  201. mp_clear(&t1);
  202. LBL_Q:
  203. mp_clear(&q);
  204. return err;
  205. }
  206. #endif
  207. #endif