Add files using upload-large-folder tool
Browse filesThis view is limited to 50 files because it contains too many changes.
See raw diff
- .gitattributes +1 -0
- tuning-competition-baseline/.venv/lib/python3.11/site-packages/Cython/Tempita/_tempita.cpython-311-x86_64-linux-gnu.so +3 -0
- tuning-competition-baseline/.venv/lib/python3.11/site-packages/fsspec/conftest.py +55 -0
- tuning-competition-baseline/.venv/lib/python3.11/site-packages/fsspec/implementations/__pycache__/__init__.cpython-311.pyc +0 -0
- tuning-competition-baseline/.venv/lib/python3.11/site-packages/fsspec/implementations/__pycache__/arrow.cpython-311.pyc +0 -0
- tuning-competition-baseline/.venv/lib/python3.11/site-packages/fsspec/implementations/__pycache__/cache_mapper.cpython-311.pyc +0 -0
- tuning-competition-baseline/.venv/lib/python3.11/site-packages/fsspec/implementations/__pycache__/cache_metadata.cpython-311.pyc +0 -0
- tuning-competition-baseline/.venv/lib/python3.11/site-packages/fsspec/implementations/__pycache__/data.cpython-311.pyc +0 -0
- tuning-competition-baseline/.venv/lib/python3.11/site-packages/fsspec/implementations/__pycache__/dirfs.cpython-311.pyc +0 -0
- tuning-competition-baseline/.venv/lib/python3.11/site-packages/fsspec/implementations/__pycache__/github.cpython-311.pyc +0 -0
- tuning-competition-baseline/.venv/lib/python3.11/site-packages/fsspec/implementations/__pycache__/http.cpython-311.pyc +0 -0
- tuning-competition-baseline/.venv/lib/python3.11/site-packages/fsspec/implementations/__pycache__/memory.cpython-311.pyc +0 -0
- tuning-competition-baseline/.venv/lib/python3.11/site-packages/fsspec/implementations/__pycache__/smb.cpython-311.pyc +0 -0
- tuning-competition-baseline/.venv/lib/python3.11/site-packages/fsspec/implementations/github.py +227 -0
- tuning-competition-baseline/.venv/lib/python3.11/site-packages/fsspec/registry.py +299 -0
- tuning-competition-baseline/.venv/lib/python3.11/site-packages/fsspec/transaction.py +85 -0
- tuning-competition-baseline/.venv/lib/python3.11/site-packages/functorch/dim/__init__.py +179 -0
- tuning-competition-baseline/.venv/lib/python3.11/site-packages/functorch/dim/__pycache__/batch_tensor.cpython-311.pyc +0 -0
- tuning-competition-baseline/.venv/lib/python3.11/site-packages/functorch/dim/__pycache__/delayed_mul_tensor.cpython-311.pyc +0 -0
- tuning-competition-baseline/.venv/lib/python3.11/site-packages/functorch/dim/__pycache__/op_properties.cpython-311.pyc +0 -0
- tuning-competition-baseline/.venv/lib/python3.11/site-packages/functorch/dim/__pycache__/tree_map.cpython-311.pyc +0 -0
- tuning-competition-baseline/.venv/lib/python3.11/site-packages/functorch/dim/__pycache__/wrap_type.cpython-311.pyc +0 -0
- tuning-competition-baseline/.venv/lib/python3.11/site-packages/functorch/dim/batch_tensor.py +25 -0
- tuning-competition-baseline/.venv/lib/python3.11/site-packages/mpmath/ctx_base.py +494 -0
- tuning-competition-baseline/.venv/lib/python3.11/site-packages/mpmath/ctx_fp.py +253 -0
- tuning-competition-baseline/.venv/lib/python3.11/site-packages/mpmath/ctx_iv.py +551 -0
- tuning-competition-baseline/.venv/lib/python3.11/site-packages/mpmath/ctx_mp.py +1339 -0
- tuning-competition-baseline/.venv/lib/python3.11/site-packages/mpmath/ctx_mp_python.py +1149 -0
- tuning-competition-baseline/.venv/lib/python3.11/site-packages/mpmath/identification.py +844 -0
- tuning-competition-baseline/.venv/lib/python3.11/site-packages/mpmath/rational.py +240 -0
- tuning-competition-baseline/.venv/lib/python3.11/site-packages/mpmath/usertools.py +93 -0
- tuning-competition-baseline/.venv/lib/python3.11/site-packages/mpmath/visualization.py +313 -0
- tuning-competition-baseline/.venv/lib/python3.11/site-packages/pip/_internal/locations/__init__.py +456 -0
- tuning-competition-baseline/.venv/lib/python3.11/site-packages/pip/_internal/locations/__pycache__/_distutils.cpython-311.pyc +0 -0
- tuning-competition-baseline/.venv/lib/python3.11/site-packages/pip/_internal/locations/__pycache__/_sysconfig.cpython-311.pyc +0 -0
- tuning-competition-baseline/.venv/lib/python3.11/site-packages/pip/_internal/locations/_sysconfig.py +214 -0
- tuning-competition-baseline/.venv/lib/python3.11/site-packages/pip/_internal/metadata/importlib/__pycache__/_compat.cpython-311.pyc +0 -0
- tuning-competition-baseline/.venv/lib/python3.11/site-packages/pip/_internal/network/__init__.py +2 -0
- tuning-competition-baseline/.venv/lib/python3.11/site-packages/pip/_internal/network/session.py +522 -0
- tuning-competition-baseline/.venv/lib/python3.11/site-packages/pip/_internal/resolution/__pycache__/base.cpython-311.pyc +0 -0
- tuning-competition-baseline/.venv/lib/python3.11/site-packages/pip/_internal/resolution/resolvelib/__init__.py +0 -0
- tuning-competition-baseline/.venv/lib/python3.11/site-packages/pip/_internal/resolution/resolvelib/__pycache__/__init__.cpython-311.pyc +0 -0
- tuning-competition-baseline/.venv/lib/python3.11/site-packages/pip/_internal/resolution/resolvelib/__pycache__/base.cpython-311.pyc +0 -0
- tuning-competition-baseline/.venv/lib/python3.11/site-packages/pip/_internal/resolution/resolvelib/__pycache__/candidates.cpython-311.pyc +0 -0
- tuning-competition-baseline/.venv/lib/python3.11/site-packages/pip/_internal/resolution/resolvelib/__pycache__/factory.cpython-311.pyc +0 -0
- tuning-competition-baseline/.venv/lib/python3.11/site-packages/pip/_internal/resolution/resolvelib/__pycache__/found_candidates.cpython-311.pyc +0 -0
- tuning-competition-baseline/.venv/lib/python3.11/site-packages/pip/_internal/resolution/resolvelib/__pycache__/provider.cpython-311.pyc +0 -0
- tuning-competition-baseline/.venv/lib/python3.11/site-packages/pip/_internal/resolution/resolvelib/__pycache__/requirements.cpython-311.pyc +0 -0
- tuning-competition-baseline/.venv/lib/python3.11/site-packages/pip/_internal/resolution/resolvelib/__pycache__/resolver.cpython-311.pyc +0 -0
- tuning-competition-baseline/.venv/lib/python3.11/site-packages/pip/_internal/resolution/resolvelib/base.py +139 -0
.gitattributes
CHANGED
|
@@ -46,3 +46,4 @@ tuning-competition-baseline/.venv/lib/python3.11/site-packages/pip/_vendor/distl
|
|
| 46 |
tuning-competition-baseline/.venv/lib/python3.11/site-packages/Cython/Utils.cpython-311-x86_64-linux-gnu.so filter=lfs diff=lfs merge=lfs -text
|
| 47 |
tuning-competition-baseline/.venv/lib/python3.11/site-packages/pip/_vendor/__pycache__/typing_extensions.cpython-311.pyc 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
|
|
|
|
|
|
| 46 |
tuning-competition-baseline/.venv/lib/python3.11/site-packages/Cython/Utils.cpython-311-x86_64-linux-gnu.so filter=lfs diff=lfs merge=lfs -text
|
| 47 |
tuning-competition-baseline/.venv/lib/python3.11/site-packages/pip/_vendor/__pycache__/typing_extensions.cpython-311.pyc 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
|
tuning-competition-baseline/.venv/lib/python3.11/site-packages/Cython/Tempita/_tempita.cpython-311-x86_64-linux-gnu.so
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:0477f20b0dfa19f79dc484a4a92c0ba4ae204d074ad171452e1d7de8bbd4d6cf
|
| 3 |
+
size 595904
|
tuning-competition-baseline/.venv/lib/python3.11/site-packages/fsspec/conftest.py
ADDED
|
@@ -0,0 +1,55 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import os
|
| 2 |
+
import shutil
|
| 3 |
+
import subprocess
|
| 4 |
+
import sys
|
| 5 |
+
import time
|
| 6 |
+
|
| 7 |
+
import pytest
|
| 8 |
+
|
| 9 |
+
import fsspec
|
| 10 |
+
from fsspec.implementations.cached import CachingFileSystem
|
| 11 |
+
|
| 12 |
+
|
| 13 |
+
@pytest.fixture()
|
| 14 |
+
def m():
|
| 15 |
+
"""
|
| 16 |
+
Fixture providing a memory filesystem.
|
| 17 |
+
"""
|
| 18 |
+
m = fsspec.filesystem("memory")
|
| 19 |
+
m.store.clear()
|
| 20 |
+
m.pseudo_dirs.clear()
|
| 21 |
+
m.pseudo_dirs.append("")
|
| 22 |
+
try:
|
| 23 |
+
yield m
|
| 24 |
+
finally:
|
| 25 |
+
m.store.clear()
|
| 26 |
+
m.pseudo_dirs.clear()
|
| 27 |
+
m.pseudo_dirs.append("")
|
| 28 |
+
|
| 29 |
+
|
| 30 |
+
@pytest.fixture
|
| 31 |
+
def ftp_writable(tmpdir):
|
| 32 |
+
"""
|
| 33 |
+
Fixture providing a writable FTP filesystem.
|
| 34 |
+
"""
|
| 35 |
+
pytest.importorskip("pyftpdlib")
|
| 36 |
+
from fsspec.implementations.ftp import FTPFileSystem
|
| 37 |
+
|
| 38 |
+
FTPFileSystem.clear_instance_cache() # remove lingering connections
|
| 39 |
+
CachingFileSystem.clear_instance_cache()
|
| 40 |
+
d = str(tmpdir)
|
| 41 |
+
with open(os.path.join(d, "out"), "wb") as f:
|
| 42 |
+
f.write(b"hello" * 10000)
|
| 43 |
+
P = subprocess.Popen(
|
| 44 |
+
[sys.executable, "-m", "pyftpdlib", "-d", d, "-u", "user", "-P", "pass", "-w"]
|
| 45 |
+
)
|
| 46 |
+
try:
|
| 47 |
+
time.sleep(1)
|
| 48 |
+
yield "localhost", 2121, "user", "pass"
|
| 49 |
+
finally:
|
| 50 |
+
P.terminate()
|
| 51 |
+
P.wait()
|
| 52 |
+
try:
|
| 53 |
+
shutil.rmtree(tmpdir)
|
| 54 |
+
except Exception:
|
| 55 |
+
pass
|
tuning-competition-baseline/.venv/lib/python3.11/site-packages/fsspec/implementations/__pycache__/__init__.cpython-311.pyc
ADDED
|
Binary file (223 Bytes). View file
|
|
|
tuning-competition-baseline/.venv/lib/python3.11/site-packages/fsspec/implementations/__pycache__/arrow.cpython-311.pyc
ADDED
|
Binary file (15.7 kB). View file
|
|
|
tuning-competition-baseline/.venv/lib/python3.11/site-packages/fsspec/implementations/__pycache__/cache_mapper.cpython-311.pyc
ADDED
|
Binary file (4.71 kB). View file
|
|
|
tuning-competition-baseline/.venv/lib/python3.11/site-packages/fsspec/implementations/__pycache__/cache_metadata.cpython-311.pyc
ADDED
|
Binary file (12.8 kB). View file
|
|
|
tuning-competition-baseline/.venv/lib/python3.11/site-packages/fsspec/implementations/__pycache__/data.cpython-311.pyc
ADDED
|
Binary file (2.8 kB). View file
|
|
|
tuning-competition-baseline/.venv/lib/python3.11/site-packages/fsspec/implementations/__pycache__/dirfs.cpython-311.pyc
ADDED
|
Binary file (25.9 kB). View file
|
|
|
tuning-competition-baseline/.venv/lib/python3.11/site-packages/fsspec/implementations/__pycache__/github.cpython-311.pyc
ADDED
|
Binary file (11.7 kB). View file
|
|
|
tuning-competition-baseline/.venv/lib/python3.11/site-packages/fsspec/implementations/__pycache__/http.cpython-311.pyc
ADDED
|
Binary file (45.5 kB). View file
|
|
|
tuning-competition-baseline/.venv/lib/python3.11/site-packages/fsspec/implementations/__pycache__/memory.cpython-311.pyc
ADDED
|
Binary file (15.3 kB). View file
|
|
|
tuning-competition-baseline/.venv/lib/python3.11/site-packages/fsspec/implementations/__pycache__/smb.cpython-311.pyc
ADDED
|
Binary file (16.4 kB). View file
|
|
|
tuning-competition-baseline/.venv/lib/python3.11/site-packages/fsspec/implementations/github.py
ADDED
|
@@ -0,0 +1,227 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import requests
|
| 2 |
+
|
| 3 |
+
from ..spec import AbstractFileSystem
|
| 4 |
+
from ..utils import infer_storage_options
|
| 5 |
+
from .memory import MemoryFile
|
| 6 |
+
|
| 7 |
+
# TODO: add GIST backend, would be very similar
|
| 8 |
+
|
| 9 |
+
|
| 10 |
+
class GithubFileSystem(AbstractFileSystem):
|
| 11 |
+
"""Interface to files in github
|
| 12 |
+
|
| 13 |
+
An instance of this class provides the files residing within a remote github
|
| 14 |
+
repository. You may specify a point in the repos history, by SHA, branch
|
| 15 |
+
or tag (default is current master).
|
| 16 |
+
|
| 17 |
+
Given that code files tend to be small, and that github does not support
|
| 18 |
+
retrieving partial content, we always fetch whole files.
|
| 19 |
+
|
| 20 |
+
When using fsspec.open, allows URIs of the form:
|
| 21 |
+
|
| 22 |
+
- "github://path/file", in which case you must specify org, repo and
|
| 23 |
+
may specify sha in the extra args
|
| 24 |
+
- 'github://org:repo@/precip/catalog.yml', where the org and repo are
|
| 25 |
+
part of the URI
|
| 26 |
+
- 'github://org:repo@sha/precip/catalog.yml', where the sha is also included
|
| 27 |
+
|
| 28 |
+
``sha`` can be the full or abbreviated hex of the commit you want to fetch
|
| 29 |
+
from, or a branch or tag name (so long as it doesn't contain special characters
|
| 30 |
+
like "/", "?", which would have to be HTTP-encoded).
|
| 31 |
+
|
| 32 |
+
For authorised access, you must provide username and token, which can be made
|
| 33 |
+
at https://github.com/settings/tokens
|
| 34 |
+
"""
|
| 35 |
+
|
| 36 |
+
url = "https://api.github.com/repos/{org}/{repo}/git/trees/{sha}"
|
| 37 |
+
rurl = "https://raw.githubusercontent.com/{org}/{repo}/{sha}/{path}"
|
| 38 |
+
protocol = "github"
|
| 39 |
+
timeout = (60, 60) # connect, read timeouts
|
| 40 |
+
|
| 41 |
+
def __init__(
|
| 42 |
+
self, org, repo, sha=None, username=None, token=None, timeout=None, **kwargs
|
| 43 |
+
):
|
| 44 |
+
super().__init__(**kwargs)
|
| 45 |
+
self.org = org
|
| 46 |
+
self.repo = repo
|
| 47 |
+
if (username is None) ^ (token is None):
|
| 48 |
+
raise ValueError("Auth required both username and token")
|
| 49 |
+
self.username = username
|
| 50 |
+
self.token = token
|
| 51 |
+
if timeout is not None:
|
| 52 |
+
self.timeout = timeout
|
| 53 |
+
if sha is None:
|
| 54 |
+
# look up default branch (not necessarily "master")
|
| 55 |
+
u = "https://api.github.com/repos/{org}/{repo}"
|
| 56 |
+
r = requests.get(
|
| 57 |
+
u.format(org=org, repo=repo), timeout=self.timeout, **self.kw
|
| 58 |
+
)
|
| 59 |
+
r.raise_for_status()
|
| 60 |
+
sha = r.json()["default_branch"]
|
| 61 |
+
|
| 62 |
+
self.root = sha
|
| 63 |
+
self.ls("")
|
| 64 |
+
|
| 65 |
+
@property
|
| 66 |
+
def kw(self):
|
| 67 |
+
if self.username:
|
| 68 |
+
return {"auth": (self.username, self.token)}
|
| 69 |
+
return {}
|
| 70 |
+
|
| 71 |
+
@classmethod
|
| 72 |
+
def repos(cls, org_or_user, is_org=True):
|
| 73 |
+
"""List repo names for given org or user
|
| 74 |
+
|
| 75 |
+
This may become the top level of the FS
|
| 76 |
+
|
| 77 |
+
Parameters
|
| 78 |
+
----------
|
| 79 |
+
org_or_user: str
|
| 80 |
+
Name of the github org or user to query
|
| 81 |
+
is_org: bool (default True)
|
| 82 |
+
Whether the name is an organisation (True) or user (False)
|
| 83 |
+
|
| 84 |
+
Returns
|
| 85 |
+
-------
|
| 86 |
+
List of string
|
| 87 |
+
"""
|
| 88 |
+
r = requests.get(
|
| 89 |
+
f"https://api.github.com/{['users', 'orgs'][is_org]}/{org_or_user}/repos",
|
| 90 |
+
timeout=cls.timeout,
|
| 91 |
+
)
|
| 92 |
+
r.raise_for_status()
|
| 93 |
+
return [repo["name"] for repo in r.json()]
|
| 94 |
+
|
| 95 |
+
@property
|
| 96 |
+
def tags(self):
|
| 97 |
+
"""Names of tags in the repo"""
|
| 98 |
+
r = requests.get(
|
| 99 |
+
f"https://api.github.com/repos/{self.org}/{self.repo}/tags",
|
| 100 |
+
timeout=self.timeout,
|
| 101 |
+
**self.kw,
|
| 102 |
+
)
|
| 103 |
+
r.raise_for_status()
|
| 104 |
+
return [t["name"] for t in r.json()]
|
| 105 |
+
|
| 106 |
+
@property
|
| 107 |
+
def branches(self):
|
| 108 |
+
"""Names of branches in the repo"""
|
| 109 |
+
r = requests.get(
|
| 110 |
+
f"https://api.github.com/repos/{self.org}/{self.repo}/branches",
|
| 111 |
+
timeout=self.timeout,
|
| 112 |
+
**self.kw,
|
| 113 |
+
)
|
| 114 |
+
r.raise_for_status()
|
| 115 |
+
return [t["name"] for t in r.json()]
|
| 116 |
+
|
| 117 |
+
@property
|
| 118 |
+
def refs(self):
|
| 119 |
+
"""Named references, tags and branches"""
|
| 120 |
+
return {"tags": self.tags, "branches": self.branches}
|
| 121 |
+
|
| 122 |
+
def ls(self, path, detail=False, sha=None, _sha=None, **kwargs):
|
| 123 |
+
"""List files at given path
|
| 124 |
+
|
| 125 |
+
Parameters
|
| 126 |
+
----------
|
| 127 |
+
path: str
|
| 128 |
+
Location to list, relative to repo root
|
| 129 |
+
detail: bool
|
| 130 |
+
If True, returns list of dicts, one per file; if False, returns
|
| 131 |
+
list of full filenames only
|
| 132 |
+
sha: str (optional)
|
| 133 |
+
List at the given point in the repo history, branch or tag name or commit
|
| 134 |
+
SHA
|
| 135 |
+
_sha: str (optional)
|
| 136 |
+
List this specific tree object (used internally to descend into trees)
|
| 137 |
+
"""
|
| 138 |
+
path = self._strip_protocol(path)
|
| 139 |
+
if path == "":
|
| 140 |
+
_sha = sha or self.root
|
| 141 |
+
if _sha is None:
|
| 142 |
+
parts = path.rstrip("/").split("/")
|
| 143 |
+
so_far = ""
|
| 144 |
+
_sha = sha or self.root
|
| 145 |
+
for part in parts:
|
| 146 |
+
out = self.ls(so_far, True, sha=sha, _sha=_sha)
|
| 147 |
+
so_far += "/" + part if so_far else part
|
| 148 |
+
out = [o for o in out if o["name"] == so_far]
|
| 149 |
+
if not out:
|
| 150 |
+
raise FileNotFoundError(path)
|
| 151 |
+
out = out[0]
|
| 152 |
+
if out["type"] == "file":
|
| 153 |
+
if detail:
|
| 154 |
+
return [out]
|
| 155 |
+
else:
|
| 156 |
+
return path
|
| 157 |
+
_sha = out["sha"]
|
| 158 |
+
if path not in self.dircache or sha not in [self.root, None]:
|
| 159 |
+
r = requests.get(
|
| 160 |
+
self.url.format(org=self.org, repo=self.repo, sha=_sha),
|
| 161 |
+
timeout=self.timeout,
|
| 162 |
+
**self.kw,
|
| 163 |
+
)
|
| 164 |
+
if r.status_code == 404:
|
| 165 |
+
raise FileNotFoundError(path)
|
| 166 |
+
r.raise_for_status()
|
| 167 |
+
types = {"blob": "file", "tree": "directory"}
|
| 168 |
+
out = [
|
| 169 |
+
{
|
| 170 |
+
"name": path + "/" + f["path"] if path else f["path"],
|
| 171 |
+
"mode": f["mode"],
|
| 172 |
+
"type": types[f["type"]],
|
| 173 |
+
"size": f.get("size", 0),
|
| 174 |
+
"sha": f["sha"],
|
| 175 |
+
}
|
| 176 |
+
for f in r.json()["tree"]
|
| 177 |
+
if f["type"] in types
|
| 178 |
+
]
|
| 179 |
+
if sha in [self.root, None]:
|
| 180 |
+
self.dircache[path] = out
|
| 181 |
+
else:
|
| 182 |
+
out = self.dircache[path]
|
| 183 |
+
if detail:
|
| 184 |
+
return out
|
| 185 |
+
else:
|
| 186 |
+
return sorted([f["name"] for f in out])
|
| 187 |
+
|
| 188 |
+
def invalidate_cache(self, path=None):
|
| 189 |
+
self.dircache.clear()
|
| 190 |
+
|
| 191 |
+
@classmethod
|
| 192 |
+
def _strip_protocol(cls, path):
|
| 193 |
+
opts = infer_storage_options(path)
|
| 194 |
+
if "username" not in opts:
|
| 195 |
+
return super()._strip_protocol(path)
|
| 196 |
+
return opts["path"].lstrip("/")
|
| 197 |
+
|
| 198 |
+
@staticmethod
|
| 199 |
+
def _get_kwargs_from_urls(path):
|
| 200 |
+
opts = infer_storage_options(path)
|
| 201 |
+
if "username" not in opts:
|
| 202 |
+
return {}
|
| 203 |
+
out = {"org": opts["username"], "repo": opts["password"]}
|
| 204 |
+
if opts["host"]:
|
| 205 |
+
out["sha"] = opts["host"]
|
| 206 |
+
return out
|
| 207 |
+
|
| 208 |
+
def _open(
|
| 209 |
+
self,
|
| 210 |
+
path,
|
| 211 |
+
mode="rb",
|
| 212 |
+
block_size=None,
|
| 213 |
+
autocommit=True,
|
| 214 |
+
cache_options=None,
|
| 215 |
+
sha=None,
|
| 216 |
+
**kwargs,
|
| 217 |
+
):
|
| 218 |
+
if mode != "rb":
|
| 219 |
+
raise NotImplementedError
|
| 220 |
+
url = self.rurl.format(
|
| 221 |
+
org=self.org, repo=self.repo, path=path, sha=sha or self.root
|
| 222 |
+
)
|
| 223 |
+
r = requests.get(url, timeout=self.timeout, **self.kw)
|
| 224 |
+
if r.status_code == 404:
|
| 225 |
+
raise FileNotFoundError(path)
|
| 226 |
+
r.raise_for_status()
|
| 227 |
+
return MemoryFile(None, None, r.content)
|
tuning-competition-baseline/.venv/lib/python3.11/site-packages/fsspec/registry.py
ADDED
|
@@ -0,0 +1,299 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from __future__ import annotations
|
| 2 |
+
|
| 3 |
+
import importlib
|
| 4 |
+
import types
|
| 5 |
+
import warnings
|
| 6 |
+
|
| 7 |
+
__all__ = ["registry", "get_filesystem_class", "default"]
|
| 8 |
+
|
| 9 |
+
# internal, mutable
|
| 10 |
+
_registry: dict[str, type] = {}
|
| 11 |
+
|
| 12 |
+
# external, immutable
|
| 13 |
+
registry = types.MappingProxyType(_registry)
|
| 14 |
+
default = "file"
|
| 15 |
+
|
| 16 |
+
|
| 17 |
+
def register_implementation(name, cls, clobber=False, errtxt=None):
|
| 18 |
+
"""Add implementation class to the registry
|
| 19 |
+
|
| 20 |
+
Parameters
|
| 21 |
+
----------
|
| 22 |
+
name: str
|
| 23 |
+
Protocol name to associate with the class
|
| 24 |
+
cls: class or str
|
| 25 |
+
if a class: fsspec-compliant implementation class (normally inherits from
|
| 26 |
+
``fsspec.AbstractFileSystem``, gets added straight to the registry. If a
|
| 27 |
+
str, the full path to an implementation class like package.module.class,
|
| 28 |
+
which gets added to known_implementations,
|
| 29 |
+
so the import is deferred until the filesystem is actually used.
|
| 30 |
+
clobber: bool (optional)
|
| 31 |
+
Whether to overwrite a protocol with the same name; if False, will raise
|
| 32 |
+
instead.
|
| 33 |
+
errtxt: str (optional)
|
| 34 |
+
If given, then a failure to import the given class will result in this
|
| 35 |
+
text being given.
|
| 36 |
+
"""
|
| 37 |
+
if isinstance(cls, str):
|
| 38 |
+
if name in known_implementations and clobber is False:
|
| 39 |
+
if cls != known_implementations[name]["class"]:
|
| 40 |
+
raise ValueError(
|
| 41 |
+
f"Name ({name}) already in the known_implementations and clobber "
|
| 42 |
+
f"is False"
|
| 43 |
+
)
|
| 44 |
+
else:
|
| 45 |
+
known_implementations[name] = {
|
| 46 |
+
"class": cls,
|
| 47 |
+
"err": errtxt or f"{cls} import failed for protocol {name}",
|
| 48 |
+
}
|
| 49 |
+
|
| 50 |
+
else:
|
| 51 |
+
if name in registry and clobber is False:
|
| 52 |
+
if _registry[name] is not cls:
|
| 53 |
+
raise ValueError(
|
| 54 |
+
f"Name ({name}) already in the registry and clobber is False"
|
| 55 |
+
)
|
| 56 |
+
else:
|
| 57 |
+
_registry[name] = cls
|
| 58 |
+
|
| 59 |
+
|
| 60 |
+
# protocols mapped to the class which implements them. This dict can be
|
| 61 |
+
# updated with register_implementation
|
| 62 |
+
known_implementations = {
|
| 63 |
+
"data": {"class": "fsspec.implementations.data.DataFileSystem"},
|
| 64 |
+
"file": {"class": "fsspec.implementations.local.LocalFileSystem"},
|
| 65 |
+
"local": {"class": "fsspec.implementations.local.LocalFileSystem"},
|
| 66 |
+
"memory": {"class": "fsspec.implementations.memory.MemoryFileSystem"},
|
| 67 |
+
"dropbox": {
|
| 68 |
+
"class": "dropboxdrivefs.DropboxDriveFileSystem",
|
| 69 |
+
"err": (
|
| 70 |
+
'DropboxFileSystem requires "dropboxdrivefs",'
|
| 71 |
+
'"requests" and "dropbox" to be installed'
|
| 72 |
+
),
|
| 73 |
+
},
|
| 74 |
+
"http": {
|
| 75 |
+
"class": "fsspec.implementations.http.HTTPFileSystem",
|
| 76 |
+
"err": 'HTTPFileSystem requires "requests" and "aiohttp" to be installed',
|
| 77 |
+
},
|
| 78 |
+
"https": {
|
| 79 |
+
"class": "fsspec.implementations.http.HTTPFileSystem",
|
| 80 |
+
"err": 'HTTPFileSystem requires "requests" and "aiohttp" to be installed',
|
| 81 |
+
},
|
| 82 |
+
"zip": {"class": "fsspec.implementations.zip.ZipFileSystem"},
|
| 83 |
+
"tar": {"class": "fsspec.implementations.tar.TarFileSystem"},
|
| 84 |
+
"gcs": {
|
| 85 |
+
"class": "gcsfs.GCSFileSystem",
|
| 86 |
+
"err": "Please install gcsfs to access Google Storage",
|
| 87 |
+
},
|
| 88 |
+
"gs": {
|
| 89 |
+
"class": "gcsfs.GCSFileSystem",
|
| 90 |
+
"err": "Please install gcsfs to access Google Storage",
|
| 91 |
+
},
|
| 92 |
+
"gdrive": {
|
| 93 |
+
"class": "gdrivefs.GoogleDriveFileSystem",
|
| 94 |
+
"err": "Please install gdrivefs for access to Google Drive",
|
| 95 |
+
},
|
| 96 |
+
"sftp": {
|
| 97 |
+
"class": "fsspec.implementations.sftp.SFTPFileSystem",
|
| 98 |
+
"err": 'SFTPFileSystem requires "paramiko" to be installed',
|
| 99 |
+
},
|
| 100 |
+
"ssh": {
|
| 101 |
+
"class": "fsspec.implementations.sftp.SFTPFileSystem",
|
| 102 |
+
"err": 'SFTPFileSystem requires "paramiko" to be installed',
|
| 103 |
+
},
|
| 104 |
+
"ftp": {"class": "fsspec.implementations.ftp.FTPFileSystem"},
|
| 105 |
+
"hdfs": {
|
| 106 |
+
"class": "fsspec.implementations.arrow.HadoopFileSystem",
|
| 107 |
+
"err": "pyarrow and local java libraries required for HDFS",
|
| 108 |
+
},
|
| 109 |
+
"arrow_hdfs": {
|
| 110 |
+
"class": "fsspec.implementations.arrow.HadoopFileSystem",
|
| 111 |
+
"err": "pyarrow and local java libraries required for HDFS",
|
| 112 |
+
},
|
| 113 |
+
"webhdfs": {
|
| 114 |
+
"class": "fsspec.implementations.webhdfs.WebHDFS",
|
| 115 |
+
"err": 'webHDFS access requires "requests" to be installed',
|
| 116 |
+
},
|
| 117 |
+
"s3": {"class": "s3fs.S3FileSystem", "err": "Install s3fs to access S3"},
|
| 118 |
+
"s3a": {"class": "s3fs.S3FileSystem", "err": "Install s3fs to access S3"},
|
| 119 |
+
"wandb": {"class": "wandbfs.WandbFS", "err": "Install wandbfs to access wandb"},
|
| 120 |
+
"oci": {
|
| 121 |
+
"class": "ocifs.OCIFileSystem",
|
| 122 |
+
"err": "Install ocifs to access OCI Object Storage",
|
| 123 |
+
},
|
| 124 |
+
"ocilake": {
|
| 125 |
+
"class": "ocifs.OCIFileSystem",
|
| 126 |
+
"err": "Install ocifs to access OCI Data Lake",
|
| 127 |
+
},
|
| 128 |
+
"asynclocal": {
|
| 129 |
+
"class": "morefs.asyn_local.AsyncLocalFileSystem",
|
| 130 |
+
"err": "Install 'morefs[asynclocalfs]' to use AsyncLocalFileSystem",
|
| 131 |
+
},
|
| 132 |
+
"adl": {
|
| 133 |
+
"class": "adlfs.AzureDatalakeFileSystem",
|
| 134 |
+
"err": "Install adlfs to access Azure Datalake Gen1",
|
| 135 |
+
},
|
| 136 |
+
"abfs": {
|
| 137 |
+
"class": "adlfs.AzureBlobFileSystem",
|
| 138 |
+
"err": "Install adlfs to access Azure Datalake Gen2 and Azure Blob Storage",
|
| 139 |
+
},
|
| 140 |
+
"az": {
|
| 141 |
+
"class": "adlfs.AzureBlobFileSystem",
|
| 142 |
+
"err": "Install adlfs to access Azure Datalake Gen2 and Azure Blob Storage",
|
| 143 |
+
},
|
| 144 |
+
"cached": {"class": "fsspec.implementations.cached.CachingFileSystem"},
|
| 145 |
+
"blockcache": {"class": "fsspec.implementations.cached.CachingFileSystem"},
|
| 146 |
+
"filecache": {"class": "fsspec.implementations.cached.WholeFileCacheFileSystem"},
|
| 147 |
+
"simplecache": {"class": "fsspec.implementations.cached.SimpleCacheFileSystem"},
|
| 148 |
+
"dask": {
|
| 149 |
+
"class": "fsspec.implementations.dask.DaskWorkerFileSystem",
|
| 150 |
+
"err": "Install dask distributed to access worker file system",
|
| 151 |
+
},
|
| 152 |
+
"dbfs": {
|
| 153 |
+
"class": "fsspec.implementations.dbfs.DatabricksFileSystem",
|
| 154 |
+
"err": "Install the requests package to use the DatabricksFileSystem",
|
| 155 |
+
},
|
| 156 |
+
"github": {
|
| 157 |
+
"class": "fsspec.implementations.github.GithubFileSystem",
|
| 158 |
+
"err": "Install the requests package to use the github FS",
|
| 159 |
+
},
|
| 160 |
+
"git": {
|
| 161 |
+
"class": "fsspec.implementations.git.GitFileSystem",
|
| 162 |
+
"err": "Install pygit2 to browse local git repos",
|
| 163 |
+
},
|
| 164 |
+
"smb": {
|
| 165 |
+
"class": "fsspec.implementations.smb.SMBFileSystem",
|
| 166 |
+
"err": 'SMB requires "smbprotocol" or "smbprotocol[kerberos]" installed',
|
| 167 |
+
},
|
| 168 |
+
"jupyter": {
|
| 169 |
+
"class": "fsspec.implementations.jupyter.JupyterFileSystem",
|
| 170 |
+
"err": "Jupyter FS requires requests to be installed",
|
| 171 |
+
},
|
| 172 |
+
"jlab": {
|
| 173 |
+
"class": "fsspec.implementations.jupyter.JupyterFileSystem",
|
| 174 |
+
"err": "Jupyter FS requires requests to be installed",
|
| 175 |
+
},
|
| 176 |
+
"libarchive": {
|
| 177 |
+
"class": "fsspec.implementations.libarchive.LibArchiveFileSystem",
|
| 178 |
+
"err": "LibArchive requires to be installed",
|
| 179 |
+
},
|
| 180 |
+
"reference": {"class": "fsspec.implementations.reference.ReferenceFileSystem"},
|
| 181 |
+
"generic": {"class": "fsspec.generic.GenericFileSystem"},
|
| 182 |
+
"oss": {
|
| 183 |
+
"class": "ossfs.OSSFileSystem",
|
| 184 |
+
"err": "Install ossfs to access Alibaba Object Storage System",
|
| 185 |
+
},
|
| 186 |
+
"webdav": {
|
| 187 |
+
"class": "webdav4.fsspec.WebdavFileSystem",
|
| 188 |
+
"err": "Install webdav4 to access WebDAV",
|
| 189 |
+
},
|
| 190 |
+
"dvc": {
|
| 191 |
+
"class": "dvc.api.DVCFileSystem",
|
| 192 |
+
"err": "Install dvc to access DVCFileSystem",
|
| 193 |
+
},
|
| 194 |
+
"hf": {
|
| 195 |
+
"class": "huggingface_hub.HfFileSystem",
|
| 196 |
+
"err": "Install huggingface_hub to access HfFileSystem",
|
| 197 |
+
},
|
| 198 |
+
"root": {
|
| 199 |
+
"class": "fsspec_xrootd.XRootDFileSystem",
|
| 200 |
+
"err": "Install fsspec-xrootd to access xrootd storage system."
|
| 201 |
+
+ " Note: 'root' is the protocol name for xrootd storage systems,"
|
| 202 |
+
+ " not referring to root directories",
|
| 203 |
+
},
|
| 204 |
+
"dir": {"class": "fsspec.implementations.dirfs.DirFileSystem"},
|
| 205 |
+
"box": {
|
| 206 |
+
"class": "boxfs.BoxFileSystem",
|
| 207 |
+
"err": "Please install boxfs to access BoxFileSystem",
|
| 208 |
+
},
|
| 209 |
+
"lakefs": {
|
| 210 |
+
"class": "lakefs_spec.LakeFSFileSystem",
|
| 211 |
+
"err": "Please install lakefs-spec to access LakeFSFileSystem",
|
| 212 |
+
},
|
| 213 |
+
}
|
| 214 |
+
|
| 215 |
+
|
| 216 |
+
def get_filesystem_class(protocol):
|
| 217 |
+
"""Fetch named protocol implementation from the registry
|
| 218 |
+
|
| 219 |
+
The dict ``known_implementations`` maps protocol names to the locations
|
| 220 |
+
of classes implementing the corresponding file-system. When used for the
|
| 221 |
+
first time, appropriate imports will happen and the class will be placed in
|
| 222 |
+
the registry. All subsequent calls will fetch directly from the registry.
|
| 223 |
+
|
| 224 |
+
Some protocol implementations require additional dependencies, and so the
|
| 225 |
+
import may fail. In this case, the string in the "err" field of the
|
| 226 |
+
``known_implementations`` will be given as the error message.
|
| 227 |
+
"""
|
| 228 |
+
if not protocol:
|
| 229 |
+
protocol = default
|
| 230 |
+
|
| 231 |
+
if protocol not in registry:
|
| 232 |
+
if protocol not in known_implementations:
|
| 233 |
+
raise ValueError(f"Protocol not known: {protocol}")
|
| 234 |
+
bit = known_implementations[protocol]
|
| 235 |
+
try:
|
| 236 |
+
register_implementation(protocol, _import_class(bit["class"]))
|
| 237 |
+
except ImportError as e:
|
| 238 |
+
raise ImportError(bit["err"]) from e
|
| 239 |
+
cls = registry[protocol]
|
| 240 |
+
if getattr(cls, "protocol", None) in ("abstract", None):
|
| 241 |
+
cls.protocol = protocol
|
| 242 |
+
|
| 243 |
+
return cls
|
| 244 |
+
|
| 245 |
+
|
| 246 |
+
s3_msg = """Your installed version of s3fs is very old and known to cause
|
| 247 |
+
severe performance issues, see also https://github.com/dask/dask/issues/10276
|
| 248 |
+
|
| 249 |
+
To fix, you should specify a lower version bound on s3fs, or
|
| 250 |
+
update the current installation.
|
| 251 |
+
"""
|
| 252 |
+
|
| 253 |
+
|
| 254 |
+
def _import_class(cls, minv=None):
|
| 255 |
+
"""Take a string FQP and return the imported class or identifier
|
| 256 |
+
|
| 257 |
+
clas is of the form "package.module.klass" or "package.module:subobject.klass"
|
| 258 |
+
"""
|
| 259 |
+
if ":" in cls:
|
| 260 |
+
mod, name = cls.rsplit(":", 1)
|
| 261 |
+
s3 = mod == "s3fs"
|
| 262 |
+
mod = importlib.import_module(mod)
|
| 263 |
+
if s3 and mod.__version__.split(".") < ["0", "5"]:
|
| 264 |
+
warnings.warn(s3_msg)
|
| 265 |
+
for part in name.split("."):
|
| 266 |
+
mod = getattr(mod, part)
|
| 267 |
+
return mod
|
| 268 |
+
else:
|
| 269 |
+
mod, name = cls.rsplit(".", 1)
|
| 270 |
+
s3 = mod == "s3fs"
|
| 271 |
+
mod = importlib.import_module(mod)
|
| 272 |
+
if s3 and mod.__version__.split(".") < ["0", "5"]:
|
| 273 |
+
warnings.warn(s3_msg)
|
| 274 |
+
return getattr(mod, name)
|
| 275 |
+
|
| 276 |
+
|
| 277 |
+
def filesystem(protocol, **storage_options):
|
| 278 |
+
"""Instantiate filesystems for given protocol and arguments
|
| 279 |
+
|
| 280 |
+
``storage_options`` are specific to the protocol being chosen, and are
|
| 281 |
+
passed directly to the class.
|
| 282 |
+
"""
|
| 283 |
+
if protocol == "arrow_hdfs":
|
| 284 |
+
warnings.warn(
|
| 285 |
+
"The 'arrow_hdfs' protocol has been deprecated and will be "
|
| 286 |
+
"removed in the future. Specify it as 'hdfs'.",
|
| 287 |
+
DeprecationWarning,
|
| 288 |
+
)
|
| 289 |
+
|
| 290 |
+
cls = get_filesystem_class(protocol)
|
| 291 |
+
return cls(**storage_options)
|
| 292 |
+
|
| 293 |
+
|
| 294 |
+
def available_protocols():
|
| 295 |
+
"""Return a list of the implemented protocols.
|
| 296 |
+
|
| 297 |
+
Note that any given protocol may require extra packages to be importable.
|
| 298 |
+
"""
|
| 299 |
+
return list(known_implementations)
|
tuning-competition-baseline/.venv/lib/python3.11/site-packages/fsspec/transaction.py
ADDED
|
@@ -0,0 +1,85 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from collections import deque
|
| 2 |
+
|
| 3 |
+
|
| 4 |
+
class Transaction:
|
| 5 |
+
"""Filesystem transaction write context
|
| 6 |
+
|
| 7 |
+
Gathers files for deferred commit or discard, so that several write
|
| 8 |
+
operations can be finalized semi-atomically. This works by having this
|
| 9 |
+
instance as the ``.transaction`` attribute of the given filesystem
|
| 10 |
+
"""
|
| 11 |
+
|
| 12 |
+
def __init__(self, fs):
|
| 13 |
+
"""
|
| 14 |
+
Parameters
|
| 15 |
+
----------
|
| 16 |
+
fs: FileSystem instance
|
| 17 |
+
"""
|
| 18 |
+
self.fs = fs
|
| 19 |
+
self.files = deque()
|
| 20 |
+
|
| 21 |
+
def __enter__(self):
|
| 22 |
+
self.start()
|
| 23 |
+
return self
|
| 24 |
+
|
| 25 |
+
def __exit__(self, exc_type, exc_val, exc_tb):
|
| 26 |
+
"""End transaction and commit, if exit is not due to exception"""
|
| 27 |
+
# only commit if there was no exception
|
| 28 |
+
self.complete(commit=exc_type is None)
|
| 29 |
+
self.fs._intrans = False
|
| 30 |
+
self.fs._transaction = None
|
| 31 |
+
|
| 32 |
+
def start(self):
|
| 33 |
+
"""Start a transaction on this FileSystem"""
|
| 34 |
+
self.files = deque() # clean up after previous failed completions
|
| 35 |
+
self.fs._intrans = True
|
| 36 |
+
|
| 37 |
+
def complete(self, commit=True):
|
| 38 |
+
"""Finish transaction: commit or discard all deferred files"""
|
| 39 |
+
while self.files:
|
| 40 |
+
f = self.files.popleft()
|
| 41 |
+
if commit:
|
| 42 |
+
f.commit()
|
| 43 |
+
else:
|
| 44 |
+
f.discard()
|
| 45 |
+
self.fs._intrans = False
|
| 46 |
+
|
| 47 |
+
|
| 48 |
+
class FileActor:
|
| 49 |
+
def __init__(self):
|
| 50 |
+
self.files = []
|
| 51 |
+
|
| 52 |
+
def commit(self):
|
| 53 |
+
for f in self.files:
|
| 54 |
+
f.commit()
|
| 55 |
+
self.files.clear()
|
| 56 |
+
|
| 57 |
+
def discard(self):
|
| 58 |
+
for f in self.files:
|
| 59 |
+
f.discard()
|
| 60 |
+
self.files.clear()
|
| 61 |
+
|
| 62 |
+
def append(self, f):
|
| 63 |
+
self.files.append(f)
|
| 64 |
+
|
| 65 |
+
|
| 66 |
+
class DaskTransaction(Transaction):
|
| 67 |
+
def __init__(self, fs):
|
| 68 |
+
"""
|
| 69 |
+
Parameters
|
| 70 |
+
----------
|
| 71 |
+
fs: FileSystem instance
|
| 72 |
+
"""
|
| 73 |
+
import distributed
|
| 74 |
+
|
| 75 |
+
super().__init__(fs)
|
| 76 |
+
client = distributed.default_client()
|
| 77 |
+
self.files = client.submit(FileActor, actor=True).result()
|
| 78 |
+
|
| 79 |
+
def complete(self, commit=True):
|
| 80 |
+
"""Finish transaction: commit or discard all deferred files"""
|
| 81 |
+
if commit:
|
| 82 |
+
self.files.commit().result()
|
| 83 |
+
else:
|
| 84 |
+
self.files.discard().result()
|
| 85 |
+
self.fs._intrans = False
|
tuning-competition-baseline/.venv/lib/python3.11/site-packages/functorch/dim/__init__.py
ADDED
|
@@ -0,0 +1,179 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import dis
|
| 2 |
+
import inspect
|
| 3 |
+
from typing import Sequence, Union
|
| 4 |
+
|
| 5 |
+
import torch
|
| 6 |
+
|
| 7 |
+
import functorch._C
|
| 8 |
+
from functorch._C import dim as _C
|
| 9 |
+
from .tree_map import tree_flatten, tree_map
|
| 10 |
+
from .wrap_type import wrap_type
|
| 11 |
+
|
| 12 |
+
_C._patch_tensor_class()
|
| 13 |
+
dims, DimList, dimlists = _C.dims, _C.DimList, _C.dimlists
|
| 14 |
+
|
| 15 |
+
|
| 16 |
+
class DimensionMismatchError(Exception):
|
| 17 |
+
pass
|
| 18 |
+
|
| 19 |
+
|
| 20 |
+
class DimensionBindError(Exception):
|
| 21 |
+
pass
|
| 22 |
+
|
| 23 |
+
|
| 24 |
+
from . import op_properties
|
| 25 |
+
|
| 26 |
+
# use dict to avoid writing C++ bindings for set
|
| 27 |
+
pointwise = dict.fromkeys(op_properties.pointwise, True)
|
| 28 |
+
|
| 29 |
+
use_c = True
|
| 30 |
+
if not use_c:
|
| 31 |
+
from . import reference
|
| 32 |
+
|
| 33 |
+
|
| 34 |
+
class _Tensor:
|
| 35 |
+
# fast path around slow wrapping/unwrapping logic for simply queries used
|
| 36 |
+
# by the implementation...
|
| 37 |
+
|
| 38 |
+
@property
|
| 39 |
+
def dims(self):
|
| 40 |
+
return tuple(d for d in self._levels if isinstance(d, Dim))
|
| 41 |
+
|
| 42 |
+
def dim(self):
|
| 43 |
+
return self.ndim
|
| 44 |
+
|
| 45 |
+
if use_c:
|
| 46 |
+
__torch_function__ = classmethod(_C.__torch_function__)
|
| 47 |
+
expand = _C._instancemethod(_C.expand)
|
| 48 |
+
else:
|
| 49 |
+
__torch_function__ = reference.__torch_function__
|
| 50 |
+
expand = reference.expand
|
| 51 |
+
|
| 52 |
+
index = _C._instancemethod(_C.index)
|
| 53 |
+
|
| 54 |
+
def __repr__(self):
|
| 55 |
+
tensor, levels, ndim = self._tensor, self._levels, self.ndim
|
| 56 |
+
return f"{tensor}\nwith dims={tuple(l + ndim if isinstance(l, int) else l for l in levels)} sizes={tuple(tensor.size())}"
|
| 57 |
+
|
| 58 |
+
|
| 59 |
+
TensorLike = (_Tensor, torch.Tensor)
|
| 60 |
+
|
| 61 |
+
|
| 62 |
+
class Dim(_C.Dim, _Tensor):
|
| 63 |
+
# note that _C.Dim comes before tensor because we want the Dim API for things like size to take precendence.
|
| 64 |
+
# Tensor defines format, but we want to print Dims with special formatting
|
| 65 |
+
__format__ = object.__format__
|
| 66 |
+
|
| 67 |
+
|
| 68 |
+
class Tensor(_Tensor, _C.Tensor):
|
| 69 |
+
if not use_c:
|
| 70 |
+
from_batched = staticmethod(_C.Tensor_from_batched)
|
| 71 |
+
from_positional = staticmethod(_C.Tensor_from_positional)
|
| 72 |
+
sum = _C._instancemethod(_C.Tensor_sum)
|
| 73 |
+
|
| 74 |
+
|
| 75 |
+
def cat(tensors, dim, new_dim):
|
| 76 |
+
n = dims()
|
| 77 |
+
return stack(tensors, n, dim).index([n, dim], new_dim)
|
| 78 |
+
|
| 79 |
+
|
| 80 |
+
if use_c:
|
| 81 |
+
_wrap = _C._wrap
|
| 82 |
+
|
| 83 |
+
def _def(name, *args, **kwargs):
|
| 84 |
+
orig = getattr(torch.Tensor, name)
|
| 85 |
+
setattr(_Tensor, name, _C._instancemethod(_wrap(orig, *args, **kwargs)))
|
| 86 |
+
|
| 87 |
+
t__getitem__ = _C._instancemethod(_C.__getitem__)
|
| 88 |
+
stack = _C.stack
|
| 89 |
+
split = _C._instancemethod(_C.split)
|
| 90 |
+
else:
|
| 91 |
+
_wrap, _def = reference._wrap, reference._def
|
| 92 |
+
t__getitem__ = reference.t__getitem__
|
| 93 |
+
stack = reference.stack
|
| 94 |
+
split = reference.split
|
| 95 |
+
|
| 96 |
+
# note: there is no python reference
|
| 97 |
+
t__setitem__ = _C._instancemethod(_C.__setitem__)
|
| 98 |
+
# this is patched in the C API because otherwise torch.Tensor will
|
| 99 |
+
# no longer be considered a sequence and things will break
|
| 100 |
+
# torch.Tensor.__getitem__ = t__getitem__
|
| 101 |
+
|
| 102 |
+
_Tensor.__getitem__ = t__getitem__
|
| 103 |
+
# torch.Tensor.__setitem__ = t__setitem__
|
| 104 |
+
_Tensor.__setitem__ = t__setitem__
|
| 105 |
+
|
| 106 |
+
torch.Tensor.split = split
|
| 107 |
+
_Tensor.split = split
|
| 108 |
+
torch.Tensor.expand = _C._instancemethod(_C.expand)
|
| 109 |
+
torch.Tensor.index = _C._instancemethod(_C.index)
|
| 110 |
+
wrap_type(use_c, _Tensor, torch.Tensor, _Tensor.__torch_function__)
|
| 111 |
+
del _Tensor.ndim
|
| 112 |
+
|
| 113 |
+
if use_c:
|
| 114 |
+
_Tensor.order = _C._instancemethod(_C.order)
|
| 115 |
+
else:
|
| 116 |
+
_Tensor.order = reference.positional
|
| 117 |
+
|
| 118 |
+
_def("mean")
|
| 119 |
+
_def("sum")
|
| 120 |
+
_def("all")
|
| 121 |
+
_def("amax")
|
| 122 |
+
_def("amin")
|
| 123 |
+
_def("aminmax")
|
| 124 |
+
_def("any")
|
| 125 |
+
_def("count_nonzero")
|
| 126 |
+
_def("logsumexp")
|
| 127 |
+
_def("nanmean")
|
| 128 |
+
_def("nansum")
|
| 129 |
+
_def("prod")
|
| 130 |
+
_def("std", keepdim_offset=2)
|
| 131 |
+
_def("var", keepdim_offset=2)
|
| 132 |
+
_def("max", single_dim=True)
|
| 133 |
+
_def("min", single_dim=True)
|
| 134 |
+
_def("argmax", single_dim=True)
|
| 135 |
+
_def("argmin", single_dim=True)
|
| 136 |
+
_def("kthvalue", single_dim=True)
|
| 137 |
+
_def("median", single_dim=True)
|
| 138 |
+
_def("nanmedian", single_dim=True)
|
| 139 |
+
_def("mode", single_dim=True)
|
| 140 |
+
_def("sort", reduce=False)
|
| 141 |
+
_def("argsort", reduce=False)
|
| 142 |
+
_def("unbind", single_dim=True)
|
| 143 |
+
_def("chunk", dim_offset=1, reduce=False)
|
| 144 |
+
_def("cummax", single_dim=True, reduce=False)
|
| 145 |
+
_def("cummin", single_dim=True, reduce=False)
|
| 146 |
+
_def("cumprod", single_dim=True, reduce=False)
|
| 147 |
+
_def("cumprod_", single_dim=True, reduce=False)
|
| 148 |
+
_def("cumsum", single_dim=True, reduce=False)
|
| 149 |
+
_def("cumsum_", single_dim=True, reduce=False)
|
| 150 |
+
_def("logcumsumexp", single_dim=True, reduce=False)
|
| 151 |
+
_def("renorm", dim_offset=1, single_dim=True, reduce=False)
|
| 152 |
+
_def("softmax", single_dim=True, reduce=False)
|
| 153 |
+
softmax = _wrap(torch.nn.functional.softmax, single_dim=True, reduce=False)
|
| 154 |
+
|
| 155 |
+
# stuff to handle in the future, because they require special
|
| 156 |
+
# binding logic for dims
|
| 157 |
+
# cross
|
| 158 |
+
# diag_embed
|
| 159 |
+
# diagonal
|
| 160 |
+
# diagonal_scatter
|
| 161 |
+
# diff
|
| 162 |
+
# nanquantile
|
| 163 |
+
# quantile
|
| 164 |
+
# roll
|
| 165 |
+
# rot90
|
| 166 |
+
# topk (new dimes on output)
|
| 167 |
+
# should these all be subsumed by inplace indexing?
|
| 168 |
+
# index_add_
|
| 169 |
+
# index_add
|
| 170 |
+
# index_copy
|
| 171 |
+
# index_copy_
|
| 172 |
+
# index_fill
|
| 173 |
+
# index_fill_
|
| 174 |
+
# index_select
|
| 175 |
+
# scatter
|
| 176 |
+
# scatter_
|
| 177 |
+
# scatter_add
|
| 178 |
+
# scatter_add_
|
| 179 |
+
# scatter_reduce
|
tuning-competition-baseline/.venv/lib/python3.11/site-packages/functorch/dim/__pycache__/batch_tensor.cpython-311.pyc
ADDED
|
Binary file (1.28 kB). View file
|
|
|
tuning-competition-baseline/.venv/lib/python3.11/site-packages/functorch/dim/__pycache__/delayed_mul_tensor.cpython-311.pyc
ADDED
|
Binary file (5.6 kB). View file
|
|
|
tuning-competition-baseline/.venv/lib/python3.11/site-packages/functorch/dim/__pycache__/op_properties.cpython-311.pyc
ADDED
|
Binary file (12.1 kB). View file
|
|
|
tuning-competition-baseline/.venv/lib/python3.11/site-packages/functorch/dim/__pycache__/tree_map.cpython-311.pyc
ADDED
|
Binary file (789 Bytes). View file
|
|
|
tuning-competition-baseline/.venv/lib/python3.11/site-packages/functorch/dim/__pycache__/wrap_type.cpython-311.pyc
ADDED
|
Binary file (2.54 kB). View file
|
|
|
tuning-competition-baseline/.venv/lib/python3.11/site-packages/functorch/dim/batch_tensor.py
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Copyright (c) Facebook, Inc. and its affiliates.
|
| 2 |
+
# All rights reserved.
|
| 3 |
+
#
|
| 4 |
+
# This source code is licensed under the BSD-style license found in the
|
| 5 |
+
# LICENSE file in the root directory of this source tree.
|
| 6 |
+
from contextlib import contextmanager
|
| 7 |
+
|
| 8 |
+
from torch._C._functorch import _vmap_add_layers, _vmap_remove_layers
|
| 9 |
+
|
| 10 |
+
_enabled = False
|
| 11 |
+
|
| 12 |
+
|
| 13 |
+
@contextmanager
|
| 14 |
+
def _enable_layers(dims):
|
| 15 |
+
global _enabled
|
| 16 |
+
assert not _enabled
|
| 17 |
+
input = sorted((d._level, d.size) for d in dims if not isinstance(d, int))
|
| 18 |
+
n = len(input)
|
| 19 |
+
try:
|
| 20 |
+
_vmap_add_layers(input)
|
| 21 |
+
_enabled = True
|
| 22 |
+
yield
|
| 23 |
+
finally:
|
| 24 |
+
_enabled = False
|
| 25 |
+
_vmap_remove_layers(n)
|
tuning-competition-baseline/.venv/lib/python3.11/site-packages/mpmath/ctx_base.py
ADDED
|
@@ -0,0 +1,494 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from operator import gt, lt
|
| 2 |
+
|
| 3 |
+
from .libmp.backend import xrange
|
| 4 |
+
|
| 5 |
+
from .functions.functions import SpecialFunctions
|
| 6 |
+
from .functions.rszeta import RSCache
|
| 7 |
+
from .calculus.quadrature import QuadratureMethods
|
| 8 |
+
from .calculus.inverselaplace import LaplaceTransformInversionMethods
|
| 9 |
+
from .calculus.calculus import CalculusMethods
|
| 10 |
+
from .calculus.optimization import OptimizationMethods
|
| 11 |
+
from .calculus.odes import ODEMethods
|
| 12 |
+
from .matrices.matrices import MatrixMethods
|
| 13 |
+
from .matrices.calculus import MatrixCalculusMethods
|
| 14 |
+
from .matrices.linalg import LinearAlgebraMethods
|
| 15 |
+
from .matrices.eigen import Eigen
|
| 16 |
+
from .identification import IdentificationMethods
|
| 17 |
+
from .visualization import VisualizationMethods
|
| 18 |
+
|
| 19 |
+
from . import libmp
|
| 20 |
+
|
| 21 |
+
class Context(object):
|
| 22 |
+
pass
|
| 23 |
+
|
| 24 |
+
class StandardBaseContext(Context,
|
| 25 |
+
SpecialFunctions,
|
| 26 |
+
RSCache,
|
| 27 |
+
QuadratureMethods,
|
| 28 |
+
LaplaceTransformInversionMethods,
|
| 29 |
+
CalculusMethods,
|
| 30 |
+
MatrixMethods,
|
| 31 |
+
MatrixCalculusMethods,
|
| 32 |
+
LinearAlgebraMethods,
|
| 33 |
+
Eigen,
|
| 34 |
+
IdentificationMethods,
|
| 35 |
+
OptimizationMethods,
|
| 36 |
+
ODEMethods,
|
| 37 |
+
VisualizationMethods):
|
| 38 |
+
|
| 39 |
+
NoConvergence = libmp.NoConvergence
|
| 40 |
+
ComplexResult = libmp.ComplexResult
|
| 41 |
+
|
| 42 |
+
def __init__(ctx):
|
| 43 |
+
ctx._aliases = {}
|
| 44 |
+
# Call those that need preinitialization (e.g. for wrappers)
|
| 45 |
+
SpecialFunctions.__init__(ctx)
|
| 46 |
+
RSCache.__init__(ctx)
|
| 47 |
+
QuadratureMethods.__init__(ctx)
|
| 48 |
+
LaplaceTransformInversionMethods.__init__(ctx)
|
| 49 |
+
CalculusMethods.__init__(ctx)
|
| 50 |
+
MatrixMethods.__init__(ctx)
|
| 51 |
+
|
| 52 |
+
def _init_aliases(ctx):
|
| 53 |
+
for alias, value in ctx._aliases.items():
|
| 54 |
+
try:
|
| 55 |
+
setattr(ctx, alias, getattr(ctx, value))
|
| 56 |
+
except AttributeError:
|
| 57 |
+
pass
|
| 58 |
+
|
| 59 |
+
_fixed_precision = False
|
| 60 |
+
|
| 61 |
+
# XXX
|
| 62 |
+
verbose = False
|
| 63 |
+
|
| 64 |
+
def warn(ctx, msg):
|
| 65 |
+
print("Warning:", msg)
|
| 66 |
+
|
| 67 |
+
def bad_domain(ctx, msg):
|
| 68 |
+
raise ValueError(msg)
|
| 69 |
+
|
| 70 |
+
def _re(ctx, x):
|
| 71 |
+
if hasattr(x, "real"):
|
| 72 |
+
return x.real
|
| 73 |
+
return x
|
| 74 |
+
|
| 75 |
+
def _im(ctx, x):
|
| 76 |
+
if hasattr(x, "imag"):
|
| 77 |
+
return x.imag
|
| 78 |
+
return ctx.zero
|
| 79 |
+
|
| 80 |
+
def _as_points(ctx, x):
|
| 81 |
+
return x
|
| 82 |
+
|
| 83 |
+
def fneg(ctx, x, **kwargs):
|
| 84 |
+
return -ctx.convert(x)
|
| 85 |
+
|
| 86 |
+
def fadd(ctx, x, y, **kwargs):
|
| 87 |
+
return ctx.convert(x)+ctx.convert(y)
|
| 88 |
+
|
| 89 |
+
def fsub(ctx, x, y, **kwargs):
|
| 90 |
+
return ctx.convert(x)-ctx.convert(y)
|
| 91 |
+
|
| 92 |
+
def fmul(ctx, x, y, **kwargs):
|
| 93 |
+
return ctx.convert(x)*ctx.convert(y)
|
| 94 |
+
|
| 95 |
+
def fdiv(ctx, x, y, **kwargs):
|
| 96 |
+
return ctx.convert(x)/ctx.convert(y)
|
| 97 |
+
|
| 98 |
+
def fsum(ctx, args, absolute=False, squared=False):
|
| 99 |
+
if absolute:
|
| 100 |
+
if squared:
|
| 101 |
+
return sum((abs(x)**2 for x in args), ctx.zero)
|
| 102 |
+
return sum((abs(x) for x in args), ctx.zero)
|
| 103 |
+
if squared:
|
| 104 |
+
return sum((x**2 for x in args), ctx.zero)
|
| 105 |
+
return sum(args, ctx.zero)
|
| 106 |
+
|
| 107 |
+
def fdot(ctx, xs, ys=None, conjugate=False):
|
| 108 |
+
if ys is not None:
|
| 109 |
+
xs = zip(xs, ys)
|
| 110 |
+
if conjugate:
|
| 111 |
+
cf = ctx.conj
|
| 112 |
+
return sum((x*cf(y) for (x,y) in xs), ctx.zero)
|
| 113 |
+
else:
|
| 114 |
+
return sum((x*y for (x,y) in xs), ctx.zero)
|
| 115 |
+
|
| 116 |
+
def fprod(ctx, args):
|
| 117 |
+
prod = ctx.one
|
| 118 |
+
for arg in args:
|
| 119 |
+
prod *= arg
|
| 120 |
+
return prod
|
| 121 |
+
|
| 122 |
+
def nprint(ctx, x, n=6, **kwargs):
|
| 123 |
+
"""
|
| 124 |
+
Equivalent to ``print(nstr(x, n))``.
|
| 125 |
+
"""
|
| 126 |
+
print(ctx.nstr(x, n, **kwargs))
|
| 127 |
+
|
| 128 |
+
def chop(ctx, x, tol=None):
|
| 129 |
+
"""
|
| 130 |
+
Chops off small real or imaginary parts, or converts
|
| 131 |
+
numbers close to zero to exact zeros. The input can be a
|
| 132 |
+
single number or an iterable::
|
| 133 |
+
|
| 134 |
+
>>> from mpmath import *
|
| 135 |
+
>>> mp.dps = 15; mp.pretty = False
|
| 136 |
+
>>> chop(5+1e-10j, tol=1e-9)
|
| 137 |
+
mpf('5.0')
|
| 138 |
+
>>> nprint(chop([1.0, 1e-20, 3+1e-18j, -4, 2]))
|
| 139 |
+
[1.0, 0.0, 3.0, -4.0, 2.0]
|
| 140 |
+
|
| 141 |
+
The tolerance defaults to ``100*eps``.
|
| 142 |
+
"""
|
| 143 |
+
if tol is None:
|
| 144 |
+
tol = 100*ctx.eps
|
| 145 |
+
try:
|
| 146 |
+
x = ctx.convert(x)
|
| 147 |
+
absx = abs(x)
|
| 148 |
+
if abs(x) < tol:
|
| 149 |
+
return ctx.zero
|
| 150 |
+
if ctx._is_complex_type(x):
|
| 151 |
+
#part_tol = min(tol, absx*tol)
|
| 152 |
+
part_tol = max(tol, absx*tol)
|
| 153 |
+
if abs(x.imag) < part_tol:
|
| 154 |
+
return x.real
|
| 155 |
+
if abs(x.real) < part_tol:
|
| 156 |
+
return ctx.mpc(0, x.imag)
|
| 157 |
+
except TypeError:
|
| 158 |
+
if isinstance(x, ctx.matrix):
|
| 159 |
+
return x.apply(lambda a: ctx.chop(a, tol))
|
| 160 |
+
if hasattr(x, "__iter__"):
|
| 161 |
+
return [ctx.chop(a, tol) for a in x]
|
| 162 |
+
return x
|
| 163 |
+
|
| 164 |
+
def almosteq(ctx, s, t, rel_eps=None, abs_eps=None):
|
| 165 |
+
r"""
|
| 166 |
+
Determine whether the difference between `s` and `t` is smaller
|
| 167 |
+
than a given epsilon, either relatively or absolutely.
|
| 168 |
+
|
| 169 |
+
Both a maximum relative difference and a maximum difference
|
| 170 |
+
('epsilons') may be specified. The absolute difference is
|
| 171 |
+
defined as `|s-t|` and the relative difference is defined
|
| 172 |
+
as `|s-t|/\max(|s|, |t|)`.
|
| 173 |
+
|
| 174 |
+
If only one epsilon is given, both are set to the same value.
|
| 175 |
+
If none is given, both epsilons are set to `2^{-p+m}` where
|
| 176 |
+
`p` is the current working precision and `m` is a small
|
| 177 |
+
integer. The default setting typically allows :func:`~mpmath.almosteq`
|
| 178 |
+
to be used to check for mathematical equality
|
| 179 |
+
in the presence of small rounding errors.
|
| 180 |
+
|
| 181 |
+
**Examples**
|
| 182 |
+
|
| 183 |
+
>>> from mpmath import *
|
| 184 |
+
>>> mp.dps = 15
|
| 185 |
+
>>> almosteq(3.141592653589793, 3.141592653589790)
|
| 186 |
+
True
|
| 187 |
+
>>> almosteq(3.141592653589793, 3.141592653589700)
|
| 188 |
+
False
|
| 189 |
+
>>> almosteq(3.141592653589793, 3.141592653589700, 1e-10)
|
| 190 |
+
True
|
| 191 |
+
>>> almosteq(1e-20, 2e-20)
|
| 192 |
+
True
|
| 193 |
+
>>> almosteq(1e-20, 2e-20, rel_eps=0, abs_eps=0)
|
| 194 |
+
False
|
| 195 |
+
|
| 196 |
+
"""
|
| 197 |
+
t = ctx.convert(t)
|
| 198 |
+
if abs_eps is None and rel_eps is None:
|
| 199 |
+
rel_eps = abs_eps = ctx.ldexp(1, -ctx.prec+4)
|
| 200 |
+
if abs_eps is None:
|
| 201 |
+
abs_eps = rel_eps
|
| 202 |
+
elif rel_eps is None:
|
| 203 |
+
rel_eps = abs_eps
|
| 204 |
+
diff = abs(s-t)
|
| 205 |
+
if diff <= abs_eps:
|
| 206 |
+
return True
|
| 207 |
+
abss = abs(s)
|
| 208 |
+
abst = abs(t)
|
| 209 |
+
if abss < abst:
|
| 210 |
+
err = diff/abst
|
| 211 |
+
else:
|
| 212 |
+
err = diff/abss
|
| 213 |
+
return err <= rel_eps
|
| 214 |
+
|
| 215 |
+
def arange(ctx, *args):
|
| 216 |
+
r"""
|
| 217 |
+
This is a generalized version of Python's :func:`~mpmath.range` function
|
| 218 |
+
that accepts fractional endpoints and step sizes and
|
| 219 |
+
returns a list of ``mpf`` instances. Like :func:`~mpmath.range`,
|
| 220 |
+
:func:`~mpmath.arange` can be called with 1, 2 or 3 arguments:
|
| 221 |
+
|
| 222 |
+
``arange(b)``
|
| 223 |
+
`[0, 1, 2, \ldots, x]`
|
| 224 |
+
``arange(a, b)``
|
| 225 |
+
`[a, a+1, a+2, \ldots, x]`
|
| 226 |
+
``arange(a, b, h)``
|
| 227 |
+
`[a, a+h, a+h, \ldots, x]`
|
| 228 |
+
|
| 229 |
+
where `b-1 \le x < b` (in the third case, `b-h \le x < b`).
|
| 230 |
+
|
| 231 |
+
Like Python's :func:`~mpmath.range`, the endpoint is not included. To
|
| 232 |
+
produce ranges where the endpoint is included, :func:`~mpmath.linspace`
|
| 233 |
+
is more convenient.
|
| 234 |
+
|
| 235 |
+
**Examples**
|
| 236 |
+
|
| 237 |
+
>>> from mpmath import *
|
| 238 |
+
>>> mp.dps = 15; mp.pretty = False
|
| 239 |
+
>>> arange(4)
|
| 240 |
+
[mpf('0.0'), mpf('1.0'), mpf('2.0'), mpf('3.0')]
|
| 241 |
+
>>> arange(1, 2, 0.25)
|
| 242 |
+
[mpf('1.0'), mpf('1.25'), mpf('1.5'), mpf('1.75')]
|
| 243 |
+
>>> arange(1, -1, -0.75)
|
| 244 |
+
[mpf('1.0'), mpf('0.25'), mpf('-0.5')]
|
| 245 |
+
|
| 246 |
+
"""
|
| 247 |
+
if not len(args) <= 3:
|
| 248 |
+
raise TypeError('arange expected at most 3 arguments, got %i'
|
| 249 |
+
% len(args))
|
| 250 |
+
if not len(args) >= 1:
|
| 251 |
+
raise TypeError('arange expected at least 1 argument, got %i'
|
| 252 |
+
% len(args))
|
| 253 |
+
# set default
|
| 254 |
+
a = 0
|
| 255 |
+
dt = 1
|
| 256 |
+
# interpret arguments
|
| 257 |
+
if len(args) == 1:
|
| 258 |
+
b = args[0]
|
| 259 |
+
elif len(args) >= 2:
|
| 260 |
+
a = args[0]
|
| 261 |
+
b = args[1]
|
| 262 |
+
if len(args) == 3:
|
| 263 |
+
dt = args[2]
|
| 264 |
+
a, b, dt = ctx.mpf(a), ctx.mpf(b), ctx.mpf(dt)
|
| 265 |
+
assert a + dt != a, 'dt is too small and would cause an infinite loop'
|
| 266 |
+
# adapt code for sign of dt
|
| 267 |
+
if a > b:
|
| 268 |
+
if dt > 0:
|
| 269 |
+
return []
|
| 270 |
+
op = gt
|
| 271 |
+
else:
|
| 272 |
+
if dt < 0:
|
| 273 |
+
return []
|
| 274 |
+
op = lt
|
| 275 |
+
# create list
|
| 276 |
+
result = []
|
| 277 |
+
i = 0
|
| 278 |
+
t = a
|
| 279 |
+
while 1:
|
| 280 |
+
t = a + dt*i
|
| 281 |
+
i += 1
|
| 282 |
+
if op(t, b):
|
| 283 |
+
result.append(t)
|
| 284 |
+
else:
|
| 285 |
+
break
|
| 286 |
+
return result
|
| 287 |
+
|
| 288 |
+
def linspace(ctx, *args, **kwargs):
|
| 289 |
+
"""
|
| 290 |
+
``linspace(a, b, n)`` returns a list of `n` evenly spaced
|
| 291 |
+
samples from `a` to `b`. The syntax ``linspace(mpi(a,b), n)``
|
| 292 |
+
is also valid.
|
| 293 |
+
|
| 294 |
+
This function is often more convenient than :func:`~mpmath.arange`
|
| 295 |
+
for partitioning an interval into subintervals, since
|
| 296 |
+
the endpoint is included::
|
| 297 |
+
|
| 298 |
+
>>> from mpmath import *
|
| 299 |
+
>>> mp.dps = 15; mp.pretty = False
|
| 300 |
+
>>> linspace(1, 4, 4)
|
| 301 |
+
[mpf('1.0'), mpf('2.0'), mpf('3.0'), mpf('4.0')]
|
| 302 |
+
|
| 303 |
+
You may also provide the keyword argument ``endpoint=False``::
|
| 304 |
+
|
| 305 |
+
>>> linspace(1, 4, 4, endpoint=False)
|
| 306 |
+
[mpf('1.0'), mpf('1.75'), mpf('2.5'), mpf('3.25')]
|
| 307 |
+
|
| 308 |
+
"""
|
| 309 |
+
if len(args) == 3:
|
| 310 |
+
a = ctx.mpf(args[0])
|
| 311 |
+
b = ctx.mpf(args[1])
|
| 312 |
+
n = int(args[2])
|
| 313 |
+
elif len(args) == 2:
|
| 314 |
+
assert hasattr(args[0], '_mpi_')
|
| 315 |
+
a = args[0].a
|
| 316 |
+
b = args[0].b
|
| 317 |
+
n = int(args[1])
|
| 318 |
+
else:
|
| 319 |
+
raise TypeError('linspace expected 2 or 3 arguments, got %i' \
|
| 320 |
+
% len(args))
|
| 321 |
+
if n < 1:
|
| 322 |
+
raise ValueError('n must be greater than 0')
|
| 323 |
+
if not 'endpoint' in kwargs or kwargs['endpoint']:
|
| 324 |
+
if n == 1:
|
| 325 |
+
return [ctx.mpf(a)]
|
| 326 |
+
step = (b - a) / ctx.mpf(n - 1)
|
| 327 |
+
y = [i*step + a for i in xrange(n)]
|
| 328 |
+
y[-1] = b
|
| 329 |
+
else:
|
| 330 |
+
step = (b - a) / ctx.mpf(n)
|
| 331 |
+
y = [i*step + a for i in xrange(n)]
|
| 332 |
+
return y
|
| 333 |
+
|
| 334 |
+
def cos_sin(ctx, z, **kwargs):
|
| 335 |
+
return ctx.cos(z, **kwargs), ctx.sin(z, **kwargs)
|
| 336 |
+
|
| 337 |
+
def cospi_sinpi(ctx, z, **kwargs):
|
| 338 |
+
return ctx.cospi(z, **kwargs), ctx.sinpi(z, **kwargs)
|
| 339 |
+
|
| 340 |
+
def _default_hyper_maxprec(ctx, p):
|
| 341 |
+
return int(1000 * p**0.25 + 4*p)
|
| 342 |
+
|
| 343 |
+
_gcd = staticmethod(libmp.gcd)
|
| 344 |
+
list_primes = staticmethod(libmp.list_primes)
|
| 345 |
+
isprime = staticmethod(libmp.isprime)
|
| 346 |
+
bernfrac = staticmethod(libmp.bernfrac)
|
| 347 |
+
moebius = staticmethod(libmp.moebius)
|
| 348 |
+
_ifac = staticmethod(libmp.ifac)
|
| 349 |
+
_eulernum = staticmethod(libmp.eulernum)
|
| 350 |
+
_stirling1 = staticmethod(libmp.stirling1)
|
| 351 |
+
_stirling2 = staticmethod(libmp.stirling2)
|
| 352 |
+
|
| 353 |
+
def sum_accurately(ctx, terms, check_step=1):
|
| 354 |
+
prec = ctx.prec
|
| 355 |
+
try:
|
| 356 |
+
extraprec = 10
|
| 357 |
+
while 1:
|
| 358 |
+
ctx.prec = prec + extraprec + 5
|
| 359 |
+
max_mag = ctx.ninf
|
| 360 |
+
s = ctx.zero
|
| 361 |
+
k = 0
|
| 362 |
+
for term in terms():
|
| 363 |
+
s += term
|
| 364 |
+
if (not k % check_step) and term:
|
| 365 |
+
term_mag = ctx.mag(term)
|
| 366 |
+
max_mag = max(max_mag, term_mag)
|
| 367 |
+
sum_mag = ctx.mag(s)
|
| 368 |
+
if sum_mag - term_mag > ctx.prec:
|
| 369 |
+
break
|
| 370 |
+
k += 1
|
| 371 |
+
cancellation = max_mag - sum_mag
|
| 372 |
+
if cancellation != cancellation:
|
| 373 |
+
break
|
| 374 |
+
if cancellation < extraprec or ctx._fixed_precision:
|
| 375 |
+
break
|
| 376 |
+
extraprec += min(ctx.prec, cancellation)
|
| 377 |
+
return s
|
| 378 |
+
finally:
|
| 379 |
+
ctx.prec = prec
|
| 380 |
+
|
| 381 |
+
def mul_accurately(ctx, factors, check_step=1):
|
| 382 |
+
prec = ctx.prec
|
| 383 |
+
try:
|
| 384 |
+
extraprec = 10
|
| 385 |
+
while 1:
|
| 386 |
+
ctx.prec = prec + extraprec + 5
|
| 387 |
+
max_mag = ctx.ninf
|
| 388 |
+
one = ctx.one
|
| 389 |
+
s = one
|
| 390 |
+
k = 0
|
| 391 |
+
for factor in factors():
|
| 392 |
+
s *= factor
|
| 393 |
+
term = factor - one
|
| 394 |
+
if (not k % check_step):
|
| 395 |
+
term_mag = ctx.mag(term)
|
| 396 |
+
max_mag = max(max_mag, term_mag)
|
| 397 |
+
sum_mag = ctx.mag(s-one)
|
| 398 |
+
#if sum_mag - term_mag > ctx.prec:
|
| 399 |
+
# break
|
| 400 |
+
if -term_mag > ctx.prec:
|
| 401 |
+
break
|
| 402 |
+
k += 1
|
| 403 |
+
cancellation = max_mag - sum_mag
|
| 404 |
+
if cancellation != cancellation:
|
| 405 |
+
break
|
| 406 |
+
if cancellation < extraprec or ctx._fixed_precision:
|
| 407 |
+
break
|
| 408 |
+
extraprec += min(ctx.prec, cancellation)
|
| 409 |
+
return s
|
| 410 |
+
finally:
|
| 411 |
+
ctx.prec = prec
|
| 412 |
+
|
| 413 |
+
def power(ctx, x, y):
|
| 414 |
+
r"""Converts `x` and `y` to mpmath numbers and evaluates
|
| 415 |
+
`x^y = \exp(y \log(x))`::
|
| 416 |
+
|
| 417 |
+
>>> from mpmath import *
|
| 418 |
+
>>> mp.dps = 30; mp.pretty = True
|
| 419 |
+
>>> power(2, 0.5)
|
| 420 |
+
1.41421356237309504880168872421
|
| 421 |
+
|
| 422 |
+
This shows the leading few digits of a large Mersenne prime
|
| 423 |
+
(performing the exact calculation ``2**43112609-1`` and
|
| 424 |
+
displaying the result in Python would be very slow)::
|
| 425 |
+
|
| 426 |
+
>>> power(2, 43112609)-1
|
| 427 |
+
3.16470269330255923143453723949e+12978188
|
| 428 |
+
"""
|
| 429 |
+
return ctx.convert(x) ** ctx.convert(y)
|
| 430 |
+
|
| 431 |
+
def _zeta_int(ctx, n):
|
| 432 |
+
return ctx.zeta(n)
|
| 433 |
+
|
| 434 |
+
def maxcalls(ctx, f, N):
|
| 435 |
+
"""
|
| 436 |
+
Return a wrapped copy of *f* that raises ``NoConvergence`` when *f*
|
| 437 |
+
has been called more than *N* times::
|
| 438 |
+
|
| 439 |
+
>>> from mpmath import *
|
| 440 |
+
>>> mp.dps = 15
|
| 441 |
+
>>> f = maxcalls(sin, 10)
|
| 442 |
+
>>> print(sum(f(n) for n in range(10)))
|
| 443 |
+
1.95520948210738
|
| 444 |
+
>>> f(10) # doctest: +IGNORE_EXCEPTION_DETAIL
|
| 445 |
+
Traceback (most recent call last):
|
| 446 |
+
...
|
| 447 |
+
NoConvergence: maxcalls: function evaluated 10 times
|
| 448 |
+
|
| 449 |
+
"""
|
| 450 |
+
counter = [0]
|
| 451 |
+
def f_maxcalls_wrapped(*args, **kwargs):
|
| 452 |
+
counter[0] += 1
|
| 453 |
+
if counter[0] > N:
|
| 454 |
+
raise ctx.NoConvergence("maxcalls: function evaluated %i times" % N)
|
| 455 |
+
return f(*args, **kwargs)
|
| 456 |
+
return f_maxcalls_wrapped
|
| 457 |
+
|
| 458 |
+
def memoize(ctx, f):
|
| 459 |
+
"""
|
| 460 |
+
Return a wrapped copy of *f* that caches computed values, i.e.
|
| 461 |
+
a memoized copy of *f*. Values are only reused if the cached precision
|
| 462 |
+
is equal to or higher than the working precision::
|
| 463 |
+
|
| 464 |
+
>>> from mpmath import *
|
| 465 |
+
>>> mp.dps = 15; mp.pretty = True
|
| 466 |
+
>>> f = memoize(maxcalls(sin, 1))
|
| 467 |
+
>>> f(2)
|
| 468 |
+
0.909297426825682
|
| 469 |
+
>>> f(2)
|
| 470 |
+
0.909297426825682
|
| 471 |
+
>>> mp.dps = 25
|
| 472 |
+
>>> f(2) # doctest: +IGNORE_EXCEPTION_DETAIL
|
| 473 |
+
Traceback (most recent call last):
|
| 474 |
+
...
|
| 475 |
+
NoConvergence: maxcalls: function evaluated 1 times
|
| 476 |
+
|
| 477 |
+
"""
|
| 478 |
+
f_cache = {}
|
| 479 |
+
def f_cached(*args, **kwargs):
|
| 480 |
+
if kwargs:
|
| 481 |
+
key = args, tuple(kwargs.items())
|
| 482 |
+
else:
|
| 483 |
+
key = args
|
| 484 |
+
prec = ctx.prec
|
| 485 |
+
if key in f_cache:
|
| 486 |
+
cprec, cvalue = f_cache[key]
|
| 487 |
+
if cprec >= prec:
|
| 488 |
+
return +cvalue
|
| 489 |
+
value = f(*args, **kwargs)
|
| 490 |
+
f_cache[key] = (prec, value)
|
| 491 |
+
return value
|
| 492 |
+
f_cached.__name__ = f.__name__
|
| 493 |
+
f_cached.__doc__ = f.__doc__
|
| 494 |
+
return f_cached
|
tuning-competition-baseline/.venv/lib/python3.11/site-packages/mpmath/ctx_fp.py
ADDED
|
@@ -0,0 +1,253 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from .ctx_base import StandardBaseContext
|
| 2 |
+
|
| 3 |
+
import math
|
| 4 |
+
import cmath
|
| 5 |
+
from . import math2
|
| 6 |
+
|
| 7 |
+
from . import function_docs
|
| 8 |
+
|
| 9 |
+
from .libmp import mpf_bernoulli, to_float, int_types
|
| 10 |
+
from . import libmp
|
| 11 |
+
|
| 12 |
+
class FPContext(StandardBaseContext):
|
| 13 |
+
"""
|
| 14 |
+
Context for fast low-precision arithmetic (53-bit precision, giving at most
|
| 15 |
+
about 15-digit accuracy), using Python's builtin float and complex.
|
| 16 |
+
"""
|
| 17 |
+
|
| 18 |
+
def __init__(ctx):
|
| 19 |
+
StandardBaseContext.__init__(ctx)
|
| 20 |
+
|
| 21 |
+
# Override SpecialFunctions implementation
|
| 22 |
+
ctx.loggamma = math2.loggamma
|
| 23 |
+
ctx._bernoulli_cache = {}
|
| 24 |
+
ctx.pretty = False
|
| 25 |
+
|
| 26 |
+
ctx._init_aliases()
|
| 27 |
+
|
| 28 |
+
_mpq = lambda cls, x: float(x[0])/x[1]
|
| 29 |
+
|
| 30 |
+
NoConvergence = libmp.NoConvergence
|
| 31 |
+
|
| 32 |
+
def _get_prec(ctx): return 53
|
| 33 |
+
def _set_prec(ctx, p): return
|
| 34 |
+
def _get_dps(ctx): return 15
|
| 35 |
+
def _set_dps(ctx, p): return
|
| 36 |
+
|
| 37 |
+
_fixed_precision = True
|
| 38 |
+
|
| 39 |
+
prec = property(_get_prec, _set_prec)
|
| 40 |
+
dps = property(_get_dps, _set_dps)
|
| 41 |
+
|
| 42 |
+
zero = 0.0
|
| 43 |
+
one = 1.0
|
| 44 |
+
eps = math2.EPS
|
| 45 |
+
inf = math2.INF
|
| 46 |
+
ninf = math2.NINF
|
| 47 |
+
nan = math2.NAN
|
| 48 |
+
j = 1j
|
| 49 |
+
|
| 50 |
+
# Called by SpecialFunctions.__init__()
|
| 51 |
+
@classmethod
|
| 52 |
+
def _wrap_specfun(cls, name, f, wrap):
|
| 53 |
+
if wrap:
|
| 54 |
+
def f_wrapped(ctx, *args, **kwargs):
|
| 55 |
+
convert = ctx.convert
|
| 56 |
+
args = [convert(a) for a in args]
|
| 57 |
+
return f(ctx, *args, **kwargs)
|
| 58 |
+
else:
|
| 59 |
+
f_wrapped = f
|
| 60 |
+
f_wrapped.__doc__ = function_docs.__dict__.get(name, f.__doc__)
|
| 61 |
+
setattr(cls, name, f_wrapped)
|
| 62 |
+
|
| 63 |
+
def bernoulli(ctx, n):
|
| 64 |
+
cache = ctx._bernoulli_cache
|
| 65 |
+
if n in cache:
|
| 66 |
+
return cache[n]
|
| 67 |
+
cache[n] = to_float(mpf_bernoulli(n, 53, 'n'), strict=True)
|
| 68 |
+
return cache[n]
|
| 69 |
+
|
| 70 |
+
pi = math2.pi
|
| 71 |
+
e = math2.e
|
| 72 |
+
euler = math2.euler
|
| 73 |
+
sqrt2 = 1.4142135623730950488
|
| 74 |
+
sqrt5 = 2.2360679774997896964
|
| 75 |
+
phi = 1.6180339887498948482
|
| 76 |
+
ln2 = 0.69314718055994530942
|
| 77 |
+
ln10 = 2.302585092994045684
|
| 78 |
+
euler = 0.57721566490153286061
|
| 79 |
+
catalan = 0.91596559417721901505
|
| 80 |
+
khinchin = 2.6854520010653064453
|
| 81 |
+
apery = 1.2020569031595942854
|
| 82 |
+
glaisher = 1.2824271291006226369
|
| 83 |
+
|
| 84 |
+
absmin = absmax = abs
|
| 85 |
+
|
| 86 |
+
def is_special(ctx, x):
|
| 87 |
+
return x - x != 0.0
|
| 88 |
+
|
| 89 |
+
def isnan(ctx, x):
|
| 90 |
+
return x != x
|
| 91 |
+
|
| 92 |
+
def isinf(ctx, x):
|
| 93 |
+
return abs(x) == math2.INF
|
| 94 |
+
|
| 95 |
+
def isnormal(ctx, x):
|
| 96 |
+
if x:
|
| 97 |
+
return x - x == 0.0
|
| 98 |
+
return False
|
| 99 |
+
|
| 100 |
+
def isnpint(ctx, x):
|
| 101 |
+
if type(x) is complex:
|
| 102 |
+
if x.imag:
|
| 103 |
+
return False
|
| 104 |
+
x = x.real
|
| 105 |
+
return x <= 0.0 and round(x) == x
|
| 106 |
+
|
| 107 |
+
mpf = float
|
| 108 |
+
mpc = complex
|
| 109 |
+
|
| 110 |
+
def convert(ctx, x):
|
| 111 |
+
try:
|
| 112 |
+
return float(x)
|
| 113 |
+
except:
|
| 114 |
+
return complex(x)
|
| 115 |
+
|
| 116 |
+
power = staticmethod(math2.pow)
|
| 117 |
+
sqrt = staticmethod(math2.sqrt)
|
| 118 |
+
exp = staticmethod(math2.exp)
|
| 119 |
+
ln = log = staticmethod(math2.log)
|
| 120 |
+
cos = staticmethod(math2.cos)
|
| 121 |
+
sin = staticmethod(math2.sin)
|
| 122 |
+
tan = staticmethod(math2.tan)
|
| 123 |
+
cos_sin = staticmethod(math2.cos_sin)
|
| 124 |
+
acos = staticmethod(math2.acos)
|
| 125 |
+
asin = staticmethod(math2.asin)
|
| 126 |
+
atan = staticmethod(math2.atan)
|
| 127 |
+
cosh = staticmethod(math2.cosh)
|
| 128 |
+
sinh = staticmethod(math2.sinh)
|
| 129 |
+
tanh = staticmethod(math2.tanh)
|
| 130 |
+
gamma = staticmethod(math2.gamma)
|
| 131 |
+
rgamma = staticmethod(math2.rgamma)
|
| 132 |
+
fac = factorial = staticmethod(math2.factorial)
|
| 133 |
+
floor = staticmethod(math2.floor)
|
| 134 |
+
ceil = staticmethod(math2.ceil)
|
| 135 |
+
cospi = staticmethod(math2.cospi)
|
| 136 |
+
sinpi = staticmethod(math2.sinpi)
|
| 137 |
+
cbrt = staticmethod(math2.cbrt)
|
| 138 |
+
_nthroot = staticmethod(math2.nthroot)
|
| 139 |
+
_ei = staticmethod(math2.ei)
|
| 140 |
+
_e1 = staticmethod(math2.e1)
|
| 141 |
+
_zeta = _zeta_int = staticmethod(math2.zeta)
|
| 142 |
+
|
| 143 |
+
# XXX: math2
|
| 144 |
+
def arg(ctx, z):
|
| 145 |
+
z = complex(z)
|
| 146 |
+
return math.atan2(z.imag, z.real)
|
| 147 |
+
|
| 148 |
+
def expj(ctx, x):
|
| 149 |
+
return ctx.exp(ctx.j*x)
|
| 150 |
+
|
| 151 |
+
def expjpi(ctx, x):
|
| 152 |
+
return ctx.exp(ctx.j*ctx.pi*x)
|
| 153 |
+
|
| 154 |
+
ldexp = math.ldexp
|
| 155 |
+
frexp = math.frexp
|
| 156 |
+
|
| 157 |
+
def mag(ctx, z):
|
| 158 |
+
if z:
|
| 159 |
+
return ctx.frexp(abs(z))[1]
|
| 160 |
+
return ctx.ninf
|
| 161 |
+
|
| 162 |
+
def isint(ctx, z):
|
| 163 |
+
if hasattr(z, "imag"): # float/int don't have .real/.imag in py2.5
|
| 164 |
+
if z.imag:
|
| 165 |
+
return False
|
| 166 |
+
z = z.real
|
| 167 |
+
try:
|
| 168 |
+
return z == int(z)
|
| 169 |
+
except:
|
| 170 |
+
return False
|
| 171 |
+
|
| 172 |
+
def nint_distance(ctx, z):
|
| 173 |
+
if hasattr(z, "imag"): # float/int don't have .real/.imag in py2.5
|
| 174 |
+
n = round(z.real)
|
| 175 |
+
else:
|
| 176 |
+
n = round(z)
|
| 177 |
+
if n == z:
|
| 178 |
+
return n, ctx.ninf
|
| 179 |
+
return n, ctx.mag(abs(z-n))
|
| 180 |
+
|
| 181 |
+
def _convert_param(ctx, z):
|
| 182 |
+
if type(z) is tuple:
|
| 183 |
+
p, q = z
|
| 184 |
+
return ctx.mpf(p) / q, 'R'
|
| 185 |
+
if hasattr(z, "imag"): # float/int don't have .real/.imag in py2.5
|
| 186 |
+
intz = int(z.real)
|
| 187 |
+
else:
|
| 188 |
+
intz = int(z)
|
| 189 |
+
if z == intz:
|
| 190 |
+
return intz, 'Z'
|
| 191 |
+
return z, 'R'
|
| 192 |
+
|
| 193 |
+
def _is_real_type(ctx, z):
|
| 194 |
+
return isinstance(z, float) or isinstance(z, int_types)
|
| 195 |
+
|
| 196 |
+
def _is_complex_type(ctx, z):
|
| 197 |
+
return isinstance(z, complex)
|
| 198 |
+
|
| 199 |
+
def hypsum(ctx, p, q, types, coeffs, z, maxterms=6000, **kwargs):
|
| 200 |
+
coeffs = list(coeffs)
|
| 201 |
+
num = range(p)
|
| 202 |
+
den = range(p,p+q)
|
| 203 |
+
tol = ctx.eps
|
| 204 |
+
s = t = 1.0
|
| 205 |
+
k = 0
|
| 206 |
+
while 1:
|
| 207 |
+
for i in num: t *= (coeffs[i]+k)
|
| 208 |
+
for i in den: t /= (coeffs[i]+k)
|
| 209 |
+
k += 1; t /= k; t *= z; s += t
|
| 210 |
+
if abs(t) < tol:
|
| 211 |
+
return s
|
| 212 |
+
if k > maxterms:
|
| 213 |
+
raise ctx.NoConvergence
|
| 214 |
+
|
| 215 |
+
def atan2(ctx, x, y):
|
| 216 |
+
return math.atan2(x, y)
|
| 217 |
+
|
| 218 |
+
def psi(ctx, m, z):
|
| 219 |
+
m = int(m)
|
| 220 |
+
if m == 0:
|
| 221 |
+
return ctx.digamma(z)
|
| 222 |
+
return (-1)**(m+1) * ctx.fac(m) * ctx.zeta(m+1, z)
|
| 223 |
+
|
| 224 |
+
digamma = staticmethod(math2.digamma)
|
| 225 |
+
|
| 226 |
+
def harmonic(ctx, x):
|
| 227 |
+
x = ctx.convert(x)
|
| 228 |
+
if x == 0 or x == 1:
|
| 229 |
+
return x
|
| 230 |
+
return ctx.digamma(x+1) + ctx.euler
|
| 231 |
+
|
| 232 |
+
nstr = str
|
| 233 |
+
|
| 234 |
+
def to_fixed(ctx, x, prec):
|
| 235 |
+
return int(math.ldexp(x, prec))
|
| 236 |
+
|
| 237 |
+
def rand(ctx):
|
| 238 |
+
import random
|
| 239 |
+
return random.random()
|
| 240 |
+
|
| 241 |
+
_erf = staticmethod(math2.erf)
|
| 242 |
+
_erfc = staticmethod(math2.erfc)
|
| 243 |
+
|
| 244 |
+
def sum_accurately(ctx, terms, check_step=1):
|
| 245 |
+
s = ctx.zero
|
| 246 |
+
k = 0
|
| 247 |
+
for term in terms():
|
| 248 |
+
s += term
|
| 249 |
+
if (not k % check_step) and term:
|
| 250 |
+
if abs(term) <= 1e-18*abs(s):
|
| 251 |
+
break
|
| 252 |
+
k += 1
|
| 253 |
+
return s
|
tuning-competition-baseline/.venv/lib/python3.11/site-packages/mpmath/ctx_iv.py
ADDED
|
@@ -0,0 +1,551 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import operator
|
| 2 |
+
|
| 3 |
+
from . import libmp
|
| 4 |
+
|
| 5 |
+
from .libmp.backend import basestring
|
| 6 |
+
|
| 7 |
+
from .libmp import (
|
| 8 |
+
int_types, MPZ_ONE,
|
| 9 |
+
prec_to_dps, dps_to_prec, repr_dps,
|
| 10 |
+
round_floor, round_ceiling,
|
| 11 |
+
fzero, finf, fninf, fnan,
|
| 12 |
+
mpf_le, mpf_neg,
|
| 13 |
+
from_int, from_float, from_str, from_rational,
|
| 14 |
+
mpi_mid, mpi_delta, mpi_str,
|
| 15 |
+
mpi_abs, mpi_pos, mpi_neg, mpi_add, mpi_sub,
|
| 16 |
+
mpi_mul, mpi_div, mpi_pow_int, mpi_pow,
|
| 17 |
+
mpi_from_str,
|
| 18 |
+
mpci_pos, mpci_neg, mpci_add, mpci_sub, mpci_mul, mpci_div, mpci_pow,
|
| 19 |
+
mpci_abs, mpci_pow, mpci_exp, mpci_log,
|
| 20 |
+
ComplexResult,
|
| 21 |
+
mpf_hash, mpc_hash)
|
| 22 |
+
from .matrices.matrices import _matrix
|
| 23 |
+
|
| 24 |
+
mpi_zero = (fzero, fzero)
|
| 25 |
+
|
| 26 |
+
from .ctx_base import StandardBaseContext
|
| 27 |
+
|
| 28 |
+
new = object.__new__
|
| 29 |
+
|
| 30 |
+
def convert_mpf_(x, prec, rounding):
|
| 31 |
+
if hasattr(x, "_mpf_"): return x._mpf_
|
| 32 |
+
if isinstance(x, int_types): return from_int(x, prec, rounding)
|
| 33 |
+
if isinstance(x, float): return from_float(x, prec, rounding)
|
| 34 |
+
if isinstance(x, basestring): return from_str(x, prec, rounding)
|
| 35 |
+
raise NotImplementedError
|
| 36 |
+
|
| 37 |
+
|
| 38 |
+
class ivmpf(object):
|
| 39 |
+
"""
|
| 40 |
+
Interval arithmetic class. Precision is controlled by iv.prec.
|
| 41 |
+
"""
|
| 42 |
+
|
| 43 |
+
def __new__(cls, x=0):
|
| 44 |
+
return cls.ctx.convert(x)
|
| 45 |
+
|
| 46 |
+
def cast(self, cls, f_convert):
|
| 47 |
+
a, b = self._mpi_
|
| 48 |
+
if a == b:
|
| 49 |
+
return cls(f_convert(a))
|
| 50 |
+
raise ValueError
|
| 51 |
+
|
| 52 |
+
def __int__(self):
|
| 53 |
+
return self.cast(int, libmp.to_int)
|
| 54 |
+
|
| 55 |
+
def __float__(self):
|
| 56 |
+
return self.cast(float, libmp.to_float)
|
| 57 |
+
|
| 58 |
+
def __complex__(self):
|
| 59 |
+
return self.cast(complex, libmp.to_float)
|
| 60 |
+
|
| 61 |
+
def __hash__(self):
|
| 62 |
+
a, b = self._mpi_
|
| 63 |
+
if a == b:
|
| 64 |
+
return mpf_hash(a)
|
| 65 |
+
else:
|
| 66 |
+
return hash(self._mpi_)
|
| 67 |
+
|
| 68 |
+
@property
|
| 69 |
+
def real(self): return self
|
| 70 |
+
|
| 71 |
+
@property
|
| 72 |
+
def imag(self): return self.ctx.zero
|
| 73 |
+
|
| 74 |
+
def conjugate(self): return self
|
| 75 |
+
|
| 76 |
+
@property
|
| 77 |
+
def a(self):
|
| 78 |
+
a, b = self._mpi_
|
| 79 |
+
return self.ctx.make_mpf((a, a))
|
| 80 |
+
|
| 81 |
+
@property
|
| 82 |
+
def b(self):
|
| 83 |
+
a, b = self._mpi_
|
| 84 |
+
return self.ctx.make_mpf((b, b))
|
| 85 |
+
|
| 86 |
+
@property
|
| 87 |
+
def mid(self):
|
| 88 |
+
ctx = self.ctx
|
| 89 |
+
v = mpi_mid(self._mpi_, ctx.prec)
|
| 90 |
+
return ctx.make_mpf((v, v))
|
| 91 |
+
|
| 92 |
+
@property
|
| 93 |
+
def delta(self):
|
| 94 |
+
ctx = self.ctx
|
| 95 |
+
v = mpi_delta(self._mpi_, ctx.prec)
|
| 96 |
+
return ctx.make_mpf((v,v))
|
| 97 |
+
|
| 98 |
+
@property
|
| 99 |
+
def _mpci_(self):
|
| 100 |
+
return self._mpi_, mpi_zero
|
| 101 |
+
|
| 102 |
+
def _compare(*args):
|
| 103 |
+
raise TypeError("no ordering relation is defined for intervals")
|
| 104 |
+
|
| 105 |
+
__gt__ = _compare
|
| 106 |
+
__le__ = _compare
|
| 107 |
+
__gt__ = _compare
|
| 108 |
+
__ge__ = _compare
|
| 109 |
+
|
| 110 |
+
def __contains__(self, t):
|
| 111 |
+
t = self.ctx.mpf(t)
|
| 112 |
+
return (self.a <= t.a) and (t.b <= self.b)
|
| 113 |
+
|
| 114 |
+
def __str__(self):
|
| 115 |
+
return mpi_str(self._mpi_, self.ctx.prec)
|
| 116 |
+
|
| 117 |
+
def __repr__(self):
|
| 118 |
+
if self.ctx.pretty:
|
| 119 |
+
return str(self)
|
| 120 |
+
a, b = self._mpi_
|
| 121 |
+
n = repr_dps(self.ctx.prec)
|
| 122 |
+
a = libmp.to_str(a, n)
|
| 123 |
+
b = libmp.to_str(b, n)
|
| 124 |
+
return "mpi(%r, %r)" % (a, b)
|
| 125 |
+
|
| 126 |
+
def _compare(s, t, cmpfun):
|
| 127 |
+
if not hasattr(t, "_mpi_"):
|
| 128 |
+
try:
|
| 129 |
+
t = s.ctx.convert(t)
|
| 130 |
+
except:
|
| 131 |
+
return NotImplemented
|
| 132 |
+
return cmpfun(s._mpi_, t._mpi_)
|
| 133 |
+
|
| 134 |
+
def __eq__(s, t): return s._compare(t, libmp.mpi_eq)
|
| 135 |
+
def __ne__(s, t): return s._compare(t, libmp.mpi_ne)
|
| 136 |
+
def __lt__(s, t): return s._compare(t, libmp.mpi_lt)
|
| 137 |
+
def __le__(s, t): return s._compare(t, libmp.mpi_le)
|
| 138 |
+
def __gt__(s, t): return s._compare(t, libmp.mpi_gt)
|
| 139 |
+
def __ge__(s, t): return s._compare(t, libmp.mpi_ge)
|
| 140 |
+
|
| 141 |
+
def __abs__(self):
|
| 142 |
+
return self.ctx.make_mpf(mpi_abs(self._mpi_, self.ctx.prec))
|
| 143 |
+
def __pos__(self):
|
| 144 |
+
return self.ctx.make_mpf(mpi_pos(self._mpi_, self.ctx.prec))
|
| 145 |
+
def __neg__(self):
|
| 146 |
+
return self.ctx.make_mpf(mpi_neg(self._mpi_, self.ctx.prec))
|
| 147 |
+
|
| 148 |
+
def ae(s, t, rel_eps=None, abs_eps=None):
|
| 149 |
+
return s.ctx.almosteq(s, t, rel_eps, abs_eps)
|
| 150 |
+
|
| 151 |
+
class ivmpc(object):
|
| 152 |
+
|
| 153 |
+
def __new__(cls, re=0, im=0):
|
| 154 |
+
re = cls.ctx.convert(re)
|
| 155 |
+
im = cls.ctx.convert(im)
|
| 156 |
+
y = new(cls)
|
| 157 |
+
y._mpci_ = re._mpi_, im._mpi_
|
| 158 |
+
return y
|
| 159 |
+
|
| 160 |
+
def __hash__(self):
|
| 161 |
+
(a, b), (c,d) = self._mpci_
|
| 162 |
+
if a == b and c == d:
|
| 163 |
+
return mpc_hash((a, c))
|
| 164 |
+
else:
|
| 165 |
+
return hash(self._mpci_)
|
| 166 |
+
|
| 167 |
+
def __repr__(s):
|
| 168 |
+
if s.ctx.pretty:
|
| 169 |
+
return str(s)
|
| 170 |
+
return "iv.mpc(%s, %s)" % (repr(s.real), repr(s.imag))
|
| 171 |
+
|
| 172 |
+
def __str__(s):
|
| 173 |
+
return "(%s + %s*j)" % (str(s.real), str(s.imag))
|
| 174 |
+
|
| 175 |
+
@property
|
| 176 |
+
def a(self):
|
| 177 |
+
(a, b), (c,d) = self._mpci_
|
| 178 |
+
return self.ctx.make_mpf((a, a))
|
| 179 |
+
|
| 180 |
+
@property
|
| 181 |
+
def b(self):
|
| 182 |
+
(a, b), (c,d) = self._mpci_
|
| 183 |
+
return self.ctx.make_mpf((b, b))
|
| 184 |
+
|
| 185 |
+
@property
|
| 186 |
+
def c(self):
|
| 187 |
+
(a, b), (c,d) = self._mpci_
|
| 188 |
+
return self.ctx.make_mpf((c, c))
|
| 189 |
+
|
| 190 |
+
@property
|
| 191 |
+
def d(self):
|
| 192 |
+
(a, b), (c,d) = self._mpci_
|
| 193 |
+
return self.ctx.make_mpf((d, d))
|
| 194 |
+
|
| 195 |
+
@property
|
| 196 |
+
def real(s):
|
| 197 |
+
return s.ctx.make_mpf(s._mpci_[0])
|
| 198 |
+
|
| 199 |
+
@property
|
| 200 |
+
def imag(s):
|
| 201 |
+
return s.ctx.make_mpf(s._mpci_[1])
|
| 202 |
+
|
| 203 |
+
def conjugate(s):
|
| 204 |
+
a, b = s._mpci_
|
| 205 |
+
return s.ctx.make_mpc((a, mpf_neg(b)))
|
| 206 |
+
|
| 207 |
+
def overlap(s, t):
|
| 208 |
+
t = s.ctx.convert(t)
|
| 209 |
+
real_overlap = (s.a <= t.a <= s.b) or (s.a <= t.b <= s.b) or (t.a <= s.a <= t.b) or (t.a <= s.b <= t.b)
|
| 210 |
+
imag_overlap = (s.c <= t.c <= s.d) or (s.c <= t.d <= s.d) or (t.c <= s.c <= t.d) or (t.c <= s.d <= t.d)
|
| 211 |
+
return real_overlap and imag_overlap
|
| 212 |
+
|
| 213 |
+
def __contains__(s, t):
|
| 214 |
+
t = s.ctx.convert(t)
|
| 215 |
+
return t.real in s.real and t.imag in s.imag
|
| 216 |
+
|
| 217 |
+
def _compare(s, t, ne=False):
|
| 218 |
+
if not isinstance(t, s.ctx._types):
|
| 219 |
+
try:
|
| 220 |
+
t = s.ctx.convert(t)
|
| 221 |
+
except:
|
| 222 |
+
return NotImplemented
|
| 223 |
+
if hasattr(t, '_mpi_'):
|
| 224 |
+
tval = t._mpi_, mpi_zero
|
| 225 |
+
elif hasattr(t, '_mpci_'):
|
| 226 |
+
tval = t._mpci_
|
| 227 |
+
if ne:
|
| 228 |
+
return s._mpci_ != tval
|
| 229 |
+
return s._mpci_ == tval
|
| 230 |
+
|
| 231 |
+
def __eq__(s, t): return s._compare(t)
|
| 232 |
+
def __ne__(s, t): return s._compare(t, True)
|
| 233 |
+
|
| 234 |
+
def __lt__(s, t): raise TypeError("complex intervals cannot be ordered")
|
| 235 |
+
__le__ = __gt__ = __ge__ = __lt__
|
| 236 |
+
|
| 237 |
+
def __neg__(s): return s.ctx.make_mpc(mpci_neg(s._mpci_, s.ctx.prec))
|
| 238 |
+
def __pos__(s): return s.ctx.make_mpc(mpci_pos(s._mpci_, s.ctx.prec))
|
| 239 |
+
def __abs__(s): return s.ctx.make_mpf(mpci_abs(s._mpci_, s.ctx.prec))
|
| 240 |
+
|
| 241 |
+
def ae(s, t, rel_eps=None, abs_eps=None):
|
| 242 |
+
return s.ctx.almosteq(s, t, rel_eps, abs_eps)
|
| 243 |
+
|
| 244 |
+
def _binary_op(f_real, f_complex):
|
| 245 |
+
def g_complex(ctx, sval, tval):
|
| 246 |
+
return ctx.make_mpc(f_complex(sval, tval, ctx.prec))
|
| 247 |
+
def g_real(ctx, sval, tval):
|
| 248 |
+
try:
|
| 249 |
+
return ctx.make_mpf(f_real(sval, tval, ctx.prec))
|
| 250 |
+
except ComplexResult:
|
| 251 |
+
sval = (sval, mpi_zero)
|
| 252 |
+
tval = (tval, mpi_zero)
|
| 253 |
+
return g_complex(ctx, sval, tval)
|
| 254 |
+
def lop_real(s, t):
|
| 255 |
+
if isinstance(t, _matrix): return NotImplemented
|
| 256 |
+
ctx = s.ctx
|
| 257 |
+
if not isinstance(t, ctx._types): t = ctx.convert(t)
|
| 258 |
+
if hasattr(t, "_mpi_"): return g_real(ctx, s._mpi_, t._mpi_)
|
| 259 |
+
if hasattr(t, "_mpci_"): return g_complex(ctx, (s._mpi_, mpi_zero), t._mpci_)
|
| 260 |
+
return NotImplemented
|
| 261 |
+
def rop_real(s, t):
|
| 262 |
+
ctx = s.ctx
|
| 263 |
+
if not isinstance(t, ctx._types): t = ctx.convert(t)
|
| 264 |
+
if hasattr(t, "_mpi_"): return g_real(ctx, t._mpi_, s._mpi_)
|
| 265 |
+
if hasattr(t, "_mpci_"): return g_complex(ctx, t._mpci_, (s._mpi_, mpi_zero))
|
| 266 |
+
return NotImplemented
|
| 267 |
+
def lop_complex(s, t):
|
| 268 |
+
if isinstance(t, _matrix): return NotImplemented
|
| 269 |
+
ctx = s.ctx
|
| 270 |
+
if not isinstance(t, s.ctx._types):
|
| 271 |
+
try:
|
| 272 |
+
t = s.ctx.convert(t)
|
| 273 |
+
except (ValueError, TypeError):
|
| 274 |
+
return NotImplemented
|
| 275 |
+
return g_complex(ctx, s._mpci_, t._mpci_)
|
| 276 |
+
def rop_complex(s, t):
|
| 277 |
+
ctx = s.ctx
|
| 278 |
+
if not isinstance(t, s.ctx._types):
|
| 279 |
+
t = s.ctx.convert(t)
|
| 280 |
+
return g_complex(ctx, t._mpci_, s._mpci_)
|
| 281 |
+
return lop_real, rop_real, lop_complex, rop_complex
|
| 282 |
+
|
| 283 |
+
ivmpf.__add__, ivmpf.__radd__, ivmpc.__add__, ivmpc.__radd__ = _binary_op(mpi_add, mpci_add)
|
| 284 |
+
ivmpf.__sub__, ivmpf.__rsub__, ivmpc.__sub__, ivmpc.__rsub__ = _binary_op(mpi_sub, mpci_sub)
|
| 285 |
+
ivmpf.__mul__, ivmpf.__rmul__, ivmpc.__mul__, ivmpc.__rmul__ = _binary_op(mpi_mul, mpci_mul)
|
| 286 |
+
ivmpf.__div__, ivmpf.__rdiv__, ivmpc.__div__, ivmpc.__rdiv__ = _binary_op(mpi_div, mpci_div)
|
| 287 |
+
ivmpf.__pow__, ivmpf.__rpow__, ivmpc.__pow__, ivmpc.__rpow__ = _binary_op(mpi_pow, mpci_pow)
|
| 288 |
+
|
| 289 |
+
ivmpf.__truediv__ = ivmpf.__div__; ivmpf.__rtruediv__ = ivmpf.__rdiv__
|
| 290 |
+
ivmpc.__truediv__ = ivmpc.__div__; ivmpc.__rtruediv__ = ivmpc.__rdiv__
|
| 291 |
+
|
| 292 |
+
class ivmpf_constant(ivmpf):
|
| 293 |
+
def __new__(cls, f):
|
| 294 |
+
self = new(cls)
|
| 295 |
+
self._f = f
|
| 296 |
+
return self
|
| 297 |
+
def _get_mpi_(self):
|
| 298 |
+
prec = self.ctx._prec[0]
|
| 299 |
+
a = self._f(prec, round_floor)
|
| 300 |
+
b = self._f(prec, round_ceiling)
|
| 301 |
+
return a, b
|
| 302 |
+
_mpi_ = property(_get_mpi_)
|
| 303 |
+
|
| 304 |
+
class MPIntervalContext(StandardBaseContext):
|
| 305 |
+
|
| 306 |
+
def __init__(ctx):
|
| 307 |
+
ctx.mpf = type('ivmpf', (ivmpf,), {})
|
| 308 |
+
ctx.mpc = type('ivmpc', (ivmpc,), {})
|
| 309 |
+
ctx._types = (ctx.mpf, ctx.mpc)
|
| 310 |
+
ctx._constant = type('ivmpf_constant', (ivmpf_constant,), {})
|
| 311 |
+
ctx._prec = [53]
|
| 312 |
+
ctx._set_prec(53)
|
| 313 |
+
ctx._constant._ctxdata = ctx.mpf._ctxdata = ctx.mpc._ctxdata = [ctx.mpf, new, ctx._prec]
|
| 314 |
+
ctx._constant.ctx = ctx.mpf.ctx = ctx.mpc.ctx = ctx
|
| 315 |
+
ctx.pretty = False
|
| 316 |
+
StandardBaseContext.__init__(ctx)
|
| 317 |
+
ctx._init_builtins()
|
| 318 |
+
|
| 319 |
+
def _mpi(ctx, a, b=None):
|
| 320 |
+
if b is None:
|
| 321 |
+
return ctx.mpf(a)
|
| 322 |
+
return ctx.mpf((a,b))
|
| 323 |
+
|
| 324 |
+
def _init_builtins(ctx):
|
| 325 |
+
ctx.one = ctx.mpf(1)
|
| 326 |
+
ctx.zero = ctx.mpf(0)
|
| 327 |
+
ctx.inf = ctx.mpf('inf')
|
| 328 |
+
ctx.ninf = -ctx.inf
|
| 329 |
+
ctx.nan = ctx.mpf('nan')
|
| 330 |
+
ctx.j = ctx.mpc(0,1)
|
| 331 |
+
ctx.exp = ctx._wrap_mpi_function(libmp.mpi_exp, libmp.mpci_exp)
|
| 332 |
+
ctx.sqrt = ctx._wrap_mpi_function(libmp.mpi_sqrt)
|
| 333 |
+
ctx.ln = ctx._wrap_mpi_function(libmp.mpi_log, libmp.mpci_log)
|
| 334 |
+
ctx.cos = ctx._wrap_mpi_function(libmp.mpi_cos, libmp.mpci_cos)
|
| 335 |
+
ctx.sin = ctx._wrap_mpi_function(libmp.mpi_sin, libmp.mpci_sin)
|
| 336 |
+
ctx.tan = ctx._wrap_mpi_function(libmp.mpi_tan)
|
| 337 |
+
ctx.gamma = ctx._wrap_mpi_function(libmp.mpi_gamma, libmp.mpci_gamma)
|
| 338 |
+
ctx.loggamma = ctx._wrap_mpi_function(libmp.mpi_loggamma, libmp.mpci_loggamma)
|
| 339 |
+
ctx.rgamma = ctx._wrap_mpi_function(libmp.mpi_rgamma, libmp.mpci_rgamma)
|
| 340 |
+
ctx.factorial = ctx._wrap_mpi_function(libmp.mpi_factorial, libmp.mpci_factorial)
|
| 341 |
+
ctx.fac = ctx.factorial
|
| 342 |
+
|
| 343 |
+
ctx.eps = ctx._constant(lambda prec, rnd: (0, MPZ_ONE, 1-prec, 1))
|
| 344 |
+
ctx.pi = ctx._constant(libmp.mpf_pi)
|
| 345 |
+
ctx.e = ctx._constant(libmp.mpf_e)
|
| 346 |
+
ctx.ln2 = ctx._constant(libmp.mpf_ln2)
|
| 347 |
+
ctx.ln10 = ctx._constant(libmp.mpf_ln10)
|
| 348 |
+
ctx.phi = ctx._constant(libmp.mpf_phi)
|
| 349 |
+
ctx.euler = ctx._constant(libmp.mpf_euler)
|
| 350 |
+
ctx.catalan = ctx._constant(libmp.mpf_catalan)
|
| 351 |
+
ctx.glaisher = ctx._constant(libmp.mpf_glaisher)
|
| 352 |
+
ctx.khinchin = ctx._constant(libmp.mpf_khinchin)
|
| 353 |
+
ctx.twinprime = ctx._constant(libmp.mpf_twinprime)
|
| 354 |
+
|
| 355 |
+
def _wrap_mpi_function(ctx, f_real, f_complex=None):
|
| 356 |
+
def g(x, **kwargs):
|
| 357 |
+
if kwargs:
|
| 358 |
+
prec = kwargs.get('prec', ctx._prec[0])
|
| 359 |
+
else:
|
| 360 |
+
prec = ctx._prec[0]
|
| 361 |
+
x = ctx.convert(x)
|
| 362 |
+
if hasattr(x, "_mpi_"):
|
| 363 |
+
return ctx.make_mpf(f_real(x._mpi_, prec))
|
| 364 |
+
if hasattr(x, "_mpci_"):
|
| 365 |
+
return ctx.make_mpc(f_complex(x._mpci_, prec))
|
| 366 |
+
raise ValueError
|
| 367 |
+
return g
|
| 368 |
+
|
| 369 |
+
@classmethod
|
| 370 |
+
def _wrap_specfun(cls, name, f, wrap):
|
| 371 |
+
if wrap:
|
| 372 |
+
def f_wrapped(ctx, *args, **kwargs):
|
| 373 |
+
convert = ctx.convert
|
| 374 |
+
args = [convert(a) for a in args]
|
| 375 |
+
prec = ctx.prec
|
| 376 |
+
try:
|
| 377 |
+
ctx.prec += 10
|
| 378 |
+
retval = f(ctx, *args, **kwargs)
|
| 379 |
+
finally:
|
| 380 |
+
ctx.prec = prec
|
| 381 |
+
return +retval
|
| 382 |
+
else:
|
| 383 |
+
f_wrapped = f
|
| 384 |
+
setattr(cls, name, f_wrapped)
|
| 385 |
+
|
| 386 |
+
def _set_prec(ctx, n):
|
| 387 |
+
ctx._prec[0] = max(1, int(n))
|
| 388 |
+
ctx._dps = prec_to_dps(n)
|
| 389 |
+
|
| 390 |
+
def _set_dps(ctx, n):
|
| 391 |
+
ctx._prec[0] = dps_to_prec(n)
|
| 392 |
+
ctx._dps = max(1, int(n))
|
| 393 |
+
|
| 394 |
+
prec = property(lambda ctx: ctx._prec[0], _set_prec)
|
| 395 |
+
dps = property(lambda ctx: ctx._dps, _set_dps)
|
| 396 |
+
|
| 397 |
+
def make_mpf(ctx, v):
|
| 398 |
+
a = new(ctx.mpf)
|
| 399 |
+
a._mpi_ = v
|
| 400 |
+
return a
|
| 401 |
+
|
| 402 |
+
def make_mpc(ctx, v):
|
| 403 |
+
a = new(ctx.mpc)
|
| 404 |
+
a._mpci_ = v
|
| 405 |
+
return a
|
| 406 |
+
|
| 407 |
+
def _mpq(ctx, pq):
|
| 408 |
+
p, q = pq
|
| 409 |
+
a = libmp.from_rational(p, q, ctx.prec, round_floor)
|
| 410 |
+
b = libmp.from_rational(p, q, ctx.prec, round_ceiling)
|
| 411 |
+
return ctx.make_mpf((a, b))
|
| 412 |
+
|
| 413 |
+
def convert(ctx, x):
|
| 414 |
+
if isinstance(x, (ctx.mpf, ctx.mpc)):
|
| 415 |
+
return x
|
| 416 |
+
if isinstance(x, ctx._constant):
|
| 417 |
+
return +x
|
| 418 |
+
if isinstance(x, complex) or hasattr(x, "_mpc_"):
|
| 419 |
+
re = ctx.convert(x.real)
|
| 420 |
+
im = ctx.convert(x.imag)
|
| 421 |
+
return ctx.mpc(re,im)
|
| 422 |
+
if isinstance(x, basestring):
|
| 423 |
+
v = mpi_from_str(x, ctx.prec)
|
| 424 |
+
return ctx.make_mpf(v)
|
| 425 |
+
if hasattr(x, "_mpi_"):
|
| 426 |
+
a, b = x._mpi_
|
| 427 |
+
else:
|
| 428 |
+
try:
|
| 429 |
+
a, b = x
|
| 430 |
+
except (TypeError, ValueError):
|
| 431 |
+
a = b = x
|
| 432 |
+
if hasattr(a, "_mpi_"):
|
| 433 |
+
a = a._mpi_[0]
|
| 434 |
+
else:
|
| 435 |
+
a = convert_mpf_(a, ctx.prec, round_floor)
|
| 436 |
+
if hasattr(b, "_mpi_"):
|
| 437 |
+
b = b._mpi_[1]
|
| 438 |
+
else:
|
| 439 |
+
b = convert_mpf_(b, ctx.prec, round_ceiling)
|
| 440 |
+
if a == fnan or b == fnan:
|
| 441 |
+
a = fninf
|
| 442 |
+
b = finf
|
| 443 |
+
assert mpf_le(a, b), "endpoints must be properly ordered"
|
| 444 |
+
return ctx.make_mpf((a, b))
|
| 445 |
+
|
| 446 |
+
def nstr(ctx, x, n=5, **kwargs):
|
| 447 |
+
x = ctx.convert(x)
|
| 448 |
+
if hasattr(x, "_mpi_"):
|
| 449 |
+
return libmp.mpi_to_str(x._mpi_, n, **kwargs)
|
| 450 |
+
if hasattr(x, "_mpci_"):
|
| 451 |
+
re = libmp.mpi_to_str(x._mpci_[0], n, **kwargs)
|
| 452 |
+
im = libmp.mpi_to_str(x._mpci_[1], n, **kwargs)
|
| 453 |
+
return "(%s + %s*j)" % (re, im)
|
| 454 |
+
|
| 455 |
+
def mag(ctx, x):
|
| 456 |
+
x = ctx.convert(x)
|
| 457 |
+
if isinstance(x, ctx.mpc):
|
| 458 |
+
return max(ctx.mag(x.real), ctx.mag(x.imag)) + 1
|
| 459 |
+
a, b = libmp.mpi_abs(x._mpi_)
|
| 460 |
+
sign, man, exp, bc = b
|
| 461 |
+
if man:
|
| 462 |
+
return exp+bc
|
| 463 |
+
if b == fzero:
|
| 464 |
+
return ctx.ninf
|
| 465 |
+
if b == fnan:
|
| 466 |
+
return ctx.nan
|
| 467 |
+
return ctx.inf
|
| 468 |
+
|
| 469 |
+
def isnan(ctx, x):
|
| 470 |
+
return False
|
| 471 |
+
|
| 472 |
+
def isinf(ctx, x):
|
| 473 |
+
return x == ctx.inf
|
| 474 |
+
|
| 475 |
+
def isint(ctx, x):
|
| 476 |
+
x = ctx.convert(x)
|
| 477 |
+
a, b = x._mpi_
|
| 478 |
+
if a == b:
|
| 479 |
+
sign, man, exp, bc = a
|
| 480 |
+
if man:
|
| 481 |
+
return exp >= 0
|
| 482 |
+
return a == fzero
|
| 483 |
+
return None
|
| 484 |
+
|
| 485 |
+
def ldexp(ctx, x, n):
|
| 486 |
+
a, b = ctx.convert(x)._mpi_
|
| 487 |
+
a = libmp.mpf_shift(a, n)
|
| 488 |
+
b = libmp.mpf_shift(b, n)
|
| 489 |
+
return ctx.make_mpf((a,b))
|
| 490 |
+
|
| 491 |
+
def absmin(ctx, x):
|
| 492 |
+
return abs(ctx.convert(x)).a
|
| 493 |
+
|
| 494 |
+
def absmax(ctx, x):
|
| 495 |
+
return abs(ctx.convert(x)).b
|
| 496 |
+
|
| 497 |
+
def atan2(ctx, y, x):
|
| 498 |
+
y = ctx.convert(y)._mpi_
|
| 499 |
+
x = ctx.convert(x)._mpi_
|
| 500 |
+
return ctx.make_mpf(libmp.mpi_atan2(y,x,ctx.prec))
|
| 501 |
+
|
| 502 |
+
def _convert_param(ctx, x):
|
| 503 |
+
if isinstance(x, libmp.int_types):
|
| 504 |
+
return x, 'Z'
|
| 505 |
+
if isinstance(x, tuple):
|
| 506 |
+
p, q = x
|
| 507 |
+
return (ctx.mpf(p) / ctx.mpf(q), 'R')
|
| 508 |
+
x = ctx.convert(x)
|
| 509 |
+
if isinstance(x, ctx.mpf):
|
| 510 |
+
return x, 'R'
|
| 511 |
+
if isinstance(x, ctx.mpc):
|
| 512 |
+
return x, 'C'
|
| 513 |
+
raise ValueError
|
| 514 |
+
|
| 515 |
+
def _is_real_type(ctx, z):
|
| 516 |
+
return isinstance(z, ctx.mpf) or isinstance(z, int_types)
|
| 517 |
+
|
| 518 |
+
def _is_complex_type(ctx, z):
|
| 519 |
+
return isinstance(z, ctx.mpc)
|
| 520 |
+
|
| 521 |
+
def hypsum(ctx, p, q, types, coeffs, z, maxterms=6000, **kwargs):
|
| 522 |
+
coeffs = list(coeffs)
|
| 523 |
+
num = range(p)
|
| 524 |
+
den = range(p,p+q)
|
| 525 |
+
#tol = ctx.eps
|
| 526 |
+
s = t = ctx.one
|
| 527 |
+
k = 0
|
| 528 |
+
while 1:
|
| 529 |
+
for i in num: t *= (coeffs[i]+k)
|
| 530 |
+
for i in den: t /= (coeffs[i]+k)
|
| 531 |
+
k += 1; t /= k; t *= z; s += t
|
| 532 |
+
if t == 0:
|
| 533 |
+
return s
|
| 534 |
+
#if abs(t) < tol:
|
| 535 |
+
# return s
|
| 536 |
+
if k > maxterms:
|
| 537 |
+
raise ctx.NoConvergence
|
| 538 |
+
|
| 539 |
+
|
| 540 |
+
# Register with "numbers" ABC
|
| 541 |
+
# We do not subclass, hence we do not use the @abstractmethod checks. While
|
| 542 |
+
# this is less invasive it may turn out that we do not actually support
|
| 543 |
+
# parts of the expected interfaces. See
|
| 544 |
+
# http://docs.python.org/2/library/numbers.html for list of abstract
|
| 545 |
+
# methods.
|
| 546 |
+
try:
|
| 547 |
+
import numbers
|
| 548 |
+
numbers.Complex.register(ivmpc)
|
| 549 |
+
numbers.Real.register(ivmpf)
|
| 550 |
+
except ImportError:
|
| 551 |
+
pass
|
tuning-competition-baseline/.venv/lib/python3.11/site-packages/mpmath/ctx_mp.py
ADDED
|
@@ -0,0 +1,1339 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"""
|
| 2 |
+
This module defines the mpf, mpc classes, and standard functions for
|
| 3 |
+
operating with them.
|
| 4 |
+
"""
|
| 5 |
+
__docformat__ = 'plaintext'
|
| 6 |
+
|
| 7 |
+
import functools
|
| 8 |
+
|
| 9 |
+
import re
|
| 10 |
+
|
| 11 |
+
from .ctx_base import StandardBaseContext
|
| 12 |
+
|
| 13 |
+
from .libmp.backend import basestring, BACKEND
|
| 14 |
+
|
| 15 |
+
from . import libmp
|
| 16 |
+
|
| 17 |
+
from .libmp import (MPZ, MPZ_ZERO, MPZ_ONE, int_types, repr_dps,
|
| 18 |
+
round_floor, round_ceiling, dps_to_prec, round_nearest, prec_to_dps,
|
| 19 |
+
ComplexResult, to_pickable, from_pickable, normalize,
|
| 20 |
+
from_int, from_float, from_str, to_int, to_float, to_str,
|
| 21 |
+
from_rational, from_man_exp,
|
| 22 |
+
fone, fzero, finf, fninf, fnan,
|
| 23 |
+
mpf_abs, mpf_pos, mpf_neg, mpf_add, mpf_sub, mpf_mul, mpf_mul_int,
|
| 24 |
+
mpf_div, mpf_rdiv_int, mpf_pow_int, mpf_mod,
|
| 25 |
+
mpf_eq, mpf_cmp, mpf_lt, mpf_gt, mpf_le, mpf_ge,
|
| 26 |
+
mpf_hash, mpf_rand,
|
| 27 |
+
mpf_sum,
|
| 28 |
+
bitcount, to_fixed,
|
| 29 |
+
mpc_to_str,
|
| 30 |
+
mpc_to_complex, mpc_hash, mpc_pos, mpc_is_nonzero, mpc_neg, mpc_conjugate,
|
| 31 |
+
mpc_abs, mpc_add, mpc_add_mpf, mpc_sub, mpc_sub_mpf, mpc_mul, mpc_mul_mpf,
|
| 32 |
+
mpc_mul_int, mpc_div, mpc_div_mpf, mpc_pow, mpc_pow_mpf, mpc_pow_int,
|
| 33 |
+
mpc_mpf_div,
|
| 34 |
+
mpf_pow,
|
| 35 |
+
mpf_pi, mpf_degree, mpf_e, mpf_phi, mpf_ln2, mpf_ln10,
|
| 36 |
+
mpf_euler, mpf_catalan, mpf_apery, mpf_khinchin,
|
| 37 |
+
mpf_glaisher, mpf_twinprime, mpf_mertens,
|
| 38 |
+
int_types)
|
| 39 |
+
|
| 40 |
+
from . import function_docs
|
| 41 |
+
from . import rational
|
| 42 |
+
|
| 43 |
+
new = object.__new__
|
| 44 |
+
|
| 45 |
+
get_complex = re.compile(r'^\(?(?P<re>[\+\-]?\d*(\.\d*)?(e[\+\-]?\d+)?)??'
|
| 46 |
+
r'(?P<im>[\+\-]?\d*(\.\d*)?(e[\+\-]?\d+)?j)?\)?$')
|
| 47 |
+
|
| 48 |
+
if BACKEND == 'sage':
|
| 49 |
+
from sage.libs.mpmath.ext_main import Context as BaseMPContext
|
| 50 |
+
# pickle hack
|
| 51 |
+
import sage.libs.mpmath.ext_main as _mpf_module
|
| 52 |
+
else:
|
| 53 |
+
from .ctx_mp_python import PythonMPContext as BaseMPContext
|
| 54 |
+
from . import ctx_mp_python as _mpf_module
|
| 55 |
+
|
| 56 |
+
from .ctx_mp_python import _mpf, _mpc, mpnumeric
|
| 57 |
+
|
| 58 |
+
class MPContext(BaseMPContext, StandardBaseContext):
|
| 59 |
+
"""
|
| 60 |
+
Context for multiprecision arithmetic with a global precision.
|
| 61 |
+
"""
|
| 62 |
+
|
| 63 |
+
def __init__(ctx):
|
| 64 |
+
BaseMPContext.__init__(ctx)
|
| 65 |
+
ctx.trap_complex = False
|
| 66 |
+
ctx.pretty = False
|
| 67 |
+
ctx.types = [ctx.mpf, ctx.mpc, ctx.constant]
|
| 68 |
+
ctx._mpq = rational.mpq
|
| 69 |
+
ctx.default()
|
| 70 |
+
StandardBaseContext.__init__(ctx)
|
| 71 |
+
|
| 72 |
+
ctx.mpq = rational.mpq
|
| 73 |
+
ctx.init_builtins()
|
| 74 |
+
|
| 75 |
+
ctx.hyp_summators = {}
|
| 76 |
+
|
| 77 |
+
ctx._init_aliases()
|
| 78 |
+
|
| 79 |
+
# XXX: automate
|
| 80 |
+
try:
|
| 81 |
+
ctx.bernoulli.im_func.func_doc = function_docs.bernoulli
|
| 82 |
+
ctx.primepi.im_func.func_doc = function_docs.primepi
|
| 83 |
+
ctx.psi.im_func.func_doc = function_docs.psi
|
| 84 |
+
ctx.atan2.im_func.func_doc = function_docs.atan2
|
| 85 |
+
except AttributeError:
|
| 86 |
+
# python 3
|
| 87 |
+
ctx.bernoulli.__func__.func_doc = function_docs.bernoulli
|
| 88 |
+
ctx.primepi.__func__.func_doc = function_docs.primepi
|
| 89 |
+
ctx.psi.__func__.func_doc = function_docs.psi
|
| 90 |
+
ctx.atan2.__func__.func_doc = function_docs.atan2
|
| 91 |
+
|
| 92 |
+
ctx.digamma.func_doc = function_docs.digamma
|
| 93 |
+
ctx.cospi.func_doc = function_docs.cospi
|
| 94 |
+
ctx.sinpi.func_doc = function_docs.sinpi
|
| 95 |
+
|
| 96 |
+
def init_builtins(ctx):
|
| 97 |
+
|
| 98 |
+
mpf = ctx.mpf
|
| 99 |
+
mpc = ctx.mpc
|
| 100 |
+
|
| 101 |
+
# Exact constants
|
| 102 |
+
ctx.one = ctx.make_mpf(fone)
|
| 103 |
+
ctx.zero = ctx.make_mpf(fzero)
|
| 104 |
+
ctx.j = ctx.make_mpc((fzero,fone))
|
| 105 |
+
ctx.inf = ctx.make_mpf(finf)
|
| 106 |
+
ctx.ninf = ctx.make_mpf(fninf)
|
| 107 |
+
ctx.nan = ctx.make_mpf(fnan)
|
| 108 |
+
|
| 109 |
+
eps = ctx.constant(lambda prec, rnd: (0, MPZ_ONE, 1-prec, 1),
|
| 110 |
+
"epsilon of working precision", "eps")
|
| 111 |
+
ctx.eps = eps
|
| 112 |
+
|
| 113 |
+
# Approximate constants
|
| 114 |
+
ctx.pi = ctx.constant(mpf_pi, "pi", "pi")
|
| 115 |
+
ctx.ln2 = ctx.constant(mpf_ln2, "ln(2)", "ln2")
|
| 116 |
+
ctx.ln10 = ctx.constant(mpf_ln10, "ln(10)", "ln10")
|
| 117 |
+
ctx.phi = ctx.constant(mpf_phi, "Golden ratio phi", "phi")
|
| 118 |
+
ctx.e = ctx.constant(mpf_e, "e = exp(1)", "e")
|
| 119 |
+
ctx.euler = ctx.constant(mpf_euler, "Euler's constant", "euler")
|
| 120 |
+
ctx.catalan = ctx.constant(mpf_catalan, "Catalan's constant", "catalan")
|
| 121 |
+
ctx.khinchin = ctx.constant(mpf_khinchin, "Khinchin's constant", "khinchin")
|
| 122 |
+
ctx.glaisher = ctx.constant(mpf_glaisher, "Glaisher's constant", "glaisher")
|
| 123 |
+
ctx.apery = ctx.constant(mpf_apery, "Apery's constant", "apery")
|
| 124 |
+
ctx.degree = ctx.constant(mpf_degree, "1 deg = pi / 180", "degree")
|
| 125 |
+
ctx.twinprime = ctx.constant(mpf_twinprime, "Twin prime constant", "twinprime")
|
| 126 |
+
ctx.mertens = ctx.constant(mpf_mertens, "Mertens' constant", "mertens")
|
| 127 |
+
|
| 128 |
+
# Standard functions
|
| 129 |
+
ctx.sqrt = ctx._wrap_libmp_function(libmp.mpf_sqrt, libmp.mpc_sqrt)
|
| 130 |
+
ctx.cbrt = ctx._wrap_libmp_function(libmp.mpf_cbrt, libmp.mpc_cbrt)
|
| 131 |
+
ctx.ln = ctx._wrap_libmp_function(libmp.mpf_log, libmp.mpc_log)
|
| 132 |
+
ctx.atan = ctx._wrap_libmp_function(libmp.mpf_atan, libmp.mpc_atan)
|
| 133 |
+
ctx.exp = ctx._wrap_libmp_function(libmp.mpf_exp, libmp.mpc_exp)
|
| 134 |
+
ctx.expj = ctx._wrap_libmp_function(libmp.mpf_expj, libmp.mpc_expj)
|
| 135 |
+
ctx.expjpi = ctx._wrap_libmp_function(libmp.mpf_expjpi, libmp.mpc_expjpi)
|
| 136 |
+
ctx.sin = ctx._wrap_libmp_function(libmp.mpf_sin, libmp.mpc_sin)
|
| 137 |
+
ctx.cos = ctx._wrap_libmp_function(libmp.mpf_cos, libmp.mpc_cos)
|
| 138 |
+
ctx.tan = ctx._wrap_libmp_function(libmp.mpf_tan, libmp.mpc_tan)
|
| 139 |
+
ctx.sinh = ctx._wrap_libmp_function(libmp.mpf_sinh, libmp.mpc_sinh)
|
| 140 |
+
ctx.cosh = ctx._wrap_libmp_function(libmp.mpf_cosh, libmp.mpc_cosh)
|
| 141 |
+
ctx.tanh = ctx._wrap_libmp_function(libmp.mpf_tanh, libmp.mpc_tanh)
|
| 142 |
+
ctx.asin = ctx._wrap_libmp_function(libmp.mpf_asin, libmp.mpc_asin)
|
| 143 |
+
ctx.acos = ctx._wrap_libmp_function(libmp.mpf_acos, libmp.mpc_acos)
|
| 144 |
+
ctx.atan = ctx._wrap_libmp_function(libmp.mpf_atan, libmp.mpc_atan)
|
| 145 |
+
ctx.asinh = ctx._wrap_libmp_function(libmp.mpf_asinh, libmp.mpc_asinh)
|
| 146 |
+
ctx.acosh = ctx._wrap_libmp_function(libmp.mpf_acosh, libmp.mpc_acosh)
|
| 147 |
+
ctx.atanh = ctx._wrap_libmp_function(libmp.mpf_atanh, libmp.mpc_atanh)
|
| 148 |
+
ctx.sinpi = ctx._wrap_libmp_function(libmp.mpf_sin_pi, libmp.mpc_sin_pi)
|
| 149 |
+
ctx.cospi = ctx._wrap_libmp_function(libmp.mpf_cos_pi, libmp.mpc_cos_pi)
|
| 150 |
+
ctx.floor = ctx._wrap_libmp_function(libmp.mpf_floor, libmp.mpc_floor)
|
| 151 |
+
ctx.ceil = ctx._wrap_libmp_function(libmp.mpf_ceil, libmp.mpc_ceil)
|
| 152 |
+
ctx.nint = ctx._wrap_libmp_function(libmp.mpf_nint, libmp.mpc_nint)
|
| 153 |
+
ctx.frac = ctx._wrap_libmp_function(libmp.mpf_frac, libmp.mpc_frac)
|
| 154 |
+
ctx.fib = ctx.fibonacci = ctx._wrap_libmp_function(libmp.mpf_fibonacci, libmp.mpc_fibonacci)
|
| 155 |
+
|
| 156 |
+
ctx.gamma = ctx._wrap_libmp_function(libmp.mpf_gamma, libmp.mpc_gamma)
|
| 157 |
+
ctx.rgamma = ctx._wrap_libmp_function(libmp.mpf_rgamma, libmp.mpc_rgamma)
|
| 158 |
+
ctx.loggamma = ctx._wrap_libmp_function(libmp.mpf_loggamma, libmp.mpc_loggamma)
|
| 159 |
+
ctx.fac = ctx.factorial = ctx._wrap_libmp_function(libmp.mpf_factorial, libmp.mpc_factorial)
|
| 160 |
+
|
| 161 |
+
ctx.digamma = ctx._wrap_libmp_function(libmp.mpf_psi0, libmp.mpc_psi0)
|
| 162 |
+
ctx.harmonic = ctx._wrap_libmp_function(libmp.mpf_harmonic, libmp.mpc_harmonic)
|
| 163 |
+
ctx.ei = ctx._wrap_libmp_function(libmp.mpf_ei, libmp.mpc_ei)
|
| 164 |
+
ctx.e1 = ctx._wrap_libmp_function(libmp.mpf_e1, libmp.mpc_e1)
|
| 165 |
+
ctx._ci = ctx._wrap_libmp_function(libmp.mpf_ci, libmp.mpc_ci)
|
| 166 |
+
ctx._si = ctx._wrap_libmp_function(libmp.mpf_si, libmp.mpc_si)
|
| 167 |
+
ctx.ellipk = ctx._wrap_libmp_function(libmp.mpf_ellipk, libmp.mpc_ellipk)
|
| 168 |
+
ctx._ellipe = ctx._wrap_libmp_function(libmp.mpf_ellipe, libmp.mpc_ellipe)
|
| 169 |
+
ctx.agm1 = ctx._wrap_libmp_function(libmp.mpf_agm1, libmp.mpc_agm1)
|
| 170 |
+
ctx._erf = ctx._wrap_libmp_function(libmp.mpf_erf, None)
|
| 171 |
+
ctx._erfc = ctx._wrap_libmp_function(libmp.mpf_erfc, None)
|
| 172 |
+
ctx._zeta = ctx._wrap_libmp_function(libmp.mpf_zeta, libmp.mpc_zeta)
|
| 173 |
+
ctx._altzeta = ctx._wrap_libmp_function(libmp.mpf_altzeta, libmp.mpc_altzeta)
|
| 174 |
+
|
| 175 |
+
# Faster versions
|
| 176 |
+
ctx.sqrt = getattr(ctx, "_sage_sqrt", ctx.sqrt)
|
| 177 |
+
ctx.exp = getattr(ctx, "_sage_exp", ctx.exp)
|
| 178 |
+
ctx.ln = getattr(ctx, "_sage_ln", ctx.ln)
|
| 179 |
+
ctx.cos = getattr(ctx, "_sage_cos", ctx.cos)
|
| 180 |
+
ctx.sin = getattr(ctx, "_sage_sin", ctx.sin)
|
| 181 |
+
|
| 182 |
+
def to_fixed(ctx, x, prec):
|
| 183 |
+
return x.to_fixed(prec)
|
| 184 |
+
|
| 185 |
+
def hypot(ctx, x, y):
|
| 186 |
+
r"""
|
| 187 |
+
Computes the Euclidean norm of the vector `(x, y)`, equal
|
| 188 |
+
to `\sqrt{x^2 + y^2}`. Both `x` and `y` must be real."""
|
| 189 |
+
x = ctx.convert(x)
|
| 190 |
+
y = ctx.convert(y)
|
| 191 |
+
return ctx.make_mpf(libmp.mpf_hypot(x._mpf_, y._mpf_, *ctx._prec_rounding))
|
| 192 |
+
|
| 193 |
+
def _gamma_upper_int(ctx, n, z):
|
| 194 |
+
n = int(ctx._re(n))
|
| 195 |
+
if n == 0:
|
| 196 |
+
return ctx.e1(z)
|
| 197 |
+
if not hasattr(z, '_mpf_'):
|
| 198 |
+
raise NotImplementedError
|
| 199 |
+
prec, rounding = ctx._prec_rounding
|
| 200 |
+
real, imag = libmp.mpf_expint(n, z._mpf_, prec, rounding, gamma=True)
|
| 201 |
+
if imag is None:
|
| 202 |
+
return ctx.make_mpf(real)
|
| 203 |
+
else:
|
| 204 |
+
return ctx.make_mpc((real, imag))
|
| 205 |
+
|
| 206 |
+
def _expint_int(ctx, n, z):
|
| 207 |
+
n = int(n)
|
| 208 |
+
if n == 1:
|
| 209 |
+
return ctx.e1(z)
|
| 210 |
+
if not hasattr(z, '_mpf_'):
|
| 211 |
+
raise NotImplementedError
|
| 212 |
+
prec, rounding = ctx._prec_rounding
|
| 213 |
+
real, imag = libmp.mpf_expint(n, z._mpf_, prec, rounding)
|
| 214 |
+
if imag is None:
|
| 215 |
+
return ctx.make_mpf(real)
|
| 216 |
+
else:
|
| 217 |
+
return ctx.make_mpc((real, imag))
|
| 218 |
+
|
| 219 |
+
def _nthroot(ctx, x, n):
|
| 220 |
+
if hasattr(x, '_mpf_'):
|
| 221 |
+
try:
|
| 222 |
+
return ctx.make_mpf(libmp.mpf_nthroot(x._mpf_, n, *ctx._prec_rounding))
|
| 223 |
+
except ComplexResult:
|
| 224 |
+
if ctx.trap_complex:
|
| 225 |
+
raise
|
| 226 |
+
x = (x._mpf_, libmp.fzero)
|
| 227 |
+
else:
|
| 228 |
+
x = x._mpc_
|
| 229 |
+
return ctx.make_mpc(libmp.mpc_nthroot(x, n, *ctx._prec_rounding))
|
| 230 |
+
|
| 231 |
+
def _besselj(ctx, n, z):
|
| 232 |
+
prec, rounding = ctx._prec_rounding
|
| 233 |
+
if hasattr(z, '_mpf_'):
|
| 234 |
+
return ctx.make_mpf(libmp.mpf_besseljn(n, z._mpf_, prec, rounding))
|
| 235 |
+
elif hasattr(z, '_mpc_'):
|
| 236 |
+
return ctx.make_mpc(libmp.mpc_besseljn(n, z._mpc_, prec, rounding))
|
| 237 |
+
|
| 238 |
+
def _agm(ctx, a, b=1):
|
| 239 |
+
prec, rounding = ctx._prec_rounding
|
| 240 |
+
if hasattr(a, '_mpf_') and hasattr(b, '_mpf_'):
|
| 241 |
+
try:
|
| 242 |
+
v = libmp.mpf_agm(a._mpf_, b._mpf_, prec, rounding)
|
| 243 |
+
return ctx.make_mpf(v)
|
| 244 |
+
except ComplexResult:
|
| 245 |
+
pass
|
| 246 |
+
if hasattr(a, '_mpf_'): a = (a._mpf_, libmp.fzero)
|
| 247 |
+
else: a = a._mpc_
|
| 248 |
+
if hasattr(b, '_mpf_'): b = (b._mpf_, libmp.fzero)
|
| 249 |
+
else: b = b._mpc_
|
| 250 |
+
return ctx.make_mpc(libmp.mpc_agm(a, b, prec, rounding))
|
| 251 |
+
|
| 252 |
+
def bernoulli(ctx, n):
|
| 253 |
+
return ctx.make_mpf(libmp.mpf_bernoulli(int(n), *ctx._prec_rounding))
|
| 254 |
+
|
| 255 |
+
def _zeta_int(ctx, n):
|
| 256 |
+
return ctx.make_mpf(libmp.mpf_zeta_int(int(n), *ctx._prec_rounding))
|
| 257 |
+
|
| 258 |
+
def atan2(ctx, y, x):
|
| 259 |
+
x = ctx.convert(x)
|
| 260 |
+
y = ctx.convert(y)
|
| 261 |
+
return ctx.make_mpf(libmp.mpf_atan2(y._mpf_, x._mpf_, *ctx._prec_rounding))
|
| 262 |
+
|
| 263 |
+
def psi(ctx, m, z):
|
| 264 |
+
z = ctx.convert(z)
|
| 265 |
+
m = int(m)
|
| 266 |
+
if ctx._is_real_type(z):
|
| 267 |
+
return ctx.make_mpf(libmp.mpf_psi(m, z._mpf_, *ctx._prec_rounding))
|
| 268 |
+
else:
|
| 269 |
+
return ctx.make_mpc(libmp.mpc_psi(m, z._mpc_, *ctx._prec_rounding))
|
| 270 |
+
|
| 271 |
+
def cos_sin(ctx, x, **kwargs):
|
| 272 |
+
if type(x) not in ctx.types:
|
| 273 |
+
x = ctx.convert(x)
|
| 274 |
+
prec, rounding = ctx._parse_prec(kwargs)
|
| 275 |
+
if hasattr(x, '_mpf_'):
|
| 276 |
+
c, s = libmp.mpf_cos_sin(x._mpf_, prec, rounding)
|
| 277 |
+
return ctx.make_mpf(c), ctx.make_mpf(s)
|
| 278 |
+
elif hasattr(x, '_mpc_'):
|
| 279 |
+
c, s = libmp.mpc_cos_sin(x._mpc_, prec, rounding)
|
| 280 |
+
return ctx.make_mpc(c), ctx.make_mpc(s)
|
| 281 |
+
else:
|
| 282 |
+
return ctx.cos(x, **kwargs), ctx.sin(x, **kwargs)
|
| 283 |
+
|
| 284 |
+
def cospi_sinpi(ctx, x, **kwargs):
|
| 285 |
+
if type(x) not in ctx.types:
|
| 286 |
+
x = ctx.convert(x)
|
| 287 |
+
prec, rounding = ctx._parse_prec(kwargs)
|
| 288 |
+
if hasattr(x, '_mpf_'):
|
| 289 |
+
c, s = libmp.mpf_cos_sin_pi(x._mpf_, prec, rounding)
|
| 290 |
+
return ctx.make_mpf(c), ctx.make_mpf(s)
|
| 291 |
+
elif hasattr(x, '_mpc_'):
|
| 292 |
+
c, s = libmp.mpc_cos_sin_pi(x._mpc_, prec, rounding)
|
| 293 |
+
return ctx.make_mpc(c), ctx.make_mpc(s)
|
| 294 |
+
else:
|
| 295 |
+
return ctx.cos(x, **kwargs), ctx.sin(x, **kwargs)
|
| 296 |
+
|
| 297 |
+
def clone(ctx):
|
| 298 |
+
"""
|
| 299 |
+
Create a copy of the context, with the same working precision.
|
| 300 |
+
"""
|
| 301 |
+
a = ctx.__class__()
|
| 302 |
+
a.prec = ctx.prec
|
| 303 |
+
return a
|
| 304 |
+
|
| 305 |
+
# Several helper methods
|
| 306 |
+
# TODO: add more of these, make consistent, write docstrings, ...
|
| 307 |
+
|
| 308 |
+
def _is_real_type(ctx, x):
|
| 309 |
+
if hasattr(x, '_mpc_') or type(x) is complex:
|
| 310 |
+
return False
|
| 311 |
+
return True
|
| 312 |
+
|
| 313 |
+
def _is_complex_type(ctx, x):
|
| 314 |
+
if hasattr(x, '_mpc_') or type(x) is complex:
|
| 315 |
+
return True
|
| 316 |
+
return False
|
| 317 |
+
|
| 318 |
+
def isnan(ctx, x):
|
| 319 |
+
"""
|
| 320 |
+
Return *True* if *x* is a NaN (not-a-number), or for a complex
|
| 321 |
+
number, whether either the real or complex part is NaN;
|
| 322 |
+
otherwise return *False*::
|
| 323 |
+
|
| 324 |
+
>>> from mpmath import *
|
| 325 |
+
>>> isnan(3.14)
|
| 326 |
+
False
|
| 327 |
+
>>> isnan(nan)
|
| 328 |
+
True
|
| 329 |
+
>>> isnan(mpc(3.14,2.72))
|
| 330 |
+
False
|
| 331 |
+
>>> isnan(mpc(3.14,nan))
|
| 332 |
+
True
|
| 333 |
+
|
| 334 |
+
"""
|
| 335 |
+
if hasattr(x, "_mpf_"):
|
| 336 |
+
return x._mpf_ == fnan
|
| 337 |
+
if hasattr(x, "_mpc_"):
|
| 338 |
+
return fnan in x._mpc_
|
| 339 |
+
if isinstance(x, int_types) or isinstance(x, rational.mpq):
|
| 340 |
+
return False
|
| 341 |
+
x = ctx.convert(x)
|
| 342 |
+
if hasattr(x, '_mpf_') or hasattr(x, '_mpc_'):
|
| 343 |
+
return ctx.isnan(x)
|
| 344 |
+
raise TypeError("isnan() needs a number as input")
|
| 345 |
+
|
| 346 |
+
def isfinite(ctx, x):
|
| 347 |
+
"""
|
| 348 |
+
Return *True* if *x* is a finite number, i.e. neither
|
| 349 |
+
an infinity or a NaN.
|
| 350 |
+
|
| 351 |
+
>>> from mpmath import *
|
| 352 |
+
>>> isfinite(inf)
|
| 353 |
+
False
|
| 354 |
+
>>> isfinite(-inf)
|
| 355 |
+
False
|
| 356 |
+
>>> isfinite(3)
|
| 357 |
+
True
|
| 358 |
+
>>> isfinite(nan)
|
| 359 |
+
False
|
| 360 |
+
>>> isfinite(3+4j)
|
| 361 |
+
True
|
| 362 |
+
>>> isfinite(mpc(3,inf))
|
| 363 |
+
False
|
| 364 |
+
>>> isfinite(mpc(nan,3))
|
| 365 |
+
False
|
| 366 |
+
|
| 367 |
+
"""
|
| 368 |
+
if ctx.isinf(x) or ctx.isnan(x):
|
| 369 |
+
return False
|
| 370 |
+
return True
|
| 371 |
+
|
| 372 |
+
def isnpint(ctx, x):
|
| 373 |
+
"""
|
| 374 |
+
Determine if *x* is a nonpositive integer.
|
| 375 |
+
"""
|
| 376 |
+
if not x:
|
| 377 |
+
return True
|
| 378 |
+
if hasattr(x, '_mpf_'):
|
| 379 |
+
sign, man, exp, bc = x._mpf_
|
| 380 |
+
return sign and exp >= 0
|
| 381 |
+
if hasattr(x, '_mpc_'):
|
| 382 |
+
return not x.imag and ctx.isnpint(x.real)
|
| 383 |
+
if type(x) in int_types:
|
| 384 |
+
return x <= 0
|
| 385 |
+
if isinstance(x, ctx.mpq):
|
| 386 |
+
p, q = x._mpq_
|
| 387 |
+
if not p:
|
| 388 |
+
return True
|
| 389 |
+
return q == 1 and p <= 0
|
| 390 |
+
return ctx.isnpint(ctx.convert(x))
|
| 391 |
+
|
| 392 |
+
def __str__(ctx):
|
| 393 |
+
lines = ["Mpmath settings:",
|
| 394 |
+
(" mp.prec = %s" % ctx.prec).ljust(30) + "[default: 53]",
|
| 395 |
+
(" mp.dps = %s" % ctx.dps).ljust(30) + "[default: 15]",
|
| 396 |
+
(" mp.trap_complex = %s" % ctx.trap_complex).ljust(30) + "[default: False]",
|
| 397 |
+
]
|
| 398 |
+
return "\n".join(lines)
|
| 399 |
+
|
| 400 |
+
@property
|
| 401 |
+
def _repr_digits(ctx):
|
| 402 |
+
return repr_dps(ctx._prec)
|
| 403 |
+
|
| 404 |
+
@property
|
| 405 |
+
def _str_digits(ctx):
|
| 406 |
+
return ctx._dps
|
| 407 |
+
|
| 408 |
+
def extraprec(ctx, n, normalize_output=False):
|
| 409 |
+
"""
|
| 410 |
+
The block
|
| 411 |
+
|
| 412 |
+
with extraprec(n):
|
| 413 |
+
<code>
|
| 414 |
+
|
| 415 |
+
increases the precision n bits, executes <code>, and then
|
| 416 |
+
restores the precision.
|
| 417 |
+
|
| 418 |
+
extraprec(n)(f) returns a decorated version of the function f
|
| 419 |
+
that increases the working precision by n bits before execution,
|
| 420 |
+
and restores the parent precision afterwards. With
|
| 421 |
+
normalize_output=True, it rounds the return value to the parent
|
| 422 |
+
precision.
|
| 423 |
+
"""
|
| 424 |
+
return PrecisionManager(ctx, lambda p: p + n, None, normalize_output)
|
| 425 |
+
|
| 426 |
+
def extradps(ctx, n, normalize_output=False):
|
| 427 |
+
"""
|
| 428 |
+
This function is analogous to extraprec (see documentation)
|
| 429 |
+
but changes the decimal precision instead of the number of bits.
|
| 430 |
+
"""
|
| 431 |
+
return PrecisionManager(ctx, None, lambda d: d + n, normalize_output)
|
| 432 |
+
|
| 433 |
+
def workprec(ctx, n, normalize_output=False):
|
| 434 |
+
"""
|
| 435 |
+
The block
|
| 436 |
+
|
| 437 |
+
with workprec(n):
|
| 438 |
+
<code>
|
| 439 |
+
|
| 440 |
+
sets the precision to n bits, executes <code>, and then restores
|
| 441 |
+
the precision.
|
| 442 |
+
|
| 443 |
+
workprec(n)(f) returns a decorated version of the function f
|
| 444 |
+
that sets the precision to n bits before execution,
|
| 445 |
+
and restores the precision afterwards. With normalize_output=True,
|
| 446 |
+
it rounds the return value to the parent precision.
|
| 447 |
+
"""
|
| 448 |
+
return PrecisionManager(ctx, lambda p: n, None, normalize_output)
|
| 449 |
+
|
| 450 |
+
def workdps(ctx, n, normalize_output=False):
|
| 451 |
+
"""
|
| 452 |
+
This function is analogous to workprec (see documentation)
|
| 453 |
+
but changes the decimal precision instead of the number of bits.
|
| 454 |
+
"""
|
| 455 |
+
return PrecisionManager(ctx, None, lambda d: n, normalize_output)
|
| 456 |
+
|
| 457 |
+
def autoprec(ctx, f, maxprec=None, catch=(), verbose=False):
|
| 458 |
+
r"""
|
| 459 |
+
Return a wrapped copy of *f* that repeatedly evaluates *f*
|
| 460 |
+
with increasing precision until the result converges to the
|
| 461 |
+
full precision used at the point of the call.
|
| 462 |
+
|
| 463 |
+
This heuristically protects against rounding errors, at the cost of
|
| 464 |
+
roughly a 2x slowdown compared to manually setting the optimal
|
| 465 |
+
precision. This method can, however, easily be fooled if the results
|
| 466 |
+
from *f* depend "discontinuously" on the precision, for instance
|
| 467 |
+
if catastrophic cancellation can occur. Therefore, :func:`~mpmath.autoprec`
|
| 468 |
+
should be used judiciously.
|
| 469 |
+
|
| 470 |
+
**Examples**
|
| 471 |
+
|
| 472 |
+
Many functions are sensitive to perturbations of the input arguments.
|
| 473 |
+
If the arguments are decimal numbers, they may have to be converted
|
| 474 |
+
to binary at a much higher precision. If the amount of required
|
| 475 |
+
extra precision is unknown, :func:`~mpmath.autoprec` is convenient::
|
| 476 |
+
|
| 477 |
+
>>> from mpmath import *
|
| 478 |
+
>>> mp.dps = 15
|
| 479 |
+
>>> mp.pretty = True
|
| 480 |
+
>>> besselj(5, 125 * 10**28) # Exact input
|
| 481 |
+
-8.03284785591801e-17
|
| 482 |
+
>>> besselj(5, '1.25e30') # Bad
|
| 483 |
+
7.12954868316652e-16
|
| 484 |
+
>>> autoprec(besselj)(5, '1.25e30') # Good
|
| 485 |
+
-8.03284785591801e-17
|
| 486 |
+
|
| 487 |
+
The following fails to converge because `\sin(\pi) = 0` whereas all
|
| 488 |
+
finite-precision approximations of `\pi` give nonzero values::
|
| 489 |
+
|
| 490 |
+
>>> autoprec(sin)(pi) # doctest: +IGNORE_EXCEPTION_DETAIL
|
| 491 |
+
Traceback (most recent call last):
|
| 492 |
+
...
|
| 493 |
+
NoConvergence: autoprec: prec increased to 2910 without convergence
|
| 494 |
+
|
| 495 |
+
As the following example shows, :func:`~mpmath.autoprec` can protect against
|
| 496 |
+
cancellation, but is fooled by too severe cancellation::
|
| 497 |
+
|
| 498 |
+
>>> x = 1e-10
|
| 499 |
+
>>> exp(x)-1; expm1(x); autoprec(lambda t: exp(t)-1)(x)
|
| 500 |
+
1.00000008274037e-10
|
| 501 |
+
1.00000000005e-10
|
| 502 |
+
1.00000000005e-10
|
| 503 |
+
>>> x = 1e-50
|
| 504 |
+
>>> exp(x)-1; expm1(x); autoprec(lambda t: exp(t)-1)(x)
|
| 505 |
+
0.0
|
| 506 |
+
1.0e-50
|
| 507 |
+
0.0
|
| 508 |
+
|
| 509 |
+
With *catch*, an exception or list of exceptions to intercept
|
| 510 |
+
may be specified. The raised exception is interpreted
|
| 511 |
+
as signaling insufficient precision. This permits, for example,
|
| 512 |
+
evaluating a function where a too low precision results in a
|
| 513 |
+
division by zero::
|
| 514 |
+
|
| 515 |
+
>>> f = lambda x: 1/(exp(x)-1)
|
| 516 |
+
>>> f(1e-30)
|
| 517 |
+
Traceback (most recent call last):
|
| 518 |
+
...
|
| 519 |
+
ZeroDivisionError
|
| 520 |
+
>>> autoprec(f, catch=ZeroDivisionError)(1e-30)
|
| 521 |
+
1.0e+30
|
| 522 |
+
|
| 523 |
+
|
| 524 |
+
"""
|
| 525 |
+
def f_autoprec_wrapped(*args, **kwargs):
|
| 526 |
+
prec = ctx.prec
|
| 527 |
+
if maxprec is None:
|
| 528 |
+
maxprec2 = ctx._default_hyper_maxprec(prec)
|
| 529 |
+
else:
|
| 530 |
+
maxprec2 = maxprec
|
| 531 |
+
try:
|
| 532 |
+
ctx.prec = prec + 10
|
| 533 |
+
try:
|
| 534 |
+
v1 = f(*args, **kwargs)
|
| 535 |
+
except catch:
|
| 536 |
+
v1 = ctx.nan
|
| 537 |
+
prec2 = prec + 20
|
| 538 |
+
while 1:
|
| 539 |
+
ctx.prec = prec2
|
| 540 |
+
try:
|
| 541 |
+
v2 = f(*args, **kwargs)
|
| 542 |
+
except catch:
|
| 543 |
+
v2 = ctx.nan
|
| 544 |
+
if v1 == v2:
|
| 545 |
+
break
|
| 546 |
+
err = ctx.mag(v2-v1) - ctx.mag(v2)
|
| 547 |
+
if err < (-prec):
|
| 548 |
+
break
|
| 549 |
+
if verbose:
|
| 550 |
+
print("autoprec: target=%s, prec=%s, accuracy=%s" \
|
| 551 |
+
% (prec, prec2, -err))
|
| 552 |
+
v1 = v2
|
| 553 |
+
if prec2 >= maxprec2:
|
| 554 |
+
raise ctx.NoConvergence(\
|
| 555 |
+
"autoprec: prec increased to %i without convergence"\
|
| 556 |
+
% prec2)
|
| 557 |
+
prec2 += int(prec2*2)
|
| 558 |
+
prec2 = min(prec2, maxprec2)
|
| 559 |
+
finally:
|
| 560 |
+
ctx.prec = prec
|
| 561 |
+
return +v2
|
| 562 |
+
return f_autoprec_wrapped
|
| 563 |
+
|
| 564 |
+
def nstr(ctx, x, n=6, **kwargs):
|
| 565 |
+
"""
|
| 566 |
+
Convert an ``mpf`` or ``mpc`` to a decimal string literal with *n*
|
| 567 |
+
significant digits. The small default value for *n* is chosen to
|
| 568 |
+
make this function useful for printing collections of numbers
|
| 569 |
+
(lists, matrices, etc).
|
| 570 |
+
|
| 571 |
+
If *x* is a list or tuple, :func:`~mpmath.nstr` is applied recursively
|
| 572 |
+
to each element. For unrecognized classes, :func:`~mpmath.nstr`
|
| 573 |
+
simply returns ``str(x)``.
|
| 574 |
+
|
| 575 |
+
The companion function :func:`~mpmath.nprint` prints the result
|
| 576 |
+
instead of returning it.
|
| 577 |
+
|
| 578 |
+
The keyword arguments *strip_zeros*, *min_fixed*, *max_fixed*
|
| 579 |
+
and *show_zero_exponent* are forwarded to :func:`~mpmath.libmp.to_str`.
|
| 580 |
+
|
| 581 |
+
The number will be printed in fixed-point format if the position
|
| 582 |
+
of the leading digit is strictly between min_fixed
|
| 583 |
+
(default = min(-dps/3,-5)) and max_fixed (default = dps).
|
| 584 |
+
|
| 585 |
+
To force fixed-point format always, set min_fixed = -inf,
|
| 586 |
+
max_fixed = +inf. To force floating-point format, set
|
| 587 |
+
min_fixed >= max_fixed.
|
| 588 |
+
|
| 589 |
+
>>> from mpmath import *
|
| 590 |
+
>>> nstr([+pi, ldexp(1,-500)])
|
| 591 |
+
'[3.14159, 3.05494e-151]'
|
| 592 |
+
>>> nprint([+pi, ldexp(1,-500)])
|
| 593 |
+
[3.14159, 3.05494e-151]
|
| 594 |
+
>>> nstr(mpf("5e-10"), 5)
|
| 595 |
+
'5.0e-10'
|
| 596 |
+
>>> nstr(mpf("5e-10"), 5, strip_zeros=False)
|
| 597 |
+
'5.0000e-10'
|
| 598 |
+
>>> nstr(mpf("5e-10"), 5, strip_zeros=False, min_fixed=-11)
|
| 599 |
+
'0.00000000050000'
|
| 600 |
+
>>> nstr(mpf(0), 5, show_zero_exponent=True)
|
| 601 |
+
'0.0e+0'
|
| 602 |
+
|
| 603 |
+
"""
|
| 604 |
+
if isinstance(x, list):
|
| 605 |
+
return "[%s]" % (", ".join(ctx.nstr(c, n, **kwargs) for c in x))
|
| 606 |
+
if isinstance(x, tuple):
|
| 607 |
+
return "(%s)" % (", ".join(ctx.nstr(c, n, **kwargs) for c in x))
|
| 608 |
+
if hasattr(x, '_mpf_'):
|
| 609 |
+
return to_str(x._mpf_, n, **kwargs)
|
| 610 |
+
if hasattr(x, '_mpc_'):
|
| 611 |
+
return "(" + mpc_to_str(x._mpc_, n, **kwargs) + ")"
|
| 612 |
+
if isinstance(x, basestring):
|
| 613 |
+
return repr(x)
|
| 614 |
+
if isinstance(x, ctx.matrix):
|
| 615 |
+
return x.__nstr__(n, **kwargs)
|
| 616 |
+
return str(x)
|
| 617 |
+
|
| 618 |
+
def _convert_fallback(ctx, x, strings):
|
| 619 |
+
if strings and isinstance(x, basestring):
|
| 620 |
+
if 'j' in x.lower():
|
| 621 |
+
x = x.lower().replace(' ', '')
|
| 622 |
+
match = get_complex.match(x)
|
| 623 |
+
re = match.group('re')
|
| 624 |
+
if not re:
|
| 625 |
+
re = 0
|
| 626 |
+
im = match.group('im').rstrip('j')
|
| 627 |
+
return ctx.mpc(ctx.convert(re), ctx.convert(im))
|
| 628 |
+
if hasattr(x, "_mpi_"):
|
| 629 |
+
a, b = x._mpi_
|
| 630 |
+
if a == b:
|
| 631 |
+
return ctx.make_mpf(a)
|
| 632 |
+
else:
|
| 633 |
+
raise ValueError("can only create mpf from zero-width interval")
|
| 634 |
+
raise TypeError("cannot create mpf from " + repr(x))
|
| 635 |
+
|
| 636 |
+
def mpmathify(ctx, *args, **kwargs):
|
| 637 |
+
return ctx.convert(*args, **kwargs)
|
| 638 |
+
|
| 639 |
+
def _parse_prec(ctx, kwargs):
|
| 640 |
+
if kwargs:
|
| 641 |
+
if kwargs.get('exact'):
|
| 642 |
+
return 0, 'f'
|
| 643 |
+
prec, rounding = ctx._prec_rounding
|
| 644 |
+
if 'rounding' in kwargs:
|
| 645 |
+
rounding = kwargs['rounding']
|
| 646 |
+
if 'prec' in kwargs:
|
| 647 |
+
prec = kwargs['prec']
|
| 648 |
+
if prec == ctx.inf:
|
| 649 |
+
return 0, 'f'
|
| 650 |
+
else:
|
| 651 |
+
prec = int(prec)
|
| 652 |
+
elif 'dps' in kwargs:
|
| 653 |
+
dps = kwargs['dps']
|
| 654 |
+
if dps == ctx.inf:
|
| 655 |
+
return 0, 'f'
|
| 656 |
+
prec = dps_to_prec(dps)
|
| 657 |
+
return prec, rounding
|
| 658 |
+
return ctx._prec_rounding
|
| 659 |
+
|
| 660 |
+
_exact_overflow_msg = "the exact result does not fit in memory"
|
| 661 |
+
|
| 662 |
+
_hypsum_msg = """hypsum() failed to converge to the requested %i bits of accuracy
|
| 663 |
+
using a working precision of %i bits. Try with a higher maxprec,
|
| 664 |
+
maxterms, or set zeroprec."""
|
| 665 |
+
|
| 666 |
+
def hypsum(ctx, p, q, flags, coeffs, z, accurate_small=True, **kwargs):
|
| 667 |
+
if hasattr(z, "_mpf_"):
|
| 668 |
+
key = p, q, flags, 'R'
|
| 669 |
+
v = z._mpf_
|
| 670 |
+
elif hasattr(z, "_mpc_"):
|
| 671 |
+
key = p, q, flags, 'C'
|
| 672 |
+
v = z._mpc_
|
| 673 |
+
if key not in ctx.hyp_summators:
|
| 674 |
+
ctx.hyp_summators[key] = libmp.make_hyp_summator(key)[1]
|
| 675 |
+
summator = ctx.hyp_summators[key]
|
| 676 |
+
prec = ctx.prec
|
| 677 |
+
maxprec = kwargs.get('maxprec', ctx._default_hyper_maxprec(prec))
|
| 678 |
+
extraprec = 50
|
| 679 |
+
epsshift = 25
|
| 680 |
+
# Jumps in magnitude occur when parameters are close to negative
|
| 681 |
+
# integers. We must ensure that these terms are included in
|
| 682 |
+
# the sum and added accurately
|
| 683 |
+
magnitude_check = {}
|
| 684 |
+
max_total_jump = 0
|
| 685 |
+
for i, c in enumerate(coeffs):
|
| 686 |
+
if flags[i] == 'Z':
|
| 687 |
+
if i >= p and c <= 0:
|
| 688 |
+
ok = False
|
| 689 |
+
for ii, cc in enumerate(coeffs[:p]):
|
| 690 |
+
# Note: c <= cc or c < cc, depending on convention
|
| 691 |
+
if flags[ii] == 'Z' and cc <= 0 and c <= cc:
|
| 692 |
+
ok = True
|
| 693 |
+
if not ok:
|
| 694 |
+
raise ZeroDivisionError("pole in hypergeometric series")
|
| 695 |
+
continue
|
| 696 |
+
n, d = ctx.nint_distance(c)
|
| 697 |
+
n = -int(n)
|
| 698 |
+
d = -d
|
| 699 |
+
if i >= p and n >= 0 and d > 4:
|
| 700 |
+
if n in magnitude_check:
|
| 701 |
+
magnitude_check[n] += d
|
| 702 |
+
else:
|
| 703 |
+
magnitude_check[n] = d
|
| 704 |
+
extraprec = max(extraprec, d - prec + 60)
|
| 705 |
+
max_total_jump += abs(d)
|
| 706 |
+
while 1:
|
| 707 |
+
if extraprec > maxprec:
|
| 708 |
+
raise ValueError(ctx._hypsum_msg % (prec, prec+extraprec))
|
| 709 |
+
wp = prec + extraprec
|
| 710 |
+
if magnitude_check:
|
| 711 |
+
mag_dict = dict((n,None) for n in magnitude_check)
|
| 712 |
+
else:
|
| 713 |
+
mag_dict = {}
|
| 714 |
+
zv, have_complex, magnitude = summator(coeffs, v, prec, wp, \
|
| 715 |
+
epsshift, mag_dict, **kwargs)
|
| 716 |
+
cancel = -magnitude
|
| 717 |
+
jumps_resolved = True
|
| 718 |
+
if extraprec < max_total_jump:
|
| 719 |
+
for n in mag_dict.values():
|
| 720 |
+
if (n is None) or (n < prec):
|
| 721 |
+
jumps_resolved = False
|
| 722 |
+
break
|
| 723 |
+
accurate = (cancel < extraprec-25-5 or not accurate_small)
|
| 724 |
+
if jumps_resolved:
|
| 725 |
+
if accurate:
|
| 726 |
+
break
|
| 727 |
+
# zero?
|
| 728 |
+
zeroprec = kwargs.get('zeroprec')
|
| 729 |
+
if zeroprec is not None:
|
| 730 |
+
if cancel > zeroprec:
|
| 731 |
+
if have_complex:
|
| 732 |
+
return ctx.mpc(0)
|
| 733 |
+
else:
|
| 734 |
+
return ctx.zero
|
| 735 |
+
|
| 736 |
+
# Some near-singularities were not included, so increase
|
| 737 |
+
# precision and repeat until they are
|
| 738 |
+
extraprec *= 2
|
| 739 |
+
# Possible workaround for bad roundoff in fixed-point arithmetic
|
| 740 |
+
epsshift += 5
|
| 741 |
+
extraprec += 5
|
| 742 |
+
|
| 743 |
+
if type(zv) is tuple:
|
| 744 |
+
if have_complex:
|
| 745 |
+
return ctx.make_mpc(zv)
|
| 746 |
+
else:
|
| 747 |
+
return ctx.make_mpf(zv)
|
| 748 |
+
else:
|
| 749 |
+
return zv
|
| 750 |
+
|
| 751 |
+
def ldexp(ctx, x, n):
|
| 752 |
+
r"""
|
| 753 |
+
Computes `x 2^n` efficiently. No rounding is performed.
|
| 754 |
+
The argument `x` must be a real floating-point number (or
|
| 755 |
+
possible to convert into one) and `n` must be a Python ``int``.
|
| 756 |
+
|
| 757 |
+
>>> from mpmath import *
|
| 758 |
+
>>> mp.dps = 15; mp.pretty = False
|
| 759 |
+
>>> ldexp(1, 10)
|
| 760 |
+
mpf('1024.0')
|
| 761 |
+
>>> ldexp(1, -3)
|
| 762 |
+
mpf('0.125')
|
| 763 |
+
|
| 764 |
+
"""
|
| 765 |
+
x = ctx.convert(x)
|
| 766 |
+
return ctx.make_mpf(libmp.mpf_shift(x._mpf_, n))
|
| 767 |
+
|
| 768 |
+
def frexp(ctx, x):
|
| 769 |
+
r"""
|
| 770 |
+
Given a real number `x`, returns `(y, n)` with `y \in [0.5, 1)`,
|
| 771 |
+
`n` a Python integer, and such that `x = y 2^n`. No rounding is
|
| 772 |
+
performed.
|
| 773 |
+
|
| 774 |
+
>>> from mpmath import *
|
| 775 |
+
>>> mp.dps = 15; mp.pretty = False
|
| 776 |
+
>>> frexp(7.5)
|
| 777 |
+
(mpf('0.9375'), 3)
|
| 778 |
+
|
| 779 |
+
"""
|
| 780 |
+
x = ctx.convert(x)
|
| 781 |
+
y, n = libmp.mpf_frexp(x._mpf_)
|
| 782 |
+
return ctx.make_mpf(y), n
|
| 783 |
+
|
| 784 |
+
def fneg(ctx, x, **kwargs):
|
| 785 |
+
"""
|
| 786 |
+
Negates the number *x*, giving a floating-point result, optionally
|
| 787 |
+
using a custom precision and rounding mode.
|
| 788 |
+
|
| 789 |
+
See the documentation of :func:`~mpmath.fadd` for a detailed description
|
| 790 |
+
of how to specify precision and rounding.
|
| 791 |
+
|
| 792 |
+
**Examples**
|
| 793 |
+
|
| 794 |
+
An mpmath number is returned::
|
| 795 |
+
|
| 796 |
+
>>> from mpmath import *
|
| 797 |
+
>>> mp.dps = 15; mp.pretty = False
|
| 798 |
+
>>> fneg(2.5)
|
| 799 |
+
mpf('-2.5')
|
| 800 |
+
>>> fneg(-5+2j)
|
| 801 |
+
mpc(real='5.0', imag='-2.0')
|
| 802 |
+
|
| 803 |
+
Precise control over rounding is possible::
|
| 804 |
+
|
| 805 |
+
>>> x = fadd(2, 1e-100, exact=True)
|
| 806 |
+
>>> fneg(x)
|
| 807 |
+
mpf('-2.0')
|
| 808 |
+
>>> fneg(x, rounding='f')
|
| 809 |
+
mpf('-2.0000000000000004')
|
| 810 |
+
|
| 811 |
+
Negating with and without roundoff::
|
| 812 |
+
|
| 813 |
+
>>> n = 200000000000000000000001
|
| 814 |
+
>>> print(int(-mpf(n)))
|
| 815 |
+
-200000000000000016777216
|
| 816 |
+
>>> print(int(fneg(n)))
|
| 817 |
+
-200000000000000016777216
|
| 818 |
+
>>> print(int(fneg(n, prec=log(n,2)+1)))
|
| 819 |
+
-200000000000000000000001
|
| 820 |
+
>>> print(int(fneg(n, dps=log(n,10)+1)))
|
| 821 |
+
-200000000000000000000001
|
| 822 |
+
>>> print(int(fneg(n, prec=inf)))
|
| 823 |
+
-200000000000000000000001
|
| 824 |
+
>>> print(int(fneg(n, dps=inf)))
|
| 825 |
+
-200000000000000000000001
|
| 826 |
+
>>> print(int(fneg(n, exact=True)))
|
| 827 |
+
-200000000000000000000001
|
| 828 |
+
|
| 829 |
+
"""
|
| 830 |
+
prec, rounding = ctx._parse_prec(kwargs)
|
| 831 |
+
x = ctx.convert(x)
|
| 832 |
+
if hasattr(x, '_mpf_'):
|
| 833 |
+
return ctx.make_mpf(mpf_neg(x._mpf_, prec, rounding))
|
| 834 |
+
if hasattr(x, '_mpc_'):
|
| 835 |
+
return ctx.make_mpc(mpc_neg(x._mpc_, prec, rounding))
|
| 836 |
+
raise ValueError("Arguments need to be mpf or mpc compatible numbers")
|
| 837 |
+
|
| 838 |
+
def fadd(ctx, x, y, **kwargs):
|
| 839 |
+
"""
|
| 840 |
+
Adds the numbers *x* and *y*, giving a floating-point result,
|
| 841 |
+
optionally using a custom precision and rounding mode.
|
| 842 |
+
|
| 843 |
+
The default precision is the working precision of the context.
|
| 844 |
+
You can specify a custom precision in bits by passing the *prec* keyword
|
| 845 |
+
argument, or by providing an equivalent decimal precision with the *dps*
|
| 846 |
+
keyword argument. If the precision is set to ``+inf``, or if the flag
|
| 847 |
+
*exact=True* is passed, an exact addition with no rounding is performed.
|
| 848 |
+
|
| 849 |
+
When the precision is finite, the optional *rounding* keyword argument
|
| 850 |
+
specifies the direction of rounding. Valid options are ``'n'`` for
|
| 851 |
+
nearest (default), ``'f'`` for floor, ``'c'`` for ceiling, ``'d'``
|
| 852 |
+
for down, ``'u'`` for up.
|
| 853 |
+
|
| 854 |
+
**Examples**
|
| 855 |
+
|
| 856 |
+
Using :func:`~mpmath.fadd` with precision and rounding control::
|
| 857 |
+
|
| 858 |
+
>>> from mpmath import *
|
| 859 |
+
>>> mp.dps = 15; mp.pretty = False
|
| 860 |
+
>>> fadd(2, 1e-20)
|
| 861 |
+
mpf('2.0')
|
| 862 |
+
>>> fadd(2, 1e-20, rounding='u')
|
| 863 |
+
mpf('2.0000000000000004')
|
| 864 |
+
>>> nprint(fadd(2, 1e-20, prec=100), 25)
|
| 865 |
+
2.00000000000000000001
|
| 866 |
+
>>> nprint(fadd(2, 1e-20, dps=15), 25)
|
| 867 |
+
2.0
|
| 868 |
+
>>> nprint(fadd(2, 1e-20, dps=25), 25)
|
| 869 |
+
2.00000000000000000001
|
| 870 |
+
>>> nprint(fadd(2, 1e-20, exact=True), 25)
|
| 871 |
+
2.00000000000000000001
|
| 872 |
+
|
| 873 |
+
Exact addition avoids cancellation errors, enforcing familiar laws
|
| 874 |
+
of numbers such as `x+y-x = y`, which don't hold in floating-point
|
| 875 |
+
arithmetic with finite precision::
|
| 876 |
+
|
| 877 |
+
>>> x, y = mpf(2), mpf('1e-1000')
|
| 878 |
+
>>> print(x + y - x)
|
| 879 |
+
0.0
|
| 880 |
+
>>> print(fadd(x, y, prec=inf) - x)
|
| 881 |
+
1.0e-1000
|
| 882 |
+
>>> print(fadd(x, y, exact=True) - x)
|
| 883 |
+
1.0e-1000
|
| 884 |
+
|
| 885 |
+
Exact addition can be inefficient and may be impossible to perform
|
| 886 |
+
with large magnitude differences::
|
| 887 |
+
|
| 888 |
+
>>> fadd(1, '1e-100000000000000000000', prec=inf)
|
| 889 |
+
Traceback (most recent call last):
|
| 890 |
+
...
|
| 891 |
+
OverflowError: the exact result does not fit in memory
|
| 892 |
+
|
| 893 |
+
"""
|
| 894 |
+
prec, rounding = ctx._parse_prec(kwargs)
|
| 895 |
+
x = ctx.convert(x)
|
| 896 |
+
y = ctx.convert(y)
|
| 897 |
+
try:
|
| 898 |
+
if hasattr(x, '_mpf_'):
|
| 899 |
+
if hasattr(y, '_mpf_'):
|
| 900 |
+
return ctx.make_mpf(mpf_add(x._mpf_, y._mpf_, prec, rounding))
|
| 901 |
+
if hasattr(y, '_mpc_'):
|
| 902 |
+
return ctx.make_mpc(mpc_add_mpf(y._mpc_, x._mpf_, prec, rounding))
|
| 903 |
+
if hasattr(x, '_mpc_'):
|
| 904 |
+
if hasattr(y, '_mpf_'):
|
| 905 |
+
return ctx.make_mpc(mpc_add_mpf(x._mpc_, y._mpf_, prec, rounding))
|
| 906 |
+
if hasattr(y, '_mpc_'):
|
| 907 |
+
return ctx.make_mpc(mpc_add(x._mpc_, y._mpc_, prec, rounding))
|
| 908 |
+
except (ValueError, OverflowError):
|
| 909 |
+
raise OverflowError(ctx._exact_overflow_msg)
|
| 910 |
+
raise ValueError("Arguments need to be mpf or mpc compatible numbers")
|
| 911 |
+
|
| 912 |
+
def fsub(ctx, x, y, **kwargs):
|
| 913 |
+
"""
|
| 914 |
+
Subtracts the numbers *x* and *y*, giving a floating-point result,
|
| 915 |
+
optionally using a custom precision and rounding mode.
|
| 916 |
+
|
| 917 |
+
See the documentation of :func:`~mpmath.fadd` for a detailed description
|
| 918 |
+
of how to specify precision and rounding.
|
| 919 |
+
|
| 920 |
+
**Examples**
|
| 921 |
+
|
| 922 |
+
Using :func:`~mpmath.fsub` with precision and rounding control::
|
| 923 |
+
|
| 924 |
+
>>> from mpmath import *
|
| 925 |
+
>>> mp.dps = 15; mp.pretty = False
|
| 926 |
+
>>> fsub(2, 1e-20)
|
| 927 |
+
mpf('2.0')
|
| 928 |
+
>>> fsub(2, 1e-20, rounding='d')
|
| 929 |
+
mpf('1.9999999999999998')
|
| 930 |
+
>>> nprint(fsub(2, 1e-20, prec=100), 25)
|
| 931 |
+
1.99999999999999999999
|
| 932 |
+
>>> nprint(fsub(2, 1e-20, dps=15), 25)
|
| 933 |
+
2.0
|
| 934 |
+
>>> nprint(fsub(2, 1e-20, dps=25), 25)
|
| 935 |
+
1.99999999999999999999
|
| 936 |
+
>>> nprint(fsub(2, 1e-20, exact=True), 25)
|
| 937 |
+
1.99999999999999999999
|
| 938 |
+
|
| 939 |
+
Exact subtraction avoids cancellation errors, enforcing familiar laws
|
| 940 |
+
of numbers such as `x-y+y = x`, which don't hold in floating-point
|
| 941 |
+
arithmetic with finite precision::
|
| 942 |
+
|
| 943 |
+
>>> x, y = mpf(2), mpf('1e1000')
|
| 944 |
+
>>> print(x - y + y)
|
| 945 |
+
0.0
|
| 946 |
+
>>> print(fsub(x, y, prec=inf) + y)
|
| 947 |
+
2.0
|
| 948 |
+
>>> print(fsub(x, y, exact=True) + y)
|
| 949 |
+
2.0
|
| 950 |
+
|
| 951 |
+
Exact addition can be inefficient and may be impossible to perform
|
| 952 |
+
with large magnitude differences::
|
| 953 |
+
|
| 954 |
+
>>> fsub(1, '1e-100000000000000000000', prec=inf)
|
| 955 |
+
Traceback (most recent call last):
|
| 956 |
+
...
|
| 957 |
+
OverflowError: the exact result does not fit in memory
|
| 958 |
+
|
| 959 |
+
"""
|
| 960 |
+
prec, rounding = ctx._parse_prec(kwargs)
|
| 961 |
+
x = ctx.convert(x)
|
| 962 |
+
y = ctx.convert(y)
|
| 963 |
+
try:
|
| 964 |
+
if hasattr(x, '_mpf_'):
|
| 965 |
+
if hasattr(y, '_mpf_'):
|
| 966 |
+
return ctx.make_mpf(mpf_sub(x._mpf_, y._mpf_, prec, rounding))
|
| 967 |
+
if hasattr(y, '_mpc_'):
|
| 968 |
+
return ctx.make_mpc(mpc_sub((x._mpf_, fzero), y._mpc_, prec, rounding))
|
| 969 |
+
if hasattr(x, '_mpc_'):
|
| 970 |
+
if hasattr(y, '_mpf_'):
|
| 971 |
+
return ctx.make_mpc(mpc_sub_mpf(x._mpc_, y._mpf_, prec, rounding))
|
| 972 |
+
if hasattr(y, '_mpc_'):
|
| 973 |
+
return ctx.make_mpc(mpc_sub(x._mpc_, y._mpc_, prec, rounding))
|
| 974 |
+
except (ValueError, OverflowError):
|
| 975 |
+
raise OverflowError(ctx._exact_overflow_msg)
|
| 976 |
+
raise ValueError("Arguments need to be mpf or mpc compatible numbers")
|
| 977 |
+
|
| 978 |
+
def fmul(ctx, x, y, **kwargs):
|
| 979 |
+
"""
|
| 980 |
+
Multiplies the numbers *x* and *y*, giving a floating-point result,
|
| 981 |
+
optionally using a custom precision and rounding mode.
|
| 982 |
+
|
| 983 |
+
See the documentation of :func:`~mpmath.fadd` for a detailed description
|
| 984 |
+
of how to specify precision and rounding.
|
| 985 |
+
|
| 986 |
+
**Examples**
|
| 987 |
+
|
| 988 |
+
The result is an mpmath number::
|
| 989 |
+
|
| 990 |
+
>>> from mpmath import *
|
| 991 |
+
>>> mp.dps = 15; mp.pretty = False
|
| 992 |
+
>>> fmul(2, 5.0)
|
| 993 |
+
mpf('10.0')
|
| 994 |
+
>>> fmul(0.5j, 0.5)
|
| 995 |
+
mpc(real='0.0', imag='0.25')
|
| 996 |
+
|
| 997 |
+
Avoiding roundoff::
|
| 998 |
+
|
| 999 |
+
>>> x, y = 10**10+1, 10**15+1
|
| 1000 |
+
>>> print(x*y)
|
| 1001 |
+
10000000001000010000000001
|
| 1002 |
+
>>> print(mpf(x) * mpf(y))
|
| 1003 |
+
1.0000000001e+25
|
| 1004 |
+
>>> print(int(mpf(x) * mpf(y)))
|
| 1005 |
+
10000000001000011026399232
|
| 1006 |
+
>>> print(int(fmul(x, y)))
|
| 1007 |
+
10000000001000011026399232
|
| 1008 |
+
>>> print(int(fmul(x, y, dps=25)))
|
| 1009 |
+
10000000001000010000000001
|
| 1010 |
+
>>> print(int(fmul(x, y, exact=True)))
|
| 1011 |
+
10000000001000010000000001
|
| 1012 |
+
|
| 1013 |
+
Exact multiplication with complex numbers can be inefficient and may
|
| 1014 |
+
be impossible to perform with large magnitude differences between
|
| 1015 |
+
real and imaginary parts::
|
| 1016 |
+
|
| 1017 |
+
>>> x = 1+2j
|
| 1018 |
+
>>> y = mpc(2, '1e-100000000000000000000')
|
| 1019 |
+
>>> fmul(x, y)
|
| 1020 |
+
mpc(real='2.0', imag='4.0')
|
| 1021 |
+
>>> fmul(x, y, rounding='u')
|
| 1022 |
+
mpc(real='2.0', imag='4.0000000000000009')
|
| 1023 |
+
>>> fmul(x, y, exact=True)
|
| 1024 |
+
Traceback (most recent call last):
|
| 1025 |
+
...
|
| 1026 |
+
OverflowError: the exact result does not fit in memory
|
| 1027 |
+
|
| 1028 |
+
"""
|
| 1029 |
+
prec, rounding = ctx._parse_prec(kwargs)
|
| 1030 |
+
x = ctx.convert(x)
|
| 1031 |
+
y = ctx.convert(y)
|
| 1032 |
+
try:
|
| 1033 |
+
if hasattr(x, '_mpf_'):
|
| 1034 |
+
if hasattr(y, '_mpf_'):
|
| 1035 |
+
return ctx.make_mpf(mpf_mul(x._mpf_, y._mpf_, prec, rounding))
|
| 1036 |
+
if hasattr(y, '_mpc_'):
|
| 1037 |
+
return ctx.make_mpc(mpc_mul_mpf(y._mpc_, x._mpf_, prec, rounding))
|
| 1038 |
+
if hasattr(x, '_mpc_'):
|
| 1039 |
+
if hasattr(y, '_mpf_'):
|
| 1040 |
+
return ctx.make_mpc(mpc_mul_mpf(x._mpc_, y._mpf_, prec, rounding))
|
| 1041 |
+
if hasattr(y, '_mpc_'):
|
| 1042 |
+
return ctx.make_mpc(mpc_mul(x._mpc_, y._mpc_, prec, rounding))
|
| 1043 |
+
except (ValueError, OverflowError):
|
| 1044 |
+
raise OverflowError(ctx._exact_overflow_msg)
|
| 1045 |
+
raise ValueError("Arguments need to be mpf or mpc compatible numbers")
|
| 1046 |
+
|
| 1047 |
+
def fdiv(ctx, x, y, **kwargs):
|
| 1048 |
+
"""
|
| 1049 |
+
Divides the numbers *x* and *y*, giving a floating-point result,
|
| 1050 |
+
optionally using a custom precision and rounding mode.
|
| 1051 |
+
|
| 1052 |
+
See the documentation of :func:`~mpmath.fadd` for a detailed description
|
| 1053 |
+
of how to specify precision and rounding.
|
| 1054 |
+
|
| 1055 |
+
**Examples**
|
| 1056 |
+
|
| 1057 |
+
The result is an mpmath number::
|
| 1058 |
+
|
| 1059 |
+
>>> from mpmath import *
|
| 1060 |
+
>>> mp.dps = 15; mp.pretty = False
|
| 1061 |
+
>>> fdiv(3, 2)
|
| 1062 |
+
mpf('1.5')
|
| 1063 |
+
>>> fdiv(2, 3)
|
| 1064 |
+
mpf('0.66666666666666663')
|
| 1065 |
+
>>> fdiv(2+4j, 0.5)
|
| 1066 |
+
mpc(real='4.0', imag='8.0')
|
| 1067 |
+
|
| 1068 |
+
The rounding direction and precision can be controlled::
|
| 1069 |
+
|
| 1070 |
+
>>> fdiv(2, 3, dps=3) # Should be accurate to at least 3 digits
|
| 1071 |
+
mpf('0.6666259765625')
|
| 1072 |
+
>>> fdiv(2, 3, rounding='d')
|
| 1073 |
+
mpf('0.66666666666666663')
|
| 1074 |
+
>>> fdiv(2, 3, prec=60)
|
| 1075 |
+
mpf('0.66666666666666667')
|
| 1076 |
+
>>> fdiv(2, 3, rounding='u')
|
| 1077 |
+
mpf('0.66666666666666674')
|
| 1078 |
+
|
| 1079 |
+
Checking the error of a division by performing it at higher precision::
|
| 1080 |
+
|
| 1081 |
+
>>> fdiv(2, 3) - fdiv(2, 3, prec=100)
|
| 1082 |
+
mpf('-3.7007434154172148e-17')
|
| 1083 |
+
|
| 1084 |
+
Unlike :func:`~mpmath.fadd`, :func:`~mpmath.fmul`, etc., exact division is not
|
| 1085 |
+
allowed since the quotient of two floating-point numbers generally
|
| 1086 |
+
does not have an exact floating-point representation. (In the
|
| 1087 |
+
future this might be changed to allow the case where the division
|
| 1088 |
+
is actually exact.)
|
| 1089 |
+
|
| 1090 |
+
>>> fdiv(2, 3, exact=True)
|
| 1091 |
+
Traceback (most recent call last):
|
| 1092 |
+
...
|
| 1093 |
+
ValueError: division is not an exact operation
|
| 1094 |
+
|
| 1095 |
+
"""
|
| 1096 |
+
prec, rounding = ctx._parse_prec(kwargs)
|
| 1097 |
+
if not prec:
|
| 1098 |
+
raise ValueError("division is not an exact operation")
|
| 1099 |
+
x = ctx.convert(x)
|
| 1100 |
+
y = ctx.convert(y)
|
| 1101 |
+
if hasattr(x, '_mpf_'):
|
| 1102 |
+
if hasattr(y, '_mpf_'):
|
| 1103 |
+
return ctx.make_mpf(mpf_div(x._mpf_, y._mpf_, prec, rounding))
|
| 1104 |
+
if hasattr(y, '_mpc_'):
|
| 1105 |
+
return ctx.make_mpc(mpc_div((x._mpf_, fzero), y._mpc_, prec, rounding))
|
| 1106 |
+
if hasattr(x, '_mpc_'):
|
| 1107 |
+
if hasattr(y, '_mpf_'):
|
| 1108 |
+
return ctx.make_mpc(mpc_div_mpf(x._mpc_, y._mpf_, prec, rounding))
|
| 1109 |
+
if hasattr(y, '_mpc_'):
|
| 1110 |
+
return ctx.make_mpc(mpc_div(x._mpc_, y._mpc_, prec, rounding))
|
| 1111 |
+
raise ValueError("Arguments need to be mpf or mpc compatible numbers")
|
| 1112 |
+
|
| 1113 |
+
def nint_distance(ctx, x):
|
| 1114 |
+
r"""
|
| 1115 |
+
Return `(n,d)` where `n` is the nearest integer to `x` and `d` is
|
| 1116 |
+
an estimate of `\log_2(|x-n|)`. If `d < 0`, `-d` gives the precision
|
| 1117 |
+
(measured in bits) lost to cancellation when computing `x-n`.
|
| 1118 |
+
|
| 1119 |
+
>>> from mpmath import *
|
| 1120 |
+
>>> n, d = nint_distance(5)
|
| 1121 |
+
>>> print(n); print(d)
|
| 1122 |
+
5
|
| 1123 |
+
-inf
|
| 1124 |
+
>>> n, d = nint_distance(mpf(5))
|
| 1125 |
+
>>> print(n); print(d)
|
| 1126 |
+
5
|
| 1127 |
+
-inf
|
| 1128 |
+
>>> n, d = nint_distance(mpf(5.00000001))
|
| 1129 |
+
>>> print(n); print(d)
|
| 1130 |
+
5
|
| 1131 |
+
-26
|
| 1132 |
+
>>> n, d = nint_distance(mpf(4.99999999))
|
| 1133 |
+
>>> print(n); print(d)
|
| 1134 |
+
5
|
| 1135 |
+
-26
|
| 1136 |
+
>>> n, d = nint_distance(mpc(5,10))
|
| 1137 |
+
>>> print(n); print(d)
|
| 1138 |
+
5
|
| 1139 |
+
4
|
| 1140 |
+
>>> n, d = nint_distance(mpc(5,0.000001))
|
| 1141 |
+
>>> print(n); print(d)
|
| 1142 |
+
5
|
| 1143 |
+
-19
|
| 1144 |
+
|
| 1145 |
+
"""
|
| 1146 |
+
typx = type(x)
|
| 1147 |
+
if typx in int_types:
|
| 1148 |
+
return int(x), ctx.ninf
|
| 1149 |
+
elif typx is rational.mpq:
|
| 1150 |
+
p, q = x._mpq_
|
| 1151 |
+
n, r = divmod(p, q)
|
| 1152 |
+
if 2*r >= q:
|
| 1153 |
+
n += 1
|
| 1154 |
+
elif not r:
|
| 1155 |
+
return n, ctx.ninf
|
| 1156 |
+
# log(p/q-n) = log((p-nq)/q) = log(p-nq) - log(q)
|
| 1157 |
+
d = bitcount(abs(p-n*q)) - bitcount(q)
|
| 1158 |
+
return n, d
|
| 1159 |
+
if hasattr(x, "_mpf_"):
|
| 1160 |
+
re = x._mpf_
|
| 1161 |
+
im_dist = ctx.ninf
|
| 1162 |
+
elif hasattr(x, "_mpc_"):
|
| 1163 |
+
re, im = x._mpc_
|
| 1164 |
+
isign, iman, iexp, ibc = im
|
| 1165 |
+
if iman:
|
| 1166 |
+
im_dist = iexp + ibc
|
| 1167 |
+
elif im == fzero:
|
| 1168 |
+
im_dist = ctx.ninf
|
| 1169 |
+
else:
|
| 1170 |
+
raise ValueError("requires a finite number")
|
| 1171 |
+
else:
|
| 1172 |
+
x = ctx.convert(x)
|
| 1173 |
+
if hasattr(x, "_mpf_") or hasattr(x, "_mpc_"):
|
| 1174 |
+
return ctx.nint_distance(x)
|
| 1175 |
+
else:
|
| 1176 |
+
raise TypeError("requires an mpf/mpc")
|
| 1177 |
+
sign, man, exp, bc = re
|
| 1178 |
+
mag = exp+bc
|
| 1179 |
+
# |x| < 0.5
|
| 1180 |
+
if mag < 0:
|
| 1181 |
+
n = 0
|
| 1182 |
+
re_dist = mag
|
| 1183 |
+
elif man:
|
| 1184 |
+
# exact integer
|
| 1185 |
+
if exp >= 0:
|
| 1186 |
+
n = man << exp
|
| 1187 |
+
re_dist = ctx.ninf
|
| 1188 |
+
# exact half-integer
|
| 1189 |
+
elif exp == -1:
|
| 1190 |
+
n = (man>>1)+1
|
| 1191 |
+
re_dist = 0
|
| 1192 |
+
else:
|
| 1193 |
+
d = (-exp-1)
|
| 1194 |
+
t = man >> d
|
| 1195 |
+
if t & 1:
|
| 1196 |
+
t += 1
|
| 1197 |
+
man = (t<<d) - man
|
| 1198 |
+
else:
|
| 1199 |
+
man -= (t<<d)
|
| 1200 |
+
n = t>>1 # int(t)>>1
|
| 1201 |
+
re_dist = exp+bitcount(man)
|
| 1202 |
+
if sign:
|
| 1203 |
+
n = -n
|
| 1204 |
+
elif re == fzero:
|
| 1205 |
+
re_dist = ctx.ninf
|
| 1206 |
+
n = 0
|
| 1207 |
+
else:
|
| 1208 |
+
raise ValueError("requires a finite number")
|
| 1209 |
+
return n, max(re_dist, im_dist)
|
| 1210 |
+
|
| 1211 |
+
def fprod(ctx, factors):
|
| 1212 |
+
r"""
|
| 1213 |
+
Calculates a product containing a finite number of factors (for
|
| 1214 |
+
infinite products, see :func:`~mpmath.nprod`). The factors will be
|
| 1215 |
+
converted to mpmath numbers.
|
| 1216 |
+
|
| 1217 |
+
>>> from mpmath import *
|
| 1218 |
+
>>> mp.dps = 15; mp.pretty = False
|
| 1219 |
+
>>> fprod([1, 2, 0.5, 7])
|
| 1220 |
+
mpf('7.0')
|
| 1221 |
+
|
| 1222 |
+
"""
|
| 1223 |
+
orig = ctx.prec
|
| 1224 |
+
try:
|
| 1225 |
+
v = ctx.one
|
| 1226 |
+
for p in factors:
|
| 1227 |
+
v *= p
|
| 1228 |
+
finally:
|
| 1229 |
+
ctx.prec = orig
|
| 1230 |
+
return +v
|
| 1231 |
+
|
| 1232 |
+
def rand(ctx):
|
| 1233 |
+
"""
|
| 1234 |
+
Returns an ``mpf`` with value chosen randomly from `[0, 1)`.
|
| 1235 |
+
The number of randomly generated bits in the mantissa is equal
|
| 1236 |
+
to the working precision.
|
| 1237 |
+
"""
|
| 1238 |
+
return ctx.make_mpf(mpf_rand(ctx._prec))
|
| 1239 |
+
|
| 1240 |
+
def fraction(ctx, p, q):
|
| 1241 |
+
"""
|
| 1242 |
+
Given Python integers `(p, q)`, returns a lazy ``mpf`` representing
|
| 1243 |
+
the fraction `p/q`. The value is updated with the precision.
|
| 1244 |
+
|
| 1245 |
+
>>> from mpmath import *
|
| 1246 |
+
>>> mp.dps = 15
|
| 1247 |
+
>>> a = fraction(1,100)
|
| 1248 |
+
>>> b = mpf(1)/100
|
| 1249 |
+
>>> print(a); print(b)
|
| 1250 |
+
0.01
|
| 1251 |
+
0.01
|
| 1252 |
+
>>> mp.dps = 30
|
| 1253 |
+
>>> print(a); print(b) # a will be accurate
|
| 1254 |
+
0.01
|
| 1255 |
+
0.0100000000000000002081668171172
|
| 1256 |
+
>>> mp.dps = 15
|
| 1257 |
+
"""
|
| 1258 |
+
return ctx.constant(lambda prec, rnd: from_rational(p, q, prec, rnd),
|
| 1259 |
+
'%s/%s' % (p, q))
|
| 1260 |
+
|
| 1261 |
+
def absmin(ctx, x):
|
| 1262 |
+
return abs(ctx.convert(x))
|
| 1263 |
+
|
| 1264 |
+
def absmax(ctx, x):
|
| 1265 |
+
return abs(ctx.convert(x))
|
| 1266 |
+
|
| 1267 |
+
def _as_points(ctx, x):
|
| 1268 |
+
# XXX: remove this?
|
| 1269 |
+
if hasattr(x, '_mpi_'):
|
| 1270 |
+
a, b = x._mpi_
|
| 1271 |
+
return [ctx.make_mpf(a), ctx.make_mpf(b)]
|
| 1272 |
+
return x
|
| 1273 |
+
|
| 1274 |
+
'''
|
| 1275 |
+
def _zetasum(ctx, s, a, b):
|
| 1276 |
+
"""
|
| 1277 |
+
Computes sum of k^(-s) for k = a, a+1, ..., b with a, b both small
|
| 1278 |
+
integers.
|
| 1279 |
+
"""
|
| 1280 |
+
a = int(a)
|
| 1281 |
+
b = int(b)
|
| 1282 |
+
s = ctx.convert(s)
|
| 1283 |
+
prec, rounding = ctx._prec_rounding
|
| 1284 |
+
if hasattr(s, '_mpf_'):
|
| 1285 |
+
v = ctx.make_mpf(libmp.mpf_zetasum(s._mpf_, a, b, prec))
|
| 1286 |
+
elif hasattr(s, '_mpc_'):
|
| 1287 |
+
v = ctx.make_mpc(libmp.mpc_zetasum(s._mpc_, a, b, prec))
|
| 1288 |
+
return v
|
| 1289 |
+
'''
|
| 1290 |
+
|
| 1291 |
+
def _zetasum_fast(ctx, s, a, n, derivatives=[0], reflect=False):
|
| 1292 |
+
if not (ctx.isint(a) and hasattr(s, "_mpc_")):
|
| 1293 |
+
raise NotImplementedError
|
| 1294 |
+
a = int(a)
|
| 1295 |
+
prec = ctx._prec
|
| 1296 |
+
xs, ys = libmp.mpc_zetasum(s._mpc_, a, n, derivatives, reflect, prec)
|
| 1297 |
+
xs = [ctx.make_mpc(x) for x in xs]
|
| 1298 |
+
ys = [ctx.make_mpc(y) for y in ys]
|
| 1299 |
+
return xs, ys
|
| 1300 |
+
|
| 1301 |
+
class PrecisionManager:
|
| 1302 |
+
def __init__(self, ctx, precfun, dpsfun, normalize_output=False):
|
| 1303 |
+
self.ctx = ctx
|
| 1304 |
+
self.precfun = precfun
|
| 1305 |
+
self.dpsfun = dpsfun
|
| 1306 |
+
self.normalize_output = normalize_output
|
| 1307 |
+
def __call__(self, f):
|
| 1308 |
+
@functools.wraps(f)
|
| 1309 |
+
def g(*args, **kwargs):
|
| 1310 |
+
orig = self.ctx.prec
|
| 1311 |
+
try:
|
| 1312 |
+
if self.precfun:
|
| 1313 |
+
self.ctx.prec = self.precfun(self.ctx.prec)
|
| 1314 |
+
else:
|
| 1315 |
+
self.ctx.dps = self.dpsfun(self.ctx.dps)
|
| 1316 |
+
if self.normalize_output:
|
| 1317 |
+
v = f(*args, **kwargs)
|
| 1318 |
+
if type(v) is tuple:
|
| 1319 |
+
return tuple([+a for a in v])
|
| 1320 |
+
return +v
|
| 1321 |
+
else:
|
| 1322 |
+
return f(*args, **kwargs)
|
| 1323 |
+
finally:
|
| 1324 |
+
self.ctx.prec = orig
|
| 1325 |
+
return g
|
| 1326 |
+
def __enter__(self):
|
| 1327 |
+
self.origp = self.ctx.prec
|
| 1328 |
+
if self.precfun:
|
| 1329 |
+
self.ctx.prec = self.precfun(self.ctx.prec)
|
| 1330 |
+
else:
|
| 1331 |
+
self.ctx.dps = self.dpsfun(self.ctx.dps)
|
| 1332 |
+
def __exit__(self, exc_type, exc_val, exc_tb):
|
| 1333 |
+
self.ctx.prec = self.origp
|
| 1334 |
+
return False
|
| 1335 |
+
|
| 1336 |
+
|
| 1337 |
+
if __name__ == '__main__':
|
| 1338 |
+
import doctest
|
| 1339 |
+
doctest.testmod()
|
tuning-competition-baseline/.venv/lib/python3.11/site-packages/mpmath/ctx_mp_python.py
ADDED
|
@@ -0,0 +1,1149 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#from ctx_base import StandardBaseContext
|
| 2 |
+
|
| 3 |
+
from .libmp.backend import basestring, exec_
|
| 4 |
+
|
| 5 |
+
from .libmp import (MPZ, MPZ_ZERO, MPZ_ONE, int_types, repr_dps,
|
| 6 |
+
round_floor, round_ceiling, dps_to_prec, round_nearest, prec_to_dps,
|
| 7 |
+
ComplexResult, to_pickable, from_pickable, normalize,
|
| 8 |
+
from_int, from_float, from_npfloat, from_Decimal, from_str, to_int, to_float, to_str,
|
| 9 |
+
from_rational, from_man_exp,
|
| 10 |
+
fone, fzero, finf, fninf, fnan,
|
| 11 |
+
mpf_abs, mpf_pos, mpf_neg, mpf_add, mpf_sub, mpf_mul, mpf_mul_int,
|
| 12 |
+
mpf_div, mpf_rdiv_int, mpf_pow_int, mpf_mod,
|
| 13 |
+
mpf_eq, mpf_cmp, mpf_lt, mpf_gt, mpf_le, mpf_ge,
|
| 14 |
+
mpf_hash, mpf_rand,
|
| 15 |
+
mpf_sum,
|
| 16 |
+
bitcount, to_fixed,
|
| 17 |
+
mpc_to_str,
|
| 18 |
+
mpc_to_complex, mpc_hash, mpc_pos, mpc_is_nonzero, mpc_neg, mpc_conjugate,
|
| 19 |
+
mpc_abs, mpc_add, mpc_add_mpf, mpc_sub, mpc_sub_mpf, mpc_mul, mpc_mul_mpf,
|
| 20 |
+
mpc_mul_int, mpc_div, mpc_div_mpf, mpc_pow, mpc_pow_mpf, mpc_pow_int,
|
| 21 |
+
mpc_mpf_div,
|
| 22 |
+
mpf_pow,
|
| 23 |
+
mpf_pi, mpf_degree, mpf_e, mpf_phi, mpf_ln2, mpf_ln10,
|
| 24 |
+
mpf_euler, mpf_catalan, mpf_apery, mpf_khinchin,
|
| 25 |
+
mpf_glaisher, mpf_twinprime, mpf_mertens,
|
| 26 |
+
int_types)
|
| 27 |
+
|
| 28 |
+
from . import rational
|
| 29 |
+
from . import function_docs
|
| 30 |
+
|
| 31 |
+
new = object.__new__
|
| 32 |
+
|
| 33 |
+
class mpnumeric(object):
|
| 34 |
+
"""Base class for mpf and mpc."""
|
| 35 |
+
__slots__ = []
|
| 36 |
+
def __new__(cls, val):
|
| 37 |
+
raise NotImplementedError
|
| 38 |
+
|
| 39 |
+
class _mpf(mpnumeric):
|
| 40 |
+
"""
|
| 41 |
+
An mpf instance holds a real-valued floating-point number. mpf:s
|
| 42 |
+
work analogously to Python floats, but support arbitrary-precision
|
| 43 |
+
arithmetic.
|
| 44 |
+
"""
|
| 45 |
+
__slots__ = ['_mpf_']
|
| 46 |
+
|
| 47 |
+
def __new__(cls, val=fzero, **kwargs):
|
| 48 |
+
"""A new mpf can be created from a Python float, an int, a
|
| 49 |
+
or a decimal string representing a number in floating-point
|
| 50 |
+
format."""
|
| 51 |
+
prec, rounding = cls.context._prec_rounding
|
| 52 |
+
if kwargs:
|
| 53 |
+
prec = kwargs.get('prec', prec)
|
| 54 |
+
if 'dps' in kwargs:
|
| 55 |
+
prec = dps_to_prec(kwargs['dps'])
|
| 56 |
+
rounding = kwargs.get('rounding', rounding)
|
| 57 |
+
if type(val) is cls:
|
| 58 |
+
sign, man, exp, bc = val._mpf_
|
| 59 |
+
if (not man) and exp:
|
| 60 |
+
return val
|
| 61 |
+
v = new(cls)
|
| 62 |
+
v._mpf_ = normalize(sign, man, exp, bc, prec, rounding)
|
| 63 |
+
return v
|
| 64 |
+
elif type(val) is tuple:
|
| 65 |
+
if len(val) == 2:
|
| 66 |
+
v = new(cls)
|
| 67 |
+
v._mpf_ = from_man_exp(val[0], val[1], prec, rounding)
|
| 68 |
+
return v
|
| 69 |
+
if len(val) == 4:
|
| 70 |
+
if val not in (finf, fninf, fnan):
|
| 71 |
+
sign, man, exp, bc = val
|
| 72 |
+
val = normalize(sign, MPZ(man), exp, bc, prec, rounding)
|
| 73 |
+
v = new(cls)
|
| 74 |
+
v._mpf_ = val
|
| 75 |
+
return v
|
| 76 |
+
raise ValueError
|
| 77 |
+
else:
|
| 78 |
+
v = new(cls)
|
| 79 |
+
v._mpf_ = mpf_pos(cls.mpf_convert_arg(val, prec, rounding), prec, rounding)
|
| 80 |
+
return v
|
| 81 |
+
|
| 82 |
+
@classmethod
|
| 83 |
+
def mpf_convert_arg(cls, x, prec, rounding):
|
| 84 |
+
if isinstance(x, int_types): return from_int(x)
|
| 85 |
+
if isinstance(x, float): return from_float(x)
|
| 86 |
+
if isinstance(x, basestring): return from_str(x, prec, rounding)
|
| 87 |
+
if isinstance(x, cls.context.constant): return x.func(prec, rounding)
|
| 88 |
+
if hasattr(x, '_mpf_'): return x._mpf_
|
| 89 |
+
if hasattr(x, '_mpmath_'):
|
| 90 |
+
t = cls.context.convert(x._mpmath_(prec, rounding))
|
| 91 |
+
if hasattr(t, '_mpf_'):
|
| 92 |
+
return t._mpf_
|
| 93 |
+
if hasattr(x, '_mpi_'):
|
| 94 |
+
a, b = x._mpi_
|
| 95 |
+
if a == b:
|
| 96 |
+
return a
|
| 97 |
+
raise ValueError("can only create mpf from zero-width interval")
|
| 98 |
+
raise TypeError("cannot create mpf from " + repr(x))
|
| 99 |
+
|
| 100 |
+
@classmethod
|
| 101 |
+
def mpf_convert_rhs(cls, x):
|
| 102 |
+
if isinstance(x, int_types): return from_int(x)
|
| 103 |
+
if isinstance(x, float): return from_float(x)
|
| 104 |
+
if isinstance(x, complex_types): return cls.context.mpc(x)
|
| 105 |
+
if isinstance(x, rational.mpq):
|
| 106 |
+
p, q = x._mpq_
|
| 107 |
+
return from_rational(p, q, cls.context.prec)
|
| 108 |
+
if hasattr(x, '_mpf_'): return x._mpf_
|
| 109 |
+
if hasattr(x, '_mpmath_'):
|
| 110 |
+
t = cls.context.convert(x._mpmath_(*cls.context._prec_rounding))
|
| 111 |
+
if hasattr(t, '_mpf_'):
|
| 112 |
+
return t._mpf_
|
| 113 |
+
return t
|
| 114 |
+
return NotImplemented
|
| 115 |
+
|
| 116 |
+
@classmethod
|
| 117 |
+
def mpf_convert_lhs(cls, x):
|
| 118 |
+
x = cls.mpf_convert_rhs(x)
|
| 119 |
+
if type(x) is tuple:
|
| 120 |
+
return cls.context.make_mpf(x)
|
| 121 |
+
return x
|
| 122 |
+
|
| 123 |
+
man_exp = property(lambda self: self._mpf_[1:3])
|
| 124 |
+
man = property(lambda self: self._mpf_[1])
|
| 125 |
+
exp = property(lambda self: self._mpf_[2])
|
| 126 |
+
bc = property(lambda self: self._mpf_[3])
|
| 127 |
+
|
| 128 |
+
real = property(lambda self: self)
|
| 129 |
+
imag = property(lambda self: self.context.zero)
|
| 130 |
+
|
| 131 |
+
conjugate = lambda self: self
|
| 132 |
+
|
| 133 |
+
def __getstate__(self): return to_pickable(self._mpf_)
|
| 134 |
+
def __setstate__(self, val): self._mpf_ = from_pickable(val)
|
| 135 |
+
|
| 136 |
+
def __repr__(s):
|
| 137 |
+
if s.context.pretty:
|
| 138 |
+
return str(s)
|
| 139 |
+
return "mpf('%s')" % to_str(s._mpf_, s.context._repr_digits)
|
| 140 |
+
|
| 141 |
+
def __str__(s): return to_str(s._mpf_, s.context._str_digits)
|
| 142 |
+
def __hash__(s): return mpf_hash(s._mpf_)
|
| 143 |
+
def __int__(s): return int(to_int(s._mpf_))
|
| 144 |
+
def __long__(s): return long(to_int(s._mpf_))
|
| 145 |
+
def __float__(s): return to_float(s._mpf_, rnd=s.context._prec_rounding[1])
|
| 146 |
+
def __complex__(s): return complex(float(s))
|
| 147 |
+
def __nonzero__(s): return s._mpf_ != fzero
|
| 148 |
+
|
| 149 |
+
__bool__ = __nonzero__
|
| 150 |
+
|
| 151 |
+
def __abs__(s):
|
| 152 |
+
cls, new, (prec, rounding) = s._ctxdata
|
| 153 |
+
v = new(cls)
|
| 154 |
+
v._mpf_ = mpf_abs(s._mpf_, prec, rounding)
|
| 155 |
+
return v
|
| 156 |
+
|
| 157 |
+
def __pos__(s):
|
| 158 |
+
cls, new, (prec, rounding) = s._ctxdata
|
| 159 |
+
v = new(cls)
|
| 160 |
+
v._mpf_ = mpf_pos(s._mpf_, prec, rounding)
|
| 161 |
+
return v
|
| 162 |
+
|
| 163 |
+
def __neg__(s):
|
| 164 |
+
cls, new, (prec, rounding) = s._ctxdata
|
| 165 |
+
v = new(cls)
|
| 166 |
+
v._mpf_ = mpf_neg(s._mpf_, prec, rounding)
|
| 167 |
+
return v
|
| 168 |
+
|
| 169 |
+
def _cmp(s, t, func):
|
| 170 |
+
if hasattr(t, '_mpf_'):
|
| 171 |
+
t = t._mpf_
|
| 172 |
+
else:
|
| 173 |
+
t = s.mpf_convert_rhs(t)
|
| 174 |
+
if t is NotImplemented:
|
| 175 |
+
return t
|
| 176 |
+
return func(s._mpf_, t)
|
| 177 |
+
|
| 178 |
+
def __cmp__(s, t): return s._cmp(t, mpf_cmp)
|
| 179 |
+
def __lt__(s, t): return s._cmp(t, mpf_lt)
|
| 180 |
+
def __gt__(s, t): return s._cmp(t, mpf_gt)
|
| 181 |
+
def __le__(s, t): return s._cmp(t, mpf_le)
|
| 182 |
+
def __ge__(s, t): return s._cmp(t, mpf_ge)
|
| 183 |
+
|
| 184 |
+
def __ne__(s, t):
|
| 185 |
+
v = s.__eq__(t)
|
| 186 |
+
if v is NotImplemented:
|
| 187 |
+
return v
|
| 188 |
+
return not v
|
| 189 |
+
|
| 190 |
+
def __rsub__(s, t):
|
| 191 |
+
cls, new, (prec, rounding) = s._ctxdata
|
| 192 |
+
if type(t) in int_types:
|
| 193 |
+
v = new(cls)
|
| 194 |
+
v._mpf_ = mpf_sub(from_int(t), s._mpf_, prec, rounding)
|
| 195 |
+
return v
|
| 196 |
+
t = s.mpf_convert_lhs(t)
|
| 197 |
+
if t is NotImplemented:
|
| 198 |
+
return t
|
| 199 |
+
return t - s
|
| 200 |
+
|
| 201 |
+
def __rdiv__(s, t):
|
| 202 |
+
cls, new, (prec, rounding) = s._ctxdata
|
| 203 |
+
if isinstance(t, int_types):
|
| 204 |
+
v = new(cls)
|
| 205 |
+
v._mpf_ = mpf_rdiv_int(t, s._mpf_, prec, rounding)
|
| 206 |
+
return v
|
| 207 |
+
t = s.mpf_convert_lhs(t)
|
| 208 |
+
if t is NotImplemented:
|
| 209 |
+
return t
|
| 210 |
+
return t / s
|
| 211 |
+
|
| 212 |
+
def __rpow__(s, t):
|
| 213 |
+
t = s.mpf_convert_lhs(t)
|
| 214 |
+
if t is NotImplemented:
|
| 215 |
+
return t
|
| 216 |
+
return t ** s
|
| 217 |
+
|
| 218 |
+
def __rmod__(s, t):
|
| 219 |
+
t = s.mpf_convert_lhs(t)
|
| 220 |
+
if t is NotImplemented:
|
| 221 |
+
return t
|
| 222 |
+
return t % s
|
| 223 |
+
|
| 224 |
+
def sqrt(s):
|
| 225 |
+
return s.context.sqrt(s)
|
| 226 |
+
|
| 227 |
+
def ae(s, t, rel_eps=None, abs_eps=None):
|
| 228 |
+
return s.context.almosteq(s, t, rel_eps, abs_eps)
|
| 229 |
+
|
| 230 |
+
def to_fixed(self, prec):
|
| 231 |
+
return to_fixed(self._mpf_, prec)
|
| 232 |
+
|
| 233 |
+
def __round__(self, *args):
|
| 234 |
+
return round(float(self), *args)
|
| 235 |
+
|
| 236 |
+
mpf_binary_op = """
|
| 237 |
+
def %NAME%(self, other):
|
| 238 |
+
mpf, new, (prec, rounding) = self._ctxdata
|
| 239 |
+
sval = self._mpf_
|
| 240 |
+
if hasattr(other, '_mpf_'):
|
| 241 |
+
tval = other._mpf_
|
| 242 |
+
%WITH_MPF%
|
| 243 |
+
ttype = type(other)
|
| 244 |
+
if ttype in int_types:
|
| 245 |
+
%WITH_INT%
|
| 246 |
+
elif ttype is float:
|
| 247 |
+
tval = from_float(other)
|
| 248 |
+
%WITH_MPF%
|
| 249 |
+
elif hasattr(other, '_mpc_'):
|
| 250 |
+
tval = other._mpc_
|
| 251 |
+
mpc = type(other)
|
| 252 |
+
%WITH_MPC%
|
| 253 |
+
elif ttype is complex:
|
| 254 |
+
tval = from_float(other.real), from_float(other.imag)
|
| 255 |
+
mpc = self.context.mpc
|
| 256 |
+
%WITH_MPC%
|
| 257 |
+
if isinstance(other, mpnumeric):
|
| 258 |
+
return NotImplemented
|
| 259 |
+
try:
|
| 260 |
+
other = mpf.context.convert(other, strings=False)
|
| 261 |
+
except TypeError:
|
| 262 |
+
return NotImplemented
|
| 263 |
+
return self.%NAME%(other)
|
| 264 |
+
"""
|
| 265 |
+
|
| 266 |
+
return_mpf = "; obj = new(mpf); obj._mpf_ = val; return obj"
|
| 267 |
+
return_mpc = "; obj = new(mpc); obj._mpc_ = val; return obj"
|
| 268 |
+
|
| 269 |
+
mpf_pow_same = """
|
| 270 |
+
try:
|
| 271 |
+
val = mpf_pow(sval, tval, prec, rounding) %s
|
| 272 |
+
except ComplexResult:
|
| 273 |
+
if mpf.context.trap_complex:
|
| 274 |
+
raise
|
| 275 |
+
mpc = mpf.context.mpc
|
| 276 |
+
val = mpc_pow((sval, fzero), (tval, fzero), prec, rounding) %s
|
| 277 |
+
""" % (return_mpf, return_mpc)
|
| 278 |
+
|
| 279 |
+
def binary_op(name, with_mpf='', with_int='', with_mpc=''):
|
| 280 |
+
code = mpf_binary_op
|
| 281 |
+
code = code.replace("%WITH_INT%", with_int)
|
| 282 |
+
code = code.replace("%WITH_MPC%", with_mpc)
|
| 283 |
+
code = code.replace("%WITH_MPF%", with_mpf)
|
| 284 |
+
code = code.replace("%NAME%", name)
|
| 285 |
+
np = {}
|
| 286 |
+
exec_(code, globals(), np)
|
| 287 |
+
return np[name]
|
| 288 |
+
|
| 289 |
+
_mpf.__eq__ = binary_op('__eq__',
|
| 290 |
+
'return mpf_eq(sval, tval)',
|
| 291 |
+
'return mpf_eq(sval, from_int(other))',
|
| 292 |
+
'return (tval[1] == fzero) and mpf_eq(tval[0], sval)')
|
| 293 |
+
|
| 294 |
+
_mpf.__add__ = binary_op('__add__',
|
| 295 |
+
'val = mpf_add(sval, tval, prec, rounding)' + return_mpf,
|
| 296 |
+
'val = mpf_add(sval, from_int(other), prec, rounding)' + return_mpf,
|
| 297 |
+
'val = mpc_add_mpf(tval, sval, prec, rounding)' + return_mpc)
|
| 298 |
+
|
| 299 |
+
_mpf.__sub__ = binary_op('__sub__',
|
| 300 |
+
'val = mpf_sub(sval, tval, prec, rounding)' + return_mpf,
|
| 301 |
+
'val = mpf_sub(sval, from_int(other), prec, rounding)' + return_mpf,
|
| 302 |
+
'val = mpc_sub((sval, fzero), tval, prec, rounding)' + return_mpc)
|
| 303 |
+
|
| 304 |
+
_mpf.__mul__ = binary_op('__mul__',
|
| 305 |
+
'val = mpf_mul(sval, tval, prec, rounding)' + return_mpf,
|
| 306 |
+
'val = mpf_mul_int(sval, other, prec, rounding)' + return_mpf,
|
| 307 |
+
'val = mpc_mul_mpf(tval, sval, prec, rounding)' + return_mpc)
|
| 308 |
+
|
| 309 |
+
_mpf.__div__ = binary_op('__div__',
|
| 310 |
+
'val = mpf_div(sval, tval, prec, rounding)' + return_mpf,
|
| 311 |
+
'val = mpf_div(sval, from_int(other), prec, rounding)' + return_mpf,
|
| 312 |
+
'val = mpc_mpf_div(sval, tval, prec, rounding)' + return_mpc)
|
| 313 |
+
|
| 314 |
+
_mpf.__mod__ = binary_op('__mod__',
|
| 315 |
+
'val = mpf_mod(sval, tval, prec, rounding)' + return_mpf,
|
| 316 |
+
'val = mpf_mod(sval, from_int(other), prec, rounding)' + return_mpf,
|
| 317 |
+
'raise NotImplementedError("complex modulo")')
|
| 318 |
+
|
| 319 |
+
_mpf.__pow__ = binary_op('__pow__',
|
| 320 |
+
mpf_pow_same,
|
| 321 |
+
'val = mpf_pow_int(sval, other, prec, rounding)' + return_mpf,
|
| 322 |
+
'val = mpc_pow((sval, fzero), tval, prec, rounding)' + return_mpc)
|
| 323 |
+
|
| 324 |
+
_mpf.__radd__ = _mpf.__add__
|
| 325 |
+
_mpf.__rmul__ = _mpf.__mul__
|
| 326 |
+
_mpf.__truediv__ = _mpf.__div__
|
| 327 |
+
_mpf.__rtruediv__ = _mpf.__rdiv__
|
| 328 |
+
|
| 329 |
+
|
| 330 |
+
class _constant(_mpf):
|
| 331 |
+
"""Represents a mathematical constant with dynamic precision.
|
| 332 |
+
When printed or used in an arithmetic operation, a constant
|
| 333 |
+
is converted to a regular mpf at the working precision. A
|
| 334 |
+
regular mpf can also be obtained using the operation +x."""
|
| 335 |
+
|
| 336 |
+
def __new__(cls, func, name, docname=''):
|
| 337 |
+
a = object.__new__(cls)
|
| 338 |
+
a.name = name
|
| 339 |
+
a.func = func
|
| 340 |
+
a.__doc__ = getattr(function_docs, docname, '')
|
| 341 |
+
return a
|
| 342 |
+
|
| 343 |
+
def __call__(self, prec=None, dps=None, rounding=None):
|
| 344 |
+
prec2, rounding2 = self.context._prec_rounding
|
| 345 |
+
if not prec: prec = prec2
|
| 346 |
+
if not rounding: rounding = rounding2
|
| 347 |
+
if dps: prec = dps_to_prec(dps)
|
| 348 |
+
return self.context.make_mpf(self.func(prec, rounding))
|
| 349 |
+
|
| 350 |
+
@property
|
| 351 |
+
def _mpf_(self):
|
| 352 |
+
prec, rounding = self.context._prec_rounding
|
| 353 |
+
return self.func(prec, rounding)
|
| 354 |
+
|
| 355 |
+
def __repr__(self):
|
| 356 |
+
return "<%s: %s~>" % (self.name, self.context.nstr(self(dps=15)))
|
| 357 |
+
|
| 358 |
+
|
| 359 |
+
class _mpc(mpnumeric):
|
| 360 |
+
"""
|
| 361 |
+
An mpc represents a complex number using a pair of mpf:s (one
|
| 362 |
+
for the real part and another for the imaginary part.) The mpc
|
| 363 |
+
class behaves fairly similarly to Python's complex type.
|
| 364 |
+
"""
|
| 365 |
+
|
| 366 |
+
__slots__ = ['_mpc_']
|
| 367 |
+
|
| 368 |
+
def __new__(cls, real=0, imag=0):
|
| 369 |
+
s = object.__new__(cls)
|
| 370 |
+
if isinstance(real, complex_types):
|
| 371 |
+
real, imag = real.real, real.imag
|
| 372 |
+
elif hasattr(real, '_mpc_'):
|
| 373 |
+
s._mpc_ = real._mpc_
|
| 374 |
+
return s
|
| 375 |
+
real = cls.context.mpf(real)
|
| 376 |
+
imag = cls.context.mpf(imag)
|
| 377 |
+
s._mpc_ = (real._mpf_, imag._mpf_)
|
| 378 |
+
return s
|
| 379 |
+
|
| 380 |
+
real = property(lambda self: self.context.make_mpf(self._mpc_[0]))
|
| 381 |
+
imag = property(lambda self: self.context.make_mpf(self._mpc_[1]))
|
| 382 |
+
|
| 383 |
+
def __getstate__(self):
|
| 384 |
+
return to_pickable(self._mpc_[0]), to_pickable(self._mpc_[1])
|
| 385 |
+
|
| 386 |
+
def __setstate__(self, val):
|
| 387 |
+
self._mpc_ = from_pickable(val[0]), from_pickable(val[1])
|
| 388 |
+
|
| 389 |
+
def __repr__(s):
|
| 390 |
+
if s.context.pretty:
|
| 391 |
+
return str(s)
|
| 392 |
+
r = repr(s.real)[4:-1]
|
| 393 |
+
i = repr(s.imag)[4:-1]
|
| 394 |
+
return "%s(real=%s, imag=%s)" % (type(s).__name__, r, i)
|
| 395 |
+
|
| 396 |
+
def __str__(s):
|
| 397 |
+
return "(%s)" % mpc_to_str(s._mpc_, s.context._str_digits)
|
| 398 |
+
|
| 399 |
+
def __complex__(s):
|
| 400 |
+
return mpc_to_complex(s._mpc_, rnd=s.context._prec_rounding[1])
|
| 401 |
+
|
| 402 |
+
def __pos__(s):
|
| 403 |
+
cls, new, (prec, rounding) = s._ctxdata
|
| 404 |
+
v = new(cls)
|
| 405 |
+
v._mpc_ = mpc_pos(s._mpc_, prec, rounding)
|
| 406 |
+
return v
|
| 407 |
+
|
| 408 |
+
def __abs__(s):
|
| 409 |
+
prec, rounding = s.context._prec_rounding
|
| 410 |
+
v = new(s.context.mpf)
|
| 411 |
+
v._mpf_ = mpc_abs(s._mpc_, prec, rounding)
|
| 412 |
+
return v
|
| 413 |
+
|
| 414 |
+
def __neg__(s):
|
| 415 |
+
cls, new, (prec, rounding) = s._ctxdata
|
| 416 |
+
v = new(cls)
|
| 417 |
+
v._mpc_ = mpc_neg(s._mpc_, prec, rounding)
|
| 418 |
+
return v
|
| 419 |
+
|
| 420 |
+
def conjugate(s):
|
| 421 |
+
cls, new, (prec, rounding) = s._ctxdata
|
| 422 |
+
v = new(cls)
|
| 423 |
+
v._mpc_ = mpc_conjugate(s._mpc_, prec, rounding)
|
| 424 |
+
return v
|
| 425 |
+
|
| 426 |
+
def __nonzero__(s):
|
| 427 |
+
return mpc_is_nonzero(s._mpc_)
|
| 428 |
+
|
| 429 |
+
__bool__ = __nonzero__
|
| 430 |
+
|
| 431 |
+
def __hash__(s):
|
| 432 |
+
return mpc_hash(s._mpc_)
|
| 433 |
+
|
| 434 |
+
@classmethod
|
| 435 |
+
def mpc_convert_lhs(cls, x):
|
| 436 |
+
try:
|
| 437 |
+
y = cls.context.convert(x)
|
| 438 |
+
return y
|
| 439 |
+
except TypeError:
|
| 440 |
+
return NotImplemented
|
| 441 |
+
|
| 442 |
+
def __eq__(s, t):
|
| 443 |
+
if not hasattr(t, '_mpc_'):
|
| 444 |
+
if isinstance(t, str):
|
| 445 |
+
return False
|
| 446 |
+
t = s.mpc_convert_lhs(t)
|
| 447 |
+
if t is NotImplemented:
|
| 448 |
+
return t
|
| 449 |
+
return s.real == t.real and s.imag == t.imag
|
| 450 |
+
|
| 451 |
+
def __ne__(s, t):
|
| 452 |
+
b = s.__eq__(t)
|
| 453 |
+
if b is NotImplemented:
|
| 454 |
+
return b
|
| 455 |
+
return not b
|
| 456 |
+
|
| 457 |
+
def _compare(*args):
|
| 458 |
+
raise TypeError("no ordering relation is defined for complex numbers")
|
| 459 |
+
|
| 460 |
+
__gt__ = _compare
|
| 461 |
+
__le__ = _compare
|
| 462 |
+
__gt__ = _compare
|
| 463 |
+
__ge__ = _compare
|
| 464 |
+
|
| 465 |
+
def __add__(s, t):
|
| 466 |
+
cls, new, (prec, rounding) = s._ctxdata
|
| 467 |
+
if not hasattr(t, '_mpc_'):
|
| 468 |
+
t = s.mpc_convert_lhs(t)
|
| 469 |
+
if t is NotImplemented:
|
| 470 |
+
return t
|
| 471 |
+
if hasattr(t, '_mpf_'):
|
| 472 |
+
v = new(cls)
|
| 473 |
+
v._mpc_ = mpc_add_mpf(s._mpc_, t._mpf_, prec, rounding)
|
| 474 |
+
return v
|
| 475 |
+
v = new(cls)
|
| 476 |
+
v._mpc_ = mpc_add(s._mpc_, t._mpc_, prec, rounding)
|
| 477 |
+
return v
|
| 478 |
+
|
| 479 |
+
def __sub__(s, t):
|
| 480 |
+
cls, new, (prec, rounding) = s._ctxdata
|
| 481 |
+
if not hasattr(t, '_mpc_'):
|
| 482 |
+
t = s.mpc_convert_lhs(t)
|
| 483 |
+
if t is NotImplemented:
|
| 484 |
+
return t
|
| 485 |
+
if hasattr(t, '_mpf_'):
|
| 486 |
+
v = new(cls)
|
| 487 |
+
v._mpc_ = mpc_sub_mpf(s._mpc_, t._mpf_, prec, rounding)
|
| 488 |
+
return v
|
| 489 |
+
v = new(cls)
|
| 490 |
+
v._mpc_ = mpc_sub(s._mpc_, t._mpc_, prec, rounding)
|
| 491 |
+
return v
|
| 492 |
+
|
| 493 |
+
def __mul__(s, t):
|
| 494 |
+
cls, new, (prec, rounding) = s._ctxdata
|
| 495 |
+
if not hasattr(t, '_mpc_'):
|
| 496 |
+
if isinstance(t, int_types):
|
| 497 |
+
v = new(cls)
|
| 498 |
+
v._mpc_ = mpc_mul_int(s._mpc_, t, prec, rounding)
|
| 499 |
+
return v
|
| 500 |
+
t = s.mpc_convert_lhs(t)
|
| 501 |
+
if t is NotImplemented:
|
| 502 |
+
return t
|
| 503 |
+
if hasattr(t, '_mpf_'):
|
| 504 |
+
v = new(cls)
|
| 505 |
+
v._mpc_ = mpc_mul_mpf(s._mpc_, t._mpf_, prec, rounding)
|
| 506 |
+
return v
|
| 507 |
+
t = s.mpc_convert_lhs(t)
|
| 508 |
+
v = new(cls)
|
| 509 |
+
v._mpc_ = mpc_mul(s._mpc_, t._mpc_, prec, rounding)
|
| 510 |
+
return v
|
| 511 |
+
|
| 512 |
+
def __div__(s, t):
|
| 513 |
+
cls, new, (prec, rounding) = s._ctxdata
|
| 514 |
+
if not hasattr(t, '_mpc_'):
|
| 515 |
+
t = s.mpc_convert_lhs(t)
|
| 516 |
+
if t is NotImplemented:
|
| 517 |
+
return t
|
| 518 |
+
if hasattr(t, '_mpf_'):
|
| 519 |
+
v = new(cls)
|
| 520 |
+
v._mpc_ = mpc_div_mpf(s._mpc_, t._mpf_, prec, rounding)
|
| 521 |
+
return v
|
| 522 |
+
v = new(cls)
|
| 523 |
+
v._mpc_ = mpc_div(s._mpc_, t._mpc_, prec, rounding)
|
| 524 |
+
return v
|
| 525 |
+
|
| 526 |
+
def __pow__(s, t):
|
| 527 |
+
cls, new, (prec, rounding) = s._ctxdata
|
| 528 |
+
if isinstance(t, int_types):
|
| 529 |
+
v = new(cls)
|
| 530 |
+
v._mpc_ = mpc_pow_int(s._mpc_, t, prec, rounding)
|
| 531 |
+
return v
|
| 532 |
+
t = s.mpc_convert_lhs(t)
|
| 533 |
+
if t is NotImplemented:
|
| 534 |
+
return t
|
| 535 |
+
v = new(cls)
|
| 536 |
+
if hasattr(t, '_mpf_'):
|
| 537 |
+
v._mpc_ = mpc_pow_mpf(s._mpc_, t._mpf_, prec, rounding)
|
| 538 |
+
else:
|
| 539 |
+
v._mpc_ = mpc_pow(s._mpc_, t._mpc_, prec, rounding)
|
| 540 |
+
return v
|
| 541 |
+
|
| 542 |
+
__radd__ = __add__
|
| 543 |
+
|
| 544 |
+
def __rsub__(s, t):
|
| 545 |
+
t = s.mpc_convert_lhs(t)
|
| 546 |
+
if t is NotImplemented:
|
| 547 |
+
return t
|
| 548 |
+
return t - s
|
| 549 |
+
|
| 550 |
+
def __rmul__(s, t):
|
| 551 |
+
cls, new, (prec, rounding) = s._ctxdata
|
| 552 |
+
if isinstance(t, int_types):
|
| 553 |
+
v = new(cls)
|
| 554 |
+
v._mpc_ = mpc_mul_int(s._mpc_, t, prec, rounding)
|
| 555 |
+
return v
|
| 556 |
+
t = s.mpc_convert_lhs(t)
|
| 557 |
+
if t is NotImplemented:
|
| 558 |
+
return t
|
| 559 |
+
return t * s
|
| 560 |
+
|
| 561 |
+
def __rdiv__(s, t):
|
| 562 |
+
t = s.mpc_convert_lhs(t)
|
| 563 |
+
if t is NotImplemented:
|
| 564 |
+
return t
|
| 565 |
+
return t / s
|
| 566 |
+
|
| 567 |
+
def __rpow__(s, t):
|
| 568 |
+
t = s.mpc_convert_lhs(t)
|
| 569 |
+
if t is NotImplemented:
|
| 570 |
+
return t
|
| 571 |
+
return t ** s
|
| 572 |
+
|
| 573 |
+
__truediv__ = __div__
|
| 574 |
+
__rtruediv__ = __rdiv__
|
| 575 |
+
|
| 576 |
+
def ae(s, t, rel_eps=None, abs_eps=None):
|
| 577 |
+
return s.context.almosteq(s, t, rel_eps, abs_eps)
|
| 578 |
+
|
| 579 |
+
|
| 580 |
+
complex_types = (complex, _mpc)
|
| 581 |
+
|
| 582 |
+
|
| 583 |
+
class PythonMPContext(object):
|
| 584 |
+
|
| 585 |
+
def __init__(ctx):
|
| 586 |
+
ctx._prec_rounding = [53, round_nearest]
|
| 587 |
+
ctx.mpf = type('mpf', (_mpf,), {})
|
| 588 |
+
ctx.mpc = type('mpc', (_mpc,), {})
|
| 589 |
+
ctx.mpf._ctxdata = [ctx.mpf, new, ctx._prec_rounding]
|
| 590 |
+
ctx.mpc._ctxdata = [ctx.mpc, new, ctx._prec_rounding]
|
| 591 |
+
ctx.mpf.context = ctx
|
| 592 |
+
ctx.mpc.context = ctx
|
| 593 |
+
ctx.constant = type('constant', (_constant,), {})
|
| 594 |
+
ctx.constant._ctxdata = [ctx.mpf, new, ctx._prec_rounding]
|
| 595 |
+
ctx.constant.context = ctx
|
| 596 |
+
|
| 597 |
+
def make_mpf(ctx, v):
|
| 598 |
+
a = new(ctx.mpf)
|
| 599 |
+
a._mpf_ = v
|
| 600 |
+
return a
|
| 601 |
+
|
| 602 |
+
def make_mpc(ctx, v):
|
| 603 |
+
a = new(ctx.mpc)
|
| 604 |
+
a._mpc_ = v
|
| 605 |
+
return a
|
| 606 |
+
|
| 607 |
+
def default(ctx):
|
| 608 |
+
ctx._prec = ctx._prec_rounding[0] = 53
|
| 609 |
+
ctx._dps = 15
|
| 610 |
+
ctx.trap_complex = False
|
| 611 |
+
|
| 612 |
+
def _set_prec(ctx, n):
|
| 613 |
+
ctx._prec = ctx._prec_rounding[0] = max(1, int(n))
|
| 614 |
+
ctx._dps = prec_to_dps(n)
|
| 615 |
+
|
| 616 |
+
def _set_dps(ctx, n):
|
| 617 |
+
ctx._prec = ctx._prec_rounding[0] = dps_to_prec(n)
|
| 618 |
+
ctx._dps = max(1, int(n))
|
| 619 |
+
|
| 620 |
+
prec = property(lambda ctx: ctx._prec, _set_prec)
|
| 621 |
+
dps = property(lambda ctx: ctx._dps, _set_dps)
|
| 622 |
+
|
| 623 |
+
def convert(ctx, x, strings=True):
|
| 624 |
+
"""
|
| 625 |
+
Converts *x* to an ``mpf`` or ``mpc``. If *x* is of type ``mpf``,
|
| 626 |
+
``mpc``, ``int``, ``float``, ``complex``, the conversion
|
| 627 |
+
will be performed losslessly.
|
| 628 |
+
|
| 629 |
+
If *x* is a string, the result will be rounded to the present
|
| 630 |
+
working precision. Strings representing fractions or complex
|
| 631 |
+
numbers are permitted.
|
| 632 |
+
|
| 633 |
+
>>> from mpmath import *
|
| 634 |
+
>>> mp.dps = 15; mp.pretty = False
|
| 635 |
+
>>> mpmathify(3.5)
|
| 636 |
+
mpf('3.5')
|
| 637 |
+
>>> mpmathify('2.1')
|
| 638 |
+
mpf('2.1000000000000001')
|
| 639 |
+
>>> mpmathify('3/4')
|
| 640 |
+
mpf('0.75')
|
| 641 |
+
>>> mpmathify('2+3j')
|
| 642 |
+
mpc(real='2.0', imag='3.0')
|
| 643 |
+
|
| 644 |
+
"""
|
| 645 |
+
if type(x) in ctx.types: return x
|
| 646 |
+
if isinstance(x, int_types): return ctx.make_mpf(from_int(x))
|
| 647 |
+
if isinstance(x, float): return ctx.make_mpf(from_float(x))
|
| 648 |
+
if isinstance(x, complex):
|
| 649 |
+
return ctx.make_mpc((from_float(x.real), from_float(x.imag)))
|
| 650 |
+
if type(x).__module__ == 'numpy': return ctx.npconvert(x)
|
| 651 |
+
if isinstance(x, numbers.Rational): # e.g. Fraction
|
| 652 |
+
try: x = rational.mpq(int(x.numerator), int(x.denominator))
|
| 653 |
+
except: pass
|
| 654 |
+
prec, rounding = ctx._prec_rounding
|
| 655 |
+
if isinstance(x, rational.mpq):
|
| 656 |
+
p, q = x._mpq_
|
| 657 |
+
return ctx.make_mpf(from_rational(p, q, prec))
|
| 658 |
+
if strings and isinstance(x, basestring):
|
| 659 |
+
try:
|
| 660 |
+
_mpf_ = from_str(x, prec, rounding)
|
| 661 |
+
return ctx.make_mpf(_mpf_)
|
| 662 |
+
except ValueError:
|
| 663 |
+
pass
|
| 664 |
+
if hasattr(x, '_mpf_'): return ctx.make_mpf(x._mpf_)
|
| 665 |
+
if hasattr(x, '_mpc_'): return ctx.make_mpc(x._mpc_)
|
| 666 |
+
if hasattr(x, '_mpmath_'):
|
| 667 |
+
return ctx.convert(x._mpmath_(prec, rounding))
|
| 668 |
+
if type(x).__module__ == 'decimal':
|
| 669 |
+
try: return ctx.make_mpf(from_Decimal(x, prec, rounding))
|
| 670 |
+
except: pass
|
| 671 |
+
return ctx._convert_fallback(x, strings)
|
| 672 |
+
|
| 673 |
+
def npconvert(ctx, x):
|
| 674 |
+
"""
|
| 675 |
+
Converts *x* to an ``mpf`` or ``mpc``. *x* should be a numpy
|
| 676 |
+
scalar.
|
| 677 |
+
"""
|
| 678 |
+
import numpy as np
|
| 679 |
+
if isinstance(x, np.integer): return ctx.make_mpf(from_int(int(x)))
|
| 680 |
+
if isinstance(x, np.floating): return ctx.make_mpf(from_npfloat(x))
|
| 681 |
+
if isinstance(x, np.complexfloating):
|
| 682 |
+
return ctx.make_mpc((from_npfloat(x.real), from_npfloat(x.imag)))
|
| 683 |
+
raise TypeError("cannot create mpf from " + repr(x))
|
| 684 |
+
|
| 685 |
+
def isnan(ctx, x):
|
| 686 |
+
"""
|
| 687 |
+
Return *True* if *x* is a NaN (not-a-number), or for a complex
|
| 688 |
+
number, whether either the real or complex part is NaN;
|
| 689 |
+
otherwise return *False*::
|
| 690 |
+
|
| 691 |
+
>>> from mpmath import *
|
| 692 |
+
>>> isnan(3.14)
|
| 693 |
+
False
|
| 694 |
+
>>> isnan(nan)
|
| 695 |
+
True
|
| 696 |
+
>>> isnan(mpc(3.14,2.72))
|
| 697 |
+
False
|
| 698 |
+
>>> isnan(mpc(3.14,nan))
|
| 699 |
+
True
|
| 700 |
+
|
| 701 |
+
"""
|
| 702 |
+
if hasattr(x, "_mpf_"):
|
| 703 |
+
return x._mpf_ == fnan
|
| 704 |
+
if hasattr(x, "_mpc_"):
|
| 705 |
+
return fnan in x._mpc_
|
| 706 |
+
if isinstance(x, int_types) or isinstance(x, rational.mpq):
|
| 707 |
+
return False
|
| 708 |
+
x = ctx.convert(x)
|
| 709 |
+
if hasattr(x, '_mpf_') or hasattr(x, '_mpc_'):
|
| 710 |
+
return ctx.isnan(x)
|
| 711 |
+
raise TypeError("isnan() needs a number as input")
|
| 712 |
+
|
| 713 |
+
def isinf(ctx, x):
|
| 714 |
+
"""
|
| 715 |
+
Return *True* if the absolute value of *x* is infinite;
|
| 716 |
+
otherwise return *False*::
|
| 717 |
+
|
| 718 |
+
>>> from mpmath import *
|
| 719 |
+
>>> isinf(inf)
|
| 720 |
+
True
|
| 721 |
+
>>> isinf(-inf)
|
| 722 |
+
True
|
| 723 |
+
>>> isinf(3)
|
| 724 |
+
False
|
| 725 |
+
>>> isinf(3+4j)
|
| 726 |
+
False
|
| 727 |
+
>>> isinf(mpc(3,inf))
|
| 728 |
+
True
|
| 729 |
+
>>> isinf(mpc(inf,3))
|
| 730 |
+
True
|
| 731 |
+
|
| 732 |
+
"""
|
| 733 |
+
if hasattr(x, "_mpf_"):
|
| 734 |
+
return x._mpf_ in (finf, fninf)
|
| 735 |
+
if hasattr(x, "_mpc_"):
|
| 736 |
+
re, im = x._mpc_
|
| 737 |
+
return re in (finf, fninf) or im in (finf, fninf)
|
| 738 |
+
if isinstance(x, int_types) or isinstance(x, rational.mpq):
|
| 739 |
+
return False
|
| 740 |
+
x = ctx.convert(x)
|
| 741 |
+
if hasattr(x, '_mpf_') or hasattr(x, '_mpc_'):
|
| 742 |
+
return ctx.isinf(x)
|
| 743 |
+
raise TypeError("isinf() needs a number as input")
|
| 744 |
+
|
| 745 |
+
def isnormal(ctx, x):
|
| 746 |
+
"""
|
| 747 |
+
Determine whether *x* is "normal" in the sense of floating-point
|
| 748 |
+
representation; that is, return *False* if *x* is zero, an
|
| 749 |
+
infinity or NaN; otherwise return *True*. By extension, a
|
| 750 |
+
complex number *x* is considered "normal" if its magnitude is
|
| 751 |
+
normal::
|
| 752 |
+
|
| 753 |
+
>>> from mpmath import *
|
| 754 |
+
>>> isnormal(3)
|
| 755 |
+
True
|
| 756 |
+
>>> isnormal(0)
|
| 757 |
+
False
|
| 758 |
+
>>> isnormal(inf); isnormal(-inf); isnormal(nan)
|
| 759 |
+
False
|
| 760 |
+
False
|
| 761 |
+
False
|
| 762 |
+
>>> isnormal(0+0j)
|
| 763 |
+
False
|
| 764 |
+
>>> isnormal(0+3j)
|
| 765 |
+
True
|
| 766 |
+
>>> isnormal(mpc(2,nan))
|
| 767 |
+
False
|
| 768 |
+
"""
|
| 769 |
+
if hasattr(x, "_mpf_"):
|
| 770 |
+
return bool(x._mpf_[1])
|
| 771 |
+
if hasattr(x, "_mpc_"):
|
| 772 |
+
re, im = x._mpc_
|
| 773 |
+
re_normal = bool(re[1])
|
| 774 |
+
im_normal = bool(im[1])
|
| 775 |
+
if re == fzero: return im_normal
|
| 776 |
+
if im == fzero: return re_normal
|
| 777 |
+
return re_normal and im_normal
|
| 778 |
+
if isinstance(x, int_types) or isinstance(x, rational.mpq):
|
| 779 |
+
return bool(x)
|
| 780 |
+
x = ctx.convert(x)
|
| 781 |
+
if hasattr(x, '_mpf_') or hasattr(x, '_mpc_'):
|
| 782 |
+
return ctx.isnormal(x)
|
| 783 |
+
raise TypeError("isnormal() needs a number as input")
|
| 784 |
+
|
| 785 |
+
def isint(ctx, x, gaussian=False):
|
| 786 |
+
"""
|
| 787 |
+
Return *True* if *x* is integer-valued; otherwise return
|
| 788 |
+
*False*::
|
| 789 |
+
|
| 790 |
+
>>> from mpmath import *
|
| 791 |
+
>>> isint(3)
|
| 792 |
+
True
|
| 793 |
+
>>> isint(mpf(3))
|
| 794 |
+
True
|
| 795 |
+
>>> isint(3.2)
|
| 796 |
+
False
|
| 797 |
+
>>> isint(inf)
|
| 798 |
+
False
|
| 799 |
+
|
| 800 |
+
Optionally, Gaussian integers can be checked for::
|
| 801 |
+
|
| 802 |
+
>>> isint(3+0j)
|
| 803 |
+
True
|
| 804 |
+
>>> isint(3+2j)
|
| 805 |
+
False
|
| 806 |
+
>>> isint(3+2j, gaussian=True)
|
| 807 |
+
True
|
| 808 |
+
|
| 809 |
+
"""
|
| 810 |
+
if isinstance(x, int_types):
|
| 811 |
+
return True
|
| 812 |
+
if hasattr(x, "_mpf_"):
|
| 813 |
+
sign, man, exp, bc = xval = x._mpf_
|
| 814 |
+
return bool((man and exp >= 0) or xval == fzero)
|
| 815 |
+
if hasattr(x, "_mpc_"):
|
| 816 |
+
re, im = x._mpc_
|
| 817 |
+
rsign, rman, rexp, rbc = re
|
| 818 |
+
isign, iman, iexp, ibc = im
|
| 819 |
+
re_isint = (rman and rexp >= 0) or re == fzero
|
| 820 |
+
if gaussian:
|
| 821 |
+
im_isint = (iman and iexp >= 0) or im == fzero
|
| 822 |
+
return re_isint and im_isint
|
| 823 |
+
return re_isint and im == fzero
|
| 824 |
+
if isinstance(x, rational.mpq):
|
| 825 |
+
p, q = x._mpq_
|
| 826 |
+
return p % q == 0
|
| 827 |
+
x = ctx.convert(x)
|
| 828 |
+
if hasattr(x, '_mpf_') or hasattr(x, '_mpc_'):
|
| 829 |
+
return ctx.isint(x, gaussian)
|
| 830 |
+
raise TypeError("isint() needs a number as input")
|
| 831 |
+
|
| 832 |
+
def fsum(ctx, terms, absolute=False, squared=False):
|
| 833 |
+
"""
|
| 834 |
+
Calculates a sum containing a finite number of terms (for infinite
|
| 835 |
+
series, see :func:`~mpmath.nsum`). The terms will be converted to
|
| 836 |
+
mpmath numbers. For len(terms) > 2, this function is generally
|
| 837 |
+
faster and produces more accurate results than the builtin
|
| 838 |
+
Python function :func:`sum`.
|
| 839 |
+
|
| 840 |
+
>>> from mpmath import *
|
| 841 |
+
>>> mp.dps = 15; mp.pretty = False
|
| 842 |
+
>>> fsum([1, 2, 0.5, 7])
|
| 843 |
+
mpf('10.5')
|
| 844 |
+
|
| 845 |
+
With squared=True each term is squared, and with absolute=True
|
| 846 |
+
the absolute value of each term is used.
|
| 847 |
+
"""
|
| 848 |
+
prec, rnd = ctx._prec_rounding
|
| 849 |
+
real = []
|
| 850 |
+
imag = []
|
| 851 |
+
for term in terms:
|
| 852 |
+
reval = imval = 0
|
| 853 |
+
if hasattr(term, "_mpf_"):
|
| 854 |
+
reval = term._mpf_
|
| 855 |
+
elif hasattr(term, "_mpc_"):
|
| 856 |
+
reval, imval = term._mpc_
|
| 857 |
+
else:
|
| 858 |
+
term = ctx.convert(term)
|
| 859 |
+
if hasattr(term, "_mpf_"):
|
| 860 |
+
reval = term._mpf_
|
| 861 |
+
elif hasattr(term, "_mpc_"):
|
| 862 |
+
reval, imval = term._mpc_
|
| 863 |
+
else:
|
| 864 |
+
raise NotImplementedError
|
| 865 |
+
if imval:
|
| 866 |
+
if squared:
|
| 867 |
+
if absolute:
|
| 868 |
+
real.append(mpf_mul(reval,reval))
|
| 869 |
+
real.append(mpf_mul(imval,imval))
|
| 870 |
+
else:
|
| 871 |
+
reval, imval = mpc_pow_int((reval,imval),2,prec+10)
|
| 872 |
+
real.append(reval)
|
| 873 |
+
imag.append(imval)
|
| 874 |
+
elif absolute:
|
| 875 |
+
real.append(mpc_abs((reval,imval), prec))
|
| 876 |
+
else:
|
| 877 |
+
real.append(reval)
|
| 878 |
+
imag.append(imval)
|
| 879 |
+
else:
|
| 880 |
+
if squared:
|
| 881 |
+
reval = mpf_mul(reval, reval)
|
| 882 |
+
elif absolute:
|
| 883 |
+
reval = mpf_abs(reval)
|
| 884 |
+
real.append(reval)
|
| 885 |
+
s = mpf_sum(real, prec, rnd, absolute)
|
| 886 |
+
if imag:
|
| 887 |
+
s = ctx.make_mpc((s, mpf_sum(imag, prec, rnd)))
|
| 888 |
+
else:
|
| 889 |
+
s = ctx.make_mpf(s)
|
| 890 |
+
return s
|
| 891 |
+
|
| 892 |
+
def fdot(ctx, A, B=None, conjugate=False):
|
| 893 |
+
r"""
|
| 894 |
+
Computes the dot product of the iterables `A` and `B`,
|
| 895 |
+
|
| 896 |
+
.. math ::
|
| 897 |
+
|
| 898 |
+
\sum_{k=0} A_k B_k.
|
| 899 |
+
|
| 900 |
+
Alternatively, :func:`~mpmath.fdot` accepts a single iterable of pairs.
|
| 901 |
+
In other words, ``fdot(A,B)`` and ``fdot(zip(A,B))`` are equivalent.
|
| 902 |
+
The elements are automatically converted to mpmath numbers.
|
| 903 |
+
|
| 904 |
+
With ``conjugate=True``, the elements in the second vector
|
| 905 |
+
will be conjugated:
|
| 906 |
+
|
| 907 |
+
.. math ::
|
| 908 |
+
|
| 909 |
+
\sum_{k=0} A_k \overline{B_k}
|
| 910 |
+
|
| 911 |
+
**Examples**
|
| 912 |
+
|
| 913 |
+
>>> from mpmath import *
|
| 914 |
+
>>> mp.dps = 15; mp.pretty = False
|
| 915 |
+
>>> A = [2, 1.5, 3]
|
| 916 |
+
>>> B = [1, -1, 2]
|
| 917 |
+
>>> fdot(A, B)
|
| 918 |
+
mpf('6.5')
|
| 919 |
+
>>> list(zip(A, B))
|
| 920 |
+
[(2, 1), (1.5, -1), (3, 2)]
|
| 921 |
+
>>> fdot(_)
|
| 922 |
+
mpf('6.5')
|
| 923 |
+
>>> A = [2, 1.5, 3j]
|
| 924 |
+
>>> B = [1+j, 3, -1-j]
|
| 925 |
+
>>> fdot(A, B)
|
| 926 |
+
mpc(real='9.5', imag='-1.0')
|
| 927 |
+
>>> fdot(A, B, conjugate=True)
|
| 928 |
+
mpc(real='3.5', imag='-5.0')
|
| 929 |
+
|
| 930 |
+
"""
|
| 931 |
+
if B is not None:
|
| 932 |
+
A = zip(A, B)
|
| 933 |
+
prec, rnd = ctx._prec_rounding
|
| 934 |
+
real = []
|
| 935 |
+
imag = []
|
| 936 |
+
hasattr_ = hasattr
|
| 937 |
+
types = (ctx.mpf, ctx.mpc)
|
| 938 |
+
for a, b in A:
|
| 939 |
+
if type(a) not in types: a = ctx.convert(a)
|
| 940 |
+
if type(b) not in types: b = ctx.convert(b)
|
| 941 |
+
a_real = hasattr_(a, "_mpf_")
|
| 942 |
+
b_real = hasattr_(b, "_mpf_")
|
| 943 |
+
if a_real and b_real:
|
| 944 |
+
real.append(mpf_mul(a._mpf_, b._mpf_))
|
| 945 |
+
continue
|
| 946 |
+
a_complex = hasattr_(a, "_mpc_")
|
| 947 |
+
b_complex = hasattr_(b, "_mpc_")
|
| 948 |
+
if a_real and b_complex:
|
| 949 |
+
aval = a._mpf_
|
| 950 |
+
bre, bim = b._mpc_
|
| 951 |
+
if conjugate:
|
| 952 |
+
bim = mpf_neg(bim)
|
| 953 |
+
real.append(mpf_mul(aval, bre))
|
| 954 |
+
imag.append(mpf_mul(aval, bim))
|
| 955 |
+
elif b_real and a_complex:
|
| 956 |
+
are, aim = a._mpc_
|
| 957 |
+
bval = b._mpf_
|
| 958 |
+
real.append(mpf_mul(are, bval))
|
| 959 |
+
imag.append(mpf_mul(aim, bval))
|
| 960 |
+
elif a_complex and b_complex:
|
| 961 |
+
#re, im = mpc_mul(a._mpc_, b._mpc_, prec+20)
|
| 962 |
+
are, aim = a._mpc_
|
| 963 |
+
bre, bim = b._mpc_
|
| 964 |
+
if conjugate:
|
| 965 |
+
bim = mpf_neg(bim)
|
| 966 |
+
real.append(mpf_mul(are, bre))
|
| 967 |
+
real.append(mpf_neg(mpf_mul(aim, bim)))
|
| 968 |
+
imag.append(mpf_mul(are, bim))
|
| 969 |
+
imag.append(mpf_mul(aim, bre))
|
| 970 |
+
else:
|
| 971 |
+
raise NotImplementedError
|
| 972 |
+
s = mpf_sum(real, prec, rnd)
|
| 973 |
+
if imag:
|
| 974 |
+
s = ctx.make_mpc((s, mpf_sum(imag, prec, rnd)))
|
| 975 |
+
else:
|
| 976 |
+
s = ctx.make_mpf(s)
|
| 977 |
+
return s
|
| 978 |
+
|
| 979 |
+
def _wrap_libmp_function(ctx, mpf_f, mpc_f=None, mpi_f=None, doc="<no doc>"):
|
| 980 |
+
"""
|
| 981 |
+
Given a low-level mpf_ function, and optionally similar functions
|
| 982 |
+
for mpc_ and mpi_, defines the function as a context method.
|
| 983 |
+
|
| 984 |
+
It is assumed that the return type is the same as that of
|
| 985 |
+
the input; the exception is that propagation from mpf to mpc is possible
|
| 986 |
+
by raising ComplexResult.
|
| 987 |
+
|
| 988 |
+
"""
|
| 989 |
+
def f(x, **kwargs):
|
| 990 |
+
if type(x) not in ctx.types:
|
| 991 |
+
x = ctx.convert(x)
|
| 992 |
+
prec, rounding = ctx._prec_rounding
|
| 993 |
+
if kwargs:
|
| 994 |
+
prec = kwargs.get('prec', prec)
|
| 995 |
+
if 'dps' in kwargs:
|
| 996 |
+
prec = dps_to_prec(kwargs['dps'])
|
| 997 |
+
rounding = kwargs.get('rounding', rounding)
|
| 998 |
+
if hasattr(x, '_mpf_'):
|
| 999 |
+
try:
|
| 1000 |
+
return ctx.make_mpf(mpf_f(x._mpf_, prec, rounding))
|
| 1001 |
+
except ComplexResult:
|
| 1002 |
+
# Handle propagation to complex
|
| 1003 |
+
if ctx.trap_complex:
|
| 1004 |
+
raise
|
| 1005 |
+
return ctx.make_mpc(mpc_f((x._mpf_, fzero), prec, rounding))
|
| 1006 |
+
elif hasattr(x, '_mpc_'):
|
| 1007 |
+
return ctx.make_mpc(mpc_f(x._mpc_, prec, rounding))
|
| 1008 |
+
raise NotImplementedError("%s of a %s" % (name, type(x)))
|
| 1009 |
+
name = mpf_f.__name__[4:]
|
| 1010 |
+
f.__doc__ = function_docs.__dict__.get(name, "Computes the %s of x" % doc)
|
| 1011 |
+
return f
|
| 1012 |
+
|
| 1013 |
+
# Called by SpecialFunctions.__init__()
|
| 1014 |
+
@classmethod
|
| 1015 |
+
def _wrap_specfun(cls, name, f, wrap):
|
| 1016 |
+
if wrap:
|
| 1017 |
+
def f_wrapped(ctx, *args, **kwargs):
|
| 1018 |
+
convert = ctx.convert
|
| 1019 |
+
args = [convert(a) for a in args]
|
| 1020 |
+
prec = ctx.prec
|
| 1021 |
+
try:
|
| 1022 |
+
ctx.prec += 10
|
| 1023 |
+
retval = f(ctx, *args, **kwargs)
|
| 1024 |
+
finally:
|
| 1025 |
+
ctx.prec = prec
|
| 1026 |
+
return +retval
|
| 1027 |
+
else:
|
| 1028 |
+
f_wrapped = f
|
| 1029 |
+
f_wrapped.__doc__ = function_docs.__dict__.get(name, f.__doc__)
|
| 1030 |
+
setattr(cls, name, f_wrapped)
|
| 1031 |
+
|
| 1032 |
+
def _convert_param(ctx, x):
|
| 1033 |
+
if hasattr(x, "_mpc_"):
|
| 1034 |
+
v, im = x._mpc_
|
| 1035 |
+
if im != fzero:
|
| 1036 |
+
return x, 'C'
|
| 1037 |
+
elif hasattr(x, "_mpf_"):
|
| 1038 |
+
v = x._mpf_
|
| 1039 |
+
else:
|
| 1040 |
+
if type(x) in int_types:
|
| 1041 |
+
return int(x), 'Z'
|
| 1042 |
+
p = None
|
| 1043 |
+
if isinstance(x, tuple):
|
| 1044 |
+
p, q = x
|
| 1045 |
+
elif hasattr(x, '_mpq_'):
|
| 1046 |
+
p, q = x._mpq_
|
| 1047 |
+
elif isinstance(x, basestring) and '/' in x:
|
| 1048 |
+
p, q = x.split('/')
|
| 1049 |
+
p = int(p)
|
| 1050 |
+
q = int(q)
|
| 1051 |
+
if p is not None:
|
| 1052 |
+
if not p % q:
|
| 1053 |
+
return p // q, 'Z'
|
| 1054 |
+
return ctx.mpq(p,q), 'Q'
|
| 1055 |
+
x = ctx.convert(x)
|
| 1056 |
+
if hasattr(x, "_mpc_"):
|
| 1057 |
+
v, im = x._mpc_
|
| 1058 |
+
if im != fzero:
|
| 1059 |
+
return x, 'C'
|
| 1060 |
+
elif hasattr(x, "_mpf_"):
|
| 1061 |
+
v = x._mpf_
|
| 1062 |
+
else:
|
| 1063 |
+
return x, 'U'
|
| 1064 |
+
sign, man, exp, bc = v
|
| 1065 |
+
if man:
|
| 1066 |
+
if exp >= -4:
|
| 1067 |
+
if sign:
|
| 1068 |
+
man = -man
|
| 1069 |
+
if exp >= 0:
|
| 1070 |
+
return int(man) << exp, 'Z'
|
| 1071 |
+
if exp >= -4:
|
| 1072 |
+
p, q = int(man), (1<<(-exp))
|
| 1073 |
+
return ctx.mpq(p,q), 'Q'
|
| 1074 |
+
x = ctx.make_mpf(v)
|
| 1075 |
+
return x, 'R'
|
| 1076 |
+
elif not exp:
|
| 1077 |
+
return 0, 'Z'
|
| 1078 |
+
else:
|
| 1079 |
+
return x, 'U'
|
| 1080 |
+
|
| 1081 |
+
def _mpf_mag(ctx, x):
|
| 1082 |
+
sign, man, exp, bc = x
|
| 1083 |
+
if man:
|
| 1084 |
+
return exp+bc
|
| 1085 |
+
if x == fzero:
|
| 1086 |
+
return ctx.ninf
|
| 1087 |
+
if x == finf or x == fninf:
|
| 1088 |
+
return ctx.inf
|
| 1089 |
+
return ctx.nan
|
| 1090 |
+
|
| 1091 |
+
def mag(ctx, x):
|
| 1092 |
+
"""
|
| 1093 |
+
Quick logarithmic magnitude estimate of a number. Returns an
|
| 1094 |
+
integer or infinity `m` such that `|x| <= 2^m`. It is not
|
| 1095 |
+
guaranteed that `m` is an optimal bound, but it will never
|
| 1096 |
+
be too large by more than 2 (and probably not more than 1).
|
| 1097 |
+
|
| 1098 |
+
**Examples**
|
| 1099 |
+
|
| 1100 |
+
>>> from mpmath import *
|
| 1101 |
+
>>> mp.pretty = True
|
| 1102 |
+
>>> mag(10), mag(10.0), mag(mpf(10)), int(ceil(log(10,2)))
|
| 1103 |
+
(4, 4, 4, 4)
|
| 1104 |
+
>>> mag(10j), mag(10+10j)
|
| 1105 |
+
(4, 5)
|
| 1106 |
+
>>> mag(0.01), int(ceil(log(0.01,2)))
|
| 1107 |
+
(-6, -6)
|
| 1108 |
+
>>> mag(0), mag(inf), mag(-inf), mag(nan)
|
| 1109 |
+
(-inf, +inf, +inf, nan)
|
| 1110 |
+
|
| 1111 |
+
"""
|
| 1112 |
+
if hasattr(x, "_mpf_"):
|
| 1113 |
+
return ctx._mpf_mag(x._mpf_)
|
| 1114 |
+
elif hasattr(x, "_mpc_"):
|
| 1115 |
+
r, i = x._mpc_
|
| 1116 |
+
if r == fzero:
|
| 1117 |
+
return ctx._mpf_mag(i)
|
| 1118 |
+
if i == fzero:
|
| 1119 |
+
return ctx._mpf_mag(r)
|
| 1120 |
+
return 1+max(ctx._mpf_mag(r), ctx._mpf_mag(i))
|
| 1121 |
+
elif isinstance(x, int_types):
|
| 1122 |
+
if x:
|
| 1123 |
+
return bitcount(abs(x))
|
| 1124 |
+
return ctx.ninf
|
| 1125 |
+
elif isinstance(x, rational.mpq):
|
| 1126 |
+
p, q = x._mpq_
|
| 1127 |
+
if p:
|
| 1128 |
+
return 1 + bitcount(abs(p)) - bitcount(q)
|
| 1129 |
+
return ctx.ninf
|
| 1130 |
+
else:
|
| 1131 |
+
x = ctx.convert(x)
|
| 1132 |
+
if hasattr(x, "_mpf_") or hasattr(x, "_mpc_"):
|
| 1133 |
+
return ctx.mag(x)
|
| 1134 |
+
else:
|
| 1135 |
+
raise TypeError("requires an mpf/mpc")
|
| 1136 |
+
|
| 1137 |
+
|
| 1138 |
+
# Register with "numbers" ABC
|
| 1139 |
+
# We do not subclass, hence we do not use the @abstractmethod checks. While
|
| 1140 |
+
# this is less invasive it may turn out that we do not actually support
|
| 1141 |
+
# parts of the expected interfaces. See
|
| 1142 |
+
# http://docs.python.org/2/library/numbers.html for list of abstract
|
| 1143 |
+
# methods.
|
| 1144 |
+
try:
|
| 1145 |
+
import numbers
|
| 1146 |
+
numbers.Complex.register(_mpc)
|
| 1147 |
+
numbers.Real.register(_mpf)
|
| 1148 |
+
except ImportError:
|
| 1149 |
+
pass
|
tuning-competition-baseline/.venv/lib/python3.11/site-packages/mpmath/identification.py
ADDED
|
@@ -0,0 +1,844 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"""
|
| 2 |
+
Implements the PSLQ algorithm for integer relation detection,
|
| 3 |
+
and derivative algorithms for constant recognition.
|
| 4 |
+
"""
|
| 5 |
+
|
| 6 |
+
from .libmp.backend import xrange
|
| 7 |
+
from .libmp import int_types, sqrt_fixed
|
| 8 |
+
|
| 9 |
+
# round to nearest integer (can be done more elegantly...)
|
| 10 |
+
def round_fixed(x, prec):
|
| 11 |
+
return ((x + (1<<(prec-1))) >> prec) << prec
|
| 12 |
+
|
| 13 |
+
class IdentificationMethods(object):
|
| 14 |
+
pass
|
| 15 |
+
|
| 16 |
+
|
| 17 |
+
def pslq(ctx, x, tol=None, maxcoeff=1000, maxsteps=100, verbose=False):
|
| 18 |
+
r"""
|
| 19 |
+
Given a vector of real numbers `x = [x_0, x_1, ..., x_n]`, ``pslq(x)``
|
| 20 |
+
uses the PSLQ algorithm to find a list of integers
|
| 21 |
+
`[c_0, c_1, ..., c_n]` such that
|
| 22 |
+
|
| 23 |
+
.. math ::
|
| 24 |
+
|
| 25 |
+
|c_1 x_1 + c_2 x_2 + ... + c_n x_n| < \mathrm{tol}
|
| 26 |
+
|
| 27 |
+
and such that `\max |c_k| < \mathrm{maxcoeff}`. If no such vector
|
| 28 |
+
exists, :func:`~mpmath.pslq` returns ``None``. The tolerance defaults to
|
| 29 |
+
3/4 of the working precision.
|
| 30 |
+
|
| 31 |
+
**Examples**
|
| 32 |
+
|
| 33 |
+
Find rational approximations for `\pi`::
|
| 34 |
+
|
| 35 |
+
>>> from mpmath import *
|
| 36 |
+
>>> mp.dps = 15; mp.pretty = True
|
| 37 |
+
>>> pslq([-1, pi], tol=0.01)
|
| 38 |
+
[22, 7]
|
| 39 |
+
>>> pslq([-1, pi], tol=0.001)
|
| 40 |
+
[355, 113]
|
| 41 |
+
>>> mpf(22)/7; mpf(355)/113; +pi
|
| 42 |
+
3.14285714285714
|
| 43 |
+
3.14159292035398
|
| 44 |
+
3.14159265358979
|
| 45 |
+
|
| 46 |
+
Pi is not a rational number with denominator less than 1000::
|
| 47 |
+
|
| 48 |
+
>>> pslq([-1, pi])
|
| 49 |
+
>>>
|
| 50 |
+
|
| 51 |
+
To within the standard precision, it can however be approximated
|
| 52 |
+
by at least one rational number with denominator less than `10^{12}`::
|
| 53 |
+
|
| 54 |
+
>>> p, q = pslq([-1, pi], maxcoeff=10**12)
|
| 55 |
+
>>> print(p); print(q)
|
| 56 |
+
238410049439
|
| 57 |
+
75888275702
|
| 58 |
+
>>> mpf(p)/q
|
| 59 |
+
3.14159265358979
|
| 60 |
+
|
| 61 |
+
The PSLQ algorithm can be applied to long vectors. For example,
|
| 62 |
+
we can investigate the rational (in)dependence of integer square
|
| 63 |
+
roots::
|
| 64 |
+
|
| 65 |
+
>>> mp.dps = 30
|
| 66 |
+
>>> pslq([sqrt(n) for n in range(2, 5+1)])
|
| 67 |
+
>>>
|
| 68 |
+
>>> pslq([sqrt(n) for n in range(2, 6+1)])
|
| 69 |
+
>>>
|
| 70 |
+
>>> pslq([sqrt(n) for n in range(2, 8+1)])
|
| 71 |
+
[2, 0, 0, 0, 0, 0, -1]
|
| 72 |
+
|
| 73 |
+
**Machin formulas**
|
| 74 |
+
|
| 75 |
+
A famous formula for `\pi` is Machin's,
|
| 76 |
+
|
| 77 |
+
.. math ::
|
| 78 |
+
|
| 79 |
+
\frac{\pi}{4} = 4 \operatorname{acot} 5 - \operatorname{acot} 239
|
| 80 |
+
|
| 81 |
+
There are actually infinitely many formulas of this type. Two
|
| 82 |
+
others are
|
| 83 |
+
|
| 84 |
+
.. math ::
|
| 85 |
+
|
| 86 |
+
\frac{\pi}{4} = \operatorname{acot} 1
|
| 87 |
+
|
| 88 |
+
\frac{\pi}{4} = 12 \operatorname{acot} 49 + 32 \operatorname{acot} 57
|
| 89 |
+
+ 5 \operatorname{acot} 239 + 12 \operatorname{acot} 110443
|
| 90 |
+
|
| 91 |
+
We can easily verify the formulas using the PSLQ algorithm::
|
| 92 |
+
|
| 93 |
+
>>> mp.dps = 30
|
| 94 |
+
>>> pslq([pi/4, acot(1)])
|
| 95 |
+
[1, -1]
|
| 96 |
+
>>> pslq([pi/4, acot(5), acot(239)])
|
| 97 |
+
[1, -4, 1]
|
| 98 |
+
>>> pslq([pi/4, acot(49), acot(57), acot(239), acot(110443)])
|
| 99 |
+
[1, -12, -32, 5, -12]
|
| 100 |
+
|
| 101 |
+
We could try to generate a custom Machin-like formula by running
|
| 102 |
+
the PSLQ algorithm with a few inverse cotangent values, for example
|
| 103 |
+
acot(2), acot(3) ... acot(10). Unfortunately, there is a linear
|
| 104 |
+
dependence among these values, resulting in only that dependence
|
| 105 |
+
being detected, with a zero coefficient for `\pi`::
|
| 106 |
+
|
| 107 |
+
>>> pslq([pi] + [acot(n) for n in range(2,11)])
|
| 108 |
+
[0, 1, -1, 0, 0, 0, -1, 0, 0, 0]
|
| 109 |
+
|
| 110 |
+
We get better luck by removing linearly dependent terms::
|
| 111 |
+
|
| 112 |
+
>>> pslq([pi] + [acot(n) for n in range(2,11) if n not in (3, 5)])
|
| 113 |
+
[1, -8, 0, 0, 4, 0, 0, 0]
|
| 114 |
+
|
| 115 |
+
In other words, we found the following formula::
|
| 116 |
+
|
| 117 |
+
>>> 8*acot(2) - 4*acot(7)
|
| 118 |
+
3.14159265358979323846264338328
|
| 119 |
+
>>> +pi
|
| 120 |
+
3.14159265358979323846264338328
|
| 121 |
+
|
| 122 |
+
**Algorithm**
|
| 123 |
+
|
| 124 |
+
This is a fairly direct translation to Python of the pseudocode given by
|
| 125 |
+
David Bailey, "The PSLQ Integer Relation Algorithm":
|
| 126 |
+
http://www.cecm.sfu.ca/organics/papers/bailey/paper/html/node3.html
|
| 127 |
+
|
| 128 |
+
The present implementation uses fixed-point instead of floating-point
|
| 129 |
+
arithmetic, since this is significantly (about 7x) faster.
|
| 130 |
+
"""
|
| 131 |
+
|
| 132 |
+
n = len(x)
|
| 133 |
+
if n < 2:
|
| 134 |
+
raise ValueError("n cannot be less than 2")
|
| 135 |
+
|
| 136 |
+
# At too low precision, the algorithm becomes meaningless
|
| 137 |
+
prec = ctx.prec
|
| 138 |
+
if prec < 53:
|
| 139 |
+
raise ValueError("prec cannot be less than 53")
|
| 140 |
+
|
| 141 |
+
if verbose and prec // max(2,n) < 5:
|
| 142 |
+
print("Warning: precision for PSLQ may be too low")
|
| 143 |
+
|
| 144 |
+
target = int(prec * 0.75)
|
| 145 |
+
|
| 146 |
+
if tol is None:
|
| 147 |
+
tol = ctx.mpf(2)**(-target)
|
| 148 |
+
else:
|
| 149 |
+
tol = ctx.convert(tol)
|
| 150 |
+
|
| 151 |
+
extra = 60
|
| 152 |
+
prec += extra
|
| 153 |
+
|
| 154 |
+
if verbose:
|
| 155 |
+
print("PSLQ using prec %i and tol %s" % (prec, ctx.nstr(tol)))
|
| 156 |
+
|
| 157 |
+
tol = ctx.to_fixed(tol, prec)
|
| 158 |
+
assert tol
|
| 159 |
+
|
| 160 |
+
# Convert to fixed-point numbers. The dummy None is added so we can
|
| 161 |
+
# use 1-based indexing. (This just allows us to be consistent with
|
| 162 |
+
# Bailey's indexing. The algorithm is 100 lines long, so debugging
|
| 163 |
+
# a single wrong index can be painful.)
|
| 164 |
+
x = [None] + [ctx.to_fixed(ctx.mpf(xk), prec) for xk in x]
|
| 165 |
+
|
| 166 |
+
# Sanity check on magnitudes
|
| 167 |
+
minx = min(abs(xx) for xx in x[1:])
|
| 168 |
+
if not minx:
|
| 169 |
+
raise ValueError("PSLQ requires a vector of nonzero numbers")
|
| 170 |
+
if minx < tol//100:
|
| 171 |
+
if verbose:
|
| 172 |
+
print("STOPPING: (one number is too small)")
|
| 173 |
+
return None
|
| 174 |
+
|
| 175 |
+
g = sqrt_fixed((4<<prec)//3, prec)
|
| 176 |
+
A = {}
|
| 177 |
+
B = {}
|
| 178 |
+
H = {}
|
| 179 |
+
# Initialization
|
| 180 |
+
# step 1
|
| 181 |
+
for i in xrange(1, n+1):
|
| 182 |
+
for j in xrange(1, n+1):
|
| 183 |
+
A[i,j] = B[i,j] = (i==j) << prec
|
| 184 |
+
H[i,j] = 0
|
| 185 |
+
# step 2
|
| 186 |
+
s = [None] + [0] * n
|
| 187 |
+
for k in xrange(1, n+1):
|
| 188 |
+
t = 0
|
| 189 |
+
for j in xrange(k, n+1):
|
| 190 |
+
t += (x[j]**2 >> prec)
|
| 191 |
+
s[k] = sqrt_fixed(t, prec)
|
| 192 |
+
t = s[1]
|
| 193 |
+
y = x[:]
|
| 194 |
+
for k in xrange(1, n+1):
|
| 195 |
+
y[k] = (x[k] << prec) // t
|
| 196 |
+
s[k] = (s[k] << prec) // t
|
| 197 |
+
# step 3
|
| 198 |
+
for i in xrange(1, n+1):
|
| 199 |
+
for j in xrange(i+1, n):
|
| 200 |
+
H[i,j] = 0
|
| 201 |
+
if i <= n-1:
|
| 202 |
+
if s[i]:
|
| 203 |
+
H[i,i] = (s[i+1] << prec) // s[i]
|
| 204 |
+
else:
|
| 205 |
+
H[i,i] = 0
|
| 206 |
+
for j in range(1, i):
|
| 207 |
+
sjj1 = s[j]*s[j+1]
|
| 208 |
+
if sjj1:
|
| 209 |
+
H[i,j] = ((-y[i]*y[j])<<prec)//sjj1
|
| 210 |
+
else:
|
| 211 |
+
H[i,j] = 0
|
| 212 |
+
# step 4
|
| 213 |
+
for i in xrange(2, n+1):
|
| 214 |
+
for j in xrange(i-1, 0, -1):
|
| 215 |
+
#t = floor(H[i,j]/H[j,j] + 0.5)
|
| 216 |
+
if H[j,j]:
|
| 217 |
+
t = round_fixed((H[i,j] << prec)//H[j,j], prec)
|
| 218 |
+
else:
|
| 219 |
+
#t = 0
|
| 220 |
+
continue
|
| 221 |
+
y[j] = y[j] + (t*y[i] >> prec)
|
| 222 |
+
for k in xrange(1, j+1):
|
| 223 |
+
H[i,k] = H[i,k] - (t*H[j,k] >> prec)
|
| 224 |
+
for k in xrange(1, n+1):
|
| 225 |
+
A[i,k] = A[i,k] - (t*A[j,k] >> prec)
|
| 226 |
+
B[k,j] = B[k,j] + (t*B[k,i] >> prec)
|
| 227 |
+
# Main algorithm
|
| 228 |
+
for REP in range(maxsteps):
|
| 229 |
+
# Step 1
|
| 230 |
+
m = -1
|
| 231 |
+
szmax = -1
|
| 232 |
+
for i in range(1, n):
|
| 233 |
+
h = H[i,i]
|
| 234 |
+
sz = (g**i * abs(h)) >> (prec*(i-1))
|
| 235 |
+
if sz > szmax:
|
| 236 |
+
m = i
|
| 237 |
+
szmax = sz
|
| 238 |
+
# Step 2
|
| 239 |
+
y[m], y[m+1] = y[m+1], y[m]
|
| 240 |
+
for i in xrange(1,n+1): H[m,i], H[m+1,i] = H[m+1,i], H[m,i]
|
| 241 |
+
for i in xrange(1,n+1): A[m,i], A[m+1,i] = A[m+1,i], A[m,i]
|
| 242 |
+
for i in xrange(1,n+1): B[i,m], B[i,m+1] = B[i,m+1], B[i,m]
|
| 243 |
+
# Step 3
|
| 244 |
+
if m <= n - 2:
|
| 245 |
+
t0 = sqrt_fixed((H[m,m]**2 + H[m,m+1]**2)>>prec, prec)
|
| 246 |
+
# A zero element probably indicates that the precision has
|
| 247 |
+
# been exhausted. XXX: this could be spurious, due to
|
| 248 |
+
# using fixed-point arithmetic
|
| 249 |
+
if not t0:
|
| 250 |
+
break
|
| 251 |
+
t1 = (H[m,m] << prec) // t0
|
| 252 |
+
t2 = (H[m,m+1] << prec) // t0
|
| 253 |
+
for i in xrange(m, n+1):
|
| 254 |
+
t3 = H[i,m]
|
| 255 |
+
t4 = H[i,m+1]
|
| 256 |
+
H[i,m] = (t1*t3+t2*t4) >> prec
|
| 257 |
+
H[i,m+1] = (-t2*t3+t1*t4) >> prec
|
| 258 |
+
# Step 4
|
| 259 |
+
for i in xrange(m+1, n+1):
|
| 260 |
+
for j in xrange(min(i-1, m+1), 0, -1):
|
| 261 |
+
try:
|
| 262 |
+
t = round_fixed((H[i,j] << prec)//H[j,j], prec)
|
| 263 |
+
# Precision probably exhausted
|
| 264 |
+
except ZeroDivisionError:
|
| 265 |
+
break
|
| 266 |
+
y[j] = y[j] + ((t*y[i]) >> prec)
|
| 267 |
+
for k in xrange(1, j+1):
|
| 268 |
+
H[i,k] = H[i,k] - (t*H[j,k] >> prec)
|
| 269 |
+
for k in xrange(1, n+1):
|
| 270 |
+
A[i,k] = A[i,k] - (t*A[j,k] >> prec)
|
| 271 |
+
B[k,j] = B[k,j] + (t*B[k,i] >> prec)
|
| 272 |
+
# Until a relation is found, the error typically decreases
|
| 273 |
+
# slowly (e.g. a factor 1-10) with each step TODO: we could
|
| 274 |
+
# compare err from two successive iterations. If there is a
|
| 275 |
+
# large drop (several orders of magnitude), that indicates a
|
| 276 |
+
# "high quality" relation was detected. Reporting this to
|
| 277 |
+
# the user somehow might be useful.
|
| 278 |
+
best_err = maxcoeff<<prec
|
| 279 |
+
for i in xrange(1, n+1):
|
| 280 |
+
err = abs(y[i])
|
| 281 |
+
# Maybe we are done?
|
| 282 |
+
if err < tol:
|
| 283 |
+
# We are done if the coefficients are acceptable
|
| 284 |
+
vec = [int(round_fixed(B[j,i], prec) >> prec) for j in \
|
| 285 |
+
range(1,n+1)]
|
| 286 |
+
if max(abs(v) for v in vec) < maxcoeff:
|
| 287 |
+
if verbose:
|
| 288 |
+
print("FOUND relation at iter %i/%i, error: %s" % \
|
| 289 |
+
(REP, maxsteps, ctx.nstr(err / ctx.mpf(2)**prec, 1)))
|
| 290 |
+
return vec
|
| 291 |
+
best_err = min(err, best_err)
|
| 292 |
+
# Calculate a lower bound for the norm. We could do this
|
| 293 |
+
# more exactly (using the Euclidean norm) but there is probably
|
| 294 |
+
# no practical benefit.
|
| 295 |
+
recnorm = max(abs(h) for h in H.values())
|
| 296 |
+
if recnorm:
|
| 297 |
+
norm = ((1 << (2*prec)) // recnorm) >> prec
|
| 298 |
+
norm //= 100
|
| 299 |
+
else:
|
| 300 |
+
norm = ctx.inf
|
| 301 |
+
if verbose:
|
| 302 |
+
print("%i/%i: Error: %8s Norm: %s" % \
|
| 303 |
+
(REP, maxsteps, ctx.nstr(best_err / ctx.mpf(2)**prec, 1), norm))
|
| 304 |
+
if norm >= maxcoeff:
|
| 305 |
+
break
|
| 306 |
+
if verbose:
|
| 307 |
+
print("CANCELLING after step %i/%i." % (REP, maxsteps))
|
| 308 |
+
print("Could not find an integer relation. Norm bound: %s" % norm)
|
| 309 |
+
return None
|
| 310 |
+
|
| 311 |
+
def findpoly(ctx, x, n=1, **kwargs):
|
| 312 |
+
r"""
|
| 313 |
+
``findpoly(x, n)`` returns the coefficients of an integer
|
| 314 |
+
polynomial `P` of degree at most `n` such that `P(x) \approx 0`.
|
| 315 |
+
If no polynomial having `x` as a root can be found,
|
| 316 |
+
:func:`~mpmath.findpoly` returns ``None``.
|
| 317 |
+
|
| 318 |
+
:func:`~mpmath.findpoly` works by successively calling :func:`~mpmath.pslq` with
|
| 319 |
+
the vectors `[1, x]`, `[1, x, x^2]`, `[1, x, x^2, x^3]`, ...,
|
| 320 |
+
`[1, x, x^2, .., x^n]` as input. Keyword arguments given to
|
| 321 |
+
:func:`~mpmath.findpoly` are forwarded verbatim to :func:`~mpmath.pslq`. In
|
| 322 |
+
particular, you can specify a tolerance for `P(x)` with ``tol``
|
| 323 |
+
and a maximum permitted coefficient size with ``maxcoeff``.
|
| 324 |
+
|
| 325 |
+
For large values of `n`, it is recommended to run :func:`~mpmath.findpoly`
|
| 326 |
+
at high precision; preferably 50 digits or more.
|
| 327 |
+
|
| 328 |
+
**Examples**
|
| 329 |
+
|
| 330 |
+
By default (degree `n = 1`), :func:`~mpmath.findpoly` simply finds a linear
|
| 331 |
+
polynomial with a rational root::
|
| 332 |
+
|
| 333 |
+
>>> from mpmath import *
|
| 334 |
+
>>> mp.dps = 15; mp.pretty = True
|
| 335 |
+
>>> findpoly(0.7)
|
| 336 |
+
[-10, 7]
|
| 337 |
+
|
| 338 |
+
The generated coefficient list is valid input to ``polyval`` and
|
| 339 |
+
``polyroots``::
|
| 340 |
+
|
| 341 |
+
>>> nprint(polyval(findpoly(phi, 2), phi), 1)
|
| 342 |
+
-2.0e-16
|
| 343 |
+
>>> for r in polyroots(findpoly(phi, 2)):
|
| 344 |
+
... print(r)
|
| 345 |
+
...
|
| 346 |
+
-0.618033988749895
|
| 347 |
+
1.61803398874989
|
| 348 |
+
|
| 349 |
+
Numbers of the form `m + n \sqrt p` for integers `(m, n, p)` are
|
| 350 |
+
solutions to quadratic equations. As we find here, `1+\sqrt 2`
|
| 351 |
+
is a root of the polynomial `x^2 - 2x - 1`::
|
| 352 |
+
|
| 353 |
+
>>> findpoly(1+sqrt(2), 2)
|
| 354 |
+
[1, -2, -1]
|
| 355 |
+
>>> findroot(lambda x: x**2 - 2*x - 1, 1)
|
| 356 |
+
2.4142135623731
|
| 357 |
+
|
| 358 |
+
Despite only containing square roots, the following number results
|
| 359 |
+
in a polynomial of degree 4::
|
| 360 |
+
|
| 361 |
+
>>> findpoly(sqrt(2)+sqrt(3), 4)
|
| 362 |
+
[1, 0, -10, 0, 1]
|
| 363 |
+
|
| 364 |
+
In fact, `x^4 - 10x^2 + 1` is the *minimal polynomial* of
|
| 365 |
+
`r = \sqrt 2 + \sqrt 3`, meaning that a rational polynomial of
|
| 366 |
+
lower degree having `r` as a root does not exist. Given sufficient
|
| 367 |
+
precision, :func:`~mpmath.findpoly` will usually find the correct
|
| 368 |
+
minimal polynomial of a given algebraic number.
|
| 369 |
+
|
| 370 |
+
**Non-algebraic numbers**
|
| 371 |
+
|
| 372 |
+
If :func:`~mpmath.findpoly` fails to find a polynomial with given
|
| 373 |
+
coefficient size and tolerance constraints, that means no such
|
| 374 |
+
polynomial exists.
|
| 375 |
+
|
| 376 |
+
We can verify that `\pi` is not an algebraic number of degree 3 with
|
| 377 |
+
coefficients less than 1000::
|
| 378 |
+
|
| 379 |
+
>>> mp.dps = 15
|
| 380 |
+
>>> findpoly(pi, 3)
|
| 381 |
+
>>>
|
| 382 |
+
|
| 383 |
+
It is always possible to find an algebraic approximation of a number
|
| 384 |
+
using one (or several) of the following methods:
|
| 385 |
+
|
| 386 |
+
1. Increasing the permitted degree
|
| 387 |
+
2. Allowing larger coefficients
|
| 388 |
+
3. Reducing the tolerance
|
| 389 |
+
|
| 390 |
+
One example of each method is shown below::
|
| 391 |
+
|
| 392 |
+
>>> mp.dps = 15
|
| 393 |
+
>>> findpoly(pi, 4)
|
| 394 |
+
[95, -545, 863, -183, -298]
|
| 395 |
+
>>> findpoly(pi, 3, maxcoeff=10000)
|
| 396 |
+
[836, -1734, -2658, -457]
|
| 397 |
+
>>> findpoly(pi, 3, tol=1e-7)
|
| 398 |
+
[-4, 22, -29, -2]
|
| 399 |
+
|
| 400 |
+
It is unknown whether Euler's constant is transcendental (or even
|
| 401 |
+
irrational). We can use :func:`~mpmath.findpoly` to check that if is
|
| 402 |
+
an algebraic number, its minimal polynomial must have degree
|
| 403 |
+
at least 7 and a coefficient of magnitude at least 1000000::
|
| 404 |
+
|
| 405 |
+
>>> mp.dps = 200
|
| 406 |
+
>>> findpoly(euler, 6, maxcoeff=10**6, tol=1e-100, maxsteps=1000)
|
| 407 |
+
>>>
|
| 408 |
+
|
| 409 |
+
Note that the high precision and strict tolerance is necessary
|
| 410 |
+
for such high-degree runs, since otherwise unwanted low-accuracy
|
| 411 |
+
approximations will be detected. It may also be necessary to set
|
| 412 |
+
maxsteps high to prevent a premature exit (before the coefficient
|
| 413 |
+
bound has been reached). Running with ``verbose=True`` to get an
|
| 414 |
+
idea what is happening can be useful.
|
| 415 |
+
"""
|
| 416 |
+
x = ctx.mpf(x)
|
| 417 |
+
if n < 1:
|
| 418 |
+
raise ValueError("n cannot be less than 1")
|
| 419 |
+
if x == 0:
|
| 420 |
+
return [1, 0]
|
| 421 |
+
xs = [ctx.mpf(1)]
|
| 422 |
+
for i in range(1,n+1):
|
| 423 |
+
xs.append(x**i)
|
| 424 |
+
a = ctx.pslq(xs, **kwargs)
|
| 425 |
+
if a is not None:
|
| 426 |
+
return a[::-1]
|
| 427 |
+
|
| 428 |
+
def fracgcd(p, q):
|
| 429 |
+
x, y = p, q
|
| 430 |
+
while y:
|
| 431 |
+
x, y = y, x % y
|
| 432 |
+
if x != 1:
|
| 433 |
+
p //= x
|
| 434 |
+
q //= x
|
| 435 |
+
if q == 1:
|
| 436 |
+
return p
|
| 437 |
+
return p, q
|
| 438 |
+
|
| 439 |
+
def pslqstring(r, constants):
|
| 440 |
+
q = r[0]
|
| 441 |
+
r = r[1:]
|
| 442 |
+
s = []
|
| 443 |
+
for i in range(len(r)):
|
| 444 |
+
p = r[i]
|
| 445 |
+
if p:
|
| 446 |
+
z = fracgcd(-p,q)
|
| 447 |
+
cs = constants[i][1]
|
| 448 |
+
if cs == '1':
|
| 449 |
+
cs = ''
|
| 450 |
+
else:
|
| 451 |
+
cs = '*' + cs
|
| 452 |
+
if isinstance(z, int_types):
|
| 453 |
+
if z > 0: term = str(z) + cs
|
| 454 |
+
else: term = ("(%s)" % z) + cs
|
| 455 |
+
else:
|
| 456 |
+
term = ("(%s/%s)" % z) + cs
|
| 457 |
+
s.append(term)
|
| 458 |
+
s = ' + '.join(s)
|
| 459 |
+
if '+' in s or '*' in s:
|
| 460 |
+
s = '(' + s + ')'
|
| 461 |
+
return s or '0'
|
| 462 |
+
|
| 463 |
+
def prodstring(r, constants):
|
| 464 |
+
q = r[0]
|
| 465 |
+
r = r[1:]
|
| 466 |
+
num = []
|
| 467 |
+
den = []
|
| 468 |
+
for i in range(len(r)):
|
| 469 |
+
p = r[i]
|
| 470 |
+
if p:
|
| 471 |
+
z = fracgcd(-p,q)
|
| 472 |
+
cs = constants[i][1]
|
| 473 |
+
if isinstance(z, int_types):
|
| 474 |
+
if abs(z) == 1: t = cs
|
| 475 |
+
else: t = '%s**%s' % (cs, abs(z))
|
| 476 |
+
([num,den][z<0]).append(t)
|
| 477 |
+
else:
|
| 478 |
+
t = '%s**(%s/%s)' % (cs, abs(z[0]), z[1])
|
| 479 |
+
([num,den][z[0]<0]).append(t)
|
| 480 |
+
num = '*'.join(num)
|
| 481 |
+
den = '*'.join(den)
|
| 482 |
+
if num and den: return "(%s)/(%s)" % (num, den)
|
| 483 |
+
if num: return num
|
| 484 |
+
if den: return "1/(%s)" % den
|
| 485 |
+
|
| 486 |
+
def quadraticstring(ctx,t,a,b,c):
|
| 487 |
+
if c < 0:
|
| 488 |
+
a,b,c = -a,-b,-c
|
| 489 |
+
u1 = (-b+ctx.sqrt(b**2-4*a*c))/(2*c)
|
| 490 |
+
u2 = (-b-ctx.sqrt(b**2-4*a*c))/(2*c)
|
| 491 |
+
if abs(u1-t) < abs(u2-t):
|
| 492 |
+
if b: s = '((%s+sqrt(%s))/%s)' % (-b,b**2-4*a*c,2*c)
|
| 493 |
+
else: s = '(sqrt(%s)/%s)' % (-4*a*c,2*c)
|
| 494 |
+
else:
|
| 495 |
+
if b: s = '((%s-sqrt(%s))/%s)' % (-b,b**2-4*a*c,2*c)
|
| 496 |
+
else: s = '(-sqrt(%s)/%s)' % (-4*a*c,2*c)
|
| 497 |
+
return s
|
| 498 |
+
|
| 499 |
+
# Transformation y = f(x,c), with inverse function x = f(y,c)
|
| 500 |
+
# The third entry indicates whether the transformation is
|
| 501 |
+
# redundant when c = 1
|
| 502 |
+
transforms = [
|
| 503 |
+
(lambda ctx,x,c: x*c, '$y/$c', 0),
|
| 504 |
+
(lambda ctx,x,c: x/c, '$c*$y', 1),
|
| 505 |
+
(lambda ctx,x,c: c/x, '$c/$y', 0),
|
| 506 |
+
(lambda ctx,x,c: (x*c)**2, 'sqrt($y)/$c', 0),
|
| 507 |
+
(lambda ctx,x,c: (x/c)**2, '$c*sqrt($y)', 1),
|
| 508 |
+
(lambda ctx,x,c: (c/x)**2, '$c/sqrt($y)', 0),
|
| 509 |
+
(lambda ctx,x,c: c*x**2, 'sqrt($y)/sqrt($c)', 1),
|
| 510 |
+
(lambda ctx,x,c: x**2/c, 'sqrt($c)*sqrt($y)', 1),
|
| 511 |
+
(lambda ctx,x,c: c/x**2, 'sqrt($c)/sqrt($y)', 1),
|
| 512 |
+
(lambda ctx,x,c: ctx.sqrt(x*c), '$y**2/$c', 0),
|
| 513 |
+
(lambda ctx,x,c: ctx.sqrt(x/c), '$c*$y**2', 1),
|
| 514 |
+
(lambda ctx,x,c: ctx.sqrt(c/x), '$c/$y**2', 0),
|
| 515 |
+
(lambda ctx,x,c: c*ctx.sqrt(x), '$y**2/$c**2', 1),
|
| 516 |
+
(lambda ctx,x,c: ctx.sqrt(x)/c, '$c**2*$y**2', 1),
|
| 517 |
+
(lambda ctx,x,c: c/ctx.sqrt(x), '$c**2/$y**2', 1),
|
| 518 |
+
(lambda ctx,x,c: ctx.exp(x*c), 'log($y)/$c', 0),
|
| 519 |
+
(lambda ctx,x,c: ctx.exp(x/c), '$c*log($y)', 1),
|
| 520 |
+
(lambda ctx,x,c: ctx.exp(c/x), '$c/log($y)', 0),
|
| 521 |
+
(lambda ctx,x,c: c*ctx.exp(x), 'log($y/$c)', 1),
|
| 522 |
+
(lambda ctx,x,c: ctx.exp(x)/c, 'log($c*$y)', 1),
|
| 523 |
+
(lambda ctx,x,c: c/ctx.exp(x), 'log($c/$y)', 0),
|
| 524 |
+
(lambda ctx,x,c: ctx.ln(x*c), 'exp($y)/$c', 0),
|
| 525 |
+
(lambda ctx,x,c: ctx.ln(x/c), '$c*exp($y)', 1),
|
| 526 |
+
(lambda ctx,x,c: ctx.ln(c/x), '$c/exp($y)', 0),
|
| 527 |
+
(lambda ctx,x,c: c*ctx.ln(x), 'exp($y/$c)', 1),
|
| 528 |
+
(lambda ctx,x,c: ctx.ln(x)/c, 'exp($c*$y)', 1),
|
| 529 |
+
(lambda ctx,x,c: c/ctx.ln(x), 'exp($c/$y)', 0),
|
| 530 |
+
]
|
| 531 |
+
|
| 532 |
+
def identify(ctx, x, constants=[], tol=None, maxcoeff=1000, full=False,
|
| 533 |
+
verbose=False):
|
| 534 |
+
r"""
|
| 535 |
+
Given a real number `x`, ``identify(x)`` attempts to find an exact
|
| 536 |
+
formula for `x`. This formula is returned as a string. If no match
|
| 537 |
+
is found, ``None`` is returned. With ``full=True``, a list of
|
| 538 |
+
matching formulas is returned.
|
| 539 |
+
|
| 540 |
+
As a simple example, :func:`~mpmath.identify` will find an algebraic
|
| 541 |
+
formula for the golden ratio::
|
| 542 |
+
|
| 543 |
+
>>> from mpmath import *
|
| 544 |
+
>>> mp.dps = 15; mp.pretty = True
|
| 545 |
+
>>> identify(phi)
|
| 546 |
+
'((1+sqrt(5))/2)'
|
| 547 |
+
|
| 548 |
+
:func:`~mpmath.identify` can identify simple algebraic numbers and simple
|
| 549 |
+
combinations of given base constants, as well as certain basic
|
| 550 |
+
transformations thereof. More specifically, :func:`~mpmath.identify`
|
| 551 |
+
looks for the following:
|
| 552 |
+
|
| 553 |
+
1. Fractions
|
| 554 |
+
2. Quadratic algebraic numbers
|
| 555 |
+
3. Rational linear combinations of the base constants
|
| 556 |
+
4. Any of the above after first transforming `x` into `f(x)` where
|
| 557 |
+
`f(x)` is `1/x`, `\sqrt x`, `x^2`, `\log x` or `\exp x`, either
|
| 558 |
+
directly or with `x` or `f(x)` multiplied or divided by one of
|
| 559 |
+
the base constants
|
| 560 |
+
5. Products of fractional powers of the base constants and
|
| 561 |
+
small integers
|
| 562 |
+
|
| 563 |
+
Base constants can be given as a list of strings representing mpmath
|
| 564 |
+
expressions (:func:`~mpmath.identify` will ``eval`` the strings to numerical
|
| 565 |
+
values and use the original strings for the output), or as a dict of
|
| 566 |
+
formula:value pairs.
|
| 567 |
+
|
| 568 |
+
In order not to produce spurious results, :func:`~mpmath.identify` should
|
| 569 |
+
be used with high precision; preferably 50 digits or more.
|
| 570 |
+
|
| 571 |
+
**Examples**
|
| 572 |
+
|
| 573 |
+
Simple identifications can be performed safely at standard
|
| 574 |
+
precision. Here the default recognition of rational, algebraic,
|
| 575 |
+
and exp/log of algebraic numbers is demonstrated::
|
| 576 |
+
|
| 577 |
+
>>> mp.dps = 15
|
| 578 |
+
>>> identify(0.22222222222222222)
|
| 579 |
+
'(2/9)'
|
| 580 |
+
>>> identify(1.9662210973805663)
|
| 581 |
+
'sqrt(((24+sqrt(48))/8))'
|
| 582 |
+
>>> identify(4.1132503787829275)
|
| 583 |
+
'exp((sqrt(8)/2))'
|
| 584 |
+
>>> identify(0.881373587019543)
|
| 585 |
+
'log(((2+sqrt(8))/2))'
|
| 586 |
+
|
| 587 |
+
By default, :func:`~mpmath.identify` does not recognize `\pi`. At standard
|
| 588 |
+
precision it finds a not too useful approximation. At slightly
|
| 589 |
+
increased precision, this approximation is no longer accurate
|
| 590 |
+
enough and :func:`~mpmath.identify` more correctly returns ``None``::
|
| 591 |
+
|
| 592 |
+
>>> identify(pi)
|
| 593 |
+
'(2**(176/117)*3**(20/117)*5**(35/39))/(7**(92/117))'
|
| 594 |
+
>>> mp.dps = 30
|
| 595 |
+
>>> identify(pi)
|
| 596 |
+
>>>
|
| 597 |
+
|
| 598 |
+
Numbers such as `\pi`, and simple combinations of user-defined
|
| 599 |
+
constants, can be identified if they are provided explicitly::
|
| 600 |
+
|
| 601 |
+
>>> identify(3*pi-2*e, ['pi', 'e'])
|
| 602 |
+
'(3*pi + (-2)*e)'
|
| 603 |
+
|
| 604 |
+
Here is an example using a dict of constants. Note that the
|
| 605 |
+
constants need not be "atomic"; :func:`~mpmath.identify` can just
|
| 606 |
+
as well express the given number in terms of expressions
|
| 607 |
+
given by formulas::
|
| 608 |
+
|
| 609 |
+
>>> identify(pi+e, {'a':pi+2, 'b':2*e})
|
| 610 |
+
'((-2) + 1*a + (1/2)*b)'
|
| 611 |
+
|
| 612 |
+
Next, we attempt some identifications with a set of base constants.
|
| 613 |
+
It is necessary to increase the precision a bit.
|
| 614 |
+
|
| 615 |
+
>>> mp.dps = 50
|
| 616 |
+
>>> base = ['sqrt(2)','pi','log(2)']
|
| 617 |
+
>>> identify(0.25, base)
|
| 618 |
+
'(1/4)'
|
| 619 |
+
>>> identify(3*pi + 2*sqrt(2) + 5*log(2)/7, base)
|
| 620 |
+
'(2*sqrt(2) + 3*pi + (5/7)*log(2))'
|
| 621 |
+
>>> identify(exp(pi+2), base)
|
| 622 |
+
'exp((2 + 1*pi))'
|
| 623 |
+
>>> identify(1/(3+sqrt(2)), base)
|
| 624 |
+
'((3/7) + (-1/7)*sqrt(2))'
|
| 625 |
+
>>> identify(sqrt(2)/(3*pi+4), base)
|
| 626 |
+
'sqrt(2)/(4 + 3*pi)'
|
| 627 |
+
>>> identify(5**(mpf(1)/3)*pi*log(2)**2, base)
|
| 628 |
+
'5**(1/3)*pi*log(2)**2'
|
| 629 |
+
|
| 630 |
+
An example of an erroneous solution being found when too low
|
| 631 |
+
precision is used::
|
| 632 |
+
|
| 633 |
+
>>> mp.dps = 15
|
| 634 |
+
>>> identify(1/(3*pi-4*e+sqrt(8)), ['pi', 'e', 'sqrt(2)'])
|
| 635 |
+
'((11/25) + (-158/75)*pi + (76/75)*e + (44/15)*sqrt(2))'
|
| 636 |
+
>>> mp.dps = 50
|
| 637 |
+
>>> identify(1/(3*pi-4*e+sqrt(8)), ['pi', 'e', 'sqrt(2)'])
|
| 638 |
+
'1/(3*pi + (-4)*e + 2*sqrt(2))'
|
| 639 |
+
|
| 640 |
+
**Finding approximate solutions**
|
| 641 |
+
|
| 642 |
+
The tolerance ``tol`` defaults to 3/4 of the working precision.
|
| 643 |
+
Lowering the tolerance is useful for finding approximate matches.
|
| 644 |
+
We can for example try to generate approximations for pi::
|
| 645 |
+
|
| 646 |
+
>>> mp.dps = 15
|
| 647 |
+
>>> identify(pi, tol=1e-2)
|
| 648 |
+
'(22/7)'
|
| 649 |
+
>>> identify(pi, tol=1e-3)
|
| 650 |
+
'(355/113)'
|
| 651 |
+
>>> identify(pi, tol=1e-10)
|
| 652 |
+
'(5**(339/269))/(2**(64/269)*3**(13/269)*7**(92/269))'
|
| 653 |
+
|
| 654 |
+
With ``full=True``, and by supplying a few base constants,
|
| 655 |
+
``identify`` can generate almost endless lists of approximations
|
| 656 |
+
for any number (the output below has been truncated to show only
|
| 657 |
+
the first few)::
|
| 658 |
+
|
| 659 |
+
>>> for p in identify(pi, ['e', 'catalan'], tol=1e-5, full=True):
|
| 660 |
+
... print(p)
|
| 661 |
+
... # doctest: +ELLIPSIS
|
| 662 |
+
e/log((6 + (-4/3)*e))
|
| 663 |
+
(3**3*5*e*catalan**2)/(2*7**2)
|
| 664 |
+
sqrt(((-13) + 1*e + 22*catalan))
|
| 665 |
+
log(((-6) + 24*e + 4*catalan)/e)
|
| 666 |
+
exp(catalan*((-1/5) + (8/15)*e))
|
| 667 |
+
catalan*(6 + (-6)*e + 15*catalan)
|
| 668 |
+
sqrt((5 + 26*e + (-3)*catalan))/e
|
| 669 |
+
e*sqrt(((-27) + 2*e + 25*catalan))
|
| 670 |
+
log(((-1) + (-11)*e + 59*catalan))
|
| 671 |
+
((3/20) + (21/20)*e + (3/20)*catalan)
|
| 672 |
+
...
|
| 673 |
+
|
| 674 |
+
The numerical values are roughly as close to `\pi` as permitted by the
|
| 675 |
+
specified tolerance:
|
| 676 |
+
|
| 677 |
+
>>> e/log(6-4*e/3)
|
| 678 |
+
3.14157719846001
|
| 679 |
+
>>> 135*e*catalan**2/98
|
| 680 |
+
3.14166950419369
|
| 681 |
+
>>> sqrt(e-13+22*catalan)
|
| 682 |
+
3.14158000062992
|
| 683 |
+
>>> log(24*e-6+4*catalan)-1
|
| 684 |
+
3.14158791577159
|
| 685 |
+
|
| 686 |
+
**Symbolic processing**
|
| 687 |
+
|
| 688 |
+
The output formula can be evaluated as a Python expression.
|
| 689 |
+
Note however that if fractions (like '2/3') are present in
|
| 690 |
+
the formula, Python's :func:`~mpmath.eval()` may erroneously perform
|
| 691 |
+
integer division. Note also that the output is not necessarily
|
| 692 |
+
in the algebraically simplest form::
|
| 693 |
+
|
| 694 |
+
>>> identify(sqrt(2))
|
| 695 |
+
'(sqrt(8)/2)'
|
| 696 |
+
|
| 697 |
+
As a solution to both problems, consider using SymPy's
|
| 698 |
+
:func:`~mpmath.sympify` to convert the formula into a symbolic expression.
|
| 699 |
+
SymPy can be used to pretty-print or further simplify the formula
|
| 700 |
+
symbolically::
|
| 701 |
+
|
| 702 |
+
>>> from sympy import sympify # doctest: +SKIP
|
| 703 |
+
>>> sympify(identify(sqrt(2))) # doctest: +SKIP
|
| 704 |
+
2**(1/2)
|
| 705 |
+
|
| 706 |
+
Sometimes :func:`~mpmath.identify` can simplify an expression further than
|
| 707 |
+
a symbolic algorithm::
|
| 708 |
+
|
| 709 |
+
>>> from sympy import simplify # doctest: +SKIP
|
| 710 |
+
>>> x = sympify('-1/(-3/2+(1/2)*5**(1/2))*(3/2-1/2*5**(1/2))**(1/2)') # doctest: +SKIP
|
| 711 |
+
>>> x # doctest: +SKIP
|
| 712 |
+
(3/2 - 5**(1/2)/2)**(-1/2)
|
| 713 |
+
>>> x = simplify(x) # doctest: +SKIP
|
| 714 |
+
>>> x # doctest: +SKIP
|
| 715 |
+
2/(6 - 2*5**(1/2))**(1/2)
|
| 716 |
+
>>> mp.dps = 30 # doctest: +SKIP
|
| 717 |
+
>>> x = sympify(identify(x.evalf(30))) # doctest: +SKIP
|
| 718 |
+
>>> x # doctest: +SKIP
|
| 719 |
+
1/2 + 5**(1/2)/2
|
| 720 |
+
|
| 721 |
+
(In fact, this functionality is available directly in SymPy as the
|
| 722 |
+
function :func:`~mpmath.nsimplify`, which is essentially a wrapper for
|
| 723 |
+
:func:`~mpmath.identify`.)
|
| 724 |
+
|
| 725 |
+
**Miscellaneous issues and limitations**
|
| 726 |
+
|
| 727 |
+
The input `x` must be a real number. All base constants must be
|
| 728 |
+
positive real numbers and must not be rationals or rational linear
|
| 729 |
+
combinations of each other.
|
| 730 |
+
|
| 731 |
+
The worst-case computation time grows quickly with the number of
|
| 732 |
+
base constants. Already with 3 or 4 base constants,
|
| 733 |
+
:func:`~mpmath.identify` may require several seconds to finish. To search
|
| 734 |
+
for relations among a large number of constants, you should
|
| 735 |
+
consider using :func:`~mpmath.pslq` directly.
|
| 736 |
+
|
| 737 |
+
The extended transformations are applied to x, not the constants
|
| 738 |
+
separately. As a result, ``identify`` will for example be able to
|
| 739 |
+
recognize ``exp(2*pi+3)`` with ``pi`` given as a base constant, but
|
| 740 |
+
not ``2*exp(pi)+3``. It will be able to recognize the latter if
|
| 741 |
+
``exp(pi)`` is given explicitly as a base constant.
|
| 742 |
+
|
| 743 |
+
"""
|
| 744 |
+
|
| 745 |
+
solutions = []
|
| 746 |
+
|
| 747 |
+
def addsolution(s):
|
| 748 |
+
if verbose: print("Found: ", s)
|
| 749 |
+
solutions.append(s)
|
| 750 |
+
|
| 751 |
+
x = ctx.mpf(x)
|
| 752 |
+
|
| 753 |
+
# Further along, x will be assumed positive
|
| 754 |
+
if x == 0:
|
| 755 |
+
if full: return ['0']
|
| 756 |
+
else: return '0'
|
| 757 |
+
if x < 0:
|
| 758 |
+
sol = ctx.identify(-x, constants, tol, maxcoeff, full, verbose)
|
| 759 |
+
if sol is None:
|
| 760 |
+
return sol
|
| 761 |
+
if full:
|
| 762 |
+
return ["-(%s)"%s for s in sol]
|
| 763 |
+
else:
|
| 764 |
+
return "-(%s)" % sol
|
| 765 |
+
|
| 766 |
+
if tol:
|
| 767 |
+
tol = ctx.mpf(tol)
|
| 768 |
+
else:
|
| 769 |
+
tol = ctx.eps**0.7
|
| 770 |
+
M = maxcoeff
|
| 771 |
+
|
| 772 |
+
if constants:
|
| 773 |
+
if isinstance(constants, dict):
|
| 774 |
+
constants = [(ctx.mpf(v), name) for (name, v) in sorted(constants.items())]
|
| 775 |
+
else:
|
| 776 |
+
namespace = dict((name, getattr(ctx,name)) for name in dir(ctx))
|
| 777 |
+
constants = [(eval(p, namespace), p) for p in constants]
|
| 778 |
+
else:
|
| 779 |
+
constants = []
|
| 780 |
+
|
| 781 |
+
# We always want to find at least rational terms
|
| 782 |
+
if 1 not in [value for (name, value) in constants]:
|
| 783 |
+
constants = [(ctx.mpf(1), '1')] + constants
|
| 784 |
+
|
| 785 |
+
# PSLQ with simple algebraic and functional transformations
|
| 786 |
+
for ft, ftn, red in transforms:
|
| 787 |
+
for c, cn in constants:
|
| 788 |
+
if red and cn == '1':
|
| 789 |
+
continue
|
| 790 |
+
t = ft(ctx,x,c)
|
| 791 |
+
# Prevent exponential transforms from wreaking havoc
|
| 792 |
+
if abs(t) > M**2 or abs(t) < tol:
|
| 793 |
+
continue
|
| 794 |
+
# Linear combination of base constants
|
| 795 |
+
r = ctx.pslq([t] + [a[0] for a in constants], tol, M)
|
| 796 |
+
s = None
|
| 797 |
+
if r is not None and max(abs(uw) for uw in r) <= M and r[0]:
|
| 798 |
+
s = pslqstring(r, constants)
|
| 799 |
+
# Quadratic algebraic numbers
|
| 800 |
+
else:
|
| 801 |
+
q = ctx.pslq([ctx.one, t, t**2], tol, M)
|
| 802 |
+
if q is not None and len(q) == 3 and q[2]:
|
| 803 |
+
aa, bb, cc = q
|
| 804 |
+
if max(abs(aa),abs(bb),abs(cc)) <= M:
|
| 805 |
+
s = quadraticstring(ctx,t,aa,bb,cc)
|
| 806 |
+
if s:
|
| 807 |
+
if cn == '1' and ('/$c' in ftn):
|
| 808 |
+
s = ftn.replace('$y', s).replace('/$c', '')
|
| 809 |
+
else:
|
| 810 |
+
s = ftn.replace('$y', s).replace('$c', cn)
|
| 811 |
+
addsolution(s)
|
| 812 |
+
if not full: return solutions[0]
|
| 813 |
+
|
| 814 |
+
if verbose:
|
| 815 |
+
print(".")
|
| 816 |
+
|
| 817 |
+
# Check for a direct multiplicative formula
|
| 818 |
+
if x != 1:
|
| 819 |
+
# Allow fractional powers of fractions
|
| 820 |
+
ilogs = [2,3,5,7]
|
| 821 |
+
# Watch out for existing fractional powers of fractions
|
| 822 |
+
logs = []
|
| 823 |
+
for a, s in constants:
|
| 824 |
+
if not sum(bool(ctx.findpoly(ctx.ln(a)/ctx.ln(i),1)) for i in ilogs):
|
| 825 |
+
logs.append((ctx.ln(a), s))
|
| 826 |
+
logs = [(ctx.ln(i),str(i)) for i in ilogs] + logs
|
| 827 |
+
r = ctx.pslq([ctx.ln(x)] + [a[0] for a in logs], tol, M)
|
| 828 |
+
if r is not None and max(abs(uw) for uw in r) <= M and r[0]:
|
| 829 |
+
addsolution(prodstring(r, logs))
|
| 830 |
+
if not full: return solutions[0]
|
| 831 |
+
|
| 832 |
+
if full:
|
| 833 |
+
return sorted(solutions, key=len)
|
| 834 |
+
else:
|
| 835 |
+
return None
|
| 836 |
+
|
| 837 |
+
IdentificationMethods.pslq = pslq
|
| 838 |
+
IdentificationMethods.findpoly = findpoly
|
| 839 |
+
IdentificationMethods.identify = identify
|
| 840 |
+
|
| 841 |
+
|
| 842 |
+
if __name__ == '__main__':
|
| 843 |
+
import doctest
|
| 844 |
+
doctest.testmod()
|
tuning-competition-baseline/.venv/lib/python3.11/site-packages/mpmath/rational.py
ADDED
|
@@ -0,0 +1,240 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import operator
|
| 2 |
+
import sys
|
| 3 |
+
from .libmp import int_types, mpf_hash, bitcount, from_man_exp, HASH_MODULUS
|
| 4 |
+
|
| 5 |
+
new = object.__new__
|
| 6 |
+
|
| 7 |
+
def create_reduced(p, q, _cache={}):
|
| 8 |
+
key = p, q
|
| 9 |
+
if key in _cache:
|
| 10 |
+
return _cache[key]
|
| 11 |
+
x, y = p, q
|
| 12 |
+
while y:
|
| 13 |
+
x, y = y, x % y
|
| 14 |
+
if x != 1:
|
| 15 |
+
p //= x
|
| 16 |
+
q //= x
|
| 17 |
+
v = new(mpq)
|
| 18 |
+
v._mpq_ = p, q
|
| 19 |
+
# Speedup integers, half-integers and other small fractions
|
| 20 |
+
if q <= 4 and abs(key[0]) < 100:
|
| 21 |
+
_cache[key] = v
|
| 22 |
+
return v
|
| 23 |
+
|
| 24 |
+
class mpq(object):
|
| 25 |
+
"""
|
| 26 |
+
Exact rational type, currently only intended for internal use.
|
| 27 |
+
"""
|
| 28 |
+
|
| 29 |
+
__slots__ = ["_mpq_"]
|
| 30 |
+
|
| 31 |
+
def __new__(cls, p, q=1):
|
| 32 |
+
if type(p) is tuple:
|
| 33 |
+
p, q = p
|
| 34 |
+
elif hasattr(p, '_mpq_'):
|
| 35 |
+
p, q = p._mpq_
|
| 36 |
+
return create_reduced(p, q)
|
| 37 |
+
|
| 38 |
+
def __repr__(s):
|
| 39 |
+
return "mpq(%s,%s)" % s._mpq_
|
| 40 |
+
|
| 41 |
+
def __str__(s):
|
| 42 |
+
return "(%s/%s)" % s._mpq_
|
| 43 |
+
|
| 44 |
+
def __int__(s):
|
| 45 |
+
a, b = s._mpq_
|
| 46 |
+
return a // b
|
| 47 |
+
|
| 48 |
+
def __nonzero__(s):
|
| 49 |
+
return bool(s._mpq_[0])
|
| 50 |
+
|
| 51 |
+
__bool__ = __nonzero__
|
| 52 |
+
|
| 53 |
+
def __hash__(s):
|
| 54 |
+
a, b = s._mpq_
|
| 55 |
+
if sys.version_info >= (3, 2):
|
| 56 |
+
inverse = pow(b, HASH_MODULUS-2, HASH_MODULUS)
|
| 57 |
+
if not inverse:
|
| 58 |
+
h = sys.hash_info.inf
|
| 59 |
+
else:
|
| 60 |
+
h = (abs(a) * inverse) % HASH_MODULUS
|
| 61 |
+
if a < 0: h = -h
|
| 62 |
+
if h == -1: h = -2
|
| 63 |
+
return h
|
| 64 |
+
else:
|
| 65 |
+
if b == 1:
|
| 66 |
+
return hash(a)
|
| 67 |
+
# Power of two: mpf compatible hash
|
| 68 |
+
if not (b & (b-1)):
|
| 69 |
+
return mpf_hash(from_man_exp(a, 1-bitcount(b)))
|
| 70 |
+
return hash((a,b))
|
| 71 |
+
|
| 72 |
+
def __eq__(s, t):
|
| 73 |
+
ttype = type(t)
|
| 74 |
+
if ttype is mpq:
|
| 75 |
+
return s._mpq_ == t._mpq_
|
| 76 |
+
if ttype in int_types:
|
| 77 |
+
a, b = s._mpq_
|
| 78 |
+
if b != 1:
|
| 79 |
+
return False
|
| 80 |
+
return a == t
|
| 81 |
+
return NotImplemented
|
| 82 |
+
|
| 83 |
+
def __ne__(s, t):
|
| 84 |
+
ttype = type(t)
|
| 85 |
+
if ttype is mpq:
|
| 86 |
+
return s._mpq_ != t._mpq_
|
| 87 |
+
if ttype in int_types:
|
| 88 |
+
a, b = s._mpq_
|
| 89 |
+
if b != 1:
|
| 90 |
+
return True
|
| 91 |
+
return a != t
|
| 92 |
+
return NotImplemented
|
| 93 |
+
|
| 94 |
+
def _cmp(s, t, op):
|
| 95 |
+
ttype = type(t)
|
| 96 |
+
if ttype in int_types:
|
| 97 |
+
a, b = s._mpq_
|
| 98 |
+
return op(a, t*b)
|
| 99 |
+
if ttype is mpq:
|
| 100 |
+
a, b = s._mpq_
|
| 101 |
+
c, d = t._mpq_
|
| 102 |
+
return op(a*d, b*c)
|
| 103 |
+
return NotImplementedError
|
| 104 |
+
|
| 105 |
+
def __lt__(s, t): return s._cmp(t, operator.lt)
|
| 106 |
+
def __le__(s, t): return s._cmp(t, operator.le)
|
| 107 |
+
def __gt__(s, t): return s._cmp(t, operator.gt)
|
| 108 |
+
def __ge__(s, t): return s._cmp(t, operator.ge)
|
| 109 |
+
|
| 110 |
+
def __abs__(s):
|
| 111 |
+
a, b = s._mpq_
|
| 112 |
+
if a >= 0:
|
| 113 |
+
return s
|
| 114 |
+
v = new(mpq)
|
| 115 |
+
v._mpq_ = -a, b
|
| 116 |
+
return v
|
| 117 |
+
|
| 118 |
+
def __neg__(s):
|
| 119 |
+
a, b = s._mpq_
|
| 120 |
+
v = new(mpq)
|
| 121 |
+
v._mpq_ = -a, b
|
| 122 |
+
return v
|
| 123 |
+
|
| 124 |
+
def __pos__(s):
|
| 125 |
+
return s
|
| 126 |
+
|
| 127 |
+
def __add__(s, t):
|
| 128 |
+
ttype = type(t)
|
| 129 |
+
if ttype is mpq:
|
| 130 |
+
a, b = s._mpq_
|
| 131 |
+
c, d = t._mpq_
|
| 132 |
+
return create_reduced(a*d+b*c, b*d)
|
| 133 |
+
if ttype in int_types:
|
| 134 |
+
a, b = s._mpq_
|
| 135 |
+
v = new(mpq)
|
| 136 |
+
v._mpq_ = a+b*t, b
|
| 137 |
+
return v
|
| 138 |
+
return NotImplemented
|
| 139 |
+
|
| 140 |
+
__radd__ = __add__
|
| 141 |
+
|
| 142 |
+
def __sub__(s, t):
|
| 143 |
+
ttype = type(t)
|
| 144 |
+
if ttype is mpq:
|
| 145 |
+
a, b = s._mpq_
|
| 146 |
+
c, d = t._mpq_
|
| 147 |
+
return create_reduced(a*d-b*c, b*d)
|
| 148 |
+
if ttype in int_types:
|
| 149 |
+
a, b = s._mpq_
|
| 150 |
+
v = new(mpq)
|
| 151 |
+
v._mpq_ = a-b*t, b
|
| 152 |
+
return v
|
| 153 |
+
return NotImplemented
|
| 154 |
+
|
| 155 |
+
def __rsub__(s, t):
|
| 156 |
+
ttype = type(t)
|
| 157 |
+
if ttype is mpq:
|
| 158 |
+
a, b = s._mpq_
|
| 159 |
+
c, d = t._mpq_
|
| 160 |
+
return create_reduced(b*c-a*d, b*d)
|
| 161 |
+
if ttype in int_types:
|
| 162 |
+
a, b = s._mpq_
|
| 163 |
+
v = new(mpq)
|
| 164 |
+
v._mpq_ = b*t-a, b
|
| 165 |
+
return v
|
| 166 |
+
return NotImplemented
|
| 167 |
+
|
| 168 |
+
def __mul__(s, t):
|
| 169 |
+
ttype = type(t)
|
| 170 |
+
if ttype is mpq:
|
| 171 |
+
a, b = s._mpq_
|
| 172 |
+
c, d = t._mpq_
|
| 173 |
+
return create_reduced(a*c, b*d)
|
| 174 |
+
if ttype in int_types:
|
| 175 |
+
a, b = s._mpq_
|
| 176 |
+
return create_reduced(a*t, b)
|
| 177 |
+
return NotImplemented
|
| 178 |
+
|
| 179 |
+
__rmul__ = __mul__
|
| 180 |
+
|
| 181 |
+
def __div__(s, t):
|
| 182 |
+
ttype = type(t)
|
| 183 |
+
if ttype is mpq:
|
| 184 |
+
a, b = s._mpq_
|
| 185 |
+
c, d = t._mpq_
|
| 186 |
+
return create_reduced(a*d, b*c)
|
| 187 |
+
if ttype in int_types:
|
| 188 |
+
a, b = s._mpq_
|
| 189 |
+
return create_reduced(a, b*t)
|
| 190 |
+
return NotImplemented
|
| 191 |
+
|
| 192 |
+
def __rdiv__(s, t):
|
| 193 |
+
ttype = type(t)
|
| 194 |
+
if ttype is mpq:
|
| 195 |
+
a, b = s._mpq_
|
| 196 |
+
c, d = t._mpq_
|
| 197 |
+
return create_reduced(b*c, a*d)
|
| 198 |
+
if ttype in int_types:
|
| 199 |
+
a, b = s._mpq_
|
| 200 |
+
return create_reduced(b*t, a)
|
| 201 |
+
return NotImplemented
|
| 202 |
+
|
| 203 |
+
def __pow__(s, t):
|
| 204 |
+
ttype = type(t)
|
| 205 |
+
if ttype in int_types:
|
| 206 |
+
a, b = s._mpq_
|
| 207 |
+
if t:
|
| 208 |
+
if t < 0:
|
| 209 |
+
a, b, t = b, a, -t
|
| 210 |
+
v = new(mpq)
|
| 211 |
+
v._mpq_ = a**t, b**t
|
| 212 |
+
return v
|
| 213 |
+
raise ZeroDivisionError
|
| 214 |
+
return NotImplemented
|
| 215 |
+
|
| 216 |
+
|
| 217 |
+
mpq_1 = mpq((1,1))
|
| 218 |
+
mpq_0 = mpq((0,1))
|
| 219 |
+
mpq_1_2 = mpq((1,2))
|
| 220 |
+
mpq_3_2 = mpq((3,2))
|
| 221 |
+
mpq_1_4 = mpq((1,4))
|
| 222 |
+
mpq_1_16 = mpq((1,16))
|
| 223 |
+
mpq_3_16 = mpq((3,16))
|
| 224 |
+
mpq_5_2 = mpq((5,2))
|
| 225 |
+
mpq_3_4 = mpq((3,4))
|
| 226 |
+
mpq_7_4 = mpq((7,4))
|
| 227 |
+
mpq_5_4 = mpq((5,4))
|
| 228 |
+
|
| 229 |
+
|
| 230 |
+
# Register with "numbers" ABC
|
| 231 |
+
# We do not subclass, hence we do not use the @abstractmethod checks. While
|
| 232 |
+
# this is less invasive it may turn out that we do not actually support
|
| 233 |
+
# parts of the expected interfaces. See
|
| 234 |
+
# http://docs.python.org/2/library/numbers.html for list of abstract
|
| 235 |
+
# methods.
|
| 236 |
+
try:
|
| 237 |
+
import numbers
|
| 238 |
+
numbers.Rational.register(mpq)
|
| 239 |
+
except ImportError:
|
| 240 |
+
pass
|
tuning-competition-baseline/.venv/lib/python3.11/site-packages/mpmath/usertools.py
ADDED
|
@@ -0,0 +1,93 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
|
| 2 |
+
def monitor(f, input='print', output='print'):
|
| 3 |
+
"""
|
| 4 |
+
Returns a wrapped copy of *f* that monitors evaluation by calling
|
| 5 |
+
*input* with every input (*args*, *kwargs*) passed to *f* and
|
| 6 |
+
*output* with every value returned from *f*. The default action
|
| 7 |
+
(specify using the special string value ``'print'``) is to print
|
| 8 |
+
inputs and outputs to stdout, along with the total evaluation
|
| 9 |
+
count::
|
| 10 |
+
|
| 11 |
+
>>> from mpmath import *
|
| 12 |
+
>>> mp.dps = 5; mp.pretty = False
|
| 13 |
+
>>> diff(monitor(exp), 1) # diff will eval f(x-h) and f(x+h)
|
| 14 |
+
in 0 (mpf('0.99999999906867742538452148'),) {}
|
| 15 |
+
out 0 mpf('2.7182818259274480055282064')
|
| 16 |
+
in 1 (mpf('1.0000000009313225746154785'),) {}
|
| 17 |
+
out 1 mpf('2.7182818309906424675501024')
|
| 18 |
+
mpf('2.7182808')
|
| 19 |
+
|
| 20 |
+
To disable either the input or the output handler, you may
|
| 21 |
+
pass *None* as argument.
|
| 22 |
+
|
| 23 |
+
Custom input and output handlers may be used e.g. to store
|
| 24 |
+
results for later analysis::
|
| 25 |
+
|
| 26 |
+
>>> mp.dps = 15
|
| 27 |
+
>>> input = []
|
| 28 |
+
>>> output = []
|
| 29 |
+
>>> findroot(monitor(sin, input.append, output.append), 3.0)
|
| 30 |
+
mpf('3.1415926535897932')
|
| 31 |
+
>>> len(input) # Count number of evaluations
|
| 32 |
+
9
|
| 33 |
+
>>> print(input[3]); print(output[3])
|
| 34 |
+
((mpf('3.1415076583334066'),), {})
|
| 35 |
+
8.49952562843408e-5
|
| 36 |
+
>>> print(input[4]); print(output[4])
|
| 37 |
+
((mpf('3.1415928201669122'),), {})
|
| 38 |
+
-1.66577118985331e-7
|
| 39 |
+
|
| 40 |
+
"""
|
| 41 |
+
if not input:
|
| 42 |
+
input = lambda v: None
|
| 43 |
+
elif input == 'print':
|
| 44 |
+
incount = [0]
|
| 45 |
+
def input(value):
|
| 46 |
+
args, kwargs = value
|
| 47 |
+
print("in %s %r %r" % (incount[0], args, kwargs))
|
| 48 |
+
incount[0] += 1
|
| 49 |
+
if not output:
|
| 50 |
+
output = lambda v: None
|
| 51 |
+
elif output == 'print':
|
| 52 |
+
outcount = [0]
|
| 53 |
+
def output(value):
|
| 54 |
+
print("out %s %r" % (outcount[0], value))
|
| 55 |
+
outcount[0] += 1
|
| 56 |
+
def f_monitored(*args, **kwargs):
|
| 57 |
+
input((args, kwargs))
|
| 58 |
+
v = f(*args, **kwargs)
|
| 59 |
+
output(v)
|
| 60 |
+
return v
|
| 61 |
+
return f_monitored
|
| 62 |
+
|
| 63 |
+
def timing(f, *args, **kwargs):
|
| 64 |
+
"""
|
| 65 |
+
Returns time elapsed for evaluating ``f()``. Optionally arguments
|
| 66 |
+
may be passed to time the execution of ``f(*args, **kwargs)``.
|
| 67 |
+
|
| 68 |
+
If the first call is very quick, ``f`` is called
|
| 69 |
+
repeatedly and the best time is returned.
|
| 70 |
+
"""
|
| 71 |
+
once = kwargs.get('once')
|
| 72 |
+
if 'once' in kwargs:
|
| 73 |
+
del kwargs['once']
|
| 74 |
+
if args or kwargs:
|
| 75 |
+
if len(args) == 1 and not kwargs:
|
| 76 |
+
arg = args[0]
|
| 77 |
+
g = lambda: f(arg)
|
| 78 |
+
else:
|
| 79 |
+
g = lambda: f(*args, **kwargs)
|
| 80 |
+
else:
|
| 81 |
+
g = f
|
| 82 |
+
from timeit import default_timer as clock
|
| 83 |
+
t1=clock(); v=g(); t2=clock(); t=t2-t1
|
| 84 |
+
if t > 0.05 or once:
|
| 85 |
+
return t
|
| 86 |
+
for i in range(3):
|
| 87 |
+
t1=clock();
|
| 88 |
+
# Evaluate multiple times because the timer function
|
| 89 |
+
# has a significant overhead
|
| 90 |
+
g();g();g();g();g();g();g();g();g();g()
|
| 91 |
+
t2=clock()
|
| 92 |
+
t=min(t,(t2-t1)/10)
|
| 93 |
+
return t
|
tuning-competition-baseline/.venv/lib/python3.11/site-packages/mpmath/visualization.py
ADDED
|
@@ -0,0 +1,313 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"""
|
| 2 |
+
Plotting (requires matplotlib)
|
| 3 |
+
"""
|
| 4 |
+
|
| 5 |
+
from colorsys import hsv_to_rgb, hls_to_rgb
|
| 6 |
+
from .libmp import NoConvergence
|
| 7 |
+
from .libmp.backend import xrange
|
| 8 |
+
|
| 9 |
+
class VisualizationMethods(object):
|
| 10 |
+
plot_ignore = (ValueError, ArithmeticError, ZeroDivisionError, NoConvergence)
|
| 11 |
+
|
| 12 |
+
def plot(ctx, f, xlim=[-5,5], ylim=None, points=200, file=None, dpi=None,
|
| 13 |
+
singularities=[], axes=None):
|
| 14 |
+
r"""
|
| 15 |
+
Shows a simple 2D plot of a function `f(x)` or list of functions
|
| 16 |
+
`[f_0(x), f_1(x), \ldots, f_n(x)]` over a given interval
|
| 17 |
+
specified by *xlim*. Some examples::
|
| 18 |
+
|
| 19 |
+
plot(lambda x: exp(x)*li(x), [1, 4])
|
| 20 |
+
plot([cos, sin], [-4, 4])
|
| 21 |
+
plot([fresnels, fresnelc], [-4, 4])
|
| 22 |
+
plot([sqrt, cbrt], [-4, 4])
|
| 23 |
+
plot(lambda t: zeta(0.5+t*j), [-20, 20])
|
| 24 |
+
plot([floor, ceil, abs, sign], [-5, 5])
|
| 25 |
+
|
| 26 |
+
Points where the function raises a numerical exception or
|
| 27 |
+
returns an infinite value are removed from the graph.
|
| 28 |
+
Singularities can also be excluded explicitly
|
| 29 |
+
as follows (useful for removing erroneous vertical lines)::
|
| 30 |
+
|
| 31 |
+
plot(cot, ylim=[-5, 5]) # bad
|
| 32 |
+
plot(cot, ylim=[-5, 5], singularities=[-pi, 0, pi]) # good
|
| 33 |
+
|
| 34 |
+
For parts where the function assumes complex values, the
|
| 35 |
+
real part is plotted with dashes and the imaginary part
|
| 36 |
+
is plotted with dots.
|
| 37 |
+
|
| 38 |
+
.. note :: This function requires matplotlib (pylab).
|
| 39 |
+
"""
|
| 40 |
+
if file:
|
| 41 |
+
axes = None
|
| 42 |
+
fig = None
|
| 43 |
+
if not axes:
|
| 44 |
+
import pylab
|
| 45 |
+
fig = pylab.figure()
|
| 46 |
+
axes = fig.add_subplot(111)
|
| 47 |
+
if not isinstance(f, (tuple, list)):
|
| 48 |
+
f = [f]
|
| 49 |
+
a, b = xlim
|
| 50 |
+
colors = ['b', 'r', 'g', 'm', 'k']
|
| 51 |
+
for n, func in enumerate(f):
|
| 52 |
+
x = ctx.arange(a, b, (b-a)/float(points))
|
| 53 |
+
segments = []
|
| 54 |
+
segment = []
|
| 55 |
+
in_complex = False
|
| 56 |
+
for i in xrange(len(x)):
|
| 57 |
+
try:
|
| 58 |
+
if i != 0:
|
| 59 |
+
for sing in singularities:
|
| 60 |
+
if x[i-1] <= sing and x[i] >= sing:
|
| 61 |
+
raise ValueError
|
| 62 |
+
v = func(x[i])
|
| 63 |
+
if ctx.isnan(v) or abs(v) > 1e300:
|
| 64 |
+
raise ValueError
|
| 65 |
+
if hasattr(v, "imag") and v.imag:
|
| 66 |
+
re = float(v.real)
|
| 67 |
+
im = float(v.imag)
|
| 68 |
+
if not in_complex:
|
| 69 |
+
in_complex = True
|
| 70 |
+
segments.append(segment)
|
| 71 |
+
segment = []
|
| 72 |
+
segment.append((float(x[i]), re, im))
|
| 73 |
+
else:
|
| 74 |
+
if in_complex:
|
| 75 |
+
in_complex = False
|
| 76 |
+
segments.append(segment)
|
| 77 |
+
segment = []
|
| 78 |
+
if hasattr(v, "real"):
|
| 79 |
+
v = v.real
|
| 80 |
+
segment.append((float(x[i]), v))
|
| 81 |
+
except ctx.plot_ignore:
|
| 82 |
+
if segment:
|
| 83 |
+
segments.append(segment)
|
| 84 |
+
segment = []
|
| 85 |
+
if segment:
|
| 86 |
+
segments.append(segment)
|
| 87 |
+
for segment in segments:
|
| 88 |
+
x = [s[0] for s in segment]
|
| 89 |
+
y = [s[1] for s in segment]
|
| 90 |
+
if not x:
|
| 91 |
+
continue
|
| 92 |
+
c = colors[n % len(colors)]
|
| 93 |
+
if len(segment[0]) == 3:
|
| 94 |
+
z = [s[2] for s in segment]
|
| 95 |
+
axes.plot(x, y, '--'+c, linewidth=3)
|
| 96 |
+
axes.plot(x, z, ':'+c, linewidth=3)
|
| 97 |
+
else:
|
| 98 |
+
axes.plot(x, y, c, linewidth=3)
|
| 99 |
+
axes.set_xlim([float(_) for _ in xlim])
|
| 100 |
+
if ylim:
|
| 101 |
+
axes.set_ylim([float(_) for _ in ylim])
|
| 102 |
+
axes.set_xlabel('x')
|
| 103 |
+
axes.set_ylabel('f(x)')
|
| 104 |
+
axes.grid(True)
|
| 105 |
+
if fig:
|
| 106 |
+
if file:
|
| 107 |
+
pylab.savefig(file, dpi=dpi)
|
| 108 |
+
else:
|
| 109 |
+
pylab.show()
|
| 110 |
+
|
| 111 |
+
def default_color_function(ctx, z):
|
| 112 |
+
if ctx.isinf(z):
|
| 113 |
+
return (1.0, 1.0, 1.0)
|
| 114 |
+
if ctx.isnan(z):
|
| 115 |
+
return (0.5, 0.5, 0.5)
|
| 116 |
+
pi = 3.1415926535898
|
| 117 |
+
a = (float(ctx.arg(z)) + ctx.pi) / (2*ctx.pi)
|
| 118 |
+
a = (a + 0.5) % 1.0
|
| 119 |
+
b = 1.0 - float(1/(1.0+abs(z)**0.3))
|
| 120 |
+
return hls_to_rgb(a, b, 0.8)
|
| 121 |
+
|
| 122 |
+
blue_orange_colors = [
|
| 123 |
+
(-1.0, (0.0, 0.0, 0.0)),
|
| 124 |
+
(-0.95, (0.1, 0.2, 0.5)), # dark blue
|
| 125 |
+
(-0.5, (0.0, 0.5, 1.0)), # blueish
|
| 126 |
+
(-0.05, (0.4, 0.8, 0.8)), # cyanish
|
| 127 |
+
( 0.0, (1.0, 1.0, 1.0)),
|
| 128 |
+
( 0.05, (1.0, 0.9, 0.3)), # yellowish
|
| 129 |
+
( 0.5, (0.9, 0.5, 0.0)), # orangeish
|
| 130 |
+
( 0.95, (0.7, 0.1, 0.0)), # redish
|
| 131 |
+
( 1.0, (0.0, 0.0, 0.0)),
|
| 132 |
+
( 2.0, (0.0, 0.0, 0.0)),
|
| 133 |
+
]
|
| 134 |
+
|
| 135 |
+
def phase_color_function(ctx, z):
|
| 136 |
+
if ctx.isinf(z):
|
| 137 |
+
return (1.0, 1.0, 1.0)
|
| 138 |
+
if ctx.isnan(z):
|
| 139 |
+
return (0.5, 0.5, 0.5)
|
| 140 |
+
pi = 3.1415926535898
|
| 141 |
+
w = float(ctx.arg(z)) / pi
|
| 142 |
+
w = max(min(w, 1.0), -1.0)
|
| 143 |
+
for i in range(1,len(blue_orange_colors)):
|
| 144 |
+
if blue_orange_colors[i][0] > w:
|
| 145 |
+
a, (ra, ga, ba) = blue_orange_colors[i-1]
|
| 146 |
+
b, (rb, gb, bb) = blue_orange_colors[i]
|
| 147 |
+
s = (w-a) / (b-a)
|
| 148 |
+
return ra+(rb-ra)*s, ga+(gb-ga)*s, ba+(bb-ba)*s
|
| 149 |
+
|
| 150 |
+
def cplot(ctx, f, re=[-5,5], im=[-5,5], points=2000, color=None,
|
| 151 |
+
verbose=False, file=None, dpi=None, axes=None):
|
| 152 |
+
"""
|
| 153 |
+
Plots the given complex-valued function *f* over a rectangular part
|
| 154 |
+
of the complex plane specified by the pairs of intervals *re* and *im*.
|
| 155 |
+
For example::
|
| 156 |
+
|
| 157 |
+
cplot(lambda z: z, [-2, 2], [-10, 10])
|
| 158 |
+
cplot(exp)
|
| 159 |
+
cplot(zeta, [0, 1], [0, 50])
|
| 160 |
+
|
| 161 |
+
By default, the complex argument (phase) is shown as color (hue) and
|
| 162 |
+
the magnitude is show as brightness. You can also supply a
|
| 163 |
+
custom color function (*color*). This function should take a
|
| 164 |
+
complex number as input and return an RGB 3-tuple containing
|
| 165 |
+
floats in the range 0.0-1.0.
|
| 166 |
+
|
| 167 |
+
Alternatively, you can select a builtin color function by passing
|
| 168 |
+
a string as *color*:
|
| 169 |
+
|
| 170 |
+
* "default" - default color scheme
|
| 171 |
+
* "phase" - a color scheme that only renders the phase of the function,
|
| 172 |
+
with white for positive reals, black for negative reals, gold in the
|
| 173 |
+
upper half plane, and blue in the lower half plane.
|
| 174 |
+
|
| 175 |
+
To obtain a sharp image, the number of points may need to be
|
| 176 |
+
increased to 100,000 or thereabout. Since evaluating the
|
| 177 |
+
function that many times is likely to be slow, the 'verbose'
|
| 178 |
+
option is useful to display progress.
|
| 179 |
+
|
| 180 |
+
.. note :: This function requires matplotlib (pylab).
|
| 181 |
+
"""
|
| 182 |
+
if color is None or color == "default":
|
| 183 |
+
color = ctx.default_color_function
|
| 184 |
+
if color == "phase":
|
| 185 |
+
color = ctx.phase_color_function
|
| 186 |
+
import pylab
|
| 187 |
+
if file:
|
| 188 |
+
axes = None
|
| 189 |
+
fig = None
|
| 190 |
+
if not axes:
|
| 191 |
+
fig = pylab.figure()
|
| 192 |
+
axes = fig.add_subplot(111)
|
| 193 |
+
rea, reb = re
|
| 194 |
+
ima, imb = im
|
| 195 |
+
dre = reb - rea
|
| 196 |
+
dim = imb - ima
|
| 197 |
+
M = int(ctx.sqrt(points*dre/dim)+1)
|
| 198 |
+
N = int(ctx.sqrt(points*dim/dre)+1)
|
| 199 |
+
x = pylab.linspace(rea, reb, M)
|
| 200 |
+
y = pylab.linspace(ima, imb, N)
|
| 201 |
+
# Note: we have to be careful to get the right rotation.
|
| 202 |
+
# Test with these plots:
|
| 203 |
+
# cplot(lambda z: z if z.real < 0 else 0)
|
| 204 |
+
# cplot(lambda z: z if z.imag < 0 else 0)
|
| 205 |
+
w = pylab.zeros((N, M, 3))
|
| 206 |
+
for n in xrange(N):
|
| 207 |
+
for m in xrange(M):
|
| 208 |
+
z = ctx.mpc(x[m], y[n])
|
| 209 |
+
try:
|
| 210 |
+
v = color(f(z))
|
| 211 |
+
except ctx.plot_ignore:
|
| 212 |
+
v = (0.5, 0.5, 0.5)
|
| 213 |
+
w[n,m] = v
|
| 214 |
+
if verbose:
|
| 215 |
+
print(str(n) + ' of ' + str(N))
|
| 216 |
+
rea, reb, ima, imb = [float(_) for _ in [rea, reb, ima, imb]]
|
| 217 |
+
axes.imshow(w, extent=(rea, reb, ima, imb), origin='lower')
|
| 218 |
+
axes.set_xlabel('Re(z)')
|
| 219 |
+
axes.set_ylabel('Im(z)')
|
| 220 |
+
if fig:
|
| 221 |
+
if file:
|
| 222 |
+
pylab.savefig(file, dpi=dpi)
|
| 223 |
+
else:
|
| 224 |
+
pylab.show()
|
| 225 |
+
|
| 226 |
+
def splot(ctx, f, u=[-5,5], v=[-5,5], points=100, keep_aspect=True, \
|
| 227 |
+
wireframe=False, file=None, dpi=None, axes=None):
|
| 228 |
+
"""
|
| 229 |
+
Plots the surface defined by `f`.
|
| 230 |
+
|
| 231 |
+
If `f` returns a single component, then this plots the surface
|
| 232 |
+
defined by `z = f(x,y)` over the rectangular domain with
|
| 233 |
+
`x = u` and `y = v`.
|
| 234 |
+
|
| 235 |
+
If `f` returns three components, then this plots the parametric
|
| 236 |
+
surface `x, y, z = f(u,v)` over the pairs of intervals `u` and `v`.
|
| 237 |
+
|
| 238 |
+
For example, to plot a simple function::
|
| 239 |
+
|
| 240 |
+
>>> from mpmath import *
|
| 241 |
+
>>> f = lambda x, y: sin(x+y)*cos(y)
|
| 242 |
+
>>> splot(f, [-pi,pi], [-pi,pi]) # doctest: +SKIP
|
| 243 |
+
|
| 244 |
+
Plotting a donut::
|
| 245 |
+
|
| 246 |
+
>>> r, R = 1, 2.5
|
| 247 |
+
>>> f = lambda u, v: [r*cos(u), (R+r*sin(u))*cos(v), (R+r*sin(u))*sin(v)]
|
| 248 |
+
>>> splot(f, [0, 2*pi], [0, 2*pi]) # doctest: +SKIP
|
| 249 |
+
|
| 250 |
+
.. note :: This function requires matplotlib (pylab) 0.98.5.3 or higher.
|
| 251 |
+
"""
|
| 252 |
+
import pylab
|
| 253 |
+
import mpl_toolkits.mplot3d as mplot3d
|
| 254 |
+
if file:
|
| 255 |
+
axes = None
|
| 256 |
+
fig = None
|
| 257 |
+
if not axes:
|
| 258 |
+
fig = pylab.figure()
|
| 259 |
+
axes = mplot3d.axes3d.Axes3D(fig)
|
| 260 |
+
ua, ub = u
|
| 261 |
+
va, vb = v
|
| 262 |
+
du = ub - ua
|
| 263 |
+
dv = vb - va
|
| 264 |
+
if not isinstance(points, (list, tuple)):
|
| 265 |
+
points = [points, points]
|
| 266 |
+
M, N = points
|
| 267 |
+
u = pylab.linspace(ua, ub, M)
|
| 268 |
+
v = pylab.linspace(va, vb, N)
|
| 269 |
+
x, y, z = [pylab.zeros((M, N)) for i in xrange(3)]
|
| 270 |
+
xab, yab, zab = [[0, 0] for i in xrange(3)]
|
| 271 |
+
for n in xrange(N):
|
| 272 |
+
for m in xrange(M):
|
| 273 |
+
fdata = f(ctx.convert(u[m]), ctx.convert(v[n]))
|
| 274 |
+
try:
|
| 275 |
+
x[m,n], y[m,n], z[m,n] = fdata
|
| 276 |
+
except TypeError:
|
| 277 |
+
x[m,n], y[m,n], z[m,n] = u[m], v[n], fdata
|
| 278 |
+
for c, cab in [(x[m,n], xab), (y[m,n], yab), (z[m,n], zab)]:
|
| 279 |
+
if c < cab[0]:
|
| 280 |
+
cab[0] = c
|
| 281 |
+
if c > cab[1]:
|
| 282 |
+
cab[1] = c
|
| 283 |
+
if wireframe:
|
| 284 |
+
axes.plot_wireframe(x, y, z, rstride=4, cstride=4)
|
| 285 |
+
else:
|
| 286 |
+
axes.plot_surface(x, y, z, rstride=4, cstride=4)
|
| 287 |
+
axes.set_xlabel('x')
|
| 288 |
+
axes.set_ylabel('y')
|
| 289 |
+
axes.set_zlabel('z')
|
| 290 |
+
if keep_aspect:
|
| 291 |
+
dx, dy, dz = [cab[1] - cab[0] for cab in [xab, yab, zab]]
|
| 292 |
+
maxd = max(dx, dy, dz)
|
| 293 |
+
if dx < maxd:
|
| 294 |
+
delta = maxd - dx
|
| 295 |
+
axes.set_xlim3d(xab[0] - delta / 2.0, xab[1] + delta / 2.0)
|
| 296 |
+
if dy < maxd:
|
| 297 |
+
delta = maxd - dy
|
| 298 |
+
axes.set_ylim3d(yab[0] - delta / 2.0, yab[1] + delta / 2.0)
|
| 299 |
+
if dz < maxd:
|
| 300 |
+
delta = maxd - dz
|
| 301 |
+
axes.set_zlim3d(zab[0] - delta / 2.0, zab[1] + delta / 2.0)
|
| 302 |
+
if fig:
|
| 303 |
+
if file:
|
| 304 |
+
pylab.savefig(file, dpi=dpi)
|
| 305 |
+
else:
|
| 306 |
+
pylab.show()
|
| 307 |
+
|
| 308 |
+
|
| 309 |
+
VisualizationMethods.plot = plot
|
| 310 |
+
VisualizationMethods.default_color_function = default_color_function
|
| 311 |
+
VisualizationMethods.phase_color_function = phase_color_function
|
| 312 |
+
VisualizationMethods.cplot = cplot
|
| 313 |
+
VisualizationMethods.splot = splot
|
tuning-competition-baseline/.venv/lib/python3.11/site-packages/pip/_internal/locations/__init__.py
ADDED
|
@@ -0,0 +1,456 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import functools
|
| 2 |
+
import logging
|
| 3 |
+
import os
|
| 4 |
+
import pathlib
|
| 5 |
+
import sys
|
| 6 |
+
import sysconfig
|
| 7 |
+
from typing import Any, Dict, Generator, Optional, Tuple
|
| 8 |
+
|
| 9 |
+
from pip._internal.models.scheme import SCHEME_KEYS, Scheme
|
| 10 |
+
from pip._internal.utils.compat import WINDOWS
|
| 11 |
+
from pip._internal.utils.deprecation import deprecated
|
| 12 |
+
from pip._internal.utils.virtualenv import running_under_virtualenv
|
| 13 |
+
|
| 14 |
+
from . import _sysconfig
|
| 15 |
+
from .base import (
|
| 16 |
+
USER_CACHE_DIR,
|
| 17 |
+
get_major_minor_version,
|
| 18 |
+
get_src_prefix,
|
| 19 |
+
is_osx_framework,
|
| 20 |
+
site_packages,
|
| 21 |
+
user_site,
|
| 22 |
+
)
|
| 23 |
+
|
| 24 |
+
__all__ = [
|
| 25 |
+
"USER_CACHE_DIR",
|
| 26 |
+
"get_bin_prefix",
|
| 27 |
+
"get_bin_user",
|
| 28 |
+
"get_major_minor_version",
|
| 29 |
+
"get_platlib",
|
| 30 |
+
"get_purelib",
|
| 31 |
+
"get_scheme",
|
| 32 |
+
"get_src_prefix",
|
| 33 |
+
"site_packages",
|
| 34 |
+
"user_site",
|
| 35 |
+
]
|
| 36 |
+
|
| 37 |
+
|
| 38 |
+
logger = logging.getLogger(__name__)
|
| 39 |
+
|
| 40 |
+
|
| 41 |
+
_PLATLIBDIR: str = getattr(sys, "platlibdir", "lib")
|
| 42 |
+
|
| 43 |
+
_USE_SYSCONFIG_DEFAULT = sys.version_info >= (3, 10)
|
| 44 |
+
|
| 45 |
+
|
| 46 |
+
def _should_use_sysconfig() -> bool:
|
| 47 |
+
"""This function determines the value of _USE_SYSCONFIG.
|
| 48 |
+
|
| 49 |
+
By default, pip uses sysconfig on Python 3.10+.
|
| 50 |
+
But Python distributors can override this decision by setting:
|
| 51 |
+
sysconfig._PIP_USE_SYSCONFIG = True / False
|
| 52 |
+
Rationale in https://github.com/pypa/pip/issues/10647
|
| 53 |
+
|
| 54 |
+
This is a function for testability, but should be constant during any one
|
| 55 |
+
run.
|
| 56 |
+
"""
|
| 57 |
+
return bool(getattr(sysconfig, "_PIP_USE_SYSCONFIG", _USE_SYSCONFIG_DEFAULT))
|
| 58 |
+
|
| 59 |
+
|
| 60 |
+
_USE_SYSCONFIG = _should_use_sysconfig()
|
| 61 |
+
|
| 62 |
+
if not _USE_SYSCONFIG:
|
| 63 |
+
# Import distutils lazily to avoid deprecation warnings,
|
| 64 |
+
# but import it soon enough that it is in memory and available during
|
| 65 |
+
# a pip reinstall.
|
| 66 |
+
from . import _distutils
|
| 67 |
+
|
| 68 |
+
# Be noisy about incompatibilities if this platforms "should" be using
|
| 69 |
+
# sysconfig, but is explicitly opting out and using distutils instead.
|
| 70 |
+
if _USE_SYSCONFIG_DEFAULT and not _USE_SYSCONFIG:
|
| 71 |
+
_MISMATCH_LEVEL = logging.WARNING
|
| 72 |
+
else:
|
| 73 |
+
_MISMATCH_LEVEL = logging.DEBUG
|
| 74 |
+
|
| 75 |
+
|
| 76 |
+
def _looks_like_bpo_44860() -> bool:
|
| 77 |
+
"""The resolution to bpo-44860 will change this incorrect platlib.
|
| 78 |
+
|
| 79 |
+
See <https://bugs.python.org/issue44860>.
|
| 80 |
+
"""
|
| 81 |
+
from distutils.command.install import INSTALL_SCHEMES
|
| 82 |
+
|
| 83 |
+
try:
|
| 84 |
+
unix_user_platlib = INSTALL_SCHEMES["unix_user"]["platlib"]
|
| 85 |
+
except KeyError:
|
| 86 |
+
return False
|
| 87 |
+
return unix_user_platlib == "$usersite"
|
| 88 |
+
|
| 89 |
+
|
| 90 |
+
def _looks_like_red_hat_patched_platlib_purelib(scheme: Dict[str, str]) -> bool:
|
| 91 |
+
platlib = scheme["platlib"]
|
| 92 |
+
if "/$platlibdir/" in platlib:
|
| 93 |
+
platlib = platlib.replace("/$platlibdir/", f"/{_PLATLIBDIR}/")
|
| 94 |
+
if "/lib64/" not in platlib:
|
| 95 |
+
return False
|
| 96 |
+
unpatched = platlib.replace("/lib64/", "/lib/")
|
| 97 |
+
return unpatched.replace("$platbase/", "$base/") == scheme["purelib"]
|
| 98 |
+
|
| 99 |
+
|
| 100 |
+
@functools.lru_cache(maxsize=None)
|
| 101 |
+
def _looks_like_red_hat_lib() -> bool:
|
| 102 |
+
"""Red Hat patches platlib in unix_prefix and unix_home, but not purelib.
|
| 103 |
+
|
| 104 |
+
This is the only way I can see to tell a Red Hat-patched Python.
|
| 105 |
+
"""
|
| 106 |
+
from distutils.command.install import INSTALL_SCHEMES
|
| 107 |
+
|
| 108 |
+
return all(
|
| 109 |
+
k in INSTALL_SCHEMES
|
| 110 |
+
and _looks_like_red_hat_patched_platlib_purelib(INSTALL_SCHEMES[k])
|
| 111 |
+
for k in ("unix_prefix", "unix_home")
|
| 112 |
+
)
|
| 113 |
+
|
| 114 |
+
|
| 115 |
+
@functools.lru_cache(maxsize=None)
|
| 116 |
+
def _looks_like_debian_scheme() -> bool:
|
| 117 |
+
"""Debian adds two additional schemes."""
|
| 118 |
+
from distutils.command.install import INSTALL_SCHEMES
|
| 119 |
+
|
| 120 |
+
return "deb_system" in INSTALL_SCHEMES and "unix_local" in INSTALL_SCHEMES
|
| 121 |
+
|
| 122 |
+
|
| 123 |
+
@functools.lru_cache(maxsize=None)
|
| 124 |
+
def _looks_like_red_hat_scheme() -> bool:
|
| 125 |
+
"""Red Hat patches ``sys.prefix`` and ``sys.exec_prefix``.
|
| 126 |
+
|
| 127 |
+
Red Hat's ``00251-change-user-install-location.patch`` changes the install
|
| 128 |
+
command's ``prefix`` and ``exec_prefix`` to append ``"/local"``. This is
|
| 129 |
+
(fortunately?) done quite unconditionally, so we create a default command
|
| 130 |
+
object without any configuration to detect this.
|
| 131 |
+
"""
|
| 132 |
+
from distutils.command.install import install
|
| 133 |
+
from distutils.dist import Distribution
|
| 134 |
+
|
| 135 |
+
cmd: Any = install(Distribution())
|
| 136 |
+
cmd.finalize_options()
|
| 137 |
+
return (
|
| 138 |
+
cmd.exec_prefix == f"{os.path.normpath(sys.exec_prefix)}/local"
|
| 139 |
+
and cmd.prefix == f"{os.path.normpath(sys.prefix)}/local"
|
| 140 |
+
)
|
| 141 |
+
|
| 142 |
+
|
| 143 |
+
@functools.lru_cache(maxsize=None)
|
| 144 |
+
def _looks_like_slackware_scheme() -> bool:
|
| 145 |
+
"""Slackware patches sysconfig but fails to patch distutils and site.
|
| 146 |
+
|
| 147 |
+
Slackware changes sysconfig's user scheme to use ``"lib64"`` for the lib
|
| 148 |
+
path, but does not do the same to the site module.
|
| 149 |
+
"""
|
| 150 |
+
if user_site is None: # User-site not available.
|
| 151 |
+
return False
|
| 152 |
+
try:
|
| 153 |
+
paths = sysconfig.get_paths(scheme="posix_user", expand=False)
|
| 154 |
+
except KeyError: # User-site not available.
|
| 155 |
+
return False
|
| 156 |
+
return "/lib64/" in paths["purelib"] and "/lib64/" not in user_site
|
| 157 |
+
|
| 158 |
+
|
| 159 |
+
@functools.lru_cache(maxsize=None)
|
| 160 |
+
def _looks_like_msys2_mingw_scheme() -> bool:
|
| 161 |
+
"""MSYS2 patches distutils and sysconfig to use a UNIX-like scheme.
|
| 162 |
+
|
| 163 |
+
However, MSYS2 incorrectly patches sysconfig ``nt`` scheme. The fix is
|
| 164 |
+
likely going to be included in their 3.10 release, so we ignore the warning.
|
| 165 |
+
See msys2/MINGW-packages#9319.
|
| 166 |
+
|
| 167 |
+
MSYS2 MINGW's patch uses lowercase ``"lib"`` instead of the usual uppercase,
|
| 168 |
+
and is missing the final ``"site-packages"``.
|
| 169 |
+
"""
|
| 170 |
+
paths = sysconfig.get_paths("nt", expand=False)
|
| 171 |
+
return all(
|
| 172 |
+
"Lib" not in p and "lib" in p and not p.endswith("site-packages")
|
| 173 |
+
for p in (paths[key] for key in ("platlib", "purelib"))
|
| 174 |
+
)
|
| 175 |
+
|
| 176 |
+
|
| 177 |
+
def _fix_abiflags(parts: Tuple[str]) -> Generator[str, None, None]:
|
| 178 |
+
ldversion = sysconfig.get_config_var("LDVERSION")
|
| 179 |
+
abiflags = getattr(sys, "abiflags", None)
|
| 180 |
+
|
| 181 |
+
# LDVERSION does not end with sys.abiflags. Just return the path unchanged.
|
| 182 |
+
if not ldversion or not abiflags or not ldversion.endswith(abiflags):
|
| 183 |
+
yield from parts
|
| 184 |
+
return
|
| 185 |
+
|
| 186 |
+
# Strip sys.abiflags from LDVERSION-based path components.
|
| 187 |
+
for part in parts:
|
| 188 |
+
if part.endswith(ldversion):
|
| 189 |
+
part = part[: (0 - len(abiflags))]
|
| 190 |
+
yield part
|
| 191 |
+
|
| 192 |
+
|
| 193 |
+
@functools.lru_cache(maxsize=None)
|
| 194 |
+
def _warn_mismatched(old: pathlib.Path, new: pathlib.Path, *, key: str) -> None:
|
| 195 |
+
issue_url = "https://github.com/pypa/pip/issues/10151"
|
| 196 |
+
message = (
|
| 197 |
+
"Value for %s does not match. Please report this to <%s>"
|
| 198 |
+
"\ndistutils: %s"
|
| 199 |
+
"\nsysconfig: %s"
|
| 200 |
+
)
|
| 201 |
+
logger.log(_MISMATCH_LEVEL, message, key, issue_url, old, new)
|
| 202 |
+
|
| 203 |
+
|
| 204 |
+
def _warn_if_mismatch(old: pathlib.Path, new: pathlib.Path, *, key: str) -> bool:
|
| 205 |
+
if old == new:
|
| 206 |
+
return False
|
| 207 |
+
_warn_mismatched(old, new, key=key)
|
| 208 |
+
return True
|
| 209 |
+
|
| 210 |
+
|
| 211 |
+
@functools.lru_cache(maxsize=None)
|
| 212 |
+
def _log_context(
|
| 213 |
+
*,
|
| 214 |
+
user: bool = False,
|
| 215 |
+
home: Optional[str] = None,
|
| 216 |
+
root: Optional[str] = None,
|
| 217 |
+
prefix: Optional[str] = None,
|
| 218 |
+
) -> None:
|
| 219 |
+
parts = [
|
| 220 |
+
"Additional context:",
|
| 221 |
+
"user = %r",
|
| 222 |
+
"home = %r",
|
| 223 |
+
"root = %r",
|
| 224 |
+
"prefix = %r",
|
| 225 |
+
]
|
| 226 |
+
|
| 227 |
+
logger.log(_MISMATCH_LEVEL, "\n".join(parts), user, home, root, prefix)
|
| 228 |
+
|
| 229 |
+
|
| 230 |
+
def get_scheme(
|
| 231 |
+
dist_name: str,
|
| 232 |
+
user: bool = False,
|
| 233 |
+
home: Optional[str] = None,
|
| 234 |
+
root: Optional[str] = None,
|
| 235 |
+
isolated: bool = False,
|
| 236 |
+
prefix: Optional[str] = None,
|
| 237 |
+
) -> Scheme:
|
| 238 |
+
new = _sysconfig.get_scheme(
|
| 239 |
+
dist_name,
|
| 240 |
+
user=user,
|
| 241 |
+
home=home,
|
| 242 |
+
root=root,
|
| 243 |
+
isolated=isolated,
|
| 244 |
+
prefix=prefix,
|
| 245 |
+
)
|
| 246 |
+
if _USE_SYSCONFIG:
|
| 247 |
+
return new
|
| 248 |
+
|
| 249 |
+
old = _distutils.get_scheme(
|
| 250 |
+
dist_name,
|
| 251 |
+
user=user,
|
| 252 |
+
home=home,
|
| 253 |
+
root=root,
|
| 254 |
+
isolated=isolated,
|
| 255 |
+
prefix=prefix,
|
| 256 |
+
)
|
| 257 |
+
|
| 258 |
+
warning_contexts = []
|
| 259 |
+
for k in SCHEME_KEYS:
|
| 260 |
+
old_v = pathlib.Path(getattr(old, k))
|
| 261 |
+
new_v = pathlib.Path(getattr(new, k))
|
| 262 |
+
|
| 263 |
+
if old_v == new_v:
|
| 264 |
+
continue
|
| 265 |
+
|
| 266 |
+
# distutils incorrectly put PyPy packages under ``site-packages/python``
|
| 267 |
+
# in the ``posix_home`` scheme, but PyPy devs said they expect the
|
| 268 |
+
# directory name to be ``pypy`` instead. So we treat this as a bug fix
|
| 269 |
+
# and not warn about it. See bpo-43307 and python/cpython#24628.
|
| 270 |
+
skip_pypy_special_case = (
|
| 271 |
+
sys.implementation.name == "pypy"
|
| 272 |
+
and home is not None
|
| 273 |
+
and k in ("platlib", "purelib")
|
| 274 |
+
and old_v.parent == new_v.parent
|
| 275 |
+
and old_v.name.startswith("python")
|
| 276 |
+
and new_v.name.startswith("pypy")
|
| 277 |
+
)
|
| 278 |
+
if skip_pypy_special_case:
|
| 279 |
+
continue
|
| 280 |
+
|
| 281 |
+
# sysconfig's ``osx_framework_user`` does not include ``pythonX.Y`` in
|
| 282 |
+
# the ``include`` value, but distutils's ``headers`` does. We'll let
|
| 283 |
+
# CPython decide whether this is a bug or feature. See bpo-43948.
|
| 284 |
+
skip_osx_framework_user_special_case = (
|
| 285 |
+
user
|
| 286 |
+
and is_osx_framework()
|
| 287 |
+
and k == "headers"
|
| 288 |
+
and old_v.parent.parent == new_v.parent
|
| 289 |
+
and old_v.parent.name.startswith("python")
|
| 290 |
+
)
|
| 291 |
+
if skip_osx_framework_user_special_case:
|
| 292 |
+
continue
|
| 293 |
+
|
| 294 |
+
# On Red Hat and derived Linux distributions, distutils is patched to
|
| 295 |
+
# use "lib64" instead of "lib" for platlib.
|
| 296 |
+
if k == "platlib" and _looks_like_red_hat_lib():
|
| 297 |
+
continue
|
| 298 |
+
|
| 299 |
+
# On Python 3.9+, sysconfig's posix_user scheme sets platlib against
|
| 300 |
+
# sys.platlibdir, but distutils's unix_user incorrectly coninutes
|
| 301 |
+
# using the same $usersite for both platlib and purelib. This creates a
|
| 302 |
+
# mismatch when sys.platlibdir is not "lib".
|
| 303 |
+
skip_bpo_44860 = (
|
| 304 |
+
user
|
| 305 |
+
and k == "platlib"
|
| 306 |
+
and not WINDOWS
|
| 307 |
+
and sys.version_info >= (3, 9)
|
| 308 |
+
and _PLATLIBDIR != "lib"
|
| 309 |
+
and _looks_like_bpo_44860()
|
| 310 |
+
)
|
| 311 |
+
if skip_bpo_44860:
|
| 312 |
+
continue
|
| 313 |
+
|
| 314 |
+
# Slackware incorrectly patches posix_user to use lib64 instead of lib,
|
| 315 |
+
# but not usersite to match the location.
|
| 316 |
+
skip_slackware_user_scheme = (
|
| 317 |
+
user
|
| 318 |
+
and k in ("platlib", "purelib")
|
| 319 |
+
and not WINDOWS
|
| 320 |
+
and _looks_like_slackware_scheme()
|
| 321 |
+
)
|
| 322 |
+
if skip_slackware_user_scheme:
|
| 323 |
+
continue
|
| 324 |
+
|
| 325 |
+
# Both Debian and Red Hat patch Python to place the system site under
|
| 326 |
+
# /usr/local instead of /usr. Debian also places lib in dist-packages
|
| 327 |
+
# instead of site-packages, but the /usr/local check should cover it.
|
| 328 |
+
skip_linux_system_special_case = (
|
| 329 |
+
not (user or home or prefix or running_under_virtualenv())
|
| 330 |
+
and old_v.parts[1:3] == ("usr", "local")
|
| 331 |
+
and len(new_v.parts) > 1
|
| 332 |
+
and new_v.parts[1] == "usr"
|
| 333 |
+
and (len(new_v.parts) < 3 or new_v.parts[2] != "local")
|
| 334 |
+
and (_looks_like_red_hat_scheme() or _looks_like_debian_scheme())
|
| 335 |
+
)
|
| 336 |
+
if skip_linux_system_special_case:
|
| 337 |
+
continue
|
| 338 |
+
|
| 339 |
+
# MSYS2 MINGW's sysconfig patch does not include the "site-packages"
|
| 340 |
+
# part of the path. This is incorrect and will be fixed in MSYS.
|
| 341 |
+
skip_msys2_mingw_bug = (
|
| 342 |
+
WINDOWS and k in ("platlib", "purelib") and _looks_like_msys2_mingw_scheme()
|
| 343 |
+
)
|
| 344 |
+
if skip_msys2_mingw_bug:
|
| 345 |
+
continue
|
| 346 |
+
|
| 347 |
+
# CPython's POSIX install script invokes pip (via ensurepip) against the
|
| 348 |
+
# interpreter located in the source tree, not the install site. This
|
| 349 |
+
# triggers special logic in sysconfig that's not present in distutils.
|
| 350 |
+
# https://github.com/python/cpython/blob/8c21941ddaf/Lib/sysconfig.py#L178-L194
|
| 351 |
+
skip_cpython_build = (
|
| 352 |
+
sysconfig.is_python_build(check_home=True)
|
| 353 |
+
and not WINDOWS
|
| 354 |
+
and k in ("headers", "include", "platinclude")
|
| 355 |
+
)
|
| 356 |
+
if skip_cpython_build:
|
| 357 |
+
continue
|
| 358 |
+
|
| 359 |
+
warning_contexts.append((old_v, new_v, f"scheme.{k}"))
|
| 360 |
+
|
| 361 |
+
if not warning_contexts:
|
| 362 |
+
return old
|
| 363 |
+
|
| 364 |
+
# Check if this path mismatch is caused by distutils config files. Those
|
| 365 |
+
# files will no longer work once we switch to sysconfig, so this raises a
|
| 366 |
+
# deprecation message for them.
|
| 367 |
+
default_old = _distutils.distutils_scheme(
|
| 368 |
+
dist_name,
|
| 369 |
+
user,
|
| 370 |
+
home,
|
| 371 |
+
root,
|
| 372 |
+
isolated,
|
| 373 |
+
prefix,
|
| 374 |
+
ignore_config_files=True,
|
| 375 |
+
)
|
| 376 |
+
if any(default_old[k] != getattr(old, k) for k in SCHEME_KEYS):
|
| 377 |
+
deprecated(
|
| 378 |
+
reason=(
|
| 379 |
+
"Configuring installation scheme with distutils config files "
|
| 380 |
+
"is deprecated and will no longer work in the near future. If you "
|
| 381 |
+
"are using a Homebrew or Linuxbrew Python, please see discussion "
|
| 382 |
+
"at https://github.com/Homebrew/homebrew-core/issues/76621"
|
| 383 |
+
),
|
| 384 |
+
replacement=None,
|
| 385 |
+
gone_in=None,
|
| 386 |
+
)
|
| 387 |
+
return old
|
| 388 |
+
|
| 389 |
+
# Post warnings about this mismatch so user can report them back.
|
| 390 |
+
for old_v, new_v, key in warning_contexts:
|
| 391 |
+
_warn_mismatched(old_v, new_v, key=key)
|
| 392 |
+
_log_context(user=user, home=home, root=root, prefix=prefix)
|
| 393 |
+
|
| 394 |
+
return old
|
| 395 |
+
|
| 396 |
+
|
| 397 |
+
def get_bin_prefix() -> str:
|
| 398 |
+
new = _sysconfig.get_bin_prefix()
|
| 399 |
+
if _USE_SYSCONFIG:
|
| 400 |
+
return new
|
| 401 |
+
|
| 402 |
+
old = _distutils.get_bin_prefix()
|
| 403 |
+
if _warn_if_mismatch(pathlib.Path(old), pathlib.Path(new), key="bin_prefix"):
|
| 404 |
+
_log_context()
|
| 405 |
+
return old
|
| 406 |
+
|
| 407 |
+
|
| 408 |
+
def get_bin_user() -> str:
|
| 409 |
+
return _sysconfig.get_scheme("", user=True).scripts
|
| 410 |
+
|
| 411 |
+
|
| 412 |
+
def _looks_like_deb_system_dist_packages(value: str) -> bool:
|
| 413 |
+
"""Check if the value is Debian's APT-controlled dist-packages.
|
| 414 |
+
|
| 415 |
+
Debian's ``distutils.sysconfig.get_python_lib()`` implementation returns the
|
| 416 |
+
default package path controlled by APT, but does not patch ``sysconfig`` to
|
| 417 |
+
do the same. This is similar to the bug worked around in ``get_scheme()``,
|
| 418 |
+
but here the default is ``deb_system`` instead of ``unix_local``. Ultimately
|
| 419 |
+
we can't do anything about this Debian bug, and this detection allows us to
|
| 420 |
+
skip the warning when needed.
|
| 421 |
+
"""
|
| 422 |
+
if not _looks_like_debian_scheme():
|
| 423 |
+
return False
|
| 424 |
+
if value == "/usr/lib/python3/dist-packages":
|
| 425 |
+
return True
|
| 426 |
+
return False
|
| 427 |
+
|
| 428 |
+
|
| 429 |
+
def get_purelib() -> str:
|
| 430 |
+
"""Return the default pure-Python lib location."""
|
| 431 |
+
new = _sysconfig.get_purelib()
|
| 432 |
+
if _USE_SYSCONFIG:
|
| 433 |
+
return new
|
| 434 |
+
|
| 435 |
+
old = _distutils.get_purelib()
|
| 436 |
+
if _looks_like_deb_system_dist_packages(old):
|
| 437 |
+
return old
|
| 438 |
+
if _warn_if_mismatch(pathlib.Path(old), pathlib.Path(new), key="purelib"):
|
| 439 |
+
_log_context()
|
| 440 |
+
return old
|
| 441 |
+
|
| 442 |
+
|
| 443 |
+
def get_platlib() -> str:
|
| 444 |
+
"""Return the default platform-shared lib location."""
|
| 445 |
+
new = _sysconfig.get_platlib()
|
| 446 |
+
if _USE_SYSCONFIG:
|
| 447 |
+
return new
|
| 448 |
+
|
| 449 |
+
from . import _distutils
|
| 450 |
+
|
| 451 |
+
old = _distutils.get_platlib()
|
| 452 |
+
if _looks_like_deb_system_dist_packages(old):
|
| 453 |
+
return old
|
| 454 |
+
if _warn_if_mismatch(pathlib.Path(old), pathlib.Path(new), key="platlib"):
|
| 455 |
+
_log_context()
|
| 456 |
+
return old
|
tuning-competition-baseline/.venv/lib/python3.11/site-packages/pip/_internal/locations/__pycache__/_distutils.cpython-311.pyc
ADDED
|
Binary file (7.5 kB). View file
|
|
|
tuning-competition-baseline/.venv/lib/python3.11/site-packages/pip/_internal/locations/__pycache__/_sysconfig.cpython-311.pyc
ADDED
|
Binary file (8.93 kB). View file
|
|
|
tuning-competition-baseline/.venv/lib/python3.11/site-packages/pip/_internal/locations/_sysconfig.py
ADDED
|
@@ -0,0 +1,214 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import logging
|
| 2 |
+
import os
|
| 3 |
+
import sys
|
| 4 |
+
import sysconfig
|
| 5 |
+
import typing
|
| 6 |
+
|
| 7 |
+
from pip._internal.exceptions import InvalidSchemeCombination, UserInstallationInvalid
|
| 8 |
+
from pip._internal.models.scheme import SCHEME_KEYS, Scheme
|
| 9 |
+
from pip._internal.utils.virtualenv import running_under_virtualenv
|
| 10 |
+
|
| 11 |
+
from .base import change_root, get_major_minor_version, is_osx_framework
|
| 12 |
+
|
| 13 |
+
logger = logging.getLogger(__name__)
|
| 14 |
+
|
| 15 |
+
|
| 16 |
+
# Notes on _infer_* functions.
|
| 17 |
+
# Unfortunately ``get_default_scheme()`` didn't exist before 3.10, so there's no
|
| 18 |
+
# way to ask things like "what is the '_prefix' scheme on this platform". These
|
| 19 |
+
# functions try to answer that with some heuristics while accounting for ad-hoc
|
| 20 |
+
# platforms not covered by CPython's default sysconfig implementation. If the
|
| 21 |
+
# ad-hoc implementation does not fully implement sysconfig, we'll fall back to
|
| 22 |
+
# a POSIX scheme.
|
| 23 |
+
|
| 24 |
+
_AVAILABLE_SCHEMES = set(sysconfig.get_scheme_names())
|
| 25 |
+
|
| 26 |
+
_PREFERRED_SCHEME_API = getattr(sysconfig, "get_preferred_scheme", None)
|
| 27 |
+
|
| 28 |
+
|
| 29 |
+
def _should_use_osx_framework_prefix() -> bool:
|
| 30 |
+
"""Check for Apple's ``osx_framework_library`` scheme.
|
| 31 |
+
|
| 32 |
+
Python distributed by Apple's Command Line Tools has this special scheme
|
| 33 |
+
that's used when:
|
| 34 |
+
|
| 35 |
+
* This is a framework build.
|
| 36 |
+
* We are installing into the system prefix.
|
| 37 |
+
|
| 38 |
+
This does not account for ``pip install --prefix`` (also means we're not
|
| 39 |
+
installing to the system prefix), which should use ``posix_prefix``, but
|
| 40 |
+
logic here means ``_infer_prefix()`` outputs ``osx_framework_library``. But
|
| 41 |
+
since ``prefix`` is not available for ``sysconfig.get_default_scheme()``,
|
| 42 |
+
which is the stdlib replacement for ``_infer_prefix()``, presumably Apple
|
| 43 |
+
wouldn't be able to magically switch between ``osx_framework_library`` and
|
| 44 |
+
``posix_prefix``. ``_infer_prefix()`` returning ``osx_framework_library``
|
| 45 |
+
means its behavior is consistent whether we use the stdlib implementation
|
| 46 |
+
or our own, and we deal with this special case in ``get_scheme()`` instead.
|
| 47 |
+
"""
|
| 48 |
+
return (
|
| 49 |
+
"osx_framework_library" in _AVAILABLE_SCHEMES
|
| 50 |
+
and not running_under_virtualenv()
|
| 51 |
+
and is_osx_framework()
|
| 52 |
+
)
|
| 53 |
+
|
| 54 |
+
|
| 55 |
+
def _infer_prefix() -> str:
|
| 56 |
+
"""Try to find a prefix scheme for the current platform.
|
| 57 |
+
|
| 58 |
+
This tries:
|
| 59 |
+
|
| 60 |
+
* A special ``osx_framework_library`` for Python distributed by Apple's
|
| 61 |
+
Command Line Tools, when not running in a virtual environment.
|
| 62 |
+
* Implementation + OS, used by PyPy on Windows (``pypy_nt``).
|
| 63 |
+
* Implementation without OS, used by PyPy on POSIX (``pypy``).
|
| 64 |
+
* OS + "prefix", used by CPython on POSIX (``posix_prefix``).
|
| 65 |
+
* Just the OS name, used by CPython on Windows (``nt``).
|
| 66 |
+
|
| 67 |
+
If none of the above works, fall back to ``posix_prefix``.
|
| 68 |
+
"""
|
| 69 |
+
if _PREFERRED_SCHEME_API:
|
| 70 |
+
return _PREFERRED_SCHEME_API("prefix")
|
| 71 |
+
if _should_use_osx_framework_prefix():
|
| 72 |
+
return "osx_framework_library"
|
| 73 |
+
implementation_suffixed = f"{sys.implementation.name}_{os.name}"
|
| 74 |
+
if implementation_suffixed in _AVAILABLE_SCHEMES:
|
| 75 |
+
return implementation_suffixed
|
| 76 |
+
if sys.implementation.name in _AVAILABLE_SCHEMES:
|
| 77 |
+
return sys.implementation.name
|
| 78 |
+
suffixed = f"{os.name}_prefix"
|
| 79 |
+
if suffixed in _AVAILABLE_SCHEMES:
|
| 80 |
+
return suffixed
|
| 81 |
+
if os.name in _AVAILABLE_SCHEMES: # On Windows, prefx is just called "nt".
|
| 82 |
+
return os.name
|
| 83 |
+
return "posix_prefix"
|
| 84 |
+
|
| 85 |
+
|
| 86 |
+
def _infer_user() -> str:
|
| 87 |
+
"""Try to find a user scheme for the current platform."""
|
| 88 |
+
if _PREFERRED_SCHEME_API:
|
| 89 |
+
return _PREFERRED_SCHEME_API("user")
|
| 90 |
+
if is_osx_framework() and not running_under_virtualenv():
|
| 91 |
+
suffixed = "osx_framework_user"
|
| 92 |
+
else:
|
| 93 |
+
suffixed = f"{os.name}_user"
|
| 94 |
+
if suffixed in _AVAILABLE_SCHEMES:
|
| 95 |
+
return suffixed
|
| 96 |
+
if "posix_user" not in _AVAILABLE_SCHEMES: # User scheme unavailable.
|
| 97 |
+
raise UserInstallationInvalid()
|
| 98 |
+
return "posix_user"
|
| 99 |
+
|
| 100 |
+
|
| 101 |
+
def _infer_home() -> str:
|
| 102 |
+
"""Try to find a home for the current platform."""
|
| 103 |
+
if _PREFERRED_SCHEME_API:
|
| 104 |
+
return _PREFERRED_SCHEME_API("home")
|
| 105 |
+
suffixed = f"{os.name}_home"
|
| 106 |
+
if suffixed in _AVAILABLE_SCHEMES:
|
| 107 |
+
return suffixed
|
| 108 |
+
return "posix_home"
|
| 109 |
+
|
| 110 |
+
|
| 111 |
+
# Update these keys if the user sets a custom home.
|
| 112 |
+
_HOME_KEYS = [
|
| 113 |
+
"installed_base",
|
| 114 |
+
"base",
|
| 115 |
+
"installed_platbase",
|
| 116 |
+
"platbase",
|
| 117 |
+
"prefix",
|
| 118 |
+
"exec_prefix",
|
| 119 |
+
]
|
| 120 |
+
if sysconfig.get_config_var("userbase") is not None:
|
| 121 |
+
_HOME_KEYS.append("userbase")
|
| 122 |
+
|
| 123 |
+
|
| 124 |
+
def get_scheme(
|
| 125 |
+
dist_name: str,
|
| 126 |
+
user: bool = False,
|
| 127 |
+
home: typing.Optional[str] = None,
|
| 128 |
+
root: typing.Optional[str] = None,
|
| 129 |
+
isolated: bool = False,
|
| 130 |
+
prefix: typing.Optional[str] = None,
|
| 131 |
+
) -> Scheme:
|
| 132 |
+
"""
|
| 133 |
+
Get the "scheme" corresponding to the input parameters.
|
| 134 |
+
|
| 135 |
+
:param dist_name: the name of the package to retrieve the scheme for, used
|
| 136 |
+
in the headers scheme path
|
| 137 |
+
:param user: indicates to use the "user" scheme
|
| 138 |
+
:param home: indicates to use the "home" scheme
|
| 139 |
+
:param root: root under which other directories are re-based
|
| 140 |
+
:param isolated: ignored, but kept for distutils compatibility (where
|
| 141 |
+
this controls whether the user-site pydistutils.cfg is honored)
|
| 142 |
+
:param prefix: indicates to use the "prefix" scheme and provides the
|
| 143 |
+
base directory for the same
|
| 144 |
+
"""
|
| 145 |
+
if user and prefix:
|
| 146 |
+
raise InvalidSchemeCombination("--user", "--prefix")
|
| 147 |
+
if home and prefix:
|
| 148 |
+
raise InvalidSchemeCombination("--home", "--prefix")
|
| 149 |
+
|
| 150 |
+
if home is not None:
|
| 151 |
+
scheme_name = _infer_home()
|
| 152 |
+
elif user:
|
| 153 |
+
scheme_name = _infer_user()
|
| 154 |
+
else:
|
| 155 |
+
scheme_name = _infer_prefix()
|
| 156 |
+
|
| 157 |
+
# Special case: When installing into a custom prefix, use posix_prefix
|
| 158 |
+
# instead of osx_framework_library. See _should_use_osx_framework_prefix()
|
| 159 |
+
# docstring for details.
|
| 160 |
+
if prefix is not None and scheme_name == "osx_framework_library":
|
| 161 |
+
scheme_name = "posix_prefix"
|
| 162 |
+
|
| 163 |
+
if home is not None:
|
| 164 |
+
variables = {k: home for k in _HOME_KEYS}
|
| 165 |
+
elif prefix is not None:
|
| 166 |
+
variables = {k: prefix for k in _HOME_KEYS}
|
| 167 |
+
else:
|
| 168 |
+
variables = {}
|
| 169 |
+
|
| 170 |
+
paths = sysconfig.get_paths(scheme=scheme_name, vars=variables)
|
| 171 |
+
|
| 172 |
+
# Logic here is very arbitrary, we're doing it for compatibility, don't ask.
|
| 173 |
+
# 1. Pip historically uses a special header path in virtual environments.
|
| 174 |
+
# 2. If the distribution name is not known, distutils uses 'UNKNOWN'. We
|
| 175 |
+
# only do the same when not running in a virtual environment because
|
| 176 |
+
# pip's historical header path logic (see point 1) did not do this.
|
| 177 |
+
if running_under_virtualenv():
|
| 178 |
+
if user:
|
| 179 |
+
base = variables.get("userbase", sys.prefix)
|
| 180 |
+
else:
|
| 181 |
+
base = variables.get("base", sys.prefix)
|
| 182 |
+
python_xy = f"python{get_major_minor_version()}"
|
| 183 |
+
paths["include"] = os.path.join(base, "include", "site", python_xy)
|
| 184 |
+
elif not dist_name:
|
| 185 |
+
dist_name = "UNKNOWN"
|
| 186 |
+
|
| 187 |
+
scheme = Scheme(
|
| 188 |
+
platlib=paths["platlib"],
|
| 189 |
+
purelib=paths["purelib"],
|
| 190 |
+
headers=os.path.join(paths["include"], dist_name),
|
| 191 |
+
scripts=paths["scripts"],
|
| 192 |
+
data=paths["data"],
|
| 193 |
+
)
|
| 194 |
+
if root is not None:
|
| 195 |
+
converted_keys = {}
|
| 196 |
+
for key in SCHEME_KEYS:
|
| 197 |
+
converted_keys[key] = change_root(root, getattr(scheme, key))
|
| 198 |
+
scheme = Scheme(**converted_keys)
|
| 199 |
+
return scheme
|
| 200 |
+
|
| 201 |
+
|
| 202 |
+
def get_bin_prefix() -> str:
|
| 203 |
+
# Forcing to use /usr/local/bin for standard macOS framework installs.
|
| 204 |
+
if sys.platform[:6] == "darwin" and sys.prefix[:16] == "/System/Library/":
|
| 205 |
+
return "/usr/local/bin"
|
| 206 |
+
return sysconfig.get_paths()["scripts"]
|
| 207 |
+
|
| 208 |
+
|
| 209 |
+
def get_purelib() -> str:
|
| 210 |
+
return sysconfig.get_paths()["purelib"]
|
| 211 |
+
|
| 212 |
+
|
| 213 |
+
def get_platlib() -> str:
|
| 214 |
+
return sysconfig.get_paths()["platlib"]
|
tuning-competition-baseline/.venv/lib/python3.11/site-packages/pip/_internal/metadata/importlib/__pycache__/_compat.cpython-311.pyc
ADDED
|
Binary file (4.88 kB). View file
|
|
|
tuning-competition-baseline/.venv/lib/python3.11/site-packages/pip/_internal/network/__init__.py
ADDED
|
@@ -0,0 +1,2 @@
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"""Contains purely network-related utilities.
|
| 2 |
+
"""
|
tuning-competition-baseline/.venv/lib/python3.11/site-packages/pip/_internal/network/session.py
ADDED
|
@@ -0,0 +1,522 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"""PipSession and supporting code, containing all pip-specific
|
| 2 |
+
network request configuration and behavior.
|
| 3 |
+
"""
|
| 4 |
+
|
| 5 |
+
import email.utils
|
| 6 |
+
import functools
|
| 7 |
+
import io
|
| 8 |
+
import ipaddress
|
| 9 |
+
import json
|
| 10 |
+
import logging
|
| 11 |
+
import mimetypes
|
| 12 |
+
import os
|
| 13 |
+
import platform
|
| 14 |
+
import shutil
|
| 15 |
+
import subprocess
|
| 16 |
+
import sys
|
| 17 |
+
import urllib.parse
|
| 18 |
+
import warnings
|
| 19 |
+
from typing import (
|
| 20 |
+
TYPE_CHECKING,
|
| 21 |
+
Any,
|
| 22 |
+
Dict,
|
| 23 |
+
Generator,
|
| 24 |
+
List,
|
| 25 |
+
Mapping,
|
| 26 |
+
Optional,
|
| 27 |
+
Sequence,
|
| 28 |
+
Tuple,
|
| 29 |
+
Union,
|
| 30 |
+
)
|
| 31 |
+
|
| 32 |
+
from pip._vendor import requests, urllib3
|
| 33 |
+
from pip._vendor.cachecontrol import CacheControlAdapter as _BaseCacheControlAdapter
|
| 34 |
+
from pip._vendor.requests.adapters import DEFAULT_POOLBLOCK, BaseAdapter
|
| 35 |
+
from pip._vendor.requests.adapters import HTTPAdapter as _BaseHTTPAdapter
|
| 36 |
+
from pip._vendor.requests.models import PreparedRequest, Response
|
| 37 |
+
from pip._vendor.requests.structures import CaseInsensitiveDict
|
| 38 |
+
from pip._vendor.urllib3.connectionpool import ConnectionPool
|
| 39 |
+
from pip._vendor.urllib3.exceptions import InsecureRequestWarning
|
| 40 |
+
|
| 41 |
+
from pip import __version__
|
| 42 |
+
from pip._internal.metadata import get_default_environment
|
| 43 |
+
from pip._internal.models.link import Link
|
| 44 |
+
from pip._internal.network.auth import MultiDomainBasicAuth
|
| 45 |
+
from pip._internal.network.cache import SafeFileCache
|
| 46 |
+
|
| 47 |
+
# Import ssl from compat so the initial import occurs in only one place.
|
| 48 |
+
from pip._internal.utils.compat import has_tls
|
| 49 |
+
from pip._internal.utils.glibc import libc_ver
|
| 50 |
+
from pip._internal.utils.misc import build_url_from_netloc, parse_netloc
|
| 51 |
+
from pip._internal.utils.urls import url_to_path
|
| 52 |
+
|
| 53 |
+
if TYPE_CHECKING:
|
| 54 |
+
from ssl import SSLContext
|
| 55 |
+
|
| 56 |
+
from pip._vendor.urllib3.poolmanager import PoolManager
|
| 57 |
+
|
| 58 |
+
|
| 59 |
+
logger = logging.getLogger(__name__)
|
| 60 |
+
|
| 61 |
+
SecureOrigin = Tuple[str, str, Optional[Union[int, str]]]
|
| 62 |
+
|
| 63 |
+
|
| 64 |
+
# Ignore warning raised when using --trusted-host.
|
| 65 |
+
warnings.filterwarnings("ignore", category=InsecureRequestWarning)
|
| 66 |
+
|
| 67 |
+
|
| 68 |
+
SECURE_ORIGINS: List[SecureOrigin] = [
|
| 69 |
+
# protocol, hostname, port
|
| 70 |
+
# Taken from Chrome's list of secure origins (See: http://bit.ly/1qrySKC)
|
| 71 |
+
("https", "*", "*"),
|
| 72 |
+
("*", "localhost", "*"),
|
| 73 |
+
("*", "127.0.0.0/8", "*"),
|
| 74 |
+
("*", "::1/128", "*"),
|
| 75 |
+
("file", "*", None),
|
| 76 |
+
# ssh is always secure.
|
| 77 |
+
("ssh", "*", "*"),
|
| 78 |
+
]
|
| 79 |
+
|
| 80 |
+
|
| 81 |
+
# These are environment variables present when running under various
|
| 82 |
+
# CI systems. For each variable, some CI systems that use the variable
|
| 83 |
+
# are indicated. The collection was chosen so that for each of a number
|
| 84 |
+
# of popular systems, at least one of the environment variables is used.
|
| 85 |
+
# This list is used to provide some indication of and lower bound for
|
| 86 |
+
# CI traffic to PyPI. Thus, it is okay if the list is not comprehensive.
|
| 87 |
+
# For more background, see: https://github.com/pypa/pip/issues/5499
|
| 88 |
+
CI_ENVIRONMENT_VARIABLES = (
|
| 89 |
+
# Azure Pipelines
|
| 90 |
+
"BUILD_BUILDID",
|
| 91 |
+
# Jenkins
|
| 92 |
+
"BUILD_ID",
|
| 93 |
+
# AppVeyor, CircleCI, Codeship, Gitlab CI, Shippable, Travis CI
|
| 94 |
+
"CI",
|
| 95 |
+
# Explicit environment variable.
|
| 96 |
+
"PIP_IS_CI",
|
| 97 |
+
)
|
| 98 |
+
|
| 99 |
+
|
| 100 |
+
def looks_like_ci() -> bool:
|
| 101 |
+
"""
|
| 102 |
+
Return whether it looks like pip is running under CI.
|
| 103 |
+
"""
|
| 104 |
+
# We don't use the method of checking for a tty (e.g. using isatty())
|
| 105 |
+
# because some CI systems mimic a tty (e.g. Travis CI). Thus that
|
| 106 |
+
# method doesn't provide definitive information in either direction.
|
| 107 |
+
return any(name in os.environ for name in CI_ENVIRONMENT_VARIABLES)
|
| 108 |
+
|
| 109 |
+
|
| 110 |
+
@functools.lru_cache(maxsize=1)
|
| 111 |
+
def user_agent() -> str:
|
| 112 |
+
"""
|
| 113 |
+
Return a string representing the user agent.
|
| 114 |
+
"""
|
| 115 |
+
data: Dict[str, Any] = {
|
| 116 |
+
"installer": {"name": "pip", "version": __version__},
|
| 117 |
+
"python": platform.python_version(),
|
| 118 |
+
"implementation": {
|
| 119 |
+
"name": platform.python_implementation(),
|
| 120 |
+
},
|
| 121 |
+
}
|
| 122 |
+
|
| 123 |
+
if data["implementation"]["name"] == "CPython":
|
| 124 |
+
data["implementation"]["version"] = platform.python_version()
|
| 125 |
+
elif data["implementation"]["name"] == "PyPy":
|
| 126 |
+
pypy_version_info = sys.pypy_version_info # type: ignore
|
| 127 |
+
if pypy_version_info.releaselevel == "final":
|
| 128 |
+
pypy_version_info = pypy_version_info[:3]
|
| 129 |
+
data["implementation"]["version"] = ".".join(
|
| 130 |
+
[str(x) for x in pypy_version_info]
|
| 131 |
+
)
|
| 132 |
+
elif data["implementation"]["name"] == "Jython":
|
| 133 |
+
# Complete Guess
|
| 134 |
+
data["implementation"]["version"] = platform.python_version()
|
| 135 |
+
elif data["implementation"]["name"] == "IronPython":
|
| 136 |
+
# Complete Guess
|
| 137 |
+
data["implementation"]["version"] = platform.python_version()
|
| 138 |
+
|
| 139 |
+
if sys.platform.startswith("linux"):
|
| 140 |
+
from pip._vendor import distro
|
| 141 |
+
|
| 142 |
+
linux_distribution = distro.name(), distro.version(), distro.codename()
|
| 143 |
+
distro_infos: Dict[str, Any] = dict(
|
| 144 |
+
filter(
|
| 145 |
+
lambda x: x[1],
|
| 146 |
+
zip(["name", "version", "id"], linux_distribution),
|
| 147 |
+
)
|
| 148 |
+
)
|
| 149 |
+
libc = dict(
|
| 150 |
+
filter(
|
| 151 |
+
lambda x: x[1],
|
| 152 |
+
zip(["lib", "version"], libc_ver()),
|
| 153 |
+
)
|
| 154 |
+
)
|
| 155 |
+
if libc:
|
| 156 |
+
distro_infos["libc"] = libc
|
| 157 |
+
if distro_infos:
|
| 158 |
+
data["distro"] = distro_infos
|
| 159 |
+
|
| 160 |
+
if sys.platform.startswith("darwin") and platform.mac_ver()[0]:
|
| 161 |
+
data["distro"] = {"name": "macOS", "version": platform.mac_ver()[0]}
|
| 162 |
+
|
| 163 |
+
if platform.system():
|
| 164 |
+
data.setdefault("system", {})["name"] = platform.system()
|
| 165 |
+
|
| 166 |
+
if platform.release():
|
| 167 |
+
data.setdefault("system", {})["release"] = platform.release()
|
| 168 |
+
|
| 169 |
+
if platform.machine():
|
| 170 |
+
data["cpu"] = platform.machine()
|
| 171 |
+
|
| 172 |
+
if has_tls():
|
| 173 |
+
import _ssl as ssl
|
| 174 |
+
|
| 175 |
+
data["openssl_version"] = ssl.OPENSSL_VERSION
|
| 176 |
+
|
| 177 |
+
setuptools_dist = get_default_environment().get_distribution("setuptools")
|
| 178 |
+
if setuptools_dist is not None:
|
| 179 |
+
data["setuptools_version"] = str(setuptools_dist.version)
|
| 180 |
+
|
| 181 |
+
if shutil.which("rustc") is not None:
|
| 182 |
+
# If for any reason `rustc --version` fails, silently ignore it
|
| 183 |
+
try:
|
| 184 |
+
rustc_output = subprocess.check_output(
|
| 185 |
+
["rustc", "--version"], stderr=subprocess.STDOUT, timeout=0.5
|
| 186 |
+
)
|
| 187 |
+
except Exception:
|
| 188 |
+
pass
|
| 189 |
+
else:
|
| 190 |
+
if rustc_output.startswith(b"rustc "):
|
| 191 |
+
# The format of `rustc --version` is:
|
| 192 |
+
# `b'rustc 1.52.1 (9bc8c42bb 2021-05-09)\n'`
|
| 193 |
+
# We extract just the middle (1.52.1) part
|
| 194 |
+
data["rustc_version"] = rustc_output.split(b" ")[1].decode()
|
| 195 |
+
|
| 196 |
+
# Use None rather than False so as not to give the impression that
|
| 197 |
+
# pip knows it is not being run under CI. Rather, it is a null or
|
| 198 |
+
# inconclusive result. Also, we include some value rather than no
|
| 199 |
+
# value to make it easier to know that the check has been run.
|
| 200 |
+
data["ci"] = True if looks_like_ci() else None
|
| 201 |
+
|
| 202 |
+
user_data = os.environ.get("PIP_USER_AGENT_USER_DATA")
|
| 203 |
+
if user_data is not None:
|
| 204 |
+
data["user_data"] = user_data
|
| 205 |
+
|
| 206 |
+
return "{data[installer][name]}/{data[installer][version]} {json}".format(
|
| 207 |
+
data=data,
|
| 208 |
+
json=json.dumps(data, separators=(",", ":"), sort_keys=True),
|
| 209 |
+
)
|
| 210 |
+
|
| 211 |
+
|
| 212 |
+
class LocalFSAdapter(BaseAdapter):
|
| 213 |
+
def send(
|
| 214 |
+
self,
|
| 215 |
+
request: PreparedRequest,
|
| 216 |
+
stream: bool = False,
|
| 217 |
+
timeout: Optional[Union[float, Tuple[float, float]]] = None,
|
| 218 |
+
verify: Union[bool, str] = True,
|
| 219 |
+
cert: Optional[Union[str, Tuple[str, str]]] = None,
|
| 220 |
+
proxies: Optional[Mapping[str, str]] = None,
|
| 221 |
+
) -> Response:
|
| 222 |
+
pathname = url_to_path(request.url)
|
| 223 |
+
|
| 224 |
+
resp = Response()
|
| 225 |
+
resp.status_code = 200
|
| 226 |
+
resp.url = request.url
|
| 227 |
+
|
| 228 |
+
try:
|
| 229 |
+
stats = os.stat(pathname)
|
| 230 |
+
except OSError as exc:
|
| 231 |
+
# format the exception raised as a io.BytesIO object,
|
| 232 |
+
# to return a better error message:
|
| 233 |
+
resp.status_code = 404
|
| 234 |
+
resp.reason = type(exc).__name__
|
| 235 |
+
resp.raw = io.BytesIO(f"{resp.reason}: {exc}".encode())
|
| 236 |
+
else:
|
| 237 |
+
modified = email.utils.formatdate(stats.st_mtime, usegmt=True)
|
| 238 |
+
content_type = mimetypes.guess_type(pathname)[0] or "text/plain"
|
| 239 |
+
resp.headers = CaseInsensitiveDict(
|
| 240 |
+
{
|
| 241 |
+
"Content-Type": content_type,
|
| 242 |
+
"Content-Length": stats.st_size,
|
| 243 |
+
"Last-Modified": modified,
|
| 244 |
+
}
|
| 245 |
+
)
|
| 246 |
+
|
| 247 |
+
resp.raw = open(pathname, "rb")
|
| 248 |
+
resp.close = resp.raw.close
|
| 249 |
+
|
| 250 |
+
return resp
|
| 251 |
+
|
| 252 |
+
def close(self) -> None:
|
| 253 |
+
pass
|
| 254 |
+
|
| 255 |
+
|
| 256 |
+
class _SSLContextAdapterMixin:
|
| 257 |
+
"""Mixin to add the ``ssl_context`` constructor argument to HTTP adapters.
|
| 258 |
+
|
| 259 |
+
The additional argument is forwarded directly to the pool manager. This allows us
|
| 260 |
+
to dynamically decide what SSL store to use at runtime, which is used to implement
|
| 261 |
+
the optional ``truststore`` backend.
|
| 262 |
+
"""
|
| 263 |
+
|
| 264 |
+
def __init__(
|
| 265 |
+
self,
|
| 266 |
+
*,
|
| 267 |
+
ssl_context: Optional["SSLContext"] = None,
|
| 268 |
+
**kwargs: Any,
|
| 269 |
+
) -> None:
|
| 270 |
+
self._ssl_context = ssl_context
|
| 271 |
+
super().__init__(**kwargs)
|
| 272 |
+
|
| 273 |
+
def init_poolmanager(
|
| 274 |
+
self,
|
| 275 |
+
connections: int,
|
| 276 |
+
maxsize: int,
|
| 277 |
+
block: bool = DEFAULT_POOLBLOCK,
|
| 278 |
+
**pool_kwargs: Any,
|
| 279 |
+
) -> "PoolManager":
|
| 280 |
+
if self._ssl_context is not None:
|
| 281 |
+
pool_kwargs.setdefault("ssl_context", self._ssl_context)
|
| 282 |
+
return super().init_poolmanager( # type: ignore[misc]
|
| 283 |
+
connections=connections,
|
| 284 |
+
maxsize=maxsize,
|
| 285 |
+
block=block,
|
| 286 |
+
**pool_kwargs,
|
| 287 |
+
)
|
| 288 |
+
|
| 289 |
+
|
| 290 |
+
class HTTPAdapter(_SSLContextAdapterMixin, _BaseHTTPAdapter):
|
| 291 |
+
pass
|
| 292 |
+
|
| 293 |
+
|
| 294 |
+
class CacheControlAdapter(_SSLContextAdapterMixin, _BaseCacheControlAdapter):
|
| 295 |
+
pass
|
| 296 |
+
|
| 297 |
+
|
| 298 |
+
class InsecureHTTPAdapter(HTTPAdapter):
|
| 299 |
+
def cert_verify(
|
| 300 |
+
self,
|
| 301 |
+
conn: ConnectionPool,
|
| 302 |
+
url: str,
|
| 303 |
+
verify: Union[bool, str],
|
| 304 |
+
cert: Optional[Union[str, Tuple[str, str]]],
|
| 305 |
+
) -> None:
|
| 306 |
+
super().cert_verify(conn=conn, url=url, verify=False, cert=cert)
|
| 307 |
+
|
| 308 |
+
|
| 309 |
+
class InsecureCacheControlAdapter(CacheControlAdapter):
|
| 310 |
+
def cert_verify(
|
| 311 |
+
self,
|
| 312 |
+
conn: ConnectionPool,
|
| 313 |
+
url: str,
|
| 314 |
+
verify: Union[bool, str],
|
| 315 |
+
cert: Optional[Union[str, Tuple[str, str]]],
|
| 316 |
+
) -> None:
|
| 317 |
+
super().cert_verify(conn=conn, url=url, verify=False, cert=cert)
|
| 318 |
+
|
| 319 |
+
|
| 320 |
+
class PipSession(requests.Session):
|
| 321 |
+
timeout: Optional[int] = None
|
| 322 |
+
|
| 323 |
+
def __init__(
|
| 324 |
+
self,
|
| 325 |
+
*args: Any,
|
| 326 |
+
retries: int = 0,
|
| 327 |
+
cache: Optional[str] = None,
|
| 328 |
+
trusted_hosts: Sequence[str] = (),
|
| 329 |
+
index_urls: Optional[List[str]] = None,
|
| 330 |
+
ssl_context: Optional["SSLContext"] = None,
|
| 331 |
+
**kwargs: Any,
|
| 332 |
+
) -> None:
|
| 333 |
+
"""
|
| 334 |
+
:param trusted_hosts: Domains not to emit warnings for when not using
|
| 335 |
+
HTTPS.
|
| 336 |
+
"""
|
| 337 |
+
super().__init__(*args, **kwargs)
|
| 338 |
+
|
| 339 |
+
# Namespace the attribute with "pip_" just in case to prevent
|
| 340 |
+
# possible conflicts with the base class.
|
| 341 |
+
self.pip_trusted_origins: List[Tuple[str, Optional[int]]] = []
|
| 342 |
+
|
| 343 |
+
# Attach our User Agent to the request
|
| 344 |
+
self.headers["User-Agent"] = user_agent()
|
| 345 |
+
|
| 346 |
+
# Attach our Authentication handler to the session
|
| 347 |
+
self.auth = MultiDomainBasicAuth(index_urls=index_urls)
|
| 348 |
+
|
| 349 |
+
# Create our urllib3.Retry instance which will allow us to customize
|
| 350 |
+
# how we handle retries.
|
| 351 |
+
retries = urllib3.Retry(
|
| 352 |
+
# Set the total number of retries that a particular request can
|
| 353 |
+
# have.
|
| 354 |
+
total=retries,
|
| 355 |
+
# A 503 error from PyPI typically means that the Fastly -> Origin
|
| 356 |
+
# connection got interrupted in some way. A 503 error in general
|
| 357 |
+
# is typically considered a transient error so we'll go ahead and
|
| 358 |
+
# retry it.
|
| 359 |
+
# A 500 may indicate transient error in Amazon S3
|
| 360 |
+
# A 502 may be a transient error from a CDN like CloudFlare or CloudFront
|
| 361 |
+
# A 520 or 527 - may indicate transient error in CloudFlare
|
| 362 |
+
status_forcelist=[500, 502, 503, 520, 527],
|
| 363 |
+
# Add a small amount of back off between failed requests in
|
| 364 |
+
# order to prevent hammering the service.
|
| 365 |
+
backoff_factor=0.25,
|
| 366 |
+
) # type: ignore
|
| 367 |
+
|
| 368 |
+
# Our Insecure HTTPAdapter disables HTTPS validation. It does not
|
| 369 |
+
# support caching so we'll use it for all http:// URLs.
|
| 370 |
+
# If caching is disabled, we will also use it for
|
| 371 |
+
# https:// hosts that we've marked as ignoring
|
| 372 |
+
# TLS errors for (trusted-hosts).
|
| 373 |
+
insecure_adapter = InsecureHTTPAdapter(max_retries=retries)
|
| 374 |
+
|
| 375 |
+
# We want to _only_ cache responses on securely fetched origins or when
|
| 376 |
+
# the host is specified as trusted. We do this because
|
| 377 |
+
# we can't validate the response of an insecurely/untrusted fetched
|
| 378 |
+
# origin, and we don't want someone to be able to poison the cache and
|
| 379 |
+
# require manual eviction from the cache to fix it.
|
| 380 |
+
if cache:
|
| 381 |
+
secure_adapter = CacheControlAdapter(
|
| 382 |
+
cache=SafeFileCache(cache),
|
| 383 |
+
max_retries=retries,
|
| 384 |
+
ssl_context=ssl_context,
|
| 385 |
+
)
|
| 386 |
+
self._trusted_host_adapter = InsecureCacheControlAdapter(
|
| 387 |
+
cache=SafeFileCache(cache),
|
| 388 |
+
max_retries=retries,
|
| 389 |
+
)
|
| 390 |
+
else:
|
| 391 |
+
secure_adapter = HTTPAdapter(max_retries=retries, ssl_context=ssl_context)
|
| 392 |
+
self._trusted_host_adapter = insecure_adapter
|
| 393 |
+
|
| 394 |
+
self.mount("https://", secure_adapter)
|
| 395 |
+
self.mount("http://", insecure_adapter)
|
| 396 |
+
|
| 397 |
+
# Enable file:// urls
|
| 398 |
+
self.mount("file://", LocalFSAdapter())
|
| 399 |
+
|
| 400 |
+
for host in trusted_hosts:
|
| 401 |
+
self.add_trusted_host(host, suppress_logging=True)
|
| 402 |
+
|
| 403 |
+
def update_index_urls(self, new_index_urls: List[str]) -> None:
|
| 404 |
+
"""
|
| 405 |
+
:param new_index_urls: New index urls to update the authentication
|
| 406 |
+
handler with.
|
| 407 |
+
"""
|
| 408 |
+
self.auth.index_urls = new_index_urls
|
| 409 |
+
|
| 410 |
+
def add_trusted_host(
|
| 411 |
+
self, host: str, source: Optional[str] = None, suppress_logging: bool = False
|
| 412 |
+
) -> None:
|
| 413 |
+
"""
|
| 414 |
+
:param host: It is okay to provide a host that has previously been
|
| 415 |
+
added.
|
| 416 |
+
:param source: An optional source string, for logging where the host
|
| 417 |
+
string came from.
|
| 418 |
+
"""
|
| 419 |
+
if not suppress_logging:
|
| 420 |
+
msg = f"adding trusted host: {host!r}"
|
| 421 |
+
if source is not None:
|
| 422 |
+
msg += f" (from {source})"
|
| 423 |
+
logger.info(msg)
|
| 424 |
+
|
| 425 |
+
parsed_host, parsed_port = parse_netloc(host)
|
| 426 |
+
if parsed_host is None:
|
| 427 |
+
raise ValueError(f"Trusted host URL must include a host part: {host!r}")
|
| 428 |
+
if (parsed_host, parsed_port) not in self.pip_trusted_origins:
|
| 429 |
+
self.pip_trusted_origins.append((parsed_host, parsed_port))
|
| 430 |
+
|
| 431 |
+
self.mount(
|
| 432 |
+
build_url_from_netloc(host, scheme="http") + "/", self._trusted_host_adapter
|
| 433 |
+
)
|
| 434 |
+
self.mount(build_url_from_netloc(host) + "/", self._trusted_host_adapter)
|
| 435 |
+
if not parsed_port:
|
| 436 |
+
self.mount(
|
| 437 |
+
build_url_from_netloc(host, scheme="http") + ":",
|
| 438 |
+
self._trusted_host_adapter,
|
| 439 |
+
)
|
| 440 |
+
# Mount wildcard ports for the same host.
|
| 441 |
+
self.mount(build_url_from_netloc(host) + ":", self._trusted_host_adapter)
|
| 442 |
+
|
| 443 |
+
def iter_secure_origins(self) -> Generator[SecureOrigin, None, None]:
|
| 444 |
+
yield from SECURE_ORIGINS
|
| 445 |
+
for host, port in self.pip_trusted_origins:
|
| 446 |
+
yield ("*", host, "*" if port is None else port)
|
| 447 |
+
|
| 448 |
+
def is_secure_origin(self, location: Link) -> bool:
|
| 449 |
+
# Determine if this url used a secure transport mechanism
|
| 450 |
+
parsed = urllib.parse.urlparse(str(location))
|
| 451 |
+
origin_protocol, origin_host, origin_port = (
|
| 452 |
+
parsed.scheme,
|
| 453 |
+
parsed.hostname,
|
| 454 |
+
parsed.port,
|
| 455 |
+
)
|
| 456 |
+
|
| 457 |
+
# The protocol to use to see if the protocol matches.
|
| 458 |
+
# Don't count the repository type as part of the protocol: in
|
| 459 |
+
# cases such as "git+ssh", only use "ssh". (I.e., Only verify against
|
| 460 |
+
# the last scheme.)
|
| 461 |
+
origin_protocol = origin_protocol.rsplit("+", 1)[-1]
|
| 462 |
+
|
| 463 |
+
# Determine if our origin is a secure origin by looking through our
|
| 464 |
+
# hardcoded list of secure origins, as well as any additional ones
|
| 465 |
+
# configured on this PackageFinder instance.
|
| 466 |
+
for secure_origin in self.iter_secure_origins():
|
| 467 |
+
secure_protocol, secure_host, secure_port = secure_origin
|
| 468 |
+
if origin_protocol != secure_protocol and secure_protocol != "*":
|
| 469 |
+
continue
|
| 470 |
+
|
| 471 |
+
try:
|
| 472 |
+
addr = ipaddress.ip_address(origin_host or "")
|
| 473 |
+
network = ipaddress.ip_network(secure_host)
|
| 474 |
+
except ValueError:
|
| 475 |
+
# We don't have both a valid address or a valid network, so
|
| 476 |
+
# we'll check this origin against hostnames.
|
| 477 |
+
if (
|
| 478 |
+
origin_host
|
| 479 |
+
and origin_host.lower() != secure_host.lower()
|
| 480 |
+
and secure_host != "*"
|
| 481 |
+
):
|
| 482 |
+
continue
|
| 483 |
+
else:
|
| 484 |
+
# We have a valid address and network, so see if the address
|
| 485 |
+
# is contained within the network.
|
| 486 |
+
if addr not in network:
|
| 487 |
+
continue
|
| 488 |
+
|
| 489 |
+
# Check to see if the port matches.
|
| 490 |
+
if (
|
| 491 |
+
origin_port != secure_port
|
| 492 |
+
and secure_port != "*"
|
| 493 |
+
and secure_port is not None
|
| 494 |
+
):
|
| 495 |
+
continue
|
| 496 |
+
|
| 497 |
+
# If we've gotten here, then this origin matches the current
|
| 498 |
+
# secure origin and we should return True
|
| 499 |
+
return True
|
| 500 |
+
|
| 501 |
+
# If we've gotten to this point, then the origin isn't secure and we
|
| 502 |
+
# will not accept it as a valid location to search. We will however
|
| 503 |
+
# log a warning that we are ignoring it.
|
| 504 |
+
logger.warning(
|
| 505 |
+
"The repository located at %s is not a trusted or secure host and "
|
| 506 |
+
"is being ignored. If this repository is available via HTTPS we "
|
| 507 |
+
"recommend you use HTTPS instead, otherwise you may silence "
|
| 508 |
+
"this warning and allow it anyway with '--trusted-host %s'.",
|
| 509 |
+
origin_host,
|
| 510 |
+
origin_host,
|
| 511 |
+
)
|
| 512 |
+
|
| 513 |
+
return False
|
| 514 |
+
|
| 515 |
+
def request(self, method: str, url: str, *args: Any, **kwargs: Any) -> Response:
|
| 516 |
+
# Allow setting a default timeout on a session
|
| 517 |
+
kwargs.setdefault("timeout", self.timeout)
|
| 518 |
+
# Allow setting a default proxies on a session
|
| 519 |
+
kwargs.setdefault("proxies", self.proxies)
|
| 520 |
+
|
| 521 |
+
# Dispatch the actual request
|
| 522 |
+
return super().request(method, url, *args, **kwargs)
|
tuning-competition-baseline/.venv/lib/python3.11/site-packages/pip/_internal/resolution/__pycache__/base.cpython-311.pyc
ADDED
|
Binary file (1.4 kB). View file
|
|
|
tuning-competition-baseline/.venv/lib/python3.11/site-packages/pip/_internal/resolution/resolvelib/__init__.py
ADDED
|
File without changes
|
tuning-competition-baseline/.venv/lib/python3.11/site-packages/pip/_internal/resolution/resolvelib/__pycache__/__init__.cpython-311.pyc
ADDED
|
Binary file (236 Bytes). View file
|
|
|
tuning-competition-baseline/.venv/lib/python3.11/site-packages/pip/_internal/resolution/resolvelib/__pycache__/base.cpython-311.pyc
ADDED
|
Binary file (9.15 kB). View file
|
|
|
tuning-competition-baseline/.venv/lib/python3.11/site-packages/pip/_internal/resolution/resolvelib/__pycache__/candidates.cpython-311.pyc
ADDED
|
Binary file (30.3 kB). View file
|
|
|
tuning-competition-baseline/.venv/lib/python3.11/site-packages/pip/_internal/resolution/resolvelib/__pycache__/factory.cpython-311.pyc
ADDED
|
Binary file (36.3 kB). View file
|
|
|
tuning-competition-baseline/.venv/lib/python3.11/site-packages/pip/_internal/resolution/resolvelib/__pycache__/found_candidates.cpython-311.pyc
ADDED
|
Binary file (7.42 kB). View file
|
|
|
tuning-competition-baseline/.venv/lib/python3.11/site-packages/pip/_internal/resolution/resolvelib/__pycache__/provider.cpython-311.pyc
ADDED
|
Binary file (11.6 kB). View file
|
|
|
tuning-competition-baseline/.venv/lib/python3.11/site-packages/pip/_internal/resolution/resolvelib/__pycache__/requirements.cpython-311.pyc
ADDED
|
Binary file (16.1 kB). View file
|
|
|
tuning-competition-baseline/.venv/lib/python3.11/site-packages/pip/_internal/resolution/resolvelib/__pycache__/resolver.cpython-311.pyc
ADDED
|
Binary file (13.5 kB). View file
|
|
|
tuning-competition-baseline/.venv/lib/python3.11/site-packages/pip/_internal/resolution/resolvelib/base.py
ADDED
|
@@ -0,0 +1,139 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from dataclasses import dataclass
|
| 2 |
+
from typing import FrozenSet, Iterable, Optional, Tuple
|
| 3 |
+
|
| 4 |
+
from pip._vendor.packaging.specifiers import SpecifierSet
|
| 5 |
+
from pip._vendor.packaging.utils import NormalizedName
|
| 6 |
+
from pip._vendor.packaging.version import Version
|
| 7 |
+
|
| 8 |
+
from pip._internal.models.link import Link, links_equivalent
|
| 9 |
+
from pip._internal.req.req_install import InstallRequirement
|
| 10 |
+
from pip._internal.utils.hashes import Hashes
|
| 11 |
+
|
| 12 |
+
CandidateLookup = Tuple[Optional["Candidate"], Optional[InstallRequirement]]
|
| 13 |
+
|
| 14 |
+
|
| 15 |
+
def format_name(project: NormalizedName, extras: FrozenSet[NormalizedName]) -> str:
|
| 16 |
+
if not extras:
|
| 17 |
+
return project
|
| 18 |
+
extras_expr = ",".join(sorted(extras))
|
| 19 |
+
return f"{project}[{extras_expr}]"
|
| 20 |
+
|
| 21 |
+
|
| 22 |
+
@dataclass(frozen=True)
|
| 23 |
+
class Constraint:
|
| 24 |
+
specifier: SpecifierSet
|
| 25 |
+
hashes: Hashes
|
| 26 |
+
links: FrozenSet[Link]
|
| 27 |
+
|
| 28 |
+
@classmethod
|
| 29 |
+
def empty(cls) -> "Constraint":
|
| 30 |
+
return Constraint(SpecifierSet(), Hashes(), frozenset())
|
| 31 |
+
|
| 32 |
+
@classmethod
|
| 33 |
+
def from_ireq(cls, ireq: InstallRequirement) -> "Constraint":
|
| 34 |
+
links = frozenset([ireq.link]) if ireq.link else frozenset()
|
| 35 |
+
return Constraint(ireq.specifier, ireq.hashes(trust_internet=False), links)
|
| 36 |
+
|
| 37 |
+
def __bool__(self) -> bool:
|
| 38 |
+
return bool(self.specifier) or bool(self.hashes) or bool(self.links)
|
| 39 |
+
|
| 40 |
+
def __and__(self, other: InstallRequirement) -> "Constraint":
|
| 41 |
+
if not isinstance(other, InstallRequirement):
|
| 42 |
+
return NotImplemented
|
| 43 |
+
specifier = self.specifier & other.specifier
|
| 44 |
+
hashes = self.hashes & other.hashes(trust_internet=False)
|
| 45 |
+
links = self.links
|
| 46 |
+
if other.link:
|
| 47 |
+
links = links.union([other.link])
|
| 48 |
+
return Constraint(specifier, hashes, links)
|
| 49 |
+
|
| 50 |
+
def is_satisfied_by(self, candidate: "Candidate") -> bool:
|
| 51 |
+
# Reject if there are any mismatched URL constraints on this package.
|
| 52 |
+
if self.links and not all(_match_link(link, candidate) for link in self.links):
|
| 53 |
+
return False
|
| 54 |
+
# We can safely always allow prereleases here since PackageFinder
|
| 55 |
+
# already implements the prerelease logic, and would have filtered out
|
| 56 |
+
# prerelease candidates if the user does not expect them.
|
| 57 |
+
return self.specifier.contains(candidate.version, prereleases=True)
|
| 58 |
+
|
| 59 |
+
|
| 60 |
+
class Requirement:
|
| 61 |
+
@property
|
| 62 |
+
def project_name(self) -> NormalizedName:
|
| 63 |
+
"""The "project name" of a requirement.
|
| 64 |
+
|
| 65 |
+
This is different from ``name`` if this requirement contains extras,
|
| 66 |
+
in which case ``name`` would contain the ``[...]`` part, while this
|
| 67 |
+
refers to the name of the project.
|
| 68 |
+
"""
|
| 69 |
+
raise NotImplementedError("Subclass should override")
|
| 70 |
+
|
| 71 |
+
@property
|
| 72 |
+
def name(self) -> str:
|
| 73 |
+
"""The name identifying this requirement in the resolver.
|
| 74 |
+
|
| 75 |
+
This is different from ``project_name`` if this requirement contains
|
| 76 |
+
extras, where ``project_name`` would not contain the ``[...]`` part.
|
| 77 |
+
"""
|
| 78 |
+
raise NotImplementedError("Subclass should override")
|
| 79 |
+
|
| 80 |
+
def is_satisfied_by(self, candidate: "Candidate") -> bool:
|
| 81 |
+
return False
|
| 82 |
+
|
| 83 |
+
def get_candidate_lookup(self) -> CandidateLookup:
|
| 84 |
+
raise NotImplementedError("Subclass should override")
|
| 85 |
+
|
| 86 |
+
def format_for_error(self) -> str:
|
| 87 |
+
raise NotImplementedError("Subclass should override")
|
| 88 |
+
|
| 89 |
+
|
| 90 |
+
def _match_link(link: Link, candidate: "Candidate") -> bool:
|
| 91 |
+
if candidate.source_link:
|
| 92 |
+
return links_equivalent(link, candidate.source_link)
|
| 93 |
+
return False
|
| 94 |
+
|
| 95 |
+
|
| 96 |
+
class Candidate:
|
| 97 |
+
@property
|
| 98 |
+
def project_name(self) -> NormalizedName:
|
| 99 |
+
"""The "project name" of the candidate.
|
| 100 |
+
|
| 101 |
+
This is different from ``name`` if this candidate contains extras,
|
| 102 |
+
in which case ``name`` would contain the ``[...]`` part, while this
|
| 103 |
+
refers to the name of the project.
|
| 104 |
+
"""
|
| 105 |
+
raise NotImplementedError("Override in subclass")
|
| 106 |
+
|
| 107 |
+
@property
|
| 108 |
+
def name(self) -> str:
|
| 109 |
+
"""The name identifying this candidate in the resolver.
|
| 110 |
+
|
| 111 |
+
This is different from ``project_name`` if this candidate contains
|
| 112 |
+
extras, where ``project_name`` would not contain the ``[...]`` part.
|
| 113 |
+
"""
|
| 114 |
+
raise NotImplementedError("Override in subclass")
|
| 115 |
+
|
| 116 |
+
@property
|
| 117 |
+
def version(self) -> Version:
|
| 118 |
+
raise NotImplementedError("Override in subclass")
|
| 119 |
+
|
| 120 |
+
@property
|
| 121 |
+
def is_installed(self) -> bool:
|
| 122 |
+
raise NotImplementedError("Override in subclass")
|
| 123 |
+
|
| 124 |
+
@property
|
| 125 |
+
def is_editable(self) -> bool:
|
| 126 |
+
raise NotImplementedError("Override in subclass")
|
| 127 |
+
|
| 128 |
+
@property
|
| 129 |
+
def source_link(self) -> Optional[Link]:
|
| 130 |
+
raise NotImplementedError("Override in subclass")
|
| 131 |
+
|
| 132 |
+
def iter_dependencies(self, with_requires: bool) -> Iterable[Optional[Requirement]]:
|
| 133 |
+
raise NotImplementedError("Override in subclass")
|
| 134 |
+
|
| 135 |
+
def get_install_requirement(self) -> Optional[InstallRequirement]:
|
| 136 |
+
raise NotImplementedError("Override in subclass")
|
| 137 |
+
|
| 138 |
+
def format_for_error(self) -> str:
|
| 139 |
+
raise NotImplementedError("Subclass should override")
|