summaryrefslogtreecommitdiff
path: root/numpy
diff options
context:
space:
mode:
authorCharles Harris <charlesr.harris@gmail.com>2018-05-12 11:56:17 -0600
committerGitHub <noreply@github.com>2018-05-12 11:56:17 -0600
commit25a2d3079ffb9fd0df5e87639941e83d63cd480c (patch)
tree98626a3da3bc4a38ec192e2328138145ac768074 /numpy
parent88e5cb7fcb922650ec1b715104831ef18023dd6d (diff)
parent121a2ee8d6ef43cde55b9f66a301c58cc9eb1623 (diff)
downloadnumpy-25a2d3079ffb9fd0df5e87639941e83d63cd480c.tar.gz
Merge pull request #10975 from mhvk/linalg-matrix-tests-to-matrixlib
MAINT: move linalg tests using matrix to matrixlib
Diffstat (limited to 'numpy')
-rw-r--r--numpy/linalg/tests/test_linalg.py411
-rw-r--r--numpy/matrixlib/tests/test_matrix_linalg.py95
2 files changed, 327 insertions, 179 deletions
diff --git a/numpy/linalg/tests/test_linalg.py b/numpy/linalg/tests/test_linalg.py
index 4a87330c7..b3dd2e4ae 100644
--- a/numpy/linalg/tests/test_linalg.py
+++ b/numpy/linalg/tests/test_linalg.py
@@ -7,12 +7,11 @@ import os
import sys
import itertools
import traceback
-import warnings
import pytest
import numpy as np
from numpy import array, single, double, csingle, cdouble, dot, identity
-from numpy import multiply, atleast_2d, inf, asarray, matrix
+from numpy import multiply, atleast_2d, inf, asarray
from numpy import linalg
from numpy.linalg import matrix_power, norm, matrix_rank, multi_dot, LinAlgError
from numpy.linalg.linalg import _multi_dot_matrix_chain_order
@@ -22,12 +21,11 @@ from numpy.testing import (
)
-def ifthen(a, b):
- return not a or b
-
-
-def imply(a, b):
- return not a or b
+def consistent_subclass(out, in_):
+ # For ndarray subclass input, our output should have the same subclass
+ # (non-ndarray input gets converted to ndarray).
+ return type(out) is (type(in_) if isinstance(in_, np.ndarray)
+ else np.ndarray)
old_assert_almost_equal = assert_almost_equal
@@ -65,6 +63,7 @@ all_tags = {
'generalized', 'size-0', 'strided' # optional additions
}
+
class LinalgCase(object):
def __init__(self, name, a, b, tags=set()):
"""
@@ -86,6 +85,7 @@ class LinalgCase(object):
def __repr__(self):
return "<LinalgCase: %s>" % (self.name,)
+
def apply_tag(tag, cases):
"""
Add the given tag (a string) to each of the cases (a list of LinalgCase
@@ -129,10 +129,6 @@ CASES += apply_tag('square', [
np.empty((0, 0), dtype=double),
np.empty((0,), dtype=double),
tags={'size-0'}),
- LinalgCase("0x0_matrix",
- np.empty((0, 0), dtype=double).view(np.matrix),
- np.empty((0, 1), dtype=double).view(np.matrix),
- tags={'size-0'}),
LinalgCase("8x8",
np.random.rand(8, 8),
np.random.rand(8)),
@@ -142,12 +138,6 @@ CASES += apply_tag('square', [
LinalgCase("nonarray",
[[1, 2], [3, 4]],
[2, 1]),
- LinalgCase("matrix_b_only",
- array([[1., 2.], [3., 4.]]),
- matrix([2., 1.]).T),
- LinalgCase("matrix_a_and_b",
- matrix([[1., 2.], [3., 4.]]),
- matrix([2., 1.]).T),
])
# non-square test-cases
@@ -231,9 +221,6 @@ CASES += apply_tag('hermitian', [
LinalgCase("matrix_b_only",
array([[1., 2.], [2., 1.]]),
None),
- LinalgCase("hmatrix_a_and_b",
- matrix([[1., 2.], [2., 1.]]),
- None),
LinalgCase("hmatrix_1x1",
np.random.rand(1, 1),
None),
@@ -270,12 +257,13 @@ def _make_generalized_cases():
return new_cases
+
CASES += _make_generalized_cases()
+
#
# Generate stride combination variations of the above
#
-
def _stride_comb_iter(x):
"""
Generate cartesian product of strides for all axes
@@ -323,6 +311,7 @@ def _stride_comb_iter(x):
xi = np.lib.stride_tricks.as_strided(x, strides=s)
yield xi, "stride_xxx_0_0"
+
def _make_strided_cases():
new_cases = []
for case in CASES:
@@ -333,94 +322,104 @@ def _make_strided_cases():
new_cases.append(new_case)
return new_cases
+
CASES += _make_strided_cases()
#
# Test different routines against the above cases
#
+class LinalgTestCase(object):
+ TEST_CASES = CASES
-def _check_cases(func, require=set(), exclude=set()):
- """
- Run func on each of the cases with all of the tags in require, and none
- of the tags in exclude
- """
- for case in CASES:
- # filter by require and exclude
- if case.tags & require != require:
- continue
- if case.tags & exclude:
- continue
+ def check_cases(self, require=set(), exclude=set()):
+ """
+ Run func on each of the cases with all of the tags in require, and none
+ of the tags in exclude
+ """
+ for case in self.TEST_CASES:
+ # filter by require and exclude
+ if case.tags & require != require:
+ continue
+ if case.tags & exclude:
+ continue
- try:
- case.check(func)
- except Exception:
- msg = "In test case: %r\n\n" % case
- msg += traceback.format_exc()
- raise AssertionError(msg)
+ try:
+ case.check(self.do)
+ except Exception:
+ msg = "In test case: %r\n\n" % case
+ msg += traceback.format_exc()
+ raise AssertionError(msg)
-class LinalgSquareTestCase(object):
+class LinalgSquareTestCase(LinalgTestCase):
def test_sq_cases(self):
- _check_cases(self.do, require={'square'}, exclude={'generalized', 'size-0'})
+ self.check_cases(require={'square'},
+ exclude={'generalized', 'size-0'})
def test_empty_sq_cases(self):
- _check_cases(self.do, require={'square', 'size-0'}, exclude={'generalized'})
+ self.check_cases(require={'square', 'size-0'},
+ exclude={'generalized'})
-class LinalgNonsquareTestCase(object):
+class LinalgNonsquareTestCase(LinalgTestCase):
def test_nonsq_cases(self):
- _check_cases(self.do, require={'nonsquare'}, exclude={'generalized', 'size-0'})
+ self.check_cases(require={'nonsquare'},
+ exclude={'generalized', 'size-0'})
def test_empty_nonsq_cases(self):
- _check_cases(self.do, require={'nonsquare', 'size-0'}, exclude={'generalized'})
+ self.check_cases(require={'nonsquare', 'size-0'},
+ exclude={'generalized'})
-class HermitianTestCase(object):
+
+class HermitianTestCase(LinalgTestCase):
def test_herm_cases(self):
- _check_cases(self.do, require={'hermitian'}, exclude={'generalized', 'size-0'})
+ self.check_cases(require={'hermitian'},
+ exclude={'generalized', 'size-0'})
def test_empty_herm_cases(self):
- _check_cases(self.do, require={'hermitian', 'size-0'}, exclude={'generalized'})
+ self.check_cases(require={'hermitian', 'size-0'},
+ exclude={'generalized'})
-class LinalgGeneralizedSquareTestCase(object):
+class LinalgGeneralizedSquareTestCase(LinalgTestCase):
@pytest.mark.slow
def test_generalized_sq_cases(self):
- _check_cases(self.do, require={'generalized', 'square'}, exclude={'size-0'})
+ self.check_cases(require={'generalized', 'square'},
+ exclude={'size-0'})
@pytest.mark.slow
def test_generalized_empty_sq_cases(self):
- _check_cases(self.do, require={'generalized', 'square', 'size-0'})
+ self.check_cases(require={'generalized', 'square', 'size-0'})
-class LinalgGeneralizedNonsquareTestCase(object):
+class LinalgGeneralizedNonsquareTestCase(LinalgTestCase):
@pytest.mark.slow
def test_generalized_nonsq_cases(self):
- _check_cases(self.do, require={'generalized', 'nonsquare'}, exclude={'size-0'})
+ self.check_cases(require={'generalized', 'nonsquare'},
+ exclude={'size-0'})
@pytest.mark.slow
def test_generalized_empty_nonsq_cases(self):
- _check_cases(self.do, require={'generalized', 'nonsquare', 'size-0'})
+ self.check_cases(require={'generalized', 'nonsquare', 'size-0'})
-class HermitianGeneralizedTestCase(object):
+class HermitianGeneralizedTestCase(LinalgTestCase):
@pytest.mark.slow
def test_generalized_herm_cases(self):
- _check_cases(self.do,
- require={'generalized', 'hermitian'},
- exclude={'size-0'})
+ self.check_cases(require={'generalized', 'hermitian'},
+ exclude={'size-0'})
@pytest.mark.slow
def test_generalized_empty_herm_cases(self):
- _check_cases(self.do,
- require={'generalized', 'hermitian', 'size-0'},
- exclude={'none'})
+ self.check_cases(require={'generalized', 'hermitian', 'size-0'},
+ exclude={'none'})
def dot_generalized(a, b):
@@ -453,13 +452,15 @@ def identity_like_generalized(a):
return identity(a.shape[0])
-class TestSolve(LinalgSquareTestCase, LinalgGeneralizedSquareTestCase):
-
+class SolveCases(LinalgSquareTestCase, LinalgGeneralizedSquareTestCase):
+ # kept apart from TestSolve for use for testing with matrices.
def do(self, a, b, tags):
x = linalg.solve(a, b)
assert_almost_equal(b, dot_generalized(a, x))
- assert_(imply(isinstance(b, matrix), isinstance(x, matrix)))
+ assert_(consistent_subclass(x, b))
+
+class TestSolve(SolveCases):
def test_types(self):
def check(dtype):
x = np.array([[1, 0.5], [0.5, 1]], dtype=dtype)
@@ -519,14 +520,16 @@ class TestSolve(LinalgSquareTestCase, LinalgGeneralizedSquareTestCase):
assert_(isinstance(result, ArraySubclass))
-class TestInv(LinalgSquareTestCase, LinalgGeneralizedSquareTestCase):
+class InvCases(LinalgSquareTestCase, LinalgGeneralizedSquareTestCase):
def do(self, a, b, tags):
a_inv = linalg.inv(a)
assert_almost_equal(dot_generalized(a, a_inv),
identity_like_generalized(a))
- assert_(imply(isinstance(a, matrix), isinstance(a_inv, matrix)))
+ assert_(consistent_subclass(a_inv, a))
+
+class TestInv(InvCases):
def test_types(self):
def check(dtype):
x = np.array([[1, 0.5], [0.5, 1]], dtype=dtype)
@@ -551,13 +554,15 @@ class TestInv(LinalgSquareTestCase, LinalgGeneralizedSquareTestCase):
assert_(isinstance(res, ArraySubclass))
-class TestEigvals(LinalgSquareTestCase, LinalgGeneralizedSquareTestCase):
+class EigvalsCases(LinalgSquareTestCase, LinalgGeneralizedSquareTestCase):
def do(self, a, b, tags):
ev = linalg.eigvals(a)
evalues, evectors = linalg.eig(a)
assert_almost_equal(ev, evalues)
+
+class TestEigvals(EigvalsCases):
def test_types(self):
def check(dtype):
x = np.array([[1, 0.5], [0.5, 1]], dtype=dtype)
@@ -586,15 +591,17 @@ class TestEigvals(LinalgSquareTestCase, LinalgGeneralizedSquareTestCase):
assert_(isinstance(res, np.ndarray))
-class TestEig(LinalgSquareTestCase, LinalgGeneralizedSquareTestCase):
+class EigCases(LinalgSquareTestCase, LinalgGeneralizedSquareTestCase):
def do(self, a, b, tags):
evalues, evectors = linalg.eig(a)
assert_allclose(dot_generalized(a, evectors),
np.asarray(evectors) * np.asarray(evalues)[..., None, :],
rtol=get_rtol(evalues.dtype))
- assert_(imply(isinstance(a, matrix), isinstance(evectors, matrix)))
+ assert_(consistent_subclass(evectors, a))
+
+class TestEig(EigCases):
def test_types(self):
def check(dtype):
x = np.array([[1, 0.5], [0.5, 1]], dtype=dtype)
@@ -633,7 +640,7 @@ class TestEig(LinalgSquareTestCase, LinalgGeneralizedSquareTestCase):
assert_(isinstance(a, np.ndarray))
-class TestSVD(LinalgSquareTestCase, LinalgGeneralizedSquareTestCase):
+class SVDCases(LinalgSquareTestCase, LinalgGeneralizedSquareTestCase):
def do(self, a, b, tags):
if 'size-0' in tags:
@@ -644,9 +651,11 @@ class TestSVD(LinalgSquareTestCase, LinalgGeneralizedSquareTestCase):
assert_allclose(a, dot_generalized(np.asarray(u) * np.asarray(s)[..., None, :],
np.asarray(vt)),
rtol=get_rtol(u.dtype))
- assert_(imply(isinstance(a, matrix), isinstance(u, matrix)))
- assert_(imply(isinstance(a, matrix), isinstance(vt, matrix)))
+ assert_(consistent_subclass(u, a))
+ assert_(consistent_subclass(vt, a))
+
+class TestSVD(SVDCases):
def test_types(self):
def check(dtype):
x = np.array([[1, 0.5], [0.5, 1]], dtype=dtype)
@@ -671,7 +680,7 @@ class TestSVD(LinalgSquareTestCase, LinalgGeneralizedSquareTestCase):
assert_raises(linalg.LinAlgError, linalg.svd, a)
-class TestCond(LinalgSquareTestCase, LinalgGeneralizedSquareTestCase):
+class CondCases(LinalgSquareTestCase, LinalgGeneralizedSquareTestCase):
# cond(x, p) for p in (None, 2, -2)
def do(self, a, b, tags):
@@ -716,6 +725,8 @@ class TestCond(LinalgSquareTestCase, LinalgGeneralizedSquareTestCase):
* (abs(cinv)**2).sum(-1).sum(-1)),
single_decimal=5, double_decimal=11)
+
+class TestCond(CondCases):
def test_basic_nonsvd(self):
# Smoketest the non-svd norms
A = array([[1., 0, 1], [0, -2., 0], [0, 0, 3.]])
@@ -779,20 +790,24 @@ class TestCond(LinalgSquareTestCase, LinalgGeneralizedSquareTestCase):
assert_(np.isfinite(c[1,0]))
-class TestPinv(LinalgSquareTestCase,
- LinalgNonsquareTestCase,
- LinalgGeneralizedSquareTestCase,
- LinalgGeneralizedNonsquareTestCase):
+class PinvCases(LinalgSquareTestCase,
+ LinalgNonsquareTestCase,
+ LinalgGeneralizedSquareTestCase,
+ LinalgGeneralizedNonsquareTestCase):
def do(self, a, b, tags):
a_ginv = linalg.pinv(a)
# `a @ a_ginv == I` does not hold if a is singular
dot = dot_generalized
assert_almost_equal(dot(dot(a, a_ginv), a), a, single_decimal=5, double_decimal=11)
- assert_(imply(isinstance(a, matrix), isinstance(a_ginv, matrix)))
+ assert_(consistent_subclass(a_ginv, a))
+
+
+class TestPinv(PinvCases):
+ pass
-class TestDet(LinalgSquareTestCase, LinalgGeneralizedSquareTestCase):
+class DetCases(LinalgSquareTestCase, LinalgGeneralizedSquareTestCase):
def do(self, a, b, tags):
d = linalg.det(a)
@@ -811,6 +826,8 @@ class TestDet(LinalgSquareTestCase, LinalgGeneralizedSquareTestCase):
assert_almost_equal(np.abs(s[m]), 1)
assert_equal(ld[~m], -inf)
+
+class TestDet(DetCases):
def test_zero(self):
assert_equal(linalg.det([[0.0]]), 0.0)
assert_equal(type(linalg.det([[0.0]])), double)
@@ -854,7 +871,7 @@ class TestDet(LinalgSquareTestCase, LinalgGeneralizedSquareTestCase):
assert_(res[1].dtype.type is np.float64)
-class TestLstsq(LinalgSquareTestCase, LinalgNonsquareTestCase):
+class LstsqCases(LinalgSquareTestCase, LinalgNonsquareTestCase):
def do(self, a, b, tags):
if 'size-0' in tags:
@@ -882,9 +899,11 @@ class TestLstsq(LinalgSquareTestCase, LinalgNonsquareTestCase):
expect_resids = np.array([]).view(type(x))
assert_almost_equal(residuals, expect_resids)
assert_(np.issubdtype(residuals.dtype, np.floating))
- assert_(imply(isinstance(b, matrix), isinstance(x, matrix)))
- assert_(imply(isinstance(b, matrix), isinstance(residuals, matrix)))
+ assert_(consistent_subclass(x, b))
+ assert_(consistent_subclass(residuals, b))
+
+class TestLstsq(LstsqCases):
def test_future_rcond(self):
a = np.array([[0., 1., 0., 1., 2., 0.],
[0., 2., 0., 0., 1., 0.],
@@ -903,6 +922,7 @@ class TestLstsq(LinalgSquareTestCase, LinalgNonsquareTestCase):
# Warning should be raised exactly once (first command)
assert_(len(w) == 1)
+
class TestMatrixPower(object):
R90 = array([[0, 1], [-1, 0]])
Arb22 = array([[4, -7], [-2, 10]])
@@ -966,7 +986,7 @@ class TestBoolPower(object):
assert_equal(matrix_power(A, 2), A)
-class TestEigvalsh(HermitianTestCase, HermitianGeneralizedTestCase):
+class TestEigvalshCases(HermitianTestCase, HermitianGeneralizedTestCase):
def do(self, a, b, tags):
# note that eigenvalue arrays returned by eig must be sorted since
@@ -979,6 +999,8 @@ class TestEigvalsh(HermitianTestCase, HermitianGeneralizedTestCase):
ev2 = linalg.eigvalsh(a, 'U')
assert_allclose(ev2, evalues, rtol=get_rtol(ev.dtype))
+
+class TestEigvalsh(object):
def test_types(self):
def check(dtype):
x = np.array([[1, 0.5], [0.5, 1]], dtype=dtype)
@@ -1034,7 +1056,7 @@ class TestEigvalsh(HermitianTestCase, HermitianGeneralizedTestCase):
assert_(isinstance(res, np.ndarray))
-class TestEigh(HermitianTestCase, HermitianGeneralizedTestCase):
+class TestEighCases(HermitianTestCase, HermitianGeneralizedTestCase):
def do(self, a, b, tags):
# note that eigenvalue arrays returned by eig must be sorted since
@@ -1055,6 +1077,8 @@ class TestEigh(HermitianTestCase, HermitianGeneralizedTestCase):
np.asarray(ev2)[..., None, :] * np.asarray(evc2),
rtol=get_rtol(ev.dtype), err_msg=repr(a))
+
+class TestEigh(object):
def test_types(self):
def check(dtype):
x = np.array([[1, 0.5], [0.5, 1]], dtype=dtype)
@@ -1115,11 +1139,13 @@ class TestEigh(HermitianTestCase, HermitianGeneralizedTestCase):
assert_(isinstance(a, np.ndarray))
-class _TestNorm(object):
-
+class _TestNormBase(object):
dt = None
dec = None
+
+class _TestNormGeneral(_TestNormBase):
+
def test_empty(self):
assert_equal(norm([]), 0.0)
assert_equal(norm(array([], dtype=self.dt)), 0.0)
@@ -1166,57 +1192,6 @@ class _TestNorm(object):
assert_(issubclass(an.dtype.type, np.floating))
assert_almost_equal(an, 1.0)
- def test_matrix_return_type(self):
- a = np.array([[1, 0, 1], [0, 1, 1]])
-
- exact_types = np.typecodes['AllInteger']
-
- # float32, complex64, float64, complex128 types are the only types
- # allowed by `linalg`, which performs the matrix operations used
- # within `norm`.
- inexact_types = 'fdFD'
-
- all_types = exact_types + inexact_types
-
- for each_inexact_types in all_types:
- at = a.astype(each_inexact_types)
-
- an = norm(at, -np.inf)
- assert_(issubclass(an.dtype.type, np.floating))
- assert_almost_equal(an, 2.0)
-
- with suppress_warnings() as sup:
- sup.filter(RuntimeWarning, "divide by zero encountered")
- an = norm(at, -1)
- assert_(issubclass(an.dtype.type, np.floating))
- assert_almost_equal(an, 1.0)
-
- an = norm(at, 1)
- assert_(issubclass(an.dtype.type, np.floating))
- assert_almost_equal(an, 2.0)
-
- an = norm(at, 2)
- assert_(issubclass(an.dtype.type, np.floating))
- assert_almost_equal(an, 3.0**(1.0/2.0))
-
- an = norm(at, -2)
- assert_(issubclass(an.dtype.type, np.floating))
- assert_almost_equal(an, 1.0)
-
- an = norm(at, np.inf)
- assert_(issubclass(an.dtype.type, np.floating))
- assert_almost_equal(an, 2.0)
-
- an = norm(at, 'fro')
- assert_(issubclass(an.dtype.type, np.floating))
- assert_almost_equal(an, 2.0)
-
- an = norm(at, 'nuc')
- assert_(issubclass(an.dtype.type, np.floating))
- # Lower bar needed to support low precision floats.
- # They end up being off by 1 in the 7th place.
- old_assert_almost_equal(an, 2.7320508075688772, decimal=6)
-
def test_vector(self):
a = [1, 2, 3, 4]
b = [-1, -2, -3, -4]
@@ -1247,39 +1222,6 @@ class _TestNorm(object):
array(c, dtype=self.dt)):
_test(v)
- def test_matrix_2x2(self):
- A = matrix([[1, 3], [5, 7]], dtype=self.dt)
- assert_almost_equal(norm(A), 84 ** 0.5)
- assert_almost_equal(norm(A, 'fro'), 84 ** 0.5)
- assert_almost_equal(norm(A, 'nuc'), 10.0)
- assert_almost_equal(norm(A, inf), 12.0)
- assert_almost_equal(norm(A, -inf), 4.0)
- assert_almost_equal(norm(A, 1), 10.0)
- assert_almost_equal(norm(A, -1), 6.0)
- assert_almost_equal(norm(A, 2), 9.1231056256176615)
- assert_almost_equal(norm(A, -2), 0.87689437438234041)
-
- assert_raises(ValueError, norm, A, 'nofro')
- assert_raises(ValueError, norm, A, -3)
- assert_raises(ValueError, norm, A, 0)
-
- def test_matrix_3x3(self):
- # This test has been added because the 2x2 example
- # happened to have equal nuclear norm and induced 1-norm.
- # The 1/10 scaling factor accommodates the absolute tolerance
- # used in assert_almost_equal.
- A = (1 / 10) * \
- np.array([[1, 2, 3], [6, 0, 5], [3, 2, 1]], dtype=self.dt)
- assert_almost_equal(norm(A), (1 / 10) * 89 ** 0.5)
- assert_almost_equal(norm(A, 'fro'), (1 / 10) * 89 ** 0.5)
- assert_almost_equal(norm(A, 'nuc'), 1.3366836911774836)
- assert_almost_equal(norm(A, inf), 1.1)
- assert_almost_equal(norm(A, -inf), 0.6)
- assert_almost_equal(norm(A, 1), 1.0)
- assert_almost_equal(norm(A, -1), 0.4)
- assert_almost_equal(norm(A, 2), 0.88722940323461277)
- assert_almost_equal(norm(A, -2), 0.19456584790481812)
-
def test_axis(self):
# Vector norms.
# Compare the use of `axis` with computing the norm of each row
@@ -1359,10 +1301,103 @@ class _TestNorm(object):
assert_(found.shape == expected_shape,
shape_err.format(found.shape, expected_shape, order, k))
+
+class _TestNorm2D(_TestNormBase):
+ # Define the part for 2d arrays separately, so we can subclass this
+ # and run the tests using np.matrix in matrixlib.tests.test_matrix_linalg.
+ array = np.array
+
+ def test_matrix_empty(self):
+ assert_equal(norm(self.array([[]], dtype=self.dt)), 0.0)
+
+ def test_matrix_return_type(self):
+ a = self.array([[1, 0, 1], [0, 1, 1]])
+
+ exact_types = np.typecodes['AllInteger']
+
+ # float32, complex64, float64, complex128 types are the only types
+ # allowed by `linalg`, which performs the matrix operations used
+ # within `norm`.
+ inexact_types = 'fdFD'
+
+ all_types = exact_types + inexact_types
+
+ for each_inexact_types in all_types:
+ at = a.astype(each_inexact_types)
+
+ an = norm(at, -np.inf)
+ assert_(issubclass(an.dtype.type, np.floating))
+ assert_almost_equal(an, 2.0)
+
+ with suppress_warnings() as sup:
+ sup.filter(RuntimeWarning, "divide by zero encountered")
+ an = norm(at, -1)
+ assert_(issubclass(an.dtype.type, np.floating))
+ assert_almost_equal(an, 1.0)
+
+ an = norm(at, 1)
+ assert_(issubclass(an.dtype.type, np.floating))
+ assert_almost_equal(an, 2.0)
+
+ an = norm(at, 2)
+ assert_(issubclass(an.dtype.type, np.floating))
+ assert_almost_equal(an, 3.0**(1.0/2.0))
+
+ an = norm(at, -2)
+ assert_(issubclass(an.dtype.type, np.floating))
+ assert_almost_equal(an, 1.0)
+
+ an = norm(at, np.inf)
+ assert_(issubclass(an.dtype.type, np.floating))
+ assert_almost_equal(an, 2.0)
+
+ an = norm(at, 'fro')
+ assert_(issubclass(an.dtype.type, np.floating))
+ assert_almost_equal(an, 2.0)
+
+ an = norm(at, 'nuc')
+ assert_(issubclass(an.dtype.type, np.floating))
+ # Lower bar needed to support low precision floats.
+ # They end up being off by 1 in the 7th place.
+ np.testing.assert_almost_equal(an, 2.7320508075688772, decimal=6)
+
+ def test_matrix_2x2(self):
+ A = self.array([[1, 3], [5, 7]], dtype=self.dt)
+ assert_almost_equal(norm(A), 84 ** 0.5)
+ assert_almost_equal(norm(A, 'fro'), 84 ** 0.5)
+ assert_almost_equal(norm(A, 'nuc'), 10.0)
+ assert_almost_equal(norm(A, inf), 12.0)
+ assert_almost_equal(norm(A, -inf), 4.0)
+ assert_almost_equal(norm(A, 1), 10.0)
+ assert_almost_equal(norm(A, -1), 6.0)
+ assert_almost_equal(norm(A, 2), 9.1231056256176615)
+ assert_almost_equal(norm(A, -2), 0.87689437438234041)
+
+ assert_raises(ValueError, norm, A, 'nofro')
+ assert_raises(ValueError, norm, A, -3)
+ assert_raises(ValueError, norm, A, 0)
+
+ def test_matrix_3x3(self):
+ # This test has been added because the 2x2 example
+ # happened to have equal nuclear norm and induced 1-norm.
+ # The 1/10 scaling factor accommodates the absolute tolerance
+ # used in assert_almost_equal.
+ A = (1 / 10) * \
+ self.array([[1, 2, 3], [6, 0, 5], [3, 2, 1]], dtype=self.dt)
+ assert_almost_equal(norm(A), (1 / 10) * 89 ** 0.5)
+ assert_almost_equal(norm(A, 'fro'), (1 / 10) * 89 ** 0.5)
+ assert_almost_equal(norm(A, 'nuc'), 1.3366836911774836)
+ assert_almost_equal(norm(A, inf), 1.1)
+ assert_almost_equal(norm(A, -inf), 0.6)
+ assert_almost_equal(norm(A, 1), 1.0)
+ assert_almost_equal(norm(A, -1), 0.4)
+ assert_almost_equal(norm(A, 2), 0.88722940323461277)
+ assert_almost_equal(norm(A, -2), 0.19456584790481812)
+
def test_bad_args(self):
# Check that bad arguments raise the appropriate exceptions.
- A = array([[1, 2, 3], [4, 5, 6]], dtype=self.dt)
+ A = self.array([[1, 2, 3], [4, 5, 6]], dtype=self.dt)
B = np.arange(1, 25, dtype=self.dt).reshape(2, 3, 4)
# Using `axis=<integer>` or passing in a 1-D array implies vector
@@ -1386,6 +1421,10 @@ class _TestNorm(object):
assert_raises(ValueError, norm, B, None, (0, 1, 2))
+class _TestNorm(_TestNorm2D, _TestNormGeneral):
+ pass
+
+
class TestNorm_NonSystematic(object):
def test_longdouble_norm(self):
@@ -1413,21 +1452,34 @@ class TestNorm_NonSystematic(object):
old_assert_almost_equal(np.linalg.norm(d, ord=3), res, decimal=5)
-class TestNormDouble(_TestNorm):
+# Separate definitions so we can use them for matrix tests.
+class _TestNormDoubleBase(_TestNormBase):
dt = np.double
dec = 12
-class TestNormSingle(_TestNorm):
+class _TestNormSingleBase(_TestNormBase):
dt = np.float32
dec = 6
-class TestNormInt64(_TestNorm):
+class _TestNormInt64Base(_TestNormBase):
dt = np.int64
dec = 12
+class TestNormDouble(_TestNorm, _TestNormDoubleBase):
+ pass
+
+
+class TestNormSingle(_TestNorm, _TestNormSingleBase):
+ pass
+
+
+class TestNormInt64(_TestNorm, _TestNormInt64Base):
+ pass
+
+
class TestMatrixRank(object):
def test_matrix_rank(self):
@@ -1478,6 +1530,8 @@ def test_reduced_rank():
class TestQR(object):
+ # Define the array class here, so run this on matrices elsewhere.
+ array = np.array
def check_qr(self, a):
# This test expects the argument `a` to be an ndarray or
@@ -1528,7 +1582,7 @@ class TestQR(object):
# of the functions in lapack_lite. Consequently, this test is
# very limited in scope. Note that the results are in FORTRAN
# order, hence the h arrays are transposed.
- a = array([[1, 2], [3, 4], [5, 6]], dtype=np.double)
+ a = self.array([[1, 2], [3, 4], [5, 6]], dtype=np.double)
# Test double
h, tau = linalg.qr(a, mode='raw')
@@ -1544,22 +1598,21 @@ class TestQR(object):
assert_(tau.shape == (2,))
def test_mode_all_but_economic(self):
- a = array([[1, 2], [3, 4]])
- b = array([[1, 2], [3, 4], [5, 6]])
+ a = self.array([[1, 2], [3, 4]])
+ b = self.array([[1, 2], [3, 4], [5, 6]])
for dt in "fd":
m1 = a.astype(dt)
m2 = b.astype(dt)
self.check_qr(m1)
self.check_qr(m2)
self.check_qr(m2.T)
- self.check_qr(matrix(m1))
+
for dt in "fd":
m1 = 1 + 1j * a.astype(dt)
m2 = 1 + 1j * b.astype(dt)
self.check_qr(m1)
self.check_qr(m2)
self.check_qr(m2.T)
- self.check_qr(matrix(m1))
def test_0_size(self):
# There may be good ways to do (some of this) reasonably:
diff --git a/numpy/matrixlib/tests/test_matrix_linalg.py b/numpy/matrixlib/tests/test_matrix_linalg.py
new file mode 100644
index 000000000..6fc733c2e
--- /dev/null
+++ b/numpy/matrixlib/tests/test_matrix_linalg.py
@@ -0,0 +1,95 @@
+""" Test functions for linalg module using the matrix class."""
+from __future__ import division, absolute_import, print_function
+
+import numpy as np
+
+from numpy.linalg.tests.test_linalg import (
+ LinalgCase, apply_tag, TestQR as _TestQR, LinalgTestCase,
+ _TestNorm2D, _TestNormDoubleBase, _TestNormSingleBase, _TestNormInt64Base,
+ SolveCases, InvCases, EigvalsCases, EigCases, SVDCases, CondCases,
+ PinvCases, DetCases, LstsqCases)
+
+
+CASES = []
+
+# square test cases
+CASES += apply_tag('square', [
+ LinalgCase("0x0_matrix",
+ np.empty((0, 0), dtype=np.double).view(np.matrix),
+ np.empty((0, 1), dtype=np.double).view(np.matrix),
+ tags={'size-0'}),
+ LinalgCase("matrix_b_only",
+ np.array([[1., 2.], [3., 4.]]),
+ np.matrix([2., 1.]).T),
+ LinalgCase("matrix_a_and_b",
+ np.matrix([[1., 2.], [3., 4.]]),
+ np.matrix([2., 1.]).T),
+])
+
+# hermitian test-cases
+CASES += apply_tag('hermitian', [
+ LinalgCase("hmatrix_a_and_b",
+ np.matrix([[1., 2.], [2., 1.]]),
+ None),
+])
+# No need to make generalized or strided cases for matrices.
+
+
+class MatrixTestCase(LinalgTestCase):
+ TEST_CASES = CASES
+
+
+class TestSolveMatrix(SolveCases, MatrixTestCase):
+ pass
+
+
+class TestInvMatrix(InvCases, MatrixTestCase):
+ pass
+
+
+class TestEigvalsMatrix(EigvalsCases, MatrixTestCase):
+ pass
+
+
+class TestEigMatrix(EigCases, MatrixTestCase):
+ pass
+
+
+class TestSVDMatrix(SVDCases, MatrixTestCase):
+ pass
+
+
+class TestCondMatrix(CondCases, MatrixTestCase):
+ pass
+
+
+class TestPinvMatrix(PinvCases, MatrixTestCase):
+ pass
+
+
+class TestDetMatrix(DetCases, MatrixTestCase):
+ pass
+
+
+class TestLstsqMatrix(LstsqCases, MatrixTestCase):
+ pass
+
+
+class _TestNorm2DMatrix(_TestNorm2D):
+ array = np.matrix
+
+
+class TestNormDoubleMatrix(_TestNorm2DMatrix, _TestNormDoubleBase):
+ pass
+
+
+class TestNormSingleMatrix(_TestNorm2DMatrix, _TestNormSingleBase):
+ pass
+
+
+class TestNormInt64Matrix(_TestNorm2DMatrix, _TestNormInt64Base):
+ pass
+
+
+class TestQRMatrix(_TestQR):
+ array = np.matrix