Here’s an idea for integers.
We can count the number of overflows (with sign), and if it is zero then the sum using wrapping arithmetic is correct:
extension Sequence where Element: FixedWidthInteger & SignedInteger {
func sum() -> Element {
var result: Element = 0
var overflow: Bool = false
var totalOverflow: Int = 0
for x in self {
(result, overflow) = result.addingReportingOverflow(x)
if overflow {
totalOverflow += (x < 0) ? -1 : 1
}
}
precondition(totalOverflow == 0)
return result
}
}
Of course, integers that are unsigned or variable-width can use the simple version:
extension Sequence where Element: BinaryInteger {
func sum() -> Element {
return self.reduce(0, +)
}
}