bn_mp_div_d.c 2.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110
  1. #include <tommath.h>
  2. #ifdef BN_MP_DIV_D_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. static int s_is_power_of_two(mp_digit b, int *p)
  18. {
  19. int x;
  20. for (x = 1; x < DIGIT_BIT; x++) {
  21. if (b == (((mp_digit)1)<<x)) {
  22. *p = x;
  23. return 1;
  24. }
  25. }
  26. return 0;
  27. }
  28. /* single digit division (based on routine from MPI) */
  29. int mp_div_d (mp_int * a, mp_digit b, mp_int * c, mp_digit * d)
  30. {
  31. mp_int q;
  32. mp_word w;
  33. mp_digit t;
  34. int res, ix;
  35. /* cannot divide by zero */
  36. if (b == 0) {
  37. return MP_VAL;
  38. }
  39. /* quick outs */
  40. if (b == 1 || mp_iszero(a) == 1) {
  41. if (d != NULL) {
  42. *d = 0;
  43. }
  44. if (c != NULL) {
  45. return mp_copy(a, c);
  46. }
  47. return MP_OKAY;
  48. }
  49. /* power of two ? */
  50. if (s_is_power_of_two(b, &ix) == 1) {
  51. if (d != NULL) {
  52. *d = a->dp[0] & ((((mp_digit)1)<<ix) - 1);
  53. }
  54. if (c != NULL) {
  55. return mp_div_2d(a, ix, c, NULL);
  56. }
  57. return MP_OKAY;
  58. }
  59. #ifdef BN_MP_DIV_3_C
  60. /* three? */
  61. if (b == 3) {
  62. return mp_div_3(a, c, d);
  63. }
  64. #endif
  65. /* no easy answer [c'est la vie]. Just division */
  66. if ((res = mp_init_size(&q, a->used)) != MP_OKAY) {
  67. return res;
  68. }
  69. q.used = a->used;
  70. q.sign = a->sign;
  71. w = 0;
  72. for (ix = a->used - 1; ix >= 0; ix--) {
  73. w = (w << ((mp_word)DIGIT_BIT)) | ((mp_word)a->dp[ix]);
  74. if (w >= b) {
  75. t = (mp_digit)(w / b);
  76. w -= ((mp_word)t) * ((mp_word)b);
  77. } else {
  78. t = 0;
  79. }
  80. q.dp[ix] = (mp_digit)t;
  81. }
  82. if (d != NULL) {
  83. *d = (mp_digit)w;
  84. }
  85. if (c != NULL) {
  86. mp_clamp(&q);
  87. mp_exch(&q, c);
  88. }
  89. mp_clear(&q);
  90. return res;
  91. }
  92. #endif
  93. /* $Source: /cvs/libtom/libtommath/bn_mp_div_d.c,v $ */
  94. /* $Revision: 1.3 $ */
  95. /* $Date: 2006/03/31 14:18:44 $ */