wavelet-matrix 2.2.1__tar.gz → 2.2.2__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.2.1 → wavelet_matrix-2.2.2}/.github/workflows/CI.yml +2 -2
- {wavelet_matrix-2.2.1 → wavelet_matrix-2.2.2}/Cargo.lock +122 -20
- {wavelet_matrix-2.2.1 → wavelet_matrix-2.2.2}/Cargo.toml +4 -2
- {wavelet_matrix-2.2.1 → wavelet_matrix-2.2.2}/PKG-INFO +1 -7
- {wavelet_matrix-2.2.1 → wavelet_matrix-2.2.2}/README.md +0 -6
- {wavelet_matrix-2.2.1 → wavelet_matrix-2.2.2}/src/disk_wavelet_matrix/disk_bit_vector.rs +82 -25
- {wavelet_matrix-2.2.1 → wavelet_matrix-2.2.2}/src/disk_wavelet_matrix/disk_wavelet_matrix.rs +133 -41
- {wavelet_matrix-2.2.1 → wavelet_matrix-2.2.2}/src/lib.rs +1 -1
- {wavelet_matrix-2.2.1 → wavelet_matrix-2.2.2}/src/python/wavelet_matrix.rs +65 -69
- {wavelet_matrix-2.2.1 → wavelet_matrix-2.2.2}/src/wavelet_matrix/wavelet_matrix.rs +11 -12
- {wavelet_matrix-2.2.1 → wavelet_matrix-2.2.2}/.gitignore +0 -0
- {wavelet_matrix-2.2.1 → wavelet_matrix-2.2.2}/LICENSE +0 -0
- {wavelet_matrix-2.2.1 → wavelet_matrix-2.2.2}/benchmarks/__init__.py +0 -0
- {wavelet_matrix-2.2.1 → wavelet_matrix-2.2.2}/benchmarks/bench_disk_wavelet_matrix.py +0 -0
- {wavelet_matrix-2.2.1 → wavelet_matrix-2.2.2}/benchmarks/bench_dynamic_wavelet_matrix.py +0 -0
- {wavelet_matrix-2.2.1 → wavelet_matrix-2.2.2}/benchmarks/bench_wavelet_matrix.py +0 -0
- {wavelet_matrix-2.2.1 → wavelet_matrix-2.2.2}/docs/index.html +0 -0
- {wavelet_matrix-2.2.1 → wavelet_matrix-2.2.2}/docs/wavelet_matrix.html +0 -0
- {wavelet_matrix-2.2.1 → wavelet_matrix-2.2.2}/pdoc_templates/error.html.jinja2 +0 -0
- {wavelet_matrix-2.2.1 → wavelet_matrix-2.2.2}/pdoc_templates/frame.html.jinja2 +0 -0
- {wavelet_matrix-2.2.1 → wavelet_matrix-2.2.2}/pdoc_templates/index.html.jinja2 +0 -0
- {wavelet_matrix-2.2.1 → wavelet_matrix-2.2.2}/pdoc_templates/module.html.jinja2 +0 -0
- {wavelet_matrix-2.2.1 → wavelet_matrix-2.2.2}/pyproject.toml +0 -0
- {wavelet_matrix-2.2.1 → wavelet_matrix-2.2.2}/src/disk_wavelet_matrix/mod.rs +0 -0
- {wavelet_matrix-2.2.1 → wavelet_matrix-2.2.2}/src/dynamic_wavelet_matrix/dynamic_bit_vector.rs +0 -0
- {wavelet_matrix-2.2.1 → wavelet_matrix-2.2.2}/src/dynamic_wavelet_matrix/dynamic_wavelet_matrix.rs +0 -0
- {wavelet_matrix-2.2.1 → wavelet_matrix-2.2.2}/src/dynamic_wavelet_matrix/mod.rs +0 -0
- {wavelet_matrix-2.2.1 → wavelet_matrix-2.2.2}/src/python/dynamic_wavelet_matrix.rs +0 -0
- {wavelet_matrix-2.2.1 → wavelet_matrix-2.2.2}/src/python/mod.rs +0 -0
- {wavelet_matrix-2.2.1 → wavelet_matrix-2.2.2}/src/traits/bit_vector/bit_vector.rs +0 -0
- {wavelet_matrix-2.2.1 → wavelet_matrix-2.2.2}/src/traits/bit_vector/dynamic_bit_vector.rs +0 -0
- {wavelet_matrix-2.2.1 → wavelet_matrix-2.2.2}/src/traits/bit_vector/mod.rs +0 -0
- {wavelet_matrix-2.2.1 → wavelet_matrix-2.2.2}/src/traits/mod.rs +0 -0
- {wavelet_matrix-2.2.1 → wavelet_matrix-2.2.2}/src/traits/utils/bit_select.rs +0 -0
- {wavelet_matrix-2.2.1 → wavelet_matrix-2.2.2}/src/traits/utils/bit_width.rs +0 -0
- {wavelet_matrix-2.2.1 → wavelet_matrix-2.2.2}/src/traits/utils/mod.rs +0 -0
- {wavelet_matrix-2.2.1 → wavelet_matrix-2.2.2}/src/traits/wavelet_matrix/dynamic_wavelet_matrix.rs +0 -0
- {wavelet_matrix-2.2.1 → wavelet_matrix-2.2.2}/src/traits/wavelet_matrix/mod.rs +0 -0
- {wavelet_matrix-2.2.1 → wavelet_matrix-2.2.2}/src/traits/wavelet_matrix/wavelet_matrix.rs +0 -0
- {wavelet_matrix-2.2.1 → wavelet_matrix-2.2.2}/src/wavelet_matrix/bit_vector.rs +0 -0
- {wavelet_matrix-2.2.1 → wavelet_matrix-2.2.2}/src/wavelet_matrix/mod.rs +0 -0
- {wavelet_matrix-2.2.1 → wavelet_matrix-2.2.2}/tests/__init__.py +0 -0
- {wavelet_matrix-2.2.1 → wavelet_matrix-2.2.2}/tests/test_disk_wavelet_matrix.py +0 -0
- {wavelet_matrix-2.2.1 → wavelet_matrix-2.2.2}/tests/test_dynamic_wavelet_matrix.py +0 -0
- {wavelet_matrix-2.2.1 → wavelet_matrix-2.2.2}/tests/test_wavelet_matrix.py +0 -0
- {wavelet_matrix-2.2.1 → wavelet_matrix-2.2.2}/wavelet_matrix.pyi +0 -0
|
@@ -206,7 +206,7 @@ jobs:
|
|
|
206
206
|
- name: Install packages
|
|
207
207
|
run: python -m pip install -e .[test,dev]
|
|
208
208
|
- name: Run tests
|
|
209
|
-
run: pytest --benchmark-skip
|
|
209
|
+
run: python -m pytest --benchmark-skip
|
|
210
210
|
- name: Docs check
|
|
211
211
|
run: |
|
|
212
212
|
pdoc wavelet_matrix \
|
|
@@ -245,7 +245,7 @@ jobs:
|
|
|
245
245
|
python -m pip install --upgrade pip
|
|
246
246
|
python -m pip install -e .[test]
|
|
247
247
|
- name: Run benchmarks
|
|
248
|
-
run: pytest --benchmark-only --db .pymon
|
|
248
|
+
run: python -m pytest --benchmark-only --db .pymon
|
|
249
249
|
- name: Display benchmark results
|
|
250
250
|
run: |
|
|
251
251
|
sqlite3 -header -column .pymon '
|
|
@@ -8,17 +8,29 @@ version = "1.5.1"
|
|
|
8
8
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
9
9
|
checksum = "f2032f911046de80f0a198e0901378627c33f59ea0ac00e363d481118bd70a53"
|
|
10
10
|
|
|
11
|
+
[[package]]
|
|
12
|
+
name = "bitflags"
|
|
13
|
+
version = "2.13.0"
|
|
14
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
15
|
+
checksum = "b4388bee8683e3d04af747c73422af53102d2bd24d9eadb6cbc100baef4b43f8"
|
|
16
|
+
|
|
11
17
|
[[package]]
|
|
12
18
|
name = "bytemuck"
|
|
13
19
|
version = "1.25.0"
|
|
14
20
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
15
21
|
checksum = "c8efb64bd706a16a1bdde310ae86b351e4d21550d98d056f22f8a7f7a2183fec"
|
|
16
22
|
|
|
23
|
+
[[package]]
|
|
24
|
+
name = "cfg-if"
|
|
25
|
+
version = "1.0.4"
|
|
26
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
27
|
+
checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801"
|
|
28
|
+
|
|
17
29
|
[[package]]
|
|
18
30
|
name = "crossbeam-deque"
|
|
19
|
-
version = "0.8.
|
|
31
|
+
version = "0.8.7"
|
|
20
32
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
21
|
-
checksum = "
|
|
33
|
+
checksum = "5181e0de7b61eb03a81e347d6dd8797bae9da5146707b51077e2d71a54ec0ceb"
|
|
22
34
|
dependencies = [
|
|
23
35
|
"crossbeam-epoch",
|
|
24
36
|
"crossbeam-utils",
|
|
@@ -26,18 +38,18 @@ dependencies = [
|
|
|
26
38
|
|
|
27
39
|
[[package]]
|
|
28
40
|
name = "crossbeam-epoch"
|
|
29
|
-
version = "0.9.
|
|
41
|
+
version = "0.9.20"
|
|
30
42
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
31
|
-
checksum = "
|
|
43
|
+
checksum = "2d6914041f254d6e9176c01941b21115dcfb7089e55135a35411081bd106ef3f"
|
|
32
44
|
dependencies = [
|
|
33
45
|
"crossbeam-utils",
|
|
34
46
|
]
|
|
35
47
|
|
|
36
48
|
[[package]]
|
|
37
49
|
name = "crossbeam-utils"
|
|
38
|
-
version = "0.8.
|
|
50
|
+
version = "0.8.22"
|
|
39
51
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
40
|
-
checksum = "
|
|
52
|
+
checksum = "61803da095bee82a81bb1a452ecc25d3b2f1416d1897eb86430c6159ef717c17"
|
|
41
53
|
|
|
42
54
|
[[package]]
|
|
43
55
|
name = "either"
|
|
@@ -45,18 +57,60 @@ version = "1.16.0"
|
|
|
45
57
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
46
58
|
checksum = "91622ff5e7162018101f2fea40d6ebf4a78bbe5a49736a2020649edf9693679e"
|
|
47
59
|
|
|
60
|
+
[[package]]
|
|
61
|
+
name = "errno"
|
|
62
|
+
version = "0.3.14"
|
|
63
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
64
|
+
checksum = "39cab71617ae0d63f51a36d69f866391735b51691dbda63cf6f96d042b63efeb"
|
|
65
|
+
dependencies = [
|
|
66
|
+
"libc",
|
|
67
|
+
"windows-sys",
|
|
68
|
+
]
|
|
69
|
+
|
|
70
|
+
[[package]]
|
|
71
|
+
name = "fastrand"
|
|
72
|
+
version = "2.4.1"
|
|
73
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
74
|
+
checksum = "9f1f227452a390804cdb637b74a86990f2a7d7ba4b7d5693aac9b4dd6defd8d6"
|
|
75
|
+
|
|
76
|
+
[[package]]
|
|
77
|
+
name = "getrandom"
|
|
78
|
+
version = "0.4.3"
|
|
79
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
80
|
+
checksum = "300e883d756b2e4ec94e02791f39b04b522276138852cfc41d9fb7e904106099"
|
|
81
|
+
dependencies = [
|
|
82
|
+
"cfg-if",
|
|
83
|
+
"libc",
|
|
84
|
+
"r-efi",
|
|
85
|
+
]
|
|
86
|
+
|
|
48
87
|
[[package]]
|
|
49
88
|
name = "heck"
|
|
50
89
|
version = "0.5.0"
|
|
51
90
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
52
91
|
checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea"
|
|
53
92
|
|
|
93
|
+
[[package]]
|
|
94
|
+
name = "itertools"
|
|
95
|
+
version = "0.15.0"
|
|
96
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
97
|
+
checksum = "8b4baf93f58d4425749ca49a51c50ebab072c5df6994d08fed93541c331481dc"
|
|
98
|
+
dependencies = [
|
|
99
|
+
"either",
|
|
100
|
+
]
|
|
101
|
+
|
|
54
102
|
[[package]]
|
|
55
103
|
name = "libc"
|
|
56
104
|
version = "0.2.186"
|
|
57
105
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
58
106
|
checksum = "68ab91017fe16c622486840e4c83c9a37afeff978bd239b5293d61ece587de66"
|
|
59
107
|
|
|
108
|
+
[[package]]
|
|
109
|
+
name = "linux-raw-sys"
|
|
110
|
+
version = "0.12.1"
|
|
111
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
112
|
+
checksum = "32a66949e030da00e8c7d4434b251670a91556f4144941d37452769c25d58a53"
|
|
113
|
+
|
|
60
114
|
[[package]]
|
|
61
115
|
name = "memmap2"
|
|
62
116
|
version = "0.9.11"
|
|
@@ -68,9 +122,9 @@ dependencies = [
|
|
|
68
122
|
|
|
69
123
|
[[package]]
|
|
70
124
|
name = "num-bigint"
|
|
71
|
-
version = "0.4.
|
|
125
|
+
version = "0.4.8"
|
|
72
126
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
73
|
-
checksum = "
|
|
127
|
+
checksum = "c89e69e7e0f03bea5ef08013795c25018e101932225a656383bd384495ecc367"
|
|
74
128
|
dependencies = [
|
|
75
129
|
"num-integer",
|
|
76
130
|
"num-traits",
|
|
@@ -117,9 +171,9 @@ dependencies = [
|
|
|
117
171
|
|
|
118
172
|
[[package]]
|
|
119
173
|
name = "pyo3"
|
|
120
|
-
version = "0.
|
|
174
|
+
version = "0.29.0"
|
|
121
175
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
122
|
-
checksum = "
|
|
176
|
+
checksum = "cd274650b21d4bfc26a0a47587962c1edb425f69287324355cd040c3ea66071c"
|
|
123
177
|
dependencies = [
|
|
124
178
|
"libc",
|
|
125
179
|
"num-bigint",
|
|
@@ -133,18 +187,18 @@ dependencies = [
|
|
|
133
187
|
|
|
134
188
|
[[package]]
|
|
135
189
|
name = "pyo3-build-config"
|
|
136
|
-
version = "0.
|
|
190
|
+
version = "0.29.0"
|
|
137
191
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
138
|
-
checksum = "
|
|
192
|
+
checksum = "c5e2a7d2f0d013342f295c048ad19237add5154a55b1c5a254c0ec93d4109078"
|
|
139
193
|
dependencies = [
|
|
140
194
|
"target-lexicon",
|
|
141
195
|
]
|
|
142
196
|
|
|
143
197
|
[[package]]
|
|
144
198
|
name = "pyo3-ffi"
|
|
145
|
-
version = "0.
|
|
199
|
+
version = "0.29.0"
|
|
146
200
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
147
|
-
checksum = "
|
|
201
|
+
checksum = "ca85c467da1bbc8d866eea5deff9cf29ea5f7785054a17da36e65bda9c05845b"
|
|
148
202
|
dependencies = [
|
|
149
203
|
"libc",
|
|
150
204
|
"pyo3-build-config",
|
|
@@ -152,9 +206,9 @@ dependencies = [
|
|
|
152
206
|
|
|
153
207
|
[[package]]
|
|
154
208
|
name = "pyo3-macros"
|
|
155
|
-
version = "0.
|
|
209
|
+
version = "0.29.0"
|
|
156
210
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
157
|
-
checksum = "
|
|
211
|
+
checksum = "9ac53762fd065daa3194dd09337a38bd793a188100fd1a9304c4ab312d901771"
|
|
158
212
|
dependencies = [
|
|
159
213
|
"proc-macro2",
|
|
160
214
|
"pyo3-macros-backend",
|
|
@@ -164,13 +218,12 @@ dependencies = [
|
|
|
164
218
|
|
|
165
219
|
[[package]]
|
|
166
220
|
name = "pyo3-macros-backend"
|
|
167
|
-
version = "0.
|
|
221
|
+
version = "0.29.0"
|
|
168
222
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
169
|
-
checksum = "
|
|
223
|
+
checksum = "4ca3a1557399783172dc5bf39cfca835157732532cba56b71d2292161e53b362"
|
|
170
224
|
dependencies = [
|
|
171
225
|
"heck",
|
|
172
226
|
"proc-macro2",
|
|
173
|
-
"pyo3-build-config",
|
|
174
227
|
"quote",
|
|
175
228
|
"syn",
|
|
176
229
|
]
|
|
@@ -184,6 +237,12 @@ dependencies = [
|
|
|
184
237
|
"proc-macro2",
|
|
185
238
|
]
|
|
186
239
|
|
|
240
|
+
[[package]]
|
|
241
|
+
name = "r-efi"
|
|
242
|
+
version = "6.0.0"
|
|
243
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
244
|
+
checksum = "f8dcc9c7d52a811697d2151c701e0d08956f92b0e24136cf4cf27b57a6a0d9bf"
|
|
245
|
+
|
|
187
246
|
[[package]]
|
|
188
247
|
name = "rayon"
|
|
189
248
|
version = "1.12.0"
|
|
@@ -204,6 +263,19 @@ dependencies = [
|
|
|
204
263
|
"crossbeam-utils",
|
|
205
264
|
]
|
|
206
265
|
|
|
266
|
+
[[package]]
|
|
267
|
+
name = "rustix"
|
|
268
|
+
version = "1.1.4"
|
|
269
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
270
|
+
checksum = "b6fe4565b9518b83ef4f91bb47ce29620ca828bd32cb7e408f0062e9930ba190"
|
|
271
|
+
dependencies = [
|
|
272
|
+
"bitflags",
|
|
273
|
+
"errno",
|
|
274
|
+
"libc",
|
|
275
|
+
"linux-raw-sys",
|
|
276
|
+
"windows-sys",
|
|
277
|
+
]
|
|
278
|
+
|
|
207
279
|
[[package]]
|
|
208
280
|
name = "syn"
|
|
209
281
|
version = "2.0.118"
|
|
@@ -221,6 +293,19 @@ version = "0.13.5"
|
|
|
221
293
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
222
294
|
checksum = "adb6935a6f5c20170eeceb1a3835a49e12e19d792f6dd344ccc76a985ca5a6ca"
|
|
223
295
|
|
|
296
|
+
[[package]]
|
|
297
|
+
name = "tempfile"
|
|
298
|
+
version = "3.27.0"
|
|
299
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
300
|
+
checksum = "32497e9a4c7b38532efcdebeef879707aa9f794296a4f0244f6f69e9bc8574bd"
|
|
301
|
+
dependencies = [
|
|
302
|
+
"fastrand",
|
|
303
|
+
"getrandom",
|
|
304
|
+
"once_cell",
|
|
305
|
+
"rustix",
|
|
306
|
+
"windows-sys",
|
|
307
|
+
]
|
|
308
|
+
|
|
224
309
|
[[package]]
|
|
225
310
|
name = "unicode-ident"
|
|
226
311
|
version = "1.0.24"
|
|
@@ -229,13 +314,30 @@ checksum = "e6e4313cd5fcd3dad5cafa179702e2b244f760991f45397d14d4ebf38247da75"
|
|
|
229
314
|
|
|
230
315
|
[[package]]
|
|
231
316
|
name = "wavelet-matrix"
|
|
232
|
-
version = "2.2.
|
|
317
|
+
version = "2.2.2"
|
|
233
318
|
dependencies = [
|
|
234
319
|
"bytemuck",
|
|
320
|
+
"itertools",
|
|
235
321
|
"memmap2",
|
|
236
322
|
"num-bigint",
|
|
237
323
|
"num-integer",
|
|
238
324
|
"num-traits",
|
|
239
325
|
"pyo3",
|
|
240
326
|
"rayon",
|
|
327
|
+
"tempfile",
|
|
328
|
+
]
|
|
329
|
+
|
|
330
|
+
[[package]]
|
|
331
|
+
name = "windows-link"
|
|
332
|
+
version = "0.2.1"
|
|
333
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
334
|
+
checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5"
|
|
335
|
+
|
|
336
|
+
[[package]]
|
|
337
|
+
name = "windows-sys"
|
|
338
|
+
version = "0.61.2"
|
|
339
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
340
|
+
checksum = "ae137229bcbd6cdf0f7b80a31df61766145077ddf49416a728b02cb3921ff3fc"
|
|
341
|
+
dependencies = [
|
|
342
|
+
"windows-link",
|
|
241
343
|
]
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[package]
|
|
2
2
|
name = "wavelet-matrix"
|
|
3
|
-
version = "2.2.
|
|
3
|
+
version = "2.2.2"
|
|
4
4
|
edition = "2024"
|
|
5
5
|
readme = "README.md"
|
|
6
6
|
|
|
@@ -11,9 +11,11 @@ crate-type = ["cdylib"]
|
|
|
11
11
|
|
|
12
12
|
[dependencies]
|
|
13
13
|
bytemuck = "1.25.0"
|
|
14
|
+
itertools = "0.15.0"
|
|
14
15
|
memmap2 = "0.9.10"
|
|
15
16
|
num-bigint = "0.4.6"
|
|
16
17
|
num-integer = "0.1.46"
|
|
17
18
|
num-traits = "0.2.19"
|
|
18
|
-
pyo3 = { version = "0.
|
|
19
|
+
pyo3 = { version = "0.29.0", features = ["num-bigint"] }
|
|
19
20
|
rayon = "1.12.0"
|
|
21
|
+
tempfile = "3.27.0"
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: wavelet-matrix
|
|
3
|
-
Version: 2.2.
|
|
3
|
+
Version: 2.2.2
|
|
4
4
|
Classifier: Intended Audience :: Developers
|
|
5
5
|
Classifier: Intended Audience :: Science/Research
|
|
6
6
|
Classifier: Intended Audience :: Information Technology
|
|
@@ -47,7 +47,6 @@ Project-URL: repository, https://github.com/math-hiyoko/wavelet-matrix
|
|
|
47
47
|
[](https://pepy.tech/projects/wavelet-matrix)
|
|
48
48
|

|
|
49
49
|

|
|
50
|
-

|
|
51
50
|

|
|
52
51
|
|
|
53
52
|
|
|
@@ -63,7 +62,6 @@ supporting fast rank / select / range queries over indexed sequences
|
|
|
63
62
|
- Rich range queries (freq / sum / top-k / min / max)
|
|
64
63
|
- Optional disk-backed storage for static WaveletMatrix (`on_disk=True`)
|
|
65
64
|
- Optional dynamic updates (insert / remove / update)
|
|
66
|
-
- Safe Rust (no unsafe)
|
|
67
65
|
|
|
68
66
|
## Installation
|
|
69
67
|
```bash
|
|
@@ -177,10 +175,6 @@ dwm.update(index=4, value=5)
|
|
|
177
175
|
# or dwm[4] = 5
|
|
178
176
|
```
|
|
179
177
|
|
|
180
|
-
## Safety
|
|
181
|
-
- Powered by safe Rust
|
|
182
|
-
- Memory-safe by design
|
|
183
|
-
|
|
184
178
|
## Development
|
|
185
179
|
|
|
186
180
|
### Running Tests
|
|
@@ -10,7 +10,6 @@
|
|
|
10
10
|
[](https://pepy.tech/projects/wavelet-matrix)
|
|
11
11
|

|
|
12
12
|

|
|
13
|
-

|
|
14
13
|

|
|
15
14
|
|
|
16
15
|
|
|
@@ -26,7 +25,6 @@ supporting fast rank / select / range queries over indexed sequences
|
|
|
26
25
|
- Rich range queries (freq / sum / top-k / min / max)
|
|
27
26
|
- Optional disk-backed storage for static WaveletMatrix (`on_disk=True`)
|
|
28
27
|
- Optional dynamic updates (insert / remove / update)
|
|
29
|
-
- Safe Rust (no unsafe)
|
|
30
28
|
|
|
31
29
|
## Installation
|
|
32
30
|
```bash
|
|
@@ -140,10 +138,6 @@ dwm.update(index=4, value=5)
|
|
|
140
138
|
# or dwm[4] = 5
|
|
141
139
|
```
|
|
142
140
|
|
|
143
|
-
## Safety
|
|
144
|
-
- Powered by safe Rust
|
|
145
|
-
- Memory-safe by design
|
|
146
|
-
|
|
147
141
|
## Development
|
|
148
142
|
|
|
149
143
|
### Running Tests
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
use std::{iter, mem};
|
|
1
|
+
use std::{fs, iter, mem};
|
|
2
2
|
|
|
3
3
|
use bytemuck::{cast_slice, cast_slice_mut};
|
|
4
4
|
use memmap2::{Mmap, MmapMut};
|
|
@@ -8,6 +8,7 @@ use pyo3::{
|
|
|
8
8
|
PyResult,
|
|
9
9
|
exceptions::{PyIndexError, PyRuntimeError, PyValueError},
|
|
10
10
|
};
|
|
11
|
+
use tempfile::tempfile;
|
|
11
12
|
|
|
12
13
|
use crate::traits::{
|
|
13
14
|
bit_vector::bit_vector::{BitVectorTrait, BlockType},
|
|
@@ -19,19 +20,25 @@ const SELECT_INDEX_INTERVAL: usize = 512;
|
|
|
19
20
|
pub(crate) struct DiskBitVector {
|
|
20
21
|
len: usize,
|
|
21
22
|
ranks: Mmap,
|
|
23
|
+
ranks_file: fs::File,
|
|
22
24
|
blocks: Mmap,
|
|
25
|
+
blocks_file: fs::File,
|
|
23
26
|
select_index: [Mmap; 2],
|
|
27
|
+
select_index_file: [fs::File; 2],
|
|
24
28
|
}
|
|
25
29
|
|
|
26
30
|
impl DiskBitVector {
|
|
27
|
-
pub(super) fn new(blocks: Mmap, len: usize) -> PyResult<Self> {
|
|
31
|
+
pub(super) fn new(blocks: Mmap, blocks_file: fs::File, len: usize) -> PyResult<Self> {
|
|
28
32
|
assert!(blocks.len().is_multiple_of(mem::size_of::<BlockType>()));
|
|
29
33
|
let blocks_data: &[BlockType] = cast_slice(&blocks[..]);
|
|
30
34
|
|
|
31
35
|
// Build the rank index structure.
|
|
32
|
-
let
|
|
36
|
+
let ranks_file = tempfile().map_err(PyRuntimeError::new_err)?;
|
|
37
|
+
ranks_file
|
|
38
|
+
.set_len((blocks_data.len() + 1) as u64 * mem::size_of::<usize>() as u64)
|
|
33
39
|
.map_err(PyRuntimeError::new_err)?;
|
|
34
|
-
|
|
40
|
+
#[allow(unsafe_code)]
|
|
41
|
+
let mut ranks = unsafe { MmapMut::map_mut(&ranks_file).map_err(PyRuntimeError::new_err)? };
|
|
35
42
|
let ranks_data: &mut [usize] = cast_slice_mut(&mut ranks[..]);
|
|
36
43
|
iter::once(0usize)
|
|
37
44
|
.chain(blocks_data.iter().scan(0usize, |acc, block| {
|
|
@@ -41,16 +48,32 @@ impl DiskBitVector {
|
|
|
41
48
|
.enumerate()
|
|
42
49
|
.for_each(|(index, rank)| ranks_data[index] = rank);
|
|
43
50
|
|
|
44
|
-
let
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
51
|
+
let select_index_file = [
|
|
52
|
+
{
|
|
53
|
+
let file = tempfile().map_err(PyRuntimeError::new_err)?;
|
|
54
|
+
file.set_len(
|
|
55
|
+
(((len - ranks_data.last().unwrap()) / SELECT_INDEX_INTERVAL + 2)
|
|
56
|
+
* mem::size_of::<usize>()) as u64,
|
|
57
|
+
)
|
|
58
|
+
.map_err(PyRuntimeError::new_err)?;
|
|
59
|
+
file
|
|
60
|
+
},
|
|
61
|
+
{
|
|
62
|
+
let file = tempfile().map_err(PyRuntimeError::new_err)?;
|
|
63
|
+
file.set_len(
|
|
64
|
+
((ranks_data.last().unwrap() / SELECT_INDEX_INTERVAL + 2)
|
|
65
|
+
* mem::size_of::<usize>()) as u64,
|
|
66
|
+
)
|
|
67
|
+
.map_err(PyRuntimeError::new_err)?;
|
|
68
|
+
file
|
|
69
|
+
},
|
|
70
|
+
];
|
|
71
|
+
#[allow(unsafe_code)]
|
|
72
|
+
let mut select_index_0 =
|
|
73
|
+
unsafe { MmapMut::map_mut(&select_index_file[0]).map_err(PyRuntimeError::new_err)? };
|
|
74
|
+
#[allow(unsafe_code)]
|
|
75
|
+
let mut select_index_1 =
|
|
76
|
+
unsafe { MmapMut::map_mut(&select_index_file[1]).map_err(PyRuntimeError::new_err)? };
|
|
54
77
|
let select_index_data: [&mut [usize]; 2] = [
|
|
55
78
|
cast_slice_mut(&mut select_index_0[..]),
|
|
56
79
|
cast_slice_mut(&mut select_index_1[..]),
|
|
@@ -79,7 +102,9 @@ impl DiskBitVector {
|
|
|
79
102
|
Ok(Self {
|
|
80
103
|
len,
|
|
81
104
|
ranks: ranks.make_read_only().map_err(PyRuntimeError::new_err)?,
|
|
105
|
+
ranks_file,
|
|
82
106
|
blocks,
|
|
107
|
+
blocks_file,
|
|
83
108
|
select_index: [
|
|
84
109
|
select_index_0
|
|
85
110
|
.make_read_only()
|
|
@@ -88,20 +113,47 @@ impl DiskBitVector {
|
|
|
88
113
|
.make_read_only()
|
|
89
114
|
.map_err(PyRuntimeError::new_err)?,
|
|
90
115
|
],
|
|
116
|
+
select_index_file,
|
|
91
117
|
})
|
|
92
118
|
}
|
|
93
119
|
}
|
|
94
120
|
|
|
95
121
|
impl Clone for DiskBitVector {
|
|
96
122
|
fn clone(&self) -> Self {
|
|
97
|
-
let
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
MmapMut::map_anon(self.select_index[1].len()).unwrap(),
|
|
102
|
-
];
|
|
123
|
+
let ranks_file = tempfile().unwrap();
|
|
124
|
+
ranks_file.set_len(self.ranks.len() as u64).unwrap();
|
|
125
|
+
#[allow(unsafe_code)]
|
|
126
|
+
let mut ranks = unsafe { MmapMut::map_mut(&ranks_file).unwrap() };
|
|
103
127
|
ranks.copy_from_slice(&self.ranks[..]);
|
|
128
|
+
|
|
129
|
+
let blocks_file = tempfile().unwrap();
|
|
130
|
+
blocks_file.set_len(self.blocks.len() as u64).unwrap();
|
|
131
|
+
#[allow(unsafe_code)]
|
|
132
|
+
let mut blocks = unsafe { MmapMut::map_mut(&blocks_file).unwrap() };
|
|
104
133
|
blocks.copy_from_slice(&self.blocks[..]);
|
|
134
|
+
|
|
135
|
+
let select_index_file = [
|
|
136
|
+
{
|
|
137
|
+
let file = tempfile().unwrap();
|
|
138
|
+
file.set_len(self.select_index[0].len() as u64).unwrap();
|
|
139
|
+
file
|
|
140
|
+
},
|
|
141
|
+
{
|
|
142
|
+
let file = tempfile().unwrap();
|
|
143
|
+
file.set_len(self.select_index[1].len() as u64).unwrap();
|
|
144
|
+
file
|
|
145
|
+
},
|
|
146
|
+
];
|
|
147
|
+
let mut select_index = [
|
|
148
|
+
#[allow(unsafe_code)]
|
|
149
|
+
unsafe {
|
|
150
|
+
MmapMut::map_mut(&select_index_file[0]).unwrap()
|
|
151
|
+
},
|
|
152
|
+
#[allow(unsafe_code)]
|
|
153
|
+
unsafe {
|
|
154
|
+
MmapMut::map_mut(&select_index_file[1]).unwrap()
|
|
155
|
+
},
|
|
156
|
+
];
|
|
105
157
|
select_index[0].copy_from_slice(&self.select_index[0][..]);
|
|
106
158
|
select_index[1].copy_from_slice(&self.select_index[1][..]);
|
|
107
159
|
|
|
@@ -110,11 +162,14 @@ impl Clone for DiskBitVector {
|
|
|
110
162
|
Self {
|
|
111
163
|
len: self.len,
|
|
112
164
|
ranks: ranks.make_read_only().unwrap(),
|
|
165
|
+
ranks_file,
|
|
113
166
|
blocks: blocks.make_read_only().unwrap(),
|
|
167
|
+
blocks_file,
|
|
114
168
|
select_index: [
|
|
115
169
|
select_index_0.make_read_only().unwrap(),
|
|
116
170
|
select_index_1.make_read_only().unwrap(),
|
|
117
171
|
],
|
|
172
|
+
select_index_file,
|
|
118
173
|
}
|
|
119
174
|
}
|
|
120
175
|
}
|
|
@@ -217,10 +272,12 @@ mod tests {
|
|
|
217
272
|
|
|
218
273
|
fn create_disk_bit_vector(bits: Vec<bool>) -> DiskBitVector {
|
|
219
274
|
let len = bits.len();
|
|
220
|
-
let
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
275
|
+
let blocks_file = tempfile().unwrap();
|
|
276
|
+
blocks_file
|
|
277
|
+
.set_len((len.div_ceil(BlockType::BITS as usize) * mem::size_of::<BlockType>()) as u64)
|
|
278
|
+
.unwrap();
|
|
279
|
+
#[allow(unsafe_code)]
|
|
280
|
+
let mut blocks = unsafe { MmapMut::map_mut(&blocks_file).unwrap() };
|
|
224
281
|
let blocks_data: &mut [BlockType] = cast_slice_mut(&mut blocks[..]);
|
|
225
282
|
bits.chunks(BlockType::BITS as usize)
|
|
226
283
|
.enumerate()
|
|
@@ -238,7 +295,7 @@ mod tests {
|
|
|
238
295
|
})
|
|
239
296
|
});
|
|
240
297
|
|
|
241
|
-
DiskBitVector::new(blocks.make_read_only().unwrap(), len).unwrap()
|
|
298
|
+
DiskBitVector::new(blocks.make_read_only().unwrap(), blocks_file, len).unwrap()
|
|
242
299
|
}
|
|
243
300
|
|
|
244
301
|
fn create_dummy() -> DiskBitVector {
|
{wavelet_matrix-2.2.1 → wavelet_matrix-2.2.2}/src/disk_wavelet_matrix/disk_wavelet_matrix.rs
RENAMED
|
@@ -1,11 +1,12 @@
|
|
|
1
|
-
use std::{iter, marker, mem, ops};
|
|
1
|
+
use std::{fs, iter, marker, mem, ops};
|
|
2
2
|
|
|
3
3
|
use bytemuck::{Pod, cast_slice, cast_slice_mut};
|
|
4
|
-
use memmap2::
|
|
4
|
+
use memmap2::MmapMut;
|
|
5
5
|
use num_bigint::ToBigUint;
|
|
6
6
|
use num_traits::{One, PrimInt, Unsigned};
|
|
7
7
|
use pyo3::{PyResult, exceptions::PyRuntimeError};
|
|
8
8
|
use rayon::prelude::*;
|
|
9
|
+
use tempfile::tempfile;
|
|
9
10
|
|
|
10
11
|
use super::disk_bit_vector::DiskBitVector;
|
|
11
12
|
use crate::traits::{
|
|
@@ -27,11 +28,12 @@ where
|
|
|
27
28
|
NumberType: BitWidth + One + PrimInt + Unsigned + Pod + Send + Sync,
|
|
28
29
|
for<'a> &'a NumberType: ops::Shr<usize, Output = NumberType>,
|
|
29
30
|
{
|
|
30
|
-
pub(crate) fn new(data:
|
|
31
|
+
pub(crate) fn new(data: MmapMut, data_file: fs::File) -> PyResult<Self> {
|
|
31
32
|
assert!(data.len().is_multiple_of(mem::size_of::<NumberType>()));
|
|
32
33
|
let len = data.len() / mem::size_of::<NumberType>();
|
|
33
34
|
|
|
34
35
|
let mut values = data;
|
|
36
|
+
let mut _values_file = data_file;
|
|
35
37
|
let values_data: &[NumberType] = cast_slice(&values[..]);
|
|
36
38
|
let height = values_data
|
|
37
39
|
.par_iter()
|
|
@@ -41,10 +43,16 @@ where
|
|
|
41
43
|
let mut zeros_count_per_layer = Vec::with_capacity(height);
|
|
42
44
|
let mut layer_blocks_vec = Vec::with_capacity(height);
|
|
43
45
|
for i in 0..height {
|
|
44
|
-
let
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
46
|
+
let current_layer_bits_file = tempfile().map_err(PyRuntimeError::new_err)?;
|
|
47
|
+
current_layer_bits_file
|
|
48
|
+
.set_len(
|
|
49
|
+
(len.div_ceil(BlockType::BITS as usize) * mem::size_of::<BlockType>()) as u64,
|
|
50
|
+
)
|
|
51
|
+
.map_err(PyRuntimeError::new_err)?;
|
|
52
|
+
#[allow(unsafe_code)]
|
|
53
|
+
let mut current_layer_bits = unsafe {
|
|
54
|
+
MmapMut::map_mut(¤t_layer_bits_file).map_err(PyRuntimeError::new_err)?
|
|
55
|
+
};
|
|
48
56
|
assert!(
|
|
49
57
|
current_layer_bits
|
|
50
58
|
.len()
|
|
@@ -53,32 +61,39 @@ where
|
|
|
53
61
|
let current_layer_bits_data: &mut [BlockType] =
|
|
54
62
|
cast_slice_mut(&mut current_layer_bits[..]);
|
|
55
63
|
let values_data: &[NumberType] = cast_slice(&values[..]);
|
|
56
|
-
|
|
57
|
-
.
|
|
58
|
-
.
|
|
59
|
-
.
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
if
|
|
64
|
+
current_layer_bits_data
|
|
65
|
+
.iter_mut()
|
|
66
|
+
.enumerate()
|
|
67
|
+
.for_each(|(block_index, block)| {
|
|
68
|
+
let start = block_index * BlockType::BITS as usize;
|
|
69
|
+
let end = (start + BlockType::BITS as usize).min(len);
|
|
70
|
+
for (j, value) in values_data[start..end].iter().enumerate() {
|
|
71
|
+
if ((value >> (height - i - 1)) & NumberType::one()).is_one() {
|
|
64
72
|
*block |= BlockType::one() << j;
|
|
65
73
|
}
|
|
66
|
-
}
|
|
74
|
+
}
|
|
67
75
|
});
|
|
76
|
+
|
|
68
77
|
let zeros_count = len
|
|
69
78
|
- current_layer_bits_data
|
|
70
79
|
.par_iter()
|
|
71
80
|
.map(|&block| block.count_ones() as usize)
|
|
72
81
|
.sum::<usize>();
|
|
73
82
|
|
|
74
|
-
let
|
|
83
|
+
let next_values_file = tempfile().map_err(PyRuntimeError::new_err)?;
|
|
84
|
+
next_values_file
|
|
85
|
+
.set_len((len * mem::size_of::<NumberType>()) as u64)
|
|
75
86
|
.map_err(PyRuntimeError::new_err)?;
|
|
87
|
+
#[allow(unsafe_code)]
|
|
88
|
+
let mut next_values =
|
|
89
|
+
unsafe { MmapMut::map_mut(&next_values_file).map_err(PyRuntimeError::new_err)? };
|
|
76
90
|
assert!(
|
|
77
91
|
next_values
|
|
78
92
|
.len()
|
|
79
93
|
.is_multiple_of(mem::size_of::<NumberType>())
|
|
80
94
|
);
|
|
81
95
|
let next_values_data: &mut [NumberType] = cast_slice_mut(&mut next_values[..]);
|
|
96
|
+
|
|
82
97
|
let mut zero_index = 0usize;
|
|
83
98
|
let mut one_index = zeros_count;
|
|
84
99
|
for (bit, value) in iter::zip(
|
|
@@ -101,19 +116,19 @@ where
|
|
|
101
116
|
}
|
|
102
117
|
|
|
103
118
|
zeros_count_per_layer.push(zeros_count);
|
|
104
|
-
layer_blocks_vec.push(
|
|
119
|
+
layer_blocks_vec.push((
|
|
105
120
|
current_layer_bits
|
|
106
121
|
.make_read_only()
|
|
107
122
|
.map_err(PyRuntimeError::new_err)?,
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
123
|
+
current_layer_bits_file,
|
|
124
|
+
));
|
|
125
|
+
values = next_values;
|
|
126
|
+
_values_file = next_values_file;
|
|
112
127
|
}
|
|
113
128
|
|
|
114
129
|
let layers = layer_blocks_vec
|
|
115
130
|
.into_par_iter()
|
|
116
|
-
.map(|blocks| DiskBitVector::new(blocks, len))
|
|
131
|
+
.map(|(blocks, blocks_file)| DiskBitVector::new(blocks, blocks_file, len))
|
|
117
132
|
.collect::<PyResult<Vec<_>>>()?;
|
|
118
133
|
|
|
119
134
|
Ok(Self {
|
|
@@ -164,32 +179,55 @@ where
|
|
|
164
179
|
|
|
165
180
|
#[cfg(test)]
|
|
166
181
|
mod tests {
|
|
182
|
+
use num_bigint::BigUint;
|
|
167
183
|
use pyo3::Python;
|
|
168
184
|
|
|
169
185
|
use super::*;
|
|
170
186
|
|
|
171
187
|
fn create_u8() -> DiskWaveletMatrix<u8> {
|
|
172
188
|
let elements: Vec<u8> = vec![5, 4, 5, 5, 2, 1, 5, 6, 1, 3, 5, 0];
|
|
173
|
-
let
|
|
189
|
+
let file = tempfile().map_err(PyRuntimeError::new_err).unwrap();
|
|
190
|
+
file.set_len((elements.len() * mem::size_of::<u8>()) as u64)
|
|
191
|
+
.unwrap();
|
|
192
|
+
#[allow(unsafe_code)]
|
|
193
|
+
let mut mmap = unsafe {
|
|
194
|
+
MmapMut::map_mut(&file)
|
|
195
|
+
.map_err(PyRuntimeError::new_err)
|
|
196
|
+
.unwrap()
|
|
197
|
+
};
|
|
174
198
|
let mmap_data: &mut [u8] = cast_slice_mut(&mut mmap[..]);
|
|
175
199
|
mmap_data.copy_from_slice(&elements);
|
|
176
|
-
DiskWaveletMatrix::new(mmap
|
|
200
|
+
DiskWaveletMatrix::new(mmap, file).unwrap()
|
|
177
201
|
}
|
|
178
202
|
|
|
179
203
|
fn create_u128() -> DiskWaveletMatrix<u128> {
|
|
180
204
|
let elements: Vec<u128> = vec![5u128, 4, 5, 5, 2, 1, 5, 6, 1, 3, 5, 0];
|
|
181
|
-
let
|
|
205
|
+
let file = tempfile().map_err(PyRuntimeError::new_err).unwrap();
|
|
206
|
+
file.set_len((elements.len() * mem::size_of::<u128>()) as u64)
|
|
207
|
+
.unwrap();
|
|
208
|
+
#[allow(unsafe_code)]
|
|
209
|
+
let mut mmap = unsafe {
|
|
210
|
+
MmapMut::map_mut(&file)
|
|
211
|
+
.map_err(PyRuntimeError::new_err)
|
|
212
|
+
.unwrap()
|
|
213
|
+
};
|
|
182
214
|
let mmap_data: &mut [u128] = cast_slice_mut(&mut mmap[..]);
|
|
183
215
|
mmap_data.copy_from_slice(&elements);
|
|
184
|
-
DiskWaveletMatrix::new(mmap
|
|
216
|
+
DiskWaveletMatrix::new(mmap, file).unwrap()
|
|
185
217
|
}
|
|
186
218
|
|
|
187
219
|
#[test]
|
|
188
220
|
fn test_empty() {
|
|
189
221
|
Python::initialize();
|
|
190
222
|
|
|
191
|
-
let
|
|
192
|
-
|
|
223
|
+
let file = tempfile().map_err(PyRuntimeError::new_err).unwrap();
|
|
224
|
+
#[allow(unsafe_code)]
|
|
225
|
+
let mmap_empty = unsafe {
|
|
226
|
+
MmapMut::map_mut(&file)
|
|
227
|
+
.map_err(PyRuntimeError::new_err)
|
|
228
|
+
.unwrap()
|
|
229
|
+
};
|
|
230
|
+
let wv_u8 = DiskWaveletMatrix::<u8>::new(mmap_empty, file).unwrap();
|
|
193
231
|
assert_eq!(wv_u8.len(), 0);
|
|
194
232
|
assert_eq!(wv_u8.height(), 0);
|
|
195
233
|
assert_eq!(wv_u8.values().unwrap(), Vec::<u8>::new());
|
|
@@ -246,9 +284,15 @@ mod tests {
|
|
|
246
284
|
"ValueError: start must be less than end"
|
|
247
285
|
);
|
|
248
286
|
|
|
249
|
-
let
|
|
250
|
-
|
|
251
|
-
|
|
287
|
+
let file = tempfile().map_err(PyRuntimeError::new_err).unwrap();
|
|
288
|
+
file.set_len(0).unwrap();
|
|
289
|
+
#[allow(unsafe_code)]
|
|
290
|
+
let mmap_empty = unsafe {
|
|
291
|
+
MmapMut::map_mut(&file)
|
|
292
|
+
.map_err(PyRuntimeError::new_err)
|
|
293
|
+
.unwrap()
|
|
294
|
+
};
|
|
295
|
+
let wv_u128 = DiskWaveletMatrix::<u128>::new(mmap_empty, file).unwrap();
|
|
252
296
|
assert_eq!(wv_u128.height(), 0);
|
|
253
297
|
assert_eq!(wv_u128.values().unwrap(), Vec::<u128>::new());
|
|
254
298
|
assert_eq!(
|
|
@@ -315,9 +359,15 @@ mod tests {
|
|
|
315
359
|
fn test_all_zero() {
|
|
316
360
|
Python::initialize();
|
|
317
361
|
|
|
318
|
-
let
|
|
319
|
-
|
|
320
|
-
|
|
362
|
+
let file = tempfile().map_err(PyRuntimeError::new_err).unwrap();
|
|
363
|
+
file.set_len((64 * mem::size_of::<u8>()) as u64).unwrap();
|
|
364
|
+
#[allow(unsafe_code)]
|
|
365
|
+
let mmap_u8_all_zero = unsafe {
|
|
366
|
+
MmapMut::map_mut(&file)
|
|
367
|
+
.map_err(PyRuntimeError::new_err)
|
|
368
|
+
.unwrap()
|
|
369
|
+
};
|
|
370
|
+
let wv_u8 = DiskWaveletMatrix::<u8>::new(mmap_u8_all_zero, file).unwrap();
|
|
321
371
|
assert_eq!(wv_u8.len(), 64);
|
|
322
372
|
assert_eq!(wv_u8.height(), 0);
|
|
323
373
|
assert_eq!(wv_u8.values().unwrap(), vec![0u8; 64]);
|
|
@@ -334,9 +384,15 @@ mod tests {
|
|
|
334
384
|
assert_eq!(wv_u8.prev_value(0, 64, None).unwrap(), Some(0u8));
|
|
335
385
|
assert_eq!(wv_u8.next_value(0, 64, None).unwrap(), Some(0u8));
|
|
336
386
|
|
|
337
|
-
let
|
|
338
|
-
|
|
339
|
-
|
|
387
|
+
let file = tempfile().map_err(PyRuntimeError::new_err).unwrap();
|
|
388
|
+
file.set_len((64 * mem::size_of::<u128>()) as u64).unwrap();
|
|
389
|
+
#[allow(unsafe_code)]
|
|
390
|
+
let mmap_u128_all_zero = unsafe {
|
|
391
|
+
MmapMut::map_mut(&file)
|
|
392
|
+
.map_err(PyRuntimeError::new_err)
|
|
393
|
+
.unwrap()
|
|
394
|
+
};
|
|
395
|
+
let wv_u128 = DiskWaveletMatrix::<u128>::new(mmap_u128_all_zero, file).unwrap();
|
|
340
396
|
assert_eq!(wv_u128.len(), 64);
|
|
341
397
|
assert_eq!(wv_u128.height(), 0);
|
|
342
398
|
assert_eq!(wv_u128.values().unwrap(), vec![0u128; 64]);
|
|
@@ -358,11 +414,17 @@ mod tests {
|
|
|
358
414
|
fn test_max_value() {
|
|
359
415
|
Python::initialize();
|
|
360
416
|
|
|
361
|
-
let
|
|
417
|
+
let file = tempfile().map_err(PyRuntimeError::new_err).unwrap();
|
|
418
|
+
file.set_len((64 * mem::size_of::<u8>()) as u64).unwrap();
|
|
419
|
+
#[allow(unsafe_code)]
|
|
420
|
+
let mut mmap_u8_max_value = unsafe {
|
|
421
|
+
MmapMut::map_mut(&file)
|
|
422
|
+
.map_err(PyRuntimeError::new_err)
|
|
423
|
+
.unwrap()
|
|
424
|
+
};
|
|
362
425
|
let mmap_u8_data: &mut [u8] = cast_slice_mut(&mut mmap_u8_max_value[..]);
|
|
363
426
|
mmap_u8_data.fill(u8::MAX);
|
|
364
|
-
let wv_u8 =
|
|
365
|
-
DiskWaveletMatrix::<u8>::new(mmap_u8_max_value.make_read_only().unwrap()).unwrap();
|
|
427
|
+
let wv_u8 = DiskWaveletMatrix::<u8>::new(mmap_u8_max_value, file).unwrap();
|
|
366
428
|
assert_eq!(wv_u8.len(), 64);
|
|
367
429
|
assert_eq!(wv_u8.height(), 8);
|
|
368
430
|
assert_eq!(wv_u8.values().unwrap(), vec![u8::MAX; 64]);
|
|
@@ -381,6 +443,36 @@ mod tests {
|
|
|
381
443
|
assert_eq!(wv_u8.range_mink(0, 64, None).unwrap().len(), 1);
|
|
382
444
|
assert_eq!(wv_u8.prev_value(0, 64, None).unwrap(), Some(u8::MAX));
|
|
383
445
|
assert_eq!(wv_u8.next_value(0, 64, None).unwrap(), Some(u8::MAX));
|
|
446
|
+
|
|
447
|
+
let file = tempfile().map_err(PyRuntimeError::new_err).unwrap();
|
|
448
|
+
file.set_len((64 * mem::size_of::<u128>()) as u64).unwrap();
|
|
449
|
+
#[allow(unsafe_code)]
|
|
450
|
+
let mut mmap_u128_max_value = unsafe {
|
|
451
|
+
MmapMut::map_mut(&file)
|
|
452
|
+
.map_err(PyRuntimeError::new_err)
|
|
453
|
+
.unwrap()
|
|
454
|
+
};
|
|
455
|
+
let mmap_u128_data: &mut [u128] = cast_slice_mut(&mut mmap_u128_max_value[..]);
|
|
456
|
+
mmap_u128_data.fill(u128::MAX);
|
|
457
|
+
let wv_u128 = DiskWaveletMatrix::<u128>::new(mmap_u128_max_value, file).unwrap();
|
|
458
|
+
assert_eq!(wv_u128.len(), 64);
|
|
459
|
+
assert_eq!(wv_u128.height(), 128);
|
|
460
|
+
assert_eq!(wv_u128.values().unwrap(), vec![u128::MAX; 64]);
|
|
461
|
+
assert_eq!(wv_u128.access(1).unwrap(), u128::MAX);
|
|
462
|
+
assert_eq!(wv_u128.rank(&u128::MAX, 1).unwrap(), 1);
|
|
463
|
+
assert_eq!(wv_u128.select(&u128::MAX, 1).unwrap(), Some(0));
|
|
464
|
+
assert_eq!(wv_u128.quantile(0, 64, 1).unwrap(), u128::MAX);
|
|
465
|
+
assert_eq!(wv_u128.topk(0, 64, None).unwrap().len(), 1);
|
|
466
|
+
assert_eq!(
|
|
467
|
+
wv_u128.range_sum(0, 64).unwrap(),
|
|
468
|
+
BigUint::from(u128::MAX) * 64u128,
|
|
469
|
+
);
|
|
470
|
+
assert_eq!(wv_u128.range_freq(0, 64, None, None).unwrap(), 64usize);
|
|
471
|
+
assert_eq!(wv_u128.range_list(0, 64, None, None).unwrap().len(), 1);
|
|
472
|
+
assert_eq!(wv_u128.range_maxk(0, 64, None).unwrap().len(), 1);
|
|
473
|
+
assert_eq!(wv_u128.range_mink(0, 64, None).unwrap().len(), 1);
|
|
474
|
+
assert_eq!(wv_u128.prev_value(0, 64, None).unwrap(), Some(u128::MAX));
|
|
475
|
+
assert_eq!(wv_u128.next_value(0, 64, None).unwrap(), Some(u128::MAX));
|
|
384
476
|
}
|
|
385
477
|
|
|
386
478
|
#[test]
|
|
@@ -7,8 +7,9 @@ use num_traits::Zero;
|
|
|
7
7
|
use pyo3::{
|
|
8
8
|
exceptions::{PyIndexError, PyRuntimeError, PyTypeError, PyValueError},
|
|
9
9
|
prelude::*,
|
|
10
|
-
types::{PyDict, PyInt, PyList,
|
|
10
|
+
types::{PyAny, PyDict, PyInt, PyList, PySlice, PySliceIndices},
|
|
11
11
|
};
|
|
12
|
+
use tempfile::tempfile;
|
|
12
13
|
|
|
13
14
|
use crate::{
|
|
14
15
|
disk_wavelet_matrix::disk_wavelet_matrix::DiskWaveletMatrix,
|
|
@@ -66,7 +67,7 @@ impl PyWaveletMatrix {
|
|
|
66
67
|
/// Creates a new Wavelet Matrix from the given list or tuple of integers.
|
|
67
68
|
#[new]
|
|
68
69
|
#[pyo3(signature = (data, on_disk=false))]
|
|
69
|
-
fn new(data: &Bound<'_,
|
|
70
|
+
fn new(data: &Bound<'_, PyAny>, on_disk: bool) -> PyResult<Self> {
|
|
70
71
|
let (len, max_value) =
|
|
71
72
|
data.try_iter()?
|
|
72
73
|
.try_fold((0usize, BigUint::zero()), |(len, max_value), item| {
|
|
@@ -121,74 +122,69 @@ impl PyWaveletMatrix {
|
|
|
121
122
|
WaveletMatrixEnum::BigUint(WaveletMatrix::<BigUint>::new(values))
|
|
122
123
|
}
|
|
123
124
|
(true, 0..=8) => {
|
|
124
|
-
let
|
|
125
|
+
let file = tempfile().map_err(PyRuntimeError::new_err)?;
|
|
126
|
+
file.set_len((len * mem::size_of::<u8>()) as u64)
|
|
125
127
|
.map_err(PyRuntimeError::new_err)?;
|
|
128
|
+
#[allow(unsafe_code)]
|
|
129
|
+
let mut values =
|
|
130
|
+
unsafe { MmapMut::map_mut(&file).map_err(PyRuntimeError::new_err)? };
|
|
126
131
|
let values_data: &mut [u8] = cast_slice_mut(&mut values[..]);
|
|
127
|
-
data.try_iter()
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
Ok::<_, PyErr>(())
|
|
132
|
-
})?;
|
|
133
|
-
WaveletMatrixEnum::DiskU8(DiskWaveletMatrix::<u8>::new(
|
|
134
|
-
values.make_read_only().unwrap(),
|
|
135
|
-
)?)
|
|
132
|
+
for (i, item) in data.try_iter()?.enumerate() {
|
|
133
|
+
values_data[i] = item?.extract::<u8>().map_err(PyValueError::new_err)?;
|
|
134
|
+
}
|
|
135
|
+
WaveletMatrixEnum::DiskU8(DiskWaveletMatrix::<u8>::new(values, file)?)
|
|
136
136
|
}
|
|
137
137
|
(true, 9..=16) => {
|
|
138
|
-
let
|
|
138
|
+
let file = tempfile().map_err(PyRuntimeError::new_err)?;
|
|
139
|
+
file.set_len((len * mem::size_of::<u16>()) as u64)
|
|
139
140
|
.map_err(PyRuntimeError::new_err)?;
|
|
141
|
+
#[allow(unsafe_code)]
|
|
142
|
+
let mut values =
|
|
143
|
+
unsafe { MmapMut::map_mut(&file).map_err(PyRuntimeError::new_err)? };
|
|
140
144
|
let values_data: &mut [u16] = cast_slice_mut(&mut values[..]);
|
|
141
|
-
data.try_iter()
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
Ok::<_, PyErr>(())
|
|
146
|
-
})?;
|
|
147
|
-
WaveletMatrixEnum::DiskU16(DiskWaveletMatrix::<u16>::new(
|
|
148
|
-
values.make_read_only().unwrap(),
|
|
149
|
-
)?)
|
|
145
|
+
for (i, item) in data.try_iter()?.enumerate() {
|
|
146
|
+
values_data[i] = item?.extract::<u16>().map_err(PyValueError::new_err)?;
|
|
147
|
+
}
|
|
148
|
+
WaveletMatrixEnum::DiskU16(DiskWaveletMatrix::<u16>::new(values, file)?)
|
|
150
149
|
}
|
|
151
150
|
(true, 17..=32) => {
|
|
152
|
-
let
|
|
151
|
+
let file = tempfile().map_err(PyRuntimeError::new_err)?;
|
|
152
|
+
file.set_len((len * mem::size_of::<u32>()) as u64)
|
|
153
153
|
.map_err(PyRuntimeError::new_err)?;
|
|
154
|
+
#[allow(unsafe_code)]
|
|
155
|
+
let mut values =
|
|
156
|
+
unsafe { MmapMut::map_mut(&file).map_err(PyRuntimeError::new_err)? };
|
|
154
157
|
let values_data: &mut [u32] = cast_slice_mut(&mut values[..]);
|
|
155
|
-
data.try_iter()
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
Ok::<_, PyErr>(())
|
|
160
|
-
})?;
|
|
161
|
-
WaveletMatrixEnum::DiskU32(DiskWaveletMatrix::<u32>::new(
|
|
162
|
-
values.make_read_only().unwrap(),
|
|
163
|
-
)?)
|
|
158
|
+
for (i, item) in data.try_iter()?.enumerate() {
|
|
159
|
+
values_data[i] = item?.extract::<u32>().map_err(PyValueError::new_err)?;
|
|
160
|
+
}
|
|
161
|
+
WaveletMatrixEnum::DiskU32(DiskWaveletMatrix::<u32>::new(values, file)?)
|
|
164
162
|
}
|
|
165
163
|
(true, 33..=64) => {
|
|
166
|
-
let
|
|
164
|
+
let file = tempfile().map_err(PyRuntimeError::new_err)?;
|
|
165
|
+
file.set_len((len * mem::size_of::<u64>()) as u64)
|
|
167
166
|
.map_err(PyRuntimeError::new_err)?;
|
|
167
|
+
#[allow(unsafe_code)]
|
|
168
|
+
let mut values =
|
|
169
|
+
unsafe { MmapMut::map_mut(&file).map_err(PyRuntimeError::new_err)? };
|
|
168
170
|
let values_data: &mut [u64] = cast_slice_mut(&mut values[..]);
|
|
169
|
-
data.try_iter()
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
Ok::<_, PyErr>(())
|
|
174
|
-
})?;
|
|
175
|
-
WaveletMatrixEnum::DiskU64(DiskWaveletMatrix::<u64>::new(
|
|
176
|
-
values.make_read_only().unwrap(),
|
|
177
|
-
)?)
|
|
171
|
+
for (i, item) in data.try_iter()?.enumerate() {
|
|
172
|
+
values_data[i] = item?.extract::<u64>().map_err(PyValueError::new_err)?;
|
|
173
|
+
}
|
|
174
|
+
WaveletMatrixEnum::DiskU64(DiskWaveletMatrix::<u64>::new(values, file)?)
|
|
178
175
|
}
|
|
179
176
|
(true, 65..=128) => {
|
|
180
|
-
let
|
|
177
|
+
let file = tempfile().map_err(PyRuntimeError::new_err)?;
|
|
178
|
+
file.set_len((len * mem::size_of::<u128>()) as u64)
|
|
181
179
|
.map_err(PyRuntimeError::new_err)?;
|
|
180
|
+
#[allow(unsafe_code)]
|
|
181
|
+
let mut values =
|
|
182
|
+
unsafe { MmapMut::map_mut(&file).map_err(PyRuntimeError::new_err)? };
|
|
182
183
|
let values_data: &mut [u128] = cast_slice_mut(&mut values[..]);
|
|
183
|
-
data.try_iter()
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
Ok::<_, PyErr>(())
|
|
188
|
-
})?;
|
|
189
|
-
WaveletMatrixEnum::DiskU128(DiskWaveletMatrix::<u128>::new(
|
|
190
|
-
values.make_read_only().unwrap(),
|
|
191
|
-
)?)
|
|
184
|
+
for (i, item) in data.try_iter()?.enumerate() {
|
|
185
|
+
values_data[i] = item?.extract::<u128>().map_err(PyValueError::new_err)?;
|
|
186
|
+
}
|
|
187
|
+
WaveletMatrixEnum::DiskU128(DiskWaveletMatrix::<u128>::new(values, file)?)
|
|
192
188
|
}
|
|
193
189
|
(true, _) => {
|
|
194
190
|
return Err(PyValueError::new_err(
|
|
@@ -1150,9 +1146,9 @@ mod tests {
|
|
|
1150
1146
|
Python::attach(|py| {
|
|
1151
1147
|
let elements = vec![5, 4, 5, 5, 2, 1, 5, 6, 1, 3, 5, 0];
|
|
1152
1148
|
let pylist = PyList::new(py, &elements).unwrap();
|
|
1153
|
-
let
|
|
1154
|
-
let wm = PyWaveletMatrix::new(
|
|
1155
|
-
let disk_wm = PyWaveletMatrix::new(
|
|
1149
|
+
let pyany = pylist.cast::<PyAny>().unwrap();
|
|
1150
|
+
let wm = PyWaveletMatrix::new(pyany, false).unwrap();
|
|
1151
|
+
let disk_wm = PyWaveletMatrix::new(pyany, true).unwrap();
|
|
1156
1152
|
|
|
1157
1153
|
assert_eq!(wm.__len__(py).unwrap(), elements.len());
|
|
1158
1154
|
assert_eq!(disk_wm.__len__(py).unwrap(), elements.len());
|
|
@@ -1534,9 +1530,9 @@ mod tests {
|
|
|
1534
1530
|
0 << 8,
|
|
1535
1531
|
];
|
|
1536
1532
|
let pylist = PyList::new(py, &elements).unwrap();
|
|
1537
|
-
let
|
|
1538
|
-
let wm = PyWaveletMatrix::new(
|
|
1539
|
-
let disk_wm = PyWaveletMatrix::new(
|
|
1533
|
+
let pyany = pylist.cast::<PyAny>().unwrap();
|
|
1534
|
+
let wm = PyWaveletMatrix::new(pyany, false).unwrap();
|
|
1535
|
+
let disk_wm = PyWaveletMatrix::new(pyany, true).unwrap();
|
|
1540
1536
|
|
|
1541
1537
|
assert_eq!(wm.__len__(py).unwrap(), elements.len());
|
|
1542
1538
|
assert_eq!(disk_wm.__len__(py).unwrap(), elements.len());
|
|
@@ -1918,9 +1914,9 @@ mod tests {
|
|
|
1918
1914
|
0 << 16,
|
|
1919
1915
|
];
|
|
1920
1916
|
let pylist = PyList::new(py, &elements).unwrap();
|
|
1921
|
-
let
|
|
1922
|
-
let wm = PyWaveletMatrix::new(
|
|
1923
|
-
let disk_wm = PyWaveletMatrix::new(
|
|
1917
|
+
let pyany = pylist.cast::<PyAny>().unwrap();
|
|
1918
|
+
let wm = PyWaveletMatrix::new(pyany, false).unwrap();
|
|
1919
|
+
let disk_wm = PyWaveletMatrix::new(pyany, true).unwrap();
|
|
1924
1920
|
|
|
1925
1921
|
assert_eq!(wm.__len__(py).unwrap(), elements.len());
|
|
1926
1922
|
assert_eq!(disk_wm.__len__(py).unwrap(), elements.len());
|
|
@@ -2302,9 +2298,9 @@ mod tests {
|
|
|
2302
2298
|
0 << 32,
|
|
2303
2299
|
];
|
|
2304
2300
|
let pylist = PyList::new(py, &elements).unwrap();
|
|
2305
|
-
let
|
|
2306
|
-
let wm = PyWaveletMatrix::new(
|
|
2307
|
-
let disk_wm = PyWaveletMatrix::new(
|
|
2301
|
+
let pyany = pylist.cast::<PyAny>().unwrap();
|
|
2302
|
+
let wm = PyWaveletMatrix::new(pyany, false).unwrap();
|
|
2303
|
+
let disk_wm = PyWaveletMatrix::new(pyany, true).unwrap();
|
|
2308
2304
|
|
|
2309
2305
|
assert_eq!(wm.__len__(py).unwrap(), elements.len());
|
|
2310
2306
|
assert_eq!(disk_wm.__len__(py).unwrap(), elements.len());
|
|
@@ -2686,9 +2682,9 @@ mod tests {
|
|
|
2686
2682
|
0 << 64,
|
|
2687
2683
|
];
|
|
2688
2684
|
let pylist = PyList::new(py, &elements).unwrap();
|
|
2689
|
-
let
|
|
2690
|
-
let wm = PyWaveletMatrix::new(
|
|
2691
|
-
let disk_wm = PyWaveletMatrix::new(
|
|
2685
|
+
let pyany = pylist.cast::<PyAny>().unwrap();
|
|
2686
|
+
let wm = PyWaveletMatrix::new(pyany, false).unwrap();
|
|
2687
|
+
let disk_wm = PyWaveletMatrix::new(pyany, true).unwrap();
|
|
2692
2688
|
|
|
2693
2689
|
assert_eq!(wm.__len__(py).unwrap(), elements.len());
|
|
2694
2690
|
assert_eq!(disk_wm.__len__(py).unwrap(), elements.len());
|
|
@@ -3074,8 +3070,8 @@ mod tests {
|
|
|
3074
3070
|
BigUint::from(0u32) << 128,
|
|
3075
3071
|
];
|
|
3076
3072
|
let pylist = elements.clone().into_pyobject(py).unwrap();
|
|
3077
|
-
let
|
|
3078
|
-
let wm = PyWaveletMatrix::new(
|
|
3073
|
+
let pyany = pylist.cast::<PyAny>().unwrap();
|
|
3074
|
+
let wm = PyWaveletMatrix::new(pyany, false).unwrap();
|
|
3079
3075
|
|
|
3080
3076
|
assert_eq!(wm.__len__(py).unwrap(), elements.len());
|
|
3081
3077
|
assert_eq!(
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
use std::{collections, hash, iter, ops};
|
|
2
2
|
|
|
3
|
+
use itertools::Itertools;
|
|
3
4
|
use num_bigint::ToBigUint;
|
|
4
5
|
use num_traits::{One, Zero};
|
|
5
6
|
use rayon::prelude::*;
|
|
@@ -46,8 +47,8 @@ where
|
|
|
46
47
|
.par_iter()
|
|
47
48
|
.map(|value| (value >> (height - i - 1) & NumberType::one()).is_one())
|
|
48
49
|
.collect::<Vec<bool>>();
|
|
49
|
-
let zeros_count = current_layer_bits.par_iter().filter(|&&b| !b).count();
|
|
50
50
|
|
|
51
|
+
let zeros_count = current_layer_bits.par_iter().filter(|&&b| !b).count();
|
|
51
52
|
let mut next_values = vec![NumberType::one(); len];
|
|
52
53
|
let mut zero_index = 0usize;
|
|
53
54
|
let mut one_index = zeros_count;
|
|
@@ -62,19 +63,17 @@ where
|
|
|
62
63
|
}
|
|
63
64
|
|
|
64
65
|
let current_layer_blocks = current_layer_bits
|
|
65
|
-
.
|
|
66
|
+
.into_iter()
|
|
66
67
|
.chunks(BlockType::BITS as usize)
|
|
68
|
+
.into_iter()
|
|
67
69
|
.map(|chunk| {
|
|
68
|
-
chunk
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
acc
|
|
76
|
-
}
|
|
77
|
-
})
|
|
70
|
+
chunk.enumerate().fold(BlockType::zero(), |acc, (j, b)| {
|
|
71
|
+
if b {
|
|
72
|
+
acc | (BlockType::one() << j)
|
|
73
|
+
} else {
|
|
74
|
+
acc
|
|
75
|
+
}
|
|
76
|
+
})
|
|
78
77
|
})
|
|
79
78
|
.collect::<Vec<_>>();
|
|
80
79
|
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{wavelet_matrix-2.2.1 → wavelet_matrix-2.2.2}/src/dynamic_wavelet_matrix/dynamic_bit_vector.rs
RENAMED
|
File without changes
|
{wavelet_matrix-2.2.1 → wavelet_matrix-2.2.2}/src/dynamic_wavelet_matrix/dynamic_wavelet_matrix.rs
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{wavelet_matrix-2.2.1 → wavelet_matrix-2.2.2}/src/traits/wavelet_matrix/dynamic_wavelet_matrix.rs
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|