Coverage Report

Created: 2026-05-30 06:05

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/h3/src/h3lib/include/adder.h
Line
Count
Source
1
/*
2
 * Copyright 2025 Uber Technologies, Inc.
3
 *
4
 * Licensed under the Apache License, Version 2.0 (the "License");
5
 * you may not use this file except in compliance with the License.
6
 * You may obtain a copy of the License at
7
 *
8
 *         http://www.apache.org/licenses/LICENSE-2.0
9
 *
10
 * Unless required by applicable law or agreed to in writing, software
11
 * distributed under the License is distributed on an "AS IS" BASIS,
12
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
 * See the License for the specific language governing permissions and
14
 * limitations under the License.
15
 */
16
17
#ifndef ADDER_H
18
#define ADDER_H
19
20
/*
21
Header-only implementation of a "compensated summation" algorithm (Kahan
22
summation), which allows us to add up sequences of floating-point numbers
23
with better precision than naive summation, especially when the terms in
24
the sum vary significantly in magnitude.
25
See: https://en.wikipedia.org/wiki/Kahan_summation_algorithm
26
27
This is useful when computing the area of (multi)polygons, which
28
often involves adding many small terms to a large aggregate. For example,
29
D3 uses an improved accuracy summation when computing polygonal areas via its
30
`Adder` class:
31
https://github.com/d3/d3-geo/blob/main/src/area.js
32
33
There are a few potential algorithms we might consider for summation:
34
35
1. Naive sum
36
2. Kahan summation
37
3. Neumaier summation
38
4. Other approaches like pairwise summation, or Python's `fsum`
39
40
We considered the first three for simplicity, and settled on Kahan summation:
41
it achieves noticeably better accuracy than naive summation and almost as
42
good accuracy as Neumaier, while being only slightly slower than naive and
43
slightly faster and simpler than Neumaier.
44
45
See also: https://github.com/python/cpython/issues/100425 for discussion of
46
tradeoffs between Kahan, Neumaier, and `fsum`.
47
48
## Usage
49
50
Adder adder = {};  // initialize
51
kadd(&adder, x);  // add x to summation
52
out = adder.sum;  // extract final sum
53
*/
54
55
typedef struct {
56
    double sum;  // running total. public
57
    double _c;   // compensation term. private
58
} Adder;
59
60
0
static inline void kadd(Adder *adder, double x) {
61
0
    double y = x - adder->_c;
62
0
    double t = adder->sum + y;
63
0
    adder->_c = (t - adder->sum) - y;
64
0
    adder->sum = t;
65
0
}
66
67
#endif