Skip to content

Commit 9bb371d

Browse files
committed
Use ContiguousArray instead of Array to improve performance.
1 parent ea87ff4 commit 9bb371d

File tree

2 files changed

+44
-42
lines changed

2 files changed

+44
-42
lines changed

Sources/NumberKit/BigInt.swift

Lines changed: 42 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ public struct BigInt: Hashable,
3838

3939
// This is an array of `UInt32` words. The lowest significant word comes first in
4040
// the array.
41-
private let uwords: [UInt32]
41+
private let uwords: ContiguousArray<UInt32>
4242

4343
// `negative` signals whether the number is positive or negative.
4444
private let negative: Bool
@@ -125,7 +125,7 @@ public struct BigInt: Hashable,
125125

126126
/// Internal primary constructor. It removes superfluous words and normalizes the
127127
/// representation of zero.
128-
internal init(words: [UInt32], negative: Bool) {
128+
internal init(words: ContiguousArray<UInt32>, negative: Bool) {
129129
var words = words
130130
while words.count > 1 && words[words.count - 1] == 0 {
131131
words.removeLast()
@@ -137,7 +137,7 @@ public struct BigInt: Hashable,
137137
/// Internal primary constructor. It removes superfluous words and normalizes the
138138
/// representation of zero.
139139
internal init(words: [UInt], negative: Bool) {
140-
var uwords = [UInt32]()
140+
var uwords = ContiguousArray<UInt32>()
141141
uwords.reserveCapacity(words.count * 2)
142142
for word in words {
143143
let myword = UInt64(word)
@@ -179,7 +179,7 @@ public struct BigInt: Hashable,
179179
/// `BigInt` numbers.
180180
public init(digits: [UInt8], negative: Bool = false, base: Base = BigInt.decBase) {
181181
var digits = digits
182-
var words: [UInt32] = []
182+
var words = ContiguousArray<UInt32>()
183183
var iterate: Bool
184184
repeat {
185185
var sum: UInt64 = 0
@@ -208,41 +208,40 @@ public struct BigInt: Hashable,
208208
/// Creates a `BigInt` from a string containing a number using the given base.
209209
public init?(from str: String, base: Base = BigInt.decBase) {
210210
var negative = false
211-
let chars = str.characters
212-
var i = chars.startIndex
213-
while i < chars.endIndex && chars[i] == " " {
214-
i = chars.index(after: i)
211+
var i = str.startIndex
212+
while i < str.endIndex && str[i] == " " {
213+
i = str.index(after: i)
215214
}
216-
if i < chars.endIndex {
217-
if chars[i] == "-" {
215+
if i < str.endIndex {
216+
if str[i] == "-" {
218217
negative = true
219-
i = chars.index(after: i)
220-
} else if chars[i] == "+" {
221-
i = chars.index(after: i)
218+
i = str.index(after: i)
219+
} else if str[i] == "+" {
220+
i = str.index(after: i)
222221
}
223222
}
224-
if i < chars.endIndex && chars[i] == "0" {
225-
while i < chars.endIndex && chars[i] == "0" {
226-
i = chars.index(after: i)
223+
if i < str.endIndex && str[i] == "0" {
224+
while i < str.endIndex && str[i] == "0" {
225+
i = str.index(after: i)
227226
}
228-
if i == chars.endIndex {
227+
if i == str.endIndex {
229228
self.init(0)
230229
return
231230
}
232231
}
233232
var temp: [UInt8] = []
234-
while i < chars.endIndex {
235-
if let digit = base.digitMap[chars[i]] {
233+
while i < str.endIndex {
234+
if let digit = base.digitMap[str[i]] {
236235
temp.append(digit)
237-
i = chars.index(after: i)
236+
i = str.index(after: i)
238237
} else {
239238
break
240239
}
241240
}
242-
while i < chars.endIndex && chars[i] == " " {
243-
i = chars.index(after: i)
241+
while i < str.endIndex && str[i] == " " {
242+
i = str.index(after: i)
244243
}
245-
guard i == chars.endIndex else {
244+
guard i == str.endIndex else {
246245
return nil
247246
}
248247
self.init(digits: temp, negative: negative, base: base)
@@ -428,7 +427,7 @@ public struct BigInt: Hashable,
428427
return self.minus(rhs.negate)
429428
}
430429
let (b1, b2) = self.uwords.count < rhs.uwords.count ? (rhs, self) : (self, rhs)
431-
var res = [UInt32]()
430+
var res = ContiguousArray<UInt32>()
432431
res.reserveCapacity(b1.uwords.count)
433432
var sum: UInt64 = 0
434433
for i in 0..<b2.uwords.count {
@@ -459,7 +458,7 @@ public struct BigInt: Hashable,
459458
}
460459
let negative = cmp < 0 ? !self.negative : self.negative
461460
let (b1, b2) = cmp < 0 ? (rhs, self) : (self, rhs)
462-
var res = [UInt32]()
461+
var res = ContiguousArray<UInt32>()
463462
var carry: UInt64 = 0
464463
for i in 0..<b2.uwords.count {
465464
if UInt64(b1.uwords[i]) < UInt64(b2.uwords[i]) + carry {
@@ -485,7 +484,7 @@ public struct BigInt: Hashable,
485484
/// Returns the result of mulitplying `self` with `rhs` as a `BigInt`
486485
public func times(_ rhs: BigInt) -> BigInt {
487486
let (b1, b2) = self.uwords.count < rhs.uwords.count ? (rhs, self) : (self, rhs)
488-
var res = [UInt32](repeating: 0, count: b1.uwords.count + b2.uwords.count)
487+
var res = ContiguousArray<UInt32>(repeating: 0, count: b1.uwords.count + b2.uwords.count)
489488
for i in 0..<b2.uwords.count {
490489
var sum: UInt64 = 0
491490
for j in 0..<b1.uwords.count {
@@ -499,8 +498,10 @@ public struct BigInt: Hashable,
499498
return BigInt(words: res, negative: b1.negative != b2.negative)
500499
}
501500

502-
private static func multSub(_ approx: UInt32, _ divis: [UInt32],
503-
_ rem: inout [UInt32], _ from: Int) {
501+
private static func multSub(_ approx: UInt32,
502+
_ divis: ContiguousArray<UInt32>,
503+
_ rem: inout ContiguousArray<UInt32>,
504+
_ from: Int) {
504505
var sum: UInt64 = 0
505506
var carry: UInt64 = 0
506507
for j in 0..<divis.count {
@@ -517,7 +518,9 @@ public struct BigInt: Hashable,
517518
}
518519
}
519520

520-
private static func subIfPossible(divis: [UInt32], rem: inout [UInt32], from: Int) -> Bool {
521+
private static func subIfPossible(divis: ContiguousArray<UInt32>,
522+
rem: inout ContiguousArray<UInt32>,
523+
from: Int) -> Bool {
521524
var i = divis.count
522525
while i > 0 && divis[i - 1] >= rem[from + i - 1] {
523526
if divis[i - 1] > rem[from + i - 1] {
@@ -553,13 +556,13 @@ public struct BigInt: Hashable,
553556
return (BigInt(0), self.abs)
554557
}
555558
}
556-
var rem = [UInt32](self.uwords)
559+
var rem = ContiguousArray<UInt32>(self.uwords)
557560
rem.append(0)
558-
var divis = [UInt32](rhs.uwords)
561+
var divis = ContiguousArray<UInt32>(rhs.uwords)
559562
divis.append(0)
560563
var sizediff = self.uwords.count - rhs.uwords.count
561564
let div = UInt64(rhs.uwords[rhs.uwords.count - 1]) + 1
562-
var res = [UInt32](repeating: 0, count: sizediff + 1)
565+
var res = ContiguousArray<UInt32>(repeating: 0, count: sizediff + 1)
563566
var divident = rem.count - 2
564567
repeat {
565568
var x = BigInt.joinwords(rem[divident], rem[divident + 1])
@@ -617,7 +620,7 @@ public struct BigInt: Hashable,
617620
/// Computes the bitwise `and` between this value and `rhs`.
618621
public func and(_ rhs: BigInt) -> BigInt {
619622
let size = Swift.min(self.uwords.count, rhs.uwords.count)
620-
var res = [UInt32]()
623+
var res = ContiguousArray<UInt32>()
621624
res.reserveCapacity(size)
622625
for i in 0..<size {
623626
res.append(self.uwords[i] & rhs.uwords[i])
@@ -628,7 +631,7 @@ public struct BigInt: Hashable,
628631
/// Computes the bitwise `or` between this value and `rhs`.
629632
public func or(_ rhs: BigInt) -> BigInt {
630633
let size = Swift.max(self.uwords.count, rhs.uwords.count)
631-
var res = [UInt32]()
634+
var res = ContiguousArray<UInt32>()
632635
res.reserveCapacity(size)
633636
for i in 0..<size {
634637
let fst = i < self.uwords.count ? self.uwords[i] : 0
@@ -641,7 +644,7 @@ public struct BigInt: Hashable,
641644
/// Computes the bitwise `xor` between this value and `rhs`.
642645
public func xor(_ rhs: BigInt) -> BigInt {
643646
let size = Swift.max(self.uwords.count, rhs.uwords.count)
644-
var res = [UInt32]()
647+
var res = ContiguousArray<UInt32>()
645648
res.reserveCapacity(size)
646649
for i in 0..<size {
647650
let fst = i < self.uwords.count ? self.uwords[i] : 0
@@ -653,7 +656,7 @@ public struct BigInt: Hashable,
653656

654657
/// Inverts the bits in this `BigInt`.
655658
public var invert: BigInt {
656-
var res = [UInt32]()
659+
var res = ContiguousArray<UInt32>()
657660
res.reserveCapacity(self.uwords.count)
658661
for word in self.uwords {
659662
res.append(~word)
@@ -676,7 +679,7 @@ public struct BigInt: Hashable,
676679
private func shiftLeft(_ x: Int) -> BigInt {
677680
let swords = x / UInt32.bitWidth
678681
let sbits = x % UInt32.bitWidth
679-
var res = [UInt32]()
682+
var res = ContiguousArray<UInt32>()
680683
res.reserveCapacity(Int(self.uwords.count) + swords)
681684
for _ in 0..<swords {
682685
res.append(0)
@@ -695,7 +698,7 @@ public struct BigInt: Hashable,
695698
private func shiftRight(_ x: Int) -> BigInt {
696699
let swords = x / UInt32.bitWidth
697700
let sbits = x % UInt32.bitWidth
698-
var res = [UInt32]()
701+
var res = ContiguousArray<UInt32>()
699702
res.reserveCapacity(Int(self.uwords.count) - swords)
700703
var carry: UInt32 = 0
701704
var i = self.uwords.count - 1
@@ -705,7 +708,7 @@ public struct BigInt: Hashable,
705708
carry = word << (UInt32.bitWidth - sbits)
706709
i -= 1
707710
}
708-
return BigInt(words: res.reversed(), negative: self.negative)
711+
return BigInt(words: ContiguousArray<UInt32>(res.reversed()), negative: self.negative)
709712
}
710713
}
711714

Sources/NumberKit/Rational.swift

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -164,10 +164,9 @@ public struct Rational<T: IntegerNumber>: RationalNumber, CustomStringConvertibl
164164
/// Denominator = SignedInteger
165165
public init?(from str: String, radix: Int = 10) {
166166
precondition(radix >= 2, "radix >= 2 required")
167-
let chars = str.characters
168-
if let idx = chars.index(of: rationalSeparator) {
167+
if let idx = str.index(of: rationalSeparator) {
169168
if let numVal = Int64(str[..<idx], radix: radix),
170-
let denomVal = Int64(str[chars.index(after: idx)...], radix: radix) {
169+
let denomVal = Int64(str[str.index(after: idx)...], radix: radix) {
171170
self.init(T(numVal), T(denomVal))
172171
} else {
173172
return nil

0 commit comments

Comments
 (0)