当前位置: 首页 > 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 类型系统的强大能力,能够在编译时完成复杂的数学运算类型检查。

相关文章:

  • 文本网站代码空两格怎么做线上宣传渠道和宣传方式
  • 企业申请网站建设请示嘉兴百度seo
  • gta5网站正在建设中百度知道在线问答
  • 免费1级做爰片观看网站在线视频公众号推广费用一般多少
  • 网站建设的类型或分类百度识图在线识别
  • 儒枫网网站建设重庆seo论坛
  • 医疗AI数智立体化体系V2.0泛化多模块编程操作手册--架构师版(下)
  • Docker Compose与私有仓库部署
  • 多项目资料如何统一归档与权限管理
  • 2023/7 N2 jlpt词汇
  • uniapp实现远程图片下载到手机相册功能
  • DD3118S:USB3.0+Type-c双头TF/SD二合一高速0TG多功能手机读卡器ic
  • 【单元测试】单元测试的定义和作用
  • mysql 数据库连接 -h localhost 和 -h 127.0.0.1 区别是什么
  • 【AI时代速通QT】第三节:Linux环境中安装QT并做测试调试
  • C++修炼:异常
  • stm32万年历仿真+keil5程序
  • DeepSeek 和 GPT 系列模型针对越狱攻击的安全评估
  • Lombok注解 - 提高Java开发效率
  • phpstudy apache伪静态.htaccess文件置空丢失问题解决
  • WPF CommunityToolkit.Mvvm
  • JavaEE初阶第四期:解锁多线程,从 “单车道” 到 “高速公路” 的编程升级(二)
  • Unity_导航操作(鼠标控制人物移动)_运动动画
  • (C++)标准模板库(STL)相关介绍(C++教程)
  • 【轨物洞见】光伏清洁机器人本地组网探析——面向沙漠/海上电站的可靠通信架构设计
  • SAP-ABAP:MODIFY语句灵活更新数据库表详解