lophat 0.1.0__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.
- lophat-0.1.0/.gitignore +73 -0
- lophat-0.1.0/Cargo.lock +408 -0
- lophat-0.1.0/Cargo.toml +15 -0
- lophat-0.1.0/LICENSE +21 -0
- lophat-0.1.0/PKG-INFO +59 -0
- lophat-0.1.0/README.md +48 -0
- lophat-0.1.0/pyproject.toml +16 -0
- lophat-0.1.0/src/column.rs +55 -0
- lophat-0.1.0/src/decomposition.rs +71 -0
- lophat-0.1.0/src/lib.rs +43 -0
- lophat-0.1.0/src/lock_free.rs +98 -0
lophat-0.1.0/.gitignore
ADDED
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
/target
|
|
2
|
+
|
|
3
|
+
# Byte-compiled / optimized / DLL files
|
|
4
|
+
__pycache__/
|
|
5
|
+
.pytest_cache/
|
|
6
|
+
*.py[cod]
|
|
7
|
+
|
|
8
|
+
# C extensions
|
|
9
|
+
*.so
|
|
10
|
+
|
|
11
|
+
# Distribution / packaging
|
|
12
|
+
.Python
|
|
13
|
+
.venv/
|
|
14
|
+
.env/
|
|
15
|
+
env/
|
|
16
|
+
bin/
|
|
17
|
+
build/
|
|
18
|
+
develop-eggs/
|
|
19
|
+
dist/
|
|
20
|
+
eggs/
|
|
21
|
+
lib/
|
|
22
|
+
lib64/
|
|
23
|
+
parts/
|
|
24
|
+
sdist/
|
|
25
|
+
var/
|
|
26
|
+
include/
|
|
27
|
+
man/
|
|
28
|
+
venv/
|
|
29
|
+
*.egg-info/
|
|
30
|
+
.installed.cfg
|
|
31
|
+
*.egg
|
|
32
|
+
|
|
33
|
+
# Installer logs
|
|
34
|
+
pip-log.txt
|
|
35
|
+
pip-delete-this-directory.txt
|
|
36
|
+
pip-selfcheck.json
|
|
37
|
+
|
|
38
|
+
# Unit test / coverage reports
|
|
39
|
+
htmlcov/
|
|
40
|
+
.tox/
|
|
41
|
+
.coverage
|
|
42
|
+
.cache
|
|
43
|
+
nosetests.xml
|
|
44
|
+
coverage.xml
|
|
45
|
+
|
|
46
|
+
# Translations
|
|
47
|
+
*.mo
|
|
48
|
+
|
|
49
|
+
# Mr Developer
|
|
50
|
+
.mr.developer.cfg
|
|
51
|
+
.project
|
|
52
|
+
.pydevproject
|
|
53
|
+
|
|
54
|
+
# Rope
|
|
55
|
+
.ropeproject
|
|
56
|
+
|
|
57
|
+
# Django stuff:
|
|
58
|
+
*.log
|
|
59
|
+
*.pot
|
|
60
|
+
|
|
61
|
+
.DS_Store
|
|
62
|
+
|
|
63
|
+
# Sphinx documentation
|
|
64
|
+
docs/_build/
|
|
65
|
+
|
|
66
|
+
# PyCharm
|
|
67
|
+
.idea/
|
|
68
|
+
|
|
69
|
+
# VSCode
|
|
70
|
+
.vscode/
|
|
71
|
+
|
|
72
|
+
# Pyenv
|
|
73
|
+
.python-version
|
lophat-0.1.0/Cargo.lock
ADDED
|
@@ -0,0 +1,408 @@
|
|
|
1
|
+
# This file is automatically @generated by Cargo.
|
|
2
|
+
# It is not intended for manual editing.
|
|
3
|
+
version = 3
|
|
4
|
+
|
|
5
|
+
[[package]]
|
|
6
|
+
name = "autocfg"
|
|
7
|
+
version = "1.1.0"
|
|
8
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
9
|
+
checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa"
|
|
10
|
+
|
|
11
|
+
[[package]]
|
|
12
|
+
name = "bitflags"
|
|
13
|
+
version = "1.3.2"
|
|
14
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
15
|
+
checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
|
|
16
|
+
|
|
17
|
+
[[package]]
|
|
18
|
+
name = "cfg-if"
|
|
19
|
+
version = "1.0.0"
|
|
20
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
21
|
+
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
|
|
22
|
+
|
|
23
|
+
[[package]]
|
|
24
|
+
name = "crossbeam"
|
|
25
|
+
version = "0.8.2"
|
|
26
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
27
|
+
checksum = "2801af0d36612ae591caa9568261fddce32ce6e08a7275ea334a06a4ad021a2c"
|
|
28
|
+
dependencies = [
|
|
29
|
+
"cfg-if",
|
|
30
|
+
"crossbeam-channel",
|
|
31
|
+
"crossbeam-deque",
|
|
32
|
+
"crossbeam-epoch",
|
|
33
|
+
"crossbeam-queue",
|
|
34
|
+
"crossbeam-utils",
|
|
35
|
+
]
|
|
36
|
+
|
|
37
|
+
[[package]]
|
|
38
|
+
name = "crossbeam-channel"
|
|
39
|
+
version = "0.5.7"
|
|
40
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
41
|
+
checksum = "cf2b3e8478797446514c91ef04bafcb59faba183e621ad488df88983cc14128c"
|
|
42
|
+
dependencies = [
|
|
43
|
+
"cfg-if",
|
|
44
|
+
"crossbeam-utils",
|
|
45
|
+
]
|
|
46
|
+
|
|
47
|
+
[[package]]
|
|
48
|
+
name = "crossbeam-deque"
|
|
49
|
+
version = "0.8.3"
|
|
50
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
51
|
+
checksum = "ce6fd6f855243022dcecf8702fef0c297d4338e226845fe067f6341ad9fa0cef"
|
|
52
|
+
dependencies = [
|
|
53
|
+
"cfg-if",
|
|
54
|
+
"crossbeam-epoch",
|
|
55
|
+
"crossbeam-utils",
|
|
56
|
+
]
|
|
57
|
+
|
|
58
|
+
[[package]]
|
|
59
|
+
name = "crossbeam-epoch"
|
|
60
|
+
version = "0.9.14"
|
|
61
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
62
|
+
checksum = "46bd5f3f85273295a9d14aedfb86f6aadbff6d8f5295c4a9edb08e819dcf5695"
|
|
63
|
+
dependencies = [
|
|
64
|
+
"autocfg",
|
|
65
|
+
"cfg-if",
|
|
66
|
+
"crossbeam-utils",
|
|
67
|
+
"memoffset",
|
|
68
|
+
"scopeguard",
|
|
69
|
+
]
|
|
70
|
+
|
|
71
|
+
[[package]]
|
|
72
|
+
name = "crossbeam-queue"
|
|
73
|
+
version = "0.3.8"
|
|
74
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
75
|
+
checksum = "d1cfb3ea8a53f37c40dea2c7bedcbd88bdfae54f5e2175d6ecaff1c988353add"
|
|
76
|
+
dependencies = [
|
|
77
|
+
"cfg-if",
|
|
78
|
+
"crossbeam-utils",
|
|
79
|
+
]
|
|
80
|
+
|
|
81
|
+
[[package]]
|
|
82
|
+
name = "crossbeam-utils"
|
|
83
|
+
version = "0.8.15"
|
|
84
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
85
|
+
checksum = "3c063cd8cc95f5c377ed0d4b49a4b21f632396ff690e8470c29b3359b346984b"
|
|
86
|
+
dependencies = [
|
|
87
|
+
"cfg-if",
|
|
88
|
+
]
|
|
89
|
+
|
|
90
|
+
[[package]]
|
|
91
|
+
name = "either"
|
|
92
|
+
version = "1.8.1"
|
|
93
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
94
|
+
checksum = "7fcaabb2fef8c910e7f4c7ce9f67a1283a1715879a7c230ca9d6d1ae31f16d91"
|
|
95
|
+
|
|
96
|
+
[[package]]
|
|
97
|
+
name = "hermit-abi"
|
|
98
|
+
version = "0.2.6"
|
|
99
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
100
|
+
checksum = "ee512640fe35acbfb4bb779db6f0d80704c2cacfa2e39b601ef3e3f47d1ae4c7"
|
|
101
|
+
dependencies = [
|
|
102
|
+
"libc",
|
|
103
|
+
]
|
|
104
|
+
|
|
105
|
+
[[package]]
|
|
106
|
+
name = "indoc"
|
|
107
|
+
version = "1.0.9"
|
|
108
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
109
|
+
checksum = "bfa799dd5ed20a7e349f3b4639aa80d74549c81716d9ec4f994c9b5815598306"
|
|
110
|
+
|
|
111
|
+
[[package]]
|
|
112
|
+
name = "libc"
|
|
113
|
+
version = "0.2.139"
|
|
114
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
115
|
+
checksum = "201de327520df007757c1f0adce6e827fe8562fbc28bfd9c15571c66ca1f5f79"
|
|
116
|
+
|
|
117
|
+
[[package]]
|
|
118
|
+
name = "lock_api"
|
|
119
|
+
version = "0.4.9"
|
|
120
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
121
|
+
checksum = "435011366fe56583b16cf956f9df0095b405b82d76425bc8981c0e22e60ec4df"
|
|
122
|
+
dependencies = [
|
|
123
|
+
"autocfg",
|
|
124
|
+
"scopeguard",
|
|
125
|
+
]
|
|
126
|
+
|
|
127
|
+
[[package]]
|
|
128
|
+
name = "lophat"
|
|
129
|
+
version = "0.1.0"
|
|
130
|
+
dependencies = [
|
|
131
|
+
"crossbeam",
|
|
132
|
+
"pinboard",
|
|
133
|
+
"pyo3",
|
|
134
|
+
"rayon",
|
|
135
|
+
]
|
|
136
|
+
|
|
137
|
+
[[package]]
|
|
138
|
+
name = "memoffset"
|
|
139
|
+
version = "0.8.0"
|
|
140
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
141
|
+
checksum = "d61c719bcfbcf5d62b3a09efa6088de8c54bc0bfcd3ea7ae39fcc186108b8de1"
|
|
142
|
+
dependencies = [
|
|
143
|
+
"autocfg",
|
|
144
|
+
]
|
|
145
|
+
|
|
146
|
+
[[package]]
|
|
147
|
+
name = "num_cpus"
|
|
148
|
+
version = "1.15.0"
|
|
149
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
150
|
+
checksum = "0fac9e2da13b5eb447a6ce3d392f23a29d8694bff781bf03a16cd9ac8697593b"
|
|
151
|
+
dependencies = [
|
|
152
|
+
"hermit-abi",
|
|
153
|
+
"libc",
|
|
154
|
+
]
|
|
155
|
+
|
|
156
|
+
[[package]]
|
|
157
|
+
name = "once_cell"
|
|
158
|
+
version = "1.17.1"
|
|
159
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
160
|
+
checksum = "b7e5500299e16ebb147ae15a00a942af264cf3688f47923b8fc2cd5858f23ad3"
|
|
161
|
+
|
|
162
|
+
[[package]]
|
|
163
|
+
name = "parking_lot"
|
|
164
|
+
version = "0.12.1"
|
|
165
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
166
|
+
checksum = "3742b2c103b9f06bc9fff0a37ff4912935851bee6d36f3c02bcc755bcfec228f"
|
|
167
|
+
dependencies = [
|
|
168
|
+
"lock_api",
|
|
169
|
+
"parking_lot_core",
|
|
170
|
+
]
|
|
171
|
+
|
|
172
|
+
[[package]]
|
|
173
|
+
name = "parking_lot_core"
|
|
174
|
+
version = "0.9.7"
|
|
175
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
176
|
+
checksum = "9069cbb9f99e3a5083476ccb29ceb1de18b9118cafa53e90c9551235de2b9521"
|
|
177
|
+
dependencies = [
|
|
178
|
+
"cfg-if",
|
|
179
|
+
"libc",
|
|
180
|
+
"redox_syscall",
|
|
181
|
+
"smallvec",
|
|
182
|
+
"windows-sys",
|
|
183
|
+
]
|
|
184
|
+
|
|
185
|
+
[[package]]
|
|
186
|
+
name = "pinboard"
|
|
187
|
+
version = "2.1.0"
|
|
188
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
189
|
+
checksum = "6502324eee9cd4cd7dc8f22b0ed7683185a09e9ddcc0ac3028e010e2721662a3"
|
|
190
|
+
dependencies = [
|
|
191
|
+
"crossbeam-epoch",
|
|
192
|
+
]
|
|
193
|
+
|
|
194
|
+
[[package]]
|
|
195
|
+
name = "proc-macro2"
|
|
196
|
+
version = "1.0.51"
|
|
197
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
198
|
+
checksum = "5d727cae5b39d21da60fa540906919ad737832fe0b1c165da3a34d6548c849d6"
|
|
199
|
+
dependencies = [
|
|
200
|
+
"unicode-ident",
|
|
201
|
+
]
|
|
202
|
+
|
|
203
|
+
[[package]]
|
|
204
|
+
name = "pyo3"
|
|
205
|
+
version = "0.18.1"
|
|
206
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
207
|
+
checksum = "06a3d8e8a46ab2738109347433cb7b96dffda2e4a218b03ef27090238886b147"
|
|
208
|
+
dependencies = [
|
|
209
|
+
"cfg-if",
|
|
210
|
+
"indoc",
|
|
211
|
+
"libc",
|
|
212
|
+
"memoffset",
|
|
213
|
+
"parking_lot",
|
|
214
|
+
"pyo3-build-config",
|
|
215
|
+
"pyo3-ffi",
|
|
216
|
+
"pyo3-macros",
|
|
217
|
+
"unindent",
|
|
218
|
+
]
|
|
219
|
+
|
|
220
|
+
[[package]]
|
|
221
|
+
name = "pyo3-build-config"
|
|
222
|
+
version = "0.18.1"
|
|
223
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
224
|
+
checksum = "75439f995d07ddfad42b192dfcf3bc66a7ecfd8b4a1f5f6f046aa5c2c5d7677d"
|
|
225
|
+
dependencies = [
|
|
226
|
+
"once_cell",
|
|
227
|
+
"target-lexicon",
|
|
228
|
+
]
|
|
229
|
+
|
|
230
|
+
[[package]]
|
|
231
|
+
name = "pyo3-ffi"
|
|
232
|
+
version = "0.18.1"
|
|
233
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
234
|
+
checksum = "839526a5c07a17ff44823679b68add4a58004de00512a95b6c1c98a6dcac0ee5"
|
|
235
|
+
dependencies = [
|
|
236
|
+
"libc",
|
|
237
|
+
"pyo3-build-config",
|
|
238
|
+
]
|
|
239
|
+
|
|
240
|
+
[[package]]
|
|
241
|
+
name = "pyo3-macros"
|
|
242
|
+
version = "0.18.1"
|
|
243
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
244
|
+
checksum = "bd44cf207476c6a9760c4653559be4f206efafb924d3e4cbf2721475fc0d6cc5"
|
|
245
|
+
dependencies = [
|
|
246
|
+
"proc-macro2",
|
|
247
|
+
"pyo3-macros-backend",
|
|
248
|
+
"quote",
|
|
249
|
+
"syn",
|
|
250
|
+
]
|
|
251
|
+
|
|
252
|
+
[[package]]
|
|
253
|
+
name = "pyo3-macros-backend"
|
|
254
|
+
version = "0.18.1"
|
|
255
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
256
|
+
checksum = "dc1f43d8e30460f36350d18631ccf85ded64c059829208fe680904c65bcd0a4c"
|
|
257
|
+
dependencies = [
|
|
258
|
+
"proc-macro2",
|
|
259
|
+
"quote",
|
|
260
|
+
"syn",
|
|
261
|
+
]
|
|
262
|
+
|
|
263
|
+
[[package]]
|
|
264
|
+
name = "quote"
|
|
265
|
+
version = "1.0.23"
|
|
266
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
267
|
+
checksum = "8856d8364d252a14d474036ea1358d63c9e6965c8e5c1885c18f73d70bff9c7b"
|
|
268
|
+
dependencies = [
|
|
269
|
+
"proc-macro2",
|
|
270
|
+
]
|
|
271
|
+
|
|
272
|
+
[[package]]
|
|
273
|
+
name = "rayon"
|
|
274
|
+
version = "1.7.0"
|
|
275
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
276
|
+
checksum = "1d2df5196e37bcc87abebc0053e20787d73847bb33134a69841207dd0a47f03b"
|
|
277
|
+
dependencies = [
|
|
278
|
+
"either",
|
|
279
|
+
"rayon-core",
|
|
280
|
+
]
|
|
281
|
+
|
|
282
|
+
[[package]]
|
|
283
|
+
name = "rayon-core"
|
|
284
|
+
version = "1.11.0"
|
|
285
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
286
|
+
checksum = "4b8f95bd6966f5c87776639160a66bd8ab9895d9d4ab01ddba9fc60661aebe8d"
|
|
287
|
+
dependencies = [
|
|
288
|
+
"crossbeam-channel",
|
|
289
|
+
"crossbeam-deque",
|
|
290
|
+
"crossbeam-utils",
|
|
291
|
+
"num_cpus",
|
|
292
|
+
]
|
|
293
|
+
|
|
294
|
+
[[package]]
|
|
295
|
+
name = "redox_syscall"
|
|
296
|
+
version = "0.2.16"
|
|
297
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
298
|
+
checksum = "fb5a58c1855b4b6819d59012155603f0b22ad30cad752600aadfcb695265519a"
|
|
299
|
+
dependencies = [
|
|
300
|
+
"bitflags",
|
|
301
|
+
]
|
|
302
|
+
|
|
303
|
+
[[package]]
|
|
304
|
+
name = "scopeguard"
|
|
305
|
+
version = "1.1.0"
|
|
306
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
307
|
+
checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd"
|
|
308
|
+
|
|
309
|
+
[[package]]
|
|
310
|
+
name = "smallvec"
|
|
311
|
+
version = "1.10.0"
|
|
312
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
313
|
+
checksum = "a507befe795404456341dfab10cef66ead4c041f62b8b11bbb92bffe5d0953e0"
|
|
314
|
+
|
|
315
|
+
[[package]]
|
|
316
|
+
name = "syn"
|
|
317
|
+
version = "1.0.109"
|
|
318
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
319
|
+
checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237"
|
|
320
|
+
dependencies = [
|
|
321
|
+
"proc-macro2",
|
|
322
|
+
"quote",
|
|
323
|
+
"unicode-ident",
|
|
324
|
+
]
|
|
325
|
+
|
|
326
|
+
[[package]]
|
|
327
|
+
name = "target-lexicon"
|
|
328
|
+
version = "0.12.6"
|
|
329
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
330
|
+
checksum = "8ae9980cab1db3fceee2f6c6f643d5d8de2997c58ee8d25fb0cc8a9e9e7348e5"
|
|
331
|
+
|
|
332
|
+
[[package]]
|
|
333
|
+
name = "unicode-ident"
|
|
334
|
+
version = "1.0.8"
|
|
335
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
336
|
+
checksum = "e5464a87b239f13a63a501f2701565754bae92d243d4bb7eb12f6d57d2269bf4"
|
|
337
|
+
|
|
338
|
+
[[package]]
|
|
339
|
+
name = "unindent"
|
|
340
|
+
version = "0.1.11"
|
|
341
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
342
|
+
checksum = "e1766d682d402817b5ac4490b3c3002d91dfa0d22812f341609f97b08757359c"
|
|
343
|
+
|
|
344
|
+
[[package]]
|
|
345
|
+
name = "windows-sys"
|
|
346
|
+
version = "0.45.0"
|
|
347
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
348
|
+
checksum = "75283be5efb2831d37ea142365f009c02ec203cd29a3ebecbc093d52315b66d0"
|
|
349
|
+
dependencies = [
|
|
350
|
+
"windows-targets",
|
|
351
|
+
]
|
|
352
|
+
|
|
353
|
+
[[package]]
|
|
354
|
+
name = "windows-targets"
|
|
355
|
+
version = "0.42.1"
|
|
356
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
357
|
+
checksum = "8e2522491fbfcd58cc84d47aeb2958948c4b8982e9a2d8a2a35bbaed431390e7"
|
|
358
|
+
dependencies = [
|
|
359
|
+
"windows_aarch64_gnullvm",
|
|
360
|
+
"windows_aarch64_msvc",
|
|
361
|
+
"windows_i686_gnu",
|
|
362
|
+
"windows_i686_msvc",
|
|
363
|
+
"windows_x86_64_gnu",
|
|
364
|
+
"windows_x86_64_gnullvm",
|
|
365
|
+
"windows_x86_64_msvc",
|
|
366
|
+
]
|
|
367
|
+
|
|
368
|
+
[[package]]
|
|
369
|
+
name = "windows_aarch64_gnullvm"
|
|
370
|
+
version = "0.42.1"
|
|
371
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
372
|
+
checksum = "8c9864e83243fdec7fc9c5444389dcbbfd258f745e7853198f365e3c4968a608"
|
|
373
|
+
|
|
374
|
+
[[package]]
|
|
375
|
+
name = "windows_aarch64_msvc"
|
|
376
|
+
version = "0.42.1"
|
|
377
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
378
|
+
checksum = "4c8b1b673ffc16c47a9ff48570a9d85e25d265735c503681332589af6253c6c7"
|
|
379
|
+
|
|
380
|
+
[[package]]
|
|
381
|
+
name = "windows_i686_gnu"
|
|
382
|
+
version = "0.42.1"
|
|
383
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
384
|
+
checksum = "de3887528ad530ba7bdbb1faa8275ec7a1155a45ffa57c37993960277145d640"
|
|
385
|
+
|
|
386
|
+
[[package]]
|
|
387
|
+
name = "windows_i686_msvc"
|
|
388
|
+
version = "0.42.1"
|
|
389
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
390
|
+
checksum = "bf4d1122317eddd6ff351aa852118a2418ad4214e6613a50e0191f7004372605"
|
|
391
|
+
|
|
392
|
+
[[package]]
|
|
393
|
+
name = "windows_x86_64_gnu"
|
|
394
|
+
version = "0.42.1"
|
|
395
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
396
|
+
checksum = "c1040f221285e17ebccbc2591ffdc2d44ee1f9186324dd3e84e99ac68d699c45"
|
|
397
|
+
|
|
398
|
+
[[package]]
|
|
399
|
+
name = "windows_x86_64_gnullvm"
|
|
400
|
+
version = "0.42.1"
|
|
401
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
402
|
+
checksum = "628bfdf232daa22b0d64fdb62b09fcc36bb01f05a3939e20ab73aaf9470d0463"
|
|
403
|
+
|
|
404
|
+
[[package]]
|
|
405
|
+
name = "windows_x86_64_msvc"
|
|
406
|
+
version = "0.42.1"
|
|
407
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
408
|
+
checksum = "447660ad36a13288b1db4d4248e857b510e8c3a225c822ba4fb748c0aafecffd"
|
lophat-0.1.0/Cargo.toml
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
[package]
|
|
2
|
+
name = "lophat"
|
|
3
|
+
version = "0.1.0"
|
|
4
|
+
edition = "2021"
|
|
5
|
+
|
|
6
|
+
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
|
7
|
+
[lib]
|
|
8
|
+
name = "lophat"
|
|
9
|
+
crate-type = ["cdylib"]
|
|
10
|
+
|
|
11
|
+
[dependencies]
|
|
12
|
+
crossbeam = "0.8.2"
|
|
13
|
+
pinboard = "2.1.0"
|
|
14
|
+
pyo3 = "0.18.1"
|
|
15
|
+
rayon = "1.7.0"
|
lophat-0.1.0/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2023 Thomas Chaplin
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
lophat-0.1.0/PKG-INFO
ADDED
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
Metadata-Version: 2.1
|
|
2
|
+
Name: lophat
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Classifier: Programming Language :: Rust
|
|
5
|
+
Classifier: Programming Language :: Python :: Implementation :: CPython
|
|
6
|
+
Classifier: Programming Language :: Python :: Implementation :: PyPy
|
|
7
|
+
License-File: LICENSE
|
|
8
|
+
Requires-Python: >=3.7
|
|
9
|
+
Description-Content-Type: text/markdown; charset=UTF-8; variant=GFM
|
|
10
|
+
|
|
11
|
+
<div align="center">
|
|
12
|
+
|
|
13
|
+
<h1>LoPHAT</h1>
|
|
14
|
+
|
|
15
|
+
<b>Lo</b>ckfree <b>P</b>ersistent <b>H</b>omology <b>A</b>lgorithm <b>T</b>oolbox
|
|
16
|
+
|
|
17
|
+
</div>
|
|
18
|
+
|
|
19
|
+
## Overview
|
|
20
|
+
|
|
21
|
+
LoPHAT is a Rust library implementing the lockfree algorithm for computing persistent homology (PH), introduced in [[1]](#1).
|
|
22
|
+
Python bindings are provided via PyO3, with an interface familiar to those who have used PHAT [[2]](#2).
|
|
23
|
+
|
|
24
|
+
The primary goal of this library is to make the algorithm accessible to those wishing to compute PH of ___arbitrary filtered chain complexes___.
|
|
25
|
+
In particular, LoPHAT is **not** specialised to compute PH of common filtrations or even filtered simplicial complexes.
|
|
26
|
+
As such, you should expect LoPHAT to under-perform as compared to [giotto-ph [3]](#3) or [oineus [4]](#4), both of which use the algorithm of [[1]](#1).
|
|
27
|
+
|
|
28
|
+
The only changes from the algorithm described in [[1]](#1) are:
|
|
29
|
+
* We use the `pinboard` library for memory managment of the matrices.
|
|
30
|
+
* We store the $j^{th}$ column of $R$ and $V$ alongside each other in memory, allowing a full $R=DV$ decomposition (rather than just computing pairings).
|
|
31
|
+
* Rather than split the matrix into chunks, we use a work-stealing paradigm, via the `rayon` library.
|
|
32
|
+
|
|
33
|
+
> **Warning**
|
|
34
|
+
> LoPHAT is currently in alpha.
|
|
35
|
+
> The implementation is not optimised, the API is not fixed and no tests have been written.
|
|
36
|
+
> Use at your own risk.
|
|
37
|
+
|
|
38
|
+
## Usage
|
|
39
|
+
|
|
40
|
+
## References
|
|
41
|
+
|
|
42
|
+
<a id="1">[1]</a> Morozov, Dmitriy, and Arnur Nigmetov.
|
|
43
|
+
"Towards lockfree persistent homology."
|
|
44
|
+
Proceedings of the 32nd ACM Symposium on Parallelism in Algorithms and Architectures. 2020.
|
|
45
|
+
|
|
46
|
+
<a id="2">[2]</a> Bauer, Ulrich, et al.
|
|
47
|
+
"Phat–persistent homology algorithms toolbox." Journal of symbolic computation 78 (2017): 76-90.
|
|
48
|
+
[Bitbucket](https://bitbucket.org/phat-code/phat/src/master/)
|
|
49
|
+
|
|
50
|
+
<a id="3">[3]</a> Pérez, Julián Burella, et al.
|
|
51
|
+
"giotto-ph: A python library for high-performance computation of persistent homology of Vietoris-Rips filtrations."
|
|
52
|
+
arXiv preprint [arXiv:2107.05412](https://arxiv.org/abs/2107.05412) (2021).
|
|
53
|
+
[GitHub](https://github.com/giotto-ai/giotto-ph)
|
|
54
|
+
|
|
55
|
+
<a id="4">[4]</a> Nigmetov, Arnur, Morozov, Dmitriy, and USDOE.
|
|
56
|
+
Oineus v1.0. Computer software.
|
|
57
|
+
[https://www.osti.gov//servlets/purl/1774764](https://www.osti.gov//servlets/purl/1774764). USDOE. 1 Apr. 2021.
|
|
58
|
+
Web. [doi:10.11578/dc.20210407.1](https://doi.org/10.11578/dc.20210407.1). [GitHub](https://github.com/anigmetov/oineus)
|
|
59
|
+
|
lophat-0.1.0/README.md
ADDED
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
<div align="center">
|
|
2
|
+
|
|
3
|
+
<h1>LoPHAT</h1>
|
|
4
|
+
|
|
5
|
+
<b>Lo</b>ckfree <b>P</b>ersistent <b>H</b>omology <b>A</b>lgorithm <b>T</b>oolbox
|
|
6
|
+
|
|
7
|
+
</div>
|
|
8
|
+
|
|
9
|
+
## Overview
|
|
10
|
+
|
|
11
|
+
LoPHAT is a Rust library implementing the lockfree algorithm for computing persistent homology (PH), introduced in [[1]](#1).
|
|
12
|
+
Python bindings are provided via PyO3, with an interface familiar to those who have used PHAT [[2]](#2).
|
|
13
|
+
|
|
14
|
+
The primary goal of this library is to make the algorithm accessible to those wishing to compute PH of ___arbitrary filtered chain complexes___.
|
|
15
|
+
In particular, LoPHAT is **not** specialised to compute PH of common filtrations or even filtered simplicial complexes.
|
|
16
|
+
As such, you should expect LoPHAT to under-perform as compared to [giotto-ph [3]](#3) or [oineus [4]](#4), both of which use the algorithm of [[1]](#1).
|
|
17
|
+
|
|
18
|
+
The only changes from the algorithm described in [[1]](#1) are:
|
|
19
|
+
* We use the `pinboard` library for memory managment of the matrices.
|
|
20
|
+
* We store the $j^{th}$ column of $R$ and $V$ alongside each other in memory, allowing a full $R=DV$ decomposition (rather than just computing pairings).
|
|
21
|
+
* Rather than split the matrix into chunks, we use a work-stealing paradigm, via the `rayon` library.
|
|
22
|
+
|
|
23
|
+
> **Warning**
|
|
24
|
+
> LoPHAT is currently in alpha.
|
|
25
|
+
> The implementation is not optimised, the API is not fixed and no tests have been written.
|
|
26
|
+
> Use at your own risk.
|
|
27
|
+
|
|
28
|
+
## Usage
|
|
29
|
+
|
|
30
|
+
## References
|
|
31
|
+
|
|
32
|
+
<a id="1">[1]</a> Morozov, Dmitriy, and Arnur Nigmetov.
|
|
33
|
+
"Towards lockfree persistent homology."
|
|
34
|
+
Proceedings of the 32nd ACM Symposium on Parallelism in Algorithms and Architectures. 2020.
|
|
35
|
+
|
|
36
|
+
<a id="2">[2]</a> Bauer, Ulrich, et al.
|
|
37
|
+
"Phat–persistent homology algorithms toolbox." Journal of symbolic computation 78 (2017): 76-90.
|
|
38
|
+
[Bitbucket](https://bitbucket.org/phat-code/phat/src/master/)
|
|
39
|
+
|
|
40
|
+
<a id="3">[3]</a> Pérez, Julián Burella, et al.
|
|
41
|
+
"giotto-ph: A python library for high-performance computation of persistent homology of Vietoris-Rips filtrations."
|
|
42
|
+
arXiv preprint [arXiv:2107.05412](https://arxiv.org/abs/2107.05412) (2021).
|
|
43
|
+
[GitHub](https://github.com/giotto-ai/giotto-ph)
|
|
44
|
+
|
|
45
|
+
<a id="4">[4]</a> Nigmetov, Arnur, Morozov, Dmitriy, and USDOE.
|
|
46
|
+
Oineus v1.0. Computer software.
|
|
47
|
+
[https://www.osti.gov//servlets/purl/1774764](https://www.osti.gov//servlets/purl/1774764). USDOE. 1 Apr. 2021.
|
|
48
|
+
Web. [doi:10.11578/dc.20210407.1](https://doi.org/10.11578/dc.20210407.1). [GitHub](https://github.com/anigmetov/oineus)
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["maturin>=0.14,<0.15"]
|
|
3
|
+
build-backend = "maturin"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "lophat"
|
|
7
|
+
requires-python = ">=3.7"
|
|
8
|
+
classifiers = [
|
|
9
|
+
"Programming Language :: Rust",
|
|
10
|
+
"Programming Language :: Python :: Implementation :: CPython",
|
|
11
|
+
"Programming Language :: Python :: Implementation :: PyPy",
|
|
12
|
+
]
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
[tool.maturin]
|
|
16
|
+
features = ["pyo3/extension-module"]
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
use std::cmp::Ordering;
|
|
2
|
+
|
|
3
|
+
pub trait Column: Sync + Clone + Send + Default {
|
|
4
|
+
fn pivot(&self) -> Option<usize>;
|
|
5
|
+
fn add_col(&mut self, other: &Self);
|
|
6
|
+
fn add_entry(&mut self, entry: usize);
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
#[derive(Debug, Default, Clone)]
|
|
10
|
+
pub struct VecColumn {
|
|
11
|
+
pub internal: Vec<usize>,
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
impl VecColumn {
|
|
15
|
+
// Returns the index where we should try to insert next entry
|
|
16
|
+
fn add_entry_starting_at(&mut self, entry: usize, starting_idx: usize) -> usize {
|
|
17
|
+
let mut working_idx = starting_idx;
|
|
18
|
+
while let Some(value_at_idx) = self.internal.iter().nth(working_idx) {
|
|
19
|
+
match value_at_idx.cmp(&entry) {
|
|
20
|
+
Ordering::Less => {
|
|
21
|
+
working_idx += 1;
|
|
22
|
+
continue;
|
|
23
|
+
}
|
|
24
|
+
Ordering::Equal => {
|
|
25
|
+
self.internal.remove(working_idx);
|
|
26
|
+
return working_idx;
|
|
27
|
+
}
|
|
28
|
+
Ordering::Greater => {
|
|
29
|
+
self.internal.insert(working_idx, entry);
|
|
30
|
+
return working_idx + 1;
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
// Bigger than all idxs in col - add to end
|
|
35
|
+
self.internal.push(entry);
|
|
36
|
+
return self.internal.len() - 1;
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
impl Column for VecColumn {
|
|
41
|
+
fn pivot(&self) -> Option<usize> {
|
|
42
|
+
self.internal.iter().last().copied()
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
fn add_entry(&mut self, entry: usize) {
|
|
46
|
+
self.add_entry_starting_at(entry, 0);
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
fn add_col(&mut self, other: &Self) {
|
|
50
|
+
let mut working_idx = 0;
|
|
51
|
+
for entry in other.internal.iter() {
|
|
52
|
+
working_idx = self.add_entry_starting_at(*entry, working_idx);
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
}
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
use crate::Column;
|
|
2
|
+
use pyo3::prelude::*;
|
|
3
|
+
use std::collections::{HashMap, HashSet};
|
|
4
|
+
|
|
5
|
+
#[pyclass]
|
|
6
|
+
#[derive(Default, Debug, Clone)]
|
|
7
|
+
pub struct PersistenceDiagram {
|
|
8
|
+
#[pyo3(get)]
|
|
9
|
+
unpaired: HashSet<usize>,
|
|
10
|
+
#[pyo3(get)]
|
|
11
|
+
paired: Vec<(usize, usize)>,
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
#[derive(Debug, Default)]
|
|
15
|
+
pub struct RVDecomposition<C: Column> {
|
|
16
|
+
pub r: Vec<C>,
|
|
17
|
+
pub v: Vec<C>,
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
fn col_idx_with_same_low<C: Column>(col: &C, low_inverse: &HashMap<usize, usize>) -> Option<usize> {
|
|
21
|
+
let pivot = col.pivot()?;
|
|
22
|
+
low_inverse.get(&pivot).copied()
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
impl<C: Column> RVDecomposition<C> {
|
|
26
|
+
// Receives column, reduces it with left-to-right addition from R
|
|
27
|
+
// Adds reduction to self
|
|
28
|
+
pub fn reduce_column(&mut self, mut column: C, low_inverse: &mut HashMap<usize, usize>) {
|
|
29
|
+
// v_col tracks how the final reduced column is built up
|
|
30
|
+
// Currently column contains 1 lot of the latest column in D
|
|
31
|
+
let mut v_col = C::default();
|
|
32
|
+
v_col.add_entry(self.r.len());
|
|
33
|
+
// Reduce the column, keeping track of how we do this in V
|
|
34
|
+
while let Some(col_idx) = col_idx_with_same_low(&column, &low_inverse) {
|
|
35
|
+
column.add_col(&self.r[col_idx]);
|
|
36
|
+
v_col.add_col(&self.v[col_idx]);
|
|
37
|
+
}
|
|
38
|
+
// Update low inverse
|
|
39
|
+
let final_pivot = column.pivot();
|
|
40
|
+
if let Some(final_pivot) = final_pivot {
|
|
41
|
+
// This column has a lowest 1 and is being inserted at the end of R
|
|
42
|
+
low_inverse.insert(final_pivot, self.r.len());
|
|
43
|
+
}
|
|
44
|
+
// Push to decomposition
|
|
45
|
+
self.r.push(column);
|
|
46
|
+
self.v.push(v_col);
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
pub fn diagram(&self) -> PersistenceDiagram {
|
|
50
|
+
let mut diagram = PersistenceDiagram::default();
|
|
51
|
+
for (idx, col) in self.r.iter().enumerate() {
|
|
52
|
+
if let Some(lowest_idx) = col.pivot() {
|
|
53
|
+
// Negative column
|
|
54
|
+
diagram.unpaired.remove(&lowest_idx);
|
|
55
|
+
diagram.paired.push((lowest_idx, idx))
|
|
56
|
+
} else {
|
|
57
|
+
// Positive column
|
|
58
|
+
diagram.unpaired.insert(idx);
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
diagram
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
pub fn rv_decompose<C: Column>(matrix: impl Iterator<Item = C>) -> RVDecomposition<C> {
|
|
66
|
+
let mut low_inverse = HashMap::new();
|
|
67
|
+
matrix.fold(RVDecomposition::default(), |mut accum, next_col| {
|
|
68
|
+
accum.reduce_column(next_col, &mut low_inverse);
|
|
69
|
+
accum
|
|
70
|
+
})
|
|
71
|
+
}
|
lophat-0.1.0/src/lib.rs
ADDED
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
use column::VecColumn;
|
|
2
|
+
use pyo3::prelude::*;
|
|
3
|
+
use pyo3::types::PyIterator;
|
|
4
|
+
|
|
5
|
+
mod column;
|
|
6
|
+
mod decomposition;
|
|
7
|
+
mod lock_free;
|
|
8
|
+
|
|
9
|
+
pub use column::Column;
|
|
10
|
+
pub use decomposition::{rv_decompose, PersistenceDiagram, RVDecomposition};
|
|
11
|
+
pub use lock_free::rv_decompose_lock_free;
|
|
12
|
+
|
|
13
|
+
#[pyfunction]
|
|
14
|
+
fn compute_pairings_serial(matrix: &PyIterator) -> PersistenceDiagram {
|
|
15
|
+
rv_decompose(matrix.map(|col| {
|
|
16
|
+
VecColumn {
|
|
17
|
+
internal: col
|
|
18
|
+
.and_then(PyAny::extract::<Vec<usize>>)
|
|
19
|
+
.expect("Column is a list of unsigned integers"),
|
|
20
|
+
}
|
|
21
|
+
}))
|
|
22
|
+
.diagram()
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
#[pyfunction]
|
|
26
|
+
fn compute_pairings(matrix: &PyIterator) -> PersistenceDiagram {
|
|
27
|
+
rv_decompose_lock_free(matrix.map(|col| {
|
|
28
|
+
VecColumn {
|
|
29
|
+
internal: col
|
|
30
|
+
.and_then(PyAny::extract::<Vec<usize>>)
|
|
31
|
+
.expect("Column is a list of unsigned integers"),
|
|
32
|
+
}
|
|
33
|
+
}))
|
|
34
|
+
.diagram()
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/// A Python module implemented in Rust.
|
|
38
|
+
#[pymodule]
|
|
39
|
+
fn lophat(_py: Python, m: &PyModule) -> PyResult<()> {
|
|
40
|
+
m.add_function(wrap_pyfunction!(compute_pairings, m)?)?;
|
|
41
|
+
m.add_function(wrap_pyfunction!(compute_pairings_serial, m)?)?;
|
|
42
|
+
Ok(())
|
|
43
|
+
}
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
use std::fmt::Debug;
|
|
2
|
+
|
|
3
|
+
use crate::Column;
|
|
4
|
+
use crate::RVDecomposition;
|
|
5
|
+
|
|
6
|
+
use crossbeam::atomic::AtomicCell;
|
|
7
|
+
use pinboard::NonEmptyPinboard;
|
|
8
|
+
use rayon::prelude::*;
|
|
9
|
+
|
|
10
|
+
// Implements do while loop lines 6-9
|
|
11
|
+
fn get_col_with_pivot<C: Column>(
|
|
12
|
+
l: usize,
|
|
13
|
+
matrix: &Vec<NonEmptyPinboard<(C, C)>>,
|
|
14
|
+
pivots: &Vec<AtomicCell<Option<usize>>>,
|
|
15
|
+
) -> Option<(usize, (C, C))> {
|
|
16
|
+
loop {
|
|
17
|
+
let piv = pivots[l].load();
|
|
18
|
+
if let Some(piv) = piv {
|
|
19
|
+
let cols = matrix[piv].read();
|
|
20
|
+
if cols.0.pivot() != Some(l) {
|
|
21
|
+
// Got a column but it now has the wrong pivot; loop again.
|
|
22
|
+
continue;
|
|
23
|
+
};
|
|
24
|
+
// Get column with correct pivot, return to caller.
|
|
25
|
+
return Some((piv, cols));
|
|
26
|
+
} else {
|
|
27
|
+
// There is not yet a column with this pivot, inform caller.
|
|
28
|
+
return None;
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
fn reduce_column<C: Column>(
|
|
34
|
+
j: usize,
|
|
35
|
+
matrix: &Vec<NonEmptyPinboard<(C, C)>>,
|
|
36
|
+
pivots: &Vec<AtomicCell<Option<usize>>>,
|
|
37
|
+
) {
|
|
38
|
+
let mut working_j = j;
|
|
39
|
+
'outer: loop {
|
|
40
|
+
let mut curr_column = matrix[working_j].read();
|
|
41
|
+
while let Some(l) = (&curr_column).0.pivot() {
|
|
42
|
+
let piv_with_column_opt = get_col_with_pivot(l, &matrix, &pivots);
|
|
43
|
+
if let Some((piv, piv_column)) = piv_with_column_opt {
|
|
44
|
+
// Lines 17-24
|
|
45
|
+
if piv < working_j {
|
|
46
|
+
curr_column.0.add_col(&piv_column.0);
|
|
47
|
+
curr_column.1.add_col(&piv_column.1);
|
|
48
|
+
} else if piv > working_j {
|
|
49
|
+
matrix[working_j].set(curr_column);
|
|
50
|
+
if pivots[l]
|
|
51
|
+
.compare_exchange(Some(piv), Some(working_j))
|
|
52
|
+
.is_ok()
|
|
53
|
+
{
|
|
54
|
+
working_j = piv;
|
|
55
|
+
}
|
|
56
|
+
continue 'outer;
|
|
57
|
+
} else {
|
|
58
|
+
panic!()
|
|
59
|
+
}
|
|
60
|
+
} else {
|
|
61
|
+
// piv = -1 case
|
|
62
|
+
matrix[working_j].set(curr_column);
|
|
63
|
+
if pivots[l].compare_exchange(None, Some(working_j)).is_ok() {
|
|
64
|
+
return;
|
|
65
|
+
} else {
|
|
66
|
+
continue 'outer;
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
// Lines 25-27 (curr_column = 0 clause)
|
|
71
|
+
if (&curr_column.0).pivot().is_none() {
|
|
72
|
+
matrix[working_j].set(curr_column);
|
|
73
|
+
return;
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
pub fn rv_decompose_lock_free<C: Column + Debug + 'static>(
|
|
79
|
+
matrix: impl Iterator<Item = C>,
|
|
80
|
+
) -> RVDecomposition<C> {
|
|
81
|
+
let matrix: Vec<_> = matrix
|
|
82
|
+
.enumerate()
|
|
83
|
+
.map(|(idx, r_col)| {
|
|
84
|
+
let mut v_col = C::default();
|
|
85
|
+
v_col.add_entry(idx);
|
|
86
|
+
NonEmptyPinboard::new((r_col, v_col))
|
|
87
|
+
})
|
|
88
|
+
.collect();
|
|
89
|
+
let pivots: Vec<_> = (0..matrix.len()).map(|_| AtomicCell::new(None)).collect();
|
|
90
|
+
// Reduce matrix
|
|
91
|
+
// TODO: Can we advice rayon to split work in chunks?
|
|
92
|
+
(0..matrix.len())
|
|
93
|
+
.into_par_iter()
|
|
94
|
+
.for_each(|j| reduce_column(j, &matrix, &pivots));
|
|
95
|
+
// Wrap into RV decomposition
|
|
96
|
+
let (r, v) = matrix.into_iter().map(|pinboard| pinboard.read()).unzip();
|
|
97
|
+
RVDecomposition { r, v }
|
|
98
|
+
}
|