diff --git a/.buildinfo b/.buildinfo new file mode 100644 index 00000000..fcfe2019 --- /dev/null +++ b/.buildinfo @@ -0,0 +1,4 @@ +# Sphinx build info version 1 +# This file records the configuration used when building these files. When it is not found, a full rebuild will be done. +config: aa5e46060d599fd8e26b1133e885f011 +tags: 645f666f9bcd5a90fca523b33c5a78b7 diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md deleted file mode 100644 index 7c8b5c14..00000000 --- a/.github/ISSUE_TEMPLATE/bug_report.md +++ /dev/null @@ -1,20 +0,0 @@ ---- -name: Bug report -about: Create a report to help us improve -title: '' -labels: bug -assignees: '' - ---- - -**Describe the bug** -A clear and concise description of what the bug is. - -**To Reproduce** -Steps to reproduce the behavior. Ideally, you can provide a code example demonstrating the issue (including the Uniswap version, tokens/route, and network used). - -**Expected behavior** -A clear and concise description of what you expected to happen. - -**Additional context** -Add any other context about the problem here, such as a transaction ID demonstrating the problem. diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml deleted file mode 100644 index 0259c5df..00000000 --- a/.github/workflows/docs.yml +++ /dev/null @@ -1,39 +0,0 @@ -name: Docs - -on: - push: - branches: [ master ] - pull_request: - branches: [ master ] - -jobs: - build: - runs-on: ubuntu-latest - - steps: - - uses: actions/checkout@v4 - - name: Set up Python 3.12 - uses: actions/setup-python@v5 - with: - python-version: '3.12' - - name: Install dependencies - run: | - python -m pip install --upgrade pip poetry - poetry install - - name: Docs - run: | - poetry run make docs - - name: Upload build - uses: actions/upload-artifact@v4 - with: - name: build - path: docs/_build/html - - name: add CNAME file - run: | - echo 'uniswap-python.com' > docs/_build/html/CNAME - - name: Deploy - uses: peaceiris/actions-gh-pages@v4 - if: github.ref == 'refs/heads/master' - with: - github_token: ${{ secrets.GITHUB_TOKEN }} - publish_dir: docs/_build/html diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml deleted file mode 100644 index 2047980c..00000000 --- a/.github/workflows/release.yml +++ /dev/null @@ -1,30 +0,0 @@ -name: Release - -on: - release: - types: [created] - -jobs: - publish-pypi: - name: Publish to PyPi - runs-on: ubuntu-latest - - steps: - - uses: actions/checkout@v4 - - name: Set up Python - uses: actions/setup-python@v5 - with: - python-version: '3.x' - - name: Install dependencies - run: | - python -m pip install --upgrade pip - pip install poetry - - name: Build and publish - env: - PYPI_TOKEN: ${{ secrets.PYPI_TOKEN }} - run: | - # set pyproject.toml version to github.ref_name (without v prefix) - # just in case someone forgot... - VERSION=$(echo "${{ github.ref_name }}" | sed 's/^v//') - sed -i 's/^version = ".*"/version = "'"$VERSION"'"/' pyproject.toml - poetry publish --build --username=__token__ --password=$PYPI_TOKEN diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml deleted file mode 100644 index 4e0641e4..00000000 --- a/.github/workflows/test.yml +++ /dev/null @@ -1,128 +0,0 @@ -name: Test - -on: - push: - branches: [ master, dev/v4, dev/v4-fin ] - pull_request: - branches: [ master, dev/v4, dev/v4-fin ] - -env: - # The repo secret still points at a rate-limited Infura URL, so CI must use - # the public endpoint directly instead of preferring the secret on push runs. - PROVIDER_MAINNET: 'https://ethereum.publicnode.com' - PROVIDER_ARBITRUM: 'https://arb1.arbitrum.io/rpc' - PROVIDER_XDAI: 'https://rpc.ankr.com/gnosis' - -jobs: - test: - name: test (v${{ matrix.uniswap-version }}, ${{ matrix.network }}) - runs-on: ubuntu-latest - strategy: - fail-fast: false - matrix: - uniswap-version: [1, 2, 3, 4] - network: ["mainnet"] - # include: - # - network: arbitrum - # uniswap-version: 3 - #include: - # - network: xdai - # uniswap-version: 3 - #include: - # - network: optimism - # uniswap-version: 3 - #include: - # - network: polygon - # uniswap-version: 3 - - steps: - - uses: actions/checkout@v4 - - name: Set up Python - uses: actions/setup-python@v5 - with: - python-version: '3.12' - # Set up poetry cache, from https://github.com/python-poetry/poetry/blob/45a9b8f20384591d0a33ae876bcf23656f928ec0/.github/workflows/main.yml - - name: Get full python version - id: full-python-version - run: | - version=$(python3 -c "import sys; print('-'.join(str(v) for v in sys.version_info[:3]))") - echo "version=$version" >> "$GITHUB_OUTPUT" - - name: Set up poetry - run: | - python -m pip install --upgrade pip poetry - poetry config virtualenvs.in-project true - - - name: Set up cache - uses: actions/cache@v4 - id: cache - with: - path: .venv - key: venv-${{ runner.os }}-${{ steps.full-python-version.outputs.version }}-${{ hashFiles('**/poetry.lock') }} - - - name: Ensure cache is healthy - if: steps.cache.outputs.cache-hit == 'true' - run: timeout 10s poetry run pip --version || rm -rf .venv - - - name: Install dependencies - run: | - poetry install - - - name: Install Foundry - uses: foundry-rs/foundry-toolchain@v1 - - - name: Test - env: - # Use the secret if available, otherwise fallback to the public key - PROVIDER: ${{ ((matrix.network == 'mainnet') && env.PROVIDER_MAINNET) || ((matrix.network == 'arbitrum') && env.PROVIDER_ARBITRUM) }} - UNISWAP_VERSION: ${{ matrix.uniswap-version }} - run: | - make test - - - name: "Upload coverage to Codecov" - uses: codecov/codecov-action@v4 - with: - token: ${{ secrets.CODECOV_TOKEN }} - fail_ci_if_error: true - - typecheck: - name: typecheck - runs-on: ubuntu-latest - - steps: - - uses: actions/checkout@v4 - - name: Set up Python - uses: actions/setup-python@v5 - with: - python-version: '3.12' - - # Set up poetry cache, from https://github.com/python-poetry/poetry/blob/45a9b8f20384591d0a33ae876bcf23656f928ec0/.github/workflows/main.yml - - name: Get full python version - id: full-python-version - run: | - version=$(python3 -c "import sys; print('-'.join(str(v) for v in sys.version_info[:3]))") - echo "version=$version" >> "$GITHUB_OUTPUT" - - - name: Set up poetry - run: | - python -m pip install --upgrade pip poetry - poetry config virtualenvs.in-project true - - - name: Set up cache - uses: actions/cache@v4 - id: cache - with: - path: .venv - key: venv-${{ runner.os }}-${{ steps.full-python-version.outputs.version }}-${{ hashFiles('**/poetry.lock') }} - - - name: Ensure cache is healthy - if: steps.cache.outputs.cache-hit == 'true' - run: timeout 10s poetry run pip --version || rm -rf .venv - - - name: Install dependencies - run: | - python -m pip install --upgrade pip poetry - poetry install - - - name: Typecheck - run: | - make typecheck diff --git a/.gitignore b/.gitignore deleted file mode 100644 index a3c4235c..00000000 --- a/.gitignore +++ /dev/null @@ -1,84 +0,0 @@ -*.swp -.*cache -.env - -build/ -dist/ -.git/ -wheels/ -*.egg-info/ -.installed.cfg -*.egg -.idea/ -.vscode/ -__pycache__/ - -# PyInstaller -# Usually these files are written by a python script from a template -# before PyInstaller builds the exe, so as to inject date/other infos into it. -*.manifest -*.spec - -# Installer logs -pip-log.txt -pip-delete-this-directory.txt - -# Unit test / coverage reports -htmlcov/ -.tox/ -.coverage -.coverage.* -nosetests.xml -coverage.xml -*.cover -.hypothesis/ - -# Translations -*.mo -*.pot - -# Django stuff: -*.log -local_settings.py - -# Flask stuff: -instance/ - -# Scrapy stuff: -.scrapy - -# Sphinx documentation -docs/_build/ - -# PyBuilder -target/ - -# Jupyter Notebook -.ipynb_checkpoints - -# pyenv -.python-version - -# celery beat schedule file -celerybeat-schedule - -# SageMath parsed files -*.sage.py - -# dotenv -.env - -# virtualenv -.venv -venv/ -ENV/ - -# Spyder project settings -.spyderproject -.spyproject - -# Rope project settings -.ropeproject - -# mkdocs documentation -/site diff --git a/uniswap/py.typed b/.nojekyll similarity index 100% rename from uniswap/py.typed rename to .nojekyll diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml deleted file mode 100644 index 99b348fa..00000000 --- a/.pre-commit-config.yaml +++ /dev/null @@ -1,10 +0,0 @@ -repos: -- repo: https://github.com/astral-sh/ruff-pre-commit - # Ruff version. - rev: v0.15.2 - hooks: - # Run the linter. - - id: ruff-check - args: [ --fix ] - # Run the formatter. - - id: ruff-format diff --git a/CNAME b/CNAME new file mode 100644 index 00000000..eb3ecdb4 --- /dev/null +++ b/CNAME @@ -0,0 +1 @@ +uniswap-python.com diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md deleted file mode 100644 index e5cc8a63..00000000 --- a/CODE_OF_CONDUCT.md +++ /dev/null @@ -1,78 +0,0 @@ -# Contributor Covenant Code of Conduct - -## Our Pledge - -In the interest of fostering an open and welcoming environment, we as -contributors and maintainers pledge to making participation in our project and -our community a harassment-free experience for everyone, regardless of age, body -size, disability, ethnicity, sex characteristics, gender identity and expression, -level of experience, education, socio-economic status, nationality, personal -appearance, race, religion, or sexual identity and orientation. - -## Our Standards - -Examples of behavior that contributes to creating a positive environment -include: - -* Using welcoming and inclusive language -* Being respectful of differing viewpoints and experiences -* Gracefully accepting constructive criticism -* Focusing on what is best for the community -* Showing empathy towards other community members - -Examples of unacceptable behavior by participants include: - -* The use of sexualized language or imagery and unwelcome sexual attention or -advances - -* Trolling, insulting/derogatory comments, and personal or political attacks -* Public or private harassment -* Publishing others' private information, such as a physical or electronic -address, without explicit permission - -* Other conduct which could reasonably be considered inappropriate in a - professional setting - -## Our Responsibilities - -Project maintainers are responsible for clarifying the standards of acceptable -behavior and are expected to take appropriate and fair corrective action in -response to any instances of unacceptable behavior. - -Project maintainers have the right and responsibility to remove, edit, or -reject comments, commits, code, wiki edits, issues, and other contributions -that are not aligned to this Code of Conduct, or to ban temporarily or -permanently any contributor for other behaviors that they deem inappropriate, -threatening, offensive, or harmful. - -## Scope - -This Code of Conduct applies both within project spaces and in public spaces -when an individual is representing the project or its community. Examples of -representing a project or community include using an official project e-mail -address, posting via an official social media account, or acting as an appointed -representative at an online or offline event. Representation of a project may be -further defined and clarified by project maintainers. - -## Enforcement - -Instances of abusive, harassing, or otherwise unacceptable behavior may be -reported by contacting the project team at uniswappython@gmail.com. All -complaints will be reviewed and investigated and will result in a response that -is deemed necessary and appropriate to the circumstances. The project team is -obligated to maintain confidentiality with regard to the reporter of an incident. -Further details of specific enforcement policies may be posted separately. - -Project maintainers who do not follow or enforce the Code of Conduct in good -faith may face temporary or permanent repercussions as determined by other -members of the project's leadership. - -## Attribution - -This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, -available at https://www.contributor-covenant.org/version/1/4/code-of-conduct.html - -[homepage]: https://www.contributor-covenant.org - -For answers to common questions about this code of conduct, see -https://www.contributor-covenant.org/faq diff --git a/LICENSE b/LICENSE deleted file mode 100644 index e0bf8ea3..00000000 --- a/LICENSE +++ /dev/null @@ -1,21 +0,0 @@ -The MIT License (MIT) - -Copyright (c) 2018 Shane Fontaine - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. \ No newline at end of file diff --git a/Makefile b/Makefile deleted file mode 100644 index ec5ec57e..00000000 --- a/Makefile +++ /dev/null @@ -1,24 +0,0 @@ -.PHONY: test typecheck lint precommit docs - -test: - poetry run pytest -v --tb=auto --maxfail=20 --cov=uniswap --cov-report html --cov-report term --cov-report xml - -typecheck: - poetry run mypy --pretty - -lint: - poetry run ruff check uniswap - -format: - poetry run ruff format uniswap - -format-abis: - npx prettier --write --parser=json uniswap/assets/*/*.abi - -precommit: - make typecheck - make lint - make test - -docs: - cd docs/ && make html diff --git a/README.md b/README.md deleted file mode 100644 index 07fa4452..00000000 --- a/README.md +++ /dev/null @@ -1,205 +0,0 @@ -
-
-
-
-
-## Changelog
-
-_0.8.0_
-
-* Added: Uniswap V4 support
-* Added: Pool cache service for Uniswap V4
-* Full parameters customization for V4 transactions; V4 transaction replacement and cancelling.
-
-_0.7.2_
-
-* Updated: Default fee is not applied when using Uniswap V3. Default fee for Uniswap V1 and V2 is still 0.3%.
-* Updated: `InvalidFeeTier` exception is raised when a tier is not supported by the protocol version. See all supported tiers in [`uniswap.fee.FeeTier`](./uniswap/fee.py#L12)
-
-_0.7.1_
-
-* incomplete changelog
-
-_0.7.0_
-
-* incomplete changelog
-
-_0.5.4_
-
-* added use of gas estimation instead of a fixed gas limit (to support Arbitrum)
-* added `use_estimate_gas` constructor argument (used in testing)
-* added constants/basic support for Arbitrum, Optimism, Polygon, and Fantom. (untested)
-* incomplete changelog
-
-_0.5.3_
-
-* incomplete changelog
-
-_0.5.2_
-
-* incomplete changelog
-
-_0.5.1_
-
-* Updated dependencies
-* Fixed minor typing issues
-
-_0.5.0_
-
-* Basic support for Uniswap V3
-* Added new methods `get_price_input` and `get_price_output`
-* Made a lot of previously public methods private
-* Added documentation site
-* Removed ENS support (which was probably broken to begin with)
-
-_0.4.6_
-
-* Bug fix: Update bleach package from 3.1.4 to 3.3.0
-
-_0.4.5_
-* Bug fix: Use .eth instead of .ens
-
-_0.4.4_
-
-* General: Add new logo for Uniswap V2
-* Bug fix: Invalid balance check (#25)
-* Bug fix: Fixed error when passing WETH as token
-
-_0.4.3_
-
-* Allow kwargs in `approved` decorator.
-
-_0.4.2_
-
-* Add note about Uniswap V2 support
-
-_0.4.1_
-
-* Update changelog for PyPi and clean up
-
-_0.4.0_
-
-_A huge thank you [Erik Bjäreholt](https://github.com/ErikBjare) for adding Uniswap V2 support, as well as all changes in this version!_
-
-* Added support for Uniswap v2
-* Handle arbitrary tokens (by address) using the factory contract
-* Switched from setup.py to pyproject.toml/poetry
-* Switched from Travis to GitHub Actions
-* For CI to work in your repo, you need to set the secret MAINNET_PROVIDER. I use Infura.
-* Running tests on a local fork of mainnet using Anvil/Foundry (started as a fixture)
-* Fixed tests for make_trade and make_trade_output
-* Added type annotations to the entire codebase and check them with mypy in CI
-* Formatted entire codebase with black
-* Moved stuff around such that the basic import becomes from uniswap import Uniswap (instead of from uniswap.uniswap import UniswapWrapper)
-* Fixed misc bugs
-
-_0.3.3_
-* Provide token inputs as addresses instead of names
-
-_0.3.2_
-* Add ability to transfer tokens after a trade
-* Add tests for this new functionality
-
-_0.3.1_
-* Add tests for all types of trades
-
-_0.3.0_
-* Add ability to make all types of trades
-* Add example to README
-
-_0.2.1_
-* Add liquidity tests
-
-_0.2.0_
-* Add liquidity and ERC20 pool methods
-
-_0.1.1_
-* Major README update
-
-_0.1.0_
-* Add market endpoints
-* Add tests for market endpoints
diff --git a/docs/_static/logo.png b/_images/logo.png
similarity index 100%
rename from docs/_static/logo.png
rename to _images/logo.png
diff --git a/docs/api.rst b/_sources/api.rst
similarity index 100%
rename from docs/api.rst
rename to _sources/api.rst
diff --git a/docs/cli.rst b/_sources/cli.rst
similarity index 100%
rename from docs/cli.rst
rename to _sources/cli.rst
diff --git a/docs/examples.rst b/_sources/examples.rst
similarity index 100%
rename from docs/examples.rst
rename to _sources/examples.rst
diff --git a/docs/getting-started.rst b/_sources/getting-started.rst
similarity index 100%
rename from docs/getting-started.rst
rename to _sources/getting-started.rst
diff --git a/docs/index.rst b/_sources/index.rst
similarity index 100%
rename from docs/index.rst
rename to _sources/index.rst
diff --git a/docs/supported-deployments.rst b/_sources/supported-deployments.rst
similarity index 100%
rename from docs/supported-deployments.rst
rename to _sources/supported-deployments.rst
diff --git a/docs/v4.rst b/_sources/v4.rst
similarity index 100%
rename from docs/v4.rst
rename to _sources/v4.rst
diff --git a/_static/base-stemmer.js b/_static/base-stemmer.js
new file mode 100644
index 00000000..e6fa0c49
--- /dev/null
+++ b/_static/base-stemmer.js
@@ -0,0 +1,476 @@
+// @ts-check
+
+/**@constructor*/
+BaseStemmer = function() {
+ /** @protected */
+ this.current = '';
+ this.cursor = 0;
+ this.limit = 0;
+ this.limit_backward = 0;
+ this.bra = 0;
+ this.ket = 0;
+
+ /**
+ * @param {string} value
+ */
+ this.setCurrent = function(value) {
+ this.current = value;
+ this.cursor = 0;
+ this.limit = this.current.length;
+ this.limit_backward = 0;
+ this.bra = this.cursor;
+ this.ket = this.limit;
+ };
+
+ /**
+ * @return {string}
+ */
+ this.getCurrent = function() {
+ return this.current;
+ };
+
+ /**
+ * @param {BaseStemmer} other
+ */
+ this.copy_from = function(other) {
+ /** @protected */
+ this.current = other.current;
+ this.cursor = other.cursor;
+ this.limit = other.limit;
+ this.limit_backward = other.limit_backward;
+ this.bra = other.bra;
+ this.ket = other.ket;
+ };
+
+ /**
+ * @param {number[]} s
+ * @param {number} min
+ * @param {number} max
+ * @return {boolean}
+ */
+ this.in_grouping = function(s, min, max) {
+ /** @protected */
+ if (this.cursor >= this.limit) return false;
+ var ch = this.current.charCodeAt(this.cursor);
+ if (ch > max || ch < min) return false;
+ ch -= min;
+ if ((s[ch >>> 3] & (0x1 << (ch & 0x7))) == 0) return false;
+ this.cursor++;
+ return true;
+ };
+
+ /**
+ * @param {number[]} s
+ * @param {number} min
+ * @param {number} max
+ * @return {boolean}
+ */
+ this.go_in_grouping = function(s, min, max) {
+ /** @protected */
+ while (this.cursor < this.limit) {
+ var ch = this.current.charCodeAt(this.cursor);
+ if (ch > max || ch < min)
+ return true;
+ ch -= min;
+ if ((s[ch >>> 3] & (0x1 << (ch & 0x7))) == 0)
+ return true;
+ this.cursor++;
+ }
+ return false;
+ };
+
+ /**
+ * @param {number[]} s
+ * @param {number} min
+ * @param {number} max
+ * @return {boolean}
+ */
+ this.in_grouping_b = function(s, min, max) {
+ /** @protected */
+ if (this.cursor <= this.limit_backward) return false;
+ var ch = this.current.charCodeAt(this.cursor - 1);
+ if (ch > max || ch < min) return false;
+ ch -= min;
+ if ((s[ch >>> 3] & (0x1 << (ch & 0x7))) == 0) return false;
+ this.cursor--;
+ return true;
+ };
+
+ /**
+ * @param {number[]} s
+ * @param {number} min
+ * @param {number} max
+ * @return {boolean}
+ */
+ this.go_in_grouping_b = function(s, min, max) {
+ /** @protected */
+ while (this.cursor > this.limit_backward) {
+ var ch = this.current.charCodeAt(this.cursor - 1);
+ if (ch > max || ch < min) return true;
+ ch -= min;
+ if ((s[ch >>> 3] & (0x1 << (ch & 0x7))) == 0) return true;
+ this.cursor--;
+ }
+ return false;
+ };
+
+ /**
+ * @param {number[]} s
+ * @param {number} min
+ * @param {number} max
+ * @return {boolean}
+ */
+ this.out_grouping = function(s, min, max) {
+ /** @protected */
+ if (this.cursor >= this.limit) return false;
+ var ch = this.current.charCodeAt(this.cursor);
+ if (ch > max || ch < min) {
+ this.cursor++;
+ return true;
+ }
+ ch -= min;
+ if ((s[ch >>> 3] & (0X1 << (ch & 0x7))) == 0) {
+ this.cursor++;
+ return true;
+ }
+ return false;
+ };
+
+ /**
+ * @param {number[]} s
+ * @param {number} min
+ * @param {number} max
+ * @return {boolean}
+ */
+ this.go_out_grouping = function(s, min, max) {
+ /** @protected */
+ while (this.cursor < this.limit) {
+ var ch = this.current.charCodeAt(this.cursor);
+ if (ch <= max && ch >= min) {
+ ch -= min;
+ if ((s[ch >>> 3] & (0X1 << (ch & 0x7))) != 0) {
+ return true;
+ }
+ }
+ this.cursor++;
+ }
+ return false;
+ };
+
+ /**
+ * @param {number[]} s
+ * @param {number} min
+ * @param {number} max
+ * @return {boolean}
+ */
+ this.out_grouping_b = function(s, min, max) {
+ /** @protected */
+ if (this.cursor <= this.limit_backward) return false;
+ var ch = this.current.charCodeAt(this.cursor - 1);
+ if (ch > max || ch < min) {
+ this.cursor--;
+ return true;
+ }
+ ch -= min;
+ if ((s[ch >>> 3] & (0x1 << (ch & 0x7))) == 0) {
+ this.cursor--;
+ return true;
+ }
+ return false;
+ };
+
+ /**
+ * @param {number[]} s
+ * @param {number} min
+ * @param {number} max
+ * @return {boolean}
+ */
+ this.go_out_grouping_b = function(s, min, max) {
+ /** @protected */
+ while (this.cursor > this.limit_backward) {
+ var ch = this.current.charCodeAt(this.cursor - 1);
+ if (ch <= max && ch >= min) {
+ ch -= min;
+ if ((s[ch >>> 3] & (0x1 << (ch & 0x7))) != 0) {
+ return true;
+ }
+ }
+ this.cursor--;
+ }
+ return false;
+ };
+
+ /**
+ * @param {string} s
+ * @return {boolean}
+ */
+ this.eq_s = function(s)
+ {
+ /** @protected */
+ if (this.limit - this.cursor < s.length) return false;
+ if (this.current.slice(this.cursor, this.cursor + s.length) != s)
+ {
+ return false;
+ }
+ this.cursor += s.length;
+ return true;
+ };
+
+ /**
+ * @param {string} s
+ * @return {boolean}
+ */
+ this.eq_s_b = function(s)
+ {
+ /** @protected */
+ if (this.cursor - this.limit_backward < s.length) return false;
+ if (this.current.slice(this.cursor - s.length, this.cursor) != s)
+ {
+ return false;
+ }
+ this.cursor -= s.length;
+ return true;
+ };
+
+ /**
+ * @param {Among[]} v
+ * @return {number}
+ */
+ this.find_among = function(v)
+ {
+ /** @protected */
+ var i = 0;
+ var j = v.length;
+
+ var c = this.cursor;
+ var l = this.limit;
+
+ var common_i = 0;
+ var common_j = 0;
+
+ var first_key_inspected = false;
+
+ while (true)
+ {
+ var k = i + ((j - i) >>> 1);
+ var diff = 0;
+ var common = common_i < common_j ? common_i : common_j; // smaller
+ // w[0]: string, w[1]: substring_i, w[2]: result, w[3]: function (optional)
+ var w = v[k];
+ var i2;
+ for (i2 = common; i2 < w[0].length; i2++)
+ {
+ if (c + common == l)
+ {
+ diff = -1;
+ break;
+ }
+ diff = this.current.charCodeAt(c + common) - w[0].charCodeAt(i2);
+ if (diff != 0) break;
+ common++;
+ }
+ if (diff < 0)
+ {
+ j = k;
+ common_j = common;
+ }
+ else
+ {
+ i = k;
+ common_i = common;
+ }
+ if (j - i <= 1)
+ {
+ if (i > 0) break; // v->s has been inspected
+ if (j == i) break; // only one item in v
+
+ // - but now we need to go round once more to get
+ // v->s inspected. This looks messy, but is actually
+ // the optimal approach.
+
+ if (first_key_inspected) break;
+ first_key_inspected = true;
+ }
+ }
+ do {
+ var w = v[i];
+ if (common_i >= w[0].length)
+ {
+ this.cursor = c + w[0].length;
+ if (w.length < 4) return w[2];
+ var res = w[3](this);
+ this.cursor = c + w[0].length;
+ if (res) return w[2];
+ }
+ i = w[1];
+ } while (i >= 0);
+ return 0;
+ };
+
+ // find_among_b is for backwards processing. Same comments apply
+ /**
+ * @param {Among[]} v
+ * @return {number}
+ */
+ this.find_among_b = function(v)
+ {
+ /** @protected */
+ var i = 0;
+ var j = v.length
+
+ var c = this.cursor;
+ var lb = this.limit_backward;
+
+ var common_i = 0;
+ var common_j = 0;
+
+ var first_key_inspected = false;
+
+ while (true)
+ {
+ var k = i + ((j - i) >> 1);
+ var diff = 0;
+ var common = common_i < common_j ? common_i : common_j;
+ var w = v[k];
+ var i2;
+ for (i2 = w[0].length - 1 - common; i2 >= 0; i2--)
+ {
+ if (c - common == lb)
+ {
+ diff = -1;
+ break;
+ }
+ diff = this.current.charCodeAt(c - 1 - common) - w[0].charCodeAt(i2);
+ if (diff != 0) break;
+ common++;
+ }
+ if (diff < 0)
+ {
+ j = k;
+ common_j = common;
+ }
+ else
+ {
+ i = k;
+ common_i = common;
+ }
+ if (j - i <= 1)
+ {
+ if (i > 0) break;
+ if (j == i) break;
+ if (first_key_inspected) break;
+ first_key_inspected = true;
+ }
+ }
+ do {
+ var w = v[i];
+ if (common_i >= w[0].length)
+ {
+ this.cursor = c - w[0].length;
+ if (w.length < 4) return w[2];
+ var res = w[3](this);
+ this.cursor = c - w[0].length;
+ if (res) return w[2];
+ }
+ i = w[1];
+ } while (i >= 0);
+ return 0;
+ };
+
+ /* to replace chars between c_bra and c_ket in this.current by the
+ * chars in s.
+ */
+ /**
+ * @param {number} c_bra
+ * @param {number} c_ket
+ * @param {string} s
+ * @return {number}
+ */
+ this.replace_s = function(c_bra, c_ket, s)
+ {
+ /** @protected */
+ var adjustment = s.length - (c_ket - c_bra);
+ this.current = this.current.slice(0, c_bra) + s + this.current.slice(c_ket);
+ this.limit += adjustment;
+ if (this.cursor >= c_ket) this.cursor += adjustment;
+ else if (this.cursor > c_bra) this.cursor = c_bra;
+ return adjustment;
+ };
+
+ /**
+ * @return {boolean}
+ */
+ this.slice_check = function()
+ {
+ /** @protected */
+ if (this.bra < 0 ||
+ this.bra > this.ket ||
+ this.ket > this.limit ||
+ this.limit > this.current.length)
+ {
+ return false;
+ }
+ return true;
+ };
+
+ /**
+ * @param {number} c_bra
+ * @return {boolean}
+ */
+ this.slice_from = function(s)
+ {
+ /** @protected */
+ var result = false;
+ if (this.slice_check())
+ {
+ this.replace_s(this.bra, this.ket, s);
+ result = true;
+ }
+ return result;
+ };
+
+ /**
+ * @return {boolean}
+ */
+ this.slice_del = function()
+ {
+ /** @protected */
+ return this.slice_from("");
+ };
+
+ /**
+ * @param {number} c_bra
+ * @param {number} c_ket
+ * @param {string} s
+ */
+ this.insert = function(c_bra, c_ket, s)
+ {
+ /** @protected */
+ var adjustment = this.replace_s(c_bra, c_ket, s);
+ if (c_bra <= this.bra) this.bra += adjustment;
+ if (c_bra <= this.ket) this.ket += adjustment;
+ };
+
+ /**
+ * @return {string}
+ */
+ this.slice_to = function()
+ {
+ /** @protected */
+ var result = '';
+ if (this.slice_check())
+ {
+ result = this.current.slice(this.bra, this.ket);
+ }
+ return result;
+ };
+
+ /**
+ * @return {string}
+ */
+ this.assign_to = function()
+ {
+ /** @protected */
+ return this.current.slice(0, this.limit);
+ };
+};
diff --git a/_static/basic.css b/_static/basic.css
new file mode 100644
index 00000000..4738b2ed
--- /dev/null
+++ b/_static/basic.css
@@ -0,0 +1,906 @@
+/*
+ * Sphinx stylesheet -- basic theme.
+ */
+
+/* -- main layout ----------------------------------------------------------- */
+
+div.clearer {
+ clear: both;
+}
+
+div.section::after {
+ display: block;
+ content: '';
+ clear: left;
+}
+
+/* -- relbar ---------------------------------------------------------------- */
+
+div.related {
+ width: 100%;
+ font-size: 90%;
+}
+
+div.related h3 {
+ display: none;
+}
+
+div.related ul {
+ margin: 0;
+ padding: 0 0 0 10px;
+ list-style: none;
+}
+
+div.related li {
+ display: inline;
+}
+
+div.related li.right {
+ float: right;
+ margin-right: 5px;
+}
+
+/* -- sidebar --------------------------------------------------------------- */
+
+div.sphinxsidebarwrapper {
+ padding: 10px 5px 0 10px;
+}
+
+div.sphinxsidebar {
+ float: left;
+ width: 230px;
+ margin-left: -100%;
+ font-size: 90%;
+ word-wrap: break-word;
+ overflow-wrap : break-word;
+}
+
+div.sphinxsidebar ul {
+ list-style: none;
+}
+
+div.sphinxsidebar ul ul,
+div.sphinxsidebar ul.want-points {
+ margin-left: 20px;
+ list-style: square;
+}
+
+div.sphinxsidebar ul ul {
+ margin-top: 0;
+ margin-bottom: 0;
+}
+
+div.sphinxsidebar form {
+ margin-top: 10px;
+}
+
+div.sphinxsidebar input {
+ border: 1px solid #98dbcc;
+ font-family: sans-serif;
+ font-size: 1em;
+}
+
+div.sphinxsidebar #searchbox form.search {
+ overflow: hidden;
+}
+
+div.sphinxsidebar #searchbox input[type="text"] {
+ float: left;
+ width: 80%;
+ padding: 0.25em;
+ box-sizing: border-box;
+}
+
+div.sphinxsidebar #searchbox input[type="submit"] {
+ float: left;
+ width: 20%;
+ border-left: none;
+ padding: 0.25em;
+ box-sizing: border-box;
+}
+
+
+img {
+ border: 0;
+ max-width: 100%;
+}
+
+/* -- search page ----------------------------------------------------------- */
+
+ul.search {
+ margin-top: 10px;
+}
+
+ul.search li {
+ padding: 5px 0;
+}
+
+ul.search li a {
+ font-weight: bold;
+}
+
+ul.search li p.context {
+ color: #888;
+ margin: 2px 0 0 30px;
+ text-align: left;
+}
+
+ul.keywordmatches li.goodmatch a {
+ font-weight: bold;
+}
+
+/* -- index page ------------------------------------------------------------ */
+
+table.contentstable {
+ width: 90%;
+ margin-left: auto;
+ margin-right: auto;
+}
+
+table.contentstable p.biglink {
+ line-height: 150%;
+}
+
+a.biglink {
+ font-size: 1.3em;
+}
+
+span.linkdescr {
+ font-style: italic;
+ padding-top: 5px;
+ font-size: 90%;
+}
+
+/* -- general index --------------------------------------------------------- */
+
+table.indextable {
+ width: 100%;
+}
+
+table.indextable td {
+ text-align: left;
+ vertical-align: top;
+}
+
+table.indextable ul {
+ margin-top: 0;
+ margin-bottom: 0;
+ list-style-type: none;
+}
+
+table.indextable > tbody > tr > td > ul {
+ padding-left: 0em;
+}
+
+table.indextable tr.pcap {
+ height: 10px;
+}
+
+table.indextable tr.cap {
+ margin-top: 10px;
+ background-color: #f2f2f2;
+}
+
+img.toggler {
+ margin-right: 3px;
+ margin-top: 3px;
+ cursor: pointer;
+}
+
+div.modindex-jumpbox {
+ border-top: 1px solid #ddd;
+ border-bottom: 1px solid #ddd;
+ margin: 1em 0 1em 0;
+ padding: 0.4em;
+}
+
+div.genindex-jumpbox {
+ border-top: 1px solid #ddd;
+ border-bottom: 1px solid #ddd;
+ margin: 1em 0 1em 0;
+ padding: 0.4em;
+}
+
+/* -- domain module index --------------------------------------------------- */
+
+table.modindextable td {
+ padding: 2px;
+ border-collapse: collapse;
+}
+
+/* -- general body styles --------------------------------------------------- */
+
+div.body {
+ min-width: 360px;
+ max-width: 800px;
+}
+
+div.body p, div.body dd, div.body li, div.body blockquote {
+ -moz-hyphens: auto;
+ -ms-hyphens: auto;
+ -webkit-hyphens: auto;
+ hyphens: auto;
+}
+
+a.headerlink {
+ visibility: hidden;
+}
+
+a:visited {
+ color: #551A8B;
+}
+
+h1:hover > a.headerlink,
+h2:hover > a.headerlink,
+h3:hover > a.headerlink,
+h4:hover > a.headerlink,
+h5:hover > a.headerlink,
+h6:hover > a.headerlink,
+dt:hover > a.headerlink,
+caption:hover > a.headerlink,
+p.caption:hover > a.headerlink,
+div.code-block-caption:hover > a.headerlink {
+ visibility: visible;
+}
+
+div.body p.caption {
+ text-align: inherit;
+}
+
+div.body td {
+ text-align: left;
+}
+
+.first {
+ margin-top: 0 !important;
+}
+
+p.rubric {
+ margin-top: 30px;
+ font-weight: bold;
+}
+
+img.align-left, figure.align-left, .figure.align-left, object.align-left {
+ clear: left;
+ float: left;
+ margin-right: 1em;
+}
+
+img.align-right, figure.align-right, .figure.align-right, object.align-right {
+ clear: right;
+ float: right;
+ margin-left: 1em;
+}
+
+img.align-center, figure.align-center, .figure.align-center, object.align-center {
+ display: block;
+ margin-left: auto;
+ margin-right: auto;
+}
+
+img.align-default, figure.align-default, .figure.align-default {
+ display: block;
+ margin-left: auto;
+ margin-right: auto;
+}
+
+.align-left {
+ text-align: left;
+}
+
+.align-center {
+ text-align: center;
+}
+
+.align-default {
+ text-align: center;
+}
+
+.align-right {
+ text-align: right;
+}
+
+/* -- sidebars -------------------------------------------------------------- */
+
+div.sidebar,
+aside.sidebar {
+ margin: 0 0 0.5em 1em;
+ border: 1px solid #ddb;
+ padding: 7px;
+ background-color: #ffe;
+ width: 40%;
+ float: right;
+ clear: right;
+ overflow-x: auto;
+}
+
+p.sidebar-title {
+ font-weight: bold;
+}
+
+nav.contents,
+aside.topic,
+div.admonition, div.topic, blockquote {
+ clear: left;
+}
+
+/* -- topics ---------------------------------------------------------------- */
+
+nav.contents,
+aside.topic,
+div.topic {
+ border: 1px solid #ccc;
+ padding: 7px;
+ margin: 10px 0 10px 0;
+}
+
+p.topic-title {
+ font-size: 1.1em;
+ font-weight: bold;
+ margin-top: 10px;
+}
+
+/* -- admonitions ----------------------------------------------------------- */
+
+div.admonition {
+ margin-top: 10px;
+ margin-bottom: 10px;
+ padding: 7px;
+}
+
+div.admonition dt {
+ font-weight: bold;
+}
+
+p.admonition-title {
+ margin: 0px 10px 5px 0px;
+ font-weight: bold;
+}
+
+div.body p.centered {
+ text-align: center;
+ margin-top: 25px;
+}
+
+/* -- content of sidebars/topics/admonitions -------------------------------- */
+
+div.sidebar > :last-child,
+aside.sidebar > :last-child,
+nav.contents > :last-child,
+aside.topic > :last-child,
+div.topic > :last-child,
+div.admonition > :last-child {
+ margin-bottom: 0;
+}
+
+div.sidebar::after,
+aside.sidebar::after,
+nav.contents::after,
+aside.topic::after,
+div.topic::after,
+div.admonition::after,
+blockquote::after {
+ display: block;
+ content: '';
+ clear: both;
+}
+
+/* -- tables ---------------------------------------------------------------- */
+
+table.docutils {
+ margin-top: 10px;
+ margin-bottom: 10px;
+ border: 0;
+ border-collapse: collapse;
+}
+
+table.align-center {
+ margin-left: auto;
+ margin-right: auto;
+}
+
+table.align-default {
+ margin-left: auto;
+ margin-right: auto;
+}
+
+table caption span.caption-number {
+ font-style: italic;
+}
+
+table caption span.caption-text {
+}
+
+table.docutils td, table.docutils th {
+ padding: 1px 8px 1px 5px;
+ border-top: 0;
+ border-left: 0;
+ border-right: 0;
+ border-bottom: 1px solid #aaa;
+}
+
+th {
+ text-align: left;
+ padding-right: 5px;
+}
+
+table.citation {
+ border-left: solid 1px gray;
+ margin-left: 1px;
+}
+
+table.citation td {
+ border-bottom: none;
+}
+
+th > :first-child,
+td > :first-child {
+ margin-top: 0px;
+}
+
+th > :last-child,
+td > :last-child {
+ margin-bottom: 0px;
+}
+
+/* -- figures --------------------------------------------------------------- */
+
+div.figure, figure {
+ margin: 0.5em;
+ padding: 0.5em;
+}
+
+div.figure p.caption, figcaption {
+ padding: 0.3em;
+}
+
+div.figure p.caption span.caption-number,
+figcaption span.caption-number {
+ font-style: italic;
+}
+
+div.figure p.caption span.caption-text,
+figcaption span.caption-text {
+}
+
+/* -- field list styles ----------------------------------------------------- */
+
+table.field-list td, table.field-list th {
+ border: 0 !important;
+}
+
+.field-list ul {
+ margin: 0;
+ padding-left: 1em;
+}
+
+.field-list p {
+ margin: 0;
+}
+
+.field-name {
+ -moz-hyphens: manual;
+ -ms-hyphens: manual;
+ -webkit-hyphens: manual;
+ hyphens: manual;
+}
+
+/* -- hlist styles ---------------------------------------------------------- */
+
+table.hlist {
+ margin: 1em 0;
+}
+
+table.hlist td {
+ vertical-align: top;
+}
+
+/* -- object description styles --------------------------------------------- */
+
+.sig {
+ font-family: 'Consolas', 'Menlo', 'DejaVu Sans Mono', 'Bitstream Vera Sans Mono', monospace;
+}
+
+.sig-name, code.descname {
+ background-color: transparent;
+ font-weight: bold;
+}
+
+.sig-name {
+ font-size: 1.1em;
+}
+
+code.descname {
+ font-size: 1.2em;
+}
+
+.sig-prename, code.descclassname {
+ background-color: transparent;
+}
+
+.optional {
+ font-size: 1.3em;
+}
+
+.sig-paren {
+ font-size: larger;
+}
+
+.sig-param.n {
+ font-style: italic;
+}
+
+/* C++ specific styling */
+
+.sig-inline.c-texpr,
+.sig-inline.cpp-texpr {
+ font-family: unset;
+}
+
+.sig.c .k, .sig.c .kt,
+.sig.cpp .k, .sig.cpp .kt {
+ color: #0033B3;
+}
+
+.sig.c .m,
+.sig.cpp .m {
+ color: #1750EB;
+}
+
+.sig.c .s, .sig.c .sc,
+.sig.cpp .s, .sig.cpp .sc {
+ color: #067D17;
+}
+
+
+/* -- other body styles ----------------------------------------------------- */
+
+ol.arabic {
+ list-style: decimal;
+}
+
+ol.loweralpha {
+ list-style: lower-alpha;
+}
+
+ol.upperalpha {
+ list-style: upper-alpha;
+}
+
+ol.lowerroman {
+ list-style: lower-roman;
+}
+
+ol.upperroman {
+ list-style: upper-roman;
+}
+
+:not(li) > ol > li:first-child > :first-child,
+:not(li) > ul > li:first-child > :first-child {
+ margin-top: 0px;
+}
+
+:not(li) > ol > li:last-child > :last-child,
+:not(li) > ul > li:last-child > :last-child {
+ margin-bottom: 0px;
+}
+
+ol.simple ol p,
+ol.simple ul p,
+ul.simple ol p,
+ul.simple ul p {
+ margin-top: 0;
+}
+
+ol.simple > li:not(:first-child) > p,
+ul.simple > li:not(:first-child) > p {
+ margin-top: 0;
+}
+
+ol.simple p,
+ul.simple p {
+ margin-bottom: 0;
+}
+
+aside.footnote > span,
+div.citation > span {
+ float: left;
+}
+aside.footnote > span:last-of-type,
+div.citation > span:last-of-type {
+ padding-right: 0.5em;
+}
+aside.footnote > p {
+ margin-left: 2em;
+}
+div.citation > p {
+ margin-left: 4em;
+}
+aside.footnote > p:last-of-type,
+div.citation > p:last-of-type {
+ margin-bottom: 0em;
+}
+aside.footnote > p:last-of-type:after,
+div.citation > p:last-of-type:after {
+ content: "";
+ clear: both;
+}
+
+dl.field-list {
+ display: grid;
+ grid-template-columns: fit-content(30%) auto;
+}
+
+dl.field-list > dt {
+ font-weight: bold;
+ word-break: break-word;
+ padding-left: 0.5em;
+ padding-right: 5px;
+}
+
+dl.field-list > dd {
+ padding-left: 0.5em;
+ margin-top: 0em;
+ margin-left: 0em;
+ margin-bottom: 0em;
+}
+
+dl {
+ margin-bottom: 15px;
+}
+
+dd > :first-child {
+ margin-top: 0px;
+}
+
+dd ul, dd table {
+ margin-bottom: 10px;
+}
+
+dd {
+ margin-top: 3px;
+ margin-bottom: 10px;
+ margin-left: 30px;
+}
+
+.sig dd {
+ margin-top: 0px;
+ margin-bottom: 0px;
+}
+
+.sig dl {
+ margin-top: 0px;
+ margin-bottom: 0px;
+}
+
+dl > dd:last-child,
+dl > dd:last-child > :last-child {
+ margin-bottom: 0;
+}
+
+dt:target, span.highlighted {
+ background-color: #fbe54e;
+}
+
+rect.highlighted {
+ fill: #fbe54e;
+}
+
+dl.glossary dt {
+ font-weight: bold;
+ font-size: 1.1em;
+}
+
+.versionmodified {
+ font-style: italic;
+}
+
+.system-message {
+ background-color: #fda;
+ padding: 5px;
+ border: 3px solid red;
+}
+
+.footnote:target {
+ background-color: #ffa;
+}
+
+.line-block {
+ display: block;
+ margin-top: 1em;
+ margin-bottom: 1em;
+}
+
+.line-block .line-block {
+ margin-top: 0;
+ margin-bottom: 0;
+ margin-left: 1.5em;
+}
+
+.guilabel, .menuselection {
+ font-family: sans-serif;
+}
+
+.accelerator {
+ text-decoration: underline;
+}
+
+.classifier {
+ font-style: oblique;
+}
+
+.classifier:before {
+ font-style: normal;
+ margin: 0 0.5em;
+ content: ":";
+ display: inline-block;
+}
+
+abbr, acronym {
+ border-bottom: dotted 1px;
+ cursor: help;
+}
+
+/* -- code displays --------------------------------------------------------- */
+
+pre {
+ overflow: auto;
+ overflow-y: hidden; /* fixes display issues on Chrome browsers */
+}
+
+pre, div[class*="highlight-"] {
+ clear: both;
+}
+
+span.pre {
+ -moz-hyphens: none;
+ -ms-hyphens: none;
+ -webkit-hyphens: none;
+ hyphens: none;
+ white-space: nowrap;
+}
+
+div[class*="highlight-"] {
+ margin: 1em 0;
+}
+
+td.linenos pre {
+ border: 0;
+ background-color: transparent;
+ color: #aaa;
+}
+
+table.highlighttable {
+ display: block;
+}
+
+table.highlighttable tbody {
+ display: block;
+}
+
+table.highlighttable tr {
+ display: flex;
+}
+
+table.highlighttable td {
+ margin: 0;
+ padding: 0;
+}
+
+table.highlighttable td.linenos {
+ padding-right: 0.5em;
+}
+
+table.highlighttable td.code {
+ flex: 1;
+ overflow: hidden;
+}
+
+.highlight .hll {
+ display: block;
+}
+
+div.highlight pre,
+table.highlighttable pre {
+ margin: 0;
+}
+
+div.code-block-caption + div {
+ margin-top: 0;
+}
+
+div.code-block-caption {
+ margin-top: 1em;
+ padding: 2px 5px;
+ font-size: small;
+}
+
+div.code-block-caption code {
+ background-color: transparent;
+}
+
+table.highlighttable td.linenos,
+span.linenos,
+div.highlight span.gp { /* gp: Generic.Prompt */
+ user-select: none;
+ -webkit-user-select: text; /* Safari fallback only */
+ -webkit-user-select: none; /* Chrome/Safari */
+ -moz-user-select: none; /* Firefox */
+ -ms-user-select: none; /* IE10+ */
+}
+
+div.code-block-caption span.caption-number {
+ padding: 0.1em 0.3em;
+ font-style: italic;
+}
+
+div.code-block-caption span.caption-text {
+}
+
+div.literal-block-wrapper {
+ margin: 1em 0;
+}
+
+code.xref, a code {
+ background-color: transparent;
+ font-weight: bold;
+}
+
+h1 code, h2 code, h3 code, h4 code, h5 code, h6 code {
+ background-color: transparent;
+}
+
+.viewcode-link {
+ float: right;
+}
+
+.viewcode-back {
+ float: right;
+ font-family: sans-serif;
+}
+
+div.viewcode-block:target {
+ margin: -1px -10px;
+ padding: 0 10px;
+}
+
+/* -- math display ---------------------------------------------------------- */
+
+img.math {
+ vertical-align: middle;
+}
+
+div.body div.math p {
+ text-align: center;
+}
+
+span.eqno {
+ float: right;
+}
+
+span.eqno a.headerlink {
+ position: absolute;
+ z-index: 1;
+}
+
+div.math:hover a.headerlink {
+ visibility: visible;
+}
+
+/* -- printout stylesheet --------------------------------------------------- */
+
+@media print {
+ div.document,
+ div.documentwrapper,
+ div.bodywrapper {
+ margin: 0 !important;
+ width: 100%;
+ }
+
+ div.sphinxsidebar,
+ div.related,
+ div.footer,
+ #top-link {
+ display: none;
+ }
+}
\ No newline at end of file
diff --git a/_static/doctools.js b/_static/doctools.js
new file mode 100644
index 00000000..807cdb17
--- /dev/null
+++ b/_static/doctools.js
@@ -0,0 +1,150 @@
+/*
+ * Base JavaScript utilities for all Sphinx HTML documentation.
+ */
+"use strict";
+
+const BLACKLISTED_KEY_CONTROL_ELEMENTS = new Set([
+ "TEXTAREA",
+ "INPUT",
+ "SELECT",
+ "BUTTON",
+]);
+
+const _ready = (callback) => {
+ if (document.readyState !== "loading") {
+ callback();
+ } else {
+ document.addEventListener("DOMContentLoaded", callback);
+ }
+};
+
+/**
+ * Small JavaScript module for the documentation.
+ */
+const Documentation = {
+ init: () => {
+ Documentation.initDomainIndexTable();
+ Documentation.initOnKeyListeners();
+ },
+
+ /**
+ * i18n support
+ */
+ TRANSLATIONS: {},
+ PLURAL_EXPR: (n) => (n === 1 ? 0 : 1),
+ LOCALE: "unknown",
+
+ // gettext and ngettext don't access this so that the functions
+ // can safely bound to a different name (_ = Documentation.gettext)
+ gettext: (string) => {
+ const translated = Documentation.TRANSLATIONS[string];
+ switch (typeof translated) {
+ case "undefined":
+ return string; // no translation
+ case "string":
+ return translated; // translation exists
+ default:
+ return translated[0]; // (singular, plural) translation tuple exists
+ }
+ },
+
+ ngettext: (singular, plural, n) => {
+ const translated = Documentation.TRANSLATIONS[singular];
+ if (typeof translated !== "undefined")
+ return translated[Documentation.PLURAL_EXPR(n)];
+ return n === 1 ? singular : plural;
+ },
+
+ addTranslations: (catalog) => {
+ Object.assign(Documentation.TRANSLATIONS, catalog.messages);
+ Documentation.PLURAL_EXPR = new Function(
+ "n",
+ `return (${catalog.plural_expr})`,
+ );
+ Documentation.LOCALE = catalog.locale;
+ },
+
+ /**
+ * helper function to focus on search bar
+ */
+ focusSearchBar: () => {
+ document.querySelectorAll("input[name=q]")[0]?.focus();
+ },
+
+ /**
+ * Initialise the domain index toggle buttons
+ */
+ initDomainIndexTable: () => {
+ const toggler = (el) => {
+ const idNumber = el.id.substr(7);
+ const toggledRows = document.querySelectorAll(`tr.cg-${idNumber}`);
+ if (el.src.substr(-9) === "minus.png") {
+ el.src = `${el.src.substr(0, el.src.length - 9)}plus.png`;
+ toggledRows.forEach((el) => (el.style.display = "none"));
+ } else {
+ el.src = `${el.src.substr(0, el.src.length - 8)}minus.png`;
+ toggledRows.forEach((el) => (el.style.display = ""));
+ }
+ };
+
+ const togglerElements = document.querySelectorAll("img.toggler");
+ togglerElements.forEach((el) =>
+ el.addEventListener("click", (event) => toggler(event.currentTarget)),
+ );
+ togglerElements.forEach((el) => (el.style.display = ""));
+ if (DOCUMENTATION_OPTIONS.COLLAPSE_INDEX) togglerElements.forEach(toggler);
+ },
+
+ initOnKeyListeners: () => {
+ // only install a listener if it is really needed
+ if (
+ !DOCUMENTATION_OPTIONS.NAVIGATION_WITH_KEYS
+ && !DOCUMENTATION_OPTIONS.ENABLE_SEARCH_SHORTCUTS
+ )
+ return;
+
+ document.addEventListener("keydown", (event) => {
+ // bail for input elements
+ if (BLACKLISTED_KEY_CONTROL_ELEMENTS.has(document.activeElement.tagName))
+ return;
+ // bail with special keys
+ if (event.altKey || event.ctrlKey || event.metaKey) return;
+
+ if (!event.shiftKey) {
+ switch (event.key) {
+ case "ArrowLeft":
+ if (!DOCUMENTATION_OPTIONS.NAVIGATION_WITH_KEYS) break;
+
+ const prevLink = document.querySelector('link[rel="prev"]');
+ if (prevLink && prevLink.href) {
+ window.location.href = prevLink.href;
+ event.preventDefault();
+ }
+ break;
+ case "ArrowRight":
+ if (!DOCUMENTATION_OPTIONS.NAVIGATION_WITH_KEYS) break;
+
+ const nextLink = document.querySelector('link[rel="next"]');
+ if (nextLink && nextLink.href) {
+ window.location.href = nextLink.href;
+ event.preventDefault();
+ }
+ break;
+ }
+ }
+
+ // some keyboard layouts may need Shift to get /
+ switch (event.key) {
+ case "/":
+ if (!DOCUMENTATION_OPTIONS.ENABLE_SEARCH_SHORTCUTS) break;
+ Documentation.focusSearchBar();
+ event.preventDefault();
+ }
+ });
+ },
+};
+
+// quick alias for translations
+const _ = Documentation.gettext;
+
+_ready(Documentation.init);
diff --git a/_static/documentation_options.js b/_static/documentation_options.js
new file mode 100644
index 00000000..dab586c0
--- /dev/null
+++ b/_static/documentation_options.js
@@ -0,0 +1,13 @@
+const DOCUMENTATION_OPTIONS = {
+ VERSION: '',
+ LANGUAGE: 'en',
+ COLLAPSE_INDEX: false,
+ BUILDER: 'html',
+ FILE_SUFFIX: '.html',
+ LINK_SUFFIX: '.html',
+ HAS_SOURCE: true,
+ SOURCELINK_SUFFIX: '',
+ NAVIGATION_WITH_KEYS: false,
+ SHOW_SEARCH_SUMMARY: true,
+ ENABLE_SEARCH_SHORTCUTS: true,
+};
\ No newline at end of file
diff --git a/_static/english-stemmer.js b/_static/english-stemmer.js
new file mode 100644
index 00000000..056760ee
--- /dev/null
+++ b/_static/english-stemmer.js
@@ -0,0 +1,1066 @@
+// Generated from english.sbl by Snowball 3.0.1 - https://snowballstem.org/
+
+/**@constructor*/
+var EnglishStemmer = function() {
+ var base = new BaseStemmer();
+
+ /** @const */ var a_0 = [
+ ["arsen", -1, -1],
+ ["commun", -1, -1],
+ ["emerg", -1, -1],
+ ["gener", -1, -1],
+ ["later", -1, -1],
+ ["organ", -1, -1],
+ ["past", -1, -1],
+ ["univers", -1, -1]
+ ];
+
+ /** @const */ var a_1 = [
+ ["'", -1, 1],
+ ["'s'", 0, 1],
+ ["'s", -1, 1]
+ ];
+
+ /** @const */ var a_2 = [
+ ["ied", -1, 2],
+ ["s", -1, 3],
+ ["ies", 1, 2],
+ ["sses", 1, 1],
+ ["ss", 1, -1],
+ ["us", 1, -1]
+ ];
+
+ /** @const */ var a_3 = [
+ ["succ", -1, 1],
+ ["proc", -1, 1],
+ ["exc", -1, 1]
+ ];
+
+ /** @const */ var a_4 = [
+ ["even", -1, 2],
+ ["cann", -1, 2],
+ ["inn", -1, 2],
+ ["earr", -1, 2],
+ ["herr", -1, 2],
+ ["out", -1, 2],
+ ["y", -1, 1]
+ ];
+
+ /** @const */ var a_5 = [
+ ["", -1, -1],
+ ["ed", 0, 2],
+ ["eed", 1, 1],
+ ["ing", 0, 3],
+ ["edly", 0, 2],
+ ["eedly", 4, 1],
+ ["ingly", 0, 2]
+ ];
+
+ /** @const */ var a_6 = [
+ ["", -1, 3],
+ ["bb", 0, 2],
+ ["dd", 0, 2],
+ ["ff", 0, 2],
+ ["gg", 0, 2],
+ ["bl", 0, 1],
+ ["mm", 0, 2],
+ ["nn", 0, 2],
+ ["pp", 0, 2],
+ ["rr", 0, 2],
+ ["at", 0, 1],
+ ["tt", 0, 2],
+ ["iz", 0, 1]
+ ];
+
+ /** @const */ var a_7 = [
+ ["anci", -1, 3],
+ ["enci", -1, 2],
+ ["ogi", -1, 14],
+ ["li", -1, 16],
+ ["bli", 3, 12],
+ ["abli", 4, 4],
+ ["alli", 3, 8],
+ ["fulli", 3, 9],
+ ["lessli", 3, 15],
+ ["ousli", 3, 10],
+ ["entli", 3, 5],
+ ["aliti", -1, 8],
+ ["biliti", -1, 12],
+ ["iviti", -1, 11],
+ ["tional", -1, 1],
+ ["ational", 14, 7],
+ ["alism", -1, 8],
+ ["ation", -1, 7],
+ ["ization", 17, 6],
+ ["izer", -1, 6],
+ ["ator", -1, 7],
+ ["iveness", -1, 11],
+ ["fulness", -1, 9],
+ ["ousness", -1, 10],
+ ["ogist", -1, 13]
+ ];
+
+ /** @const */ var a_8 = [
+ ["icate", -1, 4],
+ ["ative", -1, 6],
+ ["alize", -1, 3],
+ ["iciti", -1, 4],
+ ["ical", -1, 4],
+ ["tional", -1, 1],
+ ["ational", 5, 2],
+ ["ful", -1, 5],
+ ["ness", -1, 5]
+ ];
+
+ /** @const */ var a_9 = [
+ ["ic", -1, 1],
+ ["ance", -1, 1],
+ ["ence", -1, 1],
+ ["able", -1, 1],
+ ["ible", -1, 1],
+ ["ate", -1, 1],
+ ["ive", -1, 1],
+ ["ize", -1, 1],
+ ["iti", -1, 1],
+ ["al", -1, 1],
+ ["ism", -1, 1],
+ ["ion", -1, 2],
+ ["er", -1, 1],
+ ["ous", -1, 1],
+ ["ant", -1, 1],
+ ["ent", -1, 1],
+ ["ment", 15, 1],
+ ["ement", 16, 1]
+ ];
+
+ /** @const */ var a_10 = [
+ ["e", -1, 1],
+ ["l", -1, 2]
+ ];
+
+ /** @const */ var a_11 = [
+ ["andes", -1, -1],
+ ["atlas", -1, -1],
+ ["bias", -1, -1],
+ ["cosmos", -1, -1],
+ ["early", -1, 5],
+ ["gently", -1, 3],
+ ["howe", -1, -1],
+ ["idly", -1, 2],
+ ["news", -1, -1],
+ ["only", -1, 6],
+ ["singly", -1, 7],
+ ["skies", -1, 1],
+ ["sky", -1, -1],
+ ["ugly", -1, 4]
+ ];
+
+ /** @const */ var /** Array