SimpleOperations.cpp 2.6 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091
  1. /*
  2. * Copyright (c) 2020, Itamar S. <itamar8910@gmail.com>
  3. * Copyright (c) 2020-2021, Dex♪ <dexes.ttp@gmail.com>
  4. *
  5. * SPDX-License-Identifier: BSD-2-Clause
  6. */
  7. #include "UnsignedBigIntegerAlgorithms.h"
  8. namespace Crypto {
  9. /**
  10. * Complexity: O(N) where N is the number of words in the larger number
  11. */
  12. void UnsignedBigIntegerAlgorithms::add_without_allocation(
  13. UnsignedBigInteger const& left,
  14. UnsignedBigInteger const& right,
  15. UnsignedBigInteger& output)
  16. {
  17. const UnsignedBigInteger* const longer = (left.length() > right.length()) ? &left : &right;
  18. const UnsignedBigInteger* const shorter = (longer == &right) ? &left : &right;
  19. u8 carry = 0;
  20. output.set_to_0();
  21. output.m_words.resize_and_keep_capacity(longer->length());
  22. for (size_t i = 0; i < shorter->length(); ++i) {
  23. u32 word_addition_result = shorter->m_words[i] + longer->m_words[i];
  24. u8 carry_out = 0;
  25. // if there was a carry, the result will be smaller than any of the operands
  26. if (word_addition_result + carry < shorter->m_words[i]) {
  27. carry_out = 1;
  28. }
  29. if (carry) {
  30. word_addition_result++;
  31. }
  32. carry = carry_out;
  33. output.m_words[i] = word_addition_result;
  34. }
  35. for (size_t i = shorter->length(); i < longer->length(); ++i) {
  36. u32 word_addition_result = longer->m_words[i] + carry;
  37. carry = 0;
  38. if (word_addition_result < longer->m_words[i]) {
  39. carry = 1;
  40. }
  41. output.m_words[i] = word_addition_result;
  42. }
  43. if (carry) {
  44. output.m_words.append(carry);
  45. }
  46. }
  47. /**
  48. * Complexity: O(N) where N is the number of words in the larger number
  49. */
  50. void UnsignedBigIntegerAlgorithms::subtract_without_allocation(
  51. UnsignedBigInteger const& left,
  52. UnsignedBigInteger const& right,
  53. UnsignedBigInteger& output)
  54. {
  55. if (left < right) {
  56. output.invalidate();
  57. return;
  58. }
  59. u8 borrow = 0;
  60. auto own_length = left.length();
  61. auto other_length = right.length();
  62. output.set_to_0();
  63. output.m_words.resize_and_keep_capacity(own_length);
  64. for (size_t i = 0; i < own_length; ++i) {
  65. u32 other_word = (i < other_length) ? right.m_words[i] : 0;
  66. i64 temp = static_cast<i64>(left.m_words[i]) - static_cast<i64>(other_word) - static_cast<i64>(borrow);
  67. // If temp < 0, we had an underflow
  68. borrow = (temp >= 0) ? 0 : 1;
  69. if (temp < 0) {
  70. temp += (UINT32_MAX + 1);
  71. }
  72. output.m_words[i] = temp;
  73. }
  74. // This assertion should not fail, because we verified that *this>=other at the beginning of the function
  75. VERIFY(borrow == 0);
  76. }
  77. }