summaryrefslogtreecommitdiff
path: root/numpy/lib/function_base.py
diff options
context:
space:
mode:
authorWarren Weckesser <warren.weckesser@gmail.com>2019-12-31 09:57:58 -0500
committerWarren Weckesser <warren.weckesser@gmail.com>2020-01-01 18:50:02 -0500
commit0fea57e2c3c890b63c91325f9f9ce07ead74b745 (patch)
treed7045e02eed6a66c809eb5a1d10d5b84cc508e46 /numpy/lib/function_base.py
parent6253ff78be7f21898178799758717bfe59368b94 (diff)
downloadnumpy-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.py17
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: