|
|
|
|
|
|
|
|
|
from functools import reduce |
|
import random |
|
|
|
from numpy.testing import (assert_equal, assert_array_almost_equal, assert_, |
|
assert_allclose, assert_almost_equal, |
|
assert_array_equal) |
|
import pytest |
|
from pytest import raises as assert_raises |
|
|
|
import numpy as np |
|
from numpy import (eye, ones, zeros, zeros_like, triu, tril, tril_indices, |
|
triu_indices) |
|
|
|
from numpy.random import rand, randint, seed |
|
|
|
from scipy.linalg import (_flapack as flapack, lapack, inv, svd, cholesky, |
|
solve, ldl, norm, block_diag, qr, eigh, qz) |
|
|
|
from scipy.linalg.lapack import _compute_lwork |
|
from scipy.stats import ortho_group, unitary_group |
|
|
|
import scipy.sparse as sps |
|
try: |
|
from scipy.__config__ import CONFIG |
|
except ImportError: |
|
CONFIG = None |
|
|
|
try: |
|
from scipy.linalg import _clapack as clapack |
|
except ImportError: |
|
clapack = None |
|
from scipy.linalg.lapack import get_lapack_funcs |
|
from scipy.linalg.blas import get_blas_funcs |
|
|
|
REAL_DTYPES = [np.float32, np.float64] |
|
COMPLEX_DTYPES = [np.complex64, np.complex128] |
|
DTYPES = REAL_DTYPES + COMPLEX_DTYPES |
|
|
|
blas_provider = blas_version = None |
|
if CONFIG is not None: |
|
blas_provider = CONFIG['Build Dependencies']['blas']['name'] |
|
blas_version = CONFIG['Build Dependencies']['blas']['version'] |
|
|
|
|
|
def generate_random_dtype_array(shape, dtype, rng): |
|
|
|
if dtype in COMPLEX_DTYPES: |
|
return (rng.rand(*shape) |
|
+ rng.rand(*shape)*1.0j).astype(dtype) |
|
return rng.rand(*shape).astype(dtype) |
|
|
|
|
|
def test_lapack_documented(): |
|
"""Test that all entries are in the doc.""" |
|
if lapack.__doc__ is None: |
|
pytest.skip('lapack.__doc__ is None') |
|
names = set(lapack.__doc__.split()) |
|
ignore_list = { |
|
"absolute_import", |
|
"clapack", |
|
"division", |
|
"find_best_lapack_type", |
|
"flapack", |
|
"print_function", |
|
"HAS_ILP64", |
|
"np", |
|
} |
|
missing = list() |
|
for name in dir(lapack): |
|
if (not name.startswith('_') and name not in ignore_list and |
|
name not in names): |
|
missing.append(name) |
|
assert missing == [], 'Name(s) missing from lapack.__doc__ or ignore_list' |
|
|
|
|
|
class TestFlapackSimple: |
|
|
|
def test_gebal(self): |
|
a = [[1, 2, 3], [4, 5, 6], [7, 8, 9]] |
|
a1 = [[1, 0, 0, 3e-4], |
|
[4, 0, 0, 2e-3], |
|
[7, 1, 0, 0], |
|
[0, 1, 0, 0]] |
|
for p in 'sdzc': |
|
f = getattr(flapack, p+'gebal', None) |
|
if f is None: |
|
continue |
|
ba, lo, hi, pivscale, info = f(a) |
|
assert_(not info, repr(info)) |
|
assert_array_almost_equal(ba, a) |
|
assert_equal((lo, hi), (0, len(a[0])-1)) |
|
assert_array_almost_equal(pivscale, np.ones(len(a))) |
|
|
|
ba, lo, hi, pivscale, info = f(a1, permute=1, scale=1) |
|
assert_(not info, repr(info)) |
|
|
|
|
|
|
|
def test_gehrd(self): |
|
a = [[-149, -50, -154], |
|
[537, 180, 546], |
|
[-27, -9, -25]] |
|
for p in 'd': |
|
f = getattr(flapack, p+'gehrd', None) |
|
if f is None: |
|
continue |
|
ht, tau, info = f(a) |
|
assert_(not info, repr(info)) |
|
|
|
def test_trsyl(self): |
|
a = np.array([[1, 2], [0, 4]]) |
|
b = np.array([[5, 6], [0, 8]]) |
|
c = np.array([[9, 10], [11, 12]]) |
|
trans = 'T' |
|
|
|
|
|
|
|
for dtype in 'fdFD': |
|
a1, b1, c1 = a.astype(dtype), b.astype(dtype), c.astype(dtype) |
|
trsyl, = get_lapack_funcs(('trsyl',), (a1,)) |
|
if dtype.isupper(): |
|
a1[0] += 1j |
|
trans = 'C' |
|
|
|
x, scale, info = trsyl(a1, b1, c1) |
|
assert_array_almost_equal(np.dot(a1, x) + np.dot(x, b1), |
|
scale * c1) |
|
|
|
x, scale, info = trsyl(a1, b1, c1, trana=trans, tranb=trans) |
|
assert_array_almost_equal( |
|
np.dot(a1.conjugate().T, x) + np.dot(x, b1.conjugate().T), |
|
scale * c1, decimal=4) |
|
|
|
x, scale, info = trsyl(a1, b1, c1, isgn=-1) |
|
assert_array_almost_equal(np.dot(a1, x) - np.dot(x, b1), |
|
scale * c1, decimal=4) |
|
|
|
def test_lange(self): |
|
a = np.array([ |
|
[-149, -50, -154], |
|
[537, 180, 546], |
|
[-27, -9, -25]]) |
|
|
|
for dtype in 'fdFD': |
|
for norm_str in 'Mm1OoIiFfEe': |
|
a1 = a.astype(dtype) |
|
if dtype.isupper(): |
|
|
|
a1[0, 0] += 1j |
|
|
|
lange, = get_lapack_funcs(('lange',), (a1,)) |
|
value = lange(norm_str, a1) |
|
|
|
if norm_str in 'FfEe': |
|
if dtype in 'Ff': |
|
decimal = 3 |
|
else: |
|
decimal = 7 |
|
ref = np.sqrt(np.sum(np.square(np.abs(a1)))) |
|
assert_almost_equal(value, ref, decimal) |
|
else: |
|
if norm_str in 'Mm': |
|
ref = np.max(np.abs(a1)) |
|
elif norm_str in '1Oo': |
|
ref = np.max(np.sum(np.abs(a1), axis=0)) |
|
elif norm_str in 'Ii': |
|
ref = np.max(np.sum(np.abs(a1), axis=1)) |
|
|
|
assert_equal(value, ref) |
|
|
|
|
|
class TestLapack: |
|
|
|
def test_flapack(self): |
|
if hasattr(flapack, 'empty_module'): |
|
|
|
pass |
|
|
|
def test_clapack(self): |
|
if hasattr(clapack, 'empty_module'): |
|
|
|
pass |
|
|
|
|
|
class TestLeastSquaresSolvers: |
|
|
|
def test_gels(self): |
|
seed(1234) |
|
|
|
for ind, dtype in enumerate(DTYPES): |
|
m = 10 |
|
n = 20 |
|
nrhs = 1 |
|
a1 = rand(m, n).astype(dtype) |
|
b1 = rand(n).astype(dtype) |
|
gls, glslw = get_lapack_funcs(('gels', 'gels_lwork'), dtype=dtype) |
|
|
|
|
|
lwork = _compute_lwork(glslw, m, n, nrhs) |
|
_, _, info = gls(a1, b1, lwork=lwork) |
|
assert_(info >= 0) |
|
_, _, info = gls(a1, b1, trans='TTCC'[ind], lwork=lwork) |
|
assert_(info >= 0) |
|
|
|
for dtype in REAL_DTYPES: |
|
a1 = np.array([[1.0, 2.0], |
|
[4.0, 5.0], |
|
[7.0, 8.0]], dtype=dtype) |
|
b1 = np.array([16.0, 17.0, 20.0], dtype=dtype) |
|
gels, gels_lwork, geqrf = get_lapack_funcs( |
|
('gels', 'gels_lwork', 'geqrf'), (a1, b1)) |
|
|
|
m, n = a1.shape |
|
if len(b1.shape) == 2: |
|
nrhs = b1.shape[1] |
|
else: |
|
nrhs = 1 |
|
|
|
|
|
lwork = _compute_lwork(gels_lwork, m, n, nrhs) |
|
|
|
lqr, x, info = gels(a1, b1, lwork=lwork) |
|
assert_allclose(x[:-1], np.array([-14.333333333333323, |
|
14.999999999999991], |
|
dtype=dtype), |
|
rtol=25*np.finfo(dtype).eps) |
|
lqr_truth, _, _, _ = geqrf(a1) |
|
assert_array_equal(lqr, lqr_truth) |
|
|
|
for dtype in COMPLEX_DTYPES: |
|
a1 = np.array([[1.0+4.0j, 2.0], |
|
[4.0+0.5j, 5.0-3.0j], |
|
[7.0-2.0j, 8.0+0.7j]], dtype=dtype) |
|
b1 = np.array([16.0, 17.0+2.0j, 20.0-4.0j], dtype=dtype) |
|
gels, gels_lwork, geqrf = get_lapack_funcs( |
|
('gels', 'gels_lwork', 'geqrf'), (a1, b1)) |
|
|
|
m, n = a1.shape |
|
if len(b1.shape) == 2: |
|
nrhs = b1.shape[1] |
|
else: |
|
nrhs = 1 |
|
|
|
|
|
lwork = _compute_lwork(gels_lwork, m, n, nrhs) |
|
|
|
lqr, x, info = gels(a1, b1, lwork=lwork) |
|
assert_allclose(x[:-1], |
|
np.array([1.161753632288328-1.901075709391912j, |
|
1.735882340522193+1.521240901196909j], |
|
dtype=dtype), rtol=25*np.finfo(dtype).eps) |
|
lqr_truth, _, _, _ = geqrf(a1) |
|
assert_array_equal(lqr, lqr_truth) |
|
|
|
def test_gelsd(self): |
|
for dtype in REAL_DTYPES: |
|
a1 = np.array([[1.0, 2.0], |
|
[4.0, 5.0], |
|
[7.0, 8.0]], dtype=dtype) |
|
b1 = np.array([16.0, 17.0, 20.0], dtype=dtype) |
|
gelsd, gelsd_lwork = get_lapack_funcs(('gelsd', 'gelsd_lwork'), |
|
(a1, b1)) |
|
|
|
m, n = a1.shape |
|
if len(b1.shape) == 2: |
|
nrhs = b1.shape[1] |
|
else: |
|
nrhs = 1 |
|
|
|
|
|
work, iwork, info = gelsd_lwork(m, n, nrhs, -1) |
|
lwork = int(np.real(work)) |
|
iwork_size = iwork |
|
|
|
x, s, rank, info = gelsd(a1, b1, lwork, iwork_size, |
|
-1, False, False) |
|
assert_allclose(x[:-1], np.array([-14.333333333333323, |
|
14.999999999999991], |
|
dtype=dtype), |
|
rtol=25*np.finfo(dtype).eps) |
|
assert_allclose(s, np.array([12.596017180511966, |
|
0.583396253199685], dtype=dtype), |
|
rtol=25*np.finfo(dtype).eps) |
|
|
|
for dtype in COMPLEX_DTYPES: |
|
a1 = np.array([[1.0+4.0j, 2.0], |
|
[4.0+0.5j, 5.0-3.0j], |
|
[7.0-2.0j, 8.0+0.7j]], dtype=dtype) |
|
b1 = np.array([16.0, 17.0+2.0j, 20.0-4.0j], dtype=dtype) |
|
gelsd, gelsd_lwork = get_lapack_funcs(('gelsd', 'gelsd_lwork'), |
|
(a1, b1)) |
|
|
|
m, n = a1.shape |
|
if len(b1.shape) == 2: |
|
nrhs = b1.shape[1] |
|
else: |
|
nrhs = 1 |
|
|
|
|
|
work, rwork, iwork, info = gelsd_lwork(m, n, nrhs, -1) |
|
lwork = int(np.real(work)) |
|
rwork_size = int(rwork) |
|
iwork_size = iwork |
|
|
|
x, s, rank, info = gelsd(a1, b1, lwork, rwork_size, iwork_size, |
|
-1, False, False) |
|
assert_allclose(x[:-1], |
|
np.array([1.161753632288328-1.901075709391912j, |
|
1.735882340522193+1.521240901196909j], |
|
dtype=dtype), rtol=25*np.finfo(dtype).eps) |
|
assert_allclose(s, |
|
np.array([13.035514762572043, 4.337666985231382], |
|
dtype=dtype), rtol=25*np.finfo(dtype).eps) |
|
|
|
def test_gelss(self): |
|
|
|
for dtype in REAL_DTYPES: |
|
a1 = np.array([[1.0, 2.0], |
|
[4.0, 5.0], |
|
[7.0, 8.0]], dtype=dtype) |
|
b1 = np.array([16.0, 17.0, 20.0], dtype=dtype) |
|
gelss, gelss_lwork = get_lapack_funcs(('gelss', 'gelss_lwork'), |
|
(a1, b1)) |
|
|
|
m, n = a1.shape |
|
if len(b1.shape) == 2: |
|
nrhs = b1.shape[1] |
|
else: |
|
nrhs = 1 |
|
|
|
|
|
work, info = gelss_lwork(m, n, nrhs, -1) |
|
lwork = int(np.real(work)) |
|
|
|
v, x, s, rank, work, info = gelss(a1, b1, -1, lwork, False, False) |
|
assert_allclose(x[:-1], np.array([-14.333333333333323, |
|
14.999999999999991], |
|
dtype=dtype), |
|
rtol=25*np.finfo(dtype).eps) |
|
assert_allclose(s, np.array([12.596017180511966, |
|
0.583396253199685], dtype=dtype), |
|
rtol=25*np.finfo(dtype).eps) |
|
|
|
for dtype in COMPLEX_DTYPES: |
|
a1 = np.array([[1.0+4.0j, 2.0], |
|
[4.0+0.5j, 5.0-3.0j], |
|
[7.0-2.0j, 8.0+0.7j]], dtype=dtype) |
|
b1 = np.array([16.0, 17.0+2.0j, 20.0-4.0j], dtype=dtype) |
|
gelss, gelss_lwork = get_lapack_funcs(('gelss', 'gelss_lwork'), |
|
(a1, b1)) |
|
|
|
m, n = a1.shape |
|
if len(b1.shape) == 2: |
|
nrhs = b1.shape[1] |
|
else: |
|
nrhs = 1 |
|
|
|
|
|
work, info = gelss_lwork(m, n, nrhs, -1) |
|
lwork = int(np.real(work)) |
|
|
|
v, x, s, rank, work, info = gelss(a1, b1, -1, lwork, False, False) |
|
assert_allclose(x[:-1], |
|
np.array([1.161753632288328-1.901075709391912j, |
|
1.735882340522193+1.521240901196909j], |
|
dtype=dtype), |
|
rtol=25*np.finfo(dtype).eps) |
|
assert_allclose(s, np.array([13.035514762572043, |
|
4.337666985231382], dtype=dtype), |
|
rtol=25*np.finfo(dtype).eps) |
|
|
|
def test_gelsy(self): |
|
|
|
for dtype in REAL_DTYPES: |
|
a1 = np.array([[1.0, 2.0], |
|
[4.0, 5.0], |
|
[7.0, 8.0]], dtype=dtype) |
|
b1 = np.array([16.0, 17.0, 20.0], dtype=dtype) |
|
gelsy, gelsy_lwork = get_lapack_funcs(('gelsy', 'gelss_lwork'), |
|
(a1, b1)) |
|
|
|
m, n = a1.shape |
|
if len(b1.shape) == 2: |
|
nrhs = b1.shape[1] |
|
else: |
|
nrhs = 1 |
|
|
|
|
|
work, info = gelsy_lwork(m, n, nrhs, 10*np.finfo(dtype).eps) |
|
lwork = int(np.real(work)) |
|
|
|
jptv = np.zeros((a1.shape[1], 1), dtype=np.int32) |
|
v, x, j, rank, info = gelsy(a1, b1, jptv, np.finfo(dtype).eps, |
|
lwork, False, False) |
|
assert_allclose(x[:-1], np.array([-14.333333333333323, |
|
14.999999999999991], |
|
dtype=dtype), |
|
rtol=25*np.finfo(dtype).eps) |
|
|
|
for dtype in COMPLEX_DTYPES: |
|
a1 = np.array([[1.0+4.0j, 2.0], |
|
[4.0+0.5j, 5.0-3.0j], |
|
[7.0-2.0j, 8.0+0.7j]], dtype=dtype) |
|
b1 = np.array([16.0, 17.0+2.0j, 20.0-4.0j], dtype=dtype) |
|
gelsy, gelsy_lwork = get_lapack_funcs(('gelsy', 'gelss_lwork'), |
|
(a1, b1)) |
|
|
|
m, n = a1.shape |
|
if len(b1.shape) == 2: |
|
nrhs = b1.shape[1] |
|
else: |
|
nrhs = 1 |
|
|
|
|
|
work, info = gelsy_lwork(m, n, nrhs, 10*np.finfo(dtype).eps) |
|
lwork = int(np.real(work)) |
|
|
|
jptv = np.zeros((a1.shape[1], 1), dtype=np.int32) |
|
v, x, j, rank, info = gelsy(a1, b1, jptv, np.finfo(dtype).eps, |
|
lwork, False, False) |
|
assert_allclose(x[:-1], |
|
np.array([1.161753632288328-1.901075709391912j, |
|
1.735882340522193+1.521240901196909j], |
|
dtype=dtype), |
|
rtol=25*np.finfo(dtype).eps) |
|
|
|
|
|
@pytest.mark.parametrize('dtype', DTYPES) |
|
@pytest.mark.parametrize('shape', [(3, 4), (5, 2), (2**18, 2**18)]) |
|
def test_geqrf_lwork(dtype, shape): |
|
geqrf_lwork = get_lapack_funcs(('geqrf_lwork'), dtype=dtype) |
|
m, n = shape |
|
lwork, info = geqrf_lwork(m=m, n=n) |
|
assert_equal(info, 0) |
|
|
|
|
|
class TestRegression: |
|
|
|
def test_ticket_1645(self): |
|
|
|
for dtype in DTYPES: |
|
a = np.zeros((300, 2), dtype=dtype) |
|
|
|
gerqf, = get_lapack_funcs(['gerqf'], [a]) |
|
assert_raises(Exception, gerqf, a, lwork=2) |
|
rq, tau, work, info = gerqf(a) |
|
|
|
if dtype in REAL_DTYPES: |
|
orgrq, = get_lapack_funcs(['orgrq'], [a]) |
|
assert_raises(Exception, orgrq, rq[-2:], tau, lwork=1) |
|
orgrq(rq[-2:], tau, lwork=2) |
|
elif dtype in COMPLEX_DTYPES: |
|
ungrq, = get_lapack_funcs(['ungrq'], [a]) |
|
assert_raises(Exception, ungrq, rq[-2:], tau, lwork=1) |
|
ungrq(rq[-2:], tau, lwork=2) |
|
|
|
|
|
class TestDpotr: |
|
def test_gh_2691(self): |
|
|
|
for lower in [True, False]: |
|
for clean in [True, False]: |
|
np.random.seed(42) |
|
x = np.random.normal(size=(3, 3)) |
|
a = x.dot(x.T) |
|
|
|
dpotrf, dpotri = get_lapack_funcs(("potrf", "potri"), (a, )) |
|
|
|
c, info = dpotrf(a, lower, clean=clean) |
|
dpt = dpotri(c, lower)[0] |
|
|
|
if lower: |
|
assert_allclose(np.tril(dpt), np.tril(inv(a))) |
|
else: |
|
assert_allclose(np.triu(dpt), np.triu(inv(a))) |
|
|
|
|
|
class TestDlasd4: |
|
def test_sing_val_update(self): |
|
|
|
sigmas = np.array([4., 3., 2., 0]) |
|
m_vec = np.array([3.12, 5.7, -4.8, -2.2]) |
|
|
|
M = np.hstack((np.vstack((np.diag(sigmas[0:-1]), |
|
np.zeros((1, len(m_vec) - 1)))), |
|
m_vec[:, np.newaxis])) |
|
SM = svd(M, full_matrices=False, compute_uv=False, overwrite_a=False, |
|
check_finite=False) |
|
|
|
it_len = len(sigmas) |
|
sgm = np.concatenate((sigmas[::-1], [sigmas[0] + it_len*norm(m_vec)])) |
|
mvc = np.concatenate((m_vec[::-1], (0,))) |
|
|
|
lasd4 = get_lapack_funcs('lasd4', (sigmas,)) |
|
|
|
roots = [] |
|
for i in range(0, it_len): |
|
res = lasd4(i, sgm, mvc) |
|
roots.append(res[1]) |
|
|
|
assert_((res[3] <= 0), "LAPACK root finding dlasd4 failed to find \ |
|
the singular value %i" % i) |
|
roots = np.array(roots)[::-1] |
|
|
|
assert_((not np.any(np.isnan(roots)), "There are NaN roots")) |
|
assert_allclose(SM, roots, atol=100*np.finfo(np.float64).eps, |
|
rtol=100*np.finfo(np.float64).eps) |
|
|
|
|
|
class TestTbtrs: |
|
|
|
@pytest.mark.parametrize('dtype', DTYPES) |
|
def test_nag_example_f07vef_f07vsf(self, dtype): |
|
"""Test real (f07vef) and complex (f07vsf) examples from NAG |
|
|
|
Examples available from: |
|
* https://www.nag.com/numeric/fl/nagdoc_latest/html/f07/f07vef.html |
|
* https://www.nag.com/numeric/fl/nagdoc_latest/html/f07/f07vsf.html |
|
|
|
""" |
|
if dtype in REAL_DTYPES: |
|
ab = np.array([[-4.16, 4.78, 6.32, 0.16], |
|
[-2.25, 5.86, -4.82, 0]], |
|
dtype=dtype) |
|
b = np.array([[-16.64, -4.16], |
|
[-13.78, -16.59], |
|
[13.10, -4.94], |
|
[-14.14, -9.96]], |
|
dtype=dtype) |
|
x_out = np.array([[4, 1], |
|
[-1, -3], |
|
[3, 2], |
|
[2, -2]], |
|
dtype=dtype) |
|
elif dtype in COMPLEX_DTYPES: |
|
ab = np.array([[-1.94+4.43j, 4.12-4.27j, 0.43-2.66j, 0.44+0.1j], |
|
[-3.39+3.44j, -1.84+5.52j, 1.74 - 0.04j, 0], |
|
[1.62+3.68j, -2.77-1.93j, 0, 0]], |
|
dtype=dtype) |
|
b = np.array([[-8.86 - 3.88j, -24.09 - 5.27j], |
|
[-15.57 - 23.41j, -57.97 + 8.14j], |
|
[-7.63 + 22.78j, 19.09 - 29.51j], |
|
[-14.74 - 2.40j, 19.17 + 21.33j]], |
|
dtype=dtype) |
|
x_out = np.array([[2j, 1 + 5j], |
|
[1 - 3j, -7 - 2j], |
|
[-4.001887 - 4.988417j, 3.026830 + 4.003182j], |
|
[1.996158 - 1.045105j, -6.103357 - 8.986653j]], |
|
dtype=dtype) |
|
else: |
|
raise ValueError(f"Datatype {dtype} not understood.") |
|
|
|
tbtrs = get_lapack_funcs(('tbtrs'), dtype=dtype) |
|
x, info = tbtrs(ab=ab, b=b, uplo='L') |
|
assert_equal(info, 0) |
|
assert_allclose(x, x_out, rtol=0, atol=1e-5) |
|
|
|
@pytest.mark.parametrize('dtype,trans', |
|
[(dtype, trans) |
|
for dtype in DTYPES for trans in ['N', 'T', 'C'] |
|
if not (trans == 'C' and dtype in REAL_DTYPES)]) |
|
@pytest.mark.parametrize('uplo', ['U', 'L']) |
|
@pytest.mark.parametrize('diag', ['N', 'U']) |
|
def test_random_matrices(self, dtype, trans, uplo, diag): |
|
rng = np.random.RandomState(1724) |
|
|
|
|
|
|
|
|
|
n, nrhs, kd = 4, 3, 2 |
|
tbtrs = get_lapack_funcs('tbtrs', dtype=dtype) |
|
|
|
is_upper = (uplo == 'U') |
|
ku = kd * is_upper |
|
kl = kd - ku |
|
|
|
|
|
|
|
band_offsets = range(ku, -kl - 1, -1) |
|
band_widths = [n - abs(x) for x in band_offsets] |
|
bands = [generate_random_dtype_array((width,), dtype, rng) |
|
for width in band_widths] |
|
|
|
if diag == 'U': |
|
bands[ku] = np.ones(n, dtype=dtype) |
|
|
|
|
|
a = sps.diags(bands, band_offsets, format='dia') |
|
|
|
|
|
ab = np.zeros((kd + 1, n), dtype) |
|
for row, k in enumerate(band_offsets): |
|
ab[row, max(k, 0):min(n+k, n)] = a.diagonal(k) |
|
|
|
|
|
b = generate_random_dtype_array((n, nrhs), dtype, rng) |
|
|
|
x, info = tbtrs(ab=ab, b=b, uplo=uplo, trans=trans, diag=diag) |
|
assert_equal(info, 0) |
|
|
|
if trans == 'N': |
|
assert_allclose(a @ x, b, rtol=5e-5) |
|
elif trans == 'T': |
|
assert_allclose(a.T @ x, b, rtol=5e-5) |
|
elif trans == 'C': |
|
assert_allclose(a.T.conjugate() @ x, b, rtol=5e-5) |
|
else: |
|
raise ValueError('Invalid trans argument') |
|
|
|
@pytest.mark.parametrize('uplo,trans,diag', |
|
[['U', 'N', 'Invalid'], |
|
['U', 'Invalid', 'N'], |
|
['Invalid', 'N', 'N']]) |
|
def test_invalid_argument_raises_exception(self, uplo, trans, diag): |
|
"""Test if invalid values of uplo, trans and diag raise exceptions""" |
|
|
|
|
|
tbtrs = get_lapack_funcs('tbtrs', dtype=np.float64) |
|
ab = rand(4, 2) |
|
b = rand(2, 4) |
|
assert_raises(Exception, tbtrs, ab, b, uplo, trans, diag) |
|
|
|
def test_zero_element_in_diagonal(self): |
|
"""Test if a matrix with a zero diagonal element is singular |
|
|
|
If the i-th diagonal of A is zero, ?tbtrs should return `i` in `info` |
|
indicating the provided matrix is singular. |
|
|
|
Note that ?tbtrs requires the matrix A to be stored in banded form. |
|
In this form the diagonal corresponds to the last row.""" |
|
ab = np.ones((3, 4), dtype=float) |
|
b = np.ones(4, dtype=float) |
|
tbtrs = get_lapack_funcs('tbtrs', dtype=float) |
|
|
|
ab[-1, 3] = 0 |
|
_, info = tbtrs(ab=ab, b=b, uplo='U') |
|
assert_equal(info, 4) |
|
|
|
@pytest.mark.parametrize('ldab,n,ldb,nrhs', [ |
|
(5, 5, 0, 5), |
|
(5, 5, 3, 5) |
|
]) |
|
def test_invalid_matrix_shapes(self, ldab, n, ldb, nrhs): |
|
"""Test ?tbtrs fails correctly if shapes are invalid.""" |
|
ab = np.ones((ldab, n), dtype=float) |
|
b = np.ones((ldb, nrhs), dtype=float) |
|
tbtrs = get_lapack_funcs('tbtrs', dtype=float) |
|
assert_raises(Exception, tbtrs, ab, b) |
|
|
|
|
|
|
|
@pytest.mark.parametrize('dtype', DTYPES) |
|
@pytest.mark.parametrize('norm', ['I', '1', 'O']) |
|
@pytest.mark.parametrize('uplo', ['U', 'L']) |
|
@pytest.mark.parametrize('diag', ['N', 'U']) |
|
@pytest.mark.parametrize('n', [3, 10]) |
|
def test_trcon(dtype, norm, uplo, diag, n): |
|
|
|
random.seed(f"{dtype}{norm}{uplo}{diag}{n}") |
|
rng = np.random.default_rng(random.randint(0, 9999999999999)) |
|
|
|
A = rng.random(size=(n, n)) + rng.random(size=(n, n))*1j |
|
|
|
offset = rng.permuted(np.logspace(0, rng.integers(0, 10), n)) |
|
A += offset |
|
A = A.real if np.issubdtype(dtype, np.floating) else A |
|
A = np.triu(A) if uplo == 'U' else np.tril(A) |
|
if diag == 'U': |
|
A /= np.diag(A)[:, np.newaxis] |
|
A = A.astype(dtype) |
|
|
|
trcon = get_lapack_funcs('trcon', (A,)) |
|
res, _ = trcon(A, norm=norm, uplo=uplo, diag=diag) |
|
|
|
if norm == 'I': |
|
norm_A = np.linalg.norm(A, ord=np.inf) |
|
norm_inv_A = np.linalg.norm(np.linalg.inv(A), ord=np.inf) |
|
ref = 1 / (norm_A * norm_inv_A) |
|
else: |
|
anorm = np.abs(A).sum(axis=0).max() |
|
gecon, getrf = get_lapack_funcs(('gecon', 'getrf'), (A,)) |
|
lu, ipvt, info = getrf(A) |
|
ref, _ = gecon(lu, anorm, norm=norm) |
|
|
|
|
|
|
|
|
|
rtol = 1 |
|
assert_allclose(res, ref, rtol=rtol) |
|
|
|
|
|
def test_lartg(): |
|
for dtype in 'fdFD': |
|
lartg = get_lapack_funcs('lartg', dtype=dtype) |
|
|
|
f = np.array(3, dtype) |
|
g = np.array(4, dtype) |
|
|
|
if np.iscomplexobj(g): |
|
g *= 1j |
|
|
|
cs, sn, r = lartg(f, g) |
|
|
|
assert_allclose(cs, 3.0/5.0) |
|
assert_allclose(r, 5.0) |
|
|
|
if np.iscomplexobj(g): |
|
assert_allclose(sn, -4.0j/5.0) |
|
assert_(isinstance(r, complex)) |
|
assert_(isinstance(cs, float)) |
|
else: |
|
assert_allclose(sn, 4.0/5.0) |
|
|
|
|
|
def test_rot(): |
|
|
|
|
|
for dtype in 'fdFD': |
|
c = 0.6 |
|
s = 0.8 |
|
|
|
u = np.full(4, 3, dtype) |
|
v = np.full(4, 4, dtype) |
|
atol = 10**-(np.finfo(dtype).precision-1) |
|
|
|
if dtype in 'fd': |
|
rot = get_blas_funcs('rot', dtype=dtype) |
|
f = 4 |
|
else: |
|
rot = get_lapack_funcs('rot', dtype=dtype) |
|
s *= -1j |
|
v *= 1j |
|
f = 4j |
|
|
|
assert_allclose(rot(u, v, c, s), [[5, 5, 5, 5], |
|
[0, 0, 0, 0]], atol=atol) |
|
assert_allclose(rot(u, v, c, s, n=2), [[5, 5, 3, 3], |
|
[0, 0, f, f]], atol=atol) |
|
assert_allclose(rot(u, v, c, s, offx=2, offy=2), |
|
[[3, 3, 5, 5], [f, f, 0, 0]], atol=atol) |
|
assert_allclose(rot(u, v, c, s, incx=2, offy=2, n=2), |
|
[[5, 3, 5, 3], [f, f, 0, 0]], atol=atol) |
|
assert_allclose(rot(u, v, c, s, offx=2, incy=2, n=2), |
|
[[3, 3, 5, 5], [0, f, 0, f]], atol=atol) |
|
assert_allclose(rot(u, v, c, s, offx=2, incx=2, offy=2, incy=2, n=1), |
|
[[3, 3, 5, 3], [f, f, 0, f]], atol=atol) |
|
assert_allclose(rot(u, v, c, s, incx=-2, incy=-2, n=2), |
|
[[5, 3, 5, 3], [0, f, 0, f]], atol=atol) |
|
|
|
a, b = rot(u, v, c, s, overwrite_x=1, overwrite_y=1) |
|
assert_(a is u) |
|
assert_(b is v) |
|
assert_allclose(a, [5, 5, 5, 5], atol=atol) |
|
assert_allclose(b, [0, 0, 0, 0], atol=atol) |
|
|
|
|
|
def test_larfg_larf(): |
|
np.random.seed(1234) |
|
a0 = np.random.random((4, 4)) |
|
a0 = a0.T.dot(a0) |
|
|
|
a0j = np.random.random((4, 4)) + 1j*np.random.random((4, 4)) |
|
a0j = a0j.T.conj().dot(a0j) |
|
|
|
|
|
|
|
|
|
for dtype in 'fdFD': |
|
larfg, larf = get_lapack_funcs(['larfg', 'larf'], dtype=dtype) |
|
|
|
if dtype in 'FD': |
|
a = a0j.copy() |
|
else: |
|
a = a0.copy() |
|
|
|
|
|
alpha, x, tau = larfg(a.shape[0]-1, a[1, 0], a[2:, 0]) |
|
|
|
|
|
expected = np.zeros_like(a[:, 0]) |
|
expected[0] = a[0, 0] |
|
expected[1] = alpha |
|
|
|
|
|
v = np.zeros_like(a[1:, 0]) |
|
v[0] = 1.0 |
|
v[1:] = x |
|
|
|
|
|
a[1:, :] = larf(v, tau.conjugate(), a[1:, :], np.zeros(a.shape[1])) |
|
|
|
|
|
a[:, 1:] = larf(v, tau, a[:, 1:], np.zeros(a.shape[0]), side='R') |
|
|
|
assert_allclose(a[:, 0], expected, atol=1e-5) |
|
assert_allclose(a[0, :], expected, atol=1e-5) |
|
|
|
|
|
def test_sgesdd_lwork_bug_workaround(): |
|
|
|
|
|
|
|
|
|
|
|
sgesdd_lwork = get_lapack_funcs('gesdd_lwork', dtype=np.float32, |
|
ilp64='preferred') |
|
n = 9537 |
|
lwork = _compute_lwork(sgesdd_lwork, n, n, |
|
compute_uv=True, full_matrices=True) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
assert lwork == 272929888 or lwork == 272929920 |
|
|
|
|
|
class TestSytrd: |
|
@pytest.mark.parametrize('dtype', REAL_DTYPES) |
|
def test_sytrd_with_zero_dim_array(self, dtype): |
|
|
|
A = np.zeros((0, 0), dtype=dtype) |
|
sytrd = get_lapack_funcs('sytrd', (A,)) |
|
assert_raises(ValueError, sytrd, A) |
|
|
|
@pytest.mark.parametrize('dtype', REAL_DTYPES) |
|
@pytest.mark.parametrize('n', (1, 3)) |
|
def test_sytrd(self, dtype, n): |
|
A = np.zeros((n, n), dtype=dtype) |
|
|
|
sytrd, sytrd_lwork = \ |
|
get_lapack_funcs(('sytrd', 'sytrd_lwork'), (A,)) |
|
|
|
|
|
A[np.triu_indices_from(A)] = \ |
|
np.arange(1, n*(n+1)//2+1, dtype=dtype) |
|
|
|
|
|
lwork, info = sytrd_lwork(n) |
|
assert_equal(info, 0) |
|
|
|
|
|
|
|
data, d, e, tau, info = sytrd(A, lower=1, lwork=lwork) |
|
assert_equal(info, 0) |
|
|
|
assert_allclose(data, A, atol=5*np.finfo(dtype).eps, rtol=1.0) |
|
assert_allclose(d, np.diag(A)) |
|
assert_allclose(e, 0.0) |
|
assert_allclose(tau, 0.0) |
|
|
|
|
|
data, d, e, tau, info = sytrd(A, lwork=lwork) |
|
assert_equal(info, 0) |
|
|
|
|
|
|
|
|
|
T = np.zeros_like(A, dtype=dtype) |
|
k = np.arange(A.shape[0]) |
|
T[k, k] = d |
|
k2 = np.arange(A.shape[0]-1) |
|
T[k2+1, k2] = e |
|
T[k2, k2+1] = e |
|
|
|
|
|
Q = np.eye(n, n, dtype=dtype) |
|
for i in range(n-1): |
|
v = np.zeros(n, dtype=dtype) |
|
v[:i] = data[:i, i+1] |
|
v[i] = 1.0 |
|
H = np.eye(n, n, dtype=dtype) - tau[i] * np.outer(v, v) |
|
Q = np.dot(H, Q) |
|
|
|
|
|
i_lower = np.tril_indices(n, -1) |
|
A[i_lower] = A.T[i_lower] |
|
|
|
QTAQ = np.dot(Q.T, np.dot(A, Q)) |
|
|
|
|
|
|
|
assert_allclose(QTAQ, T, atol=5*np.finfo(dtype).eps, rtol=1.0) |
|
|
|
|
|
class TestHetrd: |
|
@pytest.mark.parametrize('complex_dtype', COMPLEX_DTYPES) |
|
def test_hetrd_with_zero_dim_array(self, complex_dtype): |
|
|
|
A = np.zeros((0, 0), dtype=complex_dtype) |
|
hetrd = get_lapack_funcs('hetrd', (A,)) |
|
assert_raises(ValueError, hetrd, A) |
|
|
|
@pytest.mark.parametrize('real_dtype,complex_dtype', |
|
zip(REAL_DTYPES, COMPLEX_DTYPES)) |
|
@pytest.mark.parametrize('n', (1, 3)) |
|
def test_hetrd(self, n, real_dtype, complex_dtype): |
|
A = np.zeros((n, n), dtype=complex_dtype) |
|
hetrd, hetrd_lwork = \ |
|
get_lapack_funcs(('hetrd', 'hetrd_lwork'), (A,)) |
|
|
|
|
|
A[np.triu_indices_from(A)] = ( |
|
np.arange(1, n*(n+1)//2+1, dtype=real_dtype) |
|
+ 1j * np.arange(1, n*(n+1)//2+1, dtype=real_dtype) |
|
) |
|
np.fill_diagonal(A, np.real(np.diag(A))) |
|
|
|
|
|
for x in [0, 1]: |
|
_, info = hetrd_lwork(n, lower=x) |
|
assert_equal(info, 0) |
|
|
|
|
|
lwork = _compute_lwork(hetrd_lwork, n) |
|
|
|
|
|
|
|
data, d, e, tau, info = hetrd(A, lower=1, lwork=lwork) |
|
assert_equal(info, 0) |
|
|
|
assert_allclose(data, A, atol=5*np.finfo(real_dtype).eps, rtol=1.0) |
|
|
|
assert_allclose(d, np.real(np.diag(A))) |
|
assert_allclose(e, 0.0) |
|
assert_allclose(tau, 0.0) |
|
|
|
|
|
data, d, e, tau, info = hetrd(A, lwork=lwork) |
|
assert_equal(info, 0) |
|
|
|
|
|
|
|
|
|
T = np.zeros_like(A, dtype=real_dtype) |
|
k = np.arange(A.shape[0], dtype=int) |
|
T[k, k] = d |
|
k2 = np.arange(A.shape[0]-1, dtype=int) |
|
T[k2+1, k2] = e |
|
T[k2, k2+1] = e |
|
|
|
|
|
Q = np.eye(n, n, dtype=complex_dtype) |
|
for i in range(n-1): |
|
v = np.zeros(n, dtype=complex_dtype) |
|
v[:i] = data[:i, i+1] |
|
v[i] = 1.0 |
|
H = np.eye(n, n, dtype=complex_dtype) \ |
|
- tau[i] * np.outer(v, np.conj(v)) |
|
Q = np.dot(H, Q) |
|
|
|
|
|
i_lower = np.tril_indices(n, -1) |
|
A[i_lower] = np.conj(A.T[i_lower]) |
|
|
|
QHAQ = np.dot(np.conj(Q.T), np.dot(A, Q)) |
|
|
|
|
|
|
|
assert_allclose( |
|
QHAQ, T, atol=10*np.finfo(real_dtype).eps, rtol=1.0 |
|
) |
|
|
|
|
|
def test_gglse(): |
|
|
|
for ind, dtype in enumerate(DTYPES): |
|
|
|
func, func_lwork = get_lapack_funcs(('gglse', 'gglse_lwork'), |
|
dtype=dtype) |
|
lwork = _compute_lwork(func_lwork, m=6, n=4, p=2) |
|
|
|
if ind < 2: |
|
a = np.array([[-0.57, -1.28, -0.39, 0.25], |
|
[-1.93, 1.08, -0.31, -2.14], |
|
[2.30, 0.24, 0.40, -0.35], |
|
[-1.93, 0.64, -0.66, 0.08], |
|
[0.15, 0.30, 0.15, -2.13], |
|
[-0.02, 1.03, -1.43, 0.50]], dtype=dtype) |
|
c = np.array([-1.50, -2.14, 1.23, -0.54, -1.68, 0.82], dtype=dtype) |
|
d = np.array([0., 0.], dtype=dtype) |
|
|
|
else: |
|
a = np.array([[0.96-0.81j, -0.03+0.96j, -0.91+2.06j, -0.05+0.41j], |
|
[-0.98+1.98j, -1.20+0.19j, -0.66+0.42j, -0.81+0.56j], |
|
[0.62-0.46j, 1.01+0.02j, 0.63-0.17j, -1.11+0.60j], |
|
[0.37+0.38j, 0.19-0.54j, -0.98-0.36j, 0.22-0.20j], |
|
[0.83+0.51j, 0.20+0.01j, -0.17-0.46j, 1.47+1.59j], |
|
[1.08-0.28j, 0.20-0.12j, -0.07+1.23j, 0.26+0.26j]]) |
|
c = np.array([[-2.54+0.09j], |
|
[1.65-2.26j], |
|
[-2.11-3.96j], |
|
[1.82+3.30j], |
|
[-6.41+3.77j], |
|
[2.07+0.66j]]) |
|
d = np.zeros(2, dtype=dtype) |
|
|
|
b = np.array([[1., 0., -1., 0.], [0., 1., 0., -1.]], dtype=dtype) |
|
|
|
_, _, _, result, _ = func(a, b, c, d, lwork=lwork) |
|
if ind < 2: |
|
expected = np.array([0.48904455, |
|
0.99754786, |
|
0.48904455, |
|
0.99754786]) |
|
else: |
|
expected = np.array([1.08742917-1.96205783j, |
|
-0.74093902+3.72973919j, |
|
1.08742917-1.96205759j, |
|
-0.74093896+3.72973895j]) |
|
assert_array_almost_equal(result, expected, decimal=4) |
|
|
|
|
|
def test_sycon_hecon(): |
|
seed(1234) |
|
for ind, dtype in enumerate(DTYPES+COMPLEX_DTYPES): |
|
|
|
n = 10 |
|
|
|
if ind < 4: |
|
func_lwork = get_lapack_funcs('sytrf_lwork', dtype=dtype) |
|
funcon, functrf = get_lapack_funcs(('sycon', 'sytrf'), dtype=dtype) |
|
A = (rand(n, n)).astype(dtype) |
|
|
|
else: |
|
func_lwork = get_lapack_funcs('hetrf_lwork', dtype=dtype) |
|
funcon, functrf = get_lapack_funcs(('hecon', 'hetrf'), dtype=dtype) |
|
A = (rand(n, n) + rand(n, n)*1j).astype(dtype) |
|
|
|
|
|
A = (A + A.conj().T)/2 + 2*np.eye(n, dtype=dtype) |
|
|
|
anorm = norm(A, 1) |
|
lwork = _compute_lwork(func_lwork, n) |
|
ldu, ipiv, _ = functrf(A, lwork=lwork, lower=1) |
|
rcond, _ = funcon(a=ldu, ipiv=ipiv, anorm=anorm, lower=1) |
|
|
|
assert_(abs(1/rcond - np.linalg.cond(A, p=1))*rcond < 1) |
|
|
|
|
|
def test_sygst(): |
|
seed(1234) |
|
for ind, dtype in enumerate(REAL_DTYPES): |
|
|
|
n = 10 |
|
|
|
potrf, sygst, syevd, sygvd = get_lapack_funcs(('potrf', 'sygst', |
|
'syevd', 'sygvd'), |
|
dtype=dtype) |
|
|
|
A = rand(n, n).astype(dtype) |
|
A = (A + A.T)/2 |
|
|
|
B = rand(n, n).astype(dtype) |
|
B = (B + B.T)/2 + 2 * np.eye(n, dtype=dtype) |
|
|
|
|
|
eig_gvd, _, info = sygvd(A, B) |
|
assert_(info == 0) |
|
|
|
|
|
b, info = potrf(B) |
|
assert_(info == 0) |
|
a, info = sygst(A, b) |
|
assert_(info == 0) |
|
|
|
eig, _, info = syevd(a) |
|
assert_(info == 0) |
|
assert_allclose(eig, eig_gvd, rtol=1.2e-4) |
|
|
|
|
|
def test_hegst(): |
|
seed(1234) |
|
for ind, dtype in enumerate(COMPLEX_DTYPES): |
|
|
|
n = 10 |
|
|
|
potrf, hegst, heevd, hegvd = get_lapack_funcs(('potrf', 'hegst', |
|
'heevd', 'hegvd'), |
|
dtype=dtype) |
|
|
|
A = rand(n, n).astype(dtype) + 1j * rand(n, n).astype(dtype) |
|
A = (A + A.conj().T)/2 |
|
|
|
B = rand(n, n).astype(dtype) + 1j * rand(n, n).astype(dtype) |
|
B = (B + B.conj().T)/2 + 2 * np.eye(n, dtype=dtype) |
|
|
|
|
|
eig_gvd, _, info = hegvd(A, B) |
|
assert_(info == 0) |
|
|
|
|
|
b, info = potrf(B) |
|
assert_(info == 0) |
|
a, info = hegst(A, b) |
|
assert_(info == 0) |
|
|
|
eig, _, info = heevd(a) |
|
assert_(info == 0) |
|
assert_allclose(eig, eig_gvd, rtol=1e-4) |
|
|
|
|
|
def test_tzrzf(): |
|
""" |
|
This test performs an RZ decomposition in which an m x n upper trapezoidal |
|
array M (m <= n) is factorized as M = [R 0] * Z where R is upper triangular |
|
and Z is unitary. |
|
""" |
|
rng = np.random.RandomState(1234) |
|
m, n = 10, 15 |
|
for ind, dtype in enumerate(DTYPES): |
|
tzrzf, tzrzf_lw = get_lapack_funcs(('tzrzf', 'tzrzf_lwork'), |
|
dtype=dtype) |
|
lwork = _compute_lwork(tzrzf_lw, m, n) |
|
|
|
if ind < 2: |
|
A = triu(rng.rand(m, n).astype(dtype)) |
|
else: |
|
A = triu((rng.rand(m, n) + rng.rand(m, n)*1j).astype(dtype)) |
|
|
|
|
|
assert_raises(Exception, tzrzf, A.T) |
|
rz, tau, info = tzrzf(A, lwork=lwork) |
|
|
|
assert_(info == 0) |
|
|
|
|
|
R = np.hstack((rz[:, :m], np.zeros((m, n-m), dtype=dtype))) |
|
V = np.hstack((np.eye(m, dtype=dtype), rz[:, m:])) |
|
Id = np.eye(n, dtype=dtype) |
|
ref = [Id-tau[x]*V[[x], :].T.dot(V[[x], :].conj()) for x in range(m)] |
|
Z = reduce(np.dot, ref) |
|
assert_allclose(R.dot(Z) - A, zeros_like(A, dtype=dtype), |
|
atol=10*np.spacing(dtype(1.0).real), rtol=0.) |
|
|
|
|
|
def test_tfsm(): |
|
""" |
|
Test for solving a linear system with the coefficient matrix is a |
|
triangular array stored in Full Packed (RFP) format. |
|
""" |
|
rng = np.random.RandomState(1234) |
|
for ind, dtype in enumerate(DTYPES): |
|
n = 20 |
|
if ind > 1: |
|
A = triu(rng.rand(n, n) + rng.rand(n, n)*1j + eye(n)).astype(dtype) |
|
trans = 'C' |
|
else: |
|
A = triu(rng.rand(n, n) + eye(n)).astype(dtype) |
|
trans = 'T' |
|
|
|
trttf, tfttr, tfsm = get_lapack_funcs(('trttf', 'tfttr', 'tfsm'), |
|
dtype=dtype) |
|
|
|
Afp, _ = trttf(A) |
|
B = rng.rand(n, 2).astype(dtype) |
|
soln = tfsm(-1, Afp, B) |
|
assert_array_almost_equal(soln, solve(-A, B), |
|
decimal=4 if ind % 2 == 0 else 6) |
|
|
|
soln = tfsm(-1, Afp, B, trans=trans) |
|
assert_array_almost_equal(soln, solve(-A.conj().T, B), |
|
decimal=4 if ind % 2 == 0 else 6) |
|
|
|
|
|
A[np.arange(n), np.arange(n)] = dtype(1.) |
|
soln = tfsm(-1, Afp, B, trans=trans, diag='U') |
|
assert_array_almost_equal(soln, solve(-A.conj().T, B), |
|
decimal=4 if ind % 2 == 0 else 6) |
|
|
|
|
|
B2 = rng.rand(3, n).astype(dtype) |
|
soln = tfsm(-1, Afp, B2, trans=trans, diag='U', side='R') |
|
assert_array_almost_equal(soln, solve(-A, B2.T).conj().T, |
|
decimal=4 if ind % 2 == 0 else 6) |
|
|
|
|
|
def test_ormrz_unmrz(): |
|
""" |
|
This test performs a matrix multiplication with an arbitrary m x n matrix C |
|
and a unitary matrix Q without explicitly forming the array. The array data |
|
is encoded in the rectangular part of A which is obtained from ?TZRZF. Q |
|
size is inferred by m, n, side keywords. |
|
""" |
|
rng = np.random.RandomState(1234) |
|
qm, qn, cn = 10, 15, 15 |
|
for ind, dtype in enumerate(DTYPES): |
|
tzrzf, tzrzf_lw = get_lapack_funcs(('tzrzf', 'tzrzf_lwork'), |
|
dtype=dtype) |
|
lwork_rz = _compute_lwork(tzrzf_lw, qm, qn) |
|
|
|
if ind < 2: |
|
A = triu(rng.rand(qm, qn).astype(dtype)) |
|
C = rng.rand(cn, cn).astype(dtype) |
|
orun_mrz, orun_mrz_lw = get_lapack_funcs(('ormrz', 'ormrz_lwork'), |
|
dtype=dtype) |
|
else: |
|
A = triu((rng.rand(qm, qn) + rng.rand(qm, qn)*1j).astype(dtype)) |
|
C = (rng.rand(cn, cn) + rand(cn, cn)*1j).astype(dtype) |
|
orun_mrz, orun_mrz_lw = get_lapack_funcs(('unmrz', 'unmrz_lwork'), |
|
dtype=dtype) |
|
|
|
lwork_mrz = _compute_lwork(orun_mrz_lw, cn, cn) |
|
rz, tau, info = tzrzf(A, lwork=lwork_rz) |
|
|
|
|
|
V = np.hstack((np.eye(qm, dtype=dtype), rz[:, qm:])) |
|
Id = np.eye(qn, dtype=dtype) |
|
ref = [Id-tau[x]*V[[x], :].T.dot(V[[x], :].conj()) for x in range(qm)] |
|
Q = reduce(np.dot, ref) |
|
|
|
|
|
|
|
trans = 'T' if ind < 2 else 'C' |
|
tol = 10*np.spacing(dtype(1.0).real) |
|
|
|
cq, info = orun_mrz(rz, tau, C, lwork=lwork_mrz) |
|
assert_(info == 0) |
|
assert_allclose(cq - Q.dot(C), zeros_like(C), atol=tol, rtol=0.) |
|
|
|
cq, info = orun_mrz(rz, tau, C, trans=trans, lwork=lwork_mrz) |
|
assert_(info == 0) |
|
assert_allclose(cq - Q.conj().T.dot(C), zeros_like(C), atol=tol, |
|
rtol=0.) |
|
|
|
cq, info = orun_mrz(rz, tau, C, side='R', lwork=lwork_mrz) |
|
assert_(info == 0) |
|
assert_allclose(cq - C.dot(Q), zeros_like(C), atol=tol, rtol=0.) |
|
|
|
cq, info = orun_mrz(rz, tau, C, side='R', trans=trans, lwork=lwork_mrz) |
|
assert_(info == 0) |
|
assert_allclose(cq - C.dot(Q.conj().T), zeros_like(C), atol=tol, |
|
rtol=0.) |
|
|
|
|
|
def test_tfttr_trttf(): |
|
""" |
|
Test conversion routines between the Rectangular Full Packed (RFP) format |
|
and Standard Triangular Array (TR) |
|
""" |
|
rng = np.random.RandomState(1234) |
|
for ind, dtype in enumerate(DTYPES): |
|
n = 20 |
|
if ind > 1: |
|
A_full = (rng.rand(n, n) + rng.rand(n, n)*1j).astype(dtype) |
|
transr = 'C' |
|
else: |
|
A_full = (rng.rand(n, n)).astype(dtype) |
|
transr = 'T' |
|
|
|
trttf, tfttr = get_lapack_funcs(('trttf', 'tfttr'), dtype=dtype) |
|
A_tf_U, info = trttf(A_full) |
|
assert_(info == 0) |
|
A_tf_L, info = trttf(A_full, uplo='L') |
|
assert_(info == 0) |
|
A_tf_U_T, info = trttf(A_full, transr=transr, uplo='U') |
|
assert_(info == 0) |
|
A_tf_L_T, info = trttf(A_full, transr=transr, uplo='L') |
|
assert_(info == 0) |
|
|
|
|
|
A_tf_U_m = zeros((n+1, n//2), dtype=dtype) |
|
A_tf_U_m[:-1, :] = triu(A_full)[:, n//2:] |
|
A_tf_U_m[n//2+1:, :] += triu(A_full)[:n//2, :n//2].conj().T |
|
|
|
A_tf_L_m = zeros((n+1, n//2), dtype=dtype) |
|
A_tf_L_m[1:, :] = tril(A_full)[:, :n//2] |
|
A_tf_L_m[:n//2, :] += tril(A_full)[n//2:, n//2:].conj().T |
|
|
|
assert_array_almost_equal(A_tf_U, A_tf_U_m.reshape(-1, order='F')) |
|
assert_array_almost_equal(A_tf_U_T, |
|
A_tf_U_m.conj().T.reshape(-1, order='F')) |
|
|
|
assert_array_almost_equal(A_tf_L, A_tf_L_m.reshape(-1, order='F')) |
|
assert_array_almost_equal(A_tf_L_T, |
|
A_tf_L_m.conj().T.reshape(-1, order='F')) |
|
|
|
|
|
A_tr_U, info = tfttr(n, A_tf_U) |
|
assert_(info == 0) |
|
A_tr_L, info = tfttr(n, A_tf_L, uplo='L') |
|
assert_(info == 0) |
|
A_tr_U_T, info = tfttr(n, A_tf_U_T, transr=transr, uplo='U') |
|
assert_(info == 0) |
|
A_tr_L_T, info = tfttr(n, A_tf_L_T, transr=transr, uplo='L') |
|
assert_(info == 0) |
|
|
|
assert_array_almost_equal(A_tr_U, triu(A_full)) |
|
assert_array_almost_equal(A_tr_U_T, triu(A_full)) |
|
assert_array_almost_equal(A_tr_L, tril(A_full)) |
|
assert_array_almost_equal(A_tr_L_T, tril(A_full)) |
|
|
|
|
|
def test_tpttr_trttp(): |
|
""" |
|
Test conversion routines between the Rectangular Full Packed (RFP) format |
|
and Standard Triangular Array (TR) |
|
""" |
|
rng = np.random.RandomState(1234) |
|
for ind, dtype in enumerate(DTYPES): |
|
n = 20 |
|
if ind > 1: |
|
A_full = (rng.rand(n, n) + rng.rand(n, n)*1j).astype(dtype) |
|
else: |
|
A_full = (rng.rand(n, n)).astype(dtype) |
|
|
|
trttp, tpttr = get_lapack_funcs(('trttp', 'tpttr'), dtype=dtype) |
|
A_tp_U, info = trttp(A_full) |
|
assert_(info == 0) |
|
A_tp_L, info = trttp(A_full, uplo='L') |
|
assert_(info == 0) |
|
|
|
|
|
inds = tril_indices(n) |
|
A_tp_U_m = zeros(n*(n+1)//2, dtype=dtype) |
|
A_tp_U_m[:] = (triu(A_full).T)[inds] |
|
|
|
inds = triu_indices(n) |
|
A_tp_L_m = zeros(n*(n+1)//2, dtype=dtype) |
|
A_tp_L_m[:] = (tril(A_full).T)[inds] |
|
|
|
assert_array_almost_equal(A_tp_U, A_tp_U_m) |
|
assert_array_almost_equal(A_tp_L, A_tp_L_m) |
|
|
|
|
|
A_tr_U, info = tpttr(n, A_tp_U) |
|
assert_(info == 0) |
|
A_tr_L, info = tpttr(n, A_tp_L, uplo='L') |
|
assert_(info == 0) |
|
|
|
assert_array_almost_equal(A_tr_U, triu(A_full)) |
|
assert_array_almost_equal(A_tr_L, tril(A_full)) |
|
|
|
|
|
def test_pftrf(): |
|
""" |
|
Test Cholesky factorization of a positive definite Rectangular Full |
|
Packed (RFP) format array |
|
""" |
|
rng = np.random.RandomState(1234) |
|
for ind, dtype in enumerate(DTYPES): |
|
n = 20 |
|
if ind > 1: |
|
A = (rng.rand(n, n) + rng.rand(n, n)*1j).astype(dtype) |
|
A = A + A.conj().T + n*eye(n) |
|
else: |
|
A = (rng.rand(n, n)).astype(dtype) |
|
A = A + A.T + n*eye(n) |
|
|
|
pftrf, trttf, tfttr = get_lapack_funcs(('pftrf', 'trttf', 'tfttr'), |
|
dtype=dtype) |
|
|
|
|
|
Afp, info = trttf(A) |
|
Achol_rfp, info = pftrf(n, Afp) |
|
assert_(info == 0) |
|
A_chol_r, _ = tfttr(n, Achol_rfp) |
|
Achol = cholesky(A) |
|
assert_array_almost_equal(A_chol_r, Achol) |
|
|
|
|
|
def test_pftri(): |
|
""" |
|
Test Cholesky factorization of a positive definite Rectangular Full |
|
Packed (RFP) format array to find its inverse |
|
""" |
|
rng = np.random.RandomState(1234) |
|
for ind, dtype in enumerate(DTYPES): |
|
n = 20 |
|
if ind > 1: |
|
A = (rng.rand(n, n) + rng.rand(n, n)*1j).astype(dtype) |
|
A = A + A.conj().T + n*eye(n) |
|
else: |
|
A = (rng.rand(n, n)).astype(dtype) |
|
A = A + A.T + n*eye(n) |
|
|
|
pftri, pftrf, trttf, tfttr = get_lapack_funcs(('pftri', |
|
'pftrf', |
|
'trttf', |
|
'tfttr'), |
|
dtype=dtype) |
|
|
|
|
|
Afp, info = trttf(A) |
|
A_chol_rfp, info = pftrf(n, Afp) |
|
A_inv_rfp, info = pftri(n, A_chol_rfp) |
|
assert_(info == 0) |
|
A_inv_r, _ = tfttr(n, A_inv_rfp) |
|
Ainv = inv(A) |
|
assert_array_almost_equal(A_inv_r, triu(Ainv), |
|
decimal=4 if ind % 2 == 0 else 6) |
|
|
|
|
|
def test_pftrs(): |
|
""" |
|
Test Cholesky factorization of a positive definite Rectangular Full |
|
Packed (RFP) format array and solve a linear system |
|
""" |
|
rng = np.random.RandomState(1234) |
|
for ind, dtype in enumerate(DTYPES): |
|
n = 20 |
|
if ind > 1: |
|
A = (rng.rand(n, n) + rng.rand(n, n)*1j).astype(dtype) |
|
A = A + A.conj().T + n*eye(n) |
|
else: |
|
A = (rng.rand(n, n)).astype(dtype) |
|
A = A + A.T + n*eye(n) |
|
|
|
B = ones((n, 3), dtype=dtype) |
|
Bf1 = ones((n+2, 3), dtype=dtype) |
|
Bf2 = ones((n-2, 3), dtype=dtype) |
|
pftrs, pftrf, trttf, tfttr = get_lapack_funcs(('pftrs', |
|
'pftrf', |
|
'trttf', |
|
'tfttr'), |
|
dtype=dtype) |
|
|
|
|
|
Afp, info = trttf(A) |
|
A_chol_rfp, info = pftrf(n, Afp) |
|
|
|
soln, info = pftrs(n, A_chol_rfp, Bf1) |
|
assert_(info == 0) |
|
assert_raises(Exception, pftrs, n, A_chol_rfp, Bf2) |
|
soln, info = pftrs(n, A_chol_rfp, B) |
|
assert_(info == 0) |
|
assert_array_almost_equal(solve(A, B), soln, |
|
decimal=4 if ind % 2 == 0 else 6) |
|
|
|
|
|
def test_sfrk_hfrk(): |
|
""" |
|
Test for performing a symmetric rank-k operation for matrix in RFP format. |
|
""" |
|
rng = np.random.RandomState(1234) |
|
for ind, dtype in enumerate(DTYPES): |
|
n = 20 |
|
if ind > 1: |
|
A = (rng.rand(n, n) + rng.rand(n, n)*1j).astype(dtype) |
|
A = A + A.conj().T + n*eye(n) |
|
else: |
|
A = (rng.rand(n, n)).astype(dtype) |
|
A = A + A.T + n*eye(n) |
|
|
|
prefix = 's'if ind < 2 else 'h' |
|
trttf, tfttr, shfrk = get_lapack_funcs(('trttf', 'tfttr', f'{prefix}frk'), |
|
dtype=dtype) |
|
|
|
Afp, _ = trttf(A) |
|
C = rng.rand(n, 2).astype(dtype) |
|
Afp_out = shfrk(n, 2, -1, C, 2, Afp) |
|
A_out, _ = tfttr(n, Afp_out) |
|
assert_array_almost_equal(A_out, triu(-C.dot(C.conj().T) + 2*A), |
|
decimal=4 if ind % 2 == 0 else 6) |
|
|
|
|
|
def test_syconv(): |
|
""" |
|
Test for going back and forth between the returned format of he/sytrf to |
|
L and D factors/permutations. |
|
""" |
|
rng = np.random.RandomState(1234) |
|
for ind, dtype in enumerate(DTYPES): |
|
n = 10 |
|
|
|
if ind > 1: |
|
A = (rng.randint(-30, 30, (n, n)) + |
|
rng.randint(-30, 30, (n, n))*1j).astype(dtype) |
|
|
|
A = A + A.conj().T |
|
else: |
|
A = rng.randint(-30, 30, (n, n)).astype(dtype) |
|
A = A + A.T + n*eye(n) |
|
|
|
tol = 100*np.spacing(dtype(1.0).real) |
|
syconv, trf, trf_lwork = get_lapack_funcs(('syconv', 'sytrf', |
|
'sytrf_lwork'), dtype=dtype) |
|
lw = _compute_lwork(trf_lwork, n, lower=1) |
|
L, D, perm = ldl(A, lower=1, hermitian=False) |
|
lw = _compute_lwork(trf_lwork, n, lower=1) |
|
ldu, ipiv, info = trf(A, lower=1, lwork=lw) |
|
a, e, info = syconv(ldu, ipiv, lower=1) |
|
assert_allclose(tril(a, -1,), tril(L[perm, :], -1), atol=tol, rtol=0.) |
|
|
|
|
|
U, D, perm = ldl(A, lower=0, hermitian=False) |
|
ldu, ipiv, info = trf(A, lower=0) |
|
a, e, info = syconv(ldu, ipiv, lower=0) |
|
assert_allclose(triu(a, 1), triu(U[perm, :], 1), atol=tol, rtol=0.) |
|
|
|
|
|
class TestBlockedQR: |
|
""" |
|
Tests for the blocked QR factorization, namely through geqrt, gemqrt, tpqrt |
|
and tpmqr. |
|
""" |
|
|
|
def test_geqrt_gemqrt(self): |
|
rng = np.random.RandomState(1234) |
|
for ind, dtype in enumerate(DTYPES): |
|
n = 20 |
|
|
|
if ind > 1: |
|
A = (rng.rand(n, n) + rng.rand(n, n)*1j).astype(dtype) |
|
else: |
|
A = (rng.rand(n, n)).astype(dtype) |
|
|
|
tol = 100*np.spacing(dtype(1.0).real) |
|
geqrt, gemqrt = get_lapack_funcs(('geqrt', 'gemqrt'), dtype=dtype) |
|
|
|
a, t, info = geqrt(n, A) |
|
assert info == 0 |
|
|
|
|
|
|
|
v = np.tril(a, -1) + np.eye(n, dtype=dtype) |
|
|
|
Q = np.eye(n, dtype=dtype) - v @ t @ v.T.conj() |
|
R = np.triu(a) |
|
|
|
|
|
assert_allclose(Q.T.conj() @ Q, np.eye(n, dtype=dtype), atol=tol, |
|
rtol=0.) |
|
assert_allclose(Q @ R, A, atol=tol, rtol=0.) |
|
|
|
if ind > 1: |
|
C = (rng.rand(n, n) + rng.rand(n, n)*1j).astype(dtype) |
|
transpose = 'C' |
|
else: |
|
C = (rng.rand(n, n)).astype(dtype) |
|
transpose = 'T' |
|
|
|
for side in ('L', 'R'): |
|
for trans in ('N', transpose): |
|
c, info = gemqrt(a, t, C, side=side, trans=trans) |
|
assert info == 0 |
|
|
|
if trans == transpose: |
|
q = Q.T.conj() |
|
else: |
|
q = Q |
|
|
|
if side == 'L': |
|
qC = q @ C |
|
else: |
|
qC = C @ q |
|
|
|
assert_allclose(c, qC, atol=tol, rtol=0.) |
|
|
|
|
|
if (side, trans) == ('L', 'N'): |
|
c_default, info = gemqrt(a, t, C) |
|
assert info == 0 |
|
assert_equal(c_default, c) |
|
|
|
|
|
assert_raises(Exception, gemqrt, a, t, C, side='A') |
|
assert_raises(Exception, gemqrt, a, t, C, trans='A') |
|
|
|
def test_tpqrt_tpmqrt(self): |
|
rng = np.random.RandomState(1234) |
|
for ind, dtype in enumerate(DTYPES): |
|
n = 20 |
|
|
|
if ind > 1: |
|
A = (rng.rand(n, n) + rng.rand(n, n)*1j).astype(dtype) |
|
B = (rng.rand(n, n) + rng.rand(n, n)*1j).astype(dtype) |
|
else: |
|
A = (rng.rand(n, n)).astype(dtype) |
|
B = (rng.rand(n, n)).astype(dtype) |
|
|
|
tol = 100*np.spacing(dtype(1.0).real) |
|
tpqrt, tpmqrt = get_lapack_funcs(('tpqrt', 'tpmqrt'), dtype=dtype) |
|
|
|
|
|
|
|
for l in (0, n // 2, n): |
|
a, b, t, info = tpqrt(l, n, A, B) |
|
assert info == 0 |
|
|
|
|
|
assert_equal(np.tril(a, -1), np.tril(A, -1)) |
|
|
|
|
|
assert_equal(np.tril(b, l - n - 1), np.tril(B, l - n - 1)) |
|
|
|
|
|
B_pent, b_pent = np.triu(B, l - n), np.triu(b, l - n) |
|
|
|
|
|
v = np.concatenate((np.eye(n, dtype=dtype), b_pent)) |
|
|
|
Q = np.eye(2 * n, dtype=dtype) - v @ t @ v.T.conj() |
|
R = np.concatenate((np.triu(a), np.zeros_like(a))) |
|
|
|
|
|
assert_allclose(Q.T.conj() @ Q, np.eye(2 * n, dtype=dtype), |
|
atol=tol, rtol=0.) |
|
assert_allclose(Q @ R, np.concatenate((np.triu(A), B_pent)), |
|
atol=tol, rtol=0.) |
|
|
|
if ind > 1: |
|
C = (rng.rand(n, n) + rng.rand(n, n)*1j).astype(dtype) |
|
D = (rng.rand(n, n) + rng.rand(n, n)*1j).astype(dtype) |
|
transpose = 'C' |
|
else: |
|
C = (rng.rand(n, n)).astype(dtype) |
|
D = (rng.rand(n, n)).astype(dtype) |
|
transpose = 'T' |
|
|
|
for side in ('L', 'R'): |
|
for trans in ('N', transpose): |
|
c, d, info = tpmqrt(l, b, t, C, D, side=side, |
|
trans=trans) |
|
assert info == 0 |
|
|
|
if trans == transpose: |
|
q = Q.T.conj() |
|
else: |
|
q = Q |
|
|
|
if side == 'L': |
|
cd = np.concatenate((c, d), axis=0) |
|
CD = np.concatenate((C, D), axis=0) |
|
qCD = q @ CD |
|
else: |
|
cd = np.concatenate((c, d), axis=1) |
|
CD = np.concatenate((C, D), axis=1) |
|
qCD = CD @ q |
|
|
|
assert_allclose(cd, qCD, atol=tol, rtol=0.) |
|
|
|
if (side, trans) == ('L', 'N'): |
|
c_default, d_default, info = tpmqrt(l, b, t, C, D) |
|
assert info == 0 |
|
assert_equal(c_default, c) |
|
assert_equal(d_default, d) |
|
|
|
|
|
assert_raises(Exception, tpmqrt, l, b, t, C, D, side='A') |
|
assert_raises(Exception, tpmqrt, l, b, t, C, D, trans='A') |
|
|
|
|
|
def test_pstrf(): |
|
rng = np.random.RandomState(1234) |
|
for ind, dtype in enumerate(DTYPES): |
|
|
|
n = 10 |
|
r = 2 |
|
pstrf = get_lapack_funcs('pstrf', dtype=dtype) |
|
|
|
|
|
if ind > 1: |
|
A = rng.rand(n, n-r).astype(dtype) + 1j * rng.rand(n, n-r).astype(dtype) |
|
A = A @ A.conj().T |
|
else: |
|
A = rng.rand(n, n-r).astype(dtype) |
|
A = A @ A.T |
|
|
|
c, piv, r_c, info = pstrf(A) |
|
U = triu(c) |
|
U[r_c - n:, r_c - n:] = 0. |
|
|
|
assert_equal(info, 1) |
|
|
|
|
|
single_atol = 1000 * np.finfo(np.float32).eps |
|
double_atol = 1000 * np.finfo(np.float64).eps |
|
atol = single_atol if ind in [0, 2] else double_atol |
|
assert_allclose(A[piv-1][:, piv-1], U.conj().T @ U, rtol=0., atol=atol) |
|
|
|
c, piv, r_c, info = pstrf(A, lower=1) |
|
L = tril(c) |
|
L[r_c - n:, r_c - n:] = 0. |
|
|
|
assert_equal(info, 1) |
|
|
|
single_atol = 1000 * np.finfo(np.float32).eps |
|
double_atol = 1000 * np.finfo(np.float64).eps |
|
atol = single_atol if ind in [0, 2] else double_atol |
|
assert_allclose(A[piv-1][:, piv-1], L @ L.conj().T, rtol=0., atol=atol) |
|
|
|
|
|
def test_pstf2(): |
|
rng = np.random.RandomState(1234) |
|
for ind, dtype in enumerate(DTYPES): |
|
|
|
n = 10 |
|
r = 2 |
|
pstf2 = get_lapack_funcs('pstf2', dtype=dtype) |
|
|
|
|
|
if ind > 1: |
|
A = rng.rand(n, n-r).astype(dtype) + 1j * rng.rand(n, n-r).astype(dtype) |
|
A = A @ A.conj().T |
|
else: |
|
A = rng.rand(n, n-r).astype(dtype) |
|
A = A @ A.T |
|
|
|
c, piv, r_c, info = pstf2(A) |
|
U = triu(c) |
|
U[r_c - n:, r_c - n:] = 0. |
|
|
|
assert_equal(info, 1) |
|
|
|
|
|
single_atol = 1000 * np.finfo(np.float32).eps |
|
double_atol = 1000 * np.finfo(np.float64).eps |
|
atol = single_atol if ind in [0, 2] else double_atol |
|
assert_allclose(A[piv-1][:, piv-1], U.conj().T @ U, rtol=0., atol=atol) |
|
|
|
c, piv, r_c, info = pstf2(A, lower=1) |
|
L = tril(c) |
|
L[r_c - n:, r_c - n:] = 0. |
|
|
|
assert_equal(info, 1) |
|
|
|
single_atol = 1000 * np.finfo(np.float32).eps |
|
double_atol = 1000 * np.finfo(np.float64).eps |
|
atol = single_atol if ind in [0, 2] else double_atol |
|
assert_allclose(A[piv-1][:, piv-1], L @ L.conj().T, rtol=0., atol=atol) |
|
|
|
|
|
def test_geequ(): |
|
desired_real = np.array([[0.6250, 1.0000, 0.0393, -0.4269], |
|
[1.0000, -0.5619, -1.0000, -1.0000], |
|
[0.5874, -1.0000, -0.0596, -0.5341], |
|
[-1.0000, -0.5946, -0.0294, 0.9957]]) |
|
|
|
desired_cplx = np.array([[-0.2816+0.5359*1j, |
|
0.0812+0.9188*1j, |
|
-0.7439-0.2561*1j], |
|
[-0.3562-0.2954*1j, |
|
0.9566-0.0434*1j, |
|
-0.0174+0.1555*1j], |
|
[0.8607+0.1393*1j, |
|
-0.2759+0.7241*1j, |
|
-0.1642-0.1365*1j]]) |
|
|
|
for ind, dtype in enumerate(DTYPES): |
|
if ind < 2: |
|
|
|
A = np.array([[1.80e+10, 2.88e+10, 2.05e+00, -8.90e+09], |
|
[5.25e+00, -2.95e+00, -9.50e-09, -3.80e+00], |
|
[1.58e+00, -2.69e+00, -2.90e-10, -1.04e+00], |
|
[-1.11e+00, -6.60e-01, -5.90e-11, 8.00e-01]]) |
|
A = A.astype(dtype) |
|
else: |
|
A = np.array([[-1.34e+00, 0.28e+10, -6.39e+00], |
|
[-1.70e+00, 3.31e+10, -0.15e+00], |
|
[2.41e-10, -0.56e+00, -0.83e-10]], dtype=dtype) |
|
A += np.array([[2.55e+00, 3.17e+10, -2.20e+00], |
|
[-1.41e+00, -0.15e+10, 1.34e+00], |
|
[0.39e-10, 1.47e+00, -0.69e-10]])*1j |
|
|
|
A = A.astype(dtype) |
|
|
|
geequ = get_lapack_funcs('geequ', dtype=dtype) |
|
r, c, rowcnd, colcnd, amax, info = geequ(A) |
|
|
|
if ind < 2: |
|
assert_allclose(desired_real.astype(dtype), r[:, None]*A*c, |
|
rtol=0, atol=1e-4) |
|
else: |
|
assert_allclose(desired_cplx.astype(dtype), r[:, None]*A*c, |
|
rtol=0, atol=1e-4) |
|
|
|
|
|
def test_syequb(): |
|
desired_log2s = np.array([0, 0, 0, 0, 0, 0, -1, -1, -2, -3]) |
|
|
|
for ind, dtype in enumerate(DTYPES): |
|
A = np.eye(10, dtype=dtype) |
|
alpha = dtype(1. if ind < 2 else 1.j) |
|
d = np.array([alpha * 2.**x for x in range(-5, 5)], dtype=dtype) |
|
A += np.rot90(np.diag(d)) |
|
|
|
syequb = get_lapack_funcs('syequb', dtype=dtype) |
|
s, scond, amax, info = syequb(A) |
|
|
|
assert_equal(np.log2(s).astype(int), desired_log2s) |
|
|
|
|
|
@pytest.mark.skipif(True, |
|
reason="Failing on some OpenBLAS version, see gh-12276") |
|
def test_heequb(): |
|
|
|
|
|
|
|
|
|
A = np.diag([2]*5 + [1002]*5) + np.diag(np.ones(9), k=1)*1j |
|
s, scond, amax, info = lapack.zheequb(A) |
|
assert_equal(info, 0) |
|
assert_allclose(np.log2(s), [0., -1.]*2 + [0.] + [-4]*5) |
|
|
|
A = np.diag(2**np.abs(np.arange(-5, 6)) + 0j) |
|
A[5, 5] = 1024 |
|
A[5, 0] = 16j |
|
s, scond, amax, info = lapack.cheequb(A.astype(np.complex64), lower=1) |
|
assert_equal(info, 0) |
|
assert_allclose(np.log2(s), [-2, -1, -1, 0, 0, -5, 0, -1, -1, -2, -2]) |
|
|
|
|
|
def test_getc2_gesc2(): |
|
rng = np.random.RandomState(42) |
|
n = 10 |
|
desired_real = rng.rand(n) |
|
desired_cplx = rng.rand(n) + rng.rand(n)*1j |
|
|
|
for ind, dtype in enumerate(DTYPES): |
|
if ind < 2: |
|
A = rng.rand(n, n) |
|
A = A.astype(dtype) |
|
b = A @ desired_real |
|
b = b.astype(dtype) |
|
else: |
|
A = rng.rand(n, n) + rng.rand(n, n)*1j |
|
A = A.astype(dtype) |
|
b = A @ desired_cplx |
|
b = b.astype(dtype) |
|
|
|
getc2 = get_lapack_funcs('getc2', dtype=dtype) |
|
gesc2 = get_lapack_funcs('gesc2', dtype=dtype) |
|
lu, ipiv, jpiv, info = getc2(A, overwrite_a=0) |
|
x, scale = gesc2(lu, b, ipiv, jpiv, overwrite_rhs=0) |
|
|
|
if ind < 2: |
|
assert_array_almost_equal(desired_real.astype(dtype), |
|
x/scale, decimal=4) |
|
else: |
|
assert_array_almost_equal(desired_cplx.astype(dtype), |
|
x/scale, decimal=4) |
|
|
|
|
|
@pytest.mark.parametrize('size', [(6, 5), (5, 5)]) |
|
@pytest.mark.parametrize('dtype', REAL_DTYPES) |
|
@pytest.mark.parametrize('joba', range(6)) |
|
@pytest.mark.parametrize('jobu', range(4)) |
|
@pytest.mark.parametrize('jobv', range(4)) |
|
@pytest.mark.parametrize('jobr', [0, 1]) |
|
@pytest.mark.parametrize('jobp', [0, 1]) |
|
def test_gejsv_general(size, dtype, joba, jobu, jobv, jobr, jobp, jobt=0): |
|
"""Test the lapack routine ?gejsv. |
|
|
|
This function tests that a singular value decomposition can be performed |
|
on the random M-by-N matrix A. The test performs the SVD using ?gejsv |
|
then performs the following checks: |
|
|
|
* ?gejsv exist successfully (info == 0) |
|
* The returned singular values are correct |
|
* `A` can be reconstructed from `u`, `SIGMA`, `v` |
|
* Ensure that u.T @ u is the identity matrix |
|
* Ensure that v.T @ v is the identity matrix |
|
* The reported matrix rank |
|
* The reported number of singular values |
|
* If denormalized floats are required |
|
|
|
Notes |
|
----- |
|
joba specifies several choices effecting the calculation's accuracy |
|
Although all arguments are tested, the tests only check that the correct |
|
solution is returned - NOT that the prescribed actions are performed |
|
internally. |
|
|
|
jobt is, as of v3.9.0, still experimental and removed to cut down number of |
|
test cases. However keyword itself is tested externally. |
|
""" |
|
rng = np.random.RandomState(42) |
|
|
|
|
|
m, n = size |
|
atol = 100 * np.finfo(dtype).eps |
|
A = generate_random_dtype_array(size, dtype, rng) |
|
gejsv = get_lapack_funcs('gejsv', dtype=dtype) |
|
|
|
|
|
|
|
|
|
lsvec = jobu < 2 |
|
rsvec = jobv < 2 |
|
l2tran = (jobt == 1) and (m == n) |
|
is_complex = np.iscomplexobj(A) |
|
|
|
invalid_real_jobv = (jobv == 1) and (not lsvec) and (not is_complex) |
|
invalid_cplx_jobu = (jobu == 2) and not (rsvec and l2tran) and is_complex |
|
invalid_cplx_jobv = (jobv == 2) and not (lsvec and l2tran) and is_complex |
|
|
|
|
|
|
|
|
|
if invalid_cplx_jobu: |
|
exit_status = -2 |
|
elif invalid_real_jobv or invalid_cplx_jobv: |
|
exit_status = -3 |
|
else: |
|
exit_status = 0 |
|
|
|
if (jobu > 1) and (jobv == 1): |
|
assert_raises(Exception, gejsv, A, joba, jobu, jobv, jobr, jobt, jobp) |
|
else: |
|
sva, u, v, work, iwork, info = gejsv(A, |
|
joba=joba, |
|
jobu=jobu, |
|
jobv=jobv, |
|
jobr=jobr, |
|
jobt=jobt, |
|
jobp=jobp) |
|
|
|
|
|
assert_equal(info, exit_status) |
|
|
|
|
|
|
|
if not exit_status: |
|
|
|
|
|
sigma = (work[0] / work[1]) * sva[:n] |
|
assert_allclose(sigma, svd(A, compute_uv=False), atol=atol) |
|
|
|
if jobu == 1: |
|
|
|
|
|
|
|
|
|
|
|
|
|
u = u[:, :n] |
|
|
|
if lsvec and rsvec: |
|
assert_allclose(u @ np.diag(sigma) @ v.conj().T, A, atol=atol) |
|
if lsvec: |
|
assert_allclose(u.conj().T @ u, np.identity(n), atol=atol) |
|
if rsvec: |
|
assert_allclose(v.conj().T @ v, np.identity(n), atol=atol) |
|
|
|
assert_equal(iwork[0], np.linalg.matrix_rank(A)) |
|
assert_equal(iwork[1], np.count_nonzero(sigma)) |
|
|
|
|
|
assert_equal(iwork[2], 0) |
|
|
|
|
|
@pytest.mark.parametrize('dtype', REAL_DTYPES) |
|
def test_gejsv_edge_arguments(dtype): |
|
"""Test edge arguments return expected status""" |
|
gejsv = get_lapack_funcs('gejsv', dtype=dtype) |
|
|
|
|
|
sva, u, v, work, iwork, info = gejsv(1.) |
|
assert_equal(info, 0) |
|
assert_equal(u.shape, (1, 1)) |
|
assert_equal(v.shape, (1, 1)) |
|
assert_equal(sva, np.array([1.], dtype=dtype)) |
|
|
|
|
|
A = np.ones((1,), dtype=dtype) |
|
sva, u, v, work, iwork, info = gejsv(A) |
|
assert_equal(info, 0) |
|
assert_equal(u.shape, (1, 1)) |
|
assert_equal(v.shape, (1, 1)) |
|
assert_equal(sva, np.array([1.], dtype=dtype)) |
|
|
|
|
|
A = np.ones((1, 0), dtype=dtype) |
|
sva, u, v, work, iwork, info = gejsv(A) |
|
assert_equal(info, 0) |
|
assert_equal(u.shape, (1, 0)) |
|
assert_equal(v.shape, (1, 0)) |
|
assert_equal(sva, np.array([], dtype=dtype)) |
|
|
|
|
|
A = np.sin(np.arange(100).reshape(10, 10)).astype(dtype) |
|
A = np.asfortranarray(A + A.T) |
|
Ac = A.copy('A') |
|
_ = gejsv(A) |
|
assert_allclose(A, Ac) |
|
|
|
|
|
@pytest.mark.parametrize(('kwargs'), |
|
({'joba': 9}, |
|
{'jobu': 9}, |
|
{'jobv': 9}, |
|
{'jobr': 9}, |
|
{'jobt': 9}, |
|
{'jobp': 9}) |
|
) |
|
def test_gejsv_invalid_job_arguments(kwargs): |
|
"""Test invalid job arguments raise an Exception""" |
|
A = np.ones((2, 2), dtype=float) |
|
gejsv = get_lapack_funcs('gejsv', dtype=float) |
|
assert_raises(Exception, gejsv, A, **kwargs) |
|
|
|
|
|
@pytest.mark.parametrize("A,sva_expect,u_expect,v_expect", |
|
[(np.array([[2.27, -1.54, 1.15, -1.94], |
|
[0.28, -1.67, 0.94, -0.78], |
|
[-0.48, -3.09, 0.99, -0.21], |
|
[1.07, 1.22, 0.79, 0.63], |
|
[-2.35, 2.93, -1.45, 2.30], |
|
[0.62, -7.39, 1.03, -2.57]]), |
|
np.array([9.9966, 3.6831, 1.3569, 0.5000]), |
|
np.array([[0.2774, -0.6003, -0.1277, 0.1323], |
|
[0.2020, -0.0301, 0.2805, 0.7034], |
|
[0.2918, 0.3348, 0.6453, 0.1906], |
|
[-0.0938, -0.3699, 0.6781, -0.5399], |
|
[-0.4213, 0.5266, 0.0413, -0.0575], |
|
[0.7816, 0.3353, -0.1645, -0.3957]]), |
|
np.array([[0.1921, -0.8030, 0.0041, -0.5642], |
|
[-0.8794, -0.3926, -0.0752, 0.2587], |
|
[0.2140, -0.2980, 0.7827, 0.5027], |
|
[-0.3795, 0.3351, 0.6178, -0.6017]]))]) |
|
def test_gejsv_NAG(A, sva_expect, u_expect, v_expect): |
|
""" |
|
This test implements the example found in the NAG manual, f08khf. |
|
An example was not found for the complex case. |
|
""" |
|
|
|
atol = 1e-4 |
|
gejsv = get_lapack_funcs('gejsv', dtype=A.dtype) |
|
|
|
sva, u, v, work, iwork, info = gejsv(A) |
|
|
|
assert_allclose(sva_expect, sva, atol=atol) |
|
assert_allclose(u_expect, u, atol=atol) |
|
assert_allclose(v_expect, v, atol=atol) |
|
|
|
|
|
@pytest.mark.parametrize("dtype", DTYPES) |
|
def test_gttrf_gttrs(dtype): |
|
|
|
|
|
|
|
|
|
|
|
|
|
rng = np.random.RandomState(42) |
|
n = 10 |
|
atol = 100 * np.finfo(dtype).eps |
|
|
|
|
|
du = generate_random_dtype_array((n-1,), dtype=dtype, rng=rng) |
|
d = generate_random_dtype_array((n,), dtype=dtype, rng=rng) |
|
dl = generate_random_dtype_array((n-1,), dtype=dtype, rng=rng) |
|
|
|
diag_cpy = [dl.copy(), d.copy(), du.copy()] |
|
|
|
A = np.diag(d) + np.diag(dl, -1) + np.diag(du, 1) |
|
x = np.random.rand(n) |
|
b = A @ x |
|
|
|
gttrf, gttrs = get_lapack_funcs(('gttrf', 'gttrs'), dtype=dtype) |
|
|
|
_dl, _d, _du, du2, ipiv, info = gttrf(dl, d, du) |
|
|
|
assert_array_equal(dl, diag_cpy[0]) |
|
assert_array_equal(d, diag_cpy[1]) |
|
assert_array_equal(du, diag_cpy[2]) |
|
|
|
|
|
|
|
U = np.diag(_d, 0) + np.diag(_du, 1) + np.diag(du2, 2) |
|
L = np.eye(n, dtype=dtype) |
|
|
|
for i, m in enumerate(_dl): |
|
|
|
|
|
|
|
piv = ipiv[i] - 1 |
|
|
|
L[:, [i, piv]] = L[:, [piv, i]] |
|
|
|
L[:, i] += L[:, i+1]*m |
|
|
|
|
|
i, piv = -1, ipiv[-1] - 1 |
|
|
|
L[:, [i, piv]] = L[:, [piv, i]] |
|
|
|
|
|
assert_allclose(A, L @ U, atol=atol) |
|
|
|
b_cpy = b.copy() |
|
x_gttrs, info = gttrs(_dl, _d, _du, du2, ipiv, b) |
|
|
|
assert_array_equal(b, b_cpy) |
|
|
|
assert_allclose(x, x_gttrs, atol=atol) |
|
|
|
|
|
if dtype in REAL_DTYPES: |
|
trans = "T" |
|
b_trans = A.T @ x |
|
else: |
|
trans = "C" |
|
b_trans = A.conj().T @ x |
|
|
|
x_gttrs, info = gttrs(_dl, _d, _du, du2, ipiv, b_trans, trans=trans) |
|
assert_allclose(x, x_gttrs, atol=atol) |
|
|
|
|
|
with assert_raises(ValueError): |
|
gttrf(dl[:-1], d, du) |
|
with assert_raises(ValueError): |
|
gttrf(dl, d[:-1], du) |
|
with assert_raises(ValueError): |
|
gttrf(dl, d, du[:-1]) |
|
|
|
|
|
with assert_raises(ValueError): |
|
gttrf(dl[0], d[:1], du[0]) |
|
|
|
|
|
du[0] = 0 |
|
d[0] = 0 |
|
__dl, __d, __du, _du2, _ipiv, _info = gttrf(dl, d, du) |
|
np.testing.assert_(__d[info - 1] == 0, (f"?gttrf: _d[info-1] is {__d[info - 1]}," |
|
" not the illegal value :0.")) |
|
|
|
|
|
@pytest.mark.parametrize("du, d, dl, du_exp, d_exp, du2_exp, ipiv_exp, b, x", |
|
[(np.array([2.1, -1.0, 1.9, 8.0]), |
|
np.array([3.0, 2.3, -5.0, -.9, 7.1]), |
|
np.array([3.4, 3.6, 7.0, -6.0]), |
|
np.array([2.3, -5, -.9, 7.1]), |
|
np.array([3.4, 3.6, 7, -6, -1.015373]), |
|
np.array([-1, 1.9, 8]), |
|
np.array([2, 3, 4, 5, 5]), |
|
np.array([[2.7, 6.6], |
|
[-0.5, 10.8], |
|
[2.6, -3.2], |
|
[0.6, -11.2], |
|
[2.7, 19.1] |
|
]), |
|
np.array([[-4, 5], |
|
[7, -4], |
|
[3, -3], |
|
[-4, -2], |
|
[-3, 1]])), |
|
( |
|
np.array([2 - 1j, 2 + 1j, -1 + 1j, 1 - 1j]), |
|
np.array([-1.3 + 1.3j, -1.3 + 1.3j, |
|
-1.3 + 3.3j, - .3 + 4.3j, |
|
-3.3 + 1.3j]), |
|
np.array([1 - 2j, 1 + 1j, 2 - 3j, 1 + 1j]), |
|
|
|
np.array([-1.3 + 1.3j, -1.3 + 3.3j, |
|
-0.3 + 4.3j, -3.3 + 1.3j]), |
|
np.array([1 - 2j, 1 + 1j, 2 - 3j, 1 + 1j, |
|
-1.3399 + 0.2875j]), |
|
np.array([2 + 1j, -1 + 1j, 1 - 1j]), |
|
np.array([2, 3, 4, 5, 5]), |
|
np.array([[2.4 - 5j, 2.7 + 6.9j], |
|
[3.4 + 18.2j, - 6.9 - 5.3j], |
|
[-14.7 + 9.7j, - 6 - .6j], |
|
[31.9 - 7.7j, -3.9 + 9.3j], |
|
[-1 + 1.6j, -3 + 12.2j]]), |
|
np.array([[1 + 1j, 2 - 1j], |
|
[3 - 1j, 1 + 2j], |
|
[4 + 5j, -1 + 1j], |
|
[-1 - 2j, 2 + 1j], |
|
[1 - 1j, 2 - 2j]]) |
|
)]) |
|
def test_gttrf_gttrs_NAG_f07cdf_f07cef_f07crf_f07csf(du, d, dl, du_exp, d_exp, |
|
du2_exp, ipiv_exp, b, x): |
|
|
|
|
|
|
|
|
|
|
|
gttrf, gttrs = get_lapack_funcs(('gttrf', "gttrs"), (du[0], du[0])) |
|
|
|
_dl, _d, _du, du2, ipiv, info = gttrf(dl, d, du) |
|
assert_allclose(du2, du2_exp) |
|
assert_allclose(_du, du_exp) |
|
assert_allclose(_d, d_exp, atol=1e-4) |
|
assert_allclose(ipiv, ipiv_exp) |
|
|
|
x_gttrs, info = gttrs(_dl, _d, _du, du2, ipiv, b) |
|
|
|
assert_allclose(x_gttrs, x) |
|
|
|
|
|
@pytest.mark.parametrize('dtype', DTYPES) |
|
@pytest.mark.parametrize('norm', ['1', 'I', 'O']) |
|
@pytest.mark.parametrize('n', [3, 10]) |
|
def test_gtcon(dtype, norm, n): |
|
rng = np.random.default_rng(23498324) |
|
|
|
d = rng.random(n) + rng.random(n)*1j |
|
dl = rng.random(n - 1) + rng.random(n - 1)*1j |
|
du = rng.random(n - 1) + rng.random(n - 1)*1j |
|
A = np.diag(d) + np.diag(dl, -1) + np.diag(du, 1) |
|
if np.issubdtype(dtype, np.floating): |
|
A, d, dl, du = A.real, d.real, dl.real, du.real |
|
A, d, dl, du = A.astype(dtype), d.astype(dtype), dl.astype(dtype), du.astype(dtype) |
|
|
|
anorm = np.abs(A).sum(axis=0).max() |
|
|
|
gttrf, gtcon = get_lapack_funcs(('gttrf', 'gtcon'), (A,)) |
|
dl, d, du, du2, ipiv, info = gttrf(dl, d, du) |
|
res, _ = gtcon(dl, d, du, du2, ipiv, anorm, norm=norm) |
|
|
|
gecon, getrf = get_lapack_funcs(('gecon', 'getrf'), (A,)) |
|
lu, ipvt, info = getrf(A) |
|
ref, _ = gecon(lu, anorm, norm=norm) |
|
|
|
rtol = np.finfo(dtype).eps**0.75 |
|
assert_allclose(res, ref, rtol=rtol) |
|
|
|
|
|
@pytest.mark.parametrize('dtype', DTYPES) |
|
@pytest.mark.parametrize('shape', [(3, 7), (7, 3), (2**18, 2**18)]) |
|
def test_geqrfp_lwork(dtype, shape): |
|
geqrfp_lwork = get_lapack_funcs(('geqrfp_lwork'), dtype=dtype) |
|
m, n = shape |
|
lwork, info = geqrfp_lwork(m=m, n=n) |
|
assert_equal(info, 0) |
|
|
|
|
|
@pytest.mark.parametrize("ddtype,dtype", |
|
zip(REAL_DTYPES + REAL_DTYPES, DTYPES)) |
|
def test_pttrf_pttrs(ddtype, dtype): |
|
rng = np.random.RandomState(42) |
|
|
|
atol = 100*np.finfo(dtype).eps |
|
|
|
n = 10 |
|
|
|
|
|
|
|
|
|
d = generate_random_dtype_array((n,), ddtype, rng) + 4 |
|
|
|
e = generate_random_dtype_array((n-1,), dtype, rng) |
|
|
|
|
|
A = np.diag(d) + np.diag(e, -1) + np.diag(np.conj(e), 1) |
|
|
|
diag_cpy = [d.copy(), e.copy()] |
|
|
|
pttrf = get_lapack_funcs('pttrf', dtype=dtype) |
|
|
|
_d, _e, info = pttrf(d, e) |
|
|
|
assert_array_equal(d, diag_cpy[0]) |
|
assert_array_equal(e, diag_cpy[1]) |
|
assert_equal(info, 0, err_msg=f"pttrf: info = {info}, should be 0") |
|
|
|
|
|
L = np.diag(_e, -1) + np.diag(np.ones(n)) |
|
D = np.diag(_d) |
|
|
|
assert_allclose(A, L@[email protected]().T, atol=atol) |
|
|
|
|
|
x = generate_random_dtype_array((n,), dtype, rng) |
|
|
|
b = A@x |
|
|
|
|
|
pttrs = get_lapack_funcs('pttrs', dtype=dtype) |
|
_x, info = pttrs(_d, _e.conj(), b) |
|
assert_equal(info, 0, err_msg=f"pttrs: info = {info}, should be 0") |
|
|
|
|
|
assert_allclose(x, _x, atol=atol) |
|
|
|
|
|
@pytest.mark.parametrize("ddtype,dtype", |
|
zip(REAL_DTYPES + REAL_DTYPES, DTYPES)) |
|
def test_pttrf_pttrs_errors_incompatible_shape(ddtype, dtype): |
|
n = 10 |
|
rng = np.random.RandomState(1234) |
|
pttrf = get_lapack_funcs('pttrf', dtype=dtype) |
|
d = generate_random_dtype_array((n,), ddtype, rng) + 2 |
|
e = generate_random_dtype_array((n-1,), dtype, rng) |
|
|
|
assert_raises(ValueError, pttrf, d[:-1], e) |
|
assert_raises(ValueError, pttrf, d, e[:-1]) |
|
|
|
|
|
@pytest.mark.parametrize("ddtype,dtype", |
|
zip(REAL_DTYPES + REAL_DTYPES, DTYPES)) |
|
def test_pttrf_pttrs_errors_singular_nonSPD(ddtype, dtype): |
|
n = 10 |
|
rng = np.random.RandomState(42) |
|
pttrf = get_lapack_funcs('pttrf', dtype=dtype) |
|
d = generate_random_dtype_array((n,), ddtype, rng) + 2 |
|
e = generate_random_dtype_array((n-1,), dtype, rng) |
|
|
|
d[0] = 0 |
|
e[0] = 0 |
|
_d, _e, info = pttrf(d, e) |
|
assert_equal(_d[info - 1], 0, |
|
f"?pttrf: _d[info-1] is {_d[info - 1]}, not the illegal value :0.") |
|
|
|
|
|
d = generate_random_dtype_array((n,), ddtype, rng) |
|
_d, _e, info = pttrf(d, e) |
|
assert_(info != 0, "?pttrf should fail with non-spd matrix, but didn't") |
|
|
|
|
|
@pytest.mark.parametrize(("d, e, d_expect, e_expect, b, x_expect"), [ |
|
(np.array([4, 10, 29, 25, 5]), |
|
np.array([-2, -6, 15, 8]), |
|
np.array([4, 9, 25, 16, 1]), |
|
np.array([-.5, -.6667, .6, .5]), |
|
np.array([[6, 10], [9, 4], [2, 9], [14, 65], |
|
[7, 23]]), |
|
np.array([[2.5, 2], [2, -1], [1, -3], [-1, 6], |
|
[3, -5]]) |
|
), ( |
|
np.array([16, 41, 46, 21]), |
|
np.array([16 + 16j, 18 - 9j, 1 - 4j]), |
|
np.array([16, 9, 1, 4]), |
|
np.array([1+1j, 2-1j, 1-4j]), |
|
np.array([[64+16j, -16-32j], [93+62j, 61-66j], |
|
[78-80j, 71-74j], [14-27j, 35+15j]]), |
|
np.array([[2+1j, -3-2j], [1+1j, 1+1j], [1-2j, 1-2j], |
|
[1-1j, 2+1j]]) |
|
)]) |
|
def test_pttrf_pttrs_NAG(d, e, d_expect, e_expect, b, x_expect): |
|
|
|
|
|
|
|
|
|
|
|
|
|
atol = 1e-4 |
|
pttrf = get_lapack_funcs('pttrf', dtype=e[0]) |
|
_d, _e, info = pttrf(d, e) |
|
assert_allclose(_d, d_expect, atol=atol) |
|
assert_allclose(_e, e_expect, atol=atol) |
|
|
|
pttrs = get_lapack_funcs('pttrs', dtype=e[0]) |
|
_x, info = pttrs(_d, _e.conj(), b) |
|
assert_allclose(_x, x_expect, atol=atol) |
|
|
|
|
|
if e.dtype in COMPLEX_DTYPES: |
|
_x, info = pttrs(_d, _e, b, lower=1) |
|
assert_allclose(_x, x_expect, atol=atol) |
|
|
|
|
|
def pteqr_get_d_e_A_z(dtype, realtype, n, compute_z): |
|
|
|
|
|
rng = np.random.RandomState(42) |
|
if compute_z == 1: |
|
|
|
A_eig = generate_random_dtype_array((n, n), dtype, rng) |
|
A_eig = A_eig + np.diag(np.zeros(n) + 4*n) |
|
A_eig = (A_eig + A_eig.conj().T) / 2 |
|
|
|
vr = eigh(A_eig)[1] |
|
|
|
d = generate_random_dtype_array((n,), realtype, rng) + 4 |
|
e = generate_random_dtype_array((n-1,), realtype, rng) |
|
tri = np.diag(d) + np.diag(e, 1) + np.diag(e, -1) |
|
|
|
A = vr @ tri @ vr.conj().T |
|
|
|
z = vr |
|
|
|
else: |
|
|
|
d = generate_random_dtype_array((n,), realtype, rng) |
|
e = generate_random_dtype_array((n-1,), realtype, rng) |
|
|
|
|
|
d = d + 4 |
|
A = np.diag(d) + np.diag(e, 1) + np.diag(e, -1) |
|
z = np.diag(d) + np.diag(e, -1) + np.diag(e, 1) |
|
return (d, e, A, z) |
|
|
|
|
|
@pytest.mark.parametrize("dtype,realtype", |
|
zip(DTYPES, REAL_DTYPES + REAL_DTYPES)) |
|
@pytest.mark.parametrize("compute_z", range(3)) |
|
def test_pteqr(dtype, realtype, compute_z): |
|
''' |
|
Tests the ?pteqr lapack routine for all dtypes and compute_z parameters. |
|
It generates random SPD matrix diagonals d and e, and then confirms |
|
correct eigenvalues with scipy.linalg.eig. With applicable compute_z=2 it |
|
tests that z can reform A. |
|
''' |
|
seed(42) |
|
atol = 1000*np.finfo(dtype).eps |
|
pteqr = get_lapack_funcs(('pteqr'), dtype=dtype) |
|
|
|
n = 10 |
|
|
|
d, e, A, z = pteqr_get_d_e_A_z(dtype, realtype, n, compute_z) |
|
|
|
d_pteqr, e_pteqr, z_pteqr, info = pteqr(d=d, e=e, z=z, compute_z=compute_z) |
|
assert_equal(info, 0, f"info = {info}, should be 0.") |
|
|
|
|
|
assert_allclose(np.sort(eigh(A)[0]), np.sort(d_pteqr), atol=atol) |
|
|
|
if compute_z: |
|
|
|
assert_allclose(z_pteqr @ np.conj(z_pteqr).T, np.identity(n), |
|
atol=atol) |
|
|
|
assert_allclose(z_pteqr @ np.diag(d_pteqr) @ np.conj(z_pteqr).T, |
|
A, atol=atol) |
|
|
|
|
|
@pytest.mark.parametrize("dtype,realtype", |
|
zip(DTYPES, REAL_DTYPES + REAL_DTYPES)) |
|
@pytest.mark.parametrize("compute_z", range(3)) |
|
def test_pteqr_error_non_spd(dtype, realtype, compute_z): |
|
seed(42) |
|
pteqr = get_lapack_funcs(('pteqr'), dtype=dtype) |
|
|
|
n = 10 |
|
d, e, A, z = pteqr_get_d_e_A_z(dtype, realtype, n, compute_z) |
|
|
|
|
|
d_pteqr, e_pteqr, z_pteqr, info = pteqr(d - 4, e, z=z, compute_z=compute_z) |
|
assert info > 0 |
|
|
|
|
|
@pytest.mark.parametrize("dtype,realtype", |
|
zip(DTYPES, REAL_DTYPES + REAL_DTYPES)) |
|
@pytest.mark.parametrize("compute_z", range(3)) |
|
def test_pteqr_raise_error_wrong_shape(dtype, realtype, compute_z): |
|
seed(42) |
|
pteqr = get_lapack_funcs(('pteqr'), dtype=dtype) |
|
n = 10 |
|
d, e, A, z = pteqr_get_d_e_A_z(dtype, realtype, n, compute_z) |
|
|
|
assert_raises(ValueError, pteqr, d[:-1], e, z=z, compute_z=compute_z) |
|
assert_raises(ValueError, pteqr, d, e[:-1], z=z, compute_z=compute_z) |
|
if compute_z: |
|
assert_raises(ValueError, pteqr, d, e, z=z[:-1], compute_z=compute_z) |
|
|
|
|
|
@pytest.mark.parametrize("dtype,realtype", |
|
zip(DTYPES, REAL_DTYPES + REAL_DTYPES)) |
|
@pytest.mark.parametrize("compute_z", range(3)) |
|
def test_pteqr_error_singular(dtype, realtype, compute_z): |
|
seed(42) |
|
pteqr = get_lapack_funcs(('pteqr'), dtype=dtype) |
|
n = 10 |
|
d, e, A, z = pteqr_get_d_e_A_z(dtype, realtype, n, compute_z) |
|
|
|
d[0] = 0 |
|
e[0] = 0 |
|
d_pteqr, e_pteqr, z_pteqr, info = pteqr(d, e, z=z, compute_z=compute_z) |
|
assert info > 0 |
|
|
|
|
|
@pytest.mark.parametrize("compute_z,d,e,d_expect,z_expect", |
|
[(2, |
|
np.array([4.16, 5.25, 1.09, .62]), |
|
np.array([3.17, -.97, .55]), |
|
np.array([8.0023, 1.9926, 1.0014, 0.1237]), |
|
np.array([[0.6326, 0.6245, -0.4191, 0.1847], |
|
[0.7668, -0.4270, 0.4176, -0.2352], |
|
[-0.1082, 0.6071, 0.4594, -0.6393], |
|
[-0.0081, 0.2432, 0.6625, 0.7084]])), |
|
]) |
|
def test_pteqr_NAG_f08jgf(compute_z, d, e, d_expect, z_expect): |
|
''' |
|
Implements real (f08jgf) example from NAG Manual Mark 26. |
|
Tests for correct outputs. |
|
''' |
|
|
|
atol = 1e-4 |
|
pteqr = get_lapack_funcs(('pteqr'), dtype=d.dtype) |
|
|
|
z = np.diag(d) + np.diag(e, 1) + np.diag(e, -1) |
|
_d, _e, _z, info = pteqr(d=d, e=e, z=z, compute_z=compute_z) |
|
assert_allclose(_d, d_expect, atol=atol) |
|
assert_allclose(np.abs(_z), np.abs(z_expect), atol=atol) |
|
|
|
|
|
@pytest.mark.parametrize('dtype', DTYPES) |
|
@pytest.mark.parametrize('matrix_size', [(3, 4), (7, 6), (6, 6)]) |
|
def test_geqrfp(dtype, matrix_size): |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
rng = np.random.RandomState(42) |
|
rtol = 250*np.finfo(dtype).eps |
|
atol = 100*np.finfo(dtype).eps |
|
|
|
geqrfp = get_lapack_funcs(('geqrfp'), dtype=dtype) |
|
gqr = get_lapack_funcs(("orgqr"), dtype=dtype) |
|
|
|
m, n = matrix_size |
|
|
|
|
|
A = generate_random_dtype_array((m, n), dtype=dtype, rng=rng) |
|
|
|
qr_A, tau, info = geqrfp(A) |
|
|
|
|
|
r = np.triu(qr_A) |
|
|
|
|
|
|
|
|
|
if m > n: |
|
|
|
|
|
qqr = np.zeros((m, m), dtype=dtype) |
|
|
|
qqr[:, :n] = qr_A |
|
|
|
|
|
q = gqr(qqr, tau=tau, lwork=m)[0] |
|
else: |
|
q = gqr(qr_A[:, :m], tau=tau, lwork=m)[0] |
|
|
|
|
|
assert_allclose(q@r, A, rtol=rtol) |
|
|
|
assert_allclose(np.eye(q.shape[0]), q@(q.conj().T), rtol=rtol, |
|
atol=atol) |
|
|
|
assert_allclose(r, np.triu(r), rtol=rtol) |
|
|
|
assert_(np.all(np.diag(r) > np.zeros(len(np.diag(r))))) |
|
|
|
assert_(info == 0) |
|
|
|
|
|
|
|
A_negative = generate_random_dtype_array((n, m), dtype=dtype, rng=rng) * -1 |
|
r_rq_neg, q_rq_neg = qr(A_negative) |
|
rq_A_neg, tau_neg, info_neg = geqrfp(A_negative) |
|
|
|
|
|
assert_(np.any(np.diag(r_rq_neg) < 0) and |
|
np.all(np.diag(r) > 0)) |
|
|
|
|
|
def test_geqrfp_errors_with_empty_array(): |
|
|
|
A_empty = np.array([]) |
|
geqrfp = get_lapack_funcs('geqrfp', dtype=A_empty.dtype) |
|
assert_raises(Exception, geqrfp, A_empty) |
|
|
|
|
|
@pytest.mark.parametrize("driver", ['ev', 'evd', 'evr', 'evx']) |
|
@pytest.mark.parametrize("pfx", ['sy', 'he']) |
|
def test_standard_eigh_lworks(pfx, driver): |
|
n = 1200 |
|
dtype = REAL_DTYPES if pfx == 'sy' else COMPLEX_DTYPES |
|
sc_dlw = get_lapack_funcs(pfx+driver+'_lwork', dtype=dtype[0]) |
|
dz_dlw = get_lapack_funcs(pfx+driver+'_lwork', dtype=dtype[1]) |
|
try: |
|
_compute_lwork(sc_dlw, n, lower=1) |
|
_compute_lwork(dz_dlw, n, lower=1) |
|
except Exception as e: |
|
pytest.fail(f"{pfx+driver}_lwork raised unexpected exception: {e}") |
|
|
|
|
|
@pytest.mark.parametrize("driver", ['gv', 'gvx']) |
|
@pytest.mark.parametrize("pfx", ['sy', 'he']) |
|
def test_generalized_eigh_lworks(pfx, driver): |
|
n = 1200 |
|
dtype = REAL_DTYPES if pfx == 'sy' else COMPLEX_DTYPES |
|
sc_dlw = get_lapack_funcs(pfx+driver+'_lwork', dtype=dtype[0]) |
|
dz_dlw = get_lapack_funcs(pfx+driver+'_lwork', dtype=dtype[1]) |
|
|
|
try: |
|
_compute_lwork(sc_dlw, n, uplo="L") |
|
_compute_lwork(dz_dlw, n, uplo="L") |
|
except Exception as e: |
|
pytest.fail(f"{pfx+driver}_lwork raised unexpected exception: {e}") |
|
|
|
|
|
@pytest.mark.parametrize("dtype_", DTYPES) |
|
@pytest.mark.parametrize("m", [1, 10, 100, 1000]) |
|
def test_orcsd_uncsd_lwork(dtype_, m): |
|
seed(1234) |
|
p = randint(0, m) |
|
q = m - p |
|
pfx = 'or' if dtype_ in REAL_DTYPES else 'un' |
|
dlw = pfx + 'csd_lwork' |
|
lw = get_lapack_funcs(dlw, dtype=dtype_) |
|
lwval = _compute_lwork(lw, m, p, q) |
|
lwval = lwval if pfx == 'un' else (lwval,) |
|
assert all([x > 0 for x in lwval]) |
|
|
|
|
|
@pytest.mark.parametrize("dtype_", DTYPES) |
|
def test_orcsd_uncsd(dtype_): |
|
m, p, q = 250, 80, 170 |
|
|
|
pfx = 'or' if dtype_ in REAL_DTYPES else 'un' |
|
X = ortho_group.rvs(m) if pfx == 'or' else unitary_group.rvs(m) |
|
|
|
drv, dlw = get_lapack_funcs((pfx + 'csd', pfx + 'csd_lwork'), dtype=dtype_) |
|
lwval = _compute_lwork(dlw, m, p, q) |
|
lwvals = {'lwork': lwval} if pfx == 'or' else dict(zip(['lwork', |
|
'lrwork'], lwval)) |
|
|
|
cs11, cs12, cs21, cs22, theta, u1, u2, v1t, v2t, info =\ |
|
drv(X[:p, :q], X[:p, q:], X[p:, :q], X[p:, q:], **lwvals) |
|
|
|
assert info == 0 |
|
|
|
U = block_diag(u1, u2) |
|
VH = block_diag(v1t, v2t) |
|
r = min(min(p, q), min(m-p, m-q)) |
|
n11 = min(p, q) - r |
|
n12 = min(p, m-q) - r |
|
n21 = min(m-p, q) - r |
|
n22 = min(m-p, m-q) - r |
|
|
|
S = np.zeros((m, m), dtype=dtype_) |
|
one = dtype_(1.) |
|
for i in range(n11): |
|
S[i, i] = one |
|
for i in range(n22): |
|
S[p+i, q+i] = one |
|
for i in range(n12): |
|
S[i+n11+r, i+n11+r+n21+n22+r] = -one |
|
for i in range(n21): |
|
S[p+n22+r+i, n11+r+i] = one |
|
|
|
for i in range(r): |
|
S[i+n11, i+n11] = np.cos(theta[i]) |
|
S[p+n22+i, i+r+n21+n22] = np.cos(theta[i]) |
|
|
|
S[i+n11, i+n11+n21+n22+r] = -np.sin(theta[i]) |
|
S[p+n22+i, i+n11] = np.sin(theta[i]) |
|
|
|
Xc = U @ S @ VH |
|
assert_allclose(X, Xc, rtol=0., atol=1e4*np.finfo(dtype_).eps) |
|
|
|
|
|
@pytest.mark.parametrize("dtype", DTYPES) |
|
@pytest.mark.parametrize("trans_bool", [False, True]) |
|
@pytest.mark.parametrize("fact", ["F", "N"]) |
|
def test_gtsvx(dtype, trans_bool, fact): |
|
""" |
|
These tests uses ?gtsvx to solve a random Ax=b system for each dtype. |
|
It tests that the outputs define an LU matrix, that inputs are unmodified, |
|
transposal options, incompatible shapes, singular matrices, and |
|
singular factorizations. It parametrizes DTYPES and the 'fact' value along |
|
with the fact related inputs. |
|
""" |
|
rng = np.random.RandomState(42) |
|
|
|
atol = 100 * np.finfo(dtype).eps |
|
|
|
gtsvx, gttrf = get_lapack_funcs(('gtsvx', 'gttrf'), dtype=dtype) |
|
|
|
n = 10 |
|
dl = generate_random_dtype_array((n-1,), dtype=dtype, rng=rng) |
|
d = generate_random_dtype_array((n,), dtype=dtype, rng=rng) |
|
du = generate_random_dtype_array((n-1,), dtype=dtype, rng=rng) |
|
A = np.diag(dl, -1) + np.diag(d) + np.diag(du, 1) |
|
|
|
x = generate_random_dtype_array((n, 2), dtype=dtype, rng=rng) |
|
|
|
trans = ("T" if dtype in REAL_DTYPES else "C") if trans_bool else "N" |
|
b = (A.conj().T if trans_bool else A) @ x |
|
|
|
|
|
inputs_cpy = [dl.copy(), d.copy(), du.copy(), b.copy()] |
|
|
|
|
|
dlf_, df_, duf_, du2f_, ipiv_, info_ = \ |
|
gttrf(dl, d, du) if fact == 'F' else [None]*6 |
|
|
|
gtsvx_out = gtsvx(dl, d, du, b, fact=fact, trans=trans, dlf=dlf_, df=df_, |
|
duf=duf_, du2=du2f_, ipiv=ipiv_) |
|
dlf, df, duf, du2f, ipiv, x_soln, rcond, ferr, berr, info = gtsvx_out |
|
assert_(info == 0, f"?gtsvx info = {info}, should be zero") |
|
|
|
|
|
assert_array_equal(dl, inputs_cpy[0]) |
|
assert_array_equal(d, inputs_cpy[1]) |
|
assert_array_equal(du, inputs_cpy[2]) |
|
assert_array_equal(b, inputs_cpy[3]) |
|
|
|
|
|
assert_allclose(x, x_soln, atol=atol) |
|
|
|
|
|
|
|
assert_(hasattr(rcond, "__len__") is not True, |
|
f"rcond should be scalar but is {rcond}") |
|
|
|
assert_(ferr.shape[0] == b.shape[1], (f"ferr.shape is {ferr.shape[0]} but should" |
|
f" be {b.shape[1]}")) |
|
|
|
assert_(berr.shape[0] == b.shape[1], (f"berr.shape is {berr.shape[0]} but should" |
|
f" be {b.shape[1]}")) |
|
|
|
|
|
@pytest.mark.parametrize("dtype", DTYPES) |
|
@pytest.mark.parametrize("trans_bool", [0, 1]) |
|
@pytest.mark.parametrize("fact", ["F", "N"]) |
|
def test_gtsvx_error_singular(dtype, trans_bool, fact): |
|
rng = np.random.RandomState(42) |
|
|
|
gtsvx, gttrf = get_lapack_funcs(('gtsvx', 'gttrf'), dtype=dtype) |
|
|
|
n = 10 |
|
dl = generate_random_dtype_array((n-1,), dtype=dtype, rng=rng) |
|
d = generate_random_dtype_array((n,), dtype=dtype, rng=rng) |
|
du = generate_random_dtype_array((n-1,), dtype=dtype, rng=rng) |
|
A = np.diag(dl, -1) + np.diag(d) + np.diag(du, 1) |
|
|
|
x = generate_random_dtype_array((n, 2), dtype=dtype, rng=rng) |
|
|
|
trans = "T" if dtype in REAL_DTYPES else "C" |
|
b = (A.conj().T if trans_bool else A) @ x |
|
|
|
|
|
dlf_, df_, duf_, du2f_, ipiv_, info_ = \ |
|
gttrf(dl, d, du) if fact == 'F' else [None]*6 |
|
|
|
gtsvx_out = gtsvx(dl, d, du, b, fact=fact, trans=trans, dlf=dlf_, df=df_, |
|
duf=duf_, du2=du2f_, ipiv=ipiv_) |
|
dlf, df, duf, du2f, ipiv, x_soln, rcond, ferr, berr, info = gtsvx_out |
|
|
|
|
|
if fact == "N": |
|
|
|
d[-1] = 0 |
|
dl[-1] = 0 |
|
|
|
gtsvx_out = gtsvx(dl, d, du, b) |
|
dlf, df, duf, du2f, ipiv, x_soln, rcond, ferr, berr, info = gtsvx_out |
|
|
|
assert info > 0, "info should be > 0 for singular matrix" |
|
|
|
elif fact == 'F': |
|
|
|
df_[-1] = 0 |
|
duf_[-1] = 0 |
|
du2f_[-1] = 0 |
|
|
|
gtsvx_out = gtsvx(dl, d, du, b, fact=fact, dlf=dlf_, df=df_, duf=duf_, |
|
du2=du2f_, ipiv=ipiv_) |
|
dlf, df, duf, du2f, ipiv, x_soln, rcond, ferr, berr, info = gtsvx_out |
|
|
|
assert info > 0, "info should be > 0 for singular matrix" |
|
|
|
|
|
@pytest.mark.parametrize("dtype", DTYPES*2) |
|
@pytest.mark.parametrize("trans_bool", [False, True]) |
|
@pytest.mark.parametrize("fact", ["F", "N"]) |
|
def test_gtsvx_error_incompatible_size(dtype, trans_bool, fact): |
|
rng = np.random.RandomState(42) |
|
|
|
gtsvx, gttrf = get_lapack_funcs(('gtsvx', 'gttrf'), dtype=dtype) |
|
|
|
n = 10 |
|
dl = generate_random_dtype_array((n-1,), dtype=dtype, rng=rng) |
|
d = generate_random_dtype_array((n,), dtype=dtype, rng=rng) |
|
du = generate_random_dtype_array((n-1,), dtype=dtype, rng=rng) |
|
A = np.diag(dl, -1) + np.diag(d) + np.diag(du, 1) |
|
|
|
x = generate_random_dtype_array((n, 2), dtype=dtype, rng=rng) |
|
|
|
trans = "T" if dtype in REAL_DTYPES else "C" |
|
b = (A.conj().T if trans_bool else A) @ x |
|
|
|
|
|
dlf_, df_, duf_, du2f_, ipiv_, info_ = \ |
|
gttrf(dl, d, du) if fact == 'F' else [None]*6 |
|
|
|
if fact == "N": |
|
assert_raises(ValueError, gtsvx, dl[:-1], d, du, b, |
|
fact=fact, trans=trans, dlf=dlf_, df=df_, |
|
duf=duf_, du2=du2f_, ipiv=ipiv_) |
|
assert_raises(ValueError, gtsvx, dl, d[:-1], du, b, |
|
fact=fact, trans=trans, dlf=dlf_, df=df_, |
|
duf=duf_, du2=du2f_, ipiv=ipiv_) |
|
assert_raises(ValueError, gtsvx, dl, d, du[:-1], b, |
|
fact=fact, trans=trans, dlf=dlf_, df=df_, |
|
duf=duf_, du2=du2f_, ipiv=ipiv_) |
|
assert_raises(Exception, gtsvx, dl, d, du, b[:-1], |
|
fact=fact, trans=trans, dlf=dlf_, df=df_, |
|
duf=duf_, du2=du2f_, ipiv=ipiv_) |
|
else: |
|
assert_raises(ValueError, gtsvx, dl, d, du, b, |
|
fact=fact, trans=trans, dlf=dlf_[:-1], df=df_, |
|
duf=duf_, du2=du2f_, ipiv=ipiv_) |
|
assert_raises(ValueError, gtsvx, dl, d, du, b, |
|
fact=fact, trans=trans, dlf=dlf_, df=df_[:-1], |
|
duf=duf_, du2=du2f_, ipiv=ipiv_) |
|
assert_raises(ValueError, gtsvx, dl, d, du, b, |
|
fact=fact, trans=trans, dlf=dlf_, df=df_, |
|
duf=duf_[:-1], du2=du2f_, ipiv=ipiv_) |
|
assert_raises(ValueError, gtsvx, dl, d, du, b, |
|
fact=fact, trans=trans, dlf=dlf_, df=df_, |
|
duf=duf_, du2=du2f_[:-1], ipiv=ipiv_) |
|
|
|
|
|
@pytest.mark.parametrize("du,d,dl,b,x", |
|
[(np.array([2.1, -1.0, 1.9, 8.0]), |
|
np.array([3.0, 2.3, -5.0, -0.9, 7.1]), |
|
np.array([3.4, 3.6, 7.0, -6.0]), |
|
np.array([[2.7, 6.6], [-.5, 10.8], [2.6, -3.2], |
|
[.6, -11.2], [2.7, 19.1]]), |
|
np.array([[-4, 5], [7, -4], [3, -3], [-4, -2], |
|
[-3, 1]])), |
|
(np.array([2 - 1j, 2 + 1j, -1 + 1j, 1 - 1j]), |
|
np.array([-1.3 + 1.3j, -1.3 + 1.3j, -1.3 + 3.3j, |
|
-.3 + 4.3j, -3.3 + 1.3j]), |
|
np.array([1 - 2j, 1 + 1j, 2 - 3j, 1 + 1j]), |
|
np.array([[2.4 - 5j, 2.7 + 6.9j], |
|
[3.4 + 18.2j, -6.9 - 5.3j], |
|
[-14.7 + 9.7j, -6 - .6j], |
|
[31.9 - 7.7j, -3.9 + 9.3j], |
|
[-1 + 1.6j, -3 + 12.2j]]), |
|
np.array([[1 + 1j, 2 - 1j], [3 - 1j, 1 + 2j], |
|
[4 + 5j, -1 + 1j], [-1 - 2j, 2 + 1j], |
|
[1 - 1j, 2 - 2j]]))]) |
|
def test_gtsvx_NAG(du, d, dl, b, x): |
|
|
|
|
|
gtsvx = get_lapack_funcs('gtsvx', dtype=d.dtype) |
|
|
|
gtsvx_out = gtsvx(dl, d, du, b) |
|
dlf, df, duf, du2f, ipiv, x_soln, rcond, ferr, berr, info = gtsvx_out |
|
|
|
assert_array_almost_equal(x, x_soln) |
|
|
|
|
|
@pytest.mark.parametrize("dtype,realtype", zip(DTYPES, REAL_DTYPES |
|
+ REAL_DTYPES)) |
|
@pytest.mark.parametrize("fact,df_de_lambda", |
|
[("F", |
|
lambda d, e: get_lapack_funcs('pttrf', |
|
dtype=e.dtype)(d, e)), |
|
("N", lambda d, e: (None, None, None))]) |
|
def test_ptsvx(dtype, realtype, fact, df_de_lambda): |
|
''' |
|
This tests the ?ptsvx lapack routine wrapper to solve a random system |
|
Ax = b for all dtypes and input variations. Tests for: unmodified |
|
input parameters, fact options, incompatible matrix shapes raise an error, |
|
and singular matrices return info of illegal value. |
|
''' |
|
rng = np.random.RandomState(42) |
|
|
|
atol = 100 * np.finfo(dtype).eps |
|
ptsvx = get_lapack_funcs('ptsvx', dtype=dtype) |
|
n = 5 |
|
|
|
d = generate_random_dtype_array((n,), realtype, rng) + 4 |
|
e = generate_random_dtype_array((n-1,), dtype, rng) |
|
A = np.diag(d) + np.diag(e, -1) + np.diag(np.conj(e), 1) |
|
x_soln = generate_random_dtype_array((n, 2), dtype=dtype, rng=rng) |
|
b = A @ x_soln |
|
|
|
|
|
df, ef, info = df_de_lambda(d, e) |
|
|
|
|
|
diag_cpy = [d.copy(), e.copy(), b.copy()] |
|
|
|
|
|
df, ef, x, rcond, ferr, berr, info = ptsvx(d, e, b, fact=fact, |
|
df=df, ef=ef) |
|
|
|
assert_array_equal(d, diag_cpy[0]) |
|
assert_array_equal(e, diag_cpy[1]) |
|
assert_array_equal(b, diag_cpy[2]) |
|
assert_(info == 0, f"info should be 0 but is {info}.") |
|
assert_array_almost_equal(x_soln, x) |
|
|
|
|
|
L = np.diag(ef, -1) + np.diag(np.ones(n)) |
|
D = np.diag(df) |
|
assert_allclose(A, L@D@(np.conj(L).T), atol=atol) |
|
|
|
|
|
|
|
assert not hasattr(rcond, "__len__"), \ |
|
f"rcond should be scalar but is {rcond}" |
|
|
|
assert_(ferr.shape == (2,), (f"ferr.shape is {ferr.shape} but should be " |
|
"({x_soln.shape[1]},)")) |
|
|
|
assert_(berr.shape == (2,), (f"berr.shape is {berr.shape} but should be " |
|
"({x_soln.shape[1]},)")) |
|
|
|
|
|
@pytest.mark.parametrize("dtype,realtype", zip(DTYPES, REAL_DTYPES |
|
+ REAL_DTYPES)) |
|
@pytest.mark.parametrize("fact,df_de_lambda", |
|
[("F", |
|
lambda d, e: get_lapack_funcs('pttrf', |
|
dtype=e.dtype)(d, e)), |
|
("N", lambda d, e: (None, None, None))]) |
|
def test_ptsvx_error_raise_errors(dtype, realtype, fact, df_de_lambda): |
|
rng = np.random.RandomState(42) |
|
ptsvx = get_lapack_funcs('ptsvx', dtype=dtype) |
|
n = 5 |
|
|
|
d = generate_random_dtype_array((n,), realtype, rng) + 4 |
|
e = generate_random_dtype_array((n-1,), dtype, rng) |
|
A = np.diag(d) + np.diag(e, -1) + np.diag(np.conj(e), 1) |
|
x_soln = generate_random_dtype_array((n, 2), dtype=dtype, rng=rng) |
|
b = A @ x_soln |
|
|
|
|
|
df, ef, info = df_de_lambda(d, e) |
|
|
|
|
|
assert_raises(ValueError, ptsvx, d[:-1], e, b, fact=fact, df=df, ef=ef) |
|
assert_raises(ValueError, ptsvx, d, e[:-1], b, fact=fact, df=df, ef=ef) |
|
assert_raises(Exception, ptsvx, d, e, b[:-1], fact=fact, df=df, ef=ef) |
|
|
|
|
|
@pytest.mark.parametrize("dtype,realtype", zip(DTYPES, REAL_DTYPES |
|
+ REAL_DTYPES)) |
|
@pytest.mark.parametrize("fact,df_de_lambda", |
|
[("F", |
|
lambda d, e: get_lapack_funcs('pttrf', |
|
dtype=e.dtype)(d, e)), |
|
("N", lambda d, e: (None, None, None))]) |
|
def test_ptsvx_non_SPD_singular(dtype, realtype, fact, df_de_lambda): |
|
rng = np.random.RandomState(42) |
|
ptsvx = get_lapack_funcs('ptsvx', dtype=dtype) |
|
n = 5 |
|
|
|
d = generate_random_dtype_array((n,), realtype, rng) + 4 |
|
e = generate_random_dtype_array((n-1,), dtype, rng) |
|
A = np.diag(d) + np.diag(e, -1) + np.diag(np.conj(e), 1) |
|
x_soln = generate_random_dtype_array((n, 2), dtype=dtype, rng=rng) |
|
b = A @ x_soln |
|
|
|
|
|
df, ef, info = df_de_lambda(d, e) |
|
|
|
if fact == "N": |
|
d[3] = 0 |
|
|
|
df, ef, info = df_de_lambda(d, e) |
|
|
|
df, ef, x, rcond, ferr, berr, info = ptsvx(d, e, b) |
|
|
|
assert info > 0 and info <= n |
|
|
|
|
|
d = generate_random_dtype_array((n,), realtype, rng) |
|
df, ef, x, rcond, ferr, berr, info = ptsvx(d, e, b) |
|
assert info > 0 and info <= n |
|
else: |
|
|
|
df, ef, info = df_de_lambda(d, e) |
|
df[0] = 0 |
|
ef[0] = 0 |
|
df, ef, x, rcond, ferr, berr, info = ptsvx(d, e, b, fact=fact, |
|
df=df, ef=ef) |
|
assert info > 0 |
|
|
|
|
|
@pytest.mark.parametrize('d,e,b,x', |
|
[(np.array([4, 10, 29, 25, 5]), |
|
np.array([-2, -6, 15, 8]), |
|
np.array([[6, 10], [9, 4], [2, 9], [14, 65], |
|
[7, 23]]), |
|
np.array([[2.5, 2], [2, -1], [1, -3], |
|
[-1, 6], [3, -5]])), |
|
(np.array([16, 41, 46, 21]), |
|
np.array([16 + 16j, 18 - 9j, 1 - 4j]), |
|
np.array([[64 + 16j, -16 - 32j], |
|
[93 + 62j, 61 - 66j], |
|
[78 - 80j, 71 - 74j], |
|
[14 - 27j, 35 + 15j]]), |
|
np.array([[2 + 1j, -3 - 2j], |
|
[1 + 1j, 1 + 1j], |
|
[1 - 2j, 1 - 2j], |
|
[1 - 1j, 2 + 1j]]))]) |
|
def test_ptsvx_NAG(d, e, b, x): |
|
|
|
|
|
|
|
|
|
|
|
ptsvx = get_lapack_funcs('ptsvx', dtype=e.dtype) |
|
|
|
df, ef, x_ptsvx, rcond, ferr, berr, info = ptsvx(d, e, b) |
|
|
|
assert_array_almost_equal(x, x_ptsvx) |
|
|
|
|
|
@pytest.mark.parametrize('lower', [False, True]) |
|
@pytest.mark.parametrize('dtype', DTYPES) |
|
def test_pptrs_pptri_pptrf_ppsv_ppcon(dtype, lower): |
|
rng = np.random.RandomState(1234) |
|
atol = np.finfo(dtype).eps*100 |
|
|
|
n, nrhs = 10, 4 |
|
a = generate_random_dtype_array([n, n], dtype=dtype, rng=rng) |
|
b = generate_random_dtype_array([n, nrhs], dtype=dtype, rng=rng) |
|
|
|
a = a.conj().T + a + np.eye(n, dtype=dtype) * dtype(5.) |
|
if lower: |
|
inds = ([x for y in range(n) for x in range(y, n)], |
|
[y for y in range(n) for x in range(y, n)]) |
|
else: |
|
inds = ([x for y in range(1, n+1) for x in range(y)], |
|
[y-1 for y in range(1, n+1) for x in range(y)]) |
|
ap = a[inds] |
|
ppsv, pptrf, pptrs, pptri, ppcon = get_lapack_funcs( |
|
('ppsv', 'pptrf', 'pptrs', 'pptri', 'ppcon'), |
|
dtype=dtype, |
|
ilp64="preferred") |
|
|
|
ul, info = pptrf(n, ap, lower=lower) |
|
assert_equal(info, 0) |
|
aul = cholesky(a, lower=lower)[inds] |
|
assert_allclose(ul, aul, rtol=0, atol=atol) |
|
|
|
uli, info = pptri(n, ul, lower=lower) |
|
assert_equal(info, 0) |
|
auli = inv(a)[inds] |
|
assert_allclose(uli, auli, rtol=0, atol=atol) |
|
|
|
x, info = pptrs(n, ul, b, lower=lower) |
|
assert_equal(info, 0) |
|
bx = solve(a, b) |
|
assert_allclose(x, bx, rtol=0, atol=atol) |
|
|
|
xv, info = ppsv(n, ap, b, lower=lower) |
|
assert_equal(info, 0) |
|
assert_allclose(xv, bx, rtol=0, atol=atol) |
|
|
|
anorm = np.linalg.norm(a, 1) |
|
rcond, info = ppcon(n, ap, anorm=anorm, lower=lower) |
|
assert_equal(info, 0) |
|
assert_(abs(1/rcond - np.linalg.cond(a, p=1))*rcond < 1) |
|
|
|
|
|
@pytest.mark.parametrize('dtype', DTYPES) |
|
def test_gees_trexc(dtype): |
|
rng = np.random.RandomState(1234) |
|
atol = np.finfo(dtype).eps*100 |
|
|
|
n = 10 |
|
a = generate_random_dtype_array([n, n], dtype=dtype, rng=rng) |
|
|
|
gees, trexc = get_lapack_funcs(('gees', 'trexc'), dtype=dtype) |
|
|
|
result = gees(lambda x: None, a, overwrite_a=False) |
|
assert_equal(result[-1], 0) |
|
|
|
t = result[0] |
|
z = result[-3] |
|
|
|
d2 = t[6, 6] |
|
|
|
if dtype in COMPLEX_DTYPES: |
|
assert_allclose(t, np.triu(t), rtol=0, atol=atol) |
|
|
|
assert_allclose(z @ t @ z.conj().T, a, rtol=0, atol=atol) |
|
|
|
result = trexc(t, z, 7, 1) |
|
assert_equal(result[-1], 0) |
|
|
|
t = result[0] |
|
z = result[-2] |
|
|
|
if dtype in COMPLEX_DTYPES: |
|
assert_allclose(t, np.triu(t), rtol=0, atol=atol) |
|
|
|
assert_allclose(z @ t @ z.conj().T, a, rtol=0, atol=atol) |
|
|
|
assert_allclose(t[0, 0], d2, rtol=0, atol=atol) |
|
|
|
|
|
@pytest.mark.parametrize( |
|
"t, expect, ifst, ilst", |
|
[(np.array([[0.80, -0.11, 0.01, 0.03], |
|
[0.00, -0.10, 0.25, 0.35], |
|
[0.00, -0.65, -0.10, 0.20], |
|
[0.00, 0.00, 0.00, -0.10]]), |
|
np.array([[-0.1000, -0.6463, 0.0874, 0.2010], |
|
[0.2514, -0.1000, 0.0927, 0.3505], |
|
[0.0000, 0.0000, 0.8000, -0.0117], |
|
[0.0000, 0.0000, 0.0000, -0.1000]]), |
|
2, 1), |
|
(np.array([[-6.00 - 7.00j, 0.36 - 0.36j, -0.19 + 0.48j, 0.88 - 0.25j], |
|
[0.00 + 0.00j, -5.00 + 2.00j, -0.03 - 0.72j, -0.23 + 0.13j], |
|
[0.00 + 0.00j, 0.00 + 0.00j, 8.00 - 1.00j, 0.94 + 0.53j], |
|
[0.00 + 0.00j, 0.00 + 0.00j, 0.00 + 0.00j, 3.00 - 4.00j]]), |
|
np.array([[-5.0000 + 2.0000j, -0.1574 + 0.7143j, |
|
0.1781 - 0.1913j, 0.3950 + 0.3861j], |
|
[0.0000 + 0.0000j, 8.0000 - 1.0000j, |
|
1.0742 + 0.1447j, 0.2515 - 0.3397j], |
|
[0.0000 + 0.0000j, 0.0000 + 0.0000j, |
|
3.0000 - 4.0000j, 0.2264 + 0.8962j], |
|
[0.0000 + 0.0000j, 0.0000 + 0.0000j, |
|
0.0000 + 0.0000j, -6.0000 - 7.0000j]]), |
|
1, 4)]) |
|
def test_trexc_NAG(t, ifst, ilst, expect): |
|
""" |
|
This test implements the example found in the NAG manual, |
|
f08qfc, f08qtc, f08qgc, f08quc. |
|
""" |
|
|
|
atol = 1e-4 |
|
trexc = get_lapack_funcs('trexc', dtype=t.dtype) |
|
|
|
result = trexc(t, t, ifst, ilst, wantq=0) |
|
assert_equal(result[-1], 0) |
|
|
|
t = result[0] |
|
assert_allclose(expect, t, atol=atol) |
|
|
|
|
|
@pytest.mark.parametrize('dtype', DTYPES) |
|
def test_gges_tgexc(dtype): |
|
rng = np.random.RandomState(1234) |
|
atol = np.finfo(dtype).eps*100 |
|
|
|
n = 10 |
|
a = generate_random_dtype_array([n, n], dtype=dtype, rng=rng) |
|
b = generate_random_dtype_array([n, n], dtype=dtype, rng=rng) |
|
|
|
gges, tgexc = get_lapack_funcs(('gges', 'tgexc'), dtype=dtype) |
|
|
|
result = gges(lambda x: None, a, b, overwrite_a=False, overwrite_b=False) |
|
assert_equal(result[-1], 0) |
|
|
|
s = result[0] |
|
t = result[1] |
|
q = result[-4] |
|
z = result[-3] |
|
|
|
d1 = s[0, 0] / t[0, 0] |
|
d2 = s[6, 6] / t[6, 6] |
|
|
|
if dtype in COMPLEX_DTYPES: |
|
assert_allclose(s, np.triu(s), rtol=0, atol=atol) |
|
assert_allclose(t, np.triu(t), rtol=0, atol=atol) |
|
|
|
assert_allclose(q @ s @ z.conj().T, a, rtol=0, atol=atol) |
|
assert_allclose(q @ t @ z.conj().T, b, rtol=0, atol=atol) |
|
|
|
result = tgexc(s, t, q, z, 7, 1) |
|
assert_equal(result[-1], 0) |
|
|
|
s = result[0] |
|
t = result[1] |
|
q = result[2] |
|
z = result[3] |
|
|
|
if dtype in COMPLEX_DTYPES: |
|
assert_allclose(s, np.triu(s), rtol=0, atol=atol) |
|
assert_allclose(t, np.triu(t), rtol=0, atol=atol) |
|
|
|
assert_allclose(q @ s @ z.conj().T, a, rtol=0, atol=atol) |
|
assert_allclose(q @ t @ z.conj().T, b, rtol=0, atol=atol) |
|
|
|
assert_allclose(s[0, 0] / t[0, 0], d2, rtol=0, atol=atol) |
|
assert_allclose(s[1, 1] / t[1, 1], d1, rtol=0, atol=atol) |
|
|
|
|
|
@pytest.mark.parametrize('dtype', DTYPES) |
|
def test_gees_trsen(dtype): |
|
rng = np.random.RandomState(1234) |
|
atol = np.finfo(dtype).eps*100 |
|
|
|
n = 10 |
|
a = generate_random_dtype_array([n, n], dtype=dtype, rng=rng) |
|
|
|
gees, trsen, trsen_lwork = get_lapack_funcs( |
|
('gees', 'trsen', 'trsen_lwork'), dtype=dtype) |
|
|
|
result = gees(lambda x: None, a, overwrite_a=False) |
|
assert_equal(result[-1], 0) |
|
|
|
t = result[0] |
|
z = result[-3] |
|
|
|
d2 = t[6, 6] |
|
|
|
if dtype in COMPLEX_DTYPES: |
|
assert_allclose(t, np.triu(t), rtol=0, atol=atol) |
|
|
|
assert_allclose(z @ t @ z.conj().T, a, rtol=0, atol=atol) |
|
|
|
select = np.zeros(n) |
|
select[6] = 1 |
|
|
|
lwork = _compute_lwork(trsen_lwork, select, t) |
|
|
|
if dtype in COMPLEX_DTYPES: |
|
result = trsen(select, t, z, lwork=lwork) |
|
else: |
|
result = trsen(select, t, z, lwork=lwork, liwork=lwork[1]) |
|
assert_equal(result[-1], 0) |
|
|
|
t = result[0] |
|
z = result[1] |
|
|
|
if dtype in COMPLEX_DTYPES: |
|
assert_allclose(t, np.triu(t), rtol=0, atol=atol) |
|
|
|
assert_allclose(z @ t @ z.conj().T, a, rtol=0, atol=atol) |
|
|
|
assert_allclose(t[0, 0], d2, rtol=0, atol=atol) |
|
|
|
|
|
@pytest.mark.parametrize( |
|
"t, q, expect, select, expect_s, expect_sep", |
|
[(np.array([[0.7995, -0.1144, 0.0060, 0.0336], |
|
[0.0000, -0.0994, 0.2478, 0.3474], |
|
[0.0000, -0.6483, -0.0994, 0.2026], |
|
[0.0000, 0.0000, 0.0000, -0.1007]]), |
|
np.array([[0.6551, 0.1037, 0.3450, 0.6641], |
|
[0.5236, -0.5807, -0.6141, -0.1068], |
|
[-0.5362, -0.3073, -0.2935, 0.7293], |
|
[0.0956, 0.7467, -0.6463, 0.1249]]), |
|
np.array([[0.3500, 0.4500, -0.1400, -0.1700], |
|
[0.0900, 0.0700, -0.5399, 0.3500], |
|
[-0.4400, -0.3300, -0.0300, 0.1700], |
|
[0.2500, -0.3200, -0.1300, 0.1100]]), |
|
np.array([1, 0, 0, 1]), |
|
1.75e+00, 3.22e+00), |
|
(np.array([[-6.0004 - 6.9999j, 0.3637 - 0.3656j, |
|
-0.1880 + 0.4787j, 0.8785 - 0.2539j], |
|
[0.0000 + 0.0000j, -5.0000 + 2.0060j, |
|
-0.0307 - 0.7217j, -0.2290 + 0.1313j], |
|
[0.0000 + 0.0000j, 0.0000 + 0.0000j, |
|
7.9982 - 0.9964j, 0.9357 + 0.5359j], |
|
[0.0000 + 0.0000j, 0.0000 + 0.0000j, |
|
0.0000 + 0.0000j, 3.0023 - 3.9998j]]), |
|
np.array([[-0.8347 - 0.1364j, -0.0628 + 0.3806j, |
|
0.2765 - 0.0846j, 0.0633 - 0.2199j], |
|
[0.0664 - 0.2968j, 0.2365 + 0.5240j, |
|
-0.5877 - 0.4208j, 0.0835 + 0.2183j], |
|
[-0.0362 - 0.3215j, 0.3143 - 0.5473j, |
|
0.0576 - 0.5736j, 0.0057 - 0.4058j], |
|
[0.0086 + 0.2958j, -0.3416 - 0.0757j, |
|
-0.1900 - 0.1600j, 0.8327 - 0.1868j]]), |
|
np.array([[-3.9702 - 5.0406j, -4.1108 + 3.7002j, |
|
-0.3403 + 1.0098j, 1.2899 - 0.8590j], |
|
[0.3397 - 1.5006j, 1.5201 - 0.4301j, |
|
1.8797 - 5.3804j, 3.3606 + 0.6498j], |
|
[3.3101 - 3.8506j, 2.4996 + 3.4504j, |
|
0.8802 - 1.0802j, 0.6401 - 1.4800j], |
|
[-1.0999 + 0.8199j, 1.8103 - 1.5905j, |
|
3.2502 + 1.3297j, 1.5701 - 3.4397j]]), |
|
np.array([1, 0, 0, 1]), |
|
1.02e+00, 1.82e-01)]) |
|
def test_trsen_NAG(t, q, select, expect, expect_s, expect_sep): |
|
""" |
|
This test implements the example found in the NAG manual, |
|
f08qgc, f08quc. |
|
""" |
|
|
|
atol = 1e-4 |
|
atol2 = 1e-2 |
|
trsen, trsen_lwork = get_lapack_funcs( |
|
('trsen', 'trsen_lwork'), dtype=t.dtype) |
|
|
|
lwork = _compute_lwork(trsen_lwork, select, t) |
|
|
|
if t.dtype in COMPLEX_DTYPES: |
|
result = trsen(select, t, q, lwork=lwork) |
|
else: |
|
result = trsen(select, t, q, lwork=lwork, liwork=lwork[1]) |
|
assert_equal(result[-1], 0) |
|
|
|
t = result[0] |
|
q = result[1] |
|
if t.dtype in COMPLEX_DTYPES: |
|
s = result[4] |
|
sep = result[5] |
|
else: |
|
s = result[5] |
|
sep = result[6] |
|
|
|
assert_allclose(expect, q @ t @ q.conj().T, atol=atol) |
|
assert_allclose(expect_s, 1 / s, atol=atol2) |
|
assert_allclose(expect_sep, 1 / sep, atol=atol2) |
|
|
|
|
|
@pytest.mark.parametrize('dtype', DTYPES) |
|
def test_gges_tgsen(dtype): |
|
rng = np.random.RandomState(1234) |
|
atol = np.finfo(dtype).eps*100 |
|
|
|
n = 10 |
|
a = generate_random_dtype_array([n, n], dtype=dtype, rng=rng) |
|
b = generate_random_dtype_array([n, n], dtype=dtype, rng=rng) |
|
|
|
gges, tgsen, tgsen_lwork = get_lapack_funcs( |
|
('gges', 'tgsen', 'tgsen_lwork'), dtype=dtype) |
|
|
|
result = gges(lambda x: None, a, b, overwrite_a=False, overwrite_b=False) |
|
assert_equal(result[-1], 0) |
|
|
|
s = result[0] |
|
t = result[1] |
|
q = result[-4] |
|
z = result[-3] |
|
|
|
d1 = s[0, 0] / t[0, 0] |
|
d2 = s[6, 6] / t[6, 6] |
|
|
|
if dtype in COMPLEX_DTYPES: |
|
assert_allclose(s, np.triu(s), rtol=0, atol=atol) |
|
assert_allclose(t, np.triu(t), rtol=0, atol=atol) |
|
|
|
assert_allclose(q @ s @ z.conj().T, a, rtol=0, atol=atol) |
|
assert_allclose(q @ t @ z.conj().T, b, rtol=0, atol=atol) |
|
|
|
select = np.zeros(n) |
|
select[6] = 1 |
|
|
|
lwork = _compute_lwork(tgsen_lwork, select, s, t) |
|
|
|
|
|
lwork = (lwork[0]+1, lwork[1]) |
|
|
|
result = tgsen(select, s, t, q, z, lwork=lwork) |
|
assert_equal(result[-1], 0) |
|
|
|
s = result[0] |
|
t = result[1] |
|
q = result[-7] |
|
z = result[-6] |
|
|
|
if dtype in COMPLEX_DTYPES: |
|
assert_allclose(s, np.triu(s), rtol=0, atol=atol) |
|
assert_allclose(t, np.triu(t), rtol=0, atol=atol) |
|
|
|
assert_allclose(q @ s @ z.conj().T, a, rtol=0, atol=atol) |
|
assert_allclose(q @ t @ z.conj().T, b, rtol=0, atol=atol) |
|
|
|
assert_allclose(s[0, 0] / t[0, 0], d2, rtol=0, atol=atol) |
|
assert_allclose(s[1, 1] / t[1, 1], d1, rtol=0, atol=atol) |
|
|
|
|
|
@pytest.mark.parametrize( |
|
"a, b, c, d, e, f, rans, lans", |
|
[(np.array([[4.0, 1.0, 1.0, 2.0], |
|
[0.0, 3.0, 4.0, 1.0], |
|
[0.0, 1.0, 3.0, 1.0], |
|
[0.0, 0.0, 0.0, 6.0]]), |
|
np.array([[1.0, 1.0, 1.0, 1.0], |
|
[0.0, 3.0, 4.0, 1.0], |
|
[0.0, 1.0, 3.0, 1.0], |
|
[0.0, 0.0, 0.0, 4.0]]), |
|
np.array([[-4.0, 7.0, 1.0, 12.0], |
|
[-9.0, 2.0, -2.0, -2.0], |
|
[-4.0, 2.0, -2.0, 8.0], |
|
[-7.0, 7.0, -6.0, 19.0]]), |
|
np.array([[2.0, 1.0, 1.0, 3.0], |
|
[0.0, 1.0, 2.0, 1.0], |
|
[0.0, 0.0, 1.0, 1.0], |
|
[0.0, 0.0, 0.0, 2.0]]), |
|
np.array([[1.0, 1.0, 1.0, 2.0], |
|
[0.0, 1.0, 4.0, 1.0], |
|
[0.0, 0.0, 1.0, 1.0], |
|
[0.0, 0.0, 0.0, 1.0]]), |
|
np.array([[-7.0, 5.0, 0.0, 7.0], |
|
[-5.0, 1.0, -8.0, 0.0], |
|
[-1.0, 2.0, -3.0, 5.0], |
|
[-3.0, 2.0, 0.0, 5.0]]), |
|
np.array([[1.0, 1.0, 1.0, 1.0], |
|
[-1.0, 2.0, -1.0, -1.0], |
|
[-1.0, 1.0, 3.0, 1.0], |
|
[-1.0, 1.0, -1.0, 4.0]]), |
|
np.array([[4.0, -1.0, 1.0, -1.0], |
|
[1.0, 3.0, -1.0, 1.0], |
|
[-1.0, 1.0, 2.0, -1.0], |
|
[1.0, -1.0, 1.0, 1.0]]))]) |
|
@pytest.mark.parametrize('dtype', REAL_DTYPES) |
|
def test_tgsyl_NAG(a, b, c, d, e, f, rans, lans, dtype): |
|
atol = 1e-4 |
|
|
|
tgsyl = get_lapack_funcs(('tgsyl'), dtype=dtype) |
|
rout, lout, scale, dif, info = tgsyl(a, b, c, d, e, f) |
|
|
|
assert_equal(info, 0) |
|
assert_allclose(scale, 1.0, rtol=0, atol=np.finfo(dtype).eps*100, |
|
err_msg="SCALE must be 1.0") |
|
assert_allclose(dif, 0.0, rtol=0, atol=np.finfo(dtype).eps*100, |
|
err_msg="DIF must be nearly 0") |
|
assert_allclose(rout, rans, atol=atol, |
|
err_msg="Solution for R is incorrect") |
|
assert_allclose(lout, lans, atol=atol, |
|
err_msg="Solution for L is incorrect") |
|
|
|
|
|
@pytest.mark.parametrize('dtype', REAL_DTYPES) |
|
@pytest.mark.parametrize('trans', ('N', 'T')) |
|
@pytest.mark.parametrize('ijob', [0, 1, 2, 3, 4]) |
|
def test_tgsyl(dtype, trans, ijob): |
|
|
|
atol = 1e-3 if dtype == np.float32 else 1e-10 |
|
rng = np.random.default_rng(1685779866898198) |
|
m, n = 10, 15 |
|
|
|
a, d, *_ = qz(rng.uniform(-10, 10, [m, m]).astype(dtype), |
|
rng.uniform(-10, 10, [m, m]).astype(dtype), |
|
output='real') |
|
|
|
b, e, *_ = qz(rng.uniform(-10, 10, [n, n]).astype(dtype), |
|
rng.uniform(-10, 10, [n, n]).astype(dtype), |
|
output='real') |
|
|
|
c = rng.uniform(-2, 2, [m, n]).astype(dtype) |
|
f = rng.uniform(-2, 2, [m, n]).astype(dtype) |
|
|
|
tgsyl = get_lapack_funcs(('tgsyl'), dtype=dtype) |
|
rout, lout, scale, dif, info = tgsyl(a, b, c, d, e, f, |
|
trans=trans, ijob=ijob) |
|
|
|
assert info == 0, "INFO is non-zero" |
|
assert scale >= 0.0, "SCALE must be non-negative" |
|
if ijob == 0: |
|
assert_allclose(dif, 0.0, rtol=0, atol=np.finfo(dtype).eps*100, |
|
err_msg="DIF must be 0 for ijob =0") |
|
else: |
|
assert dif >= 0.0, "DIF must be non-negative" |
|
|
|
|
|
if ijob <= 2: |
|
if trans == 'N': |
|
lhs1 = a @ rout - lout @ b |
|
rhs1 = scale*c |
|
lhs2 = d @ rout - lout @ e |
|
rhs2 = scale*f |
|
elif trans == 'T': |
|
lhs1 = np.transpose(a) @ rout + np.transpose(d) @ lout |
|
rhs1 = scale*c |
|
lhs2 = rout @ np.transpose(b) + lout @ np.transpose(e) |
|
rhs2 = -1.0*scale*f |
|
|
|
assert_allclose(lhs1, rhs1, atol=atol, rtol=0., |
|
err_msg='lhs1 and rhs1 do not match') |
|
assert_allclose(lhs2, rhs2, atol=atol, rtol=0., |
|
err_msg='lhs2 and rhs2 do not match') |
|
|
|
|
|
@pytest.mark.parametrize('mtype', ['sy', 'he']) |
|
@pytest.mark.parametrize('dtype', DTYPES) |
|
@pytest.mark.parametrize('lower', (0, 1)) |
|
def test_sy_hetrs(mtype, dtype, lower): |
|
if mtype == 'he' and dtype in REAL_DTYPES: |
|
pytest.skip("hetrs not for real dtypes.") |
|
rng = np.random.default_rng(1723059677121834) |
|
n, nrhs = 20, 5 |
|
if dtype in COMPLEX_DTYPES: |
|
A = (rng.uniform(size=(n, n)) + rng.uniform(size=(n, n))*1j).astype(dtype) |
|
else: |
|
A = rng.uniform(size=(n, n)).astype(dtype) |
|
|
|
A = A + A.T if mtype == 'sy' else A + A.conj().T |
|
b = rng.uniform(size=(n, nrhs)).astype(dtype) |
|
names = f'{mtype}trf', f'{mtype}trf_lwork', f'{mtype}trs' |
|
trf, trf_lwork, trs = get_lapack_funcs(names, dtype=dtype) |
|
lwork = trf_lwork(n, lower=lower) |
|
ldu, ipiv, info = trf(A, lwork=lwork) |
|
assert info == 0 |
|
x, info = trs(a=ldu, ipiv=ipiv, b=b) |
|
assert info == 0 |
|
eps = np.finfo(dtype).eps |
|
assert_allclose(A@x, b, atol=100*n*eps) |
|
|
|
|
|
@pytest.mark.parametrize('norm', list('Mm1OoIiFfEe')) |
|
@pytest.mark.parametrize('uplo, m, n', [('U', 5, 10), ('U', 10, 10), |
|
('L', 10, 5), ('L', 10, 10)]) |
|
@pytest.mark.parametrize('diag', ['N', 'U']) |
|
@pytest.mark.parametrize('dtype', DTYPES) |
|
def test_lantr(norm, uplo, m, n, diag, dtype): |
|
rng = np.random.default_rng(98426598246982456) |
|
A = rng.random(size=(m, n)).astype(dtype) |
|
lantr, lange = get_lapack_funcs(('lantr', 'lange'), (A,)) |
|
res = lantr(norm, A, uplo=uplo, diag=diag) |
|
|
|
|
|
A = np.triu(A) if uplo == 'U' else np.tril(A) |
|
if diag == 'U': |
|
i = np.arange(min(m, n)) |
|
A[i, i] = 1 |
|
ref = lange(norm, A) |
|
|
|
assert_allclose(res, ref, rtol=2e-6) |
|
|