koichi12 commited on
Commit
e74124d
·
verified ·
1 Parent(s): b839be9

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. .gitattributes +3 -0
  2. tuning-competition-baseline/.venv/lib/python3.11/site-packages/Cython/Compiler/__pycache__/ExprNodes.cpython-311.pyc +3 -0
  3. tuning-competition-baseline/.venv/lib/python3.11/site-packages/filelock-3.13.1.dist-info/INSTALLER +1 -0
  4. tuning-competition-baseline/.venv/lib/python3.11/site-packages/filelock-3.13.1.dist-info/METADATA +56 -0
  5. tuning-competition-baseline/.venv/lib/python3.11/site-packages/filelock-3.13.1.dist-info/RECORD +22 -0
  6. tuning-competition-baseline/.venv/lib/python3.11/site-packages/filelock-3.13.1.dist-info/WHEEL +4 -0
  7. tuning-competition-baseline/.venv/lib/python3.11/site-packages/filelock-3.13.1.dist-info/licenses/LICENSE +24 -0
  8. tuning-competition-baseline/.venv/lib/python3.11/site-packages/mpmath/__pycache__/__init__.cpython-311.pyc +0 -0
  9. tuning-competition-baseline/.venv/lib/python3.11/site-packages/mpmath/__pycache__/ctx_base.cpython-311.pyc +0 -0
  10. tuning-competition-baseline/.venv/lib/python3.11/site-packages/mpmath/__pycache__/ctx_fp.cpython-311.pyc +0 -0
  11. tuning-competition-baseline/.venv/lib/python3.11/site-packages/mpmath/__pycache__/ctx_iv.cpython-311.pyc +0 -0
  12. tuning-competition-baseline/.venv/lib/python3.11/site-packages/mpmath/__pycache__/ctx_mp_python.cpython-311.pyc +0 -0
  13. tuning-competition-baseline/.venv/lib/python3.11/site-packages/mpmath/__pycache__/identification.cpython-311.pyc +0 -0
  14. tuning-competition-baseline/.venv/lib/python3.11/site-packages/mpmath/__pycache__/math2.cpython-311.pyc +0 -0
  15. tuning-competition-baseline/.venv/lib/python3.11/site-packages/mpmath/__pycache__/rational.cpython-311.pyc +0 -0
  16. tuning-competition-baseline/.venv/lib/python3.11/site-packages/mpmath/__pycache__/usertools.cpython-311.pyc +0 -0
  17. tuning-competition-baseline/.venv/lib/python3.11/site-packages/mpmath/__pycache__/visualization.cpython-311.pyc +0 -0
  18. tuning-competition-baseline/.venv/lib/python3.11/site-packages/mpmath/calculus/__pycache__/__init__.cpython-311.pyc +0 -0
  19. tuning-competition-baseline/.venv/lib/python3.11/site-packages/mpmath/calculus/__pycache__/calculus.cpython-311.pyc +0 -0
  20. tuning-competition-baseline/.venv/lib/python3.11/site-packages/mpmath/calculus/__pycache__/inverselaplace.cpython-311.pyc +0 -0
  21. tuning-competition-baseline/.venv/lib/python3.11/site-packages/mpmath/calculus/__pycache__/odes.cpython-311.pyc +0 -0
  22. tuning-competition-baseline/.venv/lib/python3.11/site-packages/mpmath/calculus/__pycache__/optimization.cpython-311.pyc +0 -0
  23. tuning-competition-baseline/.venv/lib/python3.11/site-packages/mpmath/calculus/__pycache__/polynomials.cpython-311.pyc +0 -0
  24. tuning-competition-baseline/.venv/lib/python3.11/site-packages/mpmath/calculus/inverselaplace.py +973 -0
  25. tuning-competition-baseline/.venv/lib/python3.11/site-packages/mpmath/functions/__pycache__/__init__.cpython-311.pyc +0 -0
  26. tuning-competition-baseline/.venv/lib/python3.11/site-packages/mpmath/functions/__pycache__/bessel.cpython-311.pyc +0 -0
  27. tuning-competition-baseline/.venv/lib/python3.11/site-packages/mpmath/functions/__pycache__/elliptic.cpython-311.pyc +0 -0
  28. tuning-competition-baseline/.venv/lib/python3.11/site-packages/mpmath/functions/__pycache__/factorials.cpython-311.pyc +0 -0
  29. tuning-competition-baseline/.venv/lib/python3.11/site-packages/mpmath/functions/__pycache__/functions.cpython-311.pyc +0 -0
  30. tuning-competition-baseline/.venv/lib/python3.11/site-packages/mpmath/functions/__pycache__/hypergeometric.cpython-311.pyc +0 -0
  31. tuning-competition-baseline/.venv/lib/python3.11/site-packages/mpmath/functions/__pycache__/orthogonal.cpython-311.pyc +0 -0
  32. tuning-competition-baseline/.venv/lib/python3.11/site-packages/mpmath/functions/__pycache__/rszeta.cpython-311.pyc +0 -0
  33. tuning-competition-baseline/.venv/lib/python3.11/site-packages/mpmath/functions/__pycache__/zeta.cpython-311.pyc +0 -0
  34. tuning-competition-baseline/.venv/lib/python3.11/site-packages/mpmath/functions/__pycache__/zetazeros.cpython-311.pyc +0 -0
  35. tuning-competition-baseline/.venv/lib/python3.11/site-packages/mpmath/functions/orthogonal.py +493 -0
  36. tuning-competition-baseline/.venv/lib/python3.11/site-packages/mpmath/matrices/__pycache__/__init__.cpython-311.pyc +0 -0
  37. tuning-competition-baseline/.venv/lib/python3.11/site-packages/mpmath/matrices/__pycache__/eigen.cpython-311.pyc +0 -0
  38. tuning-competition-baseline/.venv/lib/python3.11/site-packages/mpmath/matrices/__pycache__/eigen_symmetric.cpython-311.pyc +0 -0
  39. tuning-competition-baseline/.venv/lib/python3.11/site-packages/mpmath/matrices/__pycache__/linalg.cpython-311.pyc +0 -0
  40. tuning-competition-baseline/.venv/lib/python3.11/site-packages/mpmath/matrices/__pycache__/matrices.cpython-311.pyc +0 -0
  41. tuning-competition-baseline/.venv/lib/python3.11/site-packages/mpmath/matrices/eigen_symmetric.py +1807 -0
  42. tuning-competition-baseline/.venv/lib/python3.11/site-packages/mpmath/tests/__pycache__/test_elliptic.cpython-311.pyc +0 -0
  43. tuning-competition-baseline/.venv/lib/python3.11/site-packages/packaging-24.2.dist-info/LICENSE.APACHE +177 -0
  44. tuning-competition-baseline/.venv/lib/python3.11/site-packages/packaging-24.2.dist-info/LICENSE.BSD +23 -0
  45. tuning-competition-baseline/.venv/lib/python3.11/site-packages/packaging-24.2.dist-info/REQUESTED +0 -0
  46. tuning-competition-baseline/.venv/lib/python3.11/site-packages/packaging-24.2.dist-info/WHEEL +4 -0
  47. tuning-competition-baseline/.venv/lib/python3.11/site-packages/pip/_vendor/idna/__pycache__/uts46data.cpython-311.pyc +3 -0
  48. tuning-competition-baseline/.venv/lib/python3.11/site-packages/pip/_vendor/rich/__pycache__/_emoji_codes.cpython-311.pyc +3 -0
  49. tuning-competition-baseline/.venv/lib/python3.11/site-packages/pybind11/__init__.py +19 -0
  50. tuning-competition-baseline/.venv/lib/python3.11/site-packages/pybind11/__main__.py +86 -0
.gitattributes CHANGED
@@ -48,3 +48,6 @@ tuning-competition-baseline/.venv/lib/python3.11/site-packages/pip/_vendor/__pyc
48
  tuning-competition-baseline/.venv/lib/python3.11/site-packages/Cython/Compiler/__pycache__/Optimize.cpython-311.pyc filter=lfs diff=lfs merge=lfs -text
49
  tuning-competition-baseline/.venv/lib/python3.11/site-packages/Cython/Tempita/_tempita.cpython-311-x86_64-linux-gnu.so filter=lfs diff=lfs merge=lfs -text
50
  tuning-competition-baseline/.venv/lib/python3.11/site-packages/Cython/Plex/Transitions.cpython-311-x86_64-linux-gnu.so filter=lfs diff=lfs merge=lfs -text
 
 
 
 
48
  tuning-competition-baseline/.venv/lib/python3.11/site-packages/Cython/Compiler/__pycache__/Optimize.cpython-311.pyc filter=lfs diff=lfs merge=lfs -text
49
  tuning-competition-baseline/.venv/lib/python3.11/site-packages/Cython/Tempita/_tempita.cpython-311-x86_64-linux-gnu.so filter=lfs diff=lfs merge=lfs -text
50
  tuning-competition-baseline/.venv/lib/python3.11/site-packages/Cython/Plex/Transitions.cpython-311-x86_64-linux-gnu.so filter=lfs diff=lfs merge=lfs -text
51
+ tuning-competition-baseline/.venv/lib/python3.11/site-packages/Cython/Compiler/__pycache__/ExprNodes.cpython-311.pyc filter=lfs diff=lfs merge=lfs -text
52
+ tuning-competition-baseline/.venv/lib/python3.11/site-packages/pip/_vendor/idna/__pycache__/uts46data.cpython-311.pyc filter=lfs diff=lfs merge=lfs -text
53
+ tuning-competition-baseline/.venv/lib/python3.11/site-packages/pip/_vendor/rich/__pycache__/_emoji_codes.cpython-311.pyc filter=lfs diff=lfs merge=lfs -text
tuning-competition-baseline/.venv/lib/python3.11/site-packages/Cython/Compiler/__pycache__/ExprNodes.cpython-311.pyc ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:4d0a7505b29dcf29db8e842581f65690f6434ea73c26f359db97d5eda40cdff9
3
+ size 759350
tuning-competition-baseline/.venv/lib/python3.11/site-packages/filelock-3.13.1.dist-info/INSTALLER ADDED
@@ -0,0 +1 @@
 
 
1
+ pip
tuning-competition-baseline/.venv/lib/python3.11/site-packages/filelock-3.13.1.dist-info/METADATA ADDED
@@ -0,0 +1,56 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ Metadata-Version: 2.1
2
+ Name: filelock
3
+ Version: 3.13.1
4
+ Summary: A platform independent file lock.
5
+ Project-URL: Documentation, https://py-filelock.readthedocs.io
6
+ Project-URL: Homepage, https://github.com/tox-dev/py-filelock
7
+ Project-URL: Source, https://github.com/tox-dev/py-filelock
8
+ Project-URL: Tracker, https://github.com/tox-dev/py-filelock/issues
9
+ Maintainer-email: Bernát Gábor <gaborjbernat@gmail.com>
10
+ License-Expression: Unlicense
11
+ License-File: LICENSE
12
+ Keywords: application,cache,directory,log,user
13
+ Classifier: Development Status :: 5 - Production/Stable
14
+ Classifier: Intended Audience :: Developers
15
+ Classifier: License :: OSI Approved :: The Unlicense (Unlicense)
16
+ Classifier: Operating System :: OS Independent
17
+ Classifier: Programming Language :: Python
18
+ Classifier: Programming Language :: Python :: 3 :: Only
19
+ Classifier: Programming Language :: Python :: 3.8
20
+ Classifier: Programming Language :: Python :: 3.9
21
+ Classifier: Programming Language :: Python :: 3.10
22
+ Classifier: Programming Language :: Python :: 3.11
23
+ Classifier: Programming Language :: Python :: 3.12
24
+ Classifier: Topic :: Internet
25
+ Classifier: Topic :: Software Development :: Libraries
26
+ Classifier: Topic :: System
27
+ Requires-Python: >=3.8
28
+ Provides-Extra: docs
29
+ Requires-Dist: furo>=2023.9.10; extra == 'docs'
30
+ Requires-Dist: sphinx-autodoc-typehints!=1.23.4,>=1.24; extra == 'docs'
31
+ Requires-Dist: sphinx>=7.2.6; extra == 'docs'
32
+ Provides-Extra: testing
33
+ Requires-Dist: covdefaults>=2.3; extra == 'testing'
34
+ Requires-Dist: coverage>=7.3.2; extra == 'testing'
35
+ Requires-Dist: diff-cover>=8; extra == 'testing'
36
+ Requires-Dist: pytest-cov>=4.1; extra == 'testing'
37
+ Requires-Dist: pytest-mock>=3.12; extra == 'testing'
38
+ Requires-Dist: pytest-timeout>=2.2; extra == 'testing'
39
+ Requires-Dist: pytest>=7.4.3; extra == 'testing'
40
+ Provides-Extra: typing
41
+ Requires-Dist: typing-extensions>=4.8; python_version < '3.11' and extra == 'typing'
42
+ Description-Content-Type: text/markdown
43
+
44
+ # filelock
45
+
46
+ [![PyPI](https://img.shields.io/pypi/v/filelock)](https://pypi.org/project/filelock/)
47
+ [![Supported Python
48
+ versions](https://img.shields.io/pypi/pyversions/filelock.svg)](https://pypi.org/project/filelock/)
49
+ [![Documentation
50
+ status](https://readthedocs.org/projects/py-filelock/badge/?version=latest)](https://py-filelock.readthedocs.io/en/latest/?badge=latest)
51
+ [![Code style:
52
+ black](https://img.shields.io/badge/code%20style-black-000000.svg)](https://github.com/psf/black)
53
+ [![Downloads](https://static.pepy.tech/badge/filelock/month)](https://pepy.tech/project/filelock)
54
+ [![check](https://github.com/tox-dev/py-filelock/actions/workflows/check.yml/badge.svg)](https://github.com/tox-dev/py-filelock/actions/workflows/check.yml)
55
+
56
+ For more information checkout the [official documentation](https://py-filelock.readthedocs.io/en/latest/index.html).
tuning-competition-baseline/.venv/lib/python3.11/site-packages/filelock-3.13.1.dist-info/RECORD ADDED
@@ -0,0 +1,22 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ filelock-3.13.1.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4
2
+ filelock-3.13.1.dist-info/METADATA,sha256=gi7LyG-dEuOBZC32wie-OOG0OkPZHABsn9rXvxuQlcA,2784
3
+ filelock-3.13.1.dist-info/RECORD,,
4
+ filelock-3.13.1.dist-info/WHEEL,sha256=9QBuHhg6FNW7lppboF2vKVbCGTVzsFykgRQjjlajrhA,87
5
+ filelock-3.13.1.dist-info/licenses/LICENSE,sha256=iNm062BXnBkew5HKBMFhMFctfu3EqG2qWL8oxuFMm80,1210
6
+ filelock/__init__.py,sha256=wAVZ_9_-3Y14xzzupRk5BTTRewFJekR2vf9oIx4M750,1213
7
+ filelock/__pycache__/__init__.cpython-311.pyc,,
8
+ filelock/__pycache__/_api.cpython-311.pyc,,
9
+ filelock/__pycache__/_error.cpython-311.pyc,,
10
+ filelock/__pycache__/_soft.cpython-311.pyc,,
11
+ filelock/__pycache__/_unix.cpython-311.pyc,,
12
+ filelock/__pycache__/_util.cpython-311.pyc,,
13
+ filelock/__pycache__/_windows.cpython-311.pyc,,
14
+ filelock/__pycache__/version.cpython-311.pyc,,
15
+ filelock/_api.py,sha256=UsVWPEOOgFH1pR_6WMk2b5hWZ7nWhUPT5GZX9WuYaC8,11860
16
+ filelock/_error.py,sha256=-5jMcjTu60YAvAO1UbqDD1GIEjVkwr8xCFwDBtMeYDg,787
17
+ filelock/_soft.py,sha256=haqtc_TB_KJbYv2a8iuEAclKuM4fMG1vTcp28sK919c,1711
18
+ filelock/_unix.py,sha256=ViG38PgJsIhT3xaArugvw0TPP6VWoP2VJj7FEIWypkg,2157
19
+ filelock/_util.py,sha256=dBDlIj1dHL_juXX0Qqq6bZtyE53YZTN8GFhtyTV043o,1708
20
+ filelock/_windows.py,sha256=eMKL8dZKrgekf5VYVGR14an29JGEInRtUO8ui9ABywg,2177
21
+ filelock/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
22
+ filelock/version.py,sha256=fmajg3X8ZdOn-UpUewARwK5cfYf4wP4Xa0DcHjigFYo,413
tuning-competition-baseline/.venv/lib/python3.11/site-packages/filelock-3.13.1.dist-info/WHEEL ADDED
@@ -0,0 +1,4 @@
 
 
 
 
 
1
+ Wheel-Version: 1.0
2
+ Generator: hatchling 1.18.0
3
+ Root-Is-Purelib: true
4
+ Tag: py3-none-any
tuning-competition-baseline/.venv/lib/python3.11/site-packages/filelock-3.13.1.dist-info/licenses/LICENSE ADDED
@@ -0,0 +1,24 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ This is free and unencumbered software released into the public domain.
2
+
3
+ Anyone is free to copy, modify, publish, use, compile, sell, or
4
+ distribute this software, either in source code form or as a compiled
5
+ binary, for any purpose, commercial or non-commercial, and by any
6
+ means.
7
+
8
+ In jurisdictions that recognize copyright laws, the author or authors
9
+ of this software dedicate any and all copyright interest in the
10
+ software to the public domain. We make this dedication for the benefit
11
+ of the public at large and to the detriment of our heirs and
12
+ successors. We intend this dedication to be an overt act of
13
+ relinquishment in perpetuity of all present and future rights to this
14
+ software under copyright law.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
19
+ IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
20
+ OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
21
+ ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
22
+ OTHER DEALINGS IN THE SOFTWARE.
23
+
24
+ For more information, please refer to <http://unlicense.org>
tuning-competition-baseline/.venv/lib/python3.11/site-packages/mpmath/__pycache__/__init__.cpython-311.pyc ADDED
Binary file (14.7 kB). View file
 
tuning-competition-baseline/.venv/lib/python3.11/site-packages/mpmath/__pycache__/ctx_base.cpython-311.pyc ADDED
Binary file (24.4 kB). View file
 
tuning-competition-baseline/.venv/lib/python3.11/site-packages/mpmath/__pycache__/ctx_fp.cpython-311.pyc ADDED
Binary file (13 kB). View file
 
tuning-competition-baseline/.venv/lib/python3.11/site-packages/mpmath/__pycache__/ctx_iv.cpython-311.pyc ADDED
Binary file (38.7 kB). View file
 
tuning-competition-baseline/.venv/lib/python3.11/site-packages/mpmath/__pycache__/ctx_mp_python.cpython-311.pyc ADDED
Binary file (61.1 kB). View file
 
tuning-competition-baseline/.venv/lib/python3.11/site-packages/mpmath/__pycache__/identification.cpython-311.pyc ADDED
Binary file (41.3 kB). View file
 
tuning-competition-baseline/.venv/lib/python3.11/site-packages/mpmath/__pycache__/math2.cpython-311.pyc ADDED
Binary file (28.5 kB). View file
 
tuning-competition-baseline/.venv/lib/python3.11/site-packages/mpmath/__pycache__/rational.cpython-311.pyc ADDED
Binary file (10.4 kB). View file
 
tuning-competition-baseline/.venv/lib/python3.11/site-packages/mpmath/__pycache__/usertools.cpython-311.pyc ADDED
Binary file (4.94 kB). View file
 
tuning-competition-baseline/.venv/lib/python3.11/site-packages/mpmath/__pycache__/visualization.cpython-311.pyc ADDED
Binary file (17.1 kB). View file
 
tuning-competition-baseline/.venv/lib/python3.11/site-packages/mpmath/calculus/__pycache__/__init__.cpython-311.pyc ADDED
Binary file (471 Bytes). View file
 
tuning-competition-baseline/.venv/lib/python3.11/site-packages/mpmath/calculus/__pycache__/calculus.cpython-311.pyc ADDED
Binary file (658 Bytes). View file
 
tuning-competition-baseline/.venv/lib/python3.11/site-packages/mpmath/calculus/__pycache__/inverselaplace.cpython-311.pyc ADDED
Binary file (41.7 kB). View file
 
tuning-competition-baseline/.venv/lib/python3.11/site-packages/mpmath/calculus/__pycache__/odes.cpython-311.pyc ADDED
Binary file (13.3 kB). View file
 
tuning-competition-baseline/.venv/lib/python3.11/site-packages/mpmath/calculus/__pycache__/optimization.cpython-311.pyc ADDED
Binary file (42.8 kB). View file
 
tuning-competition-baseline/.venv/lib/python3.11/site-packages/mpmath/calculus/__pycache__/polynomials.cpython-311.pyc ADDED
Binary file (10.9 kB). View file
 
tuning-competition-baseline/.venv/lib/python3.11/site-packages/mpmath/calculus/inverselaplace.py ADDED
@@ -0,0 +1,973 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # contributed to mpmath by Kristopher L. Kuhlman, February 2017
2
+ # contributed to mpmath by Guillermo Navas-Palencia, February 2022
3
+
4
+ class InverseLaplaceTransform(object):
5
+ r"""
6
+ Inverse Laplace transform methods are implemented using this
7
+ class, in order to simplify the code and provide a common
8
+ infrastructure.
9
+
10
+ Implement a custom inverse Laplace transform algorithm by
11
+ subclassing :class:`InverseLaplaceTransform` and implementing the
12
+ appropriate methods. The subclass can then be used by
13
+ :func:`~mpmath.invertlaplace` by passing it as the *method*
14
+ argument.
15
+ """
16
+
17
+ def __init__(self, ctx):
18
+ self.ctx = ctx
19
+
20
+ def calc_laplace_parameter(self, t, **kwargs):
21
+ r"""
22
+ Determine the vector of Laplace parameter values needed for an
23
+ algorithm, this will depend on the choice of algorithm (de
24
+ Hoog is default), the algorithm-specific parameters passed (or
25
+ default ones), and desired time.
26
+ """
27
+ raise NotImplementedError
28
+
29
+ def calc_time_domain_solution(self, fp):
30
+ r"""
31
+ Compute the time domain solution, after computing the
32
+ Laplace-space function evaluations at the abscissa required
33
+ for the algorithm. Abscissa computed for one algorithm are
34
+ typically not useful for another algorithm.
35
+ """
36
+ raise NotImplementedError
37
+
38
+
39
+ class FixedTalbot(InverseLaplaceTransform):
40
+
41
+ def calc_laplace_parameter(self, t, **kwargs):
42
+ r"""The "fixed" Talbot method deforms the Bromwich contour towards
43
+ `-\infty` in the shape of a parabola. Traditionally the Talbot
44
+ algorithm has adjustable parameters, but the "fixed" version
45
+ does not. The `r` parameter could be passed in as a parameter,
46
+ if you want to override the default given by (Abate & Valko,
47
+ 2004).
48
+
49
+ The Laplace parameter is sampled along a parabola opening
50
+ along the negative imaginary axis, with the base of the
51
+ parabola along the real axis at
52
+ `p=\frac{r}{t_\mathrm{max}}`. As the number of terms used in
53
+ the approximation (degree) grows, the abscissa required for
54
+ function evaluation tend towards `-\infty`, requiring high
55
+ precision to prevent overflow. If any poles, branch cuts or
56
+ other singularities exist such that the deformed Bromwich
57
+ contour lies to the left of the singularity, the method will
58
+ fail.
59
+
60
+ **Optional arguments**
61
+
62
+ :class:`~mpmath.calculus.inverselaplace.FixedTalbot.calc_laplace_parameter`
63
+ recognizes the following keywords
64
+
65
+ *tmax*
66
+ maximum time associated with vector of times
67
+ (typically just the time requested)
68
+ *degree*
69
+ integer order of approximation (M = number of terms)
70
+ *r*
71
+ abscissa for `p_0` (otherwise computed using rule
72
+ of thumb `2M/5`)
73
+
74
+ The working precision will be increased according to a rule of
75
+ thumb. If 'degree' is not specified, the working precision and
76
+ degree are chosen to hopefully achieve the dps of the calling
77
+ context. If 'degree' is specified, the working precision is
78
+ chosen to achieve maximum resulting precision for the
79
+ specified degree.
80
+
81
+ .. math ::
82
+
83
+ p_0=\frac{r}{t}
84
+
85
+ .. math ::
86
+
87
+ p_i=\frac{i r \pi}{Mt_\mathrm{max}}\left[\cot\left(
88
+ \frac{i\pi}{M}\right) + j \right] \qquad 1\le i <M
89
+
90
+ where `j=\sqrt{-1}`, `r=2M/5`, and `t_\mathrm{max}` is the
91
+ maximum specified time.
92
+
93
+ """
94
+
95
+ # required
96
+ # ------------------------------
97
+ # time of desired approximation
98
+ self.t = self.ctx.convert(t)
99
+
100
+ # optional
101
+ # ------------------------------
102
+ # maximum time desired (used for scaling) default is requested
103
+ # time.
104
+ self.tmax = self.ctx.convert(kwargs.get('tmax', self.t))
105
+
106
+ # empirical relationships used here based on a linear fit of
107
+ # requested and delivered dps for exponentially decaying time
108
+ # functions for requested dps up to 512.
109
+
110
+ if 'degree' in kwargs:
111
+ self.degree = kwargs['degree']
112
+ self.dps_goal = self.degree
113
+ else:
114
+ self.dps_goal = int(1.72*self.ctx.dps)
115
+ self.degree = max(12, int(1.38*self.dps_goal))
116
+
117
+ M = self.degree
118
+
119
+ # this is adjusting the dps of the calling context hopefully
120
+ # the caller doesn't monkey around with it between calling
121
+ # this routine and calc_time_domain_solution()
122
+ self.dps_orig = self.ctx.dps
123
+ self.ctx.dps = self.dps_goal
124
+
125
+ # Abate & Valko rule of thumb for r parameter
126
+ self.r = kwargs.get('r', self.ctx.fraction(2, 5)*M)
127
+
128
+ self.theta = self.ctx.linspace(0.0, self.ctx.pi, M+1)
129
+
130
+ self.cot_theta = self.ctx.matrix(M, 1)
131
+ self.cot_theta[0] = 0 # not used
132
+
133
+ # all but time-dependent part of p
134
+ self.delta = self.ctx.matrix(M, 1)
135
+ self.delta[0] = self.r
136
+
137
+ for i in range(1, M):
138
+ self.cot_theta[i] = self.ctx.cot(self.theta[i])
139
+ self.delta[i] = self.r*self.theta[i]*(self.cot_theta[i] + 1j)
140
+
141
+ self.p = self.ctx.matrix(M, 1)
142
+ self.p = self.delta/self.tmax
143
+
144
+ # NB: p is complex (mpc)
145
+
146
+ def calc_time_domain_solution(self, fp, t, manual_prec=False):
147
+ r"""The fixed Talbot time-domain solution is computed from the
148
+ Laplace-space function evaluations using
149
+
150
+ .. math ::
151
+
152
+ f(t,M)=\frac{2}{5t}\sum_{k=0}^{M-1}\Re \left[
153
+ \gamma_k \bar{f}(p_k)\right]
154
+
155
+ where
156
+
157
+ .. math ::
158
+
159
+ \gamma_0 = \frac{1}{2}e^{r}\bar{f}(p_0)
160
+
161
+ .. math ::
162
+
163
+ \gamma_k = e^{tp_k}\left\lbrace 1 + \frac{jk\pi}{M}\left[1 +
164
+ \cot \left( \frac{k \pi}{M} \right)^2 \right] - j\cot\left(
165
+ \frac{k \pi}{M}\right)\right \rbrace \qquad 1\le k<M.
166
+
167
+ Again, `j=\sqrt{-1}`.
168
+
169
+ Before calling this function, call
170
+ :class:`~mpmath.calculus.inverselaplace.FixedTalbot.calc_laplace_parameter`
171
+ to set the parameters and compute the required coefficients.
172
+
173
+ **References**
174
+
175
+ 1. Abate, J., P. Valko (2004). Multi-precision Laplace
176
+ transform inversion. *International Journal for Numerical
177
+ Methods in Engineering* 60:979-993,
178
+ http://dx.doi.org/10.1002/nme.995
179
+ 2. Talbot, A. (1979). The accurate numerical inversion of
180
+ Laplace transforms. *IMA Journal of Applied Mathematics*
181
+ 23(1):97, http://dx.doi.org/10.1093/imamat/23.1.97
182
+ """
183
+
184
+ # required
185
+ # ------------------------------
186
+ self.t = self.ctx.convert(t)
187
+
188
+ # assume fp was computed from p matrix returned from
189
+ # calc_laplace_parameter(), so is already a list or matrix of
190
+ # mpmath 'mpc' types
191
+
192
+ # these were computed in previous call to
193
+ # calc_laplace_parameter()
194
+ theta = self.theta
195
+ delta = self.delta
196
+ M = self.degree
197
+ p = self.p
198
+ r = self.r
199
+
200
+ ans = self.ctx.matrix(M, 1)
201
+ ans[0] = self.ctx.exp(delta[0])*fp[0]/2
202
+
203
+ for i in range(1, M):
204
+ ans[i] = self.ctx.exp(delta[i])*fp[i]*(
205
+ 1 + 1j*theta[i]*(1 + self.cot_theta[i]**2) -
206
+ 1j*self.cot_theta[i])
207
+
208
+ result = self.ctx.fraction(2, 5)*self.ctx.fsum(ans)/self.t
209
+
210
+ # setting dps back to value when calc_laplace_parameter was
211
+ # called, unless flag is set.
212
+ if not manual_prec:
213
+ self.ctx.dps = self.dps_orig
214
+
215
+ return result.real
216
+
217
+
218
+ # ****************************************
219
+
220
+ class Stehfest(InverseLaplaceTransform):
221
+
222
+ def calc_laplace_parameter(self, t, **kwargs):
223
+ r"""
224
+ The Gaver-Stehfest method is a discrete approximation of the
225
+ Widder-Post inversion algorithm, rather than a direct
226
+ approximation of the Bromwich contour integral.
227
+
228
+ The method abscissa along the real axis, and therefore has
229
+ issues inverting oscillatory functions (which have poles in
230
+ pairs away from the real axis).
231
+
232
+ The working precision will be increased according to a rule of
233
+ thumb. If 'degree' is not specified, the working precision and
234
+ degree are chosen to hopefully achieve the dps of the calling
235
+ context. If 'degree' is specified, the working precision is
236
+ chosen to achieve maximum resulting precision for the
237
+ specified degree.
238
+
239
+ .. math ::
240
+
241
+ p_k = \frac{k \log 2}{t} \qquad 1 \le k \le M
242
+ """
243
+
244
+ # required
245
+ # ------------------------------
246
+ # time of desired approximation
247
+ self.t = self.ctx.convert(t)
248
+
249
+ # optional
250
+ # ------------------------------
251
+
252
+ # empirical relationships used here based on a linear fit of
253
+ # requested and delivered dps for exponentially decaying time
254
+ # functions for requested dps up to 512.
255
+
256
+ if 'degree' in kwargs:
257
+ self.degree = kwargs['degree']
258
+ self.dps_goal = int(1.38*self.degree)
259
+ else:
260
+ self.dps_goal = int(2.93*self.ctx.dps)
261
+ self.degree = max(16, self.dps_goal)
262
+
263
+ # _coeff routine requires even degree
264
+ if self.degree % 2 > 0:
265
+ self.degree += 1
266
+
267
+ M = self.degree
268
+
269
+ # this is adjusting the dps of the calling context
270
+ # hopefully the caller doesn't monkey around with it
271
+ # between calling this routine and calc_time_domain_solution()
272
+ self.dps_orig = self.ctx.dps
273
+ self.ctx.dps = self.dps_goal
274
+
275
+ self.V = self._coeff()
276
+ self.p = self.ctx.matrix(self.ctx.arange(1, M+1))*self.ctx.ln2/self.t
277
+
278
+ # NB: p is real (mpf)
279
+
280
+ def _coeff(self):
281
+ r"""Salzer summation weights (aka, "Stehfest coefficients")
282
+ only depend on the approximation order (M) and the precision"""
283
+
284
+ M = self.degree
285
+ M2 = int(M/2) # checked earlier that M is even
286
+
287
+ V = self.ctx.matrix(M, 1)
288
+
289
+ # Salzer summation weights
290
+ # get very large in magnitude and oscillate in sign,
291
+ # if the precision is not high enough, there will be
292
+ # catastrophic cancellation
293
+ for k in range(1, M+1):
294
+ z = self.ctx.matrix(min(k, M2)+1, 1)
295
+ for j in range(int((k+1)/2), min(k, M2)+1):
296
+ z[j] = (self.ctx.power(j, M2)*self.ctx.fac(2*j)/
297
+ (self.ctx.fac(M2-j)*self.ctx.fac(j)*
298
+ self.ctx.fac(j-1)*self.ctx.fac(k-j)*
299
+ self.ctx.fac(2*j-k)))
300
+ V[k-1] = self.ctx.power(-1, k+M2)*self.ctx.fsum(z)
301
+
302
+ return V
303
+
304
+ def calc_time_domain_solution(self, fp, t, manual_prec=False):
305
+ r"""Compute time-domain Stehfest algorithm solution.
306
+
307
+ .. math ::
308
+
309
+ f(t,M) = \frac{\log 2}{t} \sum_{k=1}^{M} V_k \bar{f}\left(
310
+ p_k \right)
311
+
312
+ where
313
+
314
+ .. math ::
315
+
316
+ V_k = (-1)^{k + N/2} \sum^{\min(k,N/2)}_{i=\lfloor(k+1)/2 \rfloor}
317
+ \frac{i^{\frac{N}{2}}(2i)!}{\left(\frac{N}{2}-i \right)! \, i! \,
318
+ \left(i-1 \right)! \, \left(k-i\right)! \, \left(2i-k \right)!}
319
+
320
+ As the degree increases, the abscissa (`p_k`) only increase
321
+ linearly towards `\infty`, but the Stehfest coefficients
322
+ (`V_k`) alternate in sign and increase rapidly in sign,
323
+ requiring high precision to prevent overflow or loss of
324
+ significance when evaluating the sum.
325
+
326
+ **References**
327
+
328
+ 1. Widder, D. (1941). *The Laplace Transform*. Princeton.
329
+ 2. Stehfest, H. (1970). Algorithm 368: numerical inversion of
330
+ Laplace transforms. *Communications of the ACM* 13(1):47-49,
331
+ http://dx.doi.org/10.1145/361953.361969
332
+
333
+ """
334
+
335
+ # required
336
+ self.t = self.ctx.convert(t)
337
+
338
+ # assume fp was computed from p matrix returned from
339
+ # calc_laplace_parameter(), so is already
340
+ # a list or matrix of mpmath 'mpf' types
341
+
342
+ result = self.ctx.fdot(self.V, fp)*self.ctx.ln2/self.t
343
+
344
+ # setting dps back to value when calc_laplace_parameter was called
345
+ if not manual_prec:
346
+ self.ctx.dps = self.dps_orig
347
+
348
+ # ignore any small imaginary part
349
+ return result.real
350
+
351
+
352
+ # ****************************************
353
+
354
+ class deHoog(InverseLaplaceTransform):
355
+
356
+ def calc_laplace_parameter(self, t, **kwargs):
357
+ r"""the de Hoog, Knight & Stokes algorithm is an
358
+ accelerated form of the Fourier series numerical
359
+ inverse Laplace transform algorithms.
360
+
361
+ .. math ::
362
+
363
+ p_k = \gamma + \frac{jk}{T} \qquad 0 \le k < 2M+1
364
+
365
+ where
366
+
367
+ .. math ::
368
+
369
+ \gamma = \alpha - \frac{\log \mathrm{tol}}{2T},
370
+
371
+ `j=\sqrt{-1}`, `T = 2t_\mathrm{max}` is a scaled time,
372
+ `\alpha=10^{-\mathrm{dps\_goal}}` is the real part of the
373
+ rightmost pole or singularity, which is chosen based on the
374
+ desired accuracy (assuming the rightmost singularity is 0),
375
+ and `\mathrm{tol}=10\alpha` is the desired tolerance, which is
376
+ chosen in relation to `\alpha`.`
377
+
378
+ When increasing the degree, the abscissa increase towards
379
+ `j\infty`, but more slowly than the fixed Talbot
380
+ algorithm. The de Hoog et al. algorithm typically does better
381
+ with oscillatory functions of time, and less well-behaved
382
+ functions. The method tends to be slower than the Talbot and
383
+ Stehfest algorithsm, especially so at very high precision
384
+ (e.g., `>500` digits precision).
385
+
386
+ """
387
+
388
+ # required
389
+ # ------------------------------
390
+ self.t = self.ctx.convert(t)
391
+
392
+ # optional
393
+ # ------------------------------
394
+ self.tmax = kwargs.get('tmax', self.t)
395
+
396
+ # empirical relationships used here based on a linear fit of
397
+ # requested and delivered dps for exponentially decaying time
398
+ # functions for requested dps up to 512.
399
+
400
+ if 'degree' in kwargs:
401
+ self.degree = kwargs['degree']
402
+ self.dps_goal = int(1.38*self.degree)
403
+ else:
404
+ self.dps_goal = int(self.ctx.dps*1.36)
405
+ self.degree = max(10, self.dps_goal)
406
+
407
+ # 2*M+1 terms in approximation
408
+ M = self.degree
409
+
410
+ # adjust alpha component of abscissa of convergence for higher
411
+ # precision
412
+ tmp = self.ctx.power(10.0, -self.dps_goal)
413
+ self.alpha = self.ctx.convert(kwargs.get('alpha', tmp))
414
+
415
+ # desired tolerance (here simply related to alpha)
416
+ self.tol = self.ctx.convert(kwargs.get('tol', self.alpha*10.0))
417
+ self.np = 2*self.degree+1 # number of terms in approximation
418
+
419
+ # this is adjusting the dps of the calling context
420
+ # hopefully the caller doesn't monkey around with it
421
+ # between calling this routine and calc_time_domain_solution()
422
+ self.dps_orig = self.ctx.dps
423
+ self.ctx.dps = self.dps_goal
424
+
425
+ # scaling factor (likely tun-able, but 2 is typical)
426
+ self.scale = kwargs.get('scale', 2)
427
+ self.T = self.ctx.convert(kwargs.get('T', self.scale*self.tmax))
428
+
429
+ self.p = self.ctx.matrix(2*M+1, 1)
430
+ self.gamma = self.alpha - self.ctx.log(self.tol)/(self.scale*self.T)
431
+ self.p = (self.gamma + self.ctx.pi*
432
+ self.ctx.matrix(self.ctx.arange(self.np))/self.T*1j)
433
+
434
+ # NB: p is complex (mpc)
435
+
436
+ def calc_time_domain_solution(self, fp, t, manual_prec=False):
437
+ r"""Calculate time-domain solution for
438
+ de Hoog, Knight & Stokes algorithm.
439
+
440
+ The un-accelerated Fourier series approach is:
441
+
442
+ .. math ::
443
+
444
+ f(t,2M+1) = \frac{e^{\gamma t}}{T} \sum_{k=0}^{2M}{}^{'}
445
+ \Re\left[\bar{f}\left( p_k \right)
446
+ e^{i\pi t/T} \right],
447
+
448
+ where the prime on the summation indicates the first term is halved.
449
+
450
+ This simplistic approach requires so many function evaluations
451
+ that it is not practical. Non-linear acceleration is
452
+ accomplished via Pade-approximation and an analytic expression
453
+ for the remainder of the continued fraction. See the original
454
+ paper (reference 2 below) a detailed description of the
455
+ numerical approach.
456
+
457
+ **References**
458
+
459
+ 1. Davies, B. (2005). *Integral Transforms and their
460
+ Applications*, Third Edition. Springer.
461
+ 2. de Hoog, F., J. Knight, A. Stokes (1982). An improved
462
+ method for numerical inversion of Laplace transforms. *SIAM
463
+ Journal of Scientific and Statistical Computing* 3:357-366,
464
+ http://dx.doi.org/10.1137/0903022
465
+
466
+ """
467
+
468
+ M = self.degree
469
+ np = self.np
470
+ T = self.T
471
+
472
+ self.t = self.ctx.convert(t)
473
+
474
+ # would it be useful to try re-using
475
+ # space between e&q and A&B?
476
+ e = self.ctx.zeros(np, M+1)
477
+ q = self.ctx.matrix(2*M, M)
478
+ d = self.ctx.matrix(np, 1)
479
+ A = self.ctx.zeros(np+1, 1)
480
+ B = self.ctx.ones(np+1, 1)
481
+
482
+ # initialize Q-D table
483
+ e[:, 0] = 0.0 + 0j
484
+ q[0, 0] = fp[1]/(fp[0]/2)
485
+ for i in range(1, 2*M):
486
+ q[i, 0] = fp[i+1]/fp[i]
487
+
488
+ # rhombus rule for filling triangular Q-D table (e & q)
489
+ for r in range(1, M+1):
490
+ # start with e, column 1, 0:2*M-2
491
+ mr = 2*(M-r) + 1
492
+ e[0:mr, r] = q[1:mr+1, r-1] - q[0:mr, r-1] + e[1:mr+1, r-1]
493
+ if not r == M:
494
+ rq = r+1
495
+ mr = 2*(M-rq)+1 + 2
496
+ for i in range(mr):
497
+ q[i, rq-1] = q[i+1, rq-2]*e[i+1, rq-1]/e[i, rq-1]
498
+
499
+ # build up continued fraction coefficients (d)
500
+ d[0] = fp[0]/2
501
+ for r in range(1, M+1):
502
+ d[2*r-1] = -q[0, r-1] # even terms
503
+ d[2*r] = -e[0, r] # odd terms
504
+
505
+ # seed A and B for recurrence
506
+ A[0] = 0.0 + 0.0j
507
+ A[1] = d[0]
508
+ B[0:2] = 1.0 + 0.0j
509
+
510
+ # base of the power series
511
+ z = self.ctx.expjpi(self.t/T) # i*pi is already in fcn
512
+
513
+ # coefficients of Pade approximation (A & B)
514
+ # using recurrence for all but last term
515
+ for i in range(1, 2*M):
516
+ A[i+1] = A[i] + d[i]*A[i-1]*z
517
+ B[i+1] = B[i] + d[i]*B[i-1]*z
518
+
519
+ # "improved remainder" to continued fraction
520
+ brem = (1 + (d[2*M-1] - d[2*M])*z)/2
521
+ # powm1(x,y) computes x^y - 1 more accurately near zero
522
+ rem = brem*self.ctx.powm1(1 + d[2*M]*z/brem,
523
+ self.ctx.fraction(1, 2))
524
+
525
+ # last term of recurrence using new remainder
526
+ A[np] = A[2*M] + rem*A[2*M-1]
527
+ B[np] = B[2*M] + rem*B[2*M-1]
528
+
529
+ # diagonal Pade approximation
530
+ # F=A/B represents accelerated trapezoid rule
531
+ result = self.ctx.exp(self.gamma*self.t)/T*(A[np]/B[np]).real
532
+
533
+ # setting dps back to value when calc_laplace_parameter was called
534
+ if not manual_prec:
535
+ self.ctx.dps = self.dps_orig
536
+
537
+ return result
538
+
539
+
540
+ # ****************************************
541
+
542
+ class Cohen(InverseLaplaceTransform):
543
+
544
+ def calc_laplace_parameter(self, t, **kwargs):
545
+ r"""The Cohen algorithm accelerates the convergence of the nearly
546
+ alternating series resulting from the application of the trapezoidal
547
+ rule to the Bromwich contour inversion integral.
548
+
549
+ .. math ::
550
+
551
+ p_k = \frac{\gamma}{2 t} + \frac{\pi i k}{t} \qquad 0 \le k < M
552
+
553
+ where
554
+
555
+ .. math ::
556
+
557
+ \gamma = \frac{2}{3} (d + \log(10) + \log(2 t)),
558
+
559
+ `d = \mathrm{dps\_goal}`, which is chosen based on the desired
560
+ accuracy using the method developed in [1] to improve numerical
561
+ stability. The Cohen algorithm shows robustness similar to the de Hoog
562
+ et al. algorithm, but it is faster than the fixed Talbot algorithm.
563
+
564
+ **Optional arguments**
565
+
566
+ *degree*
567
+ integer order of the approximation (M = number of terms)
568
+ *alpha*
569
+ abscissa for `p_0` (controls the discretization error)
570
+
571
+ The working precision will be increased according to a rule of
572
+ thumb. If 'degree' is not specified, the working precision and
573
+ degree are chosen to hopefully achieve the dps of the calling
574
+ context. If 'degree' is specified, the working precision is
575
+ chosen to achieve maximum resulting precision for the
576
+ specified degree.
577
+
578
+ **References**
579
+
580
+ 1. P. Glasserman, J. Ruiz-Mata (2006). Computing the credit loss
581
+ distribution in the Gaussian copula model: a comparison of methods.
582
+ *Journal of Credit Risk* 2(4):33-66, 10.21314/JCR.2006.057
583
+
584
+ """
585
+ self.t = self.ctx.convert(t)
586
+
587
+ if 'degree' in kwargs:
588
+ self.degree = kwargs['degree']
589
+ self.dps_goal = int(1.5 * self.degree)
590
+ else:
591
+ self.dps_goal = int(self.ctx.dps * 1.74)
592
+ self.degree = max(22, int(1.31 * self.dps_goal))
593
+
594
+ M = self.degree + 1
595
+
596
+ # this is adjusting the dps of the calling context hopefully
597
+ # the caller doesn't monkey around with it between calling
598
+ # this routine and calc_time_domain_solution()
599
+ self.dps_orig = self.ctx.dps
600
+ self.ctx.dps = self.dps_goal
601
+
602
+ ttwo = 2 * self.t
603
+ tmp = self.ctx.dps * self.ctx.log(10) + self.ctx.log(ttwo)
604
+ tmp = self.ctx.fraction(2, 3) * tmp
605
+ self.alpha = self.ctx.convert(kwargs.get('alpha', tmp))
606
+
607
+ # all but time-dependent part of p
608
+ a_t = self.alpha / ttwo
609
+ p_t = self.ctx.pi * 1j / self.t
610
+
611
+ self.p = self.ctx.matrix(M, 1)
612
+ self.p[0] = a_t
613
+
614
+ for i in range(1, M):
615
+ self.p[i] = a_t + i * p_t
616
+
617
+ def calc_time_domain_solution(self, fp, t, manual_prec=False):
618
+ r"""Calculate time-domain solution for Cohen algorithm.
619
+
620
+ The accelerated nearly alternating series is:
621
+
622
+ .. math ::
623
+
624
+ f(t, M) = \frac{e^{\gamma / 2}}{t} \left[\frac{1}{2}
625
+ \Re\left(\bar{f}\left(\frac{\gamma}{2t}\right) \right) -
626
+ \sum_{k=0}^{M-1}\frac{c_{M,k}}{d_M}\Re\left(\bar{f}
627
+ \left(\frac{\gamma + 2(k+1) \pi i}{2t}\right)\right)\right],
628
+
629
+ where coefficients `\frac{c_{M, k}}{d_M}` are described in [1].
630
+
631
+ 1. H. Cohen, F. Rodriguez Villegas, D. Zagier (2000). Convergence
632
+ acceleration of alternating series. *Experiment. Math* 9(1):3-12
633
+
634
+ """
635
+ self.t = self.ctx.convert(t)
636
+
637
+ n = self.degree
638
+ M = n + 1
639
+
640
+ A = self.ctx.matrix(M, 1)
641
+ for i in range(M):
642
+ A[i] = fp[i].real
643
+
644
+ d = (3 + self.ctx.sqrt(8)) ** n
645
+ d = (d + 1 / d) / 2
646
+ b = -self.ctx.one
647
+ c = -d
648
+ s = 0
649
+
650
+ for k in range(n):
651
+ c = b - c
652
+ s = s + c * A[k + 1]
653
+ b = 2 * (k + n) * (k - n) * b / ((2 * k + 1) * (k + self.ctx.one))
654
+
655
+ result = self.ctx.exp(self.alpha / 2) / self.t * (A[0] / 2 - s / d)
656
+
657
+ # setting dps back to value when calc_laplace_parameter was
658
+ # called, unless flag is set.
659
+ if not manual_prec:
660
+ self.ctx.dps = self.dps_orig
661
+
662
+ return result
663
+
664
+
665
+ # ****************************************
666
+
667
+ class LaplaceTransformInversionMethods(object):
668
+ def __init__(ctx, *args, **kwargs):
669
+ ctx._fixed_talbot = FixedTalbot(ctx)
670
+ ctx._stehfest = Stehfest(ctx)
671
+ ctx._de_hoog = deHoog(ctx)
672
+ ctx._cohen = Cohen(ctx)
673
+
674
+ def invertlaplace(ctx, f, t, **kwargs):
675
+ r"""Computes the numerical inverse Laplace transform for a
676
+ Laplace-space function at a given time. The function being
677
+ evaluated is assumed to be a real-valued function of time.
678
+
679
+ The user must supply a Laplace-space function `\bar{f}(p)`,
680
+ and a desired time at which to estimate the time-domain
681
+ solution `f(t)`.
682
+
683
+ A few basic examples of Laplace-space functions with known
684
+ inverses (see references [1,2]) :
685
+
686
+ .. math ::
687
+
688
+ \mathcal{L}\left\lbrace f(t) \right\rbrace=\bar{f}(p)
689
+
690
+ .. math ::
691
+
692
+ \mathcal{L}^{-1}\left\lbrace \bar{f}(p) \right\rbrace = f(t)
693
+
694
+ .. math ::
695
+
696
+ \bar{f}(p) = \frac{1}{(p+1)^2}
697
+
698
+ .. math ::
699
+
700
+ f(t) = t e^{-t}
701
+
702
+ >>> from mpmath import *
703
+ >>> mp.dps = 15; mp.pretty = True
704
+ >>> tt = [0.001, 0.01, 0.1, 1, 10]
705
+ >>> fp = lambda p: 1/(p+1)**2
706
+ >>> ft = lambda t: t*exp(-t)
707
+ >>> ft(tt[0]),ft(tt[0])-invertlaplace(fp,tt[0],method='talbot')
708
+ (0.000999000499833375, 8.57923043561212e-20)
709
+ >>> ft(tt[1]),ft(tt[1])-invertlaplace(fp,tt[1],method='talbot')
710
+ (0.00990049833749168, 3.27007646698047e-19)
711
+ >>> ft(tt[2]),ft(tt[2])-invertlaplace(fp,tt[2],method='talbot')
712
+ (0.090483741803596, -1.75215800052168e-18)
713
+ >>> ft(tt[3]),ft(tt[3])-invertlaplace(fp,tt[3],method='talbot')
714
+ (0.367879441171442, 1.2428864009344e-17)
715
+ >>> ft(tt[4]),ft(tt[4])-invertlaplace(fp,tt[4],method='talbot')
716
+ (0.000453999297624849, 4.04513489306658e-20)
717
+
718
+ The methods also work for higher precision:
719
+
720
+ >>> mp.dps = 100; mp.pretty = True
721
+ >>> nstr(ft(tt[0]),15),nstr(ft(tt[0])-invertlaplace(fp,tt[0],method='talbot'),15)
722
+ ('0.000999000499833375', '-4.96868310693356e-105')
723
+ >>> nstr(ft(tt[1]),15),nstr(ft(tt[1])-invertlaplace(fp,tt[1],method='talbot'),15)
724
+ ('0.00990049833749168', '1.23032291513122e-104')
725
+
726
+ .. math ::
727
+
728
+ \bar{f}(p) = \frac{1}{p^2+1}
729
+
730
+ .. math ::
731
+
732
+ f(t) = \mathrm{J}_0(t)
733
+
734
+ >>> mp.dps = 15; mp.pretty = True
735
+ >>> fp = lambda p: 1/sqrt(p*p + 1)
736
+ >>> ft = lambda t: besselj(0,t)
737
+ >>> ft(tt[0]),ft(tt[0])-invertlaplace(fp,tt[0],method='dehoog')
738
+ (0.999999750000016, -6.09717765032273e-18)
739
+ >>> ft(tt[1]),ft(tt[1])-invertlaplace(fp,tt[1],method='dehoog')
740
+ (0.99997500015625, -5.61756281076169e-17)
741
+
742
+ .. math ::
743
+
744
+ \bar{f}(p) = \frac{\log p}{p}
745
+
746
+ .. math ::
747
+
748
+ f(t) = -\gamma -\log t
749
+
750
+ >>> mp.dps = 15; mp.pretty = True
751
+ >>> fp = lambda p: log(p)/p
752
+ >>> ft = lambda t: -euler-log(t)
753
+ >>> ft(tt[0]),ft(tt[0])-invertlaplace(fp,tt[0],method='stehfest')
754
+ (6.3305396140806, -1.92126634837863e-16)
755
+ >>> ft(tt[1]),ft(tt[1])-invertlaplace(fp,tt[1],method='stehfest')
756
+ (4.02795452108656, -4.81486093200704e-16)
757
+
758
+ **Options**
759
+
760
+ :func:`~mpmath.invertlaplace` recognizes the following optional
761
+ keywords valid for all methods:
762
+
763
+ *method*
764
+ Chooses numerical inverse Laplace transform algorithm
765
+ (described below).
766
+ *degree*
767
+ Number of terms used in the approximation
768
+
769
+ **Algorithms**
770
+
771
+ Mpmath implements four numerical inverse Laplace transform
772
+ algorithms, attributed to: Talbot, Stehfest, and de Hoog,
773
+ Knight and Stokes. These can be selected by using
774
+ *method='talbot'*, *method='stehfest'*, *method='dehoog'* or
775
+ *method='cohen'* or by passing the classes *method=FixedTalbot*,
776
+ *method=Stehfest*, *method=deHoog*, or *method=Cohen*. The functions
777
+ :func:`~mpmath.invlaptalbot`, :func:`~mpmath.invlapstehfest`,
778
+ :func:`~mpmath.invlapdehoog`, and :func:`~mpmath.invlapcohen`
779
+ are also available as shortcuts.
780
+
781
+ All four algorithms implement a heuristic balance between the
782
+ requested precision and the precision used internally for the
783
+ calculations. This has been tuned for a typical exponentially
784
+ decaying function and precision up to few hundred decimal
785
+ digits.
786
+
787
+ The Laplace transform converts the variable time (i.e., along
788
+ a line) into a parameter given by the right half of the
789
+ complex `p`-plane. Singularities, poles, and branch cuts in
790
+ the complex `p`-plane contain all the information regarding
791
+ the time behavior of the corresponding function. Any numerical
792
+ method must therefore sample `p`-plane "close enough" to the
793
+ singularities to accurately characterize them, while not
794
+ getting too close to have catastrophic cancellation, overflow,
795
+ or underflow issues. Most significantly, if one or more of the
796
+ singularities in the `p`-plane is not on the left side of the
797
+ Bromwich contour, its effects will be left out of the computed
798
+ solution, and the answer will be completely wrong.
799
+
800
+ *Talbot*
801
+
802
+ The fixed Talbot method is high accuracy and fast, but the
803
+ method can catastrophically fail for certain classes of time-domain
804
+ behavior, including a Heaviside step function for positive
805
+ time (e.g., `H(t-2)`), or some oscillatory behaviors. The
806
+ Talbot method usually has adjustable parameters, but the
807
+ "fixed" variety implemented here does not. This method
808
+ deforms the Bromwich integral contour in the shape of a
809
+ parabola towards `-\infty`, which leads to problems
810
+ when the solution has a decaying exponential in it (e.g., a
811
+ Heaviside step function is equivalent to multiplying by a
812
+ decaying exponential in Laplace space).
813
+
814
+ *Stehfest*
815
+
816
+ The Stehfest algorithm only uses abscissa along the real axis
817
+ of the complex `p`-plane to estimate the time-domain
818
+ function. Oscillatory time-domain functions have poles away
819
+ from the real axis, so this method does not work well with
820
+ oscillatory functions, especially high-frequency ones. This
821
+ method also depends on summation of terms in a series that
822
+ grows very large, and will have catastrophic cancellation
823
+ during summation if the working precision is too low.
824
+
825
+ *de Hoog et al.*
826
+
827
+ The de Hoog, Knight, and Stokes method is essentially a
828
+ Fourier-series quadrature-type approximation to the Bromwich
829
+ contour integral, with non-linear series acceleration and an
830
+ analytical expression for the remainder term. This method is
831
+ typically one of the most robust. This method also involves the
832
+ greatest amount of overhead, so it is typically the slowest of the
833
+ four methods at high precision.
834
+
835
+ *Cohen*
836
+
837
+ The Cohen method is a trapezoidal rule approximation to the Bromwich
838
+ contour integral, with linear acceleration for alternating
839
+ series. This method is as robust as the de Hoog et al method and the
840
+ fastest of the four methods at high precision, and is therefore the
841
+ default method.
842
+
843
+ **Singularities**
844
+
845
+ All numerical inverse Laplace transform methods have problems
846
+ at large time when the Laplace-space function has poles,
847
+ singularities, or branch cuts to the right of the origin in
848
+ the complex plane. For simple poles in `\bar{f}(p)` at the
849
+ `p`-plane origin, the time function is constant in time (e.g.,
850
+ `\mathcal{L}\left\lbrace 1 \right\rbrace=1/p` has a pole at
851
+ `p=0`). A pole in `\bar{f}(p)` to the left of the origin is a
852
+ decreasing function of time (e.g., `\mathcal{L}\left\lbrace
853
+ e^{-t/2} \right\rbrace=1/(p+1/2)` has a pole at `p=-1/2`), and
854
+ a pole to the right of the origin leads to an increasing
855
+ function in time (e.g., `\mathcal{L}\left\lbrace t e^{t/4}
856
+ \right\rbrace = 1/(p-1/4)^2` has a pole at `p=1/4`). When
857
+ singularities occur off the real `p` axis, the time-domain
858
+ function is oscillatory. For example `\mathcal{L}\left\lbrace
859
+ \mathrm{J}_0(t) \right\rbrace=1/\sqrt{p^2+1}` has a branch cut
860
+ starting at `p=j=\sqrt{-1}` and is a decaying oscillatory
861
+ function, This range of behaviors is illustrated in Duffy [3]
862
+ Figure 4.10.4, p. 228.
863
+
864
+ In general as `p \rightarrow \infty` `t \rightarrow 0` and
865
+ vice-versa. All numerical inverse Laplace transform methods
866
+ require their abscissa to shift closer to the origin for
867
+ larger times. If the abscissa shift left of the rightmost
868
+ singularity in the Laplace domain, the answer will be
869
+ completely wrong (the effect of singularities to the right of
870
+ the Bromwich contour are not included in the results).
871
+
872
+ For example, the following exponentially growing function has
873
+ a pole at `p=3`:
874
+
875
+ .. math ::
876
+
877
+ \bar{f}(p)=\frac{1}{p^2-9}
878
+
879
+ .. math ::
880
+
881
+ f(t)=\frac{1}{3}\sinh 3t
882
+
883
+ >>> mp.dps = 15; mp.pretty = True
884
+ >>> fp = lambda p: 1/(p*p-9)
885
+ >>> ft = lambda t: sinh(3*t)/3
886
+ >>> tt = [0.01,0.1,1.0,10.0]
887
+ >>> ft(tt[0]),invertlaplace(fp,tt[0],method='talbot')
888
+ (0.0100015000675014, 0.0100015000675014)
889
+ >>> ft(tt[1]),invertlaplace(fp,tt[1],method='talbot')
890
+ (0.101506764482381, 0.101506764482381)
891
+ >>> ft(tt[2]),invertlaplace(fp,tt[2],method='talbot')
892
+ (3.33929164246997, 3.33929164246997)
893
+ >>> ft(tt[3]),invertlaplace(fp,tt[3],method='talbot')
894
+ (1781079096920.74, -1.61331069624091e-14)
895
+
896
+ **References**
897
+
898
+ 1. [DLMF]_ section 1.14 (http://dlmf.nist.gov/1.14T4)
899
+ 2. Cohen, A.M. (2007). Numerical Methods for Laplace Transform
900
+ Inversion, Springer.
901
+ 3. Duffy, D.G. (1998). Advanced Engineering Mathematics, CRC Press.
902
+
903
+ **Numerical Inverse Laplace Transform Reviews**
904
+
905
+ 1. Bellman, R., R.E. Kalaba, J.A. Lockett (1966). *Numerical
906
+ inversion of the Laplace transform: Applications to Biology,
907
+ Economics, Engineering, and Physics*. Elsevier.
908
+ 2. Davies, B., B. Martin (1979). Numerical inversion of the
909
+ Laplace transform: a survey and comparison of methods. *Journal
910
+ of Computational Physics* 33:1-32,
911
+ http://dx.doi.org/10.1016/0021-9991(79)90025-1
912
+ 3. Duffy, D.G. (1993). On the numerical inversion of Laplace
913
+ transforms: Comparison of three new methods on characteristic
914
+ problems from applications. *ACM Transactions on Mathematical
915
+ Software* 19(3):333-359, http://dx.doi.org/10.1145/155743.155788
916
+ 4. Kuhlman, K.L., (2013). Review of Inverse Laplace Transform
917
+ Algorithms for Laplace-Space Numerical Approaches, *Numerical
918
+ Algorithms*, 63(2):339-355.
919
+ http://dx.doi.org/10.1007/s11075-012-9625-3
920
+
921
+ """
922
+
923
+ rule = kwargs.get('method', 'cohen')
924
+ if type(rule) is str:
925
+ lrule = rule.lower()
926
+ if lrule == 'talbot':
927
+ rule = ctx._fixed_talbot
928
+ elif lrule == 'stehfest':
929
+ rule = ctx._stehfest
930
+ elif lrule == 'dehoog':
931
+ rule = ctx._de_hoog
932
+ elif rule == 'cohen':
933
+ rule = ctx._cohen
934
+ else:
935
+ raise ValueError("unknown invlap algorithm: %s" % rule)
936
+ else:
937
+ rule = rule(ctx)
938
+
939
+ # determine the vector of Laplace-space parameter
940
+ # needed for the requested method and desired time
941
+ rule.calc_laplace_parameter(t, **kwargs)
942
+
943
+ # compute the Laplace-space function evalutations
944
+ # at the required abscissa.
945
+ fp = [f(p) for p in rule.p]
946
+
947
+ # compute the time-domain solution from the
948
+ # Laplace-space function evaluations
949
+ return rule.calc_time_domain_solution(fp, t)
950
+
951
+ # shortcuts for the above function for specific methods
952
+ def invlaptalbot(ctx, *args, **kwargs):
953
+ kwargs['method'] = 'talbot'
954
+ return ctx.invertlaplace(*args, **kwargs)
955
+
956
+ def invlapstehfest(ctx, *args, **kwargs):
957
+ kwargs['method'] = 'stehfest'
958
+ return ctx.invertlaplace(*args, **kwargs)
959
+
960
+ def invlapdehoog(ctx, *args, **kwargs):
961
+ kwargs['method'] = 'dehoog'
962
+ return ctx.invertlaplace(*args, **kwargs)
963
+
964
+ def invlapcohen(ctx, *args, **kwargs):
965
+ kwargs['method'] = 'cohen'
966
+ return ctx.invertlaplace(*args, **kwargs)
967
+
968
+
969
+ # ****************************************
970
+
971
+ if __name__ == '__main__':
972
+ import doctest
973
+ doctest.testmod()
tuning-competition-baseline/.venv/lib/python3.11/site-packages/mpmath/functions/__pycache__/__init__.cpython-311.pyc ADDED
Binary file (834 Bytes). View file
 
tuning-competition-baseline/.venv/lib/python3.11/site-packages/mpmath/functions/__pycache__/bessel.cpython-311.pyc ADDED
Binary file (63.1 kB). View file
 
tuning-competition-baseline/.venv/lib/python3.11/site-packages/mpmath/functions/__pycache__/elliptic.cpython-311.pyc ADDED
Binary file (57.8 kB). View file
 
tuning-competition-baseline/.venv/lib/python3.11/site-packages/mpmath/functions/__pycache__/factorials.cpython-311.pyc ADDED
Binary file (10.9 kB). View file
 
tuning-competition-baseline/.venv/lib/python3.11/site-packages/mpmath/functions/__pycache__/functions.cpython-311.pyc ADDED
Binary file (33.4 kB). View file
 
tuning-competition-baseline/.venv/lib/python3.11/site-packages/mpmath/functions/__pycache__/hypergeometric.cpython-311.pyc ADDED
Binary file (76.8 kB). View file
 
tuning-competition-baseline/.venv/lib/python3.11/site-packages/mpmath/functions/__pycache__/orthogonal.cpython-311.pyc ADDED
Binary file (25.8 kB). View file
 
tuning-competition-baseline/.venv/lib/python3.11/site-packages/mpmath/functions/__pycache__/rszeta.cpython-311.pyc ADDED
Binary file (73.9 kB). View file
 
tuning-competition-baseline/.venv/lib/python3.11/site-packages/mpmath/functions/__pycache__/zeta.cpython-311.pyc ADDED
Binary file (64.2 kB). View file
 
tuning-competition-baseline/.venv/lib/python3.11/site-packages/mpmath/functions/__pycache__/zetazeros.cpython-311.pyc ADDED
Binary file (45.8 kB). View file
 
tuning-competition-baseline/.venv/lib/python3.11/site-packages/mpmath/functions/orthogonal.py ADDED
@@ -0,0 +1,493 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from .functions import defun, defun_wrapped
2
+
3
+ def _hermite_param(ctx, n, z, parabolic_cylinder):
4
+ """
5
+ Combined calculation of the Hermite polynomial H_n(z) (and its
6
+ generalization to complex n) and the parabolic cylinder
7
+ function D.
8
+ """
9
+ n, ntyp = ctx._convert_param(n)
10
+ z = ctx.convert(z)
11
+ q = -ctx.mpq_1_2
12
+ # For re(z) > 0, 2F0 -- http://functions.wolfram.com/
13
+ # HypergeometricFunctions/HermiteHGeneral/06/02/0009/
14
+ # Otherwise, there is a reflection formula
15
+ # 2F0 + http://functions.wolfram.com/HypergeometricFunctions/
16
+ # HermiteHGeneral/16/01/01/0006/
17
+ #
18
+ # TODO:
19
+ # An alternative would be to use
20
+ # http://functions.wolfram.com/HypergeometricFunctions/
21
+ # HermiteHGeneral/06/02/0006/
22
+ #
23
+ # Also, the 1F1 expansion
24
+ # http://functions.wolfram.com/HypergeometricFunctions/
25
+ # HermiteHGeneral/26/01/02/0001/
26
+ # should probably be used for tiny z
27
+ if not z:
28
+ T1 = [2, ctx.pi], [n, 0.5], [], [q*(n-1)], [], [], 0
29
+ if parabolic_cylinder:
30
+ T1[1][0] += q*n
31
+ return T1,
32
+ can_use_2f0 = ctx.isnpint(-n) or ctx.re(z) > 0 or \
33
+ (ctx.re(z) == 0 and ctx.im(z) > 0)
34
+ expprec = ctx.prec*4 + 20
35
+ if parabolic_cylinder:
36
+ u = ctx.fmul(ctx.fmul(z,z,prec=expprec), -0.25, exact=True)
37
+ w = ctx.fmul(z, ctx.sqrt(0.5,prec=expprec), prec=expprec)
38
+ else:
39
+ w = z
40
+ w2 = ctx.fmul(w, w, prec=expprec)
41
+ rw2 = ctx.fdiv(1, w2, prec=expprec)
42
+ nrw2 = ctx.fneg(rw2, exact=True)
43
+ nw = ctx.fneg(w, exact=True)
44
+ if can_use_2f0:
45
+ T1 = [2, w], [n, n], [], [], [q*n, q*(n-1)], [], nrw2
46
+ terms = [T1]
47
+ else:
48
+ T1 = [2, nw], [n, n], [], [], [q*n, q*(n-1)], [], nrw2
49
+ T2 = [2, ctx.pi, nw], [n+2, 0.5, 1], [], [q*n], [q*(n-1)], [1-q], w2
50
+ terms = [T1,T2]
51
+ # Multiply by prefactor for D_n
52
+ if parabolic_cylinder:
53
+ expu = ctx.exp(u)
54
+ for i in range(len(terms)):
55
+ terms[i][1][0] += q*n
56
+ terms[i][0].append(expu)
57
+ terms[i][1].append(1)
58
+ return tuple(terms)
59
+
60
+ @defun
61
+ def hermite(ctx, n, z, **kwargs):
62
+ return ctx.hypercomb(lambda: _hermite_param(ctx, n, z, 0), [], **kwargs)
63
+
64
+ @defun
65
+ def pcfd(ctx, n, z, **kwargs):
66
+ r"""
67
+ Gives the parabolic cylinder function in Whittaker's notation
68
+ `D_n(z) = U(-n-1/2, z)` (see :func:`~mpmath.pcfu`).
69
+ It solves the differential equation
70
+
71
+ .. math ::
72
+
73
+ y'' + \left(n + \frac{1}{2} - \frac{1}{4} z^2\right) y = 0.
74
+
75
+ and can be represented in terms of Hermite polynomials
76
+ (see :func:`~mpmath.hermite`) as
77
+
78
+ .. math ::
79
+
80
+ D_n(z) = 2^{-n/2} e^{-z^2/4} H_n\left(\frac{z}{\sqrt{2}}\right).
81
+
82
+ **Plots**
83
+
84
+ .. literalinclude :: /plots/pcfd.py
85
+ .. image :: /plots/pcfd.png
86
+
87
+ **Examples**
88
+
89
+ >>> from mpmath import *
90
+ >>> mp.dps = 25; mp.pretty = True
91
+ >>> pcfd(0,0); pcfd(1,0); pcfd(2,0); pcfd(3,0)
92
+ 1.0
93
+ 0.0
94
+ -1.0
95
+ 0.0
96
+ >>> pcfd(4,0); pcfd(-3,0)
97
+ 3.0
98
+ 0.6266570686577501256039413
99
+ >>> pcfd('1/2', 2+3j)
100
+ (-5.363331161232920734849056 - 3.858877821790010714163487j)
101
+ >>> pcfd(2, -10)
102
+ 1.374906442631438038871515e-9
103
+
104
+ Verifying the differential equation::
105
+
106
+ >>> n = mpf(2.5)
107
+ >>> y = lambda z: pcfd(n,z)
108
+ >>> z = 1.75
109
+ >>> chop(diff(y,z,2) + (n+0.5-0.25*z**2)*y(z))
110
+ 0.0
111
+
112
+ Rational Taylor series expansion when `n` is an integer::
113
+
114
+ >>> taylor(lambda z: pcfd(5,z), 0, 7)
115
+ [0.0, 15.0, 0.0, -13.75, 0.0, 3.96875, 0.0, -0.6015625]
116
+
117
+ """
118
+ return ctx.hypercomb(lambda: _hermite_param(ctx, n, z, 1), [], **kwargs)
119
+
120
+ @defun
121
+ def pcfu(ctx, a, z, **kwargs):
122
+ r"""
123
+ Gives the parabolic cylinder function `U(a,z)`, which may be
124
+ defined for `\Re(z) > 0` in terms of the confluent
125
+ U-function (see :func:`~mpmath.hyperu`) by
126
+
127
+ .. math ::
128
+
129
+ U(a,z) = 2^{-\frac{1}{4}-\frac{a}{2}} e^{-\frac{1}{4} z^2}
130
+ U\left(\frac{a}{2}+\frac{1}{4},
131
+ \frac{1}{2}, \frac{1}{2}z^2\right)
132
+
133
+ or, for arbitrary `z`,
134
+
135
+ .. math ::
136
+
137
+ e^{-\frac{1}{4}z^2} U(a,z) =
138
+ U(a,0) \,_1F_1\left(-\tfrac{a}{2}+\tfrac{1}{4};
139
+ \tfrac{1}{2}; -\tfrac{1}{2}z^2\right) +
140
+ U'(a,0) z \,_1F_1\left(-\tfrac{a}{2}+\tfrac{3}{4};
141
+ \tfrac{3}{2}; -\tfrac{1}{2}z^2\right).
142
+
143
+ **Examples**
144
+
145
+ Connection to other functions::
146
+
147
+ >>> from mpmath import *
148
+ >>> mp.dps = 25; mp.pretty = True
149
+ >>> z = mpf(3)
150
+ >>> pcfu(0.5,z)
151
+ 0.03210358129311151450551963
152
+ >>> sqrt(pi/2)*exp(z**2/4)*erfc(z/sqrt(2))
153
+ 0.03210358129311151450551963
154
+ >>> pcfu(0.5,-z)
155
+ 23.75012332835297233711255
156
+ >>> sqrt(pi/2)*exp(z**2/4)*erfc(-z/sqrt(2))
157
+ 23.75012332835297233711255
158
+ >>> pcfu(0.5,-z)
159
+ 23.75012332835297233711255
160
+ >>> sqrt(pi/2)*exp(z**2/4)*erfc(-z/sqrt(2))
161
+ 23.75012332835297233711255
162
+
163
+ """
164
+ n, _ = ctx._convert_param(a)
165
+ return ctx.pcfd(-n-ctx.mpq_1_2, z)
166
+
167
+ @defun
168
+ def pcfv(ctx, a, z, **kwargs):
169
+ r"""
170
+ Gives the parabolic cylinder function `V(a,z)`, which can be
171
+ represented in terms of :func:`~mpmath.pcfu` as
172
+
173
+ .. math ::
174
+
175
+ V(a,z) = \frac{\Gamma(a+\tfrac{1}{2}) (U(a,-z)-\sin(\pi a) U(a,z)}{\pi}.
176
+
177
+ **Examples**
178
+
179
+ Wronskian relation between `U` and `V`::
180
+
181
+ >>> from mpmath import *
182
+ >>> mp.dps = 25; mp.pretty = True
183
+ >>> a, z = 2, 3
184
+ >>> pcfu(a,z)*diff(pcfv,(a,z),(0,1))-diff(pcfu,(a,z),(0,1))*pcfv(a,z)
185
+ 0.7978845608028653558798921
186
+ >>> sqrt(2/pi)
187
+ 0.7978845608028653558798921
188
+ >>> a, z = 2.5, 3
189
+ >>> pcfu(a,z)*diff(pcfv,(a,z),(0,1))-diff(pcfu,(a,z),(0,1))*pcfv(a,z)
190
+ 0.7978845608028653558798921
191
+ >>> a, z = 0.25, -1
192
+ >>> pcfu(a,z)*diff(pcfv,(a,z),(0,1))-diff(pcfu,(a,z),(0,1))*pcfv(a,z)
193
+ 0.7978845608028653558798921
194
+ >>> a, z = 2+1j, 2+3j
195
+ >>> chop(pcfu(a,z)*diff(pcfv,(a,z),(0,1))-diff(pcfu,(a,z),(0,1))*pcfv(a,z))
196
+ 0.7978845608028653558798921
197
+
198
+ """
199
+ n, ntype = ctx._convert_param(a)
200
+ z = ctx.convert(z)
201
+ q = ctx.mpq_1_2
202
+ r = ctx.mpq_1_4
203
+ if ntype == 'Q' and ctx.isint(n*2):
204
+ # Faster for half-integers
205
+ def h():
206
+ jz = ctx.fmul(z, -1j, exact=True)
207
+ T1terms = _hermite_param(ctx, -n-q, z, 1)
208
+ T2terms = _hermite_param(ctx, n-q, jz, 1)
209
+ for T in T1terms:
210
+ T[0].append(1j)
211
+ T[1].append(1)
212
+ T[3].append(q-n)
213
+ u = ctx.expjpi((q*n-r)) * ctx.sqrt(2/ctx.pi)
214
+ for T in T2terms:
215
+ T[0].append(u)
216
+ T[1].append(1)
217
+ return T1terms + T2terms
218
+ v = ctx.hypercomb(h, [], **kwargs)
219
+ if ctx._is_real_type(n) and ctx._is_real_type(z):
220
+ v = ctx._re(v)
221
+ return v
222
+ else:
223
+ def h(n):
224
+ w = ctx.square_exp_arg(z, -0.25)
225
+ u = ctx.square_exp_arg(z, 0.5)
226
+ e = ctx.exp(w)
227
+ l = [ctx.pi, q, ctx.exp(w)]
228
+ Y1 = l, [-q, n*q+r, 1], [r-q*n], [], [q*n+r], [q], u
229
+ Y2 = l + [z], [-q, n*q-r, 1, 1], [1-r-q*n], [], [q*n+1-r], [1+q], u
230
+ c, s = ctx.cospi_sinpi(r+q*n)
231
+ Y1[0].append(s)
232
+ Y2[0].append(c)
233
+ for Y in (Y1, Y2):
234
+ Y[1].append(1)
235
+ Y[3].append(q-n)
236
+ return Y1, Y2
237
+ return ctx.hypercomb(h, [n], **kwargs)
238
+
239
+
240
+ @defun
241
+ def pcfw(ctx, a, z, **kwargs):
242
+ r"""
243
+ Gives the parabolic cylinder function `W(a,z)` defined in (DLMF 12.14).
244
+
245
+ **Examples**
246
+
247
+ Value at the origin::
248
+
249
+ >>> from mpmath import *
250
+ >>> mp.dps = 25; mp.pretty = True
251
+ >>> a = mpf(0.25)
252
+ >>> pcfw(a,0)
253
+ 0.9722833245718180765617104
254
+ >>> power(2,-0.75)*sqrt(abs(gamma(0.25+0.5j*a)/gamma(0.75+0.5j*a)))
255
+ 0.9722833245718180765617104
256
+ >>> diff(pcfw,(a,0),(0,1))
257
+ -0.5142533944210078966003624
258
+ >>> -power(2,-0.25)*sqrt(abs(gamma(0.75+0.5j*a)/gamma(0.25+0.5j*a)))
259
+ -0.5142533944210078966003624
260
+
261
+ """
262
+ n, _ = ctx._convert_param(a)
263
+ z = ctx.convert(z)
264
+ def terms():
265
+ phi2 = ctx.arg(ctx.gamma(0.5 + ctx.j*n))
266
+ phi2 = (ctx.loggamma(0.5+ctx.j*n) - ctx.loggamma(0.5-ctx.j*n))/2j
267
+ rho = ctx.pi/8 + 0.5*phi2
268
+ # XXX: cancellation computing k
269
+ k = ctx.sqrt(1 + ctx.exp(2*ctx.pi*n)) - ctx.exp(ctx.pi*n)
270
+ C = ctx.sqrt(k/2) * ctx.exp(0.25*ctx.pi*n)
271
+ yield C * ctx.expj(rho) * ctx.pcfu(ctx.j*n, z*ctx.expjpi(-0.25))
272
+ yield C * ctx.expj(-rho) * ctx.pcfu(-ctx.j*n, z*ctx.expjpi(0.25))
273
+ v = ctx.sum_accurately(terms)
274
+ if ctx._is_real_type(n) and ctx._is_real_type(z):
275
+ v = ctx._re(v)
276
+ return v
277
+
278
+ """
279
+ Even/odd PCFs. Useful?
280
+
281
+ @defun
282
+ def pcfy1(ctx, a, z, **kwargs):
283
+ a, _ = ctx._convert_param(n)
284
+ z = ctx.convert(z)
285
+ def h():
286
+ w = ctx.square_exp_arg(z)
287
+ w1 = ctx.fmul(w, -0.25, exact=True)
288
+ w2 = ctx.fmul(w, 0.5, exact=True)
289
+ e = ctx.exp(w1)
290
+ return [e], [1], [], [], [ctx.mpq_1_2*a+ctx.mpq_1_4], [ctx.mpq_1_2], w2
291
+ return ctx.hypercomb(h, [], **kwargs)
292
+
293
+ @defun
294
+ def pcfy2(ctx, a, z, **kwargs):
295
+ a, _ = ctx._convert_param(n)
296
+ z = ctx.convert(z)
297
+ def h():
298
+ w = ctx.square_exp_arg(z)
299
+ w1 = ctx.fmul(w, -0.25, exact=True)
300
+ w2 = ctx.fmul(w, 0.5, exact=True)
301
+ e = ctx.exp(w1)
302
+ return [e, z], [1, 1], [], [], [ctx.mpq_1_2*a+ctx.mpq_3_4], \
303
+ [ctx.mpq_3_2], w2
304
+ return ctx.hypercomb(h, [], **kwargs)
305
+ """
306
+
307
+ @defun_wrapped
308
+ def gegenbauer(ctx, n, a, z, **kwargs):
309
+ # Special cases: a+0.5, a*2 poles
310
+ if ctx.isnpint(a):
311
+ return 0*(z+n)
312
+ if ctx.isnpint(a+0.5):
313
+ # TODO: something else is required here
314
+ # E.g.: gegenbauer(-2, -0.5, 3) == -12
315
+ if ctx.isnpint(n+1):
316
+ raise NotImplementedError("Gegenbauer function with two limits")
317
+ def h(a):
318
+ a2 = 2*a
319
+ T = [], [], [n+a2], [n+1, a2], [-n, n+a2], [a+0.5], 0.5*(1-z)
320
+ return [T]
321
+ return ctx.hypercomb(h, [a], **kwargs)
322
+ def h(n):
323
+ a2 = 2*a
324
+ T = [], [], [n+a2], [n+1, a2], [-n, n+a2], [a+0.5], 0.5*(1-z)
325
+ return [T]
326
+ return ctx.hypercomb(h, [n], **kwargs)
327
+
328
+ @defun_wrapped
329
+ def jacobi(ctx, n, a, b, x, **kwargs):
330
+ if not ctx.isnpint(a):
331
+ def h(n):
332
+ return (([], [], [a+n+1], [n+1, a+1], [-n, a+b+n+1], [a+1], (1-x)*0.5),)
333
+ return ctx.hypercomb(h, [n], **kwargs)
334
+ if not ctx.isint(b):
335
+ def h(n, a):
336
+ return (([], [], [-b], [n+1, -b-n], [-n, a+b+n+1], [b+1], (x+1)*0.5),)
337
+ return ctx.hypercomb(h, [n, a], **kwargs)
338
+ # XXX: determine appropriate limit
339
+ return ctx.binomial(n+a,n) * ctx.hyp2f1(-n,1+n+a+b,a+1,(1-x)/2, **kwargs)
340
+
341
+ @defun_wrapped
342
+ def laguerre(ctx, n, a, z, **kwargs):
343
+ # XXX: limits, poles
344
+ #if ctx.isnpint(n):
345
+ # return 0*(a+z)
346
+ def h(a):
347
+ return (([], [], [a+n+1], [a+1, n+1], [-n], [a+1], z),)
348
+ return ctx.hypercomb(h, [a], **kwargs)
349
+
350
+ @defun_wrapped
351
+ def legendre(ctx, n, x, **kwargs):
352
+ if ctx.isint(n):
353
+ n = int(n)
354
+ # Accuracy near zeros
355
+ if (n + (n < 0)) & 1:
356
+ if not x:
357
+ return x
358
+ mag = ctx.mag(x)
359
+ if mag < -2*ctx.prec-10:
360
+ return x
361
+ if mag < -5:
362
+ ctx.prec += -mag
363
+ return ctx.hyp2f1(-n,n+1,1,(1-x)/2, **kwargs)
364
+
365
+ @defun
366
+ def legenp(ctx, n, m, z, type=2, **kwargs):
367
+ # Legendre function, 1st kind
368
+ n = ctx.convert(n)
369
+ m = ctx.convert(m)
370
+ # Faster
371
+ if not m:
372
+ return ctx.legendre(n, z, **kwargs)
373
+ # TODO: correct evaluation at singularities
374
+ if type == 2:
375
+ def h(n,m):
376
+ g = m*0.5
377
+ T = [1+z, 1-z], [g, -g], [], [1-m], [-n, n+1], [1-m], 0.5*(1-z)
378
+ return (T,)
379
+ return ctx.hypercomb(h, [n,m], **kwargs)
380
+ if type == 3:
381
+ def h(n,m):
382
+ g = m*0.5
383
+ T = [z+1, z-1], [g, -g], [], [1-m], [-n, n+1], [1-m], 0.5*(1-z)
384
+ return (T,)
385
+ return ctx.hypercomb(h, [n,m], **kwargs)
386
+ raise ValueError("requires type=2 or type=3")
387
+
388
+ @defun
389
+ def legenq(ctx, n, m, z, type=2, **kwargs):
390
+ # Legendre function, 2nd kind
391
+ n = ctx.convert(n)
392
+ m = ctx.convert(m)
393
+ z = ctx.convert(z)
394
+ if z in (1, -1):
395
+ #if ctx.isint(m):
396
+ # return ctx.nan
397
+ #return ctx.inf # unsigned
398
+ return ctx.nan
399
+ if type == 2:
400
+ def h(n, m):
401
+ cos, sin = ctx.cospi_sinpi(m)
402
+ s = 2 * sin / ctx.pi
403
+ c = cos
404
+ a = 1+z
405
+ b = 1-z
406
+ u = m/2
407
+ w = (1-z)/2
408
+ T1 = [s, c, a, b], [-1, 1, u, -u], [], [1-m], \
409
+ [-n, n+1], [1-m], w
410
+ T2 = [-s, a, b], [-1, -u, u], [n+m+1], [n-m+1, m+1], \
411
+ [-n, n+1], [m+1], w
412
+ return T1, T2
413
+ return ctx.hypercomb(h, [n, m], **kwargs)
414
+ if type == 3:
415
+ # The following is faster when there only is a single series
416
+ # Note: not valid for -1 < z < 0 (?)
417
+ if abs(z) > 1:
418
+ def h(n, m):
419
+ T1 = [ctx.expjpi(m), 2, ctx.pi, z, z-1, z+1], \
420
+ [1, -n-1, 0.5, -n-m-1, 0.5*m, 0.5*m], \
421
+ [n+m+1], [n+1.5], \
422
+ [0.5*(2+n+m), 0.5*(1+n+m)], [n+1.5], z**(-2)
423
+ return [T1]
424
+ return ctx.hypercomb(h, [n, m], **kwargs)
425
+ else:
426
+ # not valid for 1 < z < inf ?
427
+ def h(n, m):
428
+ s = 2 * ctx.sinpi(m) / ctx.pi
429
+ c = ctx.expjpi(m)
430
+ a = 1+z
431
+ b = z-1
432
+ u = m/2
433
+ w = (1-z)/2
434
+ T1 = [s, c, a, b], [-1, 1, u, -u], [], [1-m], \
435
+ [-n, n+1], [1-m], w
436
+ T2 = [-s, c, a, b], [-1, 1, -u, u], [n+m+1], [n-m+1, m+1], \
437
+ [-n, n+1], [m+1], w
438
+ return T1, T2
439
+ return ctx.hypercomb(h, [n, m], **kwargs)
440
+ raise ValueError("requires type=2 or type=3")
441
+
442
+ @defun_wrapped
443
+ def chebyt(ctx, n, x, **kwargs):
444
+ if (not x) and ctx.isint(n) and int(ctx._re(n)) % 2 == 1:
445
+ return x * 0
446
+ return ctx.hyp2f1(-n,n,(1,2),(1-x)/2, **kwargs)
447
+
448
+ @defun_wrapped
449
+ def chebyu(ctx, n, x, **kwargs):
450
+ if (not x) and ctx.isint(n) and int(ctx._re(n)) % 2 == 1:
451
+ return x * 0
452
+ return (n+1) * ctx.hyp2f1(-n, n+2, (3,2), (1-x)/2, **kwargs)
453
+
454
+ @defun
455
+ def spherharm(ctx, l, m, theta, phi, **kwargs):
456
+ l = ctx.convert(l)
457
+ m = ctx.convert(m)
458
+ theta = ctx.convert(theta)
459
+ phi = ctx.convert(phi)
460
+ l_isint = ctx.isint(l)
461
+ l_natural = l_isint and l >= 0
462
+ m_isint = ctx.isint(m)
463
+ if l_isint and l < 0 and m_isint:
464
+ return ctx.spherharm(-(l+1), m, theta, phi, **kwargs)
465
+ if theta == 0 and m_isint and m < 0:
466
+ return ctx.zero * 1j
467
+ if l_natural and m_isint:
468
+ if abs(m) > l:
469
+ return ctx.zero * 1j
470
+ # http://functions.wolfram.com/Polynomials/
471
+ # SphericalHarmonicY/26/01/02/0004/
472
+ def h(l,m):
473
+ absm = abs(m)
474
+ C = [-1, ctx.expj(m*phi),
475
+ (2*l+1)*ctx.fac(l+absm)/ctx.pi/ctx.fac(l-absm),
476
+ ctx.sin(theta)**2,
477
+ ctx.fac(absm), 2]
478
+ P = [0.5*m*(ctx.sign(m)+1), 1, 0.5, 0.5*absm, -1, -absm-1]
479
+ return ((C, P, [], [], [absm-l, l+absm+1], [absm+1],
480
+ ctx.sin(0.5*theta)**2),)
481
+ else:
482
+ # http://functions.wolfram.com/HypergeometricFunctions/
483
+ # SphericalHarmonicYGeneral/26/01/02/0001/
484
+ def h(l,m):
485
+ if ctx.isnpint(l-m+1) or ctx.isnpint(l+m+1) or ctx.isnpint(1-m):
486
+ return (([0], [-1], [], [], [], [], 0),)
487
+ cos, sin = ctx.cos_sin(0.5*theta)
488
+ C = [0.5*ctx.expj(m*phi), (2*l+1)/ctx.pi,
489
+ ctx.gamma(l-m+1), ctx.gamma(l+m+1),
490
+ cos**2, sin**2]
491
+ P = [1, 0.5, 0.5, -0.5, 0.5*m, -0.5*m]
492
+ return ((C, P, [], [1-m], [-l,l+1], [1-m], sin**2),)
493
+ return ctx.hypercomb(h, [l,m], **kwargs)
tuning-competition-baseline/.venv/lib/python3.11/site-packages/mpmath/matrices/__pycache__/__init__.cpython-311.pyc ADDED
Binary file (314 Bytes). View file
 
tuning-competition-baseline/.venv/lib/python3.11/site-packages/mpmath/matrices/__pycache__/eigen.cpython-311.pyc ADDED
Binary file (31 kB). View file
 
tuning-competition-baseline/.venv/lib/python3.11/site-packages/mpmath/matrices/__pycache__/eigen_symmetric.cpython-311.pyc ADDED
Binary file (70 kB). View file
 
tuning-competition-baseline/.venv/lib/python3.11/site-packages/mpmath/matrices/__pycache__/linalg.cpython-311.pyc ADDED
Binary file (40.1 kB). View file
 
tuning-competition-baseline/.venv/lib/python3.11/site-packages/mpmath/matrices/__pycache__/matrices.cpython-311.pyc ADDED
Binary file (44.8 kB). View file
 
tuning-competition-baseline/.venv/lib/python3.11/site-packages/mpmath/matrices/eigen_symmetric.py ADDED
@@ -0,0 +1,1807 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/usr/bin/python
2
+ # -*- coding: utf-8 -*-
3
+
4
+ ##################################################################################################
5
+ # module for the symmetric eigenvalue problem
6
+ # Copyright 2013 Timo Hartmann (thartmann15 at gmail.com)
7
+ #
8
+ # todo:
9
+ # - implement balancing
10
+ #
11
+ ##################################################################################################
12
+
13
+ """
14
+ The symmetric eigenvalue problem.
15
+ ---------------------------------
16
+
17
+ This file contains routines for the symmetric eigenvalue problem.
18
+
19
+ high level routines:
20
+
21
+ eigsy : real symmetric (ordinary) eigenvalue problem
22
+ eighe : complex hermitian (ordinary) eigenvalue problem
23
+ eigh : unified interface for eigsy and eighe
24
+ svd_r : singular value decomposition for real matrices
25
+ svd_c : singular value decomposition for complex matrices
26
+ svd : unified interface for svd_r and svd_c
27
+
28
+
29
+ low level routines:
30
+
31
+ r_sy_tridiag : reduction of real symmetric matrix to real symmetric tridiagonal matrix
32
+ c_he_tridiag_0 : reduction of complex hermitian matrix to real symmetric tridiagonal matrix
33
+ c_he_tridiag_1 : auxiliary routine to c_he_tridiag_0
34
+ c_he_tridiag_2 : auxiliary routine to c_he_tridiag_0
35
+ tridiag_eigen : solves the real symmetric tridiagonal matrix eigenvalue problem
36
+ svd_r_raw : raw singular value decomposition for real matrices
37
+ svd_c_raw : raw singular value decomposition for complex matrices
38
+ """
39
+
40
+ from ..libmp.backend import xrange
41
+ from .eigen import defun
42
+
43
+
44
+ def r_sy_tridiag(ctx, A, D, E, calc_ev = True):
45
+ """
46
+ This routine transforms a real symmetric matrix A to a real symmetric
47
+ tridiagonal matrix T using an orthogonal similarity transformation:
48
+ Q' * A * Q = T (here ' denotes the matrix transpose).
49
+ The orthogonal matrix Q is build up from Householder reflectors.
50
+
51
+ parameters:
52
+ A (input/output) On input, A contains the real symmetric matrix of
53
+ dimension (n,n). On output, if calc_ev is true, A contains the
54
+ orthogonal matrix Q, otherwise A is destroyed.
55
+
56
+ D (output) real array of length n, contains the diagonal elements
57
+ of the tridiagonal matrix
58
+
59
+ E (output) real array of length n, contains the offdiagonal elements
60
+ of the tridiagonal matrix in E[0:(n-1)] where is the dimension of
61
+ the matrix A. E[n-1] is undefined.
62
+
63
+ calc_ev (input) If calc_ev is true, this routine explicitly calculates the
64
+ orthogonal matrix Q which is then returned in A. If calc_ev is
65
+ false, Q is not explicitly calculated resulting in a shorter run time.
66
+
67
+ This routine is a python translation of the fortran routine tred2.f in the
68
+ software library EISPACK (see netlib.org) which itself is based on the algol
69
+ procedure tred2 described in:
70
+ - Num. Math. 11, p.181-195 (1968) by Martin, Reinsch and Wilkonson
71
+ - Handbook for auto. comp., Vol II, Linear Algebra, p.212-226 (1971)
72
+
73
+ For a good introduction to Householder reflections, see also
74
+ Stoer, Bulirsch - Introduction to Numerical Analysis.
75
+ """
76
+
77
+ # note : the vector v of the i-th houshoulder reflector is stored in a[(i+1):,i]
78
+ # whereas v/<v,v> is stored in a[i,(i+1):]
79
+
80
+ n = A.rows
81
+ for i in xrange(n - 1, 0, -1):
82
+ # scale the vector
83
+
84
+ scale = 0
85
+ for k in xrange(0, i):
86
+ scale += abs(A[k,i])
87
+
88
+ scale_inv = 0
89
+ if scale != 0:
90
+ scale_inv = 1/scale
91
+
92
+ # sadly there are floating point numbers not equal to zero whose reciprocal is infinity
93
+
94
+ if i == 1 or scale == 0 or ctx.isinf(scale_inv):
95
+ E[i] = A[i-1,i] # nothing to do
96
+ D[i] = 0
97
+ continue
98
+
99
+ # calculate parameters for housholder transformation
100
+
101
+ H = 0
102
+ for k in xrange(0, i):
103
+ A[k,i] *= scale_inv
104
+ H += A[k,i] * A[k,i]
105
+
106
+ F = A[i-1,i]
107
+ G = ctx.sqrt(H)
108
+ if F > 0:
109
+ G = -G
110
+ E[i] = scale * G
111
+ H -= F * G
112
+ A[i-1,i] = F - G
113
+ F = 0
114
+
115
+ # apply housholder transformation
116
+
117
+ for j in xrange(0, i):
118
+ if calc_ev:
119
+ A[i,j] = A[j,i] / H
120
+
121
+ G = 0 # calculate A*U
122
+ for k in xrange(0, j + 1):
123
+ G += A[k,j] * A[k,i]
124
+ for k in xrange(j + 1, i):
125
+ G += A[j,k] * A[k,i]
126
+
127
+ E[j] = G / H # calculate P
128
+ F += E[j] * A[j,i]
129
+
130
+ HH = F / (2 * H)
131
+
132
+ for j in xrange(0, i): # calculate reduced A
133
+ F = A[j,i]
134
+ G = E[j] - HH * F # calculate Q
135
+ E[j] = G
136
+
137
+ for k in xrange(0, j + 1):
138
+ A[k,j] -= F * E[k] + G * A[k,i]
139
+
140
+ D[i] = H
141
+
142
+ for i in xrange(1, n): # better for compatibility
143
+ E[i-1] = E[i]
144
+ E[n-1] = 0
145
+
146
+ if calc_ev:
147
+ D[0] = 0
148
+ for i in xrange(0, n):
149
+ if D[i] != 0:
150
+ for j in xrange(0, i): # accumulate transformation matrices
151
+ G = 0
152
+ for k in xrange(0, i):
153
+ G += A[i,k] * A[k,j]
154
+ for k in xrange(0, i):
155
+ A[k,j] -= G * A[k,i]
156
+
157
+ D[i] = A[i,i]
158
+ A[i,i] = 1
159
+
160
+ for j in xrange(0, i):
161
+ A[j,i] = A[i,j] = 0
162
+ else:
163
+ for i in xrange(0, n):
164
+ D[i] = A[i,i]
165
+
166
+
167
+
168
+
169
+
170
+ def c_he_tridiag_0(ctx, A, D, E, T):
171
+ """
172
+ This routine transforms a complex hermitian matrix A to a real symmetric
173
+ tridiagonal matrix T using an unitary similarity transformation:
174
+ Q' * A * Q = T (here ' denotes the hermitian matrix transpose,
175
+ i.e. transposition und conjugation).
176
+ The unitary matrix Q is build up from Householder reflectors and
177
+ an unitary diagonal matrix.
178
+
179
+ parameters:
180
+ A (input/output) On input, A contains the complex hermitian matrix
181
+ of dimension (n,n). On output, A contains the unitary matrix Q
182
+ in compressed form.
183
+
184
+ D (output) real array of length n, contains the diagonal elements
185
+ of the tridiagonal matrix.
186
+
187
+ E (output) real array of length n, contains the offdiagonal elements
188
+ of the tridiagonal matrix in E[0:(n-1)] where is the dimension of
189
+ the matrix A. E[n-1] is undefined.
190
+
191
+ T (output) complex array of length n, contains a unitary diagonal
192
+ matrix.
193
+
194
+ This routine is a python translation (in slightly modified form) of the fortran
195
+ routine htridi.f in the software library EISPACK (see netlib.org) which itself
196
+ is a complex version of the algol procedure tred1 described in:
197
+ - Num. Math. 11, p.181-195 (1968) by Martin, Reinsch and Wilkonson
198
+ - Handbook for auto. comp., Vol II, Linear Algebra, p.212-226 (1971)
199
+
200
+ For a good introduction to Householder reflections, see also
201
+ Stoer, Bulirsch - Introduction to Numerical Analysis.
202
+ """
203
+
204
+ n = A.rows
205
+ T[n-1] = 1
206
+ for i in xrange(n - 1, 0, -1):
207
+
208
+ # scale the vector
209
+
210
+ scale = 0
211
+ for k in xrange(0, i):
212
+ scale += abs(ctx.re(A[k,i])) + abs(ctx.im(A[k,i]))
213
+
214
+ scale_inv = 0
215
+ if scale != 0:
216
+ scale_inv = 1 / scale
217
+
218
+ # sadly there are floating point numbers not equal to zero whose reciprocal is infinity
219
+
220
+ if scale == 0 or ctx.isinf(scale_inv):
221
+ E[i] = 0
222
+ D[i] = 0
223
+ T[i-1] = 1
224
+ continue
225
+
226
+ if i == 1:
227
+ F = A[i-1,i]
228
+ f = abs(F)
229
+ E[i] = f
230
+ D[i] = 0
231
+ if f != 0:
232
+ T[i-1] = T[i] * F / f
233
+ else:
234
+ T[i-1] = T[i]
235
+ continue
236
+
237
+ # calculate parameters for housholder transformation
238
+
239
+ H = 0
240
+ for k in xrange(0, i):
241
+ A[k,i] *= scale_inv
242
+ rr = ctx.re(A[k,i])
243
+ ii = ctx.im(A[k,i])
244
+ H += rr * rr + ii * ii
245
+
246
+ F = A[i-1,i]
247
+ f = abs(F)
248
+ G = ctx.sqrt(H)
249
+ H += G * f
250
+ E[i] = scale * G
251
+ if f != 0:
252
+ F = F / f
253
+ TZ = - T[i] * F # T[i-1]=-T[i]*F, but we need T[i-1] as temporary storage
254
+ G *= F
255
+ else:
256
+ TZ = -T[i] # T[i-1]=-T[i]
257
+ A[i-1,i] += G
258
+ F = 0
259
+
260
+ # apply housholder transformation
261
+
262
+ for j in xrange(0, i):
263
+ A[i,j] = A[j,i] / H
264
+
265
+ G = 0 # calculate A*U
266
+ for k in xrange(0, j + 1):
267
+ G += ctx.conj(A[k,j]) * A[k,i]
268
+ for k in xrange(j + 1, i):
269
+ G += A[j,k] * A[k,i]
270
+
271
+ T[j] = G / H # calculate P
272
+ F += ctx.conj(T[j]) * A[j,i]
273
+
274
+ HH = F / (2 * H)
275
+
276
+ for j in xrange(0, i): # calculate reduced A
277
+ F = A[j,i]
278
+ G = T[j] - HH * F # calculate Q
279
+ T[j] = G
280
+
281
+ for k in xrange(0, j + 1):
282
+ A[k,j] -= ctx.conj(F) * T[k] + ctx.conj(G) * A[k,i]
283
+ # as we use the lower left part for storage
284
+ # we have to use the transpose of the normal formula
285
+
286
+ T[i-1] = TZ
287
+ D[i] = H
288
+
289
+ for i in xrange(1, n): # better for compatibility
290
+ E[i-1] = E[i]
291
+ E[n-1] = 0
292
+
293
+ D[0] = 0
294
+ for i in xrange(0, n):
295
+ zw = D[i]
296
+ D[i] = ctx.re(A[i,i])
297
+ A[i,i] = zw
298
+
299
+
300
+
301
+
302
+
303
+
304
+
305
+ def c_he_tridiag_1(ctx, A, T):
306
+ """
307
+ This routine forms the unitary matrix Q described in c_he_tridiag_0.
308
+
309
+ parameters:
310
+ A (input/output) On input, A is the same matrix as delivered by
311
+ c_he_tridiag_0. On output, A is set to Q.
312
+
313
+ T (input) On input, T is the same array as delivered by c_he_tridiag_0.
314
+
315
+ """
316
+
317
+ n = A.rows
318
+
319
+ for i in xrange(0, n):
320
+ if A[i,i] != 0:
321
+ for j in xrange(0, i):
322
+ G = 0
323
+ for k in xrange(0, i):
324
+ G += ctx.conj(A[i,k]) * A[k,j]
325
+ for k in xrange(0, i):
326
+ A[k,j] -= G * A[k,i]
327
+
328
+ A[i,i] = 1
329
+
330
+ for j in xrange(0, i):
331
+ A[j,i] = A[i,j] = 0
332
+
333
+ for i in xrange(0, n):
334
+ for k in xrange(0, n):
335
+ A[i,k] *= T[k]
336
+
337
+
338
+
339
+
340
+ def c_he_tridiag_2(ctx, A, T, B):
341
+ """
342
+ This routine applied the unitary matrix Q described in c_he_tridiag_0
343
+ onto the the matrix B, i.e. it forms Q*B.
344
+
345
+ parameters:
346
+ A (input) On input, A is the same matrix as delivered by c_he_tridiag_0.
347
+
348
+ T (input) On input, T is the same array as delivered by c_he_tridiag_0.
349
+
350
+ B (input/output) On input, B is a complex matrix. On output B is replaced
351
+ by Q*B.
352
+
353
+ This routine is a python translation of the fortran routine htribk.f in the
354
+ software library EISPACK (see netlib.org). See c_he_tridiag_0 for more
355
+ references.
356
+ """
357
+
358
+ n = A.rows
359
+
360
+ for i in xrange(0, n):
361
+ for k in xrange(0, n):
362
+ B[k,i] *= T[k]
363
+
364
+ for i in xrange(0, n):
365
+ if A[i,i] != 0:
366
+ for j in xrange(0, n):
367
+ G = 0
368
+ for k in xrange(0, i):
369
+ G += ctx.conj(A[i,k]) * B[k,j]
370
+ for k in xrange(0, i):
371
+ B[k,j] -= G * A[k,i]
372
+
373
+
374
+
375
+
376
+
377
+ def tridiag_eigen(ctx, d, e, z = False):
378
+ """
379
+ This subroutine find the eigenvalues and the first components of the
380
+ eigenvectors of a real symmetric tridiagonal matrix using the implicit
381
+ QL method.
382
+
383
+ parameters:
384
+
385
+ d (input/output) real array of length n. on input, d contains the diagonal
386
+ elements of the input matrix. on output, d contains the eigenvalues in
387
+ ascending order.
388
+
389
+ e (input) real array of length n. on input, e contains the offdiagonal
390
+ elements of the input matrix in e[0:(n-1)]. On output, e has been
391
+ destroyed.
392
+
393
+ z (input/output) If z is equal to False, no eigenvectors will be computed.
394
+ Otherwise on input z should have the format z[0:m,0:n] (i.e. a real or
395
+ complex matrix of dimension (m,n) ). On output this matrix will be
396
+ multiplied by the matrix of the eigenvectors (i.e. the columns of this
397
+ matrix are the eigenvectors): z --> z*EV
398
+ That means if z[i,j]={1 if j==j; 0 otherwise} on input, then on output
399
+ z will contain the first m components of the eigenvectors. That means
400
+ if m is equal to n, the i-th eigenvector will be z[:,i].
401
+
402
+ This routine is a python translation (in slightly modified form) of the
403
+ fortran routine imtql2.f in the software library EISPACK (see netlib.org)
404
+ which itself is based on the algol procudure imtql2 desribed in:
405
+ - num. math. 12, p. 377-383(1968) by matrin and wilkinson
406
+ - modified in num. math. 15, p. 450(1970) by dubrulle
407
+ - handbook for auto. comp., vol. II-linear algebra, p. 241-248 (1971)
408
+ See also the routine gaussq.f in netlog.org or acm algorithm 726.
409
+ """
410
+
411
+ n = len(d)
412
+ e[n-1] = 0
413
+ iterlim = 2 * ctx.dps
414
+
415
+ for l in xrange(n):
416
+ j = 0
417
+ while 1:
418
+ m = l
419
+ while 1:
420
+ # look for a small subdiagonal element
421
+ if m + 1 == n:
422
+ break
423
+ if abs(e[m]) <= ctx.eps * (abs(d[m]) + abs(d[m + 1])):
424
+ break
425
+ m = m + 1
426
+ if m == l:
427
+ break
428
+
429
+ if j >= iterlim:
430
+ raise RuntimeError("tridiag_eigen: no convergence to an eigenvalue after %d iterations" % iterlim)
431
+
432
+ j += 1
433
+
434
+ # form shift
435
+
436
+ p = d[l]
437
+ g = (d[l + 1] - p) / (2 * e[l])
438
+ r = ctx.hypot(g, 1)
439
+
440
+ if g < 0:
441
+ s = g - r
442
+ else:
443
+ s = g + r
444
+
445
+ g = d[m] - p + e[l] / s
446
+
447
+ s, c, p = 1, 1, 0
448
+
449
+ for i in xrange(m - 1, l - 1, -1):
450
+ f = s * e[i]
451
+ b = c * e[i]
452
+ if abs(f) > abs(g): # this here is a slight improvement also used in gaussq.f or acm algorithm 726.
453
+ c = g / f
454
+ r = ctx.hypot(c, 1)
455
+ e[i + 1] = f * r
456
+ s = 1 / r
457
+ c = c * s
458
+ else:
459
+ s = f / g
460
+ r = ctx.hypot(s, 1)
461
+ e[i + 1] = g * r
462
+ c = 1 / r
463
+ s = s * c
464
+ g = d[i + 1] - p
465
+ r = (d[i] - g) * s + 2 * c * b
466
+ p = s * r
467
+ d[i + 1] = g + p
468
+ g = c * r - b
469
+
470
+ if not isinstance(z, bool):
471
+ # calculate eigenvectors
472
+ for w in xrange(z.rows):
473
+ f = z[w,i+1]
474
+ z[w,i+1] = s * z[w,i] + c * f
475
+ z[w,i ] = c * z[w,i] - s * f
476
+
477
+ d[l] = d[l] - p
478
+ e[l] = g
479
+ e[m] = 0
480
+
481
+ for ii in xrange(1, n):
482
+ # sort eigenvalues and eigenvectors (bubble-sort)
483
+ i = ii - 1
484
+ k = i
485
+ p = d[i]
486
+ for j in xrange(ii, n):
487
+ if d[j] >= p:
488
+ continue
489
+ k = j
490
+ p = d[k]
491
+ if k == i:
492
+ continue
493
+ d[k] = d[i]
494
+ d[i] = p
495
+
496
+ if not isinstance(z, bool):
497
+ for w in xrange(z.rows):
498
+ p = z[w,i]
499
+ z[w,i] = z[w,k]
500
+ z[w,k] = p
501
+
502
+ ########################################################################################
503
+
504
+ @defun
505
+ def eigsy(ctx, A, eigvals_only = False, overwrite_a = False):
506
+ """
507
+ This routine solves the (ordinary) eigenvalue problem for a real symmetric
508
+ square matrix A. Given A, an orthogonal matrix Q is calculated which
509
+ diagonalizes A:
510
+
511
+ Q' A Q = diag(E) and Q Q' = Q' Q = 1
512
+
513
+ Here diag(E) is a diagonal matrix whose diagonal is E.
514
+ ' denotes the transpose.
515
+
516
+ The columns of Q are the eigenvectors of A and E contains the eigenvalues:
517
+
518
+ A Q[:,i] = E[i] Q[:,i]
519
+
520
+
521
+ input:
522
+
523
+ A: real matrix of format (n,n) which is symmetric
524
+ (i.e. A=A' or A[i,j]=A[j,i])
525
+
526
+ eigvals_only: if true, calculates only the eigenvalues E.
527
+ if false, calculates both eigenvectors and eigenvalues.
528
+
529
+ overwrite_a: if true, allows modification of A which may improve
530
+ performance. if false, A is not modified.
531
+
532
+ output:
533
+
534
+ E: vector of format (n). contains the eigenvalues of A in ascending order.
535
+
536
+ Q: orthogonal matrix of format (n,n). contains the eigenvectors
537
+ of A as columns.
538
+
539
+ return value:
540
+
541
+ E if eigvals_only is true
542
+ (E, Q) if eigvals_only is false
543
+
544
+ example:
545
+ >>> from mpmath import mp
546
+ >>> A = mp.matrix([[3, 2], [2, 0]])
547
+ >>> E = mp.eigsy(A, eigvals_only = True)
548
+ >>> print(E)
549
+ [-1.0]
550
+ [ 4.0]
551
+
552
+ >>> A = mp.matrix([[1, 2], [2, 3]])
553
+ >>> E, Q = mp.eigsy(A)
554
+ >>> print(mp.chop(A * Q[:,0] - E[0] * Q[:,0]))
555
+ [0.0]
556
+ [0.0]
557
+
558
+ see also: eighe, eigh, eig
559
+ """
560
+
561
+ if not overwrite_a:
562
+ A = A.copy()
563
+
564
+ d = ctx.zeros(A.rows, 1)
565
+ e = ctx.zeros(A.rows, 1)
566
+
567
+ if eigvals_only:
568
+ r_sy_tridiag(ctx, A, d, e, calc_ev = False)
569
+ tridiag_eigen(ctx, d, e, False)
570
+ return d
571
+ else:
572
+ r_sy_tridiag(ctx, A, d, e, calc_ev = True)
573
+ tridiag_eigen(ctx, d, e, A)
574
+ return (d, A)
575
+
576
+
577
+ @defun
578
+ def eighe(ctx, A, eigvals_only = False, overwrite_a = False):
579
+ """
580
+ This routine solves the (ordinary) eigenvalue problem for a complex
581
+ hermitian square matrix A. Given A, an unitary matrix Q is calculated which
582
+ diagonalizes A:
583
+
584
+ Q' A Q = diag(E) and Q Q' = Q' Q = 1
585
+
586
+ Here diag(E) a is diagonal matrix whose diagonal is E.
587
+ ' denotes the hermitian transpose (i.e. ordinary transposition and
588
+ complex conjugation).
589
+
590
+ The columns of Q are the eigenvectors of A and E contains the eigenvalues:
591
+
592
+ A Q[:,i] = E[i] Q[:,i]
593
+
594
+
595
+ input:
596
+
597
+ A: complex matrix of format (n,n) which is hermitian
598
+ (i.e. A=A' or A[i,j]=conj(A[j,i]))
599
+
600
+ eigvals_only: if true, calculates only the eigenvalues E.
601
+ if false, calculates both eigenvectors and eigenvalues.
602
+
603
+ overwrite_a: if true, allows modification of A which may improve
604
+ performance. if false, A is not modified.
605
+
606
+ output:
607
+
608
+ E: vector of format (n). contains the eigenvalues of A in ascending order.
609
+
610
+ Q: unitary matrix of format (n,n). contains the eigenvectors
611
+ of A as columns.
612
+
613
+ return value:
614
+
615
+ E if eigvals_only is true
616
+ (E, Q) if eigvals_only is false
617
+
618
+ example:
619
+ >>> from mpmath import mp
620
+ >>> A = mp.matrix([[1, -3 - 1j], [-3 + 1j, -2]])
621
+ >>> E = mp.eighe(A, eigvals_only = True)
622
+ >>> print(E)
623
+ [-4.0]
624
+ [ 3.0]
625
+
626
+ >>> A = mp.matrix([[1, 2 + 5j], [2 - 5j, 3]])
627
+ >>> E, Q = mp.eighe(A)
628
+ >>> print(mp.chop(A * Q[:,0] - E[0] * Q[:,0]))
629
+ [0.0]
630
+ [0.0]
631
+
632
+ see also: eigsy, eigh, eig
633
+ """
634
+
635
+ if not overwrite_a:
636
+ A = A.copy()
637
+
638
+ d = ctx.zeros(A.rows, 1)
639
+ e = ctx.zeros(A.rows, 1)
640
+ t = ctx.zeros(A.rows, 1)
641
+
642
+ if eigvals_only:
643
+ c_he_tridiag_0(ctx, A, d, e, t)
644
+ tridiag_eigen(ctx, d, e, False)
645
+ return d
646
+ else:
647
+ c_he_tridiag_0(ctx, A, d, e, t)
648
+ B = ctx.eye(A.rows)
649
+ tridiag_eigen(ctx, d, e, B)
650
+ c_he_tridiag_2(ctx, A, t, B)
651
+ return (d, B)
652
+
653
+ @defun
654
+ def eigh(ctx, A, eigvals_only = False, overwrite_a = False):
655
+ """
656
+ "eigh" is a unified interface for "eigsy" and "eighe". Depending on
657
+ whether A is real or complex the appropriate function is called.
658
+
659
+ This routine solves the (ordinary) eigenvalue problem for a real symmetric
660
+ or complex hermitian square matrix A. Given A, an orthogonal (A real) or
661
+ unitary (A complex) matrix Q is calculated which diagonalizes A:
662
+
663
+ Q' A Q = diag(E) and Q Q' = Q' Q = 1
664
+
665
+ Here diag(E) a is diagonal matrix whose diagonal is E.
666
+ ' denotes the hermitian transpose (i.e. ordinary transposition and
667
+ complex conjugation).
668
+
669
+ The columns of Q are the eigenvectors of A and E contains the eigenvalues:
670
+
671
+ A Q[:,i] = E[i] Q[:,i]
672
+
673
+ input:
674
+
675
+ A: a real or complex square matrix of format (n,n) which is symmetric
676
+ (i.e. A[i,j]=A[j,i]) or hermitian (i.e. A[i,j]=conj(A[j,i])).
677
+
678
+ eigvals_only: if true, calculates only the eigenvalues E.
679
+ if false, calculates both eigenvectors and eigenvalues.
680
+
681
+ overwrite_a: if true, allows modification of A which may improve
682
+ performance. if false, A is not modified.
683
+
684
+ output:
685
+
686
+ E: vector of format (n). contains the eigenvalues of A in ascending order.
687
+
688
+ Q: an orthogonal or unitary matrix of format (n,n). contains the
689
+ eigenvectors of A as columns.
690
+
691
+ return value:
692
+
693
+ E if eigvals_only is true
694
+ (E, Q) if eigvals_only is false
695
+
696
+ example:
697
+ >>> from mpmath import mp
698
+ >>> A = mp.matrix([[3, 2], [2, 0]])
699
+ >>> E = mp.eigh(A, eigvals_only = True)
700
+ >>> print(E)
701
+ [-1.0]
702
+ [ 4.0]
703
+
704
+ >>> A = mp.matrix([[1, 2], [2, 3]])
705
+ >>> E, Q = mp.eigh(A)
706
+ >>> print(mp.chop(A * Q[:,0] - E[0] * Q[:,0]))
707
+ [0.0]
708
+ [0.0]
709
+
710
+ >>> A = mp.matrix([[1, 2 + 5j], [2 - 5j, 3]])
711
+ >>> E, Q = mp.eigh(A)
712
+ >>> print(mp.chop(A * Q[:,0] - E[0] * Q[:,0]))
713
+ [0.0]
714
+ [0.0]
715
+
716
+ see also: eigsy, eighe, eig
717
+ """
718
+
719
+ iscomplex = any(type(x) is ctx.mpc for x in A)
720
+
721
+ if iscomplex:
722
+ return ctx.eighe(A, eigvals_only = eigvals_only, overwrite_a = overwrite_a)
723
+ else:
724
+ return ctx.eigsy(A, eigvals_only = eigvals_only, overwrite_a = overwrite_a)
725
+
726
+
727
+ @defun
728
+ def gauss_quadrature(ctx, n, qtype = "legendre", alpha = 0, beta = 0):
729
+ """
730
+ This routine calulates gaussian quadrature rules for different
731
+ families of orthogonal polynomials. Let (a, b) be an interval,
732
+ W(x) a positive weight function and n a positive integer.
733
+ Then the purpose of this routine is to calculate pairs (x_k, w_k)
734
+ for k=0, 1, 2, ... (n-1) which give
735
+
736
+ int(W(x) * F(x), x = a..b) = sum(w_k * F(x_k),k = 0..(n-1))
737
+
738
+ exact for all polynomials F(x) of degree (strictly) less than 2*n. For all
739
+ integrable functions F(x) the sum is a (more or less) good approximation to
740
+ the integral. The x_k are called nodes (which are the zeros of the
741
+ related orthogonal polynomials) and the w_k are called the weights.
742
+
743
+ parameters
744
+ n (input) The degree of the quadrature rule, i.e. its number of
745
+ nodes.
746
+
747
+ qtype (input) The family of orthogonal polynmomials for which to
748
+ compute the quadrature rule. See the list below.
749
+
750
+ alpha (input) real number, used as parameter for some orthogonal
751
+ polynomials
752
+
753
+ beta (input) real number, used as parameter for some orthogonal
754
+ polynomials.
755
+
756
+ return value
757
+
758
+ (X, W) a pair of two real arrays where x_k = X[k] and w_k = W[k].
759
+
760
+
761
+ orthogonal polynomials:
762
+
763
+ qtype polynomial
764
+ ----- ----------
765
+
766
+ "legendre" Legendre polynomials, W(x)=1 on the interval (-1, +1)
767
+ "legendre01" shifted Legendre polynomials, W(x)=1 on the interval (0, +1)
768
+ "hermite" Hermite polynomials, W(x)=exp(-x*x) on (-infinity,+infinity)
769
+ "laguerre" Laguerre polynomials, W(x)=exp(-x) on (0,+infinity)
770
+ "glaguerre" generalized Laguerre polynomials, W(x)=exp(-x)*x**alpha
771
+ on (0, +infinity)
772
+ "chebyshev1" Chebyshev polynomials of the first kind, W(x)=1/sqrt(1-x*x)
773
+ on (-1, +1)
774
+ "chebyshev2" Chebyshev polynomials of the second kind, W(x)=sqrt(1-x*x)
775
+ on (-1, +1)
776
+ "jacobi" Jacobi polynomials, W(x)=(1-x)**alpha * (1+x)**beta on (-1, +1)
777
+ with alpha>-1 and beta>-1
778
+
779
+ examples:
780
+ >>> from mpmath import mp
781
+ >>> f = lambda x: x**8 + 2 * x**6 - 3 * x**4 + 5 * x**2 - 7
782
+ >>> X, W = mp.gauss_quadrature(5, "hermite")
783
+ >>> A = mp.fdot([(f(x), w) for x, w in zip(X, W)])
784
+ >>> B = mp.sqrt(mp.pi) * 57 / 16
785
+ >>> C = mp.quad(lambda x: mp.exp(- x * x) * f(x), [-mp.inf, +mp.inf])
786
+ >>> mp.nprint((mp.chop(A-B, tol = 1e-10), mp.chop(A-C, tol = 1e-10)))
787
+ (0.0, 0.0)
788
+
789
+ >>> f = lambda x: x**5 - 2 * x**4 + 3 * x**3 - 5 * x**2 + 7 * x - 11
790
+ >>> X, W = mp.gauss_quadrature(3, "laguerre")
791
+ >>> A = mp.fdot([(f(x), w) for x, w in zip(X, W)])
792
+ >>> B = 76
793
+ >>> C = mp.quad(lambda x: mp.exp(-x) * f(x), [0, +mp.inf])
794
+ >>> mp.nprint(mp.chop(A-B, tol = 1e-10), mp.chop(A-C, tol = 1e-10))
795
+ .0
796
+
797
+ # orthogonality of the chebyshev polynomials:
798
+ >>> f = lambda x: mp.chebyt(3, x) * mp.chebyt(2, x)
799
+ >>> X, W = mp.gauss_quadrature(3, "chebyshev1")
800
+ >>> A = mp.fdot([(f(x), w) for x, w in zip(X, W)])
801
+ >>> print(mp.chop(A, tol = 1e-10))
802
+ 0.0
803
+
804
+ references:
805
+ - golub and welsch, "calculations of gaussian quadrature rules", mathematics of
806
+ computation 23, p. 221-230 (1969)
807
+ - golub, "some modified matrix eigenvalue problems", siam review 15, p. 318-334 (1973)
808
+ - stroud and secrest, "gaussian quadrature formulas", prentice-hall (1966)
809
+
810
+ See also the routine gaussq.f in netlog.org or ACM Transactions on
811
+ Mathematical Software algorithm 726.
812
+ """
813
+
814
+ d = ctx.zeros(n, 1)
815
+ e = ctx.zeros(n, 1)
816
+ z = ctx.zeros(1, n)
817
+
818
+ z[0,0] = 1
819
+
820
+ if qtype == "legendre":
821
+ # legendre on the range -1 +1 , abramowitz, table 25.4, p.916
822
+ w = 2
823
+ for i in xrange(n):
824
+ j = i + 1
825
+ e[i] = ctx.sqrt(j * j / (4 * j * j - ctx.mpf(1)))
826
+ elif qtype == "legendre01":
827
+ # legendre shifted to 0 1 , abramowitz, table 25.8, p.921
828
+ w = 1
829
+ for i in xrange(n):
830
+ d[i] = 1 / ctx.mpf(2)
831
+ j = i + 1
832
+ e[i] = ctx.sqrt(j * j / (16 * j * j - ctx.mpf(4)))
833
+ elif qtype == "hermite":
834
+ # hermite on the range -inf +inf , abramowitz, table 25.10,p.924
835
+ w = ctx.sqrt(ctx.pi)
836
+ for i in xrange(n):
837
+ j = i + 1
838
+ e[i] = ctx.sqrt(j / ctx.mpf(2))
839
+ elif qtype == "laguerre":
840
+ # laguerre on the range 0 +inf , abramowitz, table 25.9, p. 923
841
+ w = 1
842
+ for i in xrange(n):
843
+ j = i + 1
844
+ d[i] = 2 * j - 1
845
+ e[i] = j
846
+ elif qtype=="chebyshev1":
847
+ # chebyshev polynimials of the first kind
848
+ w = ctx.pi
849
+ for i in xrange(n):
850
+ e[i] = 1 / ctx.mpf(2)
851
+ e[0] = ctx.sqrt(1 / ctx.mpf(2))
852
+ elif qtype == "chebyshev2":
853
+ # chebyshev polynimials of the second kind
854
+ w = ctx.pi / 2
855
+ for i in xrange(n):
856
+ e[i] = 1 / ctx.mpf(2)
857
+ elif qtype == "glaguerre":
858
+ # generalized laguerre on the range 0 +inf
859
+ w = ctx.gamma(1 + alpha)
860
+ for i in xrange(n):
861
+ j = i + 1
862
+ d[i] = 2 * j - 1 + alpha
863
+ e[i] = ctx.sqrt(j * (j + alpha))
864
+ elif qtype == "jacobi":
865
+ # jacobi polynomials
866
+ alpha = ctx.mpf(alpha)
867
+ beta = ctx.mpf(beta)
868
+ ab = alpha + beta
869
+ abi = ab + 2
870
+ w = (2**(ab+1)) * ctx.gamma(alpha + 1) * ctx.gamma(beta + 1) / ctx.gamma(abi)
871
+ d[0] = (beta - alpha) / abi
872
+ e[0] = ctx.sqrt(4 * (1 + alpha) * (1 + beta) / ((abi + 1) * (abi * abi)))
873
+ a2b2 = beta * beta - alpha * alpha
874
+ for i in xrange(1, n):
875
+ j = i + 1
876
+ abi = 2 * j + ab
877
+ d[i] = a2b2 / ((abi - 2) * abi)
878
+ e[i] = ctx.sqrt(4 * j * (j + alpha) * (j + beta) * (j + ab) / ((abi * abi - 1) * abi * abi))
879
+ elif isinstance(qtype, str):
880
+ raise ValueError("unknown quadrature rule \"%s\"" % qtype)
881
+ elif not isinstance(qtype, str):
882
+ w = qtype(d, e)
883
+ else:
884
+ assert 0
885
+
886
+ tridiag_eigen(ctx, d, e, z)
887
+
888
+ for i in xrange(len(z)):
889
+ z[i] *= z[i]
890
+
891
+ z = z.transpose()
892
+ return (d, w * z)
893
+
894
+ ##################################################################################################
895
+ ##################################################################################################
896
+ ##################################################################################################
897
+
898
+ def svd_r_raw(ctx, A, V = False, calc_u = False):
899
+ """
900
+ This routine computes the singular value decomposition of a matrix A.
901
+ Given A, two orthogonal matrices U and V are calculated such that
902
+
903
+ A = U S V
904
+
905
+ where S is a suitable shaped matrix whose off-diagonal elements are zero.
906
+ The diagonal elements of S are the singular values of A, i.e. the
907
+ squareroots of the eigenvalues of A' A or A A'. Here ' denotes the transpose.
908
+ Householder bidiagonalization and a variant of the QR algorithm is used.
909
+
910
+ overview of the matrices :
911
+
912
+ A : m*n A gets replaced by U
913
+ U : m*n U replaces A. If n>m then only the first m*m block of U is
914
+ non-zero. column-orthogonal: U' U = B
915
+ here B is a n*n matrix whose first min(m,n) diagonal
916
+ elements are 1 and all other elements are zero.
917
+ S : n*n diagonal matrix, only the diagonal elements are stored in
918
+ the array S. only the first min(m,n) diagonal elements are non-zero.
919
+ V : n*n orthogonal: V V' = V' V = 1
920
+
921
+ parameters:
922
+ A (input/output) On input, A contains a real matrix of shape m*n.
923
+ On output, if calc_u is true A contains the column-orthogonal
924
+ matrix U; otherwise A is simply used as workspace and thus destroyed.
925
+
926
+ V (input/output) if false, the matrix V is not calculated. otherwise
927
+ V must be a matrix of shape n*n.
928
+
929
+ calc_u (input) If true, the matrix U is calculated and replaces A.
930
+ if false, U is not calculated and A is simply destroyed
931
+
932
+ return value:
933
+ S an array of length n containing the singular values of A sorted by
934
+ decreasing magnitude. only the first min(m,n) elements are non-zero.
935
+
936
+ This routine is a python translation of the fortran routine svd.f in the
937
+ software library EISPACK (see netlib.org) which itself is based on the
938
+ algol procedure svd described in:
939
+ - num. math. 14, 403-420(1970) by golub and reinsch.
940
+ - wilkinson/reinsch: handbook for auto. comp., vol ii-linear algebra, 134-151(1971).
941
+
942
+ """
943
+
944
+ m, n = A.rows, A.cols
945
+
946
+ S = ctx.zeros(n, 1)
947
+
948
+ # work is a temporary array of size n
949
+ work = ctx.zeros(n, 1)
950
+
951
+ g = scale = anorm = 0
952
+ maxits = 3 * ctx.dps
953
+
954
+ for i in xrange(n): # householder reduction to bidiagonal form
955
+ work[i] = scale*g
956
+ g = s = scale = 0
957
+ if i < m:
958
+ for k in xrange(i, m):
959
+ scale += ctx.fabs(A[k,i])
960
+ if scale != 0:
961
+ for k in xrange(i, m):
962
+ A[k,i] /= scale
963
+ s += A[k,i] * A[k,i]
964
+ f = A[i,i]
965
+ g = -ctx.sqrt(s)
966
+ if f < 0:
967
+ g = -g
968
+ h = f * g - s
969
+ A[i,i] = f - g
970
+ for j in xrange(i+1, n):
971
+ s = 0
972
+ for k in xrange(i, m):
973
+ s += A[k,i] * A[k,j]
974
+ f = s / h
975
+ for k in xrange(i, m):
976
+ A[k,j] += f * A[k,i]
977
+ for k in xrange(i,m):
978
+ A[k,i] *= scale
979
+
980
+ S[i] = scale * g
981
+ g = s = scale = 0
982
+
983
+ if i < m and i != n - 1:
984
+ for k in xrange(i+1, n):
985
+ scale += ctx.fabs(A[i,k])
986
+ if scale:
987
+ for k in xrange(i+1, n):
988
+ A[i,k] /= scale
989
+ s += A[i,k] * A[i,k]
990
+ f = A[i,i+1]
991
+ g = -ctx.sqrt(s)
992
+ if f < 0:
993
+ g = -g
994
+ h = f * g - s
995
+ A[i,i+1] = f - g
996
+
997
+ for k in xrange(i+1, n):
998
+ work[k] = A[i,k] / h
999
+
1000
+ for j in xrange(i+1, m):
1001
+ s = 0
1002
+ for k in xrange(i+1, n):
1003
+ s += A[j,k] * A[i,k]
1004
+ for k in xrange(i+1, n):
1005
+ A[j,k] += s * work[k]
1006
+
1007
+ for k in xrange(i+1, n):
1008
+ A[i,k] *= scale
1009
+
1010
+ anorm = max(anorm, ctx.fabs(S[i]) + ctx.fabs(work[i]))
1011
+
1012
+ if not isinstance(V, bool):
1013
+ for i in xrange(n-2, -1, -1): # accumulation of right hand transformations
1014
+ V[i+1,i+1] = 1
1015
+
1016
+ if work[i+1] != 0:
1017
+ for j in xrange(i+1, n):
1018
+ V[i,j] = (A[i,j] / A[i,i+1]) / work[i+1]
1019
+ for j in xrange(i+1, n):
1020
+ s = 0
1021
+ for k in xrange(i+1, n):
1022
+ s += A[i,k] * V[j,k]
1023
+ for k in xrange(i+1, n):
1024
+ V[j,k] += s * V[i,k]
1025
+
1026
+ for j in xrange(i+1, n):
1027
+ V[j,i] = V[i,j] = 0
1028
+
1029
+ V[0,0] = 1
1030
+
1031
+ if m<n : minnm = m
1032
+ else : minnm = n
1033
+
1034
+ if calc_u:
1035
+ for i in xrange(minnm-1, -1, -1): # accumulation of left hand transformations
1036
+ g = S[i]
1037
+ for j in xrange(i+1, n):
1038
+ A[i,j] = 0
1039
+ if g != 0:
1040
+ g = 1 / g
1041
+ for j in xrange(i+1, n):
1042
+ s = 0
1043
+ for k in xrange(i+1, m):
1044
+ s += A[k,i] * A[k,j]
1045
+ f = (s / A[i,i]) * g
1046
+ for k in xrange(i, m):
1047
+ A[k,j] += f * A[k,i]
1048
+ for j in xrange(i, m):
1049
+ A[j,i] *= g
1050
+ else:
1051
+ for j in xrange(i, m):
1052
+ A[j,i] = 0
1053
+ A[i,i] += 1
1054
+
1055
+ for k in xrange(n - 1, -1, -1):
1056
+ # diagonalization of the bidiagonal form:
1057
+ # loop over singular values, and over allowed itations
1058
+
1059
+ its = 0
1060
+ while 1:
1061
+ its += 1
1062
+ flag = True
1063
+
1064
+ for l in xrange(k, -1, -1):
1065
+ nm = l-1
1066
+
1067
+ if ctx.fabs(work[l]) + anorm == anorm:
1068
+ flag = False
1069
+ break
1070
+
1071
+ if ctx.fabs(S[nm]) + anorm == anorm:
1072
+ break
1073
+
1074
+ if flag:
1075
+ c = 0
1076
+ s = 1
1077
+ for i in xrange(l, k + 1):
1078
+ f = s * work[i]
1079
+ work[i] *= c
1080
+ if ctx.fabs(f) + anorm == anorm:
1081
+ break
1082
+ g = S[i]
1083
+ h = ctx.hypot(f, g)
1084
+ S[i] = h
1085
+ h = 1 / h
1086
+ c = g * h
1087
+ s = - f * h
1088
+
1089
+ if calc_u:
1090
+ for j in xrange(m):
1091
+ y = A[j,nm]
1092
+ z = A[j,i]
1093
+ A[j,nm] = y * c + z * s
1094
+ A[j,i] = z * c - y * s
1095
+
1096
+ z = S[k]
1097
+
1098
+ if l == k: # convergence
1099
+ if z < 0: # singular value is made nonnegative
1100
+ S[k] = -z
1101
+ if not isinstance(V, bool):
1102
+ for j in xrange(n):
1103
+ V[k,j] = -V[k,j]
1104
+ break
1105
+
1106
+ if its >= maxits:
1107
+ raise RuntimeError("svd: no convergence to an eigenvalue after %d iterations" % its)
1108
+
1109
+ x = S[l] # shift from bottom 2 by 2 minor
1110
+ nm = k-1
1111
+ y = S[nm]
1112
+ g = work[nm]
1113
+ h = work[k]
1114
+ f = ((y - z) * (y + z) + (g - h) * (g + h))/(2 * h * y)
1115
+ g = ctx.hypot(f, 1)
1116
+ if f >= 0: f = ((x - z) * (x + z) + h * ((y / (f + g)) - h)) / x
1117
+ else: f = ((x - z) * (x + z) + h * ((y / (f - g)) - h)) / x
1118
+
1119
+ c = s = 1 # next qt transformation
1120
+
1121
+ for j in xrange(l, nm + 1):
1122
+ g = work[j+1]
1123
+ y = S[j+1]
1124
+ h = s * g
1125
+ g = c * g
1126
+ z = ctx.hypot(f, h)
1127
+ work[j] = z
1128
+ c = f / z
1129
+ s = h / z
1130
+ f = x * c + g * s
1131
+ g = g * c - x * s
1132
+ h = y * s
1133
+ y *= c
1134
+ if not isinstance(V, bool):
1135
+ for jj in xrange(n):
1136
+ x = V[j ,jj]
1137
+ z = V[j+1,jj]
1138
+ V[j ,jj]= x * c + z * s
1139
+ V[j+1 ,jj]= z * c - x * s
1140
+ z = ctx.hypot(f, h)
1141
+ S[j] = z
1142
+ if z != 0: # rotation can be arbitray if z=0
1143
+ z = 1 / z
1144
+ c = f * z
1145
+ s = h * z
1146
+ f = c * g + s * y
1147
+ x = c * y - s * g
1148
+
1149
+ if calc_u:
1150
+ for jj in xrange(m):
1151
+ y = A[jj,j ]
1152
+ z = A[jj,j+1]
1153
+ A[jj,j ] = y * c + z * s
1154
+ A[jj,j+1 ] = z * c - y * s
1155
+
1156
+ work[l] = 0
1157
+ work[k] = f
1158
+ S[k] = x
1159
+
1160
+ ##########################
1161
+
1162
+ # Sort singular values into decreasing order (bubble-sort)
1163
+
1164
+ for i in xrange(n):
1165
+ imax = i
1166
+ s = ctx.fabs(S[i]) # s is the current maximal element
1167
+
1168
+ for j in xrange(i + 1, n):
1169
+ c = ctx.fabs(S[j])
1170
+ if c > s:
1171
+ s = c
1172
+ imax = j
1173
+
1174
+ if imax != i:
1175
+ # swap singular values
1176
+
1177
+ z = S[i]
1178
+ S[i] = S[imax]
1179
+ S[imax] = z
1180
+
1181
+ if calc_u:
1182
+ for j in xrange(m):
1183
+ z = A[j,i]
1184
+ A[j,i] = A[j,imax]
1185
+ A[j,imax] = z
1186
+
1187
+ if not isinstance(V, bool):
1188
+ for j in xrange(n):
1189
+ z = V[i,j]
1190
+ V[i,j] = V[imax,j]
1191
+ V[imax,j] = z
1192
+
1193
+ return S
1194
+
1195
+ #######################
1196
+
1197
+ def svd_c_raw(ctx, A, V = False, calc_u = False):
1198
+ """
1199
+ This routine computes the singular value decomposition of a matrix A.
1200
+ Given A, two unitary matrices U and V are calculated such that
1201
+
1202
+ A = U S V
1203
+
1204
+ where S is a suitable shaped matrix whose off-diagonal elements are zero.
1205
+ The diagonal elements of S are the singular values of A, i.e. the
1206
+ squareroots of the eigenvalues of A' A or A A'. Here ' denotes the hermitian
1207
+ transpose (i.e. transposition and conjugation). Householder bidiagonalization
1208
+ and a variant of the QR algorithm is used.
1209
+
1210
+ overview of the matrices :
1211
+
1212
+ A : m*n A gets replaced by U
1213
+ U : m*n U replaces A. If n>m then only the first m*m block of U is
1214
+ non-zero. column-unitary: U' U = B
1215
+ here B is a n*n matrix whose first min(m,n) diagonal
1216
+ elements are 1 and all other elements are zero.
1217
+ S : n*n diagonal matrix, only the diagonal elements are stored in
1218
+ the array S. only the first min(m,n) diagonal elements are non-zero.
1219
+ V : n*n unitary: V V' = V' V = 1
1220
+
1221
+ parameters:
1222
+ A (input/output) On input, A contains a complex matrix of shape m*n.
1223
+ On output, if calc_u is true A contains the column-unitary
1224
+ matrix U; otherwise A is simply used as workspace and thus destroyed.
1225
+
1226
+ V (input/output) if false, the matrix V is not calculated. otherwise
1227
+ V must be a matrix of shape n*n.
1228
+
1229
+ calc_u (input) If true, the matrix U is calculated and replaces A.
1230
+ if false, U is not calculated and A is simply destroyed
1231
+
1232
+ return value:
1233
+ S an array of length n containing the singular values of A sorted by
1234
+ decreasing magnitude. only the first min(m,n) elements are non-zero.
1235
+
1236
+ This routine is a python translation of the fortran routine svd.f in the
1237
+ software library EISPACK (see netlib.org) which itself is based on the
1238
+ algol procedure svd described in:
1239
+ - num. math. 14, 403-420(1970) by golub and reinsch.
1240
+ - wilkinson/reinsch: handbook for auto. comp., vol ii-linear algebra, 134-151(1971).
1241
+
1242
+ """
1243
+
1244
+ m, n = A.rows, A.cols
1245
+
1246
+ S = ctx.zeros(n, 1)
1247
+
1248
+ # work is a temporary array of size n
1249
+ work = ctx.zeros(n, 1)
1250
+ lbeta = ctx.zeros(n, 1)
1251
+ rbeta = ctx.zeros(n, 1)
1252
+ dwork = ctx.zeros(n, 1)
1253
+
1254
+ g = scale = anorm = 0
1255
+ maxits = 3 * ctx.dps
1256
+
1257
+ for i in xrange(n): # householder reduction to bidiagonal form
1258
+ dwork[i] = scale * g # dwork are the side-diagonal elements
1259
+ g = s = scale = 0
1260
+ if i < m:
1261
+ for k in xrange(i, m):
1262
+ scale += ctx.fabs(ctx.re(A[k,i])) + ctx.fabs(ctx.im(A[k,i]))
1263
+ if scale != 0:
1264
+ for k in xrange(i, m):
1265
+ A[k,i] /= scale
1266
+ ar = ctx.re(A[k,i])
1267
+ ai = ctx.im(A[k,i])
1268
+ s += ar * ar + ai * ai
1269
+ f = A[i,i]
1270
+ g = -ctx.sqrt(s)
1271
+ if ctx.re(f) < 0:
1272
+ beta = -g - ctx.conj(f)
1273
+ g = -g
1274
+ else:
1275
+ beta = -g + ctx.conj(f)
1276
+ beta /= ctx.conj(beta)
1277
+ beta += 1
1278
+ h = 2 * (ctx.re(f) * g - s)
1279
+ A[i,i] = f - g
1280
+ beta /= h
1281
+ lbeta[i] = (beta / scale) / scale
1282
+ for j in xrange(i+1, n):
1283
+ s = 0
1284
+ for k in xrange(i, m):
1285
+ s += ctx.conj(A[k,i]) * A[k,j]
1286
+ f = beta * s
1287
+ for k in xrange(i, m):
1288
+ A[k,j] += f * A[k,i]
1289
+ for k in xrange(i, m):
1290
+ A[k,i] *= scale
1291
+
1292
+ S[i] = scale * g # S are the diagonal elements
1293
+ g = s = scale = 0
1294
+
1295
+ if i < m and i != n - 1:
1296
+ for k in xrange(i+1, n):
1297
+ scale += ctx.fabs(ctx.re(A[i,k])) + ctx.fabs(ctx.im(A[i,k]))
1298
+ if scale:
1299
+ for k in xrange(i+1, n):
1300
+ A[i,k] /= scale
1301
+ ar = ctx.re(A[i,k])
1302
+ ai = ctx.im(A[i,k])
1303
+ s += ar * ar + ai * ai
1304
+ f = A[i,i+1]
1305
+ g = -ctx.sqrt(s)
1306
+ if ctx.re(f) < 0:
1307
+ beta = -g - ctx.conj(f)
1308
+ g = -g
1309
+ else:
1310
+ beta = -g + ctx.conj(f)
1311
+
1312
+ beta /= ctx.conj(beta)
1313
+ beta += 1
1314
+
1315
+ h = 2 * (ctx.re(f) * g - s)
1316
+ A[i,i+1] = f - g
1317
+
1318
+ beta /= h
1319
+ rbeta[i] = (beta / scale) / scale
1320
+
1321
+ for k in xrange(i+1, n):
1322
+ work[k] = A[i, k]
1323
+
1324
+ for j in xrange(i+1, m):
1325
+ s = 0
1326
+ for k in xrange(i+1, n):
1327
+ s += ctx.conj(A[i,k]) * A[j,k]
1328
+ f = s * beta
1329
+ for k in xrange(i+1,n):
1330
+ A[j,k] += f * work[k]
1331
+
1332
+ for k in xrange(i+1, n):
1333
+ A[i,k] *= scale
1334
+
1335
+ anorm = max(anorm,ctx.fabs(S[i]) + ctx.fabs(dwork[i]))
1336
+
1337
+ if not isinstance(V, bool):
1338
+ for i in xrange(n-2, -1, -1): # accumulation of right hand transformations
1339
+ V[i+1,i+1] = 1
1340
+
1341
+ if dwork[i+1] != 0:
1342
+ f = ctx.conj(rbeta[i])
1343
+ for j in xrange(i+1, n):
1344
+ V[i,j] = A[i,j] * f
1345
+ for j in xrange(i+1, n):
1346
+ s = 0
1347
+ for k in xrange(i+1, n):
1348
+ s += ctx.conj(A[i,k]) * V[j,k]
1349
+ for k in xrange(i+1, n):
1350
+ V[j,k] += s * V[i,k]
1351
+
1352
+ for j in xrange(i+1,n):
1353
+ V[j,i] = V[i,j] = 0
1354
+
1355
+ V[0,0] = 1
1356
+
1357
+ if m < n : minnm = m
1358
+ else : minnm = n
1359
+
1360
+ if calc_u:
1361
+ for i in xrange(minnm-1, -1, -1): # accumulation of left hand transformations
1362
+ g = S[i]
1363
+ for j in xrange(i+1, n):
1364
+ A[i,j] = 0
1365
+ if g != 0:
1366
+ g = 1 / g
1367
+ for j in xrange(i+1, n):
1368
+ s = 0
1369
+ for k in xrange(i+1, m):
1370
+ s += ctx.conj(A[k,i]) * A[k,j]
1371
+ f = s * ctx.conj(lbeta[i])
1372
+ for k in xrange(i, m):
1373
+ A[k,j] += f * A[k,i]
1374
+ for j in xrange(i, m):
1375
+ A[j,i] *= g
1376
+ else:
1377
+ for j in xrange(i, m):
1378
+ A[j,i] = 0
1379
+ A[i,i] += 1
1380
+
1381
+ for k in xrange(n-1, -1, -1):
1382
+ # diagonalization of the bidiagonal form:
1383
+ # loop over singular values, and over allowed itations
1384
+
1385
+ its = 0
1386
+ while 1:
1387
+ its += 1
1388
+ flag = True
1389
+
1390
+ for l in xrange(k, -1, -1):
1391
+ nm = l - 1
1392
+
1393
+ if ctx.fabs(dwork[l]) + anorm == anorm:
1394
+ flag = False
1395
+ break
1396
+
1397
+ if ctx.fabs(S[nm]) + anorm == anorm:
1398
+ break
1399
+
1400
+ if flag:
1401
+ c = 0
1402
+ s = 1
1403
+ for i in xrange(l, k+1):
1404
+ f = s * dwork[i]
1405
+ dwork[i] *= c
1406
+ if ctx.fabs(f) + anorm == anorm:
1407
+ break
1408
+ g = S[i]
1409
+ h = ctx.hypot(f, g)
1410
+ S[i] = h
1411
+ h = 1 / h
1412
+ c = g * h
1413
+ s = -f * h
1414
+
1415
+ if calc_u:
1416
+ for j in xrange(m):
1417
+ y = A[j,nm]
1418
+ z = A[j,i]
1419
+ A[j,nm]= y * c + z * s
1420
+ A[j,i] = z * c - y * s
1421
+
1422
+ z = S[k]
1423
+
1424
+ if l == k: # convergence
1425
+ if z < 0: # singular value is made nonnegative
1426
+ S[k] = -z
1427
+ if not isinstance(V, bool):
1428
+ for j in xrange(n):
1429
+ V[k,j] = -V[k,j]
1430
+ break
1431
+
1432
+ if its >= maxits:
1433
+ raise RuntimeError("svd: no convergence to an eigenvalue after %d iterations" % its)
1434
+
1435
+ x = S[l] # shift from bottom 2 by 2 minor
1436
+ nm = k-1
1437
+ y = S[nm]
1438
+ g = dwork[nm]
1439
+ h = dwork[k]
1440
+ f = ((y - z) * (y + z) + (g - h) * (g + h)) / (2 * h * y)
1441
+ g = ctx.hypot(f, 1)
1442
+ if f >=0: f = (( x - z) *( x + z) + h *((y / (f + g)) - h)) / x
1443
+ else: f = (( x - z) *( x + z) + h *((y / (f - g)) - h)) / x
1444
+
1445
+ c = s = 1 # next qt transformation
1446
+
1447
+ for j in xrange(l, nm + 1):
1448
+ g = dwork[j+1]
1449
+ y = S[j+1]
1450
+ h = s * g
1451
+ g = c * g
1452
+ z = ctx.hypot(f, h)
1453
+ dwork[j] = z
1454
+ c = f / z
1455
+ s = h / z
1456
+ f = x * c + g * s
1457
+ g = g * c - x * s
1458
+ h = y * s
1459
+ y *= c
1460
+ if not isinstance(V, bool):
1461
+ for jj in xrange(n):
1462
+ x = V[j ,jj]
1463
+ z = V[j+1,jj]
1464
+ V[j ,jj]= x * c + z * s
1465
+ V[j+1,jj ]= z * c - x * s
1466
+ z = ctx.hypot(f, h)
1467
+ S[j] = z
1468
+ if z != 0: # rotation can be arbitray if z=0
1469
+ z = 1 / z
1470
+ c = f * z
1471
+ s = h * z
1472
+ f = c * g + s * y
1473
+ x = c * y - s * g
1474
+ if calc_u:
1475
+ for jj in xrange(m):
1476
+ y = A[jj,j ]
1477
+ z = A[jj,j+1]
1478
+ A[jj,j ]= y * c + z * s
1479
+ A[jj,j+1 ]= z * c - y * s
1480
+
1481
+ dwork[l] = 0
1482
+ dwork[k] = f
1483
+ S[k] = x
1484
+
1485
+ ##########################
1486
+
1487
+ # Sort singular values into decreasing order (bubble-sort)
1488
+
1489
+ for i in xrange(n):
1490
+ imax = i
1491
+ s = ctx.fabs(S[i]) # s is the current maximal element
1492
+
1493
+ for j in xrange(i + 1, n):
1494
+ c = ctx.fabs(S[j])
1495
+ if c > s:
1496
+ s = c
1497
+ imax = j
1498
+
1499
+ if imax != i:
1500
+ # swap singular values
1501
+
1502
+ z = S[i]
1503
+ S[i] = S[imax]
1504
+ S[imax] = z
1505
+
1506
+ if calc_u:
1507
+ for j in xrange(m):
1508
+ z = A[j,i]
1509
+ A[j,i] = A[j,imax]
1510
+ A[j,imax] = z
1511
+
1512
+ if not isinstance(V, bool):
1513
+ for j in xrange(n):
1514
+ z = V[i,j]
1515
+ V[i,j] = V[imax,j]
1516
+ V[imax,j] = z
1517
+
1518
+ return S
1519
+
1520
+ ##################################################################################################
1521
+
1522
+ @defun
1523
+ def svd_r(ctx, A, full_matrices = False, compute_uv = True, overwrite_a = False):
1524
+ """
1525
+ This routine computes the singular value decomposition of a matrix A.
1526
+ Given A, two orthogonal matrices U and V are calculated such that
1527
+
1528
+ A = U S V and U' U = 1 and V V' = 1
1529
+
1530
+ where S is a suitable shaped matrix whose off-diagonal elements are zero.
1531
+ Here ' denotes the transpose. The diagonal elements of S are the singular
1532
+ values of A, i.e. the squareroots of the eigenvalues of A' A or A A'.
1533
+
1534
+ input:
1535
+ A : a real matrix of shape (m, n)
1536
+ full_matrices : if true, U and V are of shape (m, m) and (n, n).
1537
+ if false, U and V are of shape (m, min(m, n)) and (min(m, n), n).
1538
+ compute_uv : if true, U and V are calculated. if false, only S is calculated.
1539
+ overwrite_a : if true, allows modification of A which may improve
1540
+ performance. if false, A is not modified.
1541
+
1542
+ output:
1543
+ U : an orthogonal matrix: U' U = 1. if full_matrices is true, U is of
1544
+ shape (m, m). ortherwise it is of shape (m, min(m, n)).
1545
+
1546
+ S : an array of length min(m, n) containing the singular values of A sorted by
1547
+ decreasing magnitude.
1548
+
1549
+ V : an orthogonal matrix: V V' = 1. if full_matrices is true, V is of
1550
+ shape (n, n). ortherwise it is of shape (min(m, n), n).
1551
+
1552
+ return value:
1553
+
1554
+ S if compute_uv is false
1555
+ (U, S, V) if compute_uv is true
1556
+
1557
+ overview of the matrices:
1558
+
1559
+ full_matrices true:
1560
+ A : m*n
1561
+ U : m*m U' U = 1
1562
+ S as matrix : m*n
1563
+ V : n*n V V' = 1
1564
+
1565
+ full_matrices false:
1566
+ A : m*n
1567
+ U : m*min(n,m) U' U = 1
1568
+ S as matrix : min(m,n)*min(m,n)
1569
+ V : min(m,n)*n V V' = 1
1570
+
1571
+ examples:
1572
+
1573
+ >>> from mpmath import mp
1574
+ >>> A = mp.matrix([[2, -2, -1], [3, 4, -2], [-2, -2, 0]])
1575
+ >>> S = mp.svd_r(A, compute_uv = False)
1576
+ >>> print(S)
1577
+ [6.0]
1578
+ [3.0]
1579
+ [1.0]
1580
+
1581
+ >>> U, S, V = mp.svd_r(A)
1582
+ >>> print(mp.chop(A - U * mp.diag(S) * V))
1583
+ [0.0 0.0 0.0]
1584
+ [0.0 0.0 0.0]
1585
+ [0.0 0.0 0.0]
1586
+
1587
+
1588
+ see also: svd, svd_c
1589
+ """
1590
+
1591
+ m, n = A.rows, A.cols
1592
+
1593
+ if not compute_uv:
1594
+ if not overwrite_a:
1595
+ A = A.copy()
1596
+ S = svd_r_raw(ctx, A, V = False, calc_u = False)
1597
+ S = S[:min(m,n)]
1598
+ return S
1599
+
1600
+ if full_matrices and n < m:
1601
+ V = ctx.zeros(m, m)
1602
+ A0 = ctx.zeros(m, m)
1603
+ A0[:,:n] = A
1604
+ S = svd_r_raw(ctx, A0, V, calc_u = True)
1605
+
1606
+ S = S[:n]
1607
+ V = V[:n,:n]
1608
+
1609
+ return (A0, S, V)
1610
+ else:
1611
+ if not overwrite_a:
1612
+ A = A.copy()
1613
+ V = ctx.zeros(n, n)
1614
+ S = svd_r_raw(ctx, A, V, calc_u = True)
1615
+
1616
+ if n > m:
1617
+ if full_matrices == False:
1618
+ V = V[:m,:]
1619
+
1620
+ S = S[:m]
1621
+ A = A[:,:m]
1622
+
1623
+ return (A, S, V)
1624
+
1625
+ ##############################
1626
+
1627
+ @defun
1628
+ def svd_c(ctx, A, full_matrices = False, compute_uv = True, overwrite_a = False):
1629
+ """
1630
+ This routine computes the singular value decomposition of a matrix A.
1631
+ Given A, two unitary matrices U and V are calculated such that
1632
+
1633
+ A = U S V and U' U = 1 and V V' = 1
1634
+
1635
+ where S is a suitable shaped matrix whose off-diagonal elements are zero.
1636
+ Here ' denotes the hermitian transpose (i.e. transposition and complex
1637
+ conjugation). The diagonal elements of S are the singular values of A,
1638
+ i.e. the squareroots of the eigenvalues of A' A or A A'.
1639
+
1640
+ input:
1641
+ A : a complex matrix of shape (m, n)
1642
+ full_matrices : if true, U and V are of shape (m, m) and (n, n).
1643
+ if false, U and V are of shape (m, min(m, n)) and (min(m, n), n).
1644
+ compute_uv : if true, U and V are calculated. if false, only S is calculated.
1645
+ overwrite_a : if true, allows modification of A which may improve
1646
+ performance. if false, A is not modified.
1647
+
1648
+ output:
1649
+ U : an unitary matrix: U' U = 1. if full_matrices is true, U is of
1650
+ shape (m, m). ortherwise it is of shape (m, min(m, n)).
1651
+
1652
+ S : an array of length min(m, n) containing the singular values of A sorted by
1653
+ decreasing magnitude.
1654
+
1655
+ V : an unitary matrix: V V' = 1. if full_matrices is true, V is of
1656
+ shape (n, n). ortherwise it is of shape (min(m, n), n).
1657
+
1658
+ return value:
1659
+
1660
+ S if compute_uv is false
1661
+ (U, S, V) if compute_uv is true
1662
+
1663
+ overview of the matrices:
1664
+
1665
+ full_matrices true:
1666
+ A : m*n
1667
+ U : m*m U' U = 1
1668
+ S as matrix : m*n
1669
+ V : n*n V V' = 1
1670
+
1671
+ full_matrices false:
1672
+ A : m*n
1673
+ U : m*min(n,m) U' U = 1
1674
+ S as matrix : min(m,n)*min(m,n)
1675
+ V : min(m,n)*n V V' = 1
1676
+
1677
+ example:
1678
+ >>> from mpmath import mp
1679
+ >>> A = mp.matrix([[-2j, -1-3j, -2+2j], [2-2j, -1-3j, 1], [-3+1j,-2j,0]])
1680
+ >>> S = mp.svd_c(A, compute_uv = False)
1681
+ >>> print(mp.chop(S - mp.matrix([mp.sqrt(34), mp.sqrt(15), mp.sqrt(6)])))
1682
+ [0.0]
1683
+ [0.0]
1684
+ [0.0]
1685
+
1686
+ >>> U, S, V = mp.svd_c(A)
1687
+ >>> print(mp.chop(A - U * mp.diag(S) * V))
1688
+ [0.0 0.0 0.0]
1689
+ [0.0 0.0 0.0]
1690
+ [0.0 0.0 0.0]
1691
+
1692
+ see also: svd, svd_r
1693
+ """
1694
+
1695
+ m, n = A.rows, A.cols
1696
+
1697
+ if not compute_uv:
1698
+ if not overwrite_a:
1699
+ A = A.copy()
1700
+ S = svd_c_raw(ctx, A, V = False, calc_u = False)
1701
+ S = S[:min(m,n)]
1702
+ return S
1703
+
1704
+ if full_matrices and n < m:
1705
+ V = ctx.zeros(m, m)
1706
+ A0 = ctx.zeros(m, m)
1707
+ A0[:,:n] = A
1708
+ S = svd_c_raw(ctx, A0, V, calc_u = True)
1709
+
1710
+ S = S[:n]
1711
+ V = V[:n,:n]
1712
+
1713
+ return (A0, S, V)
1714
+ else:
1715
+ if not overwrite_a:
1716
+ A = A.copy()
1717
+ V = ctx.zeros(n, n)
1718
+ S = svd_c_raw(ctx, A, V, calc_u = True)
1719
+
1720
+ if n > m:
1721
+ if full_matrices == False:
1722
+ V = V[:m,:]
1723
+
1724
+ S = S[:m]
1725
+ A = A[:,:m]
1726
+
1727
+ return (A, S, V)
1728
+
1729
+ @defun
1730
+ def svd(ctx, A, full_matrices = False, compute_uv = True, overwrite_a = False):
1731
+ """
1732
+ "svd" is a unified interface for "svd_r" and "svd_c". Depending on
1733
+ whether A is real or complex the appropriate function is called.
1734
+
1735
+ This routine computes the singular value decomposition of a matrix A.
1736
+ Given A, two orthogonal (A real) or unitary (A complex) matrices U and V
1737
+ are calculated such that
1738
+
1739
+ A = U S V and U' U = 1 and V V' = 1
1740
+
1741
+ where S is a suitable shaped matrix whose off-diagonal elements are zero.
1742
+ Here ' denotes the hermitian transpose (i.e. transposition and complex
1743
+ conjugation). The diagonal elements of S are the singular values of A,
1744
+ i.e. the squareroots of the eigenvalues of A' A or A A'.
1745
+
1746
+ input:
1747
+ A : a real or complex matrix of shape (m, n)
1748
+ full_matrices : if true, U and V are of shape (m, m) and (n, n).
1749
+ if false, U and V are of shape (m, min(m, n)) and (min(m, n), n).
1750
+ compute_uv : if true, U and V are calculated. if false, only S is calculated.
1751
+ overwrite_a : if true, allows modification of A which may improve
1752
+ performance. if false, A is not modified.
1753
+
1754
+ output:
1755
+ U : an orthogonal or unitary matrix: U' U = 1. if full_matrices is true, U is of
1756
+ shape (m, m). ortherwise it is of shape (m, min(m, n)).
1757
+
1758
+ S : an array of length min(m, n) containing the singular values of A sorted by
1759
+ decreasing magnitude.
1760
+
1761
+ V : an orthogonal or unitary matrix: V V' = 1. if full_matrices is true, V is of
1762
+ shape (n, n). ortherwise it is of shape (min(m, n), n).
1763
+
1764
+ return value:
1765
+
1766
+ S if compute_uv is false
1767
+ (U, S, V) if compute_uv is true
1768
+
1769
+ overview of the matrices:
1770
+
1771
+ full_matrices true:
1772
+ A : m*n
1773
+ U : m*m U' U = 1
1774
+ S as matrix : m*n
1775
+ V : n*n V V' = 1
1776
+
1777
+ full_matrices false:
1778
+ A : m*n
1779
+ U : m*min(n,m) U' U = 1
1780
+ S as matrix : min(m,n)*min(m,n)
1781
+ V : min(m,n)*n V V' = 1
1782
+
1783
+ examples:
1784
+
1785
+ >>> from mpmath import mp
1786
+ >>> A = mp.matrix([[2, -2, -1], [3, 4, -2], [-2, -2, 0]])
1787
+ >>> S = mp.svd(A, compute_uv = False)
1788
+ >>> print(S)
1789
+ [6.0]
1790
+ [3.0]
1791
+ [1.0]
1792
+
1793
+ >>> U, S, V = mp.svd(A)
1794
+ >>> print(mp.chop(A - U * mp.diag(S) * V))
1795
+ [0.0 0.0 0.0]
1796
+ [0.0 0.0 0.0]
1797
+ [0.0 0.0 0.0]
1798
+
1799
+ see also: svd_r, svd_c
1800
+ """
1801
+
1802
+ iscomplex = any(type(x) is ctx.mpc for x in A)
1803
+
1804
+ if iscomplex:
1805
+ return ctx.svd_c(A, full_matrices = full_matrices, compute_uv = compute_uv, overwrite_a = overwrite_a)
1806
+ else:
1807
+ return ctx.svd_r(A, full_matrices = full_matrices, compute_uv = compute_uv, overwrite_a = overwrite_a)
tuning-competition-baseline/.venv/lib/python3.11/site-packages/mpmath/tests/__pycache__/test_elliptic.cpython-311.pyc ADDED
Binary file (46.2 kB). View file
 
tuning-competition-baseline/.venv/lib/python3.11/site-packages/packaging-24.2.dist-info/LICENSE.APACHE ADDED
@@ -0,0 +1,177 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+
2
+ Apache License
3
+ Version 2.0, January 2004
4
+ http://www.apache.org/licenses/
5
+
6
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
7
+
8
+ 1. Definitions.
9
+
10
+ "License" shall mean the terms and conditions for use, reproduction,
11
+ and distribution as defined by Sections 1 through 9 of this document.
12
+
13
+ "Licensor" shall mean the copyright owner or entity authorized by
14
+ the copyright owner that is granting the License.
15
+
16
+ "Legal Entity" shall mean the union of the acting entity and all
17
+ other entities that control, are controlled by, or are under common
18
+ control with that entity. For the purposes of this definition,
19
+ "control" means (i) the power, direct or indirect, to cause the
20
+ direction or management of such entity, whether by contract or
21
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
22
+ outstanding shares, or (iii) beneficial ownership of such entity.
23
+
24
+ "You" (or "Your") shall mean an individual or Legal Entity
25
+ exercising permissions granted by this License.
26
+
27
+ "Source" form shall mean the preferred form for making modifications,
28
+ including but not limited to software source code, documentation
29
+ source, and configuration files.
30
+
31
+ "Object" form shall mean any form resulting from mechanical
32
+ transformation or translation of a Source form, including but
33
+ not limited to compiled object code, generated documentation,
34
+ and conversions to other media types.
35
+
36
+ "Work" shall mean the work of authorship, whether in Source or
37
+ Object form, made available under the License, as indicated by a
38
+ copyright notice that is included in or attached to the work
39
+ (an example is provided in the Appendix below).
40
+
41
+ "Derivative Works" shall mean any work, whether in Source or Object
42
+ form, that is based on (or derived from) the Work and for which the
43
+ editorial revisions, annotations, elaborations, or other modifications
44
+ represent, as a whole, an original work of authorship. For the purposes
45
+ of this License, Derivative Works shall not include works that remain
46
+ separable from, or merely link (or bind by name) to the interfaces of,
47
+ the Work and Derivative Works thereof.
48
+
49
+ "Contribution" shall mean any work of authorship, including
50
+ the original version of the Work and any modifications or additions
51
+ to that Work or Derivative Works thereof, that is intentionally
52
+ submitted to Licensor for inclusion in the Work by the copyright owner
53
+ or by an individual or Legal Entity authorized to submit on behalf of
54
+ the copyright owner. For the purposes of this definition, "submitted"
55
+ means any form of electronic, verbal, or written communication sent
56
+ to the Licensor or its representatives, including but not limited to
57
+ communication on electronic mailing lists, source code control systems,
58
+ and issue tracking systems that are managed by, or on behalf of, the
59
+ Licensor for the purpose of discussing and improving the Work, but
60
+ excluding communication that is conspicuously marked or otherwise
61
+ designated in writing by the copyright owner as "Not a Contribution."
62
+
63
+ "Contributor" shall mean Licensor and any individual or Legal Entity
64
+ on behalf of whom a Contribution has been received by Licensor and
65
+ subsequently incorporated within the Work.
66
+
67
+ 2. Grant of Copyright License. Subject to the terms and conditions of
68
+ this License, each Contributor hereby grants to You a perpetual,
69
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
70
+ copyright license to reproduce, prepare Derivative Works of,
71
+ publicly display, publicly perform, sublicense, and distribute the
72
+ Work and such Derivative Works in Source or Object form.
73
+
74
+ 3. Grant of Patent License. Subject to the terms and conditions of
75
+ this License, each Contributor hereby grants to You a perpetual,
76
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
77
+ (except as stated in this section) patent license to make, have made,
78
+ use, offer to sell, sell, import, and otherwise transfer the Work,
79
+ where such license applies only to those patent claims licensable
80
+ by such Contributor that are necessarily infringed by their
81
+ Contribution(s) alone or by combination of their Contribution(s)
82
+ with the Work to which such Contribution(s) was submitted. If You
83
+ institute patent litigation against any entity (including a
84
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
85
+ or a Contribution incorporated within the Work constitutes direct
86
+ or contributory patent infringement, then any patent licenses
87
+ granted to You under this License for that Work shall terminate
88
+ as of the date such litigation is filed.
89
+
90
+ 4. Redistribution. You may reproduce and distribute copies of the
91
+ Work or Derivative Works thereof in any medium, with or without
92
+ modifications, and in Source or Object form, provided that You
93
+ meet the following conditions:
94
+
95
+ (a) You must give any other recipients of the Work or
96
+ Derivative Works a copy of this License; and
97
+
98
+ (b) You must cause any modified files to carry prominent notices
99
+ stating that You changed the files; and
100
+
101
+ (c) You must retain, in the Source form of any Derivative Works
102
+ that You distribute, all copyright, patent, trademark, and
103
+ attribution notices from the Source form of the Work,
104
+ excluding those notices that do not pertain to any part of
105
+ the Derivative Works; and
106
+
107
+ (d) If the Work includes a "NOTICE" text file as part of its
108
+ distribution, then any Derivative Works that You distribute must
109
+ include a readable copy of the attribution notices contained
110
+ within such NOTICE file, excluding those notices that do not
111
+ pertain to any part of the Derivative Works, in at least one
112
+ of the following places: within a NOTICE text file distributed
113
+ as part of the Derivative Works; within the Source form or
114
+ documentation, if provided along with the Derivative Works; or,
115
+ within a display generated by the Derivative Works, if and
116
+ wherever such third-party notices normally appear. The contents
117
+ of the NOTICE file are for informational purposes only and
118
+ do not modify the License. You may add Your own attribution
119
+ notices within Derivative Works that You distribute, alongside
120
+ or as an addendum to the NOTICE text from the Work, provided
121
+ that such additional attribution notices cannot be construed
122
+ as modifying the License.
123
+
124
+ You may add Your own copyright statement to Your modifications and
125
+ may provide additional or different license terms and conditions
126
+ for use, reproduction, or distribution of Your modifications, or
127
+ for any such Derivative Works as a whole, provided Your use,
128
+ reproduction, and distribution of the Work otherwise complies with
129
+ the conditions stated in this License.
130
+
131
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
132
+ any Contribution intentionally submitted for inclusion in the Work
133
+ by You to the Licensor shall be under the terms and conditions of
134
+ this License, without any additional terms or conditions.
135
+ Notwithstanding the above, nothing herein shall supersede or modify
136
+ the terms of any separate license agreement you may have executed
137
+ with Licensor regarding such Contributions.
138
+
139
+ 6. Trademarks. This License does not grant permission to use the trade
140
+ names, trademarks, service marks, or product names of the Licensor,
141
+ except as required for reasonable and customary use in describing the
142
+ origin of the Work and reproducing the content of the NOTICE file.
143
+
144
+ 7. Disclaimer of Warranty. Unless required by applicable law or
145
+ agreed to in writing, Licensor provides the Work (and each
146
+ Contributor provides its Contributions) on an "AS IS" BASIS,
147
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
148
+ implied, including, without limitation, any warranties or conditions
149
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
150
+ PARTICULAR PURPOSE. You are solely responsible for determining the
151
+ appropriateness of using or redistributing the Work and assume any
152
+ risks associated with Your exercise of permissions under this License.
153
+
154
+ 8. Limitation of Liability. In no event and under no legal theory,
155
+ whether in tort (including negligence), contract, or otherwise,
156
+ unless required by applicable law (such as deliberate and grossly
157
+ negligent acts) or agreed to in writing, shall any Contributor be
158
+ liable to You for damages, including any direct, indirect, special,
159
+ incidental, or consequential damages of any character arising as a
160
+ result of this License or out of the use or inability to use the
161
+ Work (including but not limited to damages for loss of goodwill,
162
+ work stoppage, computer failure or malfunction, or any and all
163
+ other commercial damages or losses), even if such Contributor
164
+ has been advised of the possibility of such damages.
165
+
166
+ 9. Accepting Warranty or Additional Liability. While redistributing
167
+ the Work or Derivative Works thereof, You may choose to offer,
168
+ and charge a fee for, acceptance of support, warranty, indemnity,
169
+ or other liability obligations and/or rights consistent with this
170
+ License. However, in accepting such obligations, You may act only
171
+ on Your own behalf and on Your sole responsibility, not on behalf
172
+ of any other Contributor, and only if You agree to indemnify,
173
+ defend, and hold each Contributor harmless for any liability
174
+ incurred by, or claims asserted against, such Contributor by reason
175
+ of your accepting any such warranty or additional liability.
176
+
177
+ END OF TERMS AND CONDITIONS
tuning-competition-baseline/.venv/lib/python3.11/site-packages/packaging-24.2.dist-info/LICENSE.BSD ADDED
@@ -0,0 +1,23 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ Copyright (c) Donald Stufft and individual contributors.
2
+ All rights reserved.
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
+ 1. Redistributions of source code must retain the above copyright notice,
8
+ this list of conditions and the following disclaimer.
9
+
10
+ 2. Redistributions in binary form must reproduce the above copyright
11
+ notice, this list of conditions and the following disclaimer in the
12
+ documentation and/or other materials provided with the distribution.
13
+
14
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
15
+ ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
16
+ WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
17
+ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
18
+ FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
20
+ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
21
+ CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
22
+ OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
tuning-competition-baseline/.venv/lib/python3.11/site-packages/packaging-24.2.dist-info/REQUESTED ADDED
File without changes
tuning-competition-baseline/.venv/lib/python3.11/site-packages/packaging-24.2.dist-info/WHEEL ADDED
@@ -0,0 +1,4 @@
 
 
 
 
 
1
+ Wheel-Version: 1.0
2
+ Generator: flit 3.10.1
3
+ Root-Is-Purelib: true
4
+ Tag: py3-none-any
tuning-competition-baseline/.venv/lib/python3.11/site-packages/pip/_vendor/idna/__pycache__/uts46data.cpython-311.pyc ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:41c236e9b167a346f261473ba48db901f00476843b03f377600d8c045836aacd
3
+ size 163197
tuning-competition-baseline/.venv/lib/python3.11/site-packages/pip/_vendor/rich/__pycache__/_emoji_codes.cpython-311.pyc ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:23e69f8f33ae5e21ea90c0254f3b9874d5c2ff6a1a59cffa1496ea60619d0702
3
+ size 208544
tuning-competition-baseline/.venv/lib/python3.11/site-packages/pybind11/__init__.py ADDED
@@ -0,0 +1,19 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from __future__ import annotations
2
+
3
+ import sys
4
+
5
+ if sys.version_info < (3, 7): # noqa: UP036
6
+ msg = "pybind11 does not support Python < 3.7. v2.12 was the last release supporting Python 3.6."
7
+ raise ImportError(msg)
8
+
9
+
10
+ from ._version import __version__, version_info
11
+ from .commands import get_cmake_dir, get_include, get_pkgconfig_dir
12
+
13
+ __all__ = (
14
+ "version_info",
15
+ "__version__",
16
+ "get_include",
17
+ "get_cmake_dir",
18
+ "get_pkgconfig_dir",
19
+ )
tuning-competition-baseline/.venv/lib/python3.11/site-packages/pybind11/__main__.py ADDED
@@ -0,0 +1,86 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # pylint: disable=missing-function-docstring
2
+ from __future__ import annotations
3
+
4
+ import argparse
5
+ import re
6
+ import sys
7
+ import sysconfig
8
+
9
+ from ._version import __version__
10
+ from .commands import get_cmake_dir, get_include, get_pkgconfig_dir
11
+
12
+ # This is the conditional used for os.path being posixpath
13
+ if "posix" in sys.builtin_module_names:
14
+ from shlex import quote
15
+ elif "nt" in sys.builtin_module_names:
16
+ # See https://github.com/mesonbuild/meson/blob/db22551ed9d2dd7889abea01cc1c7bba02bf1c75/mesonbuild/utils/universal.py#L1092-L1121
17
+ # and the original documents:
18
+ # https://docs.microsoft.com/en-us/cpp/c-language/parsing-c-command-line-arguments and
19
+ # https://blogs.msdn.microsoft.com/twistylittlepassagesallalike/2011/04/23/everyone-quotes-command-line-arguments-the-wrong-way/
20
+ UNSAFE = re.compile("[ \t\n\r]")
21
+
22
+ def quote(s: str) -> str:
23
+ if s and not UNSAFE.search(s):
24
+ return s
25
+
26
+ # Paths cannot contain a '"' on Windows, so we don't need to worry
27
+ # about nuanced counting here.
28
+ return f'"{s}\\"' if s.endswith("\\") else f'"{s}"'
29
+ else:
30
+
31
+ def quote(s: str) -> str:
32
+ return s
33
+
34
+
35
+ def print_includes() -> None:
36
+ dirs = [
37
+ sysconfig.get_path("include"),
38
+ sysconfig.get_path("platinclude"),
39
+ get_include(),
40
+ ]
41
+
42
+ # Make unique but preserve order
43
+ unique_dirs = []
44
+ for d in dirs:
45
+ if d and d not in unique_dirs:
46
+ unique_dirs.append(d)
47
+
48
+ print(" ".join(quote(f"-I{d}") for d in unique_dirs))
49
+
50
+
51
+ def main() -> None:
52
+ parser = argparse.ArgumentParser()
53
+ parser.add_argument(
54
+ "--version",
55
+ action="version",
56
+ version=__version__,
57
+ help="Print the version and exit.",
58
+ )
59
+ parser.add_argument(
60
+ "--includes",
61
+ action="store_true",
62
+ help="Include flags for both pybind11 and Python headers.",
63
+ )
64
+ parser.add_argument(
65
+ "--cmakedir",
66
+ action="store_true",
67
+ help="Print the CMake module directory, ideal for setting -Dpybind11_ROOT in CMake.",
68
+ )
69
+ parser.add_argument(
70
+ "--pkgconfigdir",
71
+ action="store_true",
72
+ help="Print the pkgconfig directory, ideal for setting $PKG_CONFIG_PATH.",
73
+ )
74
+ args = parser.parse_args()
75
+ if not sys.argv[1:]:
76
+ parser.print_help()
77
+ if args.includes:
78
+ print_includes()
79
+ if args.cmakedir:
80
+ print(quote(get_cmake_dir()))
81
+ if args.pkgconfigdir:
82
+ print(quote(get_pkgconfig_dir()))
83
+
84
+
85
+ if __name__ == "__main__":
86
+ main()