Function std.algorithm.iteration.sum
Sums elements of r
, which must be a finite
input range. Although
conceptually sum(r)
is equivalent to fold
!((a, b) => a +
b)(r, 0), sum
uses specialized algorithms to maximize accuracy,
as follows.
auto auto sum(R)
(
R r
)
if (isInputRange!R && !isInfinite!R && is(typeof(r .front + r .front)));
auto auto sum(R, E)
(
R r,
E seed
)
if (isInputRange!R && !isInfinite!R && is(typeof(seed = seed + r .front)));
- If
ElementType
!R is a floating-point type andR
is a random-access range with length and slicing, thensum
uses the pairwise summation algorithm. - If
ElementType!R
is a floating-point type andR
is a finite input range (but not a random-access range with slicing), thensum
uses the Kahan summation algorithm. - In all other cases, a simple element by element addition is done.
For floating point inputs, calculations are made in
real
precision for real
inputs and in double
precision otherwise
(Note this is a special case that deviates from fold
's behavior,
which would have kept float
precision for a float
range).
For all other types, the calculations are done in the same type obtained
from from adding two elements of the range, which may be a different
type from the elements themselves (for example, in case of
integral promotion).
A seed may be passed to sum
. Not only will this seed be used as an initial
value, but its type will override all the above, and determine the algorithm
and precision used for summation. If a seed is not passed, one is created with
the value of typeof(r
, or typeof(r
if no constructor exists that takes an int.
Note that these specialized summing algorithms execute more primitive operations
than vanilla summation. Therefore, if in certain cases maximum speed is required
at expense of precision, one can use fold!((a, b) => a + b)(r, 0)
, which
is not specialized for summation.
Parameters
Name | Description |
---|---|
seed | the initial value of the summation |
r | a finite input range |
Returns
The sum of all the elements in the range r.
Example
Ditto
import std .range;
//simple integral sumation
writeln(sum([1, 2, 3, 4])); // 10
//with integral promotion
writeln(sum([false, true, true, false, true])); // 3
writeln(sum(ubyte .max .repeat(100))); // 25500
//The result may overflow
writeln(uint .max .repeat(3) .sum()); // 4294967293U
//But a seed can be used to change the sumation primitive
writeln(uint .max .repeat(3) .sum(ulong .init)); // 12884901885UL
//Floating point sumation
writeln(sum([1.0, 2.0, 3.0, 4.0])); // 10
//Floating point operations have double precision minimum
static assert(is(typeof(sum([1F, 2F, 3F, 4F])) == double));
writeln(sum([1F, 2, 3, 4])); // 10
//Force pair-wise floating point sumation on large integers
import std .math : approxEqual;
assert(iota(ulong .max / 2, ulong .max / 2 + 4096) .sum(0.0)
.approxEqual((ulong .max / 2) * 4096.0 + 4096^^2 / 2));