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

【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;  // 自动推导出适当的单位和比例因子

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

相关文章:

  • python模拟键盘 鼠标操作 通过ctypes调用Windows API实现底层输入模拟
  • Android Studio 问题:Android Studio 一直开在 Updating indexes
  • 使用Mvnd加速Maven构建速度
  • 深度学习核心概念:优化器、模型可解释性与欠拟合
  • TI以太网PHY收发器晶体选择和规格
  • OpenGL学习20250610
  • 定时器任务——若依源码分析
  • 376. Wiggle Subsequence
  • Windows cmd中文乱码解决方法(Windows控制台中文乱码、CMD乱码、控制台乱码、Command Prompt命令提示符cmd.exe乱码)
  • docker 安装运行mysql8.4.4
  • 多模态商品数据接口:融合图像、语音与文字的下一代商品详情体验
  • Loss Margin的原理与推导
  • 一天时间解决期末不挂科
  • 代码解读——ReferenceNet
  • 【位运算】消失的两个数字(hard)
  • STM32 PID控制
  • Hyperlane 框架详解与使用指南
  • shell打印图案
  • 常用的OceanBase调优配置参数
  • Maven 多仓库配置及缓存清理实战分享
  • 网站全站开发/如何创建自己的域名
  • 不锈钢网站哪家最专业/网络推广项目代理
  • 做网站一条龙/国内军事新闻最新消息
  • 网站备案名称的影响/关键词排名怎么做上首页
  • 零基础学做网站教程/珠海百度关键词优化
  • 用前端做的比较酷的网站/重庆网站排名优化教程