linkcell 0.3.2__tar.gz → 0.3.4__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (80) hide show
  1. linkcell-0.3.4/.github/scripts/setup-msvc.ps1 +31 -0
  2. linkcell-0.3.4/.github/workflows/ci.yml +230 -0
  3. linkcell-0.3.4/.github/workflows/publish.yml +25 -0
  4. {linkcell-0.3.2 → linkcell-0.3.4}/.github/workflows/wheels.yml +44 -24
  5. {linkcell-0.3.2 → linkcell-0.3.4}/.gitignore +2 -0
  6. linkcell-0.3.4/CHANGELOG.md +121 -0
  7. {linkcell-0.3.2 → linkcell-0.3.4}/CITATION.cff +1 -1
  8. {linkcell-0.3.2 → linkcell-0.3.4}/CMakeLists.txt +60 -3
  9. {linkcell-0.3.2 → linkcell-0.3.4}/Cargo.lock +9 -2
  10. {linkcell-0.3.2 → linkcell-0.3.4}/Cargo.toml +2 -1
  11. {linkcell-0.3.2 → linkcell-0.3.4}/PKG-INFO +32 -11
  12. {linkcell-0.3.2 → linkcell-0.3.4}/README.md +30 -10
  13. linkcell-0.3.4/changelog.d/.gitkeep +0 -0
  14. linkcell-0.3.4/changelog.d/README.md +15 -0
  15. linkcell-0.3.4/cmake/linkcell-gpu.pc.in +12 -0
  16. {linkcell-0.3.2 → linkcell-0.3.4}/cmake/linkcellConfig.cmake.in +22 -0
  17. {linkcell-0.3.2 → linkcell-0.3.4}/docs/how-to/embed-c.md +13 -3
  18. {linkcell-0.3.2 → linkcell-0.3.4}/docs/how-to/embed-cpp.md +13 -10
  19. {linkcell-0.3.2 → linkcell-0.3.4}/docs/how-to/embed-python.md +4 -4
  20. linkcell-0.3.4/docs/how-to/pkg-config.md +41 -0
  21. {linkcell-0.3.2 → linkcell-0.3.4}/docs/reference/algorithm.md +5 -2
  22. {linkcell-0.3.2 → linkcell-0.3.4}/docs/reference/c-api.md +1 -1
  23. {linkcell-0.3.2 → linkcell-0.3.4}/examples/meson.build +2 -1
  24. {linkcell-0.3.2 → linkcell-0.3.4}/include/linkcell.hpp +5 -1
  25. {linkcell-0.3.2 → linkcell-0.3.4}/include/linkcell_gpu.h +3 -2
  26. {linkcell-0.3.2 → linkcell-0.3.4}/include/linkcell_gpu.hpp +1 -1
  27. {linkcell-0.3.2 → linkcell-0.3.4}/meson.build +81 -39
  28. {linkcell-0.3.2 → linkcell-0.3.4}/pyproject.toml +4 -3
  29. {linkcell-0.3.2 → linkcell-0.3.4}/python/Cargo.toml +2 -1
  30. {linkcell-0.3.2 → linkcell-0.3.4}/python/build.rs +10 -5
  31. {linkcell-0.3.2 → linkcell-0.3.4}/python/src/gpu.rs +98 -5
  32. {linkcell-0.3.2 → linkcell-0.3.4}/python/src/lib.rs +6 -7
  33. {linkcell-0.3.2 → linkcell-0.3.4}/scripts/check-install.sh +38 -4
  34. linkcell-0.3.4/scripts/copy-cargo-artifacts.py +65 -0
  35. linkcell-0.3.4/src/cell.rs +8 -0
  36. {linkcell-0.3.2 → linkcell-0.3.4}/src/error.rs +16 -0
  37. {linkcell-0.3.2 → linkcell-0.3.4}/src/gpu/capi.cpp +1 -1
  38. linkcell-0.3.4/src/gpu/gpulite_compat.hpp +10 -0
  39. {linkcell-0.3.2 → linkcell-0.3.4}/src/gpu/knearest.cpp +12 -12
  40. {linkcell-0.3.2 → linkcell-0.3.4}/src/knearest.rs +4 -19
  41. {linkcell-0.3.2 → linkcell-0.3.4}/src/lib.rs +4 -1
  42. linkcell-0.3.4/src/pairs.rs +244 -0
  43. {linkcell-0.3.2 → linkcell-0.3.4}/tests/agree.rs +46 -0
  44. linkcell-0.3.4/tests/cmake-consumer/CMakeLists.txt +29 -0
  45. linkcell-0.3.4/tests/cmake-consumer/gpu.cpp +6 -0
  46. {linkcell-0.3.2 → linkcell-0.3.4}/tests/gpu_agree.cpp +1 -1
  47. linkcell-0.3.4/tests/python/test_agree_vesin.py +133 -0
  48. {linkcell-0.3.2 → linkcell-0.3.4}/tests/python/test_knearest.py +1 -1
  49. {linkcell-0.3.2 → linkcell-0.3.4}/tests/python/test_knearest_cuda.py +14 -0
  50. {linkcell-0.3.2 → linkcell-0.3.4}/third_party/gpulite/gpulite/gpulite.hpp +6 -1
  51. linkcell-0.3.4/towncrier.toml +40 -0
  52. linkcell-0.3.2/.github/workflows/ci.yml +0 -163
  53. linkcell-0.3.2/CHANGELOG.md +0 -108
  54. linkcell-0.3.2/docs/how-to/pkg-config.md +0 -39
  55. linkcell-0.3.2/src/cell.rs +0 -422
  56. linkcell-0.3.2/tests/cmake-consumer/CMakeLists.txt +0 -12
  57. {linkcell-0.3.2 → linkcell-0.3.4}/LICENSE +0 -0
  58. {linkcell-0.3.2 → linkcell-0.3.4}/assets/branding/README.md +0 -0
  59. {linkcell-0.3.2 → linkcell-0.3.4}/assets/branding/linkcell-icon.svg +0 -0
  60. {linkcell-0.3.2 → linkcell-0.3.4}/assets/branding/linkcell-logo-dark.svg +0 -0
  61. {linkcell-0.3.2 → linkcell-0.3.4}/assets/branding/linkcell-logo-light.svg +0 -0
  62. {linkcell-0.3.2 → linkcell-0.3.4}/assets/branding/linkcell-mark.jpg +0 -0
  63. {linkcell-0.3.2 → linkcell-0.3.4}/cbindgen.toml +0 -0
  64. {linkcell-0.3.2 → linkcell-0.3.4}/cmake/linkcell.pc.in +0 -0
  65. {linkcell-0.3.2 → linkcell-0.3.4}/docs/explanation/mic-and-cells.md +0 -0
  66. {linkcell-0.3.2 → linkcell-0.3.4}/docs/index.md +0 -0
  67. {linkcell-0.3.2 → linkcell-0.3.4}/docs/tutorials/two-points.md +0 -0
  68. {linkcell-0.3.2 → linkcell-0.3.4}/examples/knn_hot.rs +0 -0
  69. {linkcell-0.3.2 → linkcell-0.3.4}/examples/two_points.c +0 -0
  70. {linkcell-0.3.2 → linkcell-0.3.4}/examples/two_points.cpp +0 -0
  71. {linkcell-0.3.2 → linkcell-0.3.4}/include/linkcell.h +0 -0
  72. {linkcell-0.3.2 → linkcell-0.3.4}/linkcell/__init__.py +0 -0
  73. {linkcell-0.3.2 → linkcell-0.3.4}/meson_options.txt +0 -0
  74. {linkcell-0.3.2 → linkcell-0.3.4}/scripts/regen-capi-headers.sh +0 -0
  75. {linkcell-0.3.2 → linkcell-0.3.4}/src/capi.rs +0 -0
  76. {linkcell-0.3.2 → linkcell-0.3.4}/subprojects/gpulite.wrap +0 -0
  77. {linkcell-0.3.2 → linkcell-0.3.4}/subprojects/packagefiles/gpulite/meson.build +0 -0
  78. {linkcell-0.3.2 → linkcell-0.3.4}/tests/abi.rs +0 -0
  79. {linkcell-0.3.2 → linkcell-0.3.4}/third_party/gpulite/LICENSE +0 -0
  80. {linkcell-0.3.2 → linkcell-0.3.4}/third_party/gpulite/README.md +0 -0
@@ -0,0 +1,31 @@
1
+ Set-StrictMode -Version Latest
2
+ $ErrorActionPreference = "Stop"
3
+
4
+ $environmentBefore = @{}
5
+ Get-ChildItem Env: | ForEach-Object {
6
+ $environmentBefore[$_.Name] = $_.Value
7
+ }
8
+
9
+ $vswhere = Join-Path ${env:ProgramFiles(x86)} `
10
+ "Microsoft Visual Studio\Installer\vswhere.exe"
11
+ $installationPath = & $vswhere -latest -products * `
12
+ -requires Microsoft.VisualStudio.Component.VC.Tools.x86.x64 `
13
+ -property installationPath
14
+ $installationPath = [string]($installationPath | Select-Object -First 1)
15
+ if ([string]::IsNullOrWhiteSpace($installationPath)) {
16
+ throw "Visual Studio C++ tools not found"
17
+ }
18
+
19
+ $developerShell = Join-Path $installationPath `
20
+ "Common7\Tools\Launch-VsDevShell.ps1"
21
+ & $developerShell -Arch amd64 -HostArch amd64 -SkipAutomaticLocation
22
+
23
+ Get-ChildItem Env: | Where-Object {
24
+ -not $environmentBefore.ContainsKey($_.Name) -or
25
+ $environmentBefore[$_.Name] -ne $_.Value
26
+ } | ForEach-Object {
27
+ $delimiter = "DSEAMS_$([guid]::NewGuid().ToString('N'))"
28
+ Add-Content -Path $env:GITHUB_ENV -Value "$($_.Name)<<$delimiter"
29
+ Add-Content -Path $env:GITHUB_ENV -Value $_.Value
30
+ Add-Content -Path $env:GITHUB_ENV -Value $delimiter
31
+ }
@@ -0,0 +1,230 @@
1
+ name: ci
2
+
3
+ on:
4
+ push:
5
+ branches: [main]
6
+ tags: ['v*']
7
+ pull_request:
8
+
9
+ jobs:
10
+ fmt:
11
+ runs-on: ubuntu-latest
12
+ steps:
13
+ - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
14
+ - uses: dtolnay/rust-toolchain@4360b52568e2003a75bf9bc1d59f33a8e3fc893c # stable
15
+ with:
16
+ components: rustfmt
17
+ - run: cargo fmt --check
18
+
19
+ header-check:
20
+ runs-on: ubuntu-latest
21
+ steps:
22
+ - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
23
+ - uses: dtolnay/rust-toolchain@4360b52568e2003a75bf9bc1d59f33a8e3fc893c # stable
24
+ # Pin matches the version comment cbindgen writes into include/linkcell.h.
25
+ - run: cargo install cbindgen --version 0.29.4
26
+ - run: scripts/regen-capi-headers.sh --check
27
+
28
+ python:
29
+ runs-on: ubuntu-latest
30
+ steps:
31
+ - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
32
+ - uses: dtolnay/rust-toolchain@4360b52568e2003a75bf9bc1d59f33a8e3fc893c # stable
33
+ - uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.0
34
+ with:
35
+ python-version: '3.12'
36
+ - uses: actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0
37
+ with:
38
+ path: |
39
+ ~/.cargo/registry
40
+ ~/.cargo/git
41
+ key: ${{ runner.os }}-py-${{ hashFiles('Cargo.lock', 'python/Cargo.toml') }}
42
+ restore-keys: |
43
+ ${{ runner.os }}-py-
44
+ - name: Install Python test deps
45
+ run: |
46
+ python -m venv .venv
47
+ . .venv/bin/activate
48
+ python -m pip install --upgrade pip
49
+ pip install maturin pytest numpy
50
+ pip install torch --index-url https://download.pytorch.org/whl/cpu
51
+ - name: maturin develop
52
+ run: |
53
+ . .venv/bin/activate
54
+ maturin develop
55
+ - name: pytest
56
+ run: |
57
+ . .venv/bin/activate
58
+ pytest tests/python -q
59
+
60
+ cargo:
61
+ strategy:
62
+ fail-fast: false
63
+ matrix:
64
+ os: [ubuntu-latest, macos-latest, windows-latest]
65
+ crate:
66
+ - name: default
67
+ flags: ""
68
+ - name: serial
69
+ flags: --no-default-features --features capi
70
+ name: cargo (${{ matrix.os }}, ${{ matrix.crate.name }})
71
+ runs-on: ${{ matrix.os }}
72
+ steps:
73
+ - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
74
+ - uses: dtolnay/rust-toolchain@4360b52568e2003a75bf9bc1d59f33a8e3fc893c # stable
75
+ with:
76
+ components: clippy
77
+ - uses: actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0
78
+ with:
79
+ path: |
80
+ ~/.cargo/registry
81
+ ~/.cargo/git
82
+ key: ${{ runner.os }}-cargo-${{ hashFiles('Cargo.lock') }}
83
+ restore-keys: |
84
+ ${{ runner.os }}-cargo-
85
+ - run: cargo test --locked ${{ matrix.crate.flags }}
86
+ - run: cargo clippy --locked --all-targets ${{ matrix.crate.flags }} -- -D warnings
87
+
88
+ meson:
89
+ strategy:
90
+ fail-fast: false
91
+ matrix:
92
+ os: [ubuntu-latest, macos-latest, windows-latest]
93
+ name: meson (${{ matrix.os }})
94
+ runs-on: ${{ matrix.os }}
95
+ steps:
96
+ - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
97
+ - uses: dtolnay/rust-toolchain@4360b52568e2003a75bf9bc1d59f33a8e3fc893c # stable
98
+ - name: Configure MSVC
99
+ if: runner.os == 'Windows'
100
+ shell: pwsh
101
+ run: .github/scripts/setup-msvc.ps1
102
+ - uses: actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0
103
+ with:
104
+ path: |
105
+ ~/.cargo/registry
106
+ ~/.cargo/git
107
+ key: ${{ runner.os }}-cargo-${{ hashFiles('Cargo.lock') }}
108
+ restore-keys: |
109
+ ${{ runner.os }}-cargo-
110
+ - uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.0
111
+ with:
112
+ python-version: '3.12'
113
+ - run: pip install meson ninja
114
+ - name: Meson setup
115
+ if: runner.os != 'Windows'
116
+ run: meson setup build --prefix "$PWD/prefix" --libdir lib
117
+ shell: bash
118
+ - name: Meson setup
119
+ if: runner.os == 'Windows'
120
+ run: meson setup build --prefix "$env:GITHUB_WORKSPACE/prefix" --libdir lib
121
+ shell: pwsh
122
+ - run: meson compile -C build
123
+ - run: meson test -C build --print-errorlogs
124
+ - run: meson install -C build
125
+ - name: Installed headers and libraries
126
+ shell: bash
127
+ run: |
128
+ prefix="$PWD/prefix"
129
+ test -f "$prefix/include/linkcell.h"
130
+ test -f "$prefix/include/linkcell.hpp"
131
+ test -f "$prefix/include/linkcell_gpu.h"
132
+ test -f "$prefix/include/linkcell_gpu.hpp"
133
+ case "$RUNNER_OS" in
134
+ Windows)
135
+ test -f "$prefix/bin/linkcell.dll"
136
+ test -f "$prefix/lib/linkcell.dll.lib"
137
+ test -f "$prefix/lib/linkcell.lib"
138
+ test -f "$prefix/lib/linkcell_gpu.lib"
139
+ ;;
140
+ macOS)
141
+ test -f "$prefix/lib/liblinkcell.dylib"
142
+ test -f "$prefix/lib/liblinkcell.a"
143
+ test -f "$prefix/lib/liblinkcell_gpu.a"
144
+ ;;
145
+ Linux)
146
+ test -f "$prefix/lib/liblinkcell.so"
147
+ test -f "$prefix/lib/liblinkcell.a"
148
+ test -f "$prefix/lib/liblinkcell_gpu.a"
149
+ ;;
150
+ esac
151
+ - name: pkg-config after meson install
152
+ if: runner.os != 'Windows'
153
+ run: |
154
+ prefix="$PWD/prefix"
155
+ export PKG_CONFIG_PATH="$prefix/lib/pkgconfig"
156
+ pkg-config --exists --print-errors linkcell
157
+ pkg-config --modversion linkcell
158
+ pkg-config --cflags --libs linkcell
159
+ pkg-config --exists --print-errors linkcell-gpu
160
+ pkg-config --modversion linkcell-gpu
161
+ c++ -std=c++17 tests/cmake-consumer/gpu.cpp \
162
+ $(pkg-config --cflags --libs linkcell-gpu) \
163
+ -o build/installed-gpu-consumer
164
+
165
+ cmake:
166
+ strategy:
167
+ fail-fast: false
168
+ matrix:
169
+ os: [ubuntu-latest, macos-latest, windows-latest]
170
+ name: cmake (${{ matrix.os }})
171
+ runs-on: ${{ matrix.os }}
172
+ steps:
173
+ - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
174
+ - uses: dtolnay/rust-toolchain@4360b52568e2003a75bf9bc1d59f33a8e3fc893c # stable
175
+ - name: Configure MSVC
176
+ if: runner.os == 'Windows'
177
+ shell: pwsh
178
+ run: .github/scripts/setup-msvc.ps1
179
+ - uses: actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0
180
+ with:
181
+ path: |
182
+ ~/.cargo/registry
183
+ ~/.cargo/git
184
+ key: ${{ runner.os }}-cargo-${{ hashFiles('Cargo.lock') }}
185
+ restore-keys: |
186
+ ${{ runner.os }}-cargo-
187
+ - run: cmake -S . -B build -DCMAKE_INSTALL_PREFIX="$PWD/prefix"
188
+ shell: bash
189
+ - run: cmake --build build --config Release
190
+ - run: ctest --test-dir build -C Release --output-on-failure
191
+ - run: cmake --install build --config Release
192
+ - name: find_package after cmake install
193
+ shell: bash
194
+ run: |
195
+ test -f prefix/include/linkcell.h
196
+ test -f prefix/lib/cmake/linkcell/linkcellConfig.cmake
197
+ if [[ "$RUNNER_OS" == "Windows" ]]; then
198
+ test -f prefix/bin/linkcell.dll
199
+ test -f prefix/lib/linkcell.dll.lib
200
+ test -f prefix/lib/linkcell.lib
201
+ test -f prefix/lib/linkcell_gpu.lib
202
+ elif [[ "$RUNNER_OS" == "macOS" ]]; then
203
+ test -f prefix/lib/liblinkcell.dylib
204
+ test -f prefix/lib/liblinkcell.a
205
+ test -f prefix/lib/liblinkcell_gpu.a
206
+ else
207
+ test -f prefix/lib/liblinkcell.so
208
+ test -f prefix/lib/liblinkcell.a
209
+ test -f prefix/lib/liblinkcell_gpu.a
210
+ fi
211
+ cmake -S tests/cmake-consumer -B find-build \
212
+ -DCMAKE_PREFIX_PATH="$PWD/prefix" \
213
+ -DLINKCELL_C_EXAMPLE="$PWD/examples/two_points.c" \
214
+ -DLINKCELL_CPP_EXAMPLE="$PWD/examples/two_points.cpp"
215
+ cmake --build find-build --config Release
216
+ if [[ "$RUNNER_OS" == "Windows" ]]; then
217
+ export PATH="$PWD/prefix/bin:$PATH"
218
+ elif [[ "$RUNNER_OS" == "macOS" ]]; then
219
+ export DYLD_LIBRARY_PATH="$PWD/prefix/lib${DYLD_LIBRARY_PATH:+:$DYLD_LIBRARY_PATH}"
220
+ else
221
+ export LD_LIBRARY_PATH="$PWD/prefix/lib${LD_LIBRARY_PATH:+:$LD_LIBRARY_PATH}"
222
+ fi
223
+ ctest --test-dir find-build -C Release --output-on-failure
224
+ - name: pkg-config after cmake install
225
+ if: runner.os != 'Windows'
226
+ run: |
227
+ test -f prefix/lib/pkgconfig/linkcell.pc
228
+ export PKG_CONFIG_PATH="$PWD/prefix/lib/pkgconfig"
229
+ pkg-config --exists --print-errors linkcell
230
+ pkg-config --modversion linkcell
@@ -0,0 +1,25 @@
1
+ name: publish
2
+
3
+ on:
4
+ push:
5
+ tags: ["v*"]
6
+ workflow_dispatch:
7
+
8
+ permissions:
9
+ contents: read
10
+
11
+ jobs:
12
+ publish:
13
+ runs-on: ubuntu-latest
14
+ permissions:
15
+ contents: read
16
+ id-token: write
17
+ steps:
18
+ - uses: actions/checkout@v6
19
+ - uses: dtolnay/rust-toolchain@stable
20
+ - uses: rust-lang/crates-io-auth-action@v1.0.5
21
+ id: auth
22
+ - name: Publish linkcell
23
+ env:
24
+ CARGO_REGISTRY_TOKEN: ${{ steps.auth.outputs.token }}
25
+ run: cargo publish --no-verify -p linkcell
@@ -2,6 +2,7 @@ name: wheels
2
2
 
3
3
  on:
4
4
  push:
5
+ branches: [main]
5
6
  tags: ["v*"]
6
7
  pull_request:
7
8
  paths:
@@ -37,14 +38,18 @@ jobs:
37
38
  - name: macos-arm64
38
39
  os: macos-latest
39
40
  arch: arm64
41
+ - name: windows-x86_64
42
+ os: windows-latest
43
+ arch: AMD64
40
44
  steps:
41
- - uses: actions/checkout@v4
42
- - uses: dtolnay/rust-toolchain@stable
43
- - uses: astral-sh/setup-uv@v5
45
+ - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
46
+ - uses: dtolnay/rust-toolchain@4360b52568e2003a75bf9bc1d59f33a8e3fc893c # stable
47
+ - uses: astral-sh/setup-uv@20cfd1bf945f4377ade1205e4dbc17946fc9a30d # v10.0.1
44
48
  with:
45
49
  python-version: "3.12"
50
+ cache-suffix: abi3-${{ matrix.arch }}
46
51
  - name: Build abi3 wheel
47
- run: uvx --from 'cibuildwheel>=3.2,<4' cibuildwheel --output-dir wheelhouse
52
+ run: uvx --from 'cibuildwheel>=4,<5' cibuildwheel --output-dir wheelhouse
48
53
  env:
49
54
  CIBW_BUILD: "cp312-*"
50
55
  CIBW_SKIP: "*musllinux* *i686* cp3??t-*"
@@ -52,14 +57,16 @@ jobs:
52
57
  CIBW_ENVIRONMENT: MATURIN_PEP517_ARGS="--features abi3"
53
58
  CIBW_TEST_REQUIRES: pytest numpy
54
59
  CIBW_TEST_COMMAND: pytest {project}/tests/python -q
55
- - uses: actions/upload-artifact@v4
60
+ - uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
56
61
  with:
57
62
  name: wheels-abi3-${{ matrix.name }}
58
63
  path: ./wheelhouse/*.whl
59
64
 
60
- # Free-threaded set: one wheel per CPython t ABI (no limited API).
61
- freethreaded:
62
- name: freethreaded ${{ matrix.name }}
65
+ # One abi3t wheel per platform (CPython 3.15+ GIL and free-threaded).
66
+ # abi3audit --strict still treats PEP 793 PyModExport / PyType_FromSlots
67
+ # as non-abi3, so the audit step is off for this job only.
68
+ abi3t:
69
+ name: abi3t ${{ matrix.name }}
63
70
  runs-on: ${{ matrix.os }}
64
71
  strategy:
65
72
  fail-fast: false
@@ -74,37 +81,50 @@ jobs:
74
81
  - name: macos-arm64
75
82
  os: macos-latest
76
83
  arch: arm64
84
+ - name: windows-x86_64
85
+ os: windows-latest
86
+ arch: AMD64
77
87
  steps:
78
- - uses: actions/checkout@v4
79
- - uses: dtolnay/rust-toolchain@stable
80
- - uses: astral-sh/setup-uv@v5
88
+ - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
89
+ - uses: dtolnay/rust-toolchain@4360b52568e2003a75bf9bc1d59f33a8e3fc893c # stable
90
+ - uses: astral-sh/setup-uv@20cfd1bf945f4377ade1205e4dbc17946fc9a30d # v10.0.1
81
91
  with:
82
- python-version: "3.13"
83
- - name: Build free-threaded wheels
84
- run: uvx --from 'cibuildwheel>=3.2,<4' cibuildwheel --output-dir wheelhouse
92
+ python-version: "3.15"
93
+ cache-suffix: abi3t-${{ matrix.arch }}
94
+ - name: Build abi3t wheel
95
+ run: uvx --from 'cibuildwheel>=4,<5' cibuildwheel --output-dir wheelhouse
85
96
  env:
86
- CIBW_BUILD: "cp314t-*"
87
- CIBW_SKIP: "*musllinux* *i686*"
97
+ CIBW_BUILD: "cp315-*"
98
+ CIBW_SKIP: "*musllinux* *i686* cp3??t-*"
88
99
  CIBW_ARCHS: ${{ matrix.arch }}
100
+ CIBW_ENVIRONMENT: MATURIN_PEP517_ARGS="--features abi3t"
101
+ CIBW_AUDIT_COMMAND: ""
89
102
  CIBW_TEST_REQUIRES: pytest numpy
90
103
  CIBW_TEST_COMMAND: pytest {project}/tests/python -q
91
- - uses: actions/upload-artifact@v4
104
+ - uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
92
105
  with:
93
- name: wheels-freethreaded-${{ matrix.name }}
106
+ name: wheels-abi3t-${{ matrix.name }}
94
107
  path: ./wheelhouse/*.whl
95
108
 
96
109
  sdist:
97
110
  name: Source distribution
98
111
  runs-on: ubuntu-latest
99
112
  steps:
100
- - uses: actions/checkout@v4
101
- - uses: dtolnay/rust-toolchain@stable
102
- - uses: astral-sh/setup-uv@v5
113
+ - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
114
+ - uses: dtolnay/rust-toolchain@4360b52568e2003a75bf9bc1d59f33a8e3fc893c # stable
115
+ - uses: astral-sh/setup-uv@20cfd1bf945f4377ade1205e4dbc17946fc9a30d # v10.0.1
103
116
  with:
104
117
  python-version: "3.12"
118
+ cache-suffix: sdist
105
119
  - name: Build sdist
106
120
  run: uvx maturin sdist --out dist
107
- - uses: actions/upload-artifact@v4
121
+ - name: Test installed sdist
122
+ run: |
123
+ uv venv --clear .sdist-venv
124
+ uv pip install --python .sdist-venv/bin/python dist/*.tar.gz pytest numpy
125
+ .sdist-venv/bin/python -I -c "import linkcell; print(linkcell.__file__)"
126
+ .sdist-venv/bin/python -I -m pytest --import-mode=importlib "$PWD/tests/python" -q
127
+ - uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
108
128
  with:
109
129
  name: sdist
110
130
  path: dist/*.tar.gz
@@ -114,7 +134,7 @@ jobs:
114
134
  # on this job.
115
135
  publish:
116
136
  name: Publish to PyPI
117
- needs: [abi3, freethreaded, sdist]
137
+ needs: [abi3, abi3t, sdist]
118
138
  runs-on: ubuntu-latest
119
139
  if: >-
120
140
  github.repository == 'd-SEAMS/linkcell' &&
@@ -124,7 +144,7 @@ jobs:
124
144
  id-token: write
125
145
  contents: read
126
146
  steps:
127
- - uses: actions/download-artifact@v4
147
+ - uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
128
148
  with:
129
149
  path: dist
130
150
  merge-multiple: true
@@ -30,6 +30,8 @@ rustc-ice-*.txt
30
30
 
31
31
  # Prerequisites
32
32
  *.d
33
+ !changelog.d/
34
+ !changelog.d/**
33
35
 
34
36
  # Compiled Object files
35
37
  *.slo
@@ -0,0 +1,121 @@
1
+ # Changelog
2
+
3
+ All notable changes to this project are documented in this file.
4
+
5
+ The format is [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
6
+ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
+
8
+ Unreleased notes live in [`changelog.d/`](changelog.d/) and are assembled
9
+ by [towncrier](https://towncrier.readthedocs.io/).
10
+
11
+ <!-- towncrier release notes start -->
12
+
13
+ ## [0.3.4] - 2026-09-27
14
+
15
+ ### Added
16
+
17
+ - `pairs_within` returns every atom-image pair inside a cutoff with integer cell shift `S`. `knearest` still unique-indexes. Image stencils above 2^24 fail closed.
18
+
19
+ ### Changed
20
+
21
+ - `knearest_brute` ranks with `Cell::dist2_euclidean` (Smith then Minkowski 27-image).
22
+ - The crate depends on minimage 0.1.2 from crates.io.
23
+ - CHANGELOG.md follows Keep a Changelog. Unreleased notes are changelog.d fragments assembled by towncrier.
24
+
25
+ ### Fixed
26
+
27
+ - The MSVC build defines `NOMINMAX` before `windows.h` and calls `(std::min)` / `(std::max)`, so those names are not macros. The header includes `<cassert>` and `<optional>` itself. MSVC does not provide those through the other standard headers.
28
+
29
+ ## [0.3.3] - 2026-08-17
30
+
31
+ ### Changed
32
+
33
+ - Two wheels: `abi3-py312` (GIL, CPython 3.12+) and `abi3t-py315` (PEP 803, CPython 3.15 GIL and free-threaded). cibuildwheel 4.x builds 3.15.0rc1 by default. PyO3 0.29 `abi3t-py315`; maturin 1.14+ tags the `abi3t` ABI. The 0.3.2 `cp314t` set is gone. cibuildwheel's abi3audit step is off for the abi3t job: current abi3audit flags PEP 793 `PyModExport` and `PyType_FromSlots`.
34
+
35
+ ## [0.3.2] - 2026-08-17
36
+
37
+ ### Changed
38
+
39
+ - Python `linkcell` module (maturin / PyO3). Arrays are DLPack via dlpk: any `__dlpack__()` object in, `(indices, dist2)` out. `xyz` may be `(n, 3)` or `(n_frames, n, 3)`. `cell` is a DLPack tensor on any device. A CUDA cell is inverted on device; the host reads only the four launch ints. Two wheels: CPython 3.12 limited ABI, and a free-threaded `cp314t` set. Both compile the gpulite device walk. CUDA `__dlpack__` tensors (`torch`) go to `lc_gpu_*` by device pointer; the result is a pair of CUDA DLPack capsules. `lc_knearest_d2` and `lc_knearest_many` write squared distances and a frame-major batch. `lc_gpu_*` is the C waist for the device `Workspace`. A `v*` tag on d-SEAMS/linkcell publishes the two wheel kinds and the sdist to PyPI (trusted publisher, no Actions environment).
40
+
41
+ ## [0.3.1] - 2026-08-16
42
+
43
+ ### Changed
44
+
45
+ - Device `Workspace` folds with `Hinv` and shifts with `na a + nb b + nc c`. Sheared cells use the host walk. `k <= 16`.
46
+
47
+ ## [0.3.0] - 2026-08-16
48
+
49
+ ### Changed
50
+
51
+ - Optional gpulite device path: `linkcell::gpu::Workspace::knearest_into` writes the same packed `n * k` indices as the host walk (fold, bin, Chebyshev shells). The device walk uses a tiled exclusive scan, a precomputed Chebyshev stencil, cell-major coordinates with an O(1) home slot, and `knearest_into_many` for a frame batch. Occupancy defaults to threads-per-particle 8 (HOOMD/vesin), overridable by `LINKCELL_TPP` and `LINKCELL_BLOCK`. Setup copies ride the workspace stream. Orthorhombic cells, `k <= 16`. Meson feature `with_gpulite`.
52
+
53
+ ## [0.2.4] - 2026-08-15
54
+
55
+ ### Changed
56
+
57
+ - A wrap consumer always links the static archive. The parent `default_library` does not change this option, so a shared default left `pydseams.yoda` needing `liblinkcell.so` at import time.
58
+
59
+ ## [0.2.3] - 2026-08-15
60
+
61
+ ### Changed
62
+
63
+ - A static `libyodaLib.a` no longer passes `liblinkcell.so` to `ar`. The Meson dependency attaches a generated header as the build-order edge, not both cargo outputs.
64
+
65
+ ## [0.2.2] - 2026-08-15
66
+
67
+ ### Changed
68
+
69
+ - The crate is `d-SEAMS/linkcell`. `HaoZeke/linkcell` redirects.
70
+
71
+ ## [0.2.1] - 2026-08-15
72
+
73
+ ### Changed
74
+
75
+ - `Error::MaskLen` when `mask` is `Some` and `mask.len() != n`.
76
+ - `Error::Overflow` when `n * k` does not fit a slice. `BufferSize`
77
+ - remains a caller `out` whose length is not `n * k`.
78
+ - `lc_last_error` is written only by `lc_knearest`. `lc_version` does
79
+ - not clear the slot. An interior NUL in a message no longer drops the string to `NULL`.
80
+ - C++ `Neighbours` owns the packed `n * k` buffer. `knearest_into`
81
+ - takes `out_len`. There is no 5-argument `knearest(..., int *out)`.
82
+ - CI checks `include/linkcell.h` against cbindgen 0.29.4.
83
+ - Branding: sheared linked cells, k=4 neighbours, periodic wrap
84
+ - (`assets/branding/`).
85
+
86
+ ## [0.2.0] - 2026-08-15
87
+
88
+ ### Changed
89
+
90
+ - ABI break. Existing 0.1.x C and C++ callers must rebuild.
91
+ - `lc_knearest` takes `size_t n` and `size_t k`. The 0.1.x `int` counts
92
+ - overflowed on large frames.
93
+ - `lc_last_error` is thread-local. Concurrent searches no longer share
94
+ - one process-wide slot. `lc_version` stays process-static.
95
+ - C++ `linkcell::knearest` writes a packed `n * k` index buffer (unused
96
+ - slots `-1`) and returns a `Neighbours` view. It no longer returns `std::vector<std::vector<int>>`. Failure throws `linkcell::Error`.
97
+ - Rust `Error::Empty` is an empty point list only. A wrong-length
98
+ - `knearest_into` buffer is `Error::BufferSize`. An overflowing linked-cell mesh is `Error::TooManyCells`.
99
+ - The per-source k-set keeps one image of each neighbour (the
100
+ - nearest). The same particle visited through two wraps does not occupy two slots.
101
+ - `knearest_brute` on a sheared cell takes the 27-image minimum.
102
+ - The single parallelepiped wrap is not the Wigner-Seitz cell of a 60-degree hex prism.
103
+
104
+ ## [0.1.2] - 2026-08-15
105
+
106
+ ### Changed
107
+
108
+ - Fold once, then Cartesian pair distances plus a lattice shift (the vesin / LAMMPS ghost trick). Sources run in parallel. The C ABI writes indices into the caller buffer.
109
+
110
+ ## [0.1.1] - 2026-08-15
111
+
112
+ ### Changed
113
+
114
+ - Orthorhombic boxes use the three-wrap minimum image, not two 3x3 matvecs. The C ABI reads packed xyz in place. The k-heap for k <= 16 stays on the stack.
115
+
116
+ ## [0.1.0] - 2026-08-15
117
+
118
+ ### Changed
119
+
120
+ - Periodic linked-cell k-nearest neighbour search. Rust crate, C ABI (`lc_*`), C++ header. The cell is a general parallelepiped; orthorhombic boxes are `Cell::ortho` / `lc_cell_ortho`.
121
+ - Installable from Meson (`linkcell_dep`, `pkg.generate`), CMake (`find_package(linkcell)`, `linkcell::linkcell`), and pkg-config (`linkcell.pc`).
@@ -7,7 +7,7 @@ authors:
7
7
  given-names: Rohit
8
8
  orcid: https://orcid.org/0000-0002-2393-8056
9
9
  license: MIT
10
- version: 0.3.2
10
+ version: 0.3.3
11
11
  date-released: "2026-08-17"
12
12
  repository-code: "https://github.com/d-SEAMS/linkcell"
13
13
  url: "https://github.com/d-SEAMS/linkcell"
@@ -27,6 +27,7 @@ find_program(CARGO_EXECUTABLE cargo REQUIRED)
27
27
 
28
28
  option(LINKCELL_BUILD_EXAMPLES "Build C and C++ example programs" ON)
29
29
  option(LINKCELL_INSTALL "Install headers, libraries, pkg-config, and CMake package" ON)
30
+ option(LINKCELL_WITH_GPULITE "Build the device k-nearest C and C++ APIs" ON)
30
31
 
31
32
  if(WIN32)
32
33
  set(LINKCELL_SHARED_NAME linkcell.dll)
@@ -36,6 +37,8 @@ else()
36
37
  set(LINKCELL_SHARED_NAME "${CMAKE_SHARED_LIBRARY_PREFIX}linkcell${CMAKE_SHARED_LIBRARY_SUFFIX}")
37
38
  set(LINKCELL_STATIC_NAME "${CMAKE_STATIC_LIBRARY_PREFIX}linkcell${CMAKE_STATIC_LIBRARY_SUFFIX}")
38
39
  endif()
40
+ set(LINKCELL_GPU_STATIC_NAME
41
+ "${CMAKE_STATIC_LIBRARY_PREFIX}linkcell_gpu${CMAKE_STATIC_LIBRARY_SUFFIX}")
39
42
 
40
43
  set(LINKCELL_CARGO_DIR "${CMAKE_CURRENT_BINARY_DIR}/cargo-target")
41
44
  string(TOLOWER "${CMAKE_BUILD_TYPE}" _linkcell_build_type)
@@ -128,12 +131,43 @@ set_target_properties(linkcell_static PROPERTIES
128
131
  INTERFACE_LINK_LIBRARIES "${_linkcell_sys}"
129
132
  )
130
133
 
134
+ add_library(linkcell_cpp INTERFACE)
135
+ add_library(linkcell::cpp ALIAS linkcell_cpp)
136
+ target_link_libraries(linkcell_cpp INTERFACE linkcell::linkcell)
137
+ target_compile_features(linkcell_cpp INTERFACE cxx_std_17)
138
+
139
+ set(LINKCELL_GPU_SYSTEM_LIBS Threads::Threads)
140
+ if(CMAKE_DL_LIBS)
141
+ list(APPEND LINKCELL_GPU_SYSTEM_LIBS ${CMAKE_DL_LIBS})
142
+ endif()
143
+
144
+ if(LINKCELL_WITH_GPULITE)
145
+ add_library(linkcell_gpu STATIC
146
+ src/gpu/knearest.cpp
147
+ src/gpu/capi.cpp
148
+ )
149
+ add_library(linkcell::gpu ALIAS linkcell_gpu)
150
+ target_include_directories(linkcell_gpu
151
+ PUBLIC
152
+ "$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>"
153
+ "$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>"
154
+ PRIVATE
155
+ "${CMAKE_CURRENT_SOURCE_DIR}/third_party/gpulite"
156
+ )
157
+ target_compile_definitions(linkcell_gpu PUBLIC LINKCELL_HAS_GPULITE=1)
158
+ target_compile_features(linkcell_gpu PUBLIC cxx_std_17)
159
+ target_link_libraries(linkcell_gpu PUBLIC
160
+ linkcell::linkcell
161
+ ${LINKCELL_GPU_SYSTEM_LIBS}
162
+ )
163
+ endif()
164
+
131
165
  if(LINKCELL_BUILD_EXAMPLES)
132
166
  add_executable(two_points examples/two_points.c)
133
167
  target_link_libraries(two_points PRIVATE linkcell::linkcell)
134
168
  set_target_properties(two_points PROPERTIES BUILD_RPATH "${CMAKE_CURRENT_BINARY_DIR}")
135
169
  add_executable(two_points_cpp examples/two_points.cpp)
136
- target_link_libraries(two_points_cpp PRIVATE linkcell::linkcell)
170
+ target_link_libraries(two_points_cpp PRIVATE linkcell::cpp)
137
171
  set_target_properties(two_points_cpp PROPERTIES BUILD_RPATH "${CMAKE_CURRENT_BINARY_DIR}")
138
172
  enable_testing()
139
173
  add_test(NAME two-points-c COMMAND two_points)
@@ -150,10 +184,13 @@ endif()
150
184
  if(LINKCELL_INSTALL)
151
185
  if(UNIX AND NOT APPLE)
152
186
  set(LINKCELL_PKG_LIBS_PRIVATE "-ldl -lpthread -lm")
187
+ set(LINKCELL_GPU_PKG_LIBS "-ldl -lpthread")
153
188
  elseif(APPLE)
154
189
  set(LINKCELL_PKG_LIBS_PRIVATE "-lpthread -lm")
190
+ set(LINKCELL_GPU_PKG_LIBS "-lpthread")
155
191
  else()
156
192
  set(LINKCELL_PKG_LIBS_PRIVATE "")
193
+ set(LINKCELL_GPU_PKG_LIBS "")
157
194
  endif()
158
195
 
159
196
  configure_file(
@@ -161,6 +198,13 @@ if(LINKCELL_INSTALL)
161
198
  "${CMAKE_CURRENT_BINARY_DIR}/linkcell.pc"
162
199
  @ONLY
163
200
  )
201
+ if(LINKCELL_WITH_GPULITE)
202
+ configure_file(
203
+ "${CMAKE_CURRENT_SOURCE_DIR}/cmake/linkcell-gpu.pc.in"
204
+ "${CMAKE_CURRENT_BINARY_DIR}/linkcell-gpu.pc"
205
+ @ONLY
206
+ )
207
+ endif()
164
208
  configure_package_config_file(
165
209
  "${CMAKE_CURRENT_SOURCE_DIR}/cmake/linkcellConfig.cmake.in"
166
210
  "${CMAKE_CURRENT_BINARY_DIR}/linkcellConfig.cmake"
@@ -179,16 +223,29 @@ if(LINKCELL_INSTALL)
179
223
  install(FILES "${LINKCELL_SHARED}" DESTINATION "${CMAKE_INSTALL_LIBDIR}")
180
224
  endif()
181
225
  install(FILES "${LINKCELL_STATIC}" DESTINATION "${CMAKE_INSTALL_LIBDIR}")
226
+ if(LINKCELL_WITH_GPULITE)
227
+ install(TARGETS linkcell_gpu ARCHIVE DESTINATION "${CMAKE_INSTALL_LIBDIR}")
228
+ endif()
182
229
  install(FILES
183
230
  "${CMAKE_CURRENT_SOURCE_DIR}/include/linkcell.h"
184
231
  "${CMAKE_CURRENT_SOURCE_DIR}/include/linkcell.hpp"
185
- "${CMAKE_CURRENT_SOURCE_DIR}/include/linkcell_gpu.h"
186
- "${CMAKE_CURRENT_SOURCE_DIR}/include/linkcell_gpu.hpp"
187
232
  DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}"
188
233
  )
234
+ if(LINKCELL_WITH_GPULITE)
235
+ install(FILES
236
+ "${CMAKE_CURRENT_SOURCE_DIR}/include/linkcell_gpu.h"
237
+ "${CMAKE_CURRENT_SOURCE_DIR}/include/linkcell_gpu.hpp"
238
+ DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}"
239
+ )
240
+ endif()
189
241
  install(FILES "${CMAKE_CURRENT_BINARY_DIR}/linkcell.pc"
190
242
  DESTINATION "${CMAKE_INSTALL_LIBDIR}/pkgconfig"
191
243
  )
244
+ if(LINKCELL_WITH_GPULITE)
245
+ install(FILES "${CMAKE_CURRENT_BINARY_DIR}/linkcell-gpu.pc"
246
+ DESTINATION "${CMAKE_INSTALL_LIBDIR}/pkgconfig"
247
+ )
248
+ endif()
192
249
  install(FILES
193
250
  "${CMAKE_CURRENT_BINARY_DIR}/linkcellConfig.cmake"
194
251
  "${CMAKE_CURRENT_BINARY_DIR}/linkcellConfigVersion.cmake"