xinterp 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.
@@ -0,0 +1,120 @@
1
+ # This file is autogenerated by maturin v1.4.0
2
+ # To update, run
3
+ #
4
+ # maturin generate-ci github
5
+ #
6
+ name: CI
7
+
8
+ on:
9
+ push:
10
+ branches:
11
+ - main
12
+ - master
13
+ tags:
14
+ - '*'
15
+ pull_request:
16
+ workflow_dispatch:
17
+
18
+ permissions:
19
+ contents: read
20
+
21
+ jobs:
22
+ linux:
23
+ runs-on: ubuntu-latest
24
+ strategy:
25
+ matrix:
26
+ target: [x86_64, x86, aarch64, armv7, s390x, ppc64le]
27
+ steps:
28
+ - uses: actions/checkout@v3
29
+ - uses: actions/setup-python@v4
30
+ with:
31
+ python-version: '3.10'
32
+ - name: Build wheels
33
+ uses: PyO3/maturin-action@v1
34
+ with:
35
+ target: ${{ matrix.target }}
36
+ args: --release --out dist --find-interpreter
37
+ sccache: 'true'
38
+ manylinux: auto
39
+ - name: Upload wheels
40
+ uses: actions/upload-artifact@v3
41
+ with:
42
+ name: wheels
43
+ path: dist
44
+
45
+ windows:
46
+ runs-on: windows-latest
47
+ strategy:
48
+ matrix:
49
+ target: [x64, x86]
50
+ steps:
51
+ - uses: actions/checkout@v3
52
+ - uses: actions/setup-python@v4
53
+ with:
54
+ python-version: '3.10'
55
+ architecture: ${{ matrix.target }}
56
+ - name: Build wheels
57
+ uses: PyO3/maturin-action@v1
58
+ with:
59
+ target: ${{ matrix.target }}
60
+ args: --release --out dist --find-interpreter
61
+ sccache: 'true'
62
+ - name: Upload wheels
63
+ uses: actions/upload-artifact@v3
64
+ with:
65
+ name: wheels
66
+ path: dist
67
+
68
+ macos:
69
+ runs-on: macos-latest
70
+ strategy:
71
+ matrix:
72
+ target: [x86_64, aarch64]
73
+ steps:
74
+ - uses: actions/checkout@v3
75
+ - uses: actions/setup-python@v4
76
+ with:
77
+ python-version: '3.10'
78
+ - name: Build wheels
79
+ uses: PyO3/maturin-action@v1
80
+ with:
81
+ target: ${{ matrix.target }}
82
+ args: --release --out dist --find-interpreter
83
+ sccache: 'true'
84
+ - name: Upload wheels
85
+ uses: actions/upload-artifact@v3
86
+ with:
87
+ name: wheels
88
+ path: dist
89
+
90
+ sdist:
91
+ runs-on: ubuntu-latest
92
+ steps:
93
+ - uses: actions/checkout@v3
94
+ - name: Build sdist
95
+ uses: PyO3/maturin-action@v1
96
+ with:
97
+ command: sdist
98
+ args: --out dist
99
+ - name: Upload sdist
100
+ uses: actions/upload-artifact@v3
101
+ with:
102
+ name: wheels
103
+ path: dist
104
+
105
+ release:
106
+ name: Release
107
+ runs-on: ubuntu-latest
108
+ if: "startsWith(github.ref, 'refs/tags/')"
109
+ needs: [linux, windows, macos, sdist]
110
+ steps:
111
+ - uses: actions/download-artifact@v3
112
+ with:
113
+ name: wheels
114
+ - name: Publish to PyPI
115
+ uses: PyO3/maturin-action@v1
116
+ env:
117
+ MATURIN_PYPI_TOKEN: ${{ secrets.PYPI_API_TOKEN }}
118
+ with:
119
+ command: upload
120
+ args: --non-interactive --skip-existing *
@@ -0,0 +1,75 @@
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
+ bin/
16
+ build/
17
+ develop-eggs/
18
+ dist/
19
+ eggs/
20
+ lib/
21
+ lib64/
22
+ parts/
23
+ sdist/
24
+ var/
25
+ include/
26
+ man/
27
+ venv/
28
+ *.egg-info/
29
+ .installed.cfg
30
+ *.egg
31
+
32
+ # Installer logs
33
+ pip-log.txt
34
+ pip-delete-this-directory.txt
35
+ pip-selfcheck.json
36
+
37
+ # Unit test / coverage reports
38
+ htmlcov/
39
+ .tox/
40
+ .coverage
41
+ .cache
42
+ nosetests.xml
43
+ coverage.xml
44
+
45
+ # Translations
46
+ *.mo
47
+
48
+ # Mr Developer
49
+ .mr.developer.cfg
50
+ .project
51
+ .pydevproject
52
+
53
+ # Rope
54
+ .ropeproject
55
+
56
+ # Django stuff:
57
+ *.log
58
+ *.pot
59
+
60
+ .DS_Store
61
+
62
+ # Sphinx documentation
63
+ docs/_build/
64
+
65
+ # PyCharm
66
+ .idea/
67
+
68
+ # VSCode
69
+ .vscode/
70
+
71
+ # Pyenv
72
+ .python-version
73
+
74
+ # Lock
75
+ Cargo.lock
@@ -0,0 +1,359 @@
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 = "heck"
25
+ version = "0.4.1"
26
+ source = "registry+https://github.com/rust-lang/crates.io-index"
27
+ checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8"
28
+
29
+ [[package]]
30
+ name = "indoc"
31
+ version = "2.0.4"
32
+ source = "registry+https://github.com/rust-lang/crates.io-index"
33
+ checksum = "1e186cfbae8084e513daff4240b4797e342f988cecda4fb6c939150f96315fd8"
34
+
35
+ [[package]]
36
+ name = "libc"
37
+ version = "0.2.152"
38
+ source = "registry+https://github.com/rust-lang/crates.io-index"
39
+ checksum = "13e3bf6590cbc649f4d1a3eefc9d5d6eb746f5200ffb04e5e142700b8faa56e7"
40
+
41
+ [[package]]
42
+ name = "lock_api"
43
+ version = "0.4.11"
44
+ source = "registry+https://github.com/rust-lang/crates.io-index"
45
+ checksum = "3c168f8615b12bc01f9c17e2eb0cc07dcae1940121185446edc3744920e8ef45"
46
+ dependencies = [
47
+ "autocfg",
48
+ "scopeguard",
49
+ ]
50
+
51
+ [[package]]
52
+ name = "matrixmultiply"
53
+ version = "0.3.8"
54
+ source = "registry+https://github.com/rust-lang/crates.io-index"
55
+ checksum = "7574c1cf36da4798ab73da5b215bbf444f50718207754cb522201d78d1cd0ff2"
56
+ dependencies = [
57
+ "autocfg",
58
+ "rawpointer",
59
+ ]
60
+
61
+ [[package]]
62
+ name = "memoffset"
63
+ version = "0.9.0"
64
+ source = "registry+https://github.com/rust-lang/crates.io-index"
65
+ checksum = "5a634b1c61a95585bd15607c6ab0c4e5b226e695ff2800ba0cdccddf208c406c"
66
+ dependencies = [
67
+ "autocfg",
68
+ ]
69
+
70
+ [[package]]
71
+ name = "ndarray"
72
+ version = "0.15.6"
73
+ source = "registry+https://github.com/rust-lang/crates.io-index"
74
+ checksum = "adb12d4e967ec485a5f71c6311fe28158e9d6f4bc4a447b474184d0f91a8fa32"
75
+ dependencies = [
76
+ "matrixmultiply",
77
+ "num-complex",
78
+ "num-integer",
79
+ "num-traits",
80
+ "rawpointer",
81
+ ]
82
+
83
+ [[package]]
84
+ name = "num-complex"
85
+ version = "0.4.4"
86
+ source = "registry+https://github.com/rust-lang/crates.io-index"
87
+ checksum = "1ba157ca0885411de85d6ca030ba7e2a83a28636056c7c699b07c8b6f7383214"
88
+ dependencies = [
89
+ "num-traits",
90
+ ]
91
+
92
+ [[package]]
93
+ name = "num-integer"
94
+ version = "0.1.45"
95
+ source = "registry+https://github.com/rust-lang/crates.io-index"
96
+ checksum = "225d3389fb3509a24c93f5c29eb6bde2586b98d9f016636dff58d7c6f7569cd9"
97
+ dependencies = [
98
+ "autocfg",
99
+ "num-traits",
100
+ ]
101
+
102
+ [[package]]
103
+ name = "num-traits"
104
+ version = "0.2.17"
105
+ source = "registry+https://github.com/rust-lang/crates.io-index"
106
+ checksum = "39e3200413f237f41ab11ad6d161bc7239c84dcb631773ccd7de3dfe4b5c267c"
107
+ dependencies = [
108
+ "autocfg",
109
+ ]
110
+
111
+ [[package]]
112
+ name = "numpy"
113
+ version = "0.20.0"
114
+ source = "registry+https://github.com/rust-lang/crates.io-index"
115
+ checksum = "bef41cbb417ea83b30525259e30ccef6af39b31c240bda578889494c5392d331"
116
+ dependencies = [
117
+ "libc",
118
+ "ndarray",
119
+ "num-complex",
120
+ "num-integer",
121
+ "num-traits",
122
+ "pyo3",
123
+ "rustc-hash",
124
+ ]
125
+
126
+ [[package]]
127
+ name = "once_cell"
128
+ version = "1.19.0"
129
+ source = "registry+https://github.com/rust-lang/crates.io-index"
130
+ checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92"
131
+
132
+ [[package]]
133
+ name = "parking_lot"
134
+ version = "0.12.1"
135
+ source = "registry+https://github.com/rust-lang/crates.io-index"
136
+ checksum = "3742b2c103b9f06bc9fff0a37ff4912935851bee6d36f3c02bcc755bcfec228f"
137
+ dependencies = [
138
+ "lock_api",
139
+ "parking_lot_core",
140
+ ]
141
+
142
+ [[package]]
143
+ name = "parking_lot_core"
144
+ version = "0.9.9"
145
+ source = "registry+https://github.com/rust-lang/crates.io-index"
146
+ checksum = "4c42a9226546d68acdd9c0a280d17ce19bfe27a46bf68784e4066115788d008e"
147
+ dependencies = [
148
+ "cfg-if",
149
+ "libc",
150
+ "redox_syscall",
151
+ "smallvec",
152
+ "windows-targets",
153
+ ]
154
+
155
+ [[package]]
156
+ name = "proc-macro2"
157
+ version = "1.0.76"
158
+ source = "registry+https://github.com/rust-lang/crates.io-index"
159
+ checksum = "95fc56cda0b5c3325f5fbbd7ff9fda9e02bb00bb3dac51252d2f1bfa1cb8cc8c"
160
+ dependencies = [
161
+ "unicode-ident",
162
+ ]
163
+
164
+ [[package]]
165
+ name = "pyo3"
166
+ version = "0.20.2"
167
+ source = "registry+https://github.com/rust-lang/crates.io-index"
168
+ checksum = "9a89dc7a5850d0e983be1ec2a463a171d20990487c3cfcd68b5363f1ee3d6fe0"
169
+ dependencies = [
170
+ "cfg-if",
171
+ "indoc",
172
+ "libc",
173
+ "memoffset",
174
+ "parking_lot",
175
+ "pyo3-build-config",
176
+ "pyo3-ffi",
177
+ "pyo3-macros",
178
+ "unindent",
179
+ ]
180
+
181
+ [[package]]
182
+ name = "pyo3-build-config"
183
+ version = "0.20.2"
184
+ source = "registry+https://github.com/rust-lang/crates.io-index"
185
+ checksum = "07426f0d8fe5a601f26293f300afd1a7b1ed5e78b2a705870c5f30893c5163be"
186
+ dependencies = [
187
+ "once_cell",
188
+ "target-lexicon",
189
+ ]
190
+
191
+ [[package]]
192
+ name = "pyo3-ffi"
193
+ version = "0.20.2"
194
+ source = "registry+https://github.com/rust-lang/crates.io-index"
195
+ checksum = "dbb7dec17e17766b46bca4f1a4215a85006b4c2ecde122076c562dd058da6cf1"
196
+ dependencies = [
197
+ "libc",
198
+ "pyo3-build-config",
199
+ ]
200
+
201
+ [[package]]
202
+ name = "pyo3-macros"
203
+ version = "0.20.2"
204
+ source = "registry+https://github.com/rust-lang/crates.io-index"
205
+ checksum = "05f738b4e40d50b5711957f142878cfa0f28e054aa0ebdfc3fd137a843f74ed3"
206
+ dependencies = [
207
+ "proc-macro2",
208
+ "pyo3-macros-backend",
209
+ "quote",
210
+ "syn",
211
+ ]
212
+
213
+ [[package]]
214
+ name = "pyo3-macros-backend"
215
+ version = "0.20.2"
216
+ source = "registry+https://github.com/rust-lang/crates.io-index"
217
+ checksum = "0fc910d4851847827daf9d6cdd4a823fbdaab5b8818325c5e97a86da79e8881f"
218
+ dependencies = [
219
+ "heck",
220
+ "proc-macro2",
221
+ "quote",
222
+ "syn",
223
+ ]
224
+
225
+ [[package]]
226
+ name = "quote"
227
+ version = "1.0.35"
228
+ source = "registry+https://github.com/rust-lang/crates.io-index"
229
+ checksum = "291ec9ab5efd934aaf503a6466c5d5251535d108ee747472c3977cc5acc868ef"
230
+ dependencies = [
231
+ "proc-macro2",
232
+ ]
233
+
234
+ [[package]]
235
+ name = "rawpointer"
236
+ version = "0.2.1"
237
+ source = "registry+https://github.com/rust-lang/crates.io-index"
238
+ checksum = "60a357793950651c4ed0f3f52338f53b2f809f32d83a07f72909fa13e4c6c1e3"
239
+
240
+ [[package]]
241
+ name = "redox_syscall"
242
+ version = "0.4.1"
243
+ source = "registry+https://github.com/rust-lang/crates.io-index"
244
+ checksum = "4722d768eff46b75989dd134e5c353f0d6296e5aaa3132e776cbdb56be7731aa"
245
+ dependencies = [
246
+ "bitflags",
247
+ ]
248
+
249
+ [[package]]
250
+ name = "rustc-hash"
251
+ version = "1.1.0"
252
+ source = "registry+https://github.com/rust-lang/crates.io-index"
253
+ checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2"
254
+
255
+ [[package]]
256
+ name = "scopeguard"
257
+ version = "1.2.0"
258
+ source = "registry+https://github.com/rust-lang/crates.io-index"
259
+ checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49"
260
+
261
+ [[package]]
262
+ name = "smallvec"
263
+ version = "1.12.0"
264
+ source = "registry+https://github.com/rust-lang/crates.io-index"
265
+ checksum = "2593d31f82ead8df961d8bd23a64c2ccf2eb5dd34b0a34bfb4dd54011c72009e"
266
+
267
+ [[package]]
268
+ name = "syn"
269
+ version = "2.0.48"
270
+ source = "registry+https://github.com/rust-lang/crates.io-index"
271
+ checksum = "0f3531638e407dfc0814761abb7c00a5b54992b849452a0646b7f65c9f770f3f"
272
+ dependencies = [
273
+ "proc-macro2",
274
+ "quote",
275
+ "unicode-ident",
276
+ ]
277
+
278
+ [[package]]
279
+ name = "target-lexicon"
280
+ version = "0.12.13"
281
+ source = "registry+https://github.com/rust-lang/crates.io-index"
282
+ checksum = "69758bda2e78f098e4ccb393021a0963bb3442eac05f135c30f61b7370bbafae"
283
+
284
+ [[package]]
285
+ name = "unicode-ident"
286
+ version = "1.0.12"
287
+ source = "registry+https://github.com/rust-lang/crates.io-index"
288
+ checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b"
289
+
290
+ [[package]]
291
+ name = "unindent"
292
+ version = "0.2.3"
293
+ source = "registry+https://github.com/rust-lang/crates.io-index"
294
+ checksum = "c7de7d73e1754487cb58364ee906a499937a0dfabd86bcb980fa99ec8c8fa2ce"
295
+
296
+ [[package]]
297
+ name = "windows-targets"
298
+ version = "0.48.5"
299
+ source = "registry+https://github.com/rust-lang/crates.io-index"
300
+ checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c"
301
+ dependencies = [
302
+ "windows_aarch64_gnullvm",
303
+ "windows_aarch64_msvc",
304
+ "windows_i686_gnu",
305
+ "windows_i686_msvc",
306
+ "windows_x86_64_gnu",
307
+ "windows_x86_64_gnullvm",
308
+ "windows_x86_64_msvc",
309
+ ]
310
+
311
+ [[package]]
312
+ name = "windows_aarch64_gnullvm"
313
+ version = "0.48.5"
314
+ source = "registry+https://github.com/rust-lang/crates.io-index"
315
+ checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8"
316
+
317
+ [[package]]
318
+ name = "windows_aarch64_msvc"
319
+ version = "0.48.5"
320
+ source = "registry+https://github.com/rust-lang/crates.io-index"
321
+ checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc"
322
+
323
+ [[package]]
324
+ name = "windows_i686_gnu"
325
+ version = "0.48.5"
326
+ source = "registry+https://github.com/rust-lang/crates.io-index"
327
+ checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e"
328
+
329
+ [[package]]
330
+ name = "windows_i686_msvc"
331
+ version = "0.48.5"
332
+ source = "registry+https://github.com/rust-lang/crates.io-index"
333
+ checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406"
334
+
335
+ [[package]]
336
+ name = "windows_x86_64_gnu"
337
+ version = "0.48.5"
338
+ source = "registry+https://github.com/rust-lang/crates.io-index"
339
+ checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e"
340
+
341
+ [[package]]
342
+ name = "windows_x86_64_gnullvm"
343
+ version = "0.48.5"
344
+ source = "registry+https://github.com/rust-lang/crates.io-index"
345
+ checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc"
346
+
347
+ [[package]]
348
+ name = "windows_x86_64_msvc"
349
+ version = "0.48.5"
350
+ source = "registry+https://github.com/rust-lang/crates.io-index"
351
+ checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538"
352
+
353
+ [[package]]
354
+ name = "xinterp"
355
+ version = "0.1.0"
356
+ dependencies = [
357
+ "numpy",
358
+ "pyo3",
359
+ ]
@@ -0,0 +1,13 @@
1
+ [package]
2
+ name = "xinterp"
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 = "xinterp"
9
+ crate-type = ["cdylib"]
10
+
11
+ [dependencies]
12
+ pyo3 = { version = "0.20", features = ["extension-module"] }
13
+ numpy = "0.20"
xinterp-0.1.0/PKG-INFO ADDED
@@ -0,0 +1,41 @@
1
+ Metadata-Version: 2.1
2
+ Name: xinterp
3
+ Version: 0.1.0
4
+ Classifier: Programming Language :: Rust
5
+ Classifier: Programming Language :: Python :: Implementation :: CPython
6
+ Requires-Dist: numpy
7
+ Requires-Dist: black ; extra == 'dev'
8
+ Requires-Dist: isort ; extra == 'dev'
9
+ Requires-Dist: pytest ; extra == 'dev'
10
+ Provides-Extra: dev
11
+ Requires-Python: >=3.8
12
+ Description-Content-Type: text/markdown; charset=UTF-8; variant=GFM
13
+
14
+ # xinterp
15
+
16
+ This package enables exact round to even datetime64 interpolation.
17
+
18
+ ## Installation
19
+
20
+ Clone the repository, enter the folder and:
21
+
22
+ ```
23
+ pip install -e .
24
+ ```
25
+
26
+ ## Usage
27
+
28
+ ```python
29
+ import numpy as np
30
+ from xinterp import interp_intlike
31
+
32
+ xp = np.array([0, 10, 20])
33
+ fp = np.array([0, 1000, 2000], dtype="datetime64[s]")
34
+ x = np.array([-5, 0, 5, 10, 15, 20, 25])
35
+
36
+ nat = np.datetime64("NaT")
37
+ f = interp_intlike(x, xp, fp, left=nat, right=nat)
38
+ f_expected = np.array([nat, 0, 500, 1000, 1500, 2000, nat], dtype="datetime64[s]")
39
+ assert np.array_equal(f, f_expected, equal_nan=True)
40
+ assert f.dtype == f_expected.dtype
41
+ ```
@@ -0,0 +1,28 @@
1
+ # xinterp
2
+
3
+ This package enables exact round to even datetime64 interpolation.
4
+
5
+ ## Installation
6
+
7
+ Clone the repository, enter the folder and:
8
+
9
+ ```
10
+ pip install -e .
11
+ ```
12
+
13
+ ## Usage
14
+
15
+ ```python
16
+ import numpy as np
17
+ from xinterp import interp_intlike
18
+
19
+ xp = np.array([0, 10, 20])
20
+ fp = np.array([0, 1000, 2000], dtype="datetime64[s]")
21
+ x = np.array([-5, 0, 5, 10, 15, 20, 25])
22
+
23
+ nat = np.datetime64("NaT")
24
+ f = interp_intlike(x, xp, fp, left=nat, right=nat)
25
+ f_expected = np.array([nat, 0, 500, 1000, 1500, 2000, nat], dtype="datetime64[s]")
26
+ assert np.array_equal(f, f_expected, equal_nan=True)
27
+ assert f.dtype == f_expected.dtype
28
+ ```
@@ -0,0 +1,24 @@
1
+ [build-system]
2
+ requires = ["maturin>=1.4,<2.0"]
3
+ build-backend = "maturin"
4
+
5
+ [project]
6
+ name = "xinterp"
7
+ requires-python = ">=3.8"
8
+ classifiers = [
9
+ "Programming Language :: Rust",
10
+ "Programming Language :: Python :: Implementation :: CPython",
11
+ ]
12
+ dynamic = ["version"]
13
+ dependencies = ["numpy"]
14
+
15
+ [project.optional-dependencies]
16
+ dev = [
17
+ "black",
18
+ "isort",
19
+ "pytest",
20
+ ]
21
+
22
+ [tool.maturin]
23
+ features = ["pyo3/extension-module"]
24
+ module-name = "xinterp.rust"
@@ -0,0 +1,82 @@
1
+ use numpy::{IntoPyArray, PyArray1, PyReadonlyArray1};
2
+ use pyo3::prelude::*;
3
+
4
+ #[pymodule]
5
+ fn rust<'py>(_py: Python<'py>, m: &'py PyModule) -> PyResult<()> {
6
+ use interp::interp_ndarray;
7
+
8
+ #[pyfn(m)]
9
+ fn interp_int64<'py>(
10
+ py: Python<'py>,
11
+ x: PyReadonlyArray1<'py, i64>,
12
+ xp: PyReadonlyArray1<'py, i64>,
13
+ fp: PyReadonlyArray1<'py, i64>,
14
+ left: i64,
15
+ right: i64,
16
+ ) -> &'py PyArray1<i64> {
17
+ let x = x.as_array();
18
+ let xp = xp.as_array();
19
+ let fp = fp.as_array();
20
+ let f = interp_ndarray(x, xp, fp, left, right);
21
+ f.into_pyarray(py)
22
+ }
23
+
24
+ Ok(())
25
+ }
26
+
27
+ mod interp {
28
+ use numpy::ndarray::{Array1, ArrayView1};
29
+
30
+ pub fn interp_ndarray(
31
+ x: ArrayView1<i64>,
32
+ xp: ArrayView1<i64>,
33
+ fp: ArrayView1<i64>,
34
+ left: i64,
35
+ right: i64,
36
+ ) -> Array1<i64> {
37
+ x.map(|x| interp_value(*x, xp, fp, left, right))
38
+ }
39
+
40
+ fn interp_value(
41
+ x: i64,
42
+ xp: ArrayView1<i64>,
43
+ fp: ArrayView1<i64>,
44
+ left: i64,
45
+ right: i64,
46
+ ) -> i64 {
47
+ match xp.to_slice().unwrap().binary_search(&x) {
48
+ Ok(index) => fp[index],
49
+ Err(0) => left,
50
+ Err(len) if len == xp.len() => right,
51
+ Err(index) => linear(xp[index - 1], xp[index], fp[index - 1], fp[index], x),
52
+ }
53
+ }
54
+
55
+ fn linear(x0: i64, x1: i64, f0: i64, f1: i64, x: i64) -> i64 {
56
+ let x0 = i128::from(x0);
57
+ let x1 = i128::from(x1);
58
+ let f0 = i128::from(f0);
59
+ let f1 = i128::from(f1);
60
+ let x = i128::from(x);
61
+ let out = roundiv(f0 * (x1 - x) + f1 * (x - x0), x1 - x0);
62
+ i64::try_from(out).expect("cannot convert to i64")
63
+ }
64
+
65
+ fn roundiv(n: i128, d: i128) -> i128 {
66
+ let s = n.signum() * d.signum();
67
+ let (n, d) = (n.abs(), d.abs());
68
+ let q = n / d;
69
+ let r = n % d;
70
+ if (r * 2) == d {
71
+ if q % 2 == 0 {
72
+ return s * q;
73
+ } else {
74
+ return s * (q + 1);
75
+ }
76
+ } else if (r * 2) > d {
77
+ return s * (q + 1);
78
+ } else {
79
+ return s * q;
80
+ }
81
+ }
82
+ }
@@ -0,0 +1,100 @@
1
+ import numpy as np
2
+ import pytest
3
+
4
+ from xinterp import interp_intlike, interp_int64
5
+
6
+
7
+ class TestInterpInt64:
8
+ def test_interpolation_accuracy(self):
9
+ rng = np.random.default_rng(42)
10
+ n = 1_000
11
+ m = 10_000
12
+ integers = np.arange(-32768, 32767)
13
+ xp = np.sort(rng.choice(integers, n, replace=False))
14
+ fp = rng.integers(np.min(integers), np.max(integers), n)
15
+ selected = np.arange(np.min(xp), np.max(xp) + 1)
16
+ x = np.sort(rng.choice(selected, m, replace=False))
17
+ f = interp_int64(x, xp, fp)
18
+ f_expected = np.rint(np.round(np.interp(x, xp, fp), 6)).astype("int")
19
+ assert np.array_equal(f, f_expected)
20
+ assert f.dtype == f_expected.dtype
21
+
22
+ def test_out_of_bound(self):
23
+ xp = np.array([0, 10, 20])
24
+ fp = np.array([0, 1000, 2000])
25
+ x = np.array([-10, -1, 0, 10, 20, 21, 30])
26
+
27
+ f = interp_int64(x, xp, fp)
28
+ f_expected = np.array([0, 0, 0, 1000, 2000, 2000, 2000])
29
+ assert np.array_equal(f, f_expected)
30
+ assert f.dtype == f_expected.dtype
31
+ f_expected = np.interp(x, xp, fp).astype("int")
32
+ assert np.array_equal(f, f_expected)
33
+ assert f.dtype == f_expected.dtype
34
+
35
+ f = interp_int64(x, xp, fp, left=-1, right=-2)
36
+ f_expected = np.array([-1, -1, 0, 1000, 2000, -2, -2])
37
+ assert np.array_equal(f, f_expected)
38
+ assert f.dtype == f_expected.dtype
39
+ f_expected = np.interp(x, xp, fp, left=-1, right=-2).astype("int")
40
+ assert np.array_equal(f, f_expected)
41
+ assert f.dtype == f_expected.dtype
42
+
43
+ def test_raise_if_not_strictly_incresing(self):
44
+ with pytest.raises(ValueError):
45
+ xp = np.array([0, -10, 20])
46
+ fp = np.array([0, 1000, 2000])
47
+ x = np.array([0, 5, 10, 15, 20])
48
+ f = interp_int64(x, xp, fp)
49
+
50
+
51
+ class TestInterpIntLike:
52
+ def test_f_is_datetime(self):
53
+ xp = np.array([0, 10, 20])
54
+ fp = np.array([0, 1000, 2000], dtype="datetime64[s]")
55
+ x = np.array([0, 5, 10, 15, 20])
56
+ f = interp_intlike(x, xp, fp)
57
+ f_expected = np.array([0, 500, 1000, 1500, 2000], dtype="datetime64[s]")
58
+ assert np.array_equal(f, f_expected)
59
+ assert f.dtype == f_expected.dtype
60
+
61
+ def test_x_is_datetime(self):
62
+ xp = np.array([0, 10, 20], dtype="datetime64[s]")
63
+ fp = np.array([0, 1000, 2000])
64
+ x = np.array([0, 5, 10, 15, 20], dtype="datetime64[s]")
65
+ f = interp_intlike(x, xp, fp)
66
+ f_expected = np.array([0, 500, 1000, 1500, 2000])
67
+ assert np.array_equal(f, f_expected)
68
+ assert f.dtype == f_expected.dtype
69
+
70
+ def test_out_of_bound(self):
71
+ xp = np.array([0, 10, 20])
72
+ fp = np.array([0, 1000, 2000], dtype="datetime64[s]")
73
+ x = np.array([-10, -1, 0, 10, 20, 21, 30])
74
+
75
+ f = interp_intlike(x, xp, fp)
76
+ f_expected = np.array([0, 0, 0, 1000, 2000, 2000, 2000], dtype="datetime64[s]")
77
+ assert np.array_equal(f, f_expected)
78
+ assert f.dtype == f_expected.dtype
79
+
80
+ f = interp_intlike(
81
+ x, xp, fp, left=np.datetime64(-1, "s"), right=np.datetime64(-2, "s")
82
+ )
83
+ f_expected = np.array([-1, -1, 0, 1000, 2000, -2, -2], dtype="datetime64[s]")
84
+ assert np.array_equal(f, f_expected)
85
+ assert f.dtype == f_expected.dtype
86
+
87
+ nat = np.datetime64("NaT")
88
+ f = interp_intlike(x, xp, fp, left=nat, right=nat)
89
+ f_expected = np.array(
90
+ [nat, nat, 0, 1000, 2000, nat, nat], dtype="datetime64[s]"
91
+ )
92
+ assert np.array_equal(f, f_expected, equal_nan=True)
93
+ assert f.dtype == f_expected.dtype
94
+
95
+ def test_raise_if_dtype_mismatch(self):
96
+ with pytest.raises(ValueError):
97
+ xp = np.array([0, 10, 20], dtype="datetime64[s]")
98
+ fp = np.array([0, 1000, 2000])
99
+ x = np.array([0, 5, 10, 15, 20])
100
+ f = interp_intlike(x, xp, fp)
@@ -0,0 +1 @@
1
+ from .core import interp_intlike, interp_int64
@@ -0,0 +1,51 @@
1
+ import numpy as np
2
+
3
+ from . import rust
4
+
5
+
6
+ def interp_intlike(x, xp, fp, left=None, right=None):
7
+ """
8
+ One-dimensional linear interpolation for monotonically increasing
9
+
10
+ Parameters
11
+ ----------
12
+ x : 1-D sequence of integers
13
+ The indices at which to evaluate the interpolated values.
14
+ xp : 1-D sequence of integers
15
+ The indices of the data points, must be increasing.
16
+ fp : 1-D sequence of datetime64
17
+ The values of the data points, same length as 'xp'.
18
+ left : datetime64, optional
19
+ Value to return for 'x < xp[0]', by default 'fp[0]'.
20
+ right : float, optional
21
+ Value to return for 'x > xp[-1]', by default 'fp[-1]'
22
+
23
+ Returns
24
+ -------
25
+ 1-D array of datetime64
26
+ The interpolated values, same length as x.x
27
+ """
28
+ if not x.dtype == xp.dtype:
29
+ raise ValueError("x and xp must have the same dtype")
30
+ return interp_int64(x, xp, fp, left, right).astype(fp.dtype)
31
+
32
+
33
+ def interp_int64(x, xp, fp, left=None, right=None):
34
+ x = np.asarray(x, dtype="int64")
35
+ xp = np.asarray(xp, dtype="int64")
36
+ fp = np.asarray(fp, dtype="int64")
37
+ if not np.all(np.diff(xp) > 0):
38
+ raise ValueError("xp must be strictly increasing")
39
+ if left is None:
40
+ left = fp[0]
41
+ else:
42
+ left = np.int64(left)
43
+ if right is None:
44
+ right = fp[-1]
45
+ else:
46
+ right = np.int64(right)
47
+ if not (x.ndim == 1 and xp.ndim == 1 and fp.ndim == 1):
48
+ raise
49
+ if not (xp.shape == fp.shape):
50
+ raise
51
+ return rust.interp_int64(x, xp, fp, left, right)