diff --git a/lib/matplotlib/tests/test_colorbar.py b/lib/matplotlib/tests/test_colorbar.py index 7f9b00b5e7c3..3932177565c5 100644 --- a/lib/matplotlib/tests/test_colorbar.py +++ b/lib/matplotlib/tests/test_colorbar.py @@ -570,3 +570,14 @@ def test_colorbar_label(): cbar3 = fig.colorbar(im, orientation='horizontal', label='horizontal cbar') assert cbar3.ax.get_xlabel() == 'horizontal cbar' + + +@pytest.mark.parametrize("clim", [(-20000, 20000), (-32768, 0)]) +def test_colorbar_int(clim): + # Check that we cast to float early enough to not + # overflow ``int16(20000) - int16(-20000)`` or + # run into ``abs(int16(-32768)) == -32768``. + fig, ax = plt.subplots() + im = ax.imshow([[*map(np.int16, clim)]]) + fig.colorbar(im) + assert (im.norm.vmin, im.norm.vmax) == clim diff --git a/lib/matplotlib/transforms.py b/lib/matplotlib/transforms.py index ce517c1d00b7..3292340bf99d 100644 --- a/lib/matplotlib/transforms.py +++ b/lib/matplotlib/transforms.py @@ -2791,6 +2791,10 @@ def nonsingular(vmin, vmax, expander=0.001, tiny=1e-15, increasing=True): vmin, vmax = vmax, vmin swapped = True + # Expand vmin, vmax to float: if they were integer types, they can wrap + # around in abs (abs(np.int8(-128)) == -128) and vmax - vmin can overflow. + vmin, vmax = map(float, [vmin, vmax]) + maxabsvalue = max(abs(vmin), abs(vmax)) if maxabsvalue < (1e6 / tiny) * np.finfo(float).tiny: vmin = -expander