rsnumpy 1.0.6__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 (30) hide show
  1. {rsnumpy-1.0.6 → rsnumpy-1.1.2}/.gitignore +2 -0
  2. {rsnumpy-1.0.6 → rsnumpy-1.1.2}/Cargo.lock +13 -13
  3. {rsnumpy-1.0.6 → rsnumpy-1.1.2}/Cargo.toml +1 -1
  4. {rsnumpy-1.0.6 → rsnumpy-1.1.2}/PKG-INFO +186 -22
  5. {rsnumpy-1.0.6 → rsnumpy-1.1.2}/README.md +185 -21
  6. {rsnumpy-1.0.6 → rsnumpy-1.1.2}/build_wheel.sh +4 -4
  7. {rsnumpy-1.0.6 → rsnumpy-1.1.2}/pyproject.toml +1 -1
  8. {rsnumpy-1.0.6 → rsnumpy-1.1.2}/python/rsnumpy/__init__.py +807 -98
  9. rsnumpy-1.1.2/python/rsnumpy/_extra.py +2831 -0
  10. {rsnumpy-1.0.6 → rsnumpy-1.1.2}/python/rsnumpy/array_ops.py +56 -14
  11. {rsnumpy-1.0.6 → rsnumpy-1.1.2}/python/rsnumpy/random/__init__.py +12 -7
  12. {rsnumpy-1.0.6 → rsnumpy-1.1.2}/python/rsnumpy/statistics.py +9 -18
  13. {rsnumpy-1.0.6 → rsnumpy-1.1.2}/src/lib.rs +697 -53
  14. {rsnumpy-1.0.6 → rsnumpy-1.1.2}/src/random.rs +83 -51
  15. {rsnumpy-1.0.6 → rsnumpy-1.1.2}/test/run_test.py +234 -3
  16. {rsnumpy-1.0.6 → rsnumpy-1.1.2}/.github/workflows/ci.yml +0 -0
  17. {rsnumpy-1.0.6 → rsnumpy-1.1.2}/.github/workflows/release.yml +0 -0
  18. {rsnumpy-1.0.6 → rsnumpy-1.1.2}/LICENSE +0 -0
  19. {rsnumpy-1.0.6 → rsnumpy-1.1.2}/RELEASE_NOTES.md +0 -0
  20. {rsnumpy-1.0.6 → rsnumpy-1.1.2}/python/rsnumpy/array_methods.py +0 -0
  21. {rsnumpy-1.0.6 → rsnumpy-1.1.2}/python/rsnumpy/char.py +0 -0
  22. {rsnumpy-1.0.6 → rsnumpy-1.1.2}/python/rsnumpy/io.py +0 -0
  23. {rsnumpy-1.0.6 → rsnumpy-1.1.2}/python/rsnumpy/linalg/__init__.py +0 -0
  24. {rsnumpy-1.0.6 → rsnumpy-1.1.2}/python/rsnumpy/math_functions.py +0 -0
  25. {rsnumpy-1.0.6 → rsnumpy-1.1.2}/python/rsnumpy/matlib.py +0 -0
  26. {rsnumpy-1.0.6 → rsnumpy-1.1.2}/python/rsnumpy/polynomial/__init__.py +0 -0
  27. {rsnumpy-1.0.6 → rsnumpy-1.1.2}/rust-toolchain.toml +0 -0
  28. {rsnumpy-1.0.6 → rsnumpy-1.1.2}/src/fft.rs +0 -0
  29. {rsnumpy-1.0.6 → rsnumpy-1.1.2}/src/indexing.rs +0 -0
  30. {rsnumpy-1.0.6 → rsnumpy-1.1.2}/src/linalg.rs +0 -0
@@ -41,7 +41,9 @@ debug*.py
41
41
  check*.py
42
42
  test2*.py
43
43
  map*.jpeg
44
+ bench_extra.py
44
45
  *.png
46
+ runtest_matplotlib.py
45
47
 
46
48
  # Environment
47
49
  .venv
@@ -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"
@@ -389,9 +389,9 @@ dependencies = [
389
389
 
390
390
  [[package]]
391
391
  name = "memchr"
392
- version = "2.8.2"
392
+ version = "2.8.3"
393
393
  source = "registry+https://github.com/rust-lang/crates.io-index"
394
- checksum = "88904434abc2901f197fe8cc55f0445e7ded921dba5911dad2e2b39b48e663c4"
394
+ checksum = "cf8baf1c55e62ffcace7a9f06f4bd9cd3f0c4beb022d3b367256b91b87513d98"
395
395
 
396
396
  [[package]]
397
397
  name = "miniz_oxide"
@@ -656,7 +656,7 @@ dependencies = [
656
656
 
657
657
  [[package]]
658
658
  name = "rsnumpy"
659
- version = "1.0.6"
659
+ version = "1.1.2"
660
660
  dependencies = [
661
661
  "ndarray",
662
662
  "num-complex",
@@ -686,9 +686,9 @@ dependencies = [
686
686
 
687
687
  [[package]]
688
688
  name = "rustversion"
689
- version = "1.0.22"
689
+ version = "1.0.23"
690
690
  source = "registry+https://github.com/rust-lang/crates.io-index"
691
- checksum = "b39cdef0fa800fc44525c84ccb54a029961a8215f9619753635a9c0d2538d46d"
691
+ checksum = "cf54715a573b99ac80df0bc206da022bcd442c974952c7b9720069370852e21f"
692
692
 
693
693
  [[package]]
694
694
  name = "serde"
@@ -930,9 +930,9 @@ dependencies = [
930
930
 
931
931
  [[package]]
932
932
  name = "zlib-rs"
933
- version = "0.6.5"
933
+ version = "0.6.6"
934
934
  source = "registry+https://github.com/rust-lang/crates.io-index"
935
- checksum = "5431d5661c32445236631278f27946e444ddafe4684cac70b185272d4f9c52d5"
935
+ checksum = "b142a20ec14a91d5bc708c1dc21b080c550113d8aa77afa29635673a65dd02c5"
936
936
 
937
937
  [[package]]
938
938
  name = "zopfli"
@@ -1,6 +1,6 @@
1
1
  [package]
2
2
  name = "rsnumpy"
3
- version = "1.0.6"
3
+ version = "1.1.2"
4
4
  edition = "2024"
5
5
  readme = "README.md"
6
6
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: rsnumpy
3
- Version: 1.0.6
3
+ Version: 1.1.2
4
4
  Classifier: Programming Language :: Rust
5
5
  Classifier: Programming Language :: Python :: 3
6
6
  Classifier: Programming Language :: Python :: 3 :: Only
@@ -51,15 +51,19 @@ Description-Content-Type: text/markdown; charset=UTF-8; variant=GFM
51
51
  rsnumpy/
52
52
  ├── src/ # Rust 源码
53
53
  │ ├── lib.rs # 核心 ndarray 与通用函数
54
+ │ ├── indexing.rs # 多维索引与切片
54
55
  │ ├── fft.rs # 快速傅里叶变换
55
56
  │ ├── linalg.rs # 线性代数
56
- │ └── random.rs # 随机数生成
57
- ├── rsnumpy/ # Python 薄包装
57
+ │ └── random.rs # 随机数生成(可复现并行采样)
58
+ ├── python/rsnumpy/ # Python 薄包装
58
59
  │ ├── __init__.py # 主模块,整合所有 API
59
60
  │ ├── array_methods.py # ndarray 对象方法
60
61
  │ ├── array_ops.py # 数组操作函数
62
+ │ ├── _extra.py # 补充 API(别名、nan 系列、集合运算、窗函数等)
61
63
  │ ├── math_functions.py # 数学函数
62
64
  │ ├── statistics.py # 统计函数
65
+ │ ├── char.py # 字符串数组函数
66
+ │ ├── matlib.py # 矩阵便捷构造
63
67
  │ ├── io.py # 文件 I/O
64
68
  │ ├── linalg/ # 线性代数子模块
65
69
  │ ├── polynomial/ # 多项式子模块
@@ -283,6 +287,8 @@ print(np.random.rand(3).tolist())
283
287
  print(np.random.randn(3).tolist())
284
288
  ```
285
289
 
290
+ > **可复现性**:相同 `seed` 保证生成相同的结果。大数组采样在 Rust 层并行执行,采用固定分块 + `splitmix64` 派生各分块的独立种子,因此**结果与线程数无关**,在不同机器上同样可复现。同一个 `Generator` 每次调用都会推进内部状态,连续调用不会产生重复序列。
291
+
286
292
  #### 5.7 FFT
287
293
 
288
294
  ```python
@@ -365,6 +371,81 @@ print(np.isinf(a))
365
371
  print(np.isfinite(a))
366
372
  ```
367
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
+
368
449
  ---
369
450
 
370
451
  ### 6. 常见问题
@@ -457,26 +538,32 @@ A: 当前版本仅支持 CPU。
457
538
  **Project layout:**
458
539
 
459
540
  ```
541
+
460
542
  rsnumpy/
461
- ├── src/ # Rust source
462
- │ ├── lib.rs # Core ndarray & general functions
463
- │ ├── fft.rs # Fast Fourier Transform
464
- │ ├── linalg.rs # Linear algebra
465
- │ └── random.rs # Random number generation
466
- ├── rsnumpy/ # Python thin wrappers
467
- │ ├── __init__.py # Main module, exports public API
468
- │ ├── array_methods.py # ndarray object methods
469
- │ ├── array_ops.py # Array manipulation functions
470
- │ ├── math_functions.py # Math functions
471
- │ ├── statistics.py # Statistics functions
472
- │ ├── io.py # File I/O
473
- │ ├── linalg/ # Linear algebra submodule
474
- │ ├── polynomial/ # Polynomial submodule
475
- │ └── random/ # Random submodule
476
- ├── Cargo.toml # Rust dependencies
477
- ├── pyproject.toml # Python build config
478
- ├── build_wheel.sh # Build script
479
- └── 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
+
480
567
  ```
481
568
 
482
569
  ---
@@ -692,6 +779,8 @@ print(np.random.rand(3).tolist())
692
779
  print(np.random.randn(3).tolist())
693
780
  ```
694
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
+
695
784
  #### 5.7 FFT
696
785
 
697
786
  ```python
@@ -774,6 +863,81 @@ print(np.isinf(a))
774
863
  print(np.isfinite(a))
775
864
  ```
776
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
+
777
941
  ---
778
942
 
779
943
  ### 6. FAQ
@@ -27,15 +27,19 @@
27
27
  rsnumpy/
28
28
  ├── src/ # Rust 源码
29
29
  │ ├── lib.rs # 核心 ndarray 与通用函数
30
+ │ ├── indexing.rs # 多维索引与切片
30
31
  │ ├── fft.rs # 快速傅里叶变换
31
32
  │ ├── linalg.rs # 线性代数
32
- │ └── random.rs # 随机数生成
33
- ├── rsnumpy/ # Python 薄包装
33
+ │ └── random.rs # 随机数生成(可复现并行采样)
34
+ ├── python/rsnumpy/ # Python 薄包装
34
35
  │ ├── __init__.py # 主模块,整合所有 API
35
36
  │ ├── array_methods.py # ndarray 对象方法
36
37
  │ ├── array_ops.py # 数组操作函数
38
+ │ ├── _extra.py # 补充 API(别名、nan 系列、集合运算、窗函数等)
37
39
  │ ├── math_functions.py # 数学函数
38
40
  │ ├── statistics.py # 统计函数
41
+ │ ├── char.py # 字符串数组函数
42
+ │ ├── matlib.py # 矩阵便捷构造
39
43
  │ ├── io.py # 文件 I/O
40
44
  │ ├── linalg/ # 线性代数子模块
41
45
  │ ├── polynomial/ # 多项式子模块
@@ -259,6 +263,8 @@ print(np.random.rand(3).tolist())
259
263
  print(np.random.randn(3).tolist())
260
264
  ```
261
265
 
266
+ > **可复现性**:相同 `seed` 保证生成相同的结果。大数组采样在 Rust 层并行执行,采用固定分块 + `splitmix64` 派生各分块的独立种子,因此**结果与线程数无关**,在不同机器上同样可复现。同一个 `Generator` 每次调用都会推进内部状态,连续调用不会产生重复序列。
267
+
262
268
  #### 5.7 FFT
263
269
 
264
270
  ```python
@@ -341,6 +347,81 @@ print(np.isinf(a))
341
347
  print(np.isfinite(a))
342
348
  ```
343
349
 
350
+ #### 5.11 日期时间与网格
351
+
352
+ ```python
353
+ import rsnumpy as np
354
+
355
+ # 日期时间标量(兼容 numpy.datetime64)
356
+ d = np.datetime64('2024-01-01')
357
+ delta = np.timedelta64(7, 'D') # 7 天
358
+ print(d + delta) # numpy.datetime64('2024-01-08')
359
+ print(np.datetime64('2024-01-08') - d) # numpy.timedelta64(7,'D')
360
+
361
+ # 用 datetime64/timedelta64 生成日期序列
362
+ days = np.arange(np.datetime64('2024-01-01'),
363
+ np.datetime64('2024-01-05'),
364
+ np.timedelta64(1, 'D'))
365
+
366
+ # 坐标网格(默认 'xy' 索引,与 NumPy 一致)
367
+ x = np.array([1, 2, 3])
368
+ y = np.array([10, 20])
369
+ X, Y = np.meshgrid(x, y)
370
+ print(X.tolist()) # [[1.0, 2.0, 3.0], [1.0, 2.0, 3.0]]
371
+ print(Y.tolist()) # [[10.0, 10.0, 10.0], [20.0, 20.0, 20.0]]
372
+ ```
373
+
374
+ #### 5.12 补充 API 覆盖(对齐 NumPy 2.5.1)
375
+
376
+ 在核心 Rust 原语之上,`_extra.py` 补充了约 140 个 NumPy 兼容函数,全部对照 NumPy 2.5.1 逐函数验证通过。计算密集/逐元素部分复用现有 Rust 原语,纯变形与组合类则以薄 Python 包装实现。
377
+
378
+ ```python
379
+ import rsnumpy as np
380
+
381
+ # 三角/双曲别名(Array API 命名)
382
+ np.acos(1.0); np.asin(0.0); np.atan(1.0); np.atan2(1.0, 1.0)
383
+ np.radians(180.0); np.degrees(np.pi)
384
+
385
+ # 逐元素数学
386
+ np.hypot(3.0, 4.0) # 5.0
387
+ np.maximum([1, 5], [3, 2]) # [3, 5]
388
+ np.fmax([np.nan, 2], [1, np.nan]) # 忽略 NaN
389
+ np.logaddexp(0.0, 0.0) # 数值稳定 log(exp(a)+exp(b))
390
+ np.rint([0.5, 1.5, 2.5]) # 四舍六入五成双 -> [0, 2, 2]
391
+ np.gcd(12, 8); np.lcm(4, 6)
392
+ frac, whole = np.modf([1.5, 2.25])
393
+
394
+ # nan 系列归约
395
+ a = np.array([1.0, np.nan, 3.0])
396
+ np.nansum(a); np.nanmean(a); np.nanstd(a); np.nanmax(a)
397
+ np.nancumsum(a); np.nanargmax(a)
398
+ np.prod([1, 2, 3, 4]) # 24
399
+
400
+ # 集合运算
401
+ np.intersect1d([1, 2, 3], [2, 3, 4]) # [2, 3]
402
+ np.union1d([1, 2], [2, 3]) # [1, 2, 3]
403
+ np.setdiff1d([1, 2, 3], [2]) # [1, 3]
404
+ np.isin([1, 2, 5], [1, 5]) # [True, False, True]
405
+ uniq, counts = np.unique_counts([1, 1, 2, 3, 3, 3])
406
+
407
+ # 变形 / 组合
408
+ np.block([[np.eye(2), np.ones((2, 1))]])
409
+ np.pad([1, 2, 3], (1, 2), mode='reflect')
410
+ np.kron([1, 2], [1, 1])
411
+ np.tensordot(np.ones((2, 3)), np.ones((3, 4)), axes=1)
412
+
413
+ # 复数
414
+ z = np.array([1 + 2j, 3 - 1j])
415
+ np.real(z); np.imag(z); np.conjugate(z); np.angle(z)
416
+
417
+ # 信号 / 窗函数 / 插值
418
+ np.convolve([1, 2, 3], [1, 1])
419
+ np.interp(2.5, [1, 2, 3], [10, 20, 30])
420
+ np.hanning(8); np.hamming(8); np.blackman(8); np.bartlett(8)
421
+ np.vander([1, 2, 3], 3)
422
+ np.bincount([0, 1, 1, 2, 2, 2])
423
+ ```
424
+
344
425
  ---
345
426
 
346
427
  ### 6. 常见问题
@@ -433,26 +514,32 @@ A: 当前版本仅支持 CPU。
433
514
  **Project layout:**
434
515
 
435
516
  ```
517
+
436
518
  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
519
+ ├── src/ # Rust source
520
+ │ ├── lib.rs # Core ndarray & general functions
521
+ │ ├── indexing.rs # Multi-dimensional indexing & slicing
522
+ │ ├── fft.rs # Fast Fourier Transform
523
+ │ ├── linalg.rs # Linear algebra
524
+ │ └── random.rs # Random number generation (reproducible parallel sampling)
525
+ ├── python/rsnumpy/ # Python thin wrappers
526
+ │ ├── **init**.py # Main module, exports public API
527
+ │ ├── array_methods.py # ndarray object methods
528
+ │ ├── array_ops.py # Array manipulation functions
529
+ │ ├── _extra.py # Supplementary API (aliases, nan-reductions, set ops, windows, ...)
530
+ │ ├── math_functions.py # Math functions
531
+ │ ├── statistics.py # Statistics functions
532
+ │ ├── char.py # String array functions
533
+ │ ├── matlib.py # Matrix construction helpers
534
+ │ ├── io.py # File I/O
535
+ │ ├── linalg/ # Linear algebra submodule
536
+ │ ├── polynomial/ # Polynomial submodule
537
+ │ └── random/ # Random submodule
538
+ ├── Cargo.toml # Rust dependencies
539
+ ├── pyproject.toml # Python build config
540
+ ├── build_wheel.sh # Build script
541
+ └── README.md # This file
542
+
456
543
  ```
457
544
 
458
545
  ---
@@ -668,6 +755,8 @@ print(np.random.rand(3).tolist())
668
755
  print(np.random.randn(3).tolist())
669
756
  ```
670
757
 
758
+ > **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.
759
+
671
760
  #### 5.7 FFT
672
761
 
673
762
  ```python
@@ -750,6 +839,81 @@ print(np.isinf(a))
750
839
  print(np.isfinite(a))
751
840
  ```
752
841
 
842
+ #### 5.11 Datetime & meshgrid
843
+
844
+ ```python
845
+ import rsnumpy as np
846
+
847
+ # Datetime scalars (compatible with numpy.datetime64)
848
+ d = np.datetime64('2024-01-01')
849
+ delta = np.timedelta64(7, 'D') # 7 days
850
+ print(d + delta) # numpy.datetime64('2024-01-08')
851
+ print(np.datetime64('2024-01-08') - d) # numpy.timedelta64(7,'D')
852
+
853
+ # Generate a date range with datetime64/timedelta64
854
+ days = np.arange(np.datetime64('2024-01-01'),
855
+ np.datetime64('2024-01-05'),
856
+ np.timedelta64(1, 'D'))
857
+
858
+ # Coordinate grids (default 'xy' indexing, matching NumPy)
859
+ x = np.array([1, 2, 3])
860
+ y = np.array([10, 20])
861
+ X, Y = np.meshgrid(x, y)
862
+ print(X.tolist()) # [[1.0, 2.0, 3.0], [1.0, 2.0, 3.0]]
863
+ print(Y.tolist()) # [[10.0, 10.0, 10.0], [20.0, 20.0, 20.0]]
864
+ ```
865
+
866
+ #### 5.12 Supplementary API Coverage (aligned with NumPy 2.5.1)
867
+
868
+ 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.
869
+
870
+ ```python
871
+ import rsnumpy as np
872
+
873
+ # Trig/hyperbolic aliases (Array API names)
874
+ np.acos(1.0); np.asin(0.0); np.atan(1.0); np.atan2(1.0, 1.0)
875
+ np.radians(180.0); np.degrees(np.pi)
876
+
877
+ # Element-wise math
878
+ np.hypot(3.0, 4.0) # 5.0
879
+ np.maximum([1, 5], [3, 2]) # [3, 5]
880
+ np.fmax([np.nan, 2], [1, np.nan]) # NaN-ignoring
881
+ np.logaddexp(0.0, 0.0) # numerically stable log(exp(a)+exp(b))
882
+ np.rint([0.5, 1.5, 2.5]) # round-half-to-even -> [0, 2, 2]
883
+ np.gcd(12, 8); np.lcm(4, 6)
884
+ frac, whole = np.modf([1.5, 2.25])
885
+
886
+ # nan-reductions
887
+ a = np.array([1.0, np.nan, 3.0])
888
+ np.nansum(a); np.nanmean(a); np.nanstd(a); np.nanmax(a)
889
+ np.nancumsum(a); np.nanargmax(a)
890
+ np.prod([1, 2, 3, 4]) # 24
891
+
892
+ # Set operations
893
+ np.intersect1d([1, 2, 3], [2, 3, 4]) # [2, 3]
894
+ np.union1d([1, 2], [2, 3]) # [1, 2, 3]
895
+ np.setdiff1d([1, 2, 3], [2]) # [1, 3]
896
+ np.isin([1, 2, 5], [1, 5]) # [True, False, True]
897
+ uniq, counts = np.unique_counts([1, 1, 2, 3, 3, 3])
898
+
899
+ # Reshaping / composition
900
+ np.block([[np.eye(2), np.ones((2, 1))]])
901
+ np.pad([1, 2, 3], (1, 2), mode='reflect')
902
+ np.kron([1, 2], [1, 1])
903
+ np.tensordot(np.ones((2, 3)), np.ones((3, 4)), axes=1)
904
+
905
+ # Complex
906
+ z = np.array([1 + 2j, 3 - 1j])
907
+ np.real(z); np.imag(z); np.conjugate(z); np.angle(z)
908
+
909
+ # Signal / windows / interpolation
910
+ np.convolve([1, 2, 3], [1, 1])
911
+ np.interp(2.5, [1, 2, 3], [10, 20, 30])
912
+ np.hanning(8); np.hamming(8); np.blackman(8); np.bartlett(8)
913
+ np.vander([1, 2, 3], 3)
914
+ np.bincount([0, 1, 1, 2, 2, 2])
915
+ ```
916
+
753
917
  ---
754
918
 
755
919
  ### 6. FAQ
@@ -18,10 +18,10 @@ sed -i.bak "s/^version = \".*\"/version = \"$VERSION\"/" pyproject.toml
18
18
  rm -f pyproject.toml.bak
19
19
  echo " -> pyproject.toml version updated to $VERSION"
20
20
 
21
- # ========== 同步版本到 python/rsplotlib/__init__.py ==========
22
- sed -i.bak "s/^__version__ = \".*\"/__version__ = \"$VERSION\"/" python/rsplotlib/__init__.py 2>/dev/null || true
23
- rm -f python/rsplotlib/__init__.py.bak
24
- echo " -> python/rsplotlib/__init__.py __version__ updated to $VERSION"
21
+ # ========== 同步版本到 python/rsnumpy/__init__.py ==========
22
+ sed -i.bak "s/^__version__ = \".*\"/__version__ = \"$VERSION\"/" python/rsnumpy/__init__.py 2>/dev/null || true
23
+ rm -f python/rsnumpy/__init__.py.bak
24
+ echo " -> python/rsnumpy/__init__.py __version__ updated to $VERSION"
25
25
 
26
26
  # ========== 检查 cargo 是否可用(maturin 构建需要) ==========
27
27
  if ! command -v cargo >/dev/null 2>&1; then
@@ -4,7 +4,7 @@ build-backend = "maturin"
4
4
 
5
5
  [project]
6
6
  name = "rsnumpy"
7
- version = "1.0.6"
7
+ version = "1.1.2"
8
8
  requires-python = ">=3.10"
9
9
  description = "A Rust-powered NumPy-compatible array library."
10
10
  readme = "README.md"