mpi-add.c 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155
  1. /* mpi-add.c - MPI functions
  2. * Copyright (C) 1994, 1996, 1998, 2001, 2002,
  3. * 2003 Free Software Foundation, Inc.
  4. *
  5. * This file is part of Libgcrypt.
  6. *
  7. * Note: This code is heavily based on the GNU MP Library.
  8. * Actually it's the same code with only minor changes in the
  9. * way the data is stored; this is to support the abstraction
  10. * of an optional secure memory allocation which may be used
  11. * to avoid revealing of sensitive data due to paging etc.
  12. */
  13. #include "mpi-internal.h"
  14. /****************
  15. * Add the unsigned integer V to the mpi-integer U and store the
  16. * result in W. U and V may be the same.
  17. */
  18. void mpi_add_ui(MPI w, MPI u, unsigned long v)
  19. {
  20. mpi_ptr_t wp, up;
  21. mpi_size_t usize, wsize;
  22. int usign, wsign;
  23. usize = u->nlimbs;
  24. usign = u->sign;
  25. wsign = 0;
  26. /* If not space for W (and possible carry), increase space. */
  27. wsize = usize + 1;
  28. if (w->alloced < wsize)
  29. mpi_resize(w, wsize);
  30. /* These must be after realloc (U may be the same as W). */
  31. up = u->d;
  32. wp = w->d;
  33. if (!usize) { /* simple */
  34. wp[0] = v;
  35. wsize = v ? 1:0;
  36. } else if (!usign) { /* mpi is not negative */
  37. mpi_limb_t cy;
  38. cy = mpihelp_add_1(wp, up, usize, v);
  39. wp[usize] = cy;
  40. wsize = usize + cy;
  41. } else {
  42. /* The signs are different. Need exact comparison to determine
  43. * which operand to subtract from which.
  44. */
  45. if (usize == 1 && up[0] < v) {
  46. wp[0] = v - up[0];
  47. wsize = 1;
  48. } else {
  49. mpihelp_sub_1(wp, up, usize, v);
  50. /* Size can decrease with at most one limb. */
  51. wsize = usize - (wp[usize-1] == 0);
  52. wsign = 1;
  53. }
  54. }
  55. w->nlimbs = wsize;
  56. w->sign = wsign;
  57. }
  58. void mpi_add(MPI w, MPI u, MPI v)
  59. {
  60. mpi_ptr_t wp, up, vp;
  61. mpi_size_t usize, vsize, wsize;
  62. int usign, vsign, wsign;
  63. if (u->nlimbs < v->nlimbs) { /* Swap U and V. */
  64. usize = v->nlimbs;
  65. usign = v->sign;
  66. vsize = u->nlimbs;
  67. vsign = u->sign;
  68. wsize = usize + 1;
  69. RESIZE_IF_NEEDED(w, wsize);
  70. /* These must be after realloc (u or v may be the same as w). */
  71. up = v->d;
  72. vp = u->d;
  73. } else {
  74. usize = u->nlimbs;
  75. usign = u->sign;
  76. vsize = v->nlimbs;
  77. vsign = v->sign;
  78. wsize = usize + 1;
  79. RESIZE_IF_NEEDED(w, wsize);
  80. /* These must be after realloc (u or v may be the same as w). */
  81. up = u->d;
  82. vp = v->d;
  83. }
  84. wp = w->d;
  85. wsign = 0;
  86. if (!vsize) { /* simple */
  87. MPN_COPY(wp, up, usize);
  88. wsize = usize;
  89. wsign = usign;
  90. } else if (usign != vsign) { /* different sign */
  91. /* This test is right since USIZE >= VSIZE */
  92. if (usize != vsize) {
  93. mpihelp_sub(wp, up, usize, vp, vsize);
  94. wsize = usize;
  95. MPN_NORMALIZE(wp, wsize);
  96. wsign = usign;
  97. } else if (mpihelp_cmp(up, vp, usize) < 0) {
  98. mpihelp_sub_n(wp, vp, up, usize);
  99. wsize = usize;
  100. MPN_NORMALIZE(wp, wsize);
  101. if (!usign)
  102. wsign = 1;
  103. } else {
  104. mpihelp_sub_n(wp, up, vp, usize);
  105. wsize = usize;
  106. MPN_NORMALIZE(wp, wsize);
  107. if (usign)
  108. wsign = 1;
  109. }
  110. } else { /* U and V have same sign. Add them. */
  111. mpi_limb_t cy = mpihelp_add(wp, up, usize, vp, vsize);
  112. wp[usize] = cy;
  113. wsize = usize + cy;
  114. if (usign)
  115. wsign = 1;
  116. }
  117. w->nlimbs = wsize;
  118. w->sign = wsign;
  119. }
  120. EXPORT_SYMBOL_GPL(mpi_add);
  121. void mpi_sub(MPI w, MPI u, MPI v)
  122. {
  123. MPI vv = mpi_copy(v);
  124. vv->sign = !vv->sign;
  125. mpi_add(w, u, vv);
  126. mpi_free(vv);
  127. }
  128. EXPORT_SYMBOL_GPL(mpi_sub);
  129. void mpi_addm(MPI w, MPI u, MPI v, MPI m)
  130. {
  131. mpi_add(w, u, v);
  132. mpi_mod(w, w, m);
  133. }
  134. EXPORT_SYMBOL_GPL(mpi_addm);
  135. void mpi_subm(MPI w, MPI u, MPI v, MPI m)
  136. {
  137. mpi_sub(w, u, v);
  138. mpi_mod(w, w, m);
  139. }
  140. EXPORT_SYMBOL_GPL(mpi_subm);