summaryrefslogtreecommitdiff
path: root/numpy/lib
diff options
context:
space:
mode:
Diffstat (limited to 'numpy/lib')
-rw-r--r--numpy/lib/format.py30
-rw-r--r--numpy/lib/function_base.py8
-rw-r--r--numpy/lib/tests/test_function_base.py72
-rw-r--r--numpy/lib/twodim_base.py2
4 files changed, 101 insertions, 11 deletions
diff --git a/numpy/lib/format.py b/numpy/lib/format.py
index cb2d511af..4e6e731c1 100644
--- a/numpy/lib/format.py
+++ b/numpy/lib/format.py
@@ -280,14 +280,26 @@ def dtype_to_descr(dtype):
return dtype.str
def descr_to_dtype(descr):
- '''
- descr may be stored as dtype.descr, which is a list of
- (name, format, [shape]) tuples where format may be a str or a tuple.
- Offsets are not explicitly saved, rather empty fields with
- name, format == '', '|Vn' are added as padding.
-
- This function reverses the process, eliminating the empty padding fields.
- '''
+ """
+ Returns a dtype based off the given description.
+
+ This is essentially the reverse of `dtype_to_descr()`. It will remove
+ the valueless padding fields created by, i.e. simple fields like
+ dtype('float32'), and then convert the description to its corresponding
+ dtype.
+
+ Parameters
+ ----------
+ descr : object
+ The object retreived by dtype.descr. Can be passed to
+ `numpy.dtype()` in order to replicate the input dtype.
+
+ Returns
+ -------
+ dtype : dtype
+ The dtype constructed by the description.
+
+ """
if isinstance(descr, str):
# No padding removal needed
return numpy.dtype(descr)
@@ -820,7 +832,7 @@ def open_memmap(filename, mode='r+', dtype=None, shape=None,
See Also
--------
- memmap
+ numpy.memmap
"""
if isfileobj(filename):
diff --git a/numpy/lib/function_base.py b/numpy/lib/function_base.py
index cf6f4891c..1053598b1 100644
--- a/numpy/lib/function_base.py
+++ b/numpy/lib/function_base.py
@@ -3879,7 +3879,13 @@ def _quantile_is_valid(q):
def _lerp(a, b, t, out=None):
""" Linearly interpolate from a to b by a factor of t """
- return add(a*(1 - t), b*t, out=out)
+ diff_b_a = subtract(b, a)
+ # asanyarray is a stop-gap until gh-13105
+ lerp_interpolation = asanyarray(add(a, diff_b_a*t, out=out))
+ subtract(b, diff_b_a * (1 - t), out=lerp_interpolation, where=t>=0.5)
+ if lerp_interpolation.ndim == 0 and out is None:
+ lerp_interpolation = lerp_interpolation[()] # unpack 0d arrays
+ return lerp_interpolation
def _quantile_ureduce_func(a, q, axis=None, out=None, overwrite_input=False,
diff --git a/numpy/lib/tests/test_function_base.py b/numpy/lib/tests/test_function_base.py
index 9ba0be56a..eb2fc3311 100644
--- a/numpy/lib/tests/test_function_base.py
+++ b/numpy/lib/tests/test_function_base.py
@@ -5,6 +5,10 @@ import decimal
from fractions import Fraction
import math
import pytest
+import hypothesis
+from hypothesis.extra.numpy import arrays
+import hypothesis.strategies as st
+
import numpy as np
from numpy import ma
@@ -3104,6 +3108,74 @@ class TestQuantile:
np.quantile(np.arange(100.), p, interpolation="midpoint")
assert_array_equal(p, p0)
+ def test_quantile_monotonic(self):
+ # GH 14685
+ # test that the return value of quantile is monotonic if p0 is ordered
+ p0 = np.arange(0, 1, 0.01)
+ quantile = np.quantile(np.array([0, 1, 1, 2, 2, 3, 3, 4, 5, 5, 1, 1, 9, 9, 9,
+ 8, 8, 7]) * 0.1, p0)
+ assert_equal(np.sort(quantile), quantile)
+
+ @hypothesis.given(
+ arr=arrays(dtype=np.float64,
+ shape=st.integers(min_value=3, max_value=1000),
+ elements=st.floats(allow_infinity=False, allow_nan=False,
+ min_value=-1e300, max_value=1e300)))
+ def test_quantile_monotonic_hypo(self, arr):
+ p0 = np.arange(0, 1, 0.01)
+ quantile = np.quantile(arr, p0)
+ assert_equal(np.sort(quantile), quantile)
+
+
+class TestLerp:
+ @hypothesis.given(t0=st.floats(allow_nan=False, allow_infinity=False,
+ min_value=0, max_value=1),
+ t1=st.floats(allow_nan=False, allow_infinity=False,
+ min_value=0, max_value=1),
+ a = st.floats(allow_nan=False, allow_infinity=False,
+ min_value=-1e300, max_value=1e300),
+ b = st.floats(allow_nan=False, allow_infinity=False,
+ min_value=-1e300, max_value=1e300))
+ def test_lerp_monotonic(self, t0, t1, a, b):
+ l0 = np.lib.function_base._lerp(a, b, t0)
+ l1 = np.lib.function_base._lerp(a, b, t1)
+ if t0 == t1 or a == b:
+ assert l0 == l1 # uninteresting
+ elif (t0 < t1) == (a < b):
+ assert l0 <= l1
+ else:
+ assert l0 >= l1
+
+ @hypothesis.given(t=st.floats(allow_nan=False, allow_infinity=False,
+ min_value=0, max_value=1),
+ a=st.floats(allow_nan=False, allow_infinity=False,
+ min_value=-1e300, max_value=1e300),
+ b=st.floats(allow_nan=False, allow_infinity=False,
+ min_value=-1e300, max_value=1e300))
+ def test_lerp_bounded(self, t, a, b):
+ if a <= b:
+ assert a <= np.lib.function_base._lerp(a, b, t) <= b
+ else:
+ assert b <= np.lib.function_base._lerp(a, b, t) <= a
+
+ @hypothesis.given(t=st.floats(allow_nan=False, allow_infinity=False,
+ min_value=0, max_value=1),
+ a=st.floats(allow_nan=False, allow_infinity=False,
+ min_value=-1e300, max_value=1e300),
+ b=st.floats(allow_nan=False, allow_infinity=False,
+ min_value=-1e300, max_value=1e300))
+ def test_lerp_symmetric(self, t, a, b):
+ # double subtraction is needed to remove the extra precision of t < 0.5
+ left = np.lib.function_base._lerp(a, b, 1 - (1 - t))
+ right = np.lib.function_base._lerp(b, a, 1 - t)
+ assert left == right
+
+ def test_lerp_0d_inputs(self):
+ a = np.array(2)
+ b = np.array(5)
+ t = np.array(0.2)
+ assert np.lib.function_base._lerp(a, b, t) == 2.6
+
class TestMedian:
diff --git a/numpy/lib/twodim_base.py b/numpy/lib/twodim_base.py
index 320a24856..2bb4c78a5 100644
--- a/numpy/lib/twodim_base.py
+++ b/numpy/lib/twodim_base.py
@@ -441,7 +441,7 @@ def triu(m, k=0):
"""
Upper triangle of an array.
- Return a copy of a matrix with the elements below the `k`-th diagonal
+ Return a copy of an array with the elements below the `k`-th diagonal
zeroed.
Please refer to the documentation for `tril` for further details.