Convenience functions for sum and product across a Collection type

The behavior of reduce(0, +) is not necessarily what we want for sum().

Some of the issues are discussed in these previous threads:

Pitch: Method to sum numeric arrays (see in particular these two comments by Jens and Steve Canon)
Sum with Block
Add average to FloatingPoint arrays

Notably, if the partial sums would overflow but the full sum would not, should the calculation trap like reduce does, or should sum make an effort to avoid that, perhaps by reordering or using a wider type?

Example: [100 as Int8, 100, -100, -100].sum() mathematically should equal zero, but the first two terms overflow the Int8 type.

Also, in floating-point calculations, adding a large number of small terms can cause the low-order bits to be lost, thus producing an inaccurate sum. This is exacerbated if earlier terms are substantially larger than later ones.

Example: [16_777_216 as Float, 1, 1, 1, 1].sum() mathematically should equal 16_777_220, which is exactly representable as Float, but simply adding 1 to the first value returns the first value unchanged so the result of reduce(0, +) is 16_777_216.

8 Likes