1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
//! 矩阵元素类型闸门(NumericElement)
//!
//! [`Matrix`](crate::dense::Matrix) 的元素类型被限制为**基础数字量**(整数与浮点),
//! 物理量(`Distance`、`Coef` 等)不能作为矩阵元素。
//!
//! # 为什么
//!
//! 一、**语义上做不到**。`Matrix<ROWS, COLS, T>` 只有一个元素类型,要求整个矩阵同量纲。
//! 而工程上真正需要的矩阵几乎全是异量纲的:状态转移阵 Φ、协方差阵 P、卡尔曼增益 K、
//! 雅可比 ∂f/∂x —— 它们的行列量纲各不相同,根本无法表示为单一 `T`。
//! 唯一能同量纲表达的就是旋转矩阵(元素无量纲),而它已有
//! [`CosMatrix`](crate::spatial_geometry::cos_matrix::CosMatrix) 专门实现。
//!
//! 二、**实现上是陷阱**。物理量的 `Default` 不保证是加法零元
//! (`Coef::default() == 1.0` 是有意的乘法幺元),而矩阵乘积、求和、
//! 行列式都需要以加法零元为累加器起点。一旦允许物理量进矩阵,
//! 每个累加器都成了潜伏的正确性缺陷。
//!
//! 因此本 trait 用 sealed 模式把门关死:只有本文件内列出的基础数字量能实现它,
//! 外部 crate 无法扩展。物理量在编译期就进不了 [`Matrix`](crate::dense::Matrix)。
//!
//! # 示例
//! ```compile_fail
//! use zmatrix::dense::Matrix;
//! use zmatrix::physics::basic::Coef;
//!
//! // 物理量不能作为矩阵元素,编译失败
//! let m: Matrix<2, 2, Coef> = Matrix::new([
//! [Coef::new(1.0), Coef::new(0.0)],
//! [Coef::new(0.0), Coef::new(1.0)],
//! ]);
//! ```
//!
//! ```compile_fail
//! use zmatrix::dense::Matrix;
//!
//! // 自定义类型也不行:NumericElement 是 sealed 的
//! struct MyNum(f64);
//! let m: Matrix<1, 1, MyNum> = Matrix::new([[MyNum(1.0)]]);
//! ```
/// 可作为 [`Matrix`](crate::dense::Matrix) 元素的基础数字量。
///
/// 这是一个 **sealed** trait:只有整数与浮点实现了它,外部无法扩展。
/// 它同时也是 `Copy + Send + Sync` 的来源,因此满足本 trait 的类型可直接用于 `Matrix`。
impl_numeric_element!;