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

【PhysUnits】17.6 Unit基础结构(unit.rs)

一、源码

这段代码定义了一个用于物理量单位系统的Unit结构体及其相关操作,支持单位自动推导和类型安全的运算。

//! Unit基础结构
//! 
//! 支持单位自动推导use core::marker::PhantomData;
use core::ops::{Neg, Add, Sub, Mul, Div, AddAssign, SubAssign, MulAssign, DivAssign};use crate::sealed::Sealed;
use super::{Si, Sied};
use super::ratio::{NoRatio, Scaled};
use super::Dimensional;
use super::prefix::Prefixed;
use crate::variable::{Numeric, Scalar, Var};
use super::Unitary;// ========== 辅助trait和实现 ==========
// 辅助trait,用于规范类型
pub trait UnitOrSi {type Output;fn unit(self) -> Self::Output;
}// 为所有Prefixed类型实现UnitOrSi
impl<S: Sied, R: Scaled> UnitOrSi for Unit<S, R> {type Output = Self;fn unit(self) -> Self::Output{self}
}impl<S: Sied> UnitOrSi for Unit<S, NoRatio> {type Output = S;fn unit(self) -> Self::Output{self.0}
}/// Unit基础结构
/// 
/// # 类型参数
/// - `R`: 比例因子类型
/// - `S`: SI基础类型
#[derive(Debug, Clone, Copy)]
pub struct Unit<S: Sied, R>(pub S,pub PhantomData<R>);impl<T, D, Pr, R> Unit<Si<Var<T>, D, Pr>, R>
where T: Numeric,D: Dimensional,Pr: Prefixed,Var<T>: Scalar,R: Scaled,
{pub fn new(value: T) -> Self {Self(Si::new(value),PhantomData)}
}impl< S: Sied, R: Scaled> Sealed for Unit<S, R>{}impl<S: Sied, R: Scaled> Unitary for Unit<S, R>{}// ================ 运算实现 ================// ----- 取负运算符 -----
impl<S: Sied, R: Scaled> Neg for Unit<S, R>
whereS: Neg<Output = S>,
{type Output = Self;/// 取负运算(保持单位和比例因子不变)fn neg(self) -> Self::Output {Unit(-self.0, PhantomData)}
}// ----- 加法运算符及其赋值 -----
// U + U
impl<S: Sied, R: Scaled> Add for Unit<S, R>
whereS:  Sied + Add<S, Output = S>,R: Scaled,
{type Output = Self;/// 物理量乘法fn add(self, rhs: Self) -> Self::Output {Unit(self.0 + rhs.0, PhantomData)}
}// U += U
impl<S: Sied, R: Scaled> AddAssign for Unit<S, R>
whereS:  Sied + AddAssign,R: Scaled,
{/// 加法赋值fn add_assign(&mut self, rhs: Self){self.0 += rhs.0;}
}// U += T
impl<T:Numeric, S: Sied, R: Scaled> AddAssign<T> for Unit<S, R>
whereS:  Sied + AddAssign<T>,R: Scaled,
{/// 加法赋值fn add_assign(&mut self, rhs: T){self.0 += rhs;}
}// U += Var<T>
impl<T:Numeric, S: Sied, R: Scaled> AddAssign<Var<T>> for Unit<S, R>
whereS:  Sied + AddAssign<Var<T>>,R: Scaled,
{/// 加法赋值fn add_assign(&mut self, rhs: Var<T>){self.0 += rhs;}
}// ----- 减法运算符及减法赋值 -----
// U - U
impl<S: Sied, R: Scaled> Sub for Unit<S, R>
whereS:  Sied + Sub<S, Output = S>,R: Scaled,
{type Output = Self;/// 物理量乘法fn sub(self, rhs: Self) -> Self::Output {Unit(self.0 - rhs.0, PhantomData)}
}// U -= U
impl<S: Sied, R: Scaled> SubAssign for Unit<S, R>
whereS:  Sied + SubAssign,R: Scaled,
{/// 加法赋值fn sub_assign(&mut self, rhs: Self){self.0 -= rhs.0;}
}// U -= T
impl<T:Numeric, S: Sied, R: Scaled> SubAssign<T> for Unit<S, R>
whereS:  Sied + SubAssign<T>,R: Scaled,
{/// 加法赋值fn sub_assign(&mut self, rhs: T){self.0 -= rhs;}
}// U -= Var<T>
impl<T:Numeric, S: Sied, R: Scaled> SubAssign<Var<T>> for Unit<S, R>
whereS:  Sied + SubAssign<Var<T>>,R: Scaled,
{/// 加法赋值fn sub_assign(&mut self, rhs: Var<T>){self.0 -= rhs;}
}// ----- 乘法运算符及乘法赋值 -----// U * U
impl<S1, S2, R1, R2> Mul<Unit<S2, R2>> for Unit<S1, R1>
whereS1: Sied + Mul<S2, Output: Sied>,S2: Sied,R1: Scaled + Mul<R2, Output: Scaled>,R2: Scaled,Unit<<S1 as Mul<S2>>::Output,<R1 as Mul<R2>>::Output>: UnitOrSi,
{type Output = <Unit<<S1 as Mul<S2>>::Output,<R1 as Mul<R2>>::Output> as UnitOrSi>::Output;/// 物理量乘法fn mul(self, rhs: Unit<S2, R2>) -> Self::Output {Unit(self.0 * rhs.0, PhantomData).unit()}
}// U * SI
//因为编译器对U * T与U * Si无法区分,Si必须用Si<Var<T>, D, Pr>表示
impl<S, R, T, D, Pr> Mul<Si<Var<T>, D, Pr>> for Unit<S, R>
whereT: Numeric,Var<T>: Scalar,D: Dimensional,Pr: Prefixed,S: Sied + Mul<Si<Var<T>, D, Pr>, Output: Sied>,Si<Var<T>, D, Pr>: Sied,R: Scaled,
{type Output = Unit<<S as Mul<Si<Var<T>, D, Pr>>>::Output,  // 单位相乘R>;/// 物理量乘法fn mul(self, rhs: Si<Var<T>, D, Pr>) -> Self::Output {Unit(self.0 * rhs, PhantomData)}
}// U * Var<T>
impl<S, R, T> Mul<Var<T>> for Unit<S, R>
whereT:Numeric,Var<T>: Scalar,S: Sied + Mul<Var<T>, Output: Sied>,R: Scaled,
{type Output = Unit<<S as Mul<Var<T>>>::Output,R>;/// 物理量乘法fn mul(self, rhs: Var<T>) -> Self::Output {Unit(self.0 * rhs, PhantomData)}
}// U * T
impl<T, S, R> Mul<T> for Unit<S, R>
whereT: Numeric,Var<T>: Scalar,S: Sied + Mul<T, Output: Sied>,R: Scaled,
{type Output = Unit<<S as Mul<T>>::Output,R>;/// 物理量乘法fn mul(self, rhs: T) -> Self::Output {Unit(self.0 * rhs, PhantomData)}
}// U *= Var<T>
impl<T, S, R> MulAssign<Var<T>> for Unit<S, R>
whereT: Numeric,S: Sied + MulAssign<Var<T>>,R: Scaled,Var<T>: Scalar,
{/// 标量乘法赋值 (*=)fn mul_assign(&mut self, rhs: Var<T>) {self.0 *= rhs;}
}// U *= T
impl<T, S, R> MulAssign<T> for Unit<S, R>
whereT: Numeric,S: Sied + MulAssign<Var<T>>,R: Scaled,Var<T>: Scalar,
{/// 标量乘法赋值 (*=)fn mul_assign(&mut self, rhs: T) {self.0 *= Var(rhs);}
}// ----- 除法运算符及除法赋值 -----// U / U
impl<S1, S2, R1, R2> Div<Unit<S2, R2>> for Unit<S1, R1>
whereS1: Sied + Div<S2, Output: Sied>,S2: Sied,R1: Scaled + Div<R2, Output: Scaled>,R2: Scaled,Unit<<S1 as Div<S2>>::Output,  // 单位相除<R1 as Div<R2>>::Output>: UnitOrSi,
{type Output = <Unit<<S1 as Div<S2>>::Output,  // 单位相除<R1 as Div<R2>>::Output> as UnitOrSi>::Output;/// 物理量除法fn div(self, rhs: Unit<S2, R2>) -> Self::Output {Unit(self.0 / rhs.0, PhantomData).unit()}
}// U / SI
//因为编译器对U / T与U / Si无法区分,Si必须用Si<Var<T>, D, Pr>表示
impl<S, R, T, D, Pr> Div<Si<Var<T>, D, Pr>> for Unit<S, R>
whereT: Numeric,Var<T>: Scalar,D: Dimensional,Pr: Prefixed,S: Sied + Div<Si<Var<T>, D, Pr>, Output: Sied>,Si<Var<T>, D, Pr>: Sied,R: Scaled,
{type Output = Unit<<S as Div<Si<Var<T>, D, Pr>>>::Output,  // 单位相除R>;/// 物理量除法fn div(self, rhs: Si<Var<T>, D, Pr>) -> Self::Output {Unit(self.0 / rhs, PhantomData)}
}// U / Var<T>
impl<S, R, T> Div<Var<T>> for Unit<S, R>
whereT:Numeric,Var<T>: Scalar,S: Sied + Div<Var<T>, Output: Sied>,R: Scaled,
{type Output = Unit<<S as Div<Var<T>>>::Output,R>;/// 物理量除法fn div(self, rhs: Var<T>) -> Self::Output {Unit(self.0 / rhs, PhantomData)}
}// U / T
impl<T, S, R> Div<T> for Unit<S, R>
whereT: Numeric,Var<T>: Scalar,S: Sied + Div<T, Output: Sied>,R: Scaled,
{type Output = Unit<<S as Div<T>>::Output,R>;/// 物理量除法fn div(self, rhs: T) -> Self::Output {Unit(self.0 / rhs, PhantomData)}
}// U /= Var<T>
impl<T, S, R> DivAssign<Var<T>> for Unit<S, R>
whereT: Numeric,S: Sied + DivAssign<Var<T>>,R: Scaled,Var<T>: Scalar,
{/// 标量除法赋值 (/=)fn div_assign(&mut self, rhs: Var<T>) {self.0 /= rhs;}
}// U /= T
impl<T, S, R> DivAssign<T> for Unit<S, R>
whereT: Numeric,S: Sied + DivAssign<Var<T>>,R: Scaled,Var<T>: Scalar,
{/// 标量除法赋值 (/=)fn div_assign(&mut self, rhs: T) {self.0 /= Var(rhs);}
}

二、核心结构

pub struct Unit<S: Sied, R>(pub S, pub PhantomData<R>);
  • Unit是一个泛型结构体,包含两个类型参数:

    • S: Sied:表示SI基础类型(如米、千克等)

    • R: Scaled:表示比例因子类型(如千分之一、百分之一等)

  • 使用PhantomData来标记比例因子类型R,使其在运行时没有实际存储

三、主要功能

  1. 单位转换与规范化
    通过UnitOrSi trait提供单位转换能力:
pub trait UnitOrSi {type Output;fn unit(self) -> Self::Output;
}
  • 当比例因子R是NoRatio时,返回SI基础类型S

  • 否则返回Unit自身

  1. 构造方法
pub fn new(value: T) -> Self {Self(Si::new(value), PhantomData)
}
  • 创建一个新的Unit实例,包装给定的数值和单位
  1. 运算符重载
    代码实现了丰富的运算符重载,支持类型安全的物理量运算:
算术运算
  • 取负(Neg)

  • 加法(Add, AddAssign)

  • 减法(Sub, SubAssign)

  • 乘法(Mul, MulAssign)

  • 除法(Div, DivAssign)

运算特点
  • 运算时会自动处理单位和比例因子的组合

  • 支持与标量(T)、变量(Var)和SI单位(Si)的运算

  • 乘法/除法会组合/抵消单位和比例因子

四、类型安全设计

  • 使用泛型和trait bound确保只有兼容的单位才能进行运算

  • 通过Sied(SI单位)、Scaled(比例因子)、Dimensional(量纲)等trait约束运算合法性

  • 使用PhantomData在类型系统中携带比例因子信息而不增加运行时开销

五、使用场景

这个Unit结构体可用于构建类型安全的物理量计算系统,例如:

let length = Unit::<Meter, NoRatio>::new(5.0);  // 5米
let time = Unit::<Second, Kilo>::new(2.0);      // 2千秒
let speed = length / time;  // 自动推导出适当的单位和比例因子

这样的设计可以在编译期捕获单位不匹配的错误,避免运行时单位换算错误。

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

相关文章:

  • <component :is=““>
  • CentOS7下的ZooKeeper部署
  • 55. Jump Game
  • Redis持久化策略介绍,以及如何选择?
  • 第二十四章 通用同步异步收发器(USART)
  • java异步编程难题拆解
  • Java 中 switch-case 语句的执行逻辑与避坑指南
  • Java判断规则工具类
  • 工作日记总结-transaction is aborted, commands ignored until end of transaction block
  • [软件测试]:什么是自动化测试?selenium+webdriver-manager的安装,实现你的第一个脚本
  • Kotlin基础语法二
  • 大数据学习(136)-数据埋点
  • 玄机 日志分析-Tomcat日志分析 WriteUp
  • G-Star公益行 | 公益组织入门开源技术,六月北京点燃改变的星火
  • 【MySQL数据库】InnoDB存储引擎:事务原理redolog、undolog与版本控制MVCC
  • QuecPython 文件系统操作
  • 多光谱图像技术在苗期作物与杂草识别中的研究进展
  • C语言学习20250610
  • Dynadot邮箱工具指南(六):将域名邮箱添加至网易邮箱大师
  • Leetcode 3576. Transform Array to All Equal Elements
  • 新能源知识库(34)什么是单一制和两部制
  • 【SAP MM SD FICO】销售视图和会计视图
  • C++ 8.1内联函数之宏定义
  • Metasploitable: 1靶场渗透
  • 在postgresql中,group by时取第一个值
  • 网络编程(Modbus进阶)
  • Manus 框架与 COKE 框架解析及完整 Demo
  • Unreal从入门到精通之使用 CheatManager 自定义控制台命令
  • 操作系统的一些名词
  • 期末考试复习总结-第一章《HarmonyOS介绍》