diff options
Diffstat (limited to 'numpy')
-rw-r--r-- | numpy/linalg/linalg.py | 16 | ||||
-rw-r--r-- | numpy/linalg/tests/test_linalg.py | 12 |
2 files changed, 24 insertions, 4 deletions
diff --git a/numpy/linalg/linalg.py b/numpy/linalg/linalg.py index 1b82c7cc0..dd586827e 100644 --- a/numpy/linalg/linalg.py +++ b/numpy/linalg/linalg.py @@ -22,7 +22,7 @@ from numpy.core import ( array, asarray, zeros, empty, empty_like, transpose, intc, single, double, csingle, cdouble, inexact, complexfloating, newaxis, ravel, all, Inf, dot, add, multiply, sqrt, maximum, fastCopyAndTranspose, sum, isfinite, size, - finfo, errstate, geterrobj, longdouble, rollaxis, amin, amax, product, + finfo, errstate, geterrobj, longdouble, rollaxis, amin, amax, product, abs, broadcast ) from numpy.lib import triu, asfarray @@ -2082,12 +2082,20 @@ def norm(x, ord=None, axis=None): ord + 1 except TypeError: raise ValueError("Invalid norm order for vectors.") - if x.dtype.type is not longdouble: + if x.dtype.type is longdouble: # Convert to a float type, so integer arrays give # float results. Don't apply asfarray to longdouble arrays, # because it will downcast to float64. - absx = asfarray(abs(x)) - return add.reduce(absx**ord, axis=axis)**(1.0/ord) + absx = abs(x) + else: + absx = asfarray(x) + if absx.dtype is x.dtype: + absx = abs(absx) + else: + # if the type changed, we can safely overwrite absx + abs(absx, out=absx) + absx **= ord + return add.reduce(absx, axis=axis) ** (1.0 / ord) elif len(axis) == 2: row_axis, col_axis = axis if not (-nd <= row_axis < nd and -nd <= col_axis < nd): diff --git a/numpy/linalg/tests/test_linalg.py b/numpy/linalg/tests/test_linalg.py index dd4cbcc4f..feb4c8224 100644 --- a/numpy/linalg/tests/test_linalg.py +++ b/numpy/linalg/tests/test_linalg.py @@ -909,6 +909,18 @@ class _TestNorm(object): assert_raises(ValueError, norm, B, None, (2, 3)) assert_raises(ValueError, norm, B, None, (0, 1, 2)) + def test_longdouble_norm(self): + # Non-regression test: p-norm of longdouble would previously raise + # UnboundLocalError. + x = np.arange(10, dtype=np.longdouble) + old_assert_almost_equal(norm(x, ord=3), 12.65, decimal=2) + + def test_intmin(self): + # Non-regression test: p-norm of signed integer would previously do + # float cast and abs in the wrong order. + x = np.array([-2 ** 31], dtype=np.int32) + old_assert_almost_equal(norm(x, ord=3), 2 ** 31, decimal=5) + class TestNormDouble(_TestNorm): dt = np.double |