accumulator.py
Go to the documentation of this file.
1 """accumulator.py: transcription of GeographicLib::Accumulator class."""
2 # accumulator.py
3 #
4 # This is a rather literal translation of the GeographicLib::Accumulator class
5 # from to python. See the documentation for the C++ class for more information
6 # at
7 #
8 # https://geographiclib.sourceforge.io/html/annotated.html
9 #
10 # Copyright (c) Charles Karney (2011) <charles@karney.com> and licensed under
11 # the MIT/X11 License. For more information, see
12 # https://geographiclib.sourceforge.io/
13 
14 
15 from geographiclib.geomath import Math
16 
18  """Like math.fsum, but allows a running sum"""
19 
20  def Set(self, y):
21  """Set value from argument"""
22  if type(self) == type(y):
23  self._s, self._t = y._s, y._t
24  else:
25  self._s, self._t = float(y), 0.0
26 
27  def __init__(self, y = 0.0):
28  """Constructor"""
29  self.Set(y)
30 
31  def Add(self, y):
32  """Add a value"""
33  # Here's Shewchuk's solution...
34  # hold exact sum as [s, t, u]
35  y, u = Math.sum(y, self._t) # Accumulate starting at
36  self._s, self._t = Math.sum(y, self._s) # least significant end
37  # Start is _s, _t decreasing and non-adjacent. Sum is now (s + t + u)
38  # exactly with s, t, u non-adjacent and in decreasing order (except
39  # for possible zeros). The following code tries to normalize the
40  # result. Ideally, we want _s = round(s+t+u) and _u = round(s+t+u -
41  # _s). The follow does an approximate job (and maintains the
42  # decreasing non-adjacent property). Here are two "failures" using
43  # 3-bit floats:
44  #
45  # Case 1: _s is not equal to round(s+t+u) -- off by 1 ulp
46  # [12, -1] - 8 -> [4, 0, -1] -> [4, -1] = 3 should be [3, 0] = 3
47  #
48  # Case 2: _s+_t is not as close to s+t+u as it shold be
49  # [64, 5] + 4 -> [64, 8, 1] -> [64, 8] = 72 (off by 1)
50  # should be [80, -7] = 73 (exact)
51  #
52  # "Fixing" these problems is probably not worth the expense. The
53  # representation inevitably leads to small errors in the accumulated
54  # values. The additional errors illustrated here amount to 1 ulp of
55  # the less significant word during each addition to the Accumulator
56  # and an additional possible error of 1 ulp in the reported sum.
57  #
58  # Incidentally, the "ideal" representation described above is not
59  # canonical, because _s = round(_s + _t) may not be true. For
60  # example, with 3-bit floats:
61  #
62  # [128, 16] + 1 -> [160, -16] -- 160 = round(145).
63  # But [160, 0] - 16 -> [128, 16] -- 128 = round(144).
64  #
65  if self._s == 0: # This implies t == 0,
66  self._s = u # so result is u
67  else:
68  self._t += u # otherwise just accumulate u to t.
69 
70  def Sum(self, y = 0.0):
71  """Return sum + y"""
72  if y == 0.0:
73  return self._s
74  else:
75  b = Accumulator(self)
76  b.Add(y)
77  return b._s
78 
79  def Negate(self):
80  """Negate sum"""
81  self._s *= -1
82  self._t *= -1
Definition: pytypes.h:1370


gtsam
Author(s):
autogenerated on Tue Jul 4 2023 02:33:53