【PhysUnits】15.6 引入P1后的左移运算(shl.rs)

一、源码

代码实现了Rust的类型级二进制数的左移运算(<<),使用类型系统在编译期进行计算。

rust 复制代码
use super::basic::{Z0, P1, N1, B0, B1, NonZero, NonOne, Unsigned};
use super::sub1::Sub1;
use core::ops::Shl;

// ==================== 左移运算(<<) ====================
// Z0 << U
impl<R: Unsigned> Shl<R> for Z0 {
    type Output = Z0;
    fn shl(self, _: R) -> Self::Output {
        Z0  // 0 << n = 0
    }
}

// P1 << U
impl Shl<Z0> for P1 {// P1 << Z0
    type Output = Self;
    fn shl(self, _: Z0) -> Self::Output {
        self
    }
}

impl Shl<P1> for P1 {// P1 << P1
    type Output = B0<P1>;
    fn shl(self, _: P1) -> Self::Output {
        B0::new()
    }
}

impl<R: Unsigned + NonZero + NonOne + Sub1> Shl<R> for P1
where
    P1: Shl<<R as Sub1>::Output>
{// P1 << 超过1的数
    type Output = B0<<P1 as Shl<R::Output>>::Output>;
    fn shl(self, _: R) -> Self::Output {
        B0::new()
    }
}

// N1 << U
impl Shl<Z0> for N1 {// N1 << Z0
    type Output = Self;
    fn shl(self, _: Z0) -> Self::Output {
        self
    }
}

impl Shl<P1> for N1 {// N1 << P1
    type Output = B0<N1>;
    fn shl(self, _: P1) -> Self::Output {
        B0::new()
    }
}

impl<R: Unsigned + NonZero + NonOne + Sub1> Shl<R> for N1
where
    N1: Shl<<R as Sub1>::Output>
{// P1 << 超过1的数
    type Output = B0<<N1 as Shl<R::Output>>::Output>;
    fn shl(self, _: R) -> Self::Output {
        B0::new()
    }
}

// B0 << U
impl<H: NonZero> Shl<Z0> for B0<H> {// B0 << Z0
    type Output = Self;
    fn shl(self, _: Z0) -> Self::Output {
        self
    }
}

impl<H: NonZero> Shl<P1> for B0<H> {// B0 << P1
    type Output = B0<B0<H>>;
    fn shl(self, _: P1) -> Self::Output {
        B0::new()
    }
}

impl<H: NonZero, R: Unsigned + NonZero + NonOne + Sub1> Shl<R> for B0<H>
where
    B0<H>: Shl<<R as Sub1>::Output>
{// B0 << 超过1的数
    type Output = B0<<B0<H> as Shl<R::Output>>::Output>;
    fn shl(self, _: R) -> Self::Output {
        B0::new()
    }
}

// B1 << U
impl<H: NonZero> Shl<Z0> for B1<H> {// B1 << Z0
    type Output = Self;
    fn shl(self, _: Z0) -> Self::Output {
        self
    }
}

impl<H: NonZero> Shl<P1> for B1<H> {// B1 << P1
    type Output = B0<B1<H>>;
    fn shl(self, _: P1) -> Self::Output {
        B0::new()
    }
}

impl<H: NonZero, R: Unsigned + NonZero + NonOne + Sub1> Shl<R> for B1<H>
where
    B1<H>: Shl<<R as Sub1>::Output>
{// B1 << 超过1的数
    type Output = B0<<B1<H> as Shl<R::Output>>::Output>;
    fn shl(self, _: R) -> Self::Output {
        B0::new()
    }
}

二、类型和trait引入

rust 复制代码
use super::basic::{Z0, P1, N1, B0, B1, NonZero, NonOne, Unsigned};
use super::sub1::Sub1;
use core::ops::Shl;
  • 从父模块引入基础类型:

    • Z0: 表示0

    • P1: 表示+1

    • N1: 表示-1

    • B0, B1: 二进制位(0和1)

    • 标记trait: NonZero, NonOne, Unsigned

  • Sub1: 减1操作

  • Shl: Rust的左移运算符trait

三、零的左移实现

rust 复制代码
impl<R: Unsigned> Shl<R> for Z0 {
    type Output = Z0;
    fn shl(self, _: R) -> Self::Output {
        Z0  // 0 << n = 0
    }
}
  • 任何数左移0还是0

  • 适用于所有无符号类型R

四、正一(P1)的左移

rust 复制代码
impl Shl<Z0> for P1 { // P1 << 0 = P1
    type Output = Self;
    fn shl(self, _: Z0) -> Self::Output { self }
}

impl Shl<P1> for P1 { // P1 << 1 = B0<P1> (即10,二进制表示)
    type Output = B0<P1>;
    fn shl(self, _: P1) -> Self::Output { B0::new() }
}

impl<R: Unsigned + NonZero + NonOne + Sub1> Shl<R> for P1
where P1: Shl<<R as Sub1>::Output> {
    type Output = B0<<P1 as Shl<R::Output>>::Output>;
    fn shl(self, _: R) -> Self::Output { B0::new() }
}
  • 分三种情况处理:

    • 移0位:保持不变

    • 移1位:变成B0(二进制10)

    • 移多位:递归处理

五、负一(N1)的左移

rust 复制代码
impl Shl<Z0> for N1 { ... }  // 同P1
impl Shl<P1> for N1 { ... }  // 同P1
impl<R: Unsigned + NonZero + NonOne + Sub1> Shl<R> for N1 { ... }  // 同P1
  • 处理逻辑与P1完全相同

六、B0(二进制0)的左移

rust 复制代码
impl<H: NonZero> Shl<Z0> for B0<H> { ... }  // 移0位
impl<H: NonZero> Shl<P1> for B0<H> { ... }  // 移1位
impl<H: NonZero, R: Unsigned + NonZero + NonOne + Sub1> Shl<R> for B0<H> { ... }  // 移多位
  • 在二进制数前补0:

    • B0 << 1 = B0<B0>

    • 递归处理多位移动

七、B1(二进制1)的左移

rust 复制代码
impl<H: NonZero> Shl<Z0> for B1<H> { ... }  // 移0位
impl<H: NonZero> Shl<P1> for B1<H> { ... }  // 移1位
impl<H: NonZero, R: Unsigned + NonZero + NonOne + Sub1> Shl<R> for B1<H> { ... }  // 移多位
  • 类似B0,但在二进制数低位补0

八、关键点总结

  1. 递归处理:多位移动通过递归减1实现

  2. 类型级计算:所有操作在编译期确定

  3. 二进制表示:

  • B0表示在二进制数H低位加0

  • B1表示在二进制数H低位加1

  1. 特殊值处理:
  • P1表示+1(二进制1)

  • N1表示-1

  • Z0表示0

这种实现方式常用于需要编译期计算的场景,如物理单位系统、矩阵运算等,可以完全消除运行时开销。

相关推荐
红烧code4 小时前
【Rust GUI开发入门】编写一个本地音乐播放器(4. 绘制按钮组件)
rust·gui·svg·slint
朝阳5816 小时前
使用过程宏实现自动化新增功能
后端·rust
JordanHaidee7 小时前
【Rust GUI开发入门】编写一个本地音乐播放器(8. 从文件中提取歌曲元信息)
rust
清心9159 小时前
Windows系统Rust安装与配置,解决安装慢问题
rust
清心91510 小时前
Windows系统Rust安装,自定义安装目录
rust
恒云客12 小时前
Rust开发环境配置
开发语言·后端·rust
红烧code1 天前
【Rust GUI开发入门】编写一个本地音乐播放器(1. 主要技术选型&架构设计)
rust·gui·slint·rodio·lofty
JordanHaidee1 天前
【Rust GUI开发入门】编写一个本地音乐播放器(3. UI与后台线程通信)
rust
Source.Liu2 天前
【mdBook】1 安装
笔记·rust·markdown
Vallelonga2 天前
Rust 中的 static 和 const
开发语言·经验分享·rust