当前位置: 首页 > news >正文

【PhysUnits】17.1 补充数值后量纲系统实现解析 (dimension.rs)

一、源码

这段代码实现了一个类型安全的物理单位系统,利用Rust的类型系统在编译时检查量纲正确性。

//! Physical Units Library with Type-Level Dimension Checking
//! 带类型级量纲检查的物理单位库
//!
//! 文件位置: src/quantity/dimension.rs
//! 本文件定义物理量纲系统的核心结构
//!
//! This module provides type-safe physical unit representations using Rust's type system
//! to enforce dimensional correctness at compile time.
//! 本模块提供类型安全的物理单位表示,利用Rust类型系统在编译时强制量纲正确性use crate::sealed::Sealed;
use crate::constant::{Integer, Sum, Diff, Prod};
use core::marker::PhantomData;
use core::ops::{Neg, Add, Sub, Mul, Div, AddAssign, SubAssign, MulAssign, DivAssign};
use crate::variable::{Numeric, Scalar, Var};/// Fundamental structure representing physical units with dimensional exponents
/// 表示带有量纲指数的物理单位的基础结构
///
/// 这是整个物理单位系统中最基础的结构,仅包含数值和量纲信息,不包含任何词头(如kilo-, milli-等)。
/// 具体物理类型(如Meter, Second等)在alias.rs中通过类型别名定义。
///
/// 注意:这是内部基础结构,用户代码应该使用alias.rs中定义的具名物理类型。
///
/// # Type Parameters | 类型参数
/// - `Value`: The scalar value type (e.g., i64, f64) | 标量值类型
/// - `METER`: Length dimension exponent (P1 for meter, Z0 for dimensionless) | 长度量纲指数
/// - `KILOGRAM`: Mass dimension exponent | 质量量纲指数  
/// - `SECOND`: Time dimension exponent | 时间量纲指数
/// - `AMPERE`: Current dimension exponent | 电流量纲指数
/// - `KELVIN`: Temperature dimension exponent | 温度量纲指数
/// - `MOLE`: Amount dimension exponent | 物质量量纲指数
/// - `CANDELA`: Luminous intensity dimension exponent | 光强量纲指数
///
/// # 设计说明
/// 1. 这是最底层的量纲表示结构,所有带词头的单位最终都可以转换为这种基本形式
/// 2. alias.rs中会为常用物理量创建类型别名(如type Meter = Dimension<f64, P1, Z0,...>)
/// 3. 实际使用时应优先使用alias.rs中定义的具名类型
///
#[derive(Debug, Clone, Copy)]
pub struct Dimension<Value: Scalar,METER: Integer,KILOGRAM: Integer,SECOND: Integer,AMPERE: Integer,KELVIN: Integer,MOLE: Integer,CANDELA: Integer
>(pub Value,PhantomData<(METER, KILOGRAM, SECOND, AMPERE, KELVIN, MOLE, CANDELA)>
);/// Trait marking valid Dimension types
/// 标记有效单位类型的Trait
///
/// # Safety 安全性
/// This trait is sealed and cannot be implemented outside this crate
/// 该trait是密封的,不能在本crate外实现
pub trait Dimensional: Sealed+Sized {}impl<V:Scalar, M: Integer, KG: Integer, S: Integer, A: Integer, K: Integer, MOL: Integer, CD: Integer>Sealed for Dimension<V, M, KG, S, A, K, MOL, CD>{
}impl<V:Scalar, M: Integer, KG: Integer, S: Integer, A: Integer, K: Integer, MOL: Integer, CD: Integer>Dimensional for Dimension<V, M, KG, S, A, K, MOL, CD>{}/// Creates a new unit instance with the given value
/// 用给定值创建新的单位实例
///
impl<T: Numeric, M: Integer, KG: Integer, S: Integer, A: Integer, K: Integer, MOL: Integer, CD: Integer>
Dimension<Var<T>, M, KG, S, A, K, MOL, CD>
where Var<T>: Scalar,
{/// Creates a new unit instance/// 创建新的单位实例pub fn new(value: T) -> Self {Self(Var(value), PhantomData)}
}impl<V: Scalar, M: Integer, KG: Integer, S: Integer, A: Integer, K: Integer, MOL: Integer, CD: Integer> Neg for Dimension<V, M, KG, S, A, K, MOL, CD>
whereV: Neg<Output = V>,
{type Output = Self;/// Negates the unit value while keeping the same dimensions/// 对单位值取负,同时保持相同的量纲///fn neg(self) -> Self::Output {Dimension(-self.0,PhantomData)}
}impl<M: Integer, KG: Integer, S: Integer, A: Integer, K: Integer, MOL: Integer, CD: Integer>
Dimension<Var<i64>, M, KG, S, A, K, MOL, CD>{// Raises the unit to the power of `N`/// 将单位提升到幂次 `N`////// # Note 注意/// Currently returns a unit with value 1 as the actual power operation is not implemented/// 当前返回值为1的单位,因为实际的幂运算尚未实现pub fn pow<N>(self) -> Dimension<Var<i64>,Prod<M, N>,Prod<KG, N>,Prod<S, N>,Prod<A, N>,Prod<K, N>,Prod<MOL, N>,Prod<CD, N>,>whereN: Integer,M: Mul<N>,KG: Mul<N>,S: Mul<N>,A: Mul<N>,K: Mul<N>,MOL: Mul<N>,CD: Mul<N>,Prod<M, N>: Integer,Prod<KG, N>: Integer,Prod<S, N>: Integer,Prod<A, N>: Integer,Prod<K, N>: Integer,Prod<MOL, N>: Integer,Prod<CD, N>: Integer,{Dimension::new(1_i64)}}// ========== Operator Implementations ==========
// ========== 运算符实现 ==========
impl<V: Scalar, M: Integer, KG: Integer, S: Integer, A: Integer, K: Integer, MOL: Integer, CD: Integer> Add for Dimension<V, M, KG, S, A, K, MOL, CD>
whereV: Add<V, Output = V>,
{type Output = Self;/// Adds two units of the same dimension/// 相加两个相同量纲的单位fn add(self, rhs: Self) -> Self::Output {Dimension(self.0 + rhs.0, PhantomData)}
}impl<V: Scalar, M: Integer, KG: Integer, S: Integer, A: Integer, K: Integer, MOL: Integer, CD: Integer> Sub for Dimension<V, M, KG, S, A, K, MOL, CD>
whereV: Sub<V, Output = V>,
{type Output = Self;/// Subtracts two units of the same dimension/// 相减两个相同量纲的单位fn sub(self, rhs: Self) -> Self::Output {Dimension(self.0 - rhs.0, PhantomData)}
}impl<V: Scalar, M: Integer, KG: Integer, S: Integer, A: Integer, K: Integer, MOL: Integer, CD: Integer> AddAssign for Dimension<V, M, KG, S, A, K, MOL, CD>
whereV: AddAssign<V>,
{/// Adds and assigns two units of the same dimension/// 相加并赋值两个相同量纲的单位fn add_assign(&mut self, rhs: Self) {self.0 += rhs.0;}
}impl<V: Scalar, M: Integer, KG: Integer, S: Integer, A: Integer, K: Integer, MOL: Integer, CD: Integer> SubAssign for Dimension<V, M, KG, S, A, K, MOL, CD>
whereV: SubAssign<V>,
{/// Subtracts and assigns two units of the same dimension/// 相减并赋值两个相同量纲的单位fn sub_assign(&mut self, rhs: Self) {self.0 -= rhs.0;}
}impl<V:Scalar, M1, M2, KG1, KG2, S1, S2, A1, A2, K1, K2, MOL1, MOL2, CD1, CD2> Mul<Dimension<V, M2, KG2, S2, A2, K2, MOL2, CD2>> for Dimension<V, M1, KG1, S1, A1, K1, MOL1, CD1>
whereV: Mul<V, Output = V>,M1: Integer + Add<M2>,M2: Integer,KG1: Integer + Add<KG2>,KG2: Integer,S1: Integer + Add<S2>,S2: Integer,A1: Integer + Add<A2>,A2: Integer,K1: Integer + Add<K2>,K2: Integer,MOL1: Integer + Add<MOL2>,MOL2: Integer,CD1: Integer + Add<CD2>,CD2: Integer,Sum<M1, M2>: Integer,Sum<KG1, KG2>: Integer,Sum<S1, S2>: Integer,Sum<A1, A2>: Integer,Sum<K1, K2>: Integer,Sum<MOL1, MOL2>: Integer,Sum<CD1, CD2>: Integer,
{type Output = Dimension<V,Sum<M1, M2>, Sum<KG1, KG2>, Sum<S1, S2>,Sum<A1, A2>, Sum<K1, K2>, Sum<MOL1, MOL2>, Sum<CD1, CD2>>;/// Multiplies two units by adding their dimensional exponents/// 通过相加量纲指数来相乘两个单位fn mul(self, rhs: Dimension<V, M2, KG2, S2, A2, K2, MOL2, CD2>) -> Self::Output {Dimension(self.0 * rhs.0,PhantomData)}
}impl<V: Scalar, M1, M2, KG1, KG2, S1, S2, A1, A2, K1, K2, MOL1, MOL2, CD1, CD2> Div<Dimension<V, M2, KG2, S2, A2, K2, MOL2, CD2>> for Dimension<V, M1, KG1, S1, A1, K1, MOL1, CD1>
whereV: Div<V, Output = V>,M1: Integer + Sub<M2>,M2: Integer,KG1: Integer + Sub<KG2>,KG2: Integer,S1: Integer + Sub<S2>,S2: Integer,A1: Integer + Sub<A2>,A2: Integer,K1: Integer + Sub<K2>,K2: Integer,MOL1: Integer + Sub<MOL2>,MOL2: Integer,CD1: Integer + Sub<CD2>,CD2: Integer,Diff<M1, M2>: Integer,Diff<KG1, KG2>: Integer,Diff<S1, S2>: Integer,Diff<A1, A2>: Integer,Diff<K1, K2>: Integer,Diff<MOL1, MOL2>: Integer,Diff<CD1, CD2>: Integer,
{type Output = Dimension<V,Diff<M1, M2>, Diff<KG1, KG2>, Diff<S1, S2>,Diff<A1, A2>, Diff<K1, K2>, Diff<MOL1, MOL2>, Diff<CD1, CD2>>;/// Divides two units by subtracting their dimensional exponents/// 通过相减量纲指数来相除两个单位fn div(self, rhs: Dimension<V, M2, KG2, S2, A2, K2, MOL2, CD2>) -> Self::Output {Dimension(self.0 / rhs.0,PhantomData)}
}impl<V: Scalar, M: Integer, KG: Integer, S: Integer, A: Integer, K: Integer, MOL: Integer, CD: Integer> AddAssign<V> for Dimension<V, M, KG, S, A, K, MOL, CD>
whereV: AddAssign<V>,
{/// Adds a scalar value to the unit (same dimension)/// 将标量值加到单位上(相同量纲)fn add_assign(&mut self, rhs: V) {self.0 += rhs;}
}impl<V: Scalar, M: Integer, KG: Integer, S: Integer, A: Integer, K: Integer, MOL: Integer, CD: Integer> SubAssign<V> for Dimension<V, M, KG, S, A, K, MOL, CD>
whereV: SubAssign<V>,
{/// Subtracts a scalar value from the unit (same dimension)/// 从单位中减去标量值(相同量纲)fn sub_assign(&mut self, rhs: V) {self.0 -= rhs;}
}impl<V: Scalar, M: Integer, KG: Integer, S: Integer, A: Integer, K: Integer, MOL: Integer, CD: Integer> MulAssign<V> for Dimension<V, M, KG, S, A, K, MOL, CD>
whereV: MulAssign<V>,
{/// Multiplies the unit by a scalar factor (keeps dimension)/// 将单位乘以标量倍率(保持量纲)fn mul_assign(&mut self, rhs: V) {self.0 *= rhs;}
}impl<V: Scalar, M: Integer, KG: Integer, S: Integer, A: Integer, K: Integer, MOL: Integer, CD: Integer> DivAssign<V> for Dimension<V, M, KG, S, A, K, MOL, CD>
whereV: DivAssign<V>,
{/// Divides the unit by a scalar factor (keeps dimension)/// 将单位除以标量倍率(保持量纲)fn div_assign(&mut self, rhs: V) {self.0 /= rhs;}
}#[cfg(test)]
mod tests {use super::*;use crate::constant::{P1, Z0};/// 测试基本运算和量纲检查#[test]fn test_basic_operations() {type Meter = Dimension<Var<f64>, P1, Z0, Z0, Z0, Z0, Z0, Z0>;type Second = Dimension<Var<f64>, Z0, Z0, P1, Z0, Z0, Z0, Z0>;let m1 = Meter::new(5.0);let m2 = Meter::new(3.0);let s1 = Second::new(2.0);// 测试加法assert_eq!((m1 + m2).0.0, 8.0);// 测试减法assert_eq!((m1 - m2).0.0, 2.0);// 测试取负assert_eq!((-m1).0.0, -5.0);// 测试乘法let m_s = m1 * s1;assert_eq!(m_s.0.0, 10.0);  // 5.0 m * 2.0 s = 10.0 m·s// 测试除法let speed = m1 / s1;assert_eq!(speed.0.0, 2.5);  // 5.0 m / 2.0 s = 2.5 m/s// 测试赋值运算let mut m = m1;m += m2;assert_eq!(m.0.0, 8.0);m *= Var(2_f64);assert_eq!(m.0.0, 16.0);}
}

二、核心结构:Dimension

Dimension 是表示物理单位的基础结构,它是一个泛型结构体:

pub struct Dimension<Value: Scalar,METER: Integer,    // 长度量纲指数KILOGRAM: Integer, // 质量量纲指数SECOND: Integer,   // 时间量纲指数AMPERE: Integer,   // 电流量纲指数KELVIN: Integer,   // 温度量纲指数MOLE: Integer,     // 物质量量纲指数CANDELA: Integer   // 光强量纲指数
>(...);
  • Value 是标量值类型(如i64, f64)

  • 其他类型参数表示7个基本物理量的量纲指数(使用类型级别的整数)

三、关键特性

  1. 类型安全:通过Rust的类型系统确保量纲运算的正确性

  2. 编译时检查:所有量纲检查都在编译时完成,无运行时开销

  3. 密封模式:通过Sealed trait防止外部实现,保证类型安全

四、主要功能实现

基本运算

实现了基本的算术运算和赋值运算:

  • 加法/减法(要求相同量纲)

  • 乘法/除法(自动计算新的量纲)

  • 取负运算

  • 各种赋值运算(+=, -=, *=, /=)

量纲运算

通过类型级别的整数运算实现量纲的正确组合:

  • 乘法:对应量纲指数相加

  • 除法:对应量纲指数相减

  • 幂运算:所有量纲指数乘以幂次(当前实现返回1,注释说明尚未完全实现)

类型安全机制
  1. Dimensional trait:标记有效的单位类型

  2. Sealed trait:防止外部实现,保证类型系统完整性

  3. PhantomData:在运行时不存在,仅用于类型系统

五、测试用例

测试了各种运算和量纲组合:

  • 相同量纲的加减法

  • 不同量纲的乘除法

  • 赋值运算

  • 验证运算结果的数值和量纲正确性

六、设计优势

  1. 防止量纲错误:无法将不同量纲的值相加(编译时报错)

  2. 自动量纲推导:乘除法自动计算正确的量纲

  3. 零成本抽象:所有检查在编译时完成,运行时无额外开销

  4. 清晰的类型表示:通过类型参数明确表示量纲信息

这个实现展示了如何利用Rust强大的类型系统来构建类型安全的物理计算系统,确保在编译时就能捕获潜在的量纲错误。

http://www.xdnf.cn/news/941563.html

相关文章:

  • 一键压缩图片工具
  • 2000-2020年各省第三产业增加值占GDP比重数据
  • 网络安全基础
  • Python 调用 C 程序时输出顺序错乱问题分析与解决
  • 0x-2-Oracle Linux 9上安装JDK配置环境变量
  • 第五讲 基础IO
  • Go切片与映射的内存优化技巧:实战经验与最佳实践
  • 【LeetCode】算法详解#6 ---除自身以外数组的乘积
  • JUC并发编程(六)CAS无锁实现/原子整数/原子引用/原子数组/字段更新
  • Python训练营---DAY48
  • Java线程安全与同步机制全解析
  • 嵌入式学习笔记 - freeRTOS为什么中断中不能使用互斥量
  • 《最短路(Dijkstra+Heap)》题集
  • MySql读写分离部署(一主一从,双主双从,Mycat)
  • 为什么已经有 Nginx 了,还需要服务网关?
  • 【LUT技术专题】带语义的图像自适应4DLUT
  • Cherry-Studio搭建个人知识库智能体
  • JS的数据类型分类
  • 国产变频器与codesys控制器通信融合方案
  • gitee....
  • SpringSecurity+vue通用权限系统
  • Python环境搭建:pyenv-win的使用指南
  • [Linux]假如给我Linux开发工具
  • InnoDB
  • Deep Research实践
  • U盘安装ubuntu系统
  • 高压电红外过热目标检测数据集(8类,4075 张)
  • Torch requires_grad / backward / is_leaf 的一些坑
  • C语言进程间通信:基础篇
  • 【电路】阻抗匹配