Skip to content

Commit bd3ca01

Browse files
author
Joe Shajrawi
authored
Merge pull request #22300 from apple/revert-22227-a-tall-white-fountain-played
Revert "[benchmark] RomanNumbers Redux"
2 parents 556e089 + adfce60 commit bd3ca01

File tree

1 file changed

+57
-36
lines changed

1 file changed

+57
-36
lines changed

benchmark/single-source/RomanNumbers.swift

Lines changed: 57 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -12,63 +12,84 @@
1212

1313
import TestsUtils
1414

15+
//
1516
// Mini benchmark implementing roman numeral conversions to/from integers.
16-
// Measures performance of Substring.starts(with:), dropFirst and String.append
17+
// Measures performance of Substring.starts(with:) and String.append(),
1718
// with very short string arguments.
18-
19-
let t: [BenchmarkCategory] = [.api, .String, .algorithm]
20-
let N = 270
19+
//
2120

2221
public let RomanNumbers = [
2322
BenchmarkInfo(
24-
name: "Roman.Substring.startsWith.dropFirst",
25-
runFunction: {
26-
checkId($0, upTo: N, { $0.romanNumeral }, Int.init(romanSSsWdF:)) },
27-
tags: t),
23+
name: "RomanNumbers",
24+
runFunction: run_RomanNumbers,
25+
tags: [.api, .String, .algorithm])
2826
]
2927

30-
@inline(__always)
31-
func checkId(_ n: Int, upTo limit: Int, _ itor: (Int) -> String,
32-
_ rtoi: (String) -> Int?) {
33-
for _ in 1...n {
34-
CheckResults(
35-
zip(1...limit, (1...limit).map(itor).map(rtoi)).allSatisfy { $0 == $1 })
36-
}
37-
}
38-
3928
let romanTable: KeyValuePairs<String, Int> = [
40-
"M": 1000, "CM": 900, "D": 500, "CD": 400,
41-
"C": 100_, "XC": 90_, "L": 50_, "XL": 40_,
42-
"X": 10__, "IX": 9__, "V": 5__, "IV": 4__,
29+
"M": 1000,
30+
"CM": 900,
31+
"D": 500,
32+
"CD": 400,
33+
"C": 100,
34+
"XC": 90,
35+
"L": 50,
36+
"XL": 40,
37+
"X": 10,
38+
"IX": 9,
39+
"V": 5,
40+
"IV": 4,
4341
"I": 1,
4442
]
4543

4644
extension BinaryInteger {
47-
// Imperative Style
48-
// See https://www.rosettacode.org/wiki/Roman_numerals/Encode#Swift
49-
// See https://www.rosettacode.org/wiki/Roman_numerals/Decode#Swift
50-
5145
var romanNumeral: String {
5246
var result = ""
53-
var n = self
54-
for (numeral, value) in romanTable {
55-
while n >= value {
56-
result += numeral
57-
n -= Self(value)
47+
var value = self
48+
outer:
49+
while value > 0 {
50+
var position = 0
51+
for (i, (key: s, value: v)) in romanTable[position...].enumerated() {
52+
if value >= v {
53+
result += s
54+
value -= Self(v)
55+
position = i
56+
continue outer
57+
}
5858
}
59+
fatalError("Unreachable")
5960
}
6061
return result
6162
}
6263

63-
init?(romanSSsWdF number: String) {
64+
init?(romanNumeral: String) {
6465
self = 0
65-
var raw = Substring(number)
66-
for (numeral, value) in romanTable {
67-
while raw.starts(with: numeral) {
68-
self += Self(value)
69-
raw = raw.dropFirst(numeral.count)
66+
var input = Substring(romanNumeral)
67+
outer:
68+
while !input.isEmpty {
69+
var position = 0
70+
for (i, (key: s, value: v)) in romanTable[position...].enumerated() {
71+
if input.starts(with: s) {
72+
self += Self(v)
73+
input = input.dropFirst(s.count)
74+
position = i
75+
continue outer
76+
}
7077
}
78+
return nil
7179
}
72-
guard raw.isEmpty else { return nil }
80+
}
81+
}
82+
83+
@inline(never)
84+
func checkRomanNumerals(upTo limit: Int) {
85+
for i in 0 ..< limit {
86+
CheckResults(Int(romanNumeral: identity(i.romanNumeral)) == i)
87+
}
88+
}
89+
90+
@inline(never)
91+
public func run_RomanNumbers(_ N: Int) {
92+
for _ in 0 ..< 10 * N {
93+
checkRomanNumerals(upTo: 1100)
7394
}
7495
}

0 commit comments

Comments
 (0)