【PhysUnits】15.9 引入P1后的右移运算(shr.rs)

[复制链接]
发表于 2025-6-29 02:20:56 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有账号?立即注册

×
一、源码

这段代码是用Rust实现的类型级右移运算(>>),属于类型级编程的范畴。它通过类型体系来体现和操纵二进制数,并在编译期完成计算。
  1. use super::basic::{Z0, P1, N1, B0, B1, NonZero, NonOne, Unsigned};
  2. use super::sub1::Sub1;
  3. use core::ops::Shr;
  4. // ==================== Right Shift Operation (>>) ====================
  5. // ==================== 右移运算(>>) ====================
  6. // Z0 >> U
  7. // Zero right shifted by any unsigned number is still zero
  8. // 零右移任何无符号数仍然是零
  9. impl<R: Unsigned> Shr<R> for Z0 {
  10.     type Output = Z0;
  11.     fn shr(self, _: R) -> Self::Output {
  12.         Z0  // 0 >> n = 0
  13.     }
  14. }
  15. // P1 >> U
  16. // Positive one right shifted by zero is itself
  17. // 正一右移零位是其本身
  18. impl Shr<Z0> for P1 {
  19.     type Output = Self;
  20.     fn shr(self, _: Z0) -> Self::Output {
  21.         self
  22.     }
  23. }
  24. // Positive one right shifted by any non-zero unsigned number becomes zero
  25. // 正一右移任何非零无符号数变为零
  26. impl<R: Unsigned + NonZero> Shr<R> for P1 {
  27.     type Output = Z0;
  28.     fn shr(self, _: R) -> Self::Output {
  29.         Z0::new()
  30.     }
  31. }
  32. // N1 >> U
  33. // Negative one right shifted by any unsigned number remains negative one
  34. // (due to sign extension in two's complement)
  35. // 负一右移任何无符号数仍然是负一(由于二进制补码中的符号扩展)
  36. impl<R: Unsigned> Shr<R> for N1 {
  37.     type Output = Self;
  38.     fn shr(self, _: R) -> Self::Output {
  39.         self
  40.     }
  41. }
  42. // B0 >> U
  43. // Binary number ending with 0 right shifted by zero is itself
  44. // 以0结尾的二进制数右移零位是其本身
  45. impl<H: NonZero> Shr<Z0> for B0<H> {
  46.     type Output = Self;
  47.     fn shr(self, _: Z0) -> Self::Output {
  48.         self
  49.     }
  50. }
  51. // Binary number ending with 0 right shifted by one becomes its head
  52. // 以0结尾的二进制数右移一位变为其头部
  53. impl<H: NonZero> Shr<P1> for B0<H> {
  54.     type Output = H;
  55.     fn shr(self, _: P1) -> Self::Output {
  56.         H::default()
  57.     }
  58. }
  59. // Binary number ending with 0 right shifted by more than one
  60. // Recursively shifts right by one until the shift amount is zero
  61. // 以0结尾的二进制数右移多于一位
  62. // 递归地右移一位直到移位量为零
  63. impl<H: NonZero, R: Unsigned + NonZero + NonOne + Sub1> Shr<R> for B0<H>
  64. where
  65.     H: Shr<<R as Sub1>::Output>
  66. {
  67.     type Output = <H as Shr<R::Output>>::Output;
  68.     fn shr(self, r: R) -> Self::Output {
  69.         (self>>P1)>>r.sub1()
  70.     }
  71. }
  72. // B1 >> U
  73. // Binary number ending with 1 right shifted by zero is itself
  74. // 以1结尾的二进制数右移零位是其本身
  75. impl<H: NonZero> Shr<Z0> for B1<H> {
  76.     type Output = Self;
  77.     fn shr(self, _: Z0) -> Self::Output {
  78.         self
  79.     }
  80. }
  81. // Binary number ending with 1 right shifted by one becomes its head
  82. // 以1结尾的二进制数右移一位变为其头部
  83. impl<H: NonZero> Shr<P1> for B1<H> {
  84.     type Output = H;
  85.     fn shr(self, _: P1) -> Self::Output {
  86.         H::default()
  87.     }
  88. }
  89. // Binary number ending with 1 right shifted by more than one
  90. // Recursively shifts right by one until the shift amount is zero,
  91. // and maintains the sign bit (B0 prefix)
  92. // 以1结尾的二进制数右移多于一位
  93. // 递归地右移一位直到移位量为零,并保持符号位(B0前缀)
  94. impl<H: NonZero, R: Unsigned + NonZero + NonOne + Sub1> Shr<R> for B1<H>
  95. where
  96.     H: Shr<<R as Sub1>::Output>
  97. {
  98.     type Output = <H as Shr<R::Output>>::Output;
  99.     fn shr(self, r: R) -> Self::Output {
  100.         (self>>P1)>>(r.sub1())
  101.     }
  102. }
  103. // Test cases
  104. #[cfg(test)]
  105. mod tests {
  106.     use super::*;
  107.    
  108.     #[test]
  109.     fn test_shr() {
  110.         // Test Z0
  111.         let _: Z0 = Z0 >> Z0;
  112.         let _: Z0 = Z0 >> P1;
  113.         
  114.         // Test P1
  115.         let _: P1 = P1 >> Z0;
  116.         let _: Z0 = P1 >> P1;
  117.         
  118.         // Test N1
  119.         let _: N1 = N1 >> Z0;
  120.         let _: N1 = N1 >> P1;
  121.         
  122.         // Test B0
  123.         let b0: B0<P1> = B0::new();
  124.         let _: B0<P1> = b0 >> Z0;
  125.         let _: P1 = b0 >> P1;
  126.         
  127.         // Test B1
  128.         let b1: B1<P1> = B1::new();
  129.         let _: B1<P1> = b1 >> Z0;
  130.         let _: P1 = b1 >> P1;
  131.     }
  132. }
复制代码
二、根本概念


  • 类型定义:


  • Z0:体现数字0
  • P1:体现+1
  • N1:体现-1
  • B0:体现以0末端的二进制数(如B0体现二进制10,即十进制2)
  • B1:体现以1末端的二进制数(如B1体现二进制11,即十进制3)
  • NonZero、NonOne、Unsigned:这些是标记trait,用于束缚类型参数

  • 焦点trait:


  • Shr:Rust的右移运算符trait,这里为差别类型实现了该trait
三、实现逻辑


  • Z0(零)的右移:


  • 任何数右移0位保持稳定
  • 0右移任何位数仍然是0

  • P1(+1)的右移:


  • 右移0位:保持稳定
  • 右移非零位:变为0(因为正数的右移会补0)

  • N1(-1)的右移:


  • 右移任何位数都保持稳定(因为负数的右移在补码体现中会进行符号扩展)

  • B0(以0末端的二进制数)的右移:


  • 右移0位:保持稳定
  • 右移1位:去掉最后一位0,变成头部H
  • 右移多位:递归地右移1位直到完成

  • B1(以1末端的二进制数)的右移:


  • 雷同B0,但会保持符号位
递归实现

对于多位右移操纵,代码使用了递归的方式:
  1. impl<H: NonZero, R: Unsigned + NonZero + NonOne + Sub1> Shr<R> for B0<H>
  2. where
  3.     H: Shr<<R as Sub1>::Output>
  4. {
  5.     type Output = <H as Shr<R::Output>>::Output;
  6.     fn shr(self, r: R) -> Self::Output {
  7.         (self>>P1)>>r.sub1()
  8.     }
  9. }
复制代码
这里的意思是:要计算B0 >> R,先右移1位变成H,然后对剩下的R-1位继续右移。
测试用例

测试了各种情况:


  • 零的右移
  • +1的右移
  • -1的右移
  • 以0末端的二进制数的右移
  • 以1末端的二进制数的右移
四、总结

这段代码展示了怎样使用Rust的类型体系在编译期完成右移运算。通过为差别类型实现Shr trait,并使用递归类型计算,实现了类型安全的右移操纵。这种技术常用于嵌入式开辟等需要编译期计算的场景。
回复

使用道具 举报

登录后关闭弹窗

登录参与点评抽奖  加入IT实名职场社区
去登录
快速回复 返回顶部 返回列表