SimpleOperations.cpp 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106
  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. UnsignedBigInteger const* const longer = (left.length() > right.length()) ? &left : &right;
  18. UnsignedBigInteger const* const shorter = (longer == &right) ? &left : &right;
  19. output.set_to(*longer);
  20. add_into_accumulator_without_allocation(output, *shorter);
  21. }
  22. /**
  23. * Complexity: O(N) where N is the number of words in the larger number
  24. */
  25. void UnsignedBigIntegerAlgorithms::add_into_accumulator_without_allocation(UnsignedBigInteger& accumulator, UnsignedBigInteger const& value)
  26. {
  27. auto value_length = value.trimmed_length();
  28. // If needed, resize the accumulator so it can fit the value.
  29. accumulator.resize_with_leading_zeros(value_length);
  30. auto final_length = accumulator.length();
  31. // Add the words of the value into the accumulator, rippling any carry as we go
  32. UnsignedBigInteger::Word last_carry_for_word = 0;
  33. for (size_t i = 0; i < value_length; ++i) {
  34. UnsignedBigInteger::Word current_carry_for_word = 0;
  35. if (Checked<UnsignedBigInteger::Word>::addition_would_overflow(value.m_words[i], accumulator.m_words[i])) {
  36. current_carry_for_word = 1;
  37. }
  38. UnsignedBigInteger::Word word_addition_result = value.m_words[i] + accumulator.m_words[i];
  39. if (Checked<UnsignedBigInteger::Word>::addition_would_overflow(word_addition_result, last_carry_for_word)) {
  40. current_carry_for_word = 1;
  41. }
  42. word_addition_result += last_carry_for_word;
  43. last_carry_for_word = current_carry_for_word;
  44. accumulator.m_words[i] = word_addition_result;
  45. }
  46. // Ripple the carry over the remaining words in the accumulator until either there is no carry left or we run out of words
  47. while (last_carry_for_word && final_length > value_length) {
  48. UnsignedBigInteger::Word current_carry_for_word = 0;
  49. if (Checked<UnsignedBigInteger::Word>::addition_would_overflow(accumulator.m_words[value_length], last_carry_for_word)) {
  50. current_carry_for_word = 1;
  51. }
  52. accumulator.m_words[value_length] += last_carry_for_word;
  53. last_carry_for_word = current_carry_for_word;
  54. value_length++;
  55. }
  56. if (last_carry_for_word) {
  57. // Note : The accumulator couldn't add the carry directly, so we reached its end
  58. accumulator.m_words.append(last_carry_for_word);
  59. }
  60. }
  61. /**
  62. * Complexity: O(N) where N is the number of words in the larger number
  63. */
  64. void UnsignedBigIntegerAlgorithms::subtract_without_allocation(
  65. UnsignedBigInteger const& left,
  66. UnsignedBigInteger const& right,
  67. UnsignedBigInteger& output)
  68. {
  69. if (left < right) {
  70. output.invalidate();
  71. return;
  72. }
  73. u8 borrow = 0;
  74. auto own_length = left.length();
  75. auto other_length = right.length();
  76. output.set_to_0();
  77. output.m_words.resize_and_keep_capacity(own_length);
  78. for (size_t i = 0; i < own_length; ++i) {
  79. u32 other_word = (i < other_length) ? right.m_words[i] : 0;
  80. i64 temp = static_cast<i64>(left.m_words[i]) - static_cast<i64>(other_word) - static_cast<i64>(borrow);
  81. // If temp < 0, we had an underflow
  82. borrow = (temp >= 0) ? 0 : 1;
  83. if (temp < 0) {
  84. temp += (UINT32_MAX + 1);
  85. }
  86. output.m_words[i] = temp;
  87. }
  88. // This assertion should not fail, because we verified that *this>=other at the beginning of the function
  89. VERIFY(borrow == 0);
  90. }
  91. }