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

【unitrix】 4.3 左移运算(<<)的实现(shl.rs)

一、源码

这段代码实现了一个类型级别的左移运算(<<)系统,使用 Rust 的类型系统来表示和执行二进制数的左移操作。它支持不同类型的数值(零、正一、负一、二进制数、定点数、浮点数和变量)以及不同的移位量(零、非零、变量)。

use core::ops::Shl;
use crate::number::{FixedPoint, Float, IfB0, IfB1, NonZero, Primitive, PrimitiveInt, Sub1, TypedInt, Unsigned, Var, B0, B1, N1, P1, Z0};// ==================== Left Shift Operation (<<) ====================
// ==================== 左移运算(<<) ====================// ==================== Z0 << 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 + From<P1> + Shl<Output=T>> Shl<Var<T>> for P1 {type Output = Var<T>;fn shl(self, rhs: Var<T>) -> Self::Output {Var(T::from(self) << rhs.0)}
}// ==================== 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 + From<N1> + Shl<Output=T>> Shl<Var<T>> for N1 {type Output = Var<T>;fn shl(self, rhs: Var<T>) -> Self::Output {Var(T::from(self) << rhs.0)}
}// ==================== 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 + From<B0<H>> + Shl<Output=T>> Shl<Var<T>> for B0<H> {type Output = Var<T>;fn shl(self, rhs: Var<T>) -> Self::Output {Var(T::from(self) << rhs.0)}
}// ==================== 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 + From<B1<H>> + Shl<Output=T>> Shl<Var<T>> for B1<H> {type Output = Var<T>;fn shl(self, rhs: Var<T>) -> Self::Output {Var(T::from(self) << rhs.0)}
}// ==================== FixedPoint<IntPart, FracPart> << All ====================
// ==================== 定点数左移实现 ====================// Fixed-point number left shifted by zero - no change
// 定点数左移零位 - 无变化
impl<IntPart: TypedInt, FracPart: TypedInt> 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>,
{type Output = <  FixedPoint< <IntPart as IfB0>::Output,L > as Shl<<R as Sub1>::Output>  >::Output;fn shl(self, r: R) -> Self::Output {FixedPoint::new() << r.sub1()}
}// 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>,
{type Output = <  FixedPoint< <IntPart as IfB1>::Output,L > as Shl<<R as Sub1>::Output>  >::Output;fn shl(self, r: R) -> Self::Output {FixedPoint::new() << r.sub1()}
}/* // 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)}
} */// ==================== Float << U ====================
// Floating-point number left shift
// Effectively increases the exponent (equivalent to multiplication by 2^r)
// 浮点数左移
// 实际上是增加指数(相当于乘以2^r)
impl<Significand, Exponent, R> Shl<R> for Float<Significand, Exponent>
whereR: Unsigned + NonZero,Exponent: Shl<R>, 
{type Output = Float<Significand, <Exponent as Shl<R>>::Output>;fn shl(self, _r: R) -> Self::Output {Float::new()}
}// ==================== Var << U ====================
impl<T, R> Shl<R> for Var<T>
whereT: PrimitiveInt + From<R> + Shl<Output=T>,R: Unsigned,
{type Output = Var<T>;fn shl(self, rhs: R) -> Self::Output {Var(self.0 << T::from(rhs))}
}// ==================== 辅助类型 ====================
/// 类型别名:左移一位的结果
#[allow(dead_code)]
pub type Shl1<I> = <I as Shl<P1>>::Output;

二、源码分析

  1. 基础类型和导入
use core::ops::Shl;
use crate::number::{FixedPoint, Float, IfB0, IfB1, NonZero, Primitive, PrimitiveInt, Sub1, TypedInt, Unsigned, Var, B0, B1, N1, P1, Z0};
  • Shl 是 Rust 的左移运算符 trait
    
  • 其他导入的类型用于表示各种数值和操作:
    
    •    Z0 表示零
      
      •  P1 表示正一
        
    •   N1 表示负一
      
    •    B0 和 B1 表示二进制数的位
      
    •    FixedPoint 和 Float 表示定点数和浮点数
      
    •    Var 表示变量值
      
    •    其他 trait 用于类型操作
      
  1. 零的左移 (Z0 << All)

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

  • 适用于固定位数和变量位数

  1. 正一的左移 (P1 << U)

impl Shl<Z0> for P1 {type Output = Self;fn shl(self, _: Z0) -> Self::Output { self }
}
  • 正一左移零位保持不变
    
  • 左移多于一位时递归地添加零(B0)
    
  1. 负一的左移 (N1 << U)

impl Shl<Z0> for N1 {type Output = Self;fn shl(self, _: Z0) -> Self::Output { self }
}
  • 负一左移零位保持不变

  • 左移多于一位时递归地添加零(B0),保持二进制补码表示

  1. 以0结尾的二进制数的左移 (B0 << U)

impl<H: NonZero> Shl<Z0> for B0<H> {type Output = Self;fn shl(self, _: Z0) -> Self::Output { self }
}
  • 左移零位保持不变
    
  • 左移多于一位时递归地添加零
    
  1. 以1结尾的二进制数的左移 (B1 << U)

impl<H: NonZero> Shl<Z0> for B1<H> {type Output = Self;fn shl(self, _: Z0) -> Self::Output { self }
}
  • 左移零位保持不变

  • 左移多于一位时递归地添加零

  1. 定点数的左移 (FixedPoint << U)

impl<IntPart: TypedInt, FracPart: TypedInt> Shl<Z0> for FixedPoint<IntPart, FracPart> {type Output = Self;fn shl(self, _: Z0) -> Self::Output { self }
}
  • 处理不同情况的定点数左移:

  •    零位移位:保持不变
    
  •   整数部分移位
    
  •    小数部分移位(将位从小数部分移动到整数部分)
    
  1. 浮点数的左移 (Float << U)

impl<Significand, Exponent, R> Shl<R> for Float<Significand, Exponent>
whereR: Unsigned + NonZero,Exponent: Shl<R>, 
{type Output = Float<Significand, <Exponent as Shl<R>>::Output>;fn shl(self, _r: R) -> Self::Output { Float::new() }
}
  • 浮点数左移通过增加指数实现(相当于乘以2^r)
  1. 变量的左移 (Var << U)

impl<T, R> Shl<R> for Var<T>
whereT: PrimitiveInt + From<R> + Shl<Output=T>,R: Unsigned,
{type Output = Var<T>;fn shl(self, rhs: R) -> Self::Output { Var(self.0 << T::from(rhs)) }
}
  • 对变量值执行运行时左移操作
  1. 辅助类型

pub type Shl1<I> = <I as Shl<P1>>::Output;
  • 定义类型别名表示左移一位的结果

三、特点总结

+ 类型级编程:所有操作都在编译时通过类型系统完成+ 递归实现:多位左移通过递归的单位移位实现+ 全面覆盖:支持各种数值类型和移位量+ 变量支持:提供运行时变量移位能力+ 数学正确性:正确处理符号(特别是负数的二进制补码表示)

这个系统展示了 Rust 类型系统的强大能力,能够在编译时完成复杂的数学运算类型检查。

http://www.lqws.cn/news/500527.html

相关文章:

  • Jupyter Notebook 完全指南:从入门到生产力工具
  • 【格与代数系统】示例2
  • 在训练词编码模型使用mask还是自回归,在训练生成大模型采用mask还是自回归?
  • 【格与代数系统】示例
  • linux 下 Doris 单点部署
  • 优化 ArcPy 脚本性能
  • 华为云 Flexus+DeepSeek 征文|基于 CCE 集群部署 Dify 平台工作流:科研论文翻译与 SEO 优化工具的全流程设计实践
  • python中学物理实验模拟:平抛运动和抛物运动
  • 基于 SpringBoot+JSP 的医疗预约与诊断系统设计与实现
  • JavaWeb学习——day8(MVC模式与session、cookie)
  • Node.js特训专栏-实战进阶:7.Express模板引擎选型与使用
  • Java SE - 图书管理系统模拟实现
  • Python csv 模块
  • leetcode82.删除排序链表中的重复元素II
  • AngularJS 待办事项 App
  • 触摸屏(典型 I2C + Input 子系统设备)从设备树解析到触摸事件上报
  • 73页精品PPT | 大数据平台规划与数据价值挖掘应用咨询项目解决方案
  • 124. 二叉树中的最大路径和
  • 驱动入门的进一步深入
  • 【机器学习深度学习】机器学习核心的计算公式:wx+b
  • 非对称加密实战:Python实现数字签名
  • sudo安装pip包的影响
  • 在 AI 工具海洋中掌舵:Cherry Studio 如何成为你的统一指挥中心
  • 更新麒麟连不上外网
  • C指针总结复习(结合deepseek)
  • 黑马程序员苍穹外卖DAY1
  • JimuReport:一款免费的数据可视化报表工具
  • 用于算法性能预测的 GNN 框架
  • 飞往大厂梦之算法提升-7
  • C3新增特性