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

【unitrix】 4.16 类型级别左移运算实现解析(shl.rs)

一、源码

这段代码实现了一个类型级别的左移运算(<<)系统,用于在编译时进行位运算。

/*类型级别的左移运算实现* 编制人: $ource* 修改版次:0版完成版* 本版次创建时间: 2025年6月27日* 最后修改时间: 2025年7月4日 添加Shl1特质,避免解释器递归调用* 待完善问题:无*/
use core::ops::Shl;use crate::number::{Z0, P1, N1, B0, B1, Var, FixedPoint,TypedInt, NonZero, Primitive, PrimitiveInt, Unsigned,IfB0, IfB1, Sub1,
};// ==================== Left Shift Operation / 左移运算 (<<) ====================// ==================== I << All ====================
// Zero left shifted by any amount is still zero / 零左移任何位数仍然是零
impl<R: Unsigned> Shl<R> for Z0 {type Output = Z0;fn shl(self, _: R) -> Self::Output {Z0}
}// Zero left shifted by a variable amount is still zero / 零左移可变位数仍然是零
impl<T: Primitive> Shl<Var<T>> for Z0 {type Output = Z0;fn shl(self, _: Var<T>) -> Self::Output {Z0}
}// ==================== P1 << U ====================
// Positive one left shifted by zero is itself
// 正一左移零位是其本身
impl Shl<Z0> for P1 {type Output = Self;fn shl(self, _: Z0) -> Self::Output {self}
}// Positive one left shifted by more than one
// Recursively shifts left by one until the shift amount is zero
// (equivalent to adding zeros at the least significant side)
// 正一左移多于一位
// 递归地左移一位直到移位量为零(相当于在最低有效位侧添加零)
impl<R: Unsigned + NonZero + Sub1> Shl<R> for P1
whereP1: Shl<<R as Sub1>::Output>,
{type Output = B0<<P1 as Shl<<R as Sub1>::Output>>::Output>;fn shl(self, _r: R) -> Self::Output {B0::new()}
}// Positive one left shifted by a variable amount
// 正一左移可变位数
impl<T: PrimitiveInt> Shl<Var<T>> for P1
where Var<T>: From<P1> + Shl<Output=Var<T>>,
{type Output = Var<T>;fn shl(self, rhs: Var<T>) -> Self::Output {Var::<T>::from(self) << rhs}
}// ==================== N1 << U ====================
// Negative one left shifted by zero is itself
// 负一左移零位是其本身
impl Shl<Z0> for N1 {type Output = Self;fn shl(self, _: Z0) -> Self::Output {self}
}// Negative one left shifted by more than one
// Recursively shifts left by one until the shift amount is zero
// (maintains sign in two's complement arithmetic)
// 负一左移多于一位
// 递归地左移一位直到移位量为零(在二进制补码算术中保持符号)
impl<R: Unsigned + NonZero + Sub1> Shl<R> for N1
whereN1: Shl<<R as Sub1>::Output>,
{type Output = B0<<N1 as Shl<<R as Sub1>::Output>>::Output>;fn shl(self, _r: R) -> Self::Output {B0::new()}
}// Negative one left shifted by a variable amount
// 负一左移可变位数
impl<T: PrimitiveInt> Shl<Var<T>> for N1
where Var<T>: From<N1> + Shl<Output=Var<T>>
{type Output = Var<T>;fn shl(self, rhs: Var<T>) -> Self::Output {Var::<T>::from(self) << rhs}
}// ==================== B0 << U ====================
// Binary number ending with 0 left shifted by zero is itself
// 以0结尾的二进制数左移零位是其本身
impl<H: NonZero> Shl<Z0> for B0<H> {type Output = Self;fn shl(self, _: Z0) -> Self::Output {self}
}// Binary number ending with 0 left shifted by more than one
// Recursively shifts left by one until the shift amount is zero
// 以0结尾的二进制数左移多于一位
// 递归地左移一位直到移位量为零
impl<H: NonZero, R: Unsigned + NonZero + Sub1> Shl<R> for B0<H>
where B0<H>: Shl<<R as Sub1>::Output>,
{type Output = B0<<B0<H> as Shl<<R as Sub1>::Output>>::Output>;fn shl(self, _r: R) -> Self::Output {B0::new()}
}// Binary number ending with 0 left shifted by a variable amount
// 以0结尾的二进制数左移可变位数
impl<H: NonZero, T: PrimitiveInt> Shl<Var<T>> for B0<H>
where Var<T>: From<B0<H>> + Shl<Output=Var<T>>
{type Output = Var<T>;fn shl(self, rhs: Var<T>) -> Self::Output {Var::<T>::from(self) << rhs}
}// ==================== B1 << U ====================
// Binary number ending with 1 left shifted by zero is itself
// 以1结尾的二进制数左移零位是其本身
impl<H: NonZero> Shl<Z0> for B1<H> {type Output = Self;fn shl(self, _: Z0) -> Self::Output {self}
}// Binary number ending with 1 left shifted by more than one
// Recursively shifts left by one until the shift amount is zero
// 以1结尾的二进制数左移多于一位
// 递归地左移一位直到移位量为零
impl<H: NonZero, R: Unsigned + NonZero + Sub1> Shl<R> for B1<H>
where B1<H>: Shl<<R as Sub1>::Output>,
{type Output = B0<<B1<H> as Shl<<R as Sub1>::Output>>::Output>;fn shl(self, _r: R) -> Self::Output {B0::new()}
}// Binary number ending with 1 left shifted by a variable amount
// 以1结尾的二进制数左移可变位数
impl<H: NonZero, T: PrimitiveInt> Shl<Var<T>> for B1<H>
where Var<T>: From<B1<H>> + Shl<Output=Var<T>>
{type Output = Var<T>;fn shl(self, rhs: Var<T>) -> Self::Output {Var::<T>::from(self) << rhs}
}// ==================== FixedPoint<IntPart, FracPart> << All ====================
// ==================== 定点数左移实现 ====================// Fixed-point number left shifted by zero - no change
// 定点数左移零位 - 无变化
impl<IntPart: TypedInt, FracPart: Unsigned> Shl<Z0> for FixedPoint<IntPart, FracPart> {type Output = Self;fn shl(self, _: Z0) -> Self::Output {self}
}// Fixed-point with zero fractional part left shift
// Shifting affects only the integer part
// 小数部分为零的定点数左移
// 移位仅影响整数部分
impl<IntPart: TypedInt + Shl<R>, R: Unsigned + NonZero> Shl<R> for FixedPoint<IntPart, Z0>
{type Output = FixedPoint<<IntPart as Shl<R>>::Output,Z0>;fn shl(self, _r: R) -> Self::Output {FixedPoint::new()}
}// Fixed-point with one fractional part left shift
// Shifting affects only the integer part
// 小数部分为P1的定点数左移
impl<IntPart: IfB1, R: Unsigned + NonZero + Sub1> Shl<R> for FixedPoint<IntPart, P1>
where<IntPart as IfB1>::Output: Shl<<R as Sub1>::Output>,  // 递归条件
{type Output = FixedPoint<<<IntPart as IfB1>::Output as Shl<<R as Sub1>::Output> >::Output,Z0>;fn shl(self, _r: R) -> Self::Output {FixedPoint::new()}
}// Fixed-point with fractional part ending with 0 left shift
// Shifting moves bit from fractional to integer part
// 小数部分以0结尾的定点数左移
// 移位将位从小数部分移动到整数部分
impl<IntPart: TypedInt + IfB0, L: NonZero, R: Unsigned + NonZero + Sub1> Shl<R> for FixedPoint<IntPart, B0<L>>
where FixedPoint< <IntPart as IfB0>::Output,L >: Shl<<R as Sub1>::Output, Output: Default>,
{type Output = <  FixedPoint< <IntPart as IfB0>::Output,L > as Shl<<R as Sub1>::Output>  >::Output;fn shl(self, _: R) -> Self::Output {Default::default()}
}// Fixed-point with fractional part ending with 1 left shift
// Shifting moves bit from fractional to integer part
// 小数部分以1结尾的定点数左移
// 移位将位从小数部分移动到整数部分
impl<IntPart: IfB1, L: NonZero, R: Unsigned + NonZero + Sub1> Shl<R> for FixedPoint<IntPart, B1<L>>
where FixedPoint< <IntPart as IfB1>::Output,L >: Shl<<R as Sub1>::Output, Output: Default>,
{type Output = <  FixedPoint< <IntPart as IfB1>::Output,L > as Shl<<R as Sub1>::Output>  >::Output;fn shl(self, _: R) -> Self::Output {Default::default()}
}/* // Fixed-point left shifted by a variable amount
// 定点数左移可变位数(无意义,取消)
impl<IntPart, FracPart, T> Shl<Var<T>> for FixedPoint<IntPart, FracPart>
whereT: PrimitiveInt,IntPart: Into<T>,FracPart: Into<T>,Self: Into<T>,
{type Output = Var<T>;fn shl(self, rhs: Var<T>) -> Self::Output {Var(self.into() << rhs.0)}
} */// ==================== Var << All ====================
impl<T: PrimitiveInt, R: Unsigned> Shl<R> for Var<T>
whereVar<T>: From<R> + Shl<Output=Var<T>>,
{type Output = Var<T>;fn shl(self, rhs: R) -> Self::Output {self << Var::<T>::from(rhs)}
}impl<T: PrimitiveInt + Shl<Output=T>> Shl<Var<T>> for Var<T>{type Output = Var<T>;fn shl(self, rhs: Var<T>) -> Self::Output {Var(self.0 << rhs.0)}
}#[cfg(test)]
mod tests {use crate::number::*;// ==================== Z0 左移所有情况 ====================#[test]fn test_z0_left_shift() {assert_eq!(Z0 << Z0, Z0);  // 零左移零位还是零assert_eq!(Z0 << P1, Z0);  // 零左移一位还是零assert_eq!(Z0 << B0::<P1>::new(), Z0);  // 零左移两位还是零assert_eq!(Z0 << Var::<i32>::from(5), Z0);  // 零左移变量位数还是零}// ==================== P1 左移无符号数 ====================#[test]fn test_p1_left_shift() {assert_eq!(P1 << Z0, P1);  // 正一左移零位不变assert_eq!(P1 << P1, B0::<P1>::new());  // 正一左移一位变为10(二进制)assert_eq!(P1 << B0::<P1>::new(), B0::<B0<P1>>::new());  // 正一左移两位变为100(二进制)assert_eq!(P1 << Var::<i32>::from(3), Var::<i32>(8));  // 正一左移三位等于8}// ==================== N1 左移无符号数 ====================#[test]fn test_n1_left_shift() {assert_eq!(N1 << Z0, N1);  // 负一左移零位不变assert_eq!(N1 << P1, B0::<N1>::new());  // 负一左移一位assert_eq!(N1 << B0::<P1>::new(), B0::<B0::<N1>>::new());  // 负一左移两位assert_eq!(N1 << Var::<i32>::from(2), Var::<i32>(-4));  // 负一左移两位等于-4}// ==================== B0 左移无符号数 ====================#[test]fn test_b0_left_shift() {let b01 = B0::<P1>::new();  // 二进制01(即十进制的1)let _b001 = B0::<B0::<P1>>::new();  // 二进制001assert_eq!(b01 << Z0, b01);  // 01左移零位不变assert_eq!(b01 << P1, B0::<B0::<P1>>::new());  // 01左移一位变为010assert_eq!(b01 << B0::<P1>::new(), B0::<B0::<B0::<P1>>>::new());  // 01左移两位变为0100assert_eq!(b01 << Var::<i32>::from(2), Var::<i32>(8));  // 01左移两位等于4}// ==================== B1 左移无符号数 ====================#[test]fn test_b1_left_shift() {let b11 = B1::<P1>::new();  // 二进制11(即十进制的3)let _b011 = B0::<B1::<P1>>::new();  // 二进制011assert_eq!(b11 << Z0, b11);  // 11左移零位不变assert_eq!(b11 << P1, B0::<B1::<P1>>::new());  // 11左移一位变为110assert_eq!(b11 << B0::<P1>::new(), B0::<B0::<B1::<P1>>>::new());  // 11左移两位变为1100assert_eq!(b11 << Var::<i32>::from(3), Var::<i32>(24));}// ==================== 定点数左移 ====================#[test]fn test_fixed_point_left_shift() {// 小数部分为零的定点数let fp1 = FixedPoint::<B0<P1>, Z0>::new();assert_eq!(fp1 << Z0, fp1);  // 左移零位不变assert_eq!(fp1 << P1, FixedPoint::<B0<B0<P1>>, Z0>::new());// 小数部分为1的定点数let fp2 = FixedPoint::<P1, P1>::new();assert_eq!(fp2 << P1, FixedPoint::<B1<P1>, Z0>::new());// 小数部分以0结尾的定点数let fp3 = FixedPoint::<P1, B0::<P1>>::new();assert_eq!(fp3 << P1, FixedPoint::<B0<P1>, P1>::new());// 小数部分以1结尾的定点数let fp4 = FixedPoint::<P1, B1::<P1>>::new();assert_eq!(fp4 << P1, FixedPoint::<B1<P1>, P1>::new());}// ==================== 变量左移 ====================#[test]fn test_var_left_shift() {let var1 = Var::<i32>(5);assert_eq!(var1 << Z0, Var::<i32>(5));  // 左移零位不变assert_eq!(var1 << P1, Var::<i32>(10));  // 左移一位变为10assert_eq!(var1 << B0::<P1>::new(), Var::<i32>(20));  // 左移两位变为20assert_eq!(var1 << Var::<i32>(3), Var::<i32>(40));  // 左移三位变为40}// 测试边界情况和组合情况#[test]fn test_edge_cases() {// 大位移量测试assert_eq!(P1 << B1::<P1>::new(), B0::<B0::<B0::<P1>>>::new());  // 1左移3位变为1000(8)assert_eq!(N1 << B1::<P1>::new(), B0::<B0::<B0::<N1>>>::new());  // -1左移3位// 二进制数位移测试let b101 = B1::<B0::<P1>>::new();  // 101(5)assert_eq!(b101 << P1, B0::<B1::<B0::<P1>>>::new());  // 左移一位变为1010(10)// 复杂小数部分的定点数位移let fp = FixedPoint::<P1, B1::<B0<P1>>>::new();  // 1.101assert_eq!(fp << P1, FixedPoint::<B1<P1>, B0<P1>>::new());  // 左移一位}
}// ==================== 移一位独立实现 ====================
pub trait Shl1 {type Output: Default;fn shl1(self) -> Self::Output;
}// Zero left shifted by one is still zero
impl Shl1 for Z0 {type Output = Z0;fn shl1(self) -> Self::Output {Z0}
}// Positive one left shifted by one
impl Shl1 for P1 {type Output = B0<P1>;fn shl1(self) -> Self::Output {Default::default()}
}// Negative one left shifted by one
impl Shl1 for N1 {type Output = B0<N1>;fn shl1(self) -> Self::Output {Default::default()}
}// Binary number ending with 0 left shifted by one
impl<H: NonZero> Shl1 for B0<H> {type Output = B0<B0<H>>;fn shl1(self) -> Self::Output {Default::default()}
}// Binary number ending with 1 left shifted by one
impl<H: NonZero> Shl1 for B1<H> {type Output = B0<B1<H>>;fn shl1(self) -> Self::Output {Default::default()}
}// Fixed-point number implementations with methods
impl<IntPart: TypedInt + Shl1> Shl1 for FixedPoint<IntPart, Z0> {type Output = FixedPoint<<IntPart as Shl1>::Output, Z0>;fn shl1(self) -> Self::Output {FixedPoint::new()}
}impl<IntPart: IfB1> Shl1 for FixedPoint<IntPart, P1> {type Output = FixedPoint<<IntPart as IfB1>::Output, Z0>;fn shl1(self) -> Self::Output {FixedPoint::new()}
}impl<IntPart: TypedInt + IfB0, L: NonZero> Shl1 for FixedPoint<IntPart, B0<L>> {type Output = FixedPoint<<IntPart as IfB0>::Output, L>;fn shl1(self) -> Self::Output {FixedPoint::new()}
}impl<IntPart: IfB1, L: NonZero> Shl1 for FixedPoint<IntPart, B1<L>> {type Output = FixedPoint<<IntPart as IfB1>::Output, L>;fn shl1(self) -> Self::Output {FixedPoint::new()}
}

二、代码结构概述

  1. 基础类型定义:使用了多种类型来表示数字,包括Z0(零)、P1(正一)、N1(负一)、B0/B1(二进制位)等

  2. 左移运算实现:为不同类型实现了Shl trait,表示左移操作

  3. 定点数支持:实现了定点数的左移运算

  4. 变量移位支持:支持运行时变量的移位操作

  5. 独立Shl1 trait:单独实现了一位左移操作

三、主要组件解析

  1. 零的左移(Z0)

impl<R: Unsigned> Shl<R> for Z0 {type Output = Z0;fn shl(self, _: R) -> Self::Output { Z0 }
}
  • 零左移任何位数仍然是零

  • 适用于编译时已知的任意无符号移位量

  1. 正一(P1)和负一(N1)的左移

impl Shl<Z0> for P1 {type Output = Self;fn shl(self, _: Z0) -> Self::Output { self }
}impl<R: Unsigned + NonZero + Sub1> Shl<R> for P1
whereP1: Shl<<R as Sub1>::Output>,
{type Output = B0<<P1 as Shl<<R as Sub1>::Output>>::Output>;fn shl(self, _r: R) -> Self::Output { B0::new() }
}
  • 左移零位返回自身

  • 左移N位递归实现:每次左移一位,直到移位量为零

  • 负一的实现类似,保持二进制补码特性

  1. 二进制数的左移(B0/B1)

impl<H: NonZero, R: Unsigned + NonZero + Sub1> Shl<R> for B0<H>
where B0<H>: Shl<<R as Sub1>::Output>,
{type Output = B0<<B0<H> as Shl<<R as Sub1>::Output>>::Output>;fn shl(self, _r: R) -> Self::Output { B0::new() }
}
  • 处理以0或1结尾的二进制数

  • 递归左移,每次在最右侧添加0

  1. 定点数的左移

impl<IntPart: TypedInt + Shl<R>, R: Unsigned + NonZero> Shl<R> for FixedPoint<IntPart, Z0>
{type Output = FixedPoint<<IntPart as Shl<R>>::Output, Z0>;fn shl(self, _r: R) -> Self::Output { FixedPoint::new() }
}
  • 处理整数部分和小数部分的移位

  • 根据小数部分的类型(B0/B1/P1)有不同的实现

  • 移位会将小数部分的位移动到整数部分

  1. 变量移位

impl<T: PrimitiveInt, R: Unsigned> Shl<R> for Var<T>
whereVar<T>: From<R> + Shl<Output=Var<T>>,
{type Output = Var<T>;fn shl(self, rhs: R) -> Self::Output { self << Var::<T>::from(rhs) }
}
  • 支持运行时变量的移位操作

  • 将编译时常量转换为运行时变量进行移位

  1. 独立Shl1实现

pub trait Shl1 {type Output: Default;fn shl1(self) -> Self::Output;
}
  • 单独实现一位左移操作

  • 简化了单一位移位的实现

四、测试用例解析

测试覆盖了各种场景:

  1. 零的移位

  2. 正负一的移位

  3. 二进制数的移位

  4. 定点数的移位

  5. 变量移位

  6. 边界情况测试

五、设计特点

  1. 类型安全:所有操作在编译时进行类型检查

  2. 零成本抽象:运行时不会有额外开销

  3. 递归实现:通过类型系统实现递归移位

  4. 灵活性:支持编译时和运行时移位

  5. 扩展性:易于添加新的数字类型和操作

这个实现展示了Rust类型系统的强大能力,能够在编译时完成复杂的算术运算,同时保持代码的安全性和性能。

http://www.dtcms.com/a/267028.html

相关文章:

  • spring-ai-alibaba 1.0.0.2 学习(十)——各种工具调用方式对比
  • Python 闭包(Closure)实战总结
  • 【网络与系统安全】强制访问控制——BLP模型
  • PortSwigger Labs SQLInjection LAB6-7
  • 汽车功能安全【ISO 26262】概述1
  • Python-GUI-wxPython-布局
  • 黑马python(二十五)
  • hello判断
  • 斜线投影几何分割公式 h = rx·ry/(rx+ry) 的推导方法
  • 【github】想fork的项目变为私有副本
  • boost--io_service/io_context
  • FFmpeg 升级指北
  • 【网络与系统安全】强制访问控制——Biba模型
  • AI生成式软件工程正处在从“辅助编程”到“AI原生开发”的范式转移
  • 使用坚果云扩容Zotero同步空间的简单快捷方法
  • Vue3-组件化-Vue核心思想之一
  • Python 中的余数运算及数论中的同余定理
  • 五层协议介绍
  • 指针篇(7)- 指针运算笔试题(阿里巴巴)
  • CSS——圆形头像外嵌光圈
  • springsecurity02
  • js中的FileReader对象
  • ESP32CAM通过ESPHome接入HomeAssistant(含无线刷固件等)
  • Python-GUI-wxPython-控件
  • 语音大模型速览(一)F5-TTS
  • 《汇编语言:基于X86处理器》第6章 复习题和练习,编程练习
  • Selenium 安装使用教程
  • Python 量化交易安装使用教程
  • 深度学习3(向量化编程+ python中实现逻辑回归)
  • 遗传算法的原理与实现示例