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.
- {rsnumpy-1.0.6 → rsnumpy-1.1.2}/.gitignore +2 -0
- {rsnumpy-1.0.6 → rsnumpy-1.1.2}/Cargo.lock +13 -13
- {rsnumpy-1.0.6 → rsnumpy-1.1.2}/Cargo.toml +1 -1
- {rsnumpy-1.0.6 → rsnumpy-1.1.2}/PKG-INFO +186 -22
- {rsnumpy-1.0.6 → rsnumpy-1.1.2}/README.md +185 -21
- {rsnumpy-1.0.6 → rsnumpy-1.1.2}/build_wheel.sh +4 -4
- {rsnumpy-1.0.6 → rsnumpy-1.1.2}/pyproject.toml +1 -1
- {rsnumpy-1.0.6 → rsnumpy-1.1.2}/python/rsnumpy/__init__.py +807 -98
- rsnumpy-1.1.2/python/rsnumpy/_extra.py +2831 -0
- {rsnumpy-1.0.6 → rsnumpy-1.1.2}/python/rsnumpy/array_ops.py +56 -14
- {rsnumpy-1.0.6 → rsnumpy-1.1.2}/python/rsnumpy/random/__init__.py +12 -7
- {rsnumpy-1.0.6 → rsnumpy-1.1.2}/python/rsnumpy/statistics.py +9 -18
- {rsnumpy-1.0.6 → rsnumpy-1.1.2}/src/lib.rs +697 -53
- {rsnumpy-1.0.6 → rsnumpy-1.1.2}/src/random.rs +83 -51
- {rsnumpy-1.0.6 → rsnumpy-1.1.2}/test/run_test.py +234 -3
- {rsnumpy-1.0.6 → rsnumpy-1.1.2}/.github/workflows/ci.yml +0 -0
- {rsnumpy-1.0.6 → rsnumpy-1.1.2}/.github/workflows/release.yml +0 -0
- {rsnumpy-1.0.6 → rsnumpy-1.1.2}/LICENSE +0 -0
- {rsnumpy-1.0.6 → rsnumpy-1.1.2}/RELEASE_NOTES.md +0 -0
- {rsnumpy-1.0.6 → rsnumpy-1.1.2}/python/rsnumpy/array_methods.py +0 -0
- {rsnumpy-1.0.6 → rsnumpy-1.1.2}/python/rsnumpy/char.py +0 -0
- {rsnumpy-1.0.6 → rsnumpy-1.1.2}/python/rsnumpy/io.py +0 -0
- {rsnumpy-1.0.6 → rsnumpy-1.1.2}/python/rsnumpy/linalg/__init__.py +0 -0
- {rsnumpy-1.0.6 → rsnumpy-1.1.2}/python/rsnumpy/math_functions.py +0 -0
- {rsnumpy-1.0.6 → rsnumpy-1.1.2}/python/rsnumpy/matlib.py +0 -0
- {rsnumpy-1.0.6 → rsnumpy-1.1.2}/python/rsnumpy/polynomial/__init__.py +0 -0
- {rsnumpy-1.0.6 → rsnumpy-1.1.2}/rust-toolchain.toml +0 -0
- {rsnumpy-1.0.6 → rsnumpy-1.1.2}/src/fft.rs +0 -0
- {rsnumpy-1.0.6 → rsnumpy-1.1.2}/src/indexing.rs +0 -0
- {rsnumpy-1.0.6 → rsnumpy-1.1.2}/src/linalg.rs +0 -0
|
@@ -142,9 +142,9 @@ dependencies = [
|
|
|
142
142
|
|
|
143
143
|
[[package]]
|
|
144
144
|
name = "crossbeam-deque"
|
|
145
|
-
version = "0.8.
|
|
145
|
+
version = "0.8.7"
|
|
146
146
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
147
|
-
checksum = "
|
|
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.
|
|
155
|
+
version = "0.9.20"
|
|
156
156
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
157
|
-
checksum = "
|
|
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.
|
|
164
|
+
version = "0.8.22"
|
|
165
165
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
166
|
-
checksum = "
|
|
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.
|
|
392
|
+
version = "2.8.3"
|
|
393
393
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
394
|
-
checksum = "
|
|
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.
|
|
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.
|
|
689
|
+
version = "1.0.23"
|
|
690
690
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
691
|
-
checksum = "
|
|
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.
|
|
933
|
+
version = "0.6.6"
|
|
934
934
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
935
|
-
checksum = "
|
|
935
|
+
checksum = "b142a20ec14a91d5bc708c1dc21b080c550113d8aa77afa29635673a65dd02c5"
|
|
936
936
|
|
|
937
937
|
[[package]]
|
|
938
938
|
name = "zopfli"
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: rsnumpy
|
|
3
|
-
Version: 1.
|
|
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/
|
|
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/
|
|
462
|
-
│
|
|
463
|
-
│
|
|
464
|
-
│
|
|
465
|
-
│
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
│
|
|
469
|
-
│
|
|
470
|
-
│
|
|
471
|
-
│
|
|
472
|
-
│
|
|
473
|
-
│
|
|
474
|
-
│
|
|
475
|
-
│
|
|
476
|
-
├──
|
|
477
|
-
├──
|
|
478
|
-
├──
|
|
479
|
-
└──
|
|
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/
|
|
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/
|
|
438
|
-
│
|
|
439
|
-
│
|
|
440
|
-
│
|
|
441
|
-
│
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
│
|
|
445
|
-
│
|
|
446
|
-
│
|
|
447
|
-
│
|
|
448
|
-
│
|
|
449
|
-
│
|
|
450
|
-
│
|
|
451
|
-
│
|
|
452
|
-
├──
|
|
453
|
-
├──
|
|
454
|
-
├──
|
|
455
|
-
└──
|
|
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/
|
|
22
|
-
sed -i.bak "s/^__version__ = \".*\"/__version__ = \"$VERSION\"/" python/
|
|
23
|
-
rm -f python/
|
|
24
|
-
echo " -> python/
|
|
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
|