diff --git a/lib/matplotlib/colors.py b/lib/matplotlib/colors.py index 511f46d18710..73e0c8570794 100644 --- a/lib/matplotlib/colors.py +++ b/lib/matplotlib/colors.py @@ -880,22 +880,13 @@ def process_value(value): Experimental; we may want to add an option to force the use of float32. """ - if cbook.iterable(value): - is_scalar = False - result = np.ma.asarray(value) - if result.dtype.kind == 'f': - # this is overkill for lists of floats, but required - # to support pd.Series as input until we can reliable - # determine if result and value share memory in all cases - # (list, tuple, deque, ndarray, Series, ...) - result = result.copy() - elif result.dtype.itemsize > 2: - result = result.astype(float) - else: - result = result.astype(np.float32) - else: - is_scalar = True - result = np.ma.array([value]).astype(float) + is_scalar = not cbook.iterable(value) + if is_scalar: + value = [value] + dtype = np.min_scalar_type(value) + dtype = (np.float32 if dtype.itemsize <= 2 + else np.promote_types(dtype, float)) + result = np.ma.array(value, dtype=dtype, copy=True) return result, is_scalar def __call__(self, value, clip=None): @@ -918,8 +909,6 @@ def __call__(self, value, clip=None): elif vmin > vmax: raise ValueError("minvalue must be less than or equal to maxvalue") else: - vmin = float(vmin) - vmax = float(vmax) if clip: mask = np.ma.getmask(result) result = np.ma.array(np.clip(result.filled(vmax), vmin, vmax), @@ -938,8 +927,7 @@ def __call__(self, value, clip=None): def inverse(self, value): if not self.scaled(): raise ValueError("Not invertible until scaled") - vmin = float(self.vmin) - vmax = float(self.vmax) + vmin, vmax = self.vmin, self.vmax if cbook.iterable(value): val = np.ma.asarray(value) diff --git a/lib/matplotlib/tests/test_colors.py b/lib/matplotlib/tests/test_colors.py index 072959eb8ff7..986a5c9ca5cb 100644 --- a/lib/matplotlib/tests/test_colors.py +++ b/lib/matplotlib/tests/test_colors.py @@ -194,6 +194,16 @@ def test_Normalize(): _scalar_tester(norm, vals) _mask_tester(norm, vals) + # Don't lose precision on longdoubles (float128 on Linux): + # for array inputs... + vals = np.array([1.2345678901, 9.8765432109], dtype=np.longdouble) + norm = mcolors.Normalize(vals.min(), vals.max()) + assert_array_equal(np.asarray(norm(vals)), [0, 1]) + # and for scalar ones. + eps = np.finfo(np.longdouble).resolution + norm = plt.Normalize(1, 1 + 100 * eps) + assert_equal(norm(1 + 50 * eps), .5) + def test_SymLogNorm(): """