add padding function to imgScalePadding()

This commit is contained in:
ton
2023-04-14 03:23:43 +00:00
parent c43d949309
commit 39b417dd94
15256 changed files with 525519 additions and 1048290 deletions

View File

@@ -1,339 +0,0 @@
import pytest
import numpy as np
import numpy.testing as npt
import scipy.sparse
import scipy.sparse.linalg as spla
sparray_types = ('bsr', 'coo', 'csc', 'csr', 'dia', 'dok', 'lil')
sparray_classes = [
getattr(scipy.sparse, f'{T}_array') for T in sparray_types
]
A = np.array([
[0, 1, 2, 0],
[2, 0, 0, 3],
[1, 4, 0, 0]
])
B = np.array([
[0, 1],
[2, 0]
])
X = np.array([
[1, 0, 0, 1],
[2, 1, 2, 0],
[0, 2, 1, 0],
[0, 0, 1, 2]
], dtype=float)
sparrays = [sparray(A) for sparray in sparray_classes]
square_sparrays = [sparray(B) for sparray in sparray_classes]
eig_sparrays = [sparray(X) for sparray in sparray_classes]
parametrize_sparrays = pytest.mark.parametrize(
"A", sparrays, ids=sparray_types
)
parametrize_square_sparrays = pytest.mark.parametrize(
"B", square_sparrays, ids=sparray_types
)
parametrize_eig_sparrays = pytest.mark.parametrize(
"X", eig_sparrays, ids=sparray_types
)
@parametrize_sparrays
def test_sum(A):
assert not isinstance(A.sum(axis=0), np.matrix), \
"Expected array, got matrix"
assert A.sum(axis=0).shape == (4,)
assert A.sum(axis=1).shape == (3,)
@parametrize_sparrays
def test_mean(A):
assert not isinstance(A.mean(axis=1), np.matrix), \
"Expected array, got matrix"
@parametrize_sparrays
def test_todense(A):
assert not isinstance(A.todense(), np.matrix), \
"Expected array, got matrix"
@parametrize_sparrays
def test_indexing(A):
if A.__class__.__name__[:3] in ('dia', 'coo', 'bsr'):
return
with pytest.raises(NotImplementedError):
A[1, :]
with pytest.raises(NotImplementedError):
A[:, 1]
with pytest.raises(NotImplementedError):
A[1, [1, 2]]
with pytest.raises(NotImplementedError):
A[[1, 2], 1]
assert A[[0]]._is_array, "Expected sparse array, got sparse matrix"
assert A[1, [[1, 2]]]._is_array, "Expected ndarray, got sparse array"
assert A[[[1, 2]], 1]._is_array, "Expected ndarray, got sparse array"
assert A[:, [1, 2]]._is_array, "Expected sparse array, got something else"
@parametrize_sparrays
def test_dense_addition(A):
X = np.random.random(A.shape)
assert not isinstance(A + X, np.matrix), "Expected array, got matrix"
@parametrize_sparrays
def test_sparse_addition(A):
assert (A + A)._is_array, "Expected array, got matrix"
@parametrize_sparrays
def test_elementwise_mul(A):
assert np.all((A * A).todense() == A.power(2).todense())
@parametrize_sparrays
def test_elementwise_rmul(A):
with pytest.raises(TypeError):
None * A
with pytest.raises(ValueError):
np.eye(3) * scipy.sparse.csr_array(np.arange(6).reshape(2, 3))
assert np.all((2 * A) == (A.todense() * 2))
assert np.all((A.todense() * A) == (A.todense() ** 2))
@parametrize_sparrays
def test_matmul(A):
assert np.all((A @ A.T).todense() == A.dot(A.T).todense())
@parametrize_square_sparrays
def test_pow(B):
assert (B**0)._is_array, "Expected array, got matrix"
assert (B**2)._is_array, "Expected array, got matrix"
@parametrize_sparrays
def test_sparse_divide(A):
assert isinstance(A / A, np.ndarray)
@parametrize_sparrays
def test_dense_divide(A):
assert (A / 2)._is_array, "Expected array, got matrix"
@parametrize_sparrays
def test_no_A_attr(A):
with pytest.warns(np.VisibleDeprecationWarning):
A.A
@parametrize_sparrays
def test_no_H_attr(A):
with pytest.warns(np.VisibleDeprecationWarning):
A.H
@parametrize_sparrays
def test_getrow_getcol(A):
assert A.getcol(0)._is_array
assert A.getrow(0)._is_array
@parametrize_sparrays
def test_docstr(A):
if A.__doc__ is None:
return
docstr = A.__doc__.lower()
for phrase in ('matrix', 'matrices'):
assert phrase not in docstr
# -- linalg --
@parametrize_sparrays
def test_as_linearoperator(A):
L = spla.aslinearoperator(A)
npt.assert_allclose(L * [1, 2, 3, 4], A @ [1, 2, 3, 4])
@parametrize_square_sparrays
def test_inv(B):
if B.__class__.__name__[:3] != 'csc':
return
C = spla.inv(B)
assert C._is_array
npt.assert_allclose(C.todense(), np.linalg.inv(B.todense()))
@parametrize_square_sparrays
def test_expm(B):
if B.__class__.__name__[:3] != 'csc':
return
Bmat = scipy.sparse.csc_matrix(B)
C = spla.expm(B)
assert C._is_array
npt.assert_allclose(
C.todense(),
spla.expm(Bmat).todense()
)
@parametrize_square_sparrays
def test_expm_multiply(B):
if B.__class__.__name__[:3] != 'csc':
return
npt.assert_allclose(
spla.expm_multiply(B, np.array([1, 2])),
spla.expm(B) @ [1, 2]
)
@parametrize_sparrays
def test_norm(A):
C = spla.norm(A)
npt.assert_allclose(C, np.linalg.norm(A.todense()))
@parametrize_square_sparrays
def test_onenormest(B):
C = spla.onenormest(B)
npt.assert_allclose(C, np.linalg.norm(B.todense(), 1))
@parametrize_square_sparrays
def test_spsolve(B):
if B.__class__.__name__[:3] not in ('csc', 'csr'):
return
npt.assert_allclose(
spla.spsolve(B, [1, 2]),
np.linalg.solve(B.todense(), [1, 2])
)
def test_spsolve_triangular():
X = scipy.sparse.csr_array([
[1, 0, 0, 0],
[2, 1, 0, 0],
[3, 2, 1, 0],
[4, 3, 2, 1],
])
spla.spsolve_triangular(X, [1, 2, 3, 4])
@parametrize_square_sparrays
def test_factorized(B):
if B.__class__.__name__[:3] != 'csc':
return
LU = spla.factorized(B)
npt.assert_allclose(
LU(np.array([1, 2])),
np.linalg.solve(B.todense(), [1, 2])
)
@parametrize_square_sparrays
@pytest.mark.parametrize(
"solver",
["bicg", "bicgstab", "cg", "cgs", "gmres", "lgmres", "minres", "qmr",
"gcrotmk", "tfqmr"]
)
def test_solvers(B, solver):
if solver == "minres":
kwargs = {}
else:
kwargs = {'atol': 1e-5}
x, info = getattr(spla, solver)(B, np.array([1, 2]), **kwargs)
assert info >= 0 # no errors, even if perhaps did not converge fully
npt.assert_allclose(x, [1, 1], atol=1e-1)
@parametrize_sparrays
@pytest.mark.parametrize(
"solver",
["lsqr", "lsmr"]
)
def test_lstsqr(A, solver):
x, *_ = getattr(spla, solver)(A, [1, 2, 3])
npt.assert_allclose(A @ x, [1, 2, 3])
@parametrize_eig_sparrays
def test_eigs(X):
e, v = spla.eigs(X, k=1)
npt.assert_allclose(
X @ v,
e[0] * v
)
@parametrize_eig_sparrays
def test_eigsh(X):
X = X + X.T
e, v = spla.eigsh(X, k=1)
npt.assert_allclose(
X @ v,
e[0] * v
)
@parametrize_eig_sparrays
def test_svds(X):
u, s, vh = spla.svds(X, k=3)
u2, s2, vh2 = np.linalg.svd(X.todense())
s = np.sort(s)
s2 = np.sort(s2[:3])
npt.assert_allclose(s, s2, atol=1e-3)
def test_splu():
X = scipy.sparse.csc_array([
[1, 0, 0, 0],
[2, 1, 0, 0],
[3, 2, 1, 0],
[4, 3, 2, 1],
])
LU = spla.splu(X)
npt.assert_allclose(LU.solve(np.array([1, 2, 3, 4])), [1, 0, 0, 0])
def test_spilu():
X = scipy.sparse.csc_array([
[1, 0, 0, 0],
[2, 1, 0, 0],
[3, 2, 1, 0],
[4, 3, 2, 1],
])
LU = spla.spilu(X)
npt.assert_allclose(LU.solve(np.array([1, 2, 3, 4])), [1, 0, 0, 0])
@parametrize_sparrays
def test_power_operator(A):
# https://github.com/scipy/scipy/issues/15948
npt.assert_equal((A**2).todense(), (A.todense())**2)

File diff suppressed because it is too large Load Diff

View File

@@ -1,582 +0,0 @@
"""test sparse matrix construction functions"""
import numpy as np
from numpy import array
from numpy.testing import (assert_equal, assert_,
assert_array_equal, assert_array_almost_equal_nulp)
import pytest
from pytest import raises as assert_raises
from scipy._lib._testutils import check_free_memory
from scipy._lib._util import check_random_state
from scipy.sparse import (csr_matrix, coo_matrix,
_construct as construct)
from scipy.sparse._construct import rand as sprand
from scipy.sparse._sputils import matrix
sparse_formats = ['csr','csc','coo','bsr','dia','lil','dok']
#TODO check whether format=XXX is respected
def _sprandn(m, n, density=0.01, format="coo", dtype=None, random_state=None):
# Helper function for testing.
random_state = check_random_state(random_state)
data_rvs = random_state.standard_normal
return construct.random(m, n, density, format, dtype,
random_state, data_rvs)
class TestConstructUtils:
def test_spdiags(self):
diags1 = array([[1, 2, 3, 4, 5]])
diags2 = array([[1, 2, 3, 4, 5],
[6, 7, 8, 9,10]])
diags3 = array([[1, 2, 3, 4, 5],
[6, 7, 8, 9,10],
[11,12,13,14,15]])
cases = []
cases.append((diags1, 0, 1, 1, [[1]]))
cases.append((diags1, [0], 1, 1, [[1]]))
cases.append((diags1, [0], 2, 1, [[1],[0]]))
cases.append((diags1, [0], 1, 2, [[1,0]]))
cases.append((diags1, [1], 1, 2, [[0,2]]))
cases.append((diags1,[-1], 1, 2, [[0,0]]))
cases.append((diags1, [0], 2, 2, [[1,0],[0,2]]))
cases.append((diags1,[-1], 2, 2, [[0,0],[1,0]]))
cases.append((diags1, [3], 2, 2, [[0,0],[0,0]]))
cases.append((diags1, [0], 3, 4, [[1,0,0,0],[0,2,0,0],[0,0,3,0]]))
cases.append((diags1, [1], 3, 4, [[0,2,0,0],[0,0,3,0],[0,0,0,4]]))
cases.append((diags1, [2], 3, 5, [[0,0,3,0,0],[0,0,0,4,0],[0,0,0,0,5]]))
cases.append((diags2, [0,2], 3, 3, [[1,0,8],[0,2,0],[0,0,3]]))
cases.append((diags2, [-1,0], 3, 4, [[6,0,0,0],[1,7,0,0],[0,2,8,0]]))
cases.append((diags2, [2,-3], 6, 6, [[0,0,3,0,0,0],
[0,0,0,4,0,0],
[0,0,0,0,5,0],
[6,0,0,0,0,0],
[0,7,0,0,0,0],
[0,0,8,0,0,0]]))
cases.append((diags3, [-1,0,1], 6, 6, [[6,12, 0, 0, 0, 0],
[1, 7,13, 0, 0, 0],
[0, 2, 8,14, 0, 0],
[0, 0, 3, 9,15, 0],
[0, 0, 0, 4,10, 0],
[0, 0, 0, 0, 5, 0]]))
cases.append((diags3, [-4,2,-1], 6, 5, [[0, 0, 8, 0, 0],
[11, 0, 0, 9, 0],
[0,12, 0, 0,10],
[0, 0,13, 0, 0],
[1, 0, 0,14, 0],
[0, 2, 0, 0,15]]))
cases.append((diags3, [-1, 1, 2], len(diags3[0]), len(diags3[0]),
[[0, 7, 13, 0, 0],
[1, 0, 8, 14, 0],
[0, 2, 0, 9, 15],
[0, 0, 3, 0, 10],
[0, 0, 0, 4, 0]]))
for d, o, m, n, result in cases:
if len(d[0]) == m and m == n:
assert_equal(construct.spdiags(d, o).toarray(), result)
assert_equal(construct.spdiags(d, o, m, n).toarray(), result)
assert_equal(construct.spdiags(d, o, (m, n)).toarray(), result)
def test_diags(self):
a = array([1, 2, 3, 4, 5])
b = array([6, 7, 8, 9, 10])
c = array([11, 12, 13, 14, 15])
cases = []
cases.append((a[:1], 0, (1, 1), [[1]]))
cases.append(([a[:1]], [0], (1, 1), [[1]]))
cases.append(([a[:1]], [0], (2, 1), [[1],[0]]))
cases.append(([a[:1]], [0], (1, 2), [[1,0]]))
cases.append(([a[:1]], [1], (1, 2), [[0,1]]))
cases.append(([a[:2]], [0], (2, 2), [[1,0],[0,2]]))
cases.append(([a[:1]],[-1], (2, 2), [[0,0],[1,0]]))
cases.append(([a[:3]], [0], (3, 4), [[1,0,0,0],[0,2,0,0],[0,0,3,0]]))
cases.append(([a[:3]], [1], (3, 4), [[0,1,0,0],[0,0,2,0],[0,0,0,3]]))
cases.append(([a[:1]], [-2], (3, 5), [[0,0,0,0,0],[0,0,0,0,0],[1,0,0,0,0]]))
cases.append(([a[:2]], [-1], (3, 5), [[0,0,0,0,0],[1,0,0,0,0],[0,2,0,0,0]]))
cases.append(([a[:3]], [0], (3, 5), [[1,0,0,0,0],[0,2,0,0,0],[0,0,3,0,0]]))
cases.append(([a[:3]], [1], (3, 5), [[0,1,0,0,0],[0,0,2,0,0],[0,0,0,3,0]]))
cases.append(([a[:3]], [2], (3, 5), [[0,0,1,0,0],[0,0,0,2,0],[0,0,0,0,3]]))
cases.append(([a[:2]], [3], (3, 5), [[0,0,0,1,0],[0,0,0,0,2],[0,0,0,0,0]]))
cases.append(([a[:1]], [4], (3, 5), [[0,0,0,0,1],[0,0,0,0,0],[0,0,0,0,0]]))
cases.append(([a[:1]], [-4], (5, 3), [[0,0,0],[0,0,0],[0,0,0],[0,0,0],[1,0,0]]))
cases.append(([a[:2]], [-3], (5, 3), [[0,0,0],[0,0,0],[0,0,0],[1,0,0],[0,2,0]]))
cases.append(([a[:3]], [-2], (5, 3), [[0,0,0],[0,0,0],[1,0,0],[0,2,0],[0,0,3]]))
cases.append(([a[:3]], [-1], (5, 3), [[0,0,0],[1,0,0],[0,2,0],[0,0,3],[0,0,0]]))
cases.append(([a[:3]], [0], (5, 3), [[1,0,0],[0,2,0],[0,0,3],[0,0,0],[0,0,0]]))
cases.append(([a[:2]], [1], (5, 3), [[0,1,0],[0,0,2],[0,0,0],[0,0,0],[0,0,0]]))
cases.append(([a[:1]], [2], (5, 3), [[0,0,1],[0,0,0],[0,0,0],[0,0,0],[0,0,0]]))
cases.append(([a[:3],b[:1]], [0,2], (3, 3), [[1,0,6],[0,2,0],[0,0,3]]))
cases.append(([a[:2],b[:3]], [-1,0], (3, 4), [[6,0,0,0],[1,7,0,0],[0,2,8,0]]))
cases.append(([a[:4],b[:3]], [2,-3], (6, 6), [[0,0,1,0,0,0],
[0,0,0,2,0,0],
[0,0,0,0,3,0],
[6,0,0,0,0,4],
[0,7,0,0,0,0],
[0,0,8,0,0,0]]))
cases.append(([a[:4],b,c[:4]], [-1,0,1], (5, 5), [[6,11, 0, 0, 0],
[1, 7,12, 0, 0],
[0, 2, 8,13, 0],
[0, 0, 3, 9,14],
[0, 0, 0, 4,10]]))
cases.append(([a[:2],b[:3],c], [-4,2,-1], (6, 5), [[0, 0, 6, 0, 0],
[11, 0, 0, 7, 0],
[0,12, 0, 0, 8],
[0, 0,13, 0, 0],
[1, 0, 0,14, 0],
[0, 2, 0, 0,15]]))
# too long arrays are OK
cases.append(([a], [0], (1, 1), [[1]]))
cases.append(([a[:3],b], [0,2], (3, 3), [[1, 0, 6], [0, 2, 0], [0, 0, 3]]))
cases.append((np.array([[1, 2, 3], [4, 5, 6]]), [0,-1], (3, 3), [[1, 0, 0], [4, 2, 0], [0, 5, 3]]))
# scalar case: broadcasting
cases.append(([1,-2,1], [1,0,-1], (3, 3), [[-2, 1, 0],
[1, -2, 1],
[0, 1, -2]]))
for d, o, shape, result in cases:
err_msg = "%r %r %r %r" % (d, o, shape, result)
assert_equal(construct.diags(d, o, shape=shape).toarray(),
result, err_msg=err_msg)
if shape[0] == shape[1] and hasattr(d[0], '__len__') and len(d[0]) <= max(shape):
# should be able to find the shape automatically
assert_equal(construct.diags(d, o).toarray(), result,
err_msg=err_msg)
def test_diags_default(self):
a = array([1, 2, 3, 4, 5])
assert_equal(construct.diags(a).toarray(), np.diag(a))
def test_diags_default_bad(self):
a = array([[1, 2, 3, 4, 5], [2, 3, 4, 5, 6]])
assert_raises(ValueError, construct.diags, a)
def test_diags_bad(self):
a = array([1, 2, 3, 4, 5])
b = array([6, 7, 8, 9, 10])
c = array([11, 12, 13, 14, 15])
cases = []
cases.append(([a[:0]], 0, (1, 1)))
cases.append(([a[:4],b,c[:3]], [-1,0,1], (5, 5)))
cases.append(([a[:2],c,b[:3]], [-4,2,-1], (6, 5)))
cases.append(([a[:2],c,b[:3]], [-4,2,-1], None))
cases.append(([], [-4,2,-1], None))
cases.append(([1], [-5], (4, 4)))
cases.append(([a], 0, None))
for d, o, shape in cases:
assert_raises(ValueError, construct.diags, d, o, shape)
assert_raises(TypeError, construct.diags, [[None]], [0])
def test_diags_vs_diag(self):
# Check that
#
# diags([a, b, ...], [i, j, ...]) == diag(a, i) + diag(b, j) + ...
#
np.random.seed(1234)
for n_diags in [1, 2, 3, 4, 5, 10]:
n = 1 + n_diags//2 + np.random.randint(0, 10)
offsets = np.arange(-n+1, n-1)
np.random.shuffle(offsets)
offsets = offsets[:n_diags]
diagonals = [np.random.rand(n - abs(q)) for q in offsets]
mat = construct.diags(diagonals, offsets)
dense_mat = sum([np.diag(x, j) for x, j in zip(diagonals, offsets)])
assert_array_almost_equal_nulp(mat.toarray(), dense_mat)
if len(offsets) == 1:
mat = construct.diags(diagonals[0], offsets[0])
dense_mat = np.diag(diagonals[0], offsets[0])
assert_array_almost_equal_nulp(mat.toarray(), dense_mat)
def test_diags_dtype(self):
x = construct.diags([2.2], [0], shape=(2, 2), dtype=int)
assert_equal(x.dtype, int)
assert_equal(x.toarray(), [[2, 0], [0, 2]])
def test_diags_one_diagonal(self):
d = list(range(5))
for k in range(-5, 6):
assert_equal(construct.diags(d, k).toarray(),
construct.diags([d], [k]).toarray())
def test_diags_empty(self):
x = construct.diags([])
assert_equal(x.shape, (0, 0))
def test_identity(self):
assert_equal(construct.identity(1).toarray(), [[1]])
assert_equal(construct.identity(2).toarray(), [[1,0],[0,1]])
I = construct.identity(3, dtype='int8', format='dia')
assert_equal(I.dtype, np.dtype('int8'))
assert_equal(I.format, 'dia')
for fmt in sparse_formats:
I = construct.identity(3, format=fmt)
assert_equal(I.format, fmt)
assert_equal(I.toarray(), [[1,0,0],[0,1,0],[0,0,1]])
def test_eye(self):
assert_equal(construct.eye(1,1).toarray(), [[1]])
assert_equal(construct.eye(2,3).toarray(), [[1,0,0],[0,1,0]])
assert_equal(construct.eye(3,2).toarray(), [[1,0],[0,1],[0,0]])
assert_equal(construct.eye(3,3).toarray(), [[1,0,0],[0,1,0],[0,0,1]])
assert_equal(construct.eye(3,3,dtype='int16').dtype, np.dtype('int16'))
for m in [3, 5]:
for n in [3, 5]:
for k in range(-5,6):
assert_equal(construct.eye(m, n, k=k).toarray(), np.eye(m, n, k=k))
if m == n:
assert_equal(construct.eye(m, k=k).toarray(), np.eye(m, n, k=k))
def test_eye_one(self):
assert_equal(construct.eye(1).toarray(), [[1]])
assert_equal(construct.eye(2).toarray(), [[1,0],[0,1]])
I = construct.eye(3, dtype='int8', format='dia')
assert_equal(I.dtype, np.dtype('int8'))
assert_equal(I.format, 'dia')
for fmt in sparse_formats:
I = construct.eye(3, format=fmt)
assert_equal(I.format, fmt)
assert_equal(I.toarray(), [[1,0,0],[0,1,0],[0,0,1]])
def test_kron(self):
cases = []
cases.append(array([[0]]))
cases.append(array([[-1]]))
cases.append(array([[4]]))
cases.append(array([[10]]))
cases.append(array([[0],[0]]))
cases.append(array([[0,0]]))
cases.append(array([[1,2],[3,4]]))
cases.append(array([[0,2],[5,0]]))
cases.append(array([[0,2,-6],[8,0,14]]))
cases.append(array([[5,4],[0,0],[6,0]]))
cases.append(array([[5,4,4],[1,0,0],[6,0,8]]))
cases.append(array([[0,1,0,2,0,5,8]]))
cases.append(array([[0.5,0.125,0,3.25],[0,2.5,0,0]]))
for a in cases:
for b in cases:
expected = np.kron(a, b)
for fmt in sparse_formats:
result = construct.kron(csr_matrix(a), csr_matrix(b), format=fmt)
assert_equal(result.format, fmt)
assert_array_equal(result.toarray(), expected)
def test_kron_large(self):
n = 2**16
a = construct.eye(1, n, n-1)
b = construct.eye(n, 1, 1-n)
construct.kron(a, a)
construct.kron(b, b)
def test_kronsum(self):
cases = []
cases.append(array([[0]]))
cases.append(array([[-1]]))
cases.append(array([[4]]))
cases.append(array([[10]]))
cases.append(array([[1,2],[3,4]]))
cases.append(array([[0,2],[5,0]]))
cases.append(array([[0,2,-6],[8,0,14],[0,3,0]]))
cases.append(array([[1,0,0],[0,5,-1],[4,-2,8]]))
for a in cases:
for b in cases:
result = construct.kronsum(
csr_matrix(a), csr_matrix(b)).toarray()
expected = np.kron(np.eye(len(b)), a) + \
np.kron(b, np.eye(len(a)))
assert_array_equal(result,expected)
def test_vstack(self):
A = coo_matrix([[1,2],[3,4]])
B = coo_matrix([[5,6]])
expected = array([[1, 2],
[3, 4],
[5, 6]])
assert_equal(construct.vstack([A, B]).toarray(), expected)
assert_equal(construct.vstack([A, B], dtype=np.float32).dtype,
np.float32)
assert_equal(construct.vstack([A.tocsr(), B.tocsr()]).toarray(),
expected)
result = construct.vstack([A.tocsr(), B.tocsr()], dtype=np.float32)
assert_equal(result.dtype, np.float32)
assert_equal(result.indices.dtype, np.int32)
assert_equal(result.indptr.dtype, np.int32)
assert_equal(construct.vstack([A.tocsc(), B.tocsc()]).toarray(),
expected)
result = construct.vstack([A.tocsc(), B.tocsc()], dtype=np.float32)
assert_equal(result.dtype, np.float32)
assert_equal(result.indices.dtype, np.int32)
assert_equal(result.indptr.dtype, np.int32)
def test_hstack(self):
A = coo_matrix([[1,2],[3,4]])
B = coo_matrix([[5],[6]])
expected = array([[1, 2, 5],
[3, 4, 6]])
assert_equal(construct.hstack([A, B]).toarray(), expected)
assert_equal(construct.hstack([A, B], dtype=np.float32).dtype,
np.float32)
assert_equal(construct.hstack([A.tocsc(), B.tocsc()]).toarray(),
expected)
assert_equal(construct.hstack([A.tocsc(), B.tocsc()],
dtype=np.float32).dtype,
np.float32)
assert_equal(construct.hstack([A.tocsr(), B.tocsr()]).toarray(),
expected)
assert_equal(construct.hstack([A.tocsr(), B.tocsr()],
dtype=np.float32).dtype,
np.float32)
def test_bmat(self):
A = coo_matrix([[1, 2], [3, 4]])
B = coo_matrix([[5],[6]])
C = coo_matrix([[7]])
D = coo_matrix((0, 0))
expected = array([[1, 2, 5],
[3, 4, 6],
[0, 0, 7]])
assert_equal(construct.bmat([[A, B], [None, C]]).toarray(), expected)
E = csr_matrix((1, 2), dtype=np.int32)
assert_equal(construct.bmat([[A.tocsr(), B.tocsr()],
[E, C.tocsr()]]).toarray(),
expected)
assert_equal(construct.bmat([[A.tocsc(), B.tocsc()],
[E.tocsc(), C.tocsc()]]).toarray(),
expected)
expected = array([[1, 2, 0],
[3, 4, 0],
[0, 0, 7]])
assert_equal(construct.bmat([[A, None], [None, C]]).toarray(),
expected)
assert_equal(construct.bmat([[A.tocsr(), E.T.tocsr()],
[E, C.tocsr()]]).toarray(),
expected)
assert_equal(construct.bmat([[A.tocsc(), E.T.tocsc()],
[E.tocsc(), C.tocsc()]]).toarray(),
expected)
Z = csr_matrix((1, 1), dtype=np.int32)
expected = array([[0, 5],
[0, 6],
[7, 0]])
assert_equal(construct.bmat([[None, B], [C, None]]).toarray(),
expected)
assert_equal(construct.bmat([[E.T.tocsr(), B.tocsr()],
[C.tocsr(), Z]]).toarray(),
expected)
assert_equal(construct.bmat([[E.T.tocsc(), B.tocsc()],
[C.tocsc(), Z.tocsc()]]).toarray(),
expected)
expected = matrix(np.empty((0, 0)))
assert_equal(construct.bmat([[None, None]]).toarray(), expected)
assert_equal(construct.bmat([[None, D], [D, None]]).toarray(),
expected)
# test bug reported in gh-5976
expected = array([[7]])
assert_equal(construct.bmat([[None, D], [C, None]]).toarray(),
expected)
# test failure cases
with assert_raises(ValueError) as excinfo:
construct.bmat([[A], [B]])
excinfo.match(r'Got blocks\[1,0\]\.shape\[1\] == 1, expected 2')
with assert_raises(ValueError) as excinfo:
construct.bmat([[A.tocsr()], [B.tocsr()]])
excinfo.match(r'incompatible dimensions for axis 1')
with assert_raises(ValueError) as excinfo:
construct.bmat([[A.tocsc()], [B.tocsc()]])
excinfo.match(r'Mismatching dimensions along axis 1: ({1, 2}|{2, 1})')
with assert_raises(ValueError) as excinfo:
construct.bmat([[A, C]])
excinfo.match(r'Got blocks\[0,1\]\.shape\[0\] == 1, expected 2')
with assert_raises(ValueError) as excinfo:
construct.bmat([[A.tocsr(), C.tocsr()]])
excinfo.match(r'Mismatching dimensions along axis 0: ({1, 2}|{2, 1})')
with assert_raises(ValueError) as excinfo:
construct.bmat([[A.tocsc(), C.tocsc()]])
excinfo.match(r'incompatible dimensions for axis 0')
@pytest.mark.slow
@pytest.mark.xfail_on_32bit("Can't create large array for test")
def test_concatenate_int32_overflow(self):
""" test for indptr overflow when concatenating matrices """
check_free_memory(30000)
n = 33000
A = csr_matrix(np.ones((n, n), dtype=bool))
B = A.copy()
C = construct._compressed_sparse_stack((A,B), 0)
assert_(np.all(np.equal(np.diff(C.indptr), n)))
assert_equal(C.indices.dtype, np.int64)
assert_equal(C.indptr.dtype, np.int64)
def test_block_diag_basic(self):
""" basic test for block_diag """
A = coo_matrix([[1,2],[3,4]])
B = coo_matrix([[5],[6]])
C = coo_matrix([[7]])
expected = array([[1, 2, 0, 0],
[3, 4, 0, 0],
[0, 0, 5, 0],
[0, 0, 6, 0],
[0, 0, 0, 7]])
assert_equal(construct.block_diag((A, B, C)).toarray(), expected)
def test_block_diag_scalar_1d_args(self):
""" block_diag with scalar and 1d arguments """
# one 1d matrix and a scalar
assert_array_equal(construct.block_diag([[2,3], 4]).toarray(),
[[2, 3, 0], [0, 0, 4]])
def test_block_diag_1(self):
""" block_diag with one matrix """
assert_equal(construct.block_diag([[1, 0]]).toarray(),
array([[1, 0]]))
assert_equal(construct.block_diag([[[1, 0]]]).toarray(),
array([[1, 0]]))
assert_equal(construct.block_diag([[[1], [0]]]).toarray(),
array([[1], [0]]))
# just on scalar
assert_equal(construct.block_diag([1]).toarray(),
array([[1]]))
def test_block_diag_sparse_matrices(self):
""" block_diag with sparse matrices """
sparse_col_matrices = [coo_matrix(([[1, 2, 3]]), shape=(1, 3)),
coo_matrix(([[4, 5]]), shape=(1, 2))]
block_sparse_cols_matrices = construct.block_diag(sparse_col_matrices)
assert_equal(block_sparse_cols_matrices.toarray(),
array([[1, 2, 3, 0, 0], [0, 0, 0, 4, 5]]))
sparse_row_matrices = [coo_matrix(([[1], [2], [3]]), shape=(3, 1)),
coo_matrix(([[4], [5]]), shape=(2, 1))]
block_sparse_row_matrices = construct.block_diag(sparse_row_matrices)
assert_equal(block_sparse_row_matrices.toarray(),
array([[1, 0], [2, 0], [3, 0], [0, 4], [0, 5]]))
def test_random_sampling(self):
# Simple sanity checks for sparse random sampling.
for f in sprand, _sprandn:
for t in [np.float32, np.float64, np.longdouble,
np.int32, np.int64, np.complex64, np.complex128]:
x = f(5, 10, density=0.1, dtype=t)
assert_equal(x.dtype, t)
assert_equal(x.shape, (5, 10))
assert_equal(x.nnz, 5)
x1 = f(5, 10, density=0.1, random_state=4321)
assert_equal(x1.dtype, np.double)
x2 = f(5, 10, density=0.1,
random_state=np.random.RandomState(4321))
assert_array_equal(x1.data, x2.data)
assert_array_equal(x1.row, x2.row)
assert_array_equal(x1.col, x2.col)
for density in [0.0, 0.1, 0.5, 1.0]:
x = f(5, 10, density=density)
assert_equal(x.nnz, int(density * np.prod(x.shape)))
for fmt in ['coo', 'csc', 'csr', 'lil']:
x = f(5, 10, format=fmt)
assert_equal(x.format, fmt)
assert_raises(ValueError, lambda: f(5, 10, 1.1))
assert_raises(ValueError, lambda: f(5, 10, -0.1))
def test_rand(self):
# Simple distributional checks for sparse.rand.
random_states = [None, 4321, np.random.RandomState()]
try:
gen = np.random.default_rng()
random_states.append(gen)
except AttributeError:
pass
for random_state in random_states:
x = sprand(10, 20, density=0.5, dtype=np.float64,
random_state=random_state)
assert_(np.all(np.less_equal(0, x.data)))
assert_(np.all(np.less_equal(x.data, 1)))
def test_randn(self):
# Simple distributional checks for sparse.randn.
# Statistically, some of these should be negative
# and some should be greater than 1.
random_states = [None, 4321, np.random.RandomState()]
try:
gen = np.random.default_rng()
random_states.append(gen)
except AttributeError:
pass
for random_state in random_states:
x = _sprandn(10, 20, density=0.5, dtype=np.float64,
random_state=random_state)
assert_(np.any(np.less(x.data, 0)))
assert_(np.any(np.less(1, x.data)))
def test_random_accept_str_dtype(self):
# anything that np.dtype can convert to a dtype should be accepted
# for the dtype
construct.random(10, 10, dtype='d')
def test_random_sparse_matrix_returns_correct_number_of_non_zero_elements(self):
# A 10 x 10 matrix, with density of 12.65%, should have 13 nonzero elements.
# 10 x 10 x 0.1265 = 12.65, which should be rounded up to 13, not 12.
sparse_matrix = construct.random(10, 10, density=0.1265)
assert_equal(sparse_matrix.count_nonzero(),13)

View File

@@ -1,98 +0,0 @@
import numpy as np
from numpy.testing import assert_array_almost_equal, assert_
from scipy.sparse import csr_matrix, csc_matrix, lil_matrix
import pytest
def test_csc_getrow():
N = 10
np.random.seed(0)
X = np.random.random((N, N))
X[X > 0.7] = 0
Xcsc = csc_matrix(X)
for i in range(N):
arr_row = X[i:i + 1, :]
csc_row = Xcsc.getrow(i)
assert_array_almost_equal(arr_row, csc_row.toarray())
assert_(type(csc_row) is csr_matrix)
def test_csc_getcol():
N = 10
np.random.seed(0)
X = np.random.random((N, N))
X[X > 0.7] = 0
Xcsc = csc_matrix(X)
for i in range(N):
arr_col = X[:, i:i + 1]
csc_col = Xcsc.getcol(i)
assert_array_almost_equal(arr_col, csc_col.toarray())
assert_(type(csc_col) is csc_matrix)
@pytest.mark.parametrize("matrix_input, axis, expected_shape",
[(csc_matrix([[1, 0],
[0, 0],
[0, 2]]),
0, (0, 2)),
(csc_matrix([[1, 0],
[0, 0],
[0, 2]]),
1, (3, 0)),
(csc_matrix([[1, 0],
[0, 0],
[0, 2]]),
'both', (0, 0)),
(csc_matrix([[0, 1, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0],
[0, 0, 2, 3, 0, 1]]),
0, (0, 6))])
def test_csc_empty_slices(matrix_input, axis, expected_shape):
# see gh-11127 for related discussion
slice_1 = matrix_input.A.shape[0] - 1
slice_2 = slice_1
slice_3 = slice_2 - 1
if axis == 0:
actual_shape_1 = matrix_input[slice_1:slice_2, :].A.shape
actual_shape_2 = matrix_input[slice_1:slice_3, :].A.shape
elif axis == 1:
actual_shape_1 = matrix_input[:, slice_1:slice_2].A.shape
actual_shape_2 = matrix_input[:, slice_1:slice_3].A.shape
elif axis == 'both':
actual_shape_1 = matrix_input[slice_1:slice_2, slice_1:slice_2].A.shape
actual_shape_2 = matrix_input[slice_1:slice_3, slice_1:slice_3].A.shape
assert actual_shape_1 == expected_shape
assert actual_shape_1 == actual_shape_2
@pytest.mark.parametrize('ax', (-2, -1, 0, 1, None))
def test_argmax_overflow(ax):
# See gh-13646: Windows integer overflow for large sparse matrices.
dim = (100000, 100000)
A = lil_matrix(dim)
A[-2, -2] = 42
A[-3, -3] = 0.1234
A = csc_matrix(A)
idx = A.argmax(axis=ax)
if ax is None:
# idx is a single flattened index
# that we need to convert to a 2d index pair;
# can't do this with np.unravel_index because
# the dimensions are too large
ii = idx % dim[0]
jj = idx // dim[0]
else:
# idx is an array of size of A.shape[ax];
# check the max index to make sure no overflows
# we encountered
assert np.count_nonzero(idx) == A.nnz
ii, jj = np.max(idx), np.argmax(idx)
assert A[ii, jj] == A[-2, -2]

View File

@@ -1,169 +0,0 @@
import numpy as np
from numpy.testing import assert_array_almost_equal, assert_
from scipy.sparse import csr_matrix, hstack
import pytest
def _check_csr_rowslice(i, sl, X, Xcsr):
np_slice = X[i, sl]
csr_slice = Xcsr[i, sl]
assert_array_almost_equal(np_slice, csr_slice.toarray()[0])
assert_(type(csr_slice) is csr_matrix)
def test_csr_rowslice():
N = 10
np.random.seed(0)
X = np.random.random((N, N))
X[X > 0.7] = 0
Xcsr = csr_matrix(X)
slices = [slice(None, None, None),
slice(None, None, -1),
slice(1, -2, 2),
slice(-2, 1, -2)]
for i in range(N):
for sl in slices:
_check_csr_rowslice(i, sl, X, Xcsr)
def test_csr_getrow():
N = 10
np.random.seed(0)
X = np.random.random((N, N))
X[X > 0.7] = 0
Xcsr = csr_matrix(X)
for i in range(N):
arr_row = X[i:i + 1, :]
csr_row = Xcsr.getrow(i)
assert_array_almost_equal(arr_row, csr_row.toarray())
assert_(type(csr_row) is csr_matrix)
def test_csr_getcol():
N = 10
np.random.seed(0)
X = np.random.random((N, N))
X[X > 0.7] = 0
Xcsr = csr_matrix(X)
for i in range(N):
arr_col = X[:, i:i + 1]
csr_col = Xcsr.getcol(i)
assert_array_almost_equal(arr_col, csr_col.toarray())
assert_(type(csr_col) is csr_matrix)
@pytest.mark.parametrize("matrix_input, axis, expected_shape",
[(csr_matrix([[1, 0, 0, 0],
[0, 0, 0, 0],
[0, 2, 3, 0]]),
0, (0, 4)),
(csr_matrix([[1, 0, 0, 0],
[0, 0, 0, 0],
[0, 2, 3, 0]]),
1, (3, 0)),
(csr_matrix([[1, 0, 0, 0],
[0, 0, 0, 0],
[0, 2, 3, 0]]),
'both', (0, 0)),
(csr_matrix([[0, 1, 0, 0, 0],
[0, 0, 0, 0, 0],
[0, 0, 2, 3, 0]]),
0, (0, 5))])
def test_csr_empty_slices(matrix_input, axis, expected_shape):
# see gh-11127 for related discussion
slice_1 = matrix_input.A.shape[0] - 1
slice_2 = slice_1
slice_3 = slice_2 - 1
if axis == 0:
actual_shape_1 = matrix_input[slice_1:slice_2, :].A.shape
actual_shape_2 = matrix_input[slice_1:slice_3, :].A.shape
elif axis == 1:
actual_shape_1 = matrix_input[:, slice_1:slice_2].A.shape
actual_shape_2 = matrix_input[:, slice_1:slice_3].A.shape
elif axis == 'both':
actual_shape_1 = matrix_input[slice_1:slice_2, slice_1:slice_2].A.shape
actual_shape_2 = matrix_input[slice_1:slice_3, slice_1:slice_3].A.shape
assert actual_shape_1 == expected_shape
assert actual_shape_1 == actual_shape_2
def test_csr_bool_indexing():
data = csr_matrix([[0, 1, 2], [3, 4, 5], [6, 7, 8]])
list_indices1 = [False, True, False]
array_indices1 = np.array(list_indices1)
list_indices2 = [[False, True, False], [False, True, False], [False, True, False]]
array_indices2 = np.array(list_indices2)
list_indices3 = ([False, True, False], [False, True, False])
array_indices3 = (np.array(list_indices3[0]), np.array(list_indices3[1]))
slice_list1 = data[list_indices1].toarray()
slice_array1 = data[array_indices1].toarray()
slice_list2 = data[list_indices2]
slice_array2 = data[array_indices2]
slice_list3 = data[list_indices3]
slice_array3 = data[array_indices3]
assert (slice_list1 == slice_array1).all()
assert (slice_list2 == slice_array2).all()
assert (slice_list3 == slice_array3).all()
def test_csr_hstack_int64():
"""
Tests if hstack properly promotes to indices and indptr arrays to np.int64
when using np.int32 during concatenation would result in either array
overflowing.
"""
max_int32 = np.iinfo(np.int32).max
# First case: indices would overflow with int32
data = [1.0]
row = [0]
max_indices_1 = max_int32 - 1
max_indices_2 = 3
# Individual indices arrays are representable with int32
col_1 = [max_indices_1 - 1]
col_2 = [max_indices_2 - 1]
X_1 = csr_matrix((data, (row, col_1)))
X_2 = csr_matrix((data, (row, col_2)))
assert max(max_indices_1 - 1, max_indices_2 - 1) < max_int32
assert X_1.indices.dtype == X_1.indptr.dtype == np.int32
assert X_2.indices.dtype == X_2.indptr.dtype == np.int32
# ... but when concatenating their CSR matrices, the resulting indices
# array can't be represented with int32 and must be promoted to int64.
X_hs = hstack([X_1, X_2], format="csr")
assert X_hs.indices.max() == max_indices_1 + max_indices_2 - 1
assert max_indices_1 + max_indices_2 - 1 > max_int32
assert X_hs.indices.dtype == X_hs.indptr.dtype == np.int64
# Even if the matrices are empty, we must account for their size
# contribution so that we may safely set the final elements.
X_1_empty = csr_matrix(X_1.shape)
X_2_empty = csr_matrix(X_2.shape)
X_hs_empty = hstack([X_1_empty, X_2_empty], format="csr")
assert X_hs_empty.shape == X_hs.shape
assert X_hs_empty.indices.dtype == np.int64
# Should be just small enough to stay in int32 after stack. Note that
# we theoretically could support indices.max() == max_int32, but due to an
# edge-case in the underlying sparsetools code
# (namely the `coo_tocsr` routine),
# we require that max(X_hs_32.shape) < max_int32 as well.
# Hence we can only support max_int32 - 1.
col_3 = [max_int32 - max_indices_1 - 1]
X_3 = csr_matrix((data, (row, col_3)))
X_hs_32 = hstack([X_1, X_3], format="csr")
assert X_hs_32.indices.dtype == np.int32
assert X_hs_32.indices.max() == max_int32 - 1

View File

@@ -1,42 +0,0 @@
"""test sparse matrix construction functions"""
from numpy.testing import assert_equal
from scipy.sparse import csr_matrix
import numpy as np
from scipy.sparse import _extract
class TestExtract:
def setup_method(self):
self.cases = [
csr_matrix([[1,2]]),
csr_matrix([[1,0]]),
csr_matrix([[0,0]]),
csr_matrix([[1],[2]]),
csr_matrix([[1],[0]]),
csr_matrix([[0],[0]]),
csr_matrix([[1,2],[3,4]]),
csr_matrix([[0,1],[0,0]]),
csr_matrix([[0,0],[1,0]]),
csr_matrix([[0,0],[0,0]]),
csr_matrix([[1,2,0,0,3],[4,5,0,6,7],[0,0,8,9,0]]),
csr_matrix([[1,2,0,0,3],[4,5,0,6,7],[0,0,8,9,0]]).T,
]
def find(self):
for A in self.cases:
I,J,V = _extract.find(A)
assert_equal(A.toarray(), csr_matrix(((I,J),V), shape=A.shape))
def test_tril(self):
for A in self.cases:
B = A.toarray()
for k in [-3,-2,-1,0,1,2,3]:
assert_equal(_extract.tril(A,k=k).toarray(), np.tril(B,k=k))
def test_triu(self):
for A in self.cases:
B = A.toarray()
for k in [-3,-2,-1,0,1,2,3]:
assert_equal(_extract.triu(A,k=k).toarray(), np.triu(B,k=k))

View File

@@ -1,86 +0,0 @@
import os
import numpy as np
import tempfile
from pytest import raises as assert_raises
from numpy.testing import assert_equal, assert_
from scipy.sparse import (csc_matrix, csr_matrix, bsr_matrix, dia_matrix,
coo_matrix, save_npz, load_npz, dok_matrix)
DATA_DIR = os.path.join(os.path.dirname(__file__), 'data')
def _save_and_load(matrix):
fd, tmpfile = tempfile.mkstemp(suffix='.npz')
os.close(fd)
try:
save_npz(tmpfile, matrix)
loaded_matrix = load_npz(tmpfile)
finally:
os.remove(tmpfile)
return loaded_matrix
def _check_save_and_load(dense_matrix):
for matrix_class in [csc_matrix, csr_matrix, bsr_matrix, dia_matrix, coo_matrix]:
matrix = matrix_class(dense_matrix)
loaded_matrix = _save_and_load(matrix)
assert_(type(loaded_matrix) is matrix_class)
assert_(loaded_matrix.shape == dense_matrix.shape)
assert_(loaded_matrix.dtype == dense_matrix.dtype)
assert_equal(loaded_matrix.toarray(), dense_matrix)
def test_save_and_load_random():
N = 10
np.random.seed(0)
dense_matrix = np.random.random((N, N))
dense_matrix[dense_matrix > 0.7] = 0
_check_save_and_load(dense_matrix)
def test_save_and_load_empty():
dense_matrix = np.zeros((4,6))
_check_save_and_load(dense_matrix)
def test_save_and_load_one_entry():
dense_matrix = np.zeros((4,6))
dense_matrix[1,2] = 1
_check_save_and_load(dense_matrix)
def test_malicious_load():
class Executor:
def __reduce__(self):
return (assert_, (False, 'unexpected code execution'))
fd, tmpfile = tempfile.mkstemp(suffix='.npz')
os.close(fd)
try:
np.savez(tmpfile, format=Executor())
# Should raise a ValueError, not execute code
assert_raises(ValueError, load_npz, tmpfile)
finally:
os.remove(tmpfile)
def test_py23_compatibility():
# Try loading files saved on Python 2 and Python 3. They are not
# the same, since files saved with SciPy versions < 1.0.0 may
# contain unicode.
a = load_npz(os.path.join(DATA_DIR, 'csc_py2.npz'))
b = load_npz(os.path.join(DATA_DIR, 'csc_py3.npz'))
c = csc_matrix([[0]])
assert_equal(a.toarray(), c.toarray())
assert_equal(b.toarray(), c.toarray())
def test_implemented_error():
# Attempts to save an unsupported type and checks that an
# NotImplementedError is raised.
x = dok_matrix((2,3))
x[0,1] = 1
assert_raises(NotImplementedError, save_npz, 'x.npz', x)

View File

@@ -1,337 +0,0 @@
import sys
import os
import gc
import threading
import numpy as np
from numpy.testing import assert_equal, assert_, assert_allclose
from scipy.sparse import (_sparsetools, coo_matrix, csr_matrix, csc_matrix,
bsr_matrix, dia_matrix)
from scipy.sparse._sputils import supported_dtypes
from scipy._lib._testutils import check_free_memory
import pytest
from pytest import raises as assert_raises
def int_to_int8(n):
"""
Wrap an integer to the interval [-128, 127].
"""
return (n + 128) % 256 - 128
def test_exception():
assert_raises(MemoryError, _sparsetools.test_throw_error)
def test_threads():
# Smoke test for parallel threaded execution; doesn't actually
# check that code runs in parallel, but just that it produces
# expected results.
nthreads = 10
niter = 100
n = 20
a = csr_matrix(np.ones([n, n]))
bres = []
class Worker(threading.Thread):
def run(self):
b = a.copy()
for j in range(niter):
_sparsetools.csr_plus_csr(n, n,
a.indptr, a.indices, a.data,
a.indptr, a.indices, a.data,
b.indptr, b.indices, b.data)
bres.append(b)
threads = [Worker() for _ in range(nthreads)]
for thread in threads:
thread.start()
for thread in threads:
thread.join()
for b in bres:
assert_(np.all(b.toarray() == 2))
def test_regression_std_vector_dtypes():
# Regression test for gh-3780, checking the std::vector typemaps
# in sparsetools.cxx are complete.
for dtype in supported_dtypes:
ad = np.array([[1, 2], [3, 4]]).astype(dtype)
a = csr_matrix(ad, dtype=dtype)
# getcol is one function using std::vector typemaps, and should not fail
assert_equal(a.getcol(0).toarray(), ad[:, :1])
@pytest.mark.slow
@pytest.mark.xfail_on_32bit("Can't create large array for test")
def test_nnz_overflow():
# Regression test for gh-7230 / gh-7871, checking that coo_toarray
# with nnz > int32max doesn't overflow.
nnz = np.iinfo(np.int32).max + 1
# Ensure ~20 GB of RAM is free to run this test.
check_free_memory((4 + 4 + 1) * nnz / 1e6 + 0.5)
# Use nnz duplicate entries to keep the dense version small.
row = np.zeros(nnz, dtype=np.int32)
col = np.zeros(nnz, dtype=np.int32)
data = np.zeros(nnz, dtype=np.int8)
data[-1] = 4
s = coo_matrix((data, (row, col)), shape=(1, 1), copy=False)
# Sums nnz duplicates to produce a 1x1 array containing 4.
d = s.toarray()
assert_allclose(d, [[4]])
@pytest.mark.skipif(not (sys.platform.startswith('linux') and np.dtype(np.intp).itemsize >= 8),
reason="test requires 64-bit Linux")
class TestInt32Overflow:
"""
Some of the sparsetools routines use dense 2D matrices whose
total size is not bounded by the nnz of the sparse matrix. These
routines used to suffer from int32 wraparounds; here, we try to
check that the wraparounds don't occur any more.
"""
# choose n large enough
n = 50000
def setup_method(self):
assert self.n**2 > np.iinfo(np.int32).max
# check there's enough memory even if everything is run at the
# same time
try:
parallel_count = int(os.environ.get('PYTEST_XDIST_WORKER_COUNT', '1'))
except ValueError:
parallel_count = np.inf
check_free_memory(3000 * parallel_count)
def teardown_method(self):
gc.collect()
def test_coo_todense(self):
# Check *_todense routines (cf. gh-2179)
#
# All of them in the end call coo_matrix.todense
n = self.n
i = np.array([0, n-1])
j = np.array([0, n-1])
data = np.array([1, 2], dtype=np.int8)
m = coo_matrix((data, (i, j)))
r = m.todense()
assert_equal(r[0,0], 1)
assert_equal(r[-1,-1], 2)
del r
gc.collect()
@pytest.mark.slow
def test_matvecs(self):
# Check *_matvecs routines
n = self.n
i = np.array([0, n-1])
j = np.array([0, n-1])
data = np.array([1, 2], dtype=np.int8)
m = coo_matrix((data, (i, j)))
b = np.ones((n, n), dtype=np.int8)
for sptype in (csr_matrix, csc_matrix, bsr_matrix):
m2 = sptype(m)
r = m2.dot(b)
assert_equal(r[0,0], 1)
assert_equal(r[-1,-1], 2)
del r
gc.collect()
del b
gc.collect()
@pytest.mark.slow
def test_dia_matvec(self):
# Check: huge dia_matrix _matvec
n = self.n
data = np.ones((n, n), dtype=np.int8)
offsets = np.arange(n)
m = dia_matrix((data, offsets), shape=(n, n))
v = np.ones(m.shape[1], dtype=np.int8)
r = m.dot(v)
assert_equal(r[0], int_to_int8(n))
del data, offsets, m, v, r
gc.collect()
_bsr_ops = [pytest.param("matmat", marks=pytest.mark.xslow),
pytest.param("matvecs", marks=pytest.mark.xslow),
"matvec",
"diagonal",
"sort_indices",
pytest.param("transpose", marks=pytest.mark.xslow)]
@pytest.mark.slow
@pytest.mark.parametrize("op", _bsr_ops)
def test_bsr_1_block(self, op):
# Check: huge bsr_matrix (1-block)
#
# The point here is that indices inside a block may overflow.
def get_matrix():
n = self.n
data = np.ones((1, n, n), dtype=np.int8)
indptr = np.array([0, 1], dtype=np.int32)
indices = np.array([0], dtype=np.int32)
m = bsr_matrix((data, indices, indptr), blocksize=(n, n), copy=False)
del data, indptr, indices
return m
gc.collect()
try:
getattr(self, "_check_bsr_" + op)(get_matrix)
finally:
gc.collect()
@pytest.mark.slow
@pytest.mark.parametrize("op", _bsr_ops)
def test_bsr_n_block(self, op):
# Check: huge bsr_matrix (n-block)
#
# The point here is that while indices within a block don't
# overflow, accumulators across many block may.
def get_matrix():
n = self.n
data = np.ones((n, n, 1), dtype=np.int8)
indptr = np.array([0, n], dtype=np.int32)
indices = np.arange(n, dtype=np.int32)
m = bsr_matrix((data, indices, indptr), blocksize=(n, 1), copy=False)
del data, indptr, indices
return m
gc.collect()
try:
getattr(self, "_check_bsr_" + op)(get_matrix)
finally:
gc.collect()
def _check_bsr_matvecs(self, m):
m = m()
n = self.n
# _matvecs
r = m.dot(np.ones((n, 2), dtype=np.int8))
assert_equal(r[0, 0], int_to_int8(n))
def _check_bsr_matvec(self, m):
m = m()
n = self.n
# _matvec
r = m.dot(np.ones((n,), dtype=np.int8))
assert_equal(r[0], int_to_int8(n))
def _check_bsr_diagonal(self, m):
m = m()
n = self.n
# _diagonal
r = m.diagonal()
assert_equal(r, np.ones(n))
def _check_bsr_sort_indices(self, m):
# _sort_indices
m = m()
m.sort_indices()
def _check_bsr_transpose(self, m):
# _transpose
m = m()
m.transpose()
def _check_bsr_matmat(self, m):
m = m()
n = self.n
# _bsr_matmat
m2 = bsr_matrix(np.ones((n, 2), dtype=np.int8), blocksize=(m.blocksize[1], 2))
m.dot(m2) # shouldn't SIGSEGV
del m2
# _bsr_matmat
m2 = bsr_matrix(np.ones((2, n), dtype=np.int8), blocksize=(2, m.blocksize[0]))
m2.dot(m) # shouldn't SIGSEGV
@pytest.mark.skip(reason="64-bit indices in sparse matrices not available")
def test_csr_matmat_int64_overflow():
n = 3037000500
assert n**2 > np.iinfo(np.int64).max
# the test would take crazy amounts of memory
check_free_memory(n * (8*2 + 1) * 3 / 1e6)
# int64 overflow
data = np.ones((n,), dtype=np.int8)
indptr = np.arange(n+1, dtype=np.int64)
indices = np.zeros(n, dtype=np.int64)
a = csr_matrix((data, indices, indptr))
b = a.T
assert_raises(RuntimeError, a.dot, b)
def test_upcast():
a0 = csr_matrix([[np.pi, np.pi*1j], [3, 4]], dtype=complex)
b0 = np.array([256+1j, 2**32], dtype=complex)
for a_dtype in supported_dtypes:
for b_dtype in supported_dtypes:
msg = "(%r, %r)" % (a_dtype, b_dtype)
if np.issubdtype(a_dtype, np.complexfloating):
a = a0.copy().astype(a_dtype)
else:
a = a0.real.copy().astype(a_dtype)
if np.issubdtype(b_dtype, np.complexfloating):
b = b0.copy().astype(b_dtype)
else:
with np.errstate(invalid="ignore"):
# Casting a large value (2**32) to int8 causes a warning in
# numpy >1.23
b = b0.real.copy().astype(b_dtype)
if not (a_dtype == np.bool_ and b_dtype == np.bool_):
c = np.zeros((2,), dtype=np.bool_)
assert_raises(ValueError, _sparsetools.csr_matvec,
2, 2, a.indptr, a.indices, a.data, b, c)
if ((np.issubdtype(a_dtype, np.complexfloating) and
not np.issubdtype(b_dtype, np.complexfloating)) or
(not np.issubdtype(a_dtype, np.complexfloating) and
np.issubdtype(b_dtype, np.complexfloating))):
c = np.zeros((2,), dtype=np.float64)
assert_raises(ValueError, _sparsetools.csr_matvec,
2, 2, a.indptr, a.indices, a.data, b, c)
c = np.zeros((2,), dtype=np.result_type(a_dtype, b_dtype))
_sparsetools.csr_matvec(2, 2, a.indptr, a.indices, a.data, b, c)
assert_allclose(c, np.dot(a.toarray(), b), err_msg=msg)
def test_endianness():
d = np.ones((3,4))
offsets = [-1,0,1]
a = dia_matrix((d.astype('<f8'), offsets), (4, 4))
b = dia_matrix((d.astype('>f8'), offsets), (4, 4))
v = np.arange(4)
assert_allclose(a.dot(v), [1, 3, 6, 5])
assert_allclose(b.dot(v), [1, 3, 6, 5])

View File

@@ -1,97 +0,0 @@
from numpy import array, kron, diag
from numpy.testing import assert_, assert_equal
from scipy.sparse import _spfuncs as spfuncs
from scipy.sparse import csr_matrix, csc_matrix, bsr_matrix
from scipy.sparse._sparsetools import (csr_scale_rows, csr_scale_columns,
bsr_scale_rows, bsr_scale_columns)
class TestSparseFunctions:
def test_scale_rows_and_cols(self):
D = array([[1, 0, 0, 2, 3],
[0, 4, 0, 5, 0],
[0, 0, 6, 7, 0]])
#TODO expose through function
S = csr_matrix(D)
v = array([1,2,3])
csr_scale_rows(3,5,S.indptr,S.indices,S.data,v)
assert_equal(S.toarray(), diag(v)@D)
S = csr_matrix(D)
v = array([1,2,3,4,5])
csr_scale_columns(3,5,S.indptr,S.indices,S.data,v)
assert_equal(S.toarray(), D@diag(v))
# blocks
E = kron(D,[[1,2],[3,4]])
S = bsr_matrix(E,blocksize=(2,2))
v = array([1,2,3,4,5,6])
bsr_scale_rows(3,5,2,2,S.indptr,S.indices,S.data,v)
assert_equal(S.toarray(), diag(v)@E)
S = bsr_matrix(E,blocksize=(2,2))
v = array([1,2,3,4,5,6,7,8,9,10])
bsr_scale_columns(3,5,2,2,S.indptr,S.indices,S.data,v)
assert_equal(S.toarray(), E@diag(v))
E = kron(D,[[1,2,3],[4,5,6]])
S = bsr_matrix(E,blocksize=(2,3))
v = array([1,2,3,4,5,6])
bsr_scale_rows(3,5,2,3,S.indptr,S.indices,S.data,v)
assert_equal(S.toarray(), diag(v)@E)
S = bsr_matrix(E,blocksize=(2,3))
v = array([1,2,3,4,5,6,7,8,9,10,11,12,13,14,15])
bsr_scale_columns(3,5,2,3,S.indptr,S.indices,S.data,v)
assert_equal(S.toarray(), E@diag(v))
def test_estimate_blocksize(self):
mats = []
mats.append([[0,1],[1,0]])
mats.append([[1,1,0],[0,0,1],[1,0,1]])
mats.append([[0],[0],[1]])
mats = [array(x) for x in mats]
blks = []
blks.append([[1]])
blks.append([[1,1],[1,1]])
blks.append([[1,1],[0,1]])
blks.append([[1,1,0],[1,0,1],[1,1,1]])
blks = [array(x) for x in blks]
for A in mats:
for B in blks:
X = kron(A,B)
r,c = spfuncs.estimate_blocksize(X)
assert_(r >= B.shape[0])
assert_(c >= B.shape[1])
def test_count_blocks(self):
def gold(A,bs):
R,C = bs
I,J = A.nonzero()
return len(set(zip(I//R,J//C)))
mats = []
mats.append([[0]])
mats.append([[1]])
mats.append([[1,0]])
mats.append([[1,1]])
mats.append([[0,1],[1,0]])
mats.append([[1,1,0],[0,0,1],[1,0,1]])
mats.append([[0],[0],[1]])
for A in mats:
for B in mats:
X = kron(A,B)
Y = csr_matrix(X)
for R in range(1,6):
for C in range(1,6):
assert_equal(spfuncs.count_blocks(Y, (R, C)), gold(X, (R, C)))
X = kron([[1,1,0],[0,0,1],[1,0,1]],[[1,1]])
Y = csc_matrix(X)
assert_equal(spfuncs.count_blocks(X, (1, 2)), gold(X, (1, 2)))
assert_equal(spfuncs.count_blocks(Y, (1, 2)), gold(X, (1, 2)))

View File

@@ -1,188 +0,0 @@
"""unit tests for sparse utility functions"""
import numpy as np
from numpy.testing import assert_equal
from pytest import raises as assert_raises
from scipy.sparse import _sputils as sputils
from scipy.sparse._sputils import matrix
class TestSparseUtils:
def test_upcast(self):
assert_equal(sputils.upcast('intc'), np.intc)
assert_equal(sputils.upcast('int32', 'float32'), np.float64)
assert_equal(sputils.upcast('bool', complex, float), np.complex128)
assert_equal(sputils.upcast('i', 'd'), np.float64)
def test_getdtype(self):
A = np.array([1], dtype='int8')
assert_equal(sputils.getdtype(None, default=float), float)
assert_equal(sputils.getdtype(None, a=A), np.int8)
with assert_raises(
ValueError,
match="object dtype is not supported by sparse matrices",
):
sputils.getdtype("O")
def test_isscalarlike(self):
assert_equal(sputils.isscalarlike(3.0), True)
assert_equal(sputils.isscalarlike(-4), True)
assert_equal(sputils.isscalarlike(2.5), True)
assert_equal(sputils.isscalarlike(1 + 3j), True)
assert_equal(sputils.isscalarlike(np.array(3)), True)
assert_equal(sputils.isscalarlike("16"), True)
assert_equal(sputils.isscalarlike(np.array([3])), False)
assert_equal(sputils.isscalarlike([[3]]), False)
assert_equal(sputils.isscalarlike((1,)), False)
assert_equal(sputils.isscalarlike((1, 2)), False)
def test_isintlike(self):
assert_equal(sputils.isintlike(-4), True)
assert_equal(sputils.isintlike(np.array(3)), True)
assert_equal(sputils.isintlike(np.array([3])), False)
with assert_raises(
ValueError,
match="Inexact indices into sparse matrices are not allowed"
):
sputils.isintlike(3.0)
assert_equal(sputils.isintlike(2.5), False)
assert_equal(sputils.isintlike(1 + 3j), False)
assert_equal(sputils.isintlike((1,)), False)
assert_equal(sputils.isintlike((1, 2)), False)
def test_isshape(self):
assert_equal(sputils.isshape((1, 2)), True)
assert_equal(sputils.isshape((5, 2)), True)
assert_equal(sputils.isshape((1.5, 2)), False)
assert_equal(sputils.isshape((2, 2, 2)), False)
assert_equal(sputils.isshape(([2], 2)), False)
assert_equal(sputils.isshape((-1, 2), nonneg=False),True)
assert_equal(sputils.isshape((2, -1), nonneg=False),True)
assert_equal(sputils.isshape((-1, 2), nonneg=True),False)
assert_equal(sputils.isshape((2, -1), nonneg=True),False)
def test_issequence(self):
assert_equal(sputils.issequence((1,)), True)
assert_equal(sputils.issequence((1, 2, 3)), True)
assert_equal(sputils.issequence([1]), True)
assert_equal(sputils.issequence([1, 2, 3]), True)
assert_equal(sputils.issequence(np.array([1, 2, 3])), True)
assert_equal(sputils.issequence(np.array([[1], [2], [3]])), False)
assert_equal(sputils.issequence(3), False)
def test_ismatrix(self):
assert_equal(sputils.ismatrix(((),)), True)
assert_equal(sputils.ismatrix([[1], [2]]), True)
assert_equal(sputils.ismatrix(np.arange(3)[None]), True)
assert_equal(sputils.ismatrix([1, 2]), False)
assert_equal(sputils.ismatrix(np.arange(3)), False)
assert_equal(sputils.ismatrix([[[1]]]), False)
assert_equal(sputils.ismatrix(3), False)
def test_isdense(self):
assert_equal(sputils.isdense(np.array([1])), True)
assert_equal(sputils.isdense(matrix([1])), True)
def test_validateaxis(self):
assert_raises(TypeError, sputils.validateaxis, (0, 1))
assert_raises(TypeError, sputils.validateaxis, 1.5)
assert_raises(ValueError, sputils.validateaxis, 3)
# These function calls should not raise errors
for axis in (-2, -1, 0, 1, None):
sputils.validateaxis(axis)
def test_get_index_dtype(self):
imax = np.int64(np.iinfo(np.int32).max)
too_big = imax + 1
# Check that uint32's with no values too large doesn't return
# int64
a1 = np.ones(90, dtype='uint32')
a2 = np.ones(90, dtype='uint32')
assert_equal(
np.dtype(sputils.get_index_dtype((a1, a2), check_contents=True)),
np.dtype('int32')
)
# Check that if we can not convert but all values are less than or
# equal to max that we can just convert to int32
a1[-1] = imax
assert_equal(
np.dtype(sputils.get_index_dtype((a1, a2), check_contents=True)),
np.dtype('int32')
)
# Check that if it can not convert directly and the contents are
# too large that we return int64
a1[-1] = too_big
assert_equal(
np.dtype(sputils.get_index_dtype((a1, a2), check_contents=True)),
np.dtype('int64')
)
# test that if can not convert and didn't specify to check_contents
# we return int64
a1 = np.ones(89, dtype='uint32')
a2 = np.ones(89, dtype='uint32')
assert_equal(
np.dtype(sputils.get_index_dtype((a1, a2))),
np.dtype('int64')
)
# Check that even if we have arrays that can be converted directly
# that if we specify a maxval directly it takes precedence
a1 = np.ones(12, dtype='uint32')
a2 = np.ones(12, dtype='uint32')
assert_equal(
np.dtype(sputils.get_index_dtype(
(a1, a2), maxval=too_big, check_contents=True
)),
np.dtype('int64')
)
# Check that an array with a too max size and maxval set
# still returns int64
a1[-1] = too_big
assert_equal(
np.dtype(sputils.get_index_dtype((a1, a2), maxval=too_big)),
np.dtype('int64')
)
def test_check_shape_overflow(self):
new_shape = sputils.check_shape([(10, -1)], (65535, 131070))
assert_equal(new_shape, (10, 858967245))
def test_matrix(self):
a = [[1, 2, 3]]
b = np.array(a)
assert isinstance(sputils.matrix(a), np.matrix)
assert isinstance(sputils.matrix(b), np.matrix)
c = sputils.matrix(b)
c[:, :] = 123
assert_equal(b, a)
c = sputils.matrix(b, copy=False)
c[:, :] = 123
assert_equal(b, [[123, 123, 123]])
def test_asmatrix(self):
a = [[1, 2, 3]]
b = np.array(a)
assert isinstance(sputils.asmatrix(a), np.matrix)
assert isinstance(sputils.asmatrix(b), np.matrix)
c = sputils.asmatrix(b)
c[:, :] = 123
assert_equal(b, [[123, 123, 123]])