rsnumpy 1.0.3__tar.gz → 1.1.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.
Files changed (32) hide show
  1. {rsnumpy-1.0.3 → rsnumpy-1.1.2}/.github/workflows/ci.yml +7 -5
  2. {rsnumpy-1.0.3 → rsnumpy-1.1.2}/.github/workflows/release.yml +0 -30
  3. {rsnumpy-1.0.3 → rsnumpy-1.1.2}/.gitignore +5 -0
  4. {rsnumpy-1.0.3 → rsnumpy-1.1.2}/Cargo.lock +23 -56
  5. {rsnumpy-1.0.3 → rsnumpy-1.1.2}/Cargo.toml +12 -7
  6. rsnumpy-1.0.3/README.md → rsnumpy-1.1.2/PKG-INFO +210 -21
  7. rsnumpy-1.0.3/PKG-INFO → rsnumpy-1.1.2/README.md +185 -35
  8. rsnumpy-1.1.2/build_wheel.sh +155 -0
  9. {rsnumpy-1.0.3 → rsnumpy-1.1.2}/pyproject.toml +15 -2
  10. {rsnumpy-1.0.3 → rsnumpy-1.1.2}/python/rsnumpy/__init__.py +862 -95
  11. rsnumpy-1.1.2/python/rsnumpy/_extra.py +2831 -0
  12. {rsnumpy-1.0.3 → rsnumpy-1.1.2}/python/rsnumpy/array_ops.py +56 -14
  13. {rsnumpy-1.0.3 → rsnumpy-1.1.2}/python/rsnumpy/random/__init__.py +12 -7
  14. {rsnumpy-1.0.3 → rsnumpy-1.1.2}/python/rsnumpy/statistics.py +9 -18
  15. rsnumpy-1.1.2/rust-toolchain.toml +2 -0
  16. {rsnumpy-1.0.3 → rsnumpy-1.1.2}/src/indexing.rs +23 -6
  17. {rsnumpy-1.0.3 → rsnumpy-1.1.2}/src/lib.rs +836 -53
  18. {rsnumpy-1.0.3 → rsnumpy-1.1.2}/src/random.rs +83 -51
  19. {rsnumpy-1.0.3 → rsnumpy-1.1.2}/test/run_test.py +234 -10
  20. rsnumpy-1.0.3/build_wheel.sh +0 -93
  21. rsnumpy-1.0.3/plots.py +0 -1086
  22. {rsnumpy-1.0.3 → rsnumpy-1.1.2}/LICENSE +0 -0
  23. {rsnumpy-1.0.3 → rsnumpy-1.1.2}/RELEASE_NOTES.md +0 -0
  24. {rsnumpy-1.0.3 → rsnumpy-1.1.2}/python/rsnumpy/array_methods.py +0 -0
  25. {rsnumpy-1.0.3 → rsnumpy-1.1.2}/python/rsnumpy/char.py +0 -0
  26. {rsnumpy-1.0.3 → rsnumpy-1.1.2}/python/rsnumpy/io.py +0 -0
  27. {rsnumpy-1.0.3 → rsnumpy-1.1.2}/python/rsnumpy/linalg/__init__.py +0 -0
  28. {rsnumpy-1.0.3 → rsnumpy-1.1.2}/python/rsnumpy/math_functions.py +0 -0
  29. {rsnumpy-1.0.3 → rsnumpy-1.1.2}/python/rsnumpy/matlib.py +0 -0
  30. {rsnumpy-1.0.3 → rsnumpy-1.1.2}/python/rsnumpy/polynomial/__init__.py +0 -0
  31. {rsnumpy-1.0.3 → rsnumpy-1.1.2}/src/fft.rs +0 -0
  32. {rsnumpy-1.0.3 → rsnumpy-1.1.2}/src/linalg.rs +0 -0
@@ -2,9 +2,9 @@ name: CI
2
2
 
3
3
  on:
4
4
  push:
5
- branches: [main, master, dev, development]
5
+ branches: [main, master, dev, main-dev]
6
6
  pull_request:
7
- branches: [main, master, dev, development]
7
+ branches: [main, master, dev, main-dev]
8
8
 
9
9
  # 同一分支/PR 的新推送会取消仍在进行的旧运行,节省 CI 时间。
10
10
  concurrency:
@@ -26,6 +26,11 @@ jobs:
26
26
  matrix:
27
27
  os: [ubuntu-latest, windows-latest, macos-latest]
28
28
  python-version: ["3.10", "3.13", "3.14"]
29
+ include:
30
+ - os: ubuntu-latest
31
+ python-version: "3.10"
32
+ - os: windows-latest
33
+ python-version: "3.10"
29
34
  steps:
30
35
  - uses: actions/checkout@v4
31
36
 
@@ -57,9 +62,6 @@ jobs:
57
62
  - name: Install built wheel
58
63
  run: python -m pip install --no-index --find-links dist rsnumpy
59
64
 
60
- - name: Install test dependencies
61
- run: python -m pip install numpy
62
-
63
65
  - name: Run smoke test
64
66
  run: python test/run_test.py
65
67
 
@@ -25,16 +25,6 @@ jobs:
25
25
  steps:
26
26
  - uses: actions/checkout@v4
27
27
 
28
- - name: Cache Rust build artifacts
29
- uses: actions/cache@v4
30
- with:
31
- path: |
32
- ~/.cargo/registry
33
- ~/.cargo/git
34
- key: ${{ runner.os }}-cargo-${{ hashFiles('**/Cargo.lock') }}
35
- restore-keys: |
36
- ${{ runner.os }}-cargo-
37
-
38
28
  - name: Build wheels (${{ matrix.target }})
39
29
  uses: PyO3/maturin-action@v1
40
30
  with:
@@ -57,16 +47,6 @@ jobs:
57
47
  steps:
58
48
  - uses: actions/checkout@v4
59
49
 
60
- - name: Cache Rust build artifacts
61
- uses: actions/cache@v4
62
- with:
63
- path: |
64
- ~/.cargo/registry
65
- ~/.cargo/git
66
- key: ${{ runner.os }}-cargo-${{ hashFiles('**/Cargo.lock') }}
67
- restore-keys: |
68
- ${{ runner.os }}-cargo-
69
-
70
50
  - uses: actions/setup-python@v5
71
51
  with:
72
52
  python-version: ${{ matrix.python-version }}
@@ -95,16 +75,6 @@ jobs:
95
75
  steps:
96
76
  - uses: actions/checkout@v4
97
77
 
98
- - name: Cache Rust build artifacts
99
- uses: actions/cache@v4
100
- with:
101
- path: |
102
- ~/.cargo/registry
103
- ~/.cargo/git
104
- key: ${{ runner.os }}-cargo-${{ hashFiles('**/Cargo.lock') }}
105
- restore-keys: |
106
- ${{ runner.os }}-cargo-
107
-
108
78
  - uses: actions/setup-python@v5
109
79
  with:
110
80
  python-version: ${{ matrix.python-version }}
@@ -39,6 +39,11 @@ push*.sh
39
39
  main*.py
40
40
  debug*.py
41
41
  check*.py
42
+ test2*.py
43
+ map*.jpeg
44
+ bench_extra.py
45
+ *.png
46
+ runtest_matplotlib.py
42
47
 
43
48
  # Environment
44
49
  .venv
@@ -61,9 +61,9 @@ dependencies = [
61
61
 
62
62
  [[package]]
63
63
  name = "cc"
64
- version = "1.2.65"
64
+ version = "1.2.66"
65
65
  source = "registry+https://github.com/rust-lang/crates.io-index"
66
- checksum = "e228eec9be7c17ccb640b59b36a5cd805ea2a564a4c5e162c2f659fea30d3b96"
66
+ checksum = "f5d6cac793997bd970000024b2934968efe83b382de4fdcf4fcb46b6ee4ad996"
67
67
  dependencies = [
68
68
  "find-msvc-tools",
69
69
  "jobserver",
@@ -142,9 +142,9 @@ dependencies = [
142
142
 
143
143
  [[package]]
144
144
  name = "crossbeam-deque"
145
- version = "0.8.6"
145
+ version = "0.8.7"
146
146
  source = "registry+https://github.com/rust-lang/crates.io-index"
147
- checksum = "9dd111b7b7f7d55b72c0a6ae361660ee5853c9af73f70c3c2ef6858b950e2e51"
147
+ checksum = "5181e0de7b61eb03a81e347d6dd8797bae9da5146707b51077e2d71a54ec0ceb"
148
148
  dependencies = [
149
149
  "crossbeam-epoch",
150
150
  "crossbeam-utils",
@@ -152,18 +152,18 @@ dependencies = [
152
152
 
153
153
  [[package]]
154
154
  name = "crossbeam-epoch"
155
- version = "0.9.18"
155
+ version = "0.9.20"
156
156
  source = "registry+https://github.com/rust-lang/crates.io-index"
157
- checksum = "5b82ac4a3c2ca9c3460964f020e1402edd5753411d7737aa39c3714ad1b5420e"
157
+ checksum = "2d6914041f254d6e9176c01941b21115dcfb7089e55135a35411081bd106ef3f"
158
158
  dependencies = [
159
159
  "crossbeam-utils",
160
160
  ]
161
161
 
162
162
  [[package]]
163
163
  name = "crossbeam-utils"
164
- version = "0.8.21"
164
+ version = "0.8.22"
165
165
  source = "registry+https://github.com/rust-lang/crates.io-index"
166
- checksum = "d0a5c400df2834b80a4c3327b3aad3a4c4cd4de0629063962b03235697506a28"
166
+ checksum = "61803da095bee82a81bb1a452ecc25d3b2f1416d1897eb86430c6159ef717c17"
167
167
 
168
168
  [[package]]
169
169
  name = "crypto-common"
@@ -260,18 +260,6 @@ dependencies = [
260
260
  "slab",
261
261
  ]
262
262
 
263
- [[package]]
264
- name = "getrandom"
265
- version = "0.3.4"
266
- source = "registry+https://github.com/rust-lang/crates.io-index"
267
- checksum = "899def5c37c4fd7b2664648c28120ecec138e4d395b459e5ca34f9cce2dd77fd"
268
- dependencies = [
269
- "cfg-if",
270
- "libc",
271
- "r-efi 5.3.0",
272
- "wasip2",
273
- ]
274
-
275
263
  [[package]]
276
264
  name = "getrandom"
277
265
  version = "0.4.3"
@@ -281,7 +269,7 @@ dependencies = [
281
269
  "cfg-if",
282
270
  "js-sys",
283
271
  "libc",
284
- "r-efi 6.0.0",
272
+ "r-efi",
285
273
  "rand_core",
286
274
  "wasm-bindgen",
287
275
  ]
@@ -337,11 +325,11 @@ dependencies = [
337
325
 
338
326
  [[package]]
339
327
  name = "jobserver"
340
- version = "0.1.34"
328
+ version = "0.1.35"
341
329
  source = "registry+https://github.com/rust-lang/crates.io-index"
342
- checksum = "9afb3de4395d6b3e67a780b6de64b51c978ecf11cb9a462c66be7d4ca9039d33"
330
+ checksum = "1c00acbd29eabad4a2392fa0e921c874934dbbf4194312ad20f04a0ed67a3cb3"
343
331
  dependencies = [
344
- "getrandom 0.3.4",
332
+ "getrandom",
345
333
  "libc",
346
334
  ]
347
335
 
@@ -382,9 +370,9 @@ checksum = "0ceec5bc11778974d1bcb055b18002eba7f4b3518b6a0081b3af5f21666da9ad"
382
370
 
383
371
  [[package]]
384
372
  name = "lzma-rust2"
385
- version = "0.16.4"
373
+ version = "0.16.5"
386
374
  source = "registry+https://github.com/rust-lang/crates.io-index"
387
- checksum = "ce716bf1a316f47a280fc76295f6495b5bea4752bca01c3b3885e101b1c23c02"
375
+ checksum = "ca93e534d1142d1d0dcca6d25fe302508a5dfb40b302802904577725ea0b695b"
388
376
  dependencies = [
389
377
  "sha2",
390
378
  ]
@@ -401,9 +389,9 @@ dependencies = [
401
389
 
402
390
  [[package]]
403
391
  name = "memchr"
404
- version = "2.8.2"
392
+ version = "2.8.3"
405
393
  source = "registry+https://github.com/rust-lang/crates.io-index"
406
- checksum = "88904434abc2901f197fe8cc55f0445e7ded921dba5911dad2e2b39b48e663c4"
394
+ checksum = "cf8baf1c55e62ffcace7a9f06f4bd9cd3f0c4beb022d3b367256b91b87513d98"
407
395
 
408
396
  [[package]]
409
397
  name = "miniz_oxide"
@@ -607,12 +595,6 @@ dependencies = [
607
595
  "proc-macro2",
608
596
  ]
609
597
 
610
- [[package]]
611
- name = "r-efi"
612
- version = "5.3.0"
613
- source = "registry+https://github.com/rust-lang/crates.io-index"
614
- checksum = "69cdb34c158ceb288df11e18b4bd39de994f6657d83847bdffdbd7f346754b0f"
615
-
616
598
  [[package]]
617
599
  name = "r-efi"
618
600
  version = "6.0.0"
@@ -626,7 +608,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
626
608
  checksum = "c7f5fa3a058cd35567ef9bfa5e75732bee0f9e4c55fa90477bef2dfcdbc4be80"
627
609
  dependencies = [
628
610
  "chacha20",
629
- "getrandom 0.4.3",
611
+ "getrandom",
630
612
  "rand_core",
631
613
  ]
632
614
 
@@ -674,7 +656,7 @@ dependencies = [
674
656
 
675
657
  [[package]]
676
658
  name = "rsnumpy"
677
- version = "1.0.3"
659
+ version = "1.1.2"
678
660
  dependencies = [
679
661
  "ndarray",
680
662
  "num-complex",
@@ -704,9 +686,9 @@ dependencies = [
704
686
 
705
687
  [[package]]
706
688
  name = "rustversion"
707
- version = "1.0.22"
689
+ version = "1.0.23"
708
690
  source = "registry+https://github.com/rust-lang/crates.io-index"
709
- checksum = "b39cdef0fa800fc44525c84ccb54a029961a8215f9619753635a9c0d2538d46d"
691
+ checksum = "cf54715a573b99ac80df0bc206da022bcd442c974952c7b9720069370852e21f"
710
692
 
711
693
  [[package]]
712
694
  name = "serde"
@@ -868,15 +850,6 @@ version = "1.0.24"
868
850
  source = "registry+https://github.com/rust-lang/crates.io-index"
869
851
  checksum = "e6e4313cd5fcd3dad5cafa179702e2b244f760991f45397d14d4ebf38247da75"
870
852
 
871
- [[package]]
872
- name = "wasip2"
873
- version = "1.0.4+wasi-0.2.12"
874
- source = "registry+https://github.com/rust-lang/crates.io-index"
875
- checksum = "b67efb37e106e55ce722a510d6b5f9c17f083e5fc79afc2badeb12cc313d9487"
876
- dependencies = [
877
- "wit-bindgen",
878
- ]
879
-
880
853
  [[package]]
881
854
  name = "wasm-bindgen"
882
855
  version = "0.2.126"
@@ -922,12 +895,6 @@ dependencies = [
922
895
  "unicode-ident",
923
896
  ]
924
897
 
925
- [[package]]
926
- name = "wit-bindgen"
927
- version = "0.57.1"
928
- source = "registry+https://github.com/rust-lang/crates.io-index"
929
- checksum = "1ebf944e87a7c253233ad6766e082e3cd714b5d03812acc24c318f549614536e"
930
-
931
898
  [[package]]
932
899
  name = "zeroize"
933
900
  version = "1.9.0"
@@ -946,7 +913,7 @@ dependencies = [
946
913
  "crc32fast",
947
914
  "deflate64",
948
915
  "flate2",
949
- "getrandom 0.4.3",
916
+ "getrandom",
950
917
  "hmac",
951
918
  "indexmap",
952
919
  "lzma-rust2",
@@ -963,9 +930,9 @@ dependencies = [
963
930
 
964
931
  [[package]]
965
932
  name = "zlib-rs"
966
- version = "0.6.5"
933
+ version = "0.6.6"
967
934
  source = "registry+https://github.com/rust-lang/crates.io-index"
968
- checksum = "5431d5661c32445236631278f27946e444ddafe4684cac70b185272d4f9c52d5"
935
+ checksum = "b142a20ec14a91d5bc708c1dc21b080c550113d8aa77afa29635673a65dd02c5"
969
936
 
970
937
  [[package]]
971
938
  name = "zopfli"
@@ -1,6 +1,6 @@
1
1
  [package]
2
2
  name = "rsnumpy"
3
- version = "1.0.3"
3
+ version = "1.1.2"
4
4
  edition = "2024"
5
5
  readme = "README.md"
6
6
 
@@ -9,7 +9,7 @@ name = "rsnumpy"
9
9
  crate-type = ["cdylib"]
10
10
 
11
11
  [dependencies]
12
- pyo3 = { version = "0.29.0", features = ["extension-module", "abi3-py38"] }
12
+ pyo3 = { version = "0.29.0", features = ["extension-module"] }
13
13
  ndarray = { version = "0.17.2", features = ["rayon", "serde"] }
14
14
  rayon = "1.12.0"
15
15
  rand = "0.10.2"
@@ -29,9 +29,14 @@ blas = ["ndarray/blas"]
29
29
  opt-level = 3
30
30
  lto = "fat"
31
31
  codegen-units = 1
32
- panic = "abort"
33
- strip = true
32
+ strip = "symbols"
34
33
 
35
- [profile.bench]
36
- opt-level = 3
37
- debug = false
34
+ [profile.dev]
35
+ opt-level = 0
36
+ debug = true
37
+
38
+ [lints.clippy]
39
+ too_many_arguments = "allow"
40
+ type_complexity = "allow"
41
+ cast_precision_loss = "allow"
42
+ cast_sign_loss = "allow"
@@ -1,3 +1,27 @@
1
+ Metadata-Version: 2.4
2
+ Name: rsnumpy
3
+ Version: 1.1.2
4
+ Classifier: Programming Language :: Rust
5
+ Classifier: Programming Language :: Python :: 3
6
+ Classifier: Programming Language :: Python :: 3 :: Only
7
+ Classifier: Programming Language :: Python :: 3.10
8
+ Classifier: Programming Language :: Python :: 3.11
9
+ Classifier: Programming Language :: Python :: 3.12
10
+ Classifier: Programming Language :: Python :: 3.13
11
+ Classifier: Programming Language :: Python :: 3.14
12
+ Classifier: Programming Language :: Python :: Implementation :: CPython
13
+ Classifier: Programming Language :: Python :: Implementation :: PyPy
14
+ Classifier: License :: OSI Approved :: MIT License
15
+ Classifier: Operating System :: MacOS
16
+ Classifier: Operating System :: Microsoft :: Windows
17
+ Classifier: Operating System :: POSIX :: Linux
18
+ Classifier: Topic :: Scientific/Engineering :: Visualization
19
+ License-File: LICENSE
20
+ Summary: A Rust-powered NumPy-compatible array library.
21
+ Author: YJ-Niu
22
+ Requires-Python: >=3.10
23
+ Description-Content-Type: text/markdown; charset=UTF-8; variant=GFM
24
+
1
25
  # rsnumpy
2
26
 
3
27
  **A Rust-powered NumPy-compatible array library.**
@@ -27,15 +51,19 @@
27
51
  rsnumpy/
28
52
  ├── src/ # Rust 源码
29
53
  │ ├── lib.rs # 核心 ndarray 与通用函数
54
+ │ ├── indexing.rs # 多维索引与切片
30
55
  │ ├── fft.rs # 快速傅里叶变换
31
56
  │ ├── linalg.rs # 线性代数
32
- │ └── random.rs # 随机数生成
33
- ├── rsnumpy/ # Python 薄包装
57
+ │ └── random.rs # 随机数生成(可复现并行采样)
58
+ ├── python/rsnumpy/ # Python 薄包装
34
59
  │ ├── __init__.py # 主模块,整合所有 API
35
60
  │ ├── array_methods.py # ndarray 对象方法
36
61
  │ ├── array_ops.py # 数组操作函数
62
+ │ ├── _extra.py # 补充 API(别名、nan 系列、集合运算、窗函数等)
37
63
  │ ├── math_functions.py # 数学函数
38
64
  │ ├── statistics.py # 统计函数
65
+ │ ├── char.py # 字符串数组函数
66
+ │ ├── matlib.py # 矩阵便捷构造
39
67
  │ ├── io.py # 文件 I/O
40
68
  │ ├── linalg/ # 线性代数子模块
41
69
  │ ├── polynomial/ # 多项式子模块
@@ -259,6 +287,8 @@ print(np.random.rand(3).tolist())
259
287
  print(np.random.randn(3).tolist())
260
288
  ```
261
289
 
290
+ > **可复现性**:相同 `seed` 保证生成相同的结果。大数组采样在 Rust 层并行执行,采用固定分块 + `splitmix64` 派生各分块的独立种子,因此**结果与线程数无关**,在不同机器上同样可复现。同一个 `Generator` 每次调用都会推进内部状态,连续调用不会产生重复序列。
291
+
262
292
  #### 5.7 FFT
263
293
 
264
294
  ```python
@@ -341,6 +371,81 @@ print(np.isinf(a))
341
371
  print(np.isfinite(a))
342
372
  ```
343
373
 
374
+ #### 5.11 日期时间与网格
375
+
376
+ ```python
377
+ import rsnumpy as np
378
+
379
+ # 日期时间标量(兼容 numpy.datetime64)
380
+ d = np.datetime64('2024-01-01')
381
+ delta = np.timedelta64(7, 'D') # 7 天
382
+ print(d + delta) # numpy.datetime64('2024-01-08')
383
+ print(np.datetime64('2024-01-08') - d) # numpy.timedelta64(7,'D')
384
+
385
+ # 用 datetime64/timedelta64 生成日期序列
386
+ days = np.arange(np.datetime64('2024-01-01'),
387
+ np.datetime64('2024-01-05'),
388
+ np.timedelta64(1, 'D'))
389
+
390
+ # 坐标网格(默认 'xy' 索引,与 NumPy 一致)
391
+ x = np.array([1, 2, 3])
392
+ y = np.array([10, 20])
393
+ X, Y = np.meshgrid(x, y)
394
+ print(X.tolist()) # [[1.0, 2.0, 3.0], [1.0, 2.0, 3.0]]
395
+ print(Y.tolist()) # [[10.0, 10.0, 10.0], [20.0, 20.0, 20.0]]
396
+ ```
397
+
398
+ #### 5.12 补充 API 覆盖(对齐 NumPy 2.5.1)
399
+
400
+ 在核心 Rust 原语之上,`_extra.py` 补充了约 140 个 NumPy 兼容函数,全部对照 NumPy 2.5.1 逐函数验证通过。计算密集/逐元素部分复用现有 Rust 原语,纯变形与组合类则以薄 Python 包装实现。
401
+
402
+ ```python
403
+ import rsnumpy as np
404
+
405
+ # 三角/双曲别名(Array API 命名)
406
+ np.acos(1.0); np.asin(0.0); np.atan(1.0); np.atan2(1.0, 1.0)
407
+ np.radians(180.0); np.degrees(np.pi)
408
+
409
+ # 逐元素数学
410
+ np.hypot(3.0, 4.0) # 5.0
411
+ np.maximum([1, 5], [3, 2]) # [3, 5]
412
+ np.fmax([np.nan, 2], [1, np.nan]) # 忽略 NaN
413
+ np.logaddexp(0.0, 0.0) # 数值稳定 log(exp(a)+exp(b))
414
+ np.rint([0.5, 1.5, 2.5]) # 四舍六入五成双 -> [0, 2, 2]
415
+ np.gcd(12, 8); np.lcm(4, 6)
416
+ frac, whole = np.modf([1.5, 2.25])
417
+
418
+ # nan 系列归约
419
+ a = np.array([1.0, np.nan, 3.0])
420
+ np.nansum(a); np.nanmean(a); np.nanstd(a); np.nanmax(a)
421
+ np.nancumsum(a); np.nanargmax(a)
422
+ np.prod([1, 2, 3, 4]) # 24
423
+
424
+ # 集合运算
425
+ np.intersect1d([1, 2, 3], [2, 3, 4]) # [2, 3]
426
+ np.union1d([1, 2], [2, 3]) # [1, 2, 3]
427
+ np.setdiff1d([1, 2, 3], [2]) # [1, 3]
428
+ np.isin([1, 2, 5], [1, 5]) # [True, False, True]
429
+ uniq, counts = np.unique_counts([1, 1, 2, 3, 3, 3])
430
+
431
+ # 变形 / 组合
432
+ np.block([[np.eye(2), np.ones((2, 1))]])
433
+ np.pad([1, 2, 3], (1, 2), mode='reflect')
434
+ np.kron([1, 2], [1, 1])
435
+ np.tensordot(np.ones((2, 3)), np.ones((3, 4)), axes=1)
436
+
437
+ # 复数
438
+ z = np.array([1 + 2j, 3 - 1j])
439
+ np.real(z); np.imag(z); np.conjugate(z); np.angle(z)
440
+
441
+ # 信号 / 窗函数 / 插值
442
+ np.convolve([1, 2, 3], [1, 1])
443
+ np.interp(2.5, [1, 2, 3], [10, 20, 30])
444
+ np.hanning(8); np.hamming(8); np.blackman(8); np.bartlett(8)
445
+ np.vander([1, 2, 3], 3)
446
+ np.bincount([0, 1, 1, 2, 2, 2])
447
+ ```
448
+
344
449
  ---
345
450
 
346
451
  ### 6. 常见问题
@@ -433,26 +538,32 @@ A: 当前版本仅支持 CPU。
433
538
  **Project layout:**
434
539
 
435
540
  ```
541
+
436
542
  rsnumpy/
437
- ├── src/ # Rust source
438
- │ ├── lib.rs # Core ndarray & general functions
439
- │ ├── fft.rs # Fast Fourier Transform
440
- │ ├── linalg.rs # Linear algebra
441
- │ └── random.rs # Random number generation
442
- ├── rsnumpy/ # Python thin wrappers
443
- │ ├── __init__.py # Main module, exports public API
444
- │ ├── array_methods.py # ndarray object methods
445
- │ ├── array_ops.py # Array manipulation functions
446
- │ ├── math_functions.py # Math functions
447
- │ ├── statistics.py # Statistics functions
448
- │ ├── io.py # File I/O
449
- │ ├── linalg/ # Linear algebra submodule
450
- │ ├── polynomial/ # Polynomial submodule
451
- │ └── random/ # Random submodule
452
- ├── Cargo.toml # Rust dependencies
453
- ├── pyproject.toml # Python build config
454
- ├── build_wheel.sh # Build script
455
- └── README.md # This file
543
+ ├── src/ # Rust source
544
+ │ ├── lib.rs # Core ndarray & general functions
545
+ │ ├── indexing.rs # Multi-dimensional indexing & slicing
546
+ │ ├── fft.rs # Fast Fourier Transform
547
+ │ ├── linalg.rs # Linear algebra
548
+ │ └── random.rs # Random number generation (reproducible parallel sampling)
549
+ ├── python/rsnumpy/ # Python thin wrappers
550
+ │ ├── **init**.py # Main module, exports public API
551
+ │ ├── array_methods.py # ndarray object methods
552
+ │ ├── array_ops.py # Array manipulation functions
553
+ │ ├── _extra.py # Supplementary API (aliases, nan-reductions, set ops, windows, ...)
554
+ │ ├── math_functions.py # Math functions
555
+ │ ├── statistics.py # Statistics functions
556
+ │ ├── char.py # String array functions
557
+ │ ├── matlib.py # Matrix construction helpers
558
+ │ ├── io.py # File I/O
559
+ │ ├── linalg/ # Linear algebra submodule
560
+ │ ├── polynomial/ # Polynomial submodule
561
+ │ └── random/ # Random submodule
562
+ ├── Cargo.toml # Rust dependencies
563
+ ├── pyproject.toml # Python build config
564
+ ├── build_wheel.sh # Build script
565
+ └── README.md # This file
566
+
456
567
  ```
457
568
 
458
569
  ---
@@ -668,6 +779,8 @@ print(np.random.rand(3).tolist())
668
779
  print(np.random.randn(3).tolist())
669
780
  ```
670
781
 
782
+ > **Reproducibility**: the same `seed` always produces the same result. Large-array sampling runs in parallel on the Rust side using fixed-size chunks with per-chunk seeds derived via `splitmix64`, so results are **independent of the thread count** and reproducible across machines. Each call on a `Generator` advances its internal state, so consecutive calls never repeat the same sequence.
783
+
671
784
  #### 5.7 FFT
672
785
 
673
786
  ```python
@@ -750,6 +863,81 @@ print(np.isinf(a))
750
863
  print(np.isfinite(a))
751
864
  ```
752
865
 
866
+ #### 5.11 Datetime & meshgrid
867
+
868
+ ```python
869
+ import rsnumpy as np
870
+
871
+ # Datetime scalars (compatible with numpy.datetime64)
872
+ d = np.datetime64('2024-01-01')
873
+ delta = np.timedelta64(7, 'D') # 7 days
874
+ print(d + delta) # numpy.datetime64('2024-01-08')
875
+ print(np.datetime64('2024-01-08') - d) # numpy.timedelta64(7,'D')
876
+
877
+ # Generate a date range with datetime64/timedelta64
878
+ days = np.arange(np.datetime64('2024-01-01'),
879
+ np.datetime64('2024-01-05'),
880
+ np.timedelta64(1, 'D'))
881
+
882
+ # Coordinate grids (default 'xy' indexing, matching NumPy)
883
+ x = np.array([1, 2, 3])
884
+ y = np.array([10, 20])
885
+ X, Y = np.meshgrid(x, y)
886
+ print(X.tolist()) # [[1.0, 2.0, 3.0], [1.0, 2.0, 3.0]]
887
+ print(Y.tolist()) # [[10.0, 10.0, 10.0], [20.0, 20.0, 20.0]]
888
+ ```
889
+
890
+ #### 5.12 Supplementary API Coverage (aligned with NumPy 2.5.1)
891
+
892
+ On top of the core Rust primitives, `_extra.py` adds ~140 NumPy-compatible functions, each verified against NumPy 2.5.1. Compute-heavy / element-wise paths reuse existing Rust primitives, while pure reshaping and composition helpers are implemented as thin Python wrappers.
893
+
894
+ ```python
895
+ import rsnumpy as np
896
+
897
+ # Trig/hyperbolic aliases (Array API names)
898
+ np.acos(1.0); np.asin(0.0); np.atan(1.0); np.atan2(1.0, 1.0)
899
+ np.radians(180.0); np.degrees(np.pi)
900
+
901
+ # Element-wise math
902
+ np.hypot(3.0, 4.0) # 5.0
903
+ np.maximum([1, 5], [3, 2]) # [3, 5]
904
+ np.fmax([np.nan, 2], [1, np.nan]) # NaN-ignoring
905
+ np.logaddexp(0.0, 0.0) # numerically stable log(exp(a)+exp(b))
906
+ np.rint([0.5, 1.5, 2.5]) # round-half-to-even -> [0, 2, 2]
907
+ np.gcd(12, 8); np.lcm(4, 6)
908
+ frac, whole = np.modf([1.5, 2.25])
909
+
910
+ # nan-reductions
911
+ a = np.array([1.0, np.nan, 3.0])
912
+ np.nansum(a); np.nanmean(a); np.nanstd(a); np.nanmax(a)
913
+ np.nancumsum(a); np.nanargmax(a)
914
+ np.prod([1, 2, 3, 4]) # 24
915
+
916
+ # Set operations
917
+ np.intersect1d([1, 2, 3], [2, 3, 4]) # [2, 3]
918
+ np.union1d([1, 2], [2, 3]) # [1, 2, 3]
919
+ np.setdiff1d([1, 2, 3], [2]) # [1, 3]
920
+ np.isin([1, 2, 5], [1, 5]) # [True, False, True]
921
+ uniq, counts = np.unique_counts([1, 1, 2, 3, 3, 3])
922
+
923
+ # Reshaping / composition
924
+ np.block([[np.eye(2), np.ones((2, 1))]])
925
+ np.pad([1, 2, 3], (1, 2), mode='reflect')
926
+ np.kron([1, 2], [1, 1])
927
+ np.tensordot(np.ones((2, 3)), np.ones((3, 4)), axes=1)
928
+
929
+ # Complex
930
+ z = np.array([1 + 2j, 3 - 1j])
931
+ np.real(z); np.imag(z); np.conjugate(z); np.angle(z)
932
+
933
+ # Signal / windows / interpolation
934
+ np.convolve([1, 2, 3], [1, 1])
935
+ np.interp(2.5, [1, 2, 3], [10, 20, 30])
936
+ np.hanning(8); np.hamming(8); np.blackman(8); np.bartlett(8)
937
+ np.vander([1, 2, 3], 3)
938
+ np.bincount([0, 1, 1, 2, 2, 2])
939
+ ```
940
+
753
941
  ---
754
942
 
755
943
  ### 6. FAQ
@@ -829,3 +1017,4 @@ Contributions are welcome! Please follow these steps:
829
1017
  ## License
830
1018
 
831
1019
  MIT
1020
+