Bitwise Ops.swift 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121
  1. //
  2. // Bitwise Ops.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. //MARK: Bitwise Operations
  9. extension CS.BigUInt {
  10. /// Return the ones' complement of `a`.
  11. ///
  12. /// - Complexity: O(a.count)
  13. public static prefix func ~(a: CS.BigUInt) -> CS.BigUInt {
  14. return CS.BigUInt(words: a.words.map { ~$0 })
  15. }
  16. /// Calculate the bitwise OR of `a` and `b`, and store the result in `a`.
  17. ///
  18. /// - Complexity: O(max(a.count, b.count))
  19. public static func |= (a: inout CS.BigUInt, b: CS.BigUInt) {
  20. a.reserveCapacity(b.count)
  21. for i in 0 ..< b.count {
  22. a[i] |= b[i]
  23. }
  24. }
  25. /// Calculate the bitwise AND of `a` and `b` and return the result.
  26. ///
  27. /// - Complexity: O(max(a.count, b.count))
  28. public static func &= (a: inout CS.BigUInt, b: CS.BigUInt) {
  29. for i in 0 ..< Swift.max(a.count, b.count) {
  30. a[i] &= b[i]
  31. }
  32. }
  33. /// Calculate the bitwise XOR of `a` and `b` and return the result.
  34. ///
  35. /// - Complexity: O(max(a.count, b.count))
  36. public static func ^= (a: inout CS.BigUInt, b: CS.BigUInt) {
  37. a.reserveCapacity(b.count)
  38. for i in 0 ..< b.count {
  39. a[i] ^= b[i]
  40. }
  41. }
  42. }
  43. extension CS.BigInt {
  44. public static prefix func ~(x: CS.BigInt) -> CS.BigInt {
  45. switch x.sign {
  46. case .plus:
  47. return CS.BigInt(sign: .minus, magnitude: x.magnitude + 1)
  48. case .minus:
  49. return CS.BigInt(sign: .plus, magnitude: x.magnitude - 1)
  50. }
  51. }
  52. public static func &(lhs: inout CS.BigInt, rhs: CS.BigInt) -> CS.BigInt {
  53. let left = lhs.words
  54. let right = rhs.words
  55. // Note we aren't using left.count/right.count here; we account for the sign bit separately later.
  56. let count = Swift.max(lhs.magnitude.count, rhs.magnitude.count)
  57. var words: [UInt] = []
  58. words.reserveCapacity(count)
  59. for i in 0 ..< count {
  60. words.append(left[i] & right[i])
  61. }
  62. if lhs.sign == .minus && rhs.sign == .minus {
  63. words.twosComplement()
  64. return CS.BigInt(sign: .minus, magnitude: CS.BigUInt(words: words))
  65. }
  66. return CS.BigInt(sign: .plus, magnitude: CS.BigUInt(words: words))
  67. }
  68. public static func |(lhs: inout CS.BigInt, rhs: CS.BigInt) -> CS.BigInt {
  69. let left = lhs.words
  70. let right = rhs.words
  71. // Note we aren't using left.count/right.count here; we account for the sign bit separately later.
  72. let count = Swift.max(lhs.magnitude.count, rhs.magnitude.count)
  73. var words: [UInt] = []
  74. words.reserveCapacity(count)
  75. for i in 0 ..< count {
  76. words.append(left[i] | right[i])
  77. }
  78. if lhs.sign == .minus || rhs.sign == .minus {
  79. words.twosComplement()
  80. return CS.BigInt(sign: .minus, magnitude: CS.BigUInt(words: words))
  81. }
  82. return CS.BigInt(sign: .plus, magnitude: CS.BigUInt(words: words))
  83. }
  84. public static func ^(lhs: inout CS.BigInt, rhs: CS.BigInt) -> CS.BigInt {
  85. let left = lhs.words
  86. let right = rhs.words
  87. // Note we aren't using left.count/right.count here; we account for the sign bit separately later.
  88. let count = Swift.max(lhs.magnitude.count, rhs.magnitude.count)
  89. var words: [UInt] = []
  90. words.reserveCapacity(count)
  91. for i in 0 ..< count {
  92. words.append(left[i] ^ right[i])
  93. }
  94. if (lhs.sign == .minus) != (rhs.sign == .minus) {
  95. words.twosComplement()
  96. return CS.BigInt(sign: .minus, magnitude: CS.BigUInt(words: words))
  97. }
  98. return CS.BigInt(sign: .plus, magnitude: CS.BigUInt(words: words))
  99. }
  100. public static func &=(lhs: inout CS.BigInt, rhs: CS.BigInt) {
  101. lhs = lhs & rhs
  102. }
  103. public static func |=(lhs: inout CS.BigInt, rhs: CS.BigInt) {
  104. lhs = lhs | rhs
  105. }
  106. public static func ^=(lhs: inout CS.BigInt, rhs: CS.BigInt) {
  107. lhs = lhs ^ rhs
  108. }
  109. }