Skip to content

Commit 548878f

Browse files
authored
Merge pull request #13731 from lorentey/romannumbers
[benchmark] Add roman numeral conversion benchmark
2 parents 2cd2d9e + 28dbeb5 commit 548878f

File tree

3 files changed

+98
-0
lines changed

3 files changed

+98
-0
lines changed

benchmark/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,7 @@ set(SWIFT_BENCH_MODULES
119119
single-source/RecursiveOwnedParameter
120120
single-source/ReduceInto
121121
single-source/ReversedCollections
122+
single-source/RomanNumbers
122123
single-source/SetTests
123124
single-source/SevenBoom
124125
single-source/Sim2DArray
Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
//===--- RomanNumbers.swift -----------------------------------------------===//
2+
//
3+
// This source file is part of the Swift.org open source project
4+
//
5+
// Copyright (c) 2014 - 2018 Apple Inc. and the Swift project authors
6+
// Licensed under Apache License v2.0 with Runtime Library Exception
7+
//
8+
// See https://swift.org/LICENSE.txt for license information
9+
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
10+
//
11+
//===----------------------------------------------------------------------===//
12+
13+
import TestsUtils
14+
15+
//
16+
// Mini benchmark implementing roman numeral conversions to/from integers.
17+
// Measures performance of Substring.starts(with:) and String.append(),
18+
// with very short string arguments.
19+
//
20+
21+
public let RomanNumbers = [
22+
BenchmarkInfo(
23+
name: "RomanNumbers",
24+
runFunction: run_RomanNumbers,
25+
tags: [.api, .String, .algorithm])
26+
]
27+
28+
let romanTable: DictionaryLiteral<String, Int> = [
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,
41+
"I": 1,
42+
]
43+
44+
extension BinaryInteger {
45+
var romanNumeral: String {
46+
var result = ""
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+
}
58+
}
59+
fatalError("Unreachable")
60+
}
61+
return result
62+
}
63+
64+
init?(romanNumeral: String) {
65+
self = 0
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+
}
77+
}
78+
return nil
79+
}
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)
94+
}
95+
}

benchmark/utils/main.swift

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,7 @@ import RangeReplaceableCollectionPlusDefault
107107
import RecursiveOwnedParameter
108108
import ReduceInto
109109
import ReversedCollections
110+
import RomanNumbers
110111
import SetTests
111112
import SevenBoom
112113
import Sim2DArray
@@ -242,6 +243,7 @@ registerBenchmark(RangeReplaceableCollectionPlusDefault)
242243
registerBenchmark(RecursiveOwnedParameter)
243244
registerBenchmark(ReduceInto)
244245
registerBenchmark(ReversedCollections)
246+
registerBenchmark(RomanNumbers)
245247
registerBenchmark(SetTests)
246248
registerBenchmark(SevenBoom)
247249
registerBenchmark(Sim2DArray)

0 commit comments

Comments
 (0)