bn_s_mp_sub.c 1.7 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071
  1. #include "tommath_private.h"
  2. #ifdef BN_S_MP_SUB_C
  3. /* LibTomMath, multiple-precision integer library -- Tom St Denis */
  4. /* SPDX-License-Identifier: Unlicense */
  5. /* low level subtraction (assumes |a| > |b|), HAC pp.595 Algorithm 14.9 */
  6. mp_err s_mp_sub(const mp_int *a, const mp_int *b, mp_int *c)
  7. {
  8. int olduse, min, max;
  9. mp_err err;
  10. /* find sizes */
  11. min = b->used;
  12. max = a->used;
  13. /* init result */
  14. if (c->alloc < max) {
  15. if ((err = mp_grow(c, max)) != MP_OKAY) {
  16. return err;
  17. }
  18. }
  19. olduse = c->used;
  20. c->used = max;
  21. {
  22. mp_digit u, *tmpa, *tmpb, *tmpc;
  23. int i;
  24. /* alias for digit pointers */
  25. tmpa = a->dp;
  26. tmpb = b->dp;
  27. tmpc = c->dp;
  28. /* set carry to zero */
  29. u = 0;
  30. for (i = 0; i < min; i++) {
  31. /* T[i] = A[i] - B[i] - U */
  32. *tmpc = (*tmpa++ - *tmpb++) - u;
  33. /* U = carry bit of T[i]
  34. * Note this saves performing an AND operation since
  35. * if a carry does occur it will propagate all the way to the
  36. * MSB. As a result a single shift is enough to get the carry
  37. */
  38. u = *tmpc >> (MP_SIZEOF_BITS(mp_digit) - 1u);
  39. /* Clear carry from T[i] */
  40. *tmpc++ &= MP_MASK;
  41. }
  42. /* now copy higher words if any, e.g. if A has more digits than B */
  43. for (; i < max; i++) {
  44. /* T[i] = A[i] - U */
  45. *tmpc = *tmpa++ - u;
  46. /* U = carry bit of T[i] */
  47. u = *tmpc >> (MP_SIZEOF_BITS(mp_digit) - 1u);
  48. /* Clear carry from T[i] */
  49. *tmpc++ &= MP_MASK;
  50. }
  51. /* clear digits above used (since we may not have grown result above) */
  52. MP_ZERO_DIGITS(tmpc, olduse - c->used);
  53. }
  54. mp_clamp(c);
  55. return MP_OKAY;
  56. }
  57. #endif