statspai-hdfe 0.8.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.
- statspai_hdfe-0.8.0/Cargo.lock +375 -0
- statspai_hdfe-0.8.0/Cargo.toml +34 -0
- statspai_hdfe-0.8.0/PKG-INFO +117 -0
- statspai_hdfe-0.8.0/README.md +99 -0
- statspai_hdfe-0.8.0/pyproject.toml +28 -0
- statspai_hdfe-0.8.0/src/cholesky.rs +195 -0
- statspai_hdfe-0.8.0/src/cluster.rs +213 -0
- statspai_hdfe-0.8.0/src/coef.rs +1090 -0
- statspai_hdfe-0.8.0/src/demean.rs +948 -0
- statspai_hdfe-0.8.0/src/irls.rs +345 -0
- statspai_hdfe-0.8.0/src/lib.rs +736 -0
- statspai_hdfe-0.8.0/src/pool.rs +119 -0
- statspai_hdfe-0.8.0/src/separation.rs +132 -0
- statspai_hdfe-0.8.0/src/singletons.rs +90 -0
|
@@ -0,0 +1,375 @@
|
|
|
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.5.0"
|
|
8
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
9
|
+
checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8"
|
|
10
|
+
|
|
11
|
+
[[package]]
|
|
12
|
+
name = "bitflags"
|
|
13
|
+
version = "2.11.1"
|
|
14
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
15
|
+
checksum = "c4512299f36f043ab09a583e57bceb5a5aab7a73db1805848e8fef3c9e8c78b3"
|
|
16
|
+
|
|
17
|
+
[[package]]
|
|
18
|
+
name = "cfg-if"
|
|
19
|
+
version = "1.0.4"
|
|
20
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
21
|
+
checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801"
|
|
22
|
+
|
|
23
|
+
[[package]]
|
|
24
|
+
name = "crossbeam-deque"
|
|
25
|
+
version = "0.8.6"
|
|
26
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
27
|
+
checksum = "9dd111b7b7f7d55b72c0a6ae361660ee5853c9af73f70c3c2ef6858b950e2e51"
|
|
28
|
+
dependencies = [
|
|
29
|
+
"crossbeam-epoch",
|
|
30
|
+
"crossbeam-utils",
|
|
31
|
+
]
|
|
32
|
+
|
|
33
|
+
[[package]]
|
|
34
|
+
name = "crossbeam-epoch"
|
|
35
|
+
version = "0.9.18"
|
|
36
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
37
|
+
checksum = "5b82ac4a3c2ca9c3460964f020e1402edd5753411d7737aa39c3714ad1b5420e"
|
|
38
|
+
dependencies = [
|
|
39
|
+
"crossbeam-utils",
|
|
40
|
+
]
|
|
41
|
+
|
|
42
|
+
[[package]]
|
|
43
|
+
name = "crossbeam-utils"
|
|
44
|
+
version = "0.8.21"
|
|
45
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
46
|
+
checksum = "d0a5c400df2834b80a4c3327b3aad3a4c4cd4de0629063962b03235697506a28"
|
|
47
|
+
|
|
48
|
+
[[package]]
|
|
49
|
+
name = "either"
|
|
50
|
+
version = "1.15.0"
|
|
51
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
52
|
+
checksum = "48c757948c5ede0e46177b7add2e67155f70e33c07fea8284df6576da70b3719"
|
|
53
|
+
|
|
54
|
+
[[package]]
|
|
55
|
+
name = "heck"
|
|
56
|
+
version = "0.4.1"
|
|
57
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
58
|
+
checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8"
|
|
59
|
+
|
|
60
|
+
[[package]]
|
|
61
|
+
name = "indoc"
|
|
62
|
+
version = "2.0.7"
|
|
63
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
64
|
+
checksum = "79cf5c93f93228cf8efb3ba362535fb11199ac548a09ce117c9b1adc3030d706"
|
|
65
|
+
dependencies = [
|
|
66
|
+
"rustversion",
|
|
67
|
+
]
|
|
68
|
+
|
|
69
|
+
[[package]]
|
|
70
|
+
name = "libc"
|
|
71
|
+
version = "0.2.186"
|
|
72
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
73
|
+
checksum = "68ab91017fe16c622486840e4c83c9a37afeff978bd239b5293d61ece587de66"
|
|
74
|
+
|
|
75
|
+
[[package]]
|
|
76
|
+
name = "lock_api"
|
|
77
|
+
version = "0.4.14"
|
|
78
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
79
|
+
checksum = "224399e74b87b5f3557511d98dff8b14089b3dadafcab6bb93eab67d3aace965"
|
|
80
|
+
dependencies = [
|
|
81
|
+
"scopeguard",
|
|
82
|
+
]
|
|
83
|
+
|
|
84
|
+
[[package]]
|
|
85
|
+
name = "matrixmultiply"
|
|
86
|
+
version = "0.3.10"
|
|
87
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
88
|
+
checksum = "a06de3016e9fae57a36fd14dba131fccf49f74b40b7fbdb472f96e361ec71a08"
|
|
89
|
+
dependencies = [
|
|
90
|
+
"autocfg",
|
|
91
|
+
"rawpointer",
|
|
92
|
+
]
|
|
93
|
+
|
|
94
|
+
[[package]]
|
|
95
|
+
name = "memoffset"
|
|
96
|
+
version = "0.9.1"
|
|
97
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
98
|
+
checksum = "488016bfae457b036d996092f6cb448677611ce4449e970ceaf42695203f218a"
|
|
99
|
+
dependencies = [
|
|
100
|
+
"autocfg",
|
|
101
|
+
]
|
|
102
|
+
|
|
103
|
+
[[package]]
|
|
104
|
+
name = "ndarray"
|
|
105
|
+
version = "0.15.6"
|
|
106
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
107
|
+
checksum = "adb12d4e967ec485a5f71c6311fe28158e9d6f4bc4a447b474184d0f91a8fa32"
|
|
108
|
+
dependencies = [
|
|
109
|
+
"matrixmultiply",
|
|
110
|
+
"num-complex",
|
|
111
|
+
"num-integer",
|
|
112
|
+
"num-traits",
|
|
113
|
+
"rawpointer",
|
|
114
|
+
]
|
|
115
|
+
|
|
116
|
+
[[package]]
|
|
117
|
+
name = "num-complex"
|
|
118
|
+
version = "0.4.6"
|
|
119
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
120
|
+
checksum = "73f88a1307638156682bada9d7604135552957b7818057dcef22705b4d509495"
|
|
121
|
+
dependencies = [
|
|
122
|
+
"num-traits",
|
|
123
|
+
]
|
|
124
|
+
|
|
125
|
+
[[package]]
|
|
126
|
+
name = "num-integer"
|
|
127
|
+
version = "0.1.46"
|
|
128
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
129
|
+
checksum = "7969661fd2958a5cb096e56c8e1ad0444ac2bbcd0061bd28660485a44879858f"
|
|
130
|
+
dependencies = [
|
|
131
|
+
"num-traits",
|
|
132
|
+
]
|
|
133
|
+
|
|
134
|
+
[[package]]
|
|
135
|
+
name = "num-traits"
|
|
136
|
+
version = "0.2.19"
|
|
137
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
138
|
+
checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841"
|
|
139
|
+
dependencies = [
|
|
140
|
+
"autocfg",
|
|
141
|
+
]
|
|
142
|
+
|
|
143
|
+
[[package]]
|
|
144
|
+
name = "numpy"
|
|
145
|
+
version = "0.21.0"
|
|
146
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
147
|
+
checksum = "ec170733ca37175f5d75a5bea5911d6ff45d2cd52849ce98b685394e4f2f37f4"
|
|
148
|
+
dependencies = [
|
|
149
|
+
"libc",
|
|
150
|
+
"ndarray",
|
|
151
|
+
"num-complex",
|
|
152
|
+
"num-integer",
|
|
153
|
+
"num-traits",
|
|
154
|
+
"pyo3",
|
|
155
|
+
"rustc-hash",
|
|
156
|
+
]
|
|
157
|
+
|
|
158
|
+
[[package]]
|
|
159
|
+
name = "once_cell"
|
|
160
|
+
version = "1.21.4"
|
|
161
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
162
|
+
checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50"
|
|
163
|
+
|
|
164
|
+
[[package]]
|
|
165
|
+
name = "parking_lot"
|
|
166
|
+
version = "0.12.5"
|
|
167
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
168
|
+
checksum = "93857453250e3077bd71ff98b6a65ea6621a19bb0f559a85248955ac12c45a1a"
|
|
169
|
+
dependencies = [
|
|
170
|
+
"lock_api",
|
|
171
|
+
"parking_lot_core",
|
|
172
|
+
]
|
|
173
|
+
|
|
174
|
+
[[package]]
|
|
175
|
+
name = "parking_lot_core"
|
|
176
|
+
version = "0.9.12"
|
|
177
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
178
|
+
checksum = "2621685985a2ebf1c516881c026032ac7deafcda1a2c9b7850dc81e3dfcb64c1"
|
|
179
|
+
dependencies = [
|
|
180
|
+
"cfg-if",
|
|
181
|
+
"libc",
|
|
182
|
+
"redox_syscall",
|
|
183
|
+
"smallvec",
|
|
184
|
+
"windows-link",
|
|
185
|
+
]
|
|
186
|
+
|
|
187
|
+
[[package]]
|
|
188
|
+
name = "portable-atomic"
|
|
189
|
+
version = "1.13.1"
|
|
190
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
191
|
+
checksum = "c33a9471896f1c69cecef8d20cbe2f7accd12527ce60845ff44c153bb2a21b49"
|
|
192
|
+
|
|
193
|
+
[[package]]
|
|
194
|
+
name = "proc-macro2"
|
|
195
|
+
version = "1.0.106"
|
|
196
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
197
|
+
checksum = "8fd00f0bb2e90d81d1044c2b32617f68fcb9fa3bb7640c23e9c748e53fb30934"
|
|
198
|
+
dependencies = [
|
|
199
|
+
"unicode-ident",
|
|
200
|
+
]
|
|
201
|
+
|
|
202
|
+
[[package]]
|
|
203
|
+
name = "pyo3"
|
|
204
|
+
version = "0.21.2"
|
|
205
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
206
|
+
checksum = "a5e00b96a521718e08e03b1a622f01c8a8deb50719335de3f60b3b3950f069d8"
|
|
207
|
+
dependencies = [
|
|
208
|
+
"cfg-if",
|
|
209
|
+
"indoc",
|
|
210
|
+
"libc",
|
|
211
|
+
"memoffset",
|
|
212
|
+
"parking_lot",
|
|
213
|
+
"portable-atomic",
|
|
214
|
+
"pyo3-build-config",
|
|
215
|
+
"pyo3-ffi",
|
|
216
|
+
"pyo3-macros",
|
|
217
|
+
"unindent",
|
|
218
|
+
]
|
|
219
|
+
|
|
220
|
+
[[package]]
|
|
221
|
+
name = "pyo3-build-config"
|
|
222
|
+
version = "0.21.2"
|
|
223
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
224
|
+
checksum = "7883df5835fafdad87c0d888b266c8ec0f4c9ca48a5bed6bbb592e8dedee1b50"
|
|
225
|
+
dependencies = [
|
|
226
|
+
"once_cell",
|
|
227
|
+
"target-lexicon",
|
|
228
|
+
]
|
|
229
|
+
|
|
230
|
+
[[package]]
|
|
231
|
+
name = "pyo3-ffi"
|
|
232
|
+
version = "0.21.2"
|
|
233
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
234
|
+
checksum = "01be5843dc60b916ab4dad1dca6d20b9b4e6ddc8e15f50c47fe6d85f1fb97403"
|
|
235
|
+
dependencies = [
|
|
236
|
+
"libc",
|
|
237
|
+
"pyo3-build-config",
|
|
238
|
+
]
|
|
239
|
+
|
|
240
|
+
[[package]]
|
|
241
|
+
name = "pyo3-macros"
|
|
242
|
+
version = "0.21.2"
|
|
243
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
244
|
+
checksum = "77b34069fc0682e11b31dbd10321cbf94808394c56fd996796ce45217dfac53c"
|
|
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.21.2"
|
|
255
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
256
|
+
checksum = "08260721f32db5e1a5beae69a55553f56b99bd0e1c3e6e0a5e8851a9d0f5a85c"
|
|
257
|
+
dependencies = [
|
|
258
|
+
"heck",
|
|
259
|
+
"proc-macro2",
|
|
260
|
+
"pyo3-build-config",
|
|
261
|
+
"quote",
|
|
262
|
+
"syn",
|
|
263
|
+
]
|
|
264
|
+
|
|
265
|
+
[[package]]
|
|
266
|
+
name = "quote"
|
|
267
|
+
version = "1.0.45"
|
|
268
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
269
|
+
checksum = "41f2619966050689382d2b44f664f4bc593e129785a36d6ee376ddf37259b924"
|
|
270
|
+
dependencies = [
|
|
271
|
+
"proc-macro2",
|
|
272
|
+
]
|
|
273
|
+
|
|
274
|
+
[[package]]
|
|
275
|
+
name = "rawpointer"
|
|
276
|
+
version = "0.2.1"
|
|
277
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
278
|
+
checksum = "60a357793950651c4ed0f3f52338f53b2f809f32d83a07f72909fa13e4c6c1e3"
|
|
279
|
+
|
|
280
|
+
[[package]]
|
|
281
|
+
name = "rayon"
|
|
282
|
+
version = "1.12.0"
|
|
283
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
284
|
+
checksum = "fb39b166781f92d482534ef4b4b1b2568f42613b53e5b6c160e24cfbfa30926d"
|
|
285
|
+
dependencies = [
|
|
286
|
+
"either",
|
|
287
|
+
"rayon-core",
|
|
288
|
+
]
|
|
289
|
+
|
|
290
|
+
[[package]]
|
|
291
|
+
name = "rayon-core"
|
|
292
|
+
version = "1.13.0"
|
|
293
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
294
|
+
checksum = "22e18b0f0062d30d4230b2e85ff77fdfe4326feb054b9783a3460d8435c8ab91"
|
|
295
|
+
dependencies = [
|
|
296
|
+
"crossbeam-deque",
|
|
297
|
+
"crossbeam-utils",
|
|
298
|
+
]
|
|
299
|
+
|
|
300
|
+
[[package]]
|
|
301
|
+
name = "redox_syscall"
|
|
302
|
+
version = "0.5.18"
|
|
303
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
304
|
+
checksum = "ed2bf2547551a7053d6fdfafda3f938979645c44812fbfcda098faae3f1a362d"
|
|
305
|
+
dependencies = [
|
|
306
|
+
"bitflags",
|
|
307
|
+
]
|
|
308
|
+
|
|
309
|
+
[[package]]
|
|
310
|
+
name = "rustc-hash"
|
|
311
|
+
version = "1.1.0"
|
|
312
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
313
|
+
checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2"
|
|
314
|
+
|
|
315
|
+
[[package]]
|
|
316
|
+
name = "rustversion"
|
|
317
|
+
version = "1.0.22"
|
|
318
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
319
|
+
checksum = "b39cdef0fa800fc44525c84ccb54a029961a8215f9619753635a9c0d2538d46d"
|
|
320
|
+
|
|
321
|
+
[[package]]
|
|
322
|
+
name = "scopeguard"
|
|
323
|
+
version = "1.2.0"
|
|
324
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
325
|
+
checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49"
|
|
326
|
+
|
|
327
|
+
[[package]]
|
|
328
|
+
name = "smallvec"
|
|
329
|
+
version = "1.15.1"
|
|
330
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
331
|
+
checksum = "67b1b7a3b5fe4f1376887184045fcf45c69e92af734b7aaddc05fb777b6fbd03"
|
|
332
|
+
|
|
333
|
+
[[package]]
|
|
334
|
+
name = "statspai_hdfe"
|
|
335
|
+
version = "0.8.0"
|
|
336
|
+
dependencies = [
|
|
337
|
+
"numpy",
|
|
338
|
+
"pyo3",
|
|
339
|
+
"rayon",
|
|
340
|
+
]
|
|
341
|
+
|
|
342
|
+
[[package]]
|
|
343
|
+
name = "syn"
|
|
344
|
+
version = "2.0.117"
|
|
345
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
346
|
+
checksum = "e665b8803e7b1d2a727f4023456bbbbe74da67099c585258af0ad9c5013b9b99"
|
|
347
|
+
dependencies = [
|
|
348
|
+
"proc-macro2",
|
|
349
|
+
"quote",
|
|
350
|
+
"unicode-ident",
|
|
351
|
+
]
|
|
352
|
+
|
|
353
|
+
[[package]]
|
|
354
|
+
name = "target-lexicon"
|
|
355
|
+
version = "0.12.16"
|
|
356
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
357
|
+
checksum = "61c41af27dd6d1e27b1b16b489db798443478cef1f06a660c96db617ba5de3b1"
|
|
358
|
+
|
|
359
|
+
[[package]]
|
|
360
|
+
name = "unicode-ident"
|
|
361
|
+
version = "1.0.24"
|
|
362
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
363
|
+
checksum = "e6e4313cd5fcd3dad5cafa179702e2b244f760991f45397d14d4ebf38247da75"
|
|
364
|
+
|
|
365
|
+
[[package]]
|
|
366
|
+
name = "unindent"
|
|
367
|
+
version = "0.2.4"
|
|
368
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
369
|
+
checksum = "7264e107f553ccae879d21fbea1d6724ac785e8c3bfc762137959b5802826ef3"
|
|
370
|
+
|
|
371
|
+
[[package]]
|
|
372
|
+
name = "windows-link"
|
|
373
|
+
version = "0.2.1"
|
|
374
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
375
|
+
checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5"
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
[package]
|
|
2
|
+
name = "statspai_hdfe"
|
|
3
|
+
version = "0.8.0"
|
|
4
|
+
edition = "2021"
|
|
5
|
+
authors = ["Bryce Wang <brycew6m@stanford.edu>"]
|
|
6
|
+
description = "Rust kernels (HDFE demeaning, Poisson IRLS, cluster meat) for the StatsPAI Python package"
|
|
7
|
+
license = "MIT"
|
|
8
|
+
readme = "README.md"
|
|
9
|
+
rust-version = "1.80"
|
|
10
|
+
repository = "https://github.com/brycewang-stanford/StatsPAI"
|
|
11
|
+
|
|
12
|
+
[lib]
|
|
13
|
+
name = "statspai_hdfe"
|
|
14
|
+
crate-type = ["cdylib"]
|
|
15
|
+
|
|
16
|
+
[dependencies]
|
|
17
|
+
# abi3: one wheel per platform serves every CPython >= 3.10 (the floor
|
|
18
|
+
# of StatsPAI's ``requires-python``).
|
|
19
|
+
pyo3 = { version = "0.21", features = ["abi3-py310"] }
|
|
20
|
+
numpy = "0.21"
|
|
21
|
+
rayon = "1.10"
|
|
22
|
+
|
|
23
|
+
[features]
|
|
24
|
+
# maturin turns this on (pyproject.toml); plain ``cargo test`` leaves it
|
|
25
|
+
# off so the test binary links against libpython.
|
|
26
|
+
extension-module = ["pyo3/extension-module"]
|
|
27
|
+
|
|
28
|
+
[profile.release]
|
|
29
|
+
opt-level = 3
|
|
30
|
+
lto = "fat"
|
|
31
|
+
codegen-units = 1
|
|
32
|
+
# Unwind, not abort: PyO3 turns a panic into a Python exception only
|
|
33
|
+
# when it can unwind; with "abort" any bug would kill the interpreter.
|
|
34
|
+
panic = "unwind"
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: statspai-hdfe
|
|
3
|
+
Version: 0.8.0
|
|
4
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
5
|
+
Classifier: Programming Language :: Rust
|
|
6
|
+
Classifier: Programming Language :: Python :: 3
|
|
7
|
+
Classifier: Programming Language :: Python :: Implementation :: CPython
|
|
8
|
+
Classifier: Topic :: Scientific/Engineering :: Mathematics
|
|
9
|
+
Requires-Dist: numpy>=1.20
|
|
10
|
+
Summary: Rust kernels for StatsPAI: HDFE demeaning, Poisson IRLS, cluster-robust meat
|
|
11
|
+
Author-email: Biaoyue Wang <brycew6m@stanford.edu>
|
|
12
|
+
License: MIT
|
|
13
|
+
Requires-Python: >=3.10
|
|
14
|
+
Description-Content-Type: text/markdown; charset=UTF-8; variant=GFM
|
|
15
|
+
Project-URL: Homepage, https://github.com/brycewang-stanford/StatsPAI
|
|
16
|
+
Project-URL: Source, https://github.com/brycewang-stanford/StatsPAI/tree/main/rust/statspai_hdfe
|
|
17
|
+
|
|
18
|
+
# statspai-hdfe
|
|
19
|
+
|
|
20
|
+
Rust kernels for [StatsPAI](https://github.com/brycewang-stanford/StatsPAI):
|
|
21
|
+
high-dimensional fixed-effect (HDFE) demeaning, the native Poisson IRLS
|
|
22
|
+
behind `sp.fast.fepois`, and the cluster-robust sandwich meat.
|
|
23
|
+
|
|
24
|
+
```bash
|
|
25
|
+
pip install "statspai[rust]" # or: pip install statspai-hdfe
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
StatsPAI never requires this package. Without it the same functions run
|
|
29
|
+
on NumPy / Numba and agree with the Rust path to within the
|
|
30
|
+
residualisation tolerance. Check which one is in use:
|
|
31
|
+
|
|
32
|
+
```python
|
|
33
|
+
import statspai as sp
|
|
34
|
+
sp.fast.backend_info() # {'available': True, 'version': '0.8.0', 'threads': 8, ...}
|
|
35
|
+
sp.fast.set_num_threads(4) # or set STATSPAI_NUM_THREADS before starting Python
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
`STATSPAI_SKIP_RUST=1` makes StatsPAI ignore an installed extension.
|
|
39
|
+
|
|
40
|
+
## What uses it
|
|
41
|
+
|
|
42
|
+
| StatsPAI entry point | Kernel |
|
|
43
|
+
| --- | --- |
|
|
44
|
+
| `sp.fast.feols`, `sp.fast.demean`, `sp.fast.within`, `sp.fast.event_study` | `demean_2d` |
|
|
45
|
+
| `sp.fast.feols(weights=)`, `sp.ppmlhdfe` (two or more FEs) | `demean_2d_weighted` |
|
|
46
|
+
| `sp.fast.fepois` | `fepois_irls`, `separation_mask` |
|
|
47
|
+
| `sp.iv(absorb=)`, `sp.didregress`, `sp.iv.iv_diag`, weak-IV diagnostics | `demean_2d` |
|
|
48
|
+
| `sp.regress(cluster=)` (one-way) | `cluster_meat` |
|
|
49
|
+
| singleton pruning in `sp.fast` | `singleton_mask` |
|
|
50
|
+
|
|
51
|
+
`sp.hdfe_ols` / `sp.Absorber`, `sp.panel` and the pyfixest-backed
|
|
52
|
+
`sp.feols` do not use it.
|
|
53
|
+
|
|
54
|
+
## Algorithm
|
|
55
|
+
|
|
56
|
+
The fixed-effect projection is solved in the space of FE coefficients,
|
|
57
|
+
as `fixest` does (Bergé 2018; `paper.bib` key `berge2018efficient`):
|
|
58
|
+
|
|
59
|
+
* **Two FEs.** One Gauss-Seidel sweep needs only the group sums of the
|
|
60
|
+
column and the sparse cross-tabulation of the two FEs, so it costs
|
|
61
|
+
`O(nnz)` instead of `O(n)`; on panels where a unit meets few levels of
|
|
62
|
+
the other FE (worker x firm, firm x year) that is a small fraction of
|
|
63
|
+
the rows. The iteration runs on the coefficients of the smaller FE and
|
|
64
|
+
is accelerated with Irons-Tuck at every step.
|
|
65
|
+
* **Three or more FEs.** The two FEs with the most levels form a block
|
|
66
|
+
solved by the two-FE routine (warm-started) inside an outer
|
|
67
|
+
Gauss-Seidel over the others, accelerated with Irons-Tuck. The inner
|
|
68
|
+
tolerance starts loose and follows the outer change down.
|
|
69
|
+
* **Stopping rule.** Stop when the bound on the change of the residual
|
|
70
|
+
between two sweeps is at most `tol_abs + tol_rel * max|x|`, the rule of
|
|
71
|
+
the NumPy reference in `statspai.fast.demean`.
|
|
72
|
+
* **IRLS.** The FE structure is built once per `fepois` call; each
|
|
73
|
+
iteration re-weights it and restarts every column from its FE
|
|
74
|
+
coefficients of the previous iteration.
|
|
75
|
+
|
|
76
|
+
Columns are processed in parallel. The cluster meat sums fixed blocks of
|
|
77
|
+
clusters in parallel and adds the block sums in order, so its result is
|
|
78
|
+
the same at any thread count; the demeaning is per column and therefore
|
|
79
|
+
also independent of the thread count.
|
|
80
|
+
|
|
81
|
+
## Safety
|
|
82
|
+
|
|
83
|
+
Every entry point validates lengths, contiguity and code ranges before
|
|
84
|
+
running and raises `ValueError` on bad input. The crate is built with
|
|
85
|
+
`panic = "unwind"`, so an unexpected panic surfaces as a Python exception
|
|
86
|
+
instead of aborting the interpreter. The kernels run on their own thread
|
|
87
|
+
pool (never Rayon's global one), which is rebuilt in a forked child.
|
|
88
|
+
|
|
89
|
+
## Build from source
|
|
90
|
+
|
|
91
|
+
```bash
|
|
92
|
+
pip install maturin
|
|
93
|
+
cd rust/statspai_hdfe
|
|
94
|
+
maturin develop --release # into the active environment
|
|
95
|
+
maturin build --release # a wheel in target/wheels
|
|
96
|
+
PYO3_PYTHON=python cargo test --release
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
Wheels are abi3: one per platform serves every CPython >= 3.10. The
|
|
100
|
+
`rust-hdfe` GitHub workflow tests the crate on Linux, macOS and Windows,
|
|
101
|
+
builds wheels on demand, and publishes on an `hdfe-v*` tag.
|
|
102
|
+
|
|
103
|
+
## Kernel API
|
|
104
|
+
|
|
105
|
+
`statspai_hdfe.API_VERSION` names the interface level; StatsPAI ignores
|
|
106
|
+
an extension older than the level it was written against
|
|
107
|
+
(`statspai._rust_backend.MIN_API_VERSION`) and warns once.
|
|
108
|
+
|
|
109
|
+
| Level | Crate | Change |
|
|
110
|
+
| --- | --- | --- |
|
|
111
|
+
| 1 | 0.1 – 0.7 | data-space alternating projections; inputs not validated |
|
|
112
|
+
| 2 | 0.8 | coefficient-space solver; validated inputs; `fepois_irls` reports `singular` / `fe_converged`; thread-pool control; reproducible `cluster_meat` |
|
|
113
|
+
|
|
114
|
+
## License
|
|
115
|
+
|
|
116
|
+
MIT.
|
|
117
|
+
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
# statspai-hdfe
|
|
2
|
+
|
|
3
|
+
Rust kernels for [StatsPAI](https://github.com/brycewang-stanford/StatsPAI):
|
|
4
|
+
high-dimensional fixed-effect (HDFE) demeaning, the native Poisson IRLS
|
|
5
|
+
behind `sp.fast.fepois`, and the cluster-robust sandwich meat.
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
pip install "statspai[rust]" # or: pip install statspai-hdfe
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
StatsPAI never requires this package. Without it the same functions run
|
|
12
|
+
on NumPy / Numba and agree with the Rust path to within the
|
|
13
|
+
residualisation tolerance. Check which one is in use:
|
|
14
|
+
|
|
15
|
+
```python
|
|
16
|
+
import statspai as sp
|
|
17
|
+
sp.fast.backend_info() # {'available': True, 'version': '0.8.0', 'threads': 8, ...}
|
|
18
|
+
sp.fast.set_num_threads(4) # or set STATSPAI_NUM_THREADS before starting Python
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
`STATSPAI_SKIP_RUST=1` makes StatsPAI ignore an installed extension.
|
|
22
|
+
|
|
23
|
+
## What uses it
|
|
24
|
+
|
|
25
|
+
| StatsPAI entry point | Kernel |
|
|
26
|
+
| --- | --- |
|
|
27
|
+
| `sp.fast.feols`, `sp.fast.demean`, `sp.fast.within`, `sp.fast.event_study` | `demean_2d` |
|
|
28
|
+
| `sp.fast.feols(weights=)`, `sp.ppmlhdfe` (two or more FEs) | `demean_2d_weighted` |
|
|
29
|
+
| `sp.fast.fepois` | `fepois_irls`, `separation_mask` |
|
|
30
|
+
| `sp.iv(absorb=)`, `sp.didregress`, `sp.iv.iv_diag`, weak-IV diagnostics | `demean_2d` |
|
|
31
|
+
| `sp.regress(cluster=)` (one-way) | `cluster_meat` |
|
|
32
|
+
| singleton pruning in `sp.fast` | `singleton_mask` |
|
|
33
|
+
|
|
34
|
+
`sp.hdfe_ols` / `sp.Absorber`, `sp.panel` and the pyfixest-backed
|
|
35
|
+
`sp.feols` do not use it.
|
|
36
|
+
|
|
37
|
+
## Algorithm
|
|
38
|
+
|
|
39
|
+
The fixed-effect projection is solved in the space of FE coefficients,
|
|
40
|
+
as `fixest` does (Bergé 2018; `paper.bib` key `berge2018efficient`):
|
|
41
|
+
|
|
42
|
+
* **Two FEs.** One Gauss-Seidel sweep needs only the group sums of the
|
|
43
|
+
column and the sparse cross-tabulation of the two FEs, so it costs
|
|
44
|
+
`O(nnz)` instead of `O(n)`; on panels where a unit meets few levels of
|
|
45
|
+
the other FE (worker x firm, firm x year) that is a small fraction of
|
|
46
|
+
the rows. The iteration runs on the coefficients of the smaller FE and
|
|
47
|
+
is accelerated with Irons-Tuck at every step.
|
|
48
|
+
* **Three or more FEs.** The two FEs with the most levels form a block
|
|
49
|
+
solved by the two-FE routine (warm-started) inside an outer
|
|
50
|
+
Gauss-Seidel over the others, accelerated with Irons-Tuck. The inner
|
|
51
|
+
tolerance starts loose and follows the outer change down.
|
|
52
|
+
* **Stopping rule.** Stop when the bound on the change of the residual
|
|
53
|
+
between two sweeps is at most `tol_abs + tol_rel * max|x|`, the rule of
|
|
54
|
+
the NumPy reference in `statspai.fast.demean`.
|
|
55
|
+
* **IRLS.** The FE structure is built once per `fepois` call; each
|
|
56
|
+
iteration re-weights it and restarts every column from its FE
|
|
57
|
+
coefficients of the previous iteration.
|
|
58
|
+
|
|
59
|
+
Columns are processed in parallel. The cluster meat sums fixed blocks of
|
|
60
|
+
clusters in parallel and adds the block sums in order, so its result is
|
|
61
|
+
the same at any thread count; the demeaning is per column and therefore
|
|
62
|
+
also independent of the thread count.
|
|
63
|
+
|
|
64
|
+
## Safety
|
|
65
|
+
|
|
66
|
+
Every entry point validates lengths, contiguity and code ranges before
|
|
67
|
+
running and raises `ValueError` on bad input. The crate is built with
|
|
68
|
+
`panic = "unwind"`, so an unexpected panic surfaces as a Python exception
|
|
69
|
+
instead of aborting the interpreter. The kernels run on their own thread
|
|
70
|
+
pool (never Rayon's global one), which is rebuilt in a forked child.
|
|
71
|
+
|
|
72
|
+
## Build from source
|
|
73
|
+
|
|
74
|
+
```bash
|
|
75
|
+
pip install maturin
|
|
76
|
+
cd rust/statspai_hdfe
|
|
77
|
+
maturin develop --release # into the active environment
|
|
78
|
+
maturin build --release # a wheel in target/wheels
|
|
79
|
+
PYO3_PYTHON=python cargo test --release
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
Wheels are abi3: one per platform serves every CPython >= 3.10. The
|
|
83
|
+
`rust-hdfe` GitHub workflow tests the crate on Linux, macOS and Windows,
|
|
84
|
+
builds wheels on demand, and publishes on an `hdfe-v*` tag.
|
|
85
|
+
|
|
86
|
+
## Kernel API
|
|
87
|
+
|
|
88
|
+
`statspai_hdfe.API_VERSION` names the interface level; StatsPAI ignores
|
|
89
|
+
an extension older than the level it was written against
|
|
90
|
+
(`statspai._rust_backend.MIN_API_VERSION`) and warns once.
|
|
91
|
+
|
|
92
|
+
| Level | Crate | Change |
|
|
93
|
+
| --- | --- | --- |
|
|
94
|
+
| 1 | 0.1 – 0.7 | data-space alternating projections; inputs not validated |
|
|
95
|
+
| 2 | 0.8 | coefficient-space solver; validated inputs; `fepois_irls` reports `singular` / `fe_converged`; thread-pool control; reproducible `cluster_meat` |
|
|
96
|
+
|
|
97
|
+
## License
|
|
98
|
+
|
|
99
|
+
MIT.
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["maturin>=1.5,<2.0"]
|
|
3
|
+
build-backend = "maturin"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "statspai-hdfe"
|
|
7
|
+
description = "Rust kernels for StatsPAI: HDFE demeaning, Poisson IRLS, cluster-robust meat"
|
|
8
|
+
readme = "README.md"
|
|
9
|
+
license = { text = "MIT" }
|
|
10
|
+
authors = [{ name = "Biaoyue Wang", email = "brycew6m@stanford.edu" }]
|
|
11
|
+
requires-python = ">=3.10"
|
|
12
|
+
dependencies = ["numpy>=1.20"]
|
|
13
|
+
dynamic = ["version"]
|
|
14
|
+
classifiers = [
|
|
15
|
+
"License :: OSI Approved :: MIT License",
|
|
16
|
+
"Programming Language :: Rust",
|
|
17
|
+
"Programming Language :: Python :: 3",
|
|
18
|
+
"Programming Language :: Python :: Implementation :: CPython",
|
|
19
|
+
"Topic :: Scientific/Engineering :: Mathematics",
|
|
20
|
+
]
|
|
21
|
+
|
|
22
|
+
[project.urls]
|
|
23
|
+
Homepage = "https://github.com/brycewang-stanford/StatsPAI"
|
|
24
|
+
Source = "https://github.com/brycewang-stanford/StatsPAI/tree/main/rust/statspai_hdfe"
|
|
25
|
+
|
|
26
|
+
[tool.maturin]
|
|
27
|
+
module-name = "statspai_hdfe"
|
|
28
|
+
features = ["extension-module"]
|