diff options
author | Warren Weckesser <warren.weckesser@gmail.com> | 2019-12-31 09:57:58 -0500 |
---|---|---|
committer | Warren Weckesser <warren.weckesser@gmail.com> | 2020-01-01 18:50:02 -0500 |
commit | 0fea57e2c3c890b63c91325f9f9ce07ead74b745 (patch) | |
tree | d7045e02eed6a66c809eb5a1d10d5b84cc508e46 /numpy/lib/function_base.py | |
parent | 6253ff78be7f21898178799758717bfe59368b94 (diff) | |
download | numpy-0fea57e2c3c890b63c91325f9f9ce07ead74b745.tar.gz |
BUG: lib: Fix handling of integer arrays by gradient.
In numpy.gradient, convert integer array inputs to float64 to avoid
unwanted modular arithmetic.
Closes gh-15207.
Diffstat (limited to 'numpy/lib/function_base.py')
-rw-r--r-- | numpy/lib/function_base.py | 17 |
1 files changed, 13 insertions, 4 deletions
diff --git a/numpy/lib/function_base.py b/numpy/lib/function_base.py index c2680b016..4c3de4df9 100644 --- a/numpy/lib/function_base.py +++ b/numpy/lib/function_base.py @@ -974,13 +974,18 @@ def gradient(f, *varargs, **kwargs): # scalar or 1d array for each axis dx = list(varargs) for i, distances in enumerate(dx): - if np.ndim(distances) == 0: + distances = np.asanyarray(distances) + if distances.ndim == 0: continue - elif np.ndim(distances) != 1: + elif distances.ndim != 1: raise ValueError("distances must be either scalars or 1d") if len(distances) != f.shape[axes[i]]: raise ValueError("when 1d, distances must match " "the length of the corresponding dimension") + if np.issubdtype(distances.dtype, np.integer): + # Convert numpy integer types to float64 to avoid modular + # arithmetic in np.diff(distances). + distances = distances.astype(np.float64) diffx = np.diff(distances) # if distances are constant reduce to the scalar case # since it brings a consistent speedup @@ -1019,8 +1024,12 @@ def gradient(f, *varargs, **kwargs): elif np.issubdtype(otype, np.inexact): pass else: - # all other types convert to floating point - otype = np.double + # All other types convert to floating point. + # First check if f is a numpy integer type; if so, convert f to float64 + # to avoid modular arithmetic when computing the changes in f. + if np.issubdtype(otype, np.integer): + f = f.astype(np.float64) + otype = np.float64 for axis, ax_dx in zip(axes, dx): if f.shape[axis] < edge_order + 1: |