diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 868b394..ee88d7e 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -13,7 +13,7 @@ jobs: test-linux: strategy: matrix: - py-version: ['3.7', '3.8', '3.9', '3.10'] + py-version: ['3.9', '3.10', '3.11', '3.12'] runs-on: ubuntu-latest steps: - name: Checkout rustfrc @@ -23,26 +23,28 @@ jobs: - uses: actions/setup-python@v2 with: python-version: ${{ matrix.py-version }} - - - name: Rust latest - run: rustup update # We install poetry as a dependency manager to read the pyproject.toml of our package. - name: Poetry - run: curl -sSL https://raw.githubusercontent.com/python-poetry/poetry/master/install-poetry.py | python - + run: pipx install poetry==1.8.2 - # GitHub has modified PATH behavior, so we use the below command to add poetry to our PATH - - name: Add poetry path - run: echo "$HOME/.local/bin" >> $GITHUB_PATH + - name: Maturin + uses: taiki-e/install-action@v2 + with: + tool: maturin # poetry update will install all dependencies for our package, as well as maturin, which we use as our build # back-end - - name: Poetry update - run: poetry update + - name: Poetry install + run: poetry install --sync --no-root + working-directory: ${{ github.workspace }} + + - name: Poetry shell + run: poetry shell working-directory: ${{ github.workspace }} - name: maturin develop - run: poetry run maturin develop + run: maturin develop working-directory: ${{ github.workspace }} - name: cargo test @@ -52,164 +54,95 @@ jobs: - name: poetry pytest run: poetry run pytest working-directory: ${{ github.workspace }} - build-manylinux: - if: ${{ github.event_name == 'release' && github.event.action == 'published' }} - needs: [test-linux] - strategy: - # Let individual matrix jobs go if one fails - matrix: - include: - # We are compatible with all supported Python versions. The 'cp37-cp37m' is the PEP 425 tag of that specific - # Python version, which is where the Python interpreters of the manylinux Docker container are located. - - py-version: '3.7' - py-pep-425: 'cp37-cp37m' - - py-version: '3.8' - py-pep-425: 'cp38-cp38' - - py-version: '3.9' - py-pep-425: 'cp39-cp39' - - py-version: '3.10' - py-pep-425: 'cp310-cp310' - runs-on: ubuntu-latest - steps: - - name: Checkout rustfrc - uses: actions/checkout@v2 - with: - path: ${{ github.repository }} - # Set up the repository with the Docker container action, which will allow us to build and run a manylinux Docker - # container that will ensure compatibility. See the action repository for more info. - - name: maturin-manylinux-wheels-action - uses: tmtenbrink/maturin-manylinux-wheels-action@v1.0.1 - with: - py-version: "python${{ matrix.py-version }}" - py-pep-425: ${{ matrix.py-pep-425 }} - package-path: ${{ github.repository }} - # Set up the package repository in a sub-path, so it doesn't overwrite the Docker container action repo - - # It now uploads all the wheel files to an artifact that we can later retrieve - - uses: actions/upload-artifact@v2 - with: - name: wheels - path: ${{ github.repository }}/dist - - build-mac: + + build-macos: if: ${{ github.event_name == 'release' && github.event.action == 'published' }} - needs: [test-linux] - runs-on: macos-11 + needs: [ test-linux ] + runs-on: macos-latest strategy: matrix: - # If we run it without this argument, it will generate only x86_64 wheels, which are compatible with more - # macOS and pip versions. Universal2 wheels are compatible with Apple Silicon (aarch64) Macs but also updated - # x86_64 Macs. In the future only universal2 wheels will be necessary. - target: ['--universal2', ''] - py-version: ['3.7', '3.8', '3.9', '3.10'] + py-version: [ '3.9', '3.10', '3.11', '3.12' ] steps: - - uses: actions/checkout@v2 - - uses: actions/setup-python@v2 + - uses: actions/checkout@v3 + - uses: actions/setup-python@v4 with: python-version: ${{ matrix.py-version }} - - - name: Rust latest - run: rustup update - # The x86_64 Rust toolchain is installed on GitHub runners, but since we compile also for Apple Silicon, we also # need the correct Rust toolchain. - name: Rustup install aarch64 target run: rustup target add aarch64-apple-darwin if: ${{ matrix.target == '--universal2' }} - - # We install poetry as a dependency manager to read the pyproject.toml of our package. - - name: Poetry - run: curl -sSL https://raw.githubusercontent.com/python-poetry/poetry/master/install-poetry.py | python - - - # GitHub has modified PATH behavior, so we use the below command to add poetry to our PATH - - name: Add poetry path - run: echo "$HOME/.local/bin" >> $GITHUB_PATH - - # poetry update will install all dependencies for our package, as well as maturin, which we use as our build - # back-end - - name: Poetry update - run: poetry update - working-directory: ${{ github.workspace }} - - # delocate is the macOS version of auditwheel. - - name: Install delocate - run: pip install delocate - working-directory: ${{ github.workspace }} - - # This command will actually compile the wheels. We use --release to make sure Rust properly optimizes the code. - # The ${{ matrix.target }} indicates whether we are building universal 2 wheels. Finally using -i python ensures - # only the Python we set up above will be used as target. - - name: maturin build release - run: poetry run maturin build --release ${{ matrix.target }} -i python - working-directory: ${{ github.workspace }} - - # We now fix the wheels using delocate - - name: delocate fix wheels - run: find . -name "*.whl" -exec delocate-wheel -w wheelhouse --require-archs=universal2 {} \; - working-directory: ${{ github.workspace }} - - - uses: actions/upload-artifact@v2 + - name: Build wheels - universal2 + uses: PyO3/maturin-action@v1 + with: + target: universal2-apple-darwin + args: --release --out dist -i ${{ matrix.py-version }} + - name: Upload wheels + uses: actions/upload-artifact@v3 with: name: wheels - path: ${{ github.workspace }}/wheelhouse + path: ${{ github.workspace }}/dist build-windows: - if: ${{ github.event_name == 'release' && github.event.action == 'published' }} - needs: [test-linux] - runs-on: windows-latest - strategy: - matrix: - py-version: ['3.7', '3.8', '3.9', '3.10'] - steps: - - uses: actions/checkout@v2 - - uses: actions/setup-python@v2 - with: - python-version: ${{ matrix.py-version }} - - - name: Rust latest - run: rustup update - - # Installing poetry requires a different command on Windows than on macOS/Linux - - name: Poetry - run: (Invoke-WebRequest -Uri https://raw.githubusercontent.com/python-poetry/poetry/master/install-poetry.py -UseBasicParsing).Content | python - - - # PATH is also different - - name: Poetry path - run: echo "$env:APPDATA\Python\Scripts" | Out-File -FilePath $env:GITHUB_PATH -Encoding utf8 -Append - - - name: Poetry update - run: | - poetry update - working-directory: ${{ github.workspace }} - - - name: maturin build release - run: poetry run maturin build --release -i python - working-directory: ${{ github.workspace }} + if: ${{ github.event_name == 'release' && github.event.action == 'published' }} + needs: [ test-linux ] + runs-on: windows-latest + strategy: + matrix: + py-version: ['3.9', '3.10', '3.11', '3.12'] + steps: + - uses: actions/checkout@v3 + - uses: actions/setup-python@v4 + with: + python-version: ${{ matrix.py-version }} + - name: Build wheels + uses: PyO3/maturin-action@v1 + with: + target: x64 + args: --release --out dist -i ${{ matrix.py-version }} + - name: Upload wheels + uses: actions/upload-artifact@v3 + with: + name: wheels + path: ${{ github.workspace }}/dist - - uses: actions/upload-artifact@v2 - with: - name: wheels - path: ${{ github.workspace }}/target/wheels + build-linux: + if: ${{ github.event_name == 'release' && github.event.action == 'published' }} + needs: [ test-linux ] + runs-on: ubuntu-latest + strategy: + matrix: + py-version: [ '3.9', '3.10', '3.11', '3.12' ] + steps: + - uses: actions/checkout@v3 + - uses: actions/setup-python@v4 + with: + python-version: ${{ matrix.py-version }} + - name: Build wheels + uses: PyO3/maturin-action@v1 + with: + rust-toolchain: stable + target: x86_64 + manylinux: auto + args: --release --out dist -i ${{ matrix.py-version }} + - name: Upload wheels + uses: actions/upload-artifact@v3 + with: + name: wheels + path: ${{ github.workspace }}/dist wheel-publish: - needs: [build-manylinux, build-mac, build-windows] - runs-on: ubuntu-latest - steps: - - name: Download artifact - uses: actions/download-artifact@v2 - with: - name: wheels - path: ${{ github.workspace }}/dist/ - - name: Set up Python - uses: actions/setup-python@v2 - with: - python-version: '3.9' - - name: Install wheel test - run: | - pip install ${{ github.workspace }}/dist/*39*manylinux*.whl - - name: Publish a Python distribution to PyPI - if: ${{ github.event_name == 'release' && github.event.action == 'published' }} - uses: pypa/gh-action-pypi-publish@release/v1 - with: - user: __token__ - password: ${{ secrets.PYPI_RUSTFRC_TOKEN }} + name: Release + runs-on: ubuntu-latest + needs: [ build-macos, build-windows, build-linux ] + steps: + - uses: actions/download-artifact@v3 + with: + name: wheels + - name: Publish to PyPI + env: + MATURIN_PYPI_TOKEN: ${{ secrets.PYPI_RUSTFRC_TOKEN }} + uses: PyO3/maturin-action@v1 + with: + command: upload + args: --skip-existing * diff --git a/.gitignore b/.gitignore index a6704a1..1c5aed6 100644 --- a/.gitignore +++ b/.gitignore @@ -4,4 +4,5 @@ Cargo.lock /tests/.pytest_cache **/__pycache__/** **/*.pyd -*.so \ No newline at end of file +*.so +.python-version \ No newline at end of file diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..1909541 --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,9 @@ +# Changelog + +## 1.1.4 2024-04-03 + +* **Drop Python 3.7, 3.8 support**: Note that this is technically a breaking change, but 1.1.3 works just fine for older versions and this doesn't include much else. This is necessary to use NumPy 1.26, which is required for Python >=3.12. +* Update interal Rust crate to use new PyO3 bounds API +* `sqr_abs` no longer performs its computation using rayon, which improves performance for arrays at least up to 4000x4000 +* Added benchmarks +* `pois_gen` no longer has a hard-coded limit for the amount of elements diff --git a/Cargo.toml b/Cargo.toml index b2f4494..40b618c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "rustfrc" -version = "1.1.3" +version = "1.1.4" edition = "2021" [lib] diff --git a/README.md b/README.md index 602d1df..c5f655b 100644 --- a/README.md +++ b/README.md @@ -3,13 +3,13 @@ ![GitHub release](https://flat.badgen.net/github/release/tmtenbrink/rustfrc) ![License](https://flat.badgen.net/github/license/tmtenbrink/rustfrc) -rustfrc is a Python package with some fast Rust functions that are using when performing Fourier Ring Correlation (FRC) computations for resolution determination in microscopy (specifically optical nanoscopy). It is in development for use in a Bachelor end project for the TU Delft in the period 2021-2022. +rustfrc is a Python package with some fast Rust functions that are useful when performing Fourier Ring Correlation (FRC) computations for resolution determination in microscopy (specifically optical nanoscopy). It was originally developed for use in a Bachelor end project for the TU Delft in the period 2021-2022. See the Python package [`frc`](https://github.com/tmtenbrink/frc) for examples of its usage. The `test_split.py` file in the `tests` directory also holds some examples. Since rustfrc contains compiled (Rust) extensions and is not pure Python, it is not available for all platforms, but only for those with available compiled wheels or a Rust toolchain and `maturin` support (see below). They are available for Windows (x86_64), macOS (x86_64 and universal2, which includes Apple Silicon) and Linux (x86_64). However, since Rust and Python are supported on many platforms, it is not difficult to compile for other platforms (see below). ## Features -Currently, rustfrc does not have many features. The primary one is `binom_split(x: ndarray) -> ndarray` which samples binomial _(n, 0.5)_ with n as the array element value. The operation is fully parallelized and somewhere between 3-10x faster than sampling using NumPy. +rustfrc has only a few features. The primary one is `binom_split(x: ndarray) -> ndarray` which samples binomial _(n, 0.5)_ with n as the array element value. The operation is fully parallelized and somewhere between 3-10x faster than sampling using NumPy. Furthermore, there are also (since version 1.1) `sqr_abs(a: ndarray) -> ndarray` and `pois_gen(lam: float, shape: tuple[int, ...]) -> ndarray`. @@ -17,8 +17,18 @@ Furthermore, there are also (since version 1.1) `sqr_abs(a: ndarray) -> ndarray` ## Requirements -* Python 3.7 or greater -* NumPy 1.18 or greater +* Python 3.8-3.12 +* NumPy 1.18 or greater (tested last with v1.26) + +## Performance + +On an i7-8750H, a decently high performance 6-core chip from 2017, I measured the following speeds: + +- `binom_split`: ~210 ms on a 4000x4000 array, with each element Poisson-generated with a mean of 200 +- `pois_gen`: ~420 ms to generate a 4000x4000 array with mean 200 +- `sqr_abs`: ~40 ms on a 4000x4000 array, where each element is a complex number with both the real and imaginary parts having a mean of 200 + +Take this with a grain of salt, but it should provide a decent order of magnitude for larger images. ## Installation @@ -32,8 +42,7 @@ However, for an optimal Python experience, use [poetry](https://github.com/pytho ### From source (using maturin) -rustfrc uses [poetry](https://github.com/python-poetry/poetry) as its Python dependency manager. For best results, create a `poetry` virtualenv (be sure to install virtualenv as a systems package) with the `pyproject.toml` and run `poetry update` to install the required packages. - Installing [maturin](https://pypi.org/project/maturin/) manually should also work. It is also necessary to have a Rust toolchain installed on your computer. Rust can be easily installed using [rustup](https://rustup.rs/). +rustfrc uses [poetry](https://github.com/python-poetry/poetry) as its Python dependency manager. For best results, create a `poetry` virtualenv (be sure to install virtualenv as a systems package) with the `pyproject.toml` and run `poetry update` to install the required packages. I recommend installing [maturin](https://pypi.org/project/maturin/) as a global tool (e.g. with `cargo binstall`). Build a wheel file like this (if using poetry, append `poetry run` before the command) from the project directory: diff --git a/poetry.lock b/poetry.lock index 819c9ba..9542b24 100644 --- a/poetry.lock +++ b/poetry.lock @@ -1,271 +1,146 @@ -[[package]] -name = "atomicwrites" -version = "1.4.0" -description = "Atomic file writes." -category = "dev" -optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" - -[[package]] -name = "attrs" -version = "21.2.0" -description = "Classes Without Boilerplate" -category = "dev" -optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" - -[package.extras] -dev = ["coverage[toml] (>=5.0.2)", "hypothesis", "pympler", "pytest (>=4.3.0)", "six", "mypy", "pytest-mypy-plugins", "zope.interface", "furo", "sphinx", "sphinx-notfound-page", "pre-commit"] -docs = ["furo", "sphinx", "zope.interface", "sphinx-notfound-page"] -tests = ["coverage[toml] (>=5.0.2)", "hypothesis", "pympler", "pytest (>=4.3.0)", "six", "mypy", "pytest-mypy-plugins", "zope.interface"] -tests_no_zope = ["coverage[toml] (>=5.0.2)", "hypothesis", "pympler", "pytest (>=4.3.0)", "six", "mypy", "pytest-mypy-plugins"] +# This file is automatically @generated by Poetry 1.8.2 and should not be changed by hand. [[package]] name = "colorama" -version = "0.4.4" +version = "0.4.6" description = "Cross-platform colored terminal text." -category = "dev" optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" +python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*,>=2.7" +files = [ + {file = "colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6"}, + {file = "colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44"}, +] [[package]] -name = "importlib-metadata" -version = "4.8.2" -description = "Read metadata from Python packages" -category = "dev" +name = "exceptiongroup" +version = "1.2.0" +description = "Backport of PEP 654 (exception groups)" optional = false -python-versions = ">=3.6" - -[package.dependencies] -typing-extensions = {version = ">=3.6.4", markers = "python_version < \"3.8\""} -zipp = ">=0.5" +python-versions = ">=3.7" +files = [ + {file = "exceptiongroup-1.2.0-py3-none-any.whl", hash = "sha256:4bfd3996ac73b41e9b9628b04e079f193850720ea5945fc96a08633c66912f14"}, + {file = "exceptiongroup-1.2.0.tar.gz", hash = "sha256:91f5c769735f051a4290d52edd0858999b57e5876e9f85937691bd4c9fa3ed68"}, +] [package.extras] -docs = ["sphinx", "jaraco.packaging (>=8.2)", "rst.linker (>=1.9)"] -perf = ["ipython"] -testing = ["pytest (>=6)", "pytest-checkdocs (>=2.4)", "pytest-flake8", "pytest-cov", "pytest-enabler (>=1.0.1)", "packaging", "pep517", "pyfakefs", "flufl.flake8", "pytest-perf (>=0.9.2)", "pytest-black (>=0.3.7)", "pytest-mypy", "importlib-resources (>=1.3)"] +test = ["pytest (>=6)"] [[package]] name = "iniconfig" -version = "1.1.1" -description = "iniconfig: brain-dead simple config-ini parsing" -category = "dev" -optional = false -python-versions = "*" - -[[package]] -name = "maturin" -version = "0.11.5" -description = "Build and publish crates with pyo3, rust-cpython and cffi bindings as well as rust binaries as python packages" -category = "dev" +version = "2.0.0" +description = "brain-dead simple config-ini parsing" optional = false -python-versions = ">=3.6" - -[package.dependencies] -toml = ">=0.10.2,<0.11.0" +python-versions = ">=3.7" +files = [ + {file = "iniconfig-2.0.0-py3-none-any.whl", hash = "sha256:b6a85871a79d2e3b22d2d1b94ac2824226a63c6b741c88f7ae975f18b6778374"}, + {file = "iniconfig-2.0.0.tar.gz", hash = "sha256:2d91e135bf72d31a410b17c16da610a82cb55f6b0477d1a902134b24a455b8b3"}, +] [[package]] name = "numpy" -version = "1.21.4" -description = "NumPy is the fundamental package for array computing with Python." -category = "main" +version = "1.26.4" +description = "Fundamental package for array computing in Python" optional = false -python-versions = ">=3.7,<3.11" +python-versions = ">=3.9" +files = [ + {file = "numpy-1.26.4-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:9ff0f4f29c51e2803569d7a51c2304de5554655a60c5d776e35b4a41413830d0"}, + {file = "numpy-1.26.4-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:2e4ee3380d6de9c9ec04745830fd9e2eccb3e6cf790d39d7b98ffd19b0dd754a"}, + {file = "numpy-1.26.4-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d209d8969599b27ad20994c8e41936ee0964e6da07478d6c35016bc386b66ad4"}, + {file = "numpy-1.26.4-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ffa75af20b44f8dba823498024771d5ac50620e6915abac414251bd971b4529f"}, + {file = "numpy-1.26.4-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:62b8e4b1e28009ef2846b4c7852046736bab361f7aeadeb6a5b89ebec3c7055a"}, + {file = "numpy-1.26.4-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:a4abb4f9001ad2858e7ac189089c42178fcce737e4169dc61321660f1a96c7d2"}, + {file = "numpy-1.26.4-cp310-cp310-win32.whl", hash = "sha256:bfe25acf8b437eb2a8b2d49d443800a5f18508cd811fea3181723922a8a82b07"}, + {file = "numpy-1.26.4-cp310-cp310-win_amd64.whl", hash = "sha256:b97fe8060236edf3662adfc2c633f56a08ae30560c56310562cb4f95500022d5"}, + {file = "numpy-1.26.4-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:4c66707fabe114439db9068ee468c26bbdf909cac0fb58686a42a24de1760c71"}, + {file = "numpy-1.26.4-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:edd8b5fe47dab091176d21bb6de568acdd906d1887a4584a15a9a96a1dca06ef"}, + {file = "numpy-1.26.4-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7ab55401287bfec946ced39700c053796e7cc0e3acbef09993a9ad2adba6ca6e"}, + {file = "numpy-1.26.4-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:666dbfb6ec68962c033a450943ded891bed2d54e6755e35e5835d63f4f6931d5"}, + {file = "numpy-1.26.4-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:96ff0b2ad353d8f990b63294c8986f1ec3cb19d749234014f4e7eb0112ceba5a"}, + {file = "numpy-1.26.4-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:60dedbb91afcbfdc9bc0b1f3f402804070deed7392c23eb7a7f07fa857868e8a"}, + {file = "numpy-1.26.4-cp311-cp311-win32.whl", hash = "sha256:1af303d6b2210eb850fcf03064d364652b7120803a0b872f5211f5234b399f20"}, + {file = "numpy-1.26.4-cp311-cp311-win_amd64.whl", hash = "sha256:cd25bcecc4974d09257ffcd1f098ee778f7834c3ad767fe5db785be9a4aa9cb2"}, + {file = "numpy-1.26.4-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:b3ce300f3644fb06443ee2222c2201dd3a89ea6040541412b8fa189341847218"}, + {file = "numpy-1.26.4-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:03a8c78d01d9781b28a6989f6fa1bb2c4f2d51201cf99d3dd875df6fbd96b23b"}, + {file = "numpy-1.26.4-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9fad7dcb1aac3c7f0584a5a8133e3a43eeb2fe127f47e3632d43d677c66c102b"}, + {file = "numpy-1.26.4-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:675d61ffbfa78604709862923189bad94014bef562cc35cf61d3a07bba02a7ed"}, + {file = "numpy-1.26.4-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:ab47dbe5cc8210f55aa58e4805fe224dac469cde56b9f731a4c098b91917159a"}, + {file = "numpy-1.26.4-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:1dda2e7b4ec9dd512f84935c5f126c8bd8b9f2fc001e9f54af255e8c5f16b0e0"}, + {file = "numpy-1.26.4-cp312-cp312-win32.whl", hash = "sha256:50193e430acfc1346175fcbdaa28ffec49947a06918b7b92130744e81e640110"}, + {file = "numpy-1.26.4-cp312-cp312-win_amd64.whl", hash = "sha256:08beddf13648eb95f8d867350f6a018a4be2e5ad54c8d8caed89ebca558b2818"}, + {file = "numpy-1.26.4-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:7349ab0fa0c429c82442a27a9673fc802ffdb7c7775fad780226cb234965e53c"}, + {file = "numpy-1.26.4-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:52b8b60467cd7dd1e9ed082188b4e6bb35aa5cdd01777621a1658910745b90be"}, + {file = "numpy-1.26.4-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d5241e0a80d808d70546c697135da2c613f30e28251ff8307eb72ba696945764"}, + {file = "numpy-1.26.4-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f870204a840a60da0b12273ef34f7051e98c3b5961b61b0c2c1be6dfd64fbcd3"}, + {file = "numpy-1.26.4-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:679b0076f67ecc0138fd2ede3a8fd196dddc2ad3254069bcb9faf9a79b1cebcd"}, + {file = "numpy-1.26.4-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:47711010ad8555514b434df65f7d7b076bb8261df1ca9bb78f53d3b2db02e95c"}, + {file = "numpy-1.26.4-cp39-cp39-win32.whl", hash = "sha256:a354325ee03388678242a4d7ebcd08b5c727033fcff3b2f536aea978e15ee9e6"}, + {file = "numpy-1.26.4-cp39-cp39-win_amd64.whl", hash = "sha256:3373d5d70a5fe74a2c1bb6d2cfd9609ecf686d47a2d7b1d37a8f3b6bf6003aea"}, + {file = "numpy-1.26.4-pp39-pypy39_pp73-macosx_10_9_x86_64.whl", hash = "sha256:afedb719a9dcfc7eaf2287b839d8198e06dcd4cb5d276a3df279231138e83d30"}, + {file = "numpy-1.26.4-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:95a7476c59002f2f6c590b9b7b998306fba6a5aa646b1e22ddfeaf8f78c3a29c"}, + {file = "numpy-1.26.4-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:7e50d0a0cc3189f9cb0aeb3a6a6af18c16f59f004b866cd2be1c14b36134a4a0"}, + {file = "numpy-1.26.4.tar.gz", hash = "sha256:2a02aba9ed12e4ac4eb3ea9421c420301a0c6460d9830d74a9df87efa4912010"}, +] [[package]] name = "packaging" -version = "21.3" +version = "24.0" description = "Core utilities for Python packages" -category = "dev" optional = false -python-versions = ">=3.6" - -[package.dependencies] -pyparsing = ">=2.0.2,<3.0.5 || >3.0.5" +python-versions = ">=3.7" +files = [ + {file = "packaging-24.0-py3-none-any.whl", hash = "sha256:2ddfb553fdf02fb784c234c7ba6ccc288296ceabec964ad2eae3777778130bc5"}, + {file = "packaging-24.0.tar.gz", hash = "sha256:eb82c5e3e56209074766e6885bb04b8c38a0c015d0a30036ebe7ece34c9989e9"}, +] [[package]] name = "pluggy" -version = "1.0.0" +version = "1.4.0" description = "plugin and hook calling mechanisms for python" -category = "dev" optional = false -python-versions = ">=3.6" - -[package.dependencies] -importlib-metadata = {version = ">=0.12", markers = "python_version < \"3.8\""} +python-versions = ">=3.8" +files = [ + {file = "pluggy-1.4.0-py3-none-any.whl", hash = "sha256:7db9f7b503d67d1c5b95f59773ebb58a8c1c288129a88665838012cfb07b8981"}, + {file = "pluggy-1.4.0.tar.gz", hash = "sha256:8c85c2876142a764e5b7548e7d9a0e0ddb46f5185161049a79b7e974454223be"}, +] [package.extras] dev = ["pre-commit", "tox"] testing = ["pytest", "pytest-benchmark"] -[[package]] -name = "py" -version = "1.11.0" -description = "library with cross-python path, ini-parsing, io, code, log facilities" -category = "dev" -optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" - -[[package]] -name = "pyparsing" -version = "3.0.6" -description = "Python parsing module" -category = "dev" -optional = false -python-versions = ">=3.6" - -[package.extras] -diagrams = ["jinja2", "railroad-diagrams"] - [[package]] name = "pytest" -version = "6.2.5" +version = "8.1.1" description = "pytest: simple powerful testing with Python" -category = "dev" optional = false -python-versions = ">=3.6" +python-versions = ">=3.8" +files = [ + {file = "pytest-8.1.1-py3-none-any.whl", hash = "sha256:2a8386cfc11fa9d2c50ee7b2a57e7d898ef90470a7a34c4b949ff59662bb78b7"}, + {file = "pytest-8.1.1.tar.gz", hash = "sha256:ac978141a75948948817d360297b7aae0fcb9d6ff6bc9ec6d514b85d5a65c044"}, +] [package.dependencies] -atomicwrites = {version = ">=1.0", markers = "sys_platform == \"win32\""} -attrs = ">=19.2.0" colorama = {version = "*", markers = "sys_platform == \"win32\""} -importlib-metadata = {version = ">=0.12", markers = "python_version < \"3.8\""} +exceptiongroup = {version = ">=1.0.0rc8", markers = "python_version < \"3.11\""} iniconfig = "*" packaging = "*" -pluggy = ">=0.12,<2.0" -py = ">=1.8.2" -toml = "*" +pluggy = ">=1.4,<2.0" +tomli = {version = ">=1", markers = "python_version < \"3.11\""} [package.extras] -testing = ["argcomplete", "hypothesis (>=3.56)", "mock", "nose", "requests", "xmlschema"] - -[[package]] -name = "toml" -version = "0.10.2" -description = "Python Library for Tom's Obvious, Minimal Language" -category = "dev" -optional = false -python-versions = ">=2.6, !=3.0.*, !=3.1.*, !=3.2.*" +testing = ["argcomplete", "attrs (>=19.2)", "hypothesis (>=3.56)", "mock", "pygments (>=2.7.2)", "requests", "setuptools", "xmlschema"] [[package]] -name = "typing-extensions" -version = "4.0.0" -description = "Backported and Experimental Type Hints for Python 3.6+" -category = "dev" +name = "tomli" +version = "2.0.1" +description = "A lil' TOML parser" optional = false -python-versions = ">=3.6" - -[[package]] -name = "zipp" -version = "3.6.0" -description = "Backport of pathlib-compatible object wrapper for zip files" -category = "dev" -optional = false -python-versions = ">=3.6" - -[package.extras] -docs = ["sphinx", "jaraco.packaging (>=8.2)", "rst.linker (>=1.9)"] -testing = ["pytest (>=4.6)", "pytest-checkdocs (>=2.4)", "pytest-flake8", "pytest-cov", "pytest-enabler (>=1.0.1)", "jaraco.itertools", "func-timeout", "pytest-black (>=0.3.7)", "pytest-mypy"] +python-versions = ">=3.7" +files = [ + {file = "tomli-2.0.1-py3-none-any.whl", hash = "sha256:939de3e7a6161af0c887ef91b7d41a53e7c5a1ca976325f429cb46ea9bc30ecc"}, + {file = "tomli-2.0.1.tar.gz", hash = "sha256:de526c12914f0c550d15924c62d72abc48d6fe7364aa87328337a31007fe8a4f"}, +] [metadata] -lock-version = "1.1" -python-versions = ">= 3.7, <3.11" -content-hash = "1931a044497b4e981eb9814970ba0b38caf06eb07abce537e85154bc2bbdc09b" - -[metadata.files] -atomicwrites = [ - {file = "atomicwrites-1.4.0-py2.py3-none-any.whl", hash = "sha256:6d1784dea7c0c8d4a5172b6c620f40b6e4cbfdf96d783691f2e1302a7b88e197"}, - {file = "atomicwrites-1.4.0.tar.gz", hash = "sha256:ae70396ad1a434f9c7046fd2dd196fc04b12f9e91ffb859164193be8b6168a7a"}, -] -attrs = [ - {file = "attrs-21.2.0-py2.py3-none-any.whl", hash = "sha256:149e90d6d8ac20db7a955ad60cf0e6881a3f20d37096140088356da6c716b0b1"}, - {file = "attrs-21.2.0.tar.gz", hash = "sha256:ef6aaac3ca6cd92904cdd0d83f629a15f18053ec84e6432106f7a4d04ae4f5fb"}, -] -colorama = [ - {file = "colorama-0.4.4-py2.py3-none-any.whl", hash = "sha256:9f47eda37229f68eee03b24b9748937c7dc3868f906e8ba69fbcbdd3bc5dc3e2"}, - {file = "colorama-0.4.4.tar.gz", hash = "sha256:5941b2b48a20143d2267e95b1c2a7603ce057ee39fd88e7329b0c292aa16869b"}, -] -importlib-metadata = [ - {file = "importlib_metadata-4.8.2-py3-none-any.whl", hash = "sha256:53ccfd5c134223e497627b9815d5030edf77d2ed573922f7a0b8f8bb81a1c100"}, - {file = "importlib_metadata-4.8.2.tar.gz", hash = "sha256:75bdec14c397f528724c1bfd9709d660b33a4d2e77387a3358f20b848bb5e5fb"}, -] -iniconfig = [ - {file = "iniconfig-1.1.1-py2.py3-none-any.whl", hash = "sha256:011e24c64b7f47f6ebd835bb12a743f2fbe9a26d4cecaa7f53bc4f35ee9da8b3"}, - {file = "iniconfig-1.1.1.tar.gz", hash = "sha256:bc3af051d7d14b2ee5ef9969666def0cd1a000e121eaea580d4a313df4b37f32"}, -] -maturin = [ - {file = "maturin-0.11.5-py3-none-macosx_10_7_x86_64.whl", hash = "sha256:d78f24561a5e02f7d119b348b26e5772ad5698a43ca49e8facb9ce77cf273714"}, - {file = "maturin-0.11.5-py3-none-macosx_10_9_x86_64.macosx_11_0_arm64.macosx_10_9_universal2.whl", hash = "sha256:c2ded8b4ef9210d627bb966bc67661b7db259535f6062afe1ce5605406b50f3f"}, - {file = "maturin-0.11.5-py3-none-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:1ce666c386ff9c3c2b5d7d3ca4b1f9f675c38d7540ffbda0d5d5bc7d6ddde49a"}, - {file = "maturin-0.11.5-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b0ac45879a7d624b47d72b093ae3370270894c19779f42aad7568a92951c5d47"}, - {file = "maturin-0.11.5-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:4191b0b7362b3025096faf126ff15cb682fbff324ac4a6ca18d55bb16e2b759b"}, - {file = "maturin-0.11.5-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:7bf96e7586bfdb5b0fadc6d662534b8a41123b33dff084fa383a81ded0ce5334"}, - {file = "maturin-0.11.5-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:ab2b3ccf66f5e0f9c3904d215835337b1bd305e79e3bf53b65bbc80a5755e01b"}, - {file = "maturin-0.11.5-py3-none-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:3354d030b88c938a33bf407a6c0f79ccdd2cce3e1e3e4a2d0c92dc2e063adc6e"}, - {file = "maturin-0.11.5-py3-none-win32.whl", hash = "sha256:20f9c30701c9932ed8026ceaf896fc77ecc76cebd6a182668dbc10ed597f8789"}, - {file = "maturin-0.11.5-py3-none-win_amd64.whl", hash = "sha256:70381be1585cb9fa5c02b83af80ae661aaad959e8aa0fddcfe195b004054bd69"}, - {file = "maturin-0.11.5.tar.gz", hash = "sha256:07074778b063a439fdfd5501bd1d1823a216ec5b657d3ecde78fd7f2c4782422"}, -] -numpy = [ - {file = "numpy-1.21.4-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:8890b3360f345e8360133bc078d2dacc2843b6ee6059b568781b15b97acbe39f"}, - {file = "numpy-1.21.4-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:69077388c5a4b997442b843dbdc3a85b420fb693ec8e33020bb24d647c164fa5"}, - {file = "numpy-1.21.4-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:e89717274b41ebd568cd7943fc9418eeb49b1785b66031bc8a7f6300463c5898"}, - {file = "numpy-1.21.4-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0b78ecfa070460104934e2caf51694ccd00f37d5e5dbe76f021b1b0b0d221823"}, - {file = "numpy-1.21.4-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:615d4e328af7204c13ae3d4df7615a13ff60a49cb0d9106fde07f541207883ca"}, - {file = "numpy-1.21.4-cp310-cp310-win_amd64.whl", hash = "sha256:1403b4e2181fc72664737d848b60e65150f272fe5a1c1cbc16145ed43884065a"}, - {file = "numpy-1.21.4-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:74b85a17528ca60cf98381a5e779fc0264b4a88b46025e6bcbe9621f46bb3e63"}, - {file = "numpy-1.21.4-cp37-cp37m-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:92aafa03da8658609f59f18722b88f0a73a249101169e28415b4fa148caf7e41"}, - {file = "numpy-1.21.4-cp37-cp37m-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:5d95668e727c75b3f5088ec7700e260f90ec83f488e4c0aaccb941148b2cd377"}, - {file = "numpy-1.21.4-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f5162ec777ba7138906c9c274353ece5603646c6965570d82905546579573f73"}, - {file = "numpy-1.21.4-cp37-cp37m-win32.whl", hash = "sha256:81225e58ef5fce7f1d80399575576fc5febec79a8a2742e8ef86d7b03beef49f"}, - {file = "numpy-1.21.4-cp37-cp37m-win_amd64.whl", hash = "sha256:32fe5b12061f6446adcbb32cf4060a14741f9c21e15aaee59a207b6ce6423469"}, - {file = "numpy-1.21.4-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:c449eb870616a7b62e097982c622d2577b3dbc800aaf8689254ec6e0197cbf1e"}, - {file = "numpy-1.21.4-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:2e4ed57f45f0aa38beca2a03b6532e70e548faf2debbeb3291cfc9b315d9be8f"}, - {file = "numpy-1.21.4-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:1247ef28387b7bb7f21caf2dbe4767f4f4175df44d30604d42ad9bd701ebb31f"}, - {file = "numpy-1.21.4-cp38-cp38-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:34f3456f530ae8b44231c63082c8899fe9c983fd9b108c997c4b1c8c2d435333"}, - {file = "numpy-1.21.4-cp38-cp38-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:4c9c23158b87ed0e70d9a50c67e5c0b3f75bcf2581a8e34668d4e9d7474d76c6"}, - {file = "numpy-1.21.4-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e4799be6a2d7d3c33699a6f77201836ac975b2e1b98c2a07f66a38f499cb50ce"}, - {file = "numpy-1.21.4-cp38-cp38-win32.whl", hash = "sha256:bc988afcea53e6156546e5b2885b7efab089570783d9d82caf1cfd323b0bb3dd"}, - {file = "numpy-1.21.4-cp38-cp38-win_amd64.whl", hash = "sha256:170b2a0805c6891ca78c1d96ee72e4c3ed1ae0a992c75444b6ab20ff038ba2cd"}, - {file = "numpy-1.21.4-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:fde96af889262e85aa033f8ee1d3241e32bf36228318a61f1ace579df4e8170d"}, - {file = "numpy-1.21.4-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:c885bfc07f77e8fee3dc879152ba993732601f1f11de248d4f357f0ffea6a6d4"}, - {file = "numpy-1.21.4-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:9e6f5f50d1eff2f2f752b3089a118aee1ea0da63d56c44f3865681009b0af162"}, - {file = "numpy-1.21.4-cp39-cp39-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:ad010846cdffe7ec27e3f933397f8a8d6c801a48634f419e3d075db27acf5880"}, - {file = "numpy-1.21.4-cp39-cp39-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:c74c699b122918a6c4611285cc2cad4a3aafdb135c22a16ec483340ef97d573c"}, - {file = "numpy-1.21.4-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9864424631775b0c052f3bd98bc2712d131b3e2cd95d1c0c68b91709170890b0"}, - {file = "numpy-1.21.4-cp39-cp39-win32.whl", hash = "sha256:b1e2312f5b8843a3e4e8224b2b48fe16119617b8fc0a54df8f50098721b5bed2"}, - {file = "numpy-1.21.4-cp39-cp39-win_amd64.whl", hash = "sha256:e3c3e990274444031482a31280bf48674441e0a5b55ddb168f3a6db3e0c38ec8"}, - {file = "numpy-1.21.4-pp37-pypy37_pp73-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:a3deb31bc84f2b42584b8c4001c85d1934dbfb4030827110bc36bfd11509b7bf"}, - {file = "numpy-1.21.4.zip", hash = "sha256:e6c76a87633aa3fa16614b61ccedfae45b91df2767cf097aa9c933932a7ed1e0"}, -] -packaging = [ - {file = "packaging-21.3-py3-none-any.whl", hash = "sha256:ef103e05f519cdc783ae24ea4e2e0f508a9c99b2d4969652eed6a2e1ea5bd522"}, - {file = "packaging-21.3.tar.gz", hash = "sha256:dd47c42927d89ab911e606518907cc2d3a1f38bbd026385970643f9c5b8ecfeb"}, -] -pluggy = [ - {file = "pluggy-1.0.0-py2.py3-none-any.whl", hash = "sha256:74134bbf457f031a36d68416e1509f34bd5ccc019f0bcc952c7b909d06b37bd3"}, - {file = "pluggy-1.0.0.tar.gz", hash = "sha256:4224373bacce55f955a878bf9cfa763c1e360858e330072059e10bad68531159"}, -] -py = [ - {file = "py-1.11.0-py2.py3-none-any.whl", hash = "sha256:607c53218732647dff4acdfcd50cb62615cedf612e72d1724fb1a0cc6405b378"}, - {file = "py-1.11.0.tar.gz", hash = "sha256:51c75c4126074b472f746a24399ad32f6053d1b34b68d2fa41e558e6f4a98719"}, -] -pyparsing = [ - {file = "pyparsing-3.0.6-py3-none-any.whl", hash = "sha256:04ff808a5b90911829c55c4e26f75fa5ca8a2f5f36aa3a51f68e27033341d3e4"}, - {file = "pyparsing-3.0.6.tar.gz", hash = "sha256:d9bdec0013ef1eb5a84ab39a3b3868911598afa494f5faa038647101504e2b81"}, -] -pytest = [ - {file = "pytest-6.2.5-py3-none-any.whl", hash = "sha256:7310f8d27bc79ced999e760ca304d69f6ba6c6649c0b60fb0e04a4a77cacc134"}, - {file = "pytest-6.2.5.tar.gz", hash = "sha256:131b36680866a76e6781d13f101efb86cf674ebb9762eb70d3082b6f29889e89"}, -] -toml = [ - {file = "toml-0.10.2-py2.py3-none-any.whl", hash = "sha256:806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b"}, - {file = "toml-0.10.2.tar.gz", hash = "sha256:b3bda1d108d5dd99f4a20d24d9c348e91c4db7ab1b749200bded2f839ccbe68f"}, -] -typing-extensions = [ - {file = "typing_extensions-4.0.0-py3-none-any.whl", hash = "sha256:829704698b22e13ec9eaf959122315eabb370b0884400e9818334d8b677023d9"}, -] -zipp = [ - {file = "zipp-3.6.0-py3-none-any.whl", hash = "sha256:9fe5ea21568a0a70e50f273397638d39b03353731e6cbbb3fd8502a33fec40bc"}, - {file = "zipp-3.6.0.tar.gz", hash = "sha256:71c644c5369f4a6e07636f0aa966270449561fcea2e3d6747b8d23efaa9d7832"}, -] +lock-version = "2.0" +python-versions = ">= 3.9, <3.13" +content-hash = "a12c73bf935b1dce33a90e4e346b84729d48174d17a7dc3950b4c677882e8e76" diff --git a/pyproject.toml b/pyproject.toml index 4114bf0..603fbc1 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,9 +1,9 @@ [project] name = "rustfrc" -version = "1.1.3" +version = "1.1.4" description = "Fast utility functions useful for Fourier Ring/Shell Correlation: binom_split, pois_gen, square_abs." readme = "README.md" -requires-python = ">=3.7, <3.11" +requires-python = ">=3.9, <3.13" license = {text = "Apache-2.0"} authors = [ {email = "T.M.tenBrink@student.tudelft.nl"}, @@ -24,18 +24,20 @@ Source = "https://github.com/tmtenbrink/rustfrc" [tool.poetry] name = "rustfrc" -version = "1.1.3" +version = "1.1.4" description = "Fast utility functions useful for Fourier Ring/Shell Correlation: binomial splitting of arrays." authors = ["Tip ten Brink "] [tool.poetry.dependencies] -python = ">= 3.7, <3.11" -numpy = " >= 1.18, < 2" +python = ">= 3.9, <3.13" +numpy = "^1.26" [tool.poetry.dev-dependencies] -maturin = "^0.11.3" -pytest = "^6.2.5" +pytest = "^8.1.1" + +[tool.maturin] +python-source = "python" [build-system] -requires = ["maturin >= 0.11, < 0.12"] +requires = ["maturin>=1.0,<2.0"] build-backend ="maturin" diff --git a/python/rustfrc/py.typed b/python/rustfrc/py.typed new file mode 100644 index 0000000..e69de29 diff --git a/python/rustfrc/split.py b/python/rustfrc/split.py index f5f303e..0ff7fcc 100644 --- a/python/rustfrc/split.py +++ b/python/rustfrc/split.py @@ -34,14 +34,11 @@ def sqr_abs(a: _np.ndarray) -> _np.ndarray: def pois_gen(lam: float, shape: tuple) -> _np.ndarray: """ Generates an array (np.ndarray with dtype float64) by sampling a Poisson distribution with parameter lambda for each - element. Takes a lambda parameter (positive) and a shape tuple of non-negative ints. Maximum number of elements in - the array is 2500000000 (due to memory limitations), so the product of all the shape elements must be less. + element. Takes a lambda parameter (positive) and a shape tuple of non-negative ints. Due to memomry limitations it might + fail for larger arrays. Below 250M elements seems to work. :param shape: Tuple of ints determining the output array shape. :param lam: Lambda parameter for Poisson distribution. :return: Generated random array. """ - too_large = 2500000000 - if _np.prod(shape) > too_large: - raise ValueError("Array shape too large! Maximum element number is {}".format(too_large)) return _internal.pois_gen_py(shape, lam) diff --git a/src/lib.rs b/src/lib.rs index 125ff0f..d05d13d 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -4,9 +4,7 @@ use std::fmt::{Display, Formatter}; use std::marker::{Send, Sync}; use std::sync::atomic::{AtomicBool, Ordering}; -use ndarray::parallel::prelude::*; -use ndarray::parallel::prelude::IntoParallelIterator; -use ndarray::{Array, ArrayD, ArrayView, Dimension, Zip}; +use ndarray::{Array, ArrayD, ArrayView, Dimension}; use ndarray_rand::rand::prelude::{Distribution, thread_rng}; use ndarray_rand::rand_distr::{Binomial, Poisson, PoissonError}; use num_complex::{Complex, Complex32, Complex64}; @@ -68,7 +66,7 @@ fn sqr_abs64_py<'py>(py: Python<'py>, a: PyReadonlyArrayDyn<'py, Complex64>) -> /// non-negative ints. #[pyfunction] #[pyo3(text_signature = "a, /")] -fn pois_gen_py<'py>(py: Python<'py>, shape: PyObject, lambda: f64 ) -> PyResult>> { +fn pois_gen_py(py: Python<'_>, shape: PyObject, lambda: f64 ) -> PyResult>> { let shape_vec: Vec = shape.extract(py)?; let shape = shape_vec.as_slice(); @@ -94,30 +92,10 @@ impl Error for ToUsizeError {} pub fn binom_split(mut a: Array) -> Result, ToUsizeError> { // AtomicBool is thread-safe, and allows for communicating an error state occurred across threads // We initialize it with the value false, since no error occurred + // Note that this comes with a negligible performance penalty let to_unsized_failed = AtomicBool::new(false); + // We map all values in parallel, since they do not depend on each other - - // let a = a.mapv(|i| { - // if !to_unsized_failed.load(Ordering::Relaxed) { - // // We use thread rng, which is fast - // let mut rng = thread_rng(); - // // We try to convert i32 to u64 (which is required for Binomial) - // // If it fails, we indicate a failure has occurred - // // Unfortunately it is not possible to escape from the loop immediately - // let n = u64::try_from(i).unwrap_or_else(|_| { - // to_unsized_failed.store(true, Ordering::Relaxed); - // 0 - // }); - // // Since the input fit into an i32 and the binomial output is always less, we know the output - // // will also fit into an i32 - // Binomial::new(n, 0.5).unwrap().sample(&mut rng) as i32 - // } - // // We just keep the rest unchanged if a failure occurred - // else { - // i - // } - // }); - a.par_mapv_inplace(|i| { // If no failure has occurred, we continue // We use Relaxed Ordering because the order in which stores and loads occur does not matter @@ -152,14 +130,9 @@ pub fn binom_split(mut a: Array) -> Result, /// Takes an ndarray (dimension D and complex number of generic float F) and computes the absolute /// value and then square for each element. pub fn sqr_abs(a: Array, D>) -> Array { - let v: Vec = a.par_iter().map(|i| i.norm_sqr()).collect(); - let v_arr = Array::from_shape_vec(a.raw_dim(), v).unwrap(); - - v_arr - - // a.mapv(|i| { - // i.norm_sqr() - // }) + a.mapv(|i| { + i.norm_sqr() + }) } /// Generates an ndarray (dynamic dimension) by sampling a Poisson distribution with parameter @@ -169,17 +142,6 @@ pub fn pois_gen(shape: &[usize], lambda: f64) -> Result, PoissonErro return Err(PoissonError::ShapeTooSmall); } - // let size = shape.iter().product(); - // let mut v = Vec::with_capacity(size); - - // (0..size).into_par_iter().map(|_i| { - // let mut rng = thread_rng(); - - // Poisson::new(lambda).unwrap().sample(&mut rng) - // }).collect_into_vec(&mut v); - - // let a = Array::from_shape_vec(shape, v).unwrap(); - let mut a = ArrayD::::from_elem(shape, lambda); a.par_mapv_inplace(|l| { let mut rng = thread_rng(); diff --git a/test.py b/test.py deleted file mode 100644 index 1c75c72..0000000 --- a/test.py +++ /dev/null @@ -1,20 +0,0 @@ -import python.rustfrc as r -import numpy as np -import time - -init_x = (np.ones((900, 700, 100))*24.31) -init_y = (np.ones((900, 700, 100))*30).astype(np.int32) -init_z = np.ones((900, 700, 50))*30 - - -# start = time.perf_counter() -# x = r.binom_split(init_x) -# end = time.perf_counter() -# print(str(end - start) + " s") -# -# -# start2 = time.perf_counter() -# rng = np.random.default_rng() -# y = rng.binomial(init_y, 0.5) -# end2 = time.perf_counter() -# print(str(end2 - start2) + " s") \ No newline at end of file diff --git a/test2.py b/test2.py deleted file mode 100644 index 4cd9091..0000000 --- a/test2.py +++ /dev/null @@ -1,18 +0,0 @@ -import numpy as np -import python.rustfrc as r - -rng = np.random.default_rng() -shp = (3000, 3000) -x = np.full(shp, 50+29j) -r_x = rng.poisson(lam=20, size=shp) -r_x3 = r.pois_gen(shp, 20) -r_x2 = r_x*0.5j -x += r_x*0.987 + r_x2 - - -def square_abs(fourier): - return np.power(np.abs(fourier), 2) - - -print(square_abs(x)) -print(r.sqr_abs(x.astype(np.complex64)))