wavelet-matrix 2.0.7__tar.gz → 2.0.9__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.
- {wavelet_matrix-2.0.7 → wavelet_matrix-2.0.9}/.github/workflows/CI.yml +39 -40
- {wavelet_matrix-2.0.7 → wavelet_matrix-2.0.9}/Cargo.lock +9 -9
- {wavelet_matrix-2.0.7 → wavelet_matrix-2.0.9}/Cargo.toml +1 -1
- wavelet_matrix-2.0.9/PKG-INFO +212 -0
- wavelet_matrix-2.0.9/README.md +175 -0
- {wavelet_matrix-2.0.7 → wavelet_matrix-2.0.9}/docs/wavelet_matrix.html +146 -472
- {wavelet_matrix-2.0.7 → wavelet_matrix-2.0.9}/pyproject.toml +0 -4
- {wavelet_matrix-2.0.7 → wavelet_matrix-2.0.9}/src/dynamic_wavelet_matrix/dynamic_bit_vector.rs +2 -2
- {wavelet_matrix-2.0.7 → wavelet_matrix-2.0.9}/src/dynamic_wavelet_matrix/dynamic_wavelet_matrix.rs +18 -12
- {wavelet_matrix-2.0.7 → wavelet_matrix-2.0.9}/src/lib.rs +1 -0
- {wavelet_matrix-2.0.7 → wavelet_matrix-2.0.9}/src/python/dynamic_wavelet_matrix.rs +75 -221
- {wavelet_matrix-2.0.7 → wavelet_matrix-2.0.9}/src/python/wavelet_matrix.rs +63 -154
- {wavelet_matrix-2.0.7 → wavelet_matrix-2.0.9}/src/wavelet_matrix/bit_vector.rs +22 -6
- {wavelet_matrix-2.0.7 → wavelet_matrix-2.0.9}/src/wavelet_matrix/wavelet_matrix.rs +18 -12
- wavelet_matrix-2.0.7/PKG-INFO +0 -255
- wavelet_matrix-2.0.7/README.md +0 -214
- {wavelet_matrix-2.0.7 → wavelet_matrix-2.0.9}/.gitignore +0 -0
- {wavelet_matrix-2.0.7 → wavelet_matrix-2.0.9}/LICENSE +0 -0
- {wavelet_matrix-2.0.7 → wavelet_matrix-2.0.9}/benchmarks/__init__.py +0 -0
- {wavelet_matrix-2.0.7 → wavelet_matrix-2.0.9}/benchmarks/bench_dynamic_wavelet_matrix.py +0 -0
- {wavelet_matrix-2.0.7 → wavelet_matrix-2.0.9}/benchmarks/bench_wavelet_matrix.py +0 -0
- {wavelet_matrix-2.0.7 → wavelet_matrix-2.0.9}/docs/index.html +0 -0
- {wavelet_matrix-2.0.7 → wavelet_matrix-2.0.9}/src/dynamic_wavelet_matrix/mod.rs +0 -0
- {wavelet_matrix-2.0.7 → wavelet_matrix-2.0.9}/src/python/mod.rs +0 -0
- {wavelet_matrix-2.0.7 → wavelet_matrix-2.0.9}/src/traits/bit_vector/bit_vector.rs +0 -0
- {wavelet_matrix-2.0.7 → wavelet_matrix-2.0.9}/src/traits/bit_vector/dynamic_bit_vector.rs +0 -0
- {wavelet_matrix-2.0.7 → wavelet_matrix-2.0.9}/src/traits/bit_vector/mod.rs +0 -0
- {wavelet_matrix-2.0.7 → wavelet_matrix-2.0.9}/src/traits/mod.rs +0 -0
- {wavelet_matrix-2.0.7 → wavelet_matrix-2.0.9}/src/traits/utils/bit_select.rs +0 -0
- {wavelet_matrix-2.0.7 → wavelet_matrix-2.0.9}/src/traits/utils/bit_width.rs +0 -0
- {wavelet_matrix-2.0.7 → wavelet_matrix-2.0.9}/src/traits/utils/mod.rs +0 -0
- {wavelet_matrix-2.0.7 → wavelet_matrix-2.0.9}/src/traits/wavelet_matrix/dynamic_wavelet_matrix.rs +0 -0
- {wavelet_matrix-2.0.7 → wavelet_matrix-2.0.9}/src/traits/wavelet_matrix/mod.rs +0 -0
- {wavelet_matrix-2.0.7 → wavelet_matrix-2.0.9}/src/traits/wavelet_matrix/wavelet_matrix.rs +0 -0
- {wavelet_matrix-2.0.7 → wavelet_matrix-2.0.9}/src/wavelet_matrix/mod.rs +0 -0
- {wavelet_matrix-2.0.7 → wavelet_matrix-2.0.9}/tests/__init__.py +0 -0
- {wavelet_matrix-2.0.7 → wavelet_matrix-2.0.9}/tests/test_dynamic_wavelet_matrix.py +0 -0
- {wavelet_matrix-2.0.7 → wavelet_matrix-2.0.9}/tests/test_wavelet_matrix.py +0 -0
- {wavelet_matrix-2.0.7 → wavelet_matrix-2.0.9}/wavelet_matrix.pyi +0 -0
|
@@ -9,7 +9,6 @@ on:
|
|
|
9
9
|
push:
|
|
10
10
|
branches:
|
|
11
11
|
- main
|
|
12
|
-
- master
|
|
13
12
|
tags:
|
|
14
13
|
- '*'
|
|
15
14
|
pull_request:
|
|
@@ -25,21 +24,21 @@ jobs:
|
|
|
25
24
|
strategy:
|
|
26
25
|
matrix:
|
|
27
26
|
platform:
|
|
28
|
-
- runner: ubuntu-
|
|
27
|
+
- runner: ubuntu-latest
|
|
29
28
|
target: x86_64
|
|
30
|
-
- runner: ubuntu-
|
|
29
|
+
- runner: ubuntu-latest
|
|
31
30
|
target: x86
|
|
32
|
-
- runner: ubuntu-
|
|
31
|
+
- runner: ubuntu-latest
|
|
33
32
|
target: aarch64
|
|
34
|
-
- runner: ubuntu-
|
|
33
|
+
- runner: ubuntu-latest
|
|
35
34
|
target: armv7
|
|
36
|
-
- runner: ubuntu-
|
|
35
|
+
- runner: ubuntu-latest
|
|
37
36
|
target: s390x
|
|
38
|
-
- runner: ubuntu-
|
|
37
|
+
- runner: ubuntu-latest
|
|
39
38
|
target: ppc64le
|
|
40
39
|
steps:
|
|
41
|
-
- uses: actions/checkout@
|
|
42
|
-
- uses: actions/setup-python@
|
|
40
|
+
- uses: actions/checkout@v6
|
|
41
|
+
- uses: actions/setup-python@v6
|
|
43
42
|
with:
|
|
44
43
|
python-version: 3.x
|
|
45
44
|
- name: Build wheels
|
|
@@ -50,7 +49,7 @@ jobs:
|
|
|
50
49
|
sccache: ${{ !startsWith(github.ref, 'refs/tags/') }}
|
|
51
50
|
manylinux: auto
|
|
52
51
|
- name: Upload wheels
|
|
53
|
-
uses: actions/upload-artifact@
|
|
52
|
+
uses: actions/upload-artifact@v6
|
|
54
53
|
with:
|
|
55
54
|
name: wheels-linux-${{ matrix.platform.target }}
|
|
56
55
|
path: dist
|
|
@@ -61,17 +60,17 @@ jobs:
|
|
|
61
60
|
strategy:
|
|
62
61
|
matrix:
|
|
63
62
|
platform:
|
|
64
|
-
- runner: ubuntu-
|
|
63
|
+
- runner: ubuntu-latest
|
|
65
64
|
target: x86_64
|
|
66
|
-
- runner: ubuntu-
|
|
65
|
+
- runner: ubuntu-latest
|
|
67
66
|
target: x86
|
|
68
|
-
- runner: ubuntu-
|
|
67
|
+
- runner: ubuntu-latest
|
|
69
68
|
target: aarch64
|
|
70
|
-
- runner: ubuntu-
|
|
69
|
+
- runner: ubuntu-latest
|
|
71
70
|
target: armv7
|
|
72
71
|
steps:
|
|
73
|
-
- uses: actions/checkout@
|
|
74
|
-
- uses: actions/setup-python@
|
|
72
|
+
- uses: actions/checkout@v6
|
|
73
|
+
- uses: actions/setup-python@v6
|
|
75
74
|
with:
|
|
76
75
|
python-version: 3.x
|
|
77
76
|
- name: Build wheels
|
|
@@ -82,7 +81,7 @@ jobs:
|
|
|
82
81
|
sccache: ${{ !startsWith(github.ref, 'refs/tags/') }}
|
|
83
82
|
manylinux: musllinux_1_2
|
|
84
83
|
- name: Upload wheels
|
|
85
|
-
uses: actions/upload-artifact@
|
|
84
|
+
uses: actions/upload-artifact@v6
|
|
86
85
|
with:
|
|
87
86
|
name: wheels-musllinux-${{ matrix.platform.target }}
|
|
88
87
|
path: dist
|
|
@@ -98,8 +97,8 @@ jobs:
|
|
|
98
97
|
- runner: windows-latest
|
|
99
98
|
target: x86
|
|
100
99
|
steps:
|
|
101
|
-
- uses: actions/checkout@
|
|
102
|
-
- uses: actions/setup-python@
|
|
100
|
+
- uses: actions/checkout@v6
|
|
101
|
+
- uses: actions/setup-python@v6
|
|
103
102
|
with:
|
|
104
103
|
python-version: 3.x
|
|
105
104
|
architecture: ${{ matrix.platform.target }}
|
|
@@ -110,7 +109,7 @@ jobs:
|
|
|
110
109
|
args: --release --out dist --find-interpreter
|
|
111
110
|
sccache: ${{ !startsWith(github.ref, 'refs/tags/') }}
|
|
112
111
|
- name: Upload wheels
|
|
113
|
-
uses: actions/upload-artifact@
|
|
112
|
+
uses: actions/upload-artifact@v6
|
|
114
113
|
with:
|
|
115
114
|
name: wheels-windows-${{ matrix.platform.target }}
|
|
116
115
|
path: dist
|
|
@@ -121,13 +120,13 @@ jobs:
|
|
|
121
120
|
strategy:
|
|
122
121
|
matrix:
|
|
123
122
|
platform:
|
|
124
|
-
- runner: macos-
|
|
123
|
+
- runner: macos-latest
|
|
125
124
|
target: x86_64
|
|
126
|
-
- runner: macos-
|
|
125
|
+
- runner: macos-latest
|
|
127
126
|
target: aarch64
|
|
128
127
|
steps:
|
|
129
|
-
- uses: actions/checkout@
|
|
130
|
-
- uses: actions/setup-python@
|
|
128
|
+
- uses: actions/checkout@v6
|
|
129
|
+
- uses: actions/setup-python@v6
|
|
131
130
|
with:
|
|
132
131
|
python-version: 3.x
|
|
133
132
|
- name: Build wheels
|
|
@@ -137,7 +136,7 @@ jobs:
|
|
|
137
136
|
args: --release --out dist --find-interpreter
|
|
138
137
|
sccache: ${{ !startsWith(github.ref, 'refs/tags/') }}
|
|
139
138
|
- name: Upload wheels
|
|
140
|
-
uses: actions/upload-artifact@
|
|
139
|
+
uses: actions/upload-artifact@v6
|
|
141
140
|
with:
|
|
142
141
|
name: wheels-macos-${{ matrix.platform.target }}
|
|
143
142
|
path: dist
|
|
@@ -146,8 +145,8 @@ jobs:
|
|
|
146
145
|
needs: [cargo-test, python-test]
|
|
147
146
|
runs-on: ubuntu-latest
|
|
148
147
|
steps:
|
|
149
|
-
- uses: actions/checkout@
|
|
150
|
-
- uses: actions/setup-python@
|
|
148
|
+
- uses: actions/checkout@v6
|
|
149
|
+
- uses: actions/setup-python@v6
|
|
151
150
|
with:
|
|
152
151
|
python-version: 3.x
|
|
153
152
|
- name: Build sdist
|
|
@@ -156,15 +155,15 @@ jobs:
|
|
|
156
155
|
command: sdist
|
|
157
156
|
args: --out dist
|
|
158
157
|
- name: Upload sdist
|
|
159
|
-
uses: actions/upload-artifact@
|
|
158
|
+
uses: actions/upload-artifact@v6
|
|
160
159
|
with:
|
|
161
160
|
name: wheels-sdist
|
|
162
161
|
path: dist
|
|
163
162
|
|
|
164
163
|
cargo-test:
|
|
165
|
-
runs-on: ubuntu-
|
|
164
|
+
runs-on: ubuntu-latest
|
|
166
165
|
steps:
|
|
167
|
-
- uses: actions/checkout@
|
|
166
|
+
- uses: actions/checkout@v6
|
|
168
167
|
- uses: dtolnay/rust-toolchain@stable
|
|
169
168
|
with:
|
|
170
169
|
components: clippy
|
|
@@ -188,14 +187,14 @@ jobs:
|
|
|
188
187
|
token: ${{ secrets.CODECOV_TOKEN }}
|
|
189
188
|
|
|
190
189
|
python-test:
|
|
191
|
-
runs-on: ubuntu-
|
|
190
|
+
runs-on: ubuntu-latest
|
|
192
191
|
steps:
|
|
193
|
-
- uses: actions/checkout@
|
|
194
|
-
- uses: actions/setup-python@
|
|
192
|
+
- uses: actions/checkout@v6
|
|
193
|
+
- uses: actions/setup-python@v6
|
|
195
194
|
with:
|
|
196
195
|
python-version: 3.x
|
|
197
196
|
- name: Install packages
|
|
198
|
-
run: python -m pip install -e .[dev]
|
|
197
|
+
run: python -m pip install -e .[test,dev]
|
|
199
198
|
- name: Run tests
|
|
200
199
|
run: pytest --benchmark-skip
|
|
201
200
|
- name: Docs check
|
|
@@ -205,7 +204,7 @@ jobs:
|
|
|
205
204
|
--no-search \
|
|
206
205
|
--no-show-source \
|
|
207
206
|
--docformat markdown \
|
|
208
|
-
--footer-text "©
|
|
207
|
+
--footer-text "© 2026 Koki Watanabe"
|
|
209
208
|
if ! git diff --exit-code -- docs; then
|
|
210
209
|
echo "::error::Docs are out of date. Please run pdoc and commit generated docs."
|
|
211
210
|
exit 1
|
|
@@ -214,7 +213,7 @@ jobs:
|
|
|
214
213
|
run: ruff check
|
|
215
214
|
|
|
216
215
|
python-benchmark:
|
|
217
|
-
runs-on: ubuntu-
|
|
216
|
+
runs-on: ubuntu-latest
|
|
218
217
|
strategy:
|
|
219
218
|
fail-fast: false
|
|
220
219
|
matrix:
|
|
@@ -227,8 +226,8 @@ jobs:
|
|
|
227
226
|
- "3.14"
|
|
228
227
|
- "pypy3.11"
|
|
229
228
|
steps:
|
|
230
|
-
- uses: actions/checkout@
|
|
231
|
-
- uses: actions/setup-python@
|
|
229
|
+
- uses: actions/checkout@v6
|
|
230
|
+
- uses: actions/setup-python@v6
|
|
232
231
|
with:
|
|
233
232
|
python-version: ${{ matrix.python }}
|
|
234
233
|
- name: Install packages
|
|
@@ -251,9 +250,9 @@ jobs:
|
|
|
251
250
|
# Used to generate artifact attestation
|
|
252
251
|
attestations: write
|
|
253
252
|
steps:
|
|
254
|
-
- uses: actions/download-artifact@
|
|
253
|
+
- uses: actions/download-artifact@v7
|
|
255
254
|
- name: Generate artifact attestation
|
|
256
|
-
uses: actions/attest-build-provenance@
|
|
255
|
+
uses: actions/attest-build-provenance@v3
|
|
257
256
|
with:
|
|
258
257
|
subject-path: 'wheels-*/*'
|
|
259
258
|
- name: Publish to PyPI
|
|
@@ -25,9 +25,9 @@ dependencies = [
|
|
|
25
25
|
|
|
26
26
|
[[package]]
|
|
27
27
|
name = "libc"
|
|
28
|
-
version = "0.2.
|
|
28
|
+
version = "0.2.180"
|
|
29
29
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
30
|
-
checksum = "
|
|
30
|
+
checksum = "bcc35a38544a891a5f7c865aca548a982ccb3b8650a5b06d0fd33a10283c56fc"
|
|
31
31
|
|
|
32
32
|
[[package]]
|
|
33
33
|
name = "memoffset"
|
|
@@ -80,9 +80,9 @@ checksum = "f89776e4d69bb58bc6993e99ffa1d11f228b839984854c7daeb5d37f87cbe950"
|
|
|
80
80
|
|
|
81
81
|
[[package]]
|
|
82
82
|
name = "proc-macro2"
|
|
83
|
-
version = "1.0.
|
|
83
|
+
version = "1.0.105"
|
|
84
84
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
85
|
-
checksum = "
|
|
85
|
+
checksum = "535d180e0ecab6268a3e718bb9fd44db66bbbc256257165fc699dadf70d16fe7"
|
|
86
86
|
dependencies = [
|
|
87
87
|
"unicode-ident",
|
|
88
88
|
]
|
|
@@ -152,9 +152,9 @@ dependencies = [
|
|
|
152
152
|
|
|
153
153
|
[[package]]
|
|
154
154
|
name = "quote"
|
|
155
|
-
version = "1.0.
|
|
155
|
+
version = "1.0.43"
|
|
156
156
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
157
|
-
checksum = "
|
|
157
|
+
checksum = "dc74d9a594b72ae6656596548f56f667211f8a97b3d4c3d467150794690dc40a"
|
|
158
158
|
dependencies = [
|
|
159
159
|
"proc-macro2",
|
|
160
160
|
]
|
|
@@ -167,9 +167,9 @@ checksum = "b39cdef0fa800fc44525c84ccb54a029961a8215f9619753635a9c0d2538d46d"
|
|
|
167
167
|
|
|
168
168
|
[[package]]
|
|
169
169
|
name = "syn"
|
|
170
|
-
version = "2.0.
|
|
170
|
+
version = "2.0.114"
|
|
171
171
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
172
|
-
checksum = "
|
|
172
|
+
checksum = "d4d107df263a3013ef9b1879b0df87d706ff80f65a86ea879bd9c31f9b307c2a"
|
|
173
173
|
dependencies = [
|
|
174
174
|
"proc-macro2",
|
|
175
175
|
"quote",
|
|
@@ -196,7 +196,7 @@ checksum = "7264e107f553ccae879d21fbea1d6724ac785e8c3bfc762137959b5802826ef3"
|
|
|
196
196
|
|
|
197
197
|
[[package]]
|
|
198
198
|
name = "wavelet-matrix"
|
|
199
|
-
version = "2.0.
|
|
199
|
+
version = "2.0.9"
|
|
200
200
|
dependencies = [
|
|
201
201
|
"num-bigint",
|
|
202
202
|
"num-integer",
|
|
@@ -0,0 +1,212 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: wavelet-matrix
|
|
3
|
+
Version: 2.0.9
|
|
4
|
+
Classifier: Intended Audience :: Developers
|
|
5
|
+
Classifier: Intended Audience :: Science/Research
|
|
6
|
+
Classifier: Intended Audience :: Information Technology
|
|
7
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
8
|
+
Classifier: Programming Language :: Python :: 3
|
|
9
|
+
Classifier: Programming Language :: Python :: 3.9
|
|
10
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
11
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
12
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
13
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
14
|
+
Classifier: Programming Language :: Python :: 3.14
|
|
15
|
+
Classifier: Programming Language :: Python :: Implementation :: CPython
|
|
16
|
+
Classifier: Programming Language :: Python :: Implementation :: PyPy
|
|
17
|
+
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
18
|
+
Classifier: Topic :: Scientific/Engineering :: Information Analysis
|
|
19
|
+
Classifier: Topic :: Scientific/Engineering :: Mathematics
|
|
20
|
+
Classifier: Typing :: Typed
|
|
21
|
+
Requires-Dist: pdoc>=16.0 ; extra == 'dev'
|
|
22
|
+
Requires-Dist: ruff>=0.14 ; extra == 'dev'
|
|
23
|
+
Requires-Dist: pytest>=7.0 ; extra == 'test'
|
|
24
|
+
Requires-Dist: pytest-benchmark>=4.0 ; extra == 'test'
|
|
25
|
+
Provides-Extra: dev
|
|
26
|
+
Provides-Extra: test
|
|
27
|
+
License-File: LICENSE
|
|
28
|
+
Summary: High-performance indexed sequence data structure powered by Rust, supporting fast rank/select and range queries.
|
|
29
|
+
Keywords: wavelet matrix,data structure,algorithm,sequence index,rank,select,quantile,top-k,range query,dynamic update,indexing,succinct
|
|
30
|
+
Author: Koki Watanabe
|
|
31
|
+
Requires-Python: >=3.9
|
|
32
|
+
Description-Content-Type: text/markdown; charset=UTF-8; variant=GFM
|
|
33
|
+
Project-URL: documentation, https://math-hiyoko.github.io/wavelet-matrix
|
|
34
|
+
Project-URL: homepage, https://github.com/math-hiyoko/wavelet-matrix
|
|
35
|
+
Project-URL: repository, https://github.com/math-hiyoko/wavelet-matrix
|
|
36
|
+
|
|
37
|
+
# Wavelet Matrix
|
|
38
|
+
|
|
39
|
+
[](https://github.com/math-hiyoko/wavelet-matrix/actions/workflows/CI.yml)
|
|
40
|
+
[](https://codecov.io/gh/math-hiyoko/wavelet-matrix)
|
|
41
|
+

|
|
42
|
+

|
|
43
|
+

|
|
44
|
+

|
|
45
|
+

|
|
46
|
+
[](https://pepy.tech/projects/wavelet-matrix)
|
|
47
|
+

|
|
48
|
+

|
|
49
|
+

|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
High-performance Wavelet Matrix implementation powered by Rust,
|
|
53
|
+
supporting fast rank / select / range queries over indexed sequences
|
|
54
|
+
|
|
55
|
+
- PyPI: https://pypi.org/project/wavelet-matrix
|
|
56
|
+
- Document: https://math-hiyoko.github.io/wavelet-matrix
|
|
57
|
+
- Repository: https://github.com/math-hiyoko/wavelet-matrix
|
|
58
|
+
|
|
59
|
+
## Features:
|
|
60
|
+
- Fast rank, select, quantile
|
|
61
|
+
- Rich range queries (freq / sum / top-k / min / max)
|
|
62
|
+
- Optional dynamic updates (insert / remove / update)
|
|
63
|
+
- Safe Rust (no unsafe)
|
|
64
|
+
|
|
65
|
+
## Installation
|
|
66
|
+
```bash
|
|
67
|
+
pip install wavelet-matrix
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
## WaveletMatrix
|
|
71
|
+
WaveletMatrix indexes a static sequence of integers,
|
|
72
|
+
enabling fast queries where runtime depends on bit-width, not data size.
|
|
73
|
+
```python
|
|
74
|
+
from wavelet_matrix import WaveletMatrix
|
|
75
|
+
|
|
76
|
+
data = [5, 4, 5, 5, 2, 1, 5, 6, 1, 3, 5, 0]
|
|
77
|
+
wm = WaveletMatrix(data)
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
### Frequency Queries
|
|
81
|
+
#### Count occurrences (rank)
|
|
82
|
+
```python
|
|
83
|
+
wm.rank(value=5, end=9)
|
|
84
|
+
# 4
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
#### Find position (select)
|
|
88
|
+
```python
|
|
89
|
+
wm.select(value=5, kth=4)
|
|
90
|
+
# 6
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
### Order Statistics
|
|
94
|
+
#### k-th smallest value (quantile)
|
|
95
|
+
```python
|
|
96
|
+
wm.quantile(start=2, end=12, kth=8)
|
|
97
|
+
# 5
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
### Range Aggregation
|
|
101
|
+
#### Sum values (range_sum)
|
|
102
|
+
```python
|
|
103
|
+
wm.range_sum(start=2, end=8)
|
|
104
|
+
# 24
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
#### Count values in [lower, upper) (range_freq)
|
|
108
|
+
```python
|
|
109
|
+
wm.range_freq(start=1, end=9, lower=4, upper=6)
|
|
110
|
+
# 4
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
#### List values with counts (range_list)
|
|
114
|
+
```python
|
|
115
|
+
wm.range_list(start=1, end=9, lower=4, upper=6)
|
|
116
|
+
# [{'value': 4, 'count': 1}, {'value': 5, 'count': 3}]
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
### Top-K Queries
|
|
120
|
+
#### Most frequent values (topk)
|
|
121
|
+
```python
|
|
122
|
+
wm.topk(start=1, end=10, k=2)
|
|
123
|
+
# [{'value': 5, 'count': 3}, {'value': 1, 'count': 2}]
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
#### Extreme values (range_maxk / range_mink)
|
|
127
|
+
```python
|
|
128
|
+
wm.range_maxk(start=1, end=9, k=2)
|
|
129
|
+
# [{'value': 6, 'count': 1}, {'value': 5, 'count': 3}]
|
|
130
|
+
wm.range_mink(start=1, end=9, k=2)
|
|
131
|
+
# [{'value': 1, 'count': 2}, {'value': 2, 'count': 1}]
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
### Boundary Queries
|
|
135
|
+
```python
|
|
136
|
+
wm.prev_value(start=1, end=9, upper=7)
|
|
137
|
+
# 6
|
|
138
|
+
wm.next_value(start=1, end=9, lower=4)
|
|
139
|
+
# 4
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
## DynamicWaveletMatrix
|
|
143
|
+
DynamicWaveletMatrix supports mutable sequences with insert/remove/update.
|
|
144
|
+
|
|
145
|
+
### Trade-off:
|
|
146
|
+
- Higher overhead
|
|
147
|
+
- Values must fit within max_bit
|
|
148
|
+
|
|
149
|
+
```python
|
|
150
|
+
from wavelet_matrix import DynamicWaveletMatrix
|
|
151
|
+
|
|
152
|
+
dwm = DynamicWaveletMatrix(data, max_bit=4)
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
### Insert
|
|
156
|
+
```python
|
|
157
|
+
dwm.insert(index=4, value=8)
|
|
158
|
+
```
|
|
159
|
+
|
|
160
|
+
#### Remove
|
|
161
|
+
```python
|
|
162
|
+
dwm.remove(index=4)
|
|
163
|
+
```
|
|
164
|
+
|
|
165
|
+
#### Update
|
|
166
|
+
```python
|
|
167
|
+
dwm.update(index=4, value=5)
|
|
168
|
+
# or dwm[4] = 5
|
|
169
|
+
```
|
|
170
|
+
|
|
171
|
+
## Safety
|
|
172
|
+
- Powered by safe Rust
|
|
173
|
+
- Memory-safe by design
|
|
174
|
+
|
|
175
|
+
## Development
|
|
176
|
+
|
|
177
|
+
### Running Tests
|
|
178
|
+
|
|
179
|
+
```bash
|
|
180
|
+
pip install -e ".[test]"
|
|
181
|
+
cargo test --all --release
|
|
182
|
+
pytest
|
|
183
|
+
```
|
|
184
|
+
|
|
185
|
+
### Formating Code
|
|
186
|
+
```bash
|
|
187
|
+
pip install -e ".[dev]"
|
|
188
|
+
cargo fmt
|
|
189
|
+
ruff format
|
|
190
|
+
```
|
|
191
|
+
|
|
192
|
+
### Generating Docs
|
|
193
|
+
```bash
|
|
194
|
+
pdoc wavelet_matrix \
|
|
195
|
+
--output-directory docs \
|
|
196
|
+
--no-search \
|
|
197
|
+
--no-show-source \
|
|
198
|
+
--docformat markdown \
|
|
199
|
+
--footer-text "© 2026 Koki Watanabe"
|
|
200
|
+
```
|
|
201
|
+
|
|
202
|
+
## References
|
|
203
|
+
|
|
204
|
+
- Francisco Claude, Gonzalo Navarro, Alberto Ordóñez,
|
|
205
|
+
The wavelet matrix: An efficient wavelet tree for large alphabets,
|
|
206
|
+
Information Systems,
|
|
207
|
+
Volume 47,
|
|
208
|
+
2015,
|
|
209
|
+
Pages 15-32,
|
|
210
|
+
ISSN 0306-4379,
|
|
211
|
+
https://doi.org/10.1016/j.is.2014.06.002.
|
|
212
|
+
|
|
@@ -0,0 +1,175 @@
|
|
|
1
|
+
# Wavelet Matrix
|
|
2
|
+
|
|
3
|
+
[](https://github.com/math-hiyoko/wavelet-matrix/actions/workflows/CI.yml)
|
|
4
|
+
[](https://codecov.io/gh/math-hiyoko/wavelet-matrix)
|
|
5
|
+

|
|
6
|
+

|
|
7
|
+

|
|
8
|
+

|
|
9
|
+

|
|
10
|
+
[](https://pepy.tech/projects/wavelet-matrix)
|
|
11
|
+

|
|
12
|
+

|
|
13
|
+

|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
High-performance Wavelet Matrix implementation powered by Rust,
|
|
17
|
+
supporting fast rank / select / range queries over indexed sequences
|
|
18
|
+
|
|
19
|
+
- PyPI: https://pypi.org/project/wavelet-matrix
|
|
20
|
+
- Document: https://math-hiyoko.github.io/wavelet-matrix
|
|
21
|
+
- Repository: https://github.com/math-hiyoko/wavelet-matrix
|
|
22
|
+
|
|
23
|
+
## Features:
|
|
24
|
+
- Fast rank, select, quantile
|
|
25
|
+
- Rich range queries (freq / sum / top-k / min / max)
|
|
26
|
+
- Optional dynamic updates (insert / remove / update)
|
|
27
|
+
- Safe Rust (no unsafe)
|
|
28
|
+
|
|
29
|
+
## Installation
|
|
30
|
+
```bash
|
|
31
|
+
pip install wavelet-matrix
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
## WaveletMatrix
|
|
35
|
+
WaveletMatrix indexes a static sequence of integers,
|
|
36
|
+
enabling fast queries where runtime depends on bit-width, not data size.
|
|
37
|
+
```python
|
|
38
|
+
from wavelet_matrix import WaveletMatrix
|
|
39
|
+
|
|
40
|
+
data = [5, 4, 5, 5, 2, 1, 5, 6, 1, 3, 5, 0]
|
|
41
|
+
wm = WaveletMatrix(data)
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
### Frequency Queries
|
|
45
|
+
#### Count occurrences (rank)
|
|
46
|
+
```python
|
|
47
|
+
wm.rank(value=5, end=9)
|
|
48
|
+
# 4
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
#### Find position (select)
|
|
52
|
+
```python
|
|
53
|
+
wm.select(value=5, kth=4)
|
|
54
|
+
# 6
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
### Order Statistics
|
|
58
|
+
#### k-th smallest value (quantile)
|
|
59
|
+
```python
|
|
60
|
+
wm.quantile(start=2, end=12, kth=8)
|
|
61
|
+
# 5
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
### Range Aggregation
|
|
65
|
+
#### Sum values (range_sum)
|
|
66
|
+
```python
|
|
67
|
+
wm.range_sum(start=2, end=8)
|
|
68
|
+
# 24
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
#### Count values in [lower, upper) (range_freq)
|
|
72
|
+
```python
|
|
73
|
+
wm.range_freq(start=1, end=9, lower=4, upper=6)
|
|
74
|
+
# 4
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
#### List values with counts (range_list)
|
|
78
|
+
```python
|
|
79
|
+
wm.range_list(start=1, end=9, lower=4, upper=6)
|
|
80
|
+
# [{'value': 4, 'count': 1}, {'value': 5, 'count': 3}]
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
### Top-K Queries
|
|
84
|
+
#### Most frequent values (topk)
|
|
85
|
+
```python
|
|
86
|
+
wm.topk(start=1, end=10, k=2)
|
|
87
|
+
# [{'value': 5, 'count': 3}, {'value': 1, 'count': 2}]
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
#### Extreme values (range_maxk / range_mink)
|
|
91
|
+
```python
|
|
92
|
+
wm.range_maxk(start=1, end=9, k=2)
|
|
93
|
+
# [{'value': 6, 'count': 1}, {'value': 5, 'count': 3}]
|
|
94
|
+
wm.range_mink(start=1, end=9, k=2)
|
|
95
|
+
# [{'value': 1, 'count': 2}, {'value': 2, 'count': 1}]
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
### Boundary Queries
|
|
99
|
+
```python
|
|
100
|
+
wm.prev_value(start=1, end=9, upper=7)
|
|
101
|
+
# 6
|
|
102
|
+
wm.next_value(start=1, end=9, lower=4)
|
|
103
|
+
# 4
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
## DynamicWaveletMatrix
|
|
107
|
+
DynamicWaveletMatrix supports mutable sequences with insert/remove/update.
|
|
108
|
+
|
|
109
|
+
### Trade-off:
|
|
110
|
+
- Higher overhead
|
|
111
|
+
- Values must fit within max_bit
|
|
112
|
+
|
|
113
|
+
```python
|
|
114
|
+
from wavelet_matrix import DynamicWaveletMatrix
|
|
115
|
+
|
|
116
|
+
dwm = DynamicWaveletMatrix(data, max_bit=4)
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
### Insert
|
|
120
|
+
```python
|
|
121
|
+
dwm.insert(index=4, value=8)
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
#### Remove
|
|
125
|
+
```python
|
|
126
|
+
dwm.remove(index=4)
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
#### Update
|
|
130
|
+
```python
|
|
131
|
+
dwm.update(index=4, value=5)
|
|
132
|
+
# or dwm[4] = 5
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
## Safety
|
|
136
|
+
- Powered by safe Rust
|
|
137
|
+
- Memory-safe by design
|
|
138
|
+
|
|
139
|
+
## Development
|
|
140
|
+
|
|
141
|
+
### Running Tests
|
|
142
|
+
|
|
143
|
+
```bash
|
|
144
|
+
pip install -e ".[test]"
|
|
145
|
+
cargo test --all --release
|
|
146
|
+
pytest
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
### Formating Code
|
|
150
|
+
```bash
|
|
151
|
+
pip install -e ".[dev]"
|
|
152
|
+
cargo fmt
|
|
153
|
+
ruff format
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
### Generating Docs
|
|
157
|
+
```bash
|
|
158
|
+
pdoc wavelet_matrix \
|
|
159
|
+
--output-directory docs \
|
|
160
|
+
--no-search \
|
|
161
|
+
--no-show-source \
|
|
162
|
+
--docformat markdown \
|
|
163
|
+
--footer-text "© 2026 Koki Watanabe"
|
|
164
|
+
```
|
|
165
|
+
|
|
166
|
+
## References
|
|
167
|
+
|
|
168
|
+
- Francisco Claude, Gonzalo Navarro, Alberto Ordóñez,
|
|
169
|
+
The wavelet matrix: An efficient wavelet tree for large alphabets,
|
|
170
|
+
Information Systems,
|
|
171
|
+
Volume 47,
|
|
172
|
+
2015,
|
|
173
|
+
Pages 15-32,
|
|
174
|
+
ISSN 0306-4379,
|
|
175
|
+
https://doi.org/10.1016/j.is.2014.06.002.
|