0001
0009 import Foundation
0010
0011 extension BigUInt {
0012
0013
0015 Complexity public mutating func multiplyInPlaceByDigit| BigUInt Multiplication.swift:39 | r.multiplyInPlaceByDigit(y) |
| BigUInt Radix Conversion.swift:70 | self.multiplyInPlaceByDigit(power) |
(y: Digit) {
0019 guard y != 0 else { self = 0; return }
0020 guard y != 1 else { return }
0021 lift()
0022 var carry: Digit = 0
0023 let c = self.count
0024 for i in 0..<c {
0025 let (h, l) = Digit.fullMultiply(self[i], y)
0026 let (low, o) = Digit.addWithOverflow(l, carry)
0027 self[i] = low
0028 carry = (o ? h + 1 : h)
0029 }
0030 self[c] = carry
0031 }
0032
0033 Complexity @warn_unused_result
0037 public func multiplyByDigit| BigUInt Division.swift:149 | let product = divisor.multiplyByDigit(q) |
| BigUInt Multiplication.swift:106 | if yc == 1 { return x.multiplyByDigit(y[0]) } |
| BigUInt Multiplication.swift:107 | if xc == 1 { return y.multiplyByDigit(x[0]) } |
(y: Digit) -> BigUInt {
0038 var r = self
0039 r.multiplyInPlaceByDigit(y)
0040 return r
0041 }
0042
0043 Note Returns Complexity public mutating func multiplyAndAddInPlace| BigUInt Multiplication.swift:115 | result.multiplyAndAddInPlace(left, right[i], shift: i) |
(x: BigUInt, _ y: Digit, shift: Int = 0) {
0050 precondition(shift >= 0)
0051 guard y != 0 && x.count > 0 else { return }
0052 guard y != 1 else { self.addInPlace(x, shift: shift); return }
0053 lift()
0054 var mulCarry: Digit = 0
0055 var addCarry = false
0056 let xc = x.count
0057 var xi = 0
0058 while xi < xc || addCarry || mulCarry > 0 {
0059 let (h, l) = Digit.fullMultiply(x[xi], y)
0060 let (low, o) = Digit.addWithOverflow(l, mulCarry)
0061 mulCarry = (o ? h + 1 : h)
0062
0063 let ai = shift + xi
0064 let (sum1, so1) = Digit.addWithOverflow(self[ai], low)
0065 if addCarry {
0066 let (sum2, so2) = Digit.addWithOverflow(sum1, 1)
0067 self[ai] = sum2
0068 addCarry = so1 || so2
0069 }
0070 else {
0071 self[ai] = sum1
0072 addCarry = so1
0073 }
0074 xi += 1
0075 }
0076 }
0077
0078 Note Complexity @warn_unused_result
0084 public func multiply(y: BigUInt) -> BigUInt {
0085 return self * y
0087 }
0088
0089 public static var directMultiplicationLimit| BigUInt Multiplication.swift:109 | if min(xc, yc) <= BigUInt.directMultiplicationLimit { |
: Int = 1024
0091 }
0092
0093
0095 NoteComplexity@warn_unused_result
0101 public func *(x: BigUInt, y: BigUInt) -> BigUInt {
0102 let xc = x.count
0103 let yc = y.count
0104 if xc == 0 { return BigUInt() }
0105 if yc == 0 { return BigUInt() }
0106 if yc == 1 { return x.multiplyByDigit(y[0]) }
0107 if xc == 1 { return y.multiplyByDigit(x[0]) }
0108
0109 if min(xc, yc) <= BigUInt.directMultiplicationLimit {
0110 let left = (xc < yc ? y : x)
0112 let right = (xc < yc ? x : y)
0113 var result = BigUInt()
0114 for i in (0 ..< right.count).reverse() {
0115 result.multiplyAndAddInPlace(left, right[i], shift: i)
0116 }
0117 return result
0118 }
0119
0120 if yc < xc {
0121 let (xh, xl) = x.split
0122 var r = xl * y
0123 r.addInPlace(xh * y, shift: x.middleIndex)
0124 return r
0125 }
0126 else if xc < yc {
0127 let (yh, yl) = y.split
0128 var r = yl * x
0129 r.addInPlace(yh * x, shift: y.middleIndex)
0130 return r
0131 }
0132
0133 let shift = x.middleIndex
0134
0135 let (a, b) = x.split
0138 let (c, d) = y.split
0139
0140 let high = a * c
0141 let low = b * d
0142 let xp = a >= b
0143 let yp = c >= d
0144 let xm = (xp ? a - b : b - a)
0145 let ym = (yp ? c - d : d - c)
0146 let m = xm * ym
0147
0148 var r = low
0149 r.addInPlace(high, shift: 2 * shift)
0150 r.addInPlace(low, shift: shift)
0151 r.addInPlace(high, shift: shift)
0152 if xp == yp {
0153 r.subtractInPlace(m, shift: shift)
0154 }
0155 else {
0156 r.addInPlace(m, shift: shift)
0157 }
0158 return r
0159 }
0160
0161 public func *=(inout a: BigUInt, b: BigUInt) {
0163 a = a * b
0164 }
0165
0166