rsnumpy 1.0.1__tar.gz → 1.0.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.1 → rsnumpy-1.0.2}/.gitignore +3 -1
- {rsnumpy-1.0.1 → rsnumpy-1.0.2}/Cargo.lock +35 -1
- rsnumpy-1.0.2/Cargo.toml +36 -0
- {rsnumpy-1.0.1 → rsnumpy-1.0.2}/PKG-INFO +1 -2
- {rsnumpy-1.0.1 → rsnumpy-1.0.2}/README.md +0 -1
- rsnumpy-1.0.2/RELEASE_NOTES.md +82 -0
- {rsnumpy-1.0.1 → rsnumpy-1.0.2}/build_wheel.sh +16 -6
- {rsnumpy-1.0.1 → rsnumpy-1.0.2}/pyproject.toml +1 -1
- {rsnumpy-1.0.1 → rsnumpy-1.0.2}/python/rsnumpy/__init__.py +13 -29
- rsnumpy-1.0.2/python/rsnumpy/array_methods.py +225 -0
- {rsnumpy-1.0.1 → rsnumpy-1.0.2}/python/rsnumpy/array_ops.py +21 -165
- {rsnumpy-1.0.1 → rsnumpy-1.0.2}/python/rsnumpy/matlib.py +11 -27
- {rsnumpy-1.0.1 → rsnumpy-1.0.2}/python/rsnumpy/random/__init__.py +4 -0
- {rsnumpy-1.0.1 → rsnumpy-1.0.2}/python/rsnumpy/statistics.py +10 -19
- rsnumpy-1.0.2/src/fft.rs +162 -0
- {rsnumpy-1.0.1 → rsnumpy-1.0.2}/src/indexing.rs +126 -185
- {rsnumpy-1.0.1 → rsnumpy-1.0.2}/src/lib.rs +805 -232
- {rsnumpy-1.0.1 → rsnumpy-1.0.2}/src/linalg.rs +318 -330
- {rsnumpy-1.0.1 → rsnumpy-1.0.2}/src/random.rs +213 -142
- rsnumpy-1.0.1/.trae/rules/git-commit-message.md +0 -6
- rsnumpy-1.0.1/Cargo.toml +0 -19
- rsnumpy-1.0.1/python/rsnumpy/array_methods.py +0 -474
- rsnumpy-1.0.1/src/fft.rs +0 -256
- {rsnumpy-1.0.1 → rsnumpy-1.0.2}/.github/ci.yml +0 -0
- {rsnumpy-1.0.1 → rsnumpy-1.0.2}/.github/release.yml +0 -0
- {rsnumpy-1.0.1 → rsnumpy-1.0.2}/.github/workflows/rust-clippy.yml +0 -0
- {rsnumpy-1.0.1 → rsnumpy-1.0.2}/LICENSE +0 -0
- {rsnumpy-1.0.1 → rsnumpy-1.0.2}/plots.py +0 -0
- {rsnumpy-1.0.1 → rsnumpy-1.0.2}/python/rsnumpy/char.py +0 -0
- {rsnumpy-1.0.1 → rsnumpy-1.0.2}/python/rsnumpy/io.py +0 -0
- {rsnumpy-1.0.1 → rsnumpy-1.0.2}/python/rsnumpy/linalg/__init__.py +0 -0
- {rsnumpy-1.0.1 → rsnumpy-1.0.2}/python/rsnumpy/math_functions.py +0 -0
- {rsnumpy-1.0.1 → rsnumpy-1.0.2}/python/rsnumpy/polynomial/__init__.py +0 -0
|
@@ -62,6 +62,15 @@ dependencies = [
|
|
|
62
62
|
"libbz2-rs-sys",
|
|
63
63
|
]
|
|
64
64
|
|
|
65
|
+
[[package]]
|
|
66
|
+
name = "cblas-sys"
|
|
67
|
+
version = "0.1.4"
|
|
68
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
69
|
+
checksum = "b6feecd82cce51b0204cf063f0041d69f24ce83f680d87514b004248e7b0fa65"
|
|
70
|
+
dependencies = [
|
|
71
|
+
"libc",
|
|
72
|
+
]
|
|
73
|
+
|
|
65
74
|
[[package]]
|
|
66
75
|
name = "cc"
|
|
67
76
|
version = "1.2.64"
|
|
@@ -461,6 +470,8 @@ version = "0.17.2"
|
|
|
461
470
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
462
471
|
checksum = "520080814a7a6b4a6e9070823bb24b4531daac8c4627e08ba5de8c5ef2f2752d"
|
|
463
472
|
dependencies = [
|
|
473
|
+
"cblas-sys",
|
|
474
|
+
"libc",
|
|
464
475
|
"matrixmultiply",
|
|
465
476
|
"num-complex",
|
|
466
477
|
"num-integer",
|
|
@@ -469,6 +480,7 @@ dependencies = [
|
|
|
469
480
|
"portable-atomic-util",
|
|
470
481
|
"rawpointer",
|
|
471
482
|
"rayon",
|
|
483
|
+
"serde",
|
|
472
484
|
]
|
|
473
485
|
|
|
474
486
|
[[package]]
|
|
@@ -721,15 +733,17 @@ dependencies = [
|
|
|
721
733
|
|
|
722
734
|
[[package]]
|
|
723
735
|
name = "rsnumpy"
|
|
724
|
-
version = "1.0.
|
|
736
|
+
version = "1.0.2"
|
|
725
737
|
dependencies = [
|
|
726
738
|
"ndarray",
|
|
739
|
+
"num-complex",
|
|
727
740
|
"num-traits",
|
|
728
741
|
"pyo3",
|
|
729
742
|
"rand",
|
|
730
743
|
"rand_distr",
|
|
731
744
|
"rayon",
|
|
732
745
|
"rustfft",
|
|
746
|
+
"thiserror",
|
|
733
747
|
"zip",
|
|
734
748
|
]
|
|
735
749
|
|
|
@@ -864,6 +878,26 @@ version = "0.13.5"
|
|
|
864
878
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
865
879
|
checksum = "adb6935a6f5c20170eeceb1a3835a49e12e19d792f6dd344ccc76a985ca5a6ca"
|
|
866
880
|
|
|
881
|
+
[[package]]
|
|
882
|
+
name = "thiserror"
|
|
883
|
+
version = "2.0.18"
|
|
884
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
885
|
+
checksum = "4288b5bcbc7920c07a1149a35cf9590a2aa808e0bc1eafaade0b80947865fbc4"
|
|
886
|
+
dependencies = [
|
|
887
|
+
"thiserror-impl",
|
|
888
|
+
]
|
|
889
|
+
|
|
890
|
+
[[package]]
|
|
891
|
+
name = "thiserror-impl"
|
|
892
|
+
version = "2.0.18"
|
|
893
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
894
|
+
checksum = "ebc4ee7f67670e9b64d05fa4253e753e016c6c95ff35b89b7941d6b856dec1d5"
|
|
895
|
+
dependencies = [
|
|
896
|
+
"proc-macro2",
|
|
897
|
+
"quote",
|
|
898
|
+
"syn",
|
|
899
|
+
]
|
|
900
|
+
|
|
867
901
|
[[package]]
|
|
868
902
|
name = "time"
|
|
869
903
|
version = "0.3.49"
|
rsnumpy-1.0.2/Cargo.toml
ADDED
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
[package]
|
|
2
|
+
name = "rsnumpy"
|
|
3
|
+
version = "1.0.2"
|
|
4
|
+
edition = "2024"
|
|
5
|
+
readme = "README.md"
|
|
6
|
+
|
|
7
|
+
[lib]
|
|
8
|
+
name = "rsnumpy"
|
|
9
|
+
crate-type = ["cdylib"]
|
|
10
|
+
|
|
11
|
+
[dependencies]
|
|
12
|
+
pyo3 = { version = "0.29.0", features = ["extension-module", "abi3-py38"] }
|
|
13
|
+
ndarray = { version = "0.17.2", features = ["rayon", "blas", "serde"] }
|
|
14
|
+
rayon = "1.12.0"
|
|
15
|
+
rand = "0.10.1"
|
|
16
|
+
rand_distr = "0.6.0"
|
|
17
|
+
num-traits = "0.2.19"
|
|
18
|
+
rustfft = "6.4.1"
|
|
19
|
+
zip = "8.6.0"
|
|
20
|
+
num-complex = "0.4.6"
|
|
21
|
+
thiserror = "2.0.0"
|
|
22
|
+
|
|
23
|
+
[features]
|
|
24
|
+
default = []
|
|
25
|
+
blas = ["ndarray/blas"]
|
|
26
|
+
|
|
27
|
+
[profile.release]
|
|
28
|
+
opt-level = 3
|
|
29
|
+
lto = "fat"
|
|
30
|
+
codegen-units = 1
|
|
31
|
+
panic = "abort"
|
|
32
|
+
strip = true
|
|
33
|
+
|
|
34
|
+
[profile.bench]
|
|
35
|
+
opt-level = 3
|
|
36
|
+
debug = false
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: rsnumpy
|
|
3
|
-
Version: 1.0.
|
|
3
|
+
Version: 1.0.2
|
|
4
4
|
Classifier: License :: OSI Approved :: MIT License
|
|
5
5
|
Classifier: Programming Language :: Rust
|
|
6
6
|
Classifier: Programming Language :: Python :: Implementation :: CPython
|
|
@@ -15,7 +15,6 @@ Description-Content-Type: text/markdown; charset=UTF-8; variant=GFM
|
|
|
15
15
|
|
|
16
16
|
**A Rust-powered NumPy-compatible array library.**
|
|
17
17
|
|
|
18
|
-

|
|
19
18
|

|
|
20
19
|

|
|
21
20
|

|
|
@@ -2,7 +2,6 @@
|
|
|
2
2
|
|
|
3
3
|
**A Rust-powered NumPy-compatible array library.**
|
|
4
4
|
|
|
5
|
-

|
|
6
5
|

|
|
7
6
|

|
|
8
7
|

|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
# Release Notes
|
|
2
|
+
|
|
3
|
+
## v1.0.2 (2026-06-24)
|
|
4
|
+
|
|
5
|
+
### 性能优化
|
|
6
|
+
|
|
7
|
+
- **索引模块优化**:向量预分配,提升花式索引性能
|
|
8
|
+
- **数组拼接优化**:`concatenate`、`stack` 等函数性能提升
|
|
9
|
+
- **数组格式化输出优化**:预分配字符串缓冲区、简化切片遍历逻辑
|
|
10
|
+
- **工具函数优化**:`arange`、`reshape` 等函数的预分配和边界处理
|
|
11
|
+
- **IO 函数优化**:`loadtxt`、`savez` 等函数的预分配和遍历逻辑
|
|
12
|
+
|
|
13
|
+
### 模块重构
|
|
14
|
+
|
|
15
|
+
- **随机数模块重构**:使用 const 初始化线程局部 RNG、优化形状解析预分配、使用 `div_ceil` 计算分块大小、简化采样类型转换
|
|
16
|
+
- **线性代数模块重构**:将 Python 绑定函数移至 PyO3 detach 闭包,避免 GIL 持有过长时间
|
|
17
|
+
- **统计函数优化**:简化 `polyfit`、`cov` 等计算的循环逻辑
|
|
18
|
+
|
|
19
|
+
### Bug 修复
|
|
20
|
+
|
|
21
|
+
- 修复 `median`、`percentile` 等统计函数的偶数长度判断逻辑
|
|
22
|
+
- 修复部分边界检查的冗余代码
|
|
23
|
+
|
|
24
|
+
### 构建优化
|
|
25
|
+
|
|
26
|
+
- 新增 `build_wheel.sh` 自动同步版本号的逻辑
|
|
27
|
+
- 优化构建配置,二进制大小略有优化
|
|
28
|
+
|
|
29
|
+
---
|
|
30
|
+
|
|
31
|
+
## v1.0.1 (2026-06-24)
|
|
32
|
+
|
|
33
|
+
### 功能增强
|
|
34
|
+
|
|
35
|
+
- **新增 ArrayFlags 支持**:提供数组标志位查询功能
|
|
36
|
+
- **新增 like-series 数组创建函数**:支持根据已有数组的属性创建新数组
|
|
37
|
+
- **改进 logspace 函数**:优化对数空间生成算法
|
|
38
|
+
|
|
39
|
+
### 性能提升
|
|
40
|
+
|
|
41
|
+
- **并行加速矩阵运算**:利用多线程并行化矩阵运算
|
|
42
|
+
- **随机数生成优化**:并行加速随机数生成
|
|
43
|
+
- **构建配置优化**:调整编译参数,提升构建效率
|
|
44
|
+
|
|
45
|
+
### 代码重构
|
|
46
|
+
|
|
47
|
+
- **迁移矩阵和数组操作到 Rust 后端**:将大量矩阵和数组操作从 Python 层迁移到 Rust 层实现
|
|
48
|
+
- **重构 matlib.py 的矩阵函数实现**:优化矩阵函数的代码结构
|
|
49
|
+
|
|
50
|
+
### 文档更新
|
|
51
|
+
|
|
52
|
+
- 更新 README 中 Python 版本支持要求至 3.10+
|
|
53
|
+
- 更新 README 文档细节并修复格式问题
|
|
54
|
+
|
|
55
|
+
---
|
|
56
|
+
|
|
57
|
+
## v1.0.0 (Initial Release)
|
|
58
|
+
|
|
59
|
+
### 核心功能
|
|
60
|
+
|
|
61
|
+
- **高性能多维数组**:基于 Rust 的 ndarray 实现,提供 NumPy 兼容的 API
|
|
62
|
+
- **数学函数**:支持 sin、cos、exp、sqrt、log 等常见数学函数
|
|
63
|
+
- **数组操作**:支持 reshape、transpose、切片、拼接等操作
|
|
64
|
+
- **统计函数**:支持 sum、mean、std、var、max、min、argmin、argmax 等
|
|
65
|
+
- **线性代数**:支持 det、inv、norm、solve、svd、qr 等矩阵运算
|
|
66
|
+
- **FFT**:支持快速傅里叶变换及其逆变换
|
|
67
|
+
- **随机数**:支持 uniform、normal、integers 等分布,兼容新旧两种 API
|
|
68
|
+
- **多项式**:支持多项式求值、求根、运算和拟合
|
|
69
|
+
- **文件 I/O**:支持 .npy、.npz 和文本文件的读写
|
|
70
|
+
|
|
71
|
+
### 优势
|
|
72
|
+
|
|
73
|
+
- **性能**:核心计算使用 Rust 实现,部分操作(sum、mean、dot 等)比 NumPy 快 1.2x-2.0x
|
|
74
|
+
- **类型安全**:利用 Rust 的强类型系统避免运行时错误
|
|
75
|
+
- **内存安全**:无数据竞争,无内存泄漏
|
|
76
|
+
- **完整 API**:覆盖 NumPy 常用功能
|
|
77
|
+
|
|
78
|
+
### 支持平台
|
|
79
|
+
|
|
80
|
+
- Python ≥ 3.10
|
|
81
|
+
- Rust ≥ 1.75
|
|
82
|
+
- macOS、Linux、Windows
|
|
@@ -4,17 +4,27 @@ set -euo pipefail
|
|
|
4
4
|
# Build Rust lib into Python wheel using maturin
|
|
5
5
|
# Usage: scripts/build_wheel.sh [--release|--debug] [--out-dir DIR] [--python PYTHON_EXEC]
|
|
6
6
|
|
|
7
|
+
# ========== 从 Cargo.toml 读取元信息 ==========
|
|
8
|
+
NAME=$(grep -m1 '^name = ' Cargo.toml | sed 's/name = "\(.*\)"/\1/')
|
|
9
|
+
VERSION=$(grep -m1 '^version = ' Cargo.toml | sed 's/version = "\(.*\)"/\1/')
|
|
10
|
+
|
|
11
|
+
echo "Project: $NAME, Version: $VERSION"
|
|
12
|
+
|
|
13
|
+
# ========== 同步版本到 pyproject.toml ==========
|
|
14
|
+
sed -i '' "s/^version = \".*\"/version = \"$VERSION\"/" pyproject.toml
|
|
15
|
+
echo " -> pyproject.toml version updated to $VERSION"
|
|
16
|
+
|
|
17
|
+
# ========== 同步版本到 python/rsnumpy/__init__.py ==========
|
|
18
|
+
sed -i '' "s/^__version__ = \".*\"/__version__ = \"$VERSION\"/" python/rsnumpy/__init__.py
|
|
19
|
+
echo " -> python/rsnumpy/__init__.py __version__ updated to $VERSION"
|
|
20
|
+
|
|
7
21
|
RELEASE=true
|
|
8
22
|
OUT_DIR="wheelhouse"
|
|
9
|
-
|
|
23
|
+
|
|
10
24
|
# 如果 wheelhouse 目录存在, 则删除
|
|
11
25
|
if [[ -d "$OUT_DIR" ]]; then
|
|
12
26
|
rm -rf "$OUT_DIR"
|
|
13
27
|
fi
|
|
14
|
-
# 如果 cache_file 目录存在, 则删除
|
|
15
|
-
if [[ -f "$cache_file" ]]; then
|
|
16
|
-
rm "$cache_file"
|
|
17
|
-
fi
|
|
18
28
|
|
|
19
29
|
# Default python executable; may be overridden by --python or positional arg
|
|
20
30
|
PYTHON_EXEC="python"
|
|
@@ -80,4 +90,4 @@ else
|
|
|
80
90
|
echo "Warning: no .whl file found in $OUT_DIR; skip install." >&2
|
|
81
91
|
fi
|
|
82
92
|
|
|
83
|
-
echo "Done."
|
|
93
|
+
echo "Done."
|
|
@@ -29,7 +29,7 @@ from .random import random_module as _random_module
|
|
|
29
29
|
from . import char as _char_module
|
|
30
30
|
from . import matlib as _matlib_module
|
|
31
31
|
|
|
32
|
-
__version__ = "1.0.
|
|
32
|
+
__version__ = "1.0.2"
|
|
33
33
|
|
|
34
34
|
class ArrayFlags:
|
|
35
35
|
"""数组内存布局信息,与 NumPy 的 np.ndarray.flags 兼容。"""
|
|
@@ -1338,11 +1338,7 @@ def repmat(a, m, n):
|
|
|
1338
1338
|
a = _to_ndarray(a)
|
|
1339
1339
|
if a.ndim == 1:
|
|
1340
1340
|
a = a.reshape(1, a.size)
|
|
1341
|
-
|
|
1342
|
-
for _ in range(m):
|
|
1343
|
-
for row in range(a.shape[0]):
|
|
1344
|
-
result.append(a[row].tolist() * n)
|
|
1345
|
-
return asarray(result)
|
|
1341
|
+
return tile(a, (m, n))
|
|
1346
1342
|
|
|
1347
1343
|
|
|
1348
1344
|
def _to_ndarray(obj):
|
|
@@ -1468,28 +1464,28 @@ def zeros_like(a, dtype=None, order='K', subok=True, shape=None):
|
|
|
1468
1464
|
"""返回与输入形状相同的零数组。"""
|
|
1469
1465
|
arr = ndarray(a)
|
|
1470
1466
|
_dtype = dtype if dtype is not None else getattr(arr, '_dtype', 'float64')
|
|
1471
|
-
return
|
|
1467
|
+
return ndarray(_core.zeros_like(arr._array), _dtype=_dtype)
|
|
1472
1468
|
|
|
1473
1469
|
|
|
1474
1470
|
def ones_like(a, dtype=None, order='K', subok=True, shape=None):
|
|
1475
1471
|
"""返回与输入形状相同的1数组。"""
|
|
1476
1472
|
arr = ndarray(a)
|
|
1477
1473
|
_dtype = dtype if dtype is not None else getattr(arr, '_dtype', 'float64')
|
|
1478
|
-
return
|
|
1474
|
+
return ndarray(_core.ones_like(arr._array), _dtype=_dtype)
|
|
1479
1475
|
|
|
1480
1476
|
|
|
1481
1477
|
def empty_like(a, dtype=None, order='K', subok=True, shape=None):
|
|
1482
1478
|
"""返回与输入形状相同的空数组。"""
|
|
1483
1479
|
arr = ndarray(a)
|
|
1484
1480
|
_dtype = dtype if dtype is not None else getattr(arr, '_dtype', 'float64')
|
|
1485
|
-
return
|
|
1481
|
+
return ndarray(_core.empty_like(arr._array), _dtype=_dtype)
|
|
1486
1482
|
|
|
1487
1483
|
|
|
1488
1484
|
def full_like(a, fill_value, dtype=None, order='K', subok=True, shape=None):
|
|
1489
1485
|
"""返回与输入形状相同的填充数组。"""
|
|
1490
1486
|
arr = ndarray(a)
|
|
1491
1487
|
_dtype = dtype if dtype is not None else getattr(arr, '_dtype', 'float64')
|
|
1492
|
-
return
|
|
1488
|
+
return ndarray(_core.full_like(arr._array, float(fill_value)), _dtype=_dtype)
|
|
1493
1489
|
|
|
1494
1490
|
|
|
1495
1491
|
def eye(N, M=None, k=0, dtype=None, order='C'):
|
|
@@ -1517,32 +1513,25 @@ def linspace(start, stop, num=50, endpoint=True, retstep=False, dtype=None, axis
|
|
|
1517
1513
|
start_val = _scalar(_ensure(start))
|
|
1518
1514
|
stop_val = _scalar(_ensure(stop))
|
|
1519
1515
|
_dtype = _resolve_dtype(dtype)
|
|
1520
|
-
|
|
1521
|
-
result = ndarray([start_val], _dtype=_dtype)
|
|
1522
|
-
step = 0.0
|
|
1523
|
-
else:
|
|
1524
|
-
result = ndarray(_core.linspace(start_val, stop_val, num, endpoint=endpoint))
|
|
1525
|
-
if _dtype != "float64":
|
|
1526
|
-
result._dtype = _dtype
|
|
1527
|
-
step = (stop_val - start_val) / (num - 1) if endpoint else (stop_val - start_val) / num
|
|
1516
|
+
result = ndarray(_core.linspace(start_val, stop_val, num, endpoint=endpoint), _dtype=_dtype)
|
|
1528
1517
|
if retstep:
|
|
1518
|
+
step = (stop_val - start_val) / (num - 1) if endpoint else (stop_val - start_val) / num
|
|
1529
1519
|
return result, _float64(step)
|
|
1530
1520
|
return result
|
|
1531
1521
|
|
|
1532
1522
|
|
|
1533
1523
|
def logspace(start, stop, num=50, endpoint=True, base=10.0, dtype=None, axis=0):
|
|
1534
1524
|
"""返回对数刻度上均匀间隔的数字。"""
|
|
1535
|
-
|
|
1525
|
+
_dtype = _resolve_dtype(dtype) if dtype else "float64"
|
|
1526
|
+
return ndarray(_core.logspace(float(start), float(stop), num, float(base)), _dtype=_dtype)
|
|
1536
1527
|
|
|
1537
1528
|
|
|
1538
1529
|
def geomspace(start, stop, num=50, endpoint=True, dtype=None, axis=0):
|
|
1539
1530
|
"""返回几何级数上均匀间隔的数字。"""
|
|
1540
|
-
import math
|
|
1541
1531
|
if start <= 0 or stop <= 0:
|
|
1542
1532
|
raise ValueError("geomspace requires positive start and stop values")
|
|
1543
|
-
|
|
1544
|
-
|
|
1545
|
-
return exp(linspace(log_start, log_stop, num, endpoint))
|
|
1533
|
+
_dtype = _resolve_dtype(dtype) if dtype else "float64"
|
|
1534
|
+
return ndarray(_core.geomspace(float(start), float(stop), num), _dtype=_dtype)
|
|
1546
1535
|
|
|
1547
1536
|
|
|
1548
1537
|
# ========== 索引函数 ==========
|
|
@@ -1943,12 +1932,7 @@ def isnan(x):
|
|
|
1943
1932
|
|
|
1944
1933
|
def binary_repr(num, width=None):
|
|
1945
1934
|
"""返回整数的二进制表示字符串。"""
|
|
1946
|
-
|
|
1947
|
-
width = num.bit_length() or 1
|
|
1948
|
-
if num >= 0:
|
|
1949
|
-
return format(num, 'b').zfill(width)
|
|
1950
|
-
# 负数:补码表示
|
|
1951
|
-
return format((1 << width) + num, 'b').zfill(width)
|
|
1935
|
+
return _core.binary_repr(num, width)
|
|
1952
1936
|
|
|
1953
1937
|
|
|
1954
1938
|
def isinf(x):
|
|
@@ -0,0 +1,225 @@
|
|
|
1
|
+
"""
|
|
2
|
+
ndarray 对象方法模块
|
|
3
|
+
|
|
4
|
+
此模块包含 rsnumpy.ndarray 类的所有对象方法和属性。
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
import rsnumpy._core as _core
|
|
8
|
+
from .__init__ import ndarray, _ensure
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
def _wrap_result(result, dtype="float64"):
|
|
12
|
+
"""包装结果为 ndarray 对象"""
|
|
13
|
+
if hasattr(result, '__class__') and result.__class__.__name__ == 'ndarray':
|
|
14
|
+
return ndarray._wrap(result, _dtype=dtype)
|
|
15
|
+
return result
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
class NdArrayMethods:
|
|
19
|
+
"""ndarray 对象方法集合"""
|
|
20
|
+
|
|
21
|
+
@staticmethod
|
|
22
|
+
def astype(arr, dtype):
|
|
23
|
+
"""将数组转换为指定的数据类型。"""
|
|
24
|
+
return _wrap_result(arr._array.astype(dtype))
|
|
25
|
+
|
|
26
|
+
@staticmethod
|
|
27
|
+
def reshape(arr, *shape):
|
|
28
|
+
"""改变数组形状而不改变数据。"""
|
|
29
|
+
if len(shape) == 1 and isinstance(shape[0], (tuple, list)):
|
|
30
|
+
shape = shape[0]
|
|
31
|
+
else:
|
|
32
|
+
shape = shape
|
|
33
|
+
result = arr._array.reshape(shape)
|
|
34
|
+
return ndarray._wrap(result, _dtype=getattr(arr, '_dtype', "float64"), _fields=getattr(arr, '_fields', None), _raw_data=getattr(arr, '_raw_data', None))
|
|
35
|
+
|
|
36
|
+
@staticmethod
|
|
37
|
+
def resize(arr, new_shape):
|
|
38
|
+
"""改变数组形状和大小。"""
|
|
39
|
+
if isinstance(new_shape, int):
|
|
40
|
+
new_shape = (new_shape,)
|
|
41
|
+
elif isinstance(new_shape, list):
|
|
42
|
+
new_shape = tuple(new_shape)
|
|
43
|
+
arr._array.resize(new_shape)
|
|
44
|
+
|
|
45
|
+
@staticmethod
|
|
46
|
+
def ravel(arr, order='C'):
|
|
47
|
+
"""将数组展平为一维。"""
|
|
48
|
+
if order == 'A' or order == 'K':
|
|
49
|
+
order = 'C'
|
|
50
|
+
return NdArrayMethods.flatten(arr, order)
|
|
51
|
+
|
|
52
|
+
@staticmethod
|
|
53
|
+
def flatten(arr, order='C'):
|
|
54
|
+
"""展平数组为一维。"""
|
|
55
|
+
dtype = getattr(arr, '_dtype', "float64")
|
|
56
|
+
result = _core.flatten_full(arr._array, order)
|
|
57
|
+
return _wrap_result(result, dtype)
|
|
58
|
+
|
|
59
|
+
@staticmethod
|
|
60
|
+
def transpose(arr, *axes):
|
|
61
|
+
"""转置数组。"""
|
|
62
|
+
dtype = getattr(arr, '_dtype', "float64")
|
|
63
|
+
fields = getattr(arr, '_fields', None)
|
|
64
|
+
raw = getattr(arr, '_raw_data', None)
|
|
65
|
+
if len(axes) == 0:
|
|
66
|
+
result = arr._array.T
|
|
67
|
+
else:
|
|
68
|
+
result = _core.transpose(arr._array)
|
|
69
|
+
return ndarray._wrap(result, _dtype=dtype, _fields=fields, _raw_data=raw)
|
|
70
|
+
|
|
71
|
+
@staticmethod
|
|
72
|
+
def swapaxes(arr, axis1, axis2):
|
|
73
|
+
"""交换两个轴的位置。"""
|
|
74
|
+
dtype = getattr(arr, '_dtype', "float64")
|
|
75
|
+
fields = getattr(arr, '_fields', None)
|
|
76
|
+
raw_data = getattr(arr, '_raw_data', None)
|
|
77
|
+
result = _core.swapaxes(arr._array, axis1, axis2)
|
|
78
|
+
return ndarray._wrap(result, _dtype=dtype, _fields=fields, _raw_data=raw_data)
|
|
79
|
+
|
|
80
|
+
@staticmethod
|
|
81
|
+
def squeeze(arr, axis=None):
|
|
82
|
+
"""移除长度为1的轴。"""
|
|
83
|
+
return _wrap_result(arr._array.squeeze())
|
|
84
|
+
|
|
85
|
+
@staticmethod
|
|
86
|
+
def max(arr, axis=None):
|
|
87
|
+
"""返回数组的最大值。"""
|
|
88
|
+
result = arr._array.max(axis)
|
|
89
|
+
if axis is None and hasattr(result, 'tolist'):
|
|
90
|
+
return result.tolist()
|
|
91
|
+
return _wrap_result(result)
|
|
92
|
+
|
|
93
|
+
@staticmethod
|
|
94
|
+
def min(arr, axis=None):
|
|
95
|
+
"""返回数组的最小值。"""
|
|
96
|
+
result = arr._array.min(axis)
|
|
97
|
+
if axis is None and hasattr(result, 'tolist'):
|
|
98
|
+
return result.tolist()
|
|
99
|
+
return _wrap_result(result)
|
|
100
|
+
|
|
101
|
+
@staticmethod
|
|
102
|
+
def mean(arr, axis=None):
|
|
103
|
+
"""计算数组的平均值。"""
|
|
104
|
+
result = arr._array.mean(axis)
|
|
105
|
+
if axis is None and hasattr(result, 'tolist'):
|
|
106
|
+
return result.tolist()
|
|
107
|
+
return _wrap_result(result)
|
|
108
|
+
|
|
109
|
+
@staticmethod
|
|
110
|
+
def std(arr, axis=None):
|
|
111
|
+
"""计算数组的标准差。"""
|
|
112
|
+
result = arr._array.std(axis)
|
|
113
|
+
if axis is None and hasattr(result, 'tolist'):
|
|
114
|
+
return result.tolist()
|
|
115
|
+
return _wrap_result(result)
|
|
116
|
+
|
|
117
|
+
@staticmethod
|
|
118
|
+
def var(arr, axis=None):
|
|
119
|
+
"""计算数组的方差。"""
|
|
120
|
+
result = arr._array.var(axis)
|
|
121
|
+
if axis is None and hasattr(result, 'tolist'):
|
|
122
|
+
return result.tolist()
|
|
123
|
+
return _wrap_result(result)
|
|
124
|
+
|
|
125
|
+
@staticmethod
|
|
126
|
+
def sum(arr, axis=None):
|
|
127
|
+
"""计算数组元素的和。"""
|
|
128
|
+
result = arr._array.sum(axis)
|
|
129
|
+
if axis is None and hasattr(result, 'tolist'):
|
|
130
|
+
return result.tolist()
|
|
131
|
+
return _wrap_result(result)
|
|
132
|
+
|
|
133
|
+
@staticmethod
|
|
134
|
+
def prod(arr, axis=None):
|
|
135
|
+
"""计算数组元素的乘积。"""
|
|
136
|
+
result = arr._array.prod(axis)
|
|
137
|
+
if axis is None and hasattr(result, 'tolist'):
|
|
138
|
+
return result.tolist()
|
|
139
|
+
return _wrap_result(result)
|
|
140
|
+
|
|
141
|
+
@staticmethod
|
|
142
|
+
def cumsum(arr, axis=None):
|
|
143
|
+
"""计算累积和。"""
|
|
144
|
+
result = arr._array.cumsum(axis)
|
|
145
|
+
return _wrap_result(result)
|
|
146
|
+
|
|
147
|
+
@staticmethod
|
|
148
|
+
def cumprod(arr, axis=None):
|
|
149
|
+
"""计算累积乘积。"""
|
|
150
|
+
result = arr._array.cumprod(axis)
|
|
151
|
+
return _wrap_result(result)
|
|
152
|
+
|
|
153
|
+
@staticmethod
|
|
154
|
+
def argmax(arr, axis=None):
|
|
155
|
+
"""返回最大值的索引。"""
|
|
156
|
+
return _wrap_result(_core.argmax_axis(arr._array, axis))
|
|
157
|
+
|
|
158
|
+
@staticmethod
|
|
159
|
+
def argmin(arr, axis=None):
|
|
160
|
+
"""返回最小值的索引。"""
|
|
161
|
+
return _wrap_result(_core.argmin_axis(arr._array, axis))
|
|
162
|
+
|
|
163
|
+
@staticmethod
|
|
164
|
+
def argsort(arr, axis=-1):
|
|
165
|
+
"""返回排序后的索引。"""
|
|
166
|
+
result = arr._array.argsort(axis)
|
|
167
|
+
return _wrap_result(result)
|
|
168
|
+
|
|
169
|
+
@staticmethod
|
|
170
|
+
def sort(arr, axis=-1):
|
|
171
|
+
"""原地排序数组。"""
|
|
172
|
+
result = arr._array.sort(axis)
|
|
173
|
+
if hasattr(result, 'shape') and result.shape == arr.shape:
|
|
174
|
+
arr._array = result
|
|
175
|
+
else:
|
|
176
|
+
arr._array.data = result.data
|
|
177
|
+
|
|
178
|
+
@staticmethod
|
|
179
|
+
def diagonal(arr, offset=0, axis1=0, axis2=1):
|
|
180
|
+
"""返回数组的对角线元素。"""
|
|
181
|
+
result = arr._array.diagonal(offset, axis1, axis2)
|
|
182
|
+
return _wrap_result(result)
|
|
183
|
+
|
|
184
|
+
@staticmethod
|
|
185
|
+
def trace(arr, offset=0, axis1=0, axis2=1):
|
|
186
|
+
"""计算数组的迹(对角线元素之和)。"""
|
|
187
|
+
return arr._array.trace(offset, axis1, axis2)
|
|
188
|
+
|
|
189
|
+
@staticmethod
|
|
190
|
+
def fill(arr, value):
|
|
191
|
+
"""用指定值填充数组。"""
|
|
192
|
+
arr._array.fill(value)
|
|
193
|
+
|
|
194
|
+
@staticmethod
|
|
195
|
+
def item(arr, *args):
|
|
196
|
+
"""获取数组的单个元素。"""
|
|
197
|
+
return arr._array.item(*args)
|
|
198
|
+
|
|
199
|
+
@staticmethod
|
|
200
|
+
def tolist(arr):
|
|
201
|
+
"""将数组转换为 Python 列表。"""
|
|
202
|
+
return arr._array.tolist()
|
|
203
|
+
|
|
204
|
+
@staticmethod
|
|
205
|
+
def take(arr, indices, axis=None):
|
|
206
|
+
"""根据索引获取元素。"""
|
|
207
|
+
result = arr._array.take(_ensure(indices), axis)
|
|
208
|
+
return _wrap_result(result)
|
|
209
|
+
|
|
210
|
+
@staticmethod
|
|
211
|
+
def put(arr, indices, values):
|
|
212
|
+
"""将值放入数组的指定位置。"""
|
|
213
|
+
arr._array.put(_ensure(indices), _ensure(values))
|
|
214
|
+
|
|
215
|
+
@staticmethod
|
|
216
|
+
def repeat(arr, repeats, axis=None):
|
|
217
|
+
"""重复数组元素。"""
|
|
218
|
+
result = arr._array.repeat(repeats, axis)
|
|
219
|
+
return _wrap_result(result)
|
|
220
|
+
|
|
221
|
+
@staticmethod
|
|
222
|
+
def nonzero(arr):
|
|
223
|
+
"""返回非零元素的索引。"""
|
|
224
|
+
raw = _core.nonzero_arrs(arr._array)
|
|
225
|
+
return tuple(ndarray._wrap(r) for r in raw)
|