Puyiiii commited on
Commit
0932c72
·
verified ·
1 Parent(s): 5692edd

Add files using upload-large-folder tool

Browse files
This view is limited to 50 files because it contains too many changes.   See raw diff
Files changed (50) hide show
  1. astra_scene_test/Scene_04/.venv/lib/python3.9/site-packages/scipy/__config__.py +161 -0
  2. astra_scene_test/Scene_04/.venv/lib/python3.9/site-packages/scipy/_distributor_init.py +18 -0
  3. astra_scene_test/Scene_04/.venv/lib/python3.9/site-packages/scipy/cluster/__init__.py +31 -0
  4. astra_scene_test/Scene_04/.venv/lib/python3.9/site-packages/scipy/cluster/hierarchy.py +0 -0
  5. astra_scene_test/Scene_04/.venv/lib/python3.9/site-packages/scipy/cluster/tests/__init__.py +0 -0
  6. astra_scene_test/Scene_04/.venv/lib/python3.9/site-packages/scipy/cluster/tests/hierarchy_test_data.py +145 -0
  7. astra_scene_test/Scene_04/.venv/lib/python3.9/site-packages/scipy/cluster/tests/test_disjoint_set.py +202 -0
  8. astra_scene_test/Scene_04/.venv/lib/python3.9/site-packages/scipy/cluster/tests/test_hierarchy.py +1225 -0
  9. astra_scene_test/Scene_04/.venv/lib/python3.9/site-packages/scipy/cluster/tests/test_vq.py +421 -0
  10. astra_scene_test/Scene_04/.venv/lib/python3.9/site-packages/scipy/cluster/vq.py +835 -0
  11. astra_scene_test/Scene_04/.venv/lib/python3.9/site-packages/scipy/linalg/__init__.py +236 -0
  12. astra_scene_test/Scene_04/.venv/lib/python3.9/site-packages/scipy/linalg/_basic.py +1919 -0
  13. astra_scene_test/Scene_04/.venv/lib/python3.9/site-packages/scipy/linalg/_blas_subroutines.h +164 -0
  14. astra_scene_test/Scene_04/.venv/lib/python3.9/site-packages/scipy/linalg/_cythonized_array_utils.pxd +40 -0
  15. astra_scene_test/Scene_04/.venv/lib/python3.9/site-packages/scipy/linalg/_cythonized_array_utils.pyi +16 -0
  16. astra_scene_test/Scene_04/.venv/lib/python3.9/site-packages/scipy/linalg/_decomp.py +1621 -0
  17. astra_scene_test/Scene_04/.venv/lib/python3.9/site-packages/scipy/linalg/_decomp_cholesky.py +356 -0
  18. astra_scene_test/Scene_04/.venv/lib/python3.9/site-packages/scipy/linalg/_decomp_cossin.py +221 -0
  19. astra_scene_test/Scene_04/.venv/lib/python3.9/site-packages/scipy/linalg/_decomp_ldl.py +353 -0
  20. astra_scene_test/Scene_04/.venv/lib/python3.9/site-packages/scipy/linalg/_decomp_lu.py +374 -0
  21. astra_scene_test/Scene_04/.venv/lib/python3.9/site-packages/scipy/linalg/_decomp_lu_cython.pyi +6 -0
  22. astra_scene_test/Scene_04/.venv/lib/python3.9/site-packages/scipy/linalg/_decomp_polar.py +111 -0
  23. astra_scene_test/Scene_04/.venv/lib/python3.9/site-packages/scipy/linalg/_decomp_qr.py +430 -0
  24. astra_scene_test/Scene_04/.venv/lib/python3.9/site-packages/scipy/linalg/_decomp_qz.py +449 -0
  25. astra_scene_test/Scene_04/.venv/lib/python3.9/site-packages/scipy/linalg/_decomp_schur.py +300 -0
  26. astra_scene_test/Scene_04/.venv/lib/python3.9/site-packages/scipy/linalg/_decomp_svd.py +517 -0
  27. astra_scene_test/Scene_04/.venv/lib/python3.9/site-packages/scipy/linalg/_expm_frechet.py +413 -0
  28. astra_scene_test/Scene_04/.venv/lib/python3.9/site-packages/scipy/linalg/_interpolative_backend.py +1681 -0
  29. astra_scene_test/Scene_04/.venv/lib/python3.9/site-packages/scipy/linalg/_lapack_subroutines.h +0 -0
  30. astra_scene_test/Scene_04/.venv/lib/python3.9/site-packages/scipy/linalg/_matfuncs.py +861 -0
  31. astra_scene_test/Scene_04/.venv/lib/python3.9/site-packages/scipy/linalg/_matfuncs_expm.pyi +6 -0
  32. astra_scene_test/Scene_04/.venv/lib/python3.9/site-packages/scipy/linalg/_matfuncs_inv_ssq.py +886 -0
  33. astra_scene_test/Scene_04/.venv/lib/python3.9/site-packages/scipy/linalg/_matfuncs_sqrtm.py +214 -0
  34. astra_scene_test/Scene_04/.venv/lib/python3.9/site-packages/scipy/linalg/_misc.py +191 -0
  35. astra_scene_test/Scene_04/.venv/lib/python3.9/site-packages/scipy/linalg/_procrustes.py +90 -0
  36. astra_scene_test/Scene_04/.venv/lib/python3.9/site-packages/scipy/linalg/_sketches.py +179 -0
  37. astra_scene_test/Scene_04/.venv/lib/python3.9/site-packages/scipy/linalg/_solvers.py +846 -0
  38. astra_scene_test/Scene_04/.venv/lib/python3.9/site-packages/scipy/linalg/_special_matrices.py +1257 -0
  39. astra_scene_test/Scene_04/.venv/lib/python3.9/site-packages/scipy/linalg/_testutils.py +65 -0
  40. astra_scene_test/Scene_04/.venv/lib/python3.9/site-packages/scipy/linalg/basic.py +24 -0
  41. astra_scene_test/Scene_04/.venv/lib/python3.9/site-packages/scipy/linalg/blas.py +484 -0
  42. astra_scene_test/Scene_04/.venv/lib/python3.9/site-packages/scipy/linalg/cython_blas.pxd +169 -0
  43. astra_scene_test/Scene_04/.venv/lib/python3.9/site-packages/scipy/linalg/cython_blas.pyx +1422 -0
  44. astra_scene_test/Scene_04/.venv/lib/python3.9/site-packages/scipy/linalg/cython_lapack.pxd +0 -0
  45. astra_scene_test/Scene_04/.venv/lib/python3.9/site-packages/scipy/linalg/cython_lapack.pyx +0 -0
  46. astra_scene_test/Scene_04/.venv/lib/python3.9/site-packages/scipy/linalg/decomp.py +25 -0
  47. astra_scene_test/Scene_04/.venv/lib/python3.9/site-packages/scipy/linalg/decomp_cholesky.py +22 -0
  48. astra_scene_test/Scene_04/.venv/lib/python3.9/site-packages/scipy/linalg/decomp_lu.py +21 -0
  49. astra_scene_test/Scene_04/.venv/lib/python3.9/site-packages/scipy/linalg/decomp_qr.py +20 -0
  50. astra_scene_test/Scene_04/.venv/lib/python3.9/site-packages/scipy/linalg/decomp_schur.py +22 -0
astra_scene_test/Scene_04/.venv/lib/python3.9/site-packages/scipy/__config__.py ADDED
@@ -0,0 +1,161 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # This file is generated by SciPy's build process
2
+ # It contains system_info results at the time of building this package.
3
+ from enum import Enum
4
+
5
+ __all__ = ["show"]
6
+ _built_with_meson = True
7
+
8
+
9
+ class DisplayModes(Enum):
10
+ stdout = "stdout"
11
+ dicts = "dicts"
12
+
13
+
14
+ def _cleanup(d):
15
+ """
16
+ Removes empty values in a `dict` recursively
17
+ This ensures we remove values that Meson could not provide to CONFIG
18
+ """
19
+ if isinstance(d, dict):
20
+ return { k: _cleanup(v) for k, v in d.items() if v != '' and _cleanup(v) != '' }
21
+ else:
22
+ return d
23
+
24
+
25
+ CONFIG = _cleanup(
26
+ {
27
+ "Compilers": {
28
+ "c": {
29
+ "name": "clang",
30
+ "linker": r"ld64",
31
+ "version": "15.0.0",
32
+ "commands": r"cc",
33
+ "args": r"",
34
+ "linker args": r"",
35
+ },
36
+ "cython": {
37
+ "name": r"cython",
38
+ "linker": r"cython",
39
+ "version": r"3.0.10",
40
+ "commands": r"cython",
41
+ "args": r"",
42
+ "linker args": r"",
43
+ },
44
+ "c++": {
45
+ "name": "clang",
46
+ "linker": r"ld64",
47
+ "version": "15.0.0",
48
+ "commands": r"c++",
49
+ "args": r"",
50
+ "linker args": r"",
51
+ },
52
+ "fortran": {
53
+ "name": "gcc",
54
+ "linker": r"ld64",
55
+ "version": "12.1.0",
56
+ "commands": r"gfortran",
57
+ "args": r"",
58
+ "linker args": r"",
59
+ },
60
+ "pythran": {
61
+ "version": r"0.15.0",
62
+ "include directory": r"../../../../../../private/var/folders/2f/8t5k6yr535sdw0s4glnpxrzm0000gn/T/pip-build-env-ddcl7dz8/overlay/lib/python3.9/site-packages/pythran"
63
+ },
64
+ },
65
+ "Machine Information": {
66
+ "host": {
67
+ "cpu": r"aarch64",
68
+ "family": r"aarch64",
69
+ "endian": r"little",
70
+ "system": r"darwin",
71
+ },
72
+ "build": {
73
+ "cpu": r"aarch64",
74
+ "family": r"aarch64",
75
+ "endian": r"little",
76
+ "system": r"darwin",
77
+ },
78
+ "cross-compiled": bool("False".lower().replace('false', '')),
79
+ },
80
+ "Build Dependencies": {
81
+ "blas": {
82
+ "name": "openblas",
83
+ "found": bool("True".lower().replace('false', '')),
84
+ "version": "0.3.27",
85
+ "detection method": "pkgconfig",
86
+ "include directory": r"/opt/arm64-builds/include",
87
+ "lib directory": r"/opt/arm64-builds/lib",
88
+ "openblas configuration": r"USE_64BITINT=0 DYNAMIC_ARCH=1 DYNAMIC_OLDER= NO_CBLAS= NO_LAPACK= NO_LAPACKE= NO_AFFINITY=1 USE_OPENMP= SANDYBRIDGE MAX_THREADS=64",
89
+ "pc file directory": r"/opt/arm64-builds/lib/pkgconfig",
90
+ },
91
+ "lapack": {
92
+ "name": "openblas",
93
+ "found": bool("True".lower().replace('false', '')),
94
+ "version": "0.3.27",
95
+ "detection method": "pkgconfig",
96
+ "include directory": r"/opt/arm64-builds/include",
97
+ "lib directory": r"/opt/arm64-builds/lib",
98
+ "openblas configuration": r"USE_64BITINT=0 DYNAMIC_ARCH=1 DYNAMIC_OLDER= NO_CBLAS= NO_LAPACK= NO_LAPACKE= NO_AFFINITY=1 USE_OPENMP= SANDYBRIDGE MAX_THREADS=64",
99
+ "pc file directory": r"/opt/arm64-builds/lib/pkgconfig",
100
+ },
101
+ "pybind11": {
102
+ "name": "pybind11",
103
+ "version": "2.12.0",
104
+ "detection method": "config-tool",
105
+ "include directory": r"unknown",
106
+ },
107
+ },
108
+ "Python Information": {
109
+ "path": r"/private/var/folders/2f/8t5k6yr535sdw0s4glnpxrzm0000gn/T/cibw-run-_36keccq/cp39-macosx_arm64/build/venv/bin/python",
110
+ "version": "3.9",
111
+ },
112
+ }
113
+ )
114
+
115
+
116
+ def _check_pyyaml():
117
+ import yaml
118
+
119
+ return yaml
120
+
121
+
122
+ def show(mode=DisplayModes.stdout.value):
123
+ """
124
+ Show libraries and system information on which SciPy was built
125
+ and is being used
126
+
127
+ Parameters
128
+ ----------
129
+ mode : {`'stdout'`, `'dicts'`}, optional.
130
+ Indicates how to display the config information.
131
+ `'stdout'` prints to console, `'dicts'` returns a dictionary
132
+ of the configuration.
133
+
134
+ Returns
135
+ -------
136
+ out : {`dict`, `None`}
137
+ If mode is `'dicts'`, a dict is returned, else None
138
+
139
+ Notes
140
+ -----
141
+ 1. The `'stdout'` mode will give more readable
142
+ output if ``pyyaml`` is installed
143
+
144
+ """
145
+ if mode == DisplayModes.stdout.value:
146
+ try: # Non-standard library, check import
147
+ yaml = _check_pyyaml()
148
+
149
+ print(yaml.dump(CONFIG))
150
+ except ModuleNotFoundError:
151
+ import warnings
152
+ import json
153
+
154
+ warnings.warn("Install `pyyaml` for better output", stacklevel=1)
155
+ print(json.dumps(CONFIG, indent=2))
156
+ elif mode == DisplayModes.dicts.value:
157
+ return CONFIG
158
+ else:
159
+ raise AttributeError(
160
+ f"Invalid `mode`, use one of: {', '.join([e.value for e in DisplayModes])}"
161
+ )
astra_scene_test/Scene_04/.venv/lib/python3.9/site-packages/scipy/_distributor_init.py ADDED
@@ -0,0 +1,18 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """ Distributor init file
2
+
3
+ Distributors: you can replace the contents of this file with your own custom
4
+ code to support particular distributions of SciPy.
5
+
6
+ For example, this is a good place to put any checks for hardware requirements
7
+ or BLAS/LAPACK library initialization.
8
+
9
+ The SciPy standard source distribution will not put code in this file beyond
10
+ the try-except import of `_distributor_init_local` (which is not part of a
11
+ standard source distribution), so you can safely replace this file with your
12
+ own version.
13
+ """
14
+
15
+ try:
16
+ from . import _distributor_init_local # noqa: F401
17
+ except ImportError:
18
+ pass
astra_scene_test/Scene_04/.venv/lib/python3.9/site-packages/scipy/cluster/__init__.py ADDED
@@ -0,0 +1,31 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """
2
+ =========================================
3
+ Clustering package (:mod:`scipy.cluster`)
4
+ =========================================
5
+
6
+ .. currentmodule:: scipy.cluster
7
+
8
+ .. toctree::
9
+ :hidden:
10
+
11
+ cluster.vq
12
+ cluster.hierarchy
13
+
14
+ Clustering algorithms are useful in information theory, target detection,
15
+ communications, compression, and other areas. The `vq` module only
16
+ supports vector quantization and the k-means algorithms.
17
+
18
+ The `hierarchy` module provides functions for hierarchical and
19
+ agglomerative clustering. Its features include generating hierarchical
20
+ clusters from distance matrices,
21
+ calculating statistics on clusters, cutting linkages
22
+ to generate flat clusters, and visualizing clusters with dendrograms.
23
+
24
+ """
25
+ __all__ = ['vq', 'hierarchy']
26
+
27
+ from . import vq, hierarchy
28
+
29
+ from scipy._lib._testutils import PytestTester
30
+ test = PytestTester(__name__)
31
+ del PytestTester
astra_scene_test/Scene_04/.venv/lib/python3.9/site-packages/scipy/cluster/hierarchy.py ADDED
The diff for this file is too large to render. See raw diff
 
astra_scene_test/Scene_04/.venv/lib/python3.9/site-packages/scipy/cluster/tests/__init__.py ADDED
File without changes
astra_scene_test/Scene_04/.venv/lib/python3.9/site-packages/scipy/cluster/tests/hierarchy_test_data.py ADDED
@@ -0,0 +1,145 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from numpy import array
2
+
3
+
4
+ Q_X = array([[5.26563660e-01, 3.14160190e-01, 8.00656370e-02],
5
+ [7.50205180e-01, 4.60299830e-01, 8.98696460e-01],
6
+ [6.65461230e-01, 6.94011420e-01, 9.10465700e-01],
7
+ [9.64047590e-01, 1.43082200e-03, 7.39874220e-01],
8
+ [1.08159060e-01, 5.53028790e-01, 6.63804780e-02],
9
+ [9.31359130e-01, 8.25424910e-01, 9.52315440e-01],
10
+ [6.78086960e-01, 3.41903970e-01, 5.61481950e-01],
11
+ [9.82730940e-01, 7.04605210e-01, 8.70978630e-02],
12
+ [6.14691610e-01, 4.69989230e-02, 6.02406450e-01],
13
+ [5.80161260e-01, 9.17354970e-01, 5.88163850e-01],
14
+ [1.38246310e+00, 1.96358160e+00, 1.94437880e+00],
15
+ [2.10675860e+00, 1.67148730e+00, 1.34854480e+00],
16
+ [1.39880070e+00, 1.66142050e+00, 1.32224550e+00],
17
+ [1.71410460e+00, 1.49176380e+00, 1.45432170e+00],
18
+ [1.54102340e+00, 1.84374950e+00, 1.64658950e+00],
19
+ [2.08512480e+00, 1.84524350e+00, 2.17340850e+00],
20
+ [1.30748740e+00, 1.53801650e+00, 2.16007740e+00],
21
+ [1.41447700e+00, 1.99329070e+00, 1.99107420e+00],
22
+ [1.61943490e+00, 1.47703280e+00, 1.89788160e+00],
23
+ [1.59880600e+00, 1.54988980e+00, 1.57563350e+00],
24
+ [3.37247380e+00, 2.69635310e+00, 3.39981700e+00],
25
+ [3.13705120e+00, 3.36528090e+00, 3.06089070e+00],
26
+ [3.29413250e+00, 3.19619500e+00, 2.90700170e+00],
27
+ [2.65510510e+00, 3.06785900e+00, 2.97198540e+00],
28
+ [3.30941040e+00, 2.59283970e+00, 2.57714110e+00],
29
+ [2.59557220e+00, 3.33477370e+00, 3.08793190e+00],
30
+ [2.58206180e+00, 3.41615670e+00, 3.26441990e+00],
31
+ [2.71127000e+00, 2.77032450e+00, 2.63466500e+00],
32
+ [2.79617850e+00, 3.25473720e+00, 3.41801560e+00],
33
+ [2.64741750e+00, 2.54538040e+00, 3.25354110e+00]])
34
+
35
+ ytdist = array([662., 877., 255., 412., 996., 295., 468., 268., 400., 754.,
36
+ 564., 138., 219., 869., 669.])
37
+
38
+ linkage_ytdist_single = array([[2., 5., 138., 2.],
39
+ [3., 4., 219., 2.],
40
+ [0., 7., 255., 3.],
41
+ [1., 8., 268., 4.],
42
+ [6., 9., 295., 6.]])
43
+
44
+ linkage_ytdist_complete = array([[2., 5., 138., 2.],
45
+ [3., 4., 219., 2.],
46
+ [1., 6., 400., 3.],
47
+ [0., 7., 412., 3.],
48
+ [8., 9., 996., 6.]])
49
+
50
+ linkage_ytdist_average = array([[2., 5., 138., 2.],
51
+ [3., 4., 219., 2.],
52
+ [0., 7., 333.5, 3.],
53
+ [1., 6., 347.5, 3.],
54
+ [8., 9., 680.77777778, 6.]])
55
+
56
+ linkage_ytdist_weighted = array([[2., 5., 138., 2.],
57
+ [3., 4., 219., 2.],
58
+ [0., 7., 333.5, 3.],
59
+ [1., 6., 347.5, 3.],
60
+ [8., 9., 670.125, 6.]])
61
+
62
+ # the optimal leaf ordering of linkage_ytdist_single
63
+ linkage_ytdist_single_olo = array([[5., 2., 138., 2.],
64
+ [4., 3., 219., 2.],
65
+ [7., 0., 255., 3.],
66
+ [1., 8., 268., 4.],
67
+ [6., 9., 295., 6.]])
68
+
69
+ X = array([[1.43054825, -7.5693489],
70
+ [6.95887839, 6.82293382],
71
+ [2.87137846, -9.68248579],
72
+ [7.87974764, -6.05485803],
73
+ [8.24018364, -6.09495602],
74
+ [7.39020262, 8.54004355]])
75
+
76
+ linkage_X_centroid = array([[3., 4., 0.36265956, 2.],
77
+ [1., 5., 1.77045373, 2.],
78
+ [0., 2., 2.55760419, 2.],
79
+ [6., 8., 6.43614494, 4.],
80
+ [7., 9., 15.17363237, 6.]])
81
+
82
+ linkage_X_median = array([[3., 4., 0.36265956, 2.],
83
+ [1., 5., 1.77045373, 2.],
84
+ [0., 2., 2.55760419, 2.],
85
+ [6., 8., 6.43614494, 4.],
86
+ [7., 9., 15.17363237, 6.]])
87
+
88
+ linkage_X_ward = array([[3., 4., 0.36265956, 2.],
89
+ [1., 5., 1.77045373, 2.],
90
+ [0., 2., 2.55760419, 2.],
91
+ [6., 8., 9.10208346, 4.],
92
+ [7., 9., 24.7784379, 6.]])
93
+
94
+ # the optimal leaf ordering of linkage_X_ward
95
+ linkage_X_ward_olo = array([[4., 3., 0.36265956, 2.],
96
+ [5., 1., 1.77045373, 2.],
97
+ [2., 0., 2.55760419, 2.],
98
+ [6., 8., 9.10208346, 4.],
99
+ [7., 9., 24.7784379, 6.]])
100
+
101
+ inconsistent_ytdist = {
102
+ 1: array([[138., 0., 1., 0.],
103
+ [219., 0., 1., 0.],
104
+ [255., 0., 1., 0.],
105
+ [268., 0., 1., 0.],
106
+ [295., 0., 1., 0.]]),
107
+ 2: array([[138., 0., 1., 0.],
108
+ [219., 0., 1., 0.],
109
+ [237., 25.45584412, 2., 0.70710678],
110
+ [261.5, 9.19238816, 2., 0.70710678],
111
+ [233.66666667, 83.9424406, 3., 0.7306594]]),
112
+ 3: array([[138., 0., 1., 0.],
113
+ [219., 0., 1., 0.],
114
+ [237., 25.45584412, 2., 0.70710678],
115
+ [247.33333333, 25.38372182, 3., 0.81417007],
116
+ [239., 69.36377537, 4., 0.80733783]]),
117
+ 4: array([[138., 0., 1., 0.],
118
+ [219., 0., 1., 0.],
119
+ [237., 25.45584412, 2., 0.70710678],
120
+ [247.33333333, 25.38372182, 3., 0.81417007],
121
+ [235., 60.73302232, 5., 0.98793042]])}
122
+
123
+ fcluster_inconsistent = {
124
+ 0.8: array([6, 2, 2, 4, 6, 2, 3, 7, 3, 5, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 1,
125
+ 1, 1, 1, 1, 1, 1, 1, 1, 1]),
126
+ 1.0: array([6, 2, 2, 4, 6, 2, 3, 7, 3, 5, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 1,
127
+ 1, 1, 1, 1, 1, 1, 1, 1, 1]),
128
+ 2.0: array([1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
129
+ 1, 1, 1, 1, 1, 1, 1, 1, 1])}
130
+
131
+ fcluster_distance = {
132
+ 0.6: array([4, 4, 4, 4, 4, 4, 4, 5, 4, 4, 6, 6, 6, 6, 6, 7, 6, 6, 6, 6, 3,
133
+ 1, 1, 1, 2, 1, 1, 1, 1, 1]),
134
+ 1.0: array([2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 1,
135
+ 1, 1, 1, 1, 1, 1, 1, 1, 1]),
136
+ 2.0: array([1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
137
+ 1, 1, 1, 1, 1, 1, 1, 1, 1])}
138
+
139
+ fcluster_maxclust = {
140
+ 8.0: array([5, 5, 5, 5, 5, 5, 5, 6, 5, 5, 7, 7, 7, 7, 7, 8, 7, 7, 7, 7, 4,
141
+ 1, 1, 1, 3, 1, 1, 1, 1, 2]),
142
+ 4.0: array([3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 2,
143
+ 1, 1, 1, 1, 1, 1, 1, 1, 1]),
144
+ 1.0: array([1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
145
+ 1, 1, 1, 1, 1, 1, 1, 1, 1])}
astra_scene_test/Scene_04/.venv/lib/python3.9/site-packages/scipy/cluster/tests/test_disjoint_set.py ADDED
@@ -0,0 +1,202 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import pytest
2
+ from pytest import raises as assert_raises
3
+ import numpy as np
4
+ from scipy.cluster.hierarchy import DisjointSet
5
+ import string
6
+
7
+
8
+ def generate_random_token():
9
+ k = len(string.ascii_letters)
10
+ tokens = list(np.arange(k, dtype=int))
11
+ tokens += list(np.arange(k, dtype=float))
12
+ tokens += list(string.ascii_letters)
13
+ tokens += [None for i in range(k)]
14
+ tokens = np.array(tokens, dtype=object)
15
+ rng = np.random.RandomState(seed=0)
16
+
17
+ while 1:
18
+ size = rng.randint(1, 3)
19
+ element = rng.choice(tokens, size)
20
+ if size == 1:
21
+ yield element[0]
22
+ else:
23
+ yield tuple(element)
24
+
25
+
26
+ def get_elements(n):
27
+ # dict is deterministic without difficulty of comparing numpy ints
28
+ elements = {}
29
+ for element in generate_random_token():
30
+ if element not in elements:
31
+ elements[element] = len(elements)
32
+ if len(elements) >= n:
33
+ break
34
+ return list(elements.keys())
35
+
36
+
37
+ def test_init():
38
+ n = 10
39
+ elements = get_elements(n)
40
+ dis = DisjointSet(elements)
41
+ assert dis.n_subsets == n
42
+ assert list(dis) == elements
43
+
44
+
45
+ def test_len():
46
+ n = 10
47
+ elements = get_elements(n)
48
+ dis = DisjointSet(elements)
49
+ assert len(dis) == n
50
+
51
+ dis.add("dummy")
52
+ assert len(dis) == n + 1
53
+
54
+
55
+ @pytest.mark.parametrize("n", [10, 100])
56
+ def test_contains(n):
57
+ elements = get_elements(n)
58
+ dis = DisjointSet(elements)
59
+ for x in elements:
60
+ assert x in dis
61
+
62
+ assert "dummy" not in dis
63
+
64
+
65
+ @pytest.mark.parametrize("n", [10, 100])
66
+ def test_add(n):
67
+ elements = get_elements(n)
68
+ dis1 = DisjointSet(elements)
69
+
70
+ dis2 = DisjointSet()
71
+ for i, x in enumerate(elements):
72
+ dis2.add(x)
73
+ assert len(dis2) == i + 1
74
+
75
+ # test idempotency by adding element again
76
+ dis2.add(x)
77
+ assert len(dis2) == i + 1
78
+
79
+ assert list(dis1) == list(dis2)
80
+
81
+
82
+ def test_element_not_present():
83
+ elements = get_elements(n=10)
84
+ dis = DisjointSet(elements)
85
+
86
+ with assert_raises(KeyError):
87
+ dis["dummy"]
88
+
89
+ with assert_raises(KeyError):
90
+ dis.merge(elements[0], "dummy")
91
+
92
+ with assert_raises(KeyError):
93
+ dis.connected(elements[0], "dummy")
94
+
95
+
96
+ @pytest.mark.parametrize("direction", ["forwards", "backwards"])
97
+ @pytest.mark.parametrize("n", [10, 100])
98
+ def test_linear_union_sequence(n, direction):
99
+ elements = get_elements(n)
100
+ dis = DisjointSet(elements)
101
+ assert elements == list(dis)
102
+
103
+ indices = list(range(n - 1))
104
+ if direction == "backwards":
105
+ indices = indices[::-1]
106
+
107
+ for it, i in enumerate(indices):
108
+ assert not dis.connected(elements[i], elements[i + 1])
109
+ assert dis.merge(elements[i], elements[i + 1])
110
+ assert dis.connected(elements[i], elements[i + 1])
111
+ assert dis.n_subsets == n - 1 - it
112
+
113
+ roots = [dis[i] for i in elements]
114
+ if direction == "forwards":
115
+ assert all(elements[0] == r for r in roots)
116
+ else:
117
+ assert all(elements[-2] == r for r in roots)
118
+ assert not dis.merge(elements[0], elements[-1])
119
+
120
+
121
+ @pytest.mark.parametrize("n", [10, 100])
122
+ def test_self_unions(n):
123
+ elements = get_elements(n)
124
+ dis = DisjointSet(elements)
125
+
126
+ for x in elements:
127
+ assert dis.connected(x, x)
128
+ assert not dis.merge(x, x)
129
+ assert dis.connected(x, x)
130
+ assert dis.n_subsets == len(elements)
131
+
132
+ assert elements == list(dis)
133
+ roots = [dis[x] for x in elements]
134
+ assert elements == roots
135
+
136
+
137
+ @pytest.mark.parametrize("order", ["ab", "ba"])
138
+ @pytest.mark.parametrize("n", [10, 100])
139
+ def test_equal_size_ordering(n, order):
140
+ elements = get_elements(n)
141
+ dis = DisjointSet(elements)
142
+
143
+ rng = np.random.RandomState(seed=0)
144
+ indices = np.arange(n)
145
+ rng.shuffle(indices)
146
+
147
+ for i in range(0, len(indices), 2):
148
+ a, b = elements[indices[i]], elements[indices[i + 1]]
149
+ if order == "ab":
150
+ assert dis.merge(a, b)
151
+ else:
152
+ assert dis.merge(b, a)
153
+
154
+ expected = elements[min(indices[i], indices[i + 1])]
155
+ assert dis[a] == expected
156
+ assert dis[b] == expected
157
+
158
+
159
+ @pytest.mark.parametrize("kmax", [5, 10])
160
+ def test_binary_tree(kmax):
161
+ n = 2**kmax
162
+ elements = get_elements(n)
163
+ dis = DisjointSet(elements)
164
+ rng = np.random.RandomState(seed=0)
165
+
166
+ for k in 2**np.arange(kmax):
167
+ for i in range(0, n, 2 * k):
168
+ r1, r2 = rng.randint(0, k, size=2)
169
+ a, b = elements[i + r1], elements[i + k + r2]
170
+ assert not dis.connected(a, b)
171
+ assert dis.merge(a, b)
172
+ assert dis.connected(a, b)
173
+
174
+ assert elements == list(dis)
175
+ roots = [dis[i] for i in elements]
176
+ expected_indices = np.arange(n) - np.arange(n) % (2 * k)
177
+ expected = [elements[i] for i in expected_indices]
178
+ assert roots == expected
179
+
180
+
181
+ @pytest.mark.parametrize("n", [10, 100])
182
+ def test_subsets(n):
183
+ elements = get_elements(n)
184
+ dis = DisjointSet(elements)
185
+
186
+ rng = np.random.RandomState(seed=0)
187
+ for i, j in rng.randint(0, n, (n, 2)):
188
+ x = elements[i]
189
+ y = elements[j]
190
+
191
+ expected = {element for element in dis if {dis[element]} == {dis[x]}}
192
+ assert dis.subset_size(x) == len(dis.subset(x))
193
+ assert expected == dis.subset(x)
194
+
195
+ expected = {dis[element]: set() for element in dis}
196
+ for element in dis:
197
+ expected[dis[element]].add(element)
198
+ expected = list(expected.values())
199
+ assert expected == dis.subsets()
200
+
201
+ dis.merge(x, y)
202
+ assert dis.subset(x) == dis.subset(y)
astra_scene_test/Scene_04/.venv/lib/python3.9/site-packages/scipy/cluster/tests/test_hierarchy.py ADDED
@@ -0,0 +1,1225 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #
2
+ # Author: Damian Eads
3
+ # Date: April 17, 2008
4
+ #
5
+ # Copyright (C) 2008 Damian Eads
6
+ #
7
+ # Redistribution and use in source and binary forms, with or without
8
+ # modification, are permitted provided that the following conditions
9
+ # are met:
10
+ #
11
+ # 1. Redistributions of source code must retain the above copyright
12
+ # notice, this list of conditions and the following disclaimer.
13
+ #
14
+ # 2. Redistributions in binary form must reproduce the above
15
+ # copyright notice, this list of conditions and the following
16
+ # disclaimer in the documentation and/or other materials provided
17
+ # with the distribution.
18
+ #
19
+ # 3. The name of the author may not be used to endorse or promote
20
+ # products derived from this software without specific prior
21
+ # written permission.
22
+ #
23
+ # THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
24
+ # OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
25
+ # WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26
+ # ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
27
+ # DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28
+ # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
29
+ # GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
30
+ # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
31
+ # WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
32
+ # NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33
+ # SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
+ import numpy as np
35
+ from numpy.testing import assert_allclose, assert_equal, assert_, assert_warns
36
+ import pytest
37
+ from pytest import raises as assert_raises
38
+
39
+ import scipy.cluster.hierarchy
40
+ from scipy.cluster.hierarchy import (
41
+ ClusterWarning, linkage, from_mlab_linkage, to_mlab_linkage,
42
+ num_obs_linkage, inconsistent, cophenet, fclusterdata, fcluster,
43
+ is_isomorphic, single, leaders,
44
+ correspond, is_monotonic, maxdists, maxinconsts, maxRstat,
45
+ is_valid_linkage, is_valid_im, to_tree, leaves_list, dendrogram,
46
+ set_link_color_palette, cut_tree, optimal_leaf_ordering,
47
+ _order_cluster_tree, _hierarchy, _LINKAGE_METHODS)
48
+ from scipy.spatial.distance import pdist
49
+ from scipy.cluster._hierarchy import Heap
50
+ from scipy.conftest import array_api_compatible
51
+ from scipy._lib._array_api import xp_assert_close, xp_assert_equal
52
+
53
+ from . import hierarchy_test_data
54
+
55
+
56
+ # Matplotlib is not a scipy dependency but is optionally used in dendrogram, so
57
+ # check if it's available
58
+ try:
59
+ import matplotlib
60
+ # and set the backend to be Agg (no gui)
61
+ matplotlib.use('Agg')
62
+ # before importing pyplot
63
+ import matplotlib.pyplot as plt
64
+ have_matplotlib = True
65
+ except Exception:
66
+ have_matplotlib = False
67
+
68
+
69
+ pytestmark = [array_api_compatible, pytest.mark.usefixtures("skip_if_array_api")]
70
+ skip_if_array_api = pytest.mark.skip_if_array_api
71
+
72
+
73
+ class TestLinkage:
74
+
75
+ @skip_if_array_api(cpu_only=True)
76
+ def test_linkage_non_finite_elements_in_distance_matrix(self, xp):
77
+ # Tests linkage(Y) where Y contains a non-finite element (e.g. NaN or Inf).
78
+ # Exception expected.
79
+ y = xp.zeros((6,))
80
+ y[0] = xp.nan
81
+ assert_raises(ValueError, linkage, y)
82
+
83
+ @skip_if_array_api(cpu_only=True)
84
+ def test_linkage_empty_distance_matrix(self, xp):
85
+ # Tests linkage(Y) where Y is a 0x4 linkage matrix. Exception expected.
86
+ y = xp.zeros((0,))
87
+ assert_raises(ValueError, linkage, y)
88
+
89
+ @skip_if_array_api(cpu_only=True)
90
+ def test_linkage_tdist(self, xp):
91
+ for method in ['single', 'complete', 'average', 'weighted']:
92
+ self.check_linkage_tdist(method, xp)
93
+
94
+ def check_linkage_tdist(self, method, xp):
95
+ # Tests linkage(Y, method) on the tdist data set.
96
+ Z = linkage(xp.asarray(hierarchy_test_data.ytdist), method)
97
+ expectedZ = getattr(hierarchy_test_data, 'linkage_ytdist_' + method)
98
+ xp_assert_close(Z, xp.asarray(expectedZ), atol=1e-10)
99
+
100
+ @skip_if_array_api(cpu_only=True)
101
+ def test_linkage_X(self, xp):
102
+ for method in ['centroid', 'median', 'ward']:
103
+ self.check_linkage_q(method, xp)
104
+
105
+ def check_linkage_q(self, method, xp):
106
+ # Tests linkage(Y, method) on the Q data set.
107
+ Z = linkage(xp.asarray(hierarchy_test_data.X), method)
108
+ expectedZ = getattr(hierarchy_test_data, 'linkage_X_' + method)
109
+ xp_assert_close(Z, xp.asarray(expectedZ), atol=1e-06)
110
+
111
+ y = scipy.spatial.distance.pdist(hierarchy_test_data.X,
112
+ metric="euclidean")
113
+ Z = linkage(xp.asarray(y), method)
114
+ xp_assert_close(Z, xp.asarray(expectedZ), atol=1e-06)
115
+
116
+ @skip_if_array_api(cpu_only=True)
117
+ def test_compare_with_trivial(self, xp):
118
+ rng = np.random.RandomState(0)
119
+ n = 20
120
+ X = rng.rand(n, 2)
121
+ d = pdist(X)
122
+
123
+ for method, code in _LINKAGE_METHODS.items():
124
+ Z_trivial = _hierarchy.linkage(d, n, code)
125
+ Z = linkage(xp.asarray(d), method)
126
+ xp_assert_close(Z, xp.asarray(Z_trivial), rtol=1e-14, atol=1e-15)
127
+
128
+ @skip_if_array_api(cpu_only=True)
129
+ def test_optimal_leaf_ordering(self, xp):
130
+ Z = linkage(xp.asarray(hierarchy_test_data.ytdist), optimal_ordering=True)
131
+ expectedZ = getattr(hierarchy_test_data, 'linkage_ytdist_single_olo')
132
+ xp_assert_close(Z, xp.asarray(expectedZ), atol=1e-10)
133
+
134
+
135
+ @skip_if_array_api(cpu_only=True)
136
+ class TestLinkageTies:
137
+
138
+ _expectations = {
139
+ 'single': np.array([[0, 1, 1.41421356, 2],
140
+ [2, 3, 1.41421356, 3]]),
141
+ 'complete': np.array([[0, 1, 1.41421356, 2],
142
+ [2, 3, 2.82842712, 3]]),
143
+ 'average': np.array([[0, 1, 1.41421356, 2],
144
+ [2, 3, 2.12132034, 3]]),
145
+ 'weighted': np.array([[0, 1, 1.41421356, 2],
146
+ [2, 3, 2.12132034, 3]]),
147
+ 'centroid': np.array([[0, 1, 1.41421356, 2],
148
+ [2, 3, 2.12132034, 3]]),
149
+ 'median': np.array([[0, 1, 1.41421356, 2],
150
+ [2, 3, 2.12132034, 3]]),
151
+ 'ward': np.array([[0, 1, 1.41421356, 2],
152
+ [2, 3, 2.44948974, 3]]),
153
+ }
154
+
155
+ def test_linkage_ties(self, xp):
156
+ for method in ['single', 'complete', 'average', 'weighted',
157
+ 'centroid', 'median', 'ward']:
158
+ self.check_linkage_ties(method, xp)
159
+
160
+ def check_linkage_ties(self, method, xp):
161
+ X = xp.asarray([[-1, -1], [0, 0], [1, 1]])
162
+ Z = linkage(X, method=method)
163
+ expectedZ = self._expectations[method]
164
+ xp_assert_close(Z, xp.asarray(expectedZ), atol=1e-06)
165
+
166
+
167
+ @skip_if_array_api(cpu_only=True)
168
+ class TestInconsistent:
169
+
170
+ def test_inconsistent_tdist(self, xp):
171
+ for depth in hierarchy_test_data.inconsistent_ytdist:
172
+ self.check_inconsistent_tdist(depth, xp)
173
+
174
+ def check_inconsistent_tdist(self, depth, xp):
175
+ Z = xp.asarray(hierarchy_test_data.linkage_ytdist_single)
176
+ xp_assert_close(inconsistent(Z, depth),
177
+ xp.asarray(hierarchy_test_data.inconsistent_ytdist[depth]))
178
+
179
+
180
+ @skip_if_array_api(cpu_only=True)
181
+ class TestCopheneticDistance:
182
+
183
+ def test_linkage_cophenet_tdist_Z(self, xp):
184
+ # Tests cophenet(Z) on tdist data set.
185
+ expectedM = xp.asarray([268, 295, 255, 255, 295, 295, 268, 268, 295, 295,
186
+ 295, 138, 219, 295, 295])
187
+ Z = xp.asarray(hierarchy_test_data.linkage_ytdist_single)
188
+ M = cophenet(Z)
189
+ xp_assert_close(M, xp.asarray(expectedM, dtype=xp.float64), atol=1e-10)
190
+
191
+ def test_linkage_cophenet_tdist_Z_Y(self, xp):
192
+ # Tests cophenet(Z, Y) on tdist data set.
193
+ Z = xp.asarray(hierarchy_test_data.linkage_ytdist_single)
194
+ (c, M) = cophenet(Z, xp.asarray(hierarchy_test_data.ytdist))
195
+ expectedM = xp.asarray([268, 295, 255, 255, 295, 295, 268, 268, 295, 295,
196
+ 295, 138, 219, 295, 295], dtype=xp.float64)
197
+ expectedc = xp.asarray(0.639931296433393415057366837573, dtype=xp.float64)[()]
198
+ xp_assert_close(c, expectedc, atol=1e-10)
199
+ xp_assert_close(M, expectedM, atol=1e-10)
200
+
201
+
202
+ class TestMLabLinkageConversion:
203
+
204
+ def test_mlab_linkage_conversion_empty(self, xp):
205
+ # Tests from/to_mlab_linkage on empty linkage array.
206
+ X = xp.asarray([], dtype=xp.float64)
207
+ xp_assert_equal(from_mlab_linkage(X), X)
208
+ xp_assert_equal(to_mlab_linkage(X), X)
209
+
210
+ @skip_if_array_api(cpu_only=True)
211
+ def test_mlab_linkage_conversion_single_row(self, xp):
212
+ # Tests from/to_mlab_linkage on linkage array with single row.
213
+ Z = xp.asarray([[0., 1., 3., 2.]])
214
+ Zm = xp.asarray([[1, 2, 3]])
215
+ xp_assert_close(from_mlab_linkage(Zm), xp.asarray(Z, dtype=xp.float64),
216
+ rtol=1e-15)
217
+ xp_assert_close(to_mlab_linkage(Z), xp.asarray(Zm, dtype=xp.float64),
218
+ rtol=1e-15)
219
+
220
+ @skip_if_array_api(cpu_only=True)
221
+ def test_mlab_linkage_conversion_multiple_rows(self, xp):
222
+ # Tests from/to_mlab_linkage on linkage array with multiple rows.
223
+ Zm = xp.asarray([[3, 6, 138], [4, 5, 219],
224
+ [1, 8, 255], [2, 9, 268], [7, 10, 295]])
225
+ Z = xp.asarray([[2., 5., 138., 2.],
226
+ [3., 4., 219., 2.],
227
+ [0., 7., 255., 3.],
228
+ [1., 8., 268., 4.],
229
+ [6., 9., 295., 6.]],
230
+ dtype=xp.float64)
231
+ xp_assert_close(from_mlab_linkage(Zm), Z, rtol=1e-15)
232
+ xp_assert_close(to_mlab_linkage(Z), xp.asarray(Zm, dtype=xp.float64),
233
+ rtol=1e-15)
234
+
235
+
236
+ @skip_if_array_api(cpu_only=True)
237
+ class TestFcluster:
238
+
239
+ def test_fclusterdata(self, xp):
240
+ for t in hierarchy_test_data.fcluster_inconsistent:
241
+ self.check_fclusterdata(t, 'inconsistent', xp)
242
+ for t in hierarchy_test_data.fcluster_distance:
243
+ self.check_fclusterdata(t, 'distance', xp)
244
+ for t in hierarchy_test_data.fcluster_maxclust:
245
+ self.check_fclusterdata(t, 'maxclust', xp)
246
+
247
+ def check_fclusterdata(self, t, criterion, xp):
248
+ # Tests fclusterdata(X, criterion=criterion, t=t) on a random 3-cluster data set
249
+ expectedT = xp.asarray(getattr(hierarchy_test_data, 'fcluster_' + criterion)[t])
250
+ X = xp.asarray(hierarchy_test_data.Q_X)
251
+ T = fclusterdata(X, criterion=criterion, t=t)
252
+ assert_(is_isomorphic(T, expectedT))
253
+
254
+ def test_fcluster(self, xp):
255
+ for t in hierarchy_test_data.fcluster_inconsistent:
256
+ self.check_fcluster(t, 'inconsistent', xp)
257
+ for t in hierarchy_test_data.fcluster_distance:
258
+ self.check_fcluster(t, 'distance', xp)
259
+ for t in hierarchy_test_data.fcluster_maxclust:
260
+ self.check_fcluster(t, 'maxclust', xp)
261
+
262
+ def check_fcluster(self, t, criterion, xp):
263
+ # Tests fcluster(Z, criterion=criterion, t=t) on a random 3-cluster data set.
264
+ expectedT = xp.asarray(getattr(hierarchy_test_data, 'fcluster_' + criterion)[t])
265
+ Z = single(xp.asarray(hierarchy_test_data.Q_X))
266
+ T = fcluster(Z, criterion=criterion, t=t)
267
+ assert_(is_isomorphic(T, expectedT))
268
+
269
+ def test_fcluster_monocrit(self, xp):
270
+ for t in hierarchy_test_data.fcluster_distance:
271
+ self.check_fcluster_monocrit(t, xp)
272
+ for t in hierarchy_test_data.fcluster_maxclust:
273
+ self.check_fcluster_maxclust_monocrit(t, xp)
274
+
275
+ def check_fcluster_monocrit(self, t, xp):
276
+ expectedT = xp.asarray(hierarchy_test_data.fcluster_distance[t])
277
+ Z = single(xp.asarray(hierarchy_test_data.Q_X))
278
+ T = fcluster(Z, t, criterion='monocrit', monocrit=maxdists(Z))
279
+ assert_(is_isomorphic(T, expectedT))
280
+
281
+ def check_fcluster_maxclust_monocrit(self, t, xp):
282
+ expectedT = xp.asarray(hierarchy_test_data.fcluster_maxclust[t])
283
+ Z = single(xp.asarray(hierarchy_test_data.Q_X))
284
+ T = fcluster(Z, t, criterion='maxclust_monocrit', monocrit=maxdists(Z))
285
+ assert_(is_isomorphic(T, expectedT))
286
+
287
+
288
+ @skip_if_array_api(cpu_only=True)
289
+ class TestLeaders:
290
+
291
+ def test_leaders_single(self, xp):
292
+ # Tests leaders using a flat clustering generated by single linkage.
293
+ X = hierarchy_test_data.Q_X
294
+ Y = pdist(X)
295
+ Y = xp.asarray(Y)
296
+ Z = linkage(Y)
297
+ T = fcluster(Z, criterion='maxclust', t=3)
298
+ Lright = (xp.asarray([53, 55, 56]), xp.asarray([2, 3, 1]))
299
+ T = xp.asarray(T, dtype=xp.int32)
300
+ L = leaders(Z, T)
301
+ assert_allclose(np.concatenate(L), np.concatenate(Lright), rtol=1e-15)
302
+
303
+
304
+ @skip_if_array_api(np_only=True,
305
+ reasons=['`is_isomorphic` only supports NumPy backend'])
306
+ class TestIsIsomorphic:
307
+
308
+ @skip_if_array_api(np_only=True,
309
+ reasons=['array-likes only supported for NumPy backend'])
310
+ def test_array_like(self, xp):
311
+ assert is_isomorphic([1, 1, 1], [2, 2, 2])
312
+ assert is_isomorphic([], [])
313
+
314
+ def test_is_isomorphic_1(self, xp):
315
+ # Tests is_isomorphic on test case #1 (one flat cluster, different labellings)
316
+ a = xp.asarray([1, 1, 1])
317
+ b = xp.asarray([2, 2, 2])
318
+ assert is_isomorphic(a, b)
319
+ assert is_isomorphic(b, a)
320
+
321
+ def test_is_isomorphic_2(self, xp):
322
+ # Tests is_isomorphic on test case #2 (two flat clusters, different labelings)
323
+ a = xp.asarray([1, 7, 1])
324
+ b = xp.asarray([2, 3, 2])
325
+ assert is_isomorphic(a, b)
326
+ assert is_isomorphic(b, a)
327
+
328
+ def test_is_isomorphic_3(self, xp):
329
+ # Tests is_isomorphic on test case #3 (no flat clusters)
330
+ a = xp.asarray([])
331
+ b = xp.asarray([])
332
+ assert is_isomorphic(a, b)
333
+
334
+ def test_is_isomorphic_4A(self, xp):
335
+ # Tests is_isomorphic on test case #4A
336
+ # (3 flat clusters, different labelings, isomorphic)
337
+ a = xp.asarray([1, 2, 3])
338
+ b = xp.asarray([1, 3, 2])
339
+ assert is_isomorphic(a, b)
340
+ assert is_isomorphic(b, a)
341
+
342
+ def test_is_isomorphic_4B(self, xp):
343
+ # Tests is_isomorphic on test case #4B
344
+ # (3 flat clusters, different labelings, nonisomorphic)
345
+ a = xp.asarray([1, 2, 3, 3])
346
+ b = xp.asarray([1, 3, 2, 3])
347
+ assert is_isomorphic(a, b) is False
348
+ assert is_isomorphic(b, a) is False
349
+
350
+ def test_is_isomorphic_4C(self, xp):
351
+ # Tests is_isomorphic on test case #4C
352
+ # (3 flat clusters, different labelings, isomorphic)
353
+ a = xp.asarray([7, 2, 3])
354
+ b = xp.asarray([6, 3, 2])
355
+ assert is_isomorphic(a, b)
356
+ assert is_isomorphic(b, a)
357
+
358
+ def test_is_isomorphic_5(self, xp):
359
+ # Tests is_isomorphic on test case #5 (1000 observations, 2/3/5 random
360
+ # clusters, random permutation of the labeling).
361
+ for nc in [2, 3, 5]:
362
+ self.help_is_isomorphic_randperm(1000, nc, xp=xp)
363
+
364
+ def test_is_isomorphic_6(self, xp):
365
+ # Tests is_isomorphic on test case #5A (1000 observations, 2/3/5 random
366
+ # clusters, random permutation of the labeling, slightly
367
+ # nonisomorphic.)
368
+ for nc in [2, 3, 5]:
369
+ self.help_is_isomorphic_randperm(1000, nc, True, 5, xp=xp)
370
+
371
+ def test_is_isomorphic_7(self, xp):
372
+ # Regression test for gh-6271
373
+ a = xp.asarray([1, 2, 3])
374
+ b = xp.asarray([1, 1, 1])
375
+ assert not is_isomorphic(a, b)
376
+
377
+ def help_is_isomorphic_randperm(self, nobs, nclusters, noniso=False, nerrors=0,
378
+ *, xp):
379
+ for k in range(3):
380
+ a = (np.random.rand(nobs) * nclusters).astype(int)
381
+ b = np.zeros(a.size, dtype=int)
382
+ P = np.random.permutation(nclusters)
383
+ for i in range(0, a.shape[0]):
384
+ b[i] = P[a[i]]
385
+ if noniso:
386
+ Q = np.random.permutation(nobs)
387
+ b[Q[0:nerrors]] += 1
388
+ b[Q[0:nerrors]] %= nclusters
389
+ a = xp.asarray(a)
390
+ b = xp.asarray(b)
391
+ assert is_isomorphic(a, b) == (not noniso)
392
+ assert is_isomorphic(b, a) == (not noniso)
393
+
394
+
395
+ @skip_if_array_api(cpu_only=True)
396
+ class TestIsValidLinkage:
397
+
398
+ def test_is_valid_linkage_various_size(self, xp):
399
+ for nrow, ncol, valid in [(2, 5, False), (2, 3, False),
400
+ (1, 4, True), (2, 4, True)]:
401
+ self.check_is_valid_linkage_various_size(nrow, ncol, valid, xp)
402
+
403
+ def check_is_valid_linkage_various_size(self, nrow, ncol, valid, xp):
404
+ # Tests is_valid_linkage(Z) with linkage matrices of various sizes
405
+ Z = xp.asarray([[0, 1, 3.0, 2, 5],
406
+ [3, 2, 4.0, 3, 3]], dtype=xp.float64)
407
+ Z = Z[:nrow, :ncol]
408
+ assert_(is_valid_linkage(Z) == valid)
409
+ if not valid:
410
+ assert_raises(ValueError, is_valid_linkage, Z, throw=True)
411
+
412
+ def test_is_valid_linkage_int_type(self, xp):
413
+ # Tests is_valid_linkage(Z) with integer type.
414
+ Z = xp.asarray([[0, 1, 3.0, 2],
415
+ [3, 2, 4.0, 3]], dtype=xp.int64)
416
+ assert_(is_valid_linkage(Z) is False)
417
+ assert_raises(TypeError, is_valid_linkage, Z, throw=True)
418
+
419
+ def test_is_valid_linkage_empty(self, xp):
420
+ # Tests is_valid_linkage(Z) with empty linkage.
421
+ Z = xp.zeros((0, 4), dtype=xp.float64)
422
+ assert_(is_valid_linkage(Z) is False)
423
+ assert_raises(ValueError, is_valid_linkage, Z, throw=True)
424
+
425
+ def test_is_valid_linkage_4_and_up(self, xp):
426
+ # Tests is_valid_linkage(Z) on linkage on observation sets between
427
+ # sizes 4 and 15 (step size 3).
428
+ for i in range(4, 15, 3):
429
+ y = np.random.rand(i*(i-1)//2)
430
+ y = xp.asarray(y)
431
+ Z = linkage(y)
432
+ assert_(is_valid_linkage(Z) is True)
433
+
434
+ def test_is_valid_linkage_4_and_up_neg_index_left(self, xp):
435
+ # Tests is_valid_linkage(Z) on linkage on observation sets between
436
+ # sizes 4 and 15 (step size 3) with negative indices (left).
437
+ for i in range(4, 15, 3):
438
+ y = np.random.rand(i*(i-1)//2)
439
+ y = xp.asarray(y)
440
+ Z = linkage(y)
441
+ Z[i//2,0] = -2
442
+ assert_(is_valid_linkage(Z) is False)
443
+ assert_raises(ValueError, is_valid_linkage, Z, throw=True)
444
+
445
+ def test_is_valid_linkage_4_and_up_neg_index_right(self, xp):
446
+ # Tests is_valid_linkage(Z) on linkage on observation sets between
447
+ # sizes 4 and 15 (step size 3) with negative indices (right).
448
+ for i in range(4, 15, 3):
449
+ y = np.random.rand(i*(i-1)//2)
450
+ y = xp.asarray(y)
451
+ Z = linkage(y)
452
+ Z[i//2,1] = -2
453
+ assert_(is_valid_linkage(Z) is False)
454
+ assert_raises(ValueError, is_valid_linkage, Z, throw=True)
455
+
456
+ def test_is_valid_linkage_4_and_up_neg_dist(self, xp):
457
+ # Tests is_valid_linkage(Z) on linkage on observation sets between
458
+ # sizes 4 and 15 (step size 3) with negative distances.
459
+ for i in range(4, 15, 3):
460
+ y = np.random.rand(i*(i-1)//2)
461
+ y = xp.asarray(y)
462
+ Z = linkage(y)
463
+ Z[i//2,2] = -0.5
464
+ assert_(is_valid_linkage(Z) is False)
465
+ assert_raises(ValueError, is_valid_linkage, Z, throw=True)
466
+
467
+ def test_is_valid_linkage_4_and_up_neg_counts(self, xp):
468
+ # Tests is_valid_linkage(Z) on linkage on observation sets between
469
+ # sizes 4 and 15 (step size 3) with negative counts.
470
+ for i in range(4, 15, 3):
471
+ y = np.random.rand(i*(i-1)//2)
472
+ y = xp.asarray(y)
473
+ Z = linkage(y)
474
+ Z[i//2,3] = -2
475
+ assert_(is_valid_linkage(Z) is False)
476
+ assert_raises(ValueError, is_valid_linkage, Z, throw=True)
477
+
478
+
479
+ @skip_if_array_api(cpu_only=True)
480
+ class TestIsValidInconsistent:
481
+
482
+ def test_is_valid_im_int_type(self, xp):
483
+ # Tests is_valid_im(R) with integer type.
484
+ R = xp.asarray([[0, 1, 3.0, 2],
485
+ [3, 2, 4.0, 3]], dtype=xp.int64)
486
+ assert_(is_valid_im(R) is False)
487
+ assert_raises(TypeError, is_valid_im, R, throw=True)
488
+
489
+ def test_is_valid_im_various_size(self, xp):
490
+ for nrow, ncol, valid in [(2, 5, False), (2, 3, False),
491
+ (1, 4, True), (2, 4, True)]:
492
+ self.check_is_valid_im_various_size(nrow, ncol, valid, xp)
493
+
494
+ def check_is_valid_im_various_size(self, nrow, ncol, valid, xp):
495
+ # Tests is_valid_im(R) with linkage matrices of various sizes
496
+ R = xp.asarray([[0, 1, 3.0, 2, 5],
497
+ [3, 2, 4.0, 3, 3]], dtype=xp.float64)
498
+ R = R[:nrow, :ncol]
499
+ assert_(is_valid_im(R) == valid)
500
+ if not valid:
501
+ assert_raises(ValueError, is_valid_im, R, throw=True)
502
+
503
+ def test_is_valid_im_empty(self, xp):
504
+ # Tests is_valid_im(R) with empty inconsistency matrix.
505
+ R = xp.zeros((0, 4), dtype=xp.float64)
506
+ assert_(is_valid_im(R) is False)
507
+ assert_raises(ValueError, is_valid_im, R, throw=True)
508
+
509
+ def test_is_valid_im_4_and_up(self, xp):
510
+ # Tests is_valid_im(R) on im on observation sets between sizes 4 and 15
511
+ # (step size 3).
512
+ for i in range(4, 15, 3):
513
+ y = np.random.rand(i*(i-1)//2)
514
+ y = xp.asarray(y)
515
+ Z = linkage(y)
516
+ R = inconsistent(Z)
517
+ assert_(is_valid_im(R) is True)
518
+
519
+ def test_is_valid_im_4_and_up_neg_index_left(self, xp):
520
+ # Tests is_valid_im(R) on im on observation sets between sizes 4 and 15
521
+ # (step size 3) with negative link height means.
522
+ for i in range(4, 15, 3):
523
+ y = np.random.rand(i*(i-1)//2)
524
+ y = xp.asarray(y)
525
+ Z = linkage(y)
526
+ R = inconsistent(Z)
527
+ R[i//2,0] = -2.0
528
+ assert_(is_valid_im(R) is False)
529
+ assert_raises(ValueError, is_valid_im, R, throw=True)
530
+
531
+ def test_is_valid_im_4_and_up_neg_index_right(self, xp):
532
+ # Tests is_valid_im(R) on im on observation sets between sizes 4 and 15
533
+ # (step size 3) with negative link height standard deviations.
534
+ for i in range(4, 15, 3):
535
+ y = np.random.rand(i*(i-1)//2)
536
+ y = xp.asarray(y)
537
+ Z = linkage(y)
538
+ R = inconsistent(Z)
539
+ R[i//2,1] = -2.0
540
+ assert_(is_valid_im(R) is False)
541
+ assert_raises(ValueError, is_valid_im, R, throw=True)
542
+
543
+ def test_is_valid_im_4_and_up_neg_dist(self, xp):
544
+ # Tests is_valid_im(R) on im on observation sets between sizes 4 and 15
545
+ # (step size 3) with negative link counts.
546
+ for i in range(4, 15, 3):
547
+ y = np.random.rand(i*(i-1)//2)
548
+ y = xp.asarray(y)
549
+ Z = linkage(y)
550
+ R = inconsistent(Z)
551
+ R[i//2,2] = -0.5
552
+ assert_(is_valid_im(R) is False)
553
+ assert_raises(ValueError, is_valid_im, R, throw=True)
554
+
555
+
556
+ class TestNumObsLinkage:
557
+
558
+ @skip_if_array_api(cpu_only=True)
559
+ def test_num_obs_linkage_empty(self, xp):
560
+ # Tests num_obs_linkage(Z) with empty linkage.
561
+ Z = xp.zeros((0, 4), dtype=xp.float64)
562
+ assert_raises(ValueError, num_obs_linkage, Z)
563
+
564
+ def test_num_obs_linkage_1x4(self, xp):
565
+ # Tests num_obs_linkage(Z) on linkage over 2 observations.
566
+ Z = xp.asarray([[0, 1, 3.0, 2]], dtype=xp.float64)
567
+ assert_equal(num_obs_linkage(Z), 2)
568
+
569
+ def test_num_obs_linkage_2x4(self, xp):
570
+ # Tests num_obs_linkage(Z) on linkage over 3 observations.
571
+ Z = xp.asarray([[0, 1, 3.0, 2],
572
+ [3, 2, 4.0, 3]], dtype=xp.float64)
573
+ assert_equal(num_obs_linkage(Z), 3)
574
+
575
+ @skip_if_array_api(cpu_only=True)
576
+ def test_num_obs_linkage_4_and_up(self, xp):
577
+ # Tests num_obs_linkage(Z) on linkage on observation sets between sizes
578
+ # 4 and 15 (step size 3).
579
+ for i in range(4, 15, 3):
580
+ y = np.random.rand(i*(i-1)//2)
581
+ y = xp.asarray(y)
582
+ Z = linkage(y)
583
+ assert_equal(num_obs_linkage(Z), i)
584
+
585
+
586
+ @skip_if_array_api(cpu_only=True)
587
+ class TestLeavesList:
588
+
589
+ def test_leaves_list_1x4(self, xp):
590
+ # Tests leaves_list(Z) on a 1x4 linkage.
591
+ Z = xp.asarray([[0, 1, 3.0, 2]], dtype=xp.float64)
592
+ to_tree(Z)
593
+ assert_allclose(leaves_list(Z), [0, 1], rtol=1e-15)
594
+
595
+ def test_leaves_list_2x4(self, xp):
596
+ # Tests leaves_list(Z) on a 2x4 linkage.
597
+ Z = xp.asarray([[0, 1, 3.0, 2],
598
+ [3, 2, 4.0, 3]], dtype=xp.float64)
599
+ to_tree(Z)
600
+ assert_allclose(leaves_list(Z), [0, 1, 2], rtol=1e-15)
601
+
602
+ def test_leaves_list_Q(self, xp):
603
+ for method in ['single', 'complete', 'average', 'weighted', 'centroid',
604
+ 'median', 'ward']:
605
+ self.check_leaves_list_Q(method, xp)
606
+
607
+ def check_leaves_list_Q(self, method, xp):
608
+ # Tests leaves_list(Z) on the Q data set
609
+ X = xp.asarray(hierarchy_test_data.Q_X)
610
+ Z = linkage(X, method)
611
+ node = to_tree(Z)
612
+ assert_allclose(node.pre_order(), leaves_list(Z), rtol=1e-15)
613
+
614
+ def test_Q_subtree_pre_order(self, xp):
615
+ # Tests that pre_order() works when called on sub-trees.
616
+ X = xp.asarray(hierarchy_test_data.Q_X)
617
+ Z = linkage(X, 'single')
618
+ node = to_tree(Z)
619
+ assert_allclose(node.pre_order(), (node.get_left().pre_order()
620
+ + node.get_right().pre_order()),
621
+ rtol=1e-15)
622
+
623
+
624
+ @skip_if_array_api(cpu_only=True)
625
+ class TestCorrespond:
626
+
627
+ def test_correspond_empty(self, xp):
628
+ # Tests correspond(Z, y) with empty linkage and condensed distance matrix.
629
+ y = xp.zeros((0,), dtype=xp.float64)
630
+ Z = xp.zeros((0,4), dtype=xp.float64)
631
+ assert_raises(ValueError, correspond, Z, y)
632
+
633
+ def test_correspond_2_and_up(self, xp):
634
+ # Tests correspond(Z, y) on linkage and CDMs over observation sets of
635
+ # different sizes.
636
+ for i in range(2, 4):
637
+ y = np.random.rand(i*(i-1)//2)
638
+ y = xp.asarray(y)
639
+ Z = linkage(y)
640
+ assert_(correspond(Z, y))
641
+ for i in range(4, 15, 3):
642
+ y = np.random.rand(i*(i-1)//2)
643
+ y = xp.asarray(y)
644
+ Z = linkage(y)
645
+ assert_(correspond(Z, y))
646
+
647
+ def test_correspond_4_and_up(self, xp):
648
+ # Tests correspond(Z, y) on linkage and CDMs over observation sets of
649
+ # different sizes. Correspondence should be false.
650
+ for (i, j) in (list(zip(list(range(2, 4)), list(range(3, 5)))) +
651
+ list(zip(list(range(3, 5)), list(range(2, 4))))):
652
+ y = np.random.rand(i*(i-1)//2)
653
+ y2 = np.random.rand(j*(j-1)//2)
654
+ y = xp.asarray(y)
655
+ y2 = xp.asarray(y2)
656
+ Z = linkage(y)
657
+ Z2 = linkage(y2)
658
+ assert not correspond(Z, y2)
659
+ assert not correspond(Z2, y)
660
+
661
+ def test_correspond_4_and_up_2(self, xp):
662
+ # Tests correspond(Z, y) on linkage and CDMs over observation sets of
663
+ # different sizes. Correspondence should be false.
664
+ for (i, j) in (list(zip(list(range(2, 7)), list(range(16, 21)))) +
665
+ list(zip(list(range(2, 7)), list(range(16, 21))))):
666
+ y = np.random.rand(i*(i-1)//2)
667
+ y2 = np.random.rand(j*(j-1)//2)
668
+ y = xp.asarray(y)
669
+ y2 = xp.asarray(y2)
670
+ Z = linkage(y)
671
+ Z2 = linkage(y2)
672
+ assert not correspond(Z, y2)
673
+ assert not correspond(Z2, y)
674
+
675
+ def test_num_obs_linkage_multi_matrix(self, xp):
676
+ # Tests num_obs_linkage with observation matrices of multiple sizes.
677
+ for n in range(2, 10):
678
+ X = np.random.rand(n, 4)
679
+ Y = pdist(X)
680
+ Y = xp.asarray(Y)
681
+ Z = linkage(Y)
682
+ assert_equal(num_obs_linkage(Z), n)
683
+
684
+
685
+ @skip_if_array_api(cpu_only=True)
686
+ class TestIsMonotonic:
687
+
688
+ def test_is_monotonic_empty(self, xp):
689
+ # Tests is_monotonic(Z) on an empty linkage.
690
+ Z = xp.zeros((0, 4), dtype=xp.float64)
691
+ assert_raises(ValueError, is_monotonic, Z)
692
+
693
+ def test_is_monotonic_1x4(self, xp):
694
+ # Tests is_monotonic(Z) on 1x4 linkage. Expecting True.
695
+ Z = xp.asarray([[0, 1, 0.3, 2]], dtype=xp.float64)
696
+ assert is_monotonic(Z)
697
+
698
+ def test_is_monotonic_2x4_T(self, xp):
699
+ # Tests is_monotonic(Z) on 2x4 linkage. Expecting True.
700
+ Z = xp.asarray([[0, 1, 0.3, 2],
701
+ [2, 3, 0.4, 3]], dtype=xp.float64)
702
+ assert is_monotonic(Z)
703
+
704
+ def test_is_monotonic_2x4_F(self, xp):
705
+ # Tests is_monotonic(Z) on 2x4 linkage. Expecting False.
706
+ Z = xp.asarray([[0, 1, 0.4, 2],
707
+ [2, 3, 0.3, 3]], dtype=xp.float64)
708
+ assert not is_monotonic(Z)
709
+
710
+ def test_is_monotonic_3x4_T(self, xp):
711
+ # Tests is_monotonic(Z) on 3x4 linkage. Expecting True.
712
+ Z = xp.asarray([[0, 1, 0.3, 2],
713
+ [2, 3, 0.4, 2],
714
+ [4, 5, 0.6, 4]], dtype=xp.float64)
715
+ assert is_monotonic(Z)
716
+
717
+ def test_is_monotonic_3x4_F1(self, xp):
718
+ # Tests is_monotonic(Z) on 3x4 linkage (case 1). Expecting False.
719
+ Z = xp.asarray([[0, 1, 0.3, 2],
720
+ [2, 3, 0.2, 2],
721
+ [4, 5, 0.6, 4]], dtype=xp.float64)
722
+ assert not is_monotonic(Z)
723
+
724
+ def test_is_monotonic_3x4_F2(self, xp):
725
+ # Tests is_monotonic(Z) on 3x4 linkage (case 2). Expecting False.
726
+ Z = xp.asarray([[0, 1, 0.8, 2],
727
+ [2, 3, 0.4, 2],
728
+ [4, 5, 0.6, 4]], dtype=xp.float64)
729
+ assert not is_monotonic(Z)
730
+
731
+ def test_is_monotonic_3x4_F3(self, xp):
732
+ # Tests is_monotonic(Z) on 3x4 linkage (case 3). Expecting False
733
+ Z = xp.asarray([[0, 1, 0.3, 2],
734
+ [2, 3, 0.4, 2],
735
+ [4, 5, 0.2, 4]], dtype=xp.float64)
736
+ assert not is_monotonic(Z)
737
+
738
+ def test_is_monotonic_tdist_linkage1(self, xp):
739
+ # Tests is_monotonic(Z) on clustering generated by single linkage on
740
+ # tdist data set. Expecting True.
741
+ Z = linkage(xp.asarray(hierarchy_test_data.ytdist), 'single')
742
+ assert is_monotonic(Z)
743
+
744
+ def test_is_monotonic_tdist_linkage2(self, xp):
745
+ # Tests is_monotonic(Z) on clustering generated by single linkage on
746
+ # tdist data set. Perturbing. Expecting False.
747
+ Z = linkage(xp.asarray(hierarchy_test_data.ytdist), 'single')
748
+ Z[2,2] = 0.0
749
+ assert not is_monotonic(Z)
750
+
751
+ def test_is_monotonic_Q_linkage(self, xp):
752
+ # Tests is_monotonic(Z) on clustering generated by single linkage on
753
+ # Q data set. Expecting True.
754
+ X = xp.asarray(hierarchy_test_data.Q_X)
755
+ Z = linkage(X, 'single')
756
+ assert is_monotonic(Z)
757
+
758
+
759
+ @skip_if_array_api(cpu_only=True)
760
+ class TestMaxDists:
761
+
762
+ def test_maxdists_empty_linkage(self, xp):
763
+ # Tests maxdists(Z) on empty linkage. Expecting exception.
764
+ Z = xp.zeros((0, 4), dtype=xp.float64)
765
+ assert_raises(ValueError, maxdists, Z)
766
+
767
+ def test_maxdists_one_cluster_linkage(self, xp):
768
+ # Tests maxdists(Z) on linkage with one cluster.
769
+ Z = xp.asarray([[0, 1, 0.3, 4]], dtype=xp.float64)
770
+ MD = maxdists(Z)
771
+ expectedMD = calculate_maximum_distances(Z, xp)
772
+ xp_assert_close(MD, expectedMD, atol=1e-15)
773
+
774
+ def test_maxdists_Q_linkage(self, xp):
775
+ for method in ['single', 'complete', 'ward', 'centroid', 'median']:
776
+ self.check_maxdists_Q_linkage(method, xp)
777
+
778
+ def check_maxdists_Q_linkage(self, method, xp):
779
+ # Tests maxdists(Z) on the Q data set
780
+ X = xp.asarray(hierarchy_test_data.Q_X)
781
+ Z = linkage(X, method)
782
+ MD = maxdists(Z)
783
+ expectedMD = calculate_maximum_distances(Z, xp)
784
+ xp_assert_close(MD, expectedMD, atol=1e-15)
785
+
786
+
787
+ class TestMaxInconsts:
788
+
789
+ @skip_if_array_api(cpu_only=True)
790
+ def test_maxinconsts_empty_linkage(self, xp):
791
+ # Tests maxinconsts(Z, R) on empty linkage. Expecting exception.
792
+ Z = xp.zeros((0, 4), dtype=xp.float64)
793
+ R = xp.zeros((0, 4), dtype=xp.float64)
794
+ assert_raises(ValueError, maxinconsts, Z, R)
795
+
796
+ def test_maxinconsts_difrow_linkage(self, xp):
797
+ # Tests maxinconsts(Z, R) on linkage and inconsistency matrices with
798
+ # different numbers of clusters. Expecting exception.
799
+ Z = xp.asarray([[0, 1, 0.3, 4]], dtype=xp.float64)
800
+ R = np.random.rand(2, 4)
801
+ R = xp.asarray(R)
802
+ assert_raises(ValueError, maxinconsts, Z, R)
803
+
804
+ @skip_if_array_api(cpu_only=True)
805
+ def test_maxinconsts_one_cluster_linkage(self, xp):
806
+ # Tests maxinconsts(Z, R) on linkage with one cluster.
807
+ Z = xp.asarray([[0, 1, 0.3, 4]], dtype=xp.float64)
808
+ R = xp.asarray([[0, 0, 0, 0.3]], dtype=xp.float64)
809
+ MD = maxinconsts(Z, R)
810
+ expectedMD = calculate_maximum_inconsistencies(Z, R, xp=xp)
811
+ xp_assert_close(MD, expectedMD, atol=1e-15)
812
+
813
+ @skip_if_array_api(cpu_only=True)
814
+ def test_maxinconsts_Q_linkage(self, xp):
815
+ for method in ['single', 'complete', 'ward', 'centroid', 'median']:
816
+ self.check_maxinconsts_Q_linkage(method, xp)
817
+
818
+ def check_maxinconsts_Q_linkage(self, method, xp):
819
+ # Tests maxinconsts(Z, R) on the Q data set
820
+ X = xp.asarray(hierarchy_test_data.Q_X)
821
+ Z = linkage(X, method)
822
+ R = inconsistent(Z)
823
+ MD = maxinconsts(Z, R)
824
+ expectedMD = calculate_maximum_inconsistencies(Z, R, xp=xp)
825
+ xp_assert_close(MD, expectedMD, atol=1e-15)
826
+
827
+
828
+ class TestMaxRStat:
829
+
830
+ def test_maxRstat_invalid_index(self, xp):
831
+ for i in [3.3, -1, 4]:
832
+ self.check_maxRstat_invalid_index(i, xp)
833
+
834
+ def check_maxRstat_invalid_index(self, i, xp):
835
+ # Tests maxRstat(Z, R, i). Expecting exception.
836
+ Z = xp.asarray([[0, 1, 0.3, 4]], dtype=xp.float64)
837
+ R = xp.asarray([[0, 0, 0, 0.3]], dtype=xp.float64)
838
+ if isinstance(i, int):
839
+ assert_raises(ValueError, maxRstat, Z, R, i)
840
+ else:
841
+ assert_raises(TypeError, maxRstat, Z, R, i)
842
+
843
+ @skip_if_array_api(cpu_only=True)
844
+ def test_maxRstat_empty_linkage(self, xp):
845
+ for i in range(4):
846
+ self.check_maxRstat_empty_linkage(i, xp)
847
+
848
+ def check_maxRstat_empty_linkage(self, i, xp):
849
+ # Tests maxRstat(Z, R, i) on empty linkage. Expecting exception.
850
+ Z = xp.zeros((0, 4), dtype=xp.float64)
851
+ R = xp.zeros((0, 4), dtype=xp.float64)
852
+ assert_raises(ValueError, maxRstat, Z, R, i)
853
+
854
+ def test_maxRstat_difrow_linkage(self, xp):
855
+ for i in range(4):
856
+ self.check_maxRstat_difrow_linkage(i, xp)
857
+
858
+ def check_maxRstat_difrow_linkage(self, i, xp):
859
+ # Tests maxRstat(Z, R, i) on linkage and inconsistency matrices with
860
+ # different numbers of clusters. Expecting exception.
861
+ Z = xp.asarray([[0, 1, 0.3, 4]], dtype=xp.float64)
862
+ R = np.random.rand(2, 4)
863
+ R = xp.asarray(R)
864
+ assert_raises(ValueError, maxRstat, Z, R, i)
865
+
866
+ @skip_if_array_api(cpu_only=True)
867
+ def test_maxRstat_one_cluster_linkage(self, xp):
868
+ for i in range(4):
869
+ self.check_maxRstat_one_cluster_linkage(i, xp)
870
+
871
+ def check_maxRstat_one_cluster_linkage(self, i, xp):
872
+ # Tests maxRstat(Z, R, i) on linkage with one cluster.
873
+ Z = xp.asarray([[0, 1, 0.3, 4]], dtype=xp.float64)
874
+ R = xp.asarray([[0, 0, 0, 0.3]], dtype=xp.float64)
875
+ MD = maxRstat(Z, R, 1)
876
+ expectedMD = calculate_maximum_inconsistencies(Z, R, 1, xp)
877
+ xp_assert_close(MD, expectedMD, atol=1e-15)
878
+
879
+ @skip_if_array_api(cpu_only=True)
880
+ def test_maxRstat_Q_linkage(self, xp):
881
+ for method in ['single', 'complete', 'ward', 'centroid', 'median']:
882
+ for i in range(4):
883
+ self.check_maxRstat_Q_linkage(method, i, xp)
884
+
885
+ def check_maxRstat_Q_linkage(self, method, i, xp):
886
+ # Tests maxRstat(Z, R, i) on the Q data set
887
+ X = xp.asarray(hierarchy_test_data.Q_X)
888
+ Z = linkage(X, method)
889
+ R = inconsistent(Z)
890
+ MD = maxRstat(Z, R, 1)
891
+ expectedMD = calculate_maximum_inconsistencies(Z, R, 1, xp)
892
+ xp_assert_close(MD, expectedMD, atol=1e-15)
893
+
894
+
895
+ @skip_if_array_api(cpu_only=True)
896
+ class TestDendrogram:
897
+
898
+ def test_dendrogram_single_linkage_tdist(self, xp):
899
+ # Tests dendrogram calculation on single linkage of the tdist data set.
900
+ Z = linkage(xp.asarray(hierarchy_test_data.ytdist), 'single')
901
+ R = dendrogram(Z, no_plot=True)
902
+ leaves = R["leaves"]
903
+ assert_equal(leaves, [2, 5, 1, 0, 3, 4])
904
+
905
+ def test_valid_orientation(self, xp):
906
+ Z = linkage(xp.asarray(hierarchy_test_data.ytdist), 'single')
907
+ assert_raises(ValueError, dendrogram, Z, orientation="foo")
908
+
909
+ def test_labels_as_array_or_list(self, xp):
910
+ # test for gh-12418
911
+ Z = linkage(xp.asarray(hierarchy_test_data.ytdist), 'single')
912
+ labels = xp.asarray([1, 3, 2, 6, 4, 5])
913
+ result1 = dendrogram(Z, labels=labels, no_plot=True)
914
+ result2 = dendrogram(Z, labels=list(labels), no_plot=True)
915
+ assert result1 == result2
916
+
917
+ @pytest.mark.skipif(not have_matplotlib, reason="no matplotlib")
918
+ def test_valid_label_size(self, xp):
919
+ link = xp.asarray([
920
+ [0, 1, 1.0, 4],
921
+ [2, 3, 1.0, 5],
922
+ [4, 5, 2.0, 6],
923
+ ])
924
+ plt.figure()
925
+ with pytest.raises(ValueError) as exc_info:
926
+ dendrogram(link, labels=list(range(100)))
927
+ assert "Dimensions of Z and labels must be consistent."\
928
+ in str(exc_info.value)
929
+
930
+ with pytest.raises(
931
+ ValueError,
932
+ match="Dimensions of Z and labels must be consistent."):
933
+ dendrogram(link, labels=[])
934
+
935
+ plt.close()
936
+
937
+ @pytest.mark.skipif(not have_matplotlib, reason="no matplotlib")
938
+ def test_dendrogram_plot(self, xp):
939
+ for orientation in ['top', 'bottom', 'left', 'right']:
940
+ self.check_dendrogram_plot(orientation, xp)
941
+
942
+ def check_dendrogram_plot(self, orientation, xp):
943
+ # Tests dendrogram plotting.
944
+ Z = linkage(xp.asarray(hierarchy_test_data.ytdist), 'single')
945
+ expected = {'color_list': ['C1', 'C0', 'C0', 'C0', 'C0'],
946
+ 'dcoord': [[0.0, 138.0, 138.0, 0.0],
947
+ [0.0, 219.0, 219.0, 0.0],
948
+ [0.0, 255.0, 255.0, 219.0],
949
+ [0.0, 268.0, 268.0, 255.0],
950
+ [138.0, 295.0, 295.0, 268.0]],
951
+ 'icoord': [[5.0, 5.0, 15.0, 15.0],
952
+ [45.0, 45.0, 55.0, 55.0],
953
+ [35.0, 35.0, 50.0, 50.0],
954
+ [25.0, 25.0, 42.5, 42.5],
955
+ [10.0, 10.0, 33.75, 33.75]],
956
+ 'ivl': ['2', '5', '1', '0', '3', '4'],
957
+ 'leaves': [2, 5, 1, 0, 3, 4],
958
+ 'leaves_color_list': ['C1', 'C1', 'C0', 'C0', 'C0', 'C0'],
959
+ }
960
+
961
+ fig = plt.figure()
962
+ ax = fig.add_subplot(221)
963
+
964
+ # test that dendrogram accepts ax keyword
965
+ R1 = dendrogram(Z, ax=ax, orientation=orientation)
966
+ R1['dcoord'] = np.asarray(R1['dcoord'])
967
+ assert_equal(R1, expected)
968
+
969
+ # test that dendrogram accepts and handle the leaf_font_size and
970
+ # leaf_rotation keywords
971
+ dendrogram(Z, ax=ax, orientation=orientation,
972
+ leaf_font_size=20, leaf_rotation=90)
973
+ testlabel = (
974
+ ax.get_xticklabels()[0]
975
+ if orientation in ['top', 'bottom']
976
+ else ax.get_yticklabels()[0]
977
+ )
978
+ assert_equal(testlabel.get_rotation(), 90)
979
+ assert_equal(testlabel.get_size(), 20)
980
+ dendrogram(Z, ax=ax, orientation=orientation,
981
+ leaf_rotation=90)
982
+ testlabel = (
983
+ ax.get_xticklabels()[0]
984
+ if orientation in ['top', 'bottom']
985
+ else ax.get_yticklabels()[0]
986
+ )
987
+ assert_equal(testlabel.get_rotation(), 90)
988
+ dendrogram(Z, ax=ax, orientation=orientation,
989
+ leaf_font_size=20)
990
+ testlabel = (
991
+ ax.get_xticklabels()[0]
992
+ if orientation in ['top', 'bottom']
993
+ else ax.get_yticklabels()[0]
994
+ )
995
+ assert_equal(testlabel.get_size(), 20)
996
+ plt.close()
997
+
998
+ # test plotting to gca (will import pylab)
999
+ R2 = dendrogram(Z, orientation=orientation)
1000
+ plt.close()
1001
+ R2['dcoord'] = np.asarray(R2['dcoord'])
1002
+ assert_equal(R2, expected)
1003
+
1004
+ @pytest.mark.skipif(not have_matplotlib, reason="no matplotlib")
1005
+ def test_dendrogram_truncate_mode(self, xp):
1006
+ Z = linkage(xp.asarray(hierarchy_test_data.ytdist), 'single')
1007
+
1008
+ R = dendrogram(Z, 2, 'lastp', show_contracted=True)
1009
+ plt.close()
1010
+ R['dcoord'] = np.asarray(R['dcoord'])
1011
+ assert_equal(R, {'color_list': ['C0'],
1012
+ 'dcoord': [[0.0, 295.0, 295.0, 0.0]],
1013
+ 'icoord': [[5.0, 5.0, 15.0, 15.0]],
1014
+ 'ivl': ['(2)', '(4)'],
1015
+ 'leaves': [6, 9],
1016
+ 'leaves_color_list': ['C0', 'C0'],
1017
+ })
1018
+
1019
+ R = dendrogram(Z, 2, 'mtica', show_contracted=True)
1020
+ plt.close()
1021
+ R['dcoord'] = np.asarray(R['dcoord'])
1022
+ assert_equal(R, {'color_list': ['C1', 'C0', 'C0', 'C0'],
1023
+ 'dcoord': [[0.0, 138.0, 138.0, 0.0],
1024
+ [0.0, 255.0, 255.0, 0.0],
1025
+ [0.0, 268.0, 268.0, 255.0],
1026
+ [138.0, 295.0, 295.0, 268.0]],
1027
+ 'icoord': [[5.0, 5.0, 15.0, 15.0],
1028
+ [35.0, 35.0, 45.0, 45.0],
1029
+ [25.0, 25.0, 40.0, 40.0],
1030
+ [10.0, 10.0, 32.5, 32.5]],
1031
+ 'ivl': ['2', '5', '1', '0', '(2)'],
1032
+ 'leaves': [2, 5, 1, 0, 7],
1033
+ 'leaves_color_list': ['C1', 'C1', 'C0', 'C0', 'C0'],
1034
+ })
1035
+
1036
+ def test_dendrogram_colors(self, xp):
1037
+ # Tests dendrogram plots with alternate colors
1038
+ Z = linkage(xp.asarray(hierarchy_test_data.ytdist), 'single')
1039
+
1040
+ set_link_color_palette(['c', 'm', 'y', 'k'])
1041
+ R = dendrogram(Z, no_plot=True,
1042
+ above_threshold_color='g', color_threshold=250)
1043
+ set_link_color_palette(['g', 'r', 'c', 'm', 'y', 'k'])
1044
+
1045
+ color_list = R['color_list']
1046
+ assert_equal(color_list, ['c', 'm', 'g', 'g', 'g'])
1047
+
1048
+ # reset color palette (global list)
1049
+ set_link_color_palette(None)
1050
+
1051
+ def test_dendrogram_leaf_colors_zero_dist(self, xp):
1052
+ # tests that the colors of leafs are correct for tree
1053
+ # with two identical points
1054
+ x = xp.asarray([[1, 0, 0],
1055
+ [0, 0, 1],
1056
+ [0, 2, 0],
1057
+ [0, 0, 1],
1058
+ [0, 1, 0],
1059
+ [0, 1, 0]])
1060
+ z = linkage(x, "single")
1061
+ d = dendrogram(z, no_plot=True)
1062
+ exp_colors = ['C0', 'C1', 'C1', 'C0', 'C2', 'C2']
1063
+ colors = d["leaves_color_list"]
1064
+ assert_equal(colors, exp_colors)
1065
+
1066
+ def test_dendrogram_leaf_colors(self, xp):
1067
+ # tests that the colors are correct for a tree
1068
+ # with two near points ((0, 0, 1.1) and (0, 0, 1))
1069
+ x = xp.asarray([[1, 0, 0],
1070
+ [0, 0, 1.1],
1071
+ [0, 2, 0],
1072
+ [0, 0, 1],
1073
+ [0, 1, 0],
1074
+ [0, 1, 0]])
1075
+ z = linkage(x, "single")
1076
+ d = dendrogram(z, no_plot=True)
1077
+ exp_colors = ['C0', 'C1', 'C1', 'C0', 'C2', 'C2']
1078
+ colors = d["leaves_color_list"]
1079
+ assert_equal(colors, exp_colors)
1080
+
1081
+
1082
+ def calculate_maximum_distances(Z, xp):
1083
+ # Used for testing correctness of maxdists.
1084
+ n = Z.shape[0] + 1
1085
+ B = xp.zeros((n-1,), dtype=Z.dtype)
1086
+ q = xp.zeros((3,))
1087
+ for i in range(0, n - 1):
1088
+ q[:] = 0.0
1089
+ left = Z[i, 0]
1090
+ right = Z[i, 1]
1091
+ if left >= n:
1092
+ q[0] = B[xp.asarray(left, dtype=xp.int64) - n]
1093
+ if right >= n:
1094
+ q[1] = B[xp.asarray(right, dtype=xp.int64) - n]
1095
+ q[2] = Z[i, 2]
1096
+ B[i] = xp.max(q)
1097
+ return B
1098
+
1099
+
1100
+ def calculate_maximum_inconsistencies(Z, R, k=3, xp=np):
1101
+ # Used for testing correctness of maxinconsts.
1102
+ n = Z.shape[0] + 1
1103
+ dtype = xp.result_type(Z, R)
1104
+ B = xp.zeros((n-1,), dtype=dtype)
1105
+ q = xp.zeros((3,))
1106
+ for i in range(0, n - 1):
1107
+ q[:] = 0.0
1108
+ left = Z[i, 0]
1109
+ right = Z[i, 1]
1110
+ if left >= n:
1111
+ q[0] = B[xp.asarray(left, dtype=xp.int64) - n]
1112
+ if right >= n:
1113
+ q[1] = B[xp.asarray(right, dtype=xp.int64) - n]
1114
+ q[2] = R[i, k]
1115
+ B[i] = xp.max(q)
1116
+ return B
1117
+
1118
+
1119
+ @skip_if_array_api(cpu_only=True)
1120
+ def test_unsupported_uncondensed_distance_matrix_linkage_warning(xp):
1121
+ assert_warns(ClusterWarning, linkage, xp.asarray([[0, 1], [1, 0]]))
1122
+
1123
+
1124
+ def test_euclidean_linkage_value_error(xp):
1125
+ for method in scipy.cluster.hierarchy._EUCLIDEAN_METHODS:
1126
+ assert_raises(ValueError, linkage, xp.asarray([[1, 1], [1, 1]]),
1127
+ method=method, metric='cityblock')
1128
+
1129
+
1130
+ @skip_if_array_api(cpu_only=True)
1131
+ def test_2x2_linkage(xp):
1132
+ Z1 = linkage(xp.asarray([1]), method='single', metric='euclidean')
1133
+ Z2 = linkage(xp.asarray([[0, 1], [0, 0]]), method='single', metric='euclidean')
1134
+ xp_assert_close(Z1, Z2, rtol=1e-15)
1135
+
1136
+
1137
+ @skip_if_array_api(cpu_only=True)
1138
+ def test_node_compare(xp):
1139
+ np.random.seed(23)
1140
+ nobs = 50
1141
+ X = np.random.randn(nobs, 4)
1142
+ X = xp.asarray(X)
1143
+ Z = scipy.cluster.hierarchy.ward(X)
1144
+ tree = to_tree(Z)
1145
+ assert_(tree > tree.get_left())
1146
+ assert_(tree.get_right() > tree.get_left())
1147
+ assert_(tree.get_right() == tree.get_right())
1148
+ assert_(tree.get_right() != tree.get_left())
1149
+
1150
+
1151
+ @skip_if_array_api(np_only=True, reasons=['`cut_tree` uses non-standard indexing'])
1152
+ def test_cut_tree(xp):
1153
+ np.random.seed(23)
1154
+ nobs = 50
1155
+ X = np.random.randn(nobs, 4)
1156
+ X = xp.asarray(X)
1157
+ Z = scipy.cluster.hierarchy.ward(X)
1158
+ cutree = cut_tree(Z)
1159
+
1160
+ # cutree.dtype varies between int32 and int64 over platforms
1161
+ xp_assert_close(cutree[:, 0], xp.arange(nobs), rtol=1e-15, check_dtype=False)
1162
+ xp_assert_close(cutree[:, -1], xp.zeros(nobs), rtol=1e-15, check_dtype=False)
1163
+ assert_equal(np.asarray(cutree).max(0), np.arange(nobs - 1, -1, -1))
1164
+
1165
+ xp_assert_close(cutree[:, [-5]], cut_tree(Z, n_clusters=5), rtol=1e-15)
1166
+ xp_assert_close(cutree[:, [-5, -10]], cut_tree(Z, n_clusters=[5, 10]), rtol=1e-15)
1167
+ xp_assert_close(cutree[:, [-10, -5]], cut_tree(Z, n_clusters=[10, 5]), rtol=1e-15)
1168
+
1169
+ nodes = _order_cluster_tree(Z)
1170
+ heights = xp.asarray([node.dist for node in nodes])
1171
+
1172
+ xp_assert_close(cutree[:, np.searchsorted(heights, [5])],
1173
+ cut_tree(Z, height=5), rtol=1e-15)
1174
+ xp_assert_close(cutree[:, np.searchsorted(heights, [5, 10])],
1175
+ cut_tree(Z, height=[5, 10]), rtol=1e-15)
1176
+ xp_assert_close(cutree[:, np.searchsorted(heights, [10, 5])],
1177
+ cut_tree(Z, height=[10, 5]), rtol=1e-15)
1178
+
1179
+
1180
+ @skip_if_array_api(cpu_only=True)
1181
+ def test_optimal_leaf_ordering(xp):
1182
+ # test with the distance vector y
1183
+ Z = optimal_leaf_ordering(linkage(xp.asarray(hierarchy_test_data.ytdist)),
1184
+ xp.asarray(hierarchy_test_data.ytdist))
1185
+ expectedZ = hierarchy_test_data.linkage_ytdist_single_olo
1186
+ xp_assert_close(Z, xp.asarray(expectedZ), atol=1e-10)
1187
+
1188
+ # test with the observation matrix X
1189
+ Z = optimal_leaf_ordering(linkage(xp.asarray(hierarchy_test_data.X), 'ward'),
1190
+ xp.asarray(hierarchy_test_data.X))
1191
+ expectedZ = hierarchy_test_data.linkage_X_ward_olo
1192
+ xp_assert_close(Z, xp.asarray(expectedZ), atol=1e-06)
1193
+
1194
+
1195
+ @skip_if_array_api(np_only=True, reasons=['`Heap` only supports NumPy backend'])
1196
+ def test_Heap(xp):
1197
+ values = xp.asarray([2, -1, 0, -1.5, 3])
1198
+ heap = Heap(values)
1199
+
1200
+ pair = heap.get_min()
1201
+ assert_equal(pair['key'], 3)
1202
+ assert_equal(pair['value'], -1.5)
1203
+
1204
+ heap.remove_min()
1205
+ pair = heap.get_min()
1206
+ assert_equal(pair['key'], 1)
1207
+ assert_equal(pair['value'], -1)
1208
+
1209
+ heap.change_value(1, 2.5)
1210
+ pair = heap.get_min()
1211
+ assert_equal(pair['key'], 2)
1212
+ assert_equal(pair['value'], 0)
1213
+
1214
+ heap.remove_min()
1215
+ heap.remove_min()
1216
+
1217
+ heap.change_value(1, 10)
1218
+ pair = heap.get_min()
1219
+ assert_equal(pair['key'], 4)
1220
+ assert_equal(pair['value'], 3)
1221
+
1222
+ heap.remove_min()
1223
+ pair = heap.get_min()
1224
+ assert_equal(pair['key'], 1)
1225
+ assert_equal(pair['value'], 10)
astra_scene_test/Scene_04/.venv/lib/python3.9/site-packages/scipy/cluster/tests/test_vq.py ADDED
@@ -0,0 +1,421 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import warnings
2
+ import sys
3
+ from copy import deepcopy
4
+
5
+ import numpy as np
6
+ from numpy.testing import (
7
+ assert_array_equal, assert_equal, assert_, suppress_warnings
8
+ )
9
+ import pytest
10
+ from pytest import raises as assert_raises
11
+
12
+ from scipy.cluster.vq import (kmeans, kmeans2, py_vq, vq, whiten,
13
+ ClusterError, _krandinit)
14
+ from scipy.cluster import _vq
15
+ from scipy.conftest import array_api_compatible
16
+ from scipy.sparse._sputils import matrix
17
+
18
+ from scipy._lib._array_api import (
19
+ SCIPY_ARRAY_API, copy, cov, xp_assert_close, xp_assert_equal
20
+ )
21
+
22
+ pytestmark = [array_api_compatible, pytest.mark.usefixtures("skip_if_array_api")]
23
+ skip_if_array_api = pytest.mark.skip_if_array_api
24
+
25
+ TESTDATA_2D = np.array([
26
+ -2.2, 1.17, -1.63, 1.69, -2.04, 4.38, -3.09, 0.95, -1.7, 4.79, -1.68, 0.68,
27
+ -2.26, 3.34, -2.29, 2.55, -1.72, -0.72, -1.99, 2.34, -2.75, 3.43, -2.45,
28
+ 2.41, -4.26, 3.65, -1.57, 1.87, -1.96, 4.03, -3.01, 3.86, -2.53, 1.28,
29
+ -4.0, 3.95, -1.62, 1.25, -3.42, 3.17, -1.17, 0.12, -3.03, -0.27, -2.07,
30
+ -0.55, -1.17, 1.34, -2.82, 3.08, -2.44, 0.24, -1.71, 2.48, -5.23, 4.29,
31
+ -2.08, 3.69, -1.89, 3.62, -2.09, 0.26, -0.92, 1.07, -2.25, 0.88, -2.25,
32
+ 2.02, -4.31, 3.86, -2.03, 3.42, -2.76, 0.3, -2.48, -0.29, -3.42, 3.21,
33
+ -2.3, 1.73, -2.84, 0.69, -1.81, 2.48, -5.24, 4.52, -2.8, 1.31, -1.67,
34
+ -2.34, -1.18, 2.17, -2.17, 2.82, -1.85, 2.25, -2.45, 1.86, -6.79, 3.94,
35
+ -2.33, 1.89, -1.55, 2.08, -1.36, 0.93, -2.51, 2.74, -2.39, 3.92, -3.33,
36
+ 2.99, -2.06, -0.9, -2.83, 3.35, -2.59, 3.05, -2.36, 1.85, -1.69, 1.8,
37
+ -1.39, 0.66, -2.06, 0.38, -1.47, 0.44, -4.68, 3.77, -5.58, 3.44, -2.29,
38
+ 2.24, -1.04, -0.38, -1.85, 4.23, -2.88, 0.73, -2.59, 1.39, -1.34, 1.75,
39
+ -1.95, 1.3, -2.45, 3.09, -1.99, 3.41, -5.55, 5.21, -1.73, 2.52, -2.17,
40
+ 0.85, -2.06, 0.49, -2.54, 2.07, -2.03, 1.3, -3.23, 3.09, -1.55, 1.44,
41
+ -0.81, 1.1, -2.99, 2.92, -1.59, 2.18, -2.45, -0.73, -3.12, -1.3, -2.83,
42
+ 0.2, -2.77, 3.24, -1.98, 1.6, -4.59, 3.39, -4.85, 3.75, -2.25, 1.71, -3.28,
43
+ 3.38, -1.74, 0.88, -2.41, 1.92, -2.24, 1.19, -2.48, 1.06, -1.68, -0.62,
44
+ -1.3, 0.39, -1.78, 2.35, -3.54, 2.44, -1.32, 0.66, -2.38, 2.76, -2.35,
45
+ 3.95, -1.86, 4.32, -2.01, -1.23, -1.79, 2.76, -2.13, -0.13, -5.25, 3.84,
46
+ -2.24, 1.59, -4.85, 2.96, -2.41, 0.01, -0.43, 0.13, -3.92, 2.91, -1.75,
47
+ -0.53, -1.69, 1.69, -1.09, 0.15, -2.11, 2.17, -1.53, 1.22, -2.1, -0.86,
48
+ -2.56, 2.28, -3.02, 3.33, -1.12, 3.86, -2.18, -1.19, -3.03, 0.79, -0.83,
49
+ 0.97, -3.19, 1.45, -1.34, 1.28, -2.52, 4.22, -4.53, 3.22, -1.97, 1.75,
50
+ -2.36, 3.19, -0.83, 1.53, -1.59, 1.86, -2.17, 2.3, -1.63, 2.71, -2.03,
51
+ 3.75, -2.57, -0.6, -1.47, 1.33, -1.95, 0.7, -1.65, 1.27, -1.42, 1.09, -3.0,
52
+ 3.87, -2.51, 3.06, -2.6, 0.74, -1.08, -0.03, -2.44, 1.31, -2.65, 2.99,
53
+ -1.84, 1.65, -4.76, 3.75, -2.07, 3.98, -2.4, 2.67, -2.21, 1.49, -1.21,
54
+ 1.22, -5.29, 2.38, -2.85, 2.28, -5.6, 3.78, -2.7, 0.8, -1.81, 3.5, -3.75,
55
+ 4.17, -1.29, 2.99, -5.92, 3.43, -1.83, 1.23, -1.24, -1.04, -2.56, 2.37,
56
+ -3.26, 0.39, -4.63, 2.51, -4.52, 3.04, -1.7, 0.36, -1.41, 0.04, -2.1, 1.0,
57
+ -1.87, 3.78, -4.32, 3.59, -2.24, 1.38, -1.99, -0.22, -1.87, 1.95, -0.84,
58
+ 2.17, -5.38, 3.56, -1.27, 2.9, -1.79, 3.31, -5.47, 3.85, -1.44, 3.69,
59
+ -2.02, 0.37, -1.29, 0.33, -2.34, 2.56, -1.74, -1.27, -1.97, 1.22, -2.51,
60
+ -0.16, -1.64, -0.96, -2.99, 1.4, -1.53, 3.31, -2.24, 0.45, -2.46, 1.71,
61
+ -2.88, 1.56, -1.63, 1.46, -1.41, 0.68, -1.96, 2.76, -1.61,
62
+ 2.11]).reshape((200, 2))
63
+
64
+
65
+ # Global data
66
+ X = np.array([[3.0, 3], [4, 3], [4, 2],
67
+ [9, 2], [5, 1], [6, 2], [9, 4],
68
+ [5, 2], [5, 4], [7, 4], [6, 5]])
69
+
70
+ CODET1 = np.array([[3.0000, 3.0000],
71
+ [6.2000, 4.0000],
72
+ [5.8000, 1.8000]])
73
+
74
+ CODET2 = np.array([[11.0/3, 8.0/3],
75
+ [6.7500, 4.2500],
76
+ [6.2500, 1.7500]])
77
+
78
+ LABEL1 = np.array([0, 1, 2, 2, 2, 2, 1, 2, 1, 1, 1])
79
+
80
+
81
+ class TestWhiten:
82
+
83
+ def test_whiten(self, xp):
84
+ desired = xp.asarray([[5.08738849, 2.97091878],
85
+ [3.19909255, 0.69660580],
86
+ [4.51041982, 0.02640918],
87
+ [4.38567074, 0.95120889],
88
+ [2.32191480, 1.63195503]])
89
+
90
+ obs = xp.asarray([[0.98744510, 0.82766775],
91
+ [0.62093317, 0.19406729],
92
+ [0.87545741, 0.00735733],
93
+ [0.85124403, 0.26499712],
94
+ [0.45067590, 0.45464607]])
95
+ xp_assert_close(whiten(obs), desired, rtol=1e-5)
96
+
97
+ def test_whiten_zero_std(self, xp):
98
+ desired = xp.asarray([[0., 1.0, 2.86666544],
99
+ [0., 1.0, 1.32460034],
100
+ [0., 1.0, 3.74382172]])
101
+
102
+ obs = xp.asarray([[0., 1., 0.74109533],
103
+ [0., 1., 0.34243798],
104
+ [0., 1., 0.96785929]])
105
+ with warnings.catch_warnings(record=True) as w:
106
+ warnings.simplefilter('always')
107
+
108
+ xp_assert_close(whiten(obs), desired, rtol=1e-5)
109
+
110
+ assert_equal(len(w), 1)
111
+ assert_(issubclass(w[-1].category, RuntimeWarning))
112
+
113
+ def test_whiten_not_finite(self, xp):
114
+ for bad_value in xp.nan, xp.inf, -xp.inf:
115
+ obs = xp.asarray([[0.98744510, bad_value],
116
+ [0.62093317, 0.19406729],
117
+ [0.87545741, 0.00735733],
118
+ [0.85124403, 0.26499712],
119
+ [0.45067590, 0.45464607]])
120
+ assert_raises(ValueError, whiten, obs)
121
+
122
+ @pytest.mark.skipif(SCIPY_ARRAY_API,
123
+ reason='`np.matrix` unsupported in array API mode')
124
+ def test_whiten_not_finite_matrix(self, xp):
125
+ for bad_value in np.nan, np.inf, -np.inf:
126
+ obs = matrix([[0.98744510, bad_value],
127
+ [0.62093317, 0.19406729],
128
+ [0.87545741, 0.00735733],
129
+ [0.85124403, 0.26499712],
130
+ [0.45067590, 0.45464607]])
131
+ assert_raises(ValueError, whiten, obs)
132
+
133
+
134
+ class TestVq:
135
+
136
+ @skip_if_array_api(cpu_only=True)
137
+ def test_py_vq(self, xp):
138
+ initc = np.concatenate([[X[0]], [X[1]], [X[2]]])
139
+ # label1.dtype varies between int32 and int64 over platforms
140
+ label1 = py_vq(xp.asarray(X), xp.asarray(initc))[0]
141
+ xp_assert_equal(label1, xp.asarray(LABEL1, dtype=xp.int64),
142
+ check_dtype=False)
143
+
144
+ @pytest.mark.skipif(SCIPY_ARRAY_API,
145
+ reason='`np.matrix` unsupported in array API mode')
146
+ def test_py_vq_matrix(self, xp):
147
+ initc = np.concatenate([[X[0]], [X[1]], [X[2]]])
148
+ # label1.dtype varies between int32 and int64 over platforms
149
+ label1 = py_vq(matrix(X), matrix(initc))[0]
150
+ assert_array_equal(label1, LABEL1)
151
+
152
+ @skip_if_array_api(np_only=True, reasons=['`_vq` only supports NumPy backend'])
153
+ def test_vq(self, xp):
154
+ initc = np.concatenate([[X[0]], [X[1]], [X[2]]])
155
+ label1, _ = _vq.vq(xp.asarray(X), xp.asarray(initc))
156
+ assert_array_equal(label1, LABEL1)
157
+ _, _ = vq(xp.asarray(X), xp.asarray(initc))
158
+
159
+ @pytest.mark.skipif(SCIPY_ARRAY_API,
160
+ reason='`np.matrix` unsupported in array API mode')
161
+ def test_vq_matrix(self, xp):
162
+ initc = np.concatenate([[X[0]], [X[1]], [X[2]]])
163
+ label1, _ = _vq.vq(matrix(X), matrix(initc))
164
+ assert_array_equal(label1, LABEL1)
165
+ _, _ = vq(matrix(X), matrix(initc))
166
+
167
+ @skip_if_array_api(cpu_only=True)
168
+ def test_vq_1d(self, xp):
169
+ # Test special rank 1 vq algo, python implementation.
170
+ data = X[:, 0]
171
+ initc = data[:3]
172
+ a, b = _vq.vq(data, initc)
173
+ data = xp.asarray(data)
174
+ initc = xp.asarray(initc)
175
+ ta, tb = py_vq(data[:, np.newaxis], initc[:, np.newaxis])
176
+ # ta.dtype varies between int32 and int64 over platforms
177
+ xp_assert_equal(ta, xp.asarray(a, dtype=xp.int64), check_dtype=False)
178
+ xp_assert_equal(tb, xp.asarray(b))
179
+
180
+ @skip_if_array_api(np_only=True, reasons=['`_vq` only supports NumPy backend'])
181
+ def test__vq_sametype(self, xp):
182
+ a = xp.asarray([1.0, 2.0], dtype=xp.float64)
183
+ b = a.astype(xp.float32)
184
+ assert_raises(TypeError, _vq.vq, a, b)
185
+
186
+ @skip_if_array_api(np_only=True, reasons=['`_vq` only supports NumPy backend'])
187
+ def test__vq_invalid_type(self, xp):
188
+ a = xp.asarray([1, 2], dtype=int)
189
+ assert_raises(TypeError, _vq.vq, a, a)
190
+
191
+ @skip_if_array_api(cpu_only=True)
192
+ def test_vq_large_nfeat(self, xp):
193
+ X = np.random.rand(20, 20)
194
+ code_book = np.random.rand(3, 20)
195
+
196
+ codes0, dis0 = _vq.vq(X, code_book)
197
+ codes1, dis1 = py_vq(
198
+ xp.asarray(X), xp.asarray(code_book)
199
+ )
200
+ xp_assert_close(dis1, xp.asarray(dis0), rtol=1e-5)
201
+ # codes1.dtype varies between int32 and int64 over platforms
202
+ xp_assert_equal(codes1, xp.asarray(codes0, dtype=xp.int64), check_dtype=False)
203
+
204
+ X = X.astype(np.float32)
205
+ code_book = code_book.astype(np.float32)
206
+
207
+ codes0, dis0 = _vq.vq(X, code_book)
208
+ codes1, dis1 = py_vq(
209
+ xp.asarray(X), xp.asarray(code_book)
210
+ )
211
+ xp_assert_close(dis1, xp.asarray(dis0, dtype=xp.float64), rtol=1e-5)
212
+ # codes1.dtype varies between int32 and int64 over platforms
213
+ xp_assert_equal(codes1, xp.asarray(codes0, dtype=xp.int64), check_dtype=False)
214
+
215
+ @skip_if_array_api(cpu_only=True)
216
+ def test_vq_large_features(self, xp):
217
+ X = np.random.rand(10, 5) * 1000000
218
+ code_book = np.random.rand(2, 5) * 1000000
219
+
220
+ codes0, dis0 = _vq.vq(X, code_book)
221
+ codes1, dis1 = py_vq(
222
+ xp.asarray(X), xp.asarray(code_book)
223
+ )
224
+ xp_assert_close(dis1, xp.asarray(dis0), rtol=1e-5)
225
+ # codes1.dtype varies between int32 and int64 over platforms
226
+ xp_assert_equal(codes1, xp.asarray(codes0, dtype=xp.int64), check_dtype=False)
227
+
228
+
229
+ # Whole class skipped on GPU for now;
230
+ # once pdist/cdist are hooked up for CuPy, more tests will work
231
+ @skip_if_array_api(cpu_only=True)
232
+ class TestKMean:
233
+
234
+ def test_large_features(self, xp):
235
+ # Generate a data set with large values, and run kmeans on it to
236
+ # (regression for 1077).
237
+ d = 300
238
+ n = 100
239
+
240
+ m1 = np.random.randn(d)
241
+ m2 = np.random.randn(d)
242
+ x = 10000 * np.random.randn(n, d) - 20000 * m1
243
+ y = 10000 * np.random.randn(n, d) + 20000 * m2
244
+
245
+ data = np.empty((x.shape[0] + y.shape[0], d), np.float64)
246
+ data[:x.shape[0]] = x
247
+ data[x.shape[0]:] = y
248
+
249
+ kmeans(xp.asarray(data), 2)
250
+
251
+ def test_kmeans_simple(self, xp):
252
+ np.random.seed(54321)
253
+ initc = np.concatenate([[X[0]], [X[1]], [X[2]]])
254
+ code1 = kmeans(xp.asarray(X), xp.asarray(initc), iter=1)[0]
255
+ xp_assert_close(code1, xp.asarray(CODET2))
256
+
257
+ @pytest.mark.skipif(SCIPY_ARRAY_API,
258
+ reason='`np.matrix` unsupported in array API mode')
259
+ def test_kmeans_simple_matrix(self, xp):
260
+ np.random.seed(54321)
261
+ initc = np.concatenate([[X[0]], [X[1]], [X[2]]])
262
+ code1 = kmeans(matrix(X), matrix(initc), iter=1)[0]
263
+ xp_assert_close(code1, CODET2)
264
+
265
+ def test_kmeans_lost_cluster(self, xp):
266
+ # This will cause kmeans to have a cluster with no points.
267
+ data = xp.asarray(TESTDATA_2D)
268
+ initk = xp.asarray([[-1.8127404, -0.67128041],
269
+ [2.04621601, 0.07401111],
270
+ [-2.31149087, -0.05160469]])
271
+
272
+ kmeans(data, initk)
273
+ with suppress_warnings() as sup:
274
+ sup.filter(UserWarning,
275
+ "One of the clusters is empty. Re-run kmeans with a "
276
+ "different initialization")
277
+ kmeans2(data, initk, missing='warn')
278
+
279
+ assert_raises(ClusterError, kmeans2, data, initk, missing='raise')
280
+
281
+ def test_kmeans2_simple(self, xp):
282
+ np.random.seed(12345678)
283
+ initc = xp.asarray(np.concatenate([[X[0]], [X[1]], [X[2]]]))
284
+ arrays = [xp.asarray] if SCIPY_ARRAY_API else [np.asarray, matrix]
285
+ for tp in arrays:
286
+ code1 = kmeans2(tp(X), tp(initc), iter=1)[0]
287
+ code2 = kmeans2(tp(X), tp(initc), iter=2)[0]
288
+
289
+ xp_assert_close(code1, xp.asarray(CODET1))
290
+ xp_assert_close(code2, xp.asarray(CODET2))
291
+
292
+ @pytest.mark.skipif(SCIPY_ARRAY_API,
293
+ reason='`np.matrix` unsupported in array API mode')
294
+ def test_kmeans2_simple_matrix(self, xp):
295
+ np.random.seed(12345678)
296
+ initc = xp.asarray(np.concatenate([[X[0]], [X[1]], [X[2]]]))
297
+ code1 = kmeans2(matrix(X), matrix(initc), iter=1)[0]
298
+ code2 = kmeans2(matrix(X), matrix(initc), iter=2)[0]
299
+
300
+ xp_assert_close(code1, CODET1)
301
+ xp_assert_close(code2, CODET2)
302
+
303
+ def test_kmeans2_rank1(self, xp):
304
+ data = xp.asarray(TESTDATA_2D)
305
+ data1 = data[:, 0]
306
+
307
+ initc = data1[:3]
308
+ code = copy(initc, xp=xp)
309
+ kmeans2(data1, code, iter=1)[0]
310
+ kmeans2(data1, code, iter=2)[0]
311
+
312
+ def test_kmeans2_rank1_2(self, xp):
313
+ data = xp.asarray(TESTDATA_2D)
314
+ data1 = data[:, 0]
315
+ kmeans2(data1, 2, iter=1)
316
+
317
+ def test_kmeans2_high_dim(self, xp):
318
+ # test kmeans2 when the number of dimensions exceeds the number
319
+ # of input points
320
+ data = xp.asarray(TESTDATA_2D)
321
+ data = xp.reshape(data, (20, 20))[:10, :]
322
+ kmeans2(data, 2)
323
+
324
+ def test_kmeans2_init(self, xp):
325
+ np.random.seed(12345)
326
+ data = xp.asarray(TESTDATA_2D)
327
+ k = 3
328
+
329
+ kmeans2(data, k, minit='points')
330
+ kmeans2(data[:, 1], k, minit='points') # special case (1-D)
331
+
332
+ kmeans2(data, k, minit='++')
333
+ kmeans2(data[:, 1], k, minit='++') # special case (1-D)
334
+
335
+ # minit='random' can give warnings, filter those
336
+ with suppress_warnings() as sup:
337
+ sup.filter(message="One of the clusters is empty. Re-run.")
338
+ kmeans2(data, k, minit='random')
339
+ kmeans2(data[:, 1], k, minit='random') # special case (1-D)
340
+
341
+ @pytest.mark.skipif(sys.platform == 'win32',
342
+ reason='Fails with MemoryError in Wine.')
343
+ def test_krandinit(self, xp):
344
+ data = xp.asarray(TESTDATA_2D)
345
+ datas = [xp.reshape(data, (200, 2)),
346
+ xp.reshape(data, (20, 20))[:10, :]]
347
+ k = int(1e6)
348
+ for data in datas:
349
+ rng = np.random.default_rng(1234)
350
+ init = _krandinit(data, k, rng, xp)
351
+ orig_cov = cov(data.T)
352
+ init_cov = cov(init.T)
353
+ xp_assert_close(orig_cov, init_cov, atol=1e-2)
354
+
355
+ def test_kmeans2_empty(self, xp):
356
+ # Regression test for gh-1032.
357
+ assert_raises(ValueError, kmeans2, xp.asarray([]), 2)
358
+
359
+ def test_kmeans_0k(self, xp):
360
+ # Regression test for gh-1073: fail when k arg is 0.
361
+ assert_raises(ValueError, kmeans, xp.asarray(X), 0)
362
+ assert_raises(ValueError, kmeans2, xp.asarray(X), 0)
363
+ assert_raises(ValueError, kmeans2, xp.asarray(X), xp.asarray([]))
364
+
365
+ def test_kmeans_large_thres(self, xp):
366
+ # Regression test for gh-1774
367
+ x = xp.asarray([1, 2, 3, 4, 10], dtype=xp.float64)
368
+ res = kmeans(x, 1, thresh=1e16)
369
+ xp_assert_close(res[0], xp.asarray([4.], dtype=xp.float64))
370
+ xp_assert_close(res[1], xp.asarray(2.3999999999999999, dtype=xp.float64)[()])
371
+
372
+ def test_kmeans2_kpp_low_dim(self, xp):
373
+ # Regression test for gh-11462
374
+ prev_res = xp.asarray([[-1.95266667, 0.898],
375
+ [-3.153375, 3.3945]], dtype=xp.float64)
376
+ np.random.seed(42)
377
+ res, _ = kmeans2(xp.asarray(TESTDATA_2D), 2, minit='++')
378
+ xp_assert_close(res, prev_res)
379
+
380
+ def test_kmeans2_kpp_high_dim(self, xp):
381
+ # Regression test for gh-11462
382
+ n_dim = 100
383
+ size = 10
384
+ centers = np.vstack([5 * np.ones(n_dim),
385
+ -5 * np.ones(n_dim)])
386
+ np.random.seed(42)
387
+ data = np.vstack([
388
+ np.random.multivariate_normal(centers[0], np.eye(n_dim), size=size),
389
+ np.random.multivariate_normal(centers[1], np.eye(n_dim), size=size)
390
+ ])
391
+
392
+ data = xp.asarray(data)
393
+ res, _ = kmeans2(data, 2, minit='++')
394
+ xp_assert_equal(xp.sign(res), xp.sign(xp.asarray(centers)))
395
+
396
+ def test_kmeans_diff_convergence(self, xp):
397
+ # Regression test for gh-8727
398
+ obs = xp.asarray([-3, -1, 0, 1, 1, 8], dtype=xp.float64)
399
+ res = kmeans(obs, xp.asarray([-3., 0.99]))
400
+ xp_assert_close(res[0], xp.asarray([-0.4, 8.], dtype=xp.float64))
401
+ xp_assert_close(res[1], xp.asarray(1.0666666666666667, dtype=xp.float64)[()])
402
+
403
+ def test_kmeans_and_kmeans2_random_seed(self, xp):
404
+
405
+ seed_list = [
406
+ 1234, np.random.RandomState(1234), np.random.default_rng(1234)
407
+ ]
408
+
409
+ for seed in seed_list:
410
+ seed1 = deepcopy(seed)
411
+ seed2 = deepcopy(seed)
412
+ data = xp.asarray(TESTDATA_2D)
413
+ # test for kmeans
414
+ res1, _ = kmeans(data, 2, seed=seed1)
415
+ res2, _ = kmeans(data, 2, seed=seed2)
416
+ xp_assert_close(res1, res2, xp=xp) # should be same results
417
+ # test for kmeans2
418
+ for minit in ["random", "points", "++"]:
419
+ res1, _ = kmeans2(data, 2, minit=minit, seed=seed1)
420
+ res2, _ = kmeans2(data, 2, minit=minit, seed=seed2)
421
+ xp_assert_close(res1, res2, xp=xp) # should be same results
astra_scene_test/Scene_04/.venv/lib/python3.9/site-packages/scipy/cluster/vq.py ADDED
@@ -0,0 +1,835 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """
2
+ K-means clustering and vector quantization (:mod:`scipy.cluster.vq`)
3
+ ====================================================================
4
+
5
+ Provides routines for k-means clustering, generating code books
6
+ from k-means models and quantizing vectors by comparing them with
7
+ centroids in a code book.
8
+
9
+ .. autosummary::
10
+ :toctree: generated/
11
+
12
+ whiten -- Normalize a group of observations so each feature has unit variance
13
+ vq -- Calculate code book membership of a set of observation vectors
14
+ kmeans -- Perform k-means on a set of observation vectors forming k clusters
15
+ kmeans2 -- A different implementation of k-means with more methods
16
+ -- for initializing centroids
17
+
18
+ Background information
19
+ ----------------------
20
+ The k-means algorithm takes as input the number of clusters to
21
+ generate, k, and a set of observation vectors to cluster. It
22
+ returns a set of centroids, one for each of the k clusters. An
23
+ observation vector is classified with the cluster number or
24
+ centroid index of the centroid closest to it.
25
+
26
+ A vector v belongs to cluster i if it is closer to centroid i than
27
+ any other centroid. If v belongs to i, we say centroid i is the
28
+ dominating centroid of v. The k-means algorithm tries to
29
+ minimize distortion, which is defined as the sum of the squared distances
30
+ between each observation vector and its dominating centroid.
31
+ The minimization is achieved by iteratively reclassifying
32
+ the observations into clusters and recalculating the centroids until
33
+ a configuration is reached in which the centroids are stable. One can
34
+ also define a maximum number of iterations.
35
+
36
+ Since vector quantization is a natural application for k-means,
37
+ information theory terminology is often used. The centroid index
38
+ or cluster index is also referred to as a "code" and the table
39
+ mapping codes to centroids and, vice versa, is often referred to as a
40
+ "code book". The result of k-means, a set of centroids, can be
41
+ used to quantize vectors. Quantization aims to find an encoding of
42
+ vectors that reduces the expected distortion.
43
+
44
+ All routines expect obs to be an M by N array, where the rows are
45
+ the observation vectors. The codebook is a k by N array, where the
46
+ ith row is the centroid of code word i. The observation vectors
47
+ and centroids have the same feature dimension.
48
+
49
+ As an example, suppose we wish to compress a 24-bit color image
50
+ (each pixel is represented by one byte for red, one for blue, and
51
+ one for green) before sending it over the web. By using a smaller
52
+ 8-bit encoding, we can reduce the amount of data by two
53
+ thirds. Ideally, the colors for each of the 256 possible 8-bit
54
+ encoding values should be chosen to minimize distortion of the
55
+ color. Running k-means with k=256 generates a code book of 256
56
+ codes, which fills up all possible 8-bit sequences. Instead of
57
+ sending a 3-byte value for each pixel, the 8-bit centroid index
58
+ (or code word) of the dominating centroid is transmitted. The code
59
+ book is also sent over the wire so each 8-bit code can be
60
+ translated back to a 24-bit pixel value representation. If the
61
+ image of interest was of an ocean, we would expect many 24-bit
62
+ blues to be represented by 8-bit codes. If it was an image of a
63
+ human face, more flesh-tone colors would be represented in the
64
+ code book.
65
+
66
+ """
67
+ import warnings
68
+ import numpy as np
69
+ from collections import deque
70
+ from scipy._lib._array_api import (
71
+ _asarray, array_namespace, size, atleast_nd, copy, cov
72
+ )
73
+ from scipy._lib._util import check_random_state, rng_integers
74
+ from scipy.spatial.distance import cdist
75
+
76
+ from . import _vq
77
+
78
+ __docformat__ = 'restructuredtext'
79
+
80
+ __all__ = ['whiten', 'vq', 'kmeans', 'kmeans2']
81
+
82
+
83
+ class ClusterError(Exception):
84
+ pass
85
+
86
+
87
+ def whiten(obs, check_finite=True):
88
+ """
89
+ Normalize a group of observations on a per feature basis.
90
+
91
+ Before running k-means, it is beneficial to rescale each feature
92
+ dimension of the observation set by its standard deviation (i.e. "whiten"
93
+ it - as in "white noise" where each frequency has equal power).
94
+ Each feature is divided by its standard deviation across all observations
95
+ to give it unit variance.
96
+
97
+ Parameters
98
+ ----------
99
+ obs : ndarray
100
+ Each row of the array is an observation. The
101
+ columns are the features seen during each observation.
102
+
103
+ >>> # f0 f1 f2
104
+ >>> obs = [[ 1., 1., 1.], #o0
105
+ ... [ 2., 2., 2.], #o1
106
+ ... [ 3., 3., 3.], #o2
107
+ ... [ 4., 4., 4.]] #o3
108
+
109
+ check_finite : bool, optional
110
+ Whether to check that the input matrices contain only finite numbers.
111
+ Disabling may give a performance gain, but may result in problems
112
+ (crashes, non-termination) if the inputs do contain infinities or NaNs.
113
+ Default: True
114
+
115
+ Returns
116
+ -------
117
+ result : ndarray
118
+ Contains the values in `obs` scaled by the standard deviation
119
+ of each column.
120
+
121
+ Examples
122
+ --------
123
+ >>> import numpy as np
124
+ >>> from scipy.cluster.vq import whiten
125
+ >>> features = np.array([[1.9, 2.3, 1.7],
126
+ ... [1.5, 2.5, 2.2],
127
+ ... [0.8, 0.6, 1.7,]])
128
+ >>> whiten(features)
129
+ array([[ 4.17944278, 2.69811351, 7.21248917],
130
+ [ 3.29956009, 2.93273208, 9.33380951],
131
+ [ 1.75976538, 0.7038557 , 7.21248917]])
132
+
133
+ """
134
+ xp = array_namespace(obs)
135
+ obs = _asarray(obs, check_finite=check_finite, xp=xp)
136
+ std_dev = xp.std(obs, axis=0)
137
+ zero_std_mask = std_dev == 0
138
+ if xp.any(zero_std_mask):
139
+ std_dev[zero_std_mask] = 1.0
140
+ warnings.warn("Some columns have standard deviation zero. "
141
+ "The values of these columns will not change.",
142
+ RuntimeWarning, stacklevel=2)
143
+ return obs / std_dev
144
+
145
+
146
+ def vq(obs, code_book, check_finite=True):
147
+ """
148
+ Assign codes from a code book to observations.
149
+
150
+ Assigns a code from a code book to each observation. Each
151
+ observation vector in the 'M' by 'N' `obs` array is compared with the
152
+ centroids in the code book and assigned the code of the closest
153
+ centroid.
154
+
155
+ The features in `obs` should have unit variance, which can be
156
+ achieved by passing them through the whiten function. The code
157
+ book can be created with the k-means algorithm or a different
158
+ encoding algorithm.
159
+
160
+ Parameters
161
+ ----------
162
+ obs : ndarray
163
+ Each row of the 'M' x 'N' array is an observation. The columns are
164
+ the "features" seen during each observation. The features must be
165
+ whitened first using the whiten function or something equivalent.
166
+ code_book : ndarray
167
+ The code book is usually generated using the k-means algorithm.
168
+ Each row of the array holds a different code, and the columns are
169
+ the features of the code.
170
+
171
+ >>> # f0 f1 f2 f3
172
+ >>> code_book = [
173
+ ... [ 1., 2., 3., 4.], #c0
174
+ ... [ 1., 2., 3., 4.], #c1
175
+ ... [ 1., 2., 3., 4.]] #c2
176
+
177
+ check_finite : bool, optional
178
+ Whether to check that the input matrices contain only finite numbers.
179
+ Disabling may give a performance gain, but may result in problems
180
+ (crashes, non-termination) if the inputs do contain infinities or NaNs.
181
+ Default: True
182
+
183
+ Returns
184
+ -------
185
+ code : ndarray
186
+ A length M array holding the code book index for each observation.
187
+ dist : ndarray
188
+ The distortion (distance) between the observation and its nearest
189
+ code.
190
+
191
+ Examples
192
+ --------
193
+ >>> import numpy as np
194
+ >>> from scipy.cluster.vq import vq
195
+ >>> code_book = np.array([[1., 1., 1.],
196
+ ... [2., 2., 2.]])
197
+ >>> features = np.array([[1.9, 2.3, 1.7],
198
+ ... [1.5, 2.5, 2.2],
199
+ ... [0.8, 0.6, 1.7]])
200
+ >>> vq(features, code_book)
201
+ (array([1, 1, 0], dtype=int32), array([0.43588989, 0.73484692, 0.83066239]))
202
+
203
+ """
204
+ xp = array_namespace(obs, code_book)
205
+ obs = _asarray(obs, xp=xp, check_finite=check_finite)
206
+ code_book = _asarray(code_book, xp=xp, check_finite=check_finite)
207
+ ct = xp.result_type(obs, code_book)
208
+
209
+ c_obs = xp.astype(obs, ct, copy=False)
210
+ c_code_book = xp.astype(code_book, ct, copy=False)
211
+
212
+ if xp.isdtype(ct, kind='real floating'):
213
+ c_obs = np.asarray(c_obs)
214
+ c_code_book = np.asarray(c_code_book)
215
+ result = _vq.vq(c_obs, c_code_book)
216
+ return xp.asarray(result[0]), xp.asarray(result[1])
217
+ return py_vq(obs, code_book, check_finite=False)
218
+
219
+
220
+ def py_vq(obs, code_book, check_finite=True):
221
+ """ Python version of vq algorithm.
222
+
223
+ The algorithm computes the Euclidean distance between each
224
+ observation and every frame in the code_book.
225
+
226
+ Parameters
227
+ ----------
228
+ obs : ndarray
229
+ Expects a rank 2 array. Each row is one observation.
230
+ code_book : ndarray
231
+ Code book to use. Same format than obs. Should have same number of
232
+ features (e.g., columns) than obs.
233
+ check_finite : bool, optional
234
+ Whether to check that the input matrices contain only finite numbers.
235
+ Disabling may give a performance gain, but may result in problems
236
+ (crashes, non-termination) if the inputs do contain infinities or NaNs.
237
+ Default: True
238
+
239
+ Returns
240
+ -------
241
+ code : ndarray
242
+ code[i] gives the label of the ith obversation; its code is
243
+ code_book[code[i]].
244
+ mind_dist : ndarray
245
+ min_dist[i] gives the distance between the ith observation and its
246
+ corresponding code.
247
+
248
+ Notes
249
+ -----
250
+ This function is slower than the C version but works for
251
+ all input types. If the inputs have the wrong types for the
252
+ C versions of the function, this one is called as a last resort.
253
+
254
+ It is about 20 times slower than the C version.
255
+
256
+ """
257
+ xp = array_namespace(obs, code_book)
258
+ obs = _asarray(obs, xp=xp, check_finite=check_finite)
259
+ code_book = _asarray(code_book, xp=xp, check_finite=check_finite)
260
+
261
+ if obs.ndim != code_book.ndim:
262
+ raise ValueError("Observation and code_book should have the same rank")
263
+
264
+ if obs.ndim == 1:
265
+ obs = obs[:, xp.newaxis]
266
+ code_book = code_book[:, xp.newaxis]
267
+
268
+ # Once `cdist` has array API support, this `xp.asarray` call can be removed
269
+ dist = xp.asarray(cdist(obs, code_book))
270
+ code = xp.argmin(dist, axis=1)
271
+ min_dist = xp.min(dist, axis=1)
272
+ return code, min_dist
273
+
274
+
275
+ def _kmeans(obs, guess, thresh=1e-5, xp=None):
276
+ """ "raw" version of k-means.
277
+
278
+ Returns
279
+ -------
280
+ code_book
281
+ The lowest distortion codebook found.
282
+ avg_dist
283
+ The average distance a observation is from a code in the book.
284
+ Lower means the code_book matches the data better.
285
+
286
+ See Also
287
+ --------
288
+ kmeans : wrapper around k-means
289
+
290
+ Examples
291
+ --------
292
+ Note: not whitened in this example.
293
+
294
+ >>> import numpy as np
295
+ >>> from scipy.cluster.vq import _kmeans
296
+ >>> features = np.array([[ 1.9,2.3],
297
+ ... [ 1.5,2.5],
298
+ ... [ 0.8,0.6],
299
+ ... [ 0.4,1.8],
300
+ ... [ 1.0,1.0]])
301
+ >>> book = np.array((features[0],features[2]))
302
+ >>> _kmeans(features,book)
303
+ (array([[ 1.7 , 2.4 ],
304
+ [ 0.73333333, 1.13333333]]), 0.40563916697728591)
305
+
306
+ """
307
+ xp = np if xp is None else xp
308
+ code_book = guess
309
+ diff = xp.inf
310
+ prev_avg_dists = deque([diff], maxlen=2)
311
+ while diff > thresh:
312
+ # compute membership and distances between obs and code_book
313
+ obs_code, distort = vq(obs, code_book, check_finite=False)
314
+ prev_avg_dists.append(xp.mean(distort, axis=-1))
315
+ # recalc code_book as centroids of associated obs
316
+ obs = np.asarray(obs)
317
+ obs_code = np.asarray(obs_code)
318
+ code_book, has_members = _vq.update_cluster_means(obs, obs_code,
319
+ code_book.shape[0])
320
+ obs = xp.asarray(obs)
321
+ obs_code = xp.asarray(obs_code)
322
+ code_book = xp.asarray(code_book)
323
+ has_members = xp.asarray(has_members)
324
+ code_book = code_book[has_members]
325
+ diff = xp.abs(prev_avg_dists[0] - prev_avg_dists[1])
326
+
327
+ return code_book, prev_avg_dists[1]
328
+
329
+
330
+ def kmeans(obs, k_or_guess, iter=20, thresh=1e-5, check_finite=True,
331
+ *, seed=None):
332
+ """
333
+ Performs k-means on a set of observation vectors forming k clusters.
334
+
335
+ The k-means algorithm adjusts the classification of the observations
336
+ into clusters and updates the cluster centroids until the position of
337
+ the centroids is stable over successive iterations. In this
338
+ implementation of the algorithm, the stability of the centroids is
339
+ determined by comparing the absolute value of the change in the average
340
+ Euclidean distance between the observations and their corresponding
341
+ centroids against a threshold. This yields
342
+ a code book mapping centroids to codes and vice versa.
343
+
344
+ Parameters
345
+ ----------
346
+ obs : ndarray
347
+ Each row of the M by N array is an observation vector. The
348
+ columns are the features seen during each observation.
349
+ The features must be whitened first with the `whiten` function.
350
+
351
+ k_or_guess : int or ndarray
352
+ The number of centroids to generate. A code is assigned to
353
+ each centroid, which is also the row index of the centroid
354
+ in the code_book matrix generated.
355
+
356
+ The initial k centroids are chosen by randomly selecting
357
+ observations from the observation matrix. Alternatively,
358
+ passing a k by N array specifies the initial k centroids.
359
+
360
+ iter : int, optional
361
+ The number of times to run k-means, returning the codebook
362
+ with the lowest distortion. This argument is ignored if
363
+ initial centroids are specified with an array for the
364
+ ``k_or_guess`` parameter. This parameter does not represent the
365
+ number of iterations of the k-means algorithm.
366
+
367
+ thresh : float, optional
368
+ Terminates the k-means algorithm if the change in
369
+ distortion since the last k-means iteration is less than
370
+ or equal to threshold.
371
+
372
+ check_finite : bool, optional
373
+ Whether to check that the input matrices contain only finite numbers.
374
+ Disabling may give a performance gain, but may result in problems
375
+ (crashes, non-termination) if the inputs do contain infinities or NaNs.
376
+ Default: True
377
+
378
+ seed : {None, int, `numpy.random.Generator`, `numpy.random.RandomState`}, optional
379
+ Seed for initializing the pseudo-random number generator.
380
+ If `seed` is None (or `numpy.random`), the `numpy.random.RandomState`
381
+ singleton is used.
382
+ If `seed` is an int, a new ``RandomState`` instance is used,
383
+ seeded with `seed`.
384
+ If `seed` is already a ``Generator`` or ``RandomState`` instance then
385
+ that instance is used.
386
+ The default is None.
387
+
388
+ Returns
389
+ -------
390
+ codebook : ndarray
391
+ A k by N array of k centroids. The ith centroid
392
+ codebook[i] is represented with the code i. The centroids
393
+ and codes generated represent the lowest distortion seen,
394
+ not necessarily the globally minimal distortion.
395
+ Note that the number of centroids is not necessarily the same as the
396
+ ``k_or_guess`` parameter, because centroids assigned to no observations
397
+ are removed during iterations.
398
+
399
+ distortion : float
400
+ The mean (non-squared) Euclidean distance between the observations
401
+ passed and the centroids generated. Note the difference to the standard
402
+ definition of distortion in the context of the k-means algorithm, which
403
+ is the sum of the squared distances.
404
+
405
+ See Also
406
+ --------
407
+ kmeans2 : a different implementation of k-means clustering
408
+ with more methods for generating initial centroids but without
409
+ using a distortion change threshold as a stopping criterion.
410
+
411
+ whiten : must be called prior to passing an observation matrix
412
+ to kmeans.
413
+
414
+ Notes
415
+ -----
416
+ For more functionalities or optimal performance, you can use
417
+ `sklearn.cluster.KMeans <https://scikit-learn.org/stable/modules/generated/sklearn.cluster.KMeans.html>`_.
418
+ `This <https://hdbscan.readthedocs.io/en/latest/performance_and_scalability.html#comparison-of-high-performance-implementations>`_
419
+ is a benchmark result of several implementations.
420
+
421
+ Examples
422
+ --------
423
+ >>> import numpy as np
424
+ >>> from scipy.cluster.vq import vq, kmeans, whiten
425
+ >>> import matplotlib.pyplot as plt
426
+ >>> features = np.array([[ 1.9,2.3],
427
+ ... [ 1.5,2.5],
428
+ ... [ 0.8,0.6],
429
+ ... [ 0.4,1.8],
430
+ ... [ 0.1,0.1],
431
+ ... [ 0.2,1.8],
432
+ ... [ 2.0,0.5],
433
+ ... [ 0.3,1.5],
434
+ ... [ 1.0,1.0]])
435
+ >>> whitened = whiten(features)
436
+ >>> book = np.array((whitened[0],whitened[2]))
437
+ >>> kmeans(whitened,book)
438
+ (array([[ 2.3110306 , 2.86287398], # random
439
+ [ 0.93218041, 1.24398691]]), 0.85684700941625547)
440
+
441
+ >>> codes = 3
442
+ >>> kmeans(whitened,codes)
443
+ (array([[ 2.3110306 , 2.86287398], # random
444
+ [ 1.32544402, 0.65607529],
445
+ [ 0.40782893, 2.02786907]]), 0.5196582527686241)
446
+
447
+ >>> # Create 50 datapoints in two clusters a and b
448
+ >>> pts = 50
449
+ >>> rng = np.random.default_rng()
450
+ >>> a = rng.multivariate_normal([0, 0], [[4, 1], [1, 4]], size=pts)
451
+ >>> b = rng.multivariate_normal([30, 10],
452
+ ... [[10, 2], [2, 1]],
453
+ ... size=pts)
454
+ >>> features = np.concatenate((a, b))
455
+ >>> # Whiten data
456
+ >>> whitened = whiten(features)
457
+ >>> # Find 2 clusters in the data
458
+ >>> codebook, distortion = kmeans(whitened, 2)
459
+ >>> # Plot whitened data and cluster centers in red
460
+ >>> plt.scatter(whitened[:, 0], whitened[:, 1])
461
+ >>> plt.scatter(codebook[:, 0], codebook[:, 1], c='r')
462
+ >>> plt.show()
463
+
464
+ """
465
+ if isinstance(k_or_guess, int):
466
+ xp = array_namespace(obs)
467
+ else:
468
+ xp = array_namespace(obs, k_or_guess)
469
+ obs = _asarray(obs, xp=xp, check_finite=check_finite)
470
+ guess = _asarray(k_or_guess, xp=xp, check_finite=check_finite)
471
+ if iter < 1:
472
+ raise ValueError("iter must be at least 1, got %s" % iter)
473
+
474
+ # Determine whether a count (scalar) or an initial guess (array) was passed.
475
+ if size(guess) != 1:
476
+ if size(guess) < 1:
477
+ raise ValueError("Asked for 0 clusters. Initial book was %s" %
478
+ guess)
479
+ return _kmeans(obs, guess, thresh=thresh, xp=xp)
480
+
481
+ # k_or_guess is a scalar, now verify that it's an integer
482
+ k = int(guess)
483
+ if k != guess:
484
+ raise ValueError("If k_or_guess is a scalar, it must be an integer.")
485
+ if k < 1:
486
+ raise ValueError("Asked for %d clusters." % k)
487
+
488
+ rng = check_random_state(seed)
489
+
490
+ # initialize best distance value to a large value
491
+ best_dist = xp.inf
492
+ for i in range(iter):
493
+ # the initial code book is randomly selected from observations
494
+ guess = _kpoints(obs, k, rng, xp)
495
+ book, dist = _kmeans(obs, guess, thresh=thresh, xp=xp)
496
+ if dist < best_dist:
497
+ best_book = book
498
+ best_dist = dist
499
+ return best_book, best_dist
500
+
501
+
502
+ def _kpoints(data, k, rng, xp):
503
+ """Pick k points at random in data (one row = one observation).
504
+
505
+ Parameters
506
+ ----------
507
+ data : ndarray
508
+ Expect a rank 1 or 2 array. Rank 1 are assumed to describe one
509
+ dimensional data, rank 2 multidimensional data, in which case one
510
+ row is one observation.
511
+ k : int
512
+ Number of samples to generate.
513
+ rng : `numpy.random.Generator` or `numpy.random.RandomState`
514
+ Random number generator.
515
+
516
+ Returns
517
+ -------
518
+ x : ndarray
519
+ A 'k' by 'N' containing the initial centroids
520
+
521
+ """
522
+ idx = rng.choice(data.shape[0], size=int(k), replace=False)
523
+ # convert to array with default integer dtype (avoids numpy#25607)
524
+ idx = xp.asarray(idx, dtype=xp.asarray([1]).dtype)
525
+ return xp.take(data, idx, axis=0)
526
+
527
+
528
+ def _krandinit(data, k, rng, xp):
529
+ """Returns k samples of a random variable whose parameters depend on data.
530
+
531
+ More precisely, it returns k observations sampled from a Gaussian random
532
+ variable whose mean and covariances are the ones estimated from the data.
533
+
534
+ Parameters
535
+ ----------
536
+ data : ndarray
537
+ Expect a rank 1 or 2 array. Rank 1 is assumed to describe 1-D
538
+ data, rank 2 multidimensional data, in which case one
539
+ row is one observation.
540
+ k : int
541
+ Number of samples to generate.
542
+ rng : `numpy.random.Generator` or `numpy.random.RandomState`
543
+ Random number generator.
544
+
545
+ Returns
546
+ -------
547
+ x : ndarray
548
+ A 'k' by 'N' containing the initial centroids
549
+
550
+ """
551
+ mu = xp.mean(data, axis=0)
552
+ k = np.asarray(k)
553
+
554
+ if data.ndim == 1:
555
+ _cov = cov(data)
556
+ x = rng.standard_normal(size=k)
557
+ x = xp.asarray(x)
558
+ x *= xp.sqrt(_cov)
559
+ elif data.shape[1] > data.shape[0]:
560
+ # initialize when the covariance matrix is rank deficient
561
+ _, s, vh = xp.linalg.svd(data - mu, full_matrices=False)
562
+ x = rng.standard_normal(size=(k, size(s)))
563
+ x = xp.asarray(x)
564
+ sVh = s[:, None] * vh / xp.sqrt(data.shape[0] - xp.asarray(1.))
565
+ x = x @ sVh
566
+ else:
567
+ _cov = atleast_nd(cov(data.T), ndim=2)
568
+
569
+ # k rows, d cols (one row = one obs)
570
+ # Generate k sample of a random variable ~ Gaussian(mu, cov)
571
+ x = rng.standard_normal(size=(k, size(mu)))
572
+ x = xp.asarray(x)
573
+ x = x @ xp.linalg.cholesky(_cov).T
574
+
575
+ x += mu
576
+ return x
577
+
578
+
579
+ def _kpp(data, k, rng, xp):
580
+ """ Picks k points in the data based on the kmeans++ method.
581
+
582
+ Parameters
583
+ ----------
584
+ data : ndarray
585
+ Expect a rank 1 or 2 array. Rank 1 is assumed to describe 1-D
586
+ data, rank 2 multidimensional data, in which case one
587
+ row is one observation.
588
+ k : int
589
+ Number of samples to generate.
590
+ rng : `numpy.random.Generator` or `numpy.random.RandomState`
591
+ Random number generator.
592
+
593
+ Returns
594
+ -------
595
+ init : ndarray
596
+ A 'k' by 'N' containing the initial centroids.
597
+
598
+ References
599
+ ----------
600
+ .. [1] D. Arthur and S. Vassilvitskii, "k-means++: the advantages of
601
+ careful seeding", Proceedings of the Eighteenth Annual ACM-SIAM Symposium
602
+ on Discrete Algorithms, 2007.
603
+ """
604
+
605
+ ndim = len(data.shape)
606
+ if ndim == 1:
607
+ data = data[:, None]
608
+
609
+ dims = data.shape[1]
610
+
611
+ init = xp.empty((int(k), dims))
612
+
613
+ for i in range(k):
614
+ if i == 0:
615
+ init[i, :] = data[rng_integers(rng, data.shape[0]), :]
616
+
617
+ else:
618
+ D2 = cdist(init[:i,:], data, metric='sqeuclidean').min(axis=0)
619
+ probs = D2/D2.sum()
620
+ cumprobs = probs.cumsum()
621
+ r = rng.uniform()
622
+ cumprobs = np.asarray(cumprobs)
623
+ init[i, :] = data[np.searchsorted(cumprobs, r), :]
624
+
625
+ if ndim == 1:
626
+ init = init[:, 0]
627
+ return init
628
+
629
+
630
+ _valid_init_meth = {'random': _krandinit, 'points': _kpoints, '++': _kpp}
631
+
632
+
633
+ def _missing_warn():
634
+ """Print a warning when called."""
635
+ warnings.warn("One of the clusters is empty. "
636
+ "Re-run kmeans with a different initialization.",
637
+ stacklevel=3)
638
+
639
+
640
+ def _missing_raise():
641
+ """Raise a ClusterError when called."""
642
+ raise ClusterError("One of the clusters is empty. "
643
+ "Re-run kmeans with a different initialization.")
644
+
645
+
646
+ _valid_miss_meth = {'warn': _missing_warn, 'raise': _missing_raise}
647
+
648
+
649
+ def kmeans2(data, k, iter=10, thresh=1e-5, minit='random',
650
+ missing='warn', check_finite=True, *, seed=None):
651
+ """
652
+ Classify a set of observations into k clusters using the k-means algorithm.
653
+
654
+ The algorithm attempts to minimize the Euclidean distance between
655
+ observations and centroids. Several initialization methods are
656
+ included.
657
+
658
+ Parameters
659
+ ----------
660
+ data : ndarray
661
+ A 'M' by 'N' array of 'M' observations in 'N' dimensions or a length
662
+ 'M' array of 'M' 1-D observations.
663
+ k : int or ndarray
664
+ The number of clusters to form as well as the number of
665
+ centroids to generate. If `minit` initialization string is
666
+ 'matrix', or if a ndarray is given instead, it is
667
+ interpreted as initial cluster to use instead.
668
+ iter : int, optional
669
+ Number of iterations of the k-means algorithm to run. Note
670
+ that this differs in meaning from the iters parameter to
671
+ the kmeans function.
672
+ thresh : float, optional
673
+ (not used yet)
674
+ minit : str, optional
675
+ Method for initialization. Available methods are 'random',
676
+ 'points', '++' and 'matrix':
677
+
678
+ 'random': generate k centroids from a Gaussian with mean and
679
+ variance estimated from the data.
680
+
681
+ 'points': choose k observations (rows) at random from data for
682
+ the initial centroids.
683
+
684
+ '++': choose k observations accordingly to the kmeans++ method
685
+ (careful seeding)
686
+
687
+ 'matrix': interpret the k parameter as a k by M (or length k
688
+ array for 1-D data) array of initial centroids.
689
+ missing : str, optional
690
+ Method to deal with empty clusters. Available methods are
691
+ 'warn' and 'raise':
692
+
693
+ 'warn': give a warning and continue.
694
+
695
+ 'raise': raise an ClusterError and terminate the algorithm.
696
+ check_finite : bool, optional
697
+ Whether to check that the input matrices contain only finite numbers.
698
+ Disabling may give a performance gain, but may result in problems
699
+ (crashes, non-termination) if the inputs do contain infinities or NaNs.
700
+ Default: True
701
+ seed : {None, int, `numpy.random.Generator`, `numpy.random.RandomState`}, optional
702
+ Seed for initializing the pseudo-random number generator.
703
+ If `seed` is None (or `numpy.random`), the `numpy.random.RandomState`
704
+ singleton is used.
705
+ If `seed` is an int, a new ``RandomState`` instance is used,
706
+ seeded with `seed`.
707
+ If `seed` is already a ``Generator`` or ``RandomState`` instance then
708
+ that instance is used.
709
+ The default is None.
710
+
711
+ Returns
712
+ -------
713
+ centroid : ndarray
714
+ A 'k' by 'N' array of centroids found at the last iteration of
715
+ k-means.
716
+ label : ndarray
717
+ label[i] is the code or index of the centroid the
718
+ ith observation is closest to.
719
+
720
+ See Also
721
+ --------
722
+ kmeans
723
+
724
+ References
725
+ ----------
726
+ .. [1] D. Arthur and S. Vassilvitskii, "k-means++: the advantages of
727
+ careful seeding", Proceedings of the Eighteenth Annual ACM-SIAM Symposium
728
+ on Discrete Algorithms, 2007.
729
+
730
+ Examples
731
+ --------
732
+ >>> from scipy.cluster.vq import kmeans2
733
+ >>> import matplotlib.pyplot as plt
734
+ >>> import numpy as np
735
+
736
+ Create z, an array with shape (100, 2) containing a mixture of samples
737
+ from three multivariate normal distributions.
738
+
739
+ >>> rng = np.random.default_rng()
740
+ >>> a = rng.multivariate_normal([0, 6], [[2, 1], [1, 1.5]], size=45)
741
+ >>> b = rng.multivariate_normal([2, 0], [[1, -1], [-1, 3]], size=30)
742
+ >>> c = rng.multivariate_normal([6, 4], [[5, 0], [0, 1.2]], size=25)
743
+ >>> z = np.concatenate((a, b, c))
744
+ >>> rng.shuffle(z)
745
+
746
+ Compute three clusters.
747
+
748
+ >>> centroid, label = kmeans2(z, 3, minit='points')
749
+ >>> centroid
750
+ array([[ 2.22274463, -0.61666946], # may vary
751
+ [ 0.54069047, 5.86541444],
752
+ [ 6.73846769, 4.01991898]])
753
+
754
+ How many points are in each cluster?
755
+
756
+ >>> counts = np.bincount(label)
757
+ >>> counts
758
+ array([29, 51, 20]) # may vary
759
+
760
+ Plot the clusters.
761
+
762
+ >>> w0 = z[label == 0]
763
+ >>> w1 = z[label == 1]
764
+ >>> w2 = z[label == 2]
765
+ >>> plt.plot(w0[:, 0], w0[:, 1], 'o', alpha=0.5, label='cluster 0')
766
+ >>> plt.plot(w1[:, 0], w1[:, 1], 'd', alpha=0.5, label='cluster 1')
767
+ >>> plt.plot(w2[:, 0], w2[:, 1], 's', alpha=0.5, label='cluster 2')
768
+ >>> plt.plot(centroid[:, 0], centroid[:, 1], 'k*', label='centroids')
769
+ >>> plt.axis('equal')
770
+ >>> plt.legend(shadow=True)
771
+ >>> plt.show()
772
+
773
+ """
774
+ if int(iter) < 1:
775
+ raise ValueError("Invalid iter (%s), "
776
+ "must be a positive integer." % iter)
777
+ try:
778
+ miss_meth = _valid_miss_meth[missing]
779
+ except KeyError as e:
780
+ raise ValueError(f"Unknown missing method {missing!r}") from e
781
+
782
+ if isinstance(k, int):
783
+ xp = array_namespace(data)
784
+ else:
785
+ xp = array_namespace(data, k)
786
+ data = _asarray(data, xp=xp, check_finite=check_finite)
787
+ code_book = copy(k, xp=xp)
788
+ if data.ndim == 1:
789
+ d = 1
790
+ elif data.ndim == 2:
791
+ d = data.shape[1]
792
+ else:
793
+ raise ValueError("Input of rank > 2 is not supported.")
794
+
795
+ if size(data) < 1 or size(code_book) < 1:
796
+ raise ValueError("Empty input is not supported.")
797
+
798
+ # If k is not a single value, it should be compatible with data's shape
799
+ if minit == 'matrix' or size(code_book) > 1:
800
+ if data.ndim != code_book.ndim:
801
+ raise ValueError("k array doesn't match data rank")
802
+ nc = code_book.shape[0]
803
+ if data.ndim > 1 and code_book.shape[1] != d:
804
+ raise ValueError("k array doesn't match data dimension")
805
+ else:
806
+ nc = int(code_book)
807
+
808
+ if nc < 1:
809
+ raise ValueError("Cannot ask kmeans2 for %d clusters"
810
+ " (k was %s)" % (nc, code_book))
811
+ elif nc != code_book:
812
+ warnings.warn("k was not an integer, was converted.", stacklevel=2)
813
+
814
+ try:
815
+ init_meth = _valid_init_meth[minit]
816
+ except KeyError as e:
817
+ raise ValueError(f"Unknown init method {minit!r}") from e
818
+ else:
819
+ rng = check_random_state(seed)
820
+ code_book = init_meth(data, code_book, rng, xp)
821
+
822
+ data = np.asarray(data)
823
+ code_book = np.asarray(code_book)
824
+ for i in range(iter):
825
+ # Compute the nearest neighbor for each obs using the current code book
826
+ label = vq(data, code_book, check_finite=check_finite)[0]
827
+ # Update the code book by computing centroids
828
+ new_code_book, has_members = _vq.update_cluster_means(data, label, nc)
829
+ if not has_members.all():
830
+ miss_meth()
831
+ # Set the empty clusters to their previous positions
832
+ new_code_book[~has_members] = code_book[~has_members]
833
+ code_book = new_code_book
834
+
835
+ return xp.asarray(code_book), xp.asarray(label)
astra_scene_test/Scene_04/.venv/lib/python3.9/site-packages/scipy/linalg/__init__.py ADDED
@@ -0,0 +1,236 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """
2
+ ====================================
3
+ Linear algebra (:mod:`scipy.linalg`)
4
+ ====================================
5
+
6
+ .. currentmodule:: scipy.linalg
7
+
8
+ .. toctree::
9
+ :hidden:
10
+
11
+ linalg.blas
12
+ linalg.cython_blas
13
+ linalg.cython_lapack
14
+ linalg.interpolative
15
+ linalg.lapack
16
+
17
+ Linear algebra functions.
18
+
19
+ .. eventually, we should replace the numpy.linalg HTML link with just `numpy.linalg`
20
+
21
+ .. seealso::
22
+
23
+ `numpy.linalg <https://www.numpy.org/devdocs/reference/routines.linalg.html>`__
24
+ for more linear algebra functions. Note that
25
+ although `scipy.linalg` imports most of them, identically named
26
+ functions from `scipy.linalg` may offer more or slightly differing
27
+ functionality.
28
+
29
+
30
+ Basics
31
+ ======
32
+
33
+ .. autosummary::
34
+ :toctree: generated/
35
+
36
+ inv - Find the inverse of a square matrix
37
+ solve - Solve a linear system of equations
38
+ solve_banded - Solve a banded linear system
39
+ solveh_banded - Solve a Hermitian or symmetric banded system
40
+ solve_circulant - Solve a circulant system
41
+ solve_triangular - Solve a triangular matrix
42
+ solve_toeplitz - Solve a toeplitz matrix
43
+ matmul_toeplitz - Multiply a Toeplitz matrix with an array.
44
+ det - Find the determinant of a square matrix
45
+ norm - Matrix and vector norm
46
+ lstsq - Solve a linear least-squares problem
47
+ pinv - Pseudo-inverse (Moore-Penrose) using lstsq
48
+ pinvh - Pseudo-inverse of hermitian matrix
49
+ kron - Kronecker product of two arrays
50
+ khatri_rao - Khatri-Rao product of two arrays
51
+ orthogonal_procrustes - Solve an orthogonal Procrustes problem
52
+ matrix_balance - Balance matrix entries with a similarity transformation
53
+ subspace_angles - Compute the subspace angles between two matrices
54
+ bandwidth - Return the lower and upper bandwidth of an array
55
+ issymmetric - Check if a square 2D array is symmetric
56
+ ishermitian - Check if a square 2D array is Hermitian
57
+ LinAlgError
58
+ LinAlgWarning
59
+
60
+ Eigenvalue Problems
61
+ ===================
62
+
63
+ .. autosummary::
64
+ :toctree: generated/
65
+
66
+ eig - Find the eigenvalues and eigenvectors of a square matrix
67
+ eigvals - Find just the eigenvalues of a square matrix
68
+ eigh - Find the e-vals and e-vectors of a Hermitian or symmetric matrix
69
+ eigvalsh - Find just the eigenvalues of a Hermitian or symmetric matrix
70
+ eig_banded - Find the eigenvalues and eigenvectors of a banded matrix
71
+ eigvals_banded - Find just the eigenvalues of a banded matrix
72
+ eigh_tridiagonal - Find the eigenvalues and eigenvectors of a tridiagonal matrix
73
+ eigvalsh_tridiagonal - Find just the eigenvalues of a tridiagonal matrix
74
+
75
+ Decompositions
76
+ ==============
77
+
78
+ .. autosummary::
79
+ :toctree: generated/
80
+
81
+ lu - LU decomposition of a matrix
82
+ lu_factor - LU decomposition returning unordered matrix and pivots
83
+ lu_solve - Solve Ax=b using back substitution with output of lu_factor
84
+ svd - Singular value decomposition of a matrix
85
+ svdvals - Singular values of a matrix
86
+ diagsvd - Construct matrix of singular values from output of svd
87
+ orth - Construct orthonormal basis for the range of A using svd
88
+ null_space - Construct orthonormal basis for the null space of A using svd
89
+ ldl - LDL.T decomposition of a Hermitian or a symmetric matrix.
90
+ cholesky - Cholesky decomposition of a matrix
91
+ cholesky_banded - Cholesky decomp. of a sym. or Hermitian banded matrix
92
+ cho_factor - Cholesky decomposition for use in solving a linear system
93
+ cho_solve - Solve previously factored linear system
94
+ cho_solve_banded - Solve previously factored banded linear system
95
+ polar - Compute the polar decomposition.
96
+ qr - QR decomposition of a matrix
97
+ qr_multiply - QR decomposition and multiplication by Q
98
+ qr_update - Rank k QR update
99
+ qr_delete - QR downdate on row or column deletion
100
+ qr_insert - QR update on row or column insertion
101
+ rq - RQ decomposition of a matrix
102
+ qz - QZ decomposition of a pair of matrices
103
+ ordqz - QZ decomposition of a pair of matrices with reordering
104
+ schur - Schur decomposition of a matrix
105
+ rsf2csf - Real to complex Schur form
106
+ hessenberg - Hessenberg form of a matrix
107
+ cdf2rdf - Complex diagonal form to real diagonal block form
108
+ cossin - Cosine sine decomposition of a unitary or orthogonal matrix
109
+
110
+ .. seealso::
111
+
112
+ `scipy.linalg.interpolative` -- Interpolative matrix decompositions
113
+
114
+
115
+ Matrix Functions
116
+ ================
117
+
118
+ .. autosummary::
119
+ :toctree: generated/
120
+
121
+ expm - Matrix exponential
122
+ logm - Matrix logarithm
123
+ cosm - Matrix cosine
124
+ sinm - Matrix sine
125
+ tanm - Matrix tangent
126
+ coshm - Matrix hyperbolic cosine
127
+ sinhm - Matrix hyperbolic sine
128
+ tanhm - Matrix hyperbolic tangent
129
+ signm - Matrix sign
130
+ sqrtm - Matrix square root
131
+ funm - Evaluating an arbitrary matrix function
132
+ expm_frechet - Frechet derivative of the matrix exponential
133
+ expm_cond - Relative condition number of expm in the Frobenius norm
134
+ fractional_matrix_power - Fractional matrix power
135
+
136
+
137
+ Matrix Equation Solvers
138
+ =======================
139
+
140
+ .. autosummary::
141
+ :toctree: generated/
142
+
143
+ solve_sylvester - Solve the Sylvester matrix equation
144
+ solve_continuous_are - Solve the continuous-time algebraic Riccati equation
145
+ solve_discrete_are - Solve the discrete-time algebraic Riccati equation
146
+ solve_continuous_lyapunov - Solve the continuous-time Lyapunov equation
147
+ solve_discrete_lyapunov - Solve the discrete-time Lyapunov equation
148
+
149
+
150
+ Sketches and Random Projections
151
+ ===============================
152
+
153
+ .. autosummary::
154
+ :toctree: generated/
155
+
156
+ clarkson_woodruff_transform - Applies the Clarkson Woodruff Sketch (a.k.a CountMin Sketch)
157
+
158
+ Special Matrices
159
+ ================
160
+
161
+ .. autosummary::
162
+ :toctree: generated/
163
+
164
+ block_diag - Construct a block diagonal matrix from submatrices
165
+ circulant - Circulant matrix
166
+ companion - Companion matrix
167
+ convolution_matrix - Convolution matrix
168
+ dft - Discrete Fourier transform matrix
169
+ fiedler - Fiedler matrix
170
+ fiedler_companion - Fiedler companion matrix
171
+ hadamard - Hadamard matrix of order 2**n
172
+ hankel - Hankel matrix
173
+ helmert - Helmert matrix
174
+ hilbert - Hilbert matrix
175
+ invhilbert - Inverse Hilbert matrix
176
+ leslie - Leslie matrix
177
+ pascal - Pascal matrix
178
+ invpascal - Inverse Pascal matrix
179
+ toeplitz - Toeplitz matrix
180
+
181
+ Low-level routines
182
+ ==================
183
+
184
+ .. autosummary::
185
+ :toctree: generated/
186
+
187
+ get_blas_funcs
188
+ get_lapack_funcs
189
+ find_best_blas_type
190
+
191
+ .. seealso::
192
+
193
+ `scipy.linalg.blas` -- Low-level BLAS functions
194
+
195
+ `scipy.linalg.lapack` -- Low-level LAPACK functions
196
+
197
+ `scipy.linalg.cython_blas` -- Low-level BLAS functions for Cython
198
+
199
+ `scipy.linalg.cython_lapack` -- Low-level LAPACK functions for Cython
200
+
201
+ """ # noqa: E501
202
+
203
+ from ._misc import *
204
+ from ._cythonized_array_utils import *
205
+ from ._basic import *
206
+ from ._decomp import *
207
+ from ._decomp_lu import *
208
+ from ._decomp_ldl import *
209
+ from ._decomp_cholesky import *
210
+ from ._decomp_qr import *
211
+ from ._decomp_qz import *
212
+ from ._decomp_svd import *
213
+ from ._decomp_schur import *
214
+ from ._decomp_polar import *
215
+ from ._matfuncs import *
216
+ from .blas import *
217
+ from .lapack import *
218
+ from ._special_matrices import *
219
+ from ._solvers import *
220
+ from ._procrustes import *
221
+ from ._decomp_update import *
222
+ from ._sketches import *
223
+ from ._decomp_cossin import *
224
+
225
+ # Deprecated namespaces, to be removed in v2.0.0
226
+ from . import (
227
+ decomp, decomp_cholesky, decomp_lu, decomp_qr, decomp_svd, decomp_schur,
228
+ basic, misc, special_matrices, matfuncs,
229
+ )
230
+
231
+ __all__ = [s for s in dir() if not s.startswith('_')]
232
+
233
+
234
+ from scipy._lib._testutils import PytestTester
235
+ test = PytestTester(__name__)
236
+ del PytestTester
astra_scene_test/Scene_04/.venv/lib/python3.9/site-packages/scipy/linalg/_basic.py ADDED
@@ -0,0 +1,1919 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #
2
+ # Author: Pearu Peterson, March 2002
3
+ #
4
+ # w/ additions by Travis Oliphant, March 2002
5
+ # and Jake Vanderplas, August 2012
6
+
7
+ from warnings import warn
8
+ from itertools import product
9
+ import numpy as np
10
+ from numpy import atleast_1d, atleast_2d
11
+ from .lapack import get_lapack_funcs, _compute_lwork
12
+ from ._misc import LinAlgError, _datacopied, LinAlgWarning
13
+ from ._decomp import _asarray_validated
14
+ from . import _decomp, _decomp_svd
15
+ from ._solve_toeplitz import levinson
16
+ from ._cythonized_array_utils import find_det_from_lu
17
+ from scipy._lib.deprecation import _NoValue, _deprecate_positional_args
18
+
19
+ __all__ = ['solve', 'solve_triangular', 'solveh_banded', 'solve_banded',
20
+ 'solve_toeplitz', 'solve_circulant', 'inv', 'det', 'lstsq',
21
+ 'pinv', 'pinvh', 'matrix_balance', 'matmul_toeplitz']
22
+
23
+
24
+ # The numpy facilities for type-casting checks are too slow for small sized
25
+ # arrays and eat away the time budget for the checkups. Here we set a
26
+ # precomputed dict container of the numpy.can_cast() table.
27
+
28
+ # It can be used to determine quickly what a dtype can be cast to LAPACK
29
+ # compatible types, i.e., 'float32, float64, complex64, complex128'.
30
+ # Then it can be checked via "casting_dict[arr.dtype.char]"
31
+ lapack_cast_dict = {x: ''.join([y for y in 'fdFD' if np.can_cast(x, y)])
32
+ for x in np.typecodes['All']}
33
+
34
+
35
+ # Linear equations
36
+ def _solve_check(n, info, lamch=None, rcond=None):
37
+ """ Check arguments during the different steps of the solution phase """
38
+ if info < 0:
39
+ raise ValueError(f'LAPACK reported an illegal value in {-info}-th argument.')
40
+ elif 0 < info:
41
+ raise LinAlgError('Matrix is singular.')
42
+
43
+ if lamch is None:
44
+ return
45
+ E = lamch('E')
46
+ if rcond < E:
47
+ warn(f'Ill-conditioned matrix (rcond={rcond:.6g}): '
48
+ 'result may not be accurate.',
49
+ LinAlgWarning, stacklevel=3)
50
+
51
+
52
+ def solve(a, b, lower=False, overwrite_a=False,
53
+ overwrite_b=False, check_finite=True, assume_a='gen',
54
+ transposed=False):
55
+ """
56
+ Solves the linear equation set ``a @ x == b`` for the unknown ``x``
57
+ for square `a` matrix.
58
+
59
+ If the data matrix is known to be a particular type then supplying the
60
+ corresponding string to ``assume_a`` key chooses the dedicated solver.
61
+ The available options are
62
+
63
+ =================== ========
64
+ generic matrix 'gen'
65
+ symmetric 'sym'
66
+ hermitian 'her'
67
+ positive definite 'pos'
68
+ =================== ========
69
+
70
+ If omitted, ``'gen'`` is the default structure.
71
+
72
+ The datatype of the arrays define which solver is called regardless
73
+ of the values. In other words, even when the complex array entries have
74
+ precisely zero imaginary parts, the complex solver will be called based
75
+ on the data type of the array.
76
+
77
+ Parameters
78
+ ----------
79
+ a : (N, N) array_like
80
+ Square input data
81
+ b : (N, NRHS) array_like
82
+ Input data for the right hand side.
83
+ lower : bool, default: False
84
+ Ignored if ``assume_a == 'gen'`` (the default). If True, the
85
+ calculation uses only the data in the lower triangle of `a`;
86
+ entries above the diagonal are ignored. If False (default), the
87
+ calculation uses only the data in the upper triangle of `a`; entries
88
+ below the diagonal are ignored.
89
+ overwrite_a : bool, default: False
90
+ Allow overwriting data in `a` (may enhance performance).
91
+ overwrite_b : bool, default: False
92
+ Allow overwriting data in `b` (may enhance performance).
93
+ check_finite : bool, default: True
94
+ Whether to check that the input matrices contain only finite numbers.
95
+ Disabling may give a performance gain, but may result in problems
96
+ (crashes, non-termination) if the inputs do contain infinities or NaNs.
97
+ assume_a : str, {'gen', 'sym', 'her', 'pos'}
98
+ Valid entries are explained above.
99
+ transposed : bool, default: False
100
+ If True, solve ``a.T @ x == b``. Raises `NotImplementedError`
101
+ for complex `a`.
102
+
103
+ Returns
104
+ -------
105
+ x : (N, NRHS) ndarray
106
+ The solution array.
107
+
108
+ Raises
109
+ ------
110
+ ValueError
111
+ If size mismatches detected or input a is not square.
112
+ LinAlgError
113
+ If the matrix is singular.
114
+ LinAlgWarning
115
+ If an ill-conditioned input a is detected.
116
+ NotImplementedError
117
+ If transposed is True and input a is a complex matrix.
118
+
119
+ Notes
120
+ -----
121
+ If the input b matrix is a 1-D array with N elements, when supplied
122
+ together with an NxN input a, it is assumed as a valid column vector
123
+ despite the apparent size mismatch. This is compatible with the
124
+ numpy.dot() behavior and the returned result is still 1-D array.
125
+
126
+ The generic, symmetric, Hermitian and positive definite solutions are
127
+ obtained via calling ?GESV, ?SYSV, ?HESV, and ?POSV routines of
128
+ LAPACK respectively.
129
+
130
+ Examples
131
+ --------
132
+ Given `a` and `b`, solve for `x`:
133
+
134
+ >>> import numpy as np
135
+ >>> a = np.array([[3, 2, 0], [1, -1, 0], [0, 5, 1]])
136
+ >>> b = np.array([2, 4, -1])
137
+ >>> from scipy import linalg
138
+ >>> x = linalg.solve(a, b)
139
+ >>> x
140
+ array([ 2., -2., 9.])
141
+ >>> np.dot(a, x) == b
142
+ array([ True, True, True], dtype=bool)
143
+
144
+ """
145
+ # Flags for 1-D or N-D right-hand side
146
+ b_is_1D = False
147
+
148
+ a1 = atleast_2d(_asarray_validated(a, check_finite=check_finite))
149
+ b1 = atleast_1d(_asarray_validated(b, check_finite=check_finite))
150
+ n = a1.shape[0]
151
+
152
+ overwrite_a = overwrite_a or _datacopied(a1, a)
153
+ overwrite_b = overwrite_b or _datacopied(b1, b)
154
+
155
+ if a1.shape[0] != a1.shape[1]:
156
+ raise ValueError('Input a needs to be a square matrix.')
157
+
158
+ if n != b1.shape[0]:
159
+ # Last chance to catch 1x1 scalar a and 1-D b arrays
160
+ if not (n == 1 and b1.size != 0):
161
+ raise ValueError('Input b has to have same number of rows as '
162
+ 'input a')
163
+
164
+ # accommodate empty arrays
165
+ if b1.size == 0:
166
+ return np.asfortranarray(b1.copy())
167
+
168
+ # regularize 1-D b arrays to 2D
169
+ if b1.ndim == 1:
170
+ if n == 1:
171
+ b1 = b1[None, :]
172
+ else:
173
+ b1 = b1[:, None]
174
+ b_is_1D = True
175
+
176
+ if assume_a not in ('gen', 'sym', 'her', 'pos'):
177
+ raise ValueError(f'{assume_a} is not a recognized matrix structure')
178
+
179
+ # for a real matrix, describe it as "symmetric", not "hermitian"
180
+ # (lapack doesn't know what to do with real hermitian matrices)
181
+ if assume_a == 'her' and not np.iscomplexobj(a1):
182
+ assume_a = 'sym'
183
+
184
+ # Get the correct lamch function.
185
+ # The LAMCH functions only exists for S and D
186
+ # So for complex values we have to convert to real/double.
187
+ if a1.dtype.char in 'fF': # single precision
188
+ lamch = get_lapack_funcs('lamch', dtype='f')
189
+ else:
190
+ lamch = get_lapack_funcs('lamch', dtype='d')
191
+
192
+ # Currently we do not have the other forms of the norm calculators
193
+ # lansy, lanpo, lanhe.
194
+ # However, in any case they only reduce computations slightly...
195
+ lange = get_lapack_funcs('lange', (a1,))
196
+
197
+ # Since the I-norm and 1-norm are the same for symmetric matrices
198
+ # we can collect them all in this one call
199
+ # Note however, that when issuing 'gen' and form!='none', then
200
+ # the I-norm should be used
201
+ if transposed:
202
+ trans = 1
203
+ norm = 'I'
204
+ if np.iscomplexobj(a1):
205
+ raise NotImplementedError('scipy.linalg.solve can currently '
206
+ 'not solve a^T x = b or a^H x = b '
207
+ 'for complex matrices.')
208
+ else:
209
+ trans = 0
210
+ norm = '1'
211
+
212
+ anorm = lange(norm, a1)
213
+
214
+ # Generalized case 'gesv'
215
+ if assume_a == 'gen':
216
+ gecon, getrf, getrs = get_lapack_funcs(('gecon', 'getrf', 'getrs'),
217
+ (a1, b1))
218
+ lu, ipvt, info = getrf(a1, overwrite_a=overwrite_a)
219
+ _solve_check(n, info)
220
+ x, info = getrs(lu, ipvt, b1,
221
+ trans=trans, overwrite_b=overwrite_b)
222
+ _solve_check(n, info)
223
+ rcond, info = gecon(lu, anorm, norm=norm)
224
+ # Hermitian case 'hesv'
225
+ elif assume_a == 'her':
226
+ hecon, hesv, hesv_lw = get_lapack_funcs(('hecon', 'hesv',
227
+ 'hesv_lwork'), (a1, b1))
228
+ lwork = _compute_lwork(hesv_lw, n, lower)
229
+ lu, ipvt, x, info = hesv(a1, b1, lwork=lwork,
230
+ lower=lower,
231
+ overwrite_a=overwrite_a,
232
+ overwrite_b=overwrite_b)
233
+ _solve_check(n, info)
234
+ rcond, info = hecon(lu, ipvt, anorm)
235
+ # Symmetric case 'sysv'
236
+ elif assume_a == 'sym':
237
+ sycon, sysv, sysv_lw = get_lapack_funcs(('sycon', 'sysv',
238
+ 'sysv_lwork'), (a1, b1))
239
+ lwork = _compute_lwork(sysv_lw, n, lower)
240
+ lu, ipvt, x, info = sysv(a1, b1, lwork=lwork,
241
+ lower=lower,
242
+ overwrite_a=overwrite_a,
243
+ overwrite_b=overwrite_b)
244
+ _solve_check(n, info)
245
+ rcond, info = sycon(lu, ipvt, anorm)
246
+ # Positive definite case 'posv'
247
+ else:
248
+ pocon, posv = get_lapack_funcs(('pocon', 'posv'),
249
+ (a1, b1))
250
+ lu, x, info = posv(a1, b1, lower=lower,
251
+ overwrite_a=overwrite_a,
252
+ overwrite_b=overwrite_b)
253
+ _solve_check(n, info)
254
+ rcond, info = pocon(lu, anorm)
255
+
256
+ _solve_check(n, info, lamch, rcond)
257
+
258
+ if b_is_1D:
259
+ x = x.ravel()
260
+
261
+ return x
262
+
263
+
264
+ def solve_triangular(a, b, trans=0, lower=False, unit_diagonal=False,
265
+ overwrite_b=False, check_finite=True):
266
+ """
267
+ Solve the equation `a x = b` for `x`, assuming a is a triangular matrix.
268
+
269
+ Parameters
270
+ ----------
271
+ a : (M, M) array_like
272
+ A triangular matrix
273
+ b : (M,) or (M, N) array_like
274
+ Right-hand side matrix in `a x = b`
275
+ lower : bool, optional
276
+ Use only data contained in the lower triangle of `a`.
277
+ Default is to use upper triangle.
278
+ trans : {0, 1, 2, 'N', 'T', 'C'}, optional
279
+ Type of system to solve:
280
+
281
+ ======== =========
282
+ trans system
283
+ ======== =========
284
+ 0 or 'N' a x = b
285
+ 1 or 'T' a^T x = b
286
+ 2 or 'C' a^H x = b
287
+ ======== =========
288
+ unit_diagonal : bool, optional
289
+ If True, diagonal elements of `a` are assumed to be 1 and
290
+ will not be referenced.
291
+ overwrite_b : bool, optional
292
+ Allow overwriting data in `b` (may enhance performance)
293
+ check_finite : bool, optional
294
+ Whether to check that the input matrices contain only finite numbers.
295
+ Disabling may give a performance gain, but may result in problems
296
+ (crashes, non-termination) if the inputs do contain infinities or NaNs.
297
+
298
+ Returns
299
+ -------
300
+ x : (M,) or (M, N) ndarray
301
+ Solution to the system `a x = b`. Shape of return matches `b`.
302
+
303
+ Raises
304
+ ------
305
+ LinAlgError
306
+ If `a` is singular
307
+
308
+ Notes
309
+ -----
310
+ .. versionadded:: 0.9.0
311
+
312
+ Examples
313
+ --------
314
+ Solve the lower triangular system a x = b, where::
315
+
316
+ [3 0 0 0] [4]
317
+ a = [2 1 0 0] b = [2]
318
+ [1 0 1 0] [4]
319
+ [1 1 1 1] [2]
320
+
321
+ >>> import numpy as np
322
+ >>> from scipy.linalg import solve_triangular
323
+ >>> a = np.array([[3, 0, 0, 0], [2, 1, 0, 0], [1, 0, 1, 0], [1, 1, 1, 1]])
324
+ >>> b = np.array([4, 2, 4, 2])
325
+ >>> x = solve_triangular(a, b, lower=True)
326
+ >>> x
327
+ array([ 1.33333333, -0.66666667, 2.66666667, -1.33333333])
328
+ >>> a.dot(x) # Check the result
329
+ array([ 4., 2., 4., 2.])
330
+
331
+ """
332
+
333
+ a1 = _asarray_validated(a, check_finite=check_finite)
334
+ b1 = _asarray_validated(b, check_finite=check_finite)
335
+ if len(a1.shape) != 2 or a1.shape[0] != a1.shape[1]:
336
+ raise ValueError('expected square matrix')
337
+ if a1.shape[0] != b1.shape[0]:
338
+ raise ValueError(f'shapes of a {a1.shape} and b {b1.shape} are incompatible')
339
+ overwrite_b = overwrite_b or _datacopied(b1, b)
340
+
341
+ trans = {'N': 0, 'T': 1, 'C': 2}.get(trans, trans)
342
+ trtrs, = get_lapack_funcs(('trtrs',), (a1, b1))
343
+ if a1.flags.f_contiguous or trans == 2:
344
+ x, info = trtrs(a1, b1, overwrite_b=overwrite_b, lower=lower,
345
+ trans=trans, unitdiag=unit_diagonal)
346
+ else:
347
+ # transposed system is solved since trtrs expects Fortran ordering
348
+ x, info = trtrs(a1.T, b1, overwrite_b=overwrite_b, lower=not lower,
349
+ trans=not trans, unitdiag=unit_diagonal)
350
+
351
+ if info == 0:
352
+ return x
353
+ if info > 0:
354
+ raise LinAlgError("singular matrix: resolution failed at diagonal %d" %
355
+ (info-1))
356
+ raise ValueError('illegal value in %dth argument of internal trtrs' %
357
+ (-info))
358
+
359
+
360
+ def solve_banded(l_and_u, ab, b, overwrite_ab=False, overwrite_b=False,
361
+ check_finite=True):
362
+ """
363
+ Solve the equation a x = b for x, assuming a is banded matrix.
364
+
365
+ The matrix a is stored in `ab` using the matrix diagonal ordered form::
366
+
367
+ ab[u + i - j, j] == a[i,j]
368
+
369
+ Example of `ab` (shape of a is (6,6), `u` =1, `l` =2)::
370
+
371
+ * a01 a12 a23 a34 a45
372
+ a00 a11 a22 a33 a44 a55
373
+ a10 a21 a32 a43 a54 *
374
+ a20 a31 a42 a53 * *
375
+
376
+ Parameters
377
+ ----------
378
+ (l, u) : (integer, integer)
379
+ Number of non-zero lower and upper diagonals
380
+ ab : (`l` + `u` + 1, M) array_like
381
+ Banded matrix
382
+ b : (M,) or (M, K) array_like
383
+ Right-hand side
384
+ overwrite_ab : bool, optional
385
+ Discard data in `ab` (may enhance performance)
386
+ overwrite_b : bool, optional
387
+ Discard data in `b` (may enhance performance)
388
+ check_finite : bool, optional
389
+ Whether to check that the input matrices contain only finite numbers.
390
+ Disabling may give a performance gain, but may result in problems
391
+ (crashes, non-termination) if the inputs do contain infinities or NaNs.
392
+
393
+ Returns
394
+ -------
395
+ x : (M,) or (M, K) ndarray
396
+ The solution to the system a x = b. Returned shape depends on the
397
+ shape of `b`.
398
+
399
+ Examples
400
+ --------
401
+ Solve the banded system a x = b, where::
402
+
403
+ [5 2 -1 0 0] [0]
404
+ [1 4 2 -1 0] [1]
405
+ a = [0 1 3 2 -1] b = [2]
406
+ [0 0 1 2 2] [2]
407
+ [0 0 0 1 1] [3]
408
+
409
+ There is one nonzero diagonal below the main diagonal (l = 1), and
410
+ two above (u = 2). The diagonal banded form of the matrix is::
411
+
412
+ [* * -1 -1 -1]
413
+ ab = [* 2 2 2 2]
414
+ [5 4 3 2 1]
415
+ [1 1 1 1 *]
416
+
417
+ >>> import numpy as np
418
+ >>> from scipy.linalg import solve_banded
419
+ >>> ab = np.array([[0, 0, -1, -1, -1],
420
+ ... [0, 2, 2, 2, 2],
421
+ ... [5, 4, 3, 2, 1],
422
+ ... [1, 1, 1, 1, 0]])
423
+ >>> b = np.array([0, 1, 2, 2, 3])
424
+ >>> x = solve_banded((1, 2), ab, b)
425
+ >>> x
426
+ array([-2.37288136, 3.93220339, -4. , 4.3559322 , -1.3559322 ])
427
+
428
+ """
429
+
430
+ a1 = _asarray_validated(ab, check_finite=check_finite, as_inexact=True)
431
+ b1 = _asarray_validated(b, check_finite=check_finite, as_inexact=True)
432
+ # Validate shapes.
433
+ if a1.shape[-1] != b1.shape[0]:
434
+ raise ValueError("shapes of ab and b are not compatible.")
435
+ (nlower, nupper) = l_and_u
436
+ if nlower + nupper + 1 != a1.shape[0]:
437
+ raise ValueError("invalid values for the number of lower and upper "
438
+ "diagonals: l+u+1 (%d) does not equal ab.shape[0] "
439
+ "(%d)" % (nlower + nupper + 1, ab.shape[0]))
440
+
441
+ overwrite_b = overwrite_b or _datacopied(b1, b)
442
+ if a1.shape[-1] == 1:
443
+ b2 = np.array(b1, copy=(not overwrite_b))
444
+ b2 /= a1[1, 0]
445
+ return b2
446
+ if nlower == nupper == 1:
447
+ overwrite_ab = overwrite_ab or _datacopied(a1, ab)
448
+ gtsv, = get_lapack_funcs(('gtsv',), (a1, b1))
449
+ du = a1[0, 1:]
450
+ d = a1[1, :]
451
+ dl = a1[2, :-1]
452
+ du2, d, du, x, info = gtsv(dl, d, du, b1, overwrite_ab, overwrite_ab,
453
+ overwrite_ab, overwrite_b)
454
+ else:
455
+ gbsv, = get_lapack_funcs(('gbsv',), (a1, b1))
456
+ a2 = np.zeros((2*nlower + nupper + 1, a1.shape[1]), dtype=gbsv.dtype)
457
+ a2[nlower:, :] = a1
458
+ lu, piv, x, info = gbsv(nlower, nupper, a2, b1, overwrite_ab=True,
459
+ overwrite_b=overwrite_b)
460
+ if info == 0:
461
+ return x
462
+ if info > 0:
463
+ raise LinAlgError("singular matrix")
464
+ raise ValueError('illegal value in %d-th argument of internal '
465
+ 'gbsv/gtsv' % -info)
466
+
467
+
468
+ def solveh_banded(ab, b, overwrite_ab=False, overwrite_b=False, lower=False,
469
+ check_finite=True):
470
+ """
471
+ Solve equation a x = b. a is Hermitian positive-definite banded matrix.
472
+
473
+ Uses Thomas' Algorithm, which is more efficient than standard LU
474
+ factorization, but should only be used for Hermitian positive-definite
475
+ matrices.
476
+
477
+ The matrix ``a`` is stored in `ab` either in lower diagonal or upper
478
+ diagonal ordered form:
479
+
480
+ ab[u + i - j, j] == a[i,j] (if upper form; i <= j)
481
+ ab[ i - j, j] == a[i,j] (if lower form; i >= j)
482
+
483
+ Example of `ab` (shape of ``a`` is (6, 6), number of upper diagonals,
484
+ ``u`` =2)::
485
+
486
+ upper form:
487
+ * * a02 a13 a24 a35
488
+ * a01 a12 a23 a34 a45
489
+ a00 a11 a22 a33 a44 a55
490
+
491
+ lower form:
492
+ a00 a11 a22 a33 a44 a55
493
+ a10 a21 a32 a43 a54 *
494
+ a20 a31 a42 a53 * *
495
+
496
+ Cells marked with * are not used.
497
+
498
+ Parameters
499
+ ----------
500
+ ab : (``u`` + 1, M) array_like
501
+ Banded matrix
502
+ b : (M,) or (M, K) array_like
503
+ Right-hand side
504
+ overwrite_ab : bool, optional
505
+ Discard data in `ab` (may enhance performance)
506
+ overwrite_b : bool, optional
507
+ Discard data in `b` (may enhance performance)
508
+ lower : bool, optional
509
+ Is the matrix in the lower form. (Default is upper form)
510
+ check_finite : bool, optional
511
+ Whether to check that the input matrices contain only finite numbers.
512
+ Disabling may give a performance gain, but may result in problems
513
+ (crashes, non-termination) if the inputs do contain infinities or NaNs.
514
+
515
+ Returns
516
+ -------
517
+ x : (M,) or (M, K) ndarray
518
+ The solution to the system ``a x = b``. Shape of return matches shape
519
+ of `b`.
520
+
521
+ Notes
522
+ -----
523
+ In the case of a non-positive definite matrix ``a``, the solver
524
+ `solve_banded` may be used.
525
+
526
+ Examples
527
+ --------
528
+ Solve the banded system ``A x = b``, where::
529
+
530
+ [ 4 2 -1 0 0 0] [1]
531
+ [ 2 5 2 -1 0 0] [2]
532
+ A = [-1 2 6 2 -1 0] b = [2]
533
+ [ 0 -1 2 7 2 -1] [3]
534
+ [ 0 0 -1 2 8 2] [3]
535
+ [ 0 0 0 -1 2 9] [3]
536
+
537
+ >>> import numpy as np
538
+ >>> from scipy.linalg import solveh_banded
539
+
540
+ ``ab`` contains the main diagonal and the nonzero diagonals below the
541
+ main diagonal. That is, we use the lower form:
542
+
543
+ >>> ab = np.array([[ 4, 5, 6, 7, 8, 9],
544
+ ... [ 2, 2, 2, 2, 2, 0],
545
+ ... [-1, -1, -1, -1, 0, 0]])
546
+ >>> b = np.array([1, 2, 2, 3, 3, 3])
547
+ >>> x = solveh_banded(ab, b, lower=True)
548
+ >>> x
549
+ array([ 0.03431373, 0.45938375, 0.05602241, 0.47759104, 0.17577031,
550
+ 0.34733894])
551
+
552
+
553
+ Solve the Hermitian banded system ``H x = b``, where::
554
+
555
+ [ 8 2-1j 0 0 ] [ 1 ]
556
+ H = [2+1j 5 1j 0 ] b = [1+1j]
557
+ [ 0 -1j 9 -2-1j] [1-2j]
558
+ [ 0 0 -2+1j 6 ] [ 0 ]
559
+
560
+ In this example, we put the upper diagonals in the array ``hb``:
561
+
562
+ >>> hb = np.array([[0, 2-1j, 1j, -2-1j],
563
+ ... [8, 5, 9, 6 ]])
564
+ >>> b = np.array([1, 1+1j, 1-2j, 0])
565
+ >>> x = solveh_banded(hb, b)
566
+ >>> x
567
+ array([ 0.07318536-0.02939412j, 0.11877624+0.17696461j,
568
+ 0.10077984-0.23035393j, -0.00479904-0.09358128j])
569
+
570
+ """
571
+ a1 = _asarray_validated(ab, check_finite=check_finite)
572
+ b1 = _asarray_validated(b, check_finite=check_finite)
573
+ # Validate shapes.
574
+ if a1.shape[-1] != b1.shape[0]:
575
+ raise ValueError("shapes of ab and b are not compatible.")
576
+
577
+ overwrite_b = overwrite_b or _datacopied(b1, b)
578
+ overwrite_ab = overwrite_ab or _datacopied(a1, ab)
579
+
580
+ if a1.shape[0] == 2:
581
+ ptsv, = get_lapack_funcs(('ptsv',), (a1, b1))
582
+ if lower:
583
+ d = a1[0, :].real
584
+ e = a1[1, :-1]
585
+ else:
586
+ d = a1[1, :].real
587
+ e = a1[0, 1:].conj()
588
+ d, du, x, info = ptsv(d, e, b1, overwrite_ab, overwrite_ab,
589
+ overwrite_b)
590
+ else:
591
+ pbsv, = get_lapack_funcs(('pbsv',), (a1, b1))
592
+ c, x, info = pbsv(a1, b1, lower=lower, overwrite_ab=overwrite_ab,
593
+ overwrite_b=overwrite_b)
594
+ if info > 0:
595
+ raise LinAlgError("%dth leading minor not positive definite" % info)
596
+ if info < 0:
597
+ raise ValueError('illegal value in %dth argument of internal '
598
+ 'pbsv' % -info)
599
+ return x
600
+
601
+
602
+ def solve_toeplitz(c_or_cr, b, check_finite=True):
603
+ """Solve a Toeplitz system using Levinson Recursion
604
+
605
+ The Toeplitz matrix has constant diagonals, with c as its first column
606
+ and r as its first row. If r is not given, ``r == conjugate(c)`` is
607
+ assumed.
608
+
609
+ Parameters
610
+ ----------
611
+ c_or_cr : array_like or tuple of (array_like, array_like)
612
+ The vector ``c``, or a tuple of arrays (``c``, ``r``). Whatever the
613
+ actual shape of ``c``, it will be converted to a 1-D array. If not
614
+ supplied, ``r = conjugate(c)`` is assumed; in this case, if c[0] is
615
+ real, the Toeplitz matrix is Hermitian. r[0] is ignored; the first row
616
+ of the Toeplitz matrix is ``[c[0], r[1:]]``. Whatever the actual shape
617
+ of ``r``, it will be converted to a 1-D array.
618
+ b : (M,) or (M, K) array_like
619
+ Right-hand side in ``T x = b``.
620
+ check_finite : bool, optional
621
+ Whether to check that the input matrices contain only finite numbers.
622
+ Disabling may give a performance gain, but may result in problems
623
+ (result entirely NaNs) if the inputs do contain infinities or NaNs.
624
+
625
+ Returns
626
+ -------
627
+ x : (M,) or (M, K) ndarray
628
+ The solution to the system ``T x = b``. Shape of return matches shape
629
+ of `b`.
630
+
631
+ See Also
632
+ --------
633
+ toeplitz : Toeplitz matrix
634
+
635
+ Notes
636
+ -----
637
+ The solution is computed using Levinson-Durbin recursion, which is faster
638
+ than generic least-squares methods, but can be less numerically stable.
639
+
640
+ Examples
641
+ --------
642
+ Solve the Toeplitz system T x = b, where::
643
+
644
+ [ 1 -1 -2 -3] [1]
645
+ T = [ 3 1 -1 -2] b = [2]
646
+ [ 6 3 1 -1] [2]
647
+ [10 6 3 1] [5]
648
+
649
+ To specify the Toeplitz matrix, only the first column and the first
650
+ row are needed.
651
+
652
+ >>> import numpy as np
653
+ >>> c = np.array([1, 3, 6, 10]) # First column of T
654
+ >>> r = np.array([1, -1, -2, -3]) # First row of T
655
+ >>> b = np.array([1, 2, 2, 5])
656
+
657
+ >>> from scipy.linalg import solve_toeplitz, toeplitz
658
+ >>> x = solve_toeplitz((c, r), b)
659
+ >>> x
660
+ array([ 1.66666667, -1. , -2.66666667, 2.33333333])
661
+
662
+ Check the result by creating the full Toeplitz matrix and
663
+ multiplying it by `x`. We should get `b`.
664
+
665
+ >>> T = toeplitz(c, r)
666
+ >>> T.dot(x)
667
+ array([ 1., 2., 2., 5.])
668
+
669
+ """
670
+ # If numerical stability of this algorithm is a problem, a future
671
+ # developer might consider implementing other O(N^2) Toeplitz solvers,
672
+ # such as GKO (https://www.jstor.org/stable/2153371) or Bareiss.
673
+
674
+ r, c, b, dtype, b_shape = _validate_args_for_toeplitz_ops(
675
+ c_or_cr, b, check_finite, keep_b_shape=True)
676
+
677
+ # Form a 1-D array of values to be used in the matrix, containing a
678
+ # reversed copy of r[1:], followed by c.
679
+ vals = np.concatenate((r[-1:0:-1], c))
680
+ if b is None:
681
+ raise ValueError('illegal value, `b` is a required argument')
682
+
683
+ if b.ndim == 1:
684
+ x, _ = levinson(vals, np.ascontiguousarray(b))
685
+ else:
686
+ x = np.column_stack([levinson(vals, np.ascontiguousarray(b[:, i]))[0]
687
+ for i in range(b.shape[1])])
688
+ x = x.reshape(*b_shape)
689
+
690
+ return x
691
+
692
+
693
+ def _get_axis_len(aname, a, axis):
694
+ ax = axis
695
+ if ax < 0:
696
+ ax += a.ndim
697
+ if 0 <= ax < a.ndim:
698
+ return a.shape[ax]
699
+ raise ValueError(f"'{aname}axis' entry is out of bounds")
700
+
701
+
702
+ def solve_circulant(c, b, singular='raise', tol=None,
703
+ caxis=-1, baxis=0, outaxis=0):
704
+ """Solve C x = b for x, where C is a circulant matrix.
705
+
706
+ `C` is the circulant matrix associated with the vector `c`.
707
+
708
+ The system is solved by doing division in Fourier space. The
709
+ calculation is::
710
+
711
+ x = ifft(fft(b) / fft(c))
712
+
713
+ where `fft` and `ifft` are the fast Fourier transform and its inverse,
714
+ respectively. For a large vector `c`, this is *much* faster than
715
+ solving the system with the full circulant matrix.
716
+
717
+ Parameters
718
+ ----------
719
+ c : array_like
720
+ The coefficients of the circulant matrix.
721
+ b : array_like
722
+ Right-hand side matrix in ``a x = b``.
723
+ singular : str, optional
724
+ This argument controls how a near singular circulant matrix is
725
+ handled. If `singular` is "raise" and the circulant matrix is
726
+ near singular, a `LinAlgError` is raised. If `singular` is
727
+ "lstsq", the least squares solution is returned. Default is "raise".
728
+ tol : float, optional
729
+ If any eigenvalue of the circulant matrix has an absolute value
730
+ that is less than or equal to `tol`, the matrix is considered to be
731
+ near singular. If not given, `tol` is set to::
732
+
733
+ tol = abs_eigs.max() * abs_eigs.size * np.finfo(np.float64).eps
734
+
735
+ where `abs_eigs` is the array of absolute values of the eigenvalues
736
+ of the circulant matrix.
737
+ caxis : int
738
+ When `c` has dimension greater than 1, it is viewed as a collection
739
+ of circulant vectors. In this case, `caxis` is the axis of `c` that
740
+ holds the vectors of circulant coefficients.
741
+ baxis : int
742
+ When `b` has dimension greater than 1, it is viewed as a collection
743
+ of vectors. In this case, `baxis` is the axis of `b` that holds the
744
+ right-hand side vectors.
745
+ outaxis : int
746
+ When `c` or `b` are multidimensional, the value returned by
747
+ `solve_circulant` is multidimensional. In this case, `outaxis` is
748
+ the axis of the result that holds the solution vectors.
749
+
750
+ Returns
751
+ -------
752
+ x : ndarray
753
+ Solution to the system ``C x = b``.
754
+
755
+ Raises
756
+ ------
757
+ LinAlgError
758
+ If the circulant matrix associated with `c` is near singular.
759
+
760
+ See Also
761
+ --------
762
+ circulant : circulant matrix
763
+
764
+ Notes
765
+ -----
766
+ For a 1-D vector `c` with length `m`, and an array `b`
767
+ with shape ``(m, ...)``,
768
+
769
+ solve_circulant(c, b)
770
+
771
+ returns the same result as
772
+
773
+ solve(circulant(c), b)
774
+
775
+ where `solve` and `circulant` are from `scipy.linalg`.
776
+
777
+ .. versionadded:: 0.16.0
778
+
779
+ Examples
780
+ --------
781
+ >>> import numpy as np
782
+ >>> from scipy.linalg import solve_circulant, solve, circulant, lstsq
783
+
784
+ >>> c = np.array([2, 2, 4])
785
+ >>> b = np.array([1, 2, 3])
786
+ >>> solve_circulant(c, b)
787
+ array([ 0.75, -0.25, 0.25])
788
+
789
+ Compare that result to solving the system with `scipy.linalg.solve`:
790
+
791
+ >>> solve(circulant(c), b)
792
+ array([ 0.75, -0.25, 0.25])
793
+
794
+ A singular example:
795
+
796
+ >>> c = np.array([1, 1, 0, 0])
797
+ >>> b = np.array([1, 2, 3, 4])
798
+
799
+ Calling ``solve_circulant(c, b)`` will raise a `LinAlgError`. For the
800
+ least square solution, use the option ``singular='lstsq'``:
801
+
802
+ >>> solve_circulant(c, b, singular='lstsq')
803
+ array([ 0.25, 1.25, 2.25, 1.25])
804
+
805
+ Compare to `scipy.linalg.lstsq`:
806
+
807
+ >>> x, resid, rnk, s = lstsq(circulant(c), b)
808
+ >>> x
809
+ array([ 0.25, 1.25, 2.25, 1.25])
810
+
811
+ A broadcasting example:
812
+
813
+ Suppose we have the vectors of two circulant matrices stored in an array
814
+ with shape (2, 5), and three `b` vectors stored in an array with shape
815
+ (3, 5). For example,
816
+
817
+ >>> c = np.array([[1.5, 2, 3, 0, 0], [1, 1, 4, 3, 2]])
818
+ >>> b = np.arange(15).reshape(-1, 5)
819
+
820
+ We want to solve all combinations of circulant matrices and `b` vectors,
821
+ with the result stored in an array with shape (2, 3, 5). When we
822
+ disregard the axes of `c` and `b` that hold the vectors of coefficients,
823
+ the shapes of the collections are (2,) and (3,), respectively, which are
824
+ not compatible for broadcasting. To have a broadcast result with shape
825
+ (2, 3), we add a trivial dimension to `c`: ``c[:, np.newaxis, :]`` has
826
+ shape (2, 1, 5). The last dimension holds the coefficients of the
827
+ circulant matrices, so when we call `solve_circulant`, we can use the
828
+ default ``caxis=-1``. The coefficients of the `b` vectors are in the last
829
+ dimension of the array `b`, so we use ``baxis=-1``. If we use the
830
+ default `outaxis`, the result will have shape (5, 2, 3), so we'll use
831
+ ``outaxis=-1`` to put the solution vectors in the last dimension.
832
+
833
+ >>> x = solve_circulant(c[:, np.newaxis, :], b, baxis=-1, outaxis=-1)
834
+ >>> x.shape
835
+ (2, 3, 5)
836
+ >>> np.set_printoptions(precision=3) # For compact output of numbers.
837
+ >>> x
838
+ array([[[-0.118, 0.22 , 1.277, -0.142, 0.302],
839
+ [ 0.651, 0.989, 2.046, 0.627, 1.072],
840
+ [ 1.42 , 1.758, 2.816, 1.396, 1.841]],
841
+ [[ 0.401, 0.304, 0.694, -0.867, 0.377],
842
+ [ 0.856, 0.758, 1.149, -0.412, 0.831],
843
+ [ 1.31 , 1.213, 1.603, 0.042, 1.286]]])
844
+
845
+ Check by solving one pair of `c` and `b` vectors (cf. ``x[1, 1, :]``):
846
+
847
+ >>> solve_circulant(c[1], b[1, :])
848
+ array([ 0.856, 0.758, 1.149, -0.412, 0.831])
849
+
850
+ """
851
+ c = np.atleast_1d(c)
852
+ nc = _get_axis_len("c", c, caxis)
853
+ b = np.atleast_1d(b)
854
+ nb = _get_axis_len("b", b, baxis)
855
+ if nc != nb:
856
+ raise ValueError(f'Shapes of c {c.shape} and b {b.shape} are incompatible')
857
+
858
+ fc = np.fft.fft(np.moveaxis(c, caxis, -1), axis=-1)
859
+ abs_fc = np.abs(fc)
860
+ if tol is None:
861
+ # This is the same tolerance as used in np.linalg.matrix_rank.
862
+ tol = abs_fc.max(axis=-1) * nc * np.finfo(np.float64).eps
863
+ if tol.shape != ():
864
+ tol.shape = tol.shape + (1,)
865
+ else:
866
+ tol = np.atleast_1d(tol)
867
+
868
+ near_zeros = abs_fc <= tol
869
+ is_near_singular = np.any(near_zeros)
870
+ if is_near_singular:
871
+ if singular == 'raise':
872
+ raise LinAlgError("near singular circulant matrix.")
873
+ else:
874
+ # Replace the small values with 1 to avoid errors in the
875
+ # division fb/fc below.
876
+ fc[near_zeros] = 1
877
+
878
+ fb = np.fft.fft(np.moveaxis(b, baxis, -1), axis=-1)
879
+
880
+ q = fb / fc
881
+
882
+ if is_near_singular:
883
+ # `near_zeros` is a boolean array, same shape as `c`, that is
884
+ # True where `fc` is (near) zero. `q` is the broadcasted result
885
+ # of fb / fc, so to set the values of `q` to 0 where `fc` is near
886
+ # zero, we use a mask that is the broadcast result of an array
887
+ # of True values shaped like `b` with `near_zeros`.
888
+ mask = np.ones_like(b, dtype=bool) & near_zeros
889
+ q[mask] = 0
890
+
891
+ x = np.fft.ifft(q, axis=-1)
892
+ if not (np.iscomplexobj(c) or np.iscomplexobj(b)):
893
+ x = x.real
894
+ if outaxis != -1:
895
+ x = np.moveaxis(x, -1, outaxis)
896
+ return x
897
+
898
+
899
+ # matrix inversion
900
+ def inv(a, overwrite_a=False, check_finite=True):
901
+ """
902
+ Compute the inverse of a matrix.
903
+
904
+ Parameters
905
+ ----------
906
+ a : array_like
907
+ Square matrix to be inverted.
908
+ overwrite_a : bool, optional
909
+ Discard data in `a` (may improve performance). Default is False.
910
+ check_finite : bool, optional
911
+ Whether to check that the input matrix contains only finite numbers.
912
+ Disabling may give a performance gain, but may result in problems
913
+ (crashes, non-termination) if the inputs do contain infinities or NaNs.
914
+
915
+ Returns
916
+ -------
917
+ ainv : ndarray
918
+ Inverse of the matrix `a`.
919
+
920
+ Raises
921
+ ------
922
+ LinAlgError
923
+ If `a` is singular.
924
+ ValueError
925
+ If `a` is not square, or not 2D.
926
+
927
+ Examples
928
+ --------
929
+ >>> import numpy as np
930
+ >>> from scipy import linalg
931
+ >>> a = np.array([[1., 2.], [3., 4.]])
932
+ >>> linalg.inv(a)
933
+ array([[-2. , 1. ],
934
+ [ 1.5, -0.5]])
935
+ >>> np.dot(a, linalg.inv(a))
936
+ array([[ 1., 0.],
937
+ [ 0., 1.]])
938
+
939
+ """
940
+ a1 = _asarray_validated(a, check_finite=check_finite)
941
+ if len(a1.shape) != 2 or a1.shape[0] != a1.shape[1]:
942
+ raise ValueError('expected square matrix')
943
+ overwrite_a = overwrite_a or _datacopied(a1, a)
944
+ getrf, getri, getri_lwork = get_lapack_funcs(('getrf', 'getri',
945
+ 'getri_lwork'),
946
+ (a1,))
947
+ lu, piv, info = getrf(a1, overwrite_a=overwrite_a)
948
+ if info == 0:
949
+ lwork = _compute_lwork(getri_lwork, a1.shape[0])
950
+
951
+ # XXX: the following line fixes curious SEGFAULT when
952
+ # benchmarking 500x500 matrix inverse. This seems to
953
+ # be a bug in LAPACK ?getri routine because if lwork is
954
+ # minimal (when using lwork[0] instead of lwork[1]) then
955
+ # all tests pass. Further investigation is required if
956
+ # more such SEGFAULTs occur.
957
+ lwork = int(1.01 * lwork)
958
+ inv_a, info = getri(lu, piv, lwork=lwork, overwrite_lu=1)
959
+ if info > 0:
960
+ raise LinAlgError("singular matrix")
961
+ if info < 0:
962
+ raise ValueError('illegal value in %d-th argument of internal '
963
+ 'getrf|getri' % -info)
964
+ return inv_a
965
+
966
+
967
+ # Determinant
968
+
969
+ def det(a, overwrite_a=False, check_finite=True):
970
+ """
971
+ Compute the determinant of a matrix
972
+
973
+ The determinant is a scalar that is a function of the associated square
974
+ matrix coefficients. The determinant value is zero for singular matrices.
975
+
976
+ Parameters
977
+ ----------
978
+ a : (..., M, M) array_like
979
+ Input array to compute determinants for.
980
+ overwrite_a : bool, optional
981
+ Allow overwriting data in a (may enhance performance).
982
+ check_finite : bool, optional
983
+ Whether to check that the input matrix contains only finite numbers.
984
+ Disabling may give a performance gain, but may result in problems
985
+ (crashes, non-termination) if the inputs do contain infinities or NaNs.
986
+
987
+ Returns
988
+ -------
989
+ det : (...) float or complex
990
+ Determinant of `a`. For stacked arrays, a scalar is returned for each
991
+ (m, m) slice in the last two dimensions of the input. For example, an
992
+ input of shape (p, q, m, m) will produce a result of shape (p, q). If
993
+ all dimensions are 1 a scalar is returned regardless of ndim.
994
+
995
+ Notes
996
+ -----
997
+ The determinant is computed by performing an LU factorization of the
998
+ input with LAPACK routine 'getrf', and then calculating the product of
999
+ diagonal entries of the U factor.
1000
+
1001
+ Even the input array is single precision (float32 or complex64), the result
1002
+ will be returned in double precision (float64 or complex128) to prevent
1003
+ overflows.
1004
+
1005
+ Examples
1006
+ --------
1007
+ >>> import numpy as np
1008
+ >>> from scipy import linalg
1009
+ >>> a = np.array([[1,2,3], [4,5,6], [7,8,9]]) # A singular matrix
1010
+ >>> linalg.det(a)
1011
+ 0.0
1012
+ >>> b = np.array([[0,2,3], [4,5,6], [7,8,9]])
1013
+ >>> linalg.det(b)
1014
+ 3.0
1015
+ >>> # An array with the shape (3, 2, 2, 2)
1016
+ >>> c = np.array([[[[1., 2.], [3., 4.]],
1017
+ ... [[5., 6.], [7., 8.]]],
1018
+ ... [[[9., 10.], [11., 12.]],
1019
+ ... [[13., 14.], [15., 16.]]],
1020
+ ... [[[17., 18.], [19., 20.]],
1021
+ ... [[21., 22.], [23., 24.]]]])
1022
+ >>> linalg.det(c) # The resulting shape is (3, 2)
1023
+ array([[-2., -2.],
1024
+ [-2., -2.],
1025
+ [-2., -2.]])
1026
+ >>> linalg.det(c[0, 0]) # Confirm the (0, 0) slice, [[1, 2], [3, 4]]
1027
+ -2.0
1028
+ """
1029
+ # The goal is to end up with a writable contiguous array to pass to Cython
1030
+
1031
+ # First we check and make arrays.
1032
+ a1 = np.asarray_chkfinite(a) if check_finite else np.asarray(a)
1033
+ if a1.ndim < 2:
1034
+ raise ValueError('The input array must be at least two-dimensional.')
1035
+ if a1.shape[-1] != a1.shape[-2]:
1036
+ raise ValueError('Last 2 dimensions of the array must be square'
1037
+ f' but received shape {a1.shape}.')
1038
+
1039
+ # Also check if dtype is LAPACK compatible
1040
+ if a1.dtype.char not in 'fdFD':
1041
+ dtype_char = lapack_cast_dict[a1.dtype.char]
1042
+ if not dtype_char: # No casting possible
1043
+ raise TypeError(f'The dtype "{a1.dtype.name}" cannot be cast '
1044
+ 'to float(32, 64) or complex(64, 128).')
1045
+
1046
+ a1 = a1.astype(dtype_char[0]) # makes a copy, free to scratch
1047
+ overwrite_a = True
1048
+
1049
+ # Empty array has determinant 1 because math.
1050
+ if min(*a1.shape) == 0:
1051
+ if a1.ndim == 2:
1052
+ return np.float64(1.)
1053
+ else:
1054
+ return np.ones(shape=a1.shape[:-2], dtype=np.float64)
1055
+
1056
+ # Scalar case
1057
+ if a1.shape[-2:] == (1, 1):
1058
+ # Either ndarray with spurious singletons or a single element
1059
+ if max(*a1.shape) > 1:
1060
+ temp = np.squeeze(a1)
1061
+ if a1.dtype.char in 'dD':
1062
+ return temp
1063
+ else:
1064
+ return (temp.astype('d') if a1.dtype.char == 'f' else
1065
+ temp.astype('D'))
1066
+ else:
1067
+ return (np.float64(a1.item()) if a1.dtype.char in 'fd' else
1068
+ np.complex128(a1.item()))
1069
+
1070
+ # Then check overwrite permission
1071
+ if not _datacopied(a1, a): # "a" still alive through "a1"
1072
+ if not overwrite_a:
1073
+ # Data belongs to "a" so make a copy
1074
+ a1 = a1.copy(order='C')
1075
+ # else: Do nothing we'll use "a" if possible
1076
+ # else: a1 has its own data thus free to scratch
1077
+
1078
+ # Then layout checks, might happen that overwrite is allowed but original
1079
+ # array was read-only or non-C-contiguous.
1080
+ if not (a1.flags['C_CONTIGUOUS'] and a1.flags['WRITEABLE']):
1081
+ a1 = a1.copy(order='C')
1082
+
1083
+ if a1.ndim == 2:
1084
+ det = find_det_from_lu(a1)
1085
+ # Convert float, complex to to NumPy scalars
1086
+ return (np.float64(det) if np.isrealobj(det) else np.complex128(det))
1087
+
1088
+ # loop over the stacked array, and avoid overflows for single precision
1089
+ # Cf. np.linalg.det(np.diag([1e+38, 1e+38]).astype(np.float32))
1090
+ dtype_char = a1.dtype.char
1091
+ if dtype_char in 'fF':
1092
+ dtype_char = 'd' if dtype_char.islower() else 'D'
1093
+
1094
+ det = np.empty(a1.shape[:-2], dtype=dtype_char)
1095
+ for ind in product(*[range(x) for x in a1.shape[:-2]]):
1096
+ det[ind] = find_det_from_lu(a1[ind])
1097
+ return det
1098
+
1099
+
1100
+ # Linear Least Squares
1101
+ def lstsq(a, b, cond=None, overwrite_a=False, overwrite_b=False,
1102
+ check_finite=True, lapack_driver=None):
1103
+ """
1104
+ Compute least-squares solution to equation Ax = b.
1105
+
1106
+ Compute a vector x such that the 2-norm ``|b - A x|`` is minimized.
1107
+
1108
+ Parameters
1109
+ ----------
1110
+ a : (M, N) array_like
1111
+ Left-hand side array
1112
+ b : (M,) or (M, K) array_like
1113
+ Right hand side array
1114
+ cond : float, optional
1115
+ Cutoff for 'small' singular values; used to determine effective
1116
+ rank of a. Singular values smaller than
1117
+ ``cond * largest_singular_value`` are considered zero.
1118
+ overwrite_a : bool, optional
1119
+ Discard data in `a` (may enhance performance). Default is False.
1120
+ overwrite_b : bool, optional
1121
+ Discard data in `b` (may enhance performance). Default is False.
1122
+ check_finite : bool, optional
1123
+ Whether to check that the input matrices contain only finite numbers.
1124
+ Disabling may give a performance gain, but may result in problems
1125
+ (crashes, non-termination) if the inputs do contain infinities or NaNs.
1126
+ lapack_driver : str, optional
1127
+ Which LAPACK driver is used to solve the least-squares problem.
1128
+ Options are ``'gelsd'``, ``'gelsy'``, ``'gelss'``. Default
1129
+ (``'gelsd'``) is a good choice. However, ``'gelsy'`` can be slightly
1130
+ faster on many problems. ``'gelss'`` was used historically. It is
1131
+ generally slow but uses less memory.
1132
+
1133
+ .. versionadded:: 0.17.0
1134
+
1135
+ Returns
1136
+ -------
1137
+ x : (N,) or (N, K) ndarray
1138
+ Least-squares solution.
1139
+ residues : (K,) ndarray or float
1140
+ Square of the 2-norm for each column in ``b - a x``, if ``M > N`` and
1141
+ ``rank(A) == n`` (returns a scalar if ``b`` is 1-D). Otherwise a
1142
+ (0,)-shaped array is returned.
1143
+ rank : int
1144
+ Effective rank of `a`.
1145
+ s : (min(M, N),) ndarray or None
1146
+ Singular values of `a`. The condition number of ``a`` is
1147
+ ``s[0] / s[-1]``.
1148
+
1149
+ Raises
1150
+ ------
1151
+ LinAlgError
1152
+ If computation does not converge.
1153
+
1154
+ ValueError
1155
+ When parameters are not compatible.
1156
+
1157
+ See Also
1158
+ --------
1159
+ scipy.optimize.nnls : linear least squares with non-negativity constraint
1160
+
1161
+ Notes
1162
+ -----
1163
+ When ``'gelsy'`` is used as a driver, `residues` is set to a (0,)-shaped
1164
+ array and `s` is always ``None``.
1165
+
1166
+ Examples
1167
+ --------
1168
+ >>> import numpy as np
1169
+ >>> from scipy.linalg import lstsq
1170
+ >>> import matplotlib.pyplot as plt
1171
+
1172
+ Suppose we have the following data:
1173
+
1174
+ >>> x = np.array([1, 2.5, 3.5, 4, 5, 7, 8.5])
1175
+ >>> y = np.array([0.3, 1.1, 1.5, 2.0, 3.2, 6.6, 8.6])
1176
+
1177
+ We want to fit a quadratic polynomial of the form ``y = a + b*x**2``
1178
+ to this data. We first form the "design matrix" M, with a constant
1179
+ column of 1s and a column containing ``x**2``:
1180
+
1181
+ >>> M = x[:, np.newaxis]**[0, 2]
1182
+ >>> M
1183
+ array([[ 1. , 1. ],
1184
+ [ 1. , 6.25],
1185
+ [ 1. , 12.25],
1186
+ [ 1. , 16. ],
1187
+ [ 1. , 25. ],
1188
+ [ 1. , 49. ],
1189
+ [ 1. , 72.25]])
1190
+
1191
+ We want to find the least-squares solution to ``M.dot(p) = y``,
1192
+ where ``p`` is a vector with length 2 that holds the parameters
1193
+ ``a`` and ``b``.
1194
+
1195
+ >>> p, res, rnk, s = lstsq(M, y)
1196
+ >>> p
1197
+ array([ 0.20925829, 0.12013861])
1198
+
1199
+ Plot the data and the fitted curve.
1200
+
1201
+ >>> plt.plot(x, y, 'o', label='data')
1202
+ >>> xx = np.linspace(0, 9, 101)
1203
+ >>> yy = p[0] + p[1]*xx**2
1204
+ >>> plt.plot(xx, yy, label='least squares fit, $y = a + bx^2$')
1205
+ >>> plt.xlabel('x')
1206
+ >>> plt.ylabel('y')
1207
+ >>> plt.legend(framealpha=1, shadow=True)
1208
+ >>> plt.grid(alpha=0.25)
1209
+ >>> plt.show()
1210
+
1211
+ """
1212
+ a1 = _asarray_validated(a, check_finite=check_finite)
1213
+ b1 = _asarray_validated(b, check_finite=check_finite)
1214
+ if len(a1.shape) != 2:
1215
+ raise ValueError('Input array a should be 2D')
1216
+ m, n = a1.shape
1217
+ if len(b1.shape) == 2:
1218
+ nrhs = b1.shape[1]
1219
+ else:
1220
+ nrhs = 1
1221
+ if m != b1.shape[0]:
1222
+ raise ValueError('Shape mismatch: a and b should have the same number'
1223
+ f' of rows ({m} != {b1.shape[0]}).')
1224
+ if m == 0 or n == 0: # Zero-sized problem, confuses LAPACK
1225
+ x = np.zeros((n,) + b1.shape[1:], dtype=np.common_type(a1, b1))
1226
+ if n == 0:
1227
+ residues = np.linalg.norm(b1, axis=0)**2
1228
+ else:
1229
+ residues = np.empty((0,))
1230
+ return x, residues, 0, np.empty((0,))
1231
+
1232
+ driver = lapack_driver
1233
+ if driver is None:
1234
+ driver = lstsq.default_lapack_driver
1235
+ if driver not in ('gelsd', 'gelsy', 'gelss'):
1236
+ raise ValueError('LAPACK driver "%s" is not found' % driver)
1237
+
1238
+ lapack_func, lapack_lwork = get_lapack_funcs((driver,
1239
+ '%s_lwork' % driver),
1240
+ (a1, b1))
1241
+ real_data = True if (lapack_func.dtype.kind == 'f') else False
1242
+
1243
+ if m < n:
1244
+ # need to extend b matrix as it will be filled with
1245
+ # a larger solution matrix
1246
+ if len(b1.shape) == 2:
1247
+ b2 = np.zeros((n, nrhs), dtype=lapack_func.dtype)
1248
+ b2[:m, :] = b1
1249
+ else:
1250
+ b2 = np.zeros(n, dtype=lapack_func.dtype)
1251
+ b2[:m] = b1
1252
+ b1 = b2
1253
+
1254
+ overwrite_a = overwrite_a or _datacopied(a1, a)
1255
+ overwrite_b = overwrite_b or _datacopied(b1, b)
1256
+
1257
+ if cond is None:
1258
+ cond = np.finfo(lapack_func.dtype).eps
1259
+
1260
+ if driver in ('gelss', 'gelsd'):
1261
+ if driver == 'gelss':
1262
+ lwork = _compute_lwork(lapack_lwork, m, n, nrhs, cond)
1263
+ v, x, s, rank, work, info = lapack_func(a1, b1, cond, lwork,
1264
+ overwrite_a=overwrite_a,
1265
+ overwrite_b=overwrite_b)
1266
+
1267
+ elif driver == 'gelsd':
1268
+ if real_data:
1269
+ lwork, iwork = _compute_lwork(lapack_lwork, m, n, nrhs, cond)
1270
+ x, s, rank, info = lapack_func(a1, b1, lwork,
1271
+ iwork, cond, False, False)
1272
+ else: # complex data
1273
+ lwork, rwork, iwork = _compute_lwork(lapack_lwork, m, n,
1274
+ nrhs, cond)
1275
+ x, s, rank, info = lapack_func(a1, b1, lwork, rwork, iwork,
1276
+ cond, False, False)
1277
+ if info > 0:
1278
+ raise LinAlgError("SVD did not converge in Linear Least Squares")
1279
+ if info < 0:
1280
+ raise ValueError('illegal value in %d-th argument of internal %s'
1281
+ % (-info, lapack_driver))
1282
+ resids = np.asarray([], dtype=x.dtype)
1283
+ if m > n:
1284
+ x1 = x[:n]
1285
+ if rank == n:
1286
+ resids = np.sum(np.abs(x[n:])**2, axis=0)
1287
+ x = x1
1288
+ return x, resids, rank, s
1289
+
1290
+ elif driver == 'gelsy':
1291
+ lwork = _compute_lwork(lapack_lwork, m, n, nrhs, cond)
1292
+ jptv = np.zeros((a1.shape[1], 1), dtype=np.int32)
1293
+ v, x, j, rank, info = lapack_func(a1, b1, jptv, cond,
1294
+ lwork, False, False)
1295
+ if info < 0:
1296
+ raise ValueError("illegal value in %d-th argument of internal "
1297
+ "gelsy" % -info)
1298
+ if m > n:
1299
+ x1 = x[:n]
1300
+ x = x1
1301
+ return x, np.array([], x.dtype), rank, None
1302
+
1303
+
1304
+ lstsq.default_lapack_driver = 'gelsd'
1305
+
1306
+
1307
+ @_deprecate_positional_args(version="1.14")
1308
+ def pinv(a, *, atol=None, rtol=None, return_rank=False, check_finite=True,
1309
+ cond=_NoValue, rcond=_NoValue):
1310
+ """
1311
+ Compute the (Moore-Penrose) pseudo-inverse of a matrix.
1312
+
1313
+ Calculate a generalized inverse of a matrix using its
1314
+ singular-value decomposition ``U @ S @ V`` in the economy mode and picking
1315
+ up only the columns/rows that are associated with significant singular
1316
+ values.
1317
+
1318
+ If ``s`` is the maximum singular value of ``a``, then the
1319
+ significance cut-off value is determined by ``atol + rtol * s``. Any
1320
+ singular value below this value is assumed insignificant.
1321
+
1322
+ Parameters
1323
+ ----------
1324
+ a : (M, N) array_like
1325
+ Matrix to be pseudo-inverted.
1326
+ atol : float, optional
1327
+ Absolute threshold term, default value is 0.
1328
+
1329
+ .. versionadded:: 1.7.0
1330
+
1331
+ rtol : float, optional
1332
+ Relative threshold term, default value is ``max(M, N) * eps`` where
1333
+ ``eps`` is the machine precision value of the datatype of ``a``.
1334
+
1335
+ .. versionadded:: 1.7.0
1336
+
1337
+ return_rank : bool, optional
1338
+ If True, return the effective rank of the matrix.
1339
+ check_finite : bool, optional
1340
+ Whether to check that the input matrix contains only finite numbers.
1341
+ Disabling may give a performance gain, but may result in problems
1342
+ (crashes, non-termination) if the inputs do contain infinities or NaNs.
1343
+ cond, rcond : float, optional
1344
+ In older versions, these values were meant to be used as ``atol`` with
1345
+ ``rtol=0``. If both were given ``rcond`` overwrote ``cond`` and hence
1346
+ the code was not correct. Thus using these are strongly discouraged and
1347
+ the tolerances above are recommended instead. In fact, if provided,
1348
+ atol, rtol takes precedence over these keywords.
1349
+
1350
+ .. deprecated:: 1.7.0
1351
+ Deprecated in favor of ``rtol`` and ``atol`` parameters above and
1352
+ will be removed in SciPy 1.14.0.
1353
+
1354
+ .. versionchanged:: 1.3.0
1355
+ Previously the default cutoff value was just ``eps*f`` where ``f``
1356
+ was ``1e3`` for single precision and ``1e6`` for double precision.
1357
+
1358
+ Returns
1359
+ -------
1360
+ B : (N, M) ndarray
1361
+ The pseudo-inverse of matrix `a`.
1362
+ rank : int
1363
+ The effective rank of the matrix. Returned if `return_rank` is True.
1364
+
1365
+ Raises
1366
+ ------
1367
+ LinAlgError
1368
+ If SVD computation does not converge.
1369
+
1370
+ See Also
1371
+ --------
1372
+ pinvh : Moore-Penrose pseudoinverse of a hermitian matrix.
1373
+
1374
+ Notes
1375
+ -----
1376
+ If ``A`` is invertible then the Moore-Penrose pseudoinverse is exactly
1377
+ the inverse of ``A`` [1]_. If ``A`` is not invertible then the
1378
+ Moore-Penrose pseudoinverse computes the ``x`` solution to ``Ax = b`` such
1379
+ that ``||Ax - b||`` is minimized [1]_.
1380
+
1381
+ References
1382
+ ----------
1383
+ .. [1] Penrose, R. (1956). On best approximate solutions of linear matrix
1384
+ equations. Mathematical Proceedings of the Cambridge Philosophical
1385
+ Society, 52(1), 17-19. doi:10.1017/S0305004100030929
1386
+
1387
+ Examples
1388
+ --------
1389
+
1390
+ Given an ``m x n`` matrix ``A`` and an ``n x m`` matrix ``B`` the four
1391
+ Moore-Penrose conditions are:
1392
+
1393
+ 1. ``ABA = A`` (``B`` is a generalized inverse of ``A``),
1394
+ 2. ``BAB = B`` (``A`` is a generalized inverse of ``B``),
1395
+ 3. ``(AB)* = AB`` (``AB`` is hermitian),
1396
+ 4. ``(BA)* = BA`` (``BA`` is hermitian) [1]_.
1397
+
1398
+ Here, ``A*`` denotes the conjugate transpose. The Moore-Penrose
1399
+ pseudoinverse is a unique ``B`` that satisfies all four of these
1400
+ conditions and exists for any ``A``. Note that, unlike the standard
1401
+ matrix inverse, ``A`` does not have to be a square matrix or have
1402
+ linearly independent columns/rows.
1403
+
1404
+ As an example, we can calculate the Moore-Penrose pseudoinverse of a
1405
+ random non-square matrix and verify it satisfies the four conditions.
1406
+
1407
+ >>> import numpy as np
1408
+ >>> from scipy import linalg
1409
+ >>> rng = np.random.default_rng()
1410
+ >>> A = rng.standard_normal((9, 6))
1411
+ >>> B = linalg.pinv(A)
1412
+ >>> np.allclose(A @ B @ A, A) # Condition 1
1413
+ True
1414
+ >>> np.allclose(B @ A @ B, B) # Condition 2
1415
+ True
1416
+ >>> np.allclose((A @ B).conj().T, A @ B) # Condition 3
1417
+ True
1418
+ >>> np.allclose((B @ A).conj().T, B @ A) # Condition 4
1419
+ True
1420
+
1421
+ """
1422
+ a = _asarray_validated(a, check_finite=check_finite)
1423
+ u, s, vh = _decomp_svd.svd(a, full_matrices=False, check_finite=False)
1424
+ t = u.dtype.char.lower()
1425
+ maxS = np.max(s)
1426
+
1427
+ if rcond is not _NoValue or cond is not _NoValue:
1428
+ warn('Use of the "cond" and "rcond" keywords are deprecated and '
1429
+ 'will be removed in SciPy 1.14.0. Use "atol" and '
1430
+ '"rtol" keywords instead', DeprecationWarning, stacklevel=2)
1431
+
1432
+ # backwards compatible only atol and rtol are both missing
1433
+ if ((rcond not in (_NoValue, None) or cond not in (_NoValue, None))
1434
+ and (atol is None) and (rtol is None)):
1435
+ atol = rcond if rcond not in (_NoValue, None) else cond
1436
+ rtol = 0.
1437
+
1438
+ atol = 0. if atol is None else atol
1439
+ rtol = max(a.shape) * np.finfo(t).eps if (rtol is None) else rtol
1440
+
1441
+ if (atol < 0.) or (rtol < 0.):
1442
+ raise ValueError("atol and rtol values must be positive.")
1443
+
1444
+ val = atol + maxS * rtol
1445
+ rank = np.sum(s > val)
1446
+
1447
+ u = u[:, :rank]
1448
+ u /= s[:rank]
1449
+ B = (u @ vh[:rank]).conj().T
1450
+
1451
+ if return_rank:
1452
+ return B, rank
1453
+ else:
1454
+ return B
1455
+
1456
+
1457
+ def pinvh(a, atol=None, rtol=None, lower=True, return_rank=False,
1458
+ check_finite=True):
1459
+ """
1460
+ Compute the (Moore-Penrose) pseudo-inverse of a Hermitian matrix.
1461
+
1462
+ Calculate a generalized inverse of a complex Hermitian/real symmetric
1463
+ matrix using its eigenvalue decomposition and including all eigenvalues
1464
+ with 'large' absolute value.
1465
+
1466
+ Parameters
1467
+ ----------
1468
+ a : (N, N) array_like
1469
+ Real symmetric or complex hermetian matrix to be pseudo-inverted
1470
+
1471
+ atol : float, optional
1472
+ Absolute threshold term, default value is 0.
1473
+
1474
+ .. versionadded:: 1.7.0
1475
+
1476
+ rtol : float, optional
1477
+ Relative threshold term, default value is ``N * eps`` where
1478
+ ``eps`` is the machine precision value of the datatype of ``a``.
1479
+
1480
+ .. versionadded:: 1.7.0
1481
+
1482
+ lower : bool, optional
1483
+ Whether the pertinent array data is taken from the lower or upper
1484
+ triangle of `a`. (Default: lower)
1485
+ return_rank : bool, optional
1486
+ If True, return the effective rank of the matrix.
1487
+ check_finite : bool, optional
1488
+ Whether to check that the input matrix contains only finite numbers.
1489
+ Disabling may give a performance gain, but may result in problems
1490
+ (crashes, non-termination) if the inputs do contain infinities or NaNs.
1491
+
1492
+ Returns
1493
+ -------
1494
+ B : (N, N) ndarray
1495
+ The pseudo-inverse of matrix `a`.
1496
+ rank : int
1497
+ The effective rank of the matrix. Returned if `return_rank` is True.
1498
+
1499
+ Raises
1500
+ ------
1501
+ LinAlgError
1502
+ If eigenvalue algorithm does not converge.
1503
+
1504
+ See Also
1505
+ --------
1506
+ pinv : Moore-Penrose pseudoinverse of a matrix.
1507
+
1508
+ Examples
1509
+ --------
1510
+
1511
+ For a more detailed example see `pinv`.
1512
+
1513
+ >>> import numpy as np
1514
+ >>> from scipy.linalg import pinvh
1515
+ >>> rng = np.random.default_rng()
1516
+ >>> a = rng.standard_normal((9, 6))
1517
+ >>> a = np.dot(a, a.T)
1518
+ >>> B = pinvh(a)
1519
+ >>> np.allclose(a, a @ B @ a)
1520
+ True
1521
+ >>> np.allclose(B, B @ a @ B)
1522
+ True
1523
+
1524
+ """
1525
+ a = _asarray_validated(a, check_finite=check_finite)
1526
+ s, u = _decomp.eigh(a, lower=lower, check_finite=False)
1527
+ t = u.dtype.char.lower()
1528
+ maxS = np.max(np.abs(s))
1529
+
1530
+ atol = 0. if atol is None else atol
1531
+ rtol = max(a.shape) * np.finfo(t).eps if (rtol is None) else rtol
1532
+
1533
+ if (atol < 0.) or (rtol < 0.):
1534
+ raise ValueError("atol and rtol values must be positive.")
1535
+
1536
+ val = atol + maxS * rtol
1537
+ above_cutoff = (abs(s) > val)
1538
+
1539
+ psigma_diag = 1.0 / s[above_cutoff]
1540
+ u = u[:, above_cutoff]
1541
+
1542
+ B = (u * psigma_diag) @ u.conj().T
1543
+
1544
+ if return_rank:
1545
+ return B, len(psigma_diag)
1546
+ else:
1547
+ return B
1548
+
1549
+
1550
+ def matrix_balance(A, permute=True, scale=True, separate=False,
1551
+ overwrite_a=False):
1552
+ """
1553
+ Compute a diagonal similarity transformation for row/column balancing.
1554
+
1555
+ The balancing tries to equalize the row and column 1-norms by applying
1556
+ a similarity transformation such that the magnitude variation of the
1557
+ matrix entries is reflected to the scaling matrices.
1558
+
1559
+ Moreover, if enabled, the matrix is first permuted to isolate the upper
1560
+ triangular parts of the matrix and, again if scaling is also enabled,
1561
+ only the remaining subblocks are subjected to scaling.
1562
+
1563
+ The balanced matrix satisfies the following equality
1564
+
1565
+ .. math::
1566
+
1567
+ B = T^{-1} A T
1568
+
1569
+ The scaling coefficients are approximated to the nearest power of 2
1570
+ to avoid round-off errors.
1571
+
1572
+ Parameters
1573
+ ----------
1574
+ A : (n, n) array_like
1575
+ Square data matrix for the balancing.
1576
+ permute : bool, optional
1577
+ The selector to define whether permutation of A is also performed
1578
+ prior to scaling.
1579
+ scale : bool, optional
1580
+ The selector to turn on and off the scaling. If False, the matrix
1581
+ will not be scaled.
1582
+ separate : bool, optional
1583
+ This switches from returning a full matrix of the transformation
1584
+ to a tuple of two separate 1-D permutation and scaling arrays.
1585
+ overwrite_a : bool, optional
1586
+ This is passed to xGEBAL directly. Essentially, overwrites the result
1587
+ to the data. It might increase the space efficiency. See LAPACK manual
1588
+ for details. This is False by default.
1589
+
1590
+ Returns
1591
+ -------
1592
+ B : (n, n) ndarray
1593
+ Balanced matrix
1594
+ T : (n, n) ndarray
1595
+ A possibly permuted diagonal matrix whose nonzero entries are
1596
+ integer powers of 2 to avoid numerical truncation errors.
1597
+ scale, perm : (n,) ndarray
1598
+ If ``separate`` keyword is set to True then instead of the array
1599
+ ``T`` above, the scaling and the permutation vectors are given
1600
+ separately as a tuple without allocating the full array ``T``.
1601
+
1602
+ Notes
1603
+ -----
1604
+ This algorithm is particularly useful for eigenvalue and matrix
1605
+ decompositions and in many cases it is already called by various
1606
+ LAPACK routines.
1607
+
1608
+ The algorithm is based on the well-known technique of [1]_ and has
1609
+ been modified to account for special cases. See [2]_ for details
1610
+ which have been implemented since LAPACK v3.5.0. Before this version
1611
+ there are corner cases where balancing can actually worsen the
1612
+ conditioning. See [3]_ for such examples.
1613
+
1614
+ The code is a wrapper around LAPACK's xGEBAL routine family for matrix
1615
+ balancing.
1616
+
1617
+ .. versionadded:: 0.19.0
1618
+
1619
+ References
1620
+ ----------
1621
+ .. [1] B.N. Parlett and C. Reinsch, "Balancing a Matrix for
1622
+ Calculation of Eigenvalues and Eigenvectors", Numerische Mathematik,
1623
+ Vol.13(4), 1969, :doi:`10.1007/BF02165404`
1624
+ .. [2] R. James, J. Langou, B.R. Lowery, "On matrix balancing and
1625
+ eigenvector computation", 2014, :arxiv:`1401.5766`
1626
+ .. [3] D.S. Watkins. A case where balancing is harmful.
1627
+ Electron. Trans. Numer. Anal, Vol.23, 2006.
1628
+
1629
+ Examples
1630
+ --------
1631
+ >>> import numpy as np
1632
+ >>> from scipy import linalg
1633
+ >>> x = np.array([[1,2,0], [9,1,0.01], [1,2,10*np.pi]])
1634
+
1635
+ >>> y, permscale = linalg.matrix_balance(x)
1636
+ >>> np.abs(x).sum(axis=0) / np.abs(x).sum(axis=1)
1637
+ array([ 3.66666667, 0.4995005 , 0.91312162])
1638
+
1639
+ >>> np.abs(y).sum(axis=0) / np.abs(y).sum(axis=1)
1640
+ array([ 1.2 , 1.27041742, 0.92658316]) # may vary
1641
+
1642
+ >>> permscale # only powers of 2 (0.5 == 2^(-1))
1643
+ array([[ 0.5, 0. , 0. ], # may vary
1644
+ [ 0. , 1. , 0. ],
1645
+ [ 0. , 0. , 1. ]])
1646
+
1647
+ """
1648
+
1649
+ A = np.atleast_2d(_asarray_validated(A, check_finite=True))
1650
+
1651
+ if not np.equal(*A.shape):
1652
+ raise ValueError('The data matrix for balancing should be square.')
1653
+
1654
+ gebal = get_lapack_funcs(('gebal'), (A,))
1655
+ B, lo, hi, ps, info = gebal(A, scale=scale, permute=permute,
1656
+ overwrite_a=overwrite_a)
1657
+
1658
+ if info < 0:
1659
+ raise ValueError('xGEBAL exited with the internal error '
1660
+ f'"illegal value in argument number {-info}.". See '
1661
+ 'LAPACK documentation for the xGEBAL error codes.')
1662
+
1663
+ # Separate the permutations from the scalings and then convert to int
1664
+ scaling = np.ones_like(ps, dtype=float)
1665
+ scaling[lo:hi+1] = ps[lo:hi+1]
1666
+
1667
+ # gebal uses 1-indexing
1668
+ ps = ps.astype(int, copy=False) - 1
1669
+ n = A.shape[0]
1670
+ perm = np.arange(n)
1671
+
1672
+ # LAPACK permutes with the ordering n --> hi, then 0--> lo
1673
+ if hi < n:
1674
+ for ind, x in enumerate(ps[hi+1:][::-1], 1):
1675
+ if n-ind == x:
1676
+ continue
1677
+ perm[[x, n-ind]] = perm[[n-ind, x]]
1678
+
1679
+ if lo > 0:
1680
+ for ind, x in enumerate(ps[:lo]):
1681
+ if ind == x:
1682
+ continue
1683
+ perm[[x, ind]] = perm[[ind, x]]
1684
+
1685
+ if separate:
1686
+ return B, (scaling, perm)
1687
+
1688
+ # get the inverse permutation
1689
+ iperm = np.empty_like(perm)
1690
+ iperm[perm] = np.arange(n)
1691
+
1692
+ return B, np.diag(scaling)[iperm, :]
1693
+
1694
+
1695
+ def _validate_args_for_toeplitz_ops(c_or_cr, b, check_finite, keep_b_shape,
1696
+ enforce_square=True):
1697
+ """Validate arguments and format inputs for toeplitz functions
1698
+
1699
+ Parameters
1700
+ ----------
1701
+ c_or_cr : array_like or tuple of (array_like, array_like)
1702
+ The vector ``c``, or a tuple of arrays (``c``, ``r``). Whatever the
1703
+ actual shape of ``c``, it will be converted to a 1-D array. If not
1704
+ supplied, ``r = conjugate(c)`` is assumed; in this case, if c[0] is
1705
+ real, the Toeplitz matrix is Hermitian. r[0] is ignored; the first row
1706
+ of the Toeplitz matrix is ``[c[0], r[1:]]``. Whatever the actual shape
1707
+ of ``r``, it will be converted to a 1-D array.
1708
+ b : (M,) or (M, K) array_like
1709
+ Right-hand side in ``T x = b``.
1710
+ check_finite : bool
1711
+ Whether to check that the input matrices contain only finite numbers.
1712
+ Disabling may give a performance gain, but may result in problems
1713
+ (result entirely NaNs) if the inputs do contain infinities or NaNs.
1714
+ keep_b_shape : bool
1715
+ Whether to convert a (M,) dimensional b into a (M, 1) dimensional
1716
+ matrix.
1717
+ enforce_square : bool, optional
1718
+ If True (default), this verifies that the Toeplitz matrix is square.
1719
+
1720
+ Returns
1721
+ -------
1722
+ r : array
1723
+ 1d array corresponding to the first row of the Toeplitz matrix.
1724
+ c: array
1725
+ 1d array corresponding to the first column of the Toeplitz matrix.
1726
+ b: array
1727
+ (M,), (M, 1) or (M, K) dimensional array, post validation,
1728
+ corresponding to ``b``.
1729
+ dtype: numpy datatype
1730
+ ``dtype`` stores the datatype of ``r``, ``c`` and ``b``. If any of
1731
+ ``r``, ``c`` or ``b`` are complex, ``dtype`` is ``np.complex128``,
1732
+ otherwise, it is ``np.float``.
1733
+ b_shape: tuple
1734
+ Shape of ``b`` after passing it through ``_asarray_validated``.
1735
+
1736
+ """
1737
+
1738
+ if isinstance(c_or_cr, tuple):
1739
+ c, r = c_or_cr
1740
+ c = _asarray_validated(c, check_finite=check_finite).ravel()
1741
+ r = _asarray_validated(r, check_finite=check_finite).ravel()
1742
+ else:
1743
+ c = _asarray_validated(c_or_cr, check_finite=check_finite).ravel()
1744
+ r = c.conjugate()
1745
+
1746
+ if b is None:
1747
+ raise ValueError('`b` must be an array, not None.')
1748
+
1749
+ b = _asarray_validated(b, check_finite=check_finite)
1750
+ b_shape = b.shape
1751
+
1752
+ is_not_square = r.shape[0] != c.shape[0]
1753
+ if (enforce_square and is_not_square) or b.shape[0] != r.shape[0]:
1754
+ raise ValueError('Incompatible dimensions.')
1755
+
1756
+ is_cmplx = np.iscomplexobj(r) or np.iscomplexobj(c) or np.iscomplexobj(b)
1757
+ dtype = np.complex128 if is_cmplx else np.float64
1758
+ r, c, b = (np.asarray(i, dtype=dtype) for i in (r, c, b))
1759
+
1760
+ if b.ndim == 1 and not keep_b_shape:
1761
+ b = b.reshape(-1, 1)
1762
+ elif b.ndim != 1:
1763
+ b = b.reshape(b.shape[0], -1)
1764
+
1765
+ return r, c, b, dtype, b_shape
1766
+
1767
+
1768
+ def matmul_toeplitz(c_or_cr, x, check_finite=False, workers=None):
1769
+ """Efficient Toeplitz Matrix-Matrix Multiplication using FFT
1770
+
1771
+ This function returns the matrix multiplication between a Toeplitz
1772
+ matrix and a dense matrix.
1773
+
1774
+ The Toeplitz matrix has constant diagonals, with c as its first column
1775
+ and r as its first row. If r is not given, ``r == conjugate(c)`` is
1776
+ assumed.
1777
+
1778
+ Parameters
1779
+ ----------
1780
+ c_or_cr : array_like or tuple of (array_like, array_like)
1781
+ The vector ``c``, or a tuple of arrays (``c``, ``r``). Whatever the
1782
+ actual shape of ``c``, it will be converted to a 1-D array. If not
1783
+ supplied, ``r = conjugate(c)`` is assumed; in this case, if c[0] is
1784
+ real, the Toeplitz matrix is Hermitian. r[0] is ignored; the first row
1785
+ of the Toeplitz matrix is ``[c[0], r[1:]]``. Whatever the actual shape
1786
+ of ``r``, it will be converted to a 1-D array.
1787
+ x : (M,) or (M, K) array_like
1788
+ Matrix with which to multiply.
1789
+ check_finite : bool, optional
1790
+ Whether to check that the input matrices contain only finite numbers.
1791
+ Disabling may give a performance gain, but may result in problems
1792
+ (result entirely NaNs) if the inputs do contain infinities or NaNs.
1793
+ workers : int, optional
1794
+ To pass to scipy.fft.fft and ifft. Maximum number of workers to use
1795
+ for parallel computation. If negative, the value wraps around from
1796
+ ``os.cpu_count()``. See scipy.fft.fft for more details.
1797
+
1798
+ Returns
1799
+ -------
1800
+ T @ x : (M,) or (M, K) ndarray
1801
+ The result of the matrix multiplication ``T @ x``. Shape of return
1802
+ matches shape of `x`.
1803
+
1804
+ See Also
1805
+ --------
1806
+ toeplitz : Toeplitz matrix
1807
+ solve_toeplitz : Solve a Toeplitz system using Levinson Recursion
1808
+
1809
+ Notes
1810
+ -----
1811
+ The Toeplitz matrix is embedded in a circulant matrix and the FFT is used
1812
+ to efficiently calculate the matrix-matrix product.
1813
+
1814
+ Because the computation is based on the FFT, integer inputs will
1815
+ result in floating point outputs. This is unlike NumPy's `matmul`,
1816
+ which preserves the data type of the input.
1817
+
1818
+ This is partly based on the implementation that can be found in [1]_,
1819
+ licensed under the MIT license. More information about the method can be
1820
+ found in reference [2]_. References [3]_ and [4]_ have more reference
1821
+ implementations in Python.
1822
+
1823
+ .. versionadded:: 1.6.0
1824
+
1825
+ References
1826
+ ----------
1827
+ .. [1] Jacob R Gardner, Geoff Pleiss, David Bindel, Kilian
1828
+ Q Weinberger, Andrew Gordon Wilson, "GPyTorch: Blackbox Matrix-Matrix
1829
+ Gaussian Process Inference with GPU Acceleration" with contributions
1830
+ from Max Balandat and Ruihan Wu. Available online:
1831
+ https://github.com/cornellius-gp/gpytorch
1832
+
1833
+ .. [2] J. Demmel, P. Koev, and X. Li, "A Brief Survey of Direct Linear
1834
+ Solvers". In Z. Bai, J. Demmel, J. Dongarra, A. Ruhe, and H. van der
1835
+ Vorst, editors. Templates for the Solution of Algebraic Eigenvalue
1836
+ Problems: A Practical Guide. SIAM, Philadelphia, 2000. Available at:
1837
+ http://www.netlib.org/utk/people/JackDongarra/etemplates/node384.html
1838
+
1839
+ .. [3] R. Scheibler, E. Bezzam, I. Dokmanic, Pyroomacoustics: A Python
1840
+ package for audio room simulations and array processing algorithms,
1841
+ Proc. IEEE ICASSP, Calgary, CA, 2018.
1842
+ https://github.com/LCAV/pyroomacoustics/blob/pypi-release/
1843
+ pyroomacoustics/adaptive/util.py
1844
+
1845
+ .. [4] Marano S, Edwards B, Ferrari G and Fah D (2017), "Fitting
1846
+ Earthquake Spectra: Colored Noise and Incomplete Data", Bulletin of
1847
+ the Seismological Society of America., January, 2017. Vol. 107(1),
1848
+ pp. 276-291.
1849
+
1850
+ Examples
1851
+ --------
1852
+ Multiply the Toeplitz matrix T with matrix x::
1853
+
1854
+ [ 1 -1 -2 -3] [1 10]
1855
+ T = [ 3 1 -1 -2] x = [2 11]
1856
+ [ 6 3 1 -1] [2 11]
1857
+ [10 6 3 1] [5 19]
1858
+
1859
+ To specify the Toeplitz matrix, only the first column and the first
1860
+ row are needed.
1861
+
1862
+ >>> import numpy as np
1863
+ >>> c = np.array([1, 3, 6, 10]) # First column of T
1864
+ >>> r = np.array([1, -1, -2, -3]) # First row of T
1865
+ >>> x = np.array([[1, 10], [2, 11], [2, 11], [5, 19]])
1866
+
1867
+ >>> from scipy.linalg import toeplitz, matmul_toeplitz
1868
+ >>> matmul_toeplitz((c, r), x)
1869
+ array([[-20., -80.],
1870
+ [ -7., -8.],
1871
+ [ 9., 85.],
1872
+ [ 33., 218.]])
1873
+
1874
+ Check the result by creating the full Toeplitz matrix and
1875
+ multiplying it by ``x``.
1876
+
1877
+ >>> toeplitz(c, r) @ x
1878
+ array([[-20, -80],
1879
+ [ -7, -8],
1880
+ [ 9, 85],
1881
+ [ 33, 218]])
1882
+
1883
+ The full matrix is never formed explicitly, so this routine
1884
+ is suitable for very large Toeplitz matrices.
1885
+
1886
+ >>> n = 1000000
1887
+ >>> matmul_toeplitz([1] + [0]*(n-1), np.ones(n))
1888
+ array([1., 1., 1., ..., 1., 1., 1.])
1889
+
1890
+ """
1891
+
1892
+ from ..fft import fft, ifft, rfft, irfft
1893
+
1894
+ r, c, x, dtype, x_shape = _validate_args_for_toeplitz_ops(
1895
+ c_or_cr, x, check_finite, keep_b_shape=False, enforce_square=False)
1896
+ n, m = x.shape
1897
+
1898
+ T_nrows = len(c)
1899
+ T_ncols = len(r)
1900
+ p = T_nrows + T_ncols - 1 # equivalent to len(embedded_col)
1901
+
1902
+ embedded_col = np.concatenate((c, r[-1:0:-1]))
1903
+
1904
+ if np.iscomplexobj(embedded_col) or np.iscomplexobj(x):
1905
+ fft_mat = fft(embedded_col, axis=0, workers=workers).reshape(-1, 1)
1906
+ fft_x = fft(x, n=p, axis=0, workers=workers)
1907
+
1908
+ mat_times_x = ifft(fft_mat*fft_x, axis=0,
1909
+ workers=workers)[:T_nrows, :]
1910
+ else:
1911
+ # Real inputs; using rfft is faster
1912
+ fft_mat = rfft(embedded_col, axis=0, workers=workers).reshape(-1, 1)
1913
+ fft_x = rfft(x, n=p, axis=0, workers=workers)
1914
+
1915
+ mat_times_x = irfft(fft_mat*fft_x, axis=0,
1916
+ workers=workers, n=p)[:T_nrows, :]
1917
+
1918
+ return_shape = (T_nrows,) if len(x_shape) == 1 else (T_nrows, m)
1919
+ return mat_times_x.reshape(*return_shape)
astra_scene_test/Scene_04/.venv/lib/python3.9/site-packages/scipy/linalg/_blas_subroutines.h ADDED
@@ -0,0 +1,164 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /*
2
+ This file was generated by _generate_pyx.py.
3
+ Do not edit this file directly.
4
+ */
5
+
6
+ #include "fortran_defs.h"
7
+ #include "npy_cblas.h"
8
+
9
+ #ifdef __cplusplus
10
+ extern "C" {
11
+ #endif
12
+
13
+ void BLAS_FUNC(caxpy)(int *n, npy_complex64 *ca, npy_complex64 *cx, int *incx, npy_complex64 *cy, int *incy);
14
+ void BLAS_FUNC(ccopy)(int *n, npy_complex64 *cx, int *incx, npy_complex64 *cy, int *incy);
15
+ void (cdotcwrp_)(npy_complex64 *out, int *n, npy_complex64 *cx, int *incx, npy_complex64 *cy, int *incy);
16
+ void (cdotuwrp_)(npy_complex64 *out, int *n, npy_complex64 *cx, int *incx, npy_complex64 *cy, int *incy);
17
+ void BLAS_FUNC(cgbmv)(char *trans, int *m, int *n, int *kl, int *ku, npy_complex64 *alpha, npy_complex64 *a, int *lda, npy_complex64 *x, int *incx, npy_complex64 *beta, npy_complex64 *y, int *incy);
18
+ void BLAS_FUNC(cgemm)(char *transa, char *transb, int *m, int *n, int *k, npy_complex64 *alpha, npy_complex64 *a, int *lda, npy_complex64 *b, int *ldb, npy_complex64 *beta, npy_complex64 *c, int *ldc);
19
+ void BLAS_FUNC(cgemv)(char *trans, int *m, int *n, npy_complex64 *alpha, npy_complex64 *a, int *lda, npy_complex64 *x, int *incx, npy_complex64 *beta, npy_complex64 *y, int *incy);
20
+ void BLAS_FUNC(cgerc)(int *m, int *n, npy_complex64 *alpha, npy_complex64 *x, int *incx, npy_complex64 *y, int *incy, npy_complex64 *a, int *lda);
21
+ void BLAS_FUNC(cgeru)(int *m, int *n, npy_complex64 *alpha, npy_complex64 *x, int *incx, npy_complex64 *y, int *incy, npy_complex64 *a, int *lda);
22
+ void BLAS_FUNC(chbmv)(char *uplo, int *n, int *k, npy_complex64 *alpha, npy_complex64 *a, int *lda, npy_complex64 *x, int *incx, npy_complex64 *beta, npy_complex64 *y, int *incy);
23
+ void BLAS_FUNC(chemm)(char *side, char *uplo, int *m, int *n, npy_complex64 *alpha, npy_complex64 *a, int *lda, npy_complex64 *b, int *ldb, npy_complex64 *beta, npy_complex64 *c, int *ldc);
24
+ void BLAS_FUNC(chemv)(char *uplo, int *n, npy_complex64 *alpha, npy_complex64 *a, int *lda, npy_complex64 *x, int *incx, npy_complex64 *beta, npy_complex64 *y, int *incy);
25
+ void BLAS_FUNC(cher)(char *uplo, int *n, float *alpha, npy_complex64 *x, int *incx, npy_complex64 *a, int *lda);
26
+ void BLAS_FUNC(cher2)(char *uplo, int *n, npy_complex64 *alpha, npy_complex64 *x, int *incx, npy_complex64 *y, int *incy, npy_complex64 *a, int *lda);
27
+ void BLAS_FUNC(cher2k)(char *uplo, char *trans, int *n, int *k, npy_complex64 *alpha, npy_complex64 *a, int *lda, npy_complex64 *b, int *ldb, float *beta, npy_complex64 *c, int *ldc);
28
+ void BLAS_FUNC(cherk)(char *uplo, char *trans, int *n, int *k, float *alpha, npy_complex64 *a, int *lda, float *beta, npy_complex64 *c, int *ldc);
29
+ void BLAS_FUNC(chpmv)(char *uplo, int *n, npy_complex64 *alpha, npy_complex64 *ap, npy_complex64 *x, int *incx, npy_complex64 *beta, npy_complex64 *y, int *incy);
30
+ void BLAS_FUNC(chpr)(char *uplo, int *n, float *alpha, npy_complex64 *x, int *incx, npy_complex64 *ap);
31
+ void BLAS_FUNC(chpr2)(char *uplo, int *n, npy_complex64 *alpha, npy_complex64 *x, int *incx, npy_complex64 *y, int *incy, npy_complex64 *ap);
32
+ void BLAS_FUNC(crotg)(npy_complex64 *ca, npy_complex64 *cb, float *c, npy_complex64 *s);
33
+ void BLAS_FUNC(cscal)(int *n, npy_complex64 *ca, npy_complex64 *cx, int *incx);
34
+ void BLAS_FUNC(csrot)(int *n, npy_complex64 *cx, int *incx, npy_complex64 *cy, int *incy, float *c, float *s);
35
+ void BLAS_FUNC(csscal)(int *n, float *sa, npy_complex64 *cx, int *incx);
36
+ void BLAS_FUNC(cswap)(int *n, npy_complex64 *cx, int *incx, npy_complex64 *cy, int *incy);
37
+ void BLAS_FUNC(csymm)(char *side, char *uplo, int *m, int *n, npy_complex64 *alpha, npy_complex64 *a, int *lda, npy_complex64 *b, int *ldb, npy_complex64 *beta, npy_complex64 *c, int *ldc);
38
+ void BLAS_FUNC(csyr2k)(char *uplo, char *trans, int *n, int *k, npy_complex64 *alpha, npy_complex64 *a, int *lda, npy_complex64 *b, int *ldb, npy_complex64 *beta, npy_complex64 *c, int *ldc);
39
+ void BLAS_FUNC(csyrk)(char *uplo, char *trans, int *n, int *k, npy_complex64 *alpha, npy_complex64 *a, int *lda, npy_complex64 *beta, npy_complex64 *c, int *ldc);
40
+ void BLAS_FUNC(ctbmv)(char *uplo, char *trans, char *diag, int *n, int *k, npy_complex64 *a, int *lda, npy_complex64 *x, int *incx);
41
+ void BLAS_FUNC(ctbsv)(char *uplo, char *trans, char *diag, int *n, int *k, npy_complex64 *a, int *lda, npy_complex64 *x, int *incx);
42
+ void BLAS_FUNC(ctpmv)(char *uplo, char *trans, char *diag, int *n, npy_complex64 *ap, npy_complex64 *x, int *incx);
43
+ void BLAS_FUNC(ctpsv)(char *uplo, char *trans, char *diag, int *n, npy_complex64 *ap, npy_complex64 *x, int *incx);
44
+ void BLAS_FUNC(ctrmm)(char *side, char *uplo, char *transa, char *diag, int *m, int *n, npy_complex64 *alpha, npy_complex64 *a, int *lda, npy_complex64 *b, int *ldb);
45
+ void BLAS_FUNC(ctrmv)(char *uplo, char *trans, char *diag, int *n, npy_complex64 *a, int *lda, npy_complex64 *x, int *incx);
46
+ void BLAS_FUNC(ctrsm)(char *side, char *uplo, char *transa, char *diag, int *m, int *n, npy_complex64 *alpha, npy_complex64 *a, int *lda, npy_complex64 *b, int *ldb);
47
+ void BLAS_FUNC(ctrsv)(char *uplo, char *trans, char *diag, int *n, npy_complex64 *a, int *lda, npy_complex64 *x, int *incx);
48
+ double BLAS_FUNC(dasum)(int *n, double *dx, int *incx);
49
+ void BLAS_FUNC(daxpy)(int *n, double *da, double *dx, int *incx, double *dy, int *incy);
50
+ double BLAS_FUNC(dcabs1)(npy_complex128 *z);
51
+ void BLAS_FUNC(dcopy)(int *n, double *dx, int *incx, double *dy, int *incy);
52
+ double BLAS_FUNC(ddot)(int *n, double *dx, int *incx, double *dy, int *incy);
53
+ void BLAS_FUNC(dgbmv)(char *trans, int *m, int *n, int *kl, int *ku, double *alpha, double *a, int *lda, double *x, int *incx, double *beta, double *y, int *incy);
54
+ void BLAS_FUNC(dgemm)(char *transa, char *transb, int *m, int *n, int *k, double *alpha, double *a, int *lda, double *b, int *ldb, double *beta, double *c, int *ldc);
55
+ void BLAS_FUNC(dgemv)(char *trans, int *m, int *n, double *alpha, double *a, int *lda, double *x, int *incx, double *beta, double *y, int *incy);
56
+ void BLAS_FUNC(dger)(int *m, int *n, double *alpha, double *x, int *incx, double *y, int *incy, double *a, int *lda);
57
+ double BLAS_FUNC(dnrm2)(int *n, double *x, int *incx);
58
+ void BLAS_FUNC(drot)(int *n, double *dx, int *incx, double *dy, int *incy, double *c, double *s);
59
+ void BLAS_FUNC(drotg)(double *da, double *db, double *c, double *s);
60
+ void BLAS_FUNC(drotm)(int *n, double *dx, int *incx, double *dy, int *incy, double *dparam);
61
+ void BLAS_FUNC(drotmg)(double *dd1, double *dd2, double *dx1, double *dy1, double *dparam);
62
+ void BLAS_FUNC(dsbmv)(char *uplo, int *n, int *k, double *alpha, double *a, int *lda, double *x, int *incx, double *beta, double *y, int *incy);
63
+ void BLAS_FUNC(dscal)(int *n, double *da, double *dx, int *incx);
64
+ double BLAS_FUNC(dsdot)(int *n, float *sx, int *incx, float *sy, int *incy);
65
+ void BLAS_FUNC(dspmv)(char *uplo, int *n, double *alpha, double *ap, double *x, int *incx, double *beta, double *y, int *incy);
66
+ void BLAS_FUNC(dspr)(char *uplo, int *n, double *alpha, double *x, int *incx, double *ap);
67
+ void BLAS_FUNC(dspr2)(char *uplo, int *n, double *alpha, double *x, int *incx, double *y, int *incy, double *ap);
68
+ void BLAS_FUNC(dswap)(int *n, double *dx, int *incx, double *dy, int *incy);
69
+ void BLAS_FUNC(dsymm)(char *side, char *uplo, int *m, int *n, double *alpha, double *a, int *lda, double *b, int *ldb, double *beta, double *c, int *ldc);
70
+ void BLAS_FUNC(dsymv)(char *uplo, int *n, double *alpha, double *a, int *lda, double *x, int *incx, double *beta, double *y, int *incy);
71
+ void BLAS_FUNC(dsyr)(char *uplo, int *n, double *alpha, double *x, int *incx, double *a, int *lda);
72
+ void BLAS_FUNC(dsyr2)(char *uplo, int *n, double *alpha, double *x, int *incx, double *y, int *incy, double *a, int *lda);
73
+ void BLAS_FUNC(dsyr2k)(char *uplo, char *trans, int *n, int *k, double *alpha, double *a, int *lda, double *b, int *ldb, double *beta, double *c, int *ldc);
74
+ void BLAS_FUNC(dsyrk)(char *uplo, char *trans, int *n, int *k, double *alpha, double *a, int *lda, double *beta, double *c, int *ldc);
75
+ void BLAS_FUNC(dtbmv)(char *uplo, char *trans, char *diag, int *n, int *k, double *a, int *lda, double *x, int *incx);
76
+ void BLAS_FUNC(dtbsv)(char *uplo, char *trans, char *diag, int *n, int *k, double *a, int *lda, double *x, int *incx);
77
+ void BLAS_FUNC(dtpmv)(char *uplo, char *trans, char *diag, int *n, double *ap, double *x, int *incx);
78
+ void BLAS_FUNC(dtpsv)(char *uplo, char *trans, char *diag, int *n, double *ap, double *x, int *incx);
79
+ void BLAS_FUNC(dtrmm)(char *side, char *uplo, char *transa, char *diag, int *m, int *n, double *alpha, double *a, int *lda, double *b, int *ldb);
80
+ void BLAS_FUNC(dtrmv)(char *uplo, char *trans, char *diag, int *n, double *a, int *lda, double *x, int *incx);
81
+ void BLAS_FUNC(dtrsm)(char *side, char *uplo, char *transa, char *diag, int *m, int *n, double *alpha, double *a, int *lda, double *b, int *ldb);
82
+ void BLAS_FUNC(dtrsv)(char *uplo, char *trans, char *diag, int *n, double *a, int *lda, double *x, int *incx);
83
+ double BLAS_FUNC(dzasum)(int *n, npy_complex128 *zx, int *incx);
84
+ double BLAS_FUNC(dznrm2)(int *n, npy_complex128 *x, int *incx);
85
+ int BLAS_FUNC(icamax)(int *n, npy_complex64 *cx, int *incx);
86
+ int BLAS_FUNC(idamax)(int *n, double *dx, int *incx);
87
+ int BLAS_FUNC(isamax)(int *n, float *sx, int *incx);
88
+ int BLAS_FUNC(izamax)(int *n, npy_complex128 *zx, int *incx);
89
+ int BLAS_FUNC(lsame)(char *ca, char *cb);
90
+ float BLAS_FUNC(sasum)(int *n, float *sx, int *incx);
91
+ void BLAS_FUNC(saxpy)(int *n, float *sa, float *sx, int *incx, float *sy, int *incy);
92
+ float BLAS_FUNC(scasum)(int *n, npy_complex64 *cx, int *incx);
93
+ float BLAS_FUNC(scnrm2)(int *n, npy_complex64 *x, int *incx);
94
+ void BLAS_FUNC(scopy)(int *n, float *sx, int *incx, float *sy, int *incy);
95
+ float BLAS_FUNC(sdot)(int *n, float *sx, int *incx, float *sy, int *incy);
96
+ float BLAS_FUNC(sdsdot)(int *n, float *sb, float *sx, int *incx, float *sy, int *incy);
97
+ void BLAS_FUNC(sgbmv)(char *trans, int *m, int *n, int *kl, int *ku, float *alpha, float *a, int *lda, float *x, int *incx, float *beta, float *y, int *incy);
98
+ void BLAS_FUNC(sgemm)(char *transa, char *transb, int *m, int *n, int *k, float *alpha, float *a, int *lda, float *b, int *ldb, float *beta, float *c, int *ldc);
99
+ void BLAS_FUNC(sgemv)(char *trans, int *m, int *n, float *alpha, float *a, int *lda, float *x, int *incx, float *beta, float *y, int *incy);
100
+ void BLAS_FUNC(sger)(int *m, int *n, float *alpha, float *x, int *incx, float *y, int *incy, float *a, int *lda);
101
+ float BLAS_FUNC(snrm2)(int *n, float *x, int *incx);
102
+ void BLAS_FUNC(srot)(int *n, float *sx, int *incx, float *sy, int *incy, float *c, float *s);
103
+ void BLAS_FUNC(srotg)(float *sa, float *sb, float *c, float *s);
104
+ void BLAS_FUNC(srotm)(int *n, float *sx, int *incx, float *sy, int *incy, float *sparam);
105
+ void BLAS_FUNC(srotmg)(float *sd1, float *sd2, float *sx1, float *sy1, float *sparam);
106
+ void BLAS_FUNC(ssbmv)(char *uplo, int *n, int *k, float *alpha, float *a, int *lda, float *x, int *incx, float *beta, float *y, int *incy);
107
+ void BLAS_FUNC(sscal)(int *n, float *sa, float *sx, int *incx);
108
+ void BLAS_FUNC(sspmv)(char *uplo, int *n, float *alpha, float *ap, float *x, int *incx, float *beta, float *y, int *incy);
109
+ void BLAS_FUNC(sspr)(char *uplo, int *n, float *alpha, float *x, int *incx, float *ap);
110
+ void BLAS_FUNC(sspr2)(char *uplo, int *n, float *alpha, float *x, int *incx, float *y, int *incy, float *ap);
111
+ void BLAS_FUNC(sswap)(int *n, float *sx, int *incx, float *sy, int *incy);
112
+ void BLAS_FUNC(ssymm)(char *side, char *uplo, int *m, int *n, float *alpha, float *a, int *lda, float *b, int *ldb, float *beta, float *c, int *ldc);
113
+ void BLAS_FUNC(ssymv)(char *uplo, int *n, float *alpha, float *a, int *lda, float *x, int *incx, float *beta, float *y, int *incy);
114
+ void BLAS_FUNC(ssyr)(char *uplo, int *n, float *alpha, float *x, int *incx, float *a, int *lda);
115
+ void BLAS_FUNC(ssyr2)(char *uplo, int *n, float *alpha, float *x, int *incx, float *y, int *incy, float *a, int *lda);
116
+ void BLAS_FUNC(ssyr2k)(char *uplo, char *trans, int *n, int *k, float *alpha, float *a, int *lda, float *b, int *ldb, float *beta, float *c, int *ldc);
117
+ void BLAS_FUNC(ssyrk)(char *uplo, char *trans, int *n, int *k, float *alpha, float *a, int *lda, float *beta, float *c, int *ldc);
118
+ void BLAS_FUNC(stbmv)(char *uplo, char *trans, char *diag, int *n, int *k, float *a, int *lda, float *x, int *incx);
119
+ void BLAS_FUNC(stbsv)(char *uplo, char *trans, char *diag, int *n, int *k, float *a, int *lda, float *x, int *incx);
120
+ void BLAS_FUNC(stpmv)(char *uplo, char *trans, char *diag, int *n, float *ap, float *x, int *incx);
121
+ void BLAS_FUNC(stpsv)(char *uplo, char *trans, char *diag, int *n, float *ap, float *x, int *incx);
122
+ void BLAS_FUNC(strmm)(char *side, char *uplo, char *transa, char *diag, int *m, int *n, float *alpha, float *a, int *lda, float *b, int *ldb);
123
+ void BLAS_FUNC(strmv)(char *uplo, char *trans, char *diag, int *n, float *a, int *lda, float *x, int *incx);
124
+ void BLAS_FUNC(strsm)(char *side, char *uplo, char *transa, char *diag, int *m, int *n, float *alpha, float *a, int *lda, float *b, int *ldb);
125
+ void BLAS_FUNC(strsv)(char *uplo, char *trans, char *diag, int *n, float *a, int *lda, float *x, int *incx);
126
+ void BLAS_FUNC(zaxpy)(int *n, npy_complex128 *za, npy_complex128 *zx, int *incx, npy_complex128 *zy, int *incy);
127
+ void BLAS_FUNC(zcopy)(int *n, npy_complex128 *zx, int *incx, npy_complex128 *zy, int *incy);
128
+ void (zdotcwrp_)(npy_complex128 *out, int *n, npy_complex128 *zx, int *incx, npy_complex128 *zy, int *incy);
129
+ void (zdotuwrp_)(npy_complex128 *out, int *n, npy_complex128 *zx, int *incx, npy_complex128 *zy, int *incy);
130
+ void BLAS_FUNC(zdrot)(int *n, npy_complex128 *cx, int *incx, npy_complex128 *cy, int *incy, double *c, double *s);
131
+ void BLAS_FUNC(zdscal)(int *n, double *da, npy_complex128 *zx, int *incx);
132
+ void BLAS_FUNC(zgbmv)(char *trans, int *m, int *n, int *kl, int *ku, npy_complex128 *alpha, npy_complex128 *a, int *lda, npy_complex128 *x, int *incx, npy_complex128 *beta, npy_complex128 *y, int *incy);
133
+ void BLAS_FUNC(zgemm)(char *transa, char *transb, int *m, int *n, int *k, npy_complex128 *alpha, npy_complex128 *a, int *lda, npy_complex128 *b, int *ldb, npy_complex128 *beta, npy_complex128 *c, int *ldc);
134
+ void BLAS_FUNC(zgemv)(char *trans, int *m, int *n, npy_complex128 *alpha, npy_complex128 *a, int *lda, npy_complex128 *x, int *incx, npy_complex128 *beta, npy_complex128 *y, int *incy);
135
+ void BLAS_FUNC(zgerc)(int *m, int *n, npy_complex128 *alpha, npy_complex128 *x, int *incx, npy_complex128 *y, int *incy, npy_complex128 *a, int *lda);
136
+ void BLAS_FUNC(zgeru)(int *m, int *n, npy_complex128 *alpha, npy_complex128 *x, int *incx, npy_complex128 *y, int *incy, npy_complex128 *a, int *lda);
137
+ void BLAS_FUNC(zhbmv)(char *uplo, int *n, int *k, npy_complex128 *alpha, npy_complex128 *a, int *lda, npy_complex128 *x, int *incx, npy_complex128 *beta, npy_complex128 *y, int *incy);
138
+ void BLAS_FUNC(zhemm)(char *side, char *uplo, int *m, int *n, npy_complex128 *alpha, npy_complex128 *a, int *lda, npy_complex128 *b, int *ldb, npy_complex128 *beta, npy_complex128 *c, int *ldc);
139
+ void BLAS_FUNC(zhemv)(char *uplo, int *n, npy_complex128 *alpha, npy_complex128 *a, int *lda, npy_complex128 *x, int *incx, npy_complex128 *beta, npy_complex128 *y, int *incy);
140
+ void BLAS_FUNC(zher)(char *uplo, int *n, double *alpha, npy_complex128 *x, int *incx, npy_complex128 *a, int *lda);
141
+ void BLAS_FUNC(zher2)(char *uplo, int *n, npy_complex128 *alpha, npy_complex128 *x, int *incx, npy_complex128 *y, int *incy, npy_complex128 *a, int *lda);
142
+ void BLAS_FUNC(zher2k)(char *uplo, char *trans, int *n, int *k, npy_complex128 *alpha, npy_complex128 *a, int *lda, npy_complex128 *b, int *ldb, double *beta, npy_complex128 *c, int *ldc);
143
+ void BLAS_FUNC(zherk)(char *uplo, char *trans, int *n, int *k, double *alpha, npy_complex128 *a, int *lda, double *beta, npy_complex128 *c, int *ldc);
144
+ void BLAS_FUNC(zhpmv)(char *uplo, int *n, npy_complex128 *alpha, npy_complex128 *ap, npy_complex128 *x, int *incx, npy_complex128 *beta, npy_complex128 *y, int *incy);
145
+ void BLAS_FUNC(zhpr)(char *uplo, int *n, double *alpha, npy_complex128 *x, int *incx, npy_complex128 *ap);
146
+ void BLAS_FUNC(zhpr2)(char *uplo, int *n, npy_complex128 *alpha, npy_complex128 *x, int *incx, npy_complex128 *y, int *incy, npy_complex128 *ap);
147
+ void BLAS_FUNC(zrotg)(npy_complex128 *ca, npy_complex128 *cb, double *c, npy_complex128 *s);
148
+ void BLAS_FUNC(zscal)(int *n, npy_complex128 *za, npy_complex128 *zx, int *incx);
149
+ void BLAS_FUNC(zswap)(int *n, npy_complex128 *zx, int *incx, npy_complex128 *zy, int *incy);
150
+ void BLAS_FUNC(zsymm)(char *side, char *uplo, int *m, int *n, npy_complex128 *alpha, npy_complex128 *a, int *lda, npy_complex128 *b, int *ldb, npy_complex128 *beta, npy_complex128 *c, int *ldc);
151
+ void BLAS_FUNC(zsyr2k)(char *uplo, char *trans, int *n, int *k, npy_complex128 *alpha, npy_complex128 *a, int *lda, npy_complex128 *b, int *ldb, npy_complex128 *beta, npy_complex128 *c, int *ldc);
152
+ void BLAS_FUNC(zsyrk)(char *uplo, char *trans, int *n, int *k, npy_complex128 *alpha, npy_complex128 *a, int *lda, npy_complex128 *beta, npy_complex128 *c, int *ldc);
153
+ void BLAS_FUNC(ztbmv)(char *uplo, char *trans, char *diag, int *n, int *k, npy_complex128 *a, int *lda, npy_complex128 *x, int *incx);
154
+ void BLAS_FUNC(ztbsv)(char *uplo, char *trans, char *diag, int *n, int *k, npy_complex128 *a, int *lda, npy_complex128 *x, int *incx);
155
+ void BLAS_FUNC(ztpmv)(char *uplo, char *trans, char *diag, int *n, npy_complex128 *ap, npy_complex128 *x, int *incx);
156
+ void BLAS_FUNC(ztpsv)(char *uplo, char *trans, char *diag, int *n, npy_complex128 *ap, npy_complex128 *x, int *incx);
157
+ void BLAS_FUNC(ztrmm)(char *side, char *uplo, char *transa, char *diag, int *m, int *n, npy_complex128 *alpha, npy_complex128 *a, int *lda, npy_complex128 *b, int *ldb);
158
+ void BLAS_FUNC(ztrmv)(char *uplo, char *trans, char *diag, int *n, npy_complex128 *a, int *lda, npy_complex128 *x, int *incx);
159
+ void BLAS_FUNC(ztrsm)(char *side, char *uplo, char *transa, char *diag, int *m, int *n, npy_complex128 *alpha, npy_complex128 *a, int *lda, npy_complex128 *b, int *ldb);
160
+ void BLAS_FUNC(ztrsv)(char *uplo, char *trans, char *diag, int *n, npy_complex128 *a, int *lda, npy_complex128 *x, int *incx);
161
+
162
+ #ifdef __cplusplus
163
+ }
164
+ #endif
astra_scene_test/Scene_04/.venv/lib/python3.9/site-packages/scipy/linalg/_cythonized_array_utils.pxd ADDED
@@ -0,0 +1,40 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ cimport numpy as cnp
2
+
3
+ ctypedef fused lapack_t:
4
+ float
5
+ double
6
+ (float complex)
7
+ (double complex)
8
+
9
+ ctypedef fused lapack_cz_t:
10
+ (float complex)
11
+ (double complex)
12
+
13
+ ctypedef fused lapack_sd_t:
14
+ float
15
+ double
16
+
17
+ ctypedef fused np_numeric_t:
18
+ cnp.int8_t
19
+ cnp.int16_t
20
+ cnp.int32_t
21
+ cnp.int64_t
22
+ cnp.uint8_t
23
+ cnp.uint16_t
24
+ cnp.uint32_t
25
+ cnp.uint64_t
26
+ cnp.float32_t
27
+ cnp.float64_t
28
+ cnp.longdouble_t
29
+ cnp.complex64_t
30
+ cnp.complex128_t
31
+
32
+ ctypedef fused np_complex_numeric_t:
33
+ cnp.complex64_t
34
+ cnp.complex128_t
35
+
36
+
37
+ cdef void swap_c_and_f_layout(lapack_t *a, lapack_t *b, int r, int c) noexcept nogil
38
+ cdef (int, int) band_check_internal_c(np_numeric_t[:, ::1]A) noexcept nogil
39
+ cdef bint is_sym_her_real_c_internal(np_numeric_t[:, ::1]A) noexcept nogil
40
+ cdef bint is_sym_her_complex_c_internal(np_complex_numeric_t[:, ::1]A) noexcept nogil
astra_scene_test/Scene_04/.venv/lib/python3.9/site-packages/scipy/linalg/_cythonized_array_utils.pyi ADDED
@@ -0,0 +1,16 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from numpy.typing import NDArray
2
+ from typing import Any
3
+
4
+ def bandwidth(a: NDArray[Any]) -> tuple[int, int]: ...
5
+
6
+ def issymmetric(
7
+ a: NDArray[Any],
8
+ atol: None | float = ...,
9
+ rtol: None | float = ...,
10
+ ) -> bool: ...
11
+
12
+ def ishermitian(
13
+ a: NDArray[Any],
14
+ atol: None | float = ...,
15
+ rtol: None | float = ...,
16
+ ) -> bool: ...
astra_scene_test/Scene_04/.venv/lib/python3.9/site-packages/scipy/linalg/_decomp.py ADDED
@@ -0,0 +1,1621 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #
2
+ # Author: Pearu Peterson, March 2002
3
+ #
4
+ # additions by Travis Oliphant, March 2002
5
+ # additions by Eric Jones, June 2002
6
+ # additions by Johannes Loehnert, June 2006
7
+ # additions by Bart Vandereycken, June 2006
8
+ # additions by Andrew D Straw, May 2007
9
+ # additions by Tiziano Zito, November 2008
10
+ #
11
+ # April 2010: Functions for LU, QR, SVD, Schur, and Cholesky decompositions
12
+ # were moved to their own files. Still in this file are functions for
13
+ # eigenstuff and for the Hessenberg form.
14
+
15
+ __all__ = ['eig', 'eigvals', 'eigh', 'eigvalsh',
16
+ 'eig_banded', 'eigvals_banded',
17
+ 'eigh_tridiagonal', 'eigvalsh_tridiagonal', 'hessenberg', 'cdf2rdf']
18
+
19
+ import warnings
20
+
21
+ import numpy
22
+ from numpy import (array, isfinite, inexact, nonzero, iscomplexobj,
23
+ flatnonzero, conj, asarray, argsort, empty,
24
+ iscomplex, zeros, einsum, eye, inf)
25
+ # Local imports
26
+ from scipy._lib._util import _asarray_validated
27
+ from ._misc import LinAlgError, _datacopied, norm
28
+ from .lapack import get_lapack_funcs, _compute_lwork
29
+ from scipy._lib.deprecation import _NoValue, _deprecate_positional_args
30
+
31
+
32
+ _I = numpy.array(1j, dtype='F')
33
+
34
+
35
+ def _make_complex_eigvecs(w, vin, dtype):
36
+ """
37
+ Produce complex-valued eigenvectors from LAPACK DGGEV real-valued output
38
+ """
39
+ # - see LAPACK man page DGGEV at ALPHAI
40
+ v = numpy.array(vin, dtype=dtype)
41
+ m = (w.imag > 0)
42
+ m[:-1] |= (w.imag[1:] < 0) # workaround for LAPACK bug, cf. ticket #709
43
+ for i in flatnonzero(m):
44
+ v.imag[:, i] = vin[:, i+1]
45
+ conj(v[:, i], v[:, i+1])
46
+ return v
47
+
48
+
49
+ def _make_eigvals(alpha, beta, homogeneous_eigvals):
50
+ if homogeneous_eigvals:
51
+ if beta is None:
52
+ return numpy.vstack((alpha, numpy.ones_like(alpha)))
53
+ else:
54
+ return numpy.vstack((alpha, beta))
55
+ else:
56
+ if beta is None:
57
+ return alpha
58
+ else:
59
+ w = numpy.empty_like(alpha)
60
+ alpha_zero = (alpha == 0)
61
+ beta_zero = (beta == 0)
62
+ beta_nonzero = ~beta_zero
63
+ w[beta_nonzero] = alpha[beta_nonzero]/beta[beta_nonzero]
64
+ # Use numpy.inf for complex values too since
65
+ # 1/numpy.inf = 0, i.e., it correctly behaves as projective
66
+ # infinity.
67
+ w[~alpha_zero & beta_zero] = numpy.inf
68
+ if numpy.all(alpha.imag == 0):
69
+ w[alpha_zero & beta_zero] = numpy.nan
70
+ else:
71
+ w[alpha_zero & beta_zero] = complex(numpy.nan, numpy.nan)
72
+ return w
73
+
74
+
75
+ def _geneig(a1, b1, left, right, overwrite_a, overwrite_b,
76
+ homogeneous_eigvals):
77
+ ggev, = get_lapack_funcs(('ggev',), (a1, b1))
78
+ cvl, cvr = left, right
79
+ res = ggev(a1, b1, lwork=-1)
80
+ lwork = res[-2][0].real.astype(numpy.int_)
81
+ if ggev.typecode in 'cz':
82
+ alpha, beta, vl, vr, work, info = ggev(a1, b1, cvl, cvr, lwork,
83
+ overwrite_a, overwrite_b)
84
+ w = _make_eigvals(alpha, beta, homogeneous_eigvals)
85
+ else:
86
+ alphar, alphai, beta, vl, vr, work, info = ggev(a1, b1, cvl, cvr,
87
+ lwork, overwrite_a,
88
+ overwrite_b)
89
+ alpha = alphar + _I * alphai
90
+ w = _make_eigvals(alpha, beta, homogeneous_eigvals)
91
+ _check_info(info, 'generalized eig algorithm (ggev)')
92
+
93
+ only_real = numpy.all(w.imag == 0.0)
94
+ if not (ggev.typecode in 'cz' or only_real):
95
+ t = w.dtype.char
96
+ if left:
97
+ vl = _make_complex_eigvecs(w, vl, t)
98
+ if right:
99
+ vr = _make_complex_eigvecs(w, vr, t)
100
+
101
+ # the eigenvectors returned by the lapack function are NOT normalized
102
+ for i in range(vr.shape[0]):
103
+ if right:
104
+ vr[:, i] /= norm(vr[:, i])
105
+ if left:
106
+ vl[:, i] /= norm(vl[:, i])
107
+
108
+ if not (left or right):
109
+ return w
110
+ if left:
111
+ if right:
112
+ return w, vl, vr
113
+ return w, vl
114
+ return w, vr
115
+
116
+
117
+ def eig(a, b=None, left=False, right=True, overwrite_a=False,
118
+ overwrite_b=False, check_finite=True, homogeneous_eigvals=False):
119
+ """
120
+ Solve an ordinary or generalized eigenvalue problem of a square matrix.
121
+
122
+ Find eigenvalues w and right or left eigenvectors of a general matrix::
123
+
124
+ a vr[:,i] = w[i] b vr[:,i]
125
+ a.H vl[:,i] = w[i].conj() b.H vl[:,i]
126
+
127
+ where ``.H`` is the Hermitian conjugation.
128
+
129
+ Parameters
130
+ ----------
131
+ a : (M, M) array_like
132
+ A complex or real matrix whose eigenvalues and eigenvectors
133
+ will be computed.
134
+ b : (M, M) array_like, optional
135
+ Right-hand side matrix in a generalized eigenvalue problem.
136
+ Default is None, identity matrix is assumed.
137
+ left : bool, optional
138
+ Whether to calculate and return left eigenvectors. Default is False.
139
+ right : bool, optional
140
+ Whether to calculate and return right eigenvectors. Default is True.
141
+ overwrite_a : bool, optional
142
+ Whether to overwrite `a`; may improve performance. Default is False.
143
+ overwrite_b : bool, optional
144
+ Whether to overwrite `b`; may improve performance. Default is False.
145
+ check_finite : bool, optional
146
+ Whether to check that the input matrices contain only finite numbers.
147
+ Disabling may give a performance gain, but may result in problems
148
+ (crashes, non-termination) if the inputs do contain infinities or NaNs.
149
+ homogeneous_eigvals : bool, optional
150
+ If True, return the eigenvalues in homogeneous coordinates.
151
+ In this case ``w`` is a (2, M) array so that::
152
+
153
+ w[1,i] a vr[:,i] = w[0,i] b vr[:,i]
154
+
155
+ Default is False.
156
+
157
+ Returns
158
+ -------
159
+ w : (M,) or (2, M) double or complex ndarray
160
+ The eigenvalues, each repeated according to its
161
+ multiplicity. The shape is (M,) unless
162
+ ``homogeneous_eigvals=True``.
163
+ vl : (M, M) double or complex ndarray
164
+ The left eigenvector corresponding to the eigenvalue
165
+ ``w[i]`` is the column ``vl[:,i]``. Only returned if ``left=True``.
166
+ The left eigenvector is not normalized.
167
+ vr : (M, M) double or complex ndarray
168
+ The normalized right eigenvector corresponding to the eigenvalue
169
+ ``w[i]`` is the column ``vr[:,i]``. Only returned if ``right=True``.
170
+
171
+ Raises
172
+ ------
173
+ LinAlgError
174
+ If eigenvalue computation does not converge.
175
+
176
+ See Also
177
+ --------
178
+ eigvals : eigenvalues of general arrays
179
+ eigh : Eigenvalues and right eigenvectors for symmetric/Hermitian arrays.
180
+ eig_banded : eigenvalues and right eigenvectors for symmetric/Hermitian
181
+ band matrices
182
+ eigh_tridiagonal : eigenvalues and right eiegenvectors for
183
+ symmetric/Hermitian tridiagonal matrices
184
+
185
+ Examples
186
+ --------
187
+ >>> import numpy as np
188
+ >>> from scipy import linalg
189
+ >>> a = np.array([[0., -1.], [1., 0.]])
190
+ >>> linalg.eigvals(a)
191
+ array([0.+1.j, 0.-1.j])
192
+
193
+ >>> b = np.array([[0., 1.], [1., 1.]])
194
+ >>> linalg.eigvals(a, b)
195
+ array([ 1.+0.j, -1.+0.j])
196
+
197
+ >>> a = np.array([[3., 0., 0.], [0., 8., 0.], [0., 0., 7.]])
198
+ >>> linalg.eigvals(a, homogeneous_eigvals=True)
199
+ array([[3.+0.j, 8.+0.j, 7.+0.j],
200
+ [1.+0.j, 1.+0.j, 1.+0.j]])
201
+
202
+ >>> a = np.array([[0., -1.], [1., 0.]])
203
+ >>> linalg.eigvals(a) == linalg.eig(a)[0]
204
+ array([ True, True])
205
+ >>> linalg.eig(a, left=True, right=False)[1] # normalized left eigenvector
206
+ array([[-0.70710678+0.j , -0.70710678-0.j ],
207
+ [-0. +0.70710678j, -0. -0.70710678j]])
208
+ >>> linalg.eig(a, left=False, right=True)[1] # normalized right eigenvector
209
+ array([[0.70710678+0.j , 0.70710678-0.j ],
210
+ [0. -0.70710678j, 0. +0.70710678j]])
211
+
212
+
213
+
214
+ """
215
+ a1 = _asarray_validated(a, check_finite=check_finite)
216
+ if len(a1.shape) != 2 or a1.shape[0] != a1.shape[1]:
217
+ raise ValueError('expected square matrix')
218
+ overwrite_a = overwrite_a or (_datacopied(a1, a))
219
+ if b is not None:
220
+ b1 = _asarray_validated(b, check_finite=check_finite)
221
+ overwrite_b = overwrite_b or _datacopied(b1, b)
222
+ if len(b1.shape) != 2 or b1.shape[0] != b1.shape[1]:
223
+ raise ValueError('expected square matrix')
224
+ if b1.shape != a1.shape:
225
+ raise ValueError('a and b must have the same shape')
226
+ return _geneig(a1, b1, left, right, overwrite_a, overwrite_b,
227
+ homogeneous_eigvals)
228
+
229
+ geev, geev_lwork = get_lapack_funcs(('geev', 'geev_lwork'), (a1,))
230
+ compute_vl, compute_vr = left, right
231
+
232
+ lwork = _compute_lwork(geev_lwork, a1.shape[0],
233
+ compute_vl=compute_vl,
234
+ compute_vr=compute_vr)
235
+
236
+ if geev.typecode in 'cz':
237
+ w, vl, vr, info = geev(a1, lwork=lwork,
238
+ compute_vl=compute_vl,
239
+ compute_vr=compute_vr,
240
+ overwrite_a=overwrite_a)
241
+ w = _make_eigvals(w, None, homogeneous_eigvals)
242
+ else:
243
+ wr, wi, vl, vr, info = geev(a1, lwork=lwork,
244
+ compute_vl=compute_vl,
245
+ compute_vr=compute_vr,
246
+ overwrite_a=overwrite_a)
247
+ t = {'f': 'F', 'd': 'D'}[wr.dtype.char]
248
+ w = wr + _I * wi
249
+ w = _make_eigvals(w, None, homogeneous_eigvals)
250
+
251
+ _check_info(info, 'eig algorithm (geev)',
252
+ positive='did not converge (only eigenvalues '
253
+ 'with order >= %d have converged)')
254
+
255
+ only_real = numpy.all(w.imag == 0.0)
256
+ if not (geev.typecode in 'cz' or only_real):
257
+ t = w.dtype.char
258
+ if left:
259
+ vl = _make_complex_eigvecs(w, vl, t)
260
+ if right:
261
+ vr = _make_complex_eigvecs(w, vr, t)
262
+ if not (left or right):
263
+ return w
264
+ if left:
265
+ if right:
266
+ return w, vl, vr
267
+ return w, vl
268
+ return w, vr
269
+
270
+
271
+ @_deprecate_positional_args(version="1.14.0")
272
+ def eigh(a, b=None, *, lower=True, eigvals_only=False, overwrite_a=False,
273
+ overwrite_b=False, turbo=_NoValue, eigvals=_NoValue, type=1,
274
+ check_finite=True, subset_by_index=None, subset_by_value=None,
275
+ driver=None):
276
+ """
277
+ Solve a standard or generalized eigenvalue problem for a complex
278
+ Hermitian or real symmetric matrix.
279
+
280
+ Find eigenvalues array ``w`` and optionally eigenvectors array ``v`` of
281
+ array ``a``, where ``b`` is positive definite such that for every
282
+ eigenvalue λ (i-th entry of w) and its eigenvector ``vi`` (i-th column of
283
+ ``v``) satisfies::
284
+
285
+ a @ vi = λ * b @ vi
286
+ vi.conj().T @ a @ vi = λ
287
+ vi.conj().T @ b @ vi = 1
288
+
289
+ In the standard problem, ``b`` is assumed to be the identity matrix.
290
+
291
+ Parameters
292
+ ----------
293
+ a : (M, M) array_like
294
+ A complex Hermitian or real symmetric matrix whose eigenvalues and
295
+ eigenvectors will be computed.
296
+ b : (M, M) array_like, optional
297
+ A complex Hermitian or real symmetric definite positive matrix in.
298
+ If omitted, identity matrix is assumed.
299
+ lower : bool, optional
300
+ Whether the pertinent array data is taken from the lower or upper
301
+ triangle of ``a`` and, if applicable, ``b``. (Default: lower)
302
+ eigvals_only : bool, optional
303
+ Whether to calculate only eigenvalues and no eigenvectors.
304
+ (Default: both are calculated)
305
+ subset_by_index : iterable, optional
306
+ If provided, this two-element iterable defines the start and the end
307
+ indices of the desired eigenvalues (ascending order and 0-indexed).
308
+ To return only the second smallest to fifth smallest eigenvalues,
309
+ ``[1, 4]`` is used. ``[n-3, n-1]`` returns the largest three. Only
310
+ available with "evr", "evx", and "gvx" drivers. The entries are
311
+ directly converted to integers via ``int()``.
312
+ subset_by_value : iterable, optional
313
+ If provided, this two-element iterable defines the half-open interval
314
+ ``(a, b]`` that, if any, only the eigenvalues between these values
315
+ are returned. Only available with "evr", "evx", and "gvx" drivers. Use
316
+ ``np.inf`` for the unconstrained ends.
317
+ driver : str, optional
318
+ Defines which LAPACK driver should be used. Valid options are "ev",
319
+ "evd", "evr", "evx" for standard problems and "gv", "gvd", "gvx" for
320
+ generalized (where b is not None) problems. See the Notes section.
321
+ The default for standard problems is "evr". For generalized problems,
322
+ "gvd" is used for full set, and "gvx" for subset requested cases.
323
+ type : int, optional
324
+ For the generalized problems, this keyword specifies the problem type
325
+ to be solved for ``w`` and ``v`` (only takes 1, 2, 3 as possible
326
+ inputs)::
327
+
328
+ 1 => a @ v = w @ b @ v
329
+ 2 => a @ b @ v = w @ v
330
+ 3 => b @ a @ v = w @ v
331
+
332
+ This keyword is ignored for standard problems.
333
+ overwrite_a : bool, optional
334
+ Whether to overwrite data in ``a`` (may improve performance). Default
335
+ is False.
336
+ overwrite_b : bool, optional
337
+ Whether to overwrite data in ``b`` (may improve performance). Default
338
+ is False.
339
+ check_finite : bool, optional
340
+ Whether to check that the input matrices contain only finite numbers.
341
+ Disabling may give a performance gain, but may result in problems
342
+ (crashes, non-termination) if the inputs do contain infinities or NaNs.
343
+ turbo : bool, optional, deprecated
344
+ .. deprecated:: 1.5.0
345
+ `eigh` keyword argument `turbo` is deprecated in favour of
346
+ ``driver=gvd`` keyword instead and will be removed in SciPy
347
+ 1.14.0.
348
+ eigvals : tuple (lo, hi), optional, deprecated
349
+ .. deprecated:: 1.5.0
350
+ `eigh` keyword argument `eigvals` is deprecated in favour of
351
+ `subset_by_index` keyword instead and will be removed in SciPy
352
+ 1.14.0.
353
+
354
+ Returns
355
+ -------
356
+ w : (N,) ndarray
357
+ The N (N<=M) selected eigenvalues, in ascending order, each
358
+ repeated according to its multiplicity.
359
+ v : (M, N) ndarray
360
+ The normalized eigenvector corresponding to the eigenvalue ``w[i]`` is
361
+ the column ``v[:,i]``. Only returned if ``eigvals_only=False``.
362
+
363
+ Raises
364
+ ------
365
+ LinAlgError
366
+ If eigenvalue computation does not converge, an error occurred, or
367
+ b matrix is not definite positive. Note that if input matrices are
368
+ not symmetric or Hermitian, no error will be reported but results will
369
+ be wrong.
370
+
371
+ See Also
372
+ --------
373
+ eigvalsh : eigenvalues of symmetric or Hermitian arrays
374
+ eig : eigenvalues and right eigenvectors for non-symmetric arrays
375
+ eigh_tridiagonal : eigenvalues and right eiegenvectors for
376
+ symmetric/Hermitian tridiagonal matrices
377
+
378
+ Notes
379
+ -----
380
+ This function does not check the input array for being Hermitian/symmetric
381
+ in order to allow for representing arrays with only their upper/lower
382
+ triangular parts. Also, note that even though not taken into account,
383
+ finiteness check applies to the whole array and unaffected by "lower"
384
+ keyword.
385
+
386
+ This function uses LAPACK drivers for computations in all possible keyword
387
+ combinations, prefixed with ``sy`` if arrays are real and ``he`` if
388
+ complex, e.g., a float array with "evr" driver is solved via
389
+ "syevr", complex arrays with "gvx" driver problem is solved via "hegvx"
390
+ etc.
391
+
392
+ As a brief summary, the slowest and the most robust driver is the
393
+ classical ``<sy/he>ev`` which uses symmetric QR. ``<sy/he>evr`` is seen as
394
+ the optimal choice for the most general cases. However, there are certain
395
+ occasions that ``<sy/he>evd`` computes faster at the expense of more
396
+ memory usage. ``<sy/he>evx``, while still being faster than ``<sy/he>ev``,
397
+ often performs worse than the rest except when very few eigenvalues are
398
+ requested for large arrays though there is still no performance guarantee.
399
+
400
+
401
+ For the generalized problem, normalization with respect to the given
402
+ type argument::
403
+
404
+ type 1 and 3 : v.conj().T @ a @ v = w
405
+ type 2 : inv(v).conj().T @ a @ inv(v) = w
406
+
407
+ type 1 or 2 : v.conj().T @ b @ v = I
408
+ type 3 : v.conj().T @ inv(b) @ v = I
409
+
410
+
411
+ Examples
412
+ --------
413
+ >>> import numpy as np
414
+ >>> from scipy.linalg import eigh
415
+ >>> A = np.array([[6, 3, 1, 5], [3, 0, 5, 1], [1, 5, 6, 2], [5, 1, 2, 2]])
416
+ >>> w, v = eigh(A)
417
+ >>> np.allclose(A @ v - v @ np.diag(w), np.zeros((4, 4)))
418
+ True
419
+
420
+ Request only the eigenvalues
421
+
422
+ >>> w = eigh(A, eigvals_only=True)
423
+
424
+ Request eigenvalues that are less than 10.
425
+
426
+ >>> A = np.array([[34, -4, -10, -7, 2],
427
+ ... [-4, 7, 2, 12, 0],
428
+ ... [-10, 2, 44, 2, -19],
429
+ ... [-7, 12, 2, 79, -34],
430
+ ... [2, 0, -19, -34, 29]])
431
+ >>> eigh(A, eigvals_only=True, subset_by_value=[-np.inf, 10])
432
+ array([6.69199443e-07, 9.11938152e+00])
433
+
434
+ Request the second smallest eigenvalue and its eigenvector
435
+
436
+ >>> w, v = eigh(A, subset_by_index=[1, 1])
437
+ >>> w
438
+ array([9.11938152])
439
+ >>> v.shape # only a single column is returned
440
+ (5, 1)
441
+
442
+ """
443
+ if turbo is not _NoValue:
444
+ warnings.warn("Keyword argument 'turbo' is deprecated in favour of '"
445
+ "driver=gvd' keyword instead and will be removed in "
446
+ "SciPy 1.14.0.",
447
+ DeprecationWarning, stacklevel=2)
448
+ if eigvals is not _NoValue:
449
+ warnings.warn("Keyword argument 'eigvals' is deprecated in favour of "
450
+ "'subset_by_index' keyword instead and will be removed "
451
+ "in SciPy 1.14.0.",
452
+ DeprecationWarning, stacklevel=2)
453
+
454
+ # set lower
455
+ uplo = 'L' if lower else 'U'
456
+ # Set job for Fortran routines
457
+ _job = 'N' if eigvals_only else 'V'
458
+
459
+ drv_str = [None, "ev", "evd", "evr", "evx", "gv", "gvd", "gvx"]
460
+ if driver not in drv_str:
461
+ raise ValueError('"{}" is unknown. Possible values are "None", "{}".'
462
+ ''.format(driver, '", "'.join(drv_str[1:])))
463
+
464
+ a1 = _asarray_validated(a, check_finite=check_finite)
465
+ if len(a1.shape) != 2 or a1.shape[0] != a1.shape[1]:
466
+ raise ValueError('expected square "a" matrix')
467
+ overwrite_a = overwrite_a or (_datacopied(a1, a))
468
+ cplx = True if iscomplexobj(a1) else False
469
+ n = a1.shape[0]
470
+ drv_args = {'overwrite_a': overwrite_a}
471
+
472
+ if b is not None:
473
+ b1 = _asarray_validated(b, check_finite=check_finite)
474
+ overwrite_b = overwrite_b or _datacopied(b1, b)
475
+ if len(b1.shape) != 2 or b1.shape[0] != b1.shape[1]:
476
+ raise ValueError('expected square "b" matrix')
477
+
478
+ if b1.shape != a1.shape:
479
+ raise ValueError(f"wrong b dimensions {b1.shape}, should be {a1.shape}")
480
+
481
+ if type not in [1, 2, 3]:
482
+ raise ValueError('"type" keyword only accepts 1, 2, and 3.')
483
+
484
+ cplx = True if iscomplexobj(b1) else (cplx or False)
485
+ drv_args.update({'overwrite_b': overwrite_b, 'itype': type})
486
+
487
+ # backwards-compatibility handling
488
+ subset_by_index = subset_by_index if (eigvals in (None, _NoValue)) else eigvals
489
+
490
+ subset = (subset_by_index is not None) or (subset_by_value is not None)
491
+
492
+ # Both subsets can't be given
493
+ if subset_by_index and subset_by_value:
494
+ raise ValueError('Either index or value subset can be requested.')
495
+
496
+ # Take turbo into account if all conditions are met otherwise ignore
497
+ if turbo not in (None, _NoValue) and b is not None:
498
+ driver = 'gvx' if subset else 'gvd'
499
+
500
+ # Check indices if given
501
+ if subset_by_index:
502
+ lo, hi = (int(x) for x in subset_by_index)
503
+ if not (0 <= lo <= hi < n):
504
+ raise ValueError('Requested eigenvalue indices are not valid. '
505
+ f'Valid range is [0, {n-1}] and start <= end, but '
506
+ f'start={lo}, end={hi} is given')
507
+ # fortran is 1-indexed
508
+ drv_args.update({'range': 'I', 'il': lo + 1, 'iu': hi + 1})
509
+
510
+ if subset_by_value:
511
+ lo, hi = subset_by_value
512
+ if not (-inf <= lo < hi <= inf):
513
+ raise ValueError('Requested eigenvalue bounds are not valid. '
514
+ 'Valid range is (-inf, inf) and low < high, but '
515
+ f'low={lo}, high={hi} is given')
516
+
517
+ drv_args.update({'range': 'V', 'vl': lo, 'vu': hi})
518
+
519
+ # fix prefix for lapack routines
520
+ pfx = 'he' if cplx else 'sy'
521
+
522
+ # decide on the driver if not given
523
+ # first early exit on incompatible choice
524
+ if driver:
525
+ if b is None and (driver in ["gv", "gvd", "gvx"]):
526
+ raise ValueError(f'{driver} requires input b array to be supplied '
527
+ 'for generalized eigenvalue problems.')
528
+ if (b is not None) and (driver in ['ev', 'evd', 'evr', 'evx']):
529
+ raise ValueError(f'"{driver}" does not accept input b array '
530
+ 'for standard eigenvalue problems.')
531
+ if subset and (driver in ["ev", "evd", "gv", "gvd"]):
532
+ raise ValueError(f'"{driver}" cannot compute subsets of eigenvalues')
533
+
534
+ # Default driver is evr and gvd
535
+ else:
536
+ driver = "evr" if b is None else ("gvx" if subset else "gvd")
537
+
538
+ lwork_spec = {
539
+ 'syevd': ['lwork', 'liwork'],
540
+ 'syevr': ['lwork', 'liwork'],
541
+ 'heevd': ['lwork', 'liwork', 'lrwork'],
542
+ 'heevr': ['lwork', 'lrwork', 'liwork'],
543
+ }
544
+
545
+ if b is None: # Standard problem
546
+ drv, drvlw = get_lapack_funcs((pfx + driver, pfx+driver+'_lwork'),
547
+ [a1])
548
+ clw_args = {'n': n, 'lower': lower}
549
+ if driver == 'evd':
550
+ clw_args.update({'compute_v': 0 if _job == "N" else 1})
551
+
552
+ lw = _compute_lwork(drvlw, **clw_args)
553
+ # Multiple lwork vars
554
+ if isinstance(lw, tuple):
555
+ lwork_args = dict(zip(lwork_spec[pfx+driver], lw))
556
+ else:
557
+ lwork_args = {'lwork': lw}
558
+
559
+ drv_args.update({'lower': lower, 'compute_v': 0 if _job == "N" else 1})
560
+ w, v, *other_args, info = drv(a=a1, **drv_args, **lwork_args)
561
+
562
+ else: # Generalized problem
563
+ # 'gvd' doesn't have lwork query
564
+ if driver == "gvd":
565
+ drv = get_lapack_funcs(pfx + "gvd", [a1, b1])
566
+ lwork_args = {}
567
+ else:
568
+ drv, drvlw = get_lapack_funcs((pfx + driver, pfx+driver+'_lwork'),
569
+ [a1, b1])
570
+ # generalized drivers use uplo instead of lower
571
+ lw = _compute_lwork(drvlw, n, uplo=uplo)
572
+ lwork_args = {'lwork': lw}
573
+
574
+ drv_args.update({'uplo': uplo, 'jobz': _job})
575
+
576
+ w, v, *other_args, info = drv(a=a1, b=b1, **drv_args, **lwork_args)
577
+
578
+ # m is always the first extra argument
579
+ w = w[:other_args[0]] if subset else w
580
+ v = v[:, :other_args[0]] if (subset and not eigvals_only) else v
581
+
582
+ # Check if we had a successful exit
583
+ if info == 0:
584
+ if eigvals_only:
585
+ return w
586
+ else:
587
+ return w, v
588
+ else:
589
+ if info < -1:
590
+ raise LinAlgError('Illegal value in argument {} of internal {}'
591
+ ''.format(-info, drv.typecode + pfx + driver))
592
+ elif info > n:
593
+ raise LinAlgError(f'The leading minor of order {info-n} of B is not '
594
+ 'positive definite. The factorization of B '
595
+ 'could not be completed and no eigenvalues '
596
+ 'or eigenvectors were computed.')
597
+ else:
598
+ drv_err = {'ev': 'The algorithm failed to converge; {} '
599
+ 'off-diagonal elements of an intermediate '
600
+ 'tridiagonal form did not converge to zero.',
601
+ 'evx': '{} eigenvectors failed to converge.',
602
+ 'evd': 'The algorithm failed to compute an eigenvalue '
603
+ 'while working on the submatrix lying in rows '
604
+ 'and columns {0}/{1} through mod({0},{1}).',
605
+ 'evr': 'Internal Error.'
606
+ }
607
+ if driver in ['ev', 'gv']:
608
+ msg = drv_err['ev'].format(info)
609
+ elif driver in ['evx', 'gvx']:
610
+ msg = drv_err['evx'].format(info)
611
+ elif driver in ['evd', 'gvd']:
612
+ if eigvals_only:
613
+ msg = drv_err['ev'].format(info)
614
+ else:
615
+ msg = drv_err['evd'].format(info, n+1)
616
+ else:
617
+ msg = drv_err['evr']
618
+
619
+ raise LinAlgError(msg)
620
+
621
+
622
+ _conv_dict = {0: 0, 1: 1, 2: 2,
623
+ 'all': 0, 'value': 1, 'index': 2,
624
+ 'a': 0, 'v': 1, 'i': 2}
625
+
626
+
627
+ def _check_select(select, select_range, max_ev, max_len):
628
+ """Check that select is valid, convert to Fortran style."""
629
+ if isinstance(select, str):
630
+ select = select.lower()
631
+ try:
632
+ select = _conv_dict[select]
633
+ except KeyError as e:
634
+ raise ValueError('invalid argument for select') from e
635
+ vl, vu = 0., 1.
636
+ il = iu = 1
637
+ if select != 0: # (non-all)
638
+ sr = asarray(select_range)
639
+ if sr.ndim != 1 or sr.size != 2 or sr[1] < sr[0]:
640
+ raise ValueError('select_range must be a 2-element array-like '
641
+ 'in nondecreasing order')
642
+ if select == 1: # (value)
643
+ vl, vu = sr
644
+ if max_ev == 0:
645
+ max_ev = max_len
646
+ else: # 2 (index)
647
+ if sr.dtype.char.lower() not in 'hilqp':
648
+ raise ValueError(
649
+ f'when using select="i", select_range must '
650
+ f'contain integers, got dtype {sr.dtype} ({sr.dtype.char})'
651
+ )
652
+ # translate Python (0 ... N-1) into Fortran (1 ... N) with + 1
653
+ il, iu = sr + 1
654
+ if min(il, iu) < 1 or max(il, iu) > max_len:
655
+ raise ValueError('select_range out of bounds')
656
+ max_ev = iu - il + 1
657
+ return select, vl, vu, il, iu, max_ev
658
+
659
+
660
+ def eig_banded(a_band, lower=False, eigvals_only=False, overwrite_a_band=False,
661
+ select='a', select_range=None, max_ev=0, check_finite=True):
662
+ """
663
+ Solve real symmetric or complex Hermitian band matrix eigenvalue problem.
664
+
665
+ Find eigenvalues w and optionally right eigenvectors v of a::
666
+
667
+ a v[:,i] = w[i] v[:,i]
668
+ v.H v = identity
669
+
670
+ The matrix a is stored in a_band either in lower diagonal or upper
671
+ diagonal ordered form:
672
+
673
+ a_band[u + i - j, j] == a[i,j] (if upper form; i <= j)
674
+ a_band[ i - j, j] == a[i,j] (if lower form; i >= j)
675
+
676
+ where u is the number of bands above the diagonal.
677
+
678
+ Example of a_band (shape of a is (6,6), u=2)::
679
+
680
+ upper form:
681
+ * * a02 a13 a24 a35
682
+ * a01 a12 a23 a34 a45
683
+ a00 a11 a22 a33 a44 a55
684
+
685
+ lower form:
686
+ a00 a11 a22 a33 a44 a55
687
+ a10 a21 a32 a43 a54 *
688
+ a20 a31 a42 a53 * *
689
+
690
+ Cells marked with * are not used.
691
+
692
+ Parameters
693
+ ----------
694
+ a_band : (u+1, M) array_like
695
+ The bands of the M by M matrix a.
696
+ lower : bool, optional
697
+ Is the matrix in the lower form. (Default is upper form)
698
+ eigvals_only : bool, optional
699
+ Compute only the eigenvalues and no eigenvectors.
700
+ (Default: calculate also eigenvectors)
701
+ overwrite_a_band : bool, optional
702
+ Discard data in a_band (may enhance performance)
703
+ select : {'a', 'v', 'i'}, optional
704
+ Which eigenvalues to calculate
705
+
706
+ ====== ========================================
707
+ select calculated
708
+ ====== ========================================
709
+ 'a' All eigenvalues
710
+ 'v' Eigenvalues in the interval (min, max]
711
+ 'i' Eigenvalues with indices min <= i <= max
712
+ ====== ========================================
713
+ select_range : (min, max), optional
714
+ Range of selected eigenvalues
715
+ max_ev : int, optional
716
+ For select=='v', maximum number of eigenvalues expected.
717
+ For other values of select, has no meaning.
718
+
719
+ In doubt, leave this parameter untouched.
720
+
721
+ check_finite : bool, optional
722
+ Whether to check that the input matrix contains only finite numbers.
723
+ Disabling may give a performance gain, but may result in problems
724
+ (crashes, non-termination) if the inputs do contain infinities or NaNs.
725
+
726
+ Returns
727
+ -------
728
+ w : (M,) ndarray
729
+ The eigenvalues, in ascending order, each repeated according to its
730
+ multiplicity.
731
+ v : (M, M) float or complex ndarray
732
+ The normalized eigenvector corresponding to the eigenvalue w[i] is
733
+ the column v[:,i]. Only returned if ``eigvals_only=False``.
734
+
735
+ Raises
736
+ ------
737
+ LinAlgError
738
+ If eigenvalue computation does not converge.
739
+
740
+ See Also
741
+ --------
742
+ eigvals_banded : eigenvalues for symmetric/Hermitian band matrices
743
+ eig : eigenvalues and right eigenvectors of general arrays.
744
+ eigh : eigenvalues and right eigenvectors for symmetric/Hermitian arrays
745
+ eigh_tridiagonal : eigenvalues and right eigenvectors for
746
+ symmetric/Hermitian tridiagonal matrices
747
+
748
+ Examples
749
+ --------
750
+ >>> import numpy as np
751
+ >>> from scipy.linalg import eig_banded
752
+ >>> A = np.array([[1, 5, 2, 0], [5, 2, 5, 2], [2, 5, 3, 5], [0, 2, 5, 4]])
753
+ >>> Ab = np.array([[1, 2, 3, 4], [5, 5, 5, 0], [2, 2, 0, 0]])
754
+ >>> w, v = eig_banded(Ab, lower=True)
755
+ >>> np.allclose(A @ v - v @ np.diag(w), np.zeros((4, 4)))
756
+ True
757
+ >>> w = eig_banded(Ab, lower=True, eigvals_only=True)
758
+ >>> w
759
+ array([-4.26200532, -2.22987175, 3.95222349, 12.53965359])
760
+
761
+ Request only the eigenvalues between ``[-3, 4]``
762
+
763
+ >>> w, v = eig_banded(Ab, lower=True, select='v', select_range=[-3, 4])
764
+ >>> w
765
+ array([-2.22987175, 3.95222349])
766
+
767
+ """
768
+ if eigvals_only or overwrite_a_band:
769
+ a1 = _asarray_validated(a_band, check_finite=check_finite)
770
+ overwrite_a_band = overwrite_a_band or (_datacopied(a1, a_band))
771
+ else:
772
+ a1 = array(a_band)
773
+ if issubclass(a1.dtype.type, inexact) and not isfinite(a1).all():
774
+ raise ValueError("array must not contain infs or NaNs")
775
+ overwrite_a_band = 1
776
+
777
+ if len(a1.shape) != 2:
778
+ raise ValueError('expected a 2-D array')
779
+ select, vl, vu, il, iu, max_ev = _check_select(
780
+ select, select_range, max_ev, a1.shape[1])
781
+ del select_range
782
+ if select == 0:
783
+ if a1.dtype.char in 'GFD':
784
+ # FIXME: implement this somewhen, for now go with builtin values
785
+ # FIXME: calc optimal lwork by calling ?hbevd(lwork=-1)
786
+ # or by using calc_lwork.f ???
787
+ # lwork = calc_lwork.hbevd(bevd.typecode, a1.shape[0], lower)
788
+ internal_name = 'hbevd'
789
+ else: # a1.dtype.char in 'fd':
790
+ # FIXME: implement this somewhen, for now go with builtin values
791
+ # see above
792
+ # lwork = calc_lwork.sbevd(bevd.typecode, a1.shape[0], lower)
793
+ internal_name = 'sbevd'
794
+ bevd, = get_lapack_funcs((internal_name,), (a1,))
795
+ w, v, info = bevd(a1, compute_v=not eigvals_only,
796
+ lower=lower, overwrite_ab=overwrite_a_band)
797
+ else: # select in [1, 2]
798
+ if eigvals_only:
799
+ max_ev = 1
800
+ # calculate optimal abstol for dsbevx (see manpage)
801
+ if a1.dtype.char in 'fF': # single precision
802
+ lamch, = get_lapack_funcs(('lamch',), (array(0, dtype='f'),))
803
+ else:
804
+ lamch, = get_lapack_funcs(('lamch',), (array(0, dtype='d'),))
805
+ abstol = 2 * lamch('s')
806
+ if a1.dtype.char in 'GFD':
807
+ internal_name = 'hbevx'
808
+ else: # a1.dtype.char in 'gfd'
809
+ internal_name = 'sbevx'
810
+ bevx, = get_lapack_funcs((internal_name,), (a1,))
811
+ w, v, m, ifail, info = bevx(
812
+ a1, vl, vu, il, iu, compute_v=not eigvals_only, mmax=max_ev,
813
+ range=select, lower=lower, overwrite_ab=overwrite_a_band,
814
+ abstol=abstol)
815
+ # crop off w and v
816
+ w = w[:m]
817
+ if not eigvals_only:
818
+ v = v[:, :m]
819
+ _check_info(info, internal_name)
820
+
821
+ if eigvals_only:
822
+ return w
823
+ return w, v
824
+
825
+
826
+ def eigvals(a, b=None, overwrite_a=False, check_finite=True,
827
+ homogeneous_eigvals=False):
828
+ """
829
+ Compute eigenvalues from an ordinary or generalized eigenvalue problem.
830
+
831
+ Find eigenvalues of a general matrix::
832
+
833
+ a vr[:,i] = w[i] b vr[:,i]
834
+
835
+ Parameters
836
+ ----------
837
+ a : (M, M) array_like
838
+ A complex or real matrix whose eigenvalues and eigenvectors
839
+ will be computed.
840
+ b : (M, M) array_like, optional
841
+ Right-hand side matrix in a generalized eigenvalue problem.
842
+ If omitted, identity matrix is assumed.
843
+ overwrite_a : bool, optional
844
+ Whether to overwrite data in a (may improve performance)
845
+ check_finite : bool, optional
846
+ Whether to check that the input matrices contain only finite numbers.
847
+ Disabling may give a performance gain, but may result in problems
848
+ (crashes, non-termination) if the inputs do contain infinities
849
+ or NaNs.
850
+ homogeneous_eigvals : bool, optional
851
+ If True, return the eigenvalues in homogeneous coordinates.
852
+ In this case ``w`` is a (2, M) array so that::
853
+
854
+ w[1,i] a vr[:,i] = w[0,i] b vr[:,i]
855
+
856
+ Default is False.
857
+
858
+ Returns
859
+ -------
860
+ w : (M,) or (2, M) double or complex ndarray
861
+ The eigenvalues, each repeated according to its multiplicity
862
+ but not in any specific order. The shape is (M,) unless
863
+ ``homogeneous_eigvals=True``.
864
+
865
+ Raises
866
+ ------
867
+ LinAlgError
868
+ If eigenvalue computation does not converge
869
+
870
+ See Also
871
+ --------
872
+ eig : eigenvalues and right eigenvectors of general arrays.
873
+ eigvalsh : eigenvalues of symmetric or Hermitian arrays
874
+ eigvals_banded : eigenvalues for symmetric/Hermitian band matrices
875
+ eigvalsh_tridiagonal : eigenvalues of symmetric/Hermitian tridiagonal
876
+ matrices
877
+
878
+ Examples
879
+ --------
880
+ >>> import numpy as np
881
+ >>> from scipy import linalg
882
+ >>> a = np.array([[0., -1.], [1., 0.]])
883
+ >>> linalg.eigvals(a)
884
+ array([0.+1.j, 0.-1.j])
885
+
886
+ >>> b = np.array([[0., 1.], [1., 1.]])
887
+ >>> linalg.eigvals(a, b)
888
+ array([ 1.+0.j, -1.+0.j])
889
+
890
+ >>> a = np.array([[3., 0., 0.], [0., 8., 0.], [0., 0., 7.]])
891
+ >>> linalg.eigvals(a, homogeneous_eigvals=True)
892
+ array([[3.+0.j, 8.+0.j, 7.+0.j],
893
+ [1.+0.j, 1.+0.j, 1.+0.j]])
894
+
895
+ """
896
+ return eig(a, b=b, left=0, right=0, overwrite_a=overwrite_a,
897
+ check_finite=check_finite,
898
+ homogeneous_eigvals=homogeneous_eigvals)
899
+
900
+
901
+ @_deprecate_positional_args(version="1.14.0")
902
+ def eigvalsh(a, b=None, *, lower=True, overwrite_a=False,
903
+ overwrite_b=False, turbo=_NoValue, eigvals=_NoValue, type=1,
904
+ check_finite=True, subset_by_index=None, subset_by_value=None,
905
+ driver=None):
906
+ """
907
+ Solves a standard or generalized eigenvalue problem for a complex
908
+ Hermitian or real symmetric matrix.
909
+
910
+ Find eigenvalues array ``w`` of array ``a``, where ``b`` is positive
911
+ definite such that for every eigenvalue λ (i-th entry of w) and its
912
+ eigenvector vi (i-th column of v) satisfies::
913
+
914
+ a @ vi = λ * b @ vi
915
+ vi.conj().T @ a @ vi = λ
916
+ vi.conj().T @ b @ vi = 1
917
+
918
+ In the standard problem, b is assumed to be the identity matrix.
919
+
920
+ Parameters
921
+ ----------
922
+ a : (M, M) array_like
923
+ A complex Hermitian or real symmetric matrix whose eigenvalues will
924
+ be computed.
925
+ b : (M, M) array_like, optional
926
+ A complex Hermitian or real symmetric definite positive matrix in.
927
+ If omitted, identity matrix is assumed.
928
+ lower : bool, optional
929
+ Whether the pertinent array data is taken from the lower or upper
930
+ triangle of ``a`` and, if applicable, ``b``. (Default: lower)
931
+ overwrite_a : bool, optional
932
+ Whether to overwrite data in ``a`` (may improve performance). Default
933
+ is False.
934
+ overwrite_b : bool, optional
935
+ Whether to overwrite data in ``b`` (may improve performance). Default
936
+ is False.
937
+ type : int, optional
938
+ For the generalized problems, this keyword specifies the problem type
939
+ to be solved for ``w`` and ``v`` (only takes 1, 2, 3 as possible
940
+ inputs)::
941
+
942
+ 1 => a @ v = w @ b @ v
943
+ 2 => a @ b @ v = w @ v
944
+ 3 => b @ a @ v = w @ v
945
+
946
+ This keyword is ignored for standard problems.
947
+ check_finite : bool, optional
948
+ Whether to check that the input matrices contain only finite numbers.
949
+ Disabling may give a performance gain, but may result in problems
950
+ (crashes, non-termination) if the inputs do contain infinities or NaNs.
951
+ subset_by_index : iterable, optional
952
+ If provided, this two-element iterable defines the start and the end
953
+ indices of the desired eigenvalues (ascending order and 0-indexed).
954
+ To return only the second smallest to fifth smallest eigenvalues,
955
+ ``[1, 4]`` is used. ``[n-3, n-1]`` returns the largest three. Only
956
+ available with "evr", "evx", and "gvx" drivers. The entries are
957
+ directly converted to integers via ``int()``.
958
+ subset_by_value : iterable, optional
959
+ If provided, this two-element iterable defines the half-open interval
960
+ ``(a, b]`` that, if any, only the eigenvalues between these values
961
+ are returned. Only available with "evr", "evx", and "gvx" drivers. Use
962
+ ``np.inf`` for the unconstrained ends.
963
+ driver : str, optional
964
+ Defines which LAPACK driver should be used. Valid options are "ev",
965
+ "evd", "evr", "evx" for standard problems and "gv", "gvd", "gvx" for
966
+ generalized (where b is not None) problems. See the Notes section of
967
+ `scipy.linalg.eigh`.
968
+ turbo : bool, optional, deprecated
969
+ .. deprecated:: 1.5.0
970
+ 'eigvalsh' keyword argument `turbo` is deprecated in favor of
971
+ ``driver=gvd`` option and will be removed in SciPy 1.14.0.
972
+
973
+ eigvals : tuple (lo, hi), optional
974
+ .. deprecated:: 1.5.0
975
+ 'eigvalsh' keyword argument `eigvals` is deprecated in favor of
976
+ `subset_by_index` option and will be removed in SciPy 1.14.0.
977
+
978
+ Returns
979
+ -------
980
+ w : (N,) ndarray
981
+ The N (N<=M) selected eigenvalues, in ascending order, each
982
+ repeated according to its multiplicity.
983
+
984
+ Raises
985
+ ------
986
+ LinAlgError
987
+ If eigenvalue computation does not converge, an error occurred, or
988
+ b matrix is not definite positive. Note that if input matrices are
989
+ not symmetric or Hermitian, no error will be reported but results will
990
+ be wrong.
991
+
992
+ See Also
993
+ --------
994
+ eigh : eigenvalues and right eigenvectors for symmetric/Hermitian arrays
995
+ eigvals : eigenvalues of general arrays
996
+ eigvals_banded : eigenvalues for symmetric/Hermitian band matrices
997
+ eigvalsh_tridiagonal : eigenvalues of symmetric/Hermitian tridiagonal
998
+ matrices
999
+
1000
+ Notes
1001
+ -----
1002
+ This function does not check the input array for being Hermitian/symmetric
1003
+ in order to allow for representing arrays with only their upper/lower
1004
+ triangular parts.
1005
+
1006
+ This function serves as a one-liner shorthand for `scipy.linalg.eigh` with
1007
+ the option ``eigvals_only=True`` to get the eigenvalues and not the
1008
+ eigenvectors. Here it is kept as a legacy convenience. It might be
1009
+ beneficial to use the main function to have full control and to be a bit
1010
+ more pythonic.
1011
+
1012
+ Examples
1013
+ --------
1014
+ For more examples see `scipy.linalg.eigh`.
1015
+
1016
+ >>> import numpy as np
1017
+ >>> from scipy.linalg import eigvalsh
1018
+ >>> A = np.array([[6, 3, 1, 5], [3, 0, 5, 1], [1, 5, 6, 2], [5, 1, 2, 2]])
1019
+ >>> w = eigvalsh(A)
1020
+ >>> w
1021
+ array([-3.74637491, -0.76263923, 6.08502336, 12.42399079])
1022
+
1023
+ """
1024
+ return eigh(a, b=b, lower=lower, eigvals_only=True,
1025
+ overwrite_a=overwrite_a, overwrite_b=overwrite_b,
1026
+ turbo=turbo, eigvals=eigvals, type=type,
1027
+ check_finite=check_finite, subset_by_index=subset_by_index,
1028
+ subset_by_value=subset_by_value, driver=driver)
1029
+
1030
+
1031
+ def eigvals_banded(a_band, lower=False, overwrite_a_band=False,
1032
+ select='a', select_range=None, check_finite=True):
1033
+ """
1034
+ Solve real symmetric or complex Hermitian band matrix eigenvalue problem.
1035
+
1036
+ Find eigenvalues w of a::
1037
+
1038
+ a v[:,i] = w[i] v[:,i]
1039
+ v.H v = identity
1040
+
1041
+ The matrix a is stored in a_band either in lower diagonal or upper
1042
+ diagonal ordered form:
1043
+
1044
+ a_band[u + i - j, j] == a[i,j] (if upper form; i <= j)
1045
+ a_band[ i - j, j] == a[i,j] (if lower form; i >= j)
1046
+
1047
+ where u is the number of bands above the diagonal.
1048
+
1049
+ Example of a_band (shape of a is (6,6), u=2)::
1050
+
1051
+ upper form:
1052
+ * * a02 a13 a24 a35
1053
+ * a01 a12 a23 a34 a45
1054
+ a00 a11 a22 a33 a44 a55
1055
+
1056
+ lower form:
1057
+ a00 a11 a22 a33 a44 a55
1058
+ a10 a21 a32 a43 a54 *
1059
+ a20 a31 a42 a53 * *
1060
+
1061
+ Cells marked with * are not used.
1062
+
1063
+ Parameters
1064
+ ----------
1065
+ a_band : (u+1, M) array_like
1066
+ The bands of the M by M matrix a.
1067
+ lower : bool, optional
1068
+ Is the matrix in the lower form. (Default is upper form)
1069
+ overwrite_a_band : bool, optional
1070
+ Discard data in a_band (may enhance performance)
1071
+ select : {'a', 'v', 'i'}, optional
1072
+ Which eigenvalues to calculate
1073
+
1074
+ ====== ========================================
1075
+ select calculated
1076
+ ====== ========================================
1077
+ 'a' All eigenvalues
1078
+ 'v' Eigenvalues in the interval (min, max]
1079
+ 'i' Eigenvalues with indices min <= i <= max
1080
+ ====== ========================================
1081
+ select_range : (min, max), optional
1082
+ Range of selected eigenvalues
1083
+ check_finite : bool, optional
1084
+ Whether to check that the input matrix contains only finite numbers.
1085
+ Disabling may give a performance gain, but may result in problems
1086
+ (crashes, non-termination) if the inputs do contain infinities or NaNs.
1087
+
1088
+ Returns
1089
+ -------
1090
+ w : (M,) ndarray
1091
+ The eigenvalues, in ascending order, each repeated according to its
1092
+ multiplicity.
1093
+
1094
+ Raises
1095
+ ------
1096
+ LinAlgError
1097
+ If eigenvalue computation does not converge.
1098
+
1099
+ See Also
1100
+ --------
1101
+ eig_banded : eigenvalues and right eigenvectors for symmetric/Hermitian
1102
+ band matrices
1103
+ eigvalsh_tridiagonal : eigenvalues of symmetric/Hermitian tridiagonal
1104
+ matrices
1105
+ eigvals : eigenvalues of general arrays
1106
+ eigh : eigenvalues and right eigenvectors for symmetric/Hermitian arrays
1107
+ eig : eigenvalues and right eigenvectors for non-symmetric arrays
1108
+
1109
+ Examples
1110
+ --------
1111
+ >>> import numpy as np
1112
+ >>> from scipy.linalg import eigvals_banded
1113
+ >>> A = np.array([[1, 5, 2, 0], [5, 2, 5, 2], [2, 5, 3, 5], [0, 2, 5, 4]])
1114
+ >>> Ab = np.array([[1, 2, 3, 4], [5, 5, 5, 0], [2, 2, 0, 0]])
1115
+ >>> w = eigvals_banded(Ab, lower=True)
1116
+ >>> w
1117
+ array([-4.26200532, -2.22987175, 3.95222349, 12.53965359])
1118
+ """
1119
+ return eig_banded(a_band, lower=lower, eigvals_only=1,
1120
+ overwrite_a_band=overwrite_a_band, select=select,
1121
+ select_range=select_range, check_finite=check_finite)
1122
+
1123
+
1124
+ def eigvalsh_tridiagonal(d, e, select='a', select_range=None,
1125
+ check_finite=True, tol=0., lapack_driver='auto'):
1126
+ """
1127
+ Solve eigenvalue problem for a real symmetric tridiagonal matrix.
1128
+
1129
+ Find eigenvalues `w` of ``a``::
1130
+
1131
+ a v[:,i] = w[i] v[:,i]
1132
+ v.H v = identity
1133
+
1134
+ For a real symmetric matrix ``a`` with diagonal elements `d` and
1135
+ off-diagonal elements `e`.
1136
+
1137
+ Parameters
1138
+ ----------
1139
+ d : ndarray, shape (ndim,)
1140
+ The diagonal elements of the array.
1141
+ e : ndarray, shape (ndim-1,)
1142
+ The off-diagonal elements of the array.
1143
+ select : {'a', 'v', 'i'}, optional
1144
+ Which eigenvalues to calculate
1145
+
1146
+ ====== ========================================
1147
+ select calculated
1148
+ ====== ========================================
1149
+ 'a' All eigenvalues
1150
+ 'v' Eigenvalues in the interval (min, max]
1151
+ 'i' Eigenvalues with indices min <= i <= max
1152
+ ====== ========================================
1153
+ select_range : (min, max), optional
1154
+ Range of selected eigenvalues
1155
+ check_finite : bool, optional
1156
+ Whether to check that the input matrix contains only finite numbers.
1157
+ Disabling may give a performance gain, but may result in problems
1158
+ (crashes, non-termination) if the inputs do contain infinities or NaNs.
1159
+ tol : float
1160
+ The absolute tolerance to which each eigenvalue is required
1161
+ (only used when ``lapack_driver='stebz'``).
1162
+ An eigenvalue (or cluster) is considered to have converged if it
1163
+ lies in an interval of this width. If <= 0. (default),
1164
+ the value ``eps*|a|`` is used where eps is the machine precision,
1165
+ and ``|a|`` is the 1-norm of the matrix ``a``.
1166
+ lapack_driver : str
1167
+ LAPACK function to use, can be 'auto', 'stemr', 'stebz', 'sterf',
1168
+ or 'stev'. When 'auto' (default), it will use 'stemr' if ``select='a'``
1169
+ and 'stebz' otherwise. 'sterf' and 'stev' can only be used when
1170
+ ``select='a'``.
1171
+
1172
+ Returns
1173
+ -------
1174
+ w : (M,) ndarray
1175
+ The eigenvalues, in ascending order, each repeated according to its
1176
+ multiplicity.
1177
+
1178
+ Raises
1179
+ ------
1180
+ LinAlgError
1181
+ If eigenvalue computation does not converge.
1182
+
1183
+ See Also
1184
+ --------
1185
+ eigh_tridiagonal : eigenvalues and right eiegenvectors for
1186
+ symmetric/Hermitian tridiagonal matrices
1187
+
1188
+ Examples
1189
+ --------
1190
+ >>> import numpy as np
1191
+ >>> from scipy.linalg import eigvalsh_tridiagonal, eigvalsh
1192
+ >>> d = 3*np.ones(4)
1193
+ >>> e = -1*np.ones(3)
1194
+ >>> w = eigvalsh_tridiagonal(d, e)
1195
+ >>> A = np.diag(d) + np.diag(e, k=1) + np.diag(e, k=-1)
1196
+ >>> w2 = eigvalsh(A) # Verify with other eigenvalue routines
1197
+ >>> np.allclose(w - w2, np.zeros(4))
1198
+ True
1199
+ """
1200
+ return eigh_tridiagonal(
1201
+ d, e, eigvals_only=True, select=select, select_range=select_range,
1202
+ check_finite=check_finite, tol=tol, lapack_driver=lapack_driver)
1203
+
1204
+
1205
+ def eigh_tridiagonal(d, e, eigvals_only=False, select='a', select_range=None,
1206
+ check_finite=True, tol=0., lapack_driver='auto'):
1207
+ """
1208
+ Solve eigenvalue problem for a real symmetric tridiagonal matrix.
1209
+
1210
+ Find eigenvalues `w` and optionally right eigenvectors `v` of ``a``::
1211
+
1212
+ a v[:,i] = w[i] v[:,i]
1213
+ v.H v = identity
1214
+
1215
+ For a real symmetric matrix ``a`` with diagonal elements `d` and
1216
+ off-diagonal elements `e`.
1217
+
1218
+ Parameters
1219
+ ----------
1220
+ d : ndarray, shape (ndim,)
1221
+ The diagonal elements of the array.
1222
+ e : ndarray, shape (ndim-1,)
1223
+ The off-diagonal elements of the array.
1224
+ eigvals_only : bool, optional
1225
+ Compute only the eigenvalues and no eigenvectors.
1226
+ (Default: calculate also eigenvectors)
1227
+ select : {'a', 'v', 'i'}, optional
1228
+ Which eigenvalues to calculate
1229
+
1230
+ ====== ========================================
1231
+ select calculated
1232
+ ====== ========================================
1233
+ 'a' All eigenvalues
1234
+ 'v' Eigenvalues in the interval (min, max]
1235
+ 'i' Eigenvalues with indices min <= i <= max
1236
+ ====== ========================================
1237
+ select_range : (min, max), optional
1238
+ Range of selected eigenvalues
1239
+ check_finite : bool, optional
1240
+ Whether to check that the input matrix contains only finite numbers.
1241
+ Disabling may give a performance gain, but may result in problems
1242
+ (crashes, non-termination) if the inputs do contain infinities or NaNs.
1243
+ tol : float
1244
+ The absolute tolerance to which each eigenvalue is required
1245
+ (only used when 'stebz' is the `lapack_driver`).
1246
+ An eigenvalue (or cluster) is considered to have converged if it
1247
+ lies in an interval of this width. If <= 0. (default),
1248
+ the value ``eps*|a|`` is used where eps is the machine precision,
1249
+ and ``|a|`` is the 1-norm of the matrix ``a``.
1250
+ lapack_driver : str
1251
+ LAPACK function to use, can be 'auto', 'stemr', 'stebz', 'sterf',
1252
+ or 'stev'. When 'auto' (default), it will use 'stemr' if ``select='a'``
1253
+ and 'stebz' otherwise. When 'stebz' is used to find the eigenvalues and
1254
+ ``eigvals_only=False``, then a second LAPACK call (to ``?STEIN``) is
1255
+ used to find the corresponding eigenvectors. 'sterf' can only be
1256
+ used when ``eigvals_only=True`` and ``select='a'``. 'stev' can only
1257
+ be used when ``select='a'``.
1258
+
1259
+ Returns
1260
+ -------
1261
+ w : (M,) ndarray
1262
+ The eigenvalues, in ascending order, each repeated according to its
1263
+ multiplicity.
1264
+ v : (M, M) ndarray
1265
+ The normalized eigenvector corresponding to the eigenvalue ``w[i]`` is
1266
+ the column ``v[:,i]``. Only returned if ``eigvals_only=False``.
1267
+
1268
+ Raises
1269
+ ------
1270
+ LinAlgError
1271
+ If eigenvalue computation does not converge.
1272
+
1273
+ See Also
1274
+ --------
1275
+ eigvalsh_tridiagonal : eigenvalues of symmetric/Hermitian tridiagonal
1276
+ matrices
1277
+ eig : eigenvalues and right eigenvectors for non-symmetric arrays
1278
+ eigh : eigenvalues and right eigenvectors for symmetric/Hermitian arrays
1279
+ eig_banded : eigenvalues and right eigenvectors for symmetric/Hermitian
1280
+ band matrices
1281
+
1282
+ Notes
1283
+ -----
1284
+ This function makes use of LAPACK ``S/DSTEMR`` routines.
1285
+
1286
+ Examples
1287
+ --------
1288
+ >>> import numpy as np
1289
+ >>> from scipy.linalg import eigh_tridiagonal
1290
+ >>> d = 3*np.ones(4)
1291
+ >>> e = -1*np.ones(3)
1292
+ >>> w, v = eigh_tridiagonal(d, e)
1293
+ >>> A = np.diag(d) + np.diag(e, k=1) + np.diag(e, k=-1)
1294
+ >>> np.allclose(A @ v - v @ np.diag(w), np.zeros((4, 4)))
1295
+ True
1296
+ """
1297
+ d = _asarray_validated(d, check_finite=check_finite)
1298
+ e = _asarray_validated(e, check_finite=check_finite)
1299
+ for check in (d, e):
1300
+ if check.ndim != 1:
1301
+ raise ValueError('expected a 1-D array')
1302
+ if check.dtype.char in 'GFD': # complex
1303
+ raise TypeError('Only real arrays currently supported')
1304
+ if d.size != e.size + 1:
1305
+ raise ValueError(f'd ({d.size}) must have one more element than e ({e.size})')
1306
+ select, vl, vu, il, iu, _ = _check_select(
1307
+ select, select_range, 0, d.size)
1308
+ if not isinstance(lapack_driver, str):
1309
+ raise TypeError('lapack_driver must be str')
1310
+ drivers = ('auto', 'stemr', 'sterf', 'stebz', 'stev')
1311
+ if lapack_driver not in drivers:
1312
+ raise ValueError(f'lapack_driver must be one of {drivers}, '
1313
+ f'got {lapack_driver}')
1314
+ if lapack_driver == 'auto':
1315
+ lapack_driver = 'stemr' if select == 0 else 'stebz'
1316
+
1317
+ # Quick exit for 1x1 case
1318
+ if len(d) == 1:
1319
+ if select == 1 and (not (vl < d[0] <= vu)): # request by value
1320
+ w = array([])
1321
+ v = empty([1, 0], dtype=d.dtype)
1322
+ else: # all and request by index
1323
+ w = array([d[0]], dtype=d.dtype)
1324
+ v = array([[1.]], dtype=d.dtype)
1325
+
1326
+ if eigvals_only:
1327
+ return w
1328
+ else:
1329
+ return w, v
1330
+
1331
+ func, = get_lapack_funcs((lapack_driver,), (d, e))
1332
+ compute_v = not eigvals_only
1333
+ if lapack_driver == 'sterf':
1334
+ if select != 0:
1335
+ raise ValueError('sterf can only be used when select == "a"')
1336
+ if not eigvals_only:
1337
+ raise ValueError('sterf can only be used when eigvals_only is '
1338
+ 'True')
1339
+ w, info = func(d, e)
1340
+ m = len(w)
1341
+ elif lapack_driver == 'stev':
1342
+ if select != 0:
1343
+ raise ValueError('stev can only be used when select == "a"')
1344
+ w, v, info = func(d, e, compute_v=compute_v)
1345
+ m = len(w)
1346
+ elif lapack_driver == 'stebz':
1347
+ tol = float(tol)
1348
+ internal_name = 'stebz'
1349
+ stebz, = get_lapack_funcs((internal_name,), (d, e))
1350
+ # If getting eigenvectors, needs to be block-ordered (B) instead of
1351
+ # matrix-ordered (E), and we will reorder later
1352
+ order = 'E' if eigvals_only else 'B'
1353
+ m, w, iblock, isplit, info = stebz(d, e, select, vl, vu, il, iu, tol,
1354
+ order)
1355
+ else: # 'stemr'
1356
+ # ?STEMR annoyingly requires size N instead of N-1
1357
+ e_ = empty(e.size+1, e.dtype)
1358
+ e_[:-1] = e
1359
+ stemr_lwork, = get_lapack_funcs(('stemr_lwork',), (d, e))
1360
+ lwork, liwork, info = stemr_lwork(d, e_, select, vl, vu, il, iu,
1361
+ compute_v=compute_v)
1362
+ _check_info(info, 'stemr_lwork')
1363
+ m, w, v, info = func(d, e_, select, vl, vu, il, iu,
1364
+ compute_v=compute_v, lwork=lwork, liwork=liwork)
1365
+ _check_info(info, lapack_driver + ' (eigh_tridiagonal)')
1366
+ w = w[:m]
1367
+ if eigvals_only:
1368
+ return w
1369
+ else:
1370
+ # Do we still need to compute the eigenvalues?
1371
+ if lapack_driver == 'stebz':
1372
+ func, = get_lapack_funcs(('stein',), (d, e))
1373
+ v, info = func(d, e, w, iblock, isplit)
1374
+ _check_info(info, 'stein (eigh_tridiagonal)',
1375
+ positive='%d eigenvectors failed to converge')
1376
+ # Convert block-order to matrix-order
1377
+ order = argsort(w)
1378
+ w, v = w[order], v[:, order]
1379
+ else:
1380
+ v = v[:, :m]
1381
+ return w, v
1382
+
1383
+
1384
+ def _check_info(info, driver, positive='did not converge (LAPACK info=%d)'):
1385
+ """Check info return value."""
1386
+ if info < 0:
1387
+ raise ValueError('illegal value in argument %d of internal %s'
1388
+ % (-info, driver))
1389
+ if info > 0 and positive:
1390
+ raise LinAlgError(("%s " + positive) % (driver, info,))
1391
+
1392
+
1393
+ def hessenberg(a, calc_q=False, overwrite_a=False, check_finite=True):
1394
+ """
1395
+ Compute Hessenberg form of a matrix.
1396
+
1397
+ The Hessenberg decomposition is::
1398
+
1399
+ A = Q H Q^H
1400
+
1401
+ where `Q` is unitary/orthogonal and `H` has only zero elements below
1402
+ the first sub-diagonal.
1403
+
1404
+ Parameters
1405
+ ----------
1406
+ a : (M, M) array_like
1407
+ Matrix to bring into Hessenberg form.
1408
+ calc_q : bool, optional
1409
+ Whether to compute the transformation matrix. Default is False.
1410
+ overwrite_a : bool, optional
1411
+ Whether to overwrite `a`; may improve performance.
1412
+ Default is False.
1413
+ check_finite : bool, optional
1414
+ Whether to check that the input matrix contains only finite numbers.
1415
+ Disabling may give a performance gain, but may result in problems
1416
+ (crashes, non-termination) if the inputs do contain infinities or NaNs.
1417
+
1418
+ Returns
1419
+ -------
1420
+ H : (M, M) ndarray
1421
+ Hessenberg form of `a`.
1422
+ Q : (M, M) ndarray
1423
+ Unitary/orthogonal similarity transformation matrix ``A = Q H Q^H``.
1424
+ Only returned if ``calc_q=True``.
1425
+
1426
+ Examples
1427
+ --------
1428
+ >>> import numpy as np
1429
+ >>> from scipy.linalg import hessenberg
1430
+ >>> A = np.array([[2, 5, 8, 7], [5, 2, 2, 8], [7, 5, 6, 6], [5, 4, 4, 8]])
1431
+ >>> H, Q = hessenberg(A, calc_q=True)
1432
+ >>> H
1433
+ array([[ 2. , -11.65843866, 1.42005301, 0.25349066],
1434
+ [ -9.94987437, 14.53535354, -5.31022304, 2.43081618],
1435
+ [ 0. , -1.83299243, 0.38969961, -0.51527034],
1436
+ [ 0. , 0. , -3.83189513, 1.07494686]])
1437
+ >>> np.allclose(Q @ H @ Q.conj().T - A, np.zeros((4, 4)))
1438
+ True
1439
+ """
1440
+ a1 = _asarray_validated(a, check_finite=check_finite)
1441
+ if len(a1.shape) != 2 or (a1.shape[0] != a1.shape[1]):
1442
+ raise ValueError('expected square matrix')
1443
+ overwrite_a = overwrite_a or (_datacopied(a1, a))
1444
+
1445
+ # if 2x2 or smaller: already in Hessenberg
1446
+ if a1.shape[0] <= 2:
1447
+ if calc_q:
1448
+ return a1, eye(a1.shape[0])
1449
+ return a1
1450
+
1451
+ gehrd, gebal, gehrd_lwork = get_lapack_funcs(('gehrd', 'gebal',
1452
+ 'gehrd_lwork'), (a1,))
1453
+ ba, lo, hi, pivscale, info = gebal(a1, permute=0, overwrite_a=overwrite_a)
1454
+ _check_info(info, 'gebal (hessenberg)', positive=False)
1455
+ n = len(a1)
1456
+
1457
+ lwork = _compute_lwork(gehrd_lwork, ba.shape[0], lo=lo, hi=hi)
1458
+
1459
+ hq, tau, info = gehrd(ba, lo=lo, hi=hi, lwork=lwork, overwrite_a=1)
1460
+ _check_info(info, 'gehrd (hessenberg)', positive=False)
1461
+ h = numpy.triu(hq, -1)
1462
+ if not calc_q:
1463
+ return h
1464
+
1465
+ # use orghr/unghr to compute q
1466
+ orghr, orghr_lwork = get_lapack_funcs(('orghr', 'orghr_lwork'), (a1,))
1467
+ lwork = _compute_lwork(orghr_lwork, n, lo=lo, hi=hi)
1468
+
1469
+ q, info = orghr(a=hq, tau=tau, lo=lo, hi=hi, lwork=lwork, overwrite_a=1)
1470
+ _check_info(info, 'orghr (hessenberg)', positive=False)
1471
+ return h, q
1472
+
1473
+
1474
+ def cdf2rdf(w, v):
1475
+ """
1476
+ Converts complex eigenvalues ``w`` and eigenvectors ``v`` to real
1477
+ eigenvalues in a block diagonal form ``wr`` and the associated real
1478
+ eigenvectors ``vr``, such that::
1479
+
1480
+ vr @ wr = X @ vr
1481
+
1482
+ continues to hold, where ``X`` is the original array for which ``w`` and
1483
+ ``v`` are the eigenvalues and eigenvectors.
1484
+
1485
+ .. versionadded:: 1.1.0
1486
+
1487
+ Parameters
1488
+ ----------
1489
+ w : (..., M) array_like
1490
+ Complex or real eigenvalues, an array or stack of arrays
1491
+
1492
+ Conjugate pairs must not be interleaved, else the wrong result
1493
+ will be produced. So ``[1+1j, 1, 1-1j]`` will give a correct result,
1494
+ but ``[1+1j, 2+1j, 1-1j, 2-1j]`` will not.
1495
+
1496
+ v : (..., M, M) array_like
1497
+ Complex or real eigenvectors, a square array or stack of square arrays.
1498
+
1499
+ Returns
1500
+ -------
1501
+ wr : (..., M, M) ndarray
1502
+ Real diagonal block form of eigenvalues
1503
+ vr : (..., M, M) ndarray
1504
+ Real eigenvectors associated with ``wr``
1505
+
1506
+ See Also
1507
+ --------
1508
+ eig : Eigenvalues and right eigenvectors for non-symmetric arrays
1509
+ rsf2csf : Convert real Schur form to complex Schur form
1510
+
1511
+ Notes
1512
+ -----
1513
+ ``w``, ``v`` must be the eigenstructure for some *real* matrix ``X``.
1514
+ For example, obtained by ``w, v = scipy.linalg.eig(X)`` or
1515
+ ``w, v = numpy.linalg.eig(X)`` in which case ``X`` can also represent
1516
+ stacked arrays.
1517
+
1518
+ .. versionadded:: 1.1.0
1519
+
1520
+ Examples
1521
+ --------
1522
+ >>> import numpy as np
1523
+ >>> X = np.array([[1, 2, 3], [0, 4, 5], [0, -5, 4]])
1524
+ >>> X
1525
+ array([[ 1, 2, 3],
1526
+ [ 0, 4, 5],
1527
+ [ 0, -5, 4]])
1528
+
1529
+ >>> from scipy import linalg
1530
+ >>> w, v = linalg.eig(X)
1531
+ >>> w
1532
+ array([ 1.+0.j, 4.+5.j, 4.-5.j])
1533
+ >>> v
1534
+ array([[ 1.00000+0.j , -0.01906-0.40016j, -0.01906+0.40016j],
1535
+ [ 0.00000+0.j , 0.00000-0.64788j, 0.00000+0.64788j],
1536
+ [ 0.00000+0.j , 0.64788+0.j , 0.64788-0.j ]])
1537
+
1538
+ >>> wr, vr = linalg.cdf2rdf(w, v)
1539
+ >>> wr
1540
+ array([[ 1., 0., 0.],
1541
+ [ 0., 4., 5.],
1542
+ [ 0., -5., 4.]])
1543
+ >>> vr
1544
+ array([[ 1. , 0.40016, -0.01906],
1545
+ [ 0. , 0.64788, 0. ],
1546
+ [ 0. , 0. , 0.64788]])
1547
+
1548
+ >>> vr @ wr
1549
+ array([[ 1. , 1.69593, 1.9246 ],
1550
+ [ 0. , 2.59153, 3.23942],
1551
+ [ 0. , -3.23942, 2.59153]])
1552
+ >>> X @ vr
1553
+ array([[ 1. , 1.69593, 1.9246 ],
1554
+ [ 0. , 2.59153, 3.23942],
1555
+ [ 0. , -3.23942, 2.59153]])
1556
+ """
1557
+ w, v = _asarray_validated(w), _asarray_validated(v)
1558
+
1559
+ # check dimensions
1560
+ if w.ndim < 1:
1561
+ raise ValueError('expected w to be at least 1D')
1562
+ if v.ndim < 2:
1563
+ raise ValueError('expected v to be at least 2D')
1564
+ if v.ndim != w.ndim + 1:
1565
+ raise ValueError('expected eigenvectors array to have exactly one '
1566
+ 'dimension more than eigenvalues array')
1567
+
1568
+ # check shapes
1569
+ n = w.shape[-1]
1570
+ M = w.shape[:-1]
1571
+ if v.shape[-2] != v.shape[-1]:
1572
+ raise ValueError('expected v to be a square matrix or stacked square '
1573
+ 'matrices: v.shape[-2] = v.shape[-1]')
1574
+ if v.shape[-1] != n:
1575
+ raise ValueError('expected the same number of eigenvalues as '
1576
+ 'eigenvectors')
1577
+
1578
+ # get indices for each first pair of complex eigenvalues
1579
+ complex_mask = iscomplex(w)
1580
+ n_complex = complex_mask.sum(axis=-1)
1581
+
1582
+ # check if all complex eigenvalues have conjugate pairs
1583
+ if not (n_complex % 2 == 0).all():
1584
+ raise ValueError('expected complex-conjugate pairs of eigenvalues')
1585
+
1586
+ # find complex indices
1587
+ idx = nonzero(complex_mask)
1588
+ idx_stack = idx[:-1]
1589
+ idx_elem = idx[-1]
1590
+
1591
+ # filter them to conjugate indices, assuming pairs are not interleaved
1592
+ j = idx_elem[0::2]
1593
+ k = idx_elem[1::2]
1594
+ stack_ind = ()
1595
+ for i in idx_stack:
1596
+ # should never happen, assuming nonzero orders by the last axis
1597
+ assert (i[0::2] == i[1::2]).all(), \
1598
+ "Conjugate pair spanned different arrays!"
1599
+ stack_ind += (i[0::2],)
1600
+
1601
+ # all eigenvalues to diagonal form
1602
+ wr = zeros(M + (n, n), dtype=w.real.dtype)
1603
+ di = range(n)
1604
+ wr[..., di, di] = w.real
1605
+
1606
+ # complex eigenvalues to real block diagonal form
1607
+ wr[stack_ind + (j, k)] = w[stack_ind + (j,)].imag
1608
+ wr[stack_ind + (k, j)] = w[stack_ind + (k,)].imag
1609
+
1610
+ # compute real eigenvectors associated with real block diagonal eigenvalues
1611
+ u = zeros(M + (n, n), dtype=numpy.cdouble)
1612
+ u[..., di, di] = 1.0
1613
+ u[stack_ind + (j, j)] = 0.5j
1614
+ u[stack_ind + (j, k)] = 0.5
1615
+ u[stack_ind + (k, j)] = -0.5j
1616
+ u[stack_ind + (k, k)] = 0.5
1617
+
1618
+ # multiply matrices v and u (equivalent to v @ u)
1619
+ vr = einsum('...ij,...jk->...ik', v, u).real
1620
+
1621
+ return wr, vr
astra_scene_test/Scene_04/.venv/lib/python3.9/site-packages/scipy/linalg/_decomp_cholesky.py ADDED
@@ -0,0 +1,356 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """Cholesky decomposition functions."""
2
+
3
+ from numpy import asarray_chkfinite, asarray, atleast_2d
4
+
5
+ # Local imports
6
+ from ._misc import LinAlgError, _datacopied
7
+ from .lapack import get_lapack_funcs
8
+
9
+ __all__ = ['cholesky', 'cho_factor', 'cho_solve', 'cholesky_banded',
10
+ 'cho_solve_banded']
11
+
12
+
13
+ def _cholesky(a, lower=False, overwrite_a=False, clean=True,
14
+ check_finite=True):
15
+ """Common code for cholesky() and cho_factor()."""
16
+
17
+ a1 = asarray_chkfinite(a) if check_finite else asarray(a)
18
+ a1 = atleast_2d(a1)
19
+
20
+ # Dimension check
21
+ if a1.ndim != 2:
22
+ raise ValueError(f'Input array needs to be 2D but received a {a1.ndim}d-array.')
23
+ # Squareness check
24
+ if a1.shape[0] != a1.shape[1]:
25
+ raise ValueError('Input array is expected to be square but has '
26
+ f'the shape: {a1.shape}.')
27
+
28
+ # Quick return for square empty array
29
+ if a1.size == 0:
30
+ return a1.copy(), lower
31
+
32
+ overwrite_a = overwrite_a or _datacopied(a1, a)
33
+ potrf, = get_lapack_funcs(('potrf',), (a1,))
34
+ c, info = potrf(a1, lower=lower, overwrite_a=overwrite_a, clean=clean)
35
+ if info > 0:
36
+ raise LinAlgError("%d-th leading minor of the array is not positive "
37
+ "definite" % info)
38
+ if info < 0:
39
+ raise ValueError(f'LAPACK reported an illegal value in {-info}-th argument'
40
+ 'on entry to "POTRF".')
41
+ return c, lower
42
+
43
+
44
+ def cholesky(a, lower=False, overwrite_a=False, check_finite=True):
45
+ """
46
+ Compute the Cholesky decomposition of a matrix.
47
+
48
+ Returns the Cholesky decomposition, :math:`A = L L^*` or
49
+ :math:`A = U^* U` of a Hermitian positive-definite matrix A.
50
+
51
+ Parameters
52
+ ----------
53
+ a : (M, M) array_like
54
+ Matrix to be decomposed
55
+ lower : bool, optional
56
+ Whether to compute the upper- or lower-triangular Cholesky
57
+ factorization. Default is upper-triangular.
58
+ overwrite_a : bool, optional
59
+ Whether to overwrite data in `a` (may improve performance).
60
+ check_finite : bool, optional
61
+ Whether to check that the input matrix contains only finite numbers.
62
+ Disabling may give a performance gain, but may result in problems
63
+ (crashes, non-termination) if the inputs do contain infinities or NaNs.
64
+
65
+ Returns
66
+ -------
67
+ c : (M, M) ndarray
68
+ Upper- or lower-triangular Cholesky factor of `a`.
69
+
70
+ Raises
71
+ ------
72
+ LinAlgError : if decomposition fails.
73
+
74
+ Examples
75
+ --------
76
+ >>> import numpy as np
77
+ >>> from scipy.linalg import cholesky
78
+ >>> a = np.array([[1,-2j],[2j,5]])
79
+ >>> L = cholesky(a, lower=True)
80
+ >>> L
81
+ array([[ 1.+0.j, 0.+0.j],
82
+ [ 0.+2.j, 1.+0.j]])
83
+ >>> L @ L.T.conj()
84
+ array([[ 1.+0.j, 0.-2.j],
85
+ [ 0.+2.j, 5.+0.j]])
86
+
87
+ """
88
+ c, lower = _cholesky(a, lower=lower, overwrite_a=overwrite_a, clean=True,
89
+ check_finite=check_finite)
90
+ return c
91
+
92
+
93
+ def cho_factor(a, lower=False, overwrite_a=False, check_finite=True):
94
+ """
95
+ Compute the Cholesky decomposition of a matrix, to use in cho_solve
96
+
97
+ Returns a matrix containing the Cholesky decomposition,
98
+ ``A = L L*`` or ``A = U* U`` of a Hermitian positive-definite matrix `a`.
99
+ The return value can be directly used as the first parameter to cho_solve.
100
+
101
+ .. warning::
102
+ The returned matrix also contains random data in the entries not
103
+ used by the Cholesky decomposition. If you need to zero these
104
+ entries, use the function `cholesky` instead.
105
+
106
+ Parameters
107
+ ----------
108
+ a : (M, M) array_like
109
+ Matrix to be decomposed
110
+ lower : bool, optional
111
+ Whether to compute the upper or lower triangular Cholesky factorization
112
+ (Default: upper-triangular)
113
+ overwrite_a : bool, optional
114
+ Whether to overwrite data in a (may improve performance)
115
+ check_finite : bool, optional
116
+ Whether to check that the input matrix contains only finite numbers.
117
+ Disabling may give a performance gain, but may result in problems
118
+ (crashes, non-termination) if the inputs do contain infinities or NaNs.
119
+
120
+ Returns
121
+ -------
122
+ c : (M, M) ndarray
123
+ Matrix whose upper or lower triangle contains the Cholesky factor
124
+ of `a`. Other parts of the matrix contain random data.
125
+ lower : bool
126
+ Flag indicating whether the factor is in the lower or upper triangle
127
+
128
+ Raises
129
+ ------
130
+ LinAlgError
131
+ Raised if decomposition fails.
132
+
133
+ See Also
134
+ --------
135
+ cho_solve : Solve a linear set equations using the Cholesky factorization
136
+ of a matrix.
137
+
138
+ Examples
139
+ --------
140
+ >>> import numpy as np
141
+ >>> from scipy.linalg import cho_factor
142
+ >>> A = np.array([[9, 3, 1, 5], [3, 7, 5, 1], [1, 5, 9, 2], [5, 1, 2, 6]])
143
+ >>> c, low = cho_factor(A)
144
+ >>> c
145
+ array([[3. , 1. , 0.33333333, 1.66666667],
146
+ [3. , 2.44948974, 1.90515869, -0.27216553],
147
+ [1. , 5. , 2.29330749, 0.8559528 ],
148
+ [5. , 1. , 2. , 1.55418563]])
149
+ >>> np.allclose(np.triu(c).T @ np. triu(c) - A, np.zeros((4, 4)))
150
+ True
151
+
152
+ """
153
+ c, lower = _cholesky(a, lower=lower, overwrite_a=overwrite_a, clean=False,
154
+ check_finite=check_finite)
155
+ return c, lower
156
+
157
+
158
+ def cho_solve(c_and_lower, b, overwrite_b=False, check_finite=True):
159
+ """Solve the linear equations A x = b, given the Cholesky factorization of A.
160
+
161
+ Parameters
162
+ ----------
163
+ (c, lower) : tuple, (array, bool)
164
+ Cholesky factorization of a, as given by cho_factor
165
+ b : array
166
+ Right-hand side
167
+ overwrite_b : bool, optional
168
+ Whether to overwrite data in b (may improve performance)
169
+ check_finite : bool, optional
170
+ Whether to check that the input matrices contain only finite numbers.
171
+ Disabling may give a performance gain, but may result in problems
172
+ (crashes, non-termination) if the inputs do contain infinities or NaNs.
173
+
174
+ Returns
175
+ -------
176
+ x : array
177
+ The solution to the system A x = b
178
+
179
+ See Also
180
+ --------
181
+ cho_factor : Cholesky factorization of a matrix
182
+
183
+ Examples
184
+ --------
185
+ >>> import numpy as np
186
+ >>> from scipy.linalg import cho_factor, cho_solve
187
+ >>> A = np.array([[9, 3, 1, 5], [3, 7, 5, 1], [1, 5, 9, 2], [5, 1, 2, 6]])
188
+ >>> c, low = cho_factor(A)
189
+ >>> x = cho_solve((c, low), [1, 1, 1, 1])
190
+ >>> np.allclose(A @ x - [1, 1, 1, 1], np.zeros(4))
191
+ True
192
+
193
+ """
194
+ (c, lower) = c_and_lower
195
+ if check_finite:
196
+ b1 = asarray_chkfinite(b)
197
+ c = asarray_chkfinite(c)
198
+ else:
199
+ b1 = asarray(b)
200
+ c = asarray(c)
201
+ if c.ndim != 2 or c.shape[0] != c.shape[1]:
202
+ raise ValueError("The factored matrix c is not square.")
203
+ if c.shape[1] != b1.shape[0]:
204
+ raise ValueError(f"incompatible dimensions ({c.shape} and {b1.shape})")
205
+
206
+ overwrite_b = overwrite_b or _datacopied(b1, b)
207
+
208
+ potrs, = get_lapack_funcs(('potrs',), (c, b1))
209
+ x, info = potrs(c, b1, lower=lower, overwrite_b=overwrite_b)
210
+ if info != 0:
211
+ raise ValueError('illegal value in %dth argument of internal potrs'
212
+ % -info)
213
+ return x
214
+
215
+
216
+ def cholesky_banded(ab, overwrite_ab=False, lower=False, check_finite=True):
217
+ """
218
+ Cholesky decompose a banded Hermitian positive-definite matrix
219
+
220
+ The matrix a is stored in ab either in lower-diagonal or upper-
221
+ diagonal ordered form::
222
+
223
+ ab[u + i - j, j] == a[i,j] (if upper form; i <= j)
224
+ ab[ i - j, j] == a[i,j] (if lower form; i >= j)
225
+
226
+ Example of ab (shape of a is (6,6), u=2)::
227
+
228
+ upper form:
229
+ * * a02 a13 a24 a35
230
+ * a01 a12 a23 a34 a45
231
+ a00 a11 a22 a33 a44 a55
232
+
233
+ lower form:
234
+ a00 a11 a22 a33 a44 a55
235
+ a10 a21 a32 a43 a54 *
236
+ a20 a31 a42 a53 * *
237
+
238
+ Parameters
239
+ ----------
240
+ ab : (u + 1, M) array_like
241
+ Banded matrix
242
+ overwrite_ab : bool, optional
243
+ Discard data in ab (may enhance performance)
244
+ lower : bool, optional
245
+ Is the matrix in the lower form. (Default is upper form)
246
+ check_finite : bool, optional
247
+ Whether to check that the input matrix contains only finite numbers.
248
+ Disabling may give a performance gain, but may result in problems
249
+ (crashes, non-termination) if the inputs do contain infinities or NaNs.
250
+
251
+ Returns
252
+ -------
253
+ c : (u + 1, M) ndarray
254
+ Cholesky factorization of a, in the same banded format as ab
255
+
256
+ See Also
257
+ --------
258
+ cho_solve_banded :
259
+ Solve a linear set equations, given the Cholesky factorization
260
+ of a banded Hermitian.
261
+
262
+ Examples
263
+ --------
264
+ >>> import numpy as np
265
+ >>> from scipy.linalg import cholesky_banded
266
+ >>> from numpy import allclose, zeros, diag
267
+ >>> Ab = np.array([[0, 0, 1j, 2, 3j], [0, -1, -2, 3, 4], [9, 8, 7, 6, 9]])
268
+ >>> A = np.diag(Ab[0,2:], k=2) + np.diag(Ab[1,1:], k=1)
269
+ >>> A = A + A.conj().T + np.diag(Ab[2, :])
270
+ >>> c = cholesky_banded(Ab)
271
+ >>> C = np.diag(c[0, 2:], k=2) + np.diag(c[1, 1:], k=1) + np.diag(c[2, :])
272
+ >>> np.allclose(C.conj().T @ C - A, np.zeros((5, 5)))
273
+ True
274
+
275
+ """
276
+ if check_finite:
277
+ ab = asarray_chkfinite(ab)
278
+ else:
279
+ ab = asarray(ab)
280
+
281
+ pbtrf, = get_lapack_funcs(('pbtrf',), (ab,))
282
+ c, info = pbtrf(ab, lower=lower, overwrite_ab=overwrite_ab)
283
+ if info > 0:
284
+ raise LinAlgError("%d-th leading minor not positive definite" % info)
285
+ if info < 0:
286
+ raise ValueError('illegal value in %d-th argument of internal pbtrf'
287
+ % -info)
288
+ return c
289
+
290
+
291
+ def cho_solve_banded(cb_and_lower, b, overwrite_b=False, check_finite=True):
292
+ """
293
+ Solve the linear equations ``A x = b``, given the Cholesky factorization of
294
+ the banded Hermitian ``A``.
295
+
296
+ Parameters
297
+ ----------
298
+ (cb, lower) : tuple, (ndarray, bool)
299
+ `cb` is the Cholesky factorization of A, as given by cholesky_banded.
300
+ `lower` must be the same value that was given to cholesky_banded.
301
+ b : array_like
302
+ Right-hand side
303
+ overwrite_b : bool, optional
304
+ If True, the function will overwrite the values in `b`.
305
+ check_finite : bool, optional
306
+ Whether to check that the input matrices contain only finite numbers.
307
+ Disabling may give a performance gain, but may result in problems
308
+ (crashes, non-termination) if the inputs do contain infinities or NaNs.
309
+
310
+ Returns
311
+ -------
312
+ x : array
313
+ The solution to the system A x = b
314
+
315
+ See Also
316
+ --------
317
+ cholesky_banded : Cholesky factorization of a banded matrix
318
+
319
+ Notes
320
+ -----
321
+
322
+ .. versionadded:: 0.8.0
323
+
324
+ Examples
325
+ --------
326
+ >>> import numpy as np
327
+ >>> from scipy.linalg import cholesky_banded, cho_solve_banded
328
+ >>> Ab = np.array([[0, 0, 1j, 2, 3j], [0, -1, -2, 3, 4], [9, 8, 7, 6, 9]])
329
+ >>> A = np.diag(Ab[0,2:], k=2) + np.diag(Ab[1,1:], k=1)
330
+ >>> A = A + A.conj().T + np.diag(Ab[2, :])
331
+ >>> c = cholesky_banded(Ab)
332
+ >>> x = cho_solve_banded((c, False), np.ones(5))
333
+ >>> np.allclose(A @ x - np.ones(5), np.zeros(5))
334
+ True
335
+
336
+ """
337
+ (cb, lower) = cb_and_lower
338
+ if check_finite:
339
+ cb = asarray_chkfinite(cb)
340
+ b = asarray_chkfinite(b)
341
+ else:
342
+ cb = asarray(cb)
343
+ b = asarray(b)
344
+
345
+ # Validate shapes.
346
+ if cb.shape[-1] != b.shape[0]:
347
+ raise ValueError("shapes of cb and b are not compatible.")
348
+
349
+ pbtrs, = get_lapack_funcs(('pbtrs',), (cb, b))
350
+ x, info = pbtrs(cb, b, lower=lower, overwrite_b=overwrite_b)
351
+ if info > 0:
352
+ raise LinAlgError("%dth leading minor not positive definite" % info)
353
+ if info < 0:
354
+ raise ValueError('illegal value in %dth argument of internal pbtrs'
355
+ % -info)
356
+ return x
astra_scene_test/Scene_04/.venv/lib/python3.9/site-packages/scipy/linalg/_decomp_cossin.py ADDED
@@ -0,0 +1,221 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from collections.abc import Iterable
2
+ import numpy as np
3
+
4
+ from scipy._lib._util import _asarray_validated
5
+ from scipy.linalg import block_diag, LinAlgError
6
+ from .lapack import _compute_lwork, get_lapack_funcs
7
+
8
+ __all__ = ['cossin']
9
+
10
+
11
+ def cossin(X, p=None, q=None, separate=False,
12
+ swap_sign=False, compute_u=True, compute_vh=True):
13
+ """
14
+ Compute the cosine-sine (CS) decomposition of an orthogonal/unitary matrix.
15
+
16
+ X is an ``(m, m)`` orthogonal/unitary matrix, partitioned as the following
17
+ where upper left block has the shape of ``(p, q)``::
18
+
19
+ ┌ ┐
20
+ │ I 0 0 │ 0 0 0 │
21
+ ┌ ┐ ┌ ┐│ 0 C 0 │ 0 -S 0 │┌ ┐*
22
+ │ X11 │ X12 │ │ U1 │ ││ 0 0 0 │ 0 0 -I ││ V1 │ │
23
+ │ ────┼──── │ = │────┼────││─────────┼─────────││────┼────│
24
+ │ X21 │ X22 │ │ │ U2 ││ 0 0 0 │ I 0 0 ││ │ V2 │
25
+ └ ┘ └ ┘│ 0 S 0 │ 0 C 0 │└ ┘
26
+ │ 0 0 I │ 0 0 0 │
27
+ └ ┘
28
+
29
+ ``U1``, ``U2``, ``V1``, ``V2`` are square orthogonal/unitary matrices of
30
+ dimensions ``(p,p)``, ``(m-p,m-p)``, ``(q,q)``, and ``(m-q,m-q)``
31
+ respectively, and ``C`` and ``S`` are ``(r, r)`` nonnegative diagonal
32
+ matrices satisfying ``C^2 + S^2 = I`` where ``r = min(p, m-p, q, m-q)``.
33
+
34
+ Moreover, the rank of the identity matrices are ``min(p, q) - r``,
35
+ ``min(p, m - q) - r``, ``min(m - p, q) - r``, and ``min(m - p, m - q) - r``
36
+ respectively.
37
+
38
+ X can be supplied either by itself and block specifications p, q or its
39
+ subblocks in an iterable from which the shapes would be derived. See the
40
+ examples below.
41
+
42
+ Parameters
43
+ ----------
44
+ X : array_like, iterable
45
+ complex unitary or real orthogonal matrix to be decomposed, or iterable
46
+ of subblocks ``X11``, ``X12``, ``X21``, ``X22``, when ``p``, ``q`` are
47
+ omitted.
48
+ p : int, optional
49
+ Number of rows of the upper left block ``X11``, used only when X is
50
+ given as an array.
51
+ q : int, optional
52
+ Number of columns of the upper left block ``X11``, used only when X is
53
+ given as an array.
54
+ separate : bool, optional
55
+ if ``True``, the low level components are returned instead of the
56
+ matrix factors, i.e. ``(u1,u2)``, ``theta``, ``(v1h,v2h)`` instead of
57
+ ``u``, ``cs``, ``vh``.
58
+ swap_sign : bool, optional
59
+ if ``True``, the ``-S``, ``-I`` block will be the bottom left,
60
+ otherwise (by default) they will be in the upper right block.
61
+ compute_u : bool, optional
62
+ if ``False``, ``u`` won't be computed and an empty array is returned.
63
+ compute_vh : bool, optional
64
+ if ``False``, ``vh`` won't be computed and an empty array is returned.
65
+
66
+ Returns
67
+ -------
68
+ u : ndarray
69
+ When ``compute_u=True``, contains the block diagonal orthogonal/unitary
70
+ matrix consisting of the blocks ``U1`` (``p`` x ``p``) and ``U2``
71
+ (``m-p`` x ``m-p``) orthogonal/unitary matrices. If ``separate=True``,
72
+ this contains the tuple of ``(U1, U2)``.
73
+ cs : ndarray
74
+ The cosine-sine factor with the structure described above.
75
+ If ``separate=True``, this contains the ``theta`` array containing the
76
+ angles in radians.
77
+ vh : ndarray
78
+ When ``compute_vh=True`, contains the block diagonal orthogonal/unitary
79
+ matrix consisting of the blocks ``V1H`` (``q`` x ``q``) and ``V2H``
80
+ (``m-q`` x ``m-q``) orthogonal/unitary matrices. If ``separate=True``,
81
+ this contains the tuple of ``(V1H, V2H)``.
82
+
83
+ References
84
+ ----------
85
+ .. [1] Brian D. Sutton. Computing the complete CS decomposition. Numer.
86
+ Algorithms, 50(1):33-65, 2009.
87
+
88
+ Examples
89
+ --------
90
+ >>> import numpy as np
91
+ >>> from scipy.linalg import cossin
92
+ >>> from scipy.stats import unitary_group
93
+ >>> x = unitary_group.rvs(4)
94
+ >>> u, cs, vdh = cossin(x, p=2, q=2)
95
+ >>> np.allclose(x, u @ cs @ vdh)
96
+ True
97
+
98
+ Same can be entered via subblocks without the need of ``p`` and ``q``. Also
99
+ let's skip the computation of ``u``
100
+
101
+ >>> ue, cs, vdh = cossin((x[:2, :2], x[:2, 2:], x[2:, :2], x[2:, 2:]),
102
+ ... compute_u=False)
103
+ >>> print(ue)
104
+ []
105
+ >>> np.allclose(x, u @ cs @ vdh)
106
+ True
107
+
108
+ """
109
+
110
+ if p or q:
111
+ p = 1 if p is None else int(p)
112
+ q = 1 if q is None else int(q)
113
+ X = _asarray_validated(X, check_finite=True)
114
+ if not np.equal(*X.shape):
115
+ raise ValueError("Cosine Sine decomposition only supports square"
116
+ f" matrices, got {X.shape}")
117
+ m = X.shape[0]
118
+ if p >= m or p <= 0:
119
+ raise ValueError(f"invalid p={p}, 0<p<{X.shape[0]} must hold")
120
+ if q >= m or q <= 0:
121
+ raise ValueError(f"invalid q={q}, 0<q<{X.shape[0]} must hold")
122
+
123
+ x11, x12, x21, x22 = X[:p, :q], X[:p, q:], X[p:, :q], X[p:, q:]
124
+ elif not isinstance(X, Iterable):
125
+ raise ValueError("When p and q are None, X must be an Iterable"
126
+ " containing the subblocks of X")
127
+ else:
128
+ if len(X) != 4:
129
+ raise ValueError("When p and q are None, exactly four arrays"
130
+ f" should be in X, got {len(X)}")
131
+
132
+ x11, x12, x21, x22 = (np.atleast_2d(x) for x in X)
133
+ for name, block in zip(["x11", "x12", "x21", "x22"],
134
+ [x11, x12, x21, x22]):
135
+ if block.shape[1] == 0:
136
+ raise ValueError(f"{name} can't be empty")
137
+ p, q = x11.shape
138
+ mmp, mmq = x22.shape
139
+
140
+ if x12.shape != (p, mmq):
141
+ raise ValueError(f"Invalid x12 dimensions: desired {(p, mmq)}, "
142
+ f"got {x12.shape}")
143
+
144
+ if x21.shape != (mmp, q):
145
+ raise ValueError(f"Invalid x21 dimensions: desired {(mmp, q)}, "
146
+ f"got {x21.shape}")
147
+
148
+ if p + mmp != q + mmq:
149
+ raise ValueError("The subblocks have compatible sizes but "
150
+ "don't form a square array (instead they form a"
151
+ " {}x{} array). This might be due to missing "
152
+ "p, q arguments.".format(p + mmp, q + mmq))
153
+
154
+ m = p + mmp
155
+
156
+ cplx = any([np.iscomplexobj(x) for x in [x11, x12, x21, x22]])
157
+ driver = "uncsd" if cplx else "orcsd"
158
+ csd, csd_lwork = get_lapack_funcs([driver, driver + "_lwork"],
159
+ [x11, x12, x21, x22])
160
+ lwork = _compute_lwork(csd_lwork, m=m, p=p, q=q)
161
+ lwork_args = ({'lwork': lwork[0], 'lrwork': lwork[1]} if cplx else
162
+ {'lwork': lwork})
163
+ *_, theta, u1, u2, v1h, v2h, info = csd(x11=x11, x12=x12, x21=x21, x22=x22,
164
+ compute_u1=compute_u,
165
+ compute_u2=compute_u,
166
+ compute_v1t=compute_vh,
167
+ compute_v2t=compute_vh,
168
+ trans=False, signs=swap_sign,
169
+ **lwork_args)
170
+
171
+ method_name = csd.typecode + driver
172
+ if info < 0:
173
+ raise ValueError(f'illegal value in argument {-info} '
174
+ f'of internal {method_name}')
175
+ if info > 0:
176
+ raise LinAlgError(f"{method_name} did not converge: {info}")
177
+
178
+ if separate:
179
+ return (u1, u2), theta, (v1h, v2h)
180
+
181
+ U = block_diag(u1, u2)
182
+ VDH = block_diag(v1h, v2h)
183
+
184
+ # Construct the middle factor CS
185
+ c = np.diag(np.cos(theta))
186
+ s = np.diag(np.sin(theta))
187
+ r = min(p, q, m - p, m - q)
188
+ n11 = min(p, q) - r
189
+ n12 = min(p, m - q) - r
190
+ n21 = min(m - p, q) - r
191
+ n22 = min(m - p, m - q) - r
192
+ Id = np.eye(np.max([n11, n12, n21, n22, r]), dtype=theta.dtype)
193
+ CS = np.zeros((m, m), dtype=theta.dtype)
194
+
195
+ CS[:n11, :n11] = Id[:n11, :n11]
196
+
197
+ xs = n11 + r
198
+ xe = n11 + r + n12
199
+ ys = n11 + n21 + n22 + 2 * r
200
+ ye = n11 + n21 + n22 + 2 * r + n12
201
+ CS[xs: xe, ys:ye] = Id[:n12, :n12] if swap_sign else -Id[:n12, :n12]
202
+
203
+ xs = p + n22 + r
204
+ xe = p + n22 + r + + n21
205
+ ys = n11 + r
206
+ ye = n11 + r + n21
207
+ CS[xs:xe, ys:ye] = -Id[:n21, :n21] if swap_sign else Id[:n21, :n21]
208
+
209
+ CS[p:p + n22, q:q + n22] = Id[:n22, :n22]
210
+ CS[n11:n11 + r, n11:n11 + r] = c
211
+ CS[p + n22:p + n22 + r, r + n21 + n22:2 * r + n21 + n22] = c
212
+
213
+ xs = n11
214
+ xe = n11 + r
215
+ ys = n11 + n21 + n22 + r
216
+ ye = n11 + n21 + n22 + 2 * r
217
+ CS[xs:xe, ys:ye] = s if swap_sign else -s
218
+
219
+ CS[p + n22:p + n22 + r, n11:n11 + r] = -s if swap_sign else s
220
+
221
+ return U, CS, VDH
astra_scene_test/Scene_04/.venv/lib/python3.9/site-packages/scipy/linalg/_decomp_ldl.py ADDED
@@ -0,0 +1,353 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from warnings import warn
2
+
3
+ import numpy as np
4
+ from numpy import (atleast_2d, arange, zeros_like, imag, diag,
5
+ iscomplexobj, tril, triu, argsort, empty_like)
6
+ from scipy._lib._util import ComplexWarning
7
+ from ._decomp import _asarray_validated
8
+ from .lapack import get_lapack_funcs, _compute_lwork
9
+
10
+ __all__ = ['ldl']
11
+
12
+
13
+ def ldl(A, lower=True, hermitian=True, overwrite_a=False, check_finite=True):
14
+ """ Computes the LDLt or Bunch-Kaufman factorization of a symmetric/
15
+ hermitian matrix.
16
+
17
+ This function returns a block diagonal matrix D consisting blocks of size
18
+ at most 2x2 and also a possibly permuted unit lower triangular matrix
19
+ ``L`` such that the factorization ``A = L D L^H`` or ``A = L D L^T``
20
+ holds. If `lower` is False then (again possibly permuted) upper
21
+ triangular matrices are returned as outer factors.
22
+
23
+ The permutation array can be used to triangularize the outer factors
24
+ simply by a row shuffle, i.e., ``lu[perm, :]`` is an upper/lower
25
+ triangular matrix. This is also equivalent to multiplication with a
26
+ permutation matrix ``P.dot(lu)``, where ``P`` is a column-permuted
27
+ identity matrix ``I[:, perm]``.
28
+
29
+ Depending on the value of the boolean `lower`, only upper or lower
30
+ triangular part of the input array is referenced. Hence, a triangular
31
+ matrix on entry would give the same result as if the full matrix is
32
+ supplied.
33
+
34
+ Parameters
35
+ ----------
36
+ A : array_like
37
+ Square input array
38
+ lower : bool, optional
39
+ This switches between the lower and upper triangular outer factors of
40
+ the factorization. Lower triangular (``lower=True``) is the default.
41
+ hermitian : bool, optional
42
+ For complex-valued arrays, this defines whether ``A = A.conj().T`` or
43
+ ``A = A.T`` is assumed. For real-valued arrays, this switch has no
44
+ effect.
45
+ overwrite_a : bool, optional
46
+ Allow overwriting data in `A` (may enhance performance). The default
47
+ is False.
48
+ check_finite : bool, optional
49
+ Whether to check that the input matrices contain only finite numbers.
50
+ Disabling may give a performance gain, but may result in problems
51
+ (crashes, non-termination) if the inputs do contain infinities or NaNs.
52
+
53
+ Returns
54
+ -------
55
+ lu : ndarray
56
+ The (possibly) permuted upper/lower triangular outer factor of the
57
+ factorization.
58
+ d : ndarray
59
+ The block diagonal multiplier of the factorization.
60
+ perm : ndarray
61
+ The row-permutation index array that brings lu into triangular form.
62
+
63
+ Raises
64
+ ------
65
+ ValueError
66
+ If input array is not square.
67
+ ComplexWarning
68
+ If a complex-valued array with nonzero imaginary parts on the
69
+ diagonal is given and hermitian is set to True.
70
+
71
+ See Also
72
+ --------
73
+ cholesky, lu
74
+
75
+ Notes
76
+ -----
77
+ This function uses ``?SYTRF`` routines for symmetric matrices and
78
+ ``?HETRF`` routines for Hermitian matrices from LAPACK. See [1]_ for
79
+ the algorithm details.
80
+
81
+ Depending on the `lower` keyword value, only lower or upper triangular
82
+ part of the input array is referenced. Moreover, this keyword also defines
83
+ the structure of the outer factors of the factorization.
84
+
85
+ .. versionadded:: 1.1.0
86
+
87
+ References
88
+ ----------
89
+ .. [1] J.R. Bunch, L. Kaufman, Some stable methods for calculating
90
+ inertia and solving symmetric linear systems, Math. Comput. Vol.31,
91
+ 1977. :doi:`10.2307/2005787`
92
+
93
+ Examples
94
+ --------
95
+ Given an upper triangular array ``a`` that represents the full symmetric
96
+ array with its entries, obtain ``l``, 'd' and the permutation vector `perm`:
97
+
98
+ >>> import numpy as np
99
+ >>> from scipy.linalg import ldl
100
+ >>> a = np.array([[2, -1, 3], [0, 2, 0], [0, 0, 1]])
101
+ >>> lu, d, perm = ldl(a, lower=0) # Use the upper part
102
+ >>> lu
103
+ array([[ 0. , 0. , 1. ],
104
+ [ 0. , 1. , -0.5],
105
+ [ 1. , 1. , 1.5]])
106
+ >>> d
107
+ array([[-5. , 0. , 0. ],
108
+ [ 0. , 1.5, 0. ],
109
+ [ 0. , 0. , 2. ]])
110
+ >>> perm
111
+ array([2, 1, 0])
112
+ >>> lu[perm, :]
113
+ array([[ 1. , 1. , 1.5],
114
+ [ 0. , 1. , -0.5],
115
+ [ 0. , 0. , 1. ]])
116
+ >>> lu.dot(d).dot(lu.T)
117
+ array([[ 2., -1., 3.],
118
+ [-1., 2., 0.],
119
+ [ 3., 0., 1.]])
120
+
121
+ """
122
+ a = atleast_2d(_asarray_validated(A, check_finite=check_finite))
123
+ if a.shape[0] != a.shape[1]:
124
+ raise ValueError('The input array "a" should be square.')
125
+ # Return empty arrays for empty square input
126
+ if a.size == 0:
127
+ return empty_like(a), empty_like(a), np.array([], dtype=int)
128
+
129
+ n = a.shape[0]
130
+ r_or_c = complex if iscomplexobj(a) else float
131
+
132
+ # Get the LAPACK routine
133
+ if r_or_c is complex and hermitian:
134
+ s, sl = 'hetrf', 'hetrf_lwork'
135
+ if np.any(imag(diag(a))):
136
+ warn('scipy.linalg.ldl():\nThe imaginary parts of the diagonal'
137
+ 'are ignored. Use "hermitian=False" for factorization of'
138
+ 'complex symmetric arrays.', ComplexWarning, stacklevel=2)
139
+ else:
140
+ s, sl = 'sytrf', 'sytrf_lwork'
141
+
142
+ solver, solver_lwork = get_lapack_funcs((s, sl), (a,))
143
+ lwork = _compute_lwork(solver_lwork, n, lower=lower)
144
+ ldu, piv, info = solver(a, lwork=lwork, lower=lower,
145
+ overwrite_a=overwrite_a)
146
+ if info < 0:
147
+ raise ValueError(f'{s.upper()} exited with the internal error "illegal value '
148
+ f'in argument number {-info}". See LAPACK documentation '
149
+ 'for the error codes.')
150
+
151
+ swap_arr, pivot_arr = _ldl_sanitize_ipiv(piv, lower=lower)
152
+ d, lu = _ldl_get_d_and_l(ldu, pivot_arr, lower=lower, hermitian=hermitian)
153
+ lu, perm = _ldl_construct_tri_factor(lu, swap_arr, pivot_arr, lower=lower)
154
+
155
+ return lu, d, perm
156
+
157
+
158
+ def _ldl_sanitize_ipiv(a, lower=True):
159
+ """
160
+ This helper function takes the rather strangely encoded permutation array
161
+ returned by the LAPACK routines ?(HE/SY)TRF and converts it into
162
+ regularized permutation and diagonal pivot size format.
163
+
164
+ Since FORTRAN uses 1-indexing and LAPACK uses different start points for
165
+ upper and lower formats there are certain offsets in the indices used
166
+ below.
167
+
168
+ Let's assume a result where the matrix is 6x6 and there are two 2x2
169
+ and two 1x1 blocks reported by the routine. To ease the coding efforts,
170
+ we still populate a 6-sized array and fill zeros as the following ::
171
+
172
+ pivots = [2, 0, 2, 0, 1, 1]
173
+
174
+ This denotes a diagonal matrix of the form ::
175
+
176
+ [x x ]
177
+ [x x ]
178
+ [ x x ]
179
+ [ x x ]
180
+ [ x ]
181
+ [ x]
182
+
183
+ In other words, we write 2 when the 2x2 block is first encountered and
184
+ automatically write 0 to the next entry and skip the next spin of the
185
+ loop. Thus, a separate counter or array appends to keep track of block
186
+ sizes are avoided. If needed, zeros can be filtered out later without
187
+ losing the block structure.
188
+
189
+ Parameters
190
+ ----------
191
+ a : ndarray
192
+ The permutation array ipiv returned by LAPACK
193
+ lower : bool, optional
194
+ The switch to select whether upper or lower triangle is chosen in
195
+ the LAPACK call.
196
+
197
+ Returns
198
+ -------
199
+ swap_ : ndarray
200
+ The array that defines the row/column swap operations. For example,
201
+ if row two is swapped with row four, the result is [0, 3, 2, 3].
202
+ pivots : ndarray
203
+ The array that defines the block diagonal structure as given above.
204
+
205
+ """
206
+ n = a.size
207
+ swap_ = arange(n)
208
+ pivots = zeros_like(swap_, dtype=int)
209
+ skip_2x2 = False
210
+
211
+ # Some upper/lower dependent offset values
212
+ # range (s)tart, r(e)nd, r(i)ncrement
213
+ x, y, rs, re, ri = (1, 0, 0, n, 1) if lower else (-1, -1, n-1, -1, -1)
214
+
215
+ for ind in range(rs, re, ri):
216
+ # If previous spin belonged already to a 2x2 block
217
+ if skip_2x2:
218
+ skip_2x2 = False
219
+ continue
220
+
221
+ cur_val = a[ind]
222
+ # do we have a 1x1 block or not?
223
+ if cur_val > 0:
224
+ if cur_val != ind+1:
225
+ # Index value != array value --> permutation required
226
+ swap_[ind] = swap_[cur_val-1]
227
+ pivots[ind] = 1
228
+ # Not.
229
+ elif cur_val < 0 and cur_val == a[ind+x]:
230
+ # first neg entry of 2x2 block identifier
231
+ if -cur_val != ind+2:
232
+ # Index value != array value --> permutation required
233
+ swap_[ind+x] = swap_[-cur_val-1]
234
+ pivots[ind+y] = 2
235
+ skip_2x2 = True
236
+ else: # Doesn't make sense, give up
237
+ raise ValueError('While parsing the permutation array '
238
+ 'in "scipy.linalg.ldl", invalid entries '
239
+ 'found. The array syntax is invalid.')
240
+ return swap_, pivots
241
+
242
+
243
+ def _ldl_get_d_and_l(ldu, pivs, lower=True, hermitian=True):
244
+ """
245
+ Helper function to extract the diagonal and triangular matrices for
246
+ LDL.T factorization.
247
+
248
+ Parameters
249
+ ----------
250
+ ldu : ndarray
251
+ The compact output returned by the LAPACK routing
252
+ pivs : ndarray
253
+ The sanitized array of {0, 1, 2} denoting the sizes of the pivots. For
254
+ every 2 there is a succeeding 0.
255
+ lower : bool, optional
256
+ If set to False, upper triangular part is considered.
257
+ hermitian : bool, optional
258
+ If set to False a symmetric complex array is assumed.
259
+
260
+ Returns
261
+ -------
262
+ d : ndarray
263
+ The block diagonal matrix.
264
+ lu : ndarray
265
+ The upper/lower triangular matrix
266
+ """
267
+ is_c = iscomplexobj(ldu)
268
+ d = diag(diag(ldu))
269
+ n = d.shape[0]
270
+ blk_i = 0 # block index
271
+
272
+ # row/column offsets for selecting sub-, super-diagonal
273
+ x, y = (1, 0) if lower else (0, 1)
274
+
275
+ lu = tril(ldu, -1) if lower else triu(ldu, 1)
276
+ diag_inds = arange(n)
277
+ lu[diag_inds, diag_inds] = 1
278
+
279
+ for blk in pivs[pivs != 0]:
280
+ # increment the block index and check for 2s
281
+ # if 2 then copy the off diagonals depending on uplo
282
+ inc = blk_i + blk
283
+
284
+ if blk == 2:
285
+ d[blk_i+x, blk_i+y] = ldu[blk_i+x, blk_i+y]
286
+ # If Hermitian matrix is factorized, the cross-offdiagonal element
287
+ # should be conjugated.
288
+ if is_c and hermitian:
289
+ d[blk_i+y, blk_i+x] = ldu[blk_i+x, blk_i+y].conj()
290
+ else:
291
+ d[blk_i+y, blk_i+x] = ldu[blk_i+x, blk_i+y]
292
+
293
+ lu[blk_i+x, blk_i+y] = 0.
294
+ blk_i = inc
295
+
296
+ return d, lu
297
+
298
+
299
+ def _ldl_construct_tri_factor(lu, swap_vec, pivs, lower=True):
300
+ """
301
+ Helper function to construct explicit outer factors of LDL factorization.
302
+
303
+ If lower is True the permuted factors are multiplied as L(1)*L(2)*...*L(k).
304
+ Otherwise, the permuted factors are multiplied as L(k)*...*L(2)*L(1). See
305
+ LAPACK documentation for more details.
306
+
307
+ Parameters
308
+ ----------
309
+ lu : ndarray
310
+ The triangular array that is extracted from LAPACK routine call with
311
+ ones on the diagonals.
312
+ swap_vec : ndarray
313
+ The array that defines the row swapping indices. If the kth entry is m
314
+ then rows k,m are swapped. Notice that the mth entry is not necessarily
315
+ k to avoid undoing the swapping.
316
+ pivs : ndarray
317
+ The array that defines the block diagonal structure returned by
318
+ _ldl_sanitize_ipiv().
319
+ lower : bool, optional
320
+ The boolean to switch between lower and upper triangular structure.
321
+
322
+ Returns
323
+ -------
324
+ lu : ndarray
325
+ The square outer factor which satisfies the L * D * L.T = A
326
+ perm : ndarray
327
+ The permutation vector that brings the lu to the triangular form
328
+
329
+ Notes
330
+ -----
331
+ Note that the original argument "lu" is overwritten.
332
+
333
+ """
334
+ n = lu.shape[0]
335
+ perm = arange(n)
336
+ # Setup the reading order of the permutation matrix for upper/lower
337
+ rs, re, ri = (n-1, -1, -1) if lower else (0, n, 1)
338
+
339
+ for ind in range(rs, re, ri):
340
+ s_ind = swap_vec[ind]
341
+ if s_ind != ind:
342
+ # Column start and end positions
343
+ col_s = ind if lower else 0
344
+ col_e = n if lower else ind+1
345
+
346
+ # If we stumble upon a 2x2 block include both cols in the perm.
347
+ if pivs[ind] == (0 if lower else 2):
348
+ col_s += -1 if lower else 0
349
+ col_e += 0 if lower else 1
350
+ lu[[s_ind, ind], col_s:col_e] = lu[[ind, s_ind], col_s:col_e]
351
+ perm[[s_ind, ind]] = perm[[ind, s_ind]]
352
+
353
+ return lu, argsort(perm)
astra_scene_test/Scene_04/.venv/lib/python3.9/site-packages/scipy/linalg/_decomp_lu.py ADDED
@@ -0,0 +1,374 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """LU decomposition functions."""
2
+
3
+ from warnings import warn
4
+
5
+ from numpy import asarray, asarray_chkfinite
6
+ import numpy as np
7
+ from itertools import product
8
+
9
+ # Local imports
10
+ from ._misc import _datacopied, LinAlgWarning
11
+ from .lapack import get_lapack_funcs
12
+ from ._decomp_lu_cython import lu_dispatcher
13
+
14
+ lapack_cast_dict = {x: ''.join([y for y in 'fdFD' if np.can_cast(x, y)])
15
+ for x in np.typecodes['All']}
16
+
17
+ __all__ = ['lu', 'lu_solve', 'lu_factor']
18
+
19
+
20
+ def lu_factor(a, overwrite_a=False, check_finite=True):
21
+ """
22
+ Compute pivoted LU decomposition of a matrix.
23
+
24
+ The decomposition is::
25
+
26
+ A = P L U
27
+
28
+ where P is a permutation matrix, L lower triangular with unit
29
+ diagonal elements, and U upper triangular.
30
+
31
+ Parameters
32
+ ----------
33
+ a : (M, N) array_like
34
+ Matrix to decompose
35
+ overwrite_a : bool, optional
36
+ Whether to overwrite data in A (may increase performance)
37
+ check_finite : bool, optional
38
+ Whether to check that the input matrix contains only finite numbers.
39
+ Disabling may give a performance gain, but may result in problems
40
+ (crashes, non-termination) if the inputs do contain infinities or NaNs.
41
+
42
+ Returns
43
+ -------
44
+ lu : (M, N) ndarray
45
+ Matrix containing U in its upper triangle, and L in its lower triangle.
46
+ The unit diagonal elements of L are not stored.
47
+ piv : (K,) ndarray
48
+ Pivot indices representing the permutation matrix P:
49
+ row i of matrix was interchanged with row piv[i].
50
+ Of shape ``(K,)``, with ``K = min(M, N)``.
51
+
52
+ See Also
53
+ --------
54
+ lu : gives lu factorization in more user-friendly format
55
+ lu_solve : solve an equation system using the LU factorization of a matrix
56
+
57
+ Notes
58
+ -----
59
+ This is a wrapper to the ``*GETRF`` routines from LAPACK. Unlike
60
+ :func:`lu`, it outputs the L and U factors into a single array
61
+ and returns pivot indices instead of a permutation matrix.
62
+
63
+ While the underlying ``*GETRF`` routines return 1-based pivot indices, the
64
+ ``piv`` array returned by ``lu_factor`` contains 0-based indices.
65
+
66
+ Examples
67
+ --------
68
+ >>> import numpy as np
69
+ >>> from scipy.linalg import lu_factor
70
+ >>> A = np.array([[2, 5, 8, 7], [5, 2, 2, 8], [7, 5, 6, 6], [5, 4, 4, 8]])
71
+ >>> lu, piv = lu_factor(A)
72
+ >>> piv
73
+ array([2, 2, 3, 3], dtype=int32)
74
+
75
+ Convert LAPACK's ``piv`` array to NumPy index and test the permutation
76
+
77
+ >>> def pivot_to_permutation(piv):
78
+ ... perm = np.arange(len(piv))
79
+ ... for i in range(len(piv)):
80
+ ... perm[i], perm[piv[i]] = perm[piv[i]], perm[i]
81
+ ... return perm
82
+ ...
83
+ >>> p_inv = pivot_to_permutation(piv)
84
+ >>> p_inv
85
+ array([2, 0, 3, 1])
86
+ >>> L, U = np.tril(lu, k=-1) + np.eye(4), np.triu(lu)
87
+ >>> np.allclose(A[p_inv] - L @ U, np.zeros((4, 4)))
88
+ True
89
+
90
+ The P matrix in P L U is defined by the inverse permutation and
91
+ can be recovered using argsort:
92
+
93
+ >>> p = np.argsort(p_inv)
94
+ >>> p
95
+ array([1, 3, 0, 2])
96
+ >>> np.allclose(A - L[p] @ U, np.zeros((4, 4)))
97
+ True
98
+
99
+ or alternatively:
100
+
101
+ >>> P = np.eye(4)[p]
102
+ >>> np.allclose(A - P @ L @ U, np.zeros((4, 4)))
103
+ True
104
+ """
105
+ if check_finite:
106
+ a1 = asarray_chkfinite(a)
107
+ else:
108
+ a1 = asarray(a)
109
+ overwrite_a = overwrite_a or (_datacopied(a1, a))
110
+ getrf, = get_lapack_funcs(('getrf',), (a1,))
111
+ lu, piv, info = getrf(a1, overwrite_a=overwrite_a)
112
+ if info < 0:
113
+ raise ValueError('illegal value in %dth argument of '
114
+ 'internal getrf (lu_factor)' % -info)
115
+ if info > 0:
116
+ warn("Diagonal number %d is exactly zero. Singular matrix." % info,
117
+ LinAlgWarning, stacklevel=2)
118
+ return lu, piv
119
+
120
+
121
+ def lu_solve(lu_and_piv, b, trans=0, overwrite_b=False, check_finite=True):
122
+ """Solve an equation system, a x = b, given the LU factorization of a
123
+
124
+ Parameters
125
+ ----------
126
+ (lu, piv)
127
+ Factorization of the coefficient matrix a, as given by lu_factor.
128
+ In particular piv are 0-indexed pivot indices.
129
+ b : array
130
+ Right-hand side
131
+ trans : {0, 1, 2}, optional
132
+ Type of system to solve:
133
+
134
+ ===== =========
135
+ trans system
136
+ ===== =========
137
+ 0 a x = b
138
+ 1 a^T x = b
139
+ 2 a^H x = b
140
+ ===== =========
141
+ overwrite_b : bool, optional
142
+ Whether to overwrite data in b (may increase performance)
143
+ check_finite : bool, optional
144
+ Whether to check that the input matrices contain only finite numbers.
145
+ Disabling may give a performance gain, but may result in problems
146
+ (crashes, non-termination) if the inputs do contain infinities or NaNs.
147
+
148
+ Returns
149
+ -------
150
+ x : array
151
+ Solution to the system
152
+
153
+ See Also
154
+ --------
155
+ lu_factor : LU factorize a matrix
156
+
157
+ Examples
158
+ --------
159
+ >>> import numpy as np
160
+ >>> from scipy.linalg import lu_factor, lu_solve
161
+ >>> A = np.array([[2, 5, 8, 7], [5, 2, 2, 8], [7, 5, 6, 6], [5, 4, 4, 8]])
162
+ >>> b = np.array([1, 1, 1, 1])
163
+ >>> lu, piv = lu_factor(A)
164
+ >>> x = lu_solve((lu, piv), b)
165
+ >>> np.allclose(A @ x - b, np.zeros((4,)))
166
+ True
167
+
168
+ """
169
+ (lu, piv) = lu_and_piv
170
+ if check_finite:
171
+ b1 = asarray_chkfinite(b)
172
+ else:
173
+ b1 = asarray(b)
174
+ overwrite_b = overwrite_b or _datacopied(b1, b)
175
+ if lu.shape[0] != b1.shape[0]:
176
+ raise ValueError(f"Shapes of lu {lu.shape} and b {b1.shape} are incompatible")
177
+
178
+ getrs, = get_lapack_funcs(('getrs',), (lu, b1))
179
+ x, info = getrs(lu, piv, b1, trans=trans, overwrite_b=overwrite_b)
180
+ if info == 0:
181
+ return x
182
+ raise ValueError('illegal value in %dth argument of internal gesv|posv'
183
+ % -info)
184
+
185
+
186
+ def lu(a, permute_l=False, overwrite_a=False, check_finite=True,
187
+ p_indices=False):
188
+ """
189
+ Compute LU decomposition of a matrix with partial pivoting.
190
+
191
+ The decomposition satisfies::
192
+
193
+ A = P @ L @ U
194
+
195
+ where ``P`` is a permutation matrix, ``L`` lower triangular with unit
196
+ diagonal elements, and ``U`` upper triangular. If `permute_l` is set to
197
+ ``True`` then ``L`` is returned already permuted and hence satisfying
198
+ ``A = L @ U``.
199
+
200
+ Parameters
201
+ ----------
202
+ a : (M, N) array_like
203
+ Array to decompose
204
+ permute_l : bool, optional
205
+ Perform the multiplication P*L (Default: do not permute)
206
+ overwrite_a : bool, optional
207
+ Whether to overwrite data in a (may improve performance)
208
+ check_finite : bool, optional
209
+ Whether to check that the input matrix contains only finite numbers.
210
+ Disabling may give a performance gain, but may result in problems
211
+ (crashes, non-termination) if the inputs do contain infinities or NaNs.
212
+ p_indices : bool, optional
213
+ If ``True`` the permutation information is returned as row indices.
214
+ The default is ``False`` for backwards-compatibility reasons.
215
+
216
+ Returns
217
+ -------
218
+ **(If `permute_l` is ``False``)**
219
+
220
+ p : (..., M, M) ndarray
221
+ Permutation arrays or vectors depending on `p_indices`
222
+ l : (..., M, K) ndarray
223
+ Lower triangular or trapezoidal array with unit diagonal.
224
+ ``K = min(M, N)``
225
+ u : (..., K, N) ndarray
226
+ Upper triangular or trapezoidal array
227
+
228
+ **(If `permute_l` is ``True``)**
229
+
230
+ pl : (..., M, K) ndarray
231
+ Permuted L matrix.
232
+ ``K = min(M, N)``
233
+ u : (..., K, N) ndarray
234
+ Upper triangular or trapezoidal array
235
+
236
+ Notes
237
+ -----
238
+ Permutation matrices are costly since they are nothing but row reorder of
239
+ ``L`` and hence indices are strongly recommended to be used instead if the
240
+ permutation is required. The relation in the 2D case then becomes simply
241
+ ``A = L[P, :] @ U``. In higher dimensions, it is better to use `permute_l`
242
+ to avoid complicated indexing tricks.
243
+
244
+ In 2D case, if one has the indices however, for some reason, the
245
+ permutation matrix is still needed then it can be constructed by
246
+ ``np.eye(M)[P, :]``.
247
+
248
+ Examples
249
+ --------
250
+
251
+ >>> import numpy as np
252
+ >>> from scipy.linalg import lu
253
+ >>> A = np.array([[2, 5, 8, 7], [5, 2, 2, 8], [7, 5, 6, 6], [5, 4, 4, 8]])
254
+ >>> p, l, u = lu(A)
255
+ >>> np.allclose(A, p @ l @ u)
256
+ True
257
+ >>> p # Permutation matrix
258
+ array([[0., 1., 0., 0.], # Row index 1
259
+ [0., 0., 0., 1.], # Row index 3
260
+ [1., 0., 0., 0.], # Row index 0
261
+ [0., 0., 1., 0.]]) # Row index 2
262
+ >>> p, _, _ = lu(A, p_indices=True)
263
+ >>> p
264
+ array([1, 3, 0, 2]) # as given by row indices above
265
+ >>> np.allclose(A, l[p, :] @ u)
266
+ True
267
+
268
+ We can also use nd-arrays, for example, a demonstration with 4D array:
269
+
270
+ >>> rng = np.random.default_rng()
271
+ >>> A = rng.uniform(low=-4, high=4, size=[3, 2, 4, 8])
272
+ >>> p, l, u = lu(A)
273
+ >>> p.shape, l.shape, u.shape
274
+ ((3, 2, 4, 4), (3, 2, 4, 4), (3, 2, 4, 8))
275
+ >>> np.allclose(A, p @ l @ u)
276
+ True
277
+ >>> PL, U = lu(A, permute_l=True)
278
+ >>> np.allclose(A, PL @ U)
279
+ True
280
+
281
+ """
282
+ a1 = np.asarray_chkfinite(a) if check_finite else np.asarray(a)
283
+ if a1.ndim < 2:
284
+ raise ValueError('The input array must be at least two-dimensional.')
285
+
286
+ # Also check if dtype is LAPACK compatible
287
+ if a1.dtype.char not in 'fdFD':
288
+ dtype_char = lapack_cast_dict[a1.dtype.char]
289
+ if not dtype_char: # No casting possible
290
+ raise TypeError(f'The dtype {a1.dtype} cannot be cast '
291
+ 'to float(32, 64) or complex(64, 128).')
292
+
293
+ a1 = a1.astype(dtype_char[0]) # makes a copy, free to scratch
294
+ overwrite_a = True
295
+
296
+ *nd, m, n = a1.shape
297
+ k = min(m, n)
298
+ real_dchar = 'f' if a1.dtype.char in 'fF' else 'd'
299
+
300
+ # Empty input
301
+ if min(*a1.shape) == 0:
302
+ if permute_l:
303
+ PL = np.empty(shape=[*nd, m, k], dtype=a1.dtype)
304
+ U = np.empty(shape=[*nd, k, n], dtype=a1.dtype)
305
+ return PL, U
306
+ else:
307
+ P = (np.empty([*nd, 0], dtype=np.int32) if p_indices else
308
+ np.empty([*nd, 0, 0], dtype=real_dchar))
309
+ L = np.empty(shape=[*nd, m, k], dtype=a1.dtype)
310
+ U = np.empty(shape=[*nd, k, n], dtype=a1.dtype)
311
+ return P, L, U
312
+
313
+ # Scalar case
314
+ if a1.shape[-2:] == (1, 1):
315
+ if permute_l:
316
+ return np.ones_like(a1), (a1 if overwrite_a else a1.copy())
317
+ else:
318
+ P = (np.zeros(shape=[*nd, m], dtype=int) if p_indices
319
+ else np.ones_like(a1))
320
+ return P, np.ones_like(a1), (a1 if overwrite_a else a1.copy())
321
+
322
+ # Then check overwrite permission
323
+ if not _datacopied(a1, a): # "a" still alive through "a1"
324
+ if not overwrite_a:
325
+ # Data belongs to "a" so make a copy
326
+ a1 = a1.copy(order='C')
327
+ # else: Do nothing we'll use "a" if possible
328
+ # else: a1 has its own data thus free to scratch
329
+
330
+ # Then layout checks, might happen that overwrite is allowed but original
331
+ # array was read-only or non-contiguous.
332
+
333
+ if not (a1.flags['C_CONTIGUOUS'] and a1.flags['WRITEABLE']):
334
+ a1 = a1.copy(order='C')
335
+
336
+ if not nd: # 2D array
337
+
338
+ p = np.empty(m, dtype=np.int32)
339
+ u = np.zeros([k, k], dtype=a1.dtype)
340
+ lu_dispatcher(a1, u, p, permute_l)
341
+ P, L, U = (p, a1, u) if m > n else (p, u, a1)
342
+
343
+ else: # Stacked array
344
+
345
+ # Prepare the contiguous data holders
346
+ P = np.empty([*nd, m], dtype=np.int32) # perm vecs
347
+
348
+ if m > n: # Tall arrays, U will be created
349
+ U = np.zeros([*nd, k, k], dtype=a1.dtype)
350
+ for ind in product(*[range(x) for x in a1.shape[:-2]]):
351
+ lu_dispatcher(a1[ind], U[ind], P[ind], permute_l)
352
+ L = a1
353
+
354
+ else: # Fat arrays, L will be created
355
+ L = np.zeros([*nd, k, k], dtype=a1.dtype)
356
+ for ind in product(*[range(x) for x in a1.shape[:-2]]):
357
+ lu_dispatcher(a1[ind], L[ind], P[ind], permute_l)
358
+ U = a1
359
+
360
+ # Convert permutation vecs to permutation arrays
361
+ # permute_l=False needed to enter here to avoid wasted efforts
362
+ if (not p_indices) and (not permute_l):
363
+ if nd:
364
+ Pa = np.zeros([*nd, m, m], dtype=real_dchar)
365
+ # An unreadable index hack - One-hot encoding for perm matrices
366
+ nd_ix = np.ix_(*([np.arange(x) for x in nd]+[np.arange(m)]))
367
+ Pa[(*nd_ix, P)] = 1
368
+ P = Pa
369
+ else: # 2D case
370
+ Pa = np.zeros([m, m], dtype=real_dchar)
371
+ Pa[np.arange(m), P] = 1
372
+ P = Pa
373
+
374
+ return (L, U) if permute_l else (P, L, U)
astra_scene_test/Scene_04/.venv/lib/python3.9/site-packages/scipy/linalg/_decomp_lu_cython.pyi ADDED
@@ -0,0 +1,6 @@
 
 
 
 
 
 
 
1
+ from numpy.typing import NDArray
2
+ from typing import Any
3
+
4
+ def lu_decompose(a: NDArray[Any], lu: NDArray[Any], perm: NDArray[Any], permute_l: bool) -> None: ... # noqa: E501
5
+
6
+ def lu_dispatcher(a: NDArray[Any], lu: NDArray[Any], perm: NDArray[Any], permute_l: bool) -> None: ... # noqa: E501
astra_scene_test/Scene_04/.venv/lib/python3.9/site-packages/scipy/linalg/_decomp_polar.py ADDED
@@ -0,0 +1,111 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import numpy as np
2
+ from scipy.linalg import svd
3
+
4
+
5
+ __all__ = ['polar']
6
+
7
+
8
+ def polar(a, side="right"):
9
+ """
10
+ Compute the polar decomposition.
11
+
12
+ Returns the factors of the polar decomposition [1]_ `u` and `p` such
13
+ that ``a = up`` (if `side` is "right") or ``a = pu`` (if `side` is
14
+ "left"), where `p` is positive semidefinite. Depending on the shape
15
+ of `a`, either the rows or columns of `u` are orthonormal. When `a`
16
+ is a square array, `u` is a square unitary array. When `a` is not
17
+ square, the "canonical polar decomposition" [2]_ is computed.
18
+
19
+ Parameters
20
+ ----------
21
+ a : (m, n) array_like
22
+ The array to be factored.
23
+ side : {'left', 'right'}, optional
24
+ Determines whether a right or left polar decomposition is computed.
25
+ If `side` is "right", then ``a = up``. If `side` is "left", then
26
+ ``a = pu``. The default is "right".
27
+
28
+ Returns
29
+ -------
30
+ u : (m, n) ndarray
31
+ If `a` is square, then `u` is unitary. If m > n, then the columns
32
+ of `a` are orthonormal, and if m < n, then the rows of `u` are
33
+ orthonormal.
34
+ p : ndarray
35
+ `p` is Hermitian positive semidefinite. If `a` is nonsingular, `p`
36
+ is positive definite. The shape of `p` is (n, n) or (m, m), depending
37
+ on whether `side` is "right" or "left", respectively.
38
+
39
+ References
40
+ ----------
41
+ .. [1] R. A. Horn and C. R. Johnson, "Matrix Analysis", Cambridge
42
+ University Press, 1985.
43
+ .. [2] N. J. Higham, "Functions of Matrices: Theory and Computation",
44
+ SIAM, 2008.
45
+
46
+ Examples
47
+ --------
48
+ >>> import numpy as np
49
+ >>> from scipy.linalg import polar
50
+ >>> a = np.array([[1, -1], [2, 4]])
51
+ >>> u, p = polar(a)
52
+ >>> u
53
+ array([[ 0.85749293, -0.51449576],
54
+ [ 0.51449576, 0.85749293]])
55
+ >>> p
56
+ array([[ 1.88648444, 1.2004901 ],
57
+ [ 1.2004901 , 3.94446746]])
58
+
59
+ A non-square example, with m < n:
60
+
61
+ >>> b = np.array([[0.5, 1, 2], [1.5, 3, 4]])
62
+ >>> u, p = polar(b)
63
+ >>> u
64
+ array([[-0.21196618, -0.42393237, 0.88054056],
65
+ [ 0.39378971, 0.78757942, 0.4739708 ]])
66
+ >>> p
67
+ array([[ 0.48470147, 0.96940295, 1.15122648],
68
+ [ 0.96940295, 1.9388059 , 2.30245295],
69
+ [ 1.15122648, 2.30245295, 3.65696431]])
70
+ >>> u.dot(p) # Verify the decomposition.
71
+ array([[ 0.5, 1. , 2. ],
72
+ [ 1.5, 3. , 4. ]])
73
+ >>> u.dot(u.T) # The rows of u are orthonormal.
74
+ array([[ 1.00000000e+00, -2.07353665e-17],
75
+ [ -2.07353665e-17, 1.00000000e+00]])
76
+
77
+ Another non-square example, with m > n:
78
+
79
+ >>> c = b.T
80
+ >>> u, p = polar(c)
81
+ >>> u
82
+ array([[-0.21196618, 0.39378971],
83
+ [-0.42393237, 0.78757942],
84
+ [ 0.88054056, 0.4739708 ]])
85
+ >>> p
86
+ array([[ 1.23116567, 1.93241587],
87
+ [ 1.93241587, 4.84930602]])
88
+ >>> u.dot(p) # Verify the decomposition.
89
+ array([[ 0.5, 1.5],
90
+ [ 1. , 3. ],
91
+ [ 2. , 4. ]])
92
+ >>> u.T.dot(u) # The columns of u are orthonormal.
93
+ array([[ 1.00000000e+00, -1.26363763e-16],
94
+ [ -1.26363763e-16, 1.00000000e+00]])
95
+
96
+ """
97
+ if side not in ['right', 'left']:
98
+ raise ValueError("`side` must be either 'right' or 'left'")
99
+ a = np.asarray(a)
100
+ if a.ndim != 2:
101
+ raise ValueError("`a` must be a 2-D array.")
102
+
103
+ w, s, vh = svd(a, full_matrices=False)
104
+ u = w.dot(vh)
105
+ if side == 'right':
106
+ # a = up
107
+ p = (vh.T.conj() * s).dot(vh)
108
+ else:
109
+ # a = pu
110
+ p = (w * s).dot(w.T.conj())
111
+ return u, p
astra_scene_test/Scene_04/.venv/lib/python3.9/site-packages/scipy/linalg/_decomp_qr.py ADDED
@@ -0,0 +1,430 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """QR decomposition functions."""
2
+ import numpy
3
+
4
+ # Local imports
5
+ from .lapack import get_lapack_funcs
6
+ from ._misc import _datacopied
7
+
8
+ __all__ = ['qr', 'qr_multiply', 'rq']
9
+
10
+
11
+ def safecall(f, name, *args, **kwargs):
12
+ """Call a LAPACK routine, determining lwork automatically and handling
13
+ error return values"""
14
+ lwork = kwargs.get("lwork", None)
15
+ if lwork in (None, -1):
16
+ kwargs['lwork'] = -1
17
+ ret = f(*args, **kwargs)
18
+ kwargs['lwork'] = ret[-2][0].real.astype(numpy.int_)
19
+ ret = f(*args, **kwargs)
20
+ if ret[-1] < 0:
21
+ raise ValueError("illegal value in %dth argument of internal %s"
22
+ % (-ret[-1], name))
23
+ return ret[:-2]
24
+
25
+
26
+ def qr(a, overwrite_a=False, lwork=None, mode='full', pivoting=False,
27
+ check_finite=True):
28
+ """
29
+ Compute QR decomposition of a matrix.
30
+
31
+ Calculate the decomposition ``A = Q R`` where Q is unitary/orthogonal
32
+ and R upper triangular.
33
+
34
+ Parameters
35
+ ----------
36
+ a : (M, N) array_like
37
+ Matrix to be decomposed
38
+ overwrite_a : bool, optional
39
+ Whether data in `a` is overwritten (may improve performance if
40
+ `overwrite_a` is set to True by reusing the existing input data
41
+ structure rather than creating a new one.)
42
+ lwork : int, optional
43
+ Work array size, lwork >= a.shape[1]. If None or -1, an optimal size
44
+ is computed.
45
+ mode : {'full', 'r', 'economic', 'raw'}, optional
46
+ Determines what information is to be returned: either both Q and R
47
+ ('full', default), only R ('r') or both Q and R but computed in
48
+ economy-size ('economic', see Notes). The final option 'raw'
49
+ (added in SciPy 0.11) makes the function return two matrices
50
+ (Q, TAU) in the internal format used by LAPACK.
51
+ pivoting : bool, optional
52
+ Whether or not factorization should include pivoting for rank-revealing
53
+ qr decomposition. If pivoting, compute the decomposition
54
+ ``A[:, P] = Q @ R`` as above, but where P is chosen such that the
55
+ diagonal of R is non-increasing.
56
+ check_finite : bool, optional
57
+ Whether to check that the input matrix contains only finite numbers.
58
+ Disabling may give a performance gain, but may result in problems
59
+ (crashes, non-termination) if the inputs do contain infinities or NaNs.
60
+
61
+ Returns
62
+ -------
63
+ Q : float or complex ndarray
64
+ Of shape (M, M), or (M, K) for ``mode='economic'``. Not returned
65
+ if ``mode='r'``. Replaced by tuple ``(Q, TAU)`` if ``mode='raw'``.
66
+ R : float or complex ndarray
67
+ Of shape (M, N), or (K, N) for ``mode in ['economic', 'raw']``.
68
+ ``K = min(M, N)``.
69
+ P : int ndarray
70
+ Of shape (N,) for ``pivoting=True``. Not returned if
71
+ ``pivoting=False``.
72
+
73
+ Raises
74
+ ------
75
+ LinAlgError
76
+ Raised if decomposition fails
77
+
78
+ Notes
79
+ -----
80
+ This is an interface to the LAPACK routines dgeqrf, zgeqrf,
81
+ dorgqr, zungqr, dgeqp3, and zgeqp3.
82
+
83
+ If ``mode=economic``, the shapes of Q and R are (M, K) and (K, N) instead
84
+ of (M,M) and (M,N), with ``K=min(M,N)``.
85
+
86
+ Examples
87
+ --------
88
+ >>> import numpy as np
89
+ >>> from scipy import linalg
90
+ >>> rng = np.random.default_rng()
91
+ >>> a = rng.standard_normal((9, 6))
92
+
93
+ >>> q, r = linalg.qr(a)
94
+ >>> np.allclose(a, np.dot(q, r))
95
+ True
96
+ >>> q.shape, r.shape
97
+ ((9, 9), (9, 6))
98
+
99
+ >>> r2 = linalg.qr(a, mode='r')
100
+ >>> np.allclose(r, r2)
101
+ True
102
+
103
+ >>> q3, r3 = linalg.qr(a, mode='economic')
104
+ >>> q3.shape, r3.shape
105
+ ((9, 6), (6, 6))
106
+
107
+ >>> q4, r4, p4 = linalg.qr(a, pivoting=True)
108
+ >>> d = np.abs(np.diag(r4))
109
+ >>> np.all(d[1:] <= d[:-1])
110
+ True
111
+ >>> np.allclose(a[:, p4], np.dot(q4, r4))
112
+ True
113
+ >>> q4.shape, r4.shape, p4.shape
114
+ ((9, 9), (9, 6), (6,))
115
+
116
+ >>> q5, r5, p5 = linalg.qr(a, mode='economic', pivoting=True)
117
+ >>> q5.shape, r5.shape, p5.shape
118
+ ((9, 6), (6, 6), (6,))
119
+
120
+ """
121
+ # 'qr' was the old default, equivalent to 'full'. Neither 'full' nor
122
+ # 'qr' are used below.
123
+ # 'raw' is used internally by qr_multiply
124
+ if mode not in ['full', 'qr', 'r', 'economic', 'raw']:
125
+ raise ValueError("Mode argument should be one of ['full', 'r',"
126
+ "'economic', 'raw']")
127
+
128
+ if check_finite:
129
+ a1 = numpy.asarray_chkfinite(a)
130
+ else:
131
+ a1 = numpy.asarray(a)
132
+ if len(a1.shape) != 2:
133
+ raise ValueError("expected a 2-D array")
134
+ M, N = a1.shape
135
+ overwrite_a = overwrite_a or (_datacopied(a1, a))
136
+
137
+ if pivoting:
138
+ geqp3, = get_lapack_funcs(('geqp3',), (a1,))
139
+ qr, jpvt, tau = safecall(geqp3, "geqp3", a1, overwrite_a=overwrite_a)
140
+ jpvt -= 1 # geqp3 returns a 1-based index array, so subtract 1
141
+ else:
142
+ geqrf, = get_lapack_funcs(('geqrf',), (a1,))
143
+ qr, tau = safecall(geqrf, "geqrf", a1, lwork=lwork,
144
+ overwrite_a=overwrite_a)
145
+
146
+ if mode not in ['economic', 'raw'] or M < N:
147
+ R = numpy.triu(qr)
148
+ else:
149
+ R = numpy.triu(qr[:N, :])
150
+
151
+ if pivoting:
152
+ Rj = R, jpvt
153
+ else:
154
+ Rj = R,
155
+
156
+ if mode == 'r':
157
+ return Rj
158
+ elif mode == 'raw':
159
+ return ((qr, tau),) + Rj
160
+
161
+ gor_un_gqr, = get_lapack_funcs(('orgqr',), (qr,))
162
+
163
+ if M < N:
164
+ Q, = safecall(gor_un_gqr, "gorgqr/gungqr", qr[:, :M], tau,
165
+ lwork=lwork, overwrite_a=1)
166
+ elif mode == 'economic':
167
+ Q, = safecall(gor_un_gqr, "gorgqr/gungqr", qr, tau, lwork=lwork,
168
+ overwrite_a=1)
169
+ else:
170
+ t = qr.dtype.char
171
+ qqr = numpy.empty((M, M), dtype=t)
172
+ qqr[:, :N] = qr
173
+ Q, = safecall(gor_un_gqr, "gorgqr/gungqr", qqr, tau, lwork=lwork,
174
+ overwrite_a=1)
175
+
176
+ return (Q,) + Rj
177
+
178
+
179
+ def qr_multiply(a, c, mode='right', pivoting=False, conjugate=False,
180
+ overwrite_a=False, overwrite_c=False):
181
+ """
182
+ Calculate the QR decomposition and multiply Q with a matrix.
183
+
184
+ Calculate the decomposition ``A = Q R`` where Q is unitary/orthogonal
185
+ and R upper triangular. Multiply Q with a vector or a matrix c.
186
+
187
+ Parameters
188
+ ----------
189
+ a : (M, N), array_like
190
+ Input array
191
+ c : array_like
192
+ Input array to be multiplied by ``q``.
193
+ mode : {'left', 'right'}, optional
194
+ ``Q @ c`` is returned if mode is 'left', ``c @ Q`` is returned if
195
+ mode is 'right'.
196
+ The shape of c must be appropriate for the matrix multiplications,
197
+ if mode is 'left', ``min(a.shape) == c.shape[0]``,
198
+ if mode is 'right', ``a.shape[0] == c.shape[1]``.
199
+ pivoting : bool, optional
200
+ Whether or not factorization should include pivoting for rank-revealing
201
+ qr decomposition, see the documentation of qr.
202
+ conjugate : bool, optional
203
+ Whether Q should be complex-conjugated. This might be faster
204
+ than explicit conjugation.
205
+ overwrite_a : bool, optional
206
+ Whether data in a is overwritten (may improve performance)
207
+ overwrite_c : bool, optional
208
+ Whether data in c is overwritten (may improve performance).
209
+ If this is used, c must be big enough to keep the result,
210
+ i.e. ``c.shape[0]`` = ``a.shape[0]`` if mode is 'left'.
211
+
212
+ Returns
213
+ -------
214
+ CQ : ndarray
215
+ The product of ``Q`` and ``c``.
216
+ R : (K, N), ndarray
217
+ R array of the resulting QR factorization where ``K = min(M, N)``.
218
+ P : (N,) ndarray
219
+ Integer pivot array. Only returned when ``pivoting=True``.
220
+
221
+ Raises
222
+ ------
223
+ LinAlgError
224
+ Raised if QR decomposition fails.
225
+
226
+ Notes
227
+ -----
228
+ This is an interface to the LAPACK routines ``?GEQRF``, ``?ORMQR``,
229
+ ``?UNMQR``, and ``?GEQP3``.
230
+
231
+ .. versionadded:: 0.11.0
232
+
233
+ Examples
234
+ --------
235
+ >>> import numpy as np
236
+ >>> from scipy.linalg import qr_multiply, qr
237
+ >>> A = np.array([[1, 3, 3], [2, 3, 2], [2, 3, 3], [1, 3, 2]])
238
+ >>> qc, r1, piv1 = qr_multiply(A, 2*np.eye(4), pivoting=1)
239
+ >>> qc
240
+ array([[-1., 1., -1.],
241
+ [-1., -1., 1.],
242
+ [-1., -1., -1.],
243
+ [-1., 1., 1.]])
244
+ >>> r1
245
+ array([[-6., -3., -5. ],
246
+ [ 0., -1., -1.11022302e-16],
247
+ [ 0., 0., -1. ]])
248
+ >>> piv1
249
+ array([1, 0, 2], dtype=int32)
250
+ >>> q2, r2, piv2 = qr(A, mode='economic', pivoting=1)
251
+ >>> np.allclose(2*q2 - qc, np.zeros((4, 3)))
252
+ True
253
+
254
+ """
255
+ if mode not in ['left', 'right']:
256
+ raise ValueError("Mode argument can only be 'left' or 'right' but "
257
+ f"not '{mode}'")
258
+ c = numpy.asarray_chkfinite(c)
259
+ if c.ndim < 2:
260
+ onedim = True
261
+ c = numpy.atleast_2d(c)
262
+ if mode == "left":
263
+ c = c.T
264
+ else:
265
+ onedim = False
266
+
267
+ a = numpy.atleast_2d(numpy.asarray(a)) # chkfinite done in qr
268
+ M, N = a.shape
269
+
270
+ if mode == 'left':
271
+ if c.shape[0] != min(M, N + overwrite_c*(M-N)):
272
+ raise ValueError('Array shapes are not compatible for Q @ c'
273
+ f' operation: {a.shape} vs {c.shape}')
274
+ else:
275
+ if M != c.shape[1]:
276
+ raise ValueError('Array shapes are not compatible for c @ Q'
277
+ f' operation: {c.shape} vs {a.shape}')
278
+
279
+ raw = qr(a, overwrite_a, None, "raw", pivoting)
280
+ Q, tau = raw[0]
281
+
282
+ gor_un_mqr, = get_lapack_funcs(('ormqr',), (Q,))
283
+ if gor_un_mqr.typecode in ('s', 'd'):
284
+ trans = "T"
285
+ else:
286
+ trans = "C"
287
+
288
+ Q = Q[:, :min(M, N)]
289
+ if M > N and mode == "left" and not overwrite_c:
290
+ if conjugate:
291
+ cc = numpy.zeros((c.shape[1], M), dtype=c.dtype, order="F")
292
+ cc[:, :N] = c.T
293
+ else:
294
+ cc = numpy.zeros((M, c.shape[1]), dtype=c.dtype, order="F")
295
+ cc[:N, :] = c
296
+ trans = "N"
297
+ if conjugate:
298
+ lr = "R"
299
+ else:
300
+ lr = "L"
301
+ overwrite_c = True
302
+ elif c.flags["C_CONTIGUOUS"] and trans == "T" or conjugate:
303
+ cc = c.T
304
+ if mode == "left":
305
+ lr = "R"
306
+ else:
307
+ lr = "L"
308
+ else:
309
+ trans = "N"
310
+ cc = c
311
+ if mode == "left":
312
+ lr = "L"
313
+ else:
314
+ lr = "R"
315
+ cQ, = safecall(gor_un_mqr, "gormqr/gunmqr", lr, trans, Q, tau, cc,
316
+ overwrite_c=overwrite_c)
317
+ if trans != "N":
318
+ cQ = cQ.T
319
+ if mode == "right":
320
+ cQ = cQ[:, :min(M, N)]
321
+ if onedim:
322
+ cQ = cQ.ravel()
323
+
324
+ return (cQ,) + raw[1:]
325
+
326
+
327
+ def rq(a, overwrite_a=False, lwork=None, mode='full', check_finite=True):
328
+ """
329
+ Compute RQ decomposition of a matrix.
330
+
331
+ Calculate the decomposition ``A = R Q`` where Q is unitary/orthogonal
332
+ and R upper triangular.
333
+
334
+ Parameters
335
+ ----------
336
+ a : (M, N) array_like
337
+ Matrix to be decomposed
338
+ overwrite_a : bool, optional
339
+ Whether data in a is overwritten (may improve performance)
340
+ lwork : int, optional
341
+ Work array size, lwork >= a.shape[1]. If None or -1, an optimal size
342
+ is computed.
343
+ mode : {'full', 'r', 'economic'}, optional
344
+ Determines what information is to be returned: either both Q and R
345
+ ('full', default), only R ('r') or both Q and R but computed in
346
+ economy-size ('economic', see Notes).
347
+ check_finite : bool, optional
348
+ Whether to check that the input matrix contains only finite numbers.
349
+ Disabling may give a performance gain, but may result in problems
350
+ (crashes, non-termination) if the inputs do contain infinities or NaNs.
351
+
352
+ Returns
353
+ -------
354
+ R : float or complex ndarray
355
+ Of shape (M, N) or (M, K) for ``mode='economic'``. ``K = min(M, N)``.
356
+ Q : float or complex ndarray
357
+ Of shape (N, N) or (K, N) for ``mode='economic'``. Not returned
358
+ if ``mode='r'``.
359
+
360
+ Raises
361
+ ------
362
+ LinAlgError
363
+ If decomposition fails.
364
+
365
+ Notes
366
+ -----
367
+ This is an interface to the LAPACK routines sgerqf, dgerqf, cgerqf, zgerqf,
368
+ sorgrq, dorgrq, cungrq and zungrq.
369
+
370
+ If ``mode=economic``, the shapes of Q and R are (K, N) and (M, K) instead
371
+ of (N,N) and (M,N), with ``K=min(M,N)``.
372
+
373
+ Examples
374
+ --------
375
+ >>> import numpy as np
376
+ >>> from scipy import linalg
377
+ >>> rng = np.random.default_rng()
378
+ >>> a = rng.standard_normal((6, 9))
379
+ >>> r, q = linalg.rq(a)
380
+ >>> np.allclose(a, r @ q)
381
+ True
382
+ >>> r.shape, q.shape
383
+ ((6, 9), (9, 9))
384
+ >>> r2 = linalg.rq(a, mode='r')
385
+ >>> np.allclose(r, r2)
386
+ True
387
+ >>> r3, q3 = linalg.rq(a, mode='economic')
388
+ >>> r3.shape, q3.shape
389
+ ((6, 6), (6, 9))
390
+
391
+ """
392
+ if mode not in ['full', 'r', 'economic']:
393
+ raise ValueError(
394
+ "Mode argument should be one of ['full', 'r', 'economic']")
395
+
396
+ if check_finite:
397
+ a1 = numpy.asarray_chkfinite(a)
398
+ else:
399
+ a1 = numpy.asarray(a)
400
+ if len(a1.shape) != 2:
401
+ raise ValueError('expected matrix')
402
+ M, N = a1.shape
403
+ overwrite_a = overwrite_a or (_datacopied(a1, a))
404
+
405
+ gerqf, = get_lapack_funcs(('gerqf',), (a1,))
406
+ rq, tau = safecall(gerqf, 'gerqf', a1, lwork=lwork,
407
+ overwrite_a=overwrite_a)
408
+ if not mode == 'economic' or N < M:
409
+ R = numpy.triu(rq, N-M)
410
+ else:
411
+ R = numpy.triu(rq[-M:, -M:])
412
+
413
+ if mode == 'r':
414
+ return R
415
+
416
+ gor_un_grq, = get_lapack_funcs(('orgrq',), (rq,))
417
+
418
+ if N < M:
419
+ Q, = safecall(gor_un_grq, "gorgrq/gungrq", rq[-N:], tau, lwork=lwork,
420
+ overwrite_a=1)
421
+ elif mode == 'economic':
422
+ Q, = safecall(gor_un_grq, "gorgrq/gungrq", rq, tau, lwork=lwork,
423
+ overwrite_a=1)
424
+ else:
425
+ rq1 = numpy.empty((N, N), dtype=rq.dtype)
426
+ rq1[-M:] = rq
427
+ Q, = safecall(gor_un_grq, "gorgrq/gungrq", rq1, tau, lwork=lwork,
428
+ overwrite_a=1)
429
+
430
+ return R, Q
astra_scene_test/Scene_04/.venv/lib/python3.9/site-packages/scipy/linalg/_decomp_qz.py ADDED
@@ -0,0 +1,449 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import warnings
2
+
3
+ import numpy as np
4
+ from numpy import asarray_chkfinite
5
+ from ._misc import LinAlgError, _datacopied, LinAlgWarning
6
+ from .lapack import get_lapack_funcs
7
+
8
+
9
+ __all__ = ['qz', 'ordqz']
10
+
11
+ _double_precision = ['i', 'l', 'd']
12
+
13
+
14
+ def _select_function(sort):
15
+ if callable(sort):
16
+ # assume the user knows what they're doing
17
+ sfunction = sort
18
+ elif sort == 'lhp':
19
+ sfunction = _lhp
20
+ elif sort == 'rhp':
21
+ sfunction = _rhp
22
+ elif sort == 'iuc':
23
+ sfunction = _iuc
24
+ elif sort == 'ouc':
25
+ sfunction = _ouc
26
+ else:
27
+ raise ValueError("sort parameter must be None, a callable, or "
28
+ "one of ('lhp','rhp','iuc','ouc')")
29
+
30
+ return sfunction
31
+
32
+
33
+ def _lhp(x, y):
34
+ out = np.empty_like(x, dtype=bool)
35
+ nonzero = (y != 0)
36
+ # handles (x, y) = (0, 0) too
37
+ out[~nonzero] = False
38
+ out[nonzero] = (np.real(x[nonzero]/y[nonzero]) < 0.0)
39
+ return out
40
+
41
+
42
+ def _rhp(x, y):
43
+ out = np.empty_like(x, dtype=bool)
44
+ nonzero = (y != 0)
45
+ # handles (x, y) = (0, 0) too
46
+ out[~nonzero] = False
47
+ out[nonzero] = (np.real(x[nonzero]/y[nonzero]) > 0.0)
48
+ return out
49
+
50
+
51
+ def _iuc(x, y):
52
+ out = np.empty_like(x, dtype=bool)
53
+ nonzero = (y != 0)
54
+ # handles (x, y) = (0, 0) too
55
+ out[~nonzero] = False
56
+ out[nonzero] = (abs(x[nonzero]/y[nonzero]) < 1.0)
57
+ return out
58
+
59
+
60
+ def _ouc(x, y):
61
+ out = np.empty_like(x, dtype=bool)
62
+ xzero = (x == 0)
63
+ yzero = (y == 0)
64
+ out[xzero & yzero] = False
65
+ out[~xzero & yzero] = True
66
+ out[~yzero] = (abs(x[~yzero]/y[~yzero]) > 1.0)
67
+ return out
68
+
69
+
70
+ def _qz(A, B, output='real', lwork=None, sort=None, overwrite_a=False,
71
+ overwrite_b=False, check_finite=True):
72
+ if sort is not None:
73
+ # Disabled due to segfaults on win32, see ticket 1717.
74
+ raise ValueError("The 'sort' input of qz() has to be None and will be "
75
+ "removed in a future release. Use ordqz instead.")
76
+
77
+ if output not in ['real', 'complex', 'r', 'c']:
78
+ raise ValueError("argument must be 'real', or 'complex'")
79
+
80
+ if check_finite:
81
+ a1 = asarray_chkfinite(A)
82
+ b1 = asarray_chkfinite(B)
83
+ else:
84
+ a1 = np.asarray(A)
85
+ b1 = np.asarray(B)
86
+
87
+ a_m, a_n = a1.shape
88
+ b_m, b_n = b1.shape
89
+ if not (a_m == a_n == b_m == b_n):
90
+ raise ValueError("Array dimensions must be square and agree")
91
+
92
+ typa = a1.dtype.char
93
+ if output in ['complex', 'c'] and typa not in ['F', 'D']:
94
+ if typa in _double_precision:
95
+ a1 = a1.astype('D')
96
+ typa = 'D'
97
+ else:
98
+ a1 = a1.astype('F')
99
+ typa = 'F'
100
+ typb = b1.dtype.char
101
+ if output in ['complex', 'c'] and typb not in ['F', 'D']:
102
+ if typb in _double_precision:
103
+ b1 = b1.astype('D')
104
+ typb = 'D'
105
+ else:
106
+ b1 = b1.astype('F')
107
+ typb = 'F'
108
+
109
+ overwrite_a = overwrite_a or (_datacopied(a1, A))
110
+ overwrite_b = overwrite_b or (_datacopied(b1, B))
111
+
112
+ gges, = get_lapack_funcs(('gges',), (a1, b1))
113
+
114
+ if lwork is None or lwork == -1:
115
+ # get optimal work array size
116
+ result = gges(lambda x: None, a1, b1, lwork=-1)
117
+ lwork = result[-2][0].real.astype(int)
118
+
119
+ def sfunction(x):
120
+ return None
121
+ result = gges(sfunction, a1, b1, lwork=lwork, overwrite_a=overwrite_a,
122
+ overwrite_b=overwrite_b, sort_t=0)
123
+
124
+ info = result[-1]
125
+ if info < 0:
126
+ raise ValueError(f"Illegal value in argument {-info} of gges")
127
+ elif info > 0 and info <= a_n:
128
+ warnings.warn("The QZ iteration failed. (a,b) are not in Schur "
129
+ "form, but ALPHAR(j), ALPHAI(j), and BETA(j) should be "
130
+ f"correct for J={info-1},...,N", LinAlgWarning,
131
+ stacklevel=3)
132
+ elif info == a_n+1:
133
+ raise LinAlgError("Something other than QZ iteration failed")
134
+ elif info == a_n+2:
135
+ raise LinAlgError("After reordering, roundoff changed values of some "
136
+ "complex eigenvalues so that leading eigenvalues "
137
+ "in the Generalized Schur form no longer satisfy "
138
+ "sort=True. This could also be due to scaling.")
139
+ elif info == a_n+3:
140
+ raise LinAlgError("Reordering failed in <s,d,c,z>tgsen")
141
+
142
+ return result, gges.typecode
143
+
144
+
145
+ def qz(A, B, output='real', lwork=None, sort=None, overwrite_a=False,
146
+ overwrite_b=False, check_finite=True):
147
+ """
148
+ QZ decomposition for generalized eigenvalues of a pair of matrices.
149
+
150
+ The QZ, or generalized Schur, decomposition for a pair of n-by-n
151
+ matrices (A,B) is::
152
+
153
+ (A,B) = (Q @ AA @ Z*, Q @ BB @ Z*)
154
+
155
+ where AA, BB is in generalized Schur form if BB is upper-triangular
156
+ with non-negative diagonal and AA is upper-triangular, or for real QZ
157
+ decomposition (``output='real'``) block upper triangular with 1x1
158
+ and 2x2 blocks. In this case, the 1x1 blocks correspond to real
159
+ generalized eigenvalues and 2x2 blocks are 'standardized' by making
160
+ the corresponding elements of BB have the form::
161
+
162
+ [ a 0 ]
163
+ [ 0 b ]
164
+
165
+ and the pair of corresponding 2x2 blocks in AA and BB will have a complex
166
+ conjugate pair of generalized eigenvalues. If (``output='complex'``) or
167
+ A and B are complex matrices, Z' denotes the conjugate-transpose of Z.
168
+ Q and Z are unitary matrices.
169
+
170
+ Parameters
171
+ ----------
172
+ A : (N, N) array_like
173
+ 2-D array to decompose
174
+ B : (N, N) array_like
175
+ 2-D array to decompose
176
+ output : {'real', 'complex'}, optional
177
+ Construct the real or complex QZ decomposition for real matrices.
178
+ Default is 'real'.
179
+ lwork : int, optional
180
+ Work array size. If None or -1, it is automatically computed.
181
+ sort : {None, callable, 'lhp', 'rhp', 'iuc', 'ouc'}, optional
182
+ NOTE: THIS INPUT IS DISABLED FOR NOW. Use ordqz instead.
183
+
184
+ Specifies whether the upper eigenvalues should be sorted. A callable
185
+ may be passed that, given a eigenvalue, returns a boolean denoting
186
+ whether the eigenvalue should be sorted to the top-left (True). For
187
+ real matrix pairs, the sort function takes three real arguments
188
+ (alphar, alphai, beta). The eigenvalue
189
+ ``x = (alphar + alphai*1j)/beta``. For complex matrix pairs or
190
+ output='complex', the sort function takes two complex arguments
191
+ (alpha, beta). The eigenvalue ``x = (alpha/beta)``. Alternatively,
192
+ string parameters may be used:
193
+
194
+ - 'lhp' Left-hand plane (x.real < 0.0)
195
+ - 'rhp' Right-hand plane (x.real > 0.0)
196
+ - 'iuc' Inside the unit circle (x*x.conjugate() < 1.0)
197
+ - 'ouc' Outside the unit circle (x*x.conjugate() > 1.0)
198
+
199
+ Defaults to None (no sorting).
200
+ overwrite_a : bool, optional
201
+ Whether to overwrite data in a (may improve performance)
202
+ overwrite_b : bool, optional
203
+ Whether to overwrite data in b (may improve performance)
204
+ check_finite : bool, optional
205
+ If true checks the elements of `A` and `B` are finite numbers. If
206
+ false does no checking and passes matrix through to
207
+ underlying algorithm.
208
+
209
+ Returns
210
+ -------
211
+ AA : (N, N) ndarray
212
+ Generalized Schur form of A.
213
+ BB : (N, N) ndarray
214
+ Generalized Schur form of B.
215
+ Q : (N, N) ndarray
216
+ The left Schur vectors.
217
+ Z : (N, N) ndarray
218
+ The right Schur vectors.
219
+
220
+ See Also
221
+ --------
222
+ ordqz
223
+
224
+ Notes
225
+ -----
226
+ Q is transposed versus the equivalent function in Matlab.
227
+
228
+ .. versionadded:: 0.11.0
229
+
230
+ Examples
231
+ --------
232
+ >>> import numpy as np
233
+ >>> from scipy.linalg import qz
234
+
235
+ >>> A = np.array([[1, 2, -1], [5, 5, 5], [2, 4, -8]])
236
+ >>> B = np.array([[1, 1, -3], [3, 1, -1], [5, 6, -2]])
237
+
238
+ Compute the decomposition. The QZ decomposition is not unique, so
239
+ depending on the underlying library that is used, there may be
240
+ differences in the signs of coefficients in the following output.
241
+
242
+ >>> AA, BB, Q, Z = qz(A, B)
243
+ >>> AA
244
+ array([[-1.36949157, -4.05459025, 7.44389431],
245
+ [ 0. , 7.65653432, 5.13476017],
246
+ [ 0. , -0.65978437, 2.4186015 ]]) # may vary
247
+ >>> BB
248
+ array([[ 1.71890633, -1.64723705, -0.72696385],
249
+ [ 0. , 8.6965692 , -0. ],
250
+ [ 0. , 0. , 2.27446233]]) # may vary
251
+ >>> Q
252
+ array([[-0.37048362, 0.1903278 , 0.90912992],
253
+ [-0.90073232, 0.16534124, -0.40167593],
254
+ [ 0.22676676, 0.96769706, -0.11017818]]) # may vary
255
+ >>> Z
256
+ array([[-0.67660785, 0.63528924, -0.37230283],
257
+ [ 0.70243299, 0.70853819, -0.06753907],
258
+ [ 0.22088393, -0.30721526, -0.92565062]]) # may vary
259
+
260
+ Verify the QZ decomposition. With real output, we only need the
261
+ transpose of ``Z`` in the following expressions.
262
+
263
+ >>> Q @ AA @ Z.T # Should be A
264
+ array([[ 1., 2., -1.],
265
+ [ 5., 5., 5.],
266
+ [ 2., 4., -8.]])
267
+ >>> Q @ BB @ Z.T # Should be B
268
+ array([[ 1., 1., -3.],
269
+ [ 3., 1., -1.],
270
+ [ 5., 6., -2.]])
271
+
272
+ Repeat the decomposition, but with ``output='complex'``.
273
+
274
+ >>> AA, BB, Q, Z = qz(A, B, output='complex')
275
+
276
+ For conciseness in the output, we use ``np.set_printoptions()`` to set
277
+ the output precision of NumPy arrays to 3 and display tiny values as 0.
278
+
279
+ >>> np.set_printoptions(precision=3, suppress=True)
280
+ >>> AA
281
+ array([[-1.369+0.j , 2.248+4.237j, 4.861-5.022j],
282
+ [ 0. +0.j , 7.037+2.922j, 0.794+4.932j],
283
+ [ 0. +0.j , 0. +0.j , 2.655-1.103j]]) # may vary
284
+ >>> BB
285
+ array([[ 1.719+0.j , -1.115+1.j , -0.763-0.646j],
286
+ [ 0. +0.j , 7.24 +0.j , -3.144+3.322j],
287
+ [ 0. +0.j , 0. +0.j , 2.732+0.j ]]) # may vary
288
+ >>> Q
289
+ array([[ 0.326+0.175j, -0.273-0.029j, -0.886-0.052j],
290
+ [ 0.794+0.426j, -0.093+0.134j, 0.402-0.02j ],
291
+ [-0.2 -0.107j, -0.816+0.482j, 0.151-0.167j]]) # may vary
292
+ >>> Z
293
+ array([[ 0.596+0.32j , -0.31 +0.414j, 0.393-0.347j],
294
+ [-0.619-0.332j, -0.479+0.314j, 0.154-0.393j],
295
+ [-0.195-0.104j, 0.576+0.27j , 0.715+0.187j]]) # may vary
296
+
297
+ With complex arrays, we must use ``Z.conj().T`` in the following
298
+ expressions to verify the decomposition.
299
+
300
+ >>> Q @ AA @ Z.conj().T # Should be A
301
+ array([[ 1.-0.j, 2.-0.j, -1.-0.j],
302
+ [ 5.+0.j, 5.+0.j, 5.-0.j],
303
+ [ 2.+0.j, 4.+0.j, -8.+0.j]])
304
+ >>> Q @ BB @ Z.conj().T # Should be B
305
+ array([[ 1.+0.j, 1.+0.j, -3.+0.j],
306
+ [ 3.-0.j, 1.-0.j, -1.+0.j],
307
+ [ 5.+0.j, 6.+0.j, -2.+0.j]])
308
+
309
+ """
310
+ # output for real
311
+ # AA, BB, sdim, alphar, alphai, beta, vsl, vsr, work, info
312
+ # output for complex
313
+ # AA, BB, sdim, alpha, beta, vsl, vsr, work, info
314
+ result, _ = _qz(A, B, output=output, lwork=lwork, sort=sort,
315
+ overwrite_a=overwrite_a, overwrite_b=overwrite_b,
316
+ check_finite=check_finite)
317
+ return result[0], result[1], result[-4], result[-3]
318
+
319
+
320
+ def ordqz(A, B, sort='lhp', output='real', overwrite_a=False,
321
+ overwrite_b=False, check_finite=True):
322
+ """QZ decomposition for a pair of matrices with reordering.
323
+
324
+ Parameters
325
+ ----------
326
+ A : (N, N) array_like
327
+ 2-D array to decompose
328
+ B : (N, N) array_like
329
+ 2-D array to decompose
330
+ sort : {callable, 'lhp', 'rhp', 'iuc', 'ouc'}, optional
331
+ Specifies whether the upper eigenvalues should be sorted. A
332
+ callable may be passed that, given an ordered pair ``(alpha,
333
+ beta)`` representing the eigenvalue ``x = (alpha/beta)``,
334
+ returns a boolean denoting whether the eigenvalue should be
335
+ sorted to the top-left (True). For the real matrix pairs
336
+ ``beta`` is real while ``alpha`` can be complex, and for
337
+ complex matrix pairs both ``alpha`` and ``beta`` can be
338
+ complex. The callable must be able to accept a NumPy
339
+ array. Alternatively, string parameters may be used:
340
+
341
+ - 'lhp' Left-hand plane (x.real < 0.0)
342
+ - 'rhp' Right-hand plane (x.real > 0.0)
343
+ - 'iuc' Inside the unit circle (x*x.conjugate() < 1.0)
344
+ - 'ouc' Outside the unit circle (x*x.conjugate() > 1.0)
345
+
346
+ With the predefined sorting functions, an infinite eigenvalue
347
+ (i.e., ``alpha != 0`` and ``beta = 0``) is considered to lie in
348
+ neither the left-hand nor the right-hand plane, but it is
349
+ considered to lie outside the unit circle. For the eigenvalue
350
+ ``(alpha, beta) = (0, 0)``, the predefined sorting functions
351
+ all return `False`.
352
+ output : str {'real','complex'}, optional
353
+ Construct the real or complex QZ decomposition for real matrices.
354
+ Default is 'real'.
355
+ overwrite_a : bool, optional
356
+ If True, the contents of A are overwritten.
357
+ overwrite_b : bool, optional
358
+ If True, the contents of B are overwritten.
359
+ check_finite : bool, optional
360
+ If true checks the elements of `A` and `B` are finite numbers. If
361
+ false does no checking and passes matrix through to
362
+ underlying algorithm.
363
+
364
+ Returns
365
+ -------
366
+ AA : (N, N) ndarray
367
+ Generalized Schur form of A.
368
+ BB : (N, N) ndarray
369
+ Generalized Schur form of B.
370
+ alpha : (N,) ndarray
371
+ alpha = alphar + alphai * 1j. See notes.
372
+ beta : (N,) ndarray
373
+ See notes.
374
+ Q : (N, N) ndarray
375
+ The left Schur vectors.
376
+ Z : (N, N) ndarray
377
+ The right Schur vectors.
378
+
379
+ See Also
380
+ --------
381
+ qz
382
+
383
+ Notes
384
+ -----
385
+ On exit, ``(ALPHAR(j) + ALPHAI(j)*i)/BETA(j), j=1,...,N``, will be the
386
+ generalized eigenvalues. ``ALPHAR(j) + ALPHAI(j)*i`` and
387
+ ``BETA(j),j=1,...,N`` are the diagonals of the complex Schur form (S,T)
388
+ that would result if the 2-by-2 diagonal blocks of the real generalized
389
+ Schur form of (A,B) were further reduced to triangular form using complex
390
+ unitary transformations. If ALPHAI(j) is zero, then the jth eigenvalue is
391
+ real; if positive, then the ``j``\\ th and ``(j+1)``\\ st eigenvalues are a
392
+ complex conjugate pair, with ``ALPHAI(j+1)`` negative.
393
+
394
+ .. versionadded:: 0.17.0
395
+
396
+ Examples
397
+ --------
398
+ >>> import numpy as np
399
+ >>> from scipy.linalg import ordqz
400
+ >>> A = np.array([[2, 5, 8, 7], [5, 2, 2, 8], [7, 5, 6, 6], [5, 4, 4, 8]])
401
+ >>> B = np.array([[0, 6, 0, 0], [5, 0, 2, 1], [5, 2, 6, 6], [4, 7, 7, 7]])
402
+ >>> AA, BB, alpha, beta, Q, Z = ordqz(A, B, sort='lhp')
403
+
404
+ Since we have sorted for left half plane eigenvalues, negatives come first
405
+
406
+ >>> (alpha/beta).real < 0
407
+ array([ True, True, False, False], dtype=bool)
408
+
409
+ """
410
+ (AA, BB, _, *ab, Q, Z, _, _), typ = _qz(A, B, output=output, sort=None,
411
+ overwrite_a=overwrite_a,
412
+ overwrite_b=overwrite_b,
413
+ check_finite=check_finite)
414
+
415
+ if typ == 's':
416
+ alpha, beta = ab[0] + ab[1]*np.complex64(1j), ab[2]
417
+ elif typ == 'd':
418
+ alpha, beta = ab[0] + ab[1]*1.j, ab[2]
419
+ else:
420
+ alpha, beta = ab
421
+
422
+ sfunction = _select_function(sort)
423
+ select = sfunction(alpha, beta)
424
+
425
+ tgsen = get_lapack_funcs('tgsen', (AA, BB))
426
+ # the real case needs 4n + 16 lwork
427
+ lwork = 4*AA.shape[0] + 16 if typ in 'sd' else 1
428
+ AAA, BBB, *ab, QQ, ZZ, _, _, _, _, info = tgsen(select, AA, BB, Q, Z,
429
+ ijob=0,
430
+ lwork=lwork, liwork=1)
431
+
432
+ # Once more for tgsen output
433
+ if typ == 's':
434
+ alpha, beta = ab[0] + ab[1]*np.complex64(1j), ab[2]
435
+ elif typ == 'd':
436
+ alpha, beta = ab[0] + ab[1]*1.j, ab[2]
437
+ else:
438
+ alpha, beta = ab
439
+
440
+ if info < 0:
441
+ raise ValueError(f"Illegal value in argument {-info} of tgsen")
442
+ elif info == 1:
443
+ raise ValueError("Reordering of (A, B) failed because the transformed"
444
+ " matrix pair (A, B) would be too far from "
445
+ "generalized Schur form; the problem is very "
446
+ "ill-conditioned. (A, B) may have been partially "
447
+ "reordered.")
448
+
449
+ return AAA, BBB, alpha, beta, QQ, ZZ
astra_scene_test/Scene_04/.venv/lib/python3.9/site-packages/scipy/linalg/_decomp_schur.py ADDED
@@ -0,0 +1,300 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """Schur decomposition functions."""
2
+ import numpy
3
+ from numpy import asarray_chkfinite, single, asarray, array
4
+ from numpy.linalg import norm
5
+
6
+
7
+ # Local imports.
8
+ from ._misc import LinAlgError, _datacopied
9
+ from .lapack import get_lapack_funcs
10
+ from ._decomp import eigvals
11
+
12
+ __all__ = ['schur', 'rsf2csf']
13
+
14
+ _double_precision = ['i', 'l', 'd']
15
+
16
+
17
+ def schur(a, output='real', lwork=None, overwrite_a=False, sort=None,
18
+ check_finite=True):
19
+ """
20
+ Compute Schur decomposition of a matrix.
21
+
22
+ The Schur decomposition is::
23
+
24
+ A = Z T Z^H
25
+
26
+ where Z is unitary and T is either upper-triangular, or for real
27
+ Schur decomposition (output='real'), quasi-upper triangular. In
28
+ the quasi-triangular form, 2x2 blocks describing complex-valued
29
+ eigenvalue pairs may extrude from the diagonal.
30
+
31
+ Parameters
32
+ ----------
33
+ a : (M, M) array_like
34
+ Matrix to decompose
35
+ output : {'real', 'complex'}, optional
36
+ Construct the real or complex Schur decomposition (for real matrices).
37
+ lwork : int, optional
38
+ Work array size. If None or -1, it is automatically computed.
39
+ overwrite_a : bool, optional
40
+ Whether to overwrite data in a (may improve performance).
41
+ sort : {None, callable, 'lhp', 'rhp', 'iuc', 'ouc'}, optional
42
+ Specifies whether the upper eigenvalues should be sorted. A callable
43
+ may be passed that, given a eigenvalue, returns a boolean denoting
44
+ whether the eigenvalue should be sorted to the top-left (True).
45
+ Alternatively, string parameters may be used::
46
+
47
+ 'lhp' Left-hand plane (x.real < 0.0)
48
+ 'rhp' Right-hand plane (x.real > 0.0)
49
+ 'iuc' Inside the unit circle (x*x.conjugate() <= 1.0)
50
+ 'ouc' Outside the unit circle (x*x.conjugate() > 1.0)
51
+
52
+ Defaults to None (no sorting).
53
+ check_finite : bool, optional
54
+ Whether to check that the input matrix contains only finite numbers.
55
+ Disabling may give a performance gain, but may result in problems
56
+ (crashes, non-termination) if the inputs do contain infinities or NaNs.
57
+
58
+ Returns
59
+ -------
60
+ T : (M, M) ndarray
61
+ Schur form of A. It is real-valued for the real Schur decomposition.
62
+ Z : (M, M) ndarray
63
+ An unitary Schur transformation matrix for A.
64
+ It is real-valued for the real Schur decomposition.
65
+ sdim : int
66
+ If and only if sorting was requested, a third return value will
67
+ contain the number of eigenvalues satisfying the sort condition.
68
+
69
+ Raises
70
+ ------
71
+ LinAlgError
72
+ Error raised under three conditions:
73
+
74
+ 1. The algorithm failed due to a failure of the QR algorithm to
75
+ compute all eigenvalues.
76
+ 2. If eigenvalue sorting was requested, the eigenvalues could not be
77
+ reordered due to a failure to separate eigenvalues, usually because
78
+ of poor conditioning.
79
+ 3. If eigenvalue sorting was requested, roundoff errors caused the
80
+ leading eigenvalues to no longer satisfy the sorting condition.
81
+
82
+ See Also
83
+ --------
84
+ rsf2csf : Convert real Schur form to complex Schur form
85
+
86
+ Examples
87
+ --------
88
+ >>> import numpy as np
89
+ >>> from scipy.linalg import schur, eigvals
90
+ >>> A = np.array([[0, 2, 2], [0, 1, 2], [1, 0, 1]])
91
+ >>> T, Z = schur(A)
92
+ >>> T
93
+ array([[ 2.65896708, 1.42440458, -1.92933439],
94
+ [ 0. , -0.32948354, -0.49063704],
95
+ [ 0. , 1.31178921, -0.32948354]])
96
+ >>> Z
97
+ array([[0.72711591, -0.60156188, 0.33079564],
98
+ [0.52839428, 0.79801892, 0.28976765],
99
+ [0.43829436, 0.03590414, -0.89811411]])
100
+
101
+ >>> T2, Z2 = schur(A, output='complex')
102
+ >>> T2
103
+ array([[ 2.65896708, -1.22839825+1.32378589j, 0.42590089+1.51937378j], # may vary
104
+ [ 0. , -0.32948354+0.80225456j, -0.59877807+0.56192146j],
105
+ [ 0. , 0. , -0.32948354-0.80225456j]])
106
+ >>> eigvals(T2)
107
+ array([2.65896708, -0.32948354+0.80225456j, -0.32948354-0.80225456j])
108
+
109
+ An arbitrary custom eig-sorting condition, having positive imaginary part,
110
+ which is satisfied by only one eigenvalue
111
+
112
+ >>> T3, Z3, sdim = schur(A, output='complex', sort=lambda x: x.imag > 0)
113
+ >>> sdim
114
+ 1
115
+
116
+ """
117
+ if output not in ['real', 'complex', 'r', 'c']:
118
+ raise ValueError("argument must be 'real', or 'complex'")
119
+ if check_finite:
120
+ a1 = asarray_chkfinite(a)
121
+ else:
122
+ a1 = asarray(a)
123
+ if numpy.issubdtype(a1.dtype, numpy.integer):
124
+ a1 = asarray(a, dtype=numpy.dtype("long"))
125
+ if len(a1.shape) != 2 or (a1.shape[0] != a1.shape[1]):
126
+ raise ValueError('expected square matrix')
127
+ typ = a1.dtype.char
128
+ if output in ['complex', 'c'] and typ not in ['F', 'D']:
129
+ if typ in _double_precision:
130
+ a1 = a1.astype('D')
131
+ typ = 'D'
132
+ else:
133
+ a1 = a1.astype('F')
134
+ typ = 'F'
135
+ overwrite_a = overwrite_a or (_datacopied(a1, a))
136
+ gees, = get_lapack_funcs(('gees',), (a1,))
137
+ if lwork is None or lwork == -1:
138
+ # get optimal work array
139
+ result = gees(lambda x: None, a1, lwork=-1)
140
+ lwork = result[-2][0].real.astype(numpy.int_)
141
+
142
+ if sort is None:
143
+ sort_t = 0
144
+ def sfunction(x):
145
+ return None
146
+ else:
147
+ sort_t = 1
148
+ if callable(sort):
149
+ sfunction = sort
150
+ elif sort == 'lhp':
151
+ def sfunction(x):
152
+ return x.real < 0.0
153
+ elif sort == 'rhp':
154
+ def sfunction(x):
155
+ return x.real >= 0.0
156
+ elif sort == 'iuc':
157
+ def sfunction(x):
158
+ return abs(x) <= 1.0
159
+ elif sort == 'ouc':
160
+ def sfunction(x):
161
+ return abs(x) > 1.0
162
+ else:
163
+ raise ValueError("'sort' parameter must either be 'None', or a "
164
+ "callable, or one of ('lhp','rhp','iuc','ouc')")
165
+
166
+ result = gees(sfunction, a1, lwork=lwork, overwrite_a=overwrite_a,
167
+ sort_t=sort_t)
168
+
169
+ info = result[-1]
170
+ if info < 0:
171
+ raise ValueError(f'illegal value in {-info}-th argument of internal gees')
172
+ elif info == a1.shape[0] + 1:
173
+ raise LinAlgError('Eigenvalues could not be separated for reordering.')
174
+ elif info == a1.shape[0] + 2:
175
+ raise LinAlgError('Leading eigenvalues do not satisfy sort condition.')
176
+ elif info > 0:
177
+ raise LinAlgError("Schur form not found. Possibly ill-conditioned.")
178
+
179
+ if sort_t == 0:
180
+ return result[0], result[-3]
181
+ else:
182
+ return result[0], result[-3], result[1]
183
+
184
+
185
+ eps = numpy.finfo(float).eps
186
+ feps = numpy.finfo(single).eps
187
+
188
+ _array_kind = {'b': 0, 'h': 0, 'B': 0, 'i': 0, 'l': 0,
189
+ 'f': 0, 'd': 0, 'F': 1, 'D': 1}
190
+ _array_precision = {'i': 1, 'l': 1, 'f': 0, 'd': 1, 'F': 0, 'D': 1}
191
+ _array_type = [['f', 'd'], ['F', 'D']]
192
+
193
+
194
+ def _commonType(*arrays):
195
+ kind = 0
196
+ precision = 0
197
+ for a in arrays:
198
+ t = a.dtype.char
199
+ kind = max(kind, _array_kind[t])
200
+ precision = max(precision, _array_precision[t])
201
+ return _array_type[kind][precision]
202
+
203
+
204
+ def _castCopy(type, *arrays):
205
+ cast_arrays = ()
206
+ for a in arrays:
207
+ if a.dtype.char == type:
208
+ cast_arrays = cast_arrays + (a.copy(),)
209
+ else:
210
+ cast_arrays = cast_arrays + (a.astype(type),)
211
+ if len(cast_arrays) == 1:
212
+ return cast_arrays[0]
213
+ else:
214
+ return cast_arrays
215
+
216
+
217
+ def rsf2csf(T, Z, check_finite=True):
218
+ """
219
+ Convert real Schur form to complex Schur form.
220
+
221
+ Convert a quasi-diagonal real-valued Schur form to the upper-triangular
222
+ complex-valued Schur form.
223
+
224
+ Parameters
225
+ ----------
226
+ T : (M, M) array_like
227
+ Real Schur form of the original array
228
+ Z : (M, M) array_like
229
+ Schur transformation matrix
230
+ check_finite : bool, optional
231
+ Whether to check that the input arrays contain only finite numbers.
232
+ Disabling may give a performance gain, but may result in problems
233
+ (crashes, non-termination) if the inputs do contain infinities or NaNs.
234
+
235
+ Returns
236
+ -------
237
+ T : (M, M) ndarray
238
+ Complex Schur form of the original array
239
+ Z : (M, M) ndarray
240
+ Schur transformation matrix corresponding to the complex form
241
+
242
+ See Also
243
+ --------
244
+ schur : Schur decomposition of an array
245
+
246
+ Examples
247
+ --------
248
+ >>> import numpy as np
249
+ >>> from scipy.linalg import schur, rsf2csf
250
+ >>> A = np.array([[0, 2, 2], [0, 1, 2], [1, 0, 1]])
251
+ >>> T, Z = schur(A)
252
+ >>> T
253
+ array([[ 2.65896708, 1.42440458, -1.92933439],
254
+ [ 0. , -0.32948354, -0.49063704],
255
+ [ 0. , 1.31178921, -0.32948354]])
256
+ >>> Z
257
+ array([[0.72711591, -0.60156188, 0.33079564],
258
+ [0.52839428, 0.79801892, 0.28976765],
259
+ [0.43829436, 0.03590414, -0.89811411]])
260
+ >>> T2 , Z2 = rsf2csf(T, Z)
261
+ >>> T2
262
+ array([[2.65896708+0.j, -1.64592781+0.743164187j, -1.21516887+1.00660462j],
263
+ [0.+0.j , -0.32948354+8.02254558e-01j, -0.82115218-2.77555756e-17j],
264
+ [0.+0.j , 0.+0.j, -0.32948354-0.802254558j]])
265
+ >>> Z2
266
+ array([[0.72711591+0.j, 0.28220393-0.31385693j, 0.51319638-0.17258824j],
267
+ [0.52839428+0.j, 0.24720268+0.41635578j, -0.68079517-0.15118243j],
268
+ [0.43829436+0.j, -0.76618703+0.01873251j, -0.03063006+0.46857912j]])
269
+
270
+ """
271
+ if check_finite:
272
+ Z, T = map(asarray_chkfinite, (Z, T))
273
+ else:
274
+ Z, T = map(asarray, (Z, T))
275
+
276
+ for ind, X in enumerate([Z, T]):
277
+ if X.ndim != 2 or X.shape[0] != X.shape[1]:
278
+ raise ValueError("Input '{}' must be square.".format('ZT'[ind]))
279
+
280
+ if T.shape[0] != Z.shape[0]:
281
+ message = f"Input array shapes must match: Z: {Z.shape} vs. T: {T.shape}"
282
+ raise ValueError(message)
283
+ N = T.shape[0]
284
+ t = _commonType(Z, T, array([3.0], 'F'))
285
+ Z, T = _castCopy(t, Z, T)
286
+
287
+ for m in range(N-1, 0, -1):
288
+ if abs(T[m, m-1]) > eps*(abs(T[m-1, m-1]) + abs(T[m, m])):
289
+ mu = eigvals(T[m-1:m+1, m-1:m+1]) - T[m, m]
290
+ r = norm([mu[0], T[m, m-1]])
291
+ c = mu[0] / r
292
+ s = T[m, m-1] / r
293
+ G = array([[c.conj(), s], [-s, c]], dtype=t)
294
+
295
+ T[m-1:m+1, m-1:] = G.dot(T[m-1:m+1, m-1:])
296
+ T[:m+1, m-1:m+1] = T[:m+1, m-1:m+1].dot(G.conj().T)
297
+ Z[:, m-1:m+1] = Z[:, m-1:m+1].dot(G.conj().T)
298
+
299
+ T[m, m-1] = 0.0
300
+ return T, Z
astra_scene_test/Scene_04/.venv/lib/python3.9/site-packages/scipy/linalg/_decomp_svd.py ADDED
@@ -0,0 +1,517 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """SVD decomposition functions."""
2
+ import numpy
3
+ from numpy import zeros, r_, diag, dot, arccos, arcsin, where, clip
4
+
5
+ # Local imports.
6
+ from ._misc import LinAlgError, _datacopied
7
+ from .lapack import get_lapack_funcs, _compute_lwork
8
+ from ._decomp import _asarray_validated
9
+
10
+ __all__ = ['svd', 'svdvals', 'diagsvd', 'orth', 'subspace_angles', 'null_space']
11
+
12
+
13
+ def svd(a, full_matrices=True, compute_uv=True, overwrite_a=False,
14
+ check_finite=True, lapack_driver='gesdd'):
15
+ """
16
+ Singular Value Decomposition.
17
+
18
+ Factorizes the matrix `a` into two unitary matrices ``U`` and ``Vh``, and
19
+ a 1-D array ``s`` of singular values (real, non-negative) such that
20
+ ``a == U @ S @ Vh``, where ``S`` is a suitably shaped matrix of zeros with
21
+ main diagonal ``s``.
22
+
23
+ Parameters
24
+ ----------
25
+ a : (M, N) array_like
26
+ Matrix to decompose.
27
+ full_matrices : bool, optional
28
+ If True (default), `U` and `Vh` are of shape ``(M, M)``, ``(N, N)``.
29
+ If False, the shapes are ``(M, K)`` and ``(K, N)``, where
30
+ ``K = min(M, N)``.
31
+ compute_uv : bool, optional
32
+ Whether to compute also ``U`` and ``Vh`` in addition to ``s``.
33
+ Default is True.
34
+ overwrite_a : bool, optional
35
+ Whether to overwrite `a`; may improve performance.
36
+ Default is False.
37
+ check_finite : bool, optional
38
+ Whether to check that the input matrix contains only finite numbers.
39
+ Disabling may give a performance gain, but may result in problems
40
+ (crashes, non-termination) if the inputs do contain infinities or NaNs.
41
+ lapack_driver : {'gesdd', 'gesvd'}, optional
42
+ Whether to use the more efficient divide-and-conquer approach
43
+ (``'gesdd'``) or general rectangular approach (``'gesvd'``)
44
+ to compute the SVD. MATLAB and Octave use the ``'gesvd'`` approach.
45
+ Default is ``'gesdd'``.
46
+
47
+ .. versionadded:: 0.18
48
+
49
+ Returns
50
+ -------
51
+ U : ndarray
52
+ Unitary matrix having left singular vectors as columns.
53
+ Of shape ``(M, M)`` or ``(M, K)``, depending on `full_matrices`.
54
+ s : ndarray
55
+ The singular values, sorted in non-increasing order.
56
+ Of shape (K,), with ``K = min(M, N)``.
57
+ Vh : ndarray
58
+ Unitary matrix having right singular vectors as rows.
59
+ Of shape ``(N, N)`` or ``(K, N)`` depending on `full_matrices`.
60
+
61
+ For ``compute_uv=False``, only ``s`` is returned.
62
+
63
+ Raises
64
+ ------
65
+ LinAlgError
66
+ If SVD computation does not converge.
67
+
68
+ See Also
69
+ --------
70
+ svdvals : Compute singular values of a matrix.
71
+ diagsvd : Construct the Sigma matrix, given the vector s.
72
+
73
+ Examples
74
+ --------
75
+ >>> import numpy as np
76
+ >>> from scipy import linalg
77
+ >>> rng = np.random.default_rng()
78
+ >>> m, n = 9, 6
79
+ >>> a = rng.standard_normal((m, n)) + 1.j*rng.standard_normal((m, n))
80
+ >>> U, s, Vh = linalg.svd(a)
81
+ >>> U.shape, s.shape, Vh.shape
82
+ ((9, 9), (6,), (6, 6))
83
+
84
+ Reconstruct the original matrix from the decomposition:
85
+
86
+ >>> sigma = np.zeros((m, n))
87
+ >>> for i in range(min(m, n)):
88
+ ... sigma[i, i] = s[i]
89
+ >>> a1 = np.dot(U, np.dot(sigma, Vh))
90
+ >>> np.allclose(a, a1)
91
+ True
92
+
93
+ Alternatively, use ``full_matrices=False`` (notice that the shape of
94
+ ``U`` is then ``(m, n)`` instead of ``(m, m)``):
95
+
96
+ >>> U, s, Vh = linalg.svd(a, full_matrices=False)
97
+ >>> U.shape, s.shape, Vh.shape
98
+ ((9, 6), (6,), (6, 6))
99
+ >>> S = np.diag(s)
100
+ >>> np.allclose(a, np.dot(U, np.dot(S, Vh)))
101
+ True
102
+
103
+ >>> s2 = linalg.svd(a, compute_uv=False)
104
+ >>> np.allclose(s, s2)
105
+ True
106
+
107
+ """
108
+ a1 = _asarray_validated(a, check_finite=check_finite)
109
+ if len(a1.shape) != 2:
110
+ raise ValueError('expected matrix')
111
+ m, n = a1.shape
112
+ overwrite_a = overwrite_a or (_datacopied(a1, a))
113
+
114
+ if not isinstance(lapack_driver, str):
115
+ raise TypeError('lapack_driver must be a string')
116
+ if lapack_driver not in ('gesdd', 'gesvd'):
117
+ message = f'lapack_driver must be "gesdd" or "gesvd", not "{lapack_driver}"'
118
+ raise ValueError(message)
119
+
120
+ if lapack_driver == 'gesdd' and compute_uv:
121
+ # XXX: revisit int32 when ILP64 lapack becomes a thing
122
+ max_mn, min_mn = (m, n) if m > n else (n, m)
123
+ if full_matrices:
124
+ if max_mn*max_mn > numpy.iinfo(numpy.int32).max:
125
+ raise ValueError(f"Indexing a matrix size {max_mn} x {max_mn} "
126
+ " would incur integer overflow in LAPACK.")
127
+ else:
128
+ sz = max(m * min_mn, n * min_mn)
129
+ if max(m * min_mn, n * min_mn) > numpy.iinfo(numpy.int32).max:
130
+ raise ValueError(f"Indexing a matrix of {sz} elements would "
131
+ "incur an in integer overflow in LAPACK.")
132
+
133
+ funcs = (lapack_driver, lapack_driver + '_lwork')
134
+ gesXd, gesXd_lwork = get_lapack_funcs(funcs, (a1,), ilp64='preferred')
135
+
136
+ # compute optimal lwork
137
+ lwork = _compute_lwork(gesXd_lwork, a1.shape[0], a1.shape[1],
138
+ compute_uv=compute_uv, full_matrices=full_matrices)
139
+
140
+ # perform decomposition
141
+ u, s, v, info = gesXd(a1, compute_uv=compute_uv, lwork=lwork,
142
+ full_matrices=full_matrices, overwrite_a=overwrite_a)
143
+
144
+ if info > 0:
145
+ raise LinAlgError("SVD did not converge")
146
+ if info < 0:
147
+ raise ValueError('illegal value in %dth argument of internal gesdd'
148
+ % -info)
149
+ if compute_uv:
150
+ return u, s, v
151
+ else:
152
+ return s
153
+
154
+
155
+ def svdvals(a, overwrite_a=False, check_finite=True):
156
+ """
157
+ Compute singular values of a matrix.
158
+
159
+ Parameters
160
+ ----------
161
+ a : (M, N) array_like
162
+ Matrix to decompose.
163
+ overwrite_a : bool, optional
164
+ Whether to overwrite `a`; may improve performance.
165
+ Default is False.
166
+ check_finite : bool, optional
167
+ Whether to check that the input matrix contains only finite numbers.
168
+ Disabling may give a performance gain, but may result in problems
169
+ (crashes, non-termination) if the inputs do contain infinities or NaNs.
170
+
171
+ Returns
172
+ -------
173
+ s : (min(M, N),) ndarray
174
+ The singular values, sorted in decreasing order.
175
+
176
+ Raises
177
+ ------
178
+ LinAlgError
179
+ If SVD computation does not converge.
180
+
181
+ See Also
182
+ --------
183
+ svd : Compute the full singular value decomposition of a matrix.
184
+ diagsvd : Construct the Sigma matrix, given the vector s.
185
+
186
+ Notes
187
+ -----
188
+ ``svdvals(a)`` only differs from ``svd(a, compute_uv=False)`` by its
189
+ handling of the edge case of empty ``a``, where it returns an
190
+ empty sequence:
191
+
192
+ >>> import numpy as np
193
+ >>> a = np.empty((0, 2))
194
+ >>> from scipy.linalg import svdvals
195
+ >>> svdvals(a)
196
+ array([], dtype=float64)
197
+
198
+ Examples
199
+ --------
200
+ >>> import numpy as np
201
+ >>> from scipy.linalg import svdvals
202
+ >>> m = np.array([[1.0, 0.0],
203
+ ... [2.0, 3.0],
204
+ ... [1.0, 1.0],
205
+ ... [0.0, 2.0],
206
+ ... [1.0, 0.0]])
207
+ >>> svdvals(m)
208
+ array([ 4.28091555, 1.63516424])
209
+
210
+ We can verify the maximum singular value of `m` by computing the maximum
211
+ length of `m.dot(u)` over all the unit vectors `u` in the (x,y) plane.
212
+ We approximate "all" the unit vectors with a large sample. Because
213
+ of linearity, we only need the unit vectors with angles in [0, pi].
214
+
215
+ >>> t = np.linspace(0, np.pi, 2000)
216
+ >>> u = np.array([np.cos(t), np.sin(t)])
217
+ >>> np.linalg.norm(m.dot(u), axis=0).max()
218
+ 4.2809152422538475
219
+
220
+ `p` is a projection matrix with rank 1. With exact arithmetic,
221
+ its singular values would be [1, 0, 0, 0].
222
+
223
+ >>> v = np.array([0.1, 0.3, 0.9, 0.3])
224
+ >>> p = np.outer(v, v)
225
+ >>> svdvals(p)
226
+ array([ 1.00000000e+00, 2.02021698e-17, 1.56692500e-17,
227
+ 8.15115104e-34])
228
+
229
+ The singular values of an orthogonal matrix are all 1. Here, we
230
+ create a random orthogonal matrix by using the `rvs()` method of
231
+ `scipy.stats.ortho_group`.
232
+
233
+ >>> from scipy.stats import ortho_group
234
+ >>> orth = ortho_group.rvs(4)
235
+ >>> svdvals(orth)
236
+ array([ 1., 1., 1., 1.])
237
+
238
+ """
239
+ a = _asarray_validated(a, check_finite=check_finite)
240
+ if a.size:
241
+ return svd(a, compute_uv=0, overwrite_a=overwrite_a,
242
+ check_finite=False)
243
+ elif len(a.shape) != 2:
244
+ raise ValueError('expected matrix')
245
+ else:
246
+ return numpy.empty(0)
247
+
248
+
249
+ def diagsvd(s, M, N):
250
+ """
251
+ Construct the sigma matrix in SVD from singular values and size M, N.
252
+
253
+ Parameters
254
+ ----------
255
+ s : (M,) or (N,) array_like
256
+ Singular values
257
+ M : int
258
+ Size of the matrix whose singular values are `s`.
259
+ N : int
260
+ Size of the matrix whose singular values are `s`.
261
+
262
+ Returns
263
+ -------
264
+ S : (M, N) ndarray
265
+ The S-matrix in the singular value decomposition
266
+
267
+ See Also
268
+ --------
269
+ svd : Singular value decomposition of a matrix
270
+ svdvals : Compute singular values of a matrix.
271
+
272
+ Examples
273
+ --------
274
+ >>> import numpy as np
275
+ >>> from scipy.linalg import diagsvd
276
+ >>> vals = np.array([1, 2, 3]) # The array representing the computed svd
277
+ >>> diagsvd(vals, 3, 4)
278
+ array([[1, 0, 0, 0],
279
+ [0, 2, 0, 0],
280
+ [0, 0, 3, 0]])
281
+ >>> diagsvd(vals, 4, 3)
282
+ array([[1, 0, 0],
283
+ [0, 2, 0],
284
+ [0, 0, 3],
285
+ [0, 0, 0]])
286
+
287
+ """
288
+ part = diag(s)
289
+ typ = part.dtype.char
290
+ MorN = len(s)
291
+ if MorN == M:
292
+ return numpy.hstack((part, zeros((M, N - M), dtype=typ)))
293
+ elif MorN == N:
294
+ return r_[part, zeros((M - N, N), dtype=typ)]
295
+ else:
296
+ raise ValueError("Length of s must be M or N.")
297
+
298
+
299
+ # Orthonormal decomposition
300
+
301
+ def orth(A, rcond=None):
302
+ """
303
+ Construct an orthonormal basis for the range of A using SVD
304
+
305
+ Parameters
306
+ ----------
307
+ A : (M, N) array_like
308
+ Input array
309
+ rcond : float, optional
310
+ Relative condition number. Singular values ``s`` smaller than
311
+ ``rcond * max(s)`` are considered zero.
312
+ Default: floating point eps * max(M,N).
313
+
314
+ Returns
315
+ -------
316
+ Q : (M, K) ndarray
317
+ Orthonormal basis for the range of A.
318
+ K = effective rank of A, as determined by rcond
319
+
320
+ See Also
321
+ --------
322
+ svd : Singular value decomposition of a matrix
323
+ null_space : Matrix null space
324
+
325
+ Examples
326
+ --------
327
+ >>> import numpy as np
328
+ >>> from scipy.linalg import orth
329
+ >>> A = np.array([[2, 0, 0], [0, 5, 0]]) # rank 2 array
330
+ >>> orth(A)
331
+ array([[0., 1.],
332
+ [1., 0.]])
333
+ >>> orth(A.T)
334
+ array([[0., 1.],
335
+ [1., 0.],
336
+ [0., 0.]])
337
+
338
+ """
339
+ u, s, vh = svd(A, full_matrices=False)
340
+ M, N = u.shape[0], vh.shape[1]
341
+ if rcond is None:
342
+ rcond = numpy.finfo(s.dtype).eps * max(M, N)
343
+ tol = numpy.amax(s) * rcond
344
+ num = numpy.sum(s > tol, dtype=int)
345
+ Q = u[:, :num]
346
+ return Q
347
+
348
+
349
+ def null_space(A, rcond=None):
350
+ """
351
+ Construct an orthonormal basis for the null space of A using SVD
352
+
353
+ Parameters
354
+ ----------
355
+ A : (M, N) array_like
356
+ Input array
357
+ rcond : float, optional
358
+ Relative condition number. Singular values ``s`` smaller than
359
+ ``rcond * max(s)`` are considered zero.
360
+ Default: floating point eps * max(M,N).
361
+
362
+ Returns
363
+ -------
364
+ Z : (N, K) ndarray
365
+ Orthonormal basis for the null space of A.
366
+ K = dimension of effective null space, as determined by rcond
367
+
368
+ See Also
369
+ --------
370
+ svd : Singular value decomposition of a matrix
371
+ orth : Matrix range
372
+
373
+ Examples
374
+ --------
375
+ 1-D null space:
376
+
377
+ >>> import numpy as np
378
+ >>> from scipy.linalg import null_space
379
+ >>> A = np.array([[1, 1], [1, 1]])
380
+ >>> ns = null_space(A)
381
+ >>> ns * np.copysign(1, ns[0,0]) # Remove the sign ambiguity of the vector
382
+ array([[ 0.70710678],
383
+ [-0.70710678]])
384
+
385
+ 2-D null space:
386
+
387
+ >>> from numpy.random import default_rng
388
+ >>> rng = default_rng()
389
+ >>> B = rng.random((3, 5))
390
+ >>> Z = null_space(B)
391
+ >>> Z.shape
392
+ (5, 2)
393
+ >>> np.allclose(B.dot(Z), 0)
394
+ True
395
+
396
+ The basis vectors are orthonormal (up to rounding error):
397
+
398
+ >>> Z.T.dot(Z)
399
+ array([[ 1.00000000e+00, 6.92087741e-17],
400
+ [ 6.92087741e-17, 1.00000000e+00]])
401
+
402
+ """
403
+ u, s, vh = svd(A, full_matrices=True)
404
+ M, N = u.shape[0], vh.shape[1]
405
+ if rcond is None:
406
+ rcond = numpy.finfo(s.dtype).eps * max(M, N)
407
+ tol = numpy.amax(s) * rcond
408
+ num = numpy.sum(s > tol, dtype=int)
409
+ Q = vh[num:,:].T.conj()
410
+ return Q
411
+
412
+
413
+ def subspace_angles(A, B):
414
+ r"""
415
+ Compute the subspace angles between two matrices.
416
+
417
+ Parameters
418
+ ----------
419
+ A : (M, N) array_like
420
+ The first input array.
421
+ B : (M, K) array_like
422
+ The second input array.
423
+
424
+ Returns
425
+ -------
426
+ angles : ndarray, shape (min(N, K),)
427
+ The subspace angles between the column spaces of `A` and `B` in
428
+ descending order.
429
+
430
+ See Also
431
+ --------
432
+ orth
433
+ svd
434
+
435
+ Notes
436
+ -----
437
+ This computes the subspace angles according to the formula
438
+ provided in [1]_. For equivalence with MATLAB and Octave behavior,
439
+ use ``angles[0]``.
440
+
441
+ .. versionadded:: 1.0
442
+
443
+ References
444
+ ----------
445
+ .. [1] Knyazev A, Argentati M (2002) Principal Angles between Subspaces
446
+ in an A-Based Scalar Product: Algorithms and Perturbation
447
+ Estimates. SIAM J. Sci. Comput. 23:2008-2040.
448
+
449
+ Examples
450
+ --------
451
+ An Hadamard matrix, which has orthogonal columns, so we expect that
452
+ the suspace angle to be :math:`\frac{\pi}{2}`:
453
+
454
+ >>> import numpy as np
455
+ >>> from scipy.linalg import hadamard, subspace_angles
456
+ >>> rng = np.random.default_rng()
457
+ >>> H = hadamard(4)
458
+ >>> print(H)
459
+ [[ 1 1 1 1]
460
+ [ 1 -1 1 -1]
461
+ [ 1 1 -1 -1]
462
+ [ 1 -1 -1 1]]
463
+ >>> np.rad2deg(subspace_angles(H[:, :2], H[:, 2:]))
464
+ array([ 90., 90.])
465
+
466
+ And the subspace angle of a matrix to itself should be zero:
467
+
468
+ >>> subspace_angles(H[:, :2], H[:, :2]) <= 2 * np.finfo(float).eps
469
+ array([ True, True], dtype=bool)
470
+
471
+ The angles between non-orthogonal subspaces are in between these extremes:
472
+
473
+ >>> x = rng.standard_normal((4, 3))
474
+ >>> np.rad2deg(subspace_angles(x[:, :2], x[:, [2]]))
475
+ array([ 55.832]) # random
476
+ """
477
+ # Steps here omit the U and V calculation steps from the paper
478
+
479
+ # 1. Compute orthonormal bases of column-spaces
480
+ A = _asarray_validated(A, check_finite=True)
481
+ if len(A.shape) != 2:
482
+ raise ValueError(f'expected 2D array, got shape {A.shape}')
483
+ QA = orth(A)
484
+ del A
485
+
486
+ B = _asarray_validated(B, check_finite=True)
487
+ if len(B.shape) != 2:
488
+ raise ValueError(f'expected 2D array, got shape {B.shape}')
489
+ if len(B) != len(QA):
490
+ raise ValueError('A and B must have the same number of rows, got '
491
+ f'{QA.shape[0]} and {B.shape[0]}')
492
+ QB = orth(B)
493
+ del B
494
+
495
+ # 2. Compute SVD for cosine
496
+ QA_H_QB = dot(QA.T.conj(), QB)
497
+ sigma = svdvals(QA_H_QB)
498
+
499
+ # 3. Compute matrix B
500
+ if QA.shape[1] >= QB.shape[1]:
501
+ B = QB - dot(QA, QA_H_QB)
502
+ else:
503
+ B = QA - dot(QB, QA_H_QB.T.conj())
504
+ del QA, QB, QA_H_QB
505
+
506
+ # 4. Compute SVD for sine
507
+ mask = sigma ** 2 >= 0.5
508
+ if mask.any():
509
+ mu_arcsin = arcsin(clip(svdvals(B, overwrite_a=True), -1., 1.))
510
+ else:
511
+ mu_arcsin = 0.
512
+
513
+ # 5. Compute the principal angles
514
+ # with reverse ordering of sigma because smallest sigma belongs to largest
515
+ # angle theta
516
+ theta = where(mask, mu_arcsin, arccos(clip(sigma[::-1], -1., 1.)))
517
+ return theta
astra_scene_test/Scene_04/.venv/lib/python3.9/site-packages/scipy/linalg/_expm_frechet.py ADDED
@@ -0,0 +1,413 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """Frechet derivative of the matrix exponential."""
2
+ import numpy as np
3
+ import scipy.linalg
4
+
5
+ __all__ = ['expm_frechet', 'expm_cond']
6
+
7
+
8
+ def expm_frechet(A, E, method=None, compute_expm=True, check_finite=True):
9
+ """
10
+ Frechet derivative of the matrix exponential of A in the direction E.
11
+
12
+ Parameters
13
+ ----------
14
+ A : (N, N) array_like
15
+ Matrix of which to take the matrix exponential.
16
+ E : (N, N) array_like
17
+ Matrix direction in which to take the Frechet derivative.
18
+ method : str, optional
19
+ Choice of algorithm. Should be one of
20
+
21
+ - `SPS` (default)
22
+ - `blockEnlarge`
23
+
24
+ compute_expm : bool, optional
25
+ Whether to compute also `expm_A` in addition to `expm_frechet_AE`.
26
+ Default is True.
27
+ check_finite : bool, optional
28
+ Whether to check that the input matrix contains only finite numbers.
29
+ Disabling may give a performance gain, but may result in problems
30
+ (crashes, non-termination) if the inputs do contain infinities or NaNs.
31
+
32
+ Returns
33
+ -------
34
+ expm_A : ndarray
35
+ Matrix exponential of A.
36
+ expm_frechet_AE : ndarray
37
+ Frechet derivative of the matrix exponential of A in the direction E.
38
+ For ``compute_expm = False``, only `expm_frechet_AE` is returned.
39
+
40
+ See Also
41
+ --------
42
+ expm : Compute the exponential of a matrix.
43
+
44
+ Notes
45
+ -----
46
+ This section describes the available implementations that can be selected
47
+ by the `method` parameter. The default method is *SPS*.
48
+
49
+ Method *blockEnlarge* is a naive algorithm.
50
+
51
+ Method *SPS* is Scaling-Pade-Squaring [1]_.
52
+ It is a sophisticated implementation which should take
53
+ only about 3/8 as much time as the naive implementation.
54
+ The asymptotics are the same.
55
+
56
+ .. versionadded:: 0.13.0
57
+
58
+ References
59
+ ----------
60
+ .. [1] Awad H. Al-Mohy and Nicholas J. Higham (2009)
61
+ Computing the Frechet Derivative of the Matrix Exponential,
62
+ with an application to Condition Number Estimation.
63
+ SIAM Journal On Matrix Analysis and Applications.,
64
+ 30 (4). pp. 1639-1657. ISSN 1095-7162
65
+
66
+ Examples
67
+ --------
68
+ >>> import numpy as np
69
+ >>> from scipy import linalg
70
+ >>> rng = np.random.default_rng()
71
+
72
+ >>> A = rng.standard_normal((3, 3))
73
+ >>> E = rng.standard_normal((3, 3))
74
+ >>> expm_A, expm_frechet_AE = linalg.expm_frechet(A, E)
75
+ >>> expm_A.shape, expm_frechet_AE.shape
76
+ ((3, 3), (3, 3))
77
+
78
+ Create a 6x6 matrix containing [[A, E], [0, A]]:
79
+
80
+ >>> M = np.zeros((6, 6))
81
+ >>> M[:3, :3] = A
82
+ >>> M[:3, 3:] = E
83
+ >>> M[3:, 3:] = A
84
+
85
+ >>> expm_M = linalg.expm(M)
86
+ >>> np.allclose(expm_A, expm_M[:3, :3])
87
+ True
88
+ >>> np.allclose(expm_frechet_AE, expm_M[:3, 3:])
89
+ True
90
+
91
+ """
92
+ if check_finite:
93
+ A = np.asarray_chkfinite(A)
94
+ E = np.asarray_chkfinite(E)
95
+ else:
96
+ A = np.asarray(A)
97
+ E = np.asarray(E)
98
+ if A.ndim != 2 or A.shape[0] != A.shape[1]:
99
+ raise ValueError('expected A to be a square matrix')
100
+ if E.ndim != 2 or E.shape[0] != E.shape[1]:
101
+ raise ValueError('expected E to be a square matrix')
102
+ if A.shape != E.shape:
103
+ raise ValueError('expected A and E to be the same shape')
104
+ if method is None:
105
+ method = 'SPS'
106
+ if method == 'SPS':
107
+ expm_A, expm_frechet_AE = expm_frechet_algo_64(A, E)
108
+ elif method == 'blockEnlarge':
109
+ expm_A, expm_frechet_AE = expm_frechet_block_enlarge(A, E)
110
+ else:
111
+ raise ValueError('Unknown implementation %s' % method)
112
+ if compute_expm:
113
+ return expm_A, expm_frechet_AE
114
+ else:
115
+ return expm_frechet_AE
116
+
117
+
118
+ def expm_frechet_block_enlarge(A, E):
119
+ """
120
+ This is a helper function, mostly for testing and profiling.
121
+ Return expm(A), frechet(A, E)
122
+ """
123
+ n = A.shape[0]
124
+ M = np.vstack([
125
+ np.hstack([A, E]),
126
+ np.hstack([np.zeros_like(A), A])])
127
+ expm_M = scipy.linalg.expm(M)
128
+ return expm_M[:n, :n], expm_M[:n, n:]
129
+
130
+
131
+ """
132
+ Maximal values ell_m of ||2**-s A|| such that the backward error bound
133
+ does not exceed 2**-53.
134
+ """
135
+ ell_table_61 = (
136
+ None,
137
+ # 1
138
+ 2.11e-8,
139
+ 3.56e-4,
140
+ 1.08e-2,
141
+ 6.49e-2,
142
+ 2.00e-1,
143
+ 4.37e-1,
144
+ 7.83e-1,
145
+ 1.23e0,
146
+ 1.78e0,
147
+ 2.42e0,
148
+ # 11
149
+ 3.13e0,
150
+ 3.90e0,
151
+ 4.74e0,
152
+ 5.63e0,
153
+ 6.56e0,
154
+ 7.52e0,
155
+ 8.53e0,
156
+ 9.56e0,
157
+ 1.06e1,
158
+ 1.17e1,
159
+ )
160
+
161
+
162
+ # The b vectors and U and V are copypasted
163
+ # from scipy.sparse.linalg.matfuncs.py.
164
+ # M, Lu, Lv follow (6.11), (6.12), (6.13), (3.3)
165
+
166
+ def _diff_pade3(A, E, ident):
167
+ b = (120., 60., 12., 1.)
168
+ A2 = A.dot(A)
169
+ M2 = np.dot(A, E) + np.dot(E, A)
170
+ U = A.dot(b[3]*A2 + b[1]*ident)
171
+ V = b[2]*A2 + b[0]*ident
172
+ Lu = A.dot(b[3]*M2) + E.dot(b[3]*A2 + b[1]*ident)
173
+ Lv = b[2]*M2
174
+ return U, V, Lu, Lv
175
+
176
+
177
+ def _diff_pade5(A, E, ident):
178
+ b = (30240., 15120., 3360., 420., 30., 1.)
179
+ A2 = A.dot(A)
180
+ M2 = np.dot(A, E) + np.dot(E, A)
181
+ A4 = np.dot(A2, A2)
182
+ M4 = np.dot(A2, M2) + np.dot(M2, A2)
183
+ U = A.dot(b[5]*A4 + b[3]*A2 + b[1]*ident)
184
+ V = b[4]*A4 + b[2]*A2 + b[0]*ident
185
+ Lu = (A.dot(b[5]*M4 + b[3]*M2) +
186
+ E.dot(b[5]*A4 + b[3]*A2 + b[1]*ident))
187
+ Lv = b[4]*M4 + b[2]*M2
188
+ return U, V, Lu, Lv
189
+
190
+
191
+ def _diff_pade7(A, E, ident):
192
+ b = (17297280., 8648640., 1995840., 277200., 25200., 1512., 56., 1.)
193
+ A2 = A.dot(A)
194
+ M2 = np.dot(A, E) + np.dot(E, A)
195
+ A4 = np.dot(A2, A2)
196
+ M4 = np.dot(A2, M2) + np.dot(M2, A2)
197
+ A6 = np.dot(A2, A4)
198
+ M6 = np.dot(A4, M2) + np.dot(M4, A2)
199
+ U = A.dot(b[7]*A6 + b[5]*A4 + b[3]*A2 + b[1]*ident)
200
+ V = b[6]*A6 + b[4]*A4 + b[2]*A2 + b[0]*ident
201
+ Lu = (A.dot(b[7]*M6 + b[5]*M4 + b[3]*M2) +
202
+ E.dot(b[7]*A6 + b[5]*A4 + b[3]*A2 + b[1]*ident))
203
+ Lv = b[6]*M6 + b[4]*M4 + b[2]*M2
204
+ return U, V, Lu, Lv
205
+
206
+
207
+ def _diff_pade9(A, E, ident):
208
+ b = (17643225600., 8821612800., 2075673600., 302702400., 30270240.,
209
+ 2162160., 110880., 3960., 90., 1.)
210
+ A2 = A.dot(A)
211
+ M2 = np.dot(A, E) + np.dot(E, A)
212
+ A4 = np.dot(A2, A2)
213
+ M4 = np.dot(A2, M2) + np.dot(M2, A2)
214
+ A6 = np.dot(A2, A4)
215
+ M6 = np.dot(A4, M2) + np.dot(M4, A2)
216
+ A8 = np.dot(A4, A4)
217
+ M8 = np.dot(A4, M4) + np.dot(M4, A4)
218
+ U = A.dot(b[9]*A8 + b[7]*A6 + b[5]*A4 + b[3]*A2 + b[1]*ident)
219
+ V = b[8]*A8 + b[6]*A6 + b[4]*A4 + b[2]*A2 + b[0]*ident
220
+ Lu = (A.dot(b[9]*M8 + b[7]*M6 + b[5]*M4 + b[3]*M2) +
221
+ E.dot(b[9]*A8 + b[7]*A6 + b[5]*A4 + b[3]*A2 + b[1]*ident))
222
+ Lv = b[8]*M8 + b[6]*M6 + b[4]*M4 + b[2]*M2
223
+ return U, V, Lu, Lv
224
+
225
+
226
+ def expm_frechet_algo_64(A, E):
227
+ n = A.shape[0]
228
+ s = None
229
+ ident = np.identity(n)
230
+ A_norm_1 = scipy.linalg.norm(A, 1)
231
+ m_pade_pairs = (
232
+ (3, _diff_pade3),
233
+ (5, _diff_pade5),
234
+ (7, _diff_pade7),
235
+ (9, _diff_pade9))
236
+ for m, pade in m_pade_pairs:
237
+ if A_norm_1 <= ell_table_61[m]:
238
+ U, V, Lu, Lv = pade(A, E, ident)
239
+ s = 0
240
+ break
241
+ if s is None:
242
+ # scaling
243
+ s = max(0, int(np.ceil(np.log2(A_norm_1 / ell_table_61[13]))))
244
+ A = A * 2.0**-s
245
+ E = E * 2.0**-s
246
+ # pade order 13
247
+ A2 = np.dot(A, A)
248
+ M2 = np.dot(A, E) + np.dot(E, A)
249
+ A4 = np.dot(A2, A2)
250
+ M4 = np.dot(A2, M2) + np.dot(M2, A2)
251
+ A6 = np.dot(A2, A4)
252
+ M6 = np.dot(A4, M2) + np.dot(M4, A2)
253
+ b = (64764752532480000., 32382376266240000., 7771770303897600.,
254
+ 1187353796428800., 129060195264000., 10559470521600.,
255
+ 670442572800., 33522128640., 1323241920., 40840800., 960960.,
256
+ 16380., 182., 1.)
257
+ W1 = b[13]*A6 + b[11]*A4 + b[9]*A2
258
+ W2 = b[7]*A6 + b[5]*A4 + b[3]*A2 + b[1]*ident
259
+ Z1 = b[12]*A6 + b[10]*A4 + b[8]*A2
260
+ Z2 = b[6]*A6 + b[4]*A4 + b[2]*A2 + b[0]*ident
261
+ W = np.dot(A6, W1) + W2
262
+ U = np.dot(A, W)
263
+ V = np.dot(A6, Z1) + Z2
264
+ Lw1 = b[13]*M6 + b[11]*M4 + b[9]*M2
265
+ Lw2 = b[7]*M6 + b[5]*M4 + b[3]*M2
266
+ Lz1 = b[12]*M6 + b[10]*M4 + b[8]*M2
267
+ Lz2 = b[6]*M6 + b[4]*M4 + b[2]*M2
268
+ Lw = np.dot(A6, Lw1) + np.dot(M6, W1) + Lw2
269
+ Lu = np.dot(A, Lw) + np.dot(E, W)
270
+ Lv = np.dot(A6, Lz1) + np.dot(M6, Z1) + Lz2
271
+ # factor once and solve twice
272
+ lu_piv = scipy.linalg.lu_factor(-U + V)
273
+ R = scipy.linalg.lu_solve(lu_piv, U + V)
274
+ L = scipy.linalg.lu_solve(lu_piv, Lu + Lv + np.dot((Lu - Lv), R))
275
+ # squaring
276
+ for k in range(s):
277
+ L = np.dot(R, L) + np.dot(L, R)
278
+ R = np.dot(R, R)
279
+ return R, L
280
+
281
+
282
+ def vec(M):
283
+ """
284
+ Stack columns of M to construct a single vector.
285
+
286
+ This is somewhat standard notation in linear algebra.
287
+
288
+ Parameters
289
+ ----------
290
+ M : 2-D array_like
291
+ Input matrix
292
+
293
+ Returns
294
+ -------
295
+ v : 1-D ndarray
296
+ Output vector
297
+
298
+ """
299
+ return M.T.ravel()
300
+
301
+
302
+ def expm_frechet_kronform(A, method=None, check_finite=True):
303
+ """
304
+ Construct the Kronecker form of the Frechet derivative of expm.
305
+
306
+ Parameters
307
+ ----------
308
+ A : array_like with shape (N, N)
309
+ Matrix to be expm'd.
310
+ method : str, optional
311
+ Extra keyword to be passed to expm_frechet.
312
+ check_finite : bool, optional
313
+ Whether to check that the input matrix contains only finite numbers.
314
+ Disabling may give a performance gain, but may result in problems
315
+ (crashes, non-termination) if the inputs do contain infinities or NaNs.
316
+
317
+ Returns
318
+ -------
319
+ K : 2-D ndarray with shape (N*N, N*N)
320
+ Kronecker form of the Frechet derivative of the matrix exponential.
321
+
322
+ Notes
323
+ -----
324
+ This function is used to help compute the condition number
325
+ of the matrix exponential.
326
+
327
+ See Also
328
+ --------
329
+ expm : Compute a matrix exponential.
330
+ expm_frechet : Compute the Frechet derivative of the matrix exponential.
331
+ expm_cond : Compute the relative condition number of the matrix exponential
332
+ in the Frobenius norm.
333
+
334
+ """
335
+ if check_finite:
336
+ A = np.asarray_chkfinite(A)
337
+ else:
338
+ A = np.asarray(A)
339
+ if len(A.shape) != 2 or A.shape[0] != A.shape[1]:
340
+ raise ValueError('expected a square matrix')
341
+
342
+ n = A.shape[0]
343
+ ident = np.identity(n)
344
+ cols = []
345
+ for i in range(n):
346
+ for j in range(n):
347
+ E = np.outer(ident[i], ident[j])
348
+ F = expm_frechet(A, E,
349
+ method=method, compute_expm=False, check_finite=False)
350
+ cols.append(vec(F))
351
+ return np.vstack(cols).T
352
+
353
+
354
+ def expm_cond(A, check_finite=True):
355
+ """
356
+ Relative condition number of the matrix exponential in the Frobenius norm.
357
+
358
+ Parameters
359
+ ----------
360
+ A : 2-D array_like
361
+ Square input matrix with shape (N, N).
362
+ check_finite : bool, optional
363
+ Whether to check that the input matrix contains only finite numbers.
364
+ Disabling may give a performance gain, but may result in problems
365
+ (crashes, non-termination) if the inputs do contain infinities or NaNs.
366
+
367
+ Returns
368
+ -------
369
+ kappa : float
370
+ The relative condition number of the matrix exponential
371
+ in the Frobenius norm
372
+
373
+ See Also
374
+ --------
375
+ expm : Compute the exponential of a matrix.
376
+ expm_frechet : Compute the Frechet derivative of the matrix exponential.
377
+
378
+ Notes
379
+ -----
380
+ A faster estimate for the condition number in the 1-norm
381
+ has been published but is not yet implemented in SciPy.
382
+
383
+ .. versionadded:: 0.14.0
384
+
385
+ Examples
386
+ --------
387
+ >>> import numpy as np
388
+ >>> from scipy.linalg import expm_cond
389
+ >>> A = np.array([[-0.3, 0.2, 0.6], [0.6, 0.3, -0.1], [-0.7, 1.2, 0.9]])
390
+ >>> k = expm_cond(A)
391
+ >>> k
392
+ 1.7787805864469866
393
+
394
+ """
395
+ if check_finite:
396
+ A = np.asarray_chkfinite(A)
397
+ else:
398
+ A = np.asarray(A)
399
+ if len(A.shape) != 2 or A.shape[0] != A.shape[1]:
400
+ raise ValueError('expected a square matrix')
401
+
402
+ X = scipy.linalg.expm(A)
403
+ K = expm_frechet_kronform(A, check_finite=False)
404
+
405
+ # The following norm choices are deliberate.
406
+ # The norms of A and X are Frobenius norms,
407
+ # and the norm of K is the induced 2-norm.
408
+ A_norm = scipy.linalg.norm(A, 'fro')
409
+ X_norm = scipy.linalg.norm(X, 'fro')
410
+ K_norm = scipy.linalg.norm(K, 2)
411
+
412
+ kappa = (K_norm * A_norm) / X_norm
413
+ return kappa
astra_scene_test/Scene_04/.venv/lib/python3.9/site-packages/scipy/linalg/_interpolative_backend.py ADDED
@@ -0,0 +1,1681 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #******************************************************************************
2
+ # Copyright (C) 2013 Kenneth L. Ho
3
+ #
4
+ # Redistribution and use in source and binary forms, with or without
5
+ # modification, are permitted provided that the following conditions are met:
6
+ #
7
+ # Redistributions of source code must retain the above copyright notice, this
8
+ # list of conditions and the following disclaimer. Redistributions in binary
9
+ # form must reproduce the above copyright notice, this list of conditions and
10
+ # the following disclaimer in the documentation and/or other materials
11
+ # provided with the distribution.
12
+ #
13
+ # None of the names of the copyright holders may be used to endorse or
14
+ # promote products derived from this software without specific prior written
15
+ # permission.
16
+ #
17
+ # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
18
+ # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19
+ # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20
+ # ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
21
+ # LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22
+ # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23
+ # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24
+ # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
25
+ # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
26
+ # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27
+ # POSSIBILITY OF SUCH DAMAGE.
28
+ #******************************************************************************
29
+
30
+ """
31
+ Direct wrappers for Fortran `id_dist` backend.
32
+ """
33
+
34
+ import scipy.linalg._interpolative as _id
35
+ import numpy as np
36
+
37
+ _RETCODE_ERROR = RuntimeError("nonzero return code")
38
+
39
+
40
+ def _asfortranarray_copy(A):
41
+ """
42
+ Same as np.asfortranarray, but ensure a copy
43
+ """
44
+ A = np.asarray(A)
45
+ if A.flags.f_contiguous:
46
+ A = A.copy(order="F")
47
+ else:
48
+ A = np.asfortranarray(A)
49
+ return A
50
+
51
+
52
+ #------------------------------------------------------------------------------
53
+ # id_rand.f
54
+ #------------------------------------------------------------------------------
55
+
56
+ def id_srand(n):
57
+ """
58
+ Generate standard uniform pseudorandom numbers via a very efficient lagged
59
+ Fibonacci method.
60
+
61
+ :param n:
62
+ Number of pseudorandom numbers to generate.
63
+ :type n: int
64
+
65
+ :return:
66
+ Pseudorandom numbers.
67
+ :rtype: :class:`numpy.ndarray`
68
+ """
69
+ return _id.id_srand(n)
70
+
71
+
72
+ def id_srandi(t):
73
+ """
74
+ Initialize seed values for :func:`id_srand` (any appropriately random
75
+ numbers will do).
76
+
77
+ :param t:
78
+ Array of 55 seed values.
79
+ :type t: :class:`numpy.ndarray`
80
+ """
81
+ t = np.asfortranarray(t)
82
+ _id.id_srandi(t)
83
+
84
+
85
+ def id_srando():
86
+ """
87
+ Reset seed values to their original values.
88
+ """
89
+ _id.id_srando()
90
+
91
+
92
+ #------------------------------------------------------------------------------
93
+ # idd_frm.f
94
+ #------------------------------------------------------------------------------
95
+
96
+ def idd_frm(n, w, x):
97
+ """
98
+ Transform real vector via a composition of Rokhlin's random transform,
99
+ random subselection, and an FFT.
100
+
101
+ In contrast to :func:`idd_sfrm`, this routine works best when the length of
102
+ the transformed vector is the power-of-two integer output by
103
+ :func:`idd_frmi`, or when the length is not specified but instead
104
+ determined a posteriori from the output. The returned transformed vector is
105
+ randomly permuted.
106
+
107
+ :param n:
108
+ Greatest power-of-two integer satisfying `n <= x.size` as obtained from
109
+ :func:`idd_frmi`; `n` is also the length of the output vector.
110
+ :type n: int
111
+ :param w:
112
+ Initialization array constructed by :func:`idd_frmi`.
113
+ :type w: :class:`numpy.ndarray`
114
+ :param x:
115
+ Vector to be transformed.
116
+ :type x: :class:`numpy.ndarray`
117
+
118
+ :return:
119
+ Transformed vector.
120
+ :rtype: :class:`numpy.ndarray`
121
+ """
122
+ return _id.idd_frm(n, w, x)
123
+
124
+
125
+ def idd_sfrm(l, n, w, x):
126
+ """
127
+ Transform real vector via a composition of Rokhlin's random transform,
128
+ random subselection, and an FFT.
129
+
130
+ In contrast to :func:`idd_frm`, this routine works best when the length of
131
+ the transformed vector is known a priori.
132
+
133
+ :param l:
134
+ Length of transformed vector, satisfying `l <= n`.
135
+ :type l: int
136
+ :param n:
137
+ Greatest power-of-two integer satisfying `n <= x.size` as obtained from
138
+ :func:`idd_sfrmi`.
139
+ :type n: int
140
+ :param w:
141
+ Initialization array constructed by :func:`idd_sfrmi`.
142
+ :type w: :class:`numpy.ndarray`
143
+ :param x:
144
+ Vector to be transformed.
145
+ :type x: :class:`numpy.ndarray`
146
+
147
+ :return:
148
+ Transformed vector.
149
+ :rtype: :class:`numpy.ndarray`
150
+ """
151
+ return _id.idd_sfrm(l, n, w, x)
152
+
153
+
154
+ def idd_frmi(m):
155
+ """
156
+ Initialize data for :func:`idd_frm`.
157
+
158
+ :param m:
159
+ Length of vector to be transformed.
160
+ :type m: int
161
+
162
+ :return:
163
+ Greatest power-of-two integer `n` satisfying `n <= m`.
164
+ :rtype: int
165
+ :return:
166
+ Initialization array to be used by :func:`idd_frm`.
167
+ :rtype: :class:`numpy.ndarray`
168
+ """
169
+ return _id.idd_frmi(m)
170
+
171
+
172
+ def idd_sfrmi(l, m):
173
+ """
174
+ Initialize data for :func:`idd_sfrm`.
175
+
176
+ :param l:
177
+ Length of output transformed vector.
178
+ :type l: int
179
+ :param m:
180
+ Length of the vector to be transformed.
181
+ :type m: int
182
+
183
+ :return:
184
+ Greatest power-of-two integer `n` satisfying `n <= m`.
185
+ :rtype: int
186
+ :return:
187
+ Initialization array to be used by :func:`idd_sfrm`.
188
+ :rtype: :class:`numpy.ndarray`
189
+ """
190
+ return _id.idd_sfrmi(l, m)
191
+
192
+
193
+ #------------------------------------------------------------------------------
194
+ # idd_id.f
195
+ #------------------------------------------------------------------------------
196
+
197
+ def iddp_id(eps, A):
198
+ """
199
+ Compute ID of a real matrix to a specified relative precision.
200
+
201
+ :param eps:
202
+ Relative precision.
203
+ :type eps: float
204
+ :param A:
205
+ Matrix.
206
+ :type A: :class:`numpy.ndarray`
207
+
208
+ :return:
209
+ Rank of ID.
210
+ :rtype: int
211
+ :return:
212
+ Column index array.
213
+ :rtype: :class:`numpy.ndarray`
214
+ :return:
215
+ Interpolation coefficients.
216
+ :rtype: :class:`numpy.ndarray`
217
+ """
218
+ A = _asfortranarray_copy(A)
219
+ k, idx, rnorms = _id.iddp_id(eps, A)
220
+ n = A.shape[1]
221
+ proj = A.T.ravel()[:k*(n-k)].reshape((k, n-k), order='F')
222
+ return k, idx, proj
223
+
224
+
225
+ def iddr_id(A, k):
226
+ """
227
+ Compute ID of a real matrix to a specified rank.
228
+
229
+ :param A:
230
+ Matrix.
231
+ :type A: :class:`numpy.ndarray`
232
+ :param k:
233
+ Rank of ID.
234
+ :type k: int
235
+
236
+ :return:
237
+ Column index array.
238
+ :rtype: :class:`numpy.ndarray`
239
+ :return:
240
+ Interpolation coefficients.
241
+ :rtype: :class:`numpy.ndarray`
242
+ """
243
+ A = _asfortranarray_copy(A)
244
+ idx, rnorms = _id.iddr_id(A, k)
245
+ n = A.shape[1]
246
+ proj = A.T.ravel()[:k*(n-k)].reshape((k, n-k), order='F')
247
+ return idx, proj
248
+
249
+
250
+ def idd_reconid(B, idx, proj):
251
+ """
252
+ Reconstruct matrix from real ID.
253
+
254
+ :param B:
255
+ Skeleton matrix.
256
+ :type B: :class:`numpy.ndarray`
257
+ :param idx:
258
+ Column index array.
259
+ :type idx: :class:`numpy.ndarray`
260
+ :param proj:
261
+ Interpolation coefficients.
262
+ :type proj: :class:`numpy.ndarray`
263
+
264
+ :return:
265
+ Reconstructed matrix.
266
+ :rtype: :class:`numpy.ndarray`
267
+ """
268
+ B = np.asfortranarray(B)
269
+ if proj.size > 0:
270
+ return _id.idd_reconid(B, idx, proj)
271
+ else:
272
+ return B[:, np.argsort(idx)]
273
+
274
+
275
+ def idd_reconint(idx, proj):
276
+ """
277
+ Reconstruct interpolation matrix from real ID.
278
+
279
+ :param idx:
280
+ Column index array.
281
+ :type idx: :class:`numpy.ndarray`
282
+ :param proj:
283
+ Interpolation coefficients.
284
+ :type proj: :class:`numpy.ndarray`
285
+
286
+ :return:
287
+ Interpolation matrix.
288
+ :rtype: :class:`numpy.ndarray`
289
+ """
290
+ return _id.idd_reconint(idx, proj)
291
+
292
+
293
+ def idd_copycols(A, k, idx):
294
+ """
295
+ Reconstruct skeleton matrix from real ID.
296
+
297
+ :param A:
298
+ Original matrix.
299
+ :type A: :class:`numpy.ndarray`
300
+ :param k:
301
+ Rank of ID.
302
+ :type k: int
303
+ :param idx:
304
+ Column index array.
305
+ :type idx: :class:`numpy.ndarray`
306
+
307
+ :return:
308
+ Skeleton matrix.
309
+ :rtype: :class:`numpy.ndarray`
310
+ """
311
+ A = np.asfortranarray(A)
312
+ return _id.idd_copycols(A, k, idx)
313
+
314
+
315
+ #------------------------------------------------------------------------------
316
+ # idd_id2svd.f
317
+ #------------------------------------------------------------------------------
318
+
319
+ def idd_id2svd(B, idx, proj):
320
+ """
321
+ Convert real ID to SVD.
322
+
323
+ :param B:
324
+ Skeleton matrix.
325
+ :type B: :class:`numpy.ndarray`
326
+ :param idx:
327
+ Column index array.
328
+ :type idx: :class:`numpy.ndarray`
329
+ :param proj:
330
+ Interpolation coefficients.
331
+ :type proj: :class:`numpy.ndarray`
332
+
333
+ :return:
334
+ Left singular vectors.
335
+ :rtype: :class:`numpy.ndarray`
336
+ :return:
337
+ Right singular vectors.
338
+ :rtype: :class:`numpy.ndarray`
339
+ :return:
340
+ Singular values.
341
+ :rtype: :class:`numpy.ndarray`
342
+ """
343
+ B = np.asfortranarray(B)
344
+ U, V, S, ier = _id.idd_id2svd(B, idx, proj)
345
+ if ier:
346
+ raise _RETCODE_ERROR
347
+ return U, V, S
348
+
349
+
350
+ #------------------------------------------------------------------------------
351
+ # idd_snorm.f
352
+ #------------------------------------------------------------------------------
353
+
354
+ def idd_snorm(m, n, matvect, matvec, its=20):
355
+ """
356
+ Estimate spectral norm of a real matrix by the randomized power method.
357
+
358
+ :param m:
359
+ Matrix row dimension.
360
+ :type m: int
361
+ :param n:
362
+ Matrix column dimension.
363
+ :type n: int
364
+ :param matvect:
365
+ Function to apply the matrix transpose to a vector, with call signature
366
+ `y = matvect(x)`, where `x` and `y` are the input and output vectors,
367
+ respectively.
368
+ :type matvect: function
369
+ :param matvec:
370
+ Function to apply the matrix to a vector, with call signature
371
+ `y = matvec(x)`, where `x` and `y` are the input and output vectors,
372
+ respectively.
373
+ :type matvec: function
374
+ :param its:
375
+ Number of power method iterations.
376
+ :type its: int
377
+
378
+ :return:
379
+ Spectral norm estimate.
380
+ :rtype: float
381
+ """
382
+ snorm, v = _id.idd_snorm(m, n, matvect, matvec, its)
383
+ return snorm
384
+
385
+
386
+ def idd_diffsnorm(m, n, matvect, matvect2, matvec, matvec2, its=20):
387
+ """
388
+ Estimate spectral norm of the difference of two real matrices by the
389
+ randomized power method.
390
+
391
+ :param m:
392
+ Matrix row dimension.
393
+ :type m: int
394
+ :param n:
395
+ Matrix column dimension.
396
+ :type n: int
397
+ :param matvect:
398
+ Function to apply the transpose of the first matrix to a vector, with
399
+ call signature `y = matvect(x)`, where `x` and `y` are the input and
400
+ output vectors, respectively.
401
+ :type matvect: function
402
+ :param matvect2:
403
+ Function to apply the transpose of the second matrix to a vector, with
404
+ call signature `y = matvect2(x)`, where `x` and `y` are the input and
405
+ output vectors, respectively.
406
+ :type matvect2: function
407
+ :param matvec:
408
+ Function to apply the first matrix to a vector, with call signature
409
+ `y = matvec(x)`, where `x` and `y` are the input and output vectors,
410
+ respectively.
411
+ :type matvec: function
412
+ :param matvec2:
413
+ Function to apply the second matrix to a vector, with call signature
414
+ `y = matvec2(x)`, where `x` and `y` are the input and output vectors,
415
+ respectively.
416
+ :type matvec2: function
417
+ :param its:
418
+ Number of power method iterations.
419
+ :type its: int
420
+
421
+ :return:
422
+ Spectral norm estimate of matrix difference.
423
+ :rtype: float
424
+ """
425
+ return _id.idd_diffsnorm(m, n, matvect, matvect2, matvec, matvec2, its)
426
+
427
+
428
+ #------------------------------------------------------------------------------
429
+ # idd_svd.f
430
+ #------------------------------------------------------------------------------
431
+
432
+ def iddr_svd(A, k):
433
+ """
434
+ Compute SVD of a real matrix to a specified rank.
435
+
436
+ :param A:
437
+ Matrix.
438
+ :type A: :class:`numpy.ndarray`
439
+ :param k:
440
+ Rank of SVD.
441
+ :type k: int
442
+
443
+ :return:
444
+ Left singular vectors.
445
+ :rtype: :class:`numpy.ndarray`
446
+ :return:
447
+ Right singular vectors.
448
+ :rtype: :class:`numpy.ndarray`
449
+ :return:
450
+ Singular values.
451
+ :rtype: :class:`numpy.ndarray`
452
+ """
453
+ A = np.asfortranarray(A)
454
+ U, V, S, ier = _id.iddr_svd(A, k)
455
+ if ier:
456
+ raise _RETCODE_ERROR
457
+ return U, V, S
458
+
459
+
460
+ def iddp_svd(eps, A):
461
+ """
462
+ Compute SVD of a real matrix to a specified relative precision.
463
+
464
+ :param eps:
465
+ Relative precision.
466
+ :type eps: float
467
+ :param A:
468
+ Matrix.
469
+ :type A: :class:`numpy.ndarray`
470
+
471
+ :return:
472
+ Left singular vectors.
473
+ :rtype: :class:`numpy.ndarray`
474
+ :return:
475
+ Right singular vectors.
476
+ :rtype: :class:`numpy.ndarray`
477
+ :return:
478
+ Singular values.
479
+ :rtype: :class:`numpy.ndarray`
480
+ """
481
+ A = np.asfortranarray(A)
482
+ m, n = A.shape
483
+ k, iU, iV, iS, w, ier = _id.iddp_svd(eps, A)
484
+ if ier:
485
+ raise _RETCODE_ERROR
486
+ U = w[iU-1:iU+m*k-1].reshape((m, k), order='F')
487
+ V = w[iV-1:iV+n*k-1].reshape((n, k), order='F')
488
+ S = w[iS-1:iS+k-1]
489
+ return U, V, S
490
+
491
+
492
+ #------------------------------------------------------------------------------
493
+ # iddp_aid.f
494
+ #------------------------------------------------------------------------------
495
+
496
+ def iddp_aid(eps, A):
497
+ """
498
+ Compute ID of a real matrix to a specified relative precision using random
499
+ sampling.
500
+
501
+ :param eps:
502
+ Relative precision.
503
+ :type eps: float
504
+ :param A:
505
+ Matrix.
506
+ :type A: :class:`numpy.ndarray`
507
+
508
+ :return:
509
+ Rank of ID.
510
+ :rtype: int
511
+ :return:
512
+ Column index array.
513
+ :rtype: :class:`numpy.ndarray`
514
+ :return:
515
+ Interpolation coefficients.
516
+ :rtype: :class:`numpy.ndarray`
517
+ """
518
+ A = np.asfortranarray(A)
519
+ m, n = A.shape
520
+ n2, w = idd_frmi(m)
521
+ proj = np.empty(n*(2*n2 + 1) + n2 + 1, order='F')
522
+ k, idx, proj = _id.iddp_aid(eps, A, w, proj)
523
+ proj = proj[:k*(n-k)].reshape((k, n-k), order='F')
524
+ return k, idx, proj
525
+
526
+
527
+ def idd_estrank(eps, A):
528
+ """
529
+ Estimate rank of a real matrix to a specified relative precision using
530
+ random sampling.
531
+
532
+ The output rank is typically about 8 higher than the actual rank.
533
+
534
+ :param eps:
535
+ Relative precision.
536
+ :type eps: float
537
+ :param A:
538
+ Matrix.
539
+ :type A: :class:`numpy.ndarray`
540
+
541
+ :return:
542
+ Rank estimate.
543
+ :rtype: int
544
+ """
545
+ A = np.asfortranarray(A)
546
+ m, n = A.shape
547
+ n2, w = idd_frmi(m)
548
+ ra = np.empty(n*n2 + (n + 1)*(n2 + 1), order='F')
549
+ k, ra = _id.idd_estrank(eps, A, w, ra)
550
+ return k
551
+
552
+
553
+ #------------------------------------------------------------------------------
554
+ # iddp_asvd.f
555
+ #------------------------------------------------------------------------------
556
+
557
+ def iddp_asvd(eps, A):
558
+ """
559
+ Compute SVD of a real matrix to a specified relative precision using random
560
+ sampling.
561
+
562
+ :param eps:
563
+ Relative precision.
564
+ :type eps: float
565
+ :param A:
566
+ Matrix.
567
+ :type A: :class:`numpy.ndarray`
568
+
569
+ :return:
570
+ Left singular vectors.
571
+ :rtype: :class:`numpy.ndarray`
572
+ :return:
573
+ Right singular vectors.
574
+ :rtype: :class:`numpy.ndarray`
575
+ :return:
576
+ Singular values.
577
+ :rtype: :class:`numpy.ndarray`
578
+ """
579
+ A = np.asfortranarray(A)
580
+ m, n = A.shape
581
+ n2, winit = _id.idd_frmi(m)
582
+ w = np.empty(
583
+ max((min(m, n) + 1)*(3*m + 5*n + 1) + 25*min(m, n)**2,
584
+ (2*n + 1)*(n2 + 1)),
585
+ order='F')
586
+ k, iU, iV, iS, w, ier = _id.iddp_asvd(eps, A, winit, w)
587
+ if ier:
588
+ raise _RETCODE_ERROR
589
+ U = w[iU-1:iU+m*k-1].reshape((m, k), order='F')
590
+ V = w[iV-1:iV+n*k-1].reshape((n, k), order='F')
591
+ S = w[iS-1:iS+k-1]
592
+ return U, V, S
593
+
594
+
595
+ #------------------------------------------------------------------------------
596
+ # iddp_rid.f
597
+ #------------------------------------------------------------------------------
598
+
599
+ def iddp_rid(eps, m, n, matvect):
600
+ """
601
+ Compute ID of a real matrix to a specified relative precision using random
602
+ matrix-vector multiplication.
603
+
604
+ :param eps:
605
+ Relative precision.
606
+ :type eps: float
607
+ :param m:
608
+ Matrix row dimension.
609
+ :type m: int
610
+ :param n:
611
+ Matrix column dimension.
612
+ :type n: int
613
+ :param matvect:
614
+ Function to apply the matrix transpose to a vector, with call signature
615
+ `y = matvect(x)`, where `x` and `y` are the input and output vectors,
616
+ respectively.
617
+ :type matvect: function
618
+
619
+ :return:
620
+ Rank of ID.
621
+ :rtype: int
622
+ :return:
623
+ Column index array.
624
+ :rtype: :class:`numpy.ndarray`
625
+ :return:
626
+ Interpolation coefficients.
627
+ :rtype: :class:`numpy.ndarray`
628
+ """
629
+ proj = np.empty(m + 1 + 2*n*(min(m, n) + 1), order='F')
630
+ k, idx, proj, ier = _id.iddp_rid(eps, m, n, matvect, proj)
631
+ if ier != 0:
632
+ raise _RETCODE_ERROR
633
+ proj = proj[:k*(n-k)].reshape((k, n-k), order='F')
634
+ return k, idx, proj
635
+
636
+
637
+ def idd_findrank(eps, m, n, matvect):
638
+ """
639
+ Estimate rank of a real matrix to a specified relative precision using
640
+ random matrix-vector multiplication.
641
+
642
+ :param eps:
643
+ Relative precision.
644
+ :type eps: float
645
+ :param m:
646
+ Matrix row dimension.
647
+ :type m: int
648
+ :param n:
649
+ Matrix column dimension.
650
+ :type n: int
651
+ :param matvect:
652
+ Function to apply the matrix transpose to a vector, with call signature
653
+ `y = matvect(x)`, where `x` and `y` are the input and output vectors,
654
+ respectively.
655
+ :type matvect: function
656
+
657
+ :return:
658
+ Rank estimate.
659
+ :rtype: int
660
+ """
661
+ k, ra, ier = _id.idd_findrank(eps, m, n, matvect)
662
+ if ier:
663
+ raise _RETCODE_ERROR
664
+ return k
665
+
666
+
667
+ #------------------------------------------------------------------------------
668
+ # iddp_rsvd.f
669
+ #------------------------------------------------------------------------------
670
+
671
+ def iddp_rsvd(eps, m, n, matvect, matvec):
672
+ """
673
+ Compute SVD of a real matrix to a specified relative precision using random
674
+ matrix-vector multiplication.
675
+
676
+ :param eps:
677
+ Relative precision.
678
+ :type eps: float
679
+ :param m:
680
+ Matrix row dimension.
681
+ :type m: int
682
+ :param n:
683
+ Matrix column dimension.
684
+ :type n: int
685
+ :param matvect:
686
+ Function to apply the matrix transpose to a vector, with call signature
687
+ `y = matvect(x)`, where `x` and `y` are the input and output vectors,
688
+ respectively.
689
+ :type matvect: function
690
+ :param matvec:
691
+ Function to apply the matrix to a vector, with call signature
692
+ `y = matvec(x)`, where `x` and `y` are the input and output vectors,
693
+ respectively.
694
+ :type matvec: function
695
+
696
+ :return:
697
+ Left singular vectors.
698
+ :rtype: :class:`numpy.ndarray`
699
+ :return:
700
+ Right singular vectors.
701
+ :rtype: :class:`numpy.ndarray`
702
+ :return:
703
+ Singular values.
704
+ :rtype: :class:`numpy.ndarray`
705
+ """
706
+ k, iU, iV, iS, w, ier = _id.iddp_rsvd(eps, m, n, matvect, matvec)
707
+ if ier:
708
+ raise _RETCODE_ERROR
709
+ U = w[iU-1:iU+m*k-1].reshape((m, k), order='F')
710
+ V = w[iV-1:iV+n*k-1].reshape((n, k), order='F')
711
+ S = w[iS-1:iS+k-1]
712
+ return U, V, S
713
+
714
+
715
+ #------------------------------------------------------------------------------
716
+ # iddr_aid.f
717
+ #------------------------------------------------------------------------------
718
+
719
+ def iddr_aid(A, k):
720
+ """
721
+ Compute ID of a real matrix to a specified rank using random sampling.
722
+
723
+ :param A:
724
+ Matrix.
725
+ :type A: :class:`numpy.ndarray`
726
+ :param k:
727
+ Rank of ID.
728
+ :type k: int
729
+
730
+ :return:
731
+ Column index array.
732
+ :rtype: :class:`numpy.ndarray`
733
+ :return:
734
+ Interpolation coefficients.
735
+ :rtype: :class:`numpy.ndarray`
736
+ """
737
+ A = np.asfortranarray(A)
738
+ m, n = A.shape
739
+ w = iddr_aidi(m, n, k)
740
+ idx, proj = _id.iddr_aid(A, k, w)
741
+ if k == n:
742
+ proj = np.empty((k, n-k), dtype='float64', order='F')
743
+ else:
744
+ proj = proj.reshape((k, n-k), order='F')
745
+ return idx, proj
746
+
747
+
748
+ def iddr_aidi(m, n, k):
749
+ """
750
+ Initialize array for :func:`iddr_aid`.
751
+
752
+ :param m:
753
+ Matrix row dimension.
754
+ :type m: int
755
+ :param n:
756
+ Matrix column dimension.
757
+ :type n: int
758
+ :param k:
759
+ Rank of ID.
760
+ :type k: int
761
+
762
+ :return:
763
+ Initialization array to be used by :func:`iddr_aid`.
764
+ :rtype: :class:`numpy.ndarray`
765
+ """
766
+ return _id.iddr_aidi(m, n, k)
767
+
768
+
769
+ #------------------------------------------------------------------------------
770
+ # iddr_asvd.f
771
+ #------------------------------------------------------------------------------
772
+
773
+ def iddr_asvd(A, k):
774
+ """
775
+ Compute SVD of a real matrix to a specified rank using random sampling.
776
+
777
+ :param A:
778
+ Matrix.
779
+ :type A: :class:`numpy.ndarray`
780
+ :param k:
781
+ Rank of SVD.
782
+ :type k: int
783
+
784
+ :return:
785
+ Left singular vectors.
786
+ :rtype: :class:`numpy.ndarray`
787
+ :return:
788
+ Right singular vectors.
789
+ :rtype: :class:`numpy.ndarray`
790
+ :return:
791
+ Singular values.
792
+ :rtype: :class:`numpy.ndarray`
793
+ """
794
+ A = np.asfortranarray(A)
795
+ m, n = A.shape
796
+ w = np.empty((2*k + 28)*m + (6*k + 21)*n + 25*k**2 + 100, order='F')
797
+ w_ = iddr_aidi(m, n, k)
798
+ w[:w_.size] = w_
799
+ U, V, S, ier = _id.iddr_asvd(A, k, w)
800
+ if ier != 0:
801
+ raise _RETCODE_ERROR
802
+ return U, V, S
803
+
804
+
805
+ #------------------------------------------------------------------------------
806
+ # iddr_rid.f
807
+ #------------------------------------------------------------------------------
808
+
809
+ def iddr_rid(m, n, matvect, k):
810
+ """
811
+ Compute ID of a real matrix to a specified rank using random matrix-vector
812
+ multiplication.
813
+
814
+ :param m:
815
+ Matrix row dimension.
816
+ :type m: int
817
+ :param n:
818
+ Matrix column dimension.
819
+ :type n: int
820
+ :param matvect:
821
+ Function to apply the matrix transpose to a vector, with call signature
822
+ `y = matvect(x)`, where `x` and `y` are the input and output vectors,
823
+ respectively.
824
+ :type matvect: function
825
+ :param k:
826
+ Rank of ID.
827
+ :type k: int
828
+
829
+ :return:
830
+ Column index array.
831
+ :rtype: :class:`numpy.ndarray`
832
+ :return:
833
+ Interpolation coefficients.
834
+ :rtype: :class:`numpy.ndarray`
835
+ """
836
+ idx, proj = _id.iddr_rid(m, n, matvect, k)
837
+ proj = proj[:k*(n-k)].reshape((k, n-k), order='F')
838
+ return idx, proj
839
+
840
+
841
+ #------------------------------------------------------------------------------
842
+ # iddr_rsvd.f
843
+ #------------------------------------------------------------------------------
844
+
845
+ def iddr_rsvd(m, n, matvect, matvec, k):
846
+ """
847
+ Compute SVD of a real matrix to a specified rank using random matrix-vector
848
+ multiplication.
849
+
850
+ :param m:
851
+ Matrix row dimension.
852
+ :type m: int
853
+ :param n:
854
+ Matrix column dimension.
855
+ :type n: int
856
+ :param matvect:
857
+ Function to apply the matrix transpose to a vector, with call signature
858
+ `y = matvect(x)`, where `x` and `y` are the input and output vectors,
859
+ respectively.
860
+ :type matvect: function
861
+ :param matvec:
862
+ Function to apply the matrix to a vector, with call signature
863
+ `y = matvec(x)`, where `x` and `y` are the input and output vectors,
864
+ respectively.
865
+ :type matvec: function
866
+ :param k:
867
+ Rank of SVD.
868
+ :type k: int
869
+
870
+ :return:
871
+ Left singular vectors.
872
+ :rtype: :class:`numpy.ndarray`
873
+ :return:
874
+ Right singular vectors.
875
+ :rtype: :class:`numpy.ndarray`
876
+ :return:
877
+ Singular values.
878
+ :rtype: :class:`numpy.ndarray`
879
+ """
880
+ U, V, S, ier = _id.iddr_rsvd(m, n, matvect, matvec, k)
881
+ if ier != 0:
882
+ raise _RETCODE_ERROR
883
+ return U, V, S
884
+
885
+
886
+ #------------------------------------------------------------------------------
887
+ # idz_frm.f
888
+ #------------------------------------------------------------------------------
889
+
890
+ def idz_frm(n, w, x):
891
+ """
892
+ Transform complex vector via a composition of Rokhlin's random transform,
893
+ random subselection, and an FFT.
894
+
895
+ In contrast to :func:`idz_sfrm`, this routine works best when the length of
896
+ the transformed vector is the power-of-two integer output by
897
+ :func:`idz_frmi`, or when the length is not specified but instead
898
+ determined a posteriori from the output. The returned transformed vector is
899
+ randomly permuted.
900
+
901
+ :param n:
902
+ Greatest power-of-two integer satisfying `n <= x.size` as obtained from
903
+ :func:`idz_frmi`; `n` is also the length of the output vector.
904
+ :type n: int
905
+ :param w:
906
+ Initialization array constructed by :func:`idz_frmi`.
907
+ :type w: :class:`numpy.ndarray`
908
+ :param x:
909
+ Vector to be transformed.
910
+ :type x: :class:`numpy.ndarray`
911
+
912
+ :return:
913
+ Transformed vector.
914
+ :rtype: :class:`numpy.ndarray`
915
+ """
916
+ return _id.idz_frm(n, w, x)
917
+
918
+
919
+ def idz_sfrm(l, n, w, x):
920
+ """
921
+ Transform complex vector via a composition of Rokhlin's random transform,
922
+ random subselection, and an FFT.
923
+
924
+ In contrast to :func:`idz_frm`, this routine works best when the length of
925
+ the transformed vector is known a priori.
926
+
927
+ :param l:
928
+ Length of transformed vector, satisfying `l <= n`.
929
+ :type l: int
930
+ :param n:
931
+ Greatest power-of-two integer satisfying `n <= x.size` as obtained from
932
+ :func:`idz_sfrmi`.
933
+ :type n: int
934
+ :param w:
935
+ Initialization array constructed by :func:`idd_sfrmi`.
936
+ :type w: :class:`numpy.ndarray`
937
+ :param x:
938
+ Vector to be transformed.
939
+ :type x: :class:`numpy.ndarray`
940
+
941
+ :return:
942
+ Transformed vector.
943
+ :rtype: :class:`numpy.ndarray`
944
+ """
945
+ return _id.idz_sfrm(l, n, w, x)
946
+
947
+
948
+ def idz_frmi(m):
949
+ """
950
+ Initialize data for :func:`idz_frm`.
951
+
952
+ :param m:
953
+ Length of vector to be transformed.
954
+ :type m: int
955
+
956
+ :return:
957
+ Greatest power-of-two integer `n` satisfying `n <= m`.
958
+ :rtype: int
959
+ :return:
960
+ Initialization array to be used by :func:`idz_frm`.
961
+ :rtype: :class:`numpy.ndarray`
962
+ """
963
+ return _id.idz_frmi(m)
964
+
965
+
966
+ def idz_sfrmi(l, m):
967
+ """
968
+ Initialize data for :func:`idz_sfrm`.
969
+
970
+ :param l:
971
+ Length of output transformed vector.
972
+ :type l: int
973
+ :param m:
974
+ Length of the vector to be transformed.
975
+ :type m: int
976
+
977
+ :return:
978
+ Greatest power-of-two integer `n` satisfying `n <= m`.
979
+ :rtype: int
980
+ :return:
981
+ Initialization array to be used by :func:`idz_sfrm`.
982
+ :rtype: :class:`numpy.ndarray`
983
+ """
984
+ return _id.idz_sfrmi(l, m)
985
+
986
+
987
+ #------------------------------------------------------------------------------
988
+ # idz_id.f
989
+ #------------------------------------------------------------------------------
990
+
991
+ def idzp_id(eps, A):
992
+ """
993
+ Compute ID of a complex matrix to a specified relative precision.
994
+
995
+ :param eps:
996
+ Relative precision.
997
+ :type eps: float
998
+ :param A:
999
+ Matrix.
1000
+ :type A: :class:`numpy.ndarray`
1001
+
1002
+ :return:
1003
+ Rank of ID.
1004
+ :rtype: int
1005
+ :return:
1006
+ Column index array.
1007
+ :rtype: :class:`numpy.ndarray`
1008
+ :return:
1009
+ Interpolation coefficients.
1010
+ :rtype: :class:`numpy.ndarray`
1011
+ """
1012
+ A = _asfortranarray_copy(A)
1013
+ k, idx, rnorms = _id.idzp_id(eps, A)
1014
+ n = A.shape[1]
1015
+ proj = A.T.ravel()[:k*(n-k)].reshape((k, n-k), order='F')
1016
+ return k, idx, proj
1017
+
1018
+
1019
+ def idzr_id(A, k):
1020
+ """
1021
+ Compute ID of a complex matrix to a specified rank.
1022
+
1023
+ :param A:
1024
+ Matrix.
1025
+ :type A: :class:`numpy.ndarray`
1026
+ :param k:
1027
+ Rank of ID.
1028
+ :type k: int
1029
+
1030
+ :return:
1031
+ Column index array.
1032
+ :rtype: :class:`numpy.ndarray`
1033
+ :return:
1034
+ Interpolation coefficients.
1035
+ :rtype: :class:`numpy.ndarray`
1036
+ """
1037
+ A = _asfortranarray_copy(A)
1038
+ idx, rnorms = _id.idzr_id(A, k)
1039
+ n = A.shape[1]
1040
+ proj = A.T.ravel()[:k*(n-k)].reshape((k, n-k), order='F')
1041
+ return idx, proj
1042
+
1043
+
1044
+ def idz_reconid(B, idx, proj):
1045
+ """
1046
+ Reconstruct matrix from complex ID.
1047
+
1048
+ :param B:
1049
+ Skeleton matrix.
1050
+ :type B: :class:`numpy.ndarray`
1051
+ :param idx:
1052
+ Column index array.
1053
+ :type idx: :class:`numpy.ndarray`
1054
+ :param proj:
1055
+ Interpolation coefficients.
1056
+ :type proj: :class:`numpy.ndarray`
1057
+
1058
+ :return:
1059
+ Reconstructed matrix.
1060
+ :rtype: :class:`numpy.ndarray`
1061
+ """
1062
+ B = np.asfortranarray(B)
1063
+ if proj.size > 0:
1064
+ return _id.idz_reconid(B, idx, proj)
1065
+ else:
1066
+ return B[:, np.argsort(idx)]
1067
+
1068
+
1069
+ def idz_reconint(idx, proj):
1070
+ """
1071
+ Reconstruct interpolation matrix from complex ID.
1072
+
1073
+ :param idx:
1074
+ Column index array.
1075
+ :type idx: :class:`numpy.ndarray`
1076
+ :param proj:
1077
+ Interpolation coefficients.
1078
+ :type proj: :class:`numpy.ndarray`
1079
+
1080
+ :return:
1081
+ Interpolation matrix.
1082
+ :rtype: :class:`numpy.ndarray`
1083
+ """
1084
+ return _id.idz_reconint(idx, proj)
1085
+
1086
+
1087
+ def idz_copycols(A, k, idx):
1088
+ """
1089
+ Reconstruct skeleton matrix from complex ID.
1090
+
1091
+ :param A:
1092
+ Original matrix.
1093
+ :type A: :class:`numpy.ndarray`
1094
+ :param k:
1095
+ Rank of ID.
1096
+ :type k: int
1097
+ :param idx:
1098
+ Column index array.
1099
+ :type idx: :class:`numpy.ndarray`
1100
+
1101
+ :return:
1102
+ Skeleton matrix.
1103
+ :rtype: :class:`numpy.ndarray`
1104
+ """
1105
+ A = np.asfortranarray(A)
1106
+ return _id.idz_copycols(A, k, idx)
1107
+
1108
+
1109
+ #------------------------------------------------------------------------------
1110
+ # idz_id2svd.f
1111
+ #------------------------------------------------------------------------------
1112
+
1113
+ def idz_id2svd(B, idx, proj):
1114
+ """
1115
+ Convert complex ID to SVD.
1116
+
1117
+ :param B:
1118
+ Skeleton matrix.
1119
+ :type B: :class:`numpy.ndarray`
1120
+ :param idx:
1121
+ Column index array.
1122
+ :type idx: :class:`numpy.ndarray`
1123
+ :param proj:
1124
+ Interpolation coefficients.
1125
+ :type proj: :class:`numpy.ndarray`
1126
+
1127
+ :return:
1128
+ Left singular vectors.
1129
+ :rtype: :class:`numpy.ndarray`
1130
+ :return:
1131
+ Right singular vectors.
1132
+ :rtype: :class:`numpy.ndarray`
1133
+ :return:
1134
+ Singular values.
1135
+ :rtype: :class:`numpy.ndarray`
1136
+ """
1137
+ B = np.asfortranarray(B)
1138
+ U, V, S, ier = _id.idz_id2svd(B, idx, proj)
1139
+ if ier:
1140
+ raise _RETCODE_ERROR
1141
+ return U, V, S
1142
+
1143
+
1144
+ #------------------------------------------------------------------------------
1145
+ # idz_snorm.f
1146
+ #------------------------------------------------------------------------------
1147
+
1148
+ def idz_snorm(m, n, matveca, matvec, its=20):
1149
+ """
1150
+ Estimate spectral norm of a complex matrix by the randomized power method.
1151
+
1152
+ :param m:
1153
+ Matrix row dimension.
1154
+ :type m: int
1155
+ :param n:
1156
+ Matrix column dimension.
1157
+ :type n: int
1158
+ :param matveca:
1159
+ Function to apply the matrix adjoint to a vector, with call signature
1160
+ `y = matveca(x)`, where `x` and `y` are the input and output vectors,
1161
+ respectively.
1162
+ :type matveca: function
1163
+ :param matvec:
1164
+ Function to apply the matrix to a vector, with call signature
1165
+ `y = matvec(x)`, where `x` and `y` are the input and output vectors,
1166
+ respectively.
1167
+ :type matvec: function
1168
+ :param its:
1169
+ Number of power method iterations.
1170
+ :type its: int
1171
+
1172
+ :return:
1173
+ Spectral norm estimate.
1174
+ :rtype: float
1175
+ """
1176
+ snorm, v = _id.idz_snorm(m, n, matveca, matvec, its)
1177
+ return snorm
1178
+
1179
+
1180
+ def idz_diffsnorm(m, n, matveca, matveca2, matvec, matvec2, its=20):
1181
+ """
1182
+ Estimate spectral norm of the difference of two complex matrices by the
1183
+ randomized power method.
1184
+
1185
+ :param m:
1186
+ Matrix row dimension.
1187
+ :type m: int
1188
+ :param n:
1189
+ Matrix column dimension.
1190
+ :type n: int
1191
+ :param matveca:
1192
+ Function to apply the adjoint of the first matrix to a vector, with
1193
+ call signature `y = matveca(x)`, where `x` and `y` are the input and
1194
+ output vectors, respectively.
1195
+ :type matveca: function
1196
+ :param matveca2:
1197
+ Function to apply the adjoint of the second matrix to a vector, with
1198
+ call signature `y = matveca2(x)`, where `x` and `y` are the input and
1199
+ output vectors, respectively.
1200
+ :type matveca2: function
1201
+ :param matvec:
1202
+ Function to apply the first matrix to a vector, with call signature
1203
+ `y = matvec(x)`, where `x` and `y` are the input and output vectors,
1204
+ respectively.
1205
+ :type matvec: function
1206
+ :param matvec2:
1207
+ Function to apply the second matrix to a vector, with call signature
1208
+ `y = matvec2(x)`, where `x` and `y` are the input and output vectors,
1209
+ respectively.
1210
+ :type matvec2: function
1211
+ :param its:
1212
+ Number of power method iterations.
1213
+ :type its: int
1214
+
1215
+ :return:
1216
+ Spectral norm estimate of matrix difference.
1217
+ :rtype: float
1218
+ """
1219
+ return _id.idz_diffsnorm(m, n, matveca, matveca2, matvec, matvec2, its)
1220
+
1221
+
1222
+ #------------------------------------------------------------------------------
1223
+ # idz_svd.f
1224
+ #------------------------------------------------------------------------------
1225
+
1226
+ def idzr_svd(A, k):
1227
+ """
1228
+ Compute SVD of a complex matrix to a specified rank.
1229
+
1230
+ :param A:
1231
+ Matrix.
1232
+ :type A: :class:`numpy.ndarray`
1233
+ :param k:
1234
+ Rank of SVD.
1235
+ :type k: int
1236
+
1237
+ :return:
1238
+ Left singular vectors.
1239
+ :rtype: :class:`numpy.ndarray`
1240
+ :return:
1241
+ Right singular vectors.
1242
+ :rtype: :class:`numpy.ndarray`
1243
+ :return:
1244
+ Singular values.
1245
+ :rtype: :class:`numpy.ndarray`
1246
+ """
1247
+ A = np.asfortranarray(A)
1248
+ U, V, S, ier = _id.idzr_svd(A, k)
1249
+ if ier:
1250
+ raise _RETCODE_ERROR
1251
+ return U, V, S
1252
+
1253
+
1254
+ def idzp_svd(eps, A):
1255
+ """
1256
+ Compute SVD of a complex matrix to a specified relative precision.
1257
+
1258
+ :param eps:
1259
+ Relative precision.
1260
+ :type eps: float
1261
+ :param A:
1262
+ Matrix.
1263
+ :type A: :class:`numpy.ndarray`
1264
+
1265
+ :return:
1266
+ Left singular vectors.
1267
+ :rtype: :class:`numpy.ndarray`
1268
+ :return:
1269
+ Right singular vectors.
1270
+ :rtype: :class:`numpy.ndarray`
1271
+ :return:
1272
+ Singular values.
1273
+ :rtype: :class:`numpy.ndarray`
1274
+ """
1275
+ A = np.asfortranarray(A)
1276
+ m, n = A.shape
1277
+ k, iU, iV, iS, w, ier = _id.idzp_svd(eps, A)
1278
+ if ier:
1279
+ raise _RETCODE_ERROR
1280
+ U = w[iU-1:iU+m*k-1].reshape((m, k), order='F')
1281
+ V = w[iV-1:iV+n*k-1].reshape((n, k), order='F')
1282
+ S = w[iS-1:iS+k-1]
1283
+ return U, V, S
1284
+
1285
+
1286
+ #------------------------------------------------------------------------------
1287
+ # idzp_aid.f
1288
+ #------------------------------------------------------------------------------
1289
+
1290
+ def idzp_aid(eps, A):
1291
+ """
1292
+ Compute ID of a complex matrix to a specified relative precision using
1293
+ random sampling.
1294
+
1295
+ :param eps:
1296
+ Relative precision.
1297
+ :type eps: float
1298
+ :param A:
1299
+ Matrix.
1300
+ :type A: :class:`numpy.ndarray`
1301
+
1302
+ :return:
1303
+ Rank of ID.
1304
+ :rtype: int
1305
+ :return:
1306
+ Column index array.
1307
+ :rtype: :class:`numpy.ndarray`
1308
+ :return:
1309
+ Interpolation coefficients.
1310
+ :rtype: :class:`numpy.ndarray`
1311
+ """
1312
+ A = np.asfortranarray(A)
1313
+ m, n = A.shape
1314
+ n2, w = idz_frmi(m)
1315
+ proj = np.empty(n*(2*n2 + 1) + n2 + 1, dtype='complex128', order='F')
1316
+ k, idx, proj = _id.idzp_aid(eps, A, w, proj)
1317
+ proj = proj[:k*(n-k)].reshape((k, n-k), order='F')
1318
+ return k, idx, proj
1319
+
1320
+
1321
+ def idz_estrank(eps, A):
1322
+ """
1323
+ Estimate rank of a complex matrix to a specified relative precision using
1324
+ random sampling.
1325
+
1326
+ The output rank is typically about 8 higher than the actual rank.
1327
+
1328
+ :param eps:
1329
+ Relative precision.
1330
+ :type eps: float
1331
+ :param A:
1332
+ Matrix.
1333
+ :type A: :class:`numpy.ndarray`
1334
+
1335
+ :return:
1336
+ Rank estimate.
1337
+ :rtype: int
1338
+ """
1339
+ A = np.asfortranarray(A)
1340
+ m, n = A.shape
1341
+ n2, w = idz_frmi(m)
1342
+ ra = np.empty(n*n2 + (n + 1)*(n2 + 1), dtype='complex128', order='F')
1343
+ k, ra = _id.idz_estrank(eps, A, w, ra)
1344
+ return k
1345
+
1346
+
1347
+ #------------------------------------------------------------------------------
1348
+ # idzp_asvd.f
1349
+ #------------------------------------------------------------------------------
1350
+
1351
+ def idzp_asvd(eps, A):
1352
+ """
1353
+ Compute SVD of a complex matrix to a specified relative precision using
1354
+ random sampling.
1355
+
1356
+ :param eps:
1357
+ Relative precision.
1358
+ :type eps: float
1359
+ :param A:
1360
+ Matrix.
1361
+ :type A: :class:`numpy.ndarray`
1362
+
1363
+ :return:
1364
+ Left singular vectors.
1365
+ :rtype: :class:`numpy.ndarray`
1366
+ :return:
1367
+ Right singular vectors.
1368
+ :rtype: :class:`numpy.ndarray`
1369
+ :return:
1370
+ Singular values.
1371
+ :rtype: :class:`numpy.ndarray`
1372
+ """
1373
+ A = np.asfortranarray(A)
1374
+ m, n = A.shape
1375
+ n2, winit = _id.idz_frmi(m)
1376
+ w = np.empty(
1377
+ max((min(m, n) + 1)*(3*m + 5*n + 11) + 8*min(m, n)**2,
1378
+ (2*n + 1)*(n2 + 1)),
1379
+ dtype=np.complex128, order='F')
1380
+ k, iU, iV, iS, w, ier = _id.idzp_asvd(eps, A, winit, w)
1381
+ if ier:
1382
+ raise _RETCODE_ERROR
1383
+ U = w[iU-1:iU+m*k-1].reshape((m, k), order='F')
1384
+ V = w[iV-1:iV+n*k-1].reshape((n, k), order='F')
1385
+ S = w[iS-1:iS+k-1]
1386
+ return U, V, S
1387
+
1388
+
1389
+ #------------------------------------------------------------------------------
1390
+ # idzp_rid.f
1391
+ #------------------------------------------------------------------------------
1392
+
1393
+ def idzp_rid(eps, m, n, matveca):
1394
+ """
1395
+ Compute ID of a complex matrix to a specified relative precision using
1396
+ random matrix-vector multiplication.
1397
+
1398
+ :param eps:
1399
+ Relative precision.
1400
+ :type eps: float
1401
+ :param m:
1402
+ Matrix row dimension.
1403
+ :type m: int
1404
+ :param n:
1405
+ Matrix column dimension.
1406
+ :type n: int
1407
+ :param matveca:
1408
+ Function to apply the matrix adjoint to a vector, with call signature
1409
+ `y = matveca(x)`, where `x` and `y` are the input and output vectors,
1410
+ respectively.
1411
+ :type matveca: function
1412
+
1413
+ :return:
1414
+ Rank of ID.
1415
+ :rtype: int
1416
+ :return:
1417
+ Column index array.
1418
+ :rtype: :class:`numpy.ndarray`
1419
+ :return:
1420
+ Interpolation coefficients.
1421
+ :rtype: :class:`numpy.ndarray`
1422
+ """
1423
+ proj = np.empty(
1424
+ m + 1 + 2*n*(min(m, n) + 1),
1425
+ dtype=np.complex128, order='F')
1426
+ k, idx, proj, ier = _id.idzp_rid(eps, m, n, matveca, proj)
1427
+ if ier:
1428
+ raise _RETCODE_ERROR
1429
+ proj = proj[:k*(n-k)].reshape((k, n-k), order='F')
1430
+ return k, idx, proj
1431
+
1432
+
1433
+ def idz_findrank(eps, m, n, matveca):
1434
+ """
1435
+ Estimate rank of a complex matrix to a specified relative precision using
1436
+ random matrix-vector multiplication.
1437
+
1438
+ :param eps:
1439
+ Relative precision.
1440
+ :type eps: float
1441
+ :param m:
1442
+ Matrix row dimension.
1443
+ :type m: int
1444
+ :param n:
1445
+ Matrix column dimension.
1446
+ :type n: int
1447
+ :param matveca:
1448
+ Function to apply the matrix adjoint to a vector, with call signature
1449
+ `y = matveca(x)`, where `x` and `y` are the input and output vectors,
1450
+ respectively.
1451
+ :type matveca: function
1452
+
1453
+ :return:
1454
+ Rank estimate.
1455
+ :rtype: int
1456
+ """
1457
+ k, ra, ier = _id.idz_findrank(eps, m, n, matveca)
1458
+ if ier:
1459
+ raise _RETCODE_ERROR
1460
+ return k
1461
+
1462
+
1463
+ #------------------------------------------------------------------------------
1464
+ # idzp_rsvd.f
1465
+ #------------------------------------------------------------------------------
1466
+
1467
+ def idzp_rsvd(eps, m, n, matveca, matvec):
1468
+ """
1469
+ Compute SVD of a complex matrix to a specified relative precision using
1470
+ random matrix-vector multiplication.
1471
+
1472
+ :param eps:
1473
+ Relative precision.
1474
+ :type eps: float
1475
+ :param m:
1476
+ Matrix row dimension.
1477
+ :type m: int
1478
+ :param n:
1479
+ Matrix column dimension.
1480
+ :type n: int
1481
+ :param matveca:
1482
+ Function to apply the matrix adjoint to a vector, with call signature
1483
+ `y = matveca(x)`, where `x` and `y` are the input and output vectors,
1484
+ respectively.
1485
+ :type matveca: function
1486
+ :param matvec:
1487
+ Function to apply the matrix to a vector, with call signature
1488
+ `y = matvec(x)`, where `x` and `y` are the input and output vectors,
1489
+ respectively.
1490
+ :type matvec: function
1491
+
1492
+ :return:
1493
+ Left singular vectors.
1494
+ :rtype: :class:`numpy.ndarray`
1495
+ :return:
1496
+ Right singular vectors.
1497
+ :rtype: :class:`numpy.ndarray`
1498
+ :return:
1499
+ Singular values.
1500
+ :rtype: :class:`numpy.ndarray`
1501
+ """
1502
+ k, iU, iV, iS, w, ier = _id.idzp_rsvd(eps, m, n, matveca, matvec)
1503
+ if ier:
1504
+ raise _RETCODE_ERROR
1505
+ U = w[iU-1:iU+m*k-1].reshape((m, k), order='F')
1506
+ V = w[iV-1:iV+n*k-1].reshape((n, k), order='F')
1507
+ S = w[iS-1:iS+k-1]
1508
+ return U, V, S
1509
+
1510
+
1511
+ #------------------------------------------------------------------------------
1512
+ # idzr_aid.f
1513
+ #------------------------------------------------------------------------------
1514
+
1515
+ def idzr_aid(A, k):
1516
+ """
1517
+ Compute ID of a complex matrix to a specified rank using random sampling.
1518
+
1519
+ :param A:
1520
+ Matrix.
1521
+ :type A: :class:`numpy.ndarray`
1522
+ :param k:
1523
+ Rank of ID.
1524
+ :type k: int
1525
+
1526
+ :return:
1527
+ Column index array.
1528
+ :rtype: :class:`numpy.ndarray`
1529
+ :return:
1530
+ Interpolation coefficients.
1531
+ :rtype: :class:`numpy.ndarray`
1532
+ """
1533
+ A = np.asfortranarray(A)
1534
+ m, n = A.shape
1535
+ w = idzr_aidi(m, n, k)
1536
+ idx, proj = _id.idzr_aid(A, k, w)
1537
+ if k == n:
1538
+ proj = np.empty((k, n-k), dtype='complex128', order='F')
1539
+ else:
1540
+ proj = proj.reshape((k, n-k), order='F')
1541
+ return idx, proj
1542
+
1543
+
1544
+ def idzr_aidi(m, n, k):
1545
+ """
1546
+ Initialize array for :func:`idzr_aid`.
1547
+
1548
+ :param m:
1549
+ Matrix row dimension.
1550
+ :type m: int
1551
+ :param n:
1552
+ Matrix column dimension.
1553
+ :type n: int
1554
+ :param k:
1555
+ Rank of ID.
1556
+ :type k: int
1557
+
1558
+ :return:
1559
+ Initialization array to be used by :func:`idzr_aid`.
1560
+ :rtype: :class:`numpy.ndarray`
1561
+ """
1562
+ return _id.idzr_aidi(m, n, k)
1563
+
1564
+
1565
+ #------------------------------------------------------------------------------
1566
+ # idzr_asvd.f
1567
+ #------------------------------------------------------------------------------
1568
+
1569
+ def idzr_asvd(A, k):
1570
+ """
1571
+ Compute SVD of a complex matrix to a specified rank using random sampling.
1572
+
1573
+ :param A:
1574
+ Matrix.
1575
+ :type A: :class:`numpy.ndarray`
1576
+ :param k:
1577
+ Rank of SVD.
1578
+ :type k: int
1579
+
1580
+ :return:
1581
+ Left singular vectors.
1582
+ :rtype: :class:`numpy.ndarray`
1583
+ :return:
1584
+ Right singular vectors.
1585
+ :rtype: :class:`numpy.ndarray`
1586
+ :return:
1587
+ Singular values.
1588
+ :rtype: :class:`numpy.ndarray`
1589
+ """
1590
+ A = np.asfortranarray(A)
1591
+ m, n = A.shape
1592
+ w = np.empty(
1593
+ (2*k + 22)*m + (6*k + 21)*n + 8*k**2 + 10*k + 90,
1594
+ dtype='complex128', order='F')
1595
+ w_ = idzr_aidi(m, n, k)
1596
+ w[:w_.size] = w_
1597
+ U, V, S, ier = _id.idzr_asvd(A, k, w)
1598
+ if ier:
1599
+ raise _RETCODE_ERROR
1600
+ return U, V, S
1601
+
1602
+
1603
+ #------------------------------------------------------------------------------
1604
+ # idzr_rid.f
1605
+ #------------------------------------------------------------------------------
1606
+
1607
+ def idzr_rid(m, n, matveca, k):
1608
+ """
1609
+ Compute ID of a complex matrix to a specified rank using random
1610
+ matrix-vector multiplication.
1611
+
1612
+ :param m:
1613
+ Matrix row dimension.
1614
+ :type m: int
1615
+ :param n:
1616
+ Matrix column dimension.
1617
+ :type n: int
1618
+ :param matveca:
1619
+ Function to apply the matrix adjoint to a vector, with call signature
1620
+ `y = matveca(x)`, where `x` and `y` are the input and output vectors,
1621
+ respectively.
1622
+ :type matveca: function
1623
+ :param k:
1624
+ Rank of ID.
1625
+ :type k: int
1626
+
1627
+ :return:
1628
+ Column index array.
1629
+ :rtype: :class:`numpy.ndarray`
1630
+ :return:
1631
+ Interpolation coefficients.
1632
+ :rtype: :class:`numpy.ndarray`
1633
+ """
1634
+ idx, proj = _id.idzr_rid(m, n, matveca, k)
1635
+ proj = proj[:k*(n-k)].reshape((k, n-k), order='F')
1636
+ return idx, proj
1637
+
1638
+
1639
+ #------------------------------------------------------------------------------
1640
+ # idzr_rsvd.f
1641
+ #------------------------------------------------------------------------------
1642
+
1643
+ def idzr_rsvd(m, n, matveca, matvec, k):
1644
+ """
1645
+ Compute SVD of a complex matrix to a specified rank using random
1646
+ matrix-vector multiplication.
1647
+
1648
+ :param m:
1649
+ Matrix row dimension.
1650
+ :type m: int
1651
+ :param n:
1652
+ Matrix column dimension.
1653
+ :type n: int
1654
+ :param matveca:
1655
+ Function to apply the matrix adjoint to a vector, with call signature
1656
+ `y = matveca(x)`, where `x` and `y` are the input and output vectors,
1657
+ respectively.
1658
+ :type matveca: function
1659
+ :param matvec:
1660
+ Function to apply the matrix to a vector, with call signature
1661
+ `y = matvec(x)`, where `x` and `y` are the input and output vectors,
1662
+ respectively.
1663
+ :type matvec: function
1664
+ :param k:
1665
+ Rank of SVD.
1666
+ :type k: int
1667
+
1668
+ :return:
1669
+ Left singular vectors.
1670
+ :rtype: :class:`numpy.ndarray`
1671
+ :return:
1672
+ Right singular vectors.
1673
+ :rtype: :class:`numpy.ndarray`
1674
+ :return:
1675
+ Singular values.
1676
+ :rtype: :class:`numpy.ndarray`
1677
+ """
1678
+ U, V, S, ier = _id.idzr_rsvd(m, n, matveca, matvec, k)
1679
+ if ier:
1680
+ raise _RETCODE_ERROR
1681
+ return U, V, S
astra_scene_test/Scene_04/.venv/lib/python3.9/site-packages/scipy/linalg/_lapack_subroutines.h ADDED
The diff for this file is too large to render. See raw diff
 
astra_scene_test/Scene_04/.venv/lib/python3.9/site-packages/scipy/linalg/_matfuncs.py ADDED
@@ -0,0 +1,861 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #
2
+ # Author: Travis Oliphant, March 2002
3
+ #
4
+ from itertools import product
5
+
6
+ import numpy as np
7
+ from numpy import (dot, diag, prod, logical_not, ravel, transpose,
8
+ conjugate, absolute, amax, sign, isfinite, triu)
9
+
10
+ # Local imports
11
+ from scipy.linalg import LinAlgError, bandwidth
12
+ from ._misc import norm
13
+ from ._basic import solve, inv
14
+ from ._decomp_svd import svd
15
+ from ._decomp_schur import schur, rsf2csf
16
+ from ._expm_frechet import expm_frechet, expm_cond
17
+ from ._matfuncs_sqrtm import sqrtm
18
+ from ._matfuncs_expm import pick_pade_structure, pade_UV_calc
19
+
20
+ # deprecated imports to be removed in SciPy 1.13.0
21
+ from numpy import single # noqa: F401
22
+
23
+ __all__ = ['expm', 'cosm', 'sinm', 'tanm', 'coshm', 'sinhm', 'tanhm', 'logm',
24
+ 'funm', 'signm', 'sqrtm', 'fractional_matrix_power', 'expm_frechet',
25
+ 'expm_cond', 'khatri_rao']
26
+
27
+ eps = np.finfo('d').eps
28
+ feps = np.finfo('f').eps
29
+
30
+ _array_precision = {'i': 1, 'l': 1, 'f': 0, 'd': 1, 'F': 0, 'D': 1}
31
+
32
+
33
+ ###############################################################################
34
+ # Utility functions.
35
+
36
+
37
+ def _asarray_square(A):
38
+ """
39
+ Wraps asarray with the extra requirement that the input be a square matrix.
40
+
41
+ The motivation is that the matfuncs module has real functions that have
42
+ been lifted to square matrix functions.
43
+
44
+ Parameters
45
+ ----------
46
+ A : array_like
47
+ A square matrix.
48
+
49
+ Returns
50
+ -------
51
+ out : ndarray
52
+ An ndarray copy or view or other representation of A.
53
+
54
+ """
55
+ A = np.asarray(A)
56
+ if len(A.shape) != 2 or A.shape[0] != A.shape[1]:
57
+ raise ValueError('expected square array_like input')
58
+ return A
59
+
60
+
61
+ def _maybe_real(A, B, tol=None):
62
+ """
63
+ Return either B or the real part of B, depending on properties of A and B.
64
+
65
+ The motivation is that B has been computed as a complicated function of A,
66
+ and B may be perturbed by negligible imaginary components.
67
+ If A is real and B is complex with small imaginary components,
68
+ then return a real copy of B. The assumption in that case would be that
69
+ the imaginary components of B are numerical artifacts.
70
+
71
+ Parameters
72
+ ----------
73
+ A : ndarray
74
+ Input array whose type is to be checked as real vs. complex.
75
+ B : ndarray
76
+ Array to be returned, possibly without its imaginary part.
77
+ tol : float
78
+ Absolute tolerance.
79
+
80
+ Returns
81
+ -------
82
+ out : real or complex array
83
+ Either the input array B or only the real part of the input array B.
84
+
85
+ """
86
+ # Note that booleans and integers compare as real.
87
+ if np.isrealobj(A) and np.iscomplexobj(B):
88
+ if tol is None:
89
+ tol = {0: feps*1e3, 1: eps*1e6}[_array_precision[B.dtype.char]]
90
+ if np.allclose(B.imag, 0.0, atol=tol):
91
+ B = B.real
92
+ return B
93
+
94
+
95
+ ###############################################################################
96
+ # Matrix functions.
97
+
98
+
99
+ def fractional_matrix_power(A, t):
100
+ """
101
+ Compute the fractional power of a matrix.
102
+
103
+ Proceeds according to the discussion in section (6) of [1]_.
104
+
105
+ Parameters
106
+ ----------
107
+ A : (N, N) array_like
108
+ Matrix whose fractional power to evaluate.
109
+ t : float
110
+ Fractional power.
111
+
112
+ Returns
113
+ -------
114
+ X : (N, N) array_like
115
+ The fractional power of the matrix.
116
+
117
+ References
118
+ ----------
119
+ .. [1] Nicholas J. Higham and Lijing lin (2011)
120
+ "A Schur-Pade Algorithm for Fractional Powers of a Matrix."
121
+ SIAM Journal on Matrix Analysis and Applications,
122
+ 32 (3). pp. 1056-1078. ISSN 0895-4798
123
+
124
+ Examples
125
+ --------
126
+ >>> import numpy as np
127
+ >>> from scipy.linalg import fractional_matrix_power
128
+ >>> a = np.array([[1.0, 3.0], [1.0, 4.0]])
129
+ >>> b = fractional_matrix_power(a, 0.5)
130
+ >>> b
131
+ array([[ 0.75592895, 1.13389342],
132
+ [ 0.37796447, 1.88982237]])
133
+ >>> np.dot(b, b) # Verify square root
134
+ array([[ 1., 3.],
135
+ [ 1., 4.]])
136
+
137
+ """
138
+ # This fixes some issue with imports;
139
+ # this function calls onenormest which is in scipy.sparse.
140
+ A = _asarray_square(A)
141
+ import scipy.linalg._matfuncs_inv_ssq
142
+ return scipy.linalg._matfuncs_inv_ssq._fractional_matrix_power(A, t)
143
+
144
+
145
+ def logm(A, disp=True):
146
+ """
147
+ Compute matrix logarithm.
148
+
149
+ The matrix logarithm is the inverse of
150
+ expm: expm(logm(`A`)) == `A`
151
+
152
+ Parameters
153
+ ----------
154
+ A : (N, N) array_like
155
+ Matrix whose logarithm to evaluate
156
+ disp : bool, optional
157
+ Print warning if error in the result is estimated large
158
+ instead of returning estimated error. (Default: True)
159
+
160
+ Returns
161
+ -------
162
+ logm : (N, N) ndarray
163
+ Matrix logarithm of `A`
164
+ errest : float
165
+ (if disp == False)
166
+
167
+ 1-norm of the estimated error, ||err||_1 / ||A||_1
168
+
169
+ References
170
+ ----------
171
+ .. [1] Awad H. Al-Mohy and Nicholas J. Higham (2012)
172
+ "Improved Inverse Scaling and Squaring Algorithms
173
+ for the Matrix Logarithm."
174
+ SIAM Journal on Scientific Computing, 34 (4). C152-C169.
175
+ ISSN 1095-7197
176
+
177
+ .. [2] Nicholas J. Higham (2008)
178
+ "Functions of Matrices: Theory and Computation"
179
+ ISBN 978-0-898716-46-7
180
+
181
+ .. [3] Nicholas J. Higham and Lijing lin (2011)
182
+ "A Schur-Pade Algorithm for Fractional Powers of a Matrix."
183
+ SIAM Journal on Matrix Analysis and Applications,
184
+ 32 (3). pp. 1056-1078. ISSN 0895-4798
185
+
186
+ Examples
187
+ --------
188
+ >>> import numpy as np
189
+ >>> from scipy.linalg import logm, expm
190
+ >>> a = np.array([[1.0, 3.0], [1.0, 4.0]])
191
+ >>> b = logm(a)
192
+ >>> b
193
+ array([[-1.02571087, 2.05142174],
194
+ [ 0.68380725, 1.02571087]])
195
+ >>> expm(b) # Verify expm(logm(a)) returns a
196
+ array([[ 1., 3.],
197
+ [ 1., 4.]])
198
+
199
+ """
200
+ A = _asarray_square(A)
201
+ # Avoid circular import ... this is OK, right?
202
+ import scipy.linalg._matfuncs_inv_ssq
203
+ F = scipy.linalg._matfuncs_inv_ssq._logm(A)
204
+ F = _maybe_real(A, F)
205
+ errtol = 1000*eps
206
+ # TODO use a better error approximation
207
+ errest = norm(expm(F)-A, 1) / norm(A, 1)
208
+ if disp:
209
+ if not isfinite(errest) or errest >= errtol:
210
+ print("logm result may be inaccurate, approximate err =", errest)
211
+ return F
212
+ else:
213
+ return F, errest
214
+
215
+
216
+ def expm(A):
217
+ """Compute the matrix exponential of an array.
218
+
219
+ Parameters
220
+ ----------
221
+ A : ndarray
222
+ Input with last two dimensions are square ``(..., n, n)``.
223
+
224
+ Returns
225
+ -------
226
+ eA : ndarray
227
+ The resulting matrix exponential with the same shape of ``A``
228
+
229
+ Notes
230
+ -----
231
+ Implements the algorithm given in [1], which is essentially a Pade
232
+ approximation with a variable order that is decided based on the array
233
+ data.
234
+
235
+ For input with size ``n``, the memory usage is in the worst case in the
236
+ order of ``8*(n**2)``. If the input data is not of single and double
237
+ precision of real and complex dtypes, it is copied to a new array.
238
+
239
+ For cases ``n >= 400``, the exact 1-norm computation cost, breaks even with
240
+ 1-norm estimation and from that point on the estimation scheme given in
241
+ [2] is used to decide on the approximation order.
242
+
243
+ References
244
+ ----------
245
+ .. [1] Awad H. Al-Mohy and Nicholas J. Higham, (2009), "A New Scaling
246
+ and Squaring Algorithm for the Matrix Exponential", SIAM J. Matrix
247
+ Anal. Appl. 31(3):970-989, :doi:`10.1137/09074721X`
248
+
249
+ .. [2] Nicholas J. Higham and Francoise Tisseur (2000), "A Block Algorithm
250
+ for Matrix 1-Norm Estimation, with an Application to 1-Norm
251
+ Pseudospectra." SIAM J. Matrix Anal. Appl. 21(4):1185-1201,
252
+ :doi:`10.1137/S0895479899356080`
253
+
254
+ Examples
255
+ --------
256
+ >>> import numpy as np
257
+ >>> from scipy.linalg import expm, sinm, cosm
258
+
259
+ Matrix version of the formula exp(0) = 1:
260
+
261
+ >>> expm(np.zeros((3, 2, 2)))
262
+ array([[[1., 0.],
263
+ [0., 1.]],
264
+ <BLANKLINE>
265
+ [[1., 0.],
266
+ [0., 1.]],
267
+ <BLANKLINE>
268
+ [[1., 0.],
269
+ [0., 1.]]])
270
+
271
+ Euler's identity (exp(i*theta) = cos(theta) + i*sin(theta))
272
+ applied to a matrix:
273
+
274
+ >>> a = np.array([[1.0, 2.0], [-1.0, 3.0]])
275
+ >>> expm(1j*a)
276
+ array([[ 0.42645930+1.89217551j, -2.13721484-0.97811252j],
277
+ [ 1.06860742+0.48905626j, -1.71075555+0.91406299j]])
278
+ >>> cosm(a) + 1j*sinm(a)
279
+ array([[ 0.42645930+1.89217551j, -2.13721484-0.97811252j],
280
+ [ 1.06860742+0.48905626j, -1.71075555+0.91406299j]])
281
+
282
+ """
283
+ a = np.asarray(A)
284
+ if a.size == 1 and a.ndim < 2:
285
+ return np.array([[np.exp(a.item())]])
286
+
287
+ if a.ndim < 2:
288
+ raise LinAlgError('The input array must be at least two-dimensional')
289
+ if a.shape[-1] != a.shape[-2]:
290
+ raise LinAlgError('Last 2 dimensions of the array must be square')
291
+ n = a.shape[-1]
292
+ # Empty array
293
+ if min(*a.shape) == 0:
294
+ return np.empty_like(a)
295
+
296
+ # Scalar case
297
+ if a.shape[-2:] == (1, 1):
298
+ return np.exp(a)
299
+
300
+ if not np.issubdtype(a.dtype, np.inexact):
301
+ a = a.astype(np.float64)
302
+ elif a.dtype == np.float16:
303
+ a = a.astype(np.float32)
304
+
305
+ # An explicit formula for 2x2 case exists (formula (2.2) in [1]). However, without
306
+ # Kahan's method, numerical instabilities can occur (See gh-19584). Hence removed
307
+ # here until we have a more stable implementation.
308
+
309
+ n = a.shape[-1]
310
+ eA = np.empty(a.shape, dtype=a.dtype)
311
+ # working memory to hold intermediate arrays
312
+ Am = np.empty((5, n, n), dtype=a.dtype)
313
+
314
+ # Main loop to go through the slices of an ndarray and passing to expm
315
+ for ind in product(*[range(x) for x in a.shape[:-2]]):
316
+ aw = a[ind]
317
+
318
+ lu = bandwidth(aw)
319
+ if not any(lu): # a is diagonal?
320
+ eA[ind] = np.diag(np.exp(np.diag(aw)))
321
+ continue
322
+
323
+ # Generic/triangular case; copy the slice into scratch and send.
324
+ # Am will be mutated by pick_pade_structure
325
+ Am[0, :, :] = aw
326
+ m, s = pick_pade_structure(Am)
327
+
328
+ if s != 0: # scaling needed
329
+ Am[:4] *= [[[2**(-s)]], [[4**(-s)]], [[16**(-s)]], [[64**(-s)]]]
330
+
331
+ pade_UV_calc(Am, n, m)
332
+ eAw = Am[0]
333
+
334
+ if s != 0: # squaring needed
335
+
336
+ if (lu[1] == 0) or (lu[0] == 0): # lower/upper triangular
337
+ # This branch implements Code Fragment 2.1 of [1]
338
+
339
+ diag_aw = np.diag(aw)
340
+ # einsum returns a writable view
341
+ np.einsum('ii->i', eAw)[:] = np.exp(diag_aw * 2**(-s))
342
+ # super/sub diagonal
343
+ sd = np.diag(aw, k=-1 if lu[1] == 0 else 1)
344
+
345
+ for i in range(s-1, -1, -1):
346
+ eAw = eAw @ eAw
347
+
348
+ # diagonal
349
+ np.einsum('ii->i', eAw)[:] = np.exp(diag_aw * 2.**(-i))
350
+ exp_sd = _exp_sinch(diag_aw * (2.**(-i))) * (sd * 2**(-i))
351
+ if lu[1] == 0: # lower
352
+ np.einsum('ii->i', eAw[1:, :-1])[:] = exp_sd
353
+ else: # upper
354
+ np.einsum('ii->i', eAw[:-1, 1:])[:] = exp_sd
355
+
356
+ else: # generic
357
+ for _ in range(s):
358
+ eAw = eAw @ eAw
359
+
360
+ # Zero out the entries from np.empty in case of triangular input
361
+ if (lu[0] == 0) or (lu[1] == 0):
362
+ eA[ind] = np.triu(eAw) if lu[0] == 0 else np.tril(eAw)
363
+ else:
364
+ eA[ind] = eAw
365
+
366
+ return eA
367
+
368
+
369
+ def _exp_sinch(x):
370
+ # Higham's formula (10.42), might overflow, see GH-11839
371
+ lexp_diff = np.diff(np.exp(x))
372
+ l_diff = np.diff(x)
373
+ mask_z = l_diff == 0.
374
+ lexp_diff[~mask_z] /= l_diff[~mask_z]
375
+ lexp_diff[mask_z] = np.exp(x[:-1][mask_z])
376
+ return lexp_diff
377
+
378
+
379
+ def cosm(A):
380
+ """
381
+ Compute the matrix cosine.
382
+
383
+ This routine uses expm to compute the matrix exponentials.
384
+
385
+ Parameters
386
+ ----------
387
+ A : (N, N) array_like
388
+ Input array
389
+
390
+ Returns
391
+ -------
392
+ cosm : (N, N) ndarray
393
+ Matrix cosine of A
394
+
395
+ Examples
396
+ --------
397
+ >>> import numpy as np
398
+ >>> from scipy.linalg import expm, sinm, cosm
399
+
400
+ Euler's identity (exp(i*theta) = cos(theta) + i*sin(theta))
401
+ applied to a matrix:
402
+
403
+ >>> a = np.array([[1.0, 2.0], [-1.0, 3.0]])
404
+ >>> expm(1j*a)
405
+ array([[ 0.42645930+1.89217551j, -2.13721484-0.97811252j],
406
+ [ 1.06860742+0.48905626j, -1.71075555+0.91406299j]])
407
+ >>> cosm(a) + 1j*sinm(a)
408
+ array([[ 0.42645930+1.89217551j, -2.13721484-0.97811252j],
409
+ [ 1.06860742+0.48905626j, -1.71075555+0.91406299j]])
410
+
411
+ """
412
+ A = _asarray_square(A)
413
+ if np.iscomplexobj(A):
414
+ return 0.5*(expm(1j*A) + expm(-1j*A))
415
+ else:
416
+ return expm(1j*A).real
417
+
418
+
419
+ def sinm(A):
420
+ """
421
+ Compute the matrix sine.
422
+
423
+ This routine uses expm to compute the matrix exponentials.
424
+
425
+ Parameters
426
+ ----------
427
+ A : (N, N) array_like
428
+ Input array.
429
+
430
+ Returns
431
+ -------
432
+ sinm : (N, N) ndarray
433
+ Matrix sine of `A`
434
+
435
+ Examples
436
+ --------
437
+ >>> import numpy as np
438
+ >>> from scipy.linalg import expm, sinm, cosm
439
+
440
+ Euler's identity (exp(i*theta) = cos(theta) + i*sin(theta))
441
+ applied to a matrix:
442
+
443
+ >>> a = np.array([[1.0, 2.0], [-1.0, 3.0]])
444
+ >>> expm(1j*a)
445
+ array([[ 0.42645930+1.89217551j, -2.13721484-0.97811252j],
446
+ [ 1.06860742+0.48905626j, -1.71075555+0.91406299j]])
447
+ >>> cosm(a) + 1j*sinm(a)
448
+ array([[ 0.42645930+1.89217551j, -2.13721484-0.97811252j],
449
+ [ 1.06860742+0.48905626j, -1.71075555+0.91406299j]])
450
+
451
+ """
452
+ A = _asarray_square(A)
453
+ if np.iscomplexobj(A):
454
+ return -0.5j*(expm(1j*A) - expm(-1j*A))
455
+ else:
456
+ return expm(1j*A).imag
457
+
458
+
459
+ def tanm(A):
460
+ """
461
+ Compute the matrix tangent.
462
+
463
+ This routine uses expm to compute the matrix exponentials.
464
+
465
+ Parameters
466
+ ----------
467
+ A : (N, N) array_like
468
+ Input array.
469
+
470
+ Returns
471
+ -------
472
+ tanm : (N, N) ndarray
473
+ Matrix tangent of `A`
474
+
475
+ Examples
476
+ --------
477
+ >>> import numpy as np
478
+ >>> from scipy.linalg import tanm, sinm, cosm
479
+ >>> a = np.array([[1.0, 3.0], [1.0, 4.0]])
480
+ >>> t = tanm(a)
481
+ >>> t
482
+ array([[ -2.00876993, -8.41880636],
483
+ [ -2.80626879, -10.42757629]])
484
+
485
+ Verify tanm(a) = sinm(a).dot(inv(cosm(a)))
486
+
487
+ >>> s = sinm(a)
488
+ >>> c = cosm(a)
489
+ >>> s.dot(np.linalg.inv(c))
490
+ array([[ -2.00876993, -8.41880636],
491
+ [ -2.80626879, -10.42757629]])
492
+
493
+ """
494
+ A = _asarray_square(A)
495
+ return _maybe_real(A, solve(cosm(A), sinm(A)))
496
+
497
+
498
+ def coshm(A):
499
+ """
500
+ Compute the hyperbolic matrix cosine.
501
+
502
+ This routine uses expm to compute the matrix exponentials.
503
+
504
+ Parameters
505
+ ----------
506
+ A : (N, N) array_like
507
+ Input array.
508
+
509
+ Returns
510
+ -------
511
+ coshm : (N, N) ndarray
512
+ Hyperbolic matrix cosine of `A`
513
+
514
+ Examples
515
+ --------
516
+ >>> import numpy as np
517
+ >>> from scipy.linalg import tanhm, sinhm, coshm
518
+ >>> a = np.array([[1.0, 3.0], [1.0, 4.0]])
519
+ >>> c = coshm(a)
520
+ >>> c
521
+ array([[ 11.24592233, 38.76236492],
522
+ [ 12.92078831, 50.00828725]])
523
+
524
+ Verify tanhm(a) = sinhm(a).dot(inv(coshm(a)))
525
+
526
+ >>> t = tanhm(a)
527
+ >>> s = sinhm(a)
528
+ >>> t - s.dot(np.linalg.inv(c))
529
+ array([[ 2.72004641e-15, 4.55191440e-15],
530
+ [ 0.00000000e+00, -5.55111512e-16]])
531
+
532
+ """
533
+ A = _asarray_square(A)
534
+ return _maybe_real(A, 0.5 * (expm(A) + expm(-A)))
535
+
536
+
537
+ def sinhm(A):
538
+ """
539
+ Compute the hyperbolic matrix sine.
540
+
541
+ This routine uses expm to compute the matrix exponentials.
542
+
543
+ Parameters
544
+ ----------
545
+ A : (N, N) array_like
546
+ Input array.
547
+
548
+ Returns
549
+ -------
550
+ sinhm : (N, N) ndarray
551
+ Hyperbolic matrix sine of `A`
552
+
553
+ Examples
554
+ --------
555
+ >>> import numpy as np
556
+ >>> from scipy.linalg import tanhm, sinhm, coshm
557
+ >>> a = np.array([[1.0, 3.0], [1.0, 4.0]])
558
+ >>> s = sinhm(a)
559
+ >>> s
560
+ array([[ 10.57300653, 39.28826594],
561
+ [ 13.09608865, 49.86127247]])
562
+
563
+ Verify tanhm(a) = sinhm(a).dot(inv(coshm(a)))
564
+
565
+ >>> t = tanhm(a)
566
+ >>> c = coshm(a)
567
+ >>> t - s.dot(np.linalg.inv(c))
568
+ array([[ 2.72004641e-15, 4.55191440e-15],
569
+ [ 0.00000000e+00, -5.55111512e-16]])
570
+
571
+ """
572
+ A = _asarray_square(A)
573
+ return _maybe_real(A, 0.5 * (expm(A) - expm(-A)))
574
+
575
+
576
+ def tanhm(A):
577
+ """
578
+ Compute the hyperbolic matrix tangent.
579
+
580
+ This routine uses expm to compute the matrix exponentials.
581
+
582
+ Parameters
583
+ ----------
584
+ A : (N, N) array_like
585
+ Input array
586
+
587
+ Returns
588
+ -------
589
+ tanhm : (N, N) ndarray
590
+ Hyperbolic matrix tangent of `A`
591
+
592
+ Examples
593
+ --------
594
+ >>> import numpy as np
595
+ >>> from scipy.linalg import tanhm, sinhm, coshm
596
+ >>> a = np.array([[1.0, 3.0], [1.0, 4.0]])
597
+ >>> t = tanhm(a)
598
+ >>> t
599
+ array([[ 0.3428582 , 0.51987926],
600
+ [ 0.17329309, 0.86273746]])
601
+
602
+ Verify tanhm(a) = sinhm(a).dot(inv(coshm(a)))
603
+
604
+ >>> s = sinhm(a)
605
+ >>> c = coshm(a)
606
+ >>> t - s.dot(np.linalg.inv(c))
607
+ array([[ 2.72004641e-15, 4.55191440e-15],
608
+ [ 0.00000000e+00, -5.55111512e-16]])
609
+
610
+ """
611
+ A = _asarray_square(A)
612
+ return _maybe_real(A, solve(coshm(A), sinhm(A)))
613
+
614
+
615
+ def funm(A, func, disp=True):
616
+ """
617
+ Evaluate a matrix function specified by a callable.
618
+
619
+ Returns the value of matrix-valued function ``f`` at `A`. The
620
+ function ``f`` is an extension of the scalar-valued function `func`
621
+ to matrices.
622
+
623
+ Parameters
624
+ ----------
625
+ A : (N, N) array_like
626
+ Matrix at which to evaluate the function
627
+ func : callable
628
+ Callable object that evaluates a scalar function f.
629
+ Must be vectorized (eg. using vectorize).
630
+ disp : bool, optional
631
+ Print warning if error in the result is estimated large
632
+ instead of returning estimated error. (Default: True)
633
+
634
+ Returns
635
+ -------
636
+ funm : (N, N) ndarray
637
+ Value of the matrix function specified by func evaluated at `A`
638
+ errest : float
639
+ (if disp == False)
640
+
641
+ 1-norm of the estimated error, ||err||_1 / ||A||_1
642
+
643
+ Notes
644
+ -----
645
+ This function implements the general algorithm based on Schur decomposition
646
+ (Algorithm 9.1.1. in [1]_).
647
+
648
+ If the input matrix is known to be diagonalizable, then relying on the
649
+ eigendecomposition is likely to be faster. For example, if your matrix is
650
+ Hermitian, you can do
651
+
652
+ >>> from scipy.linalg import eigh
653
+ >>> def funm_herm(a, func, check_finite=False):
654
+ ... w, v = eigh(a, check_finite=check_finite)
655
+ ... ## if you further know that your matrix is positive semidefinite,
656
+ ... ## you can optionally guard against precision errors by doing
657
+ ... # w = np.maximum(w, 0)
658
+ ... w = func(w)
659
+ ... return (v * w).dot(v.conj().T)
660
+
661
+ References
662
+ ----------
663
+ .. [1] Gene H. Golub, Charles F. van Loan, Matrix Computations 4th ed.
664
+
665
+ Examples
666
+ --------
667
+ >>> import numpy as np
668
+ >>> from scipy.linalg import funm
669
+ >>> a = np.array([[1.0, 3.0], [1.0, 4.0]])
670
+ >>> funm(a, lambda x: x*x)
671
+ array([[ 4., 15.],
672
+ [ 5., 19.]])
673
+ >>> a.dot(a)
674
+ array([[ 4., 15.],
675
+ [ 5., 19.]])
676
+
677
+ """
678
+ A = _asarray_square(A)
679
+ # Perform Shur decomposition (lapack ?gees)
680
+ T, Z = schur(A)
681
+ T, Z = rsf2csf(T, Z)
682
+ n, n = T.shape
683
+ F = diag(func(diag(T))) # apply function to diagonal elements
684
+ F = F.astype(T.dtype.char) # e.g., when F is real but T is complex
685
+
686
+ minden = abs(T[0, 0])
687
+
688
+ # implement Algorithm 11.1.1 from Golub and Van Loan
689
+ # "matrix Computations."
690
+ for p in range(1, n):
691
+ for i in range(1, n-p+1):
692
+ j = i + p
693
+ s = T[i-1, j-1] * (F[j-1, j-1] - F[i-1, i-1])
694
+ ksl = slice(i, j-1)
695
+ val = dot(T[i-1, ksl], F[ksl, j-1]) - dot(F[i-1, ksl], T[ksl, j-1])
696
+ s = s + val
697
+ den = T[j-1, j-1] - T[i-1, i-1]
698
+ if den != 0.0:
699
+ s = s / den
700
+ F[i-1, j-1] = s
701
+ minden = min(minden, abs(den))
702
+
703
+ F = dot(dot(Z, F), transpose(conjugate(Z)))
704
+ F = _maybe_real(A, F)
705
+
706
+ tol = {0: feps, 1: eps}[_array_precision[F.dtype.char]]
707
+ if minden == 0.0:
708
+ minden = tol
709
+ err = min(1, max(tol, (tol/minden)*norm(triu(T, 1), 1)))
710
+ if prod(ravel(logical_not(isfinite(F))), axis=0):
711
+ err = np.inf
712
+ if disp:
713
+ if err > 1000*tol:
714
+ print("funm result may be inaccurate, approximate err =", err)
715
+ return F
716
+ else:
717
+ return F, err
718
+
719
+
720
+ def signm(A, disp=True):
721
+ """
722
+ Matrix sign function.
723
+
724
+ Extension of the scalar sign(x) to matrices.
725
+
726
+ Parameters
727
+ ----------
728
+ A : (N, N) array_like
729
+ Matrix at which to evaluate the sign function
730
+ disp : bool, optional
731
+ Print warning if error in the result is estimated large
732
+ instead of returning estimated error. (Default: True)
733
+
734
+ Returns
735
+ -------
736
+ signm : (N, N) ndarray
737
+ Value of the sign function at `A`
738
+ errest : float
739
+ (if disp == False)
740
+
741
+ 1-norm of the estimated error, ||err||_1 / ||A||_1
742
+
743
+ Examples
744
+ --------
745
+ >>> from scipy.linalg import signm, eigvals
746
+ >>> a = [[1,2,3], [1,2,1], [1,1,1]]
747
+ >>> eigvals(a)
748
+ array([ 4.12488542+0.j, -0.76155718+0.j, 0.63667176+0.j])
749
+ >>> eigvals(signm(a))
750
+ array([-1.+0.j, 1.+0.j, 1.+0.j])
751
+
752
+ """
753
+ A = _asarray_square(A)
754
+
755
+ def rounded_sign(x):
756
+ rx = np.real(x)
757
+ if rx.dtype.char == 'f':
758
+ c = 1e3*feps*amax(x)
759
+ else:
760
+ c = 1e3*eps*amax(x)
761
+ return sign((absolute(rx) > c) * rx)
762
+ result, errest = funm(A, rounded_sign, disp=0)
763
+ errtol = {0: 1e3*feps, 1: 1e3*eps}[_array_precision[result.dtype.char]]
764
+ if errest < errtol:
765
+ return result
766
+
767
+ # Handle signm of defective matrices:
768
+
769
+ # See "E.D.Denman and J.Leyva-Ramos, Appl.Math.Comp.,
770
+ # 8:237-250,1981" for how to improve the following (currently a
771
+ # rather naive) iteration process:
772
+
773
+ # a = result # sometimes iteration converges faster but where??
774
+
775
+ # Shifting to avoid zero eigenvalues. How to ensure that shifting does
776
+ # not change the spectrum too much?
777
+ vals = svd(A, compute_uv=False)
778
+ max_sv = np.amax(vals)
779
+ # min_nonzero_sv = vals[(vals>max_sv*errtol).tolist().count(1)-1]
780
+ # c = 0.5/min_nonzero_sv
781
+ c = 0.5/max_sv
782
+ S0 = A + c*np.identity(A.shape[0])
783
+ prev_errest = errest
784
+ for i in range(100):
785
+ iS0 = inv(S0)
786
+ S0 = 0.5*(S0 + iS0)
787
+ Pp = 0.5*(dot(S0, S0)+S0)
788
+ errest = norm(dot(Pp, Pp)-Pp, 1)
789
+ if errest < errtol or prev_errest == errest:
790
+ break
791
+ prev_errest = errest
792
+ if disp:
793
+ if not isfinite(errest) or errest >= errtol:
794
+ print("signm result may be inaccurate, approximate err =", errest)
795
+ return S0
796
+ else:
797
+ return S0, errest
798
+
799
+
800
+ def khatri_rao(a, b):
801
+ r"""
802
+ Khatri-rao product
803
+
804
+ A column-wise Kronecker product of two matrices
805
+
806
+ Parameters
807
+ ----------
808
+ a : (n, k) array_like
809
+ Input array
810
+ b : (m, k) array_like
811
+ Input array
812
+
813
+ Returns
814
+ -------
815
+ c: (n*m, k) ndarray
816
+ Khatri-rao product of `a` and `b`.
817
+
818
+ See Also
819
+ --------
820
+ kron : Kronecker product
821
+
822
+ Notes
823
+ -----
824
+ The mathematical definition of the Khatri-Rao product is:
825
+
826
+ .. math::
827
+
828
+ (A_{ij} \bigotimes B_{ij})_{ij}
829
+
830
+ which is the Kronecker product of every column of A and B, e.g.::
831
+
832
+ c = np.vstack([np.kron(a[:, k], b[:, k]) for k in range(b.shape[1])]).T
833
+
834
+ Examples
835
+ --------
836
+ >>> import numpy as np
837
+ >>> from scipy import linalg
838
+ >>> a = np.array([[1, 2, 3], [4, 5, 6]])
839
+ >>> b = np.array([[3, 4, 5], [6, 7, 8], [2, 3, 9]])
840
+ >>> linalg.khatri_rao(a, b)
841
+ array([[ 3, 8, 15],
842
+ [ 6, 14, 24],
843
+ [ 2, 6, 27],
844
+ [12, 20, 30],
845
+ [24, 35, 48],
846
+ [ 8, 15, 54]])
847
+
848
+ """
849
+ a = np.asarray(a)
850
+ b = np.asarray(b)
851
+
852
+ if not (a.ndim == 2 and b.ndim == 2):
853
+ raise ValueError("The both arrays should be 2-dimensional.")
854
+
855
+ if not a.shape[1] == b.shape[1]:
856
+ raise ValueError("The number of columns for both arrays "
857
+ "should be equal.")
858
+
859
+ # c = np.vstack([np.kron(a[:, k], b[:, k]) for k in range(b.shape[1])]).T
860
+ c = a[..., :, np.newaxis, :] * b[..., np.newaxis, :, :]
861
+ return c.reshape((-1,) + c.shape[2:])
astra_scene_test/Scene_04/.venv/lib/python3.9/site-packages/scipy/linalg/_matfuncs_expm.pyi ADDED
@@ -0,0 +1,6 @@
 
 
 
 
 
 
 
1
+ from numpy.typing import NDArray
2
+ from typing import Any
3
+
4
+ def pick_pade_structure(a: NDArray[Any]) -> tuple[int, int]: ...
5
+
6
+ def pade_UV_calc(Am: NDArray[Any], n: int, m: int) -> None: ...
astra_scene_test/Scene_04/.venv/lib/python3.9/site-packages/scipy/linalg/_matfuncs_inv_ssq.py ADDED
@@ -0,0 +1,886 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """
2
+ Matrix functions that use Pade approximation with inverse scaling and squaring.
3
+
4
+ """
5
+ import warnings
6
+
7
+ import numpy as np
8
+
9
+ from scipy.linalg._matfuncs_sqrtm import SqrtmError, _sqrtm_triu
10
+ from scipy.linalg._decomp_schur import schur, rsf2csf
11
+ from scipy.linalg._matfuncs import funm
12
+ from scipy.linalg import svdvals, solve_triangular
13
+ from scipy.sparse.linalg._interface import LinearOperator
14
+ from scipy.sparse.linalg import onenormest
15
+ import scipy.special
16
+
17
+
18
+ class LogmRankWarning(UserWarning):
19
+ pass
20
+
21
+
22
+ class LogmExactlySingularWarning(LogmRankWarning):
23
+ pass
24
+
25
+
26
+ class LogmNearlySingularWarning(LogmRankWarning):
27
+ pass
28
+
29
+
30
+ class LogmError(np.linalg.LinAlgError):
31
+ pass
32
+
33
+
34
+ class FractionalMatrixPowerError(np.linalg.LinAlgError):
35
+ pass
36
+
37
+
38
+ #TODO renovate or move this class when scipy operators are more mature
39
+ class _MatrixM1PowerOperator(LinearOperator):
40
+ """
41
+ A representation of the linear operator (A - I)^p.
42
+ """
43
+
44
+ def __init__(self, A, p):
45
+ if A.ndim != 2 or A.shape[0] != A.shape[1]:
46
+ raise ValueError('expected A to be like a square matrix')
47
+ if p < 0 or p != int(p):
48
+ raise ValueError('expected p to be a non-negative integer')
49
+ self._A = A
50
+ self._p = p
51
+ self.ndim = A.ndim
52
+ self.shape = A.shape
53
+
54
+ def _matvec(self, x):
55
+ for i in range(self._p):
56
+ x = self._A.dot(x) - x
57
+ return x
58
+
59
+ def _rmatvec(self, x):
60
+ for i in range(self._p):
61
+ x = x.dot(self._A) - x
62
+ return x
63
+
64
+ def _matmat(self, X):
65
+ for i in range(self._p):
66
+ X = self._A.dot(X) - X
67
+ return X
68
+
69
+ def _adjoint(self):
70
+ return _MatrixM1PowerOperator(self._A.T, self._p)
71
+
72
+
73
+ #TODO renovate or move this function when SciPy operators are more mature
74
+ def _onenormest_m1_power(A, p,
75
+ t=2, itmax=5, compute_v=False, compute_w=False):
76
+ """
77
+ Efficiently estimate the 1-norm of (A - I)^p.
78
+
79
+ Parameters
80
+ ----------
81
+ A : ndarray
82
+ Matrix whose 1-norm of a power is to be computed.
83
+ p : int
84
+ Non-negative integer power.
85
+ t : int, optional
86
+ A positive parameter controlling the tradeoff between
87
+ accuracy versus time and memory usage.
88
+ Larger values take longer and use more memory
89
+ but give more accurate output.
90
+ itmax : int, optional
91
+ Use at most this many iterations.
92
+ compute_v : bool, optional
93
+ Request a norm-maximizing linear operator input vector if True.
94
+ compute_w : bool, optional
95
+ Request a norm-maximizing linear operator output vector if True.
96
+
97
+ Returns
98
+ -------
99
+ est : float
100
+ An underestimate of the 1-norm of the sparse matrix.
101
+ v : ndarray, optional
102
+ The vector such that ||Av||_1 == est*||v||_1.
103
+ It can be thought of as an input to the linear operator
104
+ that gives an output with particularly large norm.
105
+ w : ndarray, optional
106
+ The vector Av which has relatively large 1-norm.
107
+ It can be thought of as an output of the linear operator
108
+ that is relatively large in norm compared to the input.
109
+
110
+ """
111
+ return onenormest(_MatrixM1PowerOperator(A, p),
112
+ t=t, itmax=itmax, compute_v=compute_v, compute_w=compute_w)
113
+
114
+
115
+ def _unwindk(z):
116
+ """
117
+ Compute the scalar unwinding number.
118
+
119
+ Uses Eq. (5.3) in [1]_, and should be equal to (z - log(exp(z)) / (2 pi i).
120
+ Note that this definition differs in sign from the original definition
121
+ in equations (5, 6) in [2]_. The sign convention is justified in [3]_.
122
+
123
+ Parameters
124
+ ----------
125
+ z : complex
126
+ A complex number.
127
+
128
+ Returns
129
+ -------
130
+ unwinding_number : integer
131
+ The scalar unwinding number of z.
132
+
133
+ References
134
+ ----------
135
+ .. [1] Nicholas J. Higham and Lijing lin (2011)
136
+ "A Schur-Pade Algorithm for Fractional Powers of a Matrix."
137
+ SIAM Journal on Matrix Analysis and Applications,
138
+ 32 (3). pp. 1056-1078. ISSN 0895-4798
139
+
140
+ .. [2] Robert M. Corless and David J. Jeffrey,
141
+ "The unwinding number." Newsletter ACM SIGSAM Bulletin
142
+ Volume 30, Issue 2, June 1996, Pages 28-35.
143
+
144
+ .. [3] Russell Bradford and Robert M. Corless and James H. Davenport and
145
+ David J. Jeffrey and Stephen M. Watt,
146
+ "Reasoning about the elementary functions of complex analysis"
147
+ Annals of Mathematics and Artificial Intelligence,
148
+ 36: 303-318, 2002.
149
+
150
+ """
151
+ return int(np.ceil((z.imag - np.pi) / (2*np.pi)))
152
+
153
+
154
+ def _briggs_helper_function(a, k):
155
+ """
156
+ Computes r = a^(1 / (2^k)) - 1.
157
+
158
+ This is algorithm (2) of [1]_.
159
+ The purpose is to avoid a danger of subtractive cancellation.
160
+ For more computational efficiency it should probably be cythonized.
161
+
162
+ Parameters
163
+ ----------
164
+ a : complex
165
+ A complex number.
166
+ k : integer
167
+ A nonnegative integer.
168
+
169
+ Returns
170
+ -------
171
+ r : complex
172
+ The value r = a^(1 / (2^k)) - 1 computed with less cancellation.
173
+
174
+ Notes
175
+ -----
176
+ The algorithm as formulated in the reference does not handle k=0 or k=1
177
+ correctly, so these are special-cased in this implementation.
178
+ This function is intended to not allow `a` to belong to the closed
179
+ negative real axis, but this constraint is relaxed.
180
+
181
+ References
182
+ ----------
183
+ .. [1] Awad H. Al-Mohy (2012)
184
+ "A more accurate Briggs method for the logarithm",
185
+ Numerical Algorithms, 59 : 393--402.
186
+
187
+ """
188
+ if k < 0 or int(k) != k:
189
+ raise ValueError('expected a nonnegative integer k')
190
+ if k == 0:
191
+ return a - 1
192
+ elif k == 1:
193
+ return np.sqrt(a) - 1
194
+ else:
195
+ k_hat = k
196
+ if np.angle(a) >= np.pi / 2:
197
+ a = np.sqrt(a)
198
+ k_hat = k - 1
199
+ z0 = a - 1
200
+ a = np.sqrt(a)
201
+ r = 1 + a
202
+ for j in range(1, k_hat):
203
+ a = np.sqrt(a)
204
+ r = r * (1 + a)
205
+ r = z0 / r
206
+ return r
207
+
208
+
209
+ def _fractional_power_superdiag_entry(l1, l2, t12, p):
210
+ """
211
+ Compute a superdiagonal entry of a fractional matrix power.
212
+
213
+ This is Eq. (5.6) in [1]_.
214
+
215
+ Parameters
216
+ ----------
217
+ l1 : complex
218
+ A diagonal entry of the matrix.
219
+ l2 : complex
220
+ A diagonal entry of the matrix.
221
+ t12 : complex
222
+ A superdiagonal entry of the matrix.
223
+ p : float
224
+ A fractional power.
225
+
226
+ Returns
227
+ -------
228
+ f12 : complex
229
+ A superdiagonal entry of the fractional matrix power.
230
+
231
+ Notes
232
+ -----
233
+ Care has been taken to return a real number if possible when
234
+ all of the inputs are real numbers.
235
+
236
+ References
237
+ ----------
238
+ .. [1] Nicholas J. Higham and Lijing lin (2011)
239
+ "A Schur-Pade Algorithm for Fractional Powers of a Matrix."
240
+ SIAM Journal on Matrix Analysis and Applications,
241
+ 32 (3). pp. 1056-1078. ISSN 0895-4798
242
+
243
+ """
244
+ if l1 == l2:
245
+ f12 = t12 * p * l1**(p-1)
246
+ elif abs(l2 - l1) > abs(l1 + l2) / 2:
247
+ f12 = t12 * ((l2**p) - (l1**p)) / (l2 - l1)
248
+ else:
249
+ # This is Eq. (5.5) in [1].
250
+ z = (l2 - l1) / (l2 + l1)
251
+ log_l1 = np.log(l1)
252
+ log_l2 = np.log(l2)
253
+ arctanh_z = np.arctanh(z)
254
+ tmp_a = t12 * np.exp((p/2)*(log_l2 + log_l1))
255
+ tmp_u = _unwindk(log_l2 - log_l1)
256
+ if tmp_u:
257
+ tmp_b = p * (arctanh_z + np.pi * 1j * tmp_u)
258
+ else:
259
+ tmp_b = p * arctanh_z
260
+ tmp_c = 2 * np.sinh(tmp_b) / (l2 - l1)
261
+ f12 = tmp_a * tmp_c
262
+ return f12
263
+
264
+
265
+ def _logm_superdiag_entry(l1, l2, t12):
266
+ """
267
+ Compute a superdiagonal entry of a matrix logarithm.
268
+
269
+ This is like Eq. (11.28) in [1]_, except the determination of whether
270
+ l1 and l2 are sufficiently far apart has been modified.
271
+
272
+ Parameters
273
+ ----------
274
+ l1 : complex
275
+ A diagonal entry of the matrix.
276
+ l2 : complex
277
+ A diagonal entry of the matrix.
278
+ t12 : complex
279
+ A superdiagonal entry of the matrix.
280
+
281
+ Returns
282
+ -------
283
+ f12 : complex
284
+ A superdiagonal entry of the matrix logarithm.
285
+
286
+ Notes
287
+ -----
288
+ Care has been taken to return a real number if possible when
289
+ all of the inputs are real numbers.
290
+
291
+ References
292
+ ----------
293
+ .. [1] Nicholas J. Higham (2008)
294
+ "Functions of Matrices: Theory and Computation"
295
+ ISBN 978-0-898716-46-7
296
+
297
+ """
298
+ if l1 == l2:
299
+ f12 = t12 / l1
300
+ elif abs(l2 - l1) > abs(l1 + l2) / 2:
301
+ f12 = t12 * (np.log(l2) - np.log(l1)) / (l2 - l1)
302
+ else:
303
+ z = (l2 - l1) / (l2 + l1)
304
+ u = _unwindk(np.log(l2) - np.log(l1))
305
+ if u:
306
+ f12 = t12 * 2 * (np.arctanh(z) + np.pi*1j*u) / (l2 - l1)
307
+ else:
308
+ f12 = t12 * 2 * np.arctanh(z) / (l2 - l1)
309
+ return f12
310
+
311
+
312
+ def _inverse_squaring_helper(T0, theta):
313
+ """
314
+ A helper function for inverse scaling and squaring for Pade approximation.
315
+
316
+ Parameters
317
+ ----------
318
+ T0 : (N, N) array_like upper triangular
319
+ Matrix involved in inverse scaling and squaring.
320
+ theta : indexable
321
+ The values theta[1] .. theta[7] must be available.
322
+ They represent bounds related to Pade approximation, and they depend
323
+ on the matrix function which is being computed.
324
+ For example, different values of theta are required for
325
+ matrix logarithm than for fractional matrix power.
326
+
327
+ Returns
328
+ -------
329
+ R : (N, N) array_like upper triangular
330
+ Composition of zero or more matrix square roots of T0, minus I.
331
+ s : non-negative integer
332
+ Number of square roots taken.
333
+ m : positive integer
334
+ The degree of the Pade approximation.
335
+
336
+ Notes
337
+ -----
338
+ This subroutine appears as a chunk of lines within
339
+ a couple of published algorithms; for example it appears
340
+ as lines 4--35 in algorithm (3.1) of [1]_, and
341
+ as lines 3--34 in algorithm (4.1) of [2]_.
342
+ The instances of 'goto line 38' in algorithm (3.1) of [1]_
343
+ probably mean 'goto line 36' and have been interpreted accordingly.
344
+
345
+ References
346
+ ----------
347
+ .. [1] Nicholas J. Higham and Lijing Lin (2013)
348
+ "An Improved Schur-Pade Algorithm for Fractional Powers
349
+ of a Matrix and their Frechet Derivatives."
350
+
351
+ .. [2] Awad H. Al-Mohy and Nicholas J. Higham (2012)
352
+ "Improved Inverse Scaling and Squaring Algorithms
353
+ for the Matrix Logarithm."
354
+ SIAM Journal on Scientific Computing, 34 (4). C152-C169.
355
+ ISSN 1095-7197
356
+
357
+ """
358
+ if len(T0.shape) != 2 or T0.shape[0] != T0.shape[1]:
359
+ raise ValueError('expected an upper triangular square matrix')
360
+ n, n = T0.shape
361
+ T = T0
362
+
363
+ # Find s0, the smallest s such that the spectral radius
364
+ # of a certain diagonal matrix is at most theta[7].
365
+ # Note that because theta[7] < 1,
366
+ # this search will not terminate if any diagonal entry of T is zero.
367
+ s0 = 0
368
+ tmp_diag = np.diag(T)
369
+ if np.count_nonzero(tmp_diag) != n:
370
+ raise Exception('Diagonal entries of T must be nonzero')
371
+ while np.max(np.absolute(tmp_diag - 1)) > theta[7]:
372
+ tmp_diag = np.sqrt(tmp_diag)
373
+ s0 += 1
374
+
375
+ # Take matrix square roots of T.
376
+ for i in range(s0):
377
+ T = _sqrtm_triu(T)
378
+
379
+ # Flow control in this section is a little odd.
380
+ # This is because I am translating algorithm descriptions
381
+ # which have GOTOs in the publication.
382
+ s = s0
383
+ k = 0
384
+ d2 = _onenormest_m1_power(T, 2) ** (1/2)
385
+ d3 = _onenormest_m1_power(T, 3) ** (1/3)
386
+ a2 = max(d2, d3)
387
+ m = None
388
+ for i in (1, 2):
389
+ if a2 <= theta[i]:
390
+ m = i
391
+ break
392
+ while m is None:
393
+ if s > s0:
394
+ d3 = _onenormest_m1_power(T, 3) ** (1/3)
395
+ d4 = _onenormest_m1_power(T, 4) ** (1/4)
396
+ a3 = max(d3, d4)
397
+ if a3 <= theta[7]:
398
+ j1 = min(i for i in (3, 4, 5, 6, 7) if a3 <= theta[i])
399
+ if j1 <= 6:
400
+ m = j1
401
+ break
402
+ elif a3 / 2 <= theta[5] and k < 2:
403
+ k += 1
404
+ T = _sqrtm_triu(T)
405
+ s += 1
406
+ continue
407
+ d5 = _onenormest_m1_power(T, 5) ** (1/5)
408
+ a4 = max(d4, d5)
409
+ eta = min(a3, a4)
410
+ for i in (6, 7):
411
+ if eta <= theta[i]:
412
+ m = i
413
+ break
414
+ if m is not None:
415
+ break
416
+ T = _sqrtm_triu(T)
417
+ s += 1
418
+
419
+ # The subtraction of the identity is redundant here,
420
+ # because the diagonal will be replaced for improved numerical accuracy,
421
+ # but this formulation should help clarify the meaning of R.
422
+ R = T - np.identity(n)
423
+
424
+ # Replace the diagonal and first superdiagonal of T0^(1/(2^s)) - I
425
+ # using formulas that have less subtractive cancellation.
426
+ # Skip this step if the principal branch
427
+ # does not exist at T0; this happens when a diagonal entry of T0
428
+ # is negative with imaginary part 0.
429
+ has_principal_branch = all(x.real > 0 or x.imag != 0 for x in np.diag(T0))
430
+ if has_principal_branch:
431
+ for j in range(n):
432
+ a = T0[j, j]
433
+ r = _briggs_helper_function(a, s)
434
+ R[j, j] = r
435
+ p = np.exp2(-s)
436
+ for j in range(n-1):
437
+ l1 = T0[j, j]
438
+ l2 = T0[j+1, j+1]
439
+ t12 = T0[j, j+1]
440
+ f12 = _fractional_power_superdiag_entry(l1, l2, t12, p)
441
+ R[j, j+1] = f12
442
+
443
+ # Return the T-I matrix, the number of square roots, and the Pade degree.
444
+ if not np.array_equal(R, np.triu(R)):
445
+ raise Exception('R is not upper triangular')
446
+ return R, s, m
447
+
448
+
449
+ def _fractional_power_pade_constant(i, t):
450
+ # A helper function for matrix fractional power.
451
+ if i < 1:
452
+ raise ValueError('expected a positive integer i')
453
+ if not (-1 < t < 1):
454
+ raise ValueError('expected -1 < t < 1')
455
+ if i == 1:
456
+ return -t
457
+ elif i % 2 == 0:
458
+ j = i // 2
459
+ return (-j + t) / (2 * (2*j - 1))
460
+ elif i % 2 == 1:
461
+ j = (i - 1) // 2
462
+ return (-j - t) / (2 * (2*j + 1))
463
+ else:
464
+ raise Exception(f'unnexpected value of i, i = {i}')
465
+
466
+
467
+ def _fractional_power_pade(R, t, m):
468
+ """
469
+ Evaluate the Pade approximation of a fractional matrix power.
470
+
471
+ Evaluate the degree-m Pade approximation of R
472
+ to the fractional matrix power t using the continued fraction
473
+ in bottom-up fashion using algorithm (4.1) in [1]_.
474
+
475
+ Parameters
476
+ ----------
477
+ R : (N, N) array_like
478
+ Upper triangular matrix whose fractional power to evaluate.
479
+ t : float
480
+ Fractional power between -1 and 1 exclusive.
481
+ m : positive integer
482
+ Degree of Pade approximation.
483
+
484
+ Returns
485
+ -------
486
+ U : (N, N) array_like
487
+ The degree-m Pade approximation of R to the fractional power t.
488
+ This matrix will be upper triangular.
489
+
490
+ References
491
+ ----------
492
+ .. [1] Nicholas J. Higham and Lijing lin (2011)
493
+ "A Schur-Pade Algorithm for Fractional Powers of a Matrix."
494
+ SIAM Journal on Matrix Analysis and Applications,
495
+ 32 (3). pp. 1056-1078. ISSN 0895-4798
496
+
497
+ """
498
+ if m < 1 or int(m) != m:
499
+ raise ValueError('expected a positive integer m')
500
+ if not (-1 < t < 1):
501
+ raise ValueError('expected -1 < t < 1')
502
+ R = np.asarray(R)
503
+ if len(R.shape) != 2 or R.shape[0] != R.shape[1]:
504
+ raise ValueError('expected an upper triangular square matrix')
505
+ n, n = R.shape
506
+ ident = np.identity(n)
507
+ Y = R * _fractional_power_pade_constant(2*m, t)
508
+ for j in range(2*m - 1, 0, -1):
509
+ rhs = R * _fractional_power_pade_constant(j, t)
510
+ Y = solve_triangular(ident + Y, rhs)
511
+ U = ident + Y
512
+ if not np.array_equal(U, np.triu(U)):
513
+ raise Exception('U is not upper triangular')
514
+ return U
515
+
516
+
517
+ def _remainder_matrix_power_triu(T, t):
518
+ """
519
+ Compute a fractional power of an upper triangular matrix.
520
+
521
+ The fractional power is restricted to fractions -1 < t < 1.
522
+ This uses algorithm (3.1) of [1]_.
523
+ The Pade approximation itself uses algorithm (4.1) of [2]_.
524
+
525
+ Parameters
526
+ ----------
527
+ T : (N, N) array_like
528
+ Upper triangular matrix whose fractional power to evaluate.
529
+ t : float
530
+ Fractional power between -1 and 1 exclusive.
531
+
532
+ Returns
533
+ -------
534
+ X : (N, N) array_like
535
+ The fractional power of the matrix.
536
+
537
+ References
538
+ ----------
539
+ .. [1] Nicholas J. Higham and Lijing Lin (2013)
540
+ "An Improved Schur-Pade Algorithm for Fractional Powers
541
+ of a Matrix and their Frechet Derivatives."
542
+
543
+ .. [2] Nicholas J. Higham and Lijing lin (2011)
544
+ "A Schur-Pade Algorithm for Fractional Powers of a Matrix."
545
+ SIAM Journal on Matrix Analysis and Applications,
546
+ 32 (3). pp. 1056-1078. ISSN 0895-4798
547
+
548
+ """
549
+ m_to_theta = {
550
+ 1: 1.51e-5,
551
+ 2: 2.24e-3,
552
+ 3: 1.88e-2,
553
+ 4: 6.04e-2,
554
+ 5: 1.24e-1,
555
+ 6: 2.00e-1,
556
+ 7: 2.79e-1,
557
+ }
558
+ n, n = T.shape
559
+ T0 = T
560
+ T0_diag = np.diag(T0)
561
+ if np.array_equal(T0, np.diag(T0_diag)):
562
+ U = np.diag(T0_diag ** t)
563
+ else:
564
+ R, s, m = _inverse_squaring_helper(T0, m_to_theta)
565
+
566
+ # Evaluate the Pade approximation.
567
+ # Note that this function expects the negative of the matrix
568
+ # returned by the inverse squaring helper.
569
+ U = _fractional_power_pade(-R, t, m)
570
+
571
+ # Undo the inverse scaling and squaring.
572
+ # Be less clever about this
573
+ # if the principal branch does not exist at T0;
574
+ # this happens when a diagonal entry of T0
575
+ # is negative with imaginary part 0.
576
+ eivals = np.diag(T0)
577
+ has_principal_branch = all(x.real > 0 or x.imag != 0 for x in eivals)
578
+ for i in range(s, -1, -1):
579
+ if i < s:
580
+ U = U.dot(U)
581
+ else:
582
+ if has_principal_branch:
583
+ p = t * np.exp2(-i)
584
+ U[np.diag_indices(n)] = T0_diag ** p
585
+ for j in range(n-1):
586
+ l1 = T0[j, j]
587
+ l2 = T0[j+1, j+1]
588
+ t12 = T0[j, j+1]
589
+ f12 = _fractional_power_superdiag_entry(l1, l2, t12, p)
590
+ U[j, j+1] = f12
591
+ if not np.array_equal(U, np.triu(U)):
592
+ raise Exception('U is not upper triangular')
593
+ return U
594
+
595
+
596
+ def _remainder_matrix_power(A, t):
597
+ """
598
+ Compute the fractional power of a matrix, for fractions -1 < t < 1.
599
+
600
+ This uses algorithm (3.1) of [1]_.
601
+ The Pade approximation itself uses algorithm (4.1) of [2]_.
602
+
603
+ Parameters
604
+ ----------
605
+ A : (N, N) array_like
606
+ Matrix whose fractional power to evaluate.
607
+ t : float
608
+ Fractional power between -1 and 1 exclusive.
609
+
610
+ Returns
611
+ -------
612
+ X : (N, N) array_like
613
+ The fractional power of the matrix.
614
+
615
+ References
616
+ ----------
617
+ .. [1] Nicholas J. Higham and Lijing Lin (2013)
618
+ "An Improved Schur-Pade Algorithm for Fractional Powers
619
+ of a Matrix and their Frechet Derivatives."
620
+
621
+ .. [2] Nicholas J. Higham and Lijing lin (2011)
622
+ "A Schur-Pade Algorithm for Fractional Powers of a Matrix."
623
+ SIAM Journal on Matrix Analysis and Applications,
624
+ 32 (3). pp. 1056-1078. ISSN 0895-4798
625
+
626
+ """
627
+ # This code block is copied from numpy.matrix_power().
628
+ A = np.asarray(A)
629
+ if len(A.shape) != 2 or A.shape[0] != A.shape[1]:
630
+ raise ValueError('input must be a square array')
631
+
632
+ # Get the number of rows and columns.
633
+ n, n = A.shape
634
+
635
+ # Triangularize the matrix if necessary,
636
+ # attempting to preserve dtype if possible.
637
+ if np.array_equal(A, np.triu(A)):
638
+ Z = None
639
+ T = A
640
+ else:
641
+ if np.isrealobj(A):
642
+ T, Z = schur(A)
643
+ if not np.array_equal(T, np.triu(T)):
644
+ T, Z = rsf2csf(T, Z)
645
+ else:
646
+ T, Z = schur(A, output='complex')
647
+
648
+ # Zeros on the diagonal of the triangular matrix are forbidden,
649
+ # because the inverse scaling and squaring cannot deal with it.
650
+ T_diag = np.diag(T)
651
+ if np.count_nonzero(T_diag) != n:
652
+ raise FractionalMatrixPowerError(
653
+ 'cannot use inverse scaling and squaring to find '
654
+ 'the fractional matrix power of a singular matrix')
655
+
656
+ # If the triangular matrix is real and has a negative
657
+ # entry on the diagonal, then force the matrix to be complex.
658
+ if np.isrealobj(T) and np.min(T_diag) < 0:
659
+ T = T.astype(complex)
660
+
661
+ # Get the fractional power of the triangular matrix,
662
+ # and de-triangularize it if necessary.
663
+ U = _remainder_matrix_power_triu(T, t)
664
+ if Z is not None:
665
+ ZH = np.conjugate(Z).T
666
+ return Z.dot(U).dot(ZH)
667
+ else:
668
+ return U
669
+
670
+
671
+ def _fractional_matrix_power(A, p):
672
+ """
673
+ Compute the fractional power of a matrix.
674
+
675
+ See the fractional_matrix_power docstring in matfuncs.py for more info.
676
+
677
+ """
678
+ A = np.asarray(A)
679
+ if len(A.shape) != 2 or A.shape[0] != A.shape[1]:
680
+ raise ValueError('expected a square matrix')
681
+ if p == int(p):
682
+ return np.linalg.matrix_power(A, int(p))
683
+ # Compute singular values.
684
+ s = svdvals(A)
685
+ # Inverse scaling and squaring cannot deal with a singular matrix,
686
+ # because the process of repeatedly taking square roots
687
+ # would not converge to the identity matrix.
688
+ if s[-1]:
689
+ # Compute the condition number relative to matrix inversion,
690
+ # and use this to decide between floor(p) and ceil(p).
691
+ k2 = s[0] / s[-1]
692
+ p1 = p - np.floor(p)
693
+ p2 = p - np.ceil(p)
694
+ if p1 * k2 ** (1 - p1) <= -p2 * k2:
695
+ a = int(np.floor(p))
696
+ b = p1
697
+ else:
698
+ a = int(np.ceil(p))
699
+ b = p2
700
+ try:
701
+ R = _remainder_matrix_power(A, b)
702
+ Q = np.linalg.matrix_power(A, a)
703
+ return Q.dot(R)
704
+ except np.linalg.LinAlgError:
705
+ pass
706
+ # If p is negative then we are going to give up.
707
+ # If p is non-negative then we can fall back to generic funm.
708
+ if p < 0:
709
+ X = np.empty_like(A)
710
+ X.fill(np.nan)
711
+ return X
712
+ else:
713
+ p1 = p - np.floor(p)
714
+ a = int(np.floor(p))
715
+ b = p1
716
+ R, info = funm(A, lambda x: pow(x, b), disp=False)
717
+ Q = np.linalg.matrix_power(A, a)
718
+ return Q.dot(R)
719
+
720
+
721
+ def _logm_triu(T):
722
+ """
723
+ Compute matrix logarithm of an upper triangular matrix.
724
+
725
+ The matrix logarithm is the inverse of
726
+ expm: expm(logm(`T`)) == `T`
727
+
728
+ Parameters
729
+ ----------
730
+ T : (N, N) array_like
731
+ Upper triangular matrix whose logarithm to evaluate
732
+
733
+ Returns
734
+ -------
735
+ logm : (N, N) ndarray
736
+ Matrix logarithm of `T`
737
+
738
+ References
739
+ ----------
740
+ .. [1] Awad H. Al-Mohy and Nicholas J. Higham (2012)
741
+ "Improved Inverse Scaling and Squaring Algorithms
742
+ for the Matrix Logarithm."
743
+ SIAM Journal on Scientific Computing, 34 (4). C152-C169.
744
+ ISSN 1095-7197
745
+
746
+ .. [2] Nicholas J. Higham (2008)
747
+ "Functions of Matrices: Theory and Computation"
748
+ ISBN 978-0-898716-46-7
749
+
750
+ .. [3] Nicholas J. Higham and Lijing lin (2011)
751
+ "A Schur-Pade Algorithm for Fractional Powers of a Matrix."
752
+ SIAM Journal on Matrix Analysis and Applications,
753
+ 32 (3). pp. 1056-1078. ISSN 0895-4798
754
+
755
+ """
756
+ T = np.asarray(T)
757
+ if len(T.shape) != 2 or T.shape[0] != T.shape[1]:
758
+ raise ValueError('expected an upper triangular square matrix')
759
+ n, n = T.shape
760
+
761
+ # Construct T0 with the appropriate type,
762
+ # depending on the dtype and the spectrum of T.
763
+ T_diag = np.diag(T)
764
+ keep_it_real = np.isrealobj(T) and np.min(T_diag) >= 0
765
+ if keep_it_real:
766
+ T0 = T
767
+ else:
768
+ T0 = T.astype(complex)
769
+
770
+ # Define bounds given in Table (2.1).
771
+ theta = (None,
772
+ 1.59e-5, 2.31e-3, 1.94e-2, 6.21e-2,
773
+ 1.28e-1, 2.06e-1, 2.88e-1, 3.67e-1,
774
+ 4.39e-1, 5.03e-1, 5.60e-1, 6.09e-1,
775
+ 6.52e-1, 6.89e-1, 7.21e-1, 7.49e-1)
776
+
777
+ R, s, m = _inverse_squaring_helper(T0, theta)
778
+
779
+ # Evaluate U = 2**s r_m(T - I) using the partial fraction expansion (1.1).
780
+ # This requires the nodes and weights
781
+ # corresponding to degree-m Gauss-Legendre quadrature.
782
+ # These quadrature arrays need to be transformed from the [-1, 1] interval
783
+ # to the [0, 1] interval.
784
+ nodes, weights = scipy.special.p_roots(m)
785
+ nodes = nodes.real
786
+ if nodes.shape != (m,) or weights.shape != (m,):
787
+ raise Exception('internal error')
788
+ nodes = 0.5 + 0.5 * nodes
789
+ weights = 0.5 * weights
790
+ ident = np.identity(n)
791
+ U = np.zeros_like(R)
792
+ for alpha, beta in zip(weights, nodes):
793
+ U += solve_triangular(ident + beta*R, alpha*R)
794
+ U *= np.exp2(s)
795
+
796
+ # Skip this step if the principal branch
797
+ # does not exist at T0; this happens when a diagonal entry of T0
798
+ # is negative with imaginary part 0.
799
+ has_principal_branch = all(x.real > 0 or x.imag != 0 for x in np.diag(T0))
800
+ if has_principal_branch:
801
+
802
+ # Recompute diagonal entries of U.
803
+ U[np.diag_indices(n)] = np.log(np.diag(T0))
804
+
805
+ # Recompute superdiagonal entries of U.
806
+ # This indexing of this code should be renovated
807
+ # when newer np.diagonal() becomes available.
808
+ for i in range(n-1):
809
+ l1 = T0[i, i]
810
+ l2 = T0[i+1, i+1]
811
+ t12 = T0[i, i+1]
812
+ U[i, i+1] = _logm_superdiag_entry(l1, l2, t12)
813
+
814
+ # Return the logm of the upper triangular matrix.
815
+ if not np.array_equal(U, np.triu(U)):
816
+ raise Exception('U is not upper triangular')
817
+ return U
818
+
819
+
820
+ def _logm_force_nonsingular_triangular_matrix(T, inplace=False):
821
+ # The input matrix should be upper triangular.
822
+ # The eps is ad hoc and is not meant to be machine precision.
823
+ tri_eps = 1e-20
824
+ abs_diag = np.absolute(np.diag(T))
825
+ if np.any(abs_diag == 0):
826
+ exact_singularity_msg = 'The logm input matrix is exactly singular.'
827
+ warnings.warn(exact_singularity_msg, LogmExactlySingularWarning, stacklevel=3)
828
+ if not inplace:
829
+ T = T.copy()
830
+ n = T.shape[0]
831
+ for i in range(n):
832
+ if not T[i, i]:
833
+ T[i, i] = tri_eps
834
+ elif np.any(abs_diag < tri_eps):
835
+ near_singularity_msg = 'The logm input matrix may be nearly singular.'
836
+ warnings.warn(near_singularity_msg, LogmNearlySingularWarning, stacklevel=3)
837
+ return T
838
+
839
+
840
+ def _logm(A):
841
+ """
842
+ Compute the matrix logarithm.
843
+
844
+ See the logm docstring in matfuncs.py for more info.
845
+
846
+ Notes
847
+ -----
848
+ In this function we look at triangular matrices that are similar
849
+ to the input matrix. If any diagonal entry of such a triangular matrix
850
+ is exactly zero then the original matrix is singular.
851
+ The matrix logarithm does not exist for such matrices,
852
+ but in such cases we will pretend that the diagonal entries that are zero
853
+ are actually slightly positive by an ad-hoc amount, in the interest
854
+ of returning something more useful than NaN. This will cause a warning.
855
+
856
+ """
857
+ A = np.asarray(A)
858
+ if len(A.shape) != 2 or A.shape[0] != A.shape[1]:
859
+ raise ValueError('expected a square matrix')
860
+
861
+ # If the input matrix dtype is integer then copy to a float dtype matrix.
862
+ if issubclass(A.dtype.type, np.integer):
863
+ A = np.asarray(A, dtype=float)
864
+
865
+ keep_it_real = np.isrealobj(A)
866
+ try:
867
+ if np.array_equal(A, np.triu(A)):
868
+ A = _logm_force_nonsingular_triangular_matrix(A)
869
+ if np.min(np.diag(A)) < 0:
870
+ A = A.astype(complex)
871
+ return _logm_triu(A)
872
+ else:
873
+ if keep_it_real:
874
+ T, Z = schur(A)
875
+ if not np.array_equal(T, np.triu(T)):
876
+ T, Z = rsf2csf(T, Z)
877
+ else:
878
+ T, Z = schur(A, output='complex')
879
+ T = _logm_force_nonsingular_triangular_matrix(T, inplace=True)
880
+ U = _logm_triu(T)
881
+ ZH = np.conjugate(Z).T
882
+ return Z.dot(U).dot(ZH)
883
+ except (SqrtmError, LogmError):
884
+ X = np.empty_like(A)
885
+ X.fill(np.nan)
886
+ return X
astra_scene_test/Scene_04/.venv/lib/python3.9/site-packages/scipy/linalg/_matfuncs_sqrtm.py ADDED
@@ -0,0 +1,214 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """
2
+ Matrix square root for general matrices and for upper triangular matrices.
3
+
4
+ This module exists to avoid cyclic imports.
5
+
6
+ """
7
+ __all__ = ['sqrtm']
8
+
9
+ import numpy as np
10
+
11
+ from scipy._lib._util import _asarray_validated
12
+
13
+ # Local imports
14
+ from ._misc import norm
15
+ from .lapack import ztrsyl, dtrsyl
16
+ from ._decomp_schur import schur, rsf2csf
17
+
18
+
19
+
20
+ class SqrtmError(np.linalg.LinAlgError):
21
+ pass
22
+
23
+
24
+ from ._matfuncs_sqrtm_triu import within_block_loop # noqa: E402
25
+
26
+
27
+ def _sqrtm_triu(T, blocksize=64):
28
+ """
29
+ Matrix square root of an upper triangular matrix.
30
+
31
+ This is a helper function for `sqrtm` and `logm`.
32
+
33
+ Parameters
34
+ ----------
35
+ T : (N, N) array_like upper triangular
36
+ Matrix whose square root to evaluate
37
+ blocksize : int, optional
38
+ If the blocksize is not degenerate with respect to the
39
+ size of the input array, then use a blocked algorithm. (Default: 64)
40
+
41
+ Returns
42
+ -------
43
+ sqrtm : (N, N) ndarray
44
+ Value of the sqrt function at `T`
45
+
46
+ References
47
+ ----------
48
+ .. [1] Edvin Deadman, Nicholas J. Higham, Rui Ralha (2013)
49
+ "Blocked Schur Algorithms for Computing the Matrix Square Root,
50
+ Lecture Notes in Computer Science, 7782. pp. 171-182.
51
+
52
+ """
53
+ T_diag = np.diag(T)
54
+ keep_it_real = np.isrealobj(T) and np.min(T_diag) >= 0
55
+
56
+ # Cast to complex as necessary + ensure double precision
57
+ if not keep_it_real:
58
+ T = np.asarray(T, dtype=np.complex128, order="C")
59
+ T_diag = np.asarray(T_diag, dtype=np.complex128)
60
+ else:
61
+ T = np.asarray(T, dtype=np.float64, order="C")
62
+ T_diag = np.asarray(T_diag, dtype=np.float64)
63
+
64
+ R = np.diag(np.sqrt(T_diag))
65
+
66
+ # Compute the number of blocks to use; use at least one block.
67
+ n, n = T.shape
68
+ nblocks = max(n // blocksize, 1)
69
+
70
+ # Compute the smaller of the two sizes of blocks that
71
+ # we will actually use, and compute the number of large blocks.
72
+ bsmall, nlarge = divmod(n, nblocks)
73
+ blarge = bsmall + 1
74
+ nsmall = nblocks - nlarge
75
+ if nsmall * bsmall + nlarge * blarge != n:
76
+ raise Exception('internal inconsistency')
77
+
78
+ # Define the index range covered by each block.
79
+ start_stop_pairs = []
80
+ start = 0
81
+ for count, size in ((nsmall, bsmall), (nlarge, blarge)):
82
+ for i in range(count):
83
+ start_stop_pairs.append((start, start + size))
84
+ start += size
85
+
86
+ # Within-block interactions (Cythonized)
87
+ try:
88
+ within_block_loop(R, T, start_stop_pairs, nblocks)
89
+ except RuntimeError as e:
90
+ raise SqrtmError(*e.args) from e
91
+
92
+ # Between-block interactions (Cython would give no significant speedup)
93
+ for j in range(nblocks):
94
+ jstart, jstop = start_stop_pairs[j]
95
+ for i in range(j-1, -1, -1):
96
+ istart, istop = start_stop_pairs[i]
97
+ S = T[istart:istop, jstart:jstop]
98
+ if j - i > 1:
99
+ S = S - R[istart:istop, istop:jstart].dot(R[istop:jstart,
100
+ jstart:jstop])
101
+
102
+ # Invoke LAPACK.
103
+ # For more details, see the solve_sylvester implementation
104
+ # and the fortran dtrsyl and ztrsyl docs.
105
+ Rii = R[istart:istop, istart:istop]
106
+ Rjj = R[jstart:jstop, jstart:jstop]
107
+ if keep_it_real:
108
+ x, scale, info = dtrsyl(Rii, Rjj, S)
109
+ else:
110
+ x, scale, info = ztrsyl(Rii, Rjj, S)
111
+ R[istart:istop, jstart:jstop] = x * scale
112
+
113
+ # Return the matrix square root.
114
+ return R
115
+
116
+
117
+ def sqrtm(A, disp=True, blocksize=64):
118
+ """
119
+ Matrix square root.
120
+
121
+ Parameters
122
+ ----------
123
+ A : (N, N) array_like
124
+ Matrix whose square root to evaluate
125
+ disp : bool, optional
126
+ Print warning if error in the result is estimated large
127
+ instead of returning estimated error. (Default: True)
128
+ blocksize : integer, optional
129
+ If the blocksize is not degenerate with respect to the
130
+ size of the input array, then use a blocked algorithm. (Default: 64)
131
+
132
+ Returns
133
+ -------
134
+ sqrtm : (N, N) ndarray
135
+ Value of the sqrt function at `A`. The dtype is float or complex.
136
+ The precision (data size) is determined based on the precision of
137
+ input `A`. When the dtype is float, the precision is the same as `A`.
138
+ When the dtype is complex, the precision is double that of `A`. The
139
+ precision might be clipped by each dtype precision range.
140
+
141
+ errest : float
142
+ (if disp == False)
143
+
144
+ Frobenius norm of the estimated error, ||err||_F / ||A||_F
145
+
146
+ References
147
+ ----------
148
+ .. [1] Edvin Deadman, Nicholas J. Higham, Rui Ralha (2013)
149
+ "Blocked Schur Algorithms for Computing the Matrix Square Root,
150
+ Lecture Notes in Computer Science, 7782. pp. 171-182.
151
+
152
+ Examples
153
+ --------
154
+ >>> import numpy as np
155
+ >>> from scipy.linalg import sqrtm
156
+ >>> a = np.array([[1.0, 3.0], [1.0, 4.0]])
157
+ >>> r = sqrtm(a)
158
+ >>> r
159
+ array([[ 0.75592895, 1.13389342],
160
+ [ 0.37796447, 1.88982237]])
161
+ >>> r.dot(r)
162
+ array([[ 1., 3.],
163
+ [ 1., 4.]])
164
+
165
+ """
166
+ byte_size = np.asarray(A).dtype.itemsize
167
+ A = _asarray_validated(A, check_finite=True, as_inexact=True)
168
+ if len(A.shape) != 2:
169
+ raise ValueError("Non-matrix input to matrix function.")
170
+ if blocksize < 1:
171
+ raise ValueError("The blocksize should be at least 1.")
172
+ keep_it_real = np.isrealobj(A)
173
+ if keep_it_real:
174
+ T, Z = schur(A)
175
+ d0 = np.diagonal(T)
176
+ d1 = np.diagonal(T, -1)
177
+ eps = np.finfo(T.dtype).eps
178
+ needs_conversion = abs(d1) > eps * (abs(d0[1:]) + abs(d0[:-1]))
179
+ if needs_conversion.any():
180
+ T, Z = rsf2csf(T, Z)
181
+ else:
182
+ T, Z = schur(A, output='complex')
183
+ failflag = False
184
+ try:
185
+ R = _sqrtm_triu(T, blocksize=blocksize)
186
+ ZH = np.conjugate(Z).T
187
+ X = Z.dot(R).dot(ZH)
188
+ if not np.iscomplexobj(X):
189
+ # float byte size range: f2 ~ f16
190
+ X = X.astype(f"f{np.clip(byte_size, 2, 16)}", copy=False)
191
+ else:
192
+ # complex byte size range: c8 ~ c32.
193
+ # c32(complex256) might not be supported in some environments.
194
+ if hasattr(np, 'complex256'):
195
+ X = X.astype(f"c{np.clip(byte_size*2, 8, 32)}", copy=False)
196
+ else:
197
+ X = X.astype(f"c{np.clip(byte_size*2, 8, 16)}", copy=False)
198
+ except SqrtmError:
199
+ failflag = True
200
+ X = np.empty_like(A)
201
+ X.fill(np.nan)
202
+
203
+ if disp:
204
+ if failflag:
205
+ print("Failed to find a square root.")
206
+ return X
207
+ else:
208
+ try:
209
+ arg2 = norm(X.dot(X) - A, 'fro')**2 / norm(A, 'fro')
210
+ except ValueError:
211
+ # NaNs in matrix
212
+ arg2 = np.inf
213
+
214
+ return X, arg2
astra_scene_test/Scene_04/.venv/lib/python3.9/site-packages/scipy/linalg/_misc.py ADDED
@@ -0,0 +1,191 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import numpy as np
2
+ from numpy.linalg import LinAlgError
3
+ from .blas import get_blas_funcs
4
+ from .lapack import get_lapack_funcs
5
+
6
+ __all__ = ['LinAlgError', 'LinAlgWarning', 'norm']
7
+
8
+
9
+ class LinAlgWarning(RuntimeWarning):
10
+ """
11
+ The warning emitted when a linear algebra related operation is close
12
+ to fail conditions of the algorithm or loss of accuracy is expected.
13
+ """
14
+ pass
15
+
16
+
17
+ def norm(a, ord=None, axis=None, keepdims=False, check_finite=True):
18
+ """
19
+ Matrix or vector norm.
20
+
21
+ This function is able to return one of eight different matrix norms,
22
+ or one of an infinite number of vector norms (described below), depending
23
+ on the value of the ``ord`` parameter. For tensors with rank different from
24
+ 1 or 2, only `ord=None` is supported.
25
+
26
+ Parameters
27
+ ----------
28
+ a : array_like
29
+ Input array. If `axis` is None, `a` must be 1-D or 2-D, unless `ord`
30
+ is None. If both `axis` and `ord` are None, the 2-norm of
31
+ ``a.ravel`` will be returned.
32
+ ord : {int, inf, -inf, 'fro', 'nuc', None}, optional
33
+ Order of the norm (see table under ``Notes``). inf means NumPy's
34
+ `inf` object.
35
+ axis : {int, 2-tuple of ints, None}, optional
36
+ If `axis` is an integer, it specifies the axis of `a` along which to
37
+ compute the vector norms. If `axis` is a 2-tuple, it specifies the
38
+ axes that hold 2-D matrices, and the matrix norms of these matrices
39
+ are computed. If `axis` is None then either a vector norm (when `a`
40
+ is 1-D) or a matrix norm (when `a` is 2-D) is returned.
41
+ keepdims : bool, optional
42
+ If this is set to True, the axes which are normed over are left in the
43
+ result as dimensions with size one. With this option the result will
44
+ broadcast correctly against the original `a`.
45
+ check_finite : bool, optional
46
+ Whether to check that the input matrix contains only finite numbers.
47
+ Disabling may give a performance gain, but may result in problems
48
+ (crashes, non-termination) if the inputs do contain infinities or NaNs.
49
+
50
+ Returns
51
+ -------
52
+ n : float or ndarray
53
+ Norm of the matrix or vector(s).
54
+
55
+ Notes
56
+ -----
57
+ For values of ``ord <= 0``, the result is, strictly speaking, not a
58
+ mathematical 'norm', but it may still be useful for various numerical
59
+ purposes.
60
+
61
+ The following norms can be calculated:
62
+
63
+ ===== ============================ ==========================
64
+ ord norm for matrices norm for vectors
65
+ ===== ============================ ==========================
66
+ None Frobenius norm 2-norm
67
+ 'fro' Frobenius norm --
68
+ 'nuc' nuclear norm --
69
+ inf max(sum(abs(a), axis=1)) max(abs(a))
70
+ -inf min(sum(abs(a), axis=1)) min(abs(a))
71
+ 0 -- sum(a != 0)
72
+ 1 max(sum(abs(a), axis=0)) as below
73
+ -1 min(sum(abs(a), axis=0)) as below
74
+ 2 2-norm (largest sing. value) as below
75
+ -2 smallest singular value as below
76
+ other -- sum(abs(a)**ord)**(1./ord)
77
+ ===== ============================ ==========================
78
+
79
+ The Frobenius norm is given by [1]_:
80
+
81
+ :math:`||A||_F = [\\sum_{i,j} abs(a_{i,j})^2]^{1/2}`
82
+
83
+ The nuclear norm is the sum of the singular values.
84
+
85
+ Both the Frobenius and nuclear norm orders are only defined for
86
+ matrices.
87
+
88
+ References
89
+ ----------
90
+ .. [1] G. H. Golub and C. F. Van Loan, *Matrix Computations*,
91
+ Baltimore, MD, Johns Hopkins University Press, 1985, pg. 15
92
+
93
+ Examples
94
+ --------
95
+ >>> import numpy as np
96
+ >>> from scipy.linalg import norm
97
+ >>> a = np.arange(9) - 4.0
98
+ >>> a
99
+ array([-4., -3., -2., -1., 0., 1., 2., 3., 4.])
100
+ >>> b = a.reshape((3, 3))
101
+ >>> b
102
+ array([[-4., -3., -2.],
103
+ [-1., 0., 1.],
104
+ [ 2., 3., 4.]])
105
+
106
+ >>> norm(a)
107
+ 7.745966692414834
108
+ >>> norm(b)
109
+ 7.745966692414834
110
+ >>> norm(b, 'fro')
111
+ 7.745966692414834
112
+ >>> norm(a, np.inf)
113
+ 4
114
+ >>> norm(b, np.inf)
115
+ 9
116
+ >>> norm(a, -np.inf)
117
+ 0
118
+ >>> norm(b, -np.inf)
119
+ 2
120
+
121
+ >>> norm(a, 1)
122
+ 20
123
+ >>> norm(b, 1)
124
+ 7
125
+ >>> norm(a, -1)
126
+ -4.6566128774142013e-010
127
+ >>> norm(b, -1)
128
+ 6
129
+ >>> norm(a, 2)
130
+ 7.745966692414834
131
+ >>> norm(b, 2)
132
+ 7.3484692283495345
133
+
134
+ >>> norm(a, -2)
135
+ 0
136
+ >>> norm(b, -2)
137
+ 1.8570331885190563e-016
138
+ >>> norm(a, 3)
139
+ 5.8480354764257312
140
+ >>> norm(a, -3)
141
+ 0
142
+
143
+ """
144
+ # Differs from numpy only in non-finite handling and the use of blas.
145
+ if check_finite:
146
+ a = np.asarray_chkfinite(a)
147
+ else:
148
+ a = np.asarray(a)
149
+
150
+ if a.size and a.dtype.char in 'fdFD' and axis is None and not keepdims:
151
+
152
+ if ord in (None, 2) and (a.ndim == 1):
153
+ # use blas for fast and stable euclidean norm
154
+ nrm2 = get_blas_funcs('nrm2', dtype=a.dtype, ilp64='preferred')
155
+ return nrm2(a)
156
+
157
+ if a.ndim == 2:
158
+ # Use lapack for a couple fast matrix norms.
159
+ # For some reason the *lange frobenius norm is slow.
160
+ lange_args = None
161
+ # Make sure this works if the user uses the axis keywords
162
+ # to apply the norm to the transpose.
163
+ if ord == 1:
164
+ if np.isfortran(a):
165
+ lange_args = '1', a
166
+ elif np.isfortran(a.T):
167
+ lange_args = 'i', a.T
168
+ elif ord == np.inf:
169
+ if np.isfortran(a):
170
+ lange_args = 'i', a
171
+ elif np.isfortran(a.T):
172
+ lange_args = '1', a.T
173
+ if lange_args:
174
+ lange = get_lapack_funcs('lange', dtype=a.dtype, ilp64='preferred')
175
+ return lange(*lange_args)
176
+
177
+ # fall back to numpy in every other case
178
+ return np.linalg.norm(a, ord=ord, axis=axis, keepdims=keepdims)
179
+
180
+
181
+ def _datacopied(arr, original):
182
+ """
183
+ Strict check for `arr` not sharing any data with `original`,
184
+ under the assumption that arr = asarray(original)
185
+
186
+ """
187
+ if arr is original:
188
+ return False
189
+ if not isinstance(original, np.ndarray) and hasattr(original, '__array__'):
190
+ return False
191
+ return arr.base is None
astra_scene_test/Scene_04/.venv/lib/python3.9/site-packages/scipy/linalg/_procrustes.py ADDED
@@ -0,0 +1,90 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """
2
+ Solve the orthogonal Procrustes problem.
3
+
4
+ """
5
+ import numpy as np
6
+ from ._decomp_svd import svd
7
+
8
+
9
+ __all__ = ['orthogonal_procrustes']
10
+
11
+
12
+ def orthogonal_procrustes(A, B, check_finite=True):
13
+ """
14
+ Compute the matrix solution of the orthogonal Procrustes problem.
15
+
16
+ Given matrices A and B of equal shape, find an orthogonal matrix R
17
+ that most closely maps A to B using the algorithm given in [1]_.
18
+
19
+ Parameters
20
+ ----------
21
+ A : (M, N) array_like
22
+ Matrix to be mapped.
23
+ B : (M, N) array_like
24
+ Target matrix.
25
+ check_finite : bool, optional
26
+ Whether to check that the input matrices contain only finite numbers.
27
+ Disabling may give a performance gain, but may result in problems
28
+ (crashes, non-termination) if the inputs do contain infinities or NaNs.
29
+
30
+ Returns
31
+ -------
32
+ R : (N, N) ndarray
33
+ The matrix solution of the orthogonal Procrustes problem.
34
+ Minimizes the Frobenius norm of ``(A @ R) - B``, subject to
35
+ ``R.T @ R = I``.
36
+ scale : float
37
+ Sum of the singular values of ``A.T @ B``.
38
+
39
+ Raises
40
+ ------
41
+ ValueError
42
+ If the input array shapes don't match or if check_finite is True and
43
+ the arrays contain Inf or NaN.
44
+
45
+ Notes
46
+ -----
47
+ Note that unlike higher level Procrustes analyses of spatial data, this
48
+ function only uses orthogonal transformations like rotations and
49
+ reflections, and it does not use scaling or translation.
50
+
51
+ .. versionadded:: 0.15.0
52
+
53
+ References
54
+ ----------
55
+ .. [1] Peter H. Schonemann, "A generalized solution of the orthogonal
56
+ Procrustes problem", Psychometrica -- Vol. 31, No. 1, March, 1966.
57
+ :doi:`10.1007/BF02289451`
58
+
59
+ Examples
60
+ --------
61
+ >>> import numpy as np
62
+ >>> from scipy.linalg import orthogonal_procrustes
63
+ >>> A = np.array([[ 2, 0, 1], [-2, 0, 0]])
64
+
65
+ Flip the order of columns and check for the anti-diagonal mapping
66
+
67
+ >>> R, sca = orthogonal_procrustes(A, np.fliplr(A))
68
+ >>> R
69
+ array([[-5.34384992e-17, 0.00000000e+00, 1.00000000e+00],
70
+ [ 0.00000000e+00, 1.00000000e+00, 0.00000000e+00],
71
+ [ 1.00000000e+00, 0.00000000e+00, -7.85941422e-17]])
72
+ >>> sca
73
+ 9.0
74
+
75
+ """
76
+ if check_finite:
77
+ A = np.asarray_chkfinite(A)
78
+ B = np.asarray_chkfinite(B)
79
+ else:
80
+ A = np.asanyarray(A)
81
+ B = np.asanyarray(B)
82
+ if A.ndim != 2:
83
+ raise ValueError('expected ndim to be 2, but observed %s' % A.ndim)
84
+ if A.shape != B.shape:
85
+ raise ValueError(f'the shapes of A and B differ ({A.shape} vs {B.shape})')
86
+ # Be clever with transposes, with the intention to save memory.
87
+ u, w, vt = svd(B.T.dot(A).T)
88
+ R = u.dot(vt)
89
+ scale = w.sum()
90
+ return R, scale
astra_scene_test/Scene_04/.venv/lib/python3.9/site-packages/scipy/linalg/_sketches.py ADDED
@@ -0,0 +1,179 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """ Sketching-based Matrix Computations """
2
+
3
+ # Author: Jordi Montes <jomsdev@gmail.com>
4
+ # August 28, 2017
5
+
6
+ import numpy as np
7
+
8
+ from scipy._lib._util import check_random_state, rng_integers
9
+ from scipy.sparse import csc_matrix
10
+
11
+ __all__ = ['clarkson_woodruff_transform']
12
+
13
+
14
+ def cwt_matrix(n_rows, n_columns, seed=None):
15
+ r"""
16
+ Generate a matrix S which represents a Clarkson-Woodruff transform.
17
+
18
+ Given the desired size of matrix, the method returns a matrix S of size
19
+ (n_rows, n_columns) where each column has all the entries set to 0
20
+ except for one position which has been randomly set to +1 or -1 with
21
+ equal probability.
22
+
23
+ Parameters
24
+ ----------
25
+ n_rows : int
26
+ Number of rows of S
27
+ n_columns : int
28
+ Number of columns of S
29
+ seed : {None, int, `numpy.random.Generator`, `numpy.random.RandomState`}, optional
30
+ If `seed` is None (or `np.random`), the `numpy.random.RandomState`
31
+ singleton is used.
32
+ If `seed` is an int, a new ``RandomState`` instance is used,
33
+ seeded with `seed`.
34
+ If `seed` is already a ``Generator`` or ``RandomState`` instance then
35
+ that instance is used.
36
+
37
+ Returns
38
+ -------
39
+ S : (n_rows, n_columns) csc_matrix
40
+ The returned matrix has ``n_columns`` nonzero entries.
41
+
42
+ Notes
43
+ -----
44
+ Given a matrix A, with probability at least 9/10,
45
+ .. math:: \|SA\| = (1 \pm \epsilon)\|A\|
46
+ Where the error epsilon is related to the size of S.
47
+ """
48
+ rng = check_random_state(seed)
49
+ rows = rng_integers(rng, 0, n_rows, n_columns)
50
+ cols = np.arange(n_columns+1)
51
+ signs = rng.choice([1, -1], n_columns)
52
+ S = csc_matrix((signs, rows, cols),shape=(n_rows, n_columns))
53
+ return S
54
+
55
+
56
+ def clarkson_woodruff_transform(input_matrix, sketch_size, seed=None):
57
+ r"""
58
+ Applies a Clarkson-Woodruff Transform/sketch to the input matrix.
59
+
60
+ Given an input_matrix ``A`` of size ``(n, d)``, compute a matrix ``A'`` of
61
+ size (sketch_size, d) so that
62
+
63
+ .. math:: \|Ax\| \approx \|A'x\|
64
+
65
+ with high probability via the Clarkson-Woodruff Transform, otherwise
66
+ known as the CountSketch matrix.
67
+
68
+ Parameters
69
+ ----------
70
+ input_matrix : array_like
71
+ Input matrix, of shape ``(n, d)``.
72
+ sketch_size : int
73
+ Number of rows for the sketch.
74
+ seed : {None, int, `numpy.random.Generator`, `numpy.random.RandomState`}, optional
75
+ If `seed` is None (or `np.random`), the `numpy.random.RandomState`
76
+ singleton is used.
77
+ If `seed` is an int, a new ``RandomState`` instance is used,
78
+ seeded with `seed`.
79
+ If `seed` is already a ``Generator`` or ``RandomState`` instance then
80
+ that instance is used.
81
+
82
+ Returns
83
+ -------
84
+ A' : array_like
85
+ Sketch of the input matrix ``A``, of size ``(sketch_size, d)``.
86
+
87
+ Notes
88
+ -----
89
+ To make the statement
90
+
91
+ .. math:: \|Ax\| \approx \|A'x\|
92
+
93
+ precise, observe the following result which is adapted from the
94
+ proof of Theorem 14 of [2]_ via Markov's Inequality. If we have
95
+ a sketch size ``sketch_size=k`` which is at least
96
+
97
+ .. math:: k \geq \frac{2}{\epsilon^2\delta}
98
+
99
+ Then for any fixed vector ``x``,
100
+
101
+ .. math:: \|Ax\| = (1\pm\epsilon)\|A'x\|
102
+
103
+ with probability at least one minus delta.
104
+
105
+ This implementation takes advantage of sparsity: computing
106
+ a sketch takes time proportional to ``A.nnz``. Data ``A`` which
107
+ is in ``scipy.sparse.csc_matrix`` format gives the quickest
108
+ computation time for sparse input.
109
+
110
+ >>> import numpy as np
111
+ >>> from scipy import linalg
112
+ >>> from scipy import sparse
113
+ >>> rng = np.random.default_rng()
114
+ >>> n_rows, n_columns, density, sketch_n_rows = 15000, 100, 0.01, 200
115
+ >>> A = sparse.rand(n_rows, n_columns, density=density, format='csc')
116
+ >>> B = sparse.rand(n_rows, n_columns, density=density, format='csr')
117
+ >>> C = sparse.rand(n_rows, n_columns, density=density, format='coo')
118
+ >>> D = rng.standard_normal((n_rows, n_columns))
119
+ >>> SA = linalg.clarkson_woodruff_transform(A, sketch_n_rows) # fastest
120
+ >>> SB = linalg.clarkson_woodruff_transform(B, sketch_n_rows) # fast
121
+ >>> SC = linalg.clarkson_woodruff_transform(C, sketch_n_rows) # slower
122
+ >>> SD = linalg.clarkson_woodruff_transform(D, sketch_n_rows) # slowest
123
+
124
+ That said, this method does perform well on dense inputs, just slower
125
+ on a relative scale.
126
+
127
+ References
128
+ ----------
129
+ .. [1] Kenneth L. Clarkson and David P. Woodruff. Low rank approximation
130
+ and regression in input sparsity time. In STOC, 2013.
131
+ .. [2] David P. Woodruff. Sketching as a tool for numerical linear algebra.
132
+ In Foundations and Trends in Theoretical Computer Science, 2014.
133
+
134
+ Examples
135
+ --------
136
+ Create a big dense matrix ``A`` for the example:
137
+
138
+ >>> import numpy as np
139
+ >>> from scipy import linalg
140
+ >>> n_rows, n_columns = 15000, 100
141
+ >>> rng = np.random.default_rng()
142
+ >>> A = rng.standard_normal((n_rows, n_columns))
143
+
144
+ Apply the transform to create a new matrix with 200 rows:
145
+
146
+ >>> sketch_n_rows = 200
147
+ >>> sketch = linalg.clarkson_woodruff_transform(A, sketch_n_rows, seed=rng)
148
+ >>> sketch.shape
149
+ (200, 100)
150
+
151
+ Now with high probability, the true norm is close to the sketched norm
152
+ in absolute value.
153
+
154
+ >>> linalg.norm(A)
155
+ 1224.2812927123198
156
+ >>> linalg.norm(sketch)
157
+ 1226.518328407333
158
+
159
+ Similarly, applying our sketch preserves the solution to a linear
160
+ regression of :math:`\min \|Ax - b\|`.
161
+
162
+ >>> b = rng.standard_normal(n_rows)
163
+ >>> x = linalg.lstsq(A, b)[0]
164
+ >>> Ab = np.hstack((A, b.reshape(-1, 1)))
165
+ >>> SAb = linalg.clarkson_woodruff_transform(Ab, sketch_n_rows, seed=rng)
166
+ >>> SA, Sb = SAb[:, :-1], SAb[:, -1]
167
+ >>> x_sketched = linalg.lstsq(SA, Sb)[0]
168
+
169
+ As with the matrix norm example, ``linalg.norm(A @ x - b)`` is close
170
+ to ``linalg.norm(A @ x_sketched - b)`` with high probability.
171
+
172
+ >>> linalg.norm(A @ x - b)
173
+ 122.83242365433877
174
+ >>> linalg.norm(A @ x_sketched - b)
175
+ 166.58473879945151
176
+
177
+ """
178
+ S = cwt_matrix(sketch_size, input_matrix.shape[0], seed)
179
+ return S.dot(input_matrix)
astra_scene_test/Scene_04/.venv/lib/python3.9/site-packages/scipy/linalg/_solvers.py ADDED
@@ -0,0 +1,846 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """Matrix equation solver routines"""
2
+ # Author: Jeffrey Armstrong <jeff@approximatrix.com>
3
+ # February 24, 2012
4
+
5
+ # Modified: Chad Fulton <ChadFulton@gmail.com>
6
+ # June 19, 2014
7
+
8
+ # Modified: Ilhan Polat <ilhanpolat@gmail.com>
9
+ # September 13, 2016
10
+
11
+ import warnings
12
+ import numpy as np
13
+ from numpy.linalg import inv, LinAlgError, norm, cond, svd
14
+
15
+ from ._basic import solve, solve_triangular, matrix_balance
16
+ from .lapack import get_lapack_funcs
17
+ from ._decomp_schur import schur
18
+ from ._decomp_lu import lu
19
+ from ._decomp_qr import qr
20
+ from ._decomp_qz import ordqz
21
+ from ._decomp import _asarray_validated
22
+ from ._special_matrices import kron, block_diag
23
+
24
+ __all__ = ['solve_sylvester',
25
+ 'solve_continuous_lyapunov', 'solve_discrete_lyapunov',
26
+ 'solve_lyapunov',
27
+ 'solve_continuous_are', 'solve_discrete_are']
28
+
29
+
30
+ def solve_sylvester(a, b, q):
31
+ """
32
+ Computes a solution (X) to the Sylvester equation :math:`AX + XB = Q`.
33
+
34
+ Parameters
35
+ ----------
36
+ a : (M, M) array_like
37
+ Leading matrix of the Sylvester equation
38
+ b : (N, N) array_like
39
+ Trailing matrix of the Sylvester equation
40
+ q : (M, N) array_like
41
+ Right-hand side
42
+
43
+ Returns
44
+ -------
45
+ x : (M, N) ndarray
46
+ The solution to the Sylvester equation.
47
+
48
+ Raises
49
+ ------
50
+ LinAlgError
51
+ If solution was not found
52
+
53
+ Notes
54
+ -----
55
+ Computes a solution to the Sylvester matrix equation via the Bartels-
56
+ Stewart algorithm. The A and B matrices first undergo Schur
57
+ decompositions. The resulting matrices are used to construct an
58
+ alternative Sylvester equation (``RY + YS^T = F``) where the R and S
59
+ matrices are in quasi-triangular form (or, when R, S or F are complex,
60
+ triangular form). The simplified equation is then solved using
61
+ ``*TRSYL`` from LAPACK directly.
62
+
63
+ .. versionadded:: 0.11.0
64
+
65
+ Examples
66
+ --------
67
+ Given `a`, `b`, and `q` solve for `x`:
68
+
69
+ >>> import numpy as np
70
+ >>> from scipy import linalg
71
+ >>> a = np.array([[-3, -2, 0], [-1, -1, 3], [3, -5, -1]])
72
+ >>> b = np.array([[1]])
73
+ >>> q = np.array([[1],[2],[3]])
74
+ >>> x = linalg.solve_sylvester(a, b, q)
75
+ >>> x
76
+ array([[ 0.0625],
77
+ [-0.5625],
78
+ [ 0.6875]])
79
+ >>> np.allclose(a.dot(x) + x.dot(b), q)
80
+ True
81
+
82
+ """
83
+
84
+ # Compute the Schur decomposition form of a
85
+ r, u = schur(a, output='real')
86
+
87
+ # Compute the Schur decomposition of b
88
+ s, v = schur(b.conj().transpose(), output='real')
89
+
90
+ # Construct f = u'*q*v
91
+ f = np.dot(np.dot(u.conj().transpose(), q), v)
92
+
93
+ # Call the Sylvester equation solver
94
+ trsyl, = get_lapack_funcs(('trsyl',), (r, s, f))
95
+ if trsyl is None:
96
+ raise RuntimeError('LAPACK implementation does not contain a proper '
97
+ 'Sylvester equation solver (TRSYL)')
98
+ y, scale, info = trsyl(r, s, f, tranb='C')
99
+
100
+ y = scale*y
101
+
102
+ if info < 0:
103
+ raise LinAlgError("Illegal value encountered in "
104
+ "the %d term" % (-info,))
105
+
106
+ return np.dot(np.dot(u, y), v.conj().transpose())
107
+
108
+
109
+ def solve_continuous_lyapunov(a, q):
110
+ """
111
+ Solves the continuous Lyapunov equation :math:`AX + XA^H = Q`.
112
+
113
+ Uses the Bartels-Stewart algorithm to find :math:`X`.
114
+
115
+ Parameters
116
+ ----------
117
+ a : array_like
118
+ A square matrix
119
+
120
+ q : array_like
121
+ Right-hand side square matrix
122
+
123
+ Returns
124
+ -------
125
+ x : ndarray
126
+ Solution to the continuous Lyapunov equation
127
+
128
+ See Also
129
+ --------
130
+ solve_discrete_lyapunov : computes the solution to the discrete-time
131
+ Lyapunov equation
132
+ solve_sylvester : computes the solution to the Sylvester equation
133
+
134
+ Notes
135
+ -----
136
+ The continuous Lyapunov equation is a special form of the Sylvester
137
+ equation, hence this solver relies on LAPACK routine ?TRSYL.
138
+
139
+ .. versionadded:: 0.11.0
140
+
141
+ Examples
142
+ --------
143
+ Given `a` and `q` solve for `x`:
144
+
145
+ >>> import numpy as np
146
+ >>> from scipy import linalg
147
+ >>> a = np.array([[-3, -2, 0], [-1, -1, 0], [0, -5, -1]])
148
+ >>> b = np.array([2, 4, -1])
149
+ >>> q = np.eye(3)
150
+ >>> x = linalg.solve_continuous_lyapunov(a, q)
151
+ >>> x
152
+ array([[ -0.75 , 0.875 , -3.75 ],
153
+ [ 0.875 , -1.375 , 5.3125],
154
+ [ -3.75 , 5.3125, -27.0625]])
155
+ >>> np.allclose(a.dot(x) + x.dot(a.T), q)
156
+ True
157
+ """
158
+
159
+ a = np.atleast_2d(_asarray_validated(a, check_finite=True))
160
+ q = np.atleast_2d(_asarray_validated(q, check_finite=True))
161
+
162
+ r_or_c = float
163
+
164
+ for ind, _ in enumerate((a, q)):
165
+ if np.iscomplexobj(_):
166
+ r_or_c = complex
167
+
168
+ if not np.equal(*_.shape):
169
+ raise ValueError("Matrix {} should be square.".format("aq"[ind]))
170
+
171
+ # Shape consistency check
172
+ if a.shape != q.shape:
173
+ raise ValueError("Matrix a and q should have the same shape.")
174
+
175
+ # Compute the Schur decomposition form of a
176
+ r, u = schur(a, output='real')
177
+
178
+ # Construct f = u'*q*u
179
+ f = u.conj().T.dot(q.dot(u))
180
+
181
+ # Call the Sylvester equation solver
182
+ trsyl = get_lapack_funcs('trsyl', (r, f))
183
+
184
+ dtype_string = 'T' if r_or_c == float else 'C'
185
+ y, scale, info = trsyl(r, r, f, tranb=dtype_string)
186
+
187
+ if info < 0:
188
+ raise ValueError('?TRSYL exited with the internal error '
189
+ f'"illegal value in argument number {-info}.". See '
190
+ 'LAPACK documentation for the ?TRSYL error codes.')
191
+ elif info == 1:
192
+ warnings.warn('Input "a" has an eigenvalue pair whose sum is '
193
+ 'very close to or exactly zero. The solution is '
194
+ 'obtained via perturbing the coefficients.',
195
+ RuntimeWarning, stacklevel=2)
196
+ y *= scale
197
+
198
+ return u.dot(y).dot(u.conj().T)
199
+
200
+
201
+ # For backwards compatibility, keep the old name
202
+ solve_lyapunov = solve_continuous_lyapunov
203
+
204
+
205
+ def _solve_discrete_lyapunov_direct(a, q):
206
+ """
207
+ Solves the discrete Lyapunov equation directly.
208
+
209
+ This function is called by the `solve_discrete_lyapunov` function with
210
+ `method=direct`. It is not supposed to be called directly.
211
+ """
212
+
213
+ lhs = kron(a, a.conj())
214
+ lhs = np.eye(lhs.shape[0]) - lhs
215
+ x = solve(lhs, q.flatten())
216
+
217
+ return np.reshape(x, q.shape)
218
+
219
+
220
+ def _solve_discrete_lyapunov_bilinear(a, q):
221
+ """
222
+ Solves the discrete Lyapunov equation using a bilinear transformation.
223
+
224
+ This function is called by the `solve_discrete_lyapunov` function with
225
+ `method=bilinear`. It is not supposed to be called directly.
226
+ """
227
+ eye = np.eye(a.shape[0])
228
+ aH = a.conj().transpose()
229
+ aHI_inv = inv(aH + eye)
230
+ b = np.dot(aH - eye, aHI_inv)
231
+ c = 2*np.dot(np.dot(inv(a + eye), q), aHI_inv)
232
+ return solve_lyapunov(b.conj().transpose(), -c)
233
+
234
+
235
+ def solve_discrete_lyapunov(a, q, method=None):
236
+ """
237
+ Solves the discrete Lyapunov equation :math:`AXA^H - X + Q = 0`.
238
+
239
+ Parameters
240
+ ----------
241
+ a, q : (M, M) array_like
242
+ Square matrices corresponding to A and Q in the equation
243
+ above respectively. Must have the same shape.
244
+
245
+ method : {'direct', 'bilinear'}, optional
246
+ Type of solver.
247
+
248
+ If not given, chosen to be ``direct`` if ``M`` is less than 10 and
249
+ ``bilinear`` otherwise.
250
+
251
+ Returns
252
+ -------
253
+ x : ndarray
254
+ Solution to the discrete Lyapunov equation
255
+
256
+ See Also
257
+ --------
258
+ solve_continuous_lyapunov : computes the solution to the continuous-time
259
+ Lyapunov equation
260
+
261
+ Notes
262
+ -----
263
+ This section describes the available solvers that can be selected by the
264
+ 'method' parameter. The default method is *direct* if ``M`` is less than 10
265
+ and ``bilinear`` otherwise.
266
+
267
+ Method *direct* uses a direct analytical solution to the discrete Lyapunov
268
+ equation. The algorithm is given in, for example, [1]_. However, it requires
269
+ the linear solution of a system with dimension :math:`M^2` so that
270
+ performance degrades rapidly for even moderately sized matrices.
271
+
272
+ Method *bilinear* uses a bilinear transformation to convert the discrete
273
+ Lyapunov equation to a continuous Lyapunov equation :math:`(BX+XB'=-C)`
274
+ where :math:`B=(A-I)(A+I)^{-1}` and
275
+ :math:`C=2(A' + I)^{-1} Q (A + I)^{-1}`. The continuous equation can be
276
+ efficiently solved since it is a special case of a Sylvester equation.
277
+ The transformation algorithm is from Popov (1964) as described in [2]_.
278
+
279
+ .. versionadded:: 0.11.0
280
+
281
+ References
282
+ ----------
283
+ .. [1] Hamilton, James D. Time Series Analysis, Princeton: Princeton
284
+ University Press, 1994. 265. Print.
285
+ http://doc1.lbfl.li/aca/FLMF037168.pdf
286
+ .. [2] Gajic, Z., and M.T.J. Qureshi. 2008.
287
+ Lyapunov Matrix Equation in System Stability and Control.
288
+ Dover Books on Engineering Series. Dover Publications.
289
+
290
+ Examples
291
+ --------
292
+ Given `a` and `q` solve for `x`:
293
+
294
+ >>> import numpy as np
295
+ >>> from scipy import linalg
296
+ >>> a = np.array([[0.2, 0.5],[0.7, -0.9]])
297
+ >>> q = np.eye(2)
298
+ >>> x = linalg.solve_discrete_lyapunov(a, q)
299
+ >>> x
300
+ array([[ 0.70872893, 1.43518822],
301
+ [ 1.43518822, -2.4266315 ]])
302
+ >>> np.allclose(a.dot(x).dot(a.T)-x, -q)
303
+ True
304
+
305
+ """
306
+ a = np.asarray(a)
307
+ q = np.asarray(q)
308
+ if method is None:
309
+ # Select automatically based on size of matrices
310
+ if a.shape[0] >= 10:
311
+ method = 'bilinear'
312
+ else:
313
+ method = 'direct'
314
+
315
+ meth = method.lower()
316
+
317
+ if meth == 'direct':
318
+ x = _solve_discrete_lyapunov_direct(a, q)
319
+ elif meth == 'bilinear':
320
+ x = _solve_discrete_lyapunov_bilinear(a, q)
321
+ else:
322
+ raise ValueError('Unknown solver %s' % method)
323
+
324
+ return x
325
+
326
+
327
+ def solve_continuous_are(a, b, q, r, e=None, s=None, balanced=True):
328
+ r"""
329
+ Solves the continuous-time algebraic Riccati equation (CARE).
330
+
331
+ The CARE is defined as
332
+
333
+ .. math::
334
+
335
+ X A + A^H X - X B R^{-1} B^H X + Q = 0
336
+
337
+ The limitations for a solution to exist are :
338
+
339
+ * All eigenvalues of :math:`A` on the right half plane, should be
340
+ controllable.
341
+
342
+ * The associated hamiltonian pencil (See Notes), should have
343
+ eigenvalues sufficiently away from the imaginary axis.
344
+
345
+ Moreover, if ``e`` or ``s`` is not precisely ``None``, then the
346
+ generalized version of CARE
347
+
348
+ .. math::
349
+
350
+ E^HXA + A^HXE - (E^HXB + S) R^{-1} (B^HXE + S^H) + Q = 0
351
+
352
+ is solved. When omitted, ``e`` is assumed to be the identity and ``s``
353
+ is assumed to be the zero matrix with sizes compatible with ``a`` and
354
+ ``b``, respectively.
355
+
356
+ Parameters
357
+ ----------
358
+ a : (M, M) array_like
359
+ Square matrix
360
+ b : (M, N) array_like
361
+ Input
362
+ q : (M, M) array_like
363
+ Input
364
+ r : (N, N) array_like
365
+ Nonsingular square matrix
366
+ e : (M, M) array_like, optional
367
+ Nonsingular square matrix
368
+ s : (M, N) array_like, optional
369
+ Input
370
+ balanced : bool, optional
371
+ The boolean that indicates whether a balancing step is performed
372
+ on the data. The default is set to True.
373
+
374
+ Returns
375
+ -------
376
+ x : (M, M) ndarray
377
+ Solution to the continuous-time algebraic Riccati equation.
378
+
379
+ Raises
380
+ ------
381
+ LinAlgError
382
+ For cases where the stable subspace of the pencil could not be
383
+ isolated. See Notes section and the references for details.
384
+
385
+ See Also
386
+ --------
387
+ solve_discrete_are : Solves the discrete-time algebraic Riccati equation
388
+
389
+ Notes
390
+ -----
391
+ The equation is solved by forming the extended hamiltonian matrix pencil,
392
+ as described in [1]_, :math:`H - \lambda J` given by the block matrices ::
393
+
394
+ [ A 0 B ] [ E 0 0 ]
395
+ [-Q -A^H -S ] - \lambda * [ 0 E^H 0 ]
396
+ [ S^H B^H R ] [ 0 0 0 ]
397
+
398
+ and using a QZ decomposition method.
399
+
400
+ In this algorithm, the fail conditions are linked to the symmetry
401
+ of the product :math:`U_2 U_1^{-1}` and condition number of
402
+ :math:`U_1`. Here, :math:`U` is the 2m-by-m matrix that holds the
403
+ eigenvectors spanning the stable subspace with 2-m rows and partitioned
404
+ into two m-row matrices. See [1]_ and [2]_ for more details.
405
+
406
+ In order to improve the QZ decomposition accuracy, the pencil goes
407
+ through a balancing step where the sum of absolute values of
408
+ :math:`H` and :math:`J` entries (after removing the diagonal entries of
409
+ the sum) is balanced following the recipe given in [3]_.
410
+
411
+ .. versionadded:: 0.11.0
412
+
413
+ References
414
+ ----------
415
+ .. [1] P. van Dooren , "A Generalized Eigenvalue Approach For Solving
416
+ Riccati Equations.", SIAM Journal on Scientific and Statistical
417
+ Computing, Vol.2(2), :doi:`10.1137/0902010`
418
+
419
+ .. [2] A.J. Laub, "A Schur Method for Solving Algebraic Riccati
420
+ Equations.", Massachusetts Institute of Technology. Laboratory for
421
+ Information and Decision Systems. LIDS-R ; 859. Available online :
422
+ http://hdl.handle.net/1721.1/1301
423
+
424
+ .. [3] P. Benner, "Symplectic Balancing of Hamiltonian Matrices", 2001,
425
+ SIAM J. Sci. Comput., 2001, Vol.22(5), :doi:`10.1137/S1064827500367993`
426
+
427
+ Examples
428
+ --------
429
+ Given `a`, `b`, `q`, and `r` solve for `x`:
430
+
431
+ >>> import numpy as np
432
+ >>> from scipy import linalg
433
+ >>> a = np.array([[4, 3], [-4.5, -3.5]])
434
+ >>> b = np.array([[1], [-1]])
435
+ >>> q = np.array([[9, 6], [6, 4.]])
436
+ >>> r = 1
437
+ >>> x = linalg.solve_continuous_are(a, b, q, r)
438
+ >>> x
439
+ array([[ 21.72792206, 14.48528137],
440
+ [ 14.48528137, 9.65685425]])
441
+ >>> np.allclose(a.T.dot(x) + x.dot(a)-x.dot(b).dot(b.T).dot(x), -q)
442
+ True
443
+
444
+ """
445
+
446
+ # Validate input arguments
447
+ a, b, q, r, e, s, m, n, r_or_c, gen_are = _are_validate_args(
448
+ a, b, q, r, e, s, 'care')
449
+
450
+ H = np.empty((2*m+n, 2*m+n), dtype=r_or_c)
451
+ H[:m, :m] = a
452
+ H[:m, m:2*m] = 0.
453
+ H[:m, 2*m:] = b
454
+ H[m:2*m, :m] = -q
455
+ H[m:2*m, m:2*m] = -a.conj().T
456
+ H[m:2*m, 2*m:] = 0. if s is None else -s
457
+ H[2*m:, :m] = 0. if s is None else s.conj().T
458
+ H[2*m:, m:2*m] = b.conj().T
459
+ H[2*m:, 2*m:] = r
460
+
461
+ if gen_are and e is not None:
462
+ J = block_diag(e, e.conj().T, np.zeros_like(r, dtype=r_or_c))
463
+ else:
464
+ J = block_diag(np.eye(2*m), np.zeros_like(r, dtype=r_or_c))
465
+
466
+ if balanced:
467
+ # xGEBAL does not remove the diagonals before scaling. Also
468
+ # to avoid destroying the Symplectic structure, we follow Ref.3
469
+ M = np.abs(H) + np.abs(J)
470
+ np.fill_diagonal(M, 0.)
471
+ _, (sca, _) = matrix_balance(M, separate=1, permute=0)
472
+ # do we need to bother?
473
+ if not np.allclose(sca, np.ones_like(sca)):
474
+ # Now impose diag(D,inv(D)) from Benner where D is
475
+ # square root of s_i/s_(n+i) for i=0,....
476
+ sca = np.log2(sca)
477
+ # NOTE: Py3 uses "Bankers Rounding: round to the nearest even" !!
478
+ s = np.round((sca[m:2*m] - sca[:m])/2)
479
+ sca = 2 ** np.r_[s, -s, sca[2*m:]]
480
+ # Elementwise multiplication via broadcasting.
481
+ elwisescale = sca[:, None] * np.reciprocal(sca)
482
+ H *= elwisescale
483
+ J *= elwisescale
484
+
485
+ # Deflate the pencil to 2m x 2m ala Ref.1, eq.(55)
486
+ q, r = qr(H[:, -n:])
487
+ H = q[:, n:].conj().T.dot(H[:, :2*m])
488
+ J = q[:2*m, n:].conj().T.dot(J[:2*m, :2*m])
489
+
490
+ # Decide on which output type is needed for QZ
491
+ out_str = 'real' if r_or_c == float else 'complex'
492
+
493
+ _, _, _, _, _, u = ordqz(H, J, sort='lhp', overwrite_a=True,
494
+ overwrite_b=True, check_finite=False,
495
+ output=out_str)
496
+
497
+ # Get the relevant parts of the stable subspace basis
498
+ if e is not None:
499
+ u, _ = qr(np.vstack((e.dot(u[:m, :m]), u[m:, :m])))
500
+ u00 = u[:m, :m]
501
+ u10 = u[m:, :m]
502
+
503
+ # Solve via back-substituion after checking the condition of u00
504
+ up, ul, uu = lu(u00)
505
+ if 1/cond(uu) < np.spacing(1.):
506
+ raise LinAlgError('Failed to find a finite solution.')
507
+
508
+ # Exploit the triangular structure
509
+ x = solve_triangular(ul.conj().T,
510
+ solve_triangular(uu.conj().T,
511
+ u10.conj().T,
512
+ lower=True),
513
+ unit_diagonal=True,
514
+ ).conj().T.dot(up.conj().T)
515
+ if balanced:
516
+ x *= sca[:m, None] * sca[:m]
517
+
518
+ # Check the deviation from symmetry for lack of success
519
+ # See proof of Thm.5 item 3 in [2]
520
+ u_sym = u00.conj().T.dot(u10)
521
+ n_u_sym = norm(u_sym, 1)
522
+ u_sym = u_sym - u_sym.conj().T
523
+ sym_threshold = np.max([np.spacing(1000.), 0.1*n_u_sym])
524
+
525
+ if norm(u_sym, 1) > sym_threshold:
526
+ raise LinAlgError('The associated Hamiltonian pencil has eigenvalues '
527
+ 'too close to the imaginary axis')
528
+
529
+ return (x + x.conj().T)/2
530
+
531
+
532
+ def solve_discrete_are(a, b, q, r, e=None, s=None, balanced=True):
533
+ r"""
534
+ Solves the discrete-time algebraic Riccati equation (DARE).
535
+
536
+ The DARE is defined as
537
+
538
+ .. math::
539
+
540
+ A^HXA - X - (A^HXB) (R + B^HXB)^{-1} (B^HXA) + Q = 0
541
+
542
+ The limitations for a solution to exist are :
543
+
544
+ * All eigenvalues of :math:`A` outside the unit disc, should be
545
+ controllable.
546
+
547
+ * The associated symplectic pencil (See Notes), should have
548
+ eigenvalues sufficiently away from the unit circle.
549
+
550
+ Moreover, if ``e`` and ``s`` are not both precisely ``None``, then the
551
+ generalized version of DARE
552
+
553
+ .. math::
554
+
555
+ A^HXA - E^HXE - (A^HXB+S) (R+B^HXB)^{-1} (B^HXA+S^H) + Q = 0
556
+
557
+ is solved. When omitted, ``e`` is assumed to be the identity and ``s``
558
+ is assumed to be the zero matrix.
559
+
560
+ Parameters
561
+ ----------
562
+ a : (M, M) array_like
563
+ Square matrix
564
+ b : (M, N) array_like
565
+ Input
566
+ q : (M, M) array_like
567
+ Input
568
+ r : (N, N) array_like
569
+ Square matrix
570
+ e : (M, M) array_like, optional
571
+ Nonsingular square matrix
572
+ s : (M, N) array_like, optional
573
+ Input
574
+ balanced : bool
575
+ The boolean that indicates whether a balancing step is performed
576
+ on the data. The default is set to True.
577
+
578
+ Returns
579
+ -------
580
+ x : (M, M) ndarray
581
+ Solution to the discrete algebraic Riccati equation.
582
+
583
+ Raises
584
+ ------
585
+ LinAlgError
586
+ For cases where the stable subspace of the pencil could not be
587
+ isolated. See Notes section and the references for details.
588
+
589
+ See Also
590
+ --------
591
+ solve_continuous_are : Solves the continuous algebraic Riccati equation
592
+
593
+ Notes
594
+ -----
595
+ The equation is solved by forming the extended symplectic matrix pencil,
596
+ as described in [1]_, :math:`H - \lambda J` given by the block matrices ::
597
+
598
+ [ A 0 B ] [ E 0 B ]
599
+ [ -Q E^H -S ] - \lambda * [ 0 A^H 0 ]
600
+ [ S^H 0 R ] [ 0 -B^H 0 ]
601
+
602
+ and using a QZ decomposition method.
603
+
604
+ In this algorithm, the fail conditions are linked to the symmetry
605
+ of the product :math:`U_2 U_1^{-1}` and condition number of
606
+ :math:`U_1`. Here, :math:`U` is the 2m-by-m matrix that holds the
607
+ eigenvectors spanning the stable subspace with 2-m rows and partitioned
608
+ into two m-row matrices. See [1]_ and [2]_ for more details.
609
+
610
+ In order to improve the QZ decomposition accuracy, the pencil goes
611
+ through a balancing step where the sum of absolute values of
612
+ :math:`H` and :math:`J` rows/cols (after removing the diagonal entries)
613
+ is balanced following the recipe given in [3]_. If the data has small
614
+ numerical noise, balancing may amplify their effects and some clean up
615
+ is required.
616
+
617
+ .. versionadded:: 0.11.0
618
+
619
+ References
620
+ ----------
621
+ .. [1] P. van Dooren , "A Generalized Eigenvalue Approach For Solving
622
+ Riccati Equations.", SIAM Journal on Scientific and Statistical
623
+ Computing, Vol.2(2), :doi:`10.1137/0902010`
624
+
625
+ .. [2] A.J. Laub, "A Schur Method for Solving Algebraic Riccati
626
+ Equations.", Massachusetts Institute of Technology. Laboratory for
627
+ Information and Decision Systems. LIDS-R ; 859. Available online :
628
+ http://hdl.handle.net/1721.1/1301
629
+
630
+ .. [3] P. Benner, "Symplectic Balancing of Hamiltonian Matrices", 2001,
631
+ SIAM J. Sci. Comput., 2001, Vol.22(5), :doi:`10.1137/S1064827500367993`
632
+
633
+ Examples
634
+ --------
635
+ Given `a`, `b`, `q`, and `r` solve for `x`:
636
+
637
+ >>> import numpy as np
638
+ >>> from scipy import linalg as la
639
+ >>> a = np.array([[0, 1], [0, -1]])
640
+ >>> b = np.array([[1, 0], [2, 1]])
641
+ >>> q = np.array([[-4, -4], [-4, 7]])
642
+ >>> r = np.array([[9, 3], [3, 1]])
643
+ >>> x = la.solve_discrete_are(a, b, q, r)
644
+ >>> x
645
+ array([[-4., -4.],
646
+ [-4., 7.]])
647
+ >>> R = la.solve(r + b.T.dot(x).dot(b), b.T.dot(x).dot(a))
648
+ >>> np.allclose(a.T.dot(x).dot(a) - x - a.T.dot(x).dot(b).dot(R), -q)
649
+ True
650
+
651
+ """
652
+
653
+ # Validate input arguments
654
+ a, b, q, r, e, s, m, n, r_or_c, gen_are = _are_validate_args(
655
+ a, b, q, r, e, s, 'dare')
656
+
657
+ # Form the matrix pencil
658
+ H = np.zeros((2*m+n, 2*m+n), dtype=r_or_c)
659
+ H[:m, :m] = a
660
+ H[:m, 2*m:] = b
661
+ H[m:2*m, :m] = -q
662
+ H[m:2*m, m:2*m] = np.eye(m) if e is None else e.conj().T
663
+ H[m:2*m, 2*m:] = 0. if s is None else -s
664
+ H[2*m:, :m] = 0. if s is None else s.conj().T
665
+ H[2*m:, 2*m:] = r
666
+
667
+ J = np.zeros_like(H, dtype=r_or_c)
668
+ J[:m, :m] = np.eye(m) if e is None else e
669
+ J[m:2*m, m:2*m] = a.conj().T
670
+ J[2*m:, m:2*m] = -b.conj().T
671
+
672
+ if balanced:
673
+ # xGEBAL does not remove the diagonals before scaling. Also
674
+ # to avoid destroying the Symplectic structure, we follow Ref.3
675
+ M = np.abs(H) + np.abs(J)
676
+ np.fill_diagonal(M, 0.)
677
+ _, (sca, _) = matrix_balance(M, separate=1, permute=0)
678
+ # do we need to bother?
679
+ if not np.allclose(sca, np.ones_like(sca)):
680
+ # Now impose diag(D,inv(D)) from Benner where D is
681
+ # square root of s_i/s_(n+i) for i=0,....
682
+ sca = np.log2(sca)
683
+ # NOTE: Py3 uses "Bankers Rounding: round to the nearest even" !!
684
+ s = np.round((sca[m:2*m] - sca[:m])/2)
685
+ sca = 2 ** np.r_[s, -s, sca[2*m:]]
686
+ # Elementwise multiplication via broadcasting.
687
+ elwisescale = sca[:, None] * np.reciprocal(sca)
688
+ H *= elwisescale
689
+ J *= elwisescale
690
+
691
+ # Deflate the pencil by the R column ala Ref.1
692
+ q_of_qr, _ = qr(H[:, -n:])
693
+ H = q_of_qr[:, n:].conj().T.dot(H[:, :2*m])
694
+ J = q_of_qr[:, n:].conj().T.dot(J[:, :2*m])
695
+
696
+ # Decide on which output type is needed for QZ
697
+ out_str = 'real' if r_or_c == float else 'complex'
698
+
699
+ _, _, _, _, _, u = ordqz(H, J, sort='iuc',
700
+ overwrite_a=True,
701
+ overwrite_b=True,
702
+ check_finite=False,
703
+ output=out_str)
704
+
705
+ # Get the relevant parts of the stable subspace basis
706
+ if e is not None:
707
+ u, _ = qr(np.vstack((e.dot(u[:m, :m]), u[m:, :m])))
708
+ u00 = u[:m, :m]
709
+ u10 = u[m:, :m]
710
+
711
+ # Solve via back-substituion after checking the condition of u00
712
+ up, ul, uu = lu(u00)
713
+
714
+ if 1/cond(uu) < np.spacing(1.):
715
+ raise LinAlgError('Failed to find a finite solution.')
716
+
717
+ # Exploit the triangular structure
718
+ x = solve_triangular(ul.conj().T,
719
+ solve_triangular(uu.conj().T,
720
+ u10.conj().T,
721
+ lower=True),
722
+ unit_diagonal=True,
723
+ ).conj().T.dot(up.conj().T)
724
+ if balanced:
725
+ x *= sca[:m, None] * sca[:m]
726
+
727
+ # Check the deviation from symmetry for lack of success
728
+ # See proof of Thm.5 item 3 in [2]
729
+ u_sym = u00.conj().T.dot(u10)
730
+ n_u_sym = norm(u_sym, 1)
731
+ u_sym = u_sym - u_sym.conj().T
732
+ sym_threshold = np.max([np.spacing(1000.), 0.1*n_u_sym])
733
+
734
+ if norm(u_sym, 1) > sym_threshold:
735
+ raise LinAlgError('The associated symplectic pencil has eigenvalues '
736
+ 'too close to the unit circle')
737
+
738
+ return (x + x.conj().T)/2
739
+
740
+
741
+ def _are_validate_args(a, b, q, r, e, s, eq_type='care'):
742
+ """
743
+ A helper function to validate the arguments supplied to the
744
+ Riccati equation solvers. Any discrepancy found in the input
745
+ matrices leads to a ``ValueError`` exception.
746
+
747
+ Essentially, it performs:
748
+
749
+ - a check whether the input is free of NaN and Infs
750
+ - a pass for the data through ``numpy.atleast_2d()``
751
+ - squareness check of the relevant arrays
752
+ - shape consistency check of the arrays
753
+ - singularity check of the relevant arrays
754
+ - symmetricity check of the relevant matrices
755
+ - a check whether the regular or the generalized version is asked.
756
+
757
+ This function is used by ``solve_continuous_are`` and
758
+ ``solve_discrete_are``.
759
+
760
+ Parameters
761
+ ----------
762
+ a, b, q, r, e, s : array_like
763
+ Input data
764
+ eq_type : str
765
+ Accepted arguments are 'care' and 'dare'.
766
+
767
+ Returns
768
+ -------
769
+ a, b, q, r, e, s : ndarray
770
+ Regularized input data
771
+ m, n : int
772
+ shape of the problem
773
+ r_or_c : type
774
+ Data type of the problem, returns float or complex
775
+ gen_or_not : bool
776
+ Type of the equation, True for generalized and False for regular ARE.
777
+
778
+ """
779
+
780
+ if eq_type.lower() not in ("dare", "care"):
781
+ raise ValueError("Equation type unknown. "
782
+ "Only 'care' and 'dare' is understood")
783
+
784
+ a = np.atleast_2d(_asarray_validated(a, check_finite=True))
785
+ b = np.atleast_2d(_asarray_validated(b, check_finite=True))
786
+ q = np.atleast_2d(_asarray_validated(q, check_finite=True))
787
+ r = np.atleast_2d(_asarray_validated(r, check_finite=True))
788
+
789
+ # Get the correct data types otherwise NumPy complains
790
+ # about pushing complex numbers into real arrays.
791
+ r_or_c = complex if np.iscomplexobj(b) else float
792
+
793
+ for ind, mat in enumerate((a, q, r)):
794
+ if np.iscomplexobj(mat):
795
+ r_or_c = complex
796
+
797
+ if not np.equal(*mat.shape):
798
+ raise ValueError("Matrix {} should be square.".format("aqr"[ind]))
799
+
800
+ # Shape consistency checks
801
+ m, n = b.shape
802
+ if m != a.shape[0]:
803
+ raise ValueError("Matrix a and b should have the same number of rows.")
804
+ if m != q.shape[0]:
805
+ raise ValueError("Matrix a and q should have the same shape.")
806
+ if n != r.shape[0]:
807
+ raise ValueError("Matrix b and r should have the same number of cols.")
808
+
809
+ # Check if the data matrices q, r are (sufficiently) hermitian
810
+ for ind, mat in enumerate((q, r)):
811
+ if norm(mat - mat.conj().T, 1) > np.spacing(norm(mat, 1))*100:
812
+ raise ValueError("Matrix {} should be symmetric/hermitian."
813
+ "".format("qr"[ind]))
814
+
815
+ # Continuous time ARE should have a nonsingular r matrix.
816
+ if eq_type == 'care':
817
+ min_sv = svd(r, compute_uv=False)[-1]
818
+ if min_sv == 0. or min_sv < np.spacing(1.)*norm(r, 1):
819
+ raise ValueError('Matrix r is numerically singular.')
820
+
821
+ # Check if the generalized case is required with omitted arguments
822
+ # perform late shape checking etc.
823
+ generalized_case = e is not None or s is not None
824
+
825
+ if generalized_case:
826
+ if e is not None:
827
+ e = np.atleast_2d(_asarray_validated(e, check_finite=True))
828
+ if not np.equal(*e.shape):
829
+ raise ValueError("Matrix e should be square.")
830
+ if m != e.shape[0]:
831
+ raise ValueError("Matrix a and e should have the same shape.")
832
+ # numpy.linalg.cond doesn't check for exact zeros and
833
+ # emits a runtime warning. Hence the following manual check.
834
+ min_sv = svd(e, compute_uv=False)[-1]
835
+ if min_sv == 0. or min_sv < np.spacing(1.) * norm(e, 1):
836
+ raise ValueError('Matrix e is numerically singular.')
837
+ if np.iscomplexobj(e):
838
+ r_or_c = complex
839
+ if s is not None:
840
+ s = np.atleast_2d(_asarray_validated(s, check_finite=True))
841
+ if s.shape != b.shape:
842
+ raise ValueError("Matrix b and s should have the same shape.")
843
+ if np.iscomplexobj(s):
844
+ r_or_c = complex
845
+
846
+ return a, b, q, r, e, s, m, n, r_or_c, generalized_case
astra_scene_test/Scene_04/.venv/lib/python3.9/site-packages/scipy/linalg/_special_matrices.py ADDED
@@ -0,0 +1,1257 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import math
2
+
3
+ import numpy as np
4
+ from numpy.lib.stride_tricks import as_strided
5
+
6
+ __all__ = ['toeplitz', 'circulant', 'hankel',
7
+ 'hadamard', 'leslie', 'kron', 'block_diag', 'companion',
8
+ 'helmert', 'hilbert', 'invhilbert', 'pascal', 'invpascal', 'dft',
9
+ 'fiedler', 'fiedler_companion', 'convolution_matrix']
10
+
11
+
12
+ # -----------------------------------------------------------------------------
13
+ # matrix construction functions
14
+ # -----------------------------------------------------------------------------
15
+
16
+
17
+ def toeplitz(c, r=None):
18
+ """
19
+ Construct a Toeplitz matrix.
20
+
21
+ The Toeplitz matrix has constant diagonals, with c as its first column
22
+ and r as its first row. If r is not given, ``r == conjugate(c)`` is
23
+ assumed.
24
+
25
+ Parameters
26
+ ----------
27
+ c : array_like
28
+ First column of the matrix. Whatever the actual shape of `c`, it
29
+ will be converted to a 1-D array.
30
+ r : array_like, optional
31
+ First row of the matrix. If None, ``r = conjugate(c)`` is assumed;
32
+ in this case, if c[0] is real, the result is a Hermitian matrix.
33
+ r[0] is ignored; the first row of the returned matrix is
34
+ ``[c[0], r[1:]]``. Whatever the actual shape of `r`, it will be
35
+ converted to a 1-D array.
36
+
37
+ Returns
38
+ -------
39
+ A : (len(c), len(r)) ndarray
40
+ The Toeplitz matrix. Dtype is the same as ``(c[0] + r[0]).dtype``.
41
+
42
+ See Also
43
+ --------
44
+ circulant : circulant matrix
45
+ hankel : Hankel matrix
46
+ solve_toeplitz : Solve a Toeplitz system.
47
+
48
+ Notes
49
+ -----
50
+ The behavior when `c` or `r` is a scalar, or when `c` is complex and
51
+ `r` is None, was changed in version 0.8.0. The behavior in previous
52
+ versions was undocumented and is no longer supported.
53
+
54
+ Examples
55
+ --------
56
+ >>> from scipy.linalg import toeplitz
57
+ >>> toeplitz([1,2,3], [1,4,5,6])
58
+ array([[1, 4, 5, 6],
59
+ [2, 1, 4, 5],
60
+ [3, 2, 1, 4]])
61
+ >>> toeplitz([1.0, 2+3j, 4-1j])
62
+ array([[ 1.+0.j, 2.-3.j, 4.+1.j],
63
+ [ 2.+3.j, 1.+0.j, 2.-3.j],
64
+ [ 4.-1.j, 2.+3.j, 1.+0.j]])
65
+
66
+ """
67
+ c = np.asarray(c).ravel()
68
+ if r is None:
69
+ r = c.conjugate()
70
+ else:
71
+ r = np.asarray(r).ravel()
72
+ # Form a 1-D array containing a reversed c followed by r[1:] that could be
73
+ # strided to give us toeplitz matrix.
74
+ vals = np.concatenate((c[::-1], r[1:]))
75
+ out_shp = len(c), len(r)
76
+ n = vals.strides[0]
77
+ return as_strided(vals[len(c)-1:], shape=out_shp, strides=(-n, n)).copy()
78
+
79
+
80
+ def circulant(c):
81
+ """
82
+ Construct a circulant matrix.
83
+
84
+ Parameters
85
+ ----------
86
+ c : (N,) array_like
87
+ 1-D array, the first column of the matrix.
88
+
89
+ Returns
90
+ -------
91
+ A : (N, N) ndarray
92
+ A circulant matrix whose first column is `c`.
93
+
94
+ See Also
95
+ --------
96
+ toeplitz : Toeplitz matrix
97
+ hankel : Hankel matrix
98
+ solve_circulant : Solve a circulant system.
99
+
100
+ Notes
101
+ -----
102
+ .. versionadded:: 0.8.0
103
+
104
+ Examples
105
+ --------
106
+ >>> from scipy.linalg import circulant
107
+ >>> circulant([1, 2, 3])
108
+ array([[1, 3, 2],
109
+ [2, 1, 3],
110
+ [3, 2, 1]])
111
+
112
+ """
113
+ c = np.asarray(c).ravel()
114
+ # Form an extended array that could be strided to give circulant version
115
+ c_ext = np.concatenate((c[::-1], c[:0:-1]))
116
+ L = len(c)
117
+ n = c_ext.strides[0]
118
+ return as_strided(c_ext[L-1:], shape=(L, L), strides=(-n, n)).copy()
119
+
120
+
121
+ def hankel(c, r=None):
122
+ """
123
+ Construct a Hankel matrix.
124
+
125
+ The Hankel matrix has constant anti-diagonals, with `c` as its
126
+ first column and `r` as its last row. If `r` is not given, then
127
+ `r = zeros_like(c)` is assumed.
128
+
129
+ Parameters
130
+ ----------
131
+ c : array_like
132
+ First column of the matrix. Whatever the actual shape of `c`, it
133
+ will be converted to a 1-D array.
134
+ r : array_like, optional
135
+ Last row of the matrix. If None, ``r = zeros_like(c)`` is assumed.
136
+ r[0] is ignored; the last row of the returned matrix is
137
+ ``[c[-1], r[1:]]``. Whatever the actual shape of `r`, it will be
138
+ converted to a 1-D array.
139
+
140
+ Returns
141
+ -------
142
+ A : (len(c), len(r)) ndarray
143
+ The Hankel matrix. Dtype is the same as ``(c[0] + r[0]).dtype``.
144
+
145
+ See Also
146
+ --------
147
+ toeplitz : Toeplitz matrix
148
+ circulant : circulant matrix
149
+
150
+ Examples
151
+ --------
152
+ >>> from scipy.linalg import hankel
153
+ >>> hankel([1, 17, 99])
154
+ array([[ 1, 17, 99],
155
+ [17, 99, 0],
156
+ [99, 0, 0]])
157
+ >>> hankel([1,2,3,4], [4,7,7,8,9])
158
+ array([[1, 2, 3, 4, 7],
159
+ [2, 3, 4, 7, 7],
160
+ [3, 4, 7, 7, 8],
161
+ [4, 7, 7, 8, 9]])
162
+
163
+ """
164
+ c = np.asarray(c).ravel()
165
+ if r is None:
166
+ r = np.zeros_like(c)
167
+ else:
168
+ r = np.asarray(r).ravel()
169
+ # Form a 1-D array of values to be used in the matrix, containing `c`
170
+ # followed by r[1:].
171
+ vals = np.concatenate((c, r[1:]))
172
+ # Stride on concatenated array to get hankel matrix
173
+ out_shp = len(c), len(r)
174
+ n = vals.strides[0]
175
+ return as_strided(vals, shape=out_shp, strides=(n, n)).copy()
176
+
177
+
178
+ def hadamard(n, dtype=int):
179
+ """
180
+ Construct an Hadamard matrix.
181
+
182
+ Constructs an n-by-n Hadamard matrix, using Sylvester's
183
+ construction. `n` must be a power of 2.
184
+
185
+ Parameters
186
+ ----------
187
+ n : int
188
+ The order of the matrix. `n` must be a power of 2.
189
+ dtype : dtype, optional
190
+ The data type of the array to be constructed.
191
+
192
+ Returns
193
+ -------
194
+ H : (n, n) ndarray
195
+ The Hadamard matrix.
196
+
197
+ Notes
198
+ -----
199
+ .. versionadded:: 0.8.0
200
+
201
+ Examples
202
+ --------
203
+ >>> from scipy.linalg import hadamard
204
+ >>> hadamard(2, dtype=complex)
205
+ array([[ 1.+0.j, 1.+0.j],
206
+ [ 1.+0.j, -1.-0.j]])
207
+ >>> hadamard(4)
208
+ array([[ 1, 1, 1, 1],
209
+ [ 1, -1, 1, -1],
210
+ [ 1, 1, -1, -1],
211
+ [ 1, -1, -1, 1]])
212
+
213
+ """
214
+
215
+ # This function is a slightly modified version of the
216
+ # function contributed by Ivo in ticket #675.
217
+
218
+ if n < 1:
219
+ lg2 = 0
220
+ else:
221
+ lg2 = int(math.log(n, 2))
222
+ if 2 ** lg2 != n:
223
+ raise ValueError("n must be an positive integer, and n must be "
224
+ "a power of 2")
225
+
226
+ H = np.array([[1]], dtype=dtype)
227
+
228
+ # Sylvester's construction
229
+ for i in range(0, lg2):
230
+ H = np.vstack((np.hstack((H, H)), np.hstack((H, -H))))
231
+
232
+ return H
233
+
234
+
235
+ def leslie(f, s):
236
+ """
237
+ Create a Leslie matrix.
238
+
239
+ Given the length n array of fecundity coefficients `f` and the length
240
+ n-1 array of survival coefficients `s`, return the associated Leslie
241
+ matrix.
242
+
243
+ Parameters
244
+ ----------
245
+ f : (N,) array_like
246
+ The "fecundity" coefficients.
247
+ s : (N-1,) array_like
248
+ The "survival" coefficients, has to be 1-D. The length of `s`
249
+ must be one less than the length of `f`, and it must be at least 1.
250
+
251
+ Returns
252
+ -------
253
+ L : (N, N) ndarray
254
+ The array is zero except for the first row,
255
+ which is `f`, and the first sub-diagonal, which is `s`.
256
+ The data-type of the array will be the data-type of ``f[0]+s[0]``.
257
+
258
+ Notes
259
+ -----
260
+ .. versionadded:: 0.8.0
261
+
262
+ The Leslie matrix is used to model discrete-time, age-structured
263
+ population growth [1]_ [2]_. In a population with `n` age classes, two sets
264
+ of parameters define a Leslie matrix: the `n` "fecundity coefficients",
265
+ which give the number of offspring per-capita produced by each age
266
+ class, and the `n` - 1 "survival coefficients", which give the
267
+ per-capita survival rate of each age class.
268
+
269
+ References
270
+ ----------
271
+ .. [1] P. H. Leslie, On the use of matrices in certain population
272
+ mathematics, Biometrika, Vol. 33, No. 3, 183--212 (Nov. 1945)
273
+ .. [2] P. H. Leslie, Some further notes on the use of matrices in
274
+ population mathematics, Biometrika, Vol. 35, No. 3/4, 213--245
275
+ (Dec. 1948)
276
+
277
+ Examples
278
+ --------
279
+ >>> from scipy.linalg import leslie
280
+ >>> leslie([0.1, 2.0, 1.0, 0.1], [0.2, 0.8, 0.7])
281
+ array([[ 0.1, 2. , 1. , 0.1],
282
+ [ 0.2, 0. , 0. , 0. ],
283
+ [ 0. , 0.8, 0. , 0. ],
284
+ [ 0. , 0. , 0.7, 0. ]])
285
+
286
+ """
287
+ f = np.atleast_1d(f)
288
+ s = np.atleast_1d(s)
289
+ if f.ndim != 1:
290
+ raise ValueError("Incorrect shape for f. f must be 1D")
291
+ if s.ndim != 1:
292
+ raise ValueError("Incorrect shape for s. s must be 1D")
293
+ if f.size != s.size + 1:
294
+ raise ValueError("Incorrect lengths for f and s. The length"
295
+ " of s must be one less than the length of f.")
296
+ if s.size == 0:
297
+ raise ValueError("The length of s must be at least 1.")
298
+
299
+ tmp = f[0] + s[0]
300
+ n = f.size
301
+ a = np.zeros((n, n), dtype=tmp.dtype)
302
+ a[0] = f
303
+ a[list(range(1, n)), list(range(0, n - 1))] = s
304
+ return a
305
+
306
+
307
+ def kron(a, b):
308
+ """
309
+ Kronecker product.
310
+
311
+ The result is the block matrix::
312
+
313
+ a[0,0]*b a[0,1]*b ... a[0,-1]*b
314
+ a[1,0]*b a[1,1]*b ... a[1,-1]*b
315
+ ...
316
+ a[-1,0]*b a[-1,1]*b ... a[-1,-1]*b
317
+
318
+ Parameters
319
+ ----------
320
+ a : (M, N) ndarray
321
+ Input array
322
+ b : (P, Q) ndarray
323
+ Input array
324
+
325
+ Returns
326
+ -------
327
+ A : (M*P, N*Q) ndarray
328
+ Kronecker product of `a` and `b`.
329
+
330
+ Examples
331
+ --------
332
+ >>> from numpy import array
333
+ >>> from scipy.linalg import kron
334
+ >>> kron(array([[1,2],[3,4]]), array([[1,1,1]]))
335
+ array([[1, 1, 1, 2, 2, 2],
336
+ [3, 3, 3, 4, 4, 4]])
337
+
338
+ """
339
+ if not a.flags['CONTIGUOUS']:
340
+ a = np.reshape(a, a.shape)
341
+ if not b.flags['CONTIGUOUS']:
342
+ b = np.reshape(b, b.shape)
343
+ o = np.outer(a, b)
344
+ o = o.reshape(a.shape + b.shape)
345
+ return np.concatenate(np.concatenate(o, axis=1), axis=1)
346
+
347
+
348
+ def block_diag(*arrs):
349
+ """
350
+ Create a block diagonal matrix from provided arrays.
351
+
352
+ Given the inputs `A`, `B` and `C`, the output will have these
353
+ arrays arranged on the diagonal::
354
+
355
+ [[A, 0, 0],
356
+ [0, B, 0],
357
+ [0, 0, C]]
358
+
359
+ Parameters
360
+ ----------
361
+ A, B, C, ... : array_like, up to 2-D
362
+ Input arrays. A 1-D array or array_like sequence of length `n` is
363
+ treated as a 2-D array with shape ``(1,n)``.
364
+
365
+ Returns
366
+ -------
367
+ D : ndarray
368
+ Array with `A`, `B`, `C`, ... on the diagonal. `D` has the
369
+ same dtype as `A`.
370
+
371
+ Notes
372
+ -----
373
+ If all the input arrays are square, the output is known as a
374
+ block diagonal matrix.
375
+
376
+ Empty sequences (i.e., array-likes of zero size) will not be ignored.
377
+ Noteworthy, both [] and [[]] are treated as matrices with shape ``(1,0)``.
378
+
379
+ Examples
380
+ --------
381
+ >>> import numpy as np
382
+ >>> from scipy.linalg import block_diag
383
+ >>> A = [[1, 0],
384
+ ... [0, 1]]
385
+ >>> B = [[3, 4, 5],
386
+ ... [6, 7, 8]]
387
+ >>> C = [[7]]
388
+ >>> P = np.zeros((2, 0), dtype='int32')
389
+ >>> block_diag(A, B, C)
390
+ array([[1, 0, 0, 0, 0, 0],
391
+ [0, 1, 0, 0, 0, 0],
392
+ [0, 0, 3, 4, 5, 0],
393
+ [0, 0, 6, 7, 8, 0],
394
+ [0, 0, 0, 0, 0, 7]])
395
+ >>> block_diag(A, P, B, C)
396
+ array([[1, 0, 0, 0, 0, 0],
397
+ [0, 1, 0, 0, 0, 0],
398
+ [0, 0, 0, 0, 0, 0],
399
+ [0, 0, 0, 0, 0, 0],
400
+ [0, 0, 3, 4, 5, 0],
401
+ [0, 0, 6, 7, 8, 0],
402
+ [0, 0, 0, 0, 0, 7]])
403
+ >>> block_diag(1.0, [2, 3], [[4, 5], [6, 7]])
404
+ array([[ 1., 0., 0., 0., 0.],
405
+ [ 0., 2., 3., 0., 0.],
406
+ [ 0., 0., 0., 4., 5.],
407
+ [ 0., 0., 0., 6., 7.]])
408
+
409
+ """
410
+ if arrs == ():
411
+ arrs = ([],)
412
+ arrs = [np.atleast_2d(a) for a in arrs]
413
+
414
+ bad_args = [k for k in range(len(arrs)) if arrs[k].ndim > 2]
415
+ if bad_args:
416
+ raise ValueError("arguments in the following positions have dimension "
417
+ "greater than 2: %s" % bad_args)
418
+
419
+ shapes = np.array([a.shape for a in arrs])
420
+ out_dtype = np.result_type(*[arr.dtype for arr in arrs])
421
+ out = np.zeros(np.sum(shapes, axis=0), dtype=out_dtype)
422
+
423
+ r, c = 0, 0
424
+ for i, (rr, cc) in enumerate(shapes):
425
+ out[r:r + rr, c:c + cc] = arrs[i]
426
+ r += rr
427
+ c += cc
428
+ return out
429
+
430
+
431
+ def companion(a):
432
+ """
433
+ Create a companion matrix.
434
+
435
+ Create the companion matrix [1]_ associated with the polynomial whose
436
+ coefficients are given in `a`.
437
+
438
+ Parameters
439
+ ----------
440
+ a : (N,) array_like
441
+ 1-D array of polynomial coefficients. The length of `a` must be
442
+ at least two, and ``a[0]`` must not be zero.
443
+
444
+ Returns
445
+ -------
446
+ c : (N-1, N-1) ndarray
447
+ The first row of `c` is ``-a[1:]/a[0]``, and the first
448
+ sub-diagonal is all ones. The data-type of the array is the same
449
+ as the data-type of ``1.0*a[0]``.
450
+
451
+ Raises
452
+ ------
453
+ ValueError
454
+ If any of the following are true: a) ``a.ndim != 1``;
455
+ b) ``a.size < 2``; c) ``a[0] == 0``.
456
+
457
+ Notes
458
+ -----
459
+ .. versionadded:: 0.8.0
460
+
461
+ References
462
+ ----------
463
+ .. [1] R. A. Horn & C. R. Johnson, *Matrix Analysis*. Cambridge, UK:
464
+ Cambridge University Press, 1999, pp. 146-7.
465
+
466
+ Examples
467
+ --------
468
+ >>> from scipy.linalg import companion
469
+ >>> companion([1, -10, 31, -30])
470
+ array([[ 10., -31., 30.],
471
+ [ 1., 0., 0.],
472
+ [ 0., 1., 0.]])
473
+
474
+ """
475
+ a = np.atleast_1d(a)
476
+
477
+ if a.ndim != 1:
478
+ raise ValueError("Incorrect shape for `a`. `a` must be "
479
+ "one-dimensional.")
480
+
481
+ if a.size < 2:
482
+ raise ValueError("The length of `a` must be at least 2.")
483
+
484
+ if a[0] == 0:
485
+ raise ValueError("The first coefficient in `a` must not be zero.")
486
+
487
+ first_row = -a[1:] / (1.0 * a[0])
488
+ n = a.size
489
+ c = np.zeros((n - 1, n - 1), dtype=first_row.dtype)
490
+ c[0] = first_row
491
+ c[list(range(1, n - 1)), list(range(0, n - 2))] = 1
492
+ return c
493
+
494
+
495
+ def helmert(n, full=False):
496
+ """
497
+ Create an Helmert matrix of order `n`.
498
+
499
+ This has applications in statistics, compositional or simplicial analysis,
500
+ and in Aitchison geometry.
501
+
502
+ Parameters
503
+ ----------
504
+ n : int
505
+ The size of the array to create.
506
+ full : bool, optional
507
+ If True the (n, n) ndarray will be returned.
508
+ Otherwise the submatrix that does not include the first
509
+ row will be returned.
510
+ Default: False.
511
+
512
+ Returns
513
+ -------
514
+ M : ndarray
515
+ The Helmert matrix.
516
+ The shape is (n, n) or (n-1, n) depending on the `full` argument.
517
+
518
+ Examples
519
+ --------
520
+ >>> from scipy.linalg import helmert
521
+ >>> helmert(5, full=True)
522
+ array([[ 0.4472136 , 0.4472136 , 0.4472136 , 0.4472136 , 0.4472136 ],
523
+ [ 0.70710678, -0.70710678, 0. , 0. , 0. ],
524
+ [ 0.40824829, 0.40824829, -0.81649658, 0. , 0. ],
525
+ [ 0.28867513, 0.28867513, 0.28867513, -0.8660254 , 0. ],
526
+ [ 0.2236068 , 0.2236068 , 0.2236068 , 0.2236068 , -0.89442719]])
527
+
528
+ """
529
+ H = np.tril(np.ones((n, n)), -1) - np.diag(np.arange(n))
530
+ d = np.arange(n) * np.arange(1, n+1)
531
+ H[0] = 1
532
+ d[0] = n
533
+ H_full = H / np.sqrt(d)[:, np.newaxis]
534
+ if full:
535
+ return H_full
536
+ else:
537
+ return H_full[1:]
538
+
539
+
540
+ def hilbert(n):
541
+ """
542
+ Create a Hilbert matrix of order `n`.
543
+
544
+ Returns the `n` by `n` array with entries `h[i,j] = 1 / (i + j + 1)`.
545
+
546
+ Parameters
547
+ ----------
548
+ n : int
549
+ The size of the array to create.
550
+
551
+ Returns
552
+ -------
553
+ h : (n, n) ndarray
554
+ The Hilbert matrix.
555
+
556
+ See Also
557
+ --------
558
+ invhilbert : Compute the inverse of a Hilbert matrix.
559
+
560
+ Notes
561
+ -----
562
+ .. versionadded:: 0.10.0
563
+
564
+ Examples
565
+ --------
566
+ >>> from scipy.linalg import hilbert
567
+ >>> hilbert(3)
568
+ array([[ 1. , 0.5 , 0.33333333],
569
+ [ 0.5 , 0.33333333, 0.25 ],
570
+ [ 0.33333333, 0.25 , 0.2 ]])
571
+
572
+ """
573
+ values = 1.0 / (1.0 + np.arange(2 * n - 1))
574
+ h = hankel(values[:n], r=values[n - 1:])
575
+ return h
576
+
577
+
578
+ def invhilbert(n, exact=False):
579
+ """
580
+ Compute the inverse of the Hilbert matrix of order `n`.
581
+
582
+ The entries in the inverse of a Hilbert matrix are integers. When `n`
583
+ is greater than 14, some entries in the inverse exceed the upper limit
584
+ of 64 bit integers. The `exact` argument provides two options for
585
+ dealing with these large integers.
586
+
587
+ Parameters
588
+ ----------
589
+ n : int
590
+ The order of the Hilbert matrix.
591
+ exact : bool, optional
592
+ If False, the data type of the array that is returned is np.float64,
593
+ and the array is an approximation of the inverse.
594
+ If True, the array is the exact integer inverse array. To represent
595
+ the exact inverse when n > 14, the returned array is an object array
596
+ of long integers. For n <= 14, the exact inverse is returned as an
597
+ array with data type np.int64.
598
+
599
+ Returns
600
+ -------
601
+ invh : (n, n) ndarray
602
+ The data type of the array is np.float64 if `exact` is False.
603
+ If `exact` is True, the data type is either np.int64 (for n <= 14)
604
+ or object (for n > 14). In the latter case, the objects in the
605
+ array will be long integers.
606
+
607
+ See Also
608
+ --------
609
+ hilbert : Create a Hilbert matrix.
610
+
611
+ Notes
612
+ -----
613
+ .. versionadded:: 0.10.0
614
+
615
+ Examples
616
+ --------
617
+ >>> from scipy.linalg import invhilbert
618
+ >>> invhilbert(4)
619
+ array([[ 16., -120., 240., -140.],
620
+ [ -120., 1200., -2700., 1680.],
621
+ [ 240., -2700., 6480., -4200.],
622
+ [ -140., 1680., -4200., 2800.]])
623
+ >>> invhilbert(4, exact=True)
624
+ array([[ 16, -120, 240, -140],
625
+ [ -120, 1200, -2700, 1680],
626
+ [ 240, -2700, 6480, -4200],
627
+ [ -140, 1680, -4200, 2800]], dtype=int64)
628
+ >>> invhilbert(16)[7,7]
629
+ 4.2475099528537506e+19
630
+ >>> invhilbert(16, exact=True)[7,7]
631
+ 42475099528537378560
632
+
633
+ """
634
+ from scipy.special import comb
635
+ if exact:
636
+ if n > 14:
637
+ dtype = object
638
+ else:
639
+ dtype = np.int64
640
+ else:
641
+ dtype = np.float64
642
+ invh = np.empty((n, n), dtype=dtype)
643
+ for i in range(n):
644
+ for j in range(0, i + 1):
645
+ s = i + j
646
+ invh[i, j] = ((-1) ** s * (s + 1) *
647
+ comb(n + i, n - j - 1, exact=exact) *
648
+ comb(n + j, n - i - 1, exact=exact) *
649
+ comb(s, i, exact=exact) ** 2)
650
+ if i != j:
651
+ invh[j, i] = invh[i, j]
652
+ return invh
653
+
654
+
655
+ def pascal(n, kind='symmetric', exact=True):
656
+ """
657
+ Returns the n x n Pascal matrix.
658
+
659
+ The Pascal matrix is a matrix containing the binomial coefficients as
660
+ its elements.
661
+
662
+ Parameters
663
+ ----------
664
+ n : int
665
+ The size of the matrix to create; that is, the result is an n x n
666
+ matrix.
667
+ kind : str, optional
668
+ Must be one of 'symmetric', 'lower', or 'upper'.
669
+ Default is 'symmetric'.
670
+ exact : bool, optional
671
+ If `exact` is True, the result is either an array of type
672
+ numpy.uint64 (if n < 35) or an object array of Python long integers.
673
+ If `exact` is False, the coefficients in the matrix are computed using
674
+ `scipy.special.comb` with `exact=False`. The result will be a floating
675
+ point array, and the values in the array will not be the exact
676
+ coefficients, but this version is much faster than `exact=True`.
677
+
678
+ Returns
679
+ -------
680
+ p : (n, n) ndarray
681
+ The Pascal matrix.
682
+
683
+ See Also
684
+ --------
685
+ invpascal
686
+
687
+ Notes
688
+ -----
689
+ See https://en.wikipedia.org/wiki/Pascal_matrix for more information
690
+ about Pascal matrices.
691
+
692
+ .. versionadded:: 0.11.0
693
+
694
+ Examples
695
+ --------
696
+ >>> from scipy.linalg import pascal
697
+ >>> pascal(4)
698
+ array([[ 1, 1, 1, 1],
699
+ [ 1, 2, 3, 4],
700
+ [ 1, 3, 6, 10],
701
+ [ 1, 4, 10, 20]], dtype=uint64)
702
+ >>> pascal(4, kind='lower')
703
+ array([[1, 0, 0, 0],
704
+ [1, 1, 0, 0],
705
+ [1, 2, 1, 0],
706
+ [1, 3, 3, 1]], dtype=uint64)
707
+ >>> pascal(50)[-1, -1]
708
+ 25477612258980856902730428600
709
+ >>> from scipy.special import comb
710
+ >>> comb(98, 49, exact=True)
711
+ 25477612258980856902730428600
712
+
713
+ """
714
+
715
+ from scipy.special import comb
716
+ if kind not in ['symmetric', 'lower', 'upper']:
717
+ raise ValueError("kind must be 'symmetric', 'lower', or 'upper'")
718
+
719
+ if exact:
720
+ if n >= 35:
721
+ L_n = np.empty((n, n), dtype=object)
722
+ L_n.fill(0)
723
+ else:
724
+ L_n = np.zeros((n, n), dtype=np.uint64)
725
+ for i in range(n):
726
+ for j in range(i + 1):
727
+ L_n[i, j] = comb(i, j, exact=True)
728
+ else:
729
+ L_n = comb(*np.ogrid[:n, :n])
730
+
731
+ if kind == 'lower':
732
+ p = L_n
733
+ elif kind == 'upper':
734
+ p = L_n.T
735
+ else:
736
+ p = np.dot(L_n, L_n.T)
737
+
738
+ return p
739
+
740
+
741
+ def invpascal(n, kind='symmetric', exact=True):
742
+ """
743
+ Returns the inverse of the n x n Pascal matrix.
744
+
745
+ The Pascal matrix is a matrix containing the binomial coefficients as
746
+ its elements.
747
+
748
+ Parameters
749
+ ----------
750
+ n : int
751
+ The size of the matrix to create; that is, the result is an n x n
752
+ matrix.
753
+ kind : str, optional
754
+ Must be one of 'symmetric', 'lower', or 'upper'.
755
+ Default is 'symmetric'.
756
+ exact : bool, optional
757
+ If `exact` is True, the result is either an array of type
758
+ ``numpy.int64`` (if `n` <= 35) or an object array of Python integers.
759
+ If `exact` is False, the coefficients in the matrix are computed using
760
+ `scipy.special.comb` with `exact=False`. The result will be a floating
761
+ point array, and for large `n`, the values in the array will not be the
762
+ exact coefficients.
763
+
764
+ Returns
765
+ -------
766
+ invp : (n, n) ndarray
767
+ The inverse of the Pascal matrix.
768
+
769
+ See Also
770
+ --------
771
+ pascal
772
+
773
+ Notes
774
+ -----
775
+
776
+ .. versionadded:: 0.16.0
777
+
778
+ References
779
+ ----------
780
+ .. [1] "Pascal matrix", https://en.wikipedia.org/wiki/Pascal_matrix
781
+ .. [2] Cohen, A. M., "The inverse of a Pascal matrix", Mathematical
782
+ Gazette, 59(408), pp. 111-112, 1975.
783
+
784
+ Examples
785
+ --------
786
+ >>> from scipy.linalg import invpascal, pascal
787
+ >>> invp = invpascal(5)
788
+ >>> invp
789
+ array([[ 5, -10, 10, -5, 1],
790
+ [-10, 30, -35, 19, -4],
791
+ [ 10, -35, 46, -27, 6],
792
+ [ -5, 19, -27, 17, -4],
793
+ [ 1, -4, 6, -4, 1]])
794
+
795
+ >>> p = pascal(5)
796
+ >>> p.dot(invp)
797
+ array([[ 1., 0., 0., 0., 0.],
798
+ [ 0., 1., 0., 0., 0.],
799
+ [ 0., 0., 1., 0., 0.],
800
+ [ 0., 0., 0., 1., 0.],
801
+ [ 0., 0., 0., 0., 1.]])
802
+
803
+ An example of the use of `kind` and `exact`:
804
+
805
+ >>> invpascal(5, kind='lower', exact=False)
806
+ array([[ 1., -0., 0., -0., 0.],
807
+ [-1., 1., -0., 0., -0.],
808
+ [ 1., -2., 1., -0., 0.],
809
+ [-1., 3., -3., 1., -0.],
810
+ [ 1., -4., 6., -4., 1.]])
811
+
812
+ """
813
+ from scipy.special import comb
814
+
815
+ if kind not in ['symmetric', 'lower', 'upper']:
816
+ raise ValueError("'kind' must be 'symmetric', 'lower' or 'upper'.")
817
+
818
+ if kind == 'symmetric':
819
+ if exact:
820
+ if n > 34:
821
+ dt = object
822
+ else:
823
+ dt = np.int64
824
+ else:
825
+ dt = np.float64
826
+ invp = np.empty((n, n), dtype=dt)
827
+ for i in range(n):
828
+ for j in range(0, i + 1):
829
+ v = 0
830
+ for k in range(n - i):
831
+ v += comb(i + k, k, exact=exact) * comb(i + k, i + k - j,
832
+ exact=exact)
833
+ invp[i, j] = (-1)**(i - j) * v
834
+ if i != j:
835
+ invp[j, i] = invp[i, j]
836
+ else:
837
+ # For the 'lower' and 'upper' cases, we computer the inverse by
838
+ # changing the sign of every other diagonal of the pascal matrix.
839
+ invp = pascal(n, kind=kind, exact=exact)
840
+ if invp.dtype == np.uint64:
841
+ # This cast from np.uint64 to int64 OK, because if `kind` is not
842
+ # "symmetric", the values in invp are all much less than 2**63.
843
+ invp = invp.view(np.int64)
844
+
845
+ # The toeplitz matrix has alternating bands of 1 and -1.
846
+ invp *= toeplitz((-1)**np.arange(n)).astype(invp.dtype)
847
+
848
+ return invp
849
+
850
+
851
+ def dft(n, scale=None):
852
+ """
853
+ Discrete Fourier transform matrix.
854
+
855
+ Create the matrix that computes the discrete Fourier transform of a
856
+ sequence [1]_. The nth primitive root of unity used to generate the
857
+ matrix is exp(-2*pi*i/n), where i = sqrt(-1).
858
+
859
+ Parameters
860
+ ----------
861
+ n : int
862
+ Size the matrix to create.
863
+ scale : str, optional
864
+ Must be None, 'sqrtn', or 'n'.
865
+ If `scale` is 'sqrtn', the matrix is divided by `sqrt(n)`.
866
+ If `scale` is 'n', the matrix is divided by `n`.
867
+ If `scale` is None (the default), the matrix is not normalized, and the
868
+ return value is simply the Vandermonde matrix of the roots of unity.
869
+
870
+ Returns
871
+ -------
872
+ m : (n, n) ndarray
873
+ The DFT matrix.
874
+
875
+ Notes
876
+ -----
877
+ When `scale` is None, multiplying a vector by the matrix returned by
878
+ `dft` is mathematically equivalent to (but much less efficient than)
879
+ the calculation performed by `scipy.fft.fft`.
880
+
881
+ .. versionadded:: 0.14.0
882
+
883
+ References
884
+ ----------
885
+ .. [1] "DFT matrix", https://en.wikipedia.org/wiki/DFT_matrix
886
+
887
+ Examples
888
+ --------
889
+ >>> import numpy as np
890
+ >>> from scipy.linalg import dft
891
+ >>> np.set_printoptions(precision=2, suppress=True) # for compact output
892
+ >>> m = dft(5)
893
+ >>> m
894
+ array([[ 1. +0.j , 1. +0.j , 1. +0.j , 1. +0.j , 1. +0.j ],
895
+ [ 1. +0.j , 0.31-0.95j, -0.81-0.59j, -0.81+0.59j, 0.31+0.95j],
896
+ [ 1. +0.j , -0.81-0.59j, 0.31+0.95j, 0.31-0.95j, -0.81+0.59j],
897
+ [ 1. +0.j , -0.81+0.59j, 0.31-0.95j, 0.31+0.95j, -0.81-0.59j],
898
+ [ 1. +0.j , 0.31+0.95j, -0.81+0.59j, -0.81-0.59j, 0.31-0.95j]])
899
+ >>> x = np.array([1, 2, 3, 0, 3])
900
+ >>> m @ x # Compute the DFT of x
901
+ array([ 9. +0.j , 0.12-0.81j, -2.12+3.44j, -2.12-3.44j, 0.12+0.81j])
902
+
903
+ Verify that ``m @ x`` is the same as ``fft(x)``.
904
+
905
+ >>> from scipy.fft import fft
906
+ >>> fft(x) # Same result as m @ x
907
+ array([ 9. +0.j , 0.12-0.81j, -2.12+3.44j, -2.12-3.44j, 0.12+0.81j])
908
+ """
909
+ if scale not in [None, 'sqrtn', 'n']:
910
+ raise ValueError("scale must be None, 'sqrtn', or 'n'; "
911
+ f"{scale!r} is not valid.")
912
+
913
+ omegas = np.exp(-2j * np.pi * np.arange(n) / n).reshape(-1, 1)
914
+ m = omegas ** np.arange(n)
915
+ if scale == 'sqrtn':
916
+ m /= math.sqrt(n)
917
+ elif scale == 'n':
918
+ m /= n
919
+ return m
920
+
921
+
922
+ def fiedler(a):
923
+ """Returns a symmetric Fiedler matrix
924
+
925
+ Given an sequence of numbers `a`, Fiedler matrices have the structure
926
+ ``F[i, j] = np.abs(a[i] - a[j])``, and hence zero diagonals and nonnegative
927
+ entries. A Fiedler matrix has a dominant positive eigenvalue and other
928
+ eigenvalues are negative. Although not valid generally, for certain inputs,
929
+ the inverse and the determinant can be derived explicitly as given in [1]_.
930
+
931
+ Parameters
932
+ ----------
933
+ a : (n,) array_like
934
+ coefficient array
935
+
936
+ Returns
937
+ -------
938
+ F : (n, n) ndarray
939
+
940
+ See Also
941
+ --------
942
+ circulant, toeplitz
943
+
944
+ Notes
945
+ -----
946
+
947
+ .. versionadded:: 1.3.0
948
+
949
+ References
950
+ ----------
951
+ .. [1] J. Todd, "Basic Numerical Mathematics: Vol.2 : Numerical Algebra",
952
+ 1977, Birkhauser, :doi:`10.1007/978-3-0348-7286-7`
953
+
954
+ Examples
955
+ --------
956
+ >>> import numpy as np
957
+ >>> from scipy.linalg import det, inv, fiedler
958
+ >>> a = [1, 4, 12, 45, 77]
959
+ >>> n = len(a)
960
+ >>> A = fiedler(a)
961
+ >>> A
962
+ array([[ 0, 3, 11, 44, 76],
963
+ [ 3, 0, 8, 41, 73],
964
+ [11, 8, 0, 33, 65],
965
+ [44, 41, 33, 0, 32],
966
+ [76, 73, 65, 32, 0]])
967
+
968
+ The explicit formulas for determinant and inverse seem to hold only for
969
+ monotonically increasing/decreasing arrays. Note the tridiagonal structure
970
+ and the corners.
971
+
972
+ >>> Ai = inv(A)
973
+ >>> Ai[np.abs(Ai) < 1e-12] = 0. # cleanup the numerical noise for display
974
+ >>> Ai
975
+ array([[-0.16008772, 0.16666667, 0. , 0. , 0.00657895],
976
+ [ 0.16666667, -0.22916667, 0.0625 , 0. , 0. ],
977
+ [ 0. , 0.0625 , -0.07765152, 0.01515152, 0. ],
978
+ [ 0. , 0. , 0.01515152, -0.03077652, 0.015625 ],
979
+ [ 0.00657895, 0. , 0. , 0.015625 , -0.00904605]])
980
+ >>> det(A)
981
+ 15409151.999999998
982
+ >>> (-1)**(n-1) * 2**(n-2) * np.diff(a).prod() * (a[-1] - a[0])
983
+ 15409152
984
+
985
+ """
986
+ a = np.atleast_1d(a)
987
+
988
+ if a.ndim != 1:
989
+ raise ValueError("Input 'a' must be a 1D array.")
990
+
991
+ if a.size == 0:
992
+ return np.array([], dtype=float)
993
+ elif a.size == 1:
994
+ return np.array([[0.]])
995
+ else:
996
+ return np.abs(a[:, None] - a)
997
+
998
+
999
+ def fiedler_companion(a):
1000
+ """ Returns a Fiedler companion matrix
1001
+
1002
+ Given a polynomial coefficient array ``a``, this function forms a
1003
+ pentadiagonal matrix with a special structure whose eigenvalues coincides
1004
+ with the roots of ``a``.
1005
+
1006
+ Parameters
1007
+ ----------
1008
+ a : (N,) array_like
1009
+ 1-D array of polynomial coefficients in descending order with a nonzero
1010
+ leading coefficient. For ``N < 2``, an empty array is returned.
1011
+
1012
+ Returns
1013
+ -------
1014
+ c : (N-1, N-1) ndarray
1015
+ Resulting companion matrix
1016
+
1017
+ See Also
1018
+ --------
1019
+ companion
1020
+
1021
+ Notes
1022
+ -----
1023
+ Similar to `companion` the leading coefficient should be nonzero. In the case
1024
+ the leading coefficient is not 1, other coefficients are rescaled before
1025
+ the array generation. To avoid numerical issues, it is best to provide a
1026
+ monic polynomial.
1027
+
1028
+ .. versionadded:: 1.3.0
1029
+
1030
+ References
1031
+ ----------
1032
+ .. [1] M. Fiedler, " A note on companion matrices", Linear Algebra and its
1033
+ Applications, 2003, :doi:`10.1016/S0024-3795(03)00548-2`
1034
+
1035
+ Examples
1036
+ --------
1037
+ >>> import numpy as np
1038
+ >>> from scipy.linalg import fiedler_companion, eigvals
1039
+ >>> p = np.poly(np.arange(1, 9, 2)) # [1., -16., 86., -176., 105.]
1040
+ >>> fc = fiedler_companion(p)
1041
+ >>> fc
1042
+ array([[ 16., -86., 1., 0.],
1043
+ [ 1., 0., 0., 0.],
1044
+ [ 0., 176., 0., -105.],
1045
+ [ 0., 1., 0., 0.]])
1046
+ >>> eigvals(fc)
1047
+ array([7.+0.j, 5.+0.j, 3.+0.j, 1.+0.j])
1048
+
1049
+ """
1050
+ a = np.atleast_1d(a)
1051
+
1052
+ if a.ndim != 1:
1053
+ raise ValueError("Input 'a' must be a 1-D array.")
1054
+
1055
+ if a.size <= 2:
1056
+ if a.size == 2:
1057
+ return np.array([[-(a/a[0])[-1]]])
1058
+ return np.array([], dtype=a.dtype)
1059
+
1060
+ if a[0] == 0.:
1061
+ raise ValueError('Leading coefficient is zero.')
1062
+
1063
+ a = a/a[0]
1064
+ n = a.size - 1
1065
+ c = np.zeros((n, n), dtype=a.dtype)
1066
+ # subdiagonals
1067
+ c[range(3, n, 2), range(1, n-2, 2)] = 1.
1068
+ c[range(2, n, 2), range(1, n-1, 2)] = -a[3::2]
1069
+ # superdiagonals
1070
+ c[range(0, n-2, 2), range(2, n, 2)] = 1.
1071
+ c[range(0, n-1, 2), range(1, n, 2)] = -a[2::2]
1072
+ c[[0, 1], 0] = [-a[1], 1]
1073
+
1074
+ return c
1075
+
1076
+
1077
+ def convolution_matrix(a, n, mode='full'):
1078
+ """
1079
+ Construct a convolution matrix.
1080
+
1081
+ Constructs the Toeplitz matrix representing one-dimensional
1082
+ convolution [1]_. See the notes below for details.
1083
+
1084
+ Parameters
1085
+ ----------
1086
+ a : (m,) array_like
1087
+ The 1-D array to convolve.
1088
+ n : int
1089
+ The number of columns in the resulting matrix. It gives the length
1090
+ of the input to be convolved with `a`. This is analogous to the
1091
+ length of `v` in ``numpy.convolve(a, v)``.
1092
+ mode : str
1093
+ This is analogous to `mode` in ``numpy.convolve(v, a, mode)``.
1094
+ It must be one of ('full', 'valid', 'same').
1095
+ See below for how `mode` determines the shape of the result.
1096
+
1097
+ Returns
1098
+ -------
1099
+ A : (k, n) ndarray
1100
+ The convolution matrix whose row count `k` depends on `mode`::
1101
+
1102
+ ======= =========================
1103
+ mode k
1104
+ ======= =========================
1105
+ 'full' m + n -1
1106
+ 'same' max(m, n)
1107
+ 'valid' max(m, n) - min(m, n) + 1
1108
+ ======= =========================
1109
+
1110
+ See Also
1111
+ --------
1112
+ toeplitz : Toeplitz matrix
1113
+
1114
+ Notes
1115
+ -----
1116
+ The code::
1117
+
1118
+ A = convolution_matrix(a, n, mode)
1119
+
1120
+ creates a Toeplitz matrix `A` such that ``A @ v`` is equivalent to
1121
+ using ``convolve(a, v, mode)``. The returned array always has `n`
1122
+ columns. The number of rows depends on the specified `mode`, as
1123
+ explained above.
1124
+
1125
+ In the default 'full' mode, the entries of `A` are given by::
1126
+
1127
+ A[i, j] == (a[i-j] if (0 <= (i-j) < m) else 0)
1128
+
1129
+ where ``m = len(a)``. Suppose, for example, the input array is
1130
+ ``[x, y, z]``. The convolution matrix has the form::
1131
+
1132
+ [x, 0, 0, ..., 0, 0]
1133
+ [y, x, 0, ..., 0, 0]
1134
+ [z, y, x, ..., 0, 0]
1135
+ ...
1136
+ [0, 0, 0, ..., x, 0]
1137
+ [0, 0, 0, ..., y, x]
1138
+ [0, 0, 0, ..., z, y]
1139
+ [0, 0, 0, ..., 0, z]
1140
+
1141
+ In 'valid' mode, the entries of `A` are given by::
1142
+
1143
+ A[i, j] == (a[i-j+m-1] if (0 <= (i-j+m-1) < m) else 0)
1144
+
1145
+ This corresponds to a matrix whose rows are the subset of those from
1146
+ the 'full' case where all the coefficients in `a` are contained in the
1147
+ row. For input ``[x, y, z]``, this array looks like::
1148
+
1149
+ [z, y, x, 0, 0, ..., 0, 0, 0]
1150
+ [0, z, y, x, 0, ..., 0, 0, 0]
1151
+ [0, 0, z, y, x, ..., 0, 0, 0]
1152
+ ...
1153
+ [0, 0, 0, 0, 0, ..., x, 0, 0]
1154
+ [0, 0, 0, 0, 0, ..., y, x, 0]
1155
+ [0, 0, 0, 0, 0, ..., z, y, x]
1156
+
1157
+ In the 'same' mode, the entries of `A` are given by::
1158
+
1159
+ d = (m - 1) // 2
1160
+ A[i, j] == (a[i-j+d] if (0 <= (i-j+d) < m) else 0)
1161
+
1162
+ The typical application of the 'same' mode is when one has a signal of
1163
+ length `n` (with `n` greater than ``len(a)``), and the desired output
1164
+ is a filtered signal that is still of length `n`.
1165
+
1166
+ For input ``[x, y, z]``, this array looks like::
1167
+
1168
+ [y, x, 0, 0, ..., 0, 0, 0]
1169
+ [z, y, x, 0, ..., 0, 0, 0]
1170
+ [0, z, y, x, ..., 0, 0, 0]
1171
+ [0, 0, z, y, ..., 0, 0, 0]
1172
+ ...
1173
+ [0, 0, 0, 0, ..., y, x, 0]
1174
+ [0, 0, 0, 0, ..., z, y, x]
1175
+ [0, 0, 0, 0, ..., 0, z, y]
1176
+
1177
+ .. versionadded:: 1.5.0
1178
+
1179
+ References
1180
+ ----------
1181
+ .. [1] "Convolution", https://en.wikipedia.org/wiki/Convolution
1182
+
1183
+ Examples
1184
+ --------
1185
+ >>> import numpy as np
1186
+ >>> from scipy.linalg import convolution_matrix
1187
+ >>> A = convolution_matrix([-1, 4, -2], 5, mode='same')
1188
+ >>> A
1189
+ array([[ 4, -1, 0, 0, 0],
1190
+ [-2, 4, -1, 0, 0],
1191
+ [ 0, -2, 4, -1, 0],
1192
+ [ 0, 0, -2, 4, -1],
1193
+ [ 0, 0, 0, -2, 4]])
1194
+
1195
+ Compare multiplication by `A` with the use of `numpy.convolve`.
1196
+
1197
+ >>> x = np.array([1, 2, 0, -3, 0.5])
1198
+ >>> A @ x
1199
+ array([ 2. , 6. , -1. , -12.5, 8. ])
1200
+
1201
+ Verify that ``A @ x`` produced the same result as applying the
1202
+ convolution function.
1203
+
1204
+ >>> np.convolve([-1, 4, -2], x, mode='same')
1205
+ array([ 2. , 6. , -1. , -12.5, 8. ])
1206
+
1207
+ For comparison to the case ``mode='same'`` shown above, here are the
1208
+ matrices produced by ``mode='full'`` and ``mode='valid'`` for the
1209
+ same coefficients and size.
1210
+
1211
+ >>> convolution_matrix([-1, 4, -2], 5, mode='full')
1212
+ array([[-1, 0, 0, 0, 0],
1213
+ [ 4, -1, 0, 0, 0],
1214
+ [-2, 4, -1, 0, 0],
1215
+ [ 0, -2, 4, -1, 0],
1216
+ [ 0, 0, -2, 4, -1],
1217
+ [ 0, 0, 0, -2, 4],
1218
+ [ 0, 0, 0, 0, -2]])
1219
+
1220
+ >>> convolution_matrix([-1, 4, -2], 5, mode='valid')
1221
+ array([[-2, 4, -1, 0, 0],
1222
+ [ 0, -2, 4, -1, 0],
1223
+ [ 0, 0, -2, 4, -1]])
1224
+ """
1225
+ if n <= 0:
1226
+ raise ValueError('n must be a positive integer.')
1227
+
1228
+ a = np.asarray(a)
1229
+ if a.ndim != 1:
1230
+ raise ValueError('convolution_matrix expects a one-dimensional '
1231
+ 'array as input')
1232
+ if a.size == 0:
1233
+ raise ValueError('len(a) must be at least 1.')
1234
+
1235
+ if mode not in ('full', 'valid', 'same'):
1236
+ raise ValueError(
1237
+ "'mode' argument must be one of ('full', 'valid', 'same')")
1238
+
1239
+ # create zero padded versions of the array
1240
+ az = np.pad(a, (0, n-1), 'constant')
1241
+ raz = np.pad(a[::-1], (0, n-1), 'constant')
1242
+
1243
+ if mode == 'same':
1244
+ trim = min(n, len(a)) - 1
1245
+ tb = trim//2
1246
+ te = trim - tb
1247
+ col0 = az[tb:len(az)-te]
1248
+ row0 = raz[-n-tb:len(raz)-tb]
1249
+ elif mode == 'valid':
1250
+ tb = min(n, len(a)) - 1
1251
+ te = tb
1252
+ col0 = az[tb:len(az)-te]
1253
+ row0 = raz[-n-tb:len(raz)-tb]
1254
+ else: # 'full'
1255
+ col0 = az
1256
+ row0 = raz[-n:]
1257
+ return toeplitz(col0, row0)
astra_scene_test/Scene_04/.venv/lib/python3.9/site-packages/scipy/linalg/_testutils.py ADDED
@@ -0,0 +1,65 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import numpy as np
2
+
3
+
4
+ class _FakeMatrix:
5
+ def __init__(self, data):
6
+ self._data = data
7
+ self.__array_interface__ = data.__array_interface__
8
+
9
+
10
+ class _FakeMatrix2:
11
+ def __init__(self, data):
12
+ self._data = data
13
+
14
+ def __array__(self, dtype=None, copy=None):
15
+ if copy:
16
+ return self._data.copy()
17
+ return self._data
18
+
19
+
20
+ def _get_array(shape, dtype):
21
+ """
22
+ Get a test array of given shape and data type.
23
+ Returned NxN matrices are posdef, and 2xN are banded-posdef.
24
+
25
+ """
26
+ if len(shape) == 2 and shape[0] == 2:
27
+ # yield a banded positive definite one
28
+ x = np.zeros(shape, dtype=dtype)
29
+ x[0, 1:] = -1
30
+ x[1] = 2
31
+ return x
32
+ elif len(shape) == 2 and shape[0] == shape[1]:
33
+ # always yield a positive definite matrix
34
+ x = np.zeros(shape, dtype=dtype)
35
+ j = np.arange(shape[0])
36
+ x[j, j] = 2
37
+ x[j[:-1], j[:-1]+1] = -1
38
+ x[j[:-1]+1, j[:-1]] = -1
39
+ return x
40
+ else:
41
+ np.random.seed(1234)
42
+ return np.random.randn(*shape).astype(dtype)
43
+
44
+
45
+ def _id(x):
46
+ return x
47
+
48
+
49
+ def assert_no_overwrite(call, shapes, dtypes=None):
50
+ """
51
+ Test that a call does not overwrite its input arguments
52
+ """
53
+
54
+ if dtypes is None:
55
+ dtypes = [np.float32, np.float64, np.complex64, np.complex128]
56
+
57
+ for dtype in dtypes:
58
+ for order in ["C", "F"]:
59
+ for faker in [_id, _FakeMatrix, _FakeMatrix2]:
60
+ orig_inputs = [_get_array(s, dtype) for s in shapes]
61
+ inputs = [faker(x.copy(order)) for x in orig_inputs]
62
+ call(*inputs)
63
+ msg = f"call modified inputs [{dtype!r}, {faker!r}]"
64
+ for a, b in zip(inputs, orig_inputs):
65
+ np.testing.assert_equal(a, b, err_msg=msg)
astra_scene_test/Scene_04/.venv/lib/python3.9/site-packages/scipy/linalg/basic.py ADDED
@@ -0,0 +1,24 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # This file is not meant for public use and will be removed in SciPy v2.0.0.
2
+ # Use the `scipy.linalg` namespace for importing the functions
3
+ # included below.
4
+
5
+ from scipy._lib.deprecation import _sub_module_deprecation
6
+
7
+
8
+ __all__ = [ # noqa: F822
9
+ 'solve', 'solve_triangular', 'solveh_banded', 'solve_banded',
10
+ 'solve_toeplitz', 'solve_circulant', 'inv', 'det', 'lstsq',
11
+ 'pinv', 'pinvh', 'matrix_balance', 'matmul_toeplitz',
12
+ 'atleast_1d', 'atleast_2d', 'get_lapack_funcs',
13
+ 'LinAlgError', 'LinAlgWarning', 'levinson',
14
+ ]
15
+
16
+
17
+ def __dir__():
18
+ return __all__
19
+
20
+
21
+ def __getattr__(name):
22
+ return _sub_module_deprecation(sub_package="linalg", module="basic",
23
+ private_modules=["_basic"], all=__all__,
24
+ attribute=name)
astra_scene_test/Scene_04/.venv/lib/python3.9/site-packages/scipy/linalg/blas.py ADDED
@@ -0,0 +1,484 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """
2
+ Low-level BLAS functions (:mod:`scipy.linalg.blas`)
3
+ ===================================================
4
+
5
+ This module contains low-level functions from the BLAS library.
6
+
7
+ .. versionadded:: 0.12.0
8
+
9
+ .. note::
10
+
11
+ The common ``overwrite_<>`` option in many routines, allows the
12
+ input arrays to be overwritten to avoid extra memory allocation.
13
+ However this requires the array to satisfy two conditions
14
+ which are memory order and the data type to match exactly the
15
+ order and the type expected by the routine.
16
+
17
+ As an example, if you pass a double precision float array to any
18
+ ``S....`` routine which expects single precision arguments, f2py
19
+ will create an intermediate array to match the argument types and
20
+ overwriting will be performed on that intermediate array.
21
+
22
+ Similarly, if a C-contiguous array is passed, f2py will pass a
23
+ FORTRAN-contiguous array internally. Please make sure that these
24
+ details are satisfied. More information can be found in the f2py
25
+ documentation.
26
+
27
+ .. warning::
28
+
29
+ These functions do little to no error checking.
30
+ It is possible to cause crashes by mis-using them,
31
+ so prefer using the higher-level routines in `scipy.linalg`.
32
+
33
+ Finding functions
34
+ -----------------
35
+
36
+ .. autosummary::
37
+ :toctree: generated/
38
+
39
+ get_blas_funcs
40
+ find_best_blas_type
41
+
42
+ BLAS Level 1 functions
43
+ ----------------------
44
+
45
+ .. autosummary::
46
+ :toctree: generated/
47
+
48
+ caxpy
49
+ ccopy
50
+ cdotc
51
+ cdotu
52
+ crotg
53
+ cscal
54
+ csrot
55
+ csscal
56
+ cswap
57
+ dasum
58
+ daxpy
59
+ dcopy
60
+ ddot
61
+ dnrm2
62
+ drot
63
+ drotg
64
+ drotm
65
+ drotmg
66
+ dscal
67
+ dswap
68
+ dzasum
69
+ dznrm2
70
+ icamax
71
+ idamax
72
+ isamax
73
+ izamax
74
+ sasum
75
+ saxpy
76
+ scasum
77
+ scnrm2
78
+ scopy
79
+ sdot
80
+ snrm2
81
+ srot
82
+ srotg
83
+ srotm
84
+ srotmg
85
+ sscal
86
+ sswap
87
+ zaxpy
88
+ zcopy
89
+ zdotc
90
+ zdotu
91
+ zdrot
92
+ zdscal
93
+ zrotg
94
+ zscal
95
+ zswap
96
+
97
+ BLAS Level 2 functions
98
+ ----------------------
99
+
100
+ .. autosummary::
101
+ :toctree: generated/
102
+
103
+ sgbmv
104
+ sgemv
105
+ sger
106
+ ssbmv
107
+ sspr
108
+ sspr2
109
+ ssymv
110
+ ssyr
111
+ ssyr2
112
+ stbmv
113
+ stpsv
114
+ strmv
115
+ strsv
116
+ dgbmv
117
+ dgemv
118
+ dger
119
+ dsbmv
120
+ dspr
121
+ dspr2
122
+ dsymv
123
+ dsyr
124
+ dsyr2
125
+ dtbmv
126
+ dtpsv
127
+ dtrmv
128
+ dtrsv
129
+ cgbmv
130
+ cgemv
131
+ cgerc
132
+ cgeru
133
+ chbmv
134
+ chemv
135
+ cher
136
+ cher2
137
+ chpmv
138
+ chpr
139
+ chpr2
140
+ ctbmv
141
+ ctbsv
142
+ ctpmv
143
+ ctpsv
144
+ ctrmv
145
+ ctrsv
146
+ csyr
147
+ zgbmv
148
+ zgemv
149
+ zgerc
150
+ zgeru
151
+ zhbmv
152
+ zhemv
153
+ zher
154
+ zher2
155
+ zhpmv
156
+ zhpr
157
+ zhpr2
158
+ ztbmv
159
+ ztbsv
160
+ ztpmv
161
+ ztrmv
162
+ ztrsv
163
+ zsyr
164
+
165
+ BLAS Level 3 functions
166
+ ----------------------
167
+
168
+ .. autosummary::
169
+ :toctree: generated/
170
+
171
+ sgemm
172
+ ssymm
173
+ ssyr2k
174
+ ssyrk
175
+ strmm
176
+ strsm
177
+ dgemm
178
+ dsymm
179
+ dsyr2k
180
+ dsyrk
181
+ dtrmm
182
+ dtrsm
183
+ cgemm
184
+ chemm
185
+ cher2k
186
+ cherk
187
+ csymm
188
+ csyr2k
189
+ csyrk
190
+ ctrmm
191
+ ctrsm
192
+ zgemm
193
+ zhemm
194
+ zher2k
195
+ zherk
196
+ zsymm
197
+ zsyr2k
198
+ zsyrk
199
+ ztrmm
200
+ ztrsm
201
+
202
+ """
203
+ #
204
+ # Author: Pearu Peterson, March 2002
205
+ # refactoring by Fabian Pedregosa, March 2010
206
+ #
207
+
208
+ __all__ = ['get_blas_funcs', 'find_best_blas_type']
209
+
210
+ import numpy as _np
211
+ import functools
212
+
213
+ from scipy.linalg import _fblas
214
+ try:
215
+ from scipy.linalg import _cblas
216
+ except ImportError:
217
+ _cblas = None
218
+
219
+ try:
220
+ from scipy.linalg import _fblas_64
221
+ HAS_ILP64 = True
222
+ except ImportError:
223
+ HAS_ILP64 = False
224
+ _fblas_64 = None
225
+
226
+ # Expose all functions (only fblas --- cblas is an implementation detail)
227
+ empty_module = None
228
+ from scipy.linalg._fblas import * # noqa: E402, F403
229
+ del empty_module
230
+
231
+ # all numeric dtypes '?bBhHiIlLqQefdgFDGO' that are safe to be converted to
232
+
233
+ # single precision float : '?bBhH!!!!!!ef!!!!!!'
234
+ # double precision float : '?bBhHiIlLqQefdg!!!!'
235
+ # single precision complex : '?bBhH!!!!!!ef!!F!!!'
236
+ # double precision complex : '?bBhHiIlLqQefdgFDG!'
237
+
238
+ _type_score = {x: 1 for x in '?bBhHef'}
239
+ _type_score.update({x: 2 for x in 'iIlLqQd'})
240
+
241
+ # Handle float128(g) and complex256(G) separately in case non-Windows systems.
242
+ # On Windows, the values will be rewritten to the same key with the same value.
243
+ _type_score.update({'F': 3, 'D': 4, 'g': 2, 'G': 4})
244
+
245
+ # Final mapping to the actual prefixes and dtypes
246
+ _type_conv = {1: ('s', _np.dtype('float32')),
247
+ 2: ('d', _np.dtype('float64')),
248
+ 3: ('c', _np.dtype('complex64')),
249
+ 4: ('z', _np.dtype('complex128'))}
250
+
251
+ # some convenience alias for complex functions
252
+ _blas_alias = {'cnrm2': 'scnrm2', 'znrm2': 'dznrm2',
253
+ 'cdot': 'cdotc', 'zdot': 'zdotc',
254
+ 'cger': 'cgerc', 'zger': 'zgerc',
255
+ 'sdotc': 'sdot', 'sdotu': 'sdot',
256
+ 'ddotc': 'ddot', 'ddotu': 'ddot'}
257
+
258
+
259
+ def find_best_blas_type(arrays=(), dtype=None):
260
+ """Find best-matching BLAS/LAPACK type.
261
+
262
+ Arrays are used to determine the optimal prefix of BLAS routines.
263
+
264
+ Parameters
265
+ ----------
266
+ arrays : sequence of ndarrays, optional
267
+ Arrays can be given to determine optimal prefix of BLAS
268
+ routines. If not given, double-precision routines will be
269
+ used, otherwise the most generic type in arrays will be used.
270
+ dtype : str or dtype, optional
271
+ Data-type specifier. Not used if `arrays` is non-empty.
272
+
273
+ Returns
274
+ -------
275
+ prefix : str
276
+ BLAS/LAPACK prefix character.
277
+ dtype : dtype
278
+ Inferred Numpy data type.
279
+ prefer_fortran : bool
280
+ Whether to prefer Fortran order routines over C order.
281
+
282
+ Examples
283
+ --------
284
+ >>> import numpy as np
285
+ >>> import scipy.linalg.blas as bla
286
+ >>> rng = np.random.default_rng()
287
+ >>> a = rng.random((10,15))
288
+ >>> b = np.asfortranarray(a) # Change the memory layout order
289
+ >>> bla.find_best_blas_type((a,))
290
+ ('d', dtype('float64'), False)
291
+ >>> bla.find_best_blas_type((a*1j,))
292
+ ('z', dtype('complex128'), False)
293
+ >>> bla.find_best_blas_type((b,))
294
+ ('d', dtype('float64'), True)
295
+
296
+ """
297
+ dtype = _np.dtype(dtype)
298
+ max_score = _type_score.get(dtype.char, 5)
299
+ prefer_fortran = False
300
+
301
+ if arrays:
302
+ # In most cases, single element is passed through, quicker route
303
+ if len(arrays) == 1:
304
+ max_score = _type_score.get(arrays[0].dtype.char, 5)
305
+ prefer_fortran = arrays[0].flags['FORTRAN']
306
+ else:
307
+ # use the most generic type in arrays
308
+ scores = [_type_score.get(x.dtype.char, 5) for x in arrays]
309
+ max_score = max(scores)
310
+ ind_max_score = scores.index(max_score)
311
+ # safe upcasting for mix of float64 and complex64 --> prefix 'z'
312
+ if max_score == 3 and (2 in scores):
313
+ max_score = 4
314
+
315
+ if arrays[ind_max_score].flags['FORTRAN']:
316
+ # prefer Fortran for leading array with column major order
317
+ prefer_fortran = True
318
+
319
+ # Get the LAPACK prefix and the corresponding dtype if not fall back
320
+ # to 'd' and double precision float.
321
+ prefix, dtype = _type_conv.get(max_score, ('d', _np.dtype('float64')))
322
+
323
+ return prefix, dtype, prefer_fortran
324
+
325
+
326
+ def _get_funcs(names, arrays, dtype,
327
+ lib_name, fmodule, cmodule,
328
+ fmodule_name, cmodule_name, alias,
329
+ ilp64=False):
330
+ """
331
+ Return available BLAS/LAPACK functions.
332
+
333
+ Used also in lapack.py. See get_blas_funcs for docstring.
334
+ """
335
+
336
+ funcs = []
337
+ unpack = False
338
+ dtype = _np.dtype(dtype)
339
+ module1 = (cmodule, cmodule_name)
340
+ module2 = (fmodule, fmodule_name)
341
+
342
+ if isinstance(names, str):
343
+ names = (names,)
344
+ unpack = True
345
+
346
+ prefix, dtype, prefer_fortran = find_best_blas_type(arrays, dtype)
347
+
348
+ if prefer_fortran:
349
+ module1, module2 = module2, module1
350
+
351
+ for name in names:
352
+ func_name = prefix + name
353
+ func_name = alias.get(func_name, func_name)
354
+ func = getattr(module1[0], func_name, None)
355
+ module_name = module1[1]
356
+ if func is None:
357
+ func = getattr(module2[0], func_name, None)
358
+ module_name = module2[1]
359
+ if func is None:
360
+ raise ValueError(
361
+ f'{lib_name} function {func_name} could not be found')
362
+ func.module_name, func.typecode = module_name, prefix
363
+ func.dtype = dtype
364
+ if not ilp64:
365
+ func.int_dtype = _np.dtype(_np.intc)
366
+ else:
367
+ func.int_dtype = _np.dtype(_np.int64)
368
+ func.prefix = prefix # Backward compatibility
369
+ funcs.append(func)
370
+
371
+ if unpack:
372
+ return funcs[0]
373
+ else:
374
+ return funcs
375
+
376
+
377
+ def _memoize_get_funcs(func):
378
+ """
379
+ Memoized fast path for _get_funcs instances
380
+ """
381
+ memo = {}
382
+ func.memo = memo
383
+
384
+ @functools.wraps(func)
385
+ def getter(names, arrays=(), dtype=None, ilp64=False):
386
+ key = (names, dtype, ilp64)
387
+ for array in arrays:
388
+ # cf. find_blas_funcs
389
+ key += (array.dtype.char, array.flags.fortran)
390
+
391
+ try:
392
+ value = memo.get(key)
393
+ except TypeError:
394
+ # unhashable key etc.
395
+ key = None
396
+ value = None
397
+
398
+ if value is not None:
399
+ return value
400
+
401
+ value = func(names, arrays, dtype, ilp64)
402
+
403
+ if key is not None:
404
+ memo[key] = value
405
+
406
+ return value
407
+
408
+ return getter
409
+
410
+
411
+ @_memoize_get_funcs
412
+ def get_blas_funcs(names, arrays=(), dtype=None, ilp64=False):
413
+ """Return available BLAS function objects from names.
414
+
415
+ Arrays are used to determine the optimal prefix of BLAS routines.
416
+
417
+ Parameters
418
+ ----------
419
+ names : str or sequence of str
420
+ Name(s) of BLAS functions without type prefix.
421
+
422
+ arrays : sequence of ndarrays, optional
423
+ Arrays can be given to determine optimal prefix of BLAS
424
+ routines. If not given, double-precision routines will be
425
+ used, otherwise the most generic type in arrays will be used.
426
+
427
+ dtype : str or dtype, optional
428
+ Data-type specifier. Not used if `arrays` is non-empty.
429
+
430
+ ilp64 : {True, False, 'preferred'}, optional
431
+ Whether to return ILP64 routine variant.
432
+ Choosing 'preferred' returns ILP64 routine if available,
433
+ and otherwise the 32-bit routine. Default: False
434
+
435
+ Returns
436
+ -------
437
+ funcs : list
438
+ List containing the found function(s).
439
+
440
+
441
+ Notes
442
+ -----
443
+ This routine automatically chooses between Fortran/C
444
+ interfaces. Fortran code is used whenever possible for arrays with
445
+ column major order. In all other cases, C code is preferred.
446
+
447
+ In BLAS, the naming convention is that all functions start with a
448
+ type prefix, which depends on the type of the principal
449
+ matrix. These can be one of {'s', 'd', 'c', 'z'} for the NumPy
450
+ types {float32, float64, complex64, complex128} respectively.
451
+ The code and the dtype are stored in attributes `typecode` and `dtype`
452
+ of the returned functions.
453
+
454
+ Examples
455
+ --------
456
+ >>> import numpy as np
457
+ >>> import scipy.linalg as LA
458
+ >>> rng = np.random.default_rng()
459
+ >>> a = rng.random((3,2))
460
+ >>> x_gemv = LA.get_blas_funcs('gemv', (a,))
461
+ >>> x_gemv.typecode
462
+ 'd'
463
+ >>> x_gemv = LA.get_blas_funcs('gemv',(a*1j,))
464
+ >>> x_gemv.typecode
465
+ 'z'
466
+
467
+ """
468
+ if isinstance(ilp64, str):
469
+ if ilp64 == 'preferred':
470
+ ilp64 = HAS_ILP64
471
+ else:
472
+ raise ValueError("Invalid value for 'ilp64'")
473
+
474
+ if not ilp64:
475
+ return _get_funcs(names, arrays, dtype,
476
+ "BLAS", _fblas, _cblas, "fblas", "cblas",
477
+ _blas_alias, ilp64=False)
478
+ else:
479
+ if not HAS_ILP64:
480
+ raise RuntimeError("BLAS ILP64 routine requested, but Scipy "
481
+ "compiled only with 32-bit BLAS")
482
+ return _get_funcs(names, arrays, dtype,
483
+ "BLAS", _fblas_64, None, "fblas_64", None,
484
+ _blas_alias, ilp64=True)
astra_scene_test/Scene_04/.venv/lib/python3.9/site-packages/scipy/linalg/cython_blas.pxd ADDED
@@ -0,0 +1,169 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """
2
+ This file was generated by _generate_pyx.py.
3
+ Do not edit this file directly.
4
+ """
5
+
6
+ # Within scipy, these wrappers can be used via relative or absolute cimport.
7
+ # Examples:
8
+ # from ..linalg cimport cython_blas
9
+ # from scipy.linalg cimport cython_blas
10
+ # cimport scipy.linalg.cython_blas as cython_blas
11
+ # cimport ..linalg.cython_blas as cython_blas
12
+
13
+ # Within SciPy, if BLAS functions are needed in C/C++/Fortran,
14
+ # these wrappers should not be used.
15
+ # The original libraries should be linked directly.
16
+
17
+ ctypedef float s
18
+ ctypedef double d
19
+ ctypedef float complex c
20
+ ctypedef double complex z
21
+
22
+ cdef void caxpy(int *n, c *ca, c *cx, int *incx, c *cy, int *incy) noexcept nogil
23
+ cdef void ccopy(int *n, c *cx, int *incx, c *cy, int *incy) noexcept nogil
24
+ cdef c cdotc(int *n, c *cx, int *incx, c *cy, int *incy) noexcept nogil
25
+ cdef c cdotu(int *n, c *cx, int *incx, c *cy, int *incy) noexcept nogil
26
+ cdef void cgbmv(char *trans, int *m, int *n, int *kl, int *ku, c *alpha, c *a, int *lda, c *x, int *incx, c *beta, c *y, int *incy) noexcept nogil
27
+ cdef void cgemm(char *transa, char *transb, int *m, int *n, int *k, c *alpha, c *a, int *lda, c *b, int *ldb, c *beta, c *c, int *ldc) noexcept nogil
28
+ cdef void cgemv(char *trans, int *m, int *n, c *alpha, c *a, int *lda, c *x, int *incx, c *beta, c *y, int *incy) noexcept nogil
29
+ cdef void cgerc(int *m, int *n, c *alpha, c *x, int *incx, c *y, int *incy, c *a, int *lda) noexcept nogil
30
+ cdef void cgeru(int *m, int *n, c *alpha, c *x, int *incx, c *y, int *incy, c *a, int *lda) noexcept nogil
31
+ cdef void chbmv(char *uplo, int *n, int *k, c *alpha, c *a, int *lda, c *x, int *incx, c *beta, c *y, int *incy) noexcept nogil
32
+ cdef void chemm(char *side, char *uplo, int *m, int *n, c *alpha, c *a, int *lda, c *b, int *ldb, c *beta, c *c, int *ldc) noexcept nogil
33
+ cdef void chemv(char *uplo, int *n, c *alpha, c *a, int *lda, c *x, int *incx, c *beta, c *y, int *incy) noexcept nogil
34
+ cdef void cher(char *uplo, int *n, s *alpha, c *x, int *incx, c *a, int *lda) noexcept nogil
35
+ cdef void cher2(char *uplo, int *n, c *alpha, c *x, int *incx, c *y, int *incy, c *a, int *lda) noexcept nogil
36
+ cdef void cher2k(char *uplo, char *trans, int *n, int *k, c *alpha, c *a, int *lda, c *b, int *ldb, s *beta, c *c, int *ldc) noexcept nogil
37
+ cdef void cherk(char *uplo, char *trans, int *n, int *k, s *alpha, c *a, int *lda, s *beta, c *c, int *ldc) noexcept nogil
38
+ cdef void chpmv(char *uplo, int *n, c *alpha, c *ap, c *x, int *incx, c *beta, c *y, int *incy) noexcept nogil
39
+ cdef void chpr(char *uplo, int *n, s *alpha, c *x, int *incx, c *ap) noexcept nogil
40
+ cdef void chpr2(char *uplo, int *n, c *alpha, c *x, int *incx, c *y, int *incy, c *ap) noexcept nogil
41
+ cdef void crotg(c *ca, c *cb, s *c, c *s) noexcept nogil
42
+ cdef void cscal(int *n, c *ca, c *cx, int *incx) noexcept nogil
43
+ cdef void csrot(int *n, c *cx, int *incx, c *cy, int *incy, s *c, s *s) noexcept nogil
44
+ cdef void csscal(int *n, s *sa, c *cx, int *incx) noexcept nogil
45
+ cdef void cswap(int *n, c *cx, int *incx, c *cy, int *incy) noexcept nogil
46
+ cdef void csymm(char *side, char *uplo, int *m, int *n, c *alpha, c *a, int *lda, c *b, int *ldb, c *beta, c *c, int *ldc) noexcept nogil
47
+ cdef void csyr2k(char *uplo, char *trans, int *n, int *k, c *alpha, c *a, int *lda, c *b, int *ldb, c *beta, c *c, int *ldc) noexcept nogil
48
+ cdef void csyrk(char *uplo, char *trans, int *n, int *k, c *alpha, c *a, int *lda, c *beta, c *c, int *ldc) noexcept nogil
49
+ cdef void ctbmv(char *uplo, char *trans, char *diag, int *n, int *k, c *a, int *lda, c *x, int *incx) noexcept nogil
50
+ cdef void ctbsv(char *uplo, char *trans, char *diag, int *n, int *k, c *a, int *lda, c *x, int *incx) noexcept nogil
51
+ cdef void ctpmv(char *uplo, char *trans, char *diag, int *n, c *ap, c *x, int *incx) noexcept nogil
52
+ cdef void ctpsv(char *uplo, char *trans, char *diag, int *n, c *ap, c *x, int *incx) noexcept nogil
53
+ cdef void ctrmm(char *side, char *uplo, char *transa, char *diag, int *m, int *n, c *alpha, c *a, int *lda, c *b, int *ldb) noexcept nogil
54
+ cdef void ctrmv(char *uplo, char *trans, char *diag, int *n, c *a, int *lda, c *x, int *incx) noexcept nogil
55
+ cdef void ctrsm(char *side, char *uplo, char *transa, char *diag, int *m, int *n, c *alpha, c *a, int *lda, c *b, int *ldb) noexcept nogil
56
+ cdef void ctrsv(char *uplo, char *trans, char *diag, int *n, c *a, int *lda, c *x, int *incx) noexcept nogil
57
+ cdef d dasum(int *n, d *dx, int *incx) noexcept nogil
58
+ cdef void daxpy(int *n, d *da, d *dx, int *incx, d *dy, int *incy) noexcept nogil
59
+ cdef d dcabs1(z *z) noexcept nogil
60
+ cdef void dcopy(int *n, d *dx, int *incx, d *dy, int *incy) noexcept nogil
61
+ cdef d ddot(int *n, d *dx, int *incx, d *dy, int *incy) noexcept nogil
62
+ cdef void dgbmv(char *trans, int *m, int *n, int *kl, int *ku, d *alpha, d *a, int *lda, d *x, int *incx, d *beta, d *y, int *incy) noexcept nogil
63
+ cdef void dgemm(char *transa, char *transb, int *m, int *n, int *k, d *alpha, d *a, int *lda, d *b, int *ldb, d *beta, d *c, int *ldc) noexcept nogil
64
+ cdef void dgemv(char *trans, int *m, int *n, d *alpha, d *a, int *lda, d *x, int *incx, d *beta, d *y, int *incy) noexcept nogil
65
+ cdef void dger(int *m, int *n, d *alpha, d *x, int *incx, d *y, int *incy, d *a, int *lda) noexcept nogil
66
+ cdef d dnrm2(int *n, d *x, int *incx) noexcept nogil
67
+ cdef void drot(int *n, d *dx, int *incx, d *dy, int *incy, d *c, d *s) noexcept nogil
68
+ cdef void drotg(d *da, d *db, d *c, d *s) noexcept nogil
69
+ cdef void drotm(int *n, d *dx, int *incx, d *dy, int *incy, d *dparam) noexcept nogil
70
+ cdef void drotmg(d *dd1, d *dd2, d *dx1, d *dy1, d *dparam) noexcept nogil
71
+ cdef void dsbmv(char *uplo, int *n, int *k, d *alpha, d *a, int *lda, d *x, int *incx, d *beta, d *y, int *incy) noexcept nogil
72
+ cdef void dscal(int *n, d *da, d *dx, int *incx) noexcept nogil
73
+ cdef d dsdot(int *n, s *sx, int *incx, s *sy, int *incy) noexcept nogil
74
+ cdef void dspmv(char *uplo, int *n, d *alpha, d *ap, d *x, int *incx, d *beta, d *y, int *incy) noexcept nogil
75
+ cdef void dspr(char *uplo, int *n, d *alpha, d *x, int *incx, d *ap) noexcept nogil
76
+ cdef void dspr2(char *uplo, int *n, d *alpha, d *x, int *incx, d *y, int *incy, d *ap) noexcept nogil
77
+ cdef void dswap(int *n, d *dx, int *incx, d *dy, int *incy) noexcept nogil
78
+ cdef void dsymm(char *side, char *uplo, int *m, int *n, d *alpha, d *a, int *lda, d *b, int *ldb, d *beta, d *c, int *ldc) noexcept nogil
79
+ cdef void dsymv(char *uplo, int *n, d *alpha, d *a, int *lda, d *x, int *incx, d *beta, d *y, int *incy) noexcept nogil
80
+ cdef void dsyr(char *uplo, int *n, d *alpha, d *x, int *incx, d *a, int *lda) noexcept nogil
81
+ cdef void dsyr2(char *uplo, int *n, d *alpha, d *x, int *incx, d *y, int *incy, d *a, int *lda) noexcept nogil
82
+ cdef void dsyr2k(char *uplo, char *trans, int *n, int *k, d *alpha, d *a, int *lda, d *b, int *ldb, d *beta, d *c, int *ldc) noexcept nogil
83
+ cdef void dsyrk(char *uplo, char *trans, int *n, int *k, d *alpha, d *a, int *lda, d *beta, d *c, int *ldc) noexcept nogil
84
+ cdef void dtbmv(char *uplo, char *trans, char *diag, int *n, int *k, d *a, int *lda, d *x, int *incx) noexcept nogil
85
+ cdef void dtbsv(char *uplo, char *trans, char *diag, int *n, int *k, d *a, int *lda, d *x, int *incx) noexcept nogil
86
+ cdef void dtpmv(char *uplo, char *trans, char *diag, int *n, d *ap, d *x, int *incx) noexcept nogil
87
+ cdef void dtpsv(char *uplo, char *trans, char *diag, int *n, d *ap, d *x, int *incx) noexcept nogil
88
+ cdef void dtrmm(char *side, char *uplo, char *transa, char *diag, int *m, int *n, d *alpha, d *a, int *lda, d *b, int *ldb) noexcept nogil
89
+ cdef void dtrmv(char *uplo, char *trans, char *diag, int *n, d *a, int *lda, d *x, int *incx) noexcept nogil
90
+ cdef void dtrsm(char *side, char *uplo, char *transa, char *diag, int *m, int *n, d *alpha, d *a, int *lda, d *b, int *ldb) noexcept nogil
91
+ cdef void dtrsv(char *uplo, char *trans, char *diag, int *n, d *a, int *lda, d *x, int *incx) noexcept nogil
92
+ cdef d dzasum(int *n, z *zx, int *incx) noexcept nogil
93
+ cdef d dznrm2(int *n, z *x, int *incx) noexcept nogil
94
+ cdef int icamax(int *n, c *cx, int *incx) noexcept nogil
95
+ cdef int idamax(int *n, d *dx, int *incx) noexcept nogil
96
+ cdef int isamax(int *n, s *sx, int *incx) noexcept nogil
97
+ cdef int izamax(int *n, z *zx, int *incx) noexcept nogil
98
+ cdef bint lsame(char *ca, char *cb) noexcept nogil
99
+ cdef s sasum(int *n, s *sx, int *incx) noexcept nogil
100
+ cdef void saxpy(int *n, s *sa, s *sx, int *incx, s *sy, int *incy) noexcept nogil
101
+ cdef s scasum(int *n, c *cx, int *incx) noexcept nogil
102
+ cdef s scnrm2(int *n, c *x, int *incx) noexcept nogil
103
+ cdef void scopy(int *n, s *sx, int *incx, s *sy, int *incy) noexcept nogil
104
+ cdef s sdot(int *n, s *sx, int *incx, s *sy, int *incy) noexcept nogil
105
+ cdef s sdsdot(int *n, s *sb, s *sx, int *incx, s *sy, int *incy) noexcept nogil
106
+ cdef void sgbmv(char *trans, int *m, int *n, int *kl, int *ku, s *alpha, s *a, int *lda, s *x, int *incx, s *beta, s *y, int *incy) noexcept nogil
107
+ cdef void sgemm(char *transa, char *transb, int *m, int *n, int *k, s *alpha, s *a, int *lda, s *b, int *ldb, s *beta, s *c, int *ldc) noexcept nogil
108
+ cdef void sgemv(char *trans, int *m, int *n, s *alpha, s *a, int *lda, s *x, int *incx, s *beta, s *y, int *incy) noexcept nogil
109
+ cdef void sger(int *m, int *n, s *alpha, s *x, int *incx, s *y, int *incy, s *a, int *lda) noexcept nogil
110
+ cdef s snrm2(int *n, s *x, int *incx) noexcept nogil
111
+ cdef void srot(int *n, s *sx, int *incx, s *sy, int *incy, s *c, s *s) noexcept nogil
112
+ cdef void srotg(s *sa, s *sb, s *c, s *s) noexcept nogil
113
+ cdef void srotm(int *n, s *sx, int *incx, s *sy, int *incy, s *sparam) noexcept nogil
114
+ cdef void srotmg(s *sd1, s *sd2, s *sx1, s *sy1, s *sparam) noexcept nogil
115
+ cdef void ssbmv(char *uplo, int *n, int *k, s *alpha, s *a, int *lda, s *x, int *incx, s *beta, s *y, int *incy) noexcept nogil
116
+ cdef void sscal(int *n, s *sa, s *sx, int *incx) noexcept nogil
117
+ cdef void sspmv(char *uplo, int *n, s *alpha, s *ap, s *x, int *incx, s *beta, s *y, int *incy) noexcept nogil
118
+ cdef void sspr(char *uplo, int *n, s *alpha, s *x, int *incx, s *ap) noexcept nogil
119
+ cdef void sspr2(char *uplo, int *n, s *alpha, s *x, int *incx, s *y, int *incy, s *ap) noexcept nogil
120
+ cdef void sswap(int *n, s *sx, int *incx, s *sy, int *incy) noexcept nogil
121
+ cdef void ssymm(char *side, char *uplo, int *m, int *n, s *alpha, s *a, int *lda, s *b, int *ldb, s *beta, s *c, int *ldc) noexcept nogil
122
+ cdef void ssymv(char *uplo, int *n, s *alpha, s *a, int *lda, s *x, int *incx, s *beta, s *y, int *incy) noexcept nogil
123
+ cdef void ssyr(char *uplo, int *n, s *alpha, s *x, int *incx, s *a, int *lda) noexcept nogil
124
+ cdef void ssyr2(char *uplo, int *n, s *alpha, s *x, int *incx, s *y, int *incy, s *a, int *lda) noexcept nogil
125
+ cdef void ssyr2k(char *uplo, char *trans, int *n, int *k, s *alpha, s *a, int *lda, s *b, int *ldb, s *beta, s *c, int *ldc) noexcept nogil
126
+ cdef void ssyrk(char *uplo, char *trans, int *n, int *k, s *alpha, s *a, int *lda, s *beta, s *c, int *ldc) noexcept nogil
127
+ cdef void stbmv(char *uplo, char *trans, char *diag, int *n, int *k, s *a, int *lda, s *x, int *incx) noexcept nogil
128
+ cdef void stbsv(char *uplo, char *trans, char *diag, int *n, int *k, s *a, int *lda, s *x, int *incx) noexcept nogil
129
+ cdef void stpmv(char *uplo, char *trans, char *diag, int *n, s *ap, s *x, int *incx) noexcept nogil
130
+ cdef void stpsv(char *uplo, char *trans, char *diag, int *n, s *ap, s *x, int *incx) noexcept nogil
131
+ cdef void strmm(char *side, char *uplo, char *transa, char *diag, int *m, int *n, s *alpha, s *a, int *lda, s *b, int *ldb) noexcept nogil
132
+ cdef void strmv(char *uplo, char *trans, char *diag, int *n, s *a, int *lda, s *x, int *incx) noexcept nogil
133
+ cdef void strsm(char *side, char *uplo, char *transa, char *diag, int *m, int *n, s *alpha, s *a, int *lda, s *b, int *ldb) noexcept nogil
134
+ cdef void strsv(char *uplo, char *trans, char *diag, int *n, s *a, int *lda, s *x, int *incx) noexcept nogil
135
+ cdef void zaxpy(int *n, z *za, z *zx, int *incx, z *zy, int *incy) noexcept nogil
136
+ cdef void zcopy(int *n, z *zx, int *incx, z *zy, int *incy) noexcept nogil
137
+ cdef z zdotc(int *n, z *zx, int *incx, z *zy, int *incy) noexcept nogil
138
+ cdef z zdotu(int *n, z *zx, int *incx, z *zy, int *incy) noexcept nogil
139
+ cdef void zdrot(int *n, z *cx, int *incx, z *cy, int *incy, d *c, d *s) noexcept nogil
140
+ cdef void zdscal(int *n, d *da, z *zx, int *incx) noexcept nogil
141
+ cdef void zgbmv(char *trans, int *m, int *n, int *kl, int *ku, z *alpha, z *a, int *lda, z *x, int *incx, z *beta, z *y, int *incy) noexcept nogil
142
+ cdef void zgemm(char *transa, char *transb, int *m, int *n, int *k, z *alpha, z *a, int *lda, z *b, int *ldb, z *beta, z *c, int *ldc) noexcept nogil
143
+ cdef void zgemv(char *trans, int *m, int *n, z *alpha, z *a, int *lda, z *x, int *incx, z *beta, z *y, int *incy) noexcept nogil
144
+ cdef void zgerc(int *m, int *n, z *alpha, z *x, int *incx, z *y, int *incy, z *a, int *lda) noexcept nogil
145
+ cdef void zgeru(int *m, int *n, z *alpha, z *x, int *incx, z *y, int *incy, z *a, int *lda) noexcept nogil
146
+ cdef void zhbmv(char *uplo, int *n, int *k, z *alpha, z *a, int *lda, z *x, int *incx, z *beta, z *y, int *incy) noexcept nogil
147
+ cdef void zhemm(char *side, char *uplo, int *m, int *n, z *alpha, z *a, int *lda, z *b, int *ldb, z *beta, z *c, int *ldc) noexcept nogil
148
+ cdef void zhemv(char *uplo, int *n, z *alpha, z *a, int *lda, z *x, int *incx, z *beta, z *y, int *incy) noexcept nogil
149
+ cdef void zher(char *uplo, int *n, d *alpha, z *x, int *incx, z *a, int *lda) noexcept nogil
150
+ cdef void zher2(char *uplo, int *n, z *alpha, z *x, int *incx, z *y, int *incy, z *a, int *lda) noexcept nogil
151
+ cdef void zher2k(char *uplo, char *trans, int *n, int *k, z *alpha, z *a, int *lda, z *b, int *ldb, d *beta, z *c, int *ldc) noexcept nogil
152
+ cdef void zherk(char *uplo, char *trans, int *n, int *k, d *alpha, z *a, int *lda, d *beta, z *c, int *ldc) noexcept nogil
153
+ cdef void zhpmv(char *uplo, int *n, z *alpha, z *ap, z *x, int *incx, z *beta, z *y, int *incy) noexcept nogil
154
+ cdef void zhpr(char *uplo, int *n, d *alpha, z *x, int *incx, z *ap) noexcept nogil
155
+ cdef void zhpr2(char *uplo, int *n, z *alpha, z *x, int *incx, z *y, int *incy, z *ap) noexcept nogil
156
+ cdef void zrotg(z *ca, z *cb, d *c, z *s) noexcept nogil
157
+ cdef void zscal(int *n, z *za, z *zx, int *incx) noexcept nogil
158
+ cdef void zswap(int *n, z *zx, int *incx, z *zy, int *incy) noexcept nogil
159
+ cdef void zsymm(char *side, char *uplo, int *m, int *n, z *alpha, z *a, int *lda, z *b, int *ldb, z *beta, z *c, int *ldc) noexcept nogil
160
+ cdef void zsyr2k(char *uplo, char *trans, int *n, int *k, z *alpha, z *a, int *lda, z *b, int *ldb, z *beta, z *c, int *ldc) noexcept nogil
161
+ cdef void zsyrk(char *uplo, char *trans, int *n, int *k, z *alpha, z *a, int *lda, z *beta, z *c, int *ldc) noexcept nogil
162
+ cdef void ztbmv(char *uplo, char *trans, char *diag, int *n, int *k, z *a, int *lda, z *x, int *incx) noexcept nogil
163
+ cdef void ztbsv(char *uplo, char *trans, char *diag, int *n, int *k, z *a, int *lda, z *x, int *incx) noexcept nogil
164
+ cdef void ztpmv(char *uplo, char *trans, char *diag, int *n, z *ap, z *x, int *incx) noexcept nogil
165
+ cdef void ztpsv(char *uplo, char *trans, char *diag, int *n, z *ap, z *x, int *incx) noexcept nogil
166
+ cdef void ztrmm(char *side, char *uplo, char *transa, char *diag, int *m, int *n, z *alpha, z *a, int *lda, z *b, int *ldb) noexcept nogil
167
+ cdef void ztrmv(char *uplo, char *trans, char *diag, int *n, z *a, int *lda, z *x, int *incx) noexcept nogil
168
+ cdef void ztrsm(char *side, char *uplo, char *transa, char *diag, int *m, int *n, z *alpha, z *a, int *lda, z *b, int *ldb) noexcept nogil
169
+ cdef void ztrsv(char *uplo, char *trans, char *diag, int *n, z *a, int *lda, z *x, int *incx) noexcept nogil
astra_scene_test/Scene_04/.venv/lib/python3.9/site-packages/scipy/linalg/cython_blas.pyx ADDED
@@ -0,0 +1,1422 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # This file was generated by _generate_pyx.py.
2
+ # Do not edit this file directly.
3
+ # cython: boundscheck = False
4
+ # cython: wraparound = False
5
+ # cython: cdivision = True
6
+
7
+ """
8
+ BLAS Functions for Cython
9
+ =========================
10
+
11
+ Usable from Cython via::
12
+
13
+ cimport scipy.linalg.cython_blas
14
+
15
+ These wrappers do not check for alignment of arrays.
16
+ Alignment should be checked before these wrappers are used.
17
+
18
+ Raw function pointers (Fortran-style pointer arguments):
19
+
20
+ - caxpy
21
+ - ccopy
22
+ - cdotc
23
+ - cdotu
24
+ - cgbmv
25
+ - cgemm
26
+ - cgemv
27
+ - cgerc
28
+ - cgeru
29
+ - chbmv
30
+ - chemm
31
+ - chemv
32
+ - cher
33
+ - cher2
34
+ - cher2k
35
+ - cherk
36
+ - chpmv
37
+ - chpr
38
+ - chpr2
39
+ - crotg
40
+ - cscal
41
+ - csrot
42
+ - csscal
43
+ - cswap
44
+ - csymm
45
+ - csyr2k
46
+ - csyrk
47
+ - ctbmv
48
+ - ctbsv
49
+ - ctpmv
50
+ - ctpsv
51
+ - ctrmm
52
+ - ctrmv
53
+ - ctrsm
54
+ - ctrsv
55
+ - dasum
56
+ - daxpy
57
+ - dcabs1
58
+ - dcopy
59
+ - ddot
60
+ - dgbmv
61
+ - dgemm
62
+ - dgemv
63
+ - dger
64
+ - dnrm2
65
+ - drot
66
+ - drotg
67
+ - drotm
68
+ - drotmg
69
+ - dsbmv
70
+ - dscal
71
+ - dsdot
72
+ - dspmv
73
+ - dspr
74
+ - dspr2
75
+ - dswap
76
+ - dsymm
77
+ - dsymv
78
+ - dsyr
79
+ - dsyr2
80
+ - dsyr2k
81
+ - dsyrk
82
+ - dtbmv
83
+ - dtbsv
84
+ - dtpmv
85
+ - dtpsv
86
+ - dtrmm
87
+ - dtrmv
88
+ - dtrsm
89
+ - dtrsv
90
+ - dzasum
91
+ - dznrm2
92
+ - icamax
93
+ - idamax
94
+ - isamax
95
+ - izamax
96
+ - lsame
97
+ - sasum
98
+ - saxpy
99
+ - scasum
100
+ - scnrm2
101
+ - scopy
102
+ - sdot
103
+ - sdsdot
104
+ - sgbmv
105
+ - sgemm
106
+ - sgemv
107
+ - sger
108
+ - snrm2
109
+ - srot
110
+ - srotg
111
+ - srotm
112
+ - srotmg
113
+ - ssbmv
114
+ - sscal
115
+ - sspmv
116
+ - sspr
117
+ - sspr2
118
+ - sswap
119
+ - ssymm
120
+ - ssymv
121
+ - ssyr
122
+ - ssyr2
123
+ - ssyr2k
124
+ - ssyrk
125
+ - stbmv
126
+ - stbsv
127
+ - stpmv
128
+ - stpsv
129
+ - strmm
130
+ - strmv
131
+ - strsm
132
+ - strsv
133
+ - zaxpy
134
+ - zcopy
135
+ - zdotc
136
+ - zdotu
137
+ - zdrot
138
+ - zdscal
139
+ - zgbmv
140
+ - zgemm
141
+ - zgemv
142
+ - zgerc
143
+ - zgeru
144
+ - zhbmv
145
+ - zhemm
146
+ - zhemv
147
+ - zher
148
+ - zher2
149
+ - zher2k
150
+ - zherk
151
+ - zhpmv
152
+ - zhpr
153
+ - zhpr2
154
+ - zrotg
155
+ - zscal
156
+ - zswap
157
+ - zsymm
158
+ - zsyr2k
159
+ - zsyrk
160
+ - ztbmv
161
+ - ztbsv
162
+ - ztpmv
163
+ - ztpsv
164
+ - ztrmm
165
+ - ztrmv
166
+ - ztrsm
167
+ - ztrsv
168
+
169
+
170
+ """
171
+
172
+ # Within SciPy, these wrappers can be used via relative or absolute cimport.
173
+ # Examples:
174
+ # from ..linalg cimport cython_blas
175
+ # from scipy.linalg cimport cython_blas
176
+ # cimport scipy.linalg.cython_blas as cython_blas
177
+ # cimport ..linalg.cython_blas as cython_blas
178
+
179
+ # Within SciPy, if BLAS functions are needed in C/C++/Fortran,
180
+ # these wrappers should not be used.
181
+ # The original libraries should be linked directly.
182
+
183
+ cdef extern from "fortran_defs.h":
184
+ pass
185
+
186
+ from numpy cimport npy_complex64, npy_complex128
187
+
188
+
189
+ cdef extern from "_blas_subroutines.h":
190
+ void _fortran_caxpy "BLAS_FUNC(caxpy)"(int *n, npy_complex64 *ca, npy_complex64 *cx, int *incx, npy_complex64 *cy, int *incy) nogil
191
+ cdef void caxpy(int *n, c *ca, c *cx, int *incx, c *cy, int *incy) noexcept nogil:
192
+
193
+ _fortran_caxpy(n, <npy_complex64*>ca, <npy_complex64*>cx, incx, <npy_complex64*>cy, incy)
194
+
195
+
196
+ cdef extern from "_blas_subroutines.h":
197
+ void _fortran_ccopy "BLAS_FUNC(ccopy)"(int *n, npy_complex64 *cx, int *incx, npy_complex64 *cy, int *incy) nogil
198
+ cdef void ccopy(int *n, c *cx, int *incx, c *cy, int *incy) noexcept nogil:
199
+
200
+ _fortran_ccopy(n, <npy_complex64*>cx, incx, <npy_complex64*>cy, incy)
201
+
202
+
203
+ cdef extern from "_blas_subroutines.h":
204
+ void _fortran_cdotc "(cdotcwrp_)"(npy_complex64 *out, int *n, npy_complex64 *cx, int *incx, npy_complex64 *cy, int *incy) nogil
205
+ cdef c cdotc(int *n, c *cx, int *incx, c *cy, int *incy) noexcept nogil:
206
+ cdef c out
207
+ _fortran_cdotc(<npy_complex64*>&out, n, <npy_complex64*>cx, incx, <npy_complex64*>cy, incy)
208
+ return out
209
+
210
+ cdef extern from "_blas_subroutines.h":
211
+ void _fortran_cdotu "(cdotuwrp_)"(npy_complex64 *out, int *n, npy_complex64 *cx, int *incx, npy_complex64 *cy, int *incy) nogil
212
+ cdef c cdotu(int *n, c *cx, int *incx, c *cy, int *incy) noexcept nogil:
213
+ cdef c out
214
+ _fortran_cdotu(<npy_complex64*>&out, n, <npy_complex64*>cx, incx, <npy_complex64*>cy, incy)
215
+ return out
216
+
217
+ cdef extern from "_blas_subroutines.h":
218
+ void _fortran_cgbmv "BLAS_FUNC(cgbmv)"(char *trans, int *m, int *n, int *kl, int *ku, npy_complex64 *alpha, npy_complex64 *a, int *lda, npy_complex64 *x, int *incx, npy_complex64 *beta, npy_complex64 *y, int *incy) nogil
219
+ cdef void cgbmv(char *trans, int *m, int *n, int *kl, int *ku, c *alpha, c *a, int *lda, c *x, int *incx, c *beta, c *y, int *incy) noexcept nogil:
220
+
221
+ _fortran_cgbmv(trans, m, n, kl, ku, <npy_complex64*>alpha, <npy_complex64*>a, lda, <npy_complex64*>x, incx, <npy_complex64*>beta, <npy_complex64*>y, incy)
222
+
223
+
224
+ cdef extern from "_blas_subroutines.h":
225
+ void _fortran_cgemm "BLAS_FUNC(cgemm)"(char *transa, char *transb, int *m, int *n, int *k, npy_complex64 *alpha, npy_complex64 *a, int *lda, npy_complex64 *b, int *ldb, npy_complex64 *beta, npy_complex64 *c, int *ldc) nogil
226
+ cdef void cgemm(char *transa, char *transb, int *m, int *n, int *k, c *alpha, c *a, int *lda, c *b, int *ldb, c *beta, c *c, int *ldc) noexcept nogil:
227
+
228
+ _fortran_cgemm(transa, transb, m, n, k, <npy_complex64*>alpha, <npy_complex64*>a, lda, <npy_complex64*>b, ldb, <npy_complex64*>beta, <npy_complex64*>c, ldc)
229
+
230
+
231
+ cdef extern from "_blas_subroutines.h":
232
+ void _fortran_cgemv "BLAS_FUNC(cgemv)"(char *trans, int *m, int *n, npy_complex64 *alpha, npy_complex64 *a, int *lda, npy_complex64 *x, int *incx, npy_complex64 *beta, npy_complex64 *y, int *incy) nogil
233
+ cdef void cgemv(char *trans, int *m, int *n, c *alpha, c *a, int *lda, c *x, int *incx, c *beta, c *y, int *incy) noexcept nogil:
234
+
235
+ _fortran_cgemv(trans, m, n, <npy_complex64*>alpha, <npy_complex64*>a, lda, <npy_complex64*>x, incx, <npy_complex64*>beta, <npy_complex64*>y, incy)
236
+
237
+
238
+ cdef extern from "_blas_subroutines.h":
239
+ void _fortran_cgerc "BLAS_FUNC(cgerc)"(int *m, int *n, npy_complex64 *alpha, npy_complex64 *x, int *incx, npy_complex64 *y, int *incy, npy_complex64 *a, int *lda) nogil
240
+ cdef void cgerc(int *m, int *n, c *alpha, c *x, int *incx, c *y, int *incy, c *a, int *lda) noexcept nogil:
241
+
242
+ _fortran_cgerc(m, n, <npy_complex64*>alpha, <npy_complex64*>x, incx, <npy_complex64*>y, incy, <npy_complex64*>a, lda)
243
+
244
+
245
+ cdef extern from "_blas_subroutines.h":
246
+ void _fortran_cgeru "BLAS_FUNC(cgeru)"(int *m, int *n, npy_complex64 *alpha, npy_complex64 *x, int *incx, npy_complex64 *y, int *incy, npy_complex64 *a, int *lda) nogil
247
+ cdef void cgeru(int *m, int *n, c *alpha, c *x, int *incx, c *y, int *incy, c *a, int *lda) noexcept nogil:
248
+
249
+ _fortran_cgeru(m, n, <npy_complex64*>alpha, <npy_complex64*>x, incx, <npy_complex64*>y, incy, <npy_complex64*>a, lda)
250
+
251
+
252
+ cdef extern from "_blas_subroutines.h":
253
+ void _fortran_chbmv "BLAS_FUNC(chbmv)"(char *uplo, int *n, int *k, npy_complex64 *alpha, npy_complex64 *a, int *lda, npy_complex64 *x, int *incx, npy_complex64 *beta, npy_complex64 *y, int *incy) nogil
254
+ cdef void chbmv(char *uplo, int *n, int *k, c *alpha, c *a, int *lda, c *x, int *incx, c *beta, c *y, int *incy) noexcept nogil:
255
+
256
+ _fortran_chbmv(uplo, n, k, <npy_complex64*>alpha, <npy_complex64*>a, lda, <npy_complex64*>x, incx, <npy_complex64*>beta, <npy_complex64*>y, incy)
257
+
258
+
259
+ cdef extern from "_blas_subroutines.h":
260
+ void _fortran_chemm "BLAS_FUNC(chemm)"(char *side, char *uplo, int *m, int *n, npy_complex64 *alpha, npy_complex64 *a, int *lda, npy_complex64 *b, int *ldb, npy_complex64 *beta, npy_complex64 *c, int *ldc) nogil
261
+ cdef void chemm(char *side, char *uplo, int *m, int *n, c *alpha, c *a, int *lda, c *b, int *ldb, c *beta, c *c, int *ldc) noexcept nogil:
262
+
263
+ _fortran_chemm(side, uplo, m, n, <npy_complex64*>alpha, <npy_complex64*>a, lda, <npy_complex64*>b, ldb, <npy_complex64*>beta, <npy_complex64*>c, ldc)
264
+
265
+
266
+ cdef extern from "_blas_subroutines.h":
267
+ void _fortran_chemv "BLAS_FUNC(chemv)"(char *uplo, int *n, npy_complex64 *alpha, npy_complex64 *a, int *lda, npy_complex64 *x, int *incx, npy_complex64 *beta, npy_complex64 *y, int *incy) nogil
268
+ cdef void chemv(char *uplo, int *n, c *alpha, c *a, int *lda, c *x, int *incx, c *beta, c *y, int *incy) noexcept nogil:
269
+
270
+ _fortran_chemv(uplo, n, <npy_complex64*>alpha, <npy_complex64*>a, lda, <npy_complex64*>x, incx, <npy_complex64*>beta, <npy_complex64*>y, incy)
271
+
272
+
273
+ cdef extern from "_blas_subroutines.h":
274
+ void _fortran_cher "BLAS_FUNC(cher)"(char *uplo, int *n, s *alpha, npy_complex64 *x, int *incx, npy_complex64 *a, int *lda) nogil
275
+ cdef void cher(char *uplo, int *n, s *alpha, c *x, int *incx, c *a, int *lda) noexcept nogil:
276
+
277
+ _fortran_cher(uplo, n, alpha, <npy_complex64*>x, incx, <npy_complex64*>a, lda)
278
+
279
+
280
+ cdef extern from "_blas_subroutines.h":
281
+ void _fortran_cher2 "BLAS_FUNC(cher2)"(char *uplo, int *n, npy_complex64 *alpha, npy_complex64 *x, int *incx, npy_complex64 *y, int *incy, npy_complex64 *a, int *lda) nogil
282
+ cdef void cher2(char *uplo, int *n, c *alpha, c *x, int *incx, c *y, int *incy, c *a, int *lda) noexcept nogil:
283
+
284
+ _fortran_cher2(uplo, n, <npy_complex64*>alpha, <npy_complex64*>x, incx, <npy_complex64*>y, incy, <npy_complex64*>a, lda)
285
+
286
+
287
+ cdef extern from "_blas_subroutines.h":
288
+ void _fortran_cher2k "BLAS_FUNC(cher2k)"(char *uplo, char *trans, int *n, int *k, npy_complex64 *alpha, npy_complex64 *a, int *lda, npy_complex64 *b, int *ldb, s *beta, npy_complex64 *c, int *ldc) nogil
289
+ cdef void cher2k(char *uplo, char *trans, int *n, int *k, c *alpha, c *a, int *lda, c *b, int *ldb, s *beta, c *c, int *ldc) noexcept nogil:
290
+
291
+ _fortran_cher2k(uplo, trans, n, k, <npy_complex64*>alpha, <npy_complex64*>a, lda, <npy_complex64*>b, ldb, beta, <npy_complex64*>c, ldc)
292
+
293
+
294
+ cdef extern from "_blas_subroutines.h":
295
+ void _fortran_cherk "BLAS_FUNC(cherk)"(char *uplo, char *trans, int *n, int *k, s *alpha, npy_complex64 *a, int *lda, s *beta, npy_complex64 *c, int *ldc) nogil
296
+ cdef void cherk(char *uplo, char *trans, int *n, int *k, s *alpha, c *a, int *lda, s *beta, c *c, int *ldc) noexcept nogil:
297
+
298
+ _fortran_cherk(uplo, trans, n, k, alpha, <npy_complex64*>a, lda, beta, <npy_complex64*>c, ldc)
299
+
300
+
301
+ cdef extern from "_blas_subroutines.h":
302
+ void _fortran_chpmv "BLAS_FUNC(chpmv)"(char *uplo, int *n, npy_complex64 *alpha, npy_complex64 *ap, npy_complex64 *x, int *incx, npy_complex64 *beta, npy_complex64 *y, int *incy) nogil
303
+ cdef void chpmv(char *uplo, int *n, c *alpha, c *ap, c *x, int *incx, c *beta, c *y, int *incy) noexcept nogil:
304
+
305
+ _fortran_chpmv(uplo, n, <npy_complex64*>alpha, <npy_complex64*>ap, <npy_complex64*>x, incx, <npy_complex64*>beta, <npy_complex64*>y, incy)
306
+
307
+
308
+ cdef extern from "_blas_subroutines.h":
309
+ void _fortran_chpr "BLAS_FUNC(chpr)"(char *uplo, int *n, s *alpha, npy_complex64 *x, int *incx, npy_complex64 *ap) nogil
310
+ cdef void chpr(char *uplo, int *n, s *alpha, c *x, int *incx, c *ap) noexcept nogil:
311
+
312
+ _fortran_chpr(uplo, n, alpha, <npy_complex64*>x, incx, <npy_complex64*>ap)
313
+
314
+
315
+ cdef extern from "_blas_subroutines.h":
316
+ void _fortran_chpr2 "BLAS_FUNC(chpr2)"(char *uplo, int *n, npy_complex64 *alpha, npy_complex64 *x, int *incx, npy_complex64 *y, int *incy, npy_complex64 *ap) nogil
317
+ cdef void chpr2(char *uplo, int *n, c *alpha, c *x, int *incx, c *y, int *incy, c *ap) noexcept nogil:
318
+
319
+ _fortran_chpr2(uplo, n, <npy_complex64*>alpha, <npy_complex64*>x, incx, <npy_complex64*>y, incy, <npy_complex64*>ap)
320
+
321
+
322
+ cdef extern from "_blas_subroutines.h":
323
+ void _fortran_crotg "BLAS_FUNC(crotg)"(npy_complex64 *ca, npy_complex64 *cb, s *c, npy_complex64 *s) nogil
324
+ cdef void crotg(c *ca, c *cb, s *c, c *s) noexcept nogil:
325
+
326
+ _fortran_crotg(<npy_complex64*>ca, <npy_complex64*>cb, c, <npy_complex64*>s)
327
+
328
+
329
+ cdef extern from "_blas_subroutines.h":
330
+ void _fortran_cscal "BLAS_FUNC(cscal)"(int *n, npy_complex64 *ca, npy_complex64 *cx, int *incx) nogil
331
+ cdef void cscal(int *n, c *ca, c *cx, int *incx) noexcept nogil:
332
+
333
+ _fortran_cscal(n, <npy_complex64*>ca, <npy_complex64*>cx, incx)
334
+
335
+
336
+ cdef extern from "_blas_subroutines.h":
337
+ void _fortran_csrot "BLAS_FUNC(csrot)"(int *n, npy_complex64 *cx, int *incx, npy_complex64 *cy, int *incy, s *c, s *s) nogil
338
+ cdef void csrot(int *n, c *cx, int *incx, c *cy, int *incy, s *c, s *s) noexcept nogil:
339
+
340
+ _fortran_csrot(n, <npy_complex64*>cx, incx, <npy_complex64*>cy, incy, c, s)
341
+
342
+
343
+ cdef extern from "_blas_subroutines.h":
344
+ void _fortran_csscal "BLAS_FUNC(csscal)"(int *n, s *sa, npy_complex64 *cx, int *incx) nogil
345
+ cdef void csscal(int *n, s *sa, c *cx, int *incx) noexcept nogil:
346
+
347
+ _fortran_csscal(n, sa, <npy_complex64*>cx, incx)
348
+
349
+
350
+ cdef extern from "_blas_subroutines.h":
351
+ void _fortran_cswap "BLAS_FUNC(cswap)"(int *n, npy_complex64 *cx, int *incx, npy_complex64 *cy, int *incy) nogil
352
+ cdef void cswap(int *n, c *cx, int *incx, c *cy, int *incy) noexcept nogil:
353
+
354
+ _fortran_cswap(n, <npy_complex64*>cx, incx, <npy_complex64*>cy, incy)
355
+
356
+
357
+ cdef extern from "_blas_subroutines.h":
358
+ void _fortran_csymm "BLAS_FUNC(csymm)"(char *side, char *uplo, int *m, int *n, npy_complex64 *alpha, npy_complex64 *a, int *lda, npy_complex64 *b, int *ldb, npy_complex64 *beta, npy_complex64 *c, int *ldc) nogil
359
+ cdef void csymm(char *side, char *uplo, int *m, int *n, c *alpha, c *a, int *lda, c *b, int *ldb, c *beta, c *c, int *ldc) noexcept nogil:
360
+
361
+ _fortran_csymm(side, uplo, m, n, <npy_complex64*>alpha, <npy_complex64*>a, lda, <npy_complex64*>b, ldb, <npy_complex64*>beta, <npy_complex64*>c, ldc)
362
+
363
+
364
+ cdef extern from "_blas_subroutines.h":
365
+ void _fortran_csyr2k "BLAS_FUNC(csyr2k)"(char *uplo, char *trans, int *n, int *k, npy_complex64 *alpha, npy_complex64 *a, int *lda, npy_complex64 *b, int *ldb, npy_complex64 *beta, npy_complex64 *c, int *ldc) nogil
366
+ cdef void csyr2k(char *uplo, char *trans, int *n, int *k, c *alpha, c *a, int *lda, c *b, int *ldb, c *beta, c *c, int *ldc) noexcept nogil:
367
+
368
+ _fortran_csyr2k(uplo, trans, n, k, <npy_complex64*>alpha, <npy_complex64*>a, lda, <npy_complex64*>b, ldb, <npy_complex64*>beta, <npy_complex64*>c, ldc)
369
+
370
+
371
+ cdef extern from "_blas_subroutines.h":
372
+ void _fortran_csyrk "BLAS_FUNC(csyrk)"(char *uplo, char *trans, int *n, int *k, npy_complex64 *alpha, npy_complex64 *a, int *lda, npy_complex64 *beta, npy_complex64 *c, int *ldc) nogil
373
+ cdef void csyrk(char *uplo, char *trans, int *n, int *k, c *alpha, c *a, int *lda, c *beta, c *c, int *ldc) noexcept nogil:
374
+
375
+ _fortran_csyrk(uplo, trans, n, k, <npy_complex64*>alpha, <npy_complex64*>a, lda, <npy_complex64*>beta, <npy_complex64*>c, ldc)
376
+
377
+
378
+ cdef extern from "_blas_subroutines.h":
379
+ void _fortran_ctbmv "BLAS_FUNC(ctbmv)"(char *uplo, char *trans, char *diag, int *n, int *k, npy_complex64 *a, int *lda, npy_complex64 *x, int *incx) nogil
380
+ cdef void ctbmv(char *uplo, char *trans, char *diag, int *n, int *k, c *a, int *lda, c *x, int *incx) noexcept nogil:
381
+
382
+ _fortran_ctbmv(uplo, trans, diag, n, k, <npy_complex64*>a, lda, <npy_complex64*>x, incx)
383
+
384
+
385
+ cdef extern from "_blas_subroutines.h":
386
+ void _fortran_ctbsv "BLAS_FUNC(ctbsv)"(char *uplo, char *trans, char *diag, int *n, int *k, npy_complex64 *a, int *lda, npy_complex64 *x, int *incx) nogil
387
+ cdef void ctbsv(char *uplo, char *trans, char *diag, int *n, int *k, c *a, int *lda, c *x, int *incx) noexcept nogil:
388
+
389
+ _fortran_ctbsv(uplo, trans, diag, n, k, <npy_complex64*>a, lda, <npy_complex64*>x, incx)
390
+
391
+
392
+ cdef extern from "_blas_subroutines.h":
393
+ void _fortran_ctpmv "BLAS_FUNC(ctpmv)"(char *uplo, char *trans, char *diag, int *n, npy_complex64 *ap, npy_complex64 *x, int *incx) nogil
394
+ cdef void ctpmv(char *uplo, char *trans, char *diag, int *n, c *ap, c *x, int *incx) noexcept nogil:
395
+
396
+ _fortran_ctpmv(uplo, trans, diag, n, <npy_complex64*>ap, <npy_complex64*>x, incx)
397
+
398
+
399
+ cdef extern from "_blas_subroutines.h":
400
+ void _fortran_ctpsv "BLAS_FUNC(ctpsv)"(char *uplo, char *trans, char *diag, int *n, npy_complex64 *ap, npy_complex64 *x, int *incx) nogil
401
+ cdef void ctpsv(char *uplo, char *trans, char *diag, int *n, c *ap, c *x, int *incx) noexcept nogil:
402
+
403
+ _fortran_ctpsv(uplo, trans, diag, n, <npy_complex64*>ap, <npy_complex64*>x, incx)
404
+
405
+
406
+ cdef extern from "_blas_subroutines.h":
407
+ void _fortran_ctrmm "BLAS_FUNC(ctrmm)"(char *side, char *uplo, char *transa, char *diag, int *m, int *n, npy_complex64 *alpha, npy_complex64 *a, int *lda, npy_complex64 *b, int *ldb) nogil
408
+ cdef void ctrmm(char *side, char *uplo, char *transa, char *diag, int *m, int *n, c *alpha, c *a, int *lda, c *b, int *ldb) noexcept nogil:
409
+
410
+ _fortran_ctrmm(side, uplo, transa, diag, m, n, <npy_complex64*>alpha, <npy_complex64*>a, lda, <npy_complex64*>b, ldb)
411
+
412
+
413
+ cdef extern from "_blas_subroutines.h":
414
+ void _fortran_ctrmv "BLAS_FUNC(ctrmv)"(char *uplo, char *trans, char *diag, int *n, npy_complex64 *a, int *lda, npy_complex64 *x, int *incx) nogil
415
+ cdef void ctrmv(char *uplo, char *trans, char *diag, int *n, c *a, int *lda, c *x, int *incx) noexcept nogil:
416
+
417
+ _fortran_ctrmv(uplo, trans, diag, n, <npy_complex64*>a, lda, <npy_complex64*>x, incx)
418
+
419
+
420
+ cdef extern from "_blas_subroutines.h":
421
+ void _fortran_ctrsm "BLAS_FUNC(ctrsm)"(char *side, char *uplo, char *transa, char *diag, int *m, int *n, npy_complex64 *alpha, npy_complex64 *a, int *lda, npy_complex64 *b, int *ldb) nogil
422
+ cdef void ctrsm(char *side, char *uplo, char *transa, char *diag, int *m, int *n, c *alpha, c *a, int *lda, c *b, int *ldb) noexcept nogil:
423
+
424
+ _fortran_ctrsm(side, uplo, transa, diag, m, n, <npy_complex64*>alpha, <npy_complex64*>a, lda, <npy_complex64*>b, ldb)
425
+
426
+
427
+ cdef extern from "_blas_subroutines.h":
428
+ void _fortran_ctrsv "BLAS_FUNC(ctrsv)"(char *uplo, char *trans, char *diag, int *n, npy_complex64 *a, int *lda, npy_complex64 *x, int *incx) nogil
429
+ cdef void ctrsv(char *uplo, char *trans, char *diag, int *n, c *a, int *lda, c *x, int *incx) noexcept nogil:
430
+
431
+ _fortran_ctrsv(uplo, trans, diag, n, <npy_complex64*>a, lda, <npy_complex64*>x, incx)
432
+
433
+
434
+ cdef extern from "_blas_subroutines.h":
435
+ d _fortran_dasum "BLAS_FUNC(dasum)"(int *n, d *dx, int *incx) nogil
436
+ cdef d dasum(int *n, d *dx, int *incx) noexcept nogil:
437
+
438
+ return _fortran_dasum(n, dx, incx)
439
+
440
+
441
+ cdef extern from "_blas_subroutines.h":
442
+ void _fortran_daxpy "BLAS_FUNC(daxpy)"(int *n, d *da, d *dx, int *incx, d *dy, int *incy) nogil
443
+ cdef void daxpy(int *n, d *da, d *dx, int *incx, d *dy, int *incy) noexcept nogil:
444
+
445
+ _fortran_daxpy(n, da, dx, incx, dy, incy)
446
+
447
+
448
+ cdef extern from "_blas_subroutines.h":
449
+ d _fortran_dcabs1 "BLAS_FUNC(dcabs1)"(npy_complex128 *z) nogil
450
+ cdef d dcabs1(z *z) noexcept nogil:
451
+
452
+ return _fortran_dcabs1(<npy_complex128*>z)
453
+
454
+
455
+ cdef extern from "_blas_subroutines.h":
456
+ void _fortran_dcopy "BLAS_FUNC(dcopy)"(int *n, d *dx, int *incx, d *dy, int *incy) nogil
457
+ cdef void dcopy(int *n, d *dx, int *incx, d *dy, int *incy) noexcept nogil:
458
+
459
+ _fortran_dcopy(n, dx, incx, dy, incy)
460
+
461
+
462
+ cdef extern from "_blas_subroutines.h":
463
+ d _fortran_ddot "BLAS_FUNC(ddot)"(int *n, d *dx, int *incx, d *dy, int *incy) nogil
464
+ cdef d ddot(int *n, d *dx, int *incx, d *dy, int *incy) noexcept nogil:
465
+
466
+ return _fortran_ddot(n, dx, incx, dy, incy)
467
+
468
+
469
+ cdef extern from "_blas_subroutines.h":
470
+ void _fortran_dgbmv "BLAS_FUNC(dgbmv)"(char *trans, int *m, int *n, int *kl, int *ku, d *alpha, d *a, int *lda, d *x, int *incx, d *beta, d *y, int *incy) nogil
471
+ cdef void dgbmv(char *trans, int *m, int *n, int *kl, int *ku, d *alpha, d *a, int *lda, d *x, int *incx, d *beta, d *y, int *incy) noexcept nogil:
472
+
473
+ _fortran_dgbmv(trans, m, n, kl, ku, alpha, a, lda, x, incx, beta, y, incy)
474
+
475
+
476
+ cdef extern from "_blas_subroutines.h":
477
+ void _fortran_dgemm "BLAS_FUNC(dgemm)"(char *transa, char *transb, int *m, int *n, int *k, d *alpha, d *a, int *lda, d *b, int *ldb, d *beta, d *c, int *ldc) nogil
478
+ cdef void dgemm(char *transa, char *transb, int *m, int *n, int *k, d *alpha, d *a, int *lda, d *b, int *ldb, d *beta, d *c, int *ldc) noexcept nogil:
479
+
480
+ _fortran_dgemm(transa, transb, m, n, k, alpha, a, lda, b, ldb, beta, c, ldc)
481
+
482
+
483
+ cdef extern from "_blas_subroutines.h":
484
+ void _fortran_dgemv "BLAS_FUNC(dgemv)"(char *trans, int *m, int *n, d *alpha, d *a, int *lda, d *x, int *incx, d *beta, d *y, int *incy) nogil
485
+ cdef void dgemv(char *trans, int *m, int *n, d *alpha, d *a, int *lda, d *x, int *incx, d *beta, d *y, int *incy) noexcept nogil:
486
+
487
+ _fortran_dgemv(trans, m, n, alpha, a, lda, x, incx, beta, y, incy)
488
+
489
+
490
+ cdef extern from "_blas_subroutines.h":
491
+ void _fortran_dger "BLAS_FUNC(dger)"(int *m, int *n, d *alpha, d *x, int *incx, d *y, int *incy, d *a, int *lda) nogil
492
+ cdef void dger(int *m, int *n, d *alpha, d *x, int *incx, d *y, int *incy, d *a, int *lda) noexcept nogil:
493
+
494
+ _fortran_dger(m, n, alpha, x, incx, y, incy, a, lda)
495
+
496
+
497
+ cdef extern from "_blas_subroutines.h":
498
+ d _fortran_dnrm2 "BLAS_FUNC(dnrm2)"(int *n, d *x, int *incx) nogil
499
+ cdef d dnrm2(int *n, d *x, int *incx) noexcept nogil:
500
+
501
+ return _fortran_dnrm2(n, x, incx)
502
+
503
+
504
+ cdef extern from "_blas_subroutines.h":
505
+ void _fortran_drot "BLAS_FUNC(drot)"(int *n, d *dx, int *incx, d *dy, int *incy, d *c, d *s) nogil
506
+ cdef void drot(int *n, d *dx, int *incx, d *dy, int *incy, d *c, d *s) noexcept nogil:
507
+
508
+ _fortran_drot(n, dx, incx, dy, incy, c, s)
509
+
510
+
511
+ cdef extern from "_blas_subroutines.h":
512
+ void _fortran_drotg "BLAS_FUNC(drotg)"(d *da, d *db, d *c, d *s) nogil
513
+ cdef void drotg(d *da, d *db, d *c, d *s) noexcept nogil:
514
+
515
+ _fortran_drotg(da, db, c, s)
516
+
517
+
518
+ cdef extern from "_blas_subroutines.h":
519
+ void _fortran_drotm "BLAS_FUNC(drotm)"(int *n, d *dx, int *incx, d *dy, int *incy, d *dparam) nogil
520
+ cdef void drotm(int *n, d *dx, int *incx, d *dy, int *incy, d *dparam) noexcept nogil:
521
+
522
+ _fortran_drotm(n, dx, incx, dy, incy, dparam)
523
+
524
+
525
+ cdef extern from "_blas_subroutines.h":
526
+ void _fortran_drotmg "BLAS_FUNC(drotmg)"(d *dd1, d *dd2, d *dx1, d *dy1, d *dparam) nogil
527
+ cdef void drotmg(d *dd1, d *dd2, d *dx1, d *dy1, d *dparam) noexcept nogil:
528
+
529
+ _fortran_drotmg(dd1, dd2, dx1, dy1, dparam)
530
+
531
+
532
+ cdef extern from "_blas_subroutines.h":
533
+ void _fortran_dsbmv "BLAS_FUNC(dsbmv)"(char *uplo, int *n, int *k, d *alpha, d *a, int *lda, d *x, int *incx, d *beta, d *y, int *incy) nogil
534
+ cdef void dsbmv(char *uplo, int *n, int *k, d *alpha, d *a, int *lda, d *x, int *incx, d *beta, d *y, int *incy) noexcept nogil:
535
+
536
+ _fortran_dsbmv(uplo, n, k, alpha, a, lda, x, incx, beta, y, incy)
537
+
538
+
539
+ cdef extern from "_blas_subroutines.h":
540
+ void _fortran_dscal "BLAS_FUNC(dscal)"(int *n, d *da, d *dx, int *incx) nogil
541
+ cdef void dscal(int *n, d *da, d *dx, int *incx) noexcept nogil:
542
+
543
+ _fortran_dscal(n, da, dx, incx)
544
+
545
+
546
+ cdef extern from "_blas_subroutines.h":
547
+ d _fortran_dsdot "BLAS_FUNC(dsdot)"(int *n, s *sx, int *incx, s *sy, int *incy) nogil
548
+ cdef d dsdot(int *n, s *sx, int *incx, s *sy, int *incy) noexcept nogil:
549
+
550
+ return _fortran_dsdot(n, sx, incx, sy, incy)
551
+
552
+
553
+ cdef extern from "_blas_subroutines.h":
554
+ void _fortran_dspmv "BLAS_FUNC(dspmv)"(char *uplo, int *n, d *alpha, d *ap, d *x, int *incx, d *beta, d *y, int *incy) nogil
555
+ cdef void dspmv(char *uplo, int *n, d *alpha, d *ap, d *x, int *incx, d *beta, d *y, int *incy) noexcept nogil:
556
+
557
+ _fortran_dspmv(uplo, n, alpha, ap, x, incx, beta, y, incy)
558
+
559
+
560
+ cdef extern from "_blas_subroutines.h":
561
+ void _fortran_dspr "BLAS_FUNC(dspr)"(char *uplo, int *n, d *alpha, d *x, int *incx, d *ap) nogil
562
+ cdef void dspr(char *uplo, int *n, d *alpha, d *x, int *incx, d *ap) noexcept nogil:
563
+
564
+ _fortran_dspr(uplo, n, alpha, x, incx, ap)
565
+
566
+
567
+ cdef extern from "_blas_subroutines.h":
568
+ void _fortran_dspr2 "BLAS_FUNC(dspr2)"(char *uplo, int *n, d *alpha, d *x, int *incx, d *y, int *incy, d *ap) nogil
569
+ cdef void dspr2(char *uplo, int *n, d *alpha, d *x, int *incx, d *y, int *incy, d *ap) noexcept nogil:
570
+
571
+ _fortran_dspr2(uplo, n, alpha, x, incx, y, incy, ap)
572
+
573
+
574
+ cdef extern from "_blas_subroutines.h":
575
+ void _fortran_dswap "BLAS_FUNC(dswap)"(int *n, d *dx, int *incx, d *dy, int *incy) nogil
576
+ cdef void dswap(int *n, d *dx, int *incx, d *dy, int *incy) noexcept nogil:
577
+
578
+ _fortran_dswap(n, dx, incx, dy, incy)
579
+
580
+
581
+ cdef extern from "_blas_subroutines.h":
582
+ void _fortran_dsymm "BLAS_FUNC(dsymm)"(char *side, char *uplo, int *m, int *n, d *alpha, d *a, int *lda, d *b, int *ldb, d *beta, d *c, int *ldc) nogil
583
+ cdef void dsymm(char *side, char *uplo, int *m, int *n, d *alpha, d *a, int *lda, d *b, int *ldb, d *beta, d *c, int *ldc) noexcept nogil:
584
+
585
+ _fortran_dsymm(side, uplo, m, n, alpha, a, lda, b, ldb, beta, c, ldc)
586
+
587
+
588
+ cdef extern from "_blas_subroutines.h":
589
+ void _fortran_dsymv "BLAS_FUNC(dsymv)"(char *uplo, int *n, d *alpha, d *a, int *lda, d *x, int *incx, d *beta, d *y, int *incy) nogil
590
+ cdef void dsymv(char *uplo, int *n, d *alpha, d *a, int *lda, d *x, int *incx, d *beta, d *y, int *incy) noexcept nogil:
591
+
592
+ _fortran_dsymv(uplo, n, alpha, a, lda, x, incx, beta, y, incy)
593
+
594
+
595
+ cdef extern from "_blas_subroutines.h":
596
+ void _fortran_dsyr "BLAS_FUNC(dsyr)"(char *uplo, int *n, d *alpha, d *x, int *incx, d *a, int *lda) nogil
597
+ cdef void dsyr(char *uplo, int *n, d *alpha, d *x, int *incx, d *a, int *lda) noexcept nogil:
598
+
599
+ _fortran_dsyr(uplo, n, alpha, x, incx, a, lda)
600
+
601
+
602
+ cdef extern from "_blas_subroutines.h":
603
+ void _fortran_dsyr2 "BLAS_FUNC(dsyr2)"(char *uplo, int *n, d *alpha, d *x, int *incx, d *y, int *incy, d *a, int *lda) nogil
604
+ cdef void dsyr2(char *uplo, int *n, d *alpha, d *x, int *incx, d *y, int *incy, d *a, int *lda) noexcept nogil:
605
+
606
+ _fortran_dsyr2(uplo, n, alpha, x, incx, y, incy, a, lda)
607
+
608
+
609
+ cdef extern from "_blas_subroutines.h":
610
+ void _fortran_dsyr2k "BLAS_FUNC(dsyr2k)"(char *uplo, char *trans, int *n, int *k, d *alpha, d *a, int *lda, d *b, int *ldb, d *beta, d *c, int *ldc) nogil
611
+ cdef void dsyr2k(char *uplo, char *trans, int *n, int *k, d *alpha, d *a, int *lda, d *b, int *ldb, d *beta, d *c, int *ldc) noexcept nogil:
612
+
613
+ _fortran_dsyr2k(uplo, trans, n, k, alpha, a, lda, b, ldb, beta, c, ldc)
614
+
615
+
616
+ cdef extern from "_blas_subroutines.h":
617
+ void _fortran_dsyrk "BLAS_FUNC(dsyrk)"(char *uplo, char *trans, int *n, int *k, d *alpha, d *a, int *lda, d *beta, d *c, int *ldc) nogil
618
+ cdef void dsyrk(char *uplo, char *trans, int *n, int *k, d *alpha, d *a, int *lda, d *beta, d *c, int *ldc) noexcept nogil:
619
+
620
+ _fortran_dsyrk(uplo, trans, n, k, alpha, a, lda, beta, c, ldc)
621
+
622
+
623
+ cdef extern from "_blas_subroutines.h":
624
+ void _fortran_dtbmv "BLAS_FUNC(dtbmv)"(char *uplo, char *trans, char *diag, int *n, int *k, d *a, int *lda, d *x, int *incx) nogil
625
+ cdef void dtbmv(char *uplo, char *trans, char *diag, int *n, int *k, d *a, int *lda, d *x, int *incx) noexcept nogil:
626
+
627
+ _fortran_dtbmv(uplo, trans, diag, n, k, a, lda, x, incx)
628
+
629
+
630
+ cdef extern from "_blas_subroutines.h":
631
+ void _fortran_dtbsv "BLAS_FUNC(dtbsv)"(char *uplo, char *trans, char *diag, int *n, int *k, d *a, int *lda, d *x, int *incx) nogil
632
+ cdef void dtbsv(char *uplo, char *trans, char *diag, int *n, int *k, d *a, int *lda, d *x, int *incx) noexcept nogil:
633
+
634
+ _fortran_dtbsv(uplo, trans, diag, n, k, a, lda, x, incx)
635
+
636
+
637
+ cdef extern from "_blas_subroutines.h":
638
+ void _fortran_dtpmv "BLAS_FUNC(dtpmv)"(char *uplo, char *trans, char *diag, int *n, d *ap, d *x, int *incx) nogil
639
+ cdef void dtpmv(char *uplo, char *trans, char *diag, int *n, d *ap, d *x, int *incx) noexcept nogil:
640
+
641
+ _fortran_dtpmv(uplo, trans, diag, n, ap, x, incx)
642
+
643
+
644
+ cdef extern from "_blas_subroutines.h":
645
+ void _fortran_dtpsv "BLAS_FUNC(dtpsv)"(char *uplo, char *trans, char *diag, int *n, d *ap, d *x, int *incx) nogil
646
+ cdef void dtpsv(char *uplo, char *trans, char *diag, int *n, d *ap, d *x, int *incx) noexcept nogil:
647
+
648
+ _fortran_dtpsv(uplo, trans, diag, n, ap, x, incx)
649
+
650
+
651
+ cdef extern from "_blas_subroutines.h":
652
+ void _fortran_dtrmm "BLAS_FUNC(dtrmm)"(char *side, char *uplo, char *transa, char *diag, int *m, int *n, d *alpha, d *a, int *lda, d *b, int *ldb) nogil
653
+ cdef void dtrmm(char *side, char *uplo, char *transa, char *diag, int *m, int *n, d *alpha, d *a, int *lda, d *b, int *ldb) noexcept nogil:
654
+
655
+ _fortran_dtrmm(side, uplo, transa, diag, m, n, alpha, a, lda, b, ldb)
656
+
657
+
658
+ cdef extern from "_blas_subroutines.h":
659
+ void _fortran_dtrmv "BLAS_FUNC(dtrmv)"(char *uplo, char *trans, char *diag, int *n, d *a, int *lda, d *x, int *incx) nogil
660
+ cdef void dtrmv(char *uplo, char *trans, char *diag, int *n, d *a, int *lda, d *x, int *incx) noexcept nogil:
661
+
662
+ _fortran_dtrmv(uplo, trans, diag, n, a, lda, x, incx)
663
+
664
+
665
+ cdef extern from "_blas_subroutines.h":
666
+ void _fortran_dtrsm "BLAS_FUNC(dtrsm)"(char *side, char *uplo, char *transa, char *diag, int *m, int *n, d *alpha, d *a, int *lda, d *b, int *ldb) nogil
667
+ cdef void dtrsm(char *side, char *uplo, char *transa, char *diag, int *m, int *n, d *alpha, d *a, int *lda, d *b, int *ldb) noexcept nogil:
668
+
669
+ _fortran_dtrsm(side, uplo, transa, diag, m, n, alpha, a, lda, b, ldb)
670
+
671
+
672
+ cdef extern from "_blas_subroutines.h":
673
+ void _fortran_dtrsv "BLAS_FUNC(dtrsv)"(char *uplo, char *trans, char *diag, int *n, d *a, int *lda, d *x, int *incx) nogil
674
+ cdef void dtrsv(char *uplo, char *trans, char *diag, int *n, d *a, int *lda, d *x, int *incx) noexcept nogil:
675
+
676
+ _fortran_dtrsv(uplo, trans, diag, n, a, lda, x, incx)
677
+
678
+
679
+ cdef extern from "_blas_subroutines.h":
680
+ d _fortran_dzasum "BLAS_FUNC(dzasum)"(int *n, npy_complex128 *zx, int *incx) nogil
681
+ cdef d dzasum(int *n, z *zx, int *incx) noexcept nogil:
682
+
683
+ return _fortran_dzasum(n, <npy_complex128*>zx, incx)
684
+
685
+
686
+ cdef extern from "_blas_subroutines.h":
687
+ d _fortran_dznrm2 "BLAS_FUNC(dznrm2)"(int *n, npy_complex128 *x, int *incx) nogil
688
+ cdef d dznrm2(int *n, z *x, int *incx) noexcept nogil:
689
+
690
+ return _fortran_dznrm2(n, <npy_complex128*>x, incx)
691
+
692
+
693
+ cdef extern from "_blas_subroutines.h":
694
+ int _fortran_icamax "BLAS_FUNC(icamax)"(int *n, npy_complex64 *cx, int *incx) nogil
695
+ cdef int icamax(int *n, c *cx, int *incx) noexcept nogil:
696
+
697
+ return _fortran_icamax(n, <npy_complex64*>cx, incx)
698
+
699
+
700
+ cdef extern from "_blas_subroutines.h":
701
+ int _fortran_idamax "BLAS_FUNC(idamax)"(int *n, d *dx, int *incx) nogil
702
+ cdef int idamax(int *n, d *dx, int *incx) noexcept nogil:
703
+
704
+ return _fortran_idamax(n, dx, incx)
705
+
706
+
707
+ cdef extern from "_blas_subroutines.h":
708
+ int _fortran_isamax "BLAS_FUNC(isamax)"(int *n, s *sx, int *incx) nogil
709
+ cdef int isamax(int *n, s *sx, int *incx) noexcept nogil:
710
+
711
+ return _fortran_isamax(n, sx, incx)
712
+
713
+
714
+ cdef extern from "_blas_subroutines.h":
715
+ int _fortran_izamax "BLAS_FUNC(izamax)"(int *n, npy_complex128 *zx, int *incx) nogil
716
+ cdef int izamax(int *n, z *zx, int *incx) noexcept nogil:
717
+
718
+ return _fortran_izamax(n, <npy_complex128*>zx, incx)
719
+
720
+
721
+ cdef extern from "_blas_subroutines.h":
722
+ bint _fortran_lsame "BLAS_FUNC(lsame)"(char *ca, char *cb) nogil
723
+ cdef bint lsame(char *ca, char *cb) noexcept nogil:
724
+
725
+ return _fortran_lsame(ca, cb)
726
+
727
+
728
+ cdef extern from "_blas_subroutines.h":
729
+ s _fortran_sasum "BLAS_FUNC(sasum)"(int *n, s *sx, int *incx) nogil
730
+ cdef s sasum(int *n, s *sx, int *incx) noexcept nogil:
731
+
732
+ return _fortran_sasum(n, sx, incx)
733
+
734
+
735
+ cdef extern from "_blas_subroutines.h":
736
+ void _fortran_saxpy "BLAS_FUNC(saxpy)"(int *n, s *sa, s *sx, int *incx, s *sy, int *incy) nogil
737
+ cdef void saxpy(int *n, s *sa, s *sx, int *incx, s *sy, int *incy) noexcept nogil:
738
+
739
+ _fortran_saxpy(n, sa, sx, incx, sy, incy)
740
+
741
+
742
+ cdef extern from "_blas_subroutines.h":
743
+ s _fortran_scasum "BLAS_FUNC(scasum)"(int *n, npy_complex64 *cx, int *incx) nogil
744
+ cdef s scasum(int *n, c *cx, int *incx) noexcept nogil:
745
+
746
+ return _fortran_scasum(n, <npy_complex64*>cx, incx)
747
+
748
+
749
+ cdef extern from "_blas_subroutines.h":
750
+ s _fortran_scnrm2 "BLAS_FUNC(scnrm2)"(int *n, npy_complex64 *x, int *incx) nogil
751
+ cdef s scnrm2(int *n, c *x, int *incx) noexcept nogil:
752
+
753
+ return _fortran_scnrm2(n, <npy_complex64*>x, incx)
754
+
755
+
756
+ cdef extern from "_blas_subroutines.h":
757
+ void _fortran_scopy "BLAS_FUNC(scopy)"(int *n, s *sx, int *incx, s *sy, int *incy) nogil
758
+ cdef void scopy(int *n, s *sx, int *incx, s *sy, int *incy) noexcept nogil:
759
+
760
+ _fortran_scopy(n, sx, incx, sy, incy)
761
+
762
+
763
+ cdef extern from "_blas_subroutines.h":
764
+ s _fortran_sdot "BLAS_FUNC(sdot)"(int *n, s *sx, int *incx, s *sy, int *incy) nogil
765
+ cdef s sdot(int *n, s *sx, int *incx, s *sy, int *incy) noexcept nogil:
766
+
767
+ return _fortran_sdot(n, sx, incx, sy, incy)
768
+
769
+
770
+ cdef extern from "_blas_subroutines.h":
771
+ s _fortran_sdsdot "BLAS_FUNC(sdsdot)"(int *n, s *sb, s *sx, int *incx, s *sy, int *incy) nogil
772
+ cdef s sdsdot(int *n, s *sb, s *sx, int *incx, s *sy, int *incy) noexcept nogil:
773
+
774
+ return _fortran_sdsdot(n, sb, sx, incx, sy, incy)
775
+
776
+
777
+ cdef extern from "_blas_subroutines.h":
778
+ void _fortran_sgbmv "BLAS_FUNC(sgbmv)"(char *trans, int *m, int *n, int *kl, int *ku, s *alpha, s *a, int *lda, s *x, int *incx, s *beta, s *y, int *incy) nogil
779
+ cdef void sgbmv(char *trans, int *m, int *n, int *kl, int *ku, s *alpha, s *a, int *lda, s *x, int *incx, s *beta, s *y, int *incy) noexcept nogil:
780
+
781
+ _fortran_sgbmv(trans, m, n, kl, ku, alpha, a, lda, x, incx, beta, y, incy)
782
+
783
+
784
+ cdef extern from "_blas_subroutines.h":
785
+ void _fortran_sgemm "BLAS_FUNC(sgemm)"(char *transa, char *transb, int *m, int *n, int *k, s *alpha, s *a, int *lda, s *b, int *ldb, s *beta, s *c, int *ldc) nogil
786
+ cdef void sgemm(char *transa, char *transb, int *m, int *n, int *k, s *alpha, s *a, int *lda, s *b, int *ldb, s *beta, s *c, int *ldc) noexcept nogil:
787
+
788
+ _fortran_sgemm(transa, transb, m, n, k, alpha, a, lda, b, ldb, beta, c, ldc)
789
+
790
+
791
+ cdef extern from "_blas_subroutines.h":
792
+ void _fortran_sgemv "BLAS_FUNC(sgemv)"(char *trans, int *m, int *n, s *alpha, s *a, int *lda, s *x, int *incx, s *beta, s *y, int *incy) nogil
793
+ cdef void sgemv(char *trans, int *m, int *n, s *alpha, s *a, int *lda, s *x, int *incx, s *beta, s *y, int *incy) noexcept nogil:
794
+
795
+ _fortran_sgemv(trans, m, n, alpha, a, lda, x, incx, beta, y, incy)
796
+
797
+
798
+ cdef extern from "_blas_subroutines.h":
799
+ void _fortran_sger "BLAS_FUNC(sger)"(int *m, int *n, s *alpha, s *x, int *incx, s *y, int *incy, s *a, int *lda) nogil
800
+ cdef void sger(int *m, int *n, s *alpha, s *x, int *incx, s *y, int *incy, s *a, int *lda) noexcept nogil:
801
+
802
+ _fortran_sger(m, n, alpha, x, incx, y, incy, a, lda)
803
+
804
+
805
+ cdef extern from "_blas_subroutines.h":
806
+ s _fortran_snrm2 "BLAS_FUNC(snrm2)"(int *n, s *x, int *incx) nogil
807
+ cdef s snrm2(int *n, s *x, int *incx) noexcept nogil:
808
+
809
+ return _fortran_snrm2(n, x, incx)
810
+
811
+
812
+ cdef extern from "_blas_subroutines.h":
813
+ void _fortran_srot "BLAS_FUNC(srot)"(int *n, s *sx, int *incx, s *sy, int *incy, s *c, s *s) nogil
814
+ cdef void srot(int *n, s *sx, int *incx, s *sy, int *incy, s *c, s *s) noexcept nogil:
815
+
816
+ _fortran_srot(n, sx, incx, sy, incy, c, s)
817
+
818
+
819
+ cdef extern from "_blas_subroutines.h":
820
+ void _fortran_srotg "BLAS_FUNC(srotg)"(s *sa, s *sb, s *c, s *s) nogil
821
+ cdef void srotg(s *sa, s *sb, s *c, s *s) noexcept nogil:
822
+
823
+ _fortran_srotg(sa, sb, c, s)
824
+
825
+
826
+ cdef extern from "_blas_subroutines.h":
827
+ void _fortran_srotm "BLAS_FUNC(srotm)"(int *n, s *sx, int *incx, s *sy, int *incy, s *sparam) nogil
828
+ cdef void srotm(int *n, s *sx, int *incx, s *sy, int *incy, s *sparam) noexcept nogil:
829
+
830
+ _fortran_srotm(n, sx, incx, sy, incy, sparam)
831
+
832
+
833
+ cdef extern from "_blas_subroutines.h":
834
+ void _fortran_srotmg "BLAS_FUNC(srotmg)"(s *sd1, s *sd2, s *sx1, s *sy1, s *sparam) nogil
835
+ cdef void srotmg(s *sd1, s *sd2, s *sx1, s *sy1, s *sparam) noexcept nogil:
836
+
837
+ _fortran_srotmg(sd1, sd2, sx1, sy1, sparam)
838
+
839
+
840
+ cdef extern from "_blas_subroutines.h":
841
+ void _fortran_ssbmv "BLAS_FUNC(ssbmv)"(char *uplo, int *n, int *k, s *alpha, s *a, int *lda, s *x, int *incx, s *beta, s *y, int *incy) nogil
842
+ cdef void ssbmv(char *uplo, int *n, int *k, s *alpha, s *a, int *lda, s *x, int *incx, s *beta, s *y, int *incy) noexcept nogil:
843
+
844
+ _fortran_ssbmv(uplo, n, k, alpha, a, lda, x, incx, beta, y, incy)
845
+
846
+
847
+ cdef extern from "_blas_subroutines.h":
848
+ void _fortran_sscal "BLAS_FUNC(sscal)"(int *n, s *sa, s *sx, int *incx) nogil
849
+ cdef void sscal(int *n, s *sa, s *sx, int *incx) noexcept nogil:
850
+
851
+ _fortran_sscal(n, sa, sx, incx)
852
+
853
+
854
+ cdef extern from "_blas_subroutines.h":
855
+ void _fortran_sspmv "BLAS_FUNC(sspmv)"(char *uplo, int *n, s *alpha, s *ap, s *x, int *incx, s *beta, s *y, int *incy) nogil
856
+ cdef void sspmv(char *uplo, int *n, s *alpha, s *ap, s *x, int *incx, s *beta, s *y, int *incy) noexcept nogil:
857
+
858
+ _fortran_sspmv(uplo, n, alpha, ap, x, incx, beta, y, incy)
859
+
860
+
861
+ cdef extern from "_blas_subroutines.h":
862
+ void _fortran_sspr "BLAS_FUNC(sspr)"(char *uplo, int *n, s *alpha, s *x, int *incx, s *ap) nogil
863
+ cdef void sspr(char *uplo, int *n, s *alpha, s *x, int *incx, s *ap) noexcept nogil:
864
+
865
+ _fortran_sspr(uplo, n, alpha, x, incx, ap)
866
+
867
+
868
+ cdef extern from "_blas_subroutines.h":
869
+ void _fortran_sspr2 "BLAS_FUNC(sspr2)"(char *uplo, int *n, s *alpha, s *x, int *incx, s *y, int *incy, s *ap) nogil
870
+ cdef void sspr2(char *uplo, int *n, s *alpha, s *x, int *incx, s *y, int *incy, s *ap) noexcept nogil:
871
+
872
+ _fortran_sspr2(uplo, n, alpha, x, incx, y, incy, ap)
873
+
874
+
875
+ cdef extern from "_blas_subroutines.h":
876
+ void _fortran_sswap "BLAS_FUNC(sswap)"(int *n, s *sx, int *incx, s *sy, int *incy) nogil
877
+ cdef void sswap(int *n, s *sx, int *incx, s *sy, int *incy) noexcept nogil:
878
+
879
+ _fortran_sswap(n, sx, incx, sy, incy)
880
+
881
+
882
+ cdef extern from "_blas_subroutines.h":
883
+ void _fortran_ssymm "BLAS_FUNC(ssymm)"(char *side, char *uplo, int *m, int *n, s *alpha, s *a, int *lda, s *b, int *ldb, s *beta, s *c, int *ldc) nogil
884
+ cdef void ssymm(char *side, char *uplo, int *m, int *n, s *alpha, s *a, int *lda, s *b, int *ldb, s *beta, s *c, int *ldc) noexcept nogil:
885
+
886
+ _fortran_ssymm(side, uplo, m, n, alpha, a, lda, b, ldb, beta, c, ldc)
887
+
888
+
889
+ cdef extern from "_blas_subroutines.h":
890
+ void _fortran_ssymv "BLAS_FUNC(ssymv)"(char *uplo, int *n, s *alpha, s *a, int *lda, s *x, int *incx, s *beta, s *y, int *incy) nogil
891
+ cdef void ssymv(char *uplo, int *n, s *alpha, s *a, int *lda, s *x, int *incx, s *beta, s *y, int *incy) noexcept nogil:
892
+
893
+ _fortran_ssymv(uplo, n, alpha, a, lda, x, incx, beta, y, incy)
894
+
895
+
896
+ cdef extern from "_blas_subroutines.h":
897
+ void _fortran_ssyr "BLAS_FUNC(ssyr)"(char *uplo, int *n, s *alpha, s *x, int *incx, s *a, int *lda) nogil
898
+ cdef void ssyr(char *uplo, int *n, s *alpha, s *x, int *incx, s *a, int *lda) noexcept nogil:
899
+
900
+ _fortran_ssyr(uplo, n, alpha, x, incx, a, lda)
901
+
902
+
903
+ cdef extern from "_blas_subroutines.h":
904
+ void _fortran_ssyr2 "BLAS_FUNC(ssyr2)"(char *uplo, int *n, s *alpha, s *x, int *incx, s *y, int *incy, s *a, int *lda) nogil
905
+ cdef void ssyr2(char *uplo, int *n, s *alpha, s *x, int *incx, s *y, int *incy, s *a, int *lda) noexcept nogil:
906
+
907
+ _fortran_ssyr2(uplo, n, alpha, x, incx, y, incy, a, lda)
908
+
909
+
910
+ cdef extern from "_blas_subroutines.h":
911
+ void _fortran_ssyr2k "BLAS_FUNC(ssyr2k)"(char *uplo, char *trans, int *n, int *k, s *alpha, s *a, int *lda, s *b, int *ldb, s *beta, s *c, int *ldc) nogil
912
+ cdef void ssyr2k(char *uplo, char *trans, int *n, int *k, s *alpha, s *a, int *lda, s *b, int *ldb, s *beta, s *c, int *ldc) noexcept nogil:
913
+
914
+ _fortran_ssyr2k(uplo, trans, n, k, alpha, a, lda, b, ldb, beta, c, ldc)
915
+
916
+
917
+ cdef extern from "_blas_subroutines.h":
918
+ void _fortran_ssyrk "BLAS_FUNC(ssyrk)"(char *uplo, char *trans, int *n, int *k, s *alpha, s *a, int *lda, s *beta, s *c, int *ldc) nogil
919
+ cdef void ssyrk(char *uplo, char *trans, int *n, int *k, s *alpha, s *a, int *lda, s *beta, s *c, int *ldc) noexcept nogil:
920
+
921
+ _fortran_ssyrk(uplo, trans, n, k, alpha, a, lda, beta, c, ldc)
922
+
923
+
924
+ cdef extern from "_blas_subroutines.h":
925
+ void _fortran_stbmv "BLAS_FUNC(stbmv)"(char *uplo, char *trans, char *diag, int *n, int *k, s *a, int *lda, s *x, int *incx) nogil
926
+ cdef void stbmv(char *uplo, char *trans, char *diag, int *n, int *k, s *a, int *lda, s *x, int *incx) noexcept nogil:
927
+
928
+ _fortran_stbmv(uplo, trans, diag, n, k, a, lda, x, incx)
929
+
930
+
931
+ cdef extern from "_blas_subroutines.h":
932
+ void _fortran_stbsv "BLAS_FUNC(stbsv)"(char *uplo, char *trans, char *diag, int *n, int *k, s *a, int *lda, s *x, int *incx) nogil
933
+ cdef void stbsv(char *uplo, char *trans, char *diag, int *n, int *k, s *a, int *lda, s *x, int *incx) noexcept nogil:
934
+
935
+ _fortran_stbsv(uplo, trans, diag, n, k, a, lda, x, incx)
936
+
937
+
938
+ cdef extern from "_blas_subroutines.h":
939
+ void _fortran_stpmv "BLAS_FUNC(stpmv)"(char *uplo, char *trans, char *diag, int *n, s *ap, s *x, int *incx) nogil
940
+ cdef void stpmv(char *uplo, char *trans, char *diag, int *n, s *ap, s *x, int *incx) noexcept nogil:
941
+
942
+ _fortran_stpmv(uplo, trans, diag, n, ap, x, incx)
943
+
944
+
945
+ cdef extern from "_blas_subroutines.h":
946
+ void _fortran_stpsv "BLAS_FUNC(stpsv)"(char *uplo, char *trans, char *diag, int *n, s *ap, s *x, int *incx) nogil
947
+ cdef void stpsv(char *uplo, char *trans, char *diag, int *n, s *ap, s *x, int *incx) noexcept nogil:
948
+
949
+ _fortran_stpsv(uplo, trans, diag, n, ap, x, incx)
950
+
951
+
952
+ cdef extern from "_blas_subroutines.h":
953
+ void _fortran_strmm "BLAS_FUNC(strmm)"(char *side, char *uplo, char *transa, char *diag, int *m, int *n, s *alpha, s *a, int *lda, s *b, int *ldb) nogil
954
+ cdef void strmm(char *side, char *uplo, char *transa, char *diag, int *m, int *n, s *alpha, s *a, int *lda, s *b, int *ldb) noexcept nogil:
955
+
956
+ _fortran_strmm(side, uplo, transa, diag, m, n, alpha, a, lda, b, ldb)
957
+
958
+
959
+ cdef extern from "_blas_subroutines.h":
960
+ void _fortran_strmv "BLAS_FUNC(strmv)"(char *uplo, char *trans, char *diag, int *n, s *a, int *lda, s *x, int *incx) nogil
961
+ cdef void strmv(char *uplo, char *trans, char *diag, int *n, s *a, int *lda, s *x, int *incx) noexcept nogil:
962
+
963
+ _fortran_strmv(uplo, trans, diag, n, a, lda, x, incx)
964
+
965
+
966
+ cdef extern from "_blas_subroutines.h":
967
+ void _fortran_strsm "BLAS_FUNC(strsm)"(char *side, char *uplo, char *transa, char *diag, int *m, int *n, s *alpha, s *a, int *lda, s *b, int *ldb) nogil
968
+ cdef void strsm(char *side, char *uplo, char *transa, char *diag, int *m, int *n, s *alpha, s *a, int *lda, s *b, int *ldb) noexcept nogil:
969
+
970
+ _fortran_strsm(side, uplo, transa, diag, m, n, alpha, a, lda, b, ldb)
971
+
972
+
973
+ cdef extern from "_blas_subroutines.h":
974
+ void _fortran_strsv "BLAS_FUNC(strsv)"(char *uplo, char *trans, char *diag, int *n, s *a, int *lda, s *x, int *incx) nogil
975
+ cdef void strsv(char *uplo, char *trans, char *diag, int *n, s *a, int *lda, s *x, int *incx) noexcept nogil:
976
+
977
+ _fortran_strsv(uplo, trans, diag, n, a, lda, x, incx)
978
+
979
+
980
+ cdef extern from "_blas_subroutines.h":
981
+ void _fortran_zaxpy "BLAS_FUNC(zaxpy)"(int *n, npy_complex128 *za, npy_complex128 *zx, int *incx, npy_complex128 *zy, int *incy) nogil
982
+ cdef void zaxpy(int *n, z *za, z *zx, int *incx, z *zy, int *incy) noexcept nogil:
983
+
984
+ _fortran_zaxpy(n, <npy_complex128*>za, <npy_complex128*>zx, incx, <npy_complex128*>zy, incy)
985
+
986
+
987
+ cdef extern from "_blas_subroutines.h":
988
+ void _fortran_zcopy "BLAS_FUNC(zcopy)"(int *n, npy_complex128 *zx, int *incx, npy_complex128 *zy, int *incy) nogil
989
+ cdef void zcopy(int *n, z *zx, int *incx, z *zy, int *incy) noexcept nogil:
990
+
991
+ _fortran_zcopy(n, <npy_complex128*>zx, incx, <npy_complex128*>zy, incy)
992
+
993
+
994
+ cdef extern from "_blas_subroutines.h":
995
+ void _fortran_zdotc "(zdotcwrp_)"(npy_complex128 *out, int *n, npy_complex128 *zx, int *incx, npy_complex128 *zy, int *incy) nogil
996
+ cdef z zdotc(int *n, z *zx, int *incx, z *zy, int *incy) noexcept nogil:
997
+ cdef z out
998
+ _fortran_zdotc(<npy_complex128*>&out, n, <npy_complex128*>zx, incx, <npy_complex128*>zy, incy)
999
+ return out
1000
+
1001
+ cdef extern from "_blas_subroutines.h":
1002
+ void _fortran_zdotu "(zdotuwrp_)"(npy_complex128 *out, int *n, npy_complex128 *zx, int *incx, npy_complex128 *zy, int *incy) nogil
1003
+ cdef z zdotu(int *n, z *zx, int *incx, z *zy, int *incy) noexcept nogil:
1004
+ cdef z out
1005
+ _fortran_zdotu(<npy_complex128*>&out, n, <npy_complex128*>zx, incx, <npy_complex128*>zy, incy)
1006
+ return out
1007
+
1008
+ cdef extern from "_blas_subroutines.h":
1009
+ void _fortran_zdrot "BLAS_FUNC(zdrot)"(int *n, npy_complex128 *cx, int *incx, npy_complex128 *cy, int *incy, d *c, d *s) nogil
1010
+ cdef void zdrot(int *n, z *cx, int *incx, z *cy, int *incy, d *c, d *s) noexcept nogil:
1011
+
1012
+ _fortran_zdrot(n, <npy_complex128*>cx, incx, <npy_complex128*>cy, incy, c, s)
1013
+
1014
+
1015
+ cdef extern from "_blas_subroutines.h":
1016
+ void _fortran_zdscal "BLAS_FUNC(zdscal)"(int *n, d *da, npy_complex128 *zx, int *incx) nogil
1017
+ cdef void zdscal(int *n, d *da, z *zx, int *incx) noexcept nogil:
1018
+
1019
+ _fortran_zdscal(n, da, <npy_complex128*>zx, incx)
1020
+
1021
+
1022
+ cdef extern from "_blas_subroutines.h":
1023
+ void _fortran_zgbmv "BLAS_FUNC(zgbmv)"(char *trans, int *m, int *n, int *kl, int *ku, npy_complex128 *alpha, npy_complex128 *a, int *lda, npy_complex128 *x, int *incx, npy_complex128 *beta, npy_complex128 *y, int *incy) nogil
1024
+ cdef void zgbmv(char *trans, int *m, int *n, int *kl, int *ku, z *alpha, z *a, int *lda, z *x, int *incx, z *beta, z *y, int *incy) noexcept nogil:
1025
+
1026
+ _fortran_zgbmv(trans, m, n, kl, ku, <npy_complex128*>alpha, <npy_complex128*>a, lda, <npy_complex128*>x, incx, <npy_complex128*>beta, <npy_complex128*>y, incy)
1027
+
1028
+
1029
+ cdef extern from "_blas_subroutines.h":
1030
+ void _fortran_zgemm "BLAS_FUNC(zgemm)"(char *transa, char *transb, int *m, int *n, int *k, npy_complex128 *alpha, npy_complex128 *a, int *lda, npy_complex128 *b, int *ldb, npy_complex128 *beta, npy_complex128 *c, int *ldc) nogil
1031
+ cdef void zgemm(char *transa, char *transb, int *m, int *n, int *k, z *alpha, z *a, int *lda, z *b, int *ldb, z *beta, z *c, int *ldc) noexcept nogil:
1032
+
1033
+ _fortran_zgemm(transa, transb, m, n, k, <npy_complex128*>alpha, <npy_complex128*>a, lda, <npy_complex128*>b, ldb, <npy_complex128*>beta, <npy_complex128*>c, ldc)
1034
+
1035
+
1036
+ cdef extern from "_blas_subroutines.h":
1037
+ void _fortran_zgemv "BLAS_FUNC(zgemv)"(char *trans, int *m, int *n, npy_complex128 *alpha, npy_complex128 *a, int *lda, npy_complex128 *x, int *incx, npy_complex128 *beta, npy_complex128 *y, int *incy) nogil
1038
+ cdef void zgemv(char *trans, int *m, int *n, z *alpha, z *a, int *lda, z *x, int *incx, z *beta, z *y, int *incy) noexcept nogil:
1039
+
1040
+ _fortran_zgemv(trans, m, n, <npy_complex128*>alpha, <npy_complex128*>a, lda, <npy_complex128*>x, incx, <npy_complex128*>beta, <npy_complex128*>y, incy)
1041
+
1042
+
1043
+ cdef extern from "_blas_subroutines.h":
1044
+ void _fortran_zgerc "BLAS_FUNC(zgerc)"(int *m, int *n, npy_complex128 *alpha, npy_complex128 *x, int *incx, npy_complex128 *y, int *incy, npy_complex128 *a, int *lda) nogil
1045
+ cdef void zgerc(int *m, int *n, z *alpha, z *x, int *incx, z *y, int *incy, z *a, int *lda) noexcept nogil:
1046
+
1047
+ _fortran_zgerc(m, n, <npy_complex128*>alpha, <npy_complex128*>x, incx, <npy_complex128*>y, incy, <npy_complex128*>a, lda)
1048
+
1049
+
1050
+ cdef extern from "_blas_subroutines.h":
1051
+ void _fortran_zgeru "BLAS_FUNC(zgeru)"(int *m, int *n, npy_complex128 *alpha, npy_complex128 *x, int *incx, npy_complex128 *y, int *incy, npy_complex128 *a, int *lda) nogil
1052
+ cdef void zgeru(int *m, int *n, z *alpha, z *x, int *incx, z *y, int *incy, z *a, int *lda) noexcept nogil:
1053
+
1054
+ _fortran_zgeru(m, n, <npy_complex128*>alpha, <npy_complex128*>x, incx, <npy_complex128*>y, incy, <npy_complex128*>a, lda)
1055
+
1056
+
1057
+ cdef extern from "_blas_subroutines.h":
1058
+ void _fortran_zhbmv "BLAS_FUNC(zhbmv)"(char *uplo, int *n, int *k, npy_complex128 *alpha, npy_complex128 *a, int *lda, npy_complex128 *x, int *incx, npy_complex128 *beta, npy_complex128 *y, int *incy) nogil
1059
+ cdef void zhbmv(char *uplo, int *n, int *k, z *alpha, z *a, int *lda, z *x, int *incx, z *beta, z *y, int *incy) noexcept nogil:
1060
+
1061
+ _fortran_zhbmv(uplo, n, k, <npy_complex128*>alpha, <npy_complex128*>a, lda, <npy_complex128*>x, incx, <npy_complex128*>beta, <npy_complex128*>y, incy)
1062
+
1063
+
1064
+ cdef extern from "_blas_subroutines.h":
1065
+ void _fortran_zhemm "BLAS_FUNC(zhemm)"(char *side, char *uplo, int *m, int *n, npy_complex128 *alpha, npy_complex128 *a, int *lda, npy_complex128 *b, int *ldb, npy_complex128 *beta, npy_complex128 *c, int *ldc) nogil
1066
+ cdef void zhemm(char *side, char *uplo, int *m, int *n, z *alpha, z *a, int *lda, z *b, int *ldb, z *beta, z *c, int *ldc) noexcept nogil:
1067
+
1068
+ _fortran_zhemm(side, uplo, m, n, <npy_complex128*>alpha, <npy_complex128*>a, lda, <npy_complex128*>b, ldb, <npy_complex128*>beta, <npy_complex128*>c, ldc)
1069
+
1070
+
1071
+ cdef extern from "_blas_subroutines.h":
1072
+ void _fortran_zhemv "BLAS_FUNC(zhemv)"(char *uplo, int *n, npy_complex128 *alpha, npy_complex128 *a, int *lda, npy_complex128 *x, int *incx, npy_complex128 *beta, npy_complex128 *y, int *incy) nogil
1073
+ cdef void zhemv(char *uplo, int *n, z *alpha, z *a, int *lda, z *x, int *incx, z *beta, z *y, int *incy) noexcept nogil:
1074
+
1075
+ _fortran_zhemv(uplo, n, <npy_complex128*>alpha, <npy_complex128*>a, lda, <npy_complex128*>x, incx, <npy_complex128*>beta, <npy_complex128*>y, incy)
1076
+
1077
+
1078
+ cdef extern from "_blas_subroutines.h":
1079
+ void _fortran_zher "BLAS_FUNC(zher)"(char *uplo, int *n, d *alpha, npy_complex128 *x, int *incx, npy_complex128 *a, int *lda) nogil
1080
+ cdef void zher(char *uplo, int *n, d *alpha, z *x, int *incx, z *a, int *lda) noexcept nogil:
1081
+
1082
+ _fortran_zher(uplo, n, alpha, <npy_complex128*>x, incx, <npy_complex128*>a, lda)
1083
+
1084
+
1085
+ cdef extern from "_blas_subroutines.h":
1086
+ void _fortran_zher2 "BLAS_FUNC(zher2)"(char *uplo, int *n, npy_complex128 *alpha, npy_complex128 *x, int *incx, npy_complex128 *y, int *incy, npy_complex128 *a, int *lda) nogil
1087
+ cdef void zher2(char *uplo, int *n, z *alpha, z *x, int *incx, z *y, int *incy, z *a, int *lda) noexcept nogil:
1088
+
1089
+ _fortran_zher2(uplo, n, <npy_complex128*>alpha, <npy_complex128*>x, incx, <npy_complex128*>y, incy, <npy_complex128*>a, lda)
1090
+
1091
+
1092
+ cdef extern from "_blas_subroutines.h":
1093
+ void _fortran_zher2k "BLAS_FUNC(zher2k)"(char *uplo, char *trans, int *n, int *k, npy_complex128 *alpha, npy_complex128 *a, int *lda, npy_complex128 *b, int *ldb, d *beta, npy_complex128 *c, int *ldc) nogil
1094
+ cdef void zher2k(char *uplo, char *trans, int *n, int *k, z *alpha, z *a, int *lda, z *b, int *ldb, d *beta, z *c, int *ldc) noexcept nogil:
1095
+
1096
+ _fortran_zher2k(uplo, trans, n, k, <npy_complex128*>alpha, <npy_complex128*>a, lda, <npy_complex128*>b, ldb, beta, <npy_complex128*>c, ldc)
1097
+
1098
+
1099
+ cdef extern from "_blas_subroutines.h":
1100
+ void _fortran_zherk "BLAS_FUNC(zherk)"(char *uplo, char *trans, int *n, int *k, d *alpha, npy_complex128 *a, int *lda, d *beta, npy_complex128 *c, int *ldc) nogil
1101
+ cdef void zherk(char *uplo, char *trans, int *n, int *k, d *alpha, z *a, int *lda, d *beta, z *c, int *ldc) noexcept nogil:
1102
+
1103
+ _fortran_zherk(uplo, trans, n, k, alpha, <npy_complex128*>a, lda, beta, <npy_complex128*>c, ldc)
1104
+
1105
+
1106
+ cdef extern from "_blas_subroutines.h":
1107
+ void _fortran_zhpmv "BLAS_FUNC(zhpmv)"(char *uplo, int *n, npy_complex128 *alpha, npy_complex128 *ap, npy_complex128 *x, int *incx, npy_complex128 *beta, npy_complex128 *y, int *incy) nogil
1108
+ cdef void zhpmv(char *uplo, int *n, z *alpha, z *ap, z *x, int *incx, z *beta, z *y, int *incy) noexcept nogil:
1109
+
1110
+ _fortran_zhpmv(uplo, n, <npy_complex128*>alpha, <npy_complex128*>ap, <npy_complex128*>x, incx, <npy_complex128*>beta, <npy_complex128*>y, incy)
1111
+
1112
+
1113
+ cdef extern from "_blas_subroutines.h":
1114
+ void _fortran_zhpr "BLAS_FUNC(zhpr)"(char *uplo, int *n, d *alpha, npy_complex128 *x, int *incx, npy_complex128 *ap) nogil
1115
+ cdef void zhpr(char *uplo, int *n, d *alpha, z *x, int *incx, z *ap) noexcept nogil:
1116
+
1117
+ _fortran_zhpr(uplo, n, alpha, <npy_complex128*>x, incx, <npy_complex128*>ap)
1118
+
1119
+
1120
+ cdef extern from "_blas_subroutines.h":
1121
+ void _fortran_zhpr2 "BLAS_FUNC(zhpr2)"(char *uplo, int *n, npy_complex128 *alpha, npy_complex128 *x, int *incx, npy_complex128 *y, int *incy, npy_complex128 *ap) nogil
1122
+ cdef void zhpr2(char *uplo, int *n, z *alpha, z *x, int *incx, z *y, int *incy, z *ap) noexcept nogil:
1123
+
1124
+ _fortran_zhpr2(uplo, n, <npy_complex128*>alpha, <npy_complex128*>x, incx, <npy_complex128*>y, incy, <npy_complex128*>ap)
1125
+
1126
+
1127
+ cdef extern from "_blas_subroutines.h":
1128
+ void _fortran_zrotg "BLAS_FUNC(zrotg)"(npy_complex128 *ca, npy_complex128 *cb, d *c, npy_complex128 *s) nogil
1129
+ cdef void zrotg(z *ca, z *cb, d *c, z *s) noexcept nogil:
1130
+
1131
+ _fortran_zrotg(<npy_complex128*>ca, <npy_complex128*>cb, c, <npy_complex128*>s)
1132
+
1133
+
1134
+ cdef extern from "_blas_subroutines.h":
1135
+ void _fortran_zscal "BLAS_FUNC(zscal)"(int *n, npy_complex128 *za, npy_complex128 *zx, int *incx) nogil
1136
+ cdef void zscal(int *n, z *za, z *zx, int *incx) noexcept nogil:
1137
+
1138
+ _fortran_zscal(n, <npy_complex128*>za, <npy_complex128*>zx, incx)
1139
+
1140
+
1141
+ cdef extern from "_blas_subroutines.h":
1142
+ void _fortran_zswap "BLAS_FUNC(zswap)"(int *n, npy_complex128 *zx, int *incx, npy_complex128 *zy, int *incy) nogil
1143
+ cdef void zswap(int *n, z *zx, int *incx, z *zy, int *incy) noexcept nogil:
1144
+
1145
+ _fortran_zswap(n, <npy_complex128*>zx, incx, <npy_complex128*>zy, incy)
1146
+
1147
+
1148
+ cdef extern from "_blas_subroutines.h":
1149
+ void _fortran_zsymm "BLAS_FUNC(zsymm)"(char *side, char *uplo, int *m, int *n, npy_complex128 *alpha, npy_complex128 *a, int *lda, npy_complex128 *b, int *ldb, npy_complex128 *beta, npy_complex128 *c, int *ldc) nogil
1150
+ cdef void zsymm(char *side, char *uplo, int *m, int *n, z *alpha, z *a, int *lda, z *b, int *ldb, z *beta, z *c, int *ldc) noexcept nogil:
1151
+
1152
+ _fortran_zsymm(side, uplo, m, n, <npy_complex128*>alpha, <npy_complex128*>a, lda, <npy_complex128*>b, ldb, <npy_complex128*>beta, <npy_complex128*>c, ldc)
1153
+
1154
+
1155
+ cdef extern from "_blas_subroutines.h":
1156
+ void _fortran_zsyr2k "BLAS_FUNC(zsyr2k)"(char *uplo, char *trans, int *n, int *k, npy_complex128 *alpha, npy_complex128 *a, int *lda, npy_complex128 *b, int *ldb, npy_complex128 *beta, npy_complex128 *c, int *ldc) nogil
1157
+ cdef void zsyr2k(char *uplo, char *trans, int *n, int *k, z *alpha, z *a, int *lda, z *b, int *ldb, z *beta, z *c, int *ldc) noexcept nogil:
1158
+
1159
+ _fortran_zsyr2k(uplo, trans, n, k, <npy_complex128*>alpha, <npy_complex128*>a, lda, <npy_complex128*>b, ldb, <npy_complex128*>beta, <npy_complex128*>c, ldc)
1160
+
1161
+
1162
+ cdef extern from "_blas_subroutines.h":
1163
+ void _fortran_zsyrk "BLAS_FUNC(zsyrk)"(char *uplo, char *trans, int *n, int *k, npy_complex128 *alpha, npy_complex128 *a, int *lda, npy_complex128 *beta, npy_complex128 *c, int *ldc) nogil
1164
+ cdef void zsyrk(char *uplo, char *trans, int *n, int *k, z *alpha, z *a, int *lda, z *beta, z *c, int *ldc) noexcept nogil:
1165
+
1166
+ _fortran_zsyrk(uplo, trans, n, k, <npy_complex128*>alpha, <npy_complex128*>a, lda, <npy_complex128*>beta, <npy_complex128*>c, ldc)
1167
+
1168
+
1169
+ cdef extern from "_blas_subroutines.h":
1170
+ void _fortran_ztbmv "BLAS_FUNC(ztbmv)"(char *uplo, char *trans, char *diag, int *n, int *k, npy_complex128 *a, int *lda, npy_complex128 *x, int *incx) nogil
1171
+ cdef void ztbmv(char *uplo, char *trans, char *diag, int *n, int *k, z *a, int *lda, z *x, int *incx) noexcept nogil:
1172
+
1173
+ _fortran_ztbmv(uplo, trans, diag, n, k, <npy_complex128*>a, lda, <npy_complex128*>x, incx)
1174
+
1175
+
1176
+ cdef extern from "_blas_subroutines.h":
1177
+ void _fortran_ztbsv "BLAS_FUNC(ztbsv)"(char *uplo, char *trans, char *diag, int *n, int *k, npy_complex128 *a, int *lda, npy_complex128 *x, int *incx) nogil
1178
+ cdef void ztbsv(char *uplo, char *trans, char *diag, int *n, int *k, z *a, int *lda, z *x, int *incx) noexcept nogil:
1179
+
1180
+ _fortran_ztbsv(uplo, trans, diag, n, k, <npy_complex128*>a, lda, <npy_complex128*>x, incx)
1181
+
1182
+
1183
+ cdef extern from "_blas_subroutines.h":
1184
+ void _fortran_ztpmv "BLAS_FUNC(ztpmv)"(char *uplo, char *trans, char *diag, int *n, npy_complex128 *ap, npy_complex128 *x, int *incx) nogil
1185
+ cdef void ztpmv(char *uplo, char *trans, char *diag, int *n, z *ap, z *x, int *incx) noexcept nogil:
1186
+
1187
+ _fortran_ztpmv(uplo, trans, diag, n, <npy_complex128*>ap, <npy_complex128*>x, incx)
1188
+
1189
+
1190
+ cdef extern from "_blas_subroutines.h":
1191
+ void _fortran_ztpsv "BLAS_FUNC(ztpsv)"(char *uplo, char *trans, char *diag, int *n, npy_complex128 *ap, npy_complex128 *x, int *incx) nogil
1192
+ cdef void ztpsv(char *uplo, char *trans, char *diag, int *n, z *ap, z *x, int *incx) noexcept nogil:
1193
+
1194
+ _fortran_ztpsv(uplo, trans, diag, n, <npy_complex128*>ap, <npy_complex128*>x, incx)
1195
+
1196
+
1197
+ cdef extern from "_blas_subroutines.h":
1198
+ void _fortran_ztrmm "BLAS_FUNC(ztrmm)"(char *side, char *uplo, char *transa, char *diag, int *m, int *n, npy_complex128 *alpha, npy_complex128 *a, int *lda, npy_complex128 *b, int *ldb) nogil
1199
+ cdef void ztrmm(char *side, char *uplo, char *transa, char *diag, int *m, int *n, z *alpha, z *a, int *lda, z *b, int *ldb) noexcept nogil:
1200
+
1201
+ _fortran_ztrmm(side, uplo, transa, diag, m, n, <npy_complex128*>alpha, <npy_complex128*>a, lda, <npy_complex128*>b, ldb)
1202
+
1203
+
1204
+ cdef extern from "_blas_subroutines.h":
1205
+ void _fortran_ztrmv "BLAS_FUNC(ztrmv)"(char *uplo, char *trans, char *diag, int *n, npy_complex128 *a, int *lda, npy_complex128 *x, int *incx) nogil
1206
+ cdef void ztrmv(char *uplo, char *trans, char *diag, int *n, z *a, int *lda, z *x, int *incx) noexcept nogil:
1207
+
1208
+ _fortran_ztrmv(uplo, trans, diag, n, <npy_complex128*>a, lda, <npy_complex128*>x, incx)
1209
+
1210
+
1211
+ cdef extern from "_blas_subroutines.h":
1212
+ void _fortran_ztrsm "BLAS_FUNC(ztrsm)"(char *side, char *uplo, char *transa, char *diag, int *m, int *n, npy_complex128 *alpha, npy_complex128 *a, int *lda, npy_complex128 *b, int *ldb) nogil
1213
+ cdef void ztrsm(char *side, char *uplo, char *transa, char *diag, int *m, int *n, z *alpha, z *a, int *lda, z *b, int *ldb) noexcept nogil:
1214
+
1215
+ _fortran_ztrsm(side, uplo, transa, diag, m, n, <npy_complex128*>alpha, <npy_complex128*>a, lda, <npy_complex128*>b, ldb)
1216
+
1217
+
1218
+ cdef extern from "_blas_subroutines.h":
1219
+ void _fortran_ztrsv "BLAS_FUNC(ztrsv)"(char *uplo, char *trans, char *diag, int *n, npy_complex128 *a, int *lda, npy_complex128 *x, int *incx) nogil
1220
+ cdef void ztrsv(char *uplo, char *trans, char *diag, int *n, z *a, int *lda, z *x, int *incx) noexcept nogil:
1221
+
1222
+ _fortran_ztrsv(uplo, trans, diag, n, <npy_complex128*>a, lda, <npy_complex128*>x, incx)
1223
+
1224
+
1225
+
1226
+ # Python-accessible wrappers for testing:
1227
+
1228
+ cdef inline bint _is_contiguous(double[:,:] a, int axis) noexcept nogil:
1229
+ return (a.strides[axis] == sizeof(a[0,0]) or a.shape[axis] == 1)
1230
+
1231
+ cpdef float complex _test_cdotc(float complex[:] cx, float complex[:] cy) noexcept nogil:
1232
+ cdef:
1233
+ int n = cx.shape[0]
1234
+ int incx = cx.strides[0] // sizeof(cx[0])
1235
+ int incy = cy.strides[0] // sizeof(cy[0])
1236
+ return cdotc(&n, &cx[0], &incx, &cy[0], &incy)
1237
+
1238
+ cpdef float complex _test_cdotu(float complex[:] cx, float complex[:] cy) noexcept nogil:
1239
+ cdef:
1240
+ int n = cx.shape[0]
1241
+ int incx = cx.strides[0] // sizeof(cx[0])
1242
+ int incy = cy.strides[0] // sizeof(cy[0])
1243
+ return cdotu(&n, &cx[0], &incx, &cy[0], &incy)
1244
+
1245
+ cpdef double _test_dasum(double[:] dx) noexcept nogil:
1246
+ cdef:
1247
+ int n = dx.shape[0]
1248
+ int incx = dx.strides[0] // sizeof(dx[0])
1249
+ return dasum(&n, &dx[0], &incx)
1250
+
1251
+ cpdef double _test_ddot(double[:] dx, double[:] dy) noexcept nogil:
1252
+ cdef:
1253
+ int n = dx.shape[0]
1254
+ int incx = dx.strides[0] // sizeof(dx[0])
1255
+ int incy = dy.strides[0] // sizeof(dy[0])
1256
+ return ddot(&n, &dx[0], &incx, &dy[0], &incy)
1257
+
1258
+ cpdef int _test_dgemm(double alpha, double[:,:] a, double[:,:] b, double beta,
1259
+ double[:,:] c) except -1 nogil:
1260
+ cdef:
1261
+ char *transa
1262
+ char *transb
1263
+ int m, n, k, lda, ldb, ldc
1264
+ double *a0=&a[0,0]
1265
+ double *b0=&b[0,0]
1266
+ double *c0=&c[0,0]
1267
+ # In the case that c is C contiguous, swap a and b and
1268
+ # swap whether or not each of them is transposed.
1269
+ # This can be done because a.dot(b) = b.T.dot(a.T).T.
1270
+ if _is_contiguous(c, 1):
1271
+ if _is_contiguous(a, 1):
1272
+ transb = 'n'
1273
+ ldb = (&a[1,0]) - a0 if a.shape[0] > 1 else 1
1274
+ elif _is_contiguous(a, 0):
1275
+ transb = 't'
1276
+ ldb = (&a[0,1]) - a0 if a.shape[1] > 1 else 1
1277
+ else:
1278
+ with gil:
1279
+ raise ValueError("Input 'a' is neither C nor Fortran contiguous.")
1280
+ if _is_contiguous(b, 1):
1281
+ transa = 'n'
1282
+ lda = (&b[1,0]) - b0 if b.shape[0] > 1 else 1
1283
+ elif _is_contiguous(b, 0):
1284
+ transa = 't'
1285
+ lda = (&b[0,1]) - b0 if b.shape[1] > 1 else 1
1286
+ else:
1287
+ with gil:
1288
+ raise ValueError("Input 'b' is neither C nor Fortran contiguous.")
1289
+ k = b.shape[0]
1290
+ if k != a.shape[1]:
1291
+ with gil:
1292
+ raise ValueError("Shape mismatch in input arrays.")
1293
+ m = b.shape[1]
1294
+ n = a.shape[0]
1295
+ if n != c.shape[0] or m != c.shape[1]:
1296
+ with gil:
1297
+ raise ValueError("Output array does not have the correct shape.")
1298
+ ldc = (&c[1,0]) - c0 if c.shape[0] > 1 else 1
1299
+ dgemm(transa, transb, &m, &n, &k, &alpha, b0, &lda, a0,
1300
+ &ldb, &beta, c0, &ldc)
1301
+ elif _is_contiguous(c, 0):
1302
+ if _is_contiguous(a, 1):
1303
+ transa = 't'
1304
+ lda = (&a[1,0]) - a0 if a.shape[0] > 1 else 1
1305
+ elif _is_contiguous(a, 0):
1306
+ transa = 'n'
1307
+ lda = (&a[0,1]) - a0 if a.shape[1] > 1 else 1
1308
+ else:
1309
+ with gil:
1310
+ raise ValueError("Input 'a' is neither C nor Fortran contiguous.")
1311
+ if _is_contiguous(b, 1):
1312
+ transb = 't'
1313
+ ldb = (&b[1,0]) - b0 if b.shape[0] > 1 else 1
1314
+ elif _is_contiguous(b, 0):
1315
+ transb = 'n'
1316
+ ldb = (&b[0,1]) - b0 if b.shape[1] > 1 else 1
1317
+ else:
1318
+ with gil:
1319
+ raise ValueError("Input 'b' is neither C nor Fortran contiguous.")
1320
+ m = a.shape[0]
1321
+ k = a.shape[1]
1322
+ if k != b.shape[0]:
1323
+ with gil:
1324
+ raise ValueError("Shape mismatch in input arrays.")
1325
+ n = b.shape[1]
1326
+ if m != c.shape[0] or n != c.shape[1]:
1327
+ with gil:
1328
+ raise ValueError("Output array does not have the correct shape.")
1329
+ ldc = (&c[0,1]) - c0 if c.shape[1] > 1 else 1
1330
+ dgemm(transa, transb, &m, &n, &k, &alpha, a0, &lda, b0,
1331
+ &ldb, &beta, c0, &ldc)
1332
+ else:
1333
+ with gil:
1334
+ raise ValueError("Input 'c' is neither C nor Fortran contiguous.")
1335
+ return 0
1336
+
1337
+ cpdef double _test_dnrm2(double[:] x) noexcept nogil:
1338
+ cdef:
1339
+ int n = x.shape[0]
1340
+ int incx = x.strides[0] // sizeof(x[0])
1341
+ return dnrm2(&n, &x[0], &incx)
1342
+
1343
+ cpdef double _test_dzasum(double complex[:] zx) noexcept nogil:
1344
+ cdef:
1345
+ int n = zx.shape[0]
1346
+ int incx = zx.strides[0] // sizeof(zx[0])
1347
+ return dzasum(&n, &zx[0], &incx)
1348
+
1349
+ cpdef double _test_dznrm2(double complex[:] x) noexcept nogil:
1350
+ cdef:
1351
+ int n = x.shape[0]
1352
+ int incx = x.strides[0] // sizeof(x[0])
1353
+ return dznrm2(&n, &x[0], &incx)
1354
+
1355
+ cpdef int _test_icamax(float complex[:] cx) noexcept nogil:
1356
+ cdef:
1357
+ int n = cx.shape[0]
1358
+ int incx = cx.strides[0] // sizeof(cx[0])
1359
+ return icamax(&n, &cx[0], &incx)
1360
+
1361
+ cpdef int _test_idamax(double[:] dx) noexcept nogil:
1362
+ cdef:
1363
+ int n = dx.shape[0]
1364
+ int incx = dx.strides[0] // sizeof(dx[0])
1365
+ return idamax(&n, &dx[0], &incx)
1366
+
1367
+ cpdef int _test_isamax(float[:] sx) noexcept nogil:
1368
+ cdef:
1369
+ int n = sx.shape[0]
1370
+ int incx = sx.strides[0] // sizeof(sx[0])
1371
+ return isamax(&n, &sx[0], &incx)
1372
+
1373
+ cpdef int _test_izamax(double complex[:] zx) noexcept nogil:
1374
+ cdef:
1375
+ int n = zx.shape[0]
1376
+ int incx = zx.strides[0] // sizeof(zx[0])
1377
+ return izamax(&n, &zx[0], &incx)
1378
+
1379
+ cpdef float _test_sasum(float[:] sx) noexcept nogil:
1380
+ cdef:
1381
+ int n = sx.shape[0]
1382
+ int incx = sx.strides[0] // sizeof(sx[0])
1383
+ return sasum(&n, &sx[0], &incx)
1384
+
1385
+ cpdef float _test_scasum(float complex[:] cx) noexcept nogil:
1386
+ cdef:
1387
+ int n = cx.shape[0]
1388
+ int incx = cx.strides[0] // sizeof(cx[0])
1389
+ return scasum(&n, &cx[0], &incx)
1390
+
1391
+ cpdef float _test_scnrm2(float complex[:] x) noexcept nogil:
1392
+ cdef:
1393
+ int n = x.shape[0]
1394
+ int incx = x.strides[0] // sizeof(x[0])
1395
+ return scnrm2(&n, &x[0], &incx)
1396
+
1397
+ cpdef float _test_sdot(float[:] sx, float[:] sy) noexcept nogil:
1398
+ cdef:
1399
+ int n = sx.shape[0]
1400
+ int incx = sx.strides[0] // sizeof(sx[0])
1401
+ int incy = sy.strides[0] // sizeof(sy[0])
1402
+ return sdot(&n, &sx[0], &incx, &sy[0], &incy)
1403
+
1404
+ cpdef float _test_snrm2(float[:] x) noexcept nogil:
1405
+ cdef:
1406
+ int n = x.shape[0]
1407
+ int incx = x.strides[0] // sizeof(x[0])
1408
+ return snrm2(&n, &x[0], &incx)
1409
+
1410
+ cpdef double complex _test_zdotc(double complex[:] zx, double complex[:] zy) noexcept nogil:
1411
+ cdef:
1412
+ int n = zx.shape[0]
1413
+ int incx = zx.strides[0] // sizeof(zx[0])
1414
+ int incy = zy.strides[0] // sizeof(zy[0])
1415
+ return zdotc(&n, &zx[0], &incx, &zy[0], &incy)
1416
+
1417
+ cpdef double complex _test_zdotu(double complex[:] zx, double complex[:] zy) noexcept nogil:
1418
+ cdef:
1419
+ int n = zx.shape[0]
1420
+ int incx = zx.strides[0] // sizeof(zx[0])
1421
+ int incy = zy.strides[0] // sizeof(zy[0])
1422
+ return zdotu(&n, &zx[0], &incx, &zy[0], &incy)
astra_scene_test/Scene_04/.venv/lib/python3.9/site-packages/scipy/linalg/cython_lapack.pxd ADDED
The diff for this file is too large to render. See raw diff
 
astra_scene_test/Scene_04/.venv/lib/python3.9/site-packages/scipy/linalg/cython_lapack.pyx ADDED
The diff for this file is too large to render. See raw diff
 
astra_scene_test/Scene_04/.venv/lib/python3.9/site-packages/scipy/linalg/decomp.py ADDED
@@ -0,0 +1,25 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # This file is not meant for public use and will be removed in SciPy v2.0.0.
2
+ # Use the `scipy.linalg` namespace for importing the functions
3
+ # included below.
4
+
5
+ from scipy._lib.deprecation import _sub_module_deprecation
6
+
7
+
8
+ __all__ = [ # noqa: F822
9
+ 'eig', 'eigvals', 'eigh', 'eigvalsh',
10
+ 'eig_banded', 'eigvals_banded',
11
+ 'eigh_tridiagonal', 'eigvalsh_tridiagonal', 'hessenberg', 'cdf2rdf',
12
+ 'array', 'isfinite', 'inexact', 'nonzero', 'iscomplexobj',
13
+ 'flatnonzero', 'argsort', 'iscomplex', 'einsum', 'eye', 'inf',
14
+ 'LinAlgError', 'norm', 'get_lapack_funcs'
15
+ ]
16
+
17
+
18
+ def __dir__():
19
+ return __all__
20
+
21
+
22
+ def __getattr__(name):
23
+ return _sub_module_deprecation(sub_package="linalg", module="decomp",
24
+ private_modules=["_decomp"], all=__all__,
25
+ attribute=name)
astra_scene_test/Scene_04/.venv/lib/python3.9/site-packages/scipy/linalg/decomp_cholesky.py ADDED
@@ -0,0 +1,22 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # This file is not meant for public use and will be removed in SciPy v2.0.0.
2
+ # Use the `scipy.linalg` namespace for importing the functions
3
+ # included below.
4
+
5
+ from scipy._lib.deprecation import _sub_module_deprecation
6
+
7
+
8
+ __all__ = [ # noqa: F822
9
+ 'cholesky', 'cho_factor', 'cho_solve', 'cholesky_banded',
10
+ 'cho_solve_banded', 'asarray_chkfinite', 'atleast_2d',
11
+ 'LinAlgError', 'get_lapack_funcs'
12
+ ]
13
+
14
+
15
+ def __dir__():
16
+ return __all__
17
+
18
+
19
+ def __getattr__(name):
20
+ return _sub_module_deprecation(sub_package="linalg", module="decomp_cholesky",
21
+ private_modules=["_decomp_cholesky"], all=__all__,
22
+ attribute=name)
astra_scene_test/Scene_04/.venv/lib/python3.9/site-packages/scipy/linalg/decomp_lu.py ADDED
@@ -0,0 +1,21 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # This file is not meant for public use and will be removed in SciPy v2.0.0.
2
+ # Use the `scipy.linalg` namespace for importing the functions
3
+ # included below.
4
+
5
+ from scipy._lib.deprecation import _sub_module_deprecation
6
+
7
+
8
+ __all__ = [ # noqa: F822
9
+ 'lu', 'lu_solve', 'lu_factor',
10
+ 'asarray_chkfinite', 'LinAlgWarning', 'get_lapack_funcs',
11
+ ]
12
+
13
+
14
+ def __dir__():
15
+ return __all__
16
+
17
+
18
+ def __getattr__(name):
19
+ return _sub_module_deprecation(sub_package="linalg", module="decomp_lu",
20
+ private_modules=["_decomp_lu"], all=__all__,
21
+ attribute=name)
astra_scene_test/Scene_04/.venv/lib/python3.9/site-packages/scipy/linalg/decomp_qr.py ADDED
@@ -0,0 +1,20 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # This file is not meant for public use and will be removed in SciPy v2.0.0.
2
+ # Use the `scipy.linalg` namespace for importing the functions
3
+ # included below.
4
+
5
+ from scipy._lib.deprecation import _sub_module_deprecation
6
+
7
+
8
+ __all__ = [ # noqa: F822
9
+ 'qr', 'qr_multiply', 'rq', 'get_lapack_funcs', 'safecall'
10
+ ]
11
+
12
+
13
+ def __dir__():
14
+ return __all__
15
+
16
+
17
+ def __getattr__(name):
18
+ return _sub_module_deprecation(sub_package="linalg", module="decomp_qr",
19
+ private_modules=["_decomp_qr"], all=__all__,
20
+ attribute=name)
astra_scene_test/Scene_04/.venv/lib/python3.9/site-packages/scipy/linalg/decomp_schur.py ADDED
@@ -0,0 +1,22 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # This file is not meant for public use and will be removed in SciPy v2.0.0.
2
+ # Use the `scipy.linalg` namespace for importing the functions
3
+ # included below.
4
+
5
+ from scipy._lib.deprecation import _sub_module_deprecation
6
+
7
+
8
+ __all__ = [ # noqa: F822
9
+ 'schur', 'rsf2csf', 'asarray_chkfinite', 'single', 'array', 'norm',
10
+ 'LinAlgError', 'get_lapack_funcs', 'eigvals', 'eps', 'feps'
11
+ ]
12
+
13
+
14
+ def __dir__():
15
+ return __all__
16
+
17
+
18
+ def __getattr__(name):
19
+ return _sub_module_deprecation(sub_package="linalg", module="decomp_schur",
20
+ private_modules=["_decomp_schur"], all=__all__,
21
+ attribute=name)
22
+