Subtraction.swift 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169
  1. //
  2. // Subtraction.swift
  3. // CS.BigInt
  4. //
  5. // Created by Károly Lőrentey on 2016-01-03.
  6. // Copyright © 2016-2017 Károly Lőrentey.
  7. //
  8. extension CS.BigUInt {
  9. //MARK: Subtraction
  10. /// Subtract `word` from this integer in place, returning a flag indicating if the operation
  11. /// caused an arithmetic overflow. `word` is shifted `shift` words to the left before being subtracted.
  12. ///
  13. /// - Note: If the result indicates an overflow, then `self` becomes the two's complement of the absolute difference.
  14. /// - Complexity: O(count)
  15. internal mutating func subtractWordReportingOverflow(_ word: Word, shiftedBy shift: Int = 0) -> Bool {
  16. precondition(shift >= 0)
  17. var carry: Word = word
  18. var i = shift
  19. let count = self.count
  20. while carry > 0 && i < count {
  21. let (d, c) = self[i].subtractingReportingOverflow(carry)
  22. self[i] = d
  23. carry = (c ? 1 : 0)
  24. i += 1
  25. }
  26. return carry > 0
  27. }
  28. /// Subtract `word` from this integer, returning the difference and a flag that is true if the operation
  29. /// caused an arithmetic overflow. `word` is shifted `shift` words to the left before being subtracted.
  30. ///
  31. /// - Note: If `overflow` is true, then the returned value is the two's complement of the absolute difference.
  32. /// - Complexity: O(count)
  33. internal func subtractingWordReportingOverflow(_ word: Word, shiftedBy shift: Int = 0) -> (partialValue: CS.BigUInt, overflow: Bool) {
  34. var result = self
  35. let overflow = result.subtractWordReportingOverflow(word, shiftedBy: shift)
  36. return (result, overflow)
  37. }
  38. /// Subtract a digit `d` from this integer in place.
  39. /// `d` is shifted `shift` digits to the left before being subtracted.
  40. ///
  41. /// - Requires: self >= d * 2^shift
  42. /// - Complexity: O(count)
  43. internal mutating func subtractWord(_ word: Word, shiftedBy shift: Int = 0) {
  44. let overflow = subtractWordReportingOverflow(word, shiftedBy: shift)
  45. precondition(!overflow)
  46. }
  47. /// Subtract a digit `d` from this integer and return the result.
  48. /// `d` is shifted `shift` digits to the left before being subtracted.
  49. ///
  50. /// - Requires: self >= d * 2^shift
  51. /// - Complexity: O(count)
  52. internal func subtractingWord(_ word: Word, shiftedBy shift: Int = 0) -> CS.BigUInt {
  53. var result = self
  54. result.subtractWord(word, shiftedBy: shift)
  55. return result
  56. }
  57. /// Subtract `other` from this integer in place, and return a flag indicating if the operation caused an
  58. /// arithmetic overflow. `other` is shifted `shift` digits to the left before being subtracted.
  59. ///
  60. /// - Note: If the result indicates an overflow, then `self` becomes the twos' complement of the absolute difference.
  61. /// - Complexity: O(count)
  62. public mutating func subtractReportingOverflow(_ b: CS.BigUInt, shiftedBy shift: Int = 0) -> Bool {
  63. precondition(shift >= 0)
  64. var carry = false
  65. var bi = 0
  66. let bc = b.count
  67. let count = self.count
  68. while bi < bc || (shift + bi < count && carry) {
  69. let ai = shift + bi
  70. let (d, c) = self[ai].subtractingReportingOverflow(b[bi])
  71. if carry {
  72. let (d2, c2) = d.subtractingReportingOverflow(1)
  73. self[ai] = d2
  74. carry = c || c2
  75. }
  76. else {
  77. self[ai] = d
  78. carry = c
  79. }
  80. bi += 1
  81. }
  82. return carry
  83. }
  84. /// Subtract `other` from this integer, returning the difference and a flag indicating arithmetic overflow.
  85. /// `other` is shifted `shift` digits to the left before being subtracted.
  86. ///
  87. /// - Note: If `overflow` is true, then the result value is the twos' complement of the absolute value of the difference.
  88. /// - Complexity: O(count)
  89. public func subtractingReportingOverflow(_ other: CS.BigUInt, shiftedBy shift: Int) -> (partialValue: CS.BigUInt, overflow: Bool) {
  90. var result = self
  91. let overflow = result.subtractReportingOverflow(other, shiftedBy: shift)
  92. return (result, overflow)
  93. }
  94. /// Subtracts `other` from `self`, returning the result and a flag indicating arithmetic overflow.
  95. ///
  96. /// - Note: When the operation overflows, then `partialValue` is the twos' complement of the absolute value of the difference.
  97. /// - Complexity: O(count)
  98. public func subtractingReportingOverflow(_ other: CS.BigUInt) -> (partialValue: CS.BigUInt, overflow: Bool) {
  99. return self.subtractingReportingOverflow(other, shiftedBy: 0)
  100. }
  101. /// Subtract `other` from this integer in place.
  102. /// `other` is shifted `shift` digits to the left before being subtracted.
  103. ///
  104. /// - Requires: self >= other * 2^shift
  105. /// - Complexity: O(count)
  106. public mutating func subtract(_ other: CS.BigUInt, shiftedBy shift: Int = 0) {
  107. let overflow = subtractReportingOverflow(other, shiftedBy: shift)
  108. precondition(!overflow)
  109. }
  110. /// Subtract `b` from this integer, and return the difference.
  111. /// `b` is shifted `shift` digits to the left before being subtracted.
  112. ///
  113. /// - Requires: self >= b * 2^shift
  114. /// - Complexity: O(count)
  115. public func subtracting(_ other: CS.BigUInt, shiftedBy shift: Int = 0) -> CS.BigUInt {
  116. var result = self
  117. result.subtract(other, shiftedBy: shift)
  118. return result
  119. }
  120. /// Decrement this integer by one.
  121. ///
  122. /// - Requires: !isZero
  123. /// - Complexity: O(count)
  124. public mutating func decrement(shiftedBy shift: Int = 0) {
  125. self.subtract(1, shiftedBy: shift)
  126. }
  127. /// Subtract `b` from `a` and return the result.
  128. ///
  129. /// - Requires: a >= b
  130. /// - Complexity: O(a.count)
  131. public static func -(a: CS.BigUInt, b: CS.BigUInt) -> CS.BigUInt {
  132. return a.subtracting(b)
  133. }
  134. /// Subtract `b` from `a` and store the result in `a`.
  135. ///
  136. /// - Requires: a >= b
  137. /// - Complexity: O(a.count)
  138. public static func -=(a: inout CS.BigUInt, b: CS.BigUInt) {
  139. a.subtract(b)
  140. }
  141. }
  142. extension CS.BigInt {
  143. public mutating func negate() {
  144. guard !magnitude.isZero else { return }
  145. self.sign = self.sign == .plus ? .minus : .plus
  146. }
  147. /// Subtract `b` from `a` and return the result.
  148. public static func -(a: CS.BigInt, b: CS.BigInt) -> CS.BigInt {
  149. return a + -b
  150. }
  151. /// Subtract `b` from `a` in place.
  152. public static func -=(a: inout CS.BigInt, b: CS.BigInt) { a = a - b }
  153. }