blob: 6ccbba735099ba26c6445b9586b7f2075b87051d [file] [log] [blame]
//===--- RomanNumbers.swift -----------------------------------------------===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2018 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See https://swift.org/LICENSE.txt for license information
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//
import TestsUtils
//
// Mini benchmark implementing roman numeral conversions to/from integers.
// Measures performance of Substring.starts(with:) and String.append(),
// with very short string arguments.
//
public let RomanNumbers = [
BenchmarkInfo(
name: "RomanNumbers",
runFunction: run_RomanNumbers,
tags: [.api, .String, .algorithm])
]
let romanTable: KeyValuePairs<String, Int> = [
"M": 1000,
"CM": 900,
"D": 500,
"CD": 400,
"C": 100,
"XC": 90,
"L": 50,
"XL": 40,
"X": 10,
"IX": 9,
"V": 5,
"IV": 4,
"I": 1,
]
extension BinaryInteger {
var romanNumeral: String {
var result = ""
var value = self
outer:
while value > 0 {
var position = 0
for (i, (key: s, value: v)) in romanTable[position...].enumerated() {
if value >= v {
result += s
value -= Self(v)
position = i
continue outer
}
}
fatalError("Unreachable")
}
return result
}
init?(romanNumeral: String) {
self = 0
var input = Substring(romanNumeral)
outer:
while !input.isEmpty {
var position = 0
for (i, (key: s, value: v)) in romanTable[position...].enumerated() {
if input.starts(with: s) {
self += Self(v)
input = input.dropFirst(s.count)
position = i
continue outer
}
}
return nil
}
}
}
@inline(never)
func checkRomanNumerals(upTo limit: Int) {
for i in 0 ..< limit {
CheckResults(Int(romanNumeral: identity(i.romanNumeral)) == i)
}
}
@inline(never)
public func run_RomanNumbers(_ N: Int) {
for _ in 0 ..< 10 * N {
checkRomanNumerals(upTo: 1100)
}
}