Convenience functions for sum and product across a Collection type

And here’s a floating-point implementation with compensated summation:

extension Sequence where Element: FloatingPoint {
  func sum() -> Element {
    var result: Element = 0
    var excess: Element = 0
    
    for x in self {
      let large = Element.maximumMagnitude(result, x)
      let small = Element.minimumMagnitude(result, x)
      result += x
      excess += (result - large) - small
    }
    
    return result - excess
  }
}

Although for Float (and Float16) it’s probably better to just sum as Double:

extension Sequence where Element == Float {
  func sum() -> Float {
    return Float(self.reduce(0 as Double){ $0 + Double($1) })
  }
}

• • •

I have more thoughts on this, and I’ll work on writing them up, but the top-line is that I think sum() belongs in either the standard library or perhaps Numerics, rather than Algorithms.

There’s also some consideration for whether we ought to make Sequence.sum() trampoline off a customization point in AdditiveArithmetic to enable dynamic dispatch. That has both benefits and drawbacks, which I’ll try to cover when I get the chance.

1 Like