blob: 1388f18f4b9459ca23a81721ef5b7018c9feb1ef [file] [log] [blame]
# Copyright 2016 The Chromium Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
import math
import numpy as np
def vsum(vs, shape=None):
"""Accurate summation of a list of vectors.
This function is like ``math.fsum`` except operating over collections
of vectors rather than collections of scalars.
Args:
vs (list of np.ndarray of float): The vectors to add up.
shape (tuple of int): the shape of the vectors. Optional.
Returns:
Returns an ``np.ndarray`` if all is well, otherwise returns
``None``. The situations where all is not well (and so we return
``None``) are: (1) ``vs`` is empty and ``shape`` is not provided;
(2) a ``shape`` is provided but does not match the actual shape of
the vectors; (3) not all the vectors in the list have the same shape.
"""
if shape is None:
if not vs:
return None
shape = vs[0].shape
# It'd be better to vectorize the implementation of Shewchuk's
# algorithm directly, so we can avoid needing to traverse ``vs``
# repeatedly. However, this is deemed to have too high a maintenance
# cost for the performance benefit.
total = np.zeros(shape)
it = np.nditer(total, flags=['multi_index'], op_flags=['writeonly'])
while not it.finished:
try:
it[0] = math.fsum(v[it.multi_index] for v in vs)
except TypeError:
it[0] = sum(v[it.multi_index] for v in vs)
it.iternext()
return total